From 1d1989fdabe91a4ddf8fcba4d9a357277894a282 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sun, 16 Jun 2024 22:21:47 -0400 Subject: [PATCH 0001/2194] Fix rustfmt --- src/spanned.rs | 1 + src/types.rs | 15 ++++++++------- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/src/spanned.rs b/src/spanned.rs index 4aaf7fdb27fb0..28911f8af1dfb 100644 --- a/src/spanned.rs +++ b/src/spanned.rs @@ -181,6 +181,7 @@ impl Spanned for ast::GenericBound { match *self { ast::GenericBound::Trait(ref ptr, _) => ptr.span, ast::GenericBound::Outlives(ref l) => l.ident.span, + ast::GenericBound::Use(_, span) => span, } } } diff --git a/src/types.rs b/src/types.rs index 7d14d9e727ab5..c2c192738c910 100644 --- a/src/types.rs +++ b/src/types.rs @@ -563,6 +563,8 @@ impl Rewrite for ast::GenericBound { .map(|s| if has_paren { format!("({})", s) } else { s }) } ast::GenericBound::Outlives(ref lifetime) => lifetime.rewrite(context, shape), + // FIXME(precise_capturing): Should implement formatting before stabilization. + ast::GenericBound::Use(..) => None, } } } @@ -843,11 +845,7 @@ impl Rewrite for ast::Ty { rewrite_macro(mac, None, context, shape, MacroPosition::Expression) } ast::TyKind::ImplicitSelf => Some(String::from("")), - ast::TyKind::ImplTrait(_, ref it, ref captures) => { - // FIXME(precise_capturing): Implement formatting. - if captures.is_some() { - return None; - } + ast::TyKind::ImplTrait(_, ref it) => { // Empty trait is not a parser error. if it.is_empty() { return Some("impl".to_owned()); @@ -932,6 +930,8 @@ fn is_generic_bounds_in_order(generic_bounds: &[ast::GenericBound]) -> bool { let is_trait = |b: &ast::GenericBound| match b { ast::GenericBound::Outlives(..) => false, ast::GenericBound::Trait(..) => true, + // FIXME(precise_capturing): This ordering fn should be reworked. + ast::GenericBound::Use(..) => false, }; let is_lifetime = |b: &ast::GenericBound| !is_trait(b); let last_trait_index = generic_bounds.iter().rposition(is_trait); @@ -966,6 +966,8 @@ fn join_bounds_inner( let is_bound_extendable = |s: &str, b: &ast::GenericBound| match b { ast::GenericBound::Outlives(..) => true, ast::GenericBound::Trait(..) => last_line_extendable(s), + // FIXME(precise_capturing): This ordering fn should be reworked. + ast::GenericBound::Use(..) => true, }; // Whether a GenericBound item is a PathSegment segment that includes internal array @@ -1110,8 +1112,7 @@ fn join_bounds_inner( pub(crate) fn opaque_ty(ty: &Option>) -> Option<&ast::GenericBounds> { ty.as_ref().and_then(|t| match &t.kind { - // FIXME(precise_capturing): Implement support here - ast::TyKind::ImplTrait(_, bounds, _) => Some(bounds), + ast::TyKind::ImplTrait(_, bounds) => Some(bounds), _ => None, }) } From 0c5a75a61bb2559a3b25cd3656ea36c2a1f4bc0b Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Tue, 18 Jun 2024 10:35:56 +0000 Subject: [PATCH 0002/2194] Use a dedicated type instead of a reference for the diagnostic context This paves the way for tracking more state (e.g. error tainting) in the diagnostic context handle --- src/parse/macros/cfg_if.rs | 2 +- src/parse/macros/lazy_static.rs | 6 +++--- src/parse/macros/mod.rs | 6 +++--- src/parse/session.rs | 8 +++++--- 4 files changed, 12 insertions(+), 10 deletions(-) diff --git a/src/parse/macros/cfg_if.rs b/src/parse/macros/cfg_if.rs index 5fc988e431935..b91d203d53118 100644 --- a/src/parse/macros/cfg_if.rs +++ b/src/parse/macros/cfg_if.rs @@ -67,7 +67,7 @@ fn parse_cfg_if_inner<'a>( Ok(None) => continue, Err(err) => { err.cancel(); - parser.psess.dcx.reset_err_count(); + parser.psess.dcx().reset_err_count(); return Err( "Expected item inside cfg_if block, but failed to parse it as an item", ); diff --git a/src/parse/macros/lazy_static.rs b/src/parse/macros/lazy_static.rs index badd956995007..7026935294ace 100644 --- a/src/parse/macros/lazy_static.rs +++ b/src/parse/macros/lazy_static.rs @@ -16,8 +16,8 @@ pub(crate) fn parse_lazy_static( ($method:ident $(,)* $($arg:expr),* $(,)*) => { match parser.$method($($arg,)*) { Ok(val) => { - if parser.psess.dcx.has_errors().is_some() { - parser.psess.dcx.reset_err_count(); + if parser.psess.dcx().has_errors().is_some() { + parser.psess.dcx().reset_err_count(); return None; } else { val @@ -25,7 +25,7 @@ pub(crate) fn parse_lazy_static( } Err(err) => { err.cancel(); - parser.psess.dcx.reset_err_count(); + parser.psess.dcx().reset_err_count(); return None; } } diff --git a/src/parse/macros/mod.rs b/src/parse/macros/mod.rs index cbcc0b2d63648..89169e10715b2 100644 --- a/src/parse/macros/mod.rs +++ b/src/parse/macros/mod.rs @@ -29,8 +29,8 @@ fn parse_macro_arg<'a, 'b: 'a>(parser: &'a mut Parser<'b>) -> Option { if Parser::nonterminal_may_begin_with($nt_kind, &cloned_parser.token) { match $try_parse(&mut cloned_parser) { Ok(x) => { - if parser.psess.dcx.has_errors().is_some() { - parser.psess.dcx.reset_err_count(); + if parser.psess.dcx().has_errors().is_some() { + parser.psess.dcx().reset_err_count(); } else { // Parsing succeeded. *parser = cloned_parser; @@ -39,7 +39,7 @@ fn parse_macro_arg<'a, 'b: 'a>(parser: &'a mut Parser<'b>) -> Option { } Err(e) => { e.cancel(); - parser.psess.dcx.reset_err_count(); + parser.psess.dcx().reset_err_count(); } } } diff --git a/src/parse/session.rs b/src/parse/session.rs index 1a39d212386bd..f4fbabaf6c91b 100644 --- a/src/parse/session.rs +++ b/src/parse/session.rs @@ -210,7 +210,9 @@ impl ParseSess { rustc_driver::DEFAULT_LOCALE_RESOURCES.to_vec(), false, ); - self.raw_psess.dcx.make_silent(fallback_bundle, None, false); + self.raw_psess + .dcx() + .make_silent(fallback_bundle, None, false); } pub(crate) fn span_to_filename(&self, span: Span) -> FileName { @@ -286,11 +288,11 @@ impl ParseSess { } pub(super) fn has_errors(&self) -> bool { - self.raw_psess.dcx.has_errors().is_some() + self.raw_psess.dcx().has_errors().is_some() } pub(super) fn reset_errors(&self) { - self.raw_psess.dcx.reset_err_count(); + self.raw_psess.dcx().reset_err_count(); } } From ebce05434703268c292520cc385568019c5ec353 Mon Sep 17 00:00:00 2001 From: Caleb Cartwright Date: Sat, 22 Jun 2024 15:33:45 -0500 Subject: [PATCH 0003/2194] Merge commit 'e4944185ae09c99f59b460e358909f329010ea9c' into sync-from-rustfmt-24-06 --- .github/workflows/integration.yml | 1 - CHANGELOG.md | 107 +++++++- Cargo.lock | 61 ++--- Cargo.toml | 11 +- Configurations.md | 39 ++- Contributing.md | 2 +- Processes.md | 2 +- build.rs | 4 +- check_diff/.gitignore | 1 + check_diff/Cargo.lock | 237 ++++++++++++++++++ check_diff/Cargo.toml | 9 + check_diff/src/main.rs | 25 ++ ci/check_diff.sh | 46 +++- ci/integration.sh | 2 +- config_proc_macro/src/attrs.rs | 6 +- docs/index.html | 32 ++- intellij.md | 2 +- rust-toolchain | 2 +- src/attr.rs | 16 +- src/bin/main.rs | 17 +- src/cargo-fmt/main.rs | 9 +- src/cargo-fmt/test/mod.rs | 22 +- src/comment.rs | 49 ++-- src/config/config_type.rs | 22 +- src/config/mod.rs | 21 +- src/config/options.rs | 28 ++- src/config/style_edition.rs | 70 ++++++ src/emitter/checkstyle.rs | 14 +- src/emitter/diff.rs | 2 +- src/emitter/json.rs | 12 +- src/expr.rs | 31 ++- src/format-diff/main.rs | 18 +- src/formatting.rs | 2 +- src/formatting/generated.rs | 7 +- src/ignore_path.rs | 18 ++ src/imports.rs | 4 +- src/items.rs | 50 ++-- src/lib.rs | 16 +- src/macros.rs | 19 +- src/matches.rs | 18 +- src/overflow.rs | 28 ++- src/parse/macros/lazy_static.rs | 4 - src/parse/session.rs | 10 +- src/source_file.rs | 2 +- src/test/configuration_snippet.rs | 26 +- src/test/mod.rs | 24 +- src/types.rs | 31 ++- src/visitor.rs | 2 +- tests/config/issue-5801-v1.toml | 3 + tests/config/issue-5801-v2.toml | 3 + .../skip-files-issue-5065/main.rs | 2 +- tests/rustfmt/main.rs | 25 +- .../arrow_in_single_comment.rs | 10 + .../arrow_in_comments/multiple_arrows.rs | 14 ++ ...with_generated_marker_line_search_limit.rs | 10 + .../false_with_marker_out_scope_size.rs | 10 + .../false_with_zero_search_limit.rs | 9 + .../true_with_marker_in_scope_size.rs | 10 + .../true_with_marker_not_in_header.rs | 9 + tests/source/issue-3805.rs | 65 +++++ ...ute_unexpectedly_wraps_before_max_width.rs | 8 + ...ent_unexpectedly_wraps_before_max_width.rs | 17 ++ tests/source/issue-5987/two.rs | 13 + tests/source/issue-6059/repro.rs | 3 + tests/source/issue-6147/case_rustfmt_v1.rs | 20 ++ tests/source/issue-6147/case_rustfmt_v2.rs | 20 ++ tests/source/issue_5912.rs | 15 ++ tests/source/let_else.rs | 6 +- tests/source/no_arg_with_commnet.rs | 2 +- .../arrow_in_single_comment.rs | 10 + .../arrow_in_comments/multiple_arrows.rs | 19 ++ ...with_generated_marker_line_search_limit.rs | 10 + .../false_with_marker_out_scope_size.rs | 8 + .../false_with_zero_search_limit.rs | 8 + .../true_with_marker_in_scope_size.rs | 8 + .../true_with_marker_not_in_header.rs | 7 + tests/target/impl.rs | 5 + tests/target/issue-3805.rs | 94 +++++++ ...ttribute_does_not_wrap_within_max_width.rs | 8 + ...ute_unexpectedly_wraps_before_max_width.rs | 16 ++ .../comment_does_not_wrap_within_max_width.rs | 16 ++ ...ent_unexpectedly_wraps_before_max_width.rs | 18 ++ tests/target/issue-5885.rs | 3 + tests/target/issue-5987/one.rs | 13 + tests/target/issue-5987/two.rs | 12 + tests/target/issue-6059/additional.rs | 6 + tests/target/issue-6059/repro.rs | 3 + tests/target/issue-6105.rs | 1 + tests/target/issue-6147/case_rustfmt_v1.rs | 20 ++ tests/target/issue-6147/case_rustfmt_v2.rs | 20 ++ tests/target/issue_5912.rs | 15 ++ tests/target/issue_6069.rs | 3 + tests/target/issue_6158.rs | 7 + tests/target/issue_6159.rs | 3 + tests/target/let_else.rs | 6 +- tests/target/no_arg_with_commnet.rs | 2 +- tests/target/unsafe_attributes.rs | 34 +++ tests/target/unsafe_extern_blocks.rs | 18 ++ 98 files changed, 1563 insertions(+), 285 deletions(-) create mode 100644 check_diff/.gitignore create mode 100644 check_diff/Cargo.lock create mode 100644 check_diff/Cargo.toml create mode 100644 check_diff/src/main.rs create mode 100644 src/config/style_edition.rs create mode 100644 tests/config/issue-5801-v1.toml create mode 100644 tests/config/issue-5801-v2.toml create mode 100644 tests/source/arrow_in_comments/arrow_in_single_comment.rs create mode 100644 tests/source/arrow_in_comments/multiple_arrows.rs create mode 100644 tests/source/configs/format_generated_files/false_with_generated_marker_line_search_limit.rs create mode 100644 tests/source/configs/format_generated_files/false_with_marker_out_scope_size.rs create mode 100644 tests/source/configs/format_generated_files/false_with_zero_search_limit.rs create mode 100644 tests/source/configs/format_generated_files/true_with_marker_in_scope_size.rs create mode 100644 tests/source/configs/format_generated_files/true_with_marker_not_in_header.rs create mode 100644 tests/source/issue-3805.rs create mode 100644 tests/source/issue-5801/attribute_unexpectedly_wraps_before_max_width.rs create mode 100644 tests/source/issue-5801/comment_unexpectedly_wraps_before_max_width.rs create mode 100644 tests/source/issue-5987/two.rs create mode 100644 tests/source/issue-6059/repro.rs create mode 100644 tests/source/issue-6147/case_rustfmt_v1.rs create mode 100644 tests/source/issue-6147/case_rustfmt_v2.rs create mode 100644 tests/source/issue_5912.rs create mode 100644 tests/target/arrow_in_comments/arrow_in_single_comment.rs create mode 100644 tests/target/arrow_in_comments/multiple_arrows.rs create mode 100644 tests/target/configs/format_generated_files/false_with_generated_marker_line_search_limit.rs create mode 100644 tests/target/configs/format_generated_files/false_with_marker_out_scope_size.rs create mode 100644 tests/target/configs/format_generated_files/false_with_zero_search_limit.rs create mode 100644 tests/target/configs/format_generated_files/true_with_marker_in_scope_size.rs create mode 100644 tests/target/configs/format_generated_files/true_with_marker_not_in_header.rs create mode 100644 tests/target/issue-3805.rs create mode 100644 tests/target/issue-5801/attribute_does_not_wrap_within_max_width.rs create mode 100644 tests/target/issue-5801/attribute_unexpectedly_wraps_before_max_width.rs create mode 100644 tests/target/issue-5801/comment_does_not_wrap_within_max_width.rs create mode 100644 tests/target/issue-5801/comment_unexpectedly_wraps_before_max_width.rs create mode 100644 tests/target/issue-5885.rs create mode 100644 tests/target/issue-5987/one.rs create mode 100644 tests/target/issue-5987/two.rs create mode 100644 tests/target/issue-6059/additional.rs create mode 100644 tests/target/issue-6059/repro.rs create mode 100644 tests/target/issue-6105.rs create mode 100644 tests/target/issue-6147/case_rustfmt_v1.rs create mode 100644 tests/target/issue-6147/case_rustfmt_v2.rs create mode 100644 tests/target/issue_5912.rs create mode 100644 tests/target/issue_6069.rs create mode 100644 tests/target/issue_6158.rs create mode 100644 tests/target/issue_6159.rs create mode 100644 tests/target/unsafe_attributes.rs create mode 100644 tests/target/unsafe_extern_blocks.rs diff --git a/.github/workflows/integration.yml b/.github/workflows/integration.yml index 314ce0e84c61b..f0dd0cf73bbd4 100644 --- a/.github/workflows/integration.yml +++ b/.github/workflows/integration.yml @@ -19,7 +19,6 @@ jobs: matrix: integration: [ bitflags, - error-chain, log, mdbook, packed_simd, diff --git a/CHANGELOG.md b/CHANGELOG.md index ec4c682d2c4d0..89e90fb17ddbd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,99 @@ ## [Unreleased] +### Fixed + +- Fix an idempotency issue when rewriting where clauses in which rustfmt would continuously add a trailing comma `,` to the end of trailing line comments [#5941](https://github.com/rust-lang/rustfmt/issues/5941). +- Prevent enum variant attributes from wrapping one character early when using `version=Two` [#5801](https://github.com/rust-lang/rustfmt/issues/5801) +- Properly wrap macro matchers at the `max_width` when using `version=Two` and `format_macro_matchers=true` [#3805](https://github.com/rust-lang/rustfmt/issues/3805) +- Prevent panic when formatting trait declaration with non [Unicode Normalization Form] C (NFC) identifiers [#6069](https://github.com/rust-lang/rustfmt/issues/6069) + ```rust + // The ó below is two codepoints, ASCII o followed by U+0301 COMBINING ACUTE ACCENT. + // It NFC-normalizes to ó, U+00F3 LATIN SMALL LETTER O WITH ACUTE. + trait Foó: Bar {} + ``` + [unicode normalization form]: https://unicode.org/reports/tr15/ +- Ensure a space is added to a range expression, when the right hand side of the range expression is a binary expression that ends with a trailing period [#6059](https://github.com/rust-lang/rustfmt/issues/6059) + ```rust + let range = 3. / 2. ..4.; + ``` +- When using `version=Two`, comments in match arms that contain `=>` no longer prevent formatting [#5998](https://github.com/rust-lang/rustfmt/issues/5998) + ```rust + match a { + _ => + // comment with => + { + println!("A") + } + } + ``` +- Prevent panics when formatting input that contains the expanded form of `offset_of!` [#5885](https://github.com/rust-lang/rustfmt/issues/5885) [#6105](https://github.com/rust-lang/rustfmt/issues/6105) + ```rust + const _: () = builtin # offset_of(x, x); + ``` +- When using `version=Two` inner attributes in `match` expressions are correctly indented [#6147](https://github.com/rust-lang/rustfmt/issues/6147) + ```rust + pub fn main() { + match x { + #![attr1] + #![attr2] + _ => (), + } + } + ``` +- Output correct syntax for type ascription builtin [#6159](https://github.com/rust-lang/rustfmt/issues/6159) + ```rust + fn main() { + builtin # type_ascribe(10, usize) + } + ``` +- rustfmt no longer removes inner attributes from inline const blocks [#6158](https://github.com/rust-lang/rustfmt/issues/6158) + ```rust + fn main() { + const { + #![allow(clippy::assertions_on_constants)] + + assert!(1 < 2); + } + } + ``` +- rustfmt no longer removes `safe` and `unsafe` keywords from static items in extern blocks. + This helps support [`#![feature(unsafe_extern_blocks)]`](https://github.com/rust-lang/rust/issues/123743) [#6204](https://github.com/rust-lang/rustfmt/pull/6204) + ```rust + #![feature(unsafe_extern_blocks)] + + unsafe extern "C" { + safe static TEST1: i32; + unsafe static TEST2: i32; + } + ``` + + +### Changed + +- `hide_parse_errors` has been soft deprecated and it's been renamed to `show_parse_errors` [#5961](https://github.com/rust-lang/rustfmt/pull/5961). +- The diff output produced by `rustfmt --check` is more compatable with editors that support navigating directly to line numbers [#5971](https://github.com/rust-lang/rustfmt/pull/5971) +- When using `version=Two`, the `trace!` macro from the [log crate] is now formatted similarly to `debug!`, `info!`, `warn!`, and `error!` [#5987](https://github.com/rust-lang/rustfmt/issues/5987). + + [log crate]: https://crates.io/crates/log + + +### Added + +- `generated_marker_line_search_limit` is a new unstable configuration option that allows users to configure how many lines to search for an `@generated` marker when `format_generated_files=false` [#5658](https://github.com/rust-lang/rustfmt/issues/5658) + + +### Misc + +- Updating `dirs 4.0.0 -> 5.0.1` and `cargo_metadata 0.15.4 -> 0.18.0` [#6033] (https://github.com/rust-lang/rustfmt/issues/6033) + - For reference, here's the [dirs v5 changelog](https://github.com/dirs-dev/dirs-rs/blob/main/README.md#5) +- Updated [itertools v0.11 -> v0.12](https://github.com/rust-itertools/itertools/blob/v0.12.1/CHANGELOG.md#0120) [#6093](https://github.com/rust-lang/rustfmt/pull/6093) +- Addressed clap deprecations output when running `cargo check --features clap/deprecated` [#6101](https://github.com/rust-lang/rustfmt/pull/6101) +- Bumped bytecount `0.6.4` -> `0.6.8` to fix compilation issues with the `generic-simd` feature. See [bytecount#92] and [bytecount#93] + + [bytecount#92]: https://github.com/llogiq/bytecount/pull/92 + [bytecount#93]: https://github.com/llogiq/bytecount/pull/93 +- Replace the `lazy_static` dependency with `std::sync::OnceLock` [#6154](https://github.com/rust-lang/rustfmt/pull/6154) ## [1.7.0] 2023-10-22 @@ -27,7 +120,7 @@ } ``` - Prevent ICE when formatting `vec!{}` [#5735](https://github.com/rust-lang/rustfmt/issues/5735) -- Prevent internal trailing whitespace error when formatting an empty `macro_rules!` defintion e.g. `macro_rules! foo {}` [#5882](https://github.com/rust-lang/rustfmt/issues/5882) +- Prevent internal trailing whitespace error when formatting an empty `macro_rules!` definition e.g. `macro_rules! foo {}` [#5882](https://github.com/rust-lang/rustfmt/issues/5882) - Formatting doc comment lines that start with `.` or `)` won't be treated as ordered markdown lists because `.` or `)` must be preceded by a number to start an ordered markdown list [#5835](https://github.com/rust-lang/rustfmt/pull/5835) - Add parenthesis around closures when they're used as method receives, don't have a block body, and end with `.` [#4808](https://github.com/rust-lang/rustfmt/issues/4808) ```rust @@ -184,7 +277,7 @@ - Simplify the rustfmt help text by eliding the full path to the rustfmt binary path from the usage string when running `rustfmt --help` [#5214](https://github.com/rust-lang/rustfmt/issues/5214) -- Bumped the version for serveral dependencies. Most notably `dirs` `v2.0.1` -> `v4.0.0`. This changed the global user config directory on macOS from `$HOME/Library/Preferences` to `$HOME/Library/Application Support` [#5237](https://github.com/rust-lang/rustfmt/pull/5237) +- Bumped the version for several dependencies. Most notably `dirs` `v2.0.1` -> `v4.0.0`. This changed the global user config directory on macOS from `$HOME/Library/Preferences` to `$HOME/Library/Application Support` [#5237](https://github.com/rust-lang/rustfmt/pull/5237) ### Fixed @@ -942,7 +1035,7 @@ from formatting an attribute #3665 ### Fixed -- Do not remove path disambiugator inside macro #3142 +- Do not remove path disambiguator inside macro #3142 - Improve handling of Windows newlines #3141 - Fix alignment of a struct's fields (`struct_field_align_threshold` option) with the Visual `indent_style` #3165 - Fix a bug in formatting markdown lists within comments #3172 @@ -1031,7 +1124,7 @@ from formatting an attribute #3665 ### Changed -- Replace '--conifig-help' with '--config=help' cb10e06 +- Replace '--config-help' with '--config=help' cb10e06 - Improve formatting of slice patterns #2912 ### Fixed @@ -1075,7 +1168,7 @@ from formatting an attribute #3665 - Add max_width option for all heuristics c2ae39e - Add config option `format_macro_matchers` to format the metavariable matching patterns in macros 79c5ee8 - Add config option `format_macro_bodies` to format the bodies of macros 79c5ee8 -- Format exitential type fc307ff +- Format existential type fc307ff - Support raw identifiers in struct expressions f121b1a - Format Async block and async function 0b25f60 @@ -1131,7 +1224,7 @@ from formatting an attribute #3665 ### Changed -- Update rustc-ap-syntax to 128.0.0 and ustc-ap-rustc_target to 128.0.0 195395f +- Update rustc-ap-syntax to 128.0.0 and rustc-ap-rustc_target to 128.0.0 195395f - Put operands on its own line when each fits in a single line f8439ce - Improve CLI options 55ac062 1869888 798bffb 4d9de48 eca7796 8396da1 5d9f5aa @@ -1195,7 +1288,7 @@ from formatting an attribute #3665 - Do not collapse block around expr with condition on match arm 5b9b7d5 - Use vertical layout for complex attributes c77708f - Format array using heuristics for function calls 98c6f7b -- Implement stable ordering for impl items with the the following item priority: type, const, macro, then method fa80ddf +- Implement stable ordering for impl items with the following item priority: type, const, macro, then method fa80ddf - Reorder imports by default 164cf7d - Group `extern crate` by default 3a138a2 - Make `error_on_line_overflow` false by default f146711 diff --git a/Cargo.lock b/Cargo.lock index 8fcefa97489d8..2a1fffa50fed7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -98,12 +98,9 @@ dependencies = [ [[package]] name = "bytecount" -version = "0.6.4" +version = "0.6.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad152d03a2c813c80bb94fedbf3a3f02b28f793e39e7c214c8a0bcc196343de7" -dependencies = [ - "packed_simd", -] +checksum = "5ce89b21cab1437276d2650d57e971f9d548a2d9037cc231abdc0562b97498ce" [[package]] name = "camino" @@ -125,9 +122,9 @@ dependencies = [ [[package]] name = "cargo_metadata" -version = "0.15.4" +version = "0.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eee4243f1f26fc7a42710e7439c149e2b10b05472f88090acce52632f231a73a" +checksum = "fb9ac64500cc83ce4b9f8dafa78186aa008c8dea77a09b94cd307fd0cd5022a8" dependencies = [ "camino", "cargo-platform", @@ -217,9 +214,9 @@ checksum = "0e25ea47919b1560c4e3b7fe0aaab9becf5b84a10325ddf7db0f0ba5e1026499" [[package]] name = "dirs" -version = "4.0.0" +version = "5.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca3aa72a6f96ea37bbc5aa912f6788242832f75369bdfdadcb0e38423f100059" +checksum = "44c45a9d03d6676652bcb5e724c7e988de1acad23a711b5217ab9cbecbec2225" dependencies = [ "dirs-sys", ] @@ -236,13 +233,14 @@ dependencies = [ [[package]] name = "dirs-sys" -version = "0.3.7" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b1d1d91c932ef41c0f2663aa8b0ca0342d444d842c06914aa0a7e352d0bada6" +checksum = "520f05a5cbd335fae5a99ff7a6ab8627577660ee5cfd6a94a6a929b52ff0321c" dependencies = [ "libc", + "option-ext", "redox_users", - "winapi", + "windows-sys", ] [[package]] @@ -343,9 +341,9 @@ dependencies = [ [[package]] name = "itertools" -version = "0.10.3" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9a9d19fa1e79b6215ff29b9d6880b706147f16e9b1dbb1e4e5947b5b02bc5e3" +checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" dependencies = [ "either", ] @@ -368,12 +366,6 @@ version = "0.2.141" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3304a64d199bb964be99741b7a14d26972741915b3649639149b2479bb46f4b5" -[[package]] -name = "libm" -version = "0.2.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" - [[package]] name = "log" version = "0.4.16" @@ -408,16 +400,6 @@ dependencies = [ "winapi", ] -[[package]] -name = "num-traits" -version = "0.2.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c" -dependencies = [ - "autocfg", - "libm", -] - [[package]] name = "once_cell" version = "1.17.1" @@ -425,20 +407,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3" [[package]] -name = "overload" -version = "0.1.1" +name = "option-ext" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" +checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" [[package]] -name = "packed_simd" -version = "0.3.9" +name = "overload" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f9f08af0c877571712e2e3e686ad79efad9657dbf0f7c3c8ba943ff6c38932d" -dependencies = [ - "cfg-if", - "num-traits", -] +checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" [[package]] name = "pin-project-lite" @@ -521,7 +499,7 @@ dependencies = [ [[package]] name = "rustfmt-nightly" -version = "1.7.0" +version = "1.7.1" dependencies = [ "annotate-snippets", "anyhow", @@ -534,7 +512,6 @@ dependencies = [ "getopts", "ignore", "itertools", - "lazy_static", "regex", "rustfmt-config_proc_macro", "serde", diff --git a/Cargo.toml b/Cargo.toml index 032b9b548104b..a16620ed99bc9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "rustfmt-nightly" -version = "1.7.0" +version = "1.7.1" description = "Tool to find and fix Rust formatting issues" repository = "https://github.com/rust-lang/rustfmt" readme = "README.md" @@ -35,16 +35,15 @@ generic-simd = ["bytecount/generic-simd"] [dependencies] annotate-snippets = { version = "0.9", features = ["color"] } anyhow = "1.0" -bytecount = "0.6.4" -cargo_metadata = "0.15.4" +bytecount = "0.6.8" +cargo_metadata = "0.18" clap = { version = "4.4.2", features = ["derive"] } clap-cargo = "0.12.0" diff = "0.1" -dirs = "4.0" +dirs = "5.0" getopts = "0.2" ignore = "0.4" -itertools = "0.11" -lazy_static = "1.4" +itertools = "0.12" regex = "1.7" serde = { version = "1.0.160", features = ["derive"] } serde_json = "1.0" diff --git a/Configurations.md b/Configurations.md index ac5747800b258..f52c25731549c 100644 --- a/Configurations.md +++ b/Configurations.md @@ -1,6 +1,6 @@ # Configuring Rustfmt -Rustfmt is designed to be very configurable. You can create a TOML file called `rustfmt.toml` or `.rustfmt.toml`, place it in the project or any other parent directory and it will apply the options in that file. If none of these directories contain such a file, both your home directory and a directory called `rustfmt` in your [global config directory](https://docs.rs/dirs/4.0.0/dirs/fn.config_dir.html) (e.g. `.config/rustfmt/`) are checked as well. +Rustfmt is designed to be very configurable. You can create a TOML file called `rustfmt.toml` or `.rustfmt.toml`, place it in the project or any other parent directory and it will apply the options in that file. If none of these directories contain such a file, both your home directory and a directory called `rustfmt` in your [global config directory](https://docs.rs/dirs/5.0.1/dirs/fn.config_dir.html) (e.g. `.config/rustfmt/`) are checked as well. A possible content of `rustfmt.toml` or `.rustfmt.toml` might look like this: @@ -1050,8 +1050,8 @@ Max width for code snippets included in doc comments. Only used if [`format_code ## `format_generated_files` -Format generated files. A file is considered generated -if any of the first five lines contain a `@generated` comment marker. +Format generated files. A file is considered generated if any of the first several lines contain a `@generated` comment marker. The number of lines to check is configured by `generated_marker_line_search_limit`. + By default, generated files are reformatted, i. e. `@generated` marker is ignored. This option is currently ignored for stdin (`@generated` in stdin is ignored.) @@ -1059,6 +1059,16 @@ This option is currently ignored for stdin (`@generated` in stdin is ignored.) - **Possible values**: `true`, `false` - **Stable**: No (tracking issue: [#5080](https://github.com/rust-lang/rustfmt/issues/5080)) +## `generated_marker_line_search_limit` + +Number of lines to check for a `@generated` pragma header, starting from the top of the file. Setting this value to `0` will treat all files as non-generated. When`format_generated_files` is `true`, this option has no effect. + +- **Default value**: `5` +- **Possible values**: any positive integer +- **Stable**: No (tracking issue: [#5080](https://github.com/rust-lang/rustfmt/issues/5080)) + +See also [format_generated_files](#format_generated_files) link here. + ## `format_macro_matchers` Format the metavariable matching patterns in macros. @@ -1098,7 +1108,7 @@ See also [`format_macro_bodies`](#format_macro_bodies). ## `format_macro_bodies` -Format the bodies of macros. +Format the bodies of declarative macro definitions. - **Default value**: `true` - **Possible values**: `true`, `false` @@ -1248,12 +1258,20 @@ Control the case of the letters in hexadecimal literal values ## `hide_parse_errors` -Do not show parse errors if the parser failed to parse files. +This option is deprecated and has been renamed to `show_parse_errors` to avoid confusion around the double negative default of `hide_parse_errors=false`. - **Default value**: `false` - **Possible values**: `true`, `false` - **Stable**: No (tracking issue: [#3390](https://github.com/rust-lang/rustfmt/issues/3390)) +## `show_parse_errors` + +Show parse errors if the parser failed to parse files. + +- **Default value**: `true` +- **Possible values**: `true`, `false` +- **Stable**: No (tracking issue: [#5977](https://github.com/rust-lang/rustfmt/issues/5977)) + ## `ignore` Skip formatting files and directories that match the specified pattern. @@ -1288,6 +1306,15 @@ If you want to ignore every file under the directory where you put your rustfmt. ignore = ["/"] ``` +If you want to allow specific paths that would otherwise be ignored, prefix those paths with a `!`: + +```toml +ignore = ["bar_dir/*", "!bar_dir/*/what.rs"] +``` + +In this case, all files under `bar_dir` will be ignored, except files like `bar_dir/sub/what.rs` +or `bar_dir/another/what.rs`. + ## `imports_indent` Indent style of imports @@ -1655,7 +1682,7 @@ use core::slice; Controls whether arm bodies are wrapped in cases where the first line of the body cannot fit on the same line as the `=>` operator. -The Style Guide requires that bodies are block wrapped by default if a line break is required after the `=>`, but this option can be used to disable that behavior to prevent wrapping arm bodies in that event, so long as the body does not contain multiple statements nor line comments. +The Style Guide requires that bodies are block wrapped by default if a line break is required after the `=>`, but this option can be used to disable that behavior to prevent wrapping arm bodies in that event, so long as the body contains neither multiple statements nor line comments. - **Default value**: `true` - **Possible values**: `true`, `false` diff --git a/Contributing.md b/Contributing.md index 69a2c76369f97..2f2ccfb175a92 100644 --- a/Contributing.md +++ b/Contributing.md @@ -59,7 +59,7 @@ example, the `issue-1111.rs` test file is configured by the file ## Debugging Some `rewrite_*` methods use the `debug!` macro for printing useful information. -These messages can be printed by using the environment variable `RUSTFMT_LOG=rustfmt=DEBUG`. +These messages can be printed by using the environment variable `RUSTFMT_LOG=debug`. These traces can be helpful in understanding which part of the code was used and get a better grasp on the execution flow. diff --git a/Processes.md b/Processes.md index 61abc87eec9ff..64ef20a9bd76d 100644 --- a/Processes.md +++ b/Processes.md @@ -16,7 +16,7 @@ In this Section, we describe how to stabilise an option of the rustfmt's configu Open a pull request that closes the tracking issue. The tracking issue is listed beside the option in `Configurations.md`. - Update the `Config` enum marking the option as stable. -- Update the the `Configuration.md` file marking the option as stable. +- Update the `Configuration.md` file marking the option as stable. - Update `CHANGELOG.md` marking the option as stable. ## After the stabilisation diff --git a/build.rs b/build.rs index e7b1e1b854c07..9a8bb77a8ed19 100644 --- a/build.rs +++ b/build.rs @@ -40,7 +40,7 @@ fn channel() -> String { fn commit_hash() -> Option { Command::new("git") - .args(&["rev-parse", "--short", "HEAD"]) + .args(["rev-parse", "--short", "HEAD"]) .output() .ok() .and_then(|r| String::from_utf8(r.stdout).ok()) @@ -48,7 +48,7 @@ fn commit_hash() -> Option { fn commit_date() -> Option { Command::new("git") - .args(&["log", "-1", "--date=short", "--pretty=format:%cd"]) + .args(["log", "-1", "--date=short", "--pretty=format:%cd"]) .output() .ok() .and_then(|r| String::from_utf8(r.stdout).ok()) diff --git a/check_diff/.gitignore b/check_diff/.gitignore new file mode 100644 index 0000000000000..ea8c4bf7f35f6 --- /dev/null +++ b/check_diff/.gitignore @@ -0,0 +1 @@ +/target diff --git a/check_diff/Cargo.lock b/check_diff/Cargo.lock new file mode 100644 index 0000000000000..6716ccdf9a08c --- /dev/null +++ b/check_diff/Cargo.lock @@ -0,0 +1,237 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "anstream" +version = "0.6.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "418c75fa768af9c03be99d17643f93f79bbba589895012a80e3452a19ddda15b" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "is_terminal_polyfill", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "038dfcf04a5feb68e9c60b21c9625a54c2c0616e79b72b0fd87075a056ae1d1b" + +[[package]] +name = "anstyle-parse" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c03a11a9034d92058ceb6ee011ce58af4a9bf61491aa7e1e59ecd24bd40d22d4" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a64c907d4e79225ac72e2a354c9ce84d50ebb4586dee56c82b3ee73004f537f5" +dependencies = [ + "windows-sys", +] + +[[package]] +name = "anstyle-wincon" +version = "3.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61a38449feb7068f52bb06c12759005cf459ee52bb4adc1d5a7c4322d716fb19" +dependencies = [ + "anstyle", + "windows-sys", +] + +[[package]] +name = "check_diff" +version = "0.1.0" +dependencies = [ + "clap", +] + +[[package]] +name = "clap" +version = "4.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90bc066a67923782aa8515dbaea16946c5bcc5addbd668bb80af688e53e548a0" +dependencies = [ + "clap_builder", + "clap_derive", +] + +[[package]] +name = "clap_builder" +version = "4.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae129e2e766ae0ec03484e609954119f123cc1fe650337e155d03b022f24f7b4" +dependencies = [ + "anstream", + "anstyle", + "clap_lex", + "strsim", +] + +[[package]] +name = "clap_derive" +version = "4.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "528131438037fd55894f62d6e9f068b8f45ac57ffa77517819645d10aed04f64" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "clap_lex" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "98cc8fbded0c607b7ba9dd60cd98df59af97e84d24e49c8557331cfc26d301ce" + +[[package]] +name = "colorchoice" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b6a852b24ab71dffc585bcb46eaf7959d175cb865a7152e35b348d1b2960422" + +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + +[[package]] +name = "is_terminal_polyfill" +version = "1.70.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8478577c03552c21db0e2724ffb8986a5ce7af88107e6be5d2ee6e158c12800" + +[[package]] +name = "proc-macro2" +version = "1.0.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b33eb56c327dec362a9e55b3ad14f9d2f0904fb5a5b03b513ab5465399e9f43" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "strsim" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" + +[[package]] +name = "syn" +version = "2.0.66" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c42f3f41a2de00b01c0aaad383c5a45241efc8b2d1eda5661812fda5f3cdcff5" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "unicode-ident" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" + +[[package]] +name = "utf8parse" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0" diff --git a/check_diff/Cargo.toml b/check_diff/Cargo.toml new file mode 100644 index 0000000000000..a1ed154481a96 --- /dev/null +++ b/check_diff/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "check_diff" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +clap = { version = "4.4.2", features = ["derive"] } diff --git a/check_diff/src/main.rs b/check_diff/src/main.rs new file mode 100644 index 0000000000000..6d07c1b0df65e --- /dev/null +++ b/check_diff/src/main.rs @@ -0,0 +1,25 @@ +use clap::Parser; +/// Inputs for the check_diff script +#[derive(Parser)] +struct CliInputs { + /// Git url of a rustfmt fork to compare against the latest master rustfmt + remote_repo_url: String, + /// Name of the feature branch on the forked repo + feature_branch: String, + /// Optional commit hash from the feature branch + #[arg(short, long)] + commit_hash: Option, + /// Optional comma separated list of rustfmt config options to + /// pass when running the feature branch + #[arg(value_delimiter = ',', short, long, num_args = 1..)] + rustfmt_config: Option>, +} + +fn main() { + let args = CliInputs::parse(); + println!( + "remote_repo_url: {:?}, feature_branch: {:?}, + optional_commit_hash: {:?}, optional_rustfmt_config: {:?}", + args.remote_repo_url, args.feature_branch, args.commit_hash, args.rustfmt_config + ); +} diff --git a/ci/check_diff.sh b/ci/check_diff.sh index 50c58b1f49250..2a29cb138ef79 100755 --- a/ci/check_diff.sh +++ b/ci/check_diff.sh @@ -2,9 +2,6 @@ set -e -# https://github.com/rust-lang/rustfmt/issues/5675 -export LD_LIBRARY_PATH=$(rustc --print sysroot)/lib:$LD_LIBRARY_PATH - function print_usage() { echo "usage check_diff REMOTE_REPO FEATURE_BRANCH [COMMIT_HASH] [OPTIONAL_RUSTFMT_CONFIGS]" } @@ -31,7 +28,7 @@ function clone_repo() { GIT_TERMINAL_PROMPT=0 git clone --quiet $1 --depth 1 $2 && cd $2 } -# Initialize Git submoduels for the repo. +# Initialize Git submodules for the repo. # # Parameters # $1: list of directories to initialize @@ -46,7 +43,7 @@ function init_submodules() { # $2: Output file path for the diff # $3: Any additional configuration options to pass to rustfmt # -# Globlas: +# Globals: # $OPTIONAL_RUSTFMT_CONFIGS: Optional configs passed to the script from $4 function create_diff() { local config; @@ -67,7 +64,7 @@ function create_diff() { # Parameters # $1: Name of the repository (used for logging) # -# Globlas: +# Globals: # $RUSFMT_BIN: Path to the rustfmt master binary. Created when running `compile_rustfmt` # $FEATURE_BIN: Path to the rustfmt feature binary. Created when running `compile_rustfmt` # $OPTIONAL_RUSTFMT_CONFIGS: Optional configs passed to the script from $4 @@ -90,7 +87,7 @@ function check_diff() { ) if [ -z "$diff" ]; then - echo "no diff detected between rustfmt and the feture branch" + echo "no diff detected between rustfmt and the feature branch" return 0 else echo "$diff" @@ -104,7 +101,7 @@ function check_diff() { # Parameters: # $1: Directory where rustfmt will be cloned # -# Globlas: +# Globals: # $REMOTE_REPO: Clone URL to the rustfmt fork that we want to test # $FEATURE_BRANCH: Name of the feature branch # $OPTIONAL_COMMIT_HASH: Optional commit hash that will be checked out if provided @@ -114,15 +111,42 @@ function compile_rustfmt() { git remote add feature $REMOTE_REPO git fetch feature $FEATURE_BRANCH - cargo build --release --bin rustfmt && cp target/release/rustfmt $1/rustfmt + CARGO_VERSION=$(cargo --version) + echo -e "\ncompiling with $CARGO_VERSION\n" + + # Because we're building standalone binaries we need to set `LD_LIBRARY_PATH` so each + # binary can find it's runtime dependencies. See https://github.com/rust-lang/rustfmt/issues/5675 + # This will prepend the `LD_LIBRARY_PATH` for the master rustfmt binary + export LD_LIBRARY_PATH=$(rustc --print sysroot)/lib:$LD_LIBRARY_PATH + + echo "Building rustfmt from src" + cargo build -q --release --bin rustfmt && cp target/release/rustfmt $1/rustfmt + if [ -z "$OPTIONAL_COMMIT_HASH" ] || [ "$FEATURE_BRANCH" = "$OPTIONAL_COMMIT_HASH" ]; then git switch $FEATURE_BRANCH else git switch $OPTIONAL_COMMIT_HASH --detach fi - cargo build --release --bin rustfmt && cp target/release/rustfmt $1/feature_rustfmt + + # This will prepend the `LD_LIBRARY_PATH` for the feature branch rustfmt binary. + # In most cases the `LD_LIBRARY_PATH` should be the same for both rustfmt binaries that we build + # in `compile_rustfmt`, however, there are scenarios where each binary has different runtime + # dependencies. For example, during subtree syncs we bump the nightly toolchain required to build + # rustfmt, and therefore the feature branch relies on a newer set of runtime dependencies. + export LD_LIBRARY_PATH=$(rustc --print sysroot)/lib:$LD_LIBRARY_PATH + + echo "Building feature rustfmt from src" + cargo build -q --release --bin rustfmt && cp target/release/rustfmt $1/feature_rustfmt + + echo -e "\nRuntime dependencies for rustfmt -- LD_LIBRARY_PATH: $LD_LIBRARY_PATH" + RUSFMT_BIN=$1/rustfmt + RUSTFMT_VERSION=$($RUSFMT_BIN --version) + echo -e "\nRUSFMT_BIN $RUSTFMT_VERSION\n" + FEATURE_BIN=$1/feature_rustfmt + FEATURE_VERSION=$($FEATURE_BIN --version) + echo -e "FEATURE_BIN $FEATURE_VERSION\n" } # Check the diff for running rustfmt and the feature branch on all the .rs files in the repo. @@ -155,7 +179,7 @@ function check_repo() { STATUSES+=($?) set -e - echo "removing tmp_dir $tmp_dir" + echo -e "removing tmp_dir $tmp_dir\n\n" rm -rf $tmp_dir cd $WORKDIR } diff --git a/ci/integration.sh b/ci/integration.sh index 19d502bc5c7bd..ea96e4be1305f 100755 --- a/ci/integration.sh +++ b/ci/integration.sh @@ -104,7 +104,7 @@ case ${INTEGRATION} in check_fmt_with_all_tests cd - ;; - error-chain | tempdir) + tempdir) git clone --depth=1 https://github.com/rust-lang-deprecated/${INTEGRATION}.git cd ${INTEGRATION} show_head diff --git a/config_proc_macro/src/attrs.rs b/config_proc_macro/src/attrs.rs index d8de9aae088d7..e7534b813d706 100644 --- a/config_proc_macro/src/attrs.rs +++ b/config_proc_macro/src/attrs.rs @@ -68,7 +68,11 @@ fn get_name_value_str_lit(attr: &syn::Attribute, name: &str) -> Option { match &attr.meta { syn::Meta::NameValue(syn::MetaNameValue { path, - value: syn::Expr::Lit(syn::ExprLit { lit: syn::Lit::Str(lit_str), .. }), + value: + syn::Expr::Lit(syn::ExprLit { + lit: syn::Lit::Str(lit_str), + .. + }), .. }) if path.is_ident(name) => Some(lit_str.value()), _ => None, diff --git a/docs/index.html b/docs/index.html index ee0339bc50da3..5e588d1db5451 100644 --- a/docs/index.html +++ b/docs/index.html @@ -3,13 +3,33 @@ Rustfmt - - - - + + + + + + - - - + -
-
🖌
-
    -
  • {{name}}
  • -
+
+
+
+
Theme
+ + +
@@ -592,7 +239,7 @@

Applicability: - {{lint.applicability.applicability}} + {{lint.applicability}} (?)
@@ -605,8 +252,8 @@

Related Issues

-
diff --git a/util/gh-pages/script.js b/util/gh-pages/script.js index ed1e090e1b540..1a5330bc0e571 100644 --- a/util/gh-pages/script.js +++ b/util/gh-pages/script.js @@ -50,24 +50,6 @@ ); }; }) - .directive('themeDropdown', function ($document) { - return { - restrict: 'A', - link: function ($scope, $element, $attr) { - $element.bind('click', function () { - $element.toggleClass('open'); - $element.addClass('open-recent'); - }); - - $document.bind('click', function () { - if (!$element.hasClass('open-recent')) { - $element.removeClass('open'); - } - $element.removeClass('open-recent'); - }) - } - } - }) .directive('filterDropdown', function ($document) { return { restrict: 'A', @@ -114,28 +96,19 @@ cargo: true, complexity: true, correctness: true, - deprecated: false, nursery: true, pedantic: true, perf: true, restriction: true, style: true, suspicious: true, + deprecated: false, } $scope.groups = { ...GROUPS_FILTER_DEFAULT }; - const THEMES_DEFAULT = { - light: "Light", - rust: "Rust", - coal: "Coal", - navy: "Navy", - ayu: "Ayu" - }; - $scope.themes = THEMES_DEFAULT; - $scope.versionFilters = { "≥": {enabled: false, minorVersion: null }, "≤": {enabled: false, minorVersion: null }, @@ -153,11 +126,10 @@ ); const APPLICABILITIES_FILTER_DEFAULT = { - Unspecified: true, - Unresolved: true, MachineApplicable: true, MaybeIncorrect: true, - HasPlaceholders: true + HasPlaceholders: true, + Unspecified: true, }; $scope.applicabilities = { @@ -321,10 +293,6 @@ $location.path($scope.search); } - $scope.selectTheme = function (theme) { - setTheme(theme, true); - } - $scope.toggleLevels = function (value) { const levels = $scope.levels; for (const key in levels) { @@ -456,7 +424,7 @@ } $scope.byApplicabilities = function (lint) { - return $scope.applicabilities[lint.applicability.applicability]; + return $scope.applicabilities[lint.applicability]; }; // Show details for one lint @@ -537,6 +505,16 @@ function getQueryVariable(variable) { } } +function storeValue(settingName, value) { + try { + localStorage.setItem(`clippy-lint-list-${settingName}`, value); + } catch (e) { } +} + +function loadValue(settingName) { + return localStorage.getItem(`clippy-lint-list-${settingName}`); +} + function setTheme(theme, store) { let enableHighlight = false; let enableNight = false; @@ -569,14 +547,14 @@ function setTheme(theme, store) { document.getElementById("styleAyu").disabled = !enableAyu; if (store) { - try { - localStorage.setItem('clippy-lint-list-theme', theme); - } catch (e) { } + storeValue("theme", theme); + } else { + document.getElementById(`theme-choice`).value = theme; } } function handleShortcut(ev) { - if (ev.ctrlKey || ev.altKey || ev.metaKey) { + if (ev.ctrlKey || ev.altKey || ev.metaKey || disableShortcuts) { return; } @@ -601,11 +579,51 @@ function handleShortcut(ev) { document.addEventListener("keypress", handleShortcut); document.addEventListener("keydown", handleShortcut); +function changeSetting(elem) { + if (elem.id === "disable-shortcuts") { + disableShortcuts = elem.checked; + storeValue(elem.id, elem.checked); + } +} + +function onEachLazy(lazyArray, func) { + const arr = Array.prototype.slice.call(lazyArray); + for (const el of arr) { + func(el); + } +} + +function handleBlur(event) { + const parent = document.getElementById("settings-dropdown"); + if (!parent.contains(document.activeElement) && + !parent.contains(event.relatedTarget) + ) { + parent.classList.remove("open"); + } +} + +function generateSettings() { + const settings = document.getElementById("settings-dropdown"); + const settingsButton = settings.querySelector(".settings-icon") + settingsButton.onclick = () => settings.classList.toggle("open"); + settingsButton.onblur = handleBlur; + const settingsMenu = settings.querySelector(".settings-menu"); + settingsMenu.onblur = handleBlur; + onEachLazy( + settingsMenu.querySelectorAll("input"), + el => el.onblur = handleBlur, + ); +} + +generateSettings(); + // loading the theme after the initial load const prefersDark = window.matchMedia("(prefers-color-scheme: dark)"); -const theme = localStorage.getItem('clippy-lint-list-theme'); +const theme = loadValue('theme'); if (prefersDark.matches && !theme) { setTheme("coal", false); } else { setTheme(theme, false); } +let disableShortcuts = loadValue('disable-shortcuts') === "true"; +document.getElementById("disable-shortcuts").checked = disableShortcuts; diff --git a/util/gh-pages/style.css b/util/gh-pages/style.css new file mode 100644 index 0000000000000..a9485d511047a --- /dev/null +++ b/util/gh-pages/style.css @@ -0,0 +1,398 @@ +blockquote { font-size: 1em; } + +[ng\:cloak], [ng-cloak], [data-ng-cloak], [x-ng-cloak], .ng-cloak, .x-ng-cloak { + display: none !important; +} + +.dropdown-menu { + color: var(--fg); + background: var(--theme-popup-bg); + border: 1px solid var(--theme-popup-border); +} + +.dropdown-menu .divider { + background-color: var(--theme-popup-border); +} + +.dropdown-menu .checkbox { + display: block; + white-space: nowrap; + margin: 0; +} +.dropdown-menu .checkbox label { + padding: 3px 20px; + width: 100%; +} + +.dropdown-menu .checkbox input { + position: relative; + margin: 0 0.5rem 0; + padding: 0; +} + +.dropdown-menu .checkbox:hover { + background-color: var(--theme-hover); +} + +div.panel div.panel-body button { + background: var(--searchbar-bg); + color: var(--searchbar-fg); + border-color: var(--theme-popup-border); +} + +div.panel div.panel-body button:hover { + box-shadow: 0 0 3px var(--searchbar-shadow-color); +} + +div.panel div.panel-body button.open { + filter: brightness(90%); +} + +.dropdown-toggle .badge { + background-color: #777; +} + +.panel-heading { cursor: pointer; } + +.panel-title { display: flex; flex-wrap: wrap;} +.panel-title .label { display: inline-block; } + +.panel-title-name { flex: 1; min-width: 400px;} +.panel-title-name span { vertical-align: bottom; } + +.panel .panel-title-name .anchor { display: none; } +.panel:hover .panel-title-name .anchor { display: inline;} + +.search-control { + margin-top: 15px; +} + +@media (min-width: 992px) { + .search-control { + margin-top: 0; + } +} + +@media (min-width: 405px) { + #upper-filters { + display: flex; + flex-wrap: wrap; + } +} + +@media (max-width: 430px) { + /* Turn the version filter list to the left */ + #version-filter-selector { + right: 0; + left: auto; + } +} + +@media (max-width: 412px) { + #upper-filters, + .panel-body .search-control { + padding-right: 8px; + padding-left: 8px; + } +} + +.label { + padding-top: 0.3em; + padding-bottom: 0.3em; +} + +.label-lint-group { + min-width: 8em; +} +.label-lint-level { + min-width: 4em; +} + +.label-lint-level-allow { + background-color: #5cb85c; +} +.label-lint-level-warn { + background-color: #f0ad4e; +} +.label-lint-level-deny { + background-color: #d9534f; +} +.label-lint-level-none { + background-color: #777777; + opacity: 0.5; +} + +.label-group-deprecated { + opacity: 0.5; +} + +.label-doc-folding { + color: #000; + background-color: #fff; + border: 1px solid var(--theme-popup-border); +} +.label-doc-folding:hover { + background-color: #e6e6e6; +} + +.lint-doc-md > h3 { + border-top: 1px solid var(--theme-popup-border); + padding: 10px 15px; + margin: 0 -15px; + font-size: 18px; +} +.lint-doc-md > h3:first-child { + border-top: none; + padding-top: 0px; +} + +@media (max-width:749px) { + .lint-additional-info-container { + display: flex; + flex-flow: column; + } + .lint-additional-info-item + .lint-additional-info-item { + border-top: 1px solid var(--theme-popup-border); + } +} +@media (min-width:750px) { + .lint-additional-info-container { + display: flex; + flex-flow: row; + } + .lint-additional-info-item + .lint-additional-info-item { + border-left: 1px solid var(--theme-popup-border); + } +} + +.lint-additional-info-item { + display: inline-flex; + min-width: 200px; + flex-grow: 1; + padding: 9px 5px 5px 15px; +} + +.label-applicability { + background-color: #777777; + margin: auto 5px; +} + +.label-version { + background-color: #777777; + margin: auto 5px; + font-family: monospace; +} + +details { + border-radius: 4px; + padding: .5em .5em 0; +} + +code { + white-space: pre !important; +} + +summary { + font-weight: bold; + margin: -.5em -.5em 0; + padding: .5em; + display: revert; +} + +details[open] { + padding: .5em; +} + +/* Expanding the mdBook theme*/ +.light { + --inline-code-bg: #f6f7f6; +} +.rust { + --inline-code-bg: #f6f7f6; +} +.coal { + --inline-code-bg: #1d1f21; +} +.navy { + --inline-code-bg: #1d1f21; +} +.ayu { + --inline-code-bg: #191f26; +} + +#settings-dropdown { + position: absolute; + margin: 0.7em; + z-index: 10; + display: flex; +} + +/* Applying the mdBook theme */ +.settings-icon { + text-align: center; + width: 2em; + height: 2em; + line-height: 2em; + border: solid 1px var(--icons); + border-radius: 5px; + user-select: none; + cursor: pointer; + background: var(--theme-hover); +} +.settings-menu { + display: none; + list-style: none; + border: 1px solid var(--theme-popup-border); + border-radius: 5px; + color: var(--fg); + background: var(--theme-popup-bg); + overflow: hidden; + padding: 9px; + width: 207px; + position: absolute; + top: 28px; +} + +.settings-icon::before { + /* Wheel */ + content: url('data:image/svg+xml,\ +'); + width: 18px; + height: 18px; + display: block; + filter: invert(0.7); + padding-left: 4px; + padding-top: 3px; +} + +.settings-menu * { + font-weight: normal; +} + +.settings-menu label { + cursor: pointer; +} + +#settings-dropdown.open .settings-menu { + display: block; +} + +#theme-choice { + margin-bottom: 10px; + background: var(--searchbar-bg); + color: var(--searchbar-fg); + border-color: var(--theme-popup-border); + border-radius: 5px; + cursor: pointer; + width: 100%; + border-width: 1px; + padding: 5px; +} + +.alert { + color: var(--fg); + background: var(--theme-hover); + border: 1px solid var(--theme-popup-border); +} +.page-header { + border-color: var(--theme-popup-border); +} +.panel-default > .panel-heading { + background: var(--theme-hover); + color: var(--fg); + border: 1px solid var(--theme-popup-border); +} +.panel-default > .panel-heading:hover { + filter: brightness(90%); +} +.list-group-item { + background: 0%; + border: 1px solid var(--theme-popup-border); +} +.panel, pre, hr { + background: var(--bg); + border: 1px solid var(--theme-popup-border); +} + +#version-filter-selector .checkbox { + display: flex; +} + +#version-filter { + min-width: available; +} + +#version-filter li label { + padding-right: 0; + width: 35%; +} + +.version-filter-input { + height: 60%; + width: 30%; + text-align: center; + border: none; + border-bottom: 1px solid #000000; +} + +#filter-label, .filter-clear { + background: var(--searchbar-bg); + color: var(--searchbar-fg); + border-color: var(--theme-popup-border); + filter: brightness(95%); +} +#filter-label:hover, .filter-clear:hover { + filter: brightness(90%); +} +.filter-input { + background: var(--searchbar-bg); + color: var(--searchbar-fg); + border-color: var(--theme-popup-border); +} + +.filter-input::-webkit-input-placeholder, +.filter-input::-moz-placeholder { + color: var(--searchbar-fg); + opacity: 30%; +} + +.expansion-group { + margin-top: 15px; + padding: 0px 8px; + display: flex; + flex-wrap: nowrap; +} + +@media (min-width: 992px) { + .expansion-group { + margin-top: 0; + padding: 0px 15px; + } +} + +.expansion-control { + width: 50%; +} + +:not(pre) > code { + color: var(--inline-code-color); + background-color: var(--inline-code-bg); +} +html { + scrollbar-color: var(--scrollbar) var(--bg); +} +body { + background: var(--bg); + color: var(--fg); +} From 6f5e99b7b5a00a1bed4d29f323fce0c989cf28aa Mon Sep 17 00:00:00 2001 From: ding-young Date: Mon, 22 Jul 2024 14:55:54 +0900 Subject: [PATCH 0178/2194] update macro rewrite functions to return RewriteResult --- src/expr.rs | 17 ++-- src/items.rs | 2 +- src/macros.rs | 252 +++++++++++++++++++++++++++++------------------- src/patterns.rs | 2 +- src/rewrite.rs | 28 ++++++ src/types.rs | 2 +- src/visitor.rs | 5 +- 7 files changed, 198 insertions(+), 110 deletions(-) diff --git a/src/expr.rs b/src/expr.rs index 138689bc1320e..02372e7be130a 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -243,13 +243,16 @@ pub(crate) fn format_expr( | ast::ExprKind::MethodCall(..) | ast::ExprKind::Await(_, _) => rewrite_chain(expr, context, shape).ok(), ast::ExprKind::MacCall(ref mac) => { - rewrite_macro(mac, None, context, shape, MacroPosition::Expression).or_else(|| { - wrap_str( - context.snippet(expr.span).to_owned(), - context.config.max_width(), - shape, - ) - }) + rewrite_macro(mac, None, context, shape, MacroPosition::Expression) + .or_else(|_| { + wrap_str( + context.snippet(expr.span).to_owned(), + context.config.max_width(), + shape, + ) + .max_width_error(shape.width, expr.span) + }) + .ok() } ast::ExprKind::Ret(None) => Some("return".to_owned()), ast::ExprKind::Ret(Some(ref expr)) => { diff --git a/src/items.rs b/src/items.rs index 35591df0fd8f5..3894ee2cdf8c8 100644 --- a/src/items.rs +++ b/src/items.rs @@ -3427,7 +3427,7 @@ impl Rewrite for ast::ForeignItem { rewrite_type_alias(ty_alias, context, shape.indent, kind, span) } ast::ForeignItemKind::MacCall(ref mac) => { - rewrite_macro(mac, None, context, shape, MacroPosition::Item) + rewrite_macro(mac, None, context, shape, MacroPosition::Item).ok() } }?; diff --git a/src/macros.rs b/src/macros.rs index c520971f40c50..51ded8692296b 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -31,7 +31,9 @@ use crate::lists::{itemize_list, write_list, ListFormatting}; use crate::overflow; use crate::parse::macros::lazy_static::parse_lazy_static; use crate::parse::macros::{parse_expr, parse_macro_args, ParsedMacroArgs}; -use crate::rewrite::{Rewrite, RewriteContext, RewriteError}; +use crate::rewrite::{ + MacroErrorKind, Rewrite, RewriteContext, RewriteError, RewriteErrorExt, RewriteResult, +}; use crate::shape::{Indent, Shape}; use crate::source_map::SpanUtils; use crate::spanned::Spanned; @@ -71,22 +73,30 @@ impl MacroArg { impl Rewrite for ast::Item { fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option { + self.rewrite_result(context, shape).ok() + } + + fn rewrite_result(&self, context: &RewriteContext<'_>, shape: Shape) -> RewriteResult { let mut visitor = crate::visitor::FmtVisitor::from_context(context); visitor.block_indent = shape.indent; visitor.last_pos = self.span().lo(); visitor.visit_item(self); - Some(visitor.buffer.to_owned()) + Ok(visitor.buffer.to_owned()) } } impl Rewrite for MacroArg { fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option { + self.rewrite_result(context, shape).ok() + } + + fn rewrite_result(&self, context: &RewriteContext<'_>, shape: Shape) -> RewriteResult { match *self { - MacroArg::Expr(ref expr) => expr.rewrite(context, shape), - MacroArg::Ty(ref ty) => ty.rewrite(context, shape), - MacroArg::Pat(ref pat) => pat.rewrite(context, shape), - MacroArg::Item(ref item) => item.rewrite(context, shape), - MacroArg::Keyword(ident, _) => Some(ident.name.to_string()), + MacroArg::Expr(ref expr) => expr.rewrite_result(context, shape), + MacroArg::Ty(ref ty) => ty.rewrite_result(context, shape), + MacroArg::Pat(ref pat) => pat.rewrite_result(context, shape), + MacroArg::Item(ref item) => item.rewrite_result(context, shape), + MacroArg::Keyword(ident, _) => Ok(ident.name.to_string()), } } } @@ -110,12 +120,14 @@ fn rewrite_macro_name( } // Use this on failing to format the macro call. +// TODO(ding-young) We should also report macro parse failure to tell users why given snippet +// is left unformatted. One possible improvement is appending formatting error to context.report fn return_macro_parse_failure_fallback( context: &RewriteContext<'_>, indent: Indent, position: MacroPosition, span: Span, -) -> Option { +) -> RewriteResult { // Mark this as a failure however we format it context.macro_rewrite_failure.replace(true); @@ -133,7 +145,8 @@ fn return_macro_parse_failure_fallback( }) .unwrap_or(false); if is_like_block_indent_style { - return trim_left_preserve_layout(context.snippet(span), indent, context.config); + return trim_left_preserve_layout(context.snippet(span), indent, context.config) + .macro_error(MacroErrorKind::Unknown, span); } context.skipped_range.borrow_mut().push(( @@ -146,7 +159,7 @@ fn return_macro_parse_failure_fallback( if position == MacroPosition::Item { snippet.push(';'); } - Some(snippet) + Ok(snippet) } pub(crate) fn rewrite_macro( @@ -155,13 +168,13 @@ pub(crate) fn rewrite_macro( context: &RewriteContext<'_>, shape: Shape, position: MacroPosition, -) -> Option { +) -> RewriteResult { let should_skip = context .skip_context .macros .skip(context.snippet(mac.path.span)); if should_skip { - None + Err(RewriteError::SkipFormatting) } else { let guard = context.enter_macro(); let result = catch_unwind(AssertUnwindSafe(|| { @@ -175,9 +188,16 @@ pub(crate) fn rewrite_macro( ) })); match result { - Err(..) | Ok(None) => { + Err(..) => { context.macro_rewrite_failure.replace(true); - None + Err(RewriteError::MacroFailure { + kind: MacroErrorKind::Unknown, + span: mac.span(), + }) + } + Ok(Err(e)) => { + context.macro_rewrite_failure.replace(true); + Err(e) } Ok(rw) => rw, } @@ -191,11 +211,11 @@ fn rewrite_macro_inner( shape: Shape, position: MacroPosition, is_nested_macro: bool, -) -> Option { +) -> RewriteResult { if context.config.use_try_shorthand() { if let Some(expr) = convert_try_mac(mac, context) { context.leave_macro(); - return expr.rewrite(context, shape); + return expr.rewrite_result(context, shape); } } @@ -215,21 +235,27 @@ fn rewrite_macro_inner( if ts.is_empty() && !has_comment { return match style { Delimiter::Parenthesis if position == MacroPosition::Item => { - Some(format!("{macro_name}();")) - } - Delimiter::Bracket if position == MacroPosition::Item => { - Some(format!("{macro_name}[];")) + Ok(format!("{macro_name}();")) } - Delimiter::Parenthesis => Some(format!("{macro_name}()")), - Delimiter::Bracket => Some(format!("{macro_name}[]")), - Delimiter::Brace => Some(format!("{macro_name} {{}}")), + Delimiter::Bracket if position == MacroPosition::Item => Ok(format!("{macro_name}[];")), + Delimiter::Parenthesis => Ok(format!("{macro_name}()")), + Delimiter::Bracket => Ok(format!("{macro_name}[]")), + Delimiter::Brace => Ok(format!("{macro_name} {{}}")), _ => unreachable!(), }; } // Format well-known macros which cannot be parsed as a valid AST. if macro_name == "lazy_static!" && !has_comment { - if let success @ Some(..) = format_lazy_static(context, shape, ts.clone()) { - return success; + match format_lazy_static(context, shape, ts.clone(), mac.span()) { + Ok(rw) => return Ok(rw), + Err(err) => match err { + // We will move on to parsing macro args just like other macros + // if we could not parse lazy_static! with known syntax + RewriteError::MacroFailure { kind, span: _ } + if kind == MacroErrorKind::ParseFailure => {} + // If formatting fails even though parsing succeeds, return the err early + _ => return Err(err), + }, } } @@ -266,7 +292,7 @@ fn rewrite_macro_inner( Delimiter::Parenthesis => { // Handle special case: `vec!(expr; expr)` if vec_with_semi { - handle_vec_semi(context, shape, arg_vec, macro_name, style) + handle_vec_semi(context, shape, arg_vec, macro_name, style, mac.span()) } else { // Format macro invocation as function call, preserve the trailing // comma because not all macros support them. @@ -283,7 +309,6 @@ fn rewrite_macro_inner( Some(SeparatorTactic::Never) }, ) - .ok() .map(|rw| match position { MacroPosition::Item => format!("{};", rw), _ => rw, @@ -293,7 +318,7 @@ fn rewrite_macro_inner( Delimiter::Bracket => { // Handle special case: `vec![expr; expr]` if vec_with_semi { - handle_vec_semi(context, shape, arg_vec, macro_name, style) + handle_vec_semi(context, shape, arg_vec, macro_name, style, mac.span()) } else { // If we are rewriting `vec!` macro or other special macros, // then we can rewrite this as a usual array literal. @@ -317,14 +342,13 @@ fn rewrite_macro_inner( shape, force_trailing_comma, Some(original_style), - ) - .ok()?; + )?; let comma = match position { MacroPosition::Item => ";", _ => "", }; - Some(format!("{rewrite}{comma}")) + Ok(format!("{rewrite}{comma}")) } } Delimiter::Brace => { @@ -333,8 +357,8 @@ fn rewrite_macro_inner( // anything in between the braces (for now). let snippet = context.snippet(mac.span()).trim_start_matches(|c| c != '{'); match trim_left_preserve_layout(snippet, shape.indent, context.config) { - Some(macro_body) => Some(format!("{macro_name} {macro_body}")), - None => Some(format!("{macro_name} {snippet}")), + Some(macro_body) => Ok(format!("{macro_name} {macro_body}")), + None => Ok(format!("{macro_name} {snippet}")), } } _ => unreachable!(), @@ -347,28 +371,32 @@ fn handle_vec_semi( arg_vec: Vec, macro_name: String, delim_token: Delimiter, -) -> Option { + span: Span, +) -> RewriteResult { let (left, right) = match delim_token { Delimiter::Parenthesis => ("(", ")"), Delimiter::Bracket => ("[", "]"), _ => unreachable!(), }; - let mac_shape = shape.offset_left(macro_name.len())?; + // Should we return MaxWidthError, Or Macro failure + let mac_shape = shape + .offset_left(macro_name.len()) + .max_width_error(shape.width, span)?; // 8 = `vec![]` + `; ` or `vec!()` + `; ` let total_overhead = 8; let nested_shape = mac_shape.block_indent(context.config.tab_spaces()); - let lhs = arg_vec[0].rewrite(context, nested_shape)?; - let rhs = arg_vec[1].rewrite(context, nested_shape)?; + let lhs = arg_vec[0].rewrite_result(context, nested_shape)?; + let rhs = arg_vec[1].rewrite_result(context, nested_shape)?; if !lhs.contains('\n') && !rhs.contains('\n') && lhs.len() + rhs.len() + total_overhead <= shape.width { // macro_name(lhs; rhs) or macro_name[lhs; rhs] - Some(format!("{macro_name}{left}{lhs}; {rhs}{right}")) + Ok(format!("{macro_name}{left}{lhs}; {rhs}{right}")) } else { // macro_name(\nlhs;\nrhs\n) or macro_name[\nlhs;\nrhs\n] - Some(format!( + Ok(format!( "{}{}{}{};{}{}{}{}", macro_name, left, @@ -386,7 +414,7 @@ fn rewrite_empty_macro_def_body( context: &RewriteContext<'_>, span: Span, shape: Shape, -) -> Option { +) -> RewriteResult { // Create an empty, dummy `ast::Block` representing an empty macro body let block = ast::Block { stmts: vec![].into(), @@ -396,7 +424,7 @@ fn rewrite_empty_macro_def_body( tokens: None, could_be_bare_literal: false, }; - block.rewrite(context, shape) + block.rewrite_result(context, shape) } pub(crate) fn rewrite_macro_def( @@ -407,8 +435,8 @@ pub(crate) fn rewrite_macro_def( ident: symbol::Ident, vis: &ast::Visibility, span: Span, -) -> Option { - let snippet = Some(remove_trailing_white_spaces(context.snippet(span))); +) -> RewriteResult { + let snippet = Ok(remove_trailing_white_spaces(context.snippet(span))); if snippet.as_ref().map_or(true, |s| s.ends_with(';')) { return snippet; } @@ -443,7 +471,7 @@ pub(crate) fn rewrite_macro_def( let lo = context.snippet_provider.span_before(span, "{"); result += " "; result += &rewrite_empty_macro_def_body(context, span.with_lo(lo), shape)?; - return Some(result); + return Ok(result); } let branch_items = itemize_list( @@ -454,13 +482,14 @@ pub(crate) fn rewrite_macro_def( |branch| branch.span.lo(), |branch| branch.span.hi(), |branch| match branch.rewrite(context, arm_shape, multi_branch_style) { - Some(v) => Ok(v), + Ok(v) => Ok(v), // if the rewrite returned None because a macro could not be rewritten, then return the // original body - None if context.macro_rewrite_failure.get() => { + // TODO(ding-young) report rewrite error even if we return Ok with original snippet + Err(_) if context.macro_rewrite_failure.get() => { Ok(context.snippet(branch.body).trim().to_string()) } - None => Err(RewriteError::Unknown), + Err(e) => Err(e), }, context.snippet_provider.span_after(span, "{"), span.hi(), @@ -488,7 +517,7 @@ pub(crate) fn rewrite_macro_def( result += "}"; } - Some(result) + Ok(result) } fn register_metavariable( @@ -640,12 +669,13 @@ impl MacroArgKind { context: &RewriteContext<'_>, shape: Shape, use_multiple_lines: bool, - ) -> Option { - let rewrite_delimited_inner = |delim_tok, args| -> Option<(String, String, String)> { + ) -> RewriteResult { + type DelimitedArgsRewrite = Result<(String, String, String), RewriteError>; + let rewrite_delimited_inner = |delim_tok, args| -> DelimitedArgsRewrite { let inner = wrap_macro_args(context, args, shape)?; let (lhs, rhs) = delim_token_to_str(context, delim_tok, shape, false, inner.is_empty()); if lhs.len() + inner.len() + rhs.len() <= shape.width { - return Some((lhs, inner, rhs)); + return Ok((lhs, inner, rhs)); } let (lhs, rhs) = delim_token_to_str(context, delim_tok, shape, true, false); @@ -653,27 +683,27 @@ impl MacroArgKind { .block_indent(context.config.tab_spaces()) .with_max_width(context.config); let inner = wrap_macro_args(context, args, nested_shape)?; - Some((lhs, inner, rhs)) + Ok((lhs, inner, rhs)) }; match *self { - MacroArgKind::MetaVariable(ty, ref name) => Some(format!("${name}:{ty}")), + MacroArgKind::MetaVariable(ty, ref name) => Ok(format!("${name}:{ty}")), MacroArgKind::Repeat(delim_tok, ref args, ref another, ref tok) => { let (lhs, inner, rhs) = rewrite_delimited_inner(delim_tok, args)?; let another = another .as_ref() - .and_then(|a| a.rewrite(context, shape, use_multiple_lines)) + .and_then(|a| a.rewrite(context, shape, use_multiple_lines).ok()) .unwrap_or_else(|| "".to_owned()); let repeat_tok = pprust::token_to_string(tok); - Some(format!("${lhs}{inner}{rhs}{another}{repeat_tok}")) + Ok(format!("${lhs}{inner}{rhs}{another}{repeat_tok}")) } MacroArgKind::Delimited(delim_tok, ref args) => { rewrite_delimited_inner(delim_tok, args) .map(|(lhs, inner, rhs)| format!("{}{}{}", lhs, inner, rhs)) } - MacroArgKind::Separator(ref sep, ref prefix) => Some(format!("{prefix}{sep} ")), - MacroArgKind::Other(ref inner, ref prefix) => Some(format!("{prefix}{inner}")), + MacroArgKind::Separator(ref sep, ref prefix) => Ok(format!("{prefix}{sep} ")), + MacroArgKind::Other(ref inner, ref prefix) => Ok(format!("{prefix}{inner}")), } } } @@ -689,7 +719,7 @@ impl ParsedMacroArg { context: &RewriteContext<'_>, shape: Shape, use_multiple_lines: bool, - ) -> Option { + ) -> RewriteResult { self.kind.rewrite(context, shape, use_multiple_lines) } } @@ -967,9 +997,9 @@ fn wrap_macro_args( context: &RewriteContext<'_>, args: &[ParsedMacroArg], shape: Shape, -) -> Option { +) -> RewriteResult { wrap_macro_args_inner(context, args, shape, false) - .or_else(|| wrap_macro_args_inner(context, args, shape, true)) + .or_else(|_| wrap_macro_args_inner(context, args, shape, true)) } fn wrap_macro_args_inner( @@ -977,7 +1007,7 @@ fn wrap_macro_args_inner( args: &[ParsedMacroArg], shape: Shape, use_multiple_lines: bool, -) -> Option { +) -> RewriteResult { let mut result = String::with_capacity(128); let mut iter = args.iter().peekable(); let indent_str = shape.indent.to_string_with_newline(context.config); @@ -1003,9 +1033,9 @@ fn wrap_macro_args_inner( } if !use_multiple_lines && result.len() >= shape.width { - None + Err(RewriteError::Unknown) } else { - Some(result) + Ok(result) } } @@ -1013,22 +1043,21 @@ fn wrap_macro_args_inner( // for some common cases. I hope the basic logic is sufficient. Note that the // meaning of some tokens is a bit different here from usual Rust, e.g., `*` // and `(`/`)` have special meaning. -// -// We always try and format on one line. -// FIXME: Use multi-line when every thing does not fit on one line. fn format_macro_args( context: &RewriteContext<'_>, token_stream: TokenStream, shape: Shape, -) -> Option { +) -> RewriteResult { + let span = span_for_token_stream(&token_stream); if !context.config.format_macro_matchers() { - let span = span_for_token_stream(&token_stream); - return Some(match span { + return Ok(match span { Some(span) => context.snippet(span).to_owned(), None => String::new(), }); } - let parsed_args = MacroArgParser::new().parse(token_stream)?; + let parsed_args = MacroArgParser::new() + .parse(token_stream) + .macro_error(MacroErrorKind::ParseFailure, span.unwrap())?; wrap_macro_args(context, &parsed_args, shape) } @@ -1241,11 +1270,14 @@ impl MacroBranch { context: &RewriteContext<'_>, shape: Shape, multi_branch_style: bool, - ) -> Option { + ) -> RewriteResult { // Only attempt to format function-like macros. if self.args_paren_kind != Delimiter::Parenthesis { // FIXME(#1539): implement for non-sugared macros. - return None; + return Err(RewriteError::MacroFailure { + kind: MacroErrorKind::Unknown, + span: self.span, + }); } let old_body = context.snippet(self.body).trim(); @@ -1256,8 +1288,13 @@ impl MacroBranch { prefix_width = 6; // 6 = " => {{" } } - let mut result = - format_macro_args(context, self.args.clone(), shape.sub_width(prefix_width)?)?; + let mut result = format_macro_args( + context, + self.args.clone(), + shape + .sub_width(prefix_width) + .max_width_error(shape.width, self.span)?, + )?; if multi_branch_style { result += " =>"; @@ -1266,7 +1303,7 @@ impl MacroBranch { if !context.config.format_macro_bodies() { result += " "; result += context.snippet(self.whole_body); - return Some(result); + return Ok(result); } // The macro body is the most interesting part. It might end up as various @@ -1275,7 +1312,8 @@ impl MacroBranch { // `$$`). We'll try and format like an AST node, but we'll substitute // variables for new names with the same length first. - let (body_str, substs) = replace_names(old_body)?; + let (body_str, substs) = + replace_names(old_body).macro_error(MacroErrorKind::ReplaceMacroVariable, self.span)?; let mut config = context.config.clone(); config.set().show_parse_errors(false); @@ -1298,13 +1336,21 @@ impl MacroBranch { config.set().max_width(new_width); match crate::format_code_block(&body_str, &config, true) { Some(new_body) => new_body, - None => return None, + None => { + return Err(RewriteError::MacroFailure { + kind: MacroErrorKind::Unknown, + span: self.span, + }); + } } } }; if !filtered_str_fits(&new_body_snippet.snippet, config.max_width(), shape) { - return None; + return Err(RewriteError::ExceedsMaxWidth { + configured_width: shape.width, + span: self.span, + }); } // Indent the body since it is in a block. @@ -1330,7 +1376,10 @@ impl MacroBranch { for (old, new) in &substs { if old_body.contains(new) { debug!("rewrite_macro_def: bailing matching variable: `{}`", new); - return None; + return Err(RewriteError::MacroFailure { + kind: MacroErrorKind::ReplaceMacroVariable, + span: self.span, + }); } new_body = new_body.replace(new, old); } @@ -1345,7 +1394,7 @@ impl MacroBranch { result += "}"; - Some(result) + Ok(result) } } @@ -1365,7 +1414,8 @@ fn format_lazy_static( context: &RewriteContext<'_>, shape: Shape, ts: TokenStream, -) -> Option { + span: Span, +) -> RewriteResult { let mut result = String::with_capacity(1024); let nested_shape = shape .block_indent(context.config.tab_spaces()) @@ -1374,7 +1424,8 @@ fn format_lazy_static( result.push_str("lazy_static! {"); result.push_str(&nested_shape.indent.to_string_with_newline(context.config)); - let parsed_elems = parse_lazy_static(context, ts)?; + let parsed_elems = + parse_lazy_static(context, ts).macro_error(MacroErrorKind::ParseFailure, span)?; let last = parsed_elems.len() - 1; for (i, (vis, id, ty, expr)) in parsed_elems.iter().enumerate() { // Rewrite as a static item. @@ -1384,15 +1435,20 @@ fn format_lazy_static( "{}static ref {}: {} =", vis, id, - ty.rewrite(context, nested_shape)? + ty.rewrite_result(context, nested_shape)? )); - result.push_str(&rewrite_assign_rhs( - context, - stmt, - &*expr, - &RhsAssignKind::Expr(&expr.kind, expr.span), - nested_shape.sub_width(1)?, - )?); + result.push_str( + &rewrite_assign_rhs( + context, + stmt, + &*expr, + &RhsAssignKind::Expr(&expr.kind, expr.span), + nested_shape + .sub_width(1) + .max_width_error(nested_shape.width, expr.span)?, + ) + .unknown_error()?, + ); result.push(';'); if i != last { result.push_str(&nested_shape.indent.to_string_with_newline(context.config)); @@ -1402,7 +1458,7 @@ fn format_lazy_static( result.push_str(&shape.indent.to_string_with_newline(context.config)); result.push('}'); - Some(result) + Ok(result) } fn rewrite_macro_with_items( @@ -1414,12 +1470,12 @@ fn rewrite_macro_with_items( original_style: Delimiter, position: MacroPosition, span: Span, -) -> Option { +) -> RewriteResult { let style_to_delims = |style| match style { - Delimiter::Parenthesis => Some(("(", ")")), - Delimiter::Bracket => Some(("[", "]")), - Delimiter::Brace => Some((" {", "}")), - _ => None, + Delimiter::Parenthesis => Ok(("(", ")")), + Delimiter::Bracket => Ok(("[", "]")), + Delimiter::Brace => Ok((" {", "}")), + _ => Err(RewriteError::Unknown), }; let (opener, closer) = style_to_delims(style)?; @@ -1441,7 +1497,7 @@ fn rewrite_macro_with_items( for item in items { let item = match item { MacroArg::Item(item) => item, - _ => return None, + _ => return Err(RewriteError::Unknown), }; visitor.visit_item(item); } @@ -1454,5 +1510,5 @@ fn rewrite_macro_with_items( result.push_str(&shape.indent.to_string_with_newline(context.config)); result.push_str(closer); result.push_str(trailing_semicolon); - Some(result) + Ok(result) } diff --git a/src/patterns.rs b/src/patterns.rs index 3ae0fbf161f3d..9a4f6528ce8e9 100644 --- a/src/patterns.rs +++ b/src/patterns.rs @@ -327,7 +327,7 @@ impl Rewrite for Pat { shape, ), PatKind::MacCall(ref mac) => { - rewrite_macro(mac, None, context, shape, MacroPosition::Pat).unknown_error() + rewrite_macro(mac, None, context, shape, MacroPosition::Pat) } PatKind::Paren(ref pat) => pat .rewrite_result( diff --git a/src/rewrite.rs b/src/rewrite.rs index 6644e4b27a86e..8cefda1657f9d 100644 --- a/src/rewrite.rs +++ b/src/rewrite.rs @@ -30,6 +30,23 @@ impl Rewrite for ptr::P { } } +#[derive(Clone, Debug, PartialEq)] +pub(crate) enum MacroErrorKind { + ParseFailure, + ReplaceMacroVariable, + Unknown, +} + +impl std::fmt::Display for MacroErrorKind { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + MacroErrorKind::ParseFailure => write!(f, "(parse failure)"), + MacroErrorKind::ReplaceMacroVariable => write!(f, "(replacing macro variables with $)"), + MacroErrorKind::Unknown => write!(f, ""), + } + } +} + #[derive(Clone, Error, Debug)] pub(crate) enum RewriteError { #[error("Formatting was skipped due to skip attribute or out of file range.")] @@ -38,6 +55,9 @@ pub(crate) enum RewriteError { #[error("It exceeds the required width of {configured_width} for the span: {span:?}")] ExceedsMaxWidth { configured_width: usize, span: Span }, + #[error("Failed to format given macro{} at: {span:?}", kind)] + MacroFailure { kind: MacroErrorKind, span: Span }, + /// Format failure that does not fit to above categories. #[error("An unknown error occurred during formatting.")] Unknown, @@ -46,6 +66,7 @@ pub(crate) enum RewriteError { /// Extension trait used to conveniently convert to RewriteError pub(crate) trait RewriteErrorExt { fn max_width_error(self, width: usize, span: Span) -> Result; + fn macro_error(self, kind: MacroErrorKind, span: Span) -> Result; fn unknown_error(self) -> Result; } @@ -57,6 +78,13 @@ impl RewriteErrorExt for Option { }) } + fn macro_error(self, kind: MacroErrorKind, span: Span) -> Result { + self.ok_or_else(|| RewriteError::MacroFailure { + kind: kind, + span: span, + }) + } + fn unknown_error(self) -> Result { self.ok_or_else(|| RewriteError::Unknown) } diff --git a/src/types.rs b/src/types.rs index f9dafe7d6255d..76eb0ea0529cb 100644 --- a/src/types.rs +++ b/src/types.rs @@ -958,7 +958,7 @@ impl Rewrite for ast::Ty { ast::TyKind::BareFn(ref bare_fn) => rewrite_bare_fn(bare_fn, self.span, context, shape), ast::TyKind::Never => Ok(String::from("!")), ast::TyKind::MacCall(ref mac) => { - rewrite_macro(mac, None, context, shape, MacroPosition::Expression).unknown_error() + rewrite_macro(mac, None, context, shape, MacroPosition::Expression) } ast::TyKind::ImplicitSelf => Ok(String::from("")), ast::TyKind::ImplTrait(_, ref it) => { diff --git a/src/visitor.rs b/src/visitor.rs index b08aa35f8f886..9859100a038ca 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -584,7 +584,8 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { item.ident, &item.vis, item.span, - ); + ) + .ok(); self.push_rewrite(item.span, rewrite); } ast::ItemKind::Delegation(..) | ast::ItemKind::DelegationMac(..) => { @@ -683,7 +684,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { // 1 = ; let shape = self.shape().saturating_sub_width(1); - let rewrite = self.with_context(|ctx| rewrite_macro(mac, ident, ctx, shape, pos)); + let rewrite = self.with_context(|ctx| rewrite_macro(mac, ident, ctx, shape, pos).ok()); // As of v638 of the rustc-ap-* crates, the associated span no longer includes // the trailing semicolon. This determines the correct span to ensure scenarios // with whitespace between the delimiters and trailing semi (i.e. `foo!(abc) ;`) From 44fac8934a3b92cc4bfb87dead31f90aa75683ee Mon Sep 17 00:00:00 2001 From: binarycat Date: Sun, 25 Aug 2024 12:09:58 -0400 Subject: [PATCH 0179/2194] explain the options curl passes to bootstrap also fixes a discrepency where the rust side doesn't use -L must not be merged before #129134 docs are only on the rust side, since duplicated prose has a tendancy to get out-of-sync, and also because there are talks of removing the python script all together eventually. --- src/bootstrap/bootstrap.py | 4 ++++ src/bootstrap/src/core/download.rs | 19 +++++++++++++++++-- 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py index c19134b4594fb..1de010dc08a49 100644 --- a/src/bootstrap/bootstrap.py +++ b/src/bootstrap/bootstrap.py @@ -115,6 +115,10 @@ def _download(path, url, probably_big, verbose, exception): extra_flags = [] if curl_version() > (7, 70): extra_flags = [ "--retry-all-errors" ] + # options should be kept in sync with + # src/bootstrap/src/core/download.rs + # for consistency. + # they are also more compreprensivly explained in that file. run(["curl", option] + extra_flags + [ "-L", # Follow redirect. "-y", "30", "-Y", "10", # timeout if speed is < 10 bytes/sec for > 30 seconds diff --git a/src/bootstrap/src/core/download.rs b/src/bootstrap/src/core/download.rs index b5c55854eff58..038ca320e6b6e 100644 --- a/src/bootstrap/src/core/download.rs +++ b/src/bootstrap/src/core/download.rs @@ -227,20 +227,35 @@ impl Config { fn download_http_with_retries(&self, tempfile: &Path, url: &str, help_on_error: &str) { println!("downloading {url}"); // Try curl. If that fails and we are on windows, fallback to PowerShell. + // options should be kept in sync with + // src/bootstrap/src/core/download.rs + // for consistency let mut curl = command("curl"); curl.args([ + // follow redirect + "-L", + // timeout if speed is < 10 bytes/sec for > 30 seconds "-y", "30", "-Y", - "10", // timeout if speed is < 10 bytes/sec for > 30 seconds + "10", + // timeout if cannot connect within 30 seconds "--connect-timeout", - "30", // timeout if cannot connect within 30 seconds + "30", + // output file "-o", tempfile.to_str().unwrap(), + // if there is an error, don't restart the download, + // instead continue where it left off. "--continue-at", "-", + // retry up to 3 times. note that this means a maximum of 4 + // attempts will be made, since the first attempt isn't a *re*try. "--retry", "3", + // -S: show errors, even if -s is specified + // -R: set timestamp of downloaded file to that of the server + // -f: fail on non-ok http status "-SRf", ]); // Don't print progress in CI; the \r wrapping looks bad and downloads don't take long enough for progress to be useful. From d40e04a1cb08d00736909bfb81be01e4cca9d6d6 Mon Sep 17 00:00:00 2001 From: WeiTheShinobi Date: Sun, 25 Aug 2024 20:51:26 +0800 Subject: [PATCH 0180/2194] `used_underscore_items` will not lint exteranl item --- clippy_lints/src/misc.rs | 8 +++++- tests/ui/auxiliary/external_item.rs | 7 ++++++ tests/ui/used_underscore_items.rs | 12 +++++++++ tests/ui/used_underscore_items.stderr | 36 +++++++++++++-------------- 4 files changed, 44 insertions(+), 19 deletions(-) create mode 100644 tests/ui/auxiliary/external_item.rs diff --git a/clippy_lints/src/misc.rs b/clippy_lints/src/misc.rs index 3fc3f2b3b7fa7..3e80e48a9485d 100644 --- a/clippy_lints/src/misc.rs +++ b/clippy_lints/src/misc.rs @@ -7,6 +7,7 @@ use clippy_utils::{ }; use rustc_errors::Applicability; use rustc_hir::def::Res; +use rustc_hir::def_id::LOCAL_CRATE; use rustc_hir::intravisit::FnKind; use rustc_hir::{ BinOpKind, BindingMode, Body, ByRef, Expr, ExprKind, FnDecl, Mutability, PatKind, QPath, Stmt, StmtKind, @@ -281,9 +282,14 @@ fn used_underscore_items<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { }, _ => return, }; + let name = ident.name.as_str(); let definition_span = cx.tcx.def_span(def_id); - if name.starts_with('_') && !name.starts_with("__") && !definition_span.from_expansion() { + if name.starts_with('_') + && !name.starts_with("__") + && !definition_span.from_expansion() + && def_id.krate == LOCAL_CRATE + { span_lint_and_then( cx, USED_UNDERSCORE_ITEMS, diff --git a/tests/ui/auxiliary/external_item.rs b/tests/ui/auxiliary/external_item.rs new file mode 100644 index 0000000000000..ca4bc369e4494 --- /dev/null +++ b/tests/ui/auxiliary/external_item.rs @@ -0,0 +1,7 @@ +pub struct _ExternalStruct {} + +impl _ExternalStruct { + pub fn _foo(self) {} +} + +pub fn _exernal_foo() {} diff --git a/tests/ui/used_underscore_items.rs b/tests/ui/used_underscore_items.rs index 6b2ca44e32c4e..223016a5c9667 100644 --- a/tests/ui/used_underscore_items.rs +++ b/tests/ui/used_underscore_items.rs @@ -1,6 +1,9 @@ +//@aux-build:external_item.rs #![allow(unused)] #![warn(clippy::used_underscore_items)] +extern crate external_item; + // should not lint macro macro_rules! macro_wrap_func { () => { @@ -49,3 +52,12 @@ fn main() { let foo_struct2 = a::b::c::_FooStruct2 {}; foo_struct2._method_call(); } + +// should not lint exteranl crate. +// user cannot control how others name their items +fn external_item_call() { + let foo_struct3 = external_item::_ExternalStruct {}; + foo_struct3._foo(); + + external_item::_exernal_foo(); +} diff --git a/tests/ui/used_underscore_items.stderr b/tests/ui/used_underscore_items.stderr index 127d8248a943d..93ac3a6fec6be 100644 --- a/tests/ui/used_underscore_items.stderr +++ b/tests/ui/used_underscore_items.stderr @@ -1,11 +1,11 @@ error: used underscore-prefixed item - --> tests/ui/used_underscore_items.rs:40:5 + --> tests/ui/used_underscore_items.rs:43:5 | LL | _foo1(); | ^^^^^^^ | note: item is defined here - --> tests/ui/used_underscore_items.rs:19:1 + --> tests/ui/used_underscore_items.rs:22:1 | LL | fn _foo1() {} | ^^^^^^^^^^ @@ -13,97 +13,97 @@ LL | fn _foo1() {} = help: to override `-D warnings` add `#[allow(clippy::used_underscore_items)]` error: used underscore-prefixed item - --> tests/ui/used_underscore_items.rs:41:13 + --> tests/ui/used_underscore_items.rs:44:13 | LL | let _ = _foo2(); | ^^^^^^^ | note: item is defined here - --> tests/ui/used_underscore_items.rs:21:1 + --> tests/ui/used_underscore_items.rs:24:1 | LL | fn _foo2() -> i32 { | ^^^^^^^^^^^^^^^^^ error: used underscore-prefixed item - --> tests/ui/used_underscore_items.rs:42:5 + --> tests/ui/used_underscore_items.rs:45:5 | LL | a::b::c::_foo3(); | ^^^^^^^^^^^^^^^^ | note: item is defined here - --> tests/ui/used_underscore_items.rs:28:13 + --> tests/ui/used_underscore_items.rs:31:13 | LL | pub fn _foo3() {} | ^^^^^^^^^^^^^^ error: used underscore-prefixed item - --> tests/ui/used_underscore_items.rs:43:14 + --> tests/ui/used_underscore_items.rs:46:14 | LL | let _ = &_FooStruct {}; | ^^^^^^^^^^^^^ | note: item is defined here - --> tests/ui/used_underscore_items.rs:13:1 + --> tests/ui/used_underscore_items.rs:16:1 | LL | struct _FooStruct {} | ^^^^^^^^^^^^^^^^^ error: used underscore-prefixed item - --> tests/ui/used_underscore_items.rs:44:13 + --> tests/ui/used_underscore_items.rs:47:13 | LL | let _ = _FooStruct {}; | ^^^^^^^^^^^^^ | note: item is defined here - --> tests/ui/used_underscore_items.rs:13:1 + --> tests/ui/used_underscore_items.rs:16:1 | LL | struct _FooStruct {} | ^^^^^^^^^^^^^^^^^ error: used underscore-prefixed item - --> tests/ui/used_underscore_items.rs:46:22 + --> tests/ui/used_underscore_items.rs:49:22 | LL | let foo_struct = _FooStruct {}; | ^^^^^^^^^^^^^ | note: item is defined here - --> tests/ui/used_underscore_items.rs:13:1 + --> tests/ui/used_underscore_items.rs:16:1 | LL | struct _FooStruct {} | ^^^^^^^^^^^^^^^^^ error: used underscore-prefixed item - --> tests/ui/used_underscore_items.rs:47:5 + --> tests/ui/used_underscore_items.rs:50:5 | LL | foo_struct._method_call(); | ^^^^^^^^^^^^^^^^^^^^^^^^^ | note: item is defined here - --> tests/ui/used_underscore_items.rs:16:5 + --> tests/ui/used_underscore_items.rs:19:5 | LL | fn _method_call(self) {} | ^^^^^^^^^^^^^^^^^^^^^ error: used underscore-prefixed item - --> tests/ui/used_underscore_items.rs:49:23 + --> tests/ui/used_underscore_items.rs:52:23 | LL | let foo_struct2 = a::b::c::_FooStruct2 {}; | ^^^^^^^^^^^^^^^^^^^^^^^ | note: item is defined here - --> tests/ui/used_underscore_items.rs:30:13 + --> tests/ui/used_underscore_items.rs:33:13 | LL | pub struct _FooStruct2 {} | ^^^^^^^^^^^^^^^^^^^^^^ error: used underscore-prefixed item - --> tests/ui/used_underscore_items.rs:50:5 + --> tests/ui/used_underscore_items.rs:53:5 | LL | foo_struct2._method_call(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: item is defined here - --> tests/ui/used_underscore_items.rs:33:17 + --> tests/ui/used_underscore_items.rs:36:17 | LL | pub fn _method_call(self) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ From 13d7b546dada1cb2960dec90875b16a42ff7fb84 Mon Sep 17 00:00:00 2001 From: Lukas Bergdoll Date: Sun, 25 Aug 2024 19:14:00 +0200 Subject: [PATCH 0181/2194] Add binary-size optimized variants for stable and unstable sort as well as select_nth_unstable - Stable sort uses a simple merge-sort that re-uses the existing - rather gnarly - merge function. - Unstable sort jumps directly to the branchless heapsort fallback. - select_nth_unstable jumps directly to the median_of_medians fallback, which is augmented with a custom tiny smallsort and partition impl. Some code is duplicated but de-duplication would bring it's own problems. For example `swap_if_less` is critical for performance, if the sorting networks don't inline it perf drops drastically, however `#[inline(always)]` is also a poor fit, if the provided comparison function is huge, it gives the compiler an out to only instantiate `swap_if_less` once and call it. Another aspect that would suffer when making `swap_if_less` pub, is having to cfg out dozens of functions in in smallsort module. --- library/core/src/slice/sort/mod.rs | 1 + library/core/src/slice/sort/select.rs | 125 +++++++++++++++++- .../core/src/slice/sort/shared/smallsort.rs | 2 +- library/core/src/slice/sort/stable/mod.rs | 58 ++++++-- library/core/src/slice/sort/stable/tiny.rs | 75 +++++++++++ library/core/src/slice/sort/unstable/mod.rs | 37 ++++-- .../core/src/slice/sort/unstable/quicksort.rs | 19 ++- 7 files changed, 284 insertions(+), 33 deletions(-) create mode 100644 library/core/src/slice/sort/stable/tiny.rs diff --git a/library/core/src/slice/sort/mod.rs b/library/core/src/slice/sort/mod.rs index 79852708b81ea..81b99a4364b2e 100644 --- a/library/core/src/slice/sort/mod.rs +++ b/library/core/src/slice/sort/mod.rs @@ -5,4 +5,5 @@ pub mod stable; pub mod unstable; pub(crate) mod select; +#[cfg(not(feature = "optimize_for_size"))] pub(crate) mod shared; diff --git a/library/core/src/slice/sort/select.rs b/library/core/src/slice/sort/select.rs index f6529f23bcb3f..b60e33b3a2f0d 100644 --- a/library/core/src/slice/sort/select.rs +++ b/library/core/src/slice/sort/select.rs @@ -6,9 +6,13 @@ //! for pivot selection. Using this as a fallback ensures O(n) worst case running time with //! better performance than one would get using heapsort as fallback. +use crate::intrinsics; use crate::mem::{self, SizedTypeProperties}; +#[cfg(not(feature = "optimize_for_size"))] use crate::slice::sort::shared::pivot::choose_pivot; +#[cfg(not(feature = "optimize_for_size"))] use crate::slice::sort::shared::smallsort::insertion_sort_shift_left; +#[cfg(not(feature = "optimize_for_size"))] use crate::slice::sort::unstable::quicksort::partition; /// Reorders the slice such that the element at `index` is at its final sorted position. @@ -40,7 +44,15 @@ where let min_idx = min_index(v, &mut is_less).unwrap(); v.swap(min_idx, index); } else { - partition_at_index_loop(v, index, None, &mut is_less); + #[cfg(not(feature = "optimize_for_size"))] + { + partition_at_index_loop(v, index, None, &mut is_less); + } + + #[cfg(feature = "optimize_for_size")] + { + median_of_medians(v, &mut is_less, index); + } } let (left, right) = v.split_at_mut(index); @@ -53,6 +65,7 @@ where // most once, it doesn't make sense to use something more sophisticated than insertion-sort. const INSERTION_SORT_THRESHOLD: usize = 16; +#[cfg(not(feature = "optimize_for_size"))] fn partition_at_index_loop<'a, T, F>( mut v: &'a mut [T], mut index: usize, @@ -167,8 +180,17 @@ fn median_of_medians bool>(mut v: &mut [T], is_less: &mut loop { if v.len() <= INSERTION_SORT_THRESHOLD { if v.len() >= 2 { - insertion_sort_shift_left(v, 1, is_less); + #[cfg(not(feature = "optimize_for_size"))] + { + insertion_sort_shift_left(v, 1, is_less); + } + + #[cfg(feature = "optimize_for_size")] + { + bubble_sort(v, is_less); + } } + return; } @@ -230,7 +252,15 @@ fn median_of_ninthers bool>(v: &mut [T], is_less: &mut F) median_of_medians(&mut v[lo..lo + frac], is_less, pivot); - partition(v, lo + pivot, is_less) + #[cfg(not(feature = "optimize_for_size"))] + { + partition(v, lo + pivot, is_less) + } + + #[cfg(feature = "optimize_for_size")] + { + partition_size_opt(v, lo + pivot, is_less) + } } /// Moves around the 9 elements at the indices a..i, such that @@ -298,3 +328,92 @@ fn median_idx bool>( } b } + +// It's possible to re-use the insertion sort in the smallsort module, but with optimize_for_size it +// would clutter that module with cfg statements and make it generally harder to read and develop. +// So to decouple things and simplify it, we use a an even smaller bubble sort. +#[cfg(feature = "optimize_for_size")] +fn bubble_sort bool>(v: &mut [T], is_less: &mut F) { + let mut n = v.len(); + let mut did_swap = true; + + while did_swap && n > 1 { + did_swap = false; + for i in 1..n { + // SAFETY: The loop construction implies that `i` and `i - 1` will always be in-bounds. + unsafe { + if is_less(v.get_unchecked(i), v.get_unchecked(i - 1)) { + v.swap_unchecked(i - 1, i); + did_swap = true; + } + } + } + n -= 1; + } +} + +#[cfg(feature = "optimize_for_size")] +fn partition_size_opt(v: &mut [T], pivot: usize, is_less: &mut F) -> usize +where + F: FnMut(&T, &T) -> bool, +{ + let len = v.len(); + + // Allows for panic-free code-gen by proving this property to the compiler. + if len == 0 { + return 0; + } + + if pivot >= len { + intrinsics::abort(); + } + + // SAFETY: We checked that `pivot` is in-bounds. + unsafe { + // Place the pivot at the beginning of slice. + v.swap_unchecked(0, pivot); + } + let (pivot, v_without_pivot) = v.split_at_mut(1); + + // Assuming that Rust generates noalias LLVM IR we can be sure that a partition function + // signature of the form `(v: &mut [T], pivot: &T)` guarantees that pivot and v can't alias. + // Having this guarantee is crucial for optimizations. It's possible to copy the pivot value + // into a stack value, but this creates issues for types with interior mutability mandating + // a drop guard. + let pivot = &mut pivot[0]; + + let num_lt = partition_lomuto_branchless_simple(v_without_pivot, pivot, is_less); + + if num_lt >= len { + intrinsics::abort(); + } + + // SAFETY: We checked that `num_lt` is in-bounds. + unsafe { + // Place the pivot between the two partitions. + v.swap_unchecked(0, num_lt); + } + + num_lt +} + +#[cfg(feature = "optimize_for_size")] +fn partition_lomuto_branchless_simple bool>( + v: &mut [T], + pivot: &T, + is_less: &mut F, +) -> usize { + let mut left = 0; + + for right in 0..v.len() { + // SAFETY: `left` can at max be incremented by 1 each loop iteration, which implies that + // left <= right and that both are in-bounds. + unsafe { + let right_is_lt = is_less(v.get_unchecked(right), pivot); + v.swap_unchecked(left, right); + left += right_is_lt as usize; + } + } + + left +} diff --git a/library/core/src/slice/sort/shared/smallsort.rs b/library/core/src/slice/sort/shared/smallsort.rs index db0c5c72822c0..5027962ccb415 100644 --- a/library/core/src/slice/sort/shared/smallsort.rs +++ b/library/core/src/slice/sort/shared/smallsort.rs @@ -378,7 +378,7 @@ where /// Swap two values in the slice pointed to by `v_base` at the position `a_pos` and `b_pos` if the /// value at position `b_pos` is less than the one at position `a_pos`. -pub unsafe fn swap_if_less(v_base: *mut T, a_pos: usize, b_pos: usize, is_less: &mut F) +unsafe fn swap_if_less(v_base: *mut T, a_pos: usize, b_pos: usize, is_less: &mut F) where F: FnMut(&T, &T) -> bool, { diff --git a/library/core/src/slice/sort/stable/mod.rs b/library/core/src/slice/sort/stable/mod.rs index a383b0f589ccf..a61a95a225455 100644 --- a/library/core/src/slice/sort/stable/mod.rs +++ b/library/core/src/slice/sort/stable/mod.rs @@ -1,15 +1,24 @@ //! This module contains the entry points for `slice::sort`. +#[cfg(not(feature = "optimize_for_size"))] +use crate::cmp; +use crate::intrinsics; use crate::mem::{self, MaybeUninit, SizedTypeProperties}; +#[cfg(not(feature = "optimize_for_size"))] use crate::slice::sort::shared::smallsort::{ insertion_sort_shift_left, StableSmallSortTypeImpl, SMALL_SORT_GENERAL_SCRATCH_LEN, }; -use crate::{cmp, intrinsics}; -pub(crate) mod drift; pub(crate) mod merge; + +#[cfg(not(feature = "optimize_for_size"))] +pub(crate) mod drift; +#[cfg(not(feature = "optimize_for_size"))] pub(crate) mod quicksort; +#[cfg(feature = "optimize_for_size")] +pub(crate) mod tiny; + /// Stable sort called driftsort by Orson Peters and Lukas Bergdoll. /// Design document: /// @@ -30,25 +39,48 @@ pub fn sort bool, BufT: BufGuard>(v: &mut [T], is_less return; } - // More advanced sorting methods than insertion sort are faster if called in - // a hot loop for small inputs, but for general-purpose code the small - // binary size of insertion sort is more important. The instruction cache in - // modern processors is very valuable, and for a single sort call in general - // purpose code any gains from an advanced method are cancelled by i-cache - // misses during the sort, and thrashing the i-cache for surrounding code. - const MAX_LEN_ALWAYS_INSERTION_SORT: usize = 20; - if intrinsics::likely(len <= MAX_LEN_ALWAYS_INSERTION_SORT) { - insertion_sort_shift_left(v, 1, is_less); - return; + #[cfg(not(feature = "optimize_for_size"))] + { + // More advanced sorting methods than insertion sort are faster if called in + // a hot loop for small inputs, but for general-purpose code the small + // binary size of insertion sort is more important. The instruction cache in + // modern processors is very valuable, and for a single sort call in general + // purpose code any gains from an advanced method are cancelled by i-cache + // misses during the sort, and thrashing the i-cache for surrounding code. + const MAX_LEN_ALWAYS_INSERTION_SORT: usize = 20; + if intrinsics::likely(len <= MAX_LEN_ALWAYS_INSERTION_SORT) { + insertion_sort_shift_left(v, 1, is_less); + return; + } + + driftsort_main::(v, is_less); } - driftsort_main::(v, is_less); + #[cfg(feature = "optimize_for_size")] + { + let alloc_len = len / 2; + + // For small inputs 4KiB of stack storage suffices, which allows us to avoid + // calling the (de-)allocator. Benchmarks showed this was quite beneficial. + let mut stack_buf = AlignedStorage::::new(); + let stack_scratch = stack_buf.as_uninit_slice_mut(); + let mut heap_buf; + let scratch = if stack_scratch.len() >= alloc_len { + stack_scratch + } else { + heap_buf = BufT::with_capacity(alloc_len); + heap_buf.as_uninit_slice_mut() + }; + + tiny::mergesort(v, scratch, is_less); + } } /// See [`sort`] /// /// Deliberately don't inline the main sorting routine entrypoint to ensure the /// inlined insertion sort i-cache footprint remains minimal. +#[cfg(not(feature = "optimize_for_size"))] #[inline(never)] fn driftsort_main bool, BufT: BufGuard>(v: &mut [T], is_less: &mut F) { // By allocating n elements of memory we can ensure the entire input can diff --git a/library/core/src/slice/sort/stable/tiny.rs b/library/core/src/slice/sort/stable/tiny.rs new file mode 100644 index 0000000000000..307011f3ee8c4 --- /dev/null +++ b/library/core/src/slice/sort/stable/tiny.rs @@ -0,0 +1,75 @@ +//! Binary-size optimized mergesort inspired by https://github.com/voultapher/tiny-sort-rs. + +use crate::mem::{ManuallyDrop, MaybeUninit}; +use crate::ptr; +use crate::slice::sort::stable::merge; + +/// Tiny recursive top-down merge sort optimized for binary size. It has no adaptiveness whatsoever, +/// no run detection, etc. +#[inline(always)] +pub fn mergesort bool>( + v: &mut [T], + scratch: &mut [MaybeUninit], + is_less: &mut F, +) { + let len = v.len(); + + if len > 2 { + let mid = len / 2; + + // SAFETY: mid is in-bounds. + unsafe { + // Sort the left half recursively. + mergesort(v.get_unchecked_mut(..mid), scratch, is_less); + // Sort the right half recursively. + mergesort(v.get_unchecked_mut(mid..), scratch, is_less); + } + + merge::merge(v, scratch, mid, is_less); + } else if len == 2 { + // Branchless swap the two elements. This reduces the recursion depth and improves + // perf significantly at a small binary-size cost. Trades ~10% perf boost for integers + // for ~50 bytes in the binary. + + // SAFETY: We checked the len, the pointers we create are valid and don't overlap. + unsafe { + swap_if_less(v.as_mut_ptr(), 0, 1, is_less); + } + } +} + +/// Swap two values in the slice pointed to by `v_base` at the position `a_pos` and `b_pos` if the +/// value at position `b_pos` is less than the one at position `a_pos`. +unsafe fn swap_if_less(v_base: *mut T, a_pos: usize, b_pos: usize, is_less: &mut F) +where + F: FnMut(&T, &T) -> bool, +{ + // SAFETY: the caller must guarantee that `a` and `b` each added to `v_base` yield valid + // pointers into `v_base`, and are properly aligned, and part of the same allocation. + unsafe { + let v_a = v_base.add(a_pos); + let v_b = v_base.add(b_pos); + + // PANIC SAFETY: if is_less panics, no scratch memory was created and the slice should still be + // in a well defined state, without duplicates. + + // Important to only swap if it is more and not if it is equal. is_less should return false for + // equal, so we don't swap. + let should_swap = is_less(&*v_b, &*v_a); + + // This is a branchless version of swap if. + // The equivalent code with a branch would be: + // + // if should_swap { + // ptr::swap(left, right, 1); + // } + + // The goal is to generate cmov instructions here. + let left_swap = if should_swap { v_b } else { v_a }; + let right_swap = if should_swap { v_a } else { v_b }; + + let right_swap_tmp = ManuallyDrop::new(ptr::read(right_swap)); + ptr::copy(left_swap, v_a, 1); + ptr::copy_nonoverlapping(&*right_swap_tmp, v_b, 1); + } +} diff --git a/library/core/src/slice/sort/unstable/mod.rs b/library/core/src/slice/sort/unstable/mod.rs index 932e01f4401e5..43b5cc79fc7f3 100644 --- a/library/core/src/slice/sort/unstable/mod.rs +++ b/library/core/src/slice/sort/unstable/mod.rs @@ -2,10 +2,13 @@ use crate::intrinsics; use crate::mem::SizedTypeProperties; +#[cfg(not(feature = "optimize_for_size"))] use crate::slice::sort::shared::find_existing_run; +#[cfg(not(feature = "optimize_for_size"))] use crate::slice::sort::shared::smallsort::insertion_sort_shift_left; pub(crate) mod heapsort; +#[cfg(not(feature = "optimize_for_size"))] pub(crate) mod quicksort; /// Unstable sort called ipnsort by Lukas Bergdoll and Orson Peters. @@ -28,25 +31,37 @@ pub fn sort bool>(v: &mut [T], is_less: &mut F) { return; } - // More advanced sorting methods than insertion sort are faster if called in - // a hot loop for small inputs, but for general-purpose code the small - // binary size of insertion sort is more important. The instruction cache in - // modern processors is very valuable, and for a single sort call in general - // purpose code any gains from an advanced method are cancelled by i-cache - // misses during the sort, and thrashing the i-cache for surrounding code. - const MAX_LEN_ALWAYS_INSERTION_SORT: usize = 20; - if intrinsics::likely(len <= MAX_LEN_ALWAYS_INSERTION_SORT) { - insertion_sort_shift_left(v, 1, is_less); - return; + #[cfg(not(feature = "optimize_for_size"))] + { + // More advanced sorting methods than insertion sort are faster if called in + // a hot loop for small inputs, but for general-purpose code the small + // binary size of insertion sort is more important. The instruction cache in + // modern processors is very valuable, and for a single sort call in general + // purpose code any gains from an advanced method are cancelled by i-cache + // misses during the sort, and thrashing the i-cache for surrounding code. + const MAX_LEN_ALWAYS_INSERTION_SORT: usize = 20; + if intrinsics::likely(len <= MAX_LEN_ALWAYS_INSERTION_SORT) { + insertion_sort_shift_left(v, 1, is_less); + return; + } + + ipnsort(v, is_less); } - ipnsort(v, is_less); + #[cfg(feature = "optimize_for_size")] + { + // SAFETY: We checked that `len >= 2`. + unsafe { + heapsort::heapsort(v, is_less); + } + } } /// See [`sort`] /// /// Deliberately don't inline the main sorting routine entrypoint to ensure the /// inlined insertion sort i-cache footprint remains minimal. +#[cfg(not(feature = "optimize_for_size"))] #[inline(never)] fn ipnsort(v: &mut [T], is_less: &mut F) where diff --git a/library/core/src/slice/sort/unstable/quicksort.rs b/library/core/src/slice/sort/unstable/quicksort.rs index cd53656e9b4b8..e55ebe67e1306 100644 --- a/library/core/src/slice/sort/unstable/quicksort.rs +++ b/library/core/src/slice/sort/unstable/quicksort.rs @@ -98,13 +98,15 @@ where return 0; } - // Allows for panic-free code-gen by proving this property to the compiler. if pivot >= len { intrinsics::abort(); } - // Place the pivot at the beginning of slice. - v.swap(0, pivot); + // SAFETY: We checked that `pivot` is in-bounds. + unsafe { + // Place the pivot at the beginning of slice. + v.swap_unchecked(0, pivot); + } let (pivot, v_without_pivot) = v.split_at_mut(1); // Assuming that Rust generates noalias LLVM IR we can be sure that a partition function @@ -118,8 +120,15 @@ where // compile-time by only instantiating the code that is needed. Idea by Frank Steffahn. let num_lt = (const { inst_partition::() })(v_without_pivot, pivot, is_less); - // Place the pivot between the two partitions. - v.swap(0, num_lt); + if num_lt >= len { + intrinsics::abort(); + } + + // SAFETY: We checked that `num_lt` is in-bounds. + unsafe { + // Place the pivot between the two partitions. + v.swap_unchecked(0, num_lt); + } num_lt } From 9d694b583e3c4e899f61cb2086e2ed9627ec3619 Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Mon, 26 Aug 2024 08:28:26 +0300 Subject: [PATCH 0182/2194] support custom clippy MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Similar to cargo, rustc, and rustfmt, this adds the support of using custom clippy on bootstrap. It’s designed for those who want to test their own clippy builds or avoid downloading the stage0 clippy. Signed-off-by: onur-ozkan --- src/bootstrap/src/core/builder.rs | 8 ++++++-- src/bootstrap/src/core/config/config.rs | 11 +++++++++++ 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/src/bootstrap/src/core/builder.rs b/src/bootstrap/src/core/builder.rs index ff0d1f3a725d2..d7398b76cc91e 100644 --- a/src/bootstrap/src/core/builder.rs +++ b/src/bootstrap/src/core/builder.rs @@ -1298,8 +1298,12 @@ impl<'a> Builder<'a> { pub fn cargo_clippy_cmd(&self, run_compiler: Compiler) -> BootstrapCommand { if run_compiler.stage == 0 { - // `ensure(Clippy { stage: 0 })` *builds* clippy with stage0, it doesn't use the beta clippy. - let cargo_clippy = self.build.config.download_clippy(); + let cargo_clippy = self + .config + .initial_cargo_clippy + .clone() + .unwrap_or_else(|| self.build.config.download_clippy()); + let mut cmd = command(cargo_clippy); cmd.env("CARGO", &self.initial_cargo); return cmd; diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs index ce23b7735f8bd..cf87f1ff9470e 100644 --- a/src/bootstrap/src/core/config/config.rs +++ b/src/bootstrap/src/core/config/config.rs @@ -344,6 +344,7 @@ pub struct Config { // These are either the stage0 downloaded binaries or the locally installed ones. pub initial_cargo: PathBuf, pub initial_rustc: PathBuf, + pub initial_cargo_clippy: Option, #[cfg(not(test))] initial_rustfmt: RefCell, @@ -834,6 +835,7 @@ define_config! { cargo: Option = "cargo", rustc: Option = "rustc", rustfmt: Option = "rustfmt", + cargo_clippy: Option = "cargo-clippy", docs: Option = "docs", compiler_docs: Option = "compiler-docs", library_docs_private_items: Option = "library-docs-private-items", @@ -1439,6 +1441,7 @@ impl Config { cargo, rustc, rustfmt, + cargo_clippy, docs, compiler_docs, library_docs_private_items, @@ -1491,6 +1494,14 @@ impl Config { config.out = absolute(&config.out).expect("can't make empty path absolute"); } + if cargo_clippy.is_some() && rustc.is_none() { + println!( + "WARNING: Using `build.cargo-clippy` without `build.rustc` usually fails due to toolchain conflict." + ); + } + + config.initial_cargo_clippy = cargo_clippy; + config.initial_rustc = if let Some(rustc) = rustc { if !flags.skip_stage0_validation { config.check_stage0_version(&rustc, "rustc"); From 9dcc65600e63d23a727190ca1fd91ab645adefb8 Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Mon, 26 Aug 2024 08:28:54 +0300 Subject: [PATCH 0183/2194] document `build.cargo-clippy` option Signed-off-by: onur-ozkan --- config.example.toml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/config.example.toml b/config.example.toml index f1dc32234ccf2..b967d5d9fe8c2 100644 --- a/config.example.toml +++ b/config.example.toml @@ -230,6 +230,13 @@ # use this rustfmt binary instead as the stage0 snapshot rustfmt. #rustfmt = "/path/to/rustfmt" +# Instead of downloading the src/stage0 version of cargo-clippy specified, +# use this cargo-clippy binary instead as the stage0 snapshot cargo-clippy. +# +# Note that this option should be used with the same toolchain as the `rustc` option above. +# Otherwise, clippy is likely to fail due to a toolchain conflict. +#cargo-clippy = "/path/to/cargo-clippy" + # Whether to build documentation by default. If false, rustdoc and # friends will still be compiled but they will not be used to generate any # documentation. From 1a991e5b805832aca83862458864a7caf57d6725 Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Mon, 26 Aug 2024 08:29:17 +0300 Subject: [PATCH 0184/2194] add change entry for custom clippy support Signed-off-by: onur-ozkan --- src/bootstrap/src/utils/change_tracker.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/bootstrap/src/utils/change_tracker.rs b/src/bootstrap/src/utils/change_tracker.rs index 51a25104e4cfb..3ab14aade9f81 100644 --- a/src/bootstrap/src/utils/change_tracker.rs +++ b/src/bootstrap/src/utils/change_tracker.rs @@ -235,4 +235,9 @@ pub const CONFIG_CHANGE_HISTORY: &[ChangeInfo] = &[ severity: ChangeSeverity::Info, summary: "The `build.profiler` option now tries to use source code from `download-ci-llvm` if possible, instead of checking out the `src/llvm-project` submodule.", }, + ChangeInfo { + change_id: 129152, + severity: ChangeSeverity::Info, + summary: "New option `build.cargo-clippy` added for supporting the use of custom/external clippy.", + }, ]; From 89c9a2908fc371330edc627b9178db0628c3aee0 Mon Sep 17 00:00:00 2001 From: Lukas Bergdoll Date: Mon, 26 Aug 2024 11:17:38 +0200 Subject: [PATCH 0185/2194] Reduce code duplication by moving partition_lomuto_branchless_simple into quicksort module --- library/core/src/slice/sort/select.rs | 78 +------------------ library/core/src/slice/sort/unstable/mod.rs | 1 - .../core/src/slice/sort/unstable/quicksort.rs | 39 +++++++++- 3 files changed, 39 insertions(+), 79 deletions(-) diff --git a/library/core/src/slice/sort/select.rs b/library/core/src/slice/sort/select.rs index b60e33b3a2f0d..2b3e14755302c 100644 --- a/library/core/src/slice/sort/select.rs +++ b/library/core/src/slice/sort/select.rs @@ -6,13 +6,11 @@ //! for pivot selection. Using this as a fallback ensures O(n) worst case running time with //! better performance than one would get using heapsort as fallback. -use crate::intrinsics; use crate::mem::{self, SizedTypeProperties}; #[cfg(not(feature = "optimize_for_size"))] use crate::slice::sort::shared::pivot::choose_pivot; #[cfg(not(feature = "optimize_for_size"))] use crate::slice::sort::shared::smallsort::insertion_sort_shift_left; -#[cfg(not(feature = "optimize_for_size"))] use crate::slice::sort::unstable::quicksort::partition; /// Reorders the slice such that the element at `index` is at its final sorted position. @@ -252,15 +250,7 @@ fn median_of_ninthers bool>(v: &mut [T], is_less: &mut F) median_of_medians(&mut v[lo..lo + frac], is_less, pivot); - #[cfg(not(feature = "optimize_for_size"))] - { - partition(v, lo + pivot, is_less) - } - - #[cfg(feature = "optimize_for_size")] - { - partition_size_opt(v, lo + pivot, is_less) - } + partition(v, lo + pivot, is_less) } /// Moves around the 9 elements at the indices a..i, such that @@ -351,69 +341,3 @@ fn bubble_sort bool>(v: &mut [T], is_less: &mut F) { n -= 1; } } - -#[cfg(feature = "optimize_for_size")] -fn partition_size_opt(v: &mut [T], pivot: usize, is_less: &mut F) -> usize -where - F: FnMut(&T, &T) -> bool, -{ - let len = v.len(); - - // Allows for panic-free code-gen by proving this property to the compiler. - if len == 0 { - return 0; - } - - if pivot >= len { - intrinsics::abort(); - } - - // SAFETY: We checked that `pivot` is in-bounds. - unsafe { - // Place the pivot at the beginning of slice. - v.swap_unchecked(0, pivot); - } - let (pivot, v_without_pivot) = v.split_at_mut(1); - - // Assuming that Rust generates noalias LLVM IR we can be sure that a partition function - // signature of the form `(v: &mut [T], pivot: &T)` guarantees that pivot and v can't alias. - // Having this guarantee is crucial for optimizations. It's possible to copy the pivot value - // into a stack value, but this creates issues for types with interior mutability mandating - // a drop guard. - let pivot = &mut pivot[0]; - - let num_lt = partition_lomuto_branchless_simple(v_without_pivot, pivot, is_less); - - if num_lt >= len { - intrinsics::abort(); - } - - // SAFETY: We checked that `num_lt` is in-bounds. - unsafe { - // Place the pivot between the two partitions. - v.swap_unchecked(0, num_lt); - } - - num_lt -} - -#[cfg(feature = "optimize_for_size")] -fn partition_lomuto_branchless_simple bool>( - v: &mut [T], - pivot: &T, - is_less: &mut F, -) -> usize { - let mut left = 0; - - for right in 0..v.len() { - // SAFETY: `left` can at max be incremented by 1 each loop iteration, which implies that - // left <= right and that both are in-bounds. - unsafe { - let right_is_lt = is_less(v.get_unchecked(right), pivot); - v.swap_unchecked(left, right); - left += right_is_lt as usize; - } - } - - left -} diff --git a/library/core/src/slice/sort/unstable/mod.rs b/library/core/src/slice/sort/unstable/mod.rs index 43b5cc79fc7f3..faac97eab02b8 100644 --- a/library/core/src/slice/sort/unstable/mod.rs +++ b/library/core/src/slice/sort/unstable/mod.rs @@ -8,7 +8,6 @@ use crate::slice::sort::shared::find_existing_run; use crate::slice::sort::shared::smallsort::insertion_sort_shift_left; pub(crate) mod heapsort; -#[cfg(not(feature = "optimize_for_size"))] pub(crate) mod quicksort; /// Unstable sort called ipnsort by Lukas Bergdoll and Orson Peters. diff --git a/library/core/src/slice/sort/unstable/quicksort.rs b/library/core/src/slice/sort/unstable/quicksort.rs index e55ebe67e1306..83751d99cc261 100644 --- a/library/core/src/slice/sort/unstable/quicksort.rs +++ b/library/core/src/slice/sort/unstable/quicksort.rs @@ -1,7 +1,9 @@ //! This module contains an unstable quicksort and two partition implementations. use crate::mem::{self, ManuallyDrop}; +#[cfg(not(feature = "optimize_for_size"))] use crate::slice::sort::shared::pivot::choose_pivot; +#[cfg(not(feature = "optimize_for_size"))] use crate::slice::sort::shared::smallsort::UnstableSmallSortTypeImpl; use crate::{intrinsics, ptr}; @@ -11,6 +13,7 @@ use crate::{intrinsics, ptr}; /// /// `limit` is the number of allowed imbalanced partitions before switching to `heapsort`. If zero, /// this function will immediately switch to heapsort. +#[cfg(not(feature = "optimize_for_size"))] pub(crate) fn quicksort<'a, T, F>( mut v: &'a mut [T], mut ancestor_pivot: Option<&'a T>, @@ -138,7 +141,16 @@ const fn inst_partition bool>() -> fn(&mut [T], &T, &mut if mem::size_of::() <= MAX_BRANCHLESS_PARTITION_SIZE { // Specialize for types that are relatively cheap to copy, where branchless optimizations // have large leverage e.g. `u64` and `String`. - partition_lomuto_branchless_cyclic:: + + #[cfg(not(feature = "optimize_for_size"))] + { + partition_lomuto_branchless_cyclic:: + } + + #[cfg(feature = "optimize_for_size")] + { + partition_lomuto_branchless_simple:: + } } else { partition_hoare_branchy_cyclic:: } @@ -224,6 +236,7 @@ where } } +#[cfg(not(feature = "optimize_for_size"))] struct PartitionState { // The current element that is being looked at, scans left to right through slice. right: *mut T, @@ -234,6 +247,7 @@ struct PartitionState { gap: GapGuardRaw, } +#[cfg(not(feature = "optimize_for_size"))] fn partition_lomuto_branchless_cyclic(v: &mut [T], pivot: &T, is_less: &mut F) -> usize where F: FnMut(&T, &T) -> bool, @@ -325,6 +339,27 @@ where } } +#[cfg(feature = "optimize_for_size")] +fn partition_lomuto_branchless_simple bool>( + v: &mut [T], + pivot: &T, + is_less: &mut F, +) -> usize { + let mut left = 0; + + for right in 0..v.len() { + // SAFETY: `left` can at max be incremented by 1 each loop iteration, which implies that + // left <= right and that both are in-bounds. + unsafe { + let right_is_lt = is_less(v.get_unchecked(right), pivot); + v.swap_unchecked(left, right); + left += right_is_lt as usize; + } + } + + left +} + struct GapGuard { pos: *mut T, value: ManuallyDrop, @@ -342,11 +377,13 @@ impl Drop for GapGuard { /// Ideally this wouldn't be needed and we could just use the regular GapGuard. /// See comment in [`partition_lomuto_branchless_cyclic`]. +#[cfg(not(feature = "optimize_for_size"))] struct GapGuardRaw { pos: *mut T, value: *mut T, } +#[cfg(not(feature = "optimize_for_size"))] impl Drop for GapGuardRaw { fn drop(&mut self) { // SAFETY: `self` MUST be constructed in a way that makes copying the gap value into From 893413de5b3e574cee9e2e2cc36524a485b9ea83 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Sat, 24 Aug 2024 10:55:31 +0200 Subject: [PATCH 0186/2194] Add a run-make test for checking that certain `rustc_` crates build on stable --- .../src/external_deps/cargo.rs | 7 ++++ .../run-make-support/src/external_deps/mod.rs | 1 + .../src/external_deps/rustc.rs | 7 ++-- src/tools/run-make-support/src/lib.rs | 4 ++- .../run-make/rustc-crates-on-stable/rmake.rs | 35 +++++++++++++++++++ 5 files changed, 51 insertions(+), 3 deletions(-) create mode 100644 src/tools/run-make-support/src/external_deps/cargo.rs create mode 100644 tests/run-make/rustc-crates-on-stable/rmake.rs diff --git a/src/tools/run-make-support/src/external_deps/cargo.rs b/src/tools/run-make-support/src/external_deps/cargo.rs new file mode 100644 index 0000000000000..b0e045dc80bf8 --- /dev/null +++ b/src/tools/run-make-support/src/external_deps/cargo.rs @@ -0,0 +1,7 @@ +use crate::command::Command; +use crate::env_var; + +/// Returns a command that can be used to invoke Cargo. +pub fn cargo() -> Command { + Command::new(env_var("BOOTSTRAP_CARGO")) +} diff --git a/src/tools/run-make-support/src/external_deps/mod.rs b/src/tools/run-make-support/src/external_deps/mod.rs index f7c84724d0e07..80c34a9070fcc 100644 --- a/src/tools/run-make-support/src/external_deps/mod.rs +++ b/src/tools/run-make-support/src/external_deps/mod.rs @@ -2,6 +2,7 @@ //! such as `cc` or `python`. pub mod c_build; +pub mod cargo; pub mod cc; pub mod clang; pub mod htmldocck; diff --git a/src/tools/run-make-support/src/external_deps/rustc.rs b/src/tools/run-make-support/src/external_deps/rustc.rs index cece58d29566c..e20d87165144a 100644 --- a/src/tools/run-make-support/src/external_deps/rustc.rs +++ b/src/tools/run-make-support/src/external_deps/rustc.rs @@ -36,10 +36,13 @@ pub struct Rustc { crate::macros::impl_common_helpers!(Rustc); +pub fn rustc_path() -> String { + env_var("RUSTC") +} + #[track_caller] fn setup_common() -> Command { - let rustc = env_var("RUSTC"); - let mut cmd = Command::new(rustc); + let mut cmd = Command::new(rustc_path()); set_host_rpath(&mut cmd); cmd } diff --git a/src/tools/run-make-support/src/lib.rs b/src/tools/run-make-support/src/lib.rs index 989d00d4c2f97..efe744d6ba4a7 100644 --- a/src/tools/run-make-support/src/lib.rs +++ b/src/tools/run-make-support/src/lib.rs @@ -48,6 +48,7 @@ pub use external_deps::{c_build, cc, clang, htmldocck, llvm, python, rustc, rust // These rely on external dependencies. pub use cc::{cc, cxx, extra_c_flags, extra_cxx_flags, Cc}; pub use c_build::{build_native_dynamic_lib, build_native_static_lib, build_native_static_lib_optimized, build_native_static_lib_cxx}; +pub use cargo::cargo; pub use clang::{clang, Clang}; pub use htmldocck::htmldocck; pub use llvm::{ @@ -56,7 +57,7 @@ pub use llvm::{ LlvmProfdata, LlvmReadobj, }; pub use python::python_command; -pub use rustc::{aux_build, bare_rustc, rustc, Rustc}; +pub use rustc::{aux_build, bare_rustc, rustc, rustc_path, Rustc}; pub use rustdoc::{bare_rustdoc, rustdoc, Rustdoc}; /// [`diff`][mod@diff] is implemented in terms of the [similar] library. @@ -96,3 +97,4 @@ pub use assertion_helpers::{ pub use string::{ count_regex_matches_in_files_with_extension, invalid_utf8_contains, invalid_utf8_not_contains, }; +use crate::external_deps::cargo; diff --git a/tests/run-make/rustc-crates-on-stable/rmake.rs b/tests/run-make/rustc-crates-on-stable/rmake.rs new file mode 100644 index 0000000000000..67461788ee4b6 --- /dev/null +++ b/tests/run-make/rustc-crates-on-stable/rmake.rs @@ -0,0 +1,35 @@ +//! Checks if selected rustc crates can be compiled on the stable channel (or a "simulation" of it). +//! These crates are designed to be used by downstream users. + +use run_make_support::{cargo, rustc_path, source_root}; + +fn main() { + // Use the stage0 beta cargo for the compilation (it shouldn't really matter which cargo we use) + let cargo = cargo() + // This is required to allow using nightly cargo features (public-dependency) with beta + // cargo + .env("RUSTC_BOOTSTRAP", "1") + .env("RUSTC", rustc_path()) + .arg("build") + .arg("--manifest-path") + .arg(source_root().join("Cargo.toml")) + .args(&[ + "--config", + r#"workspace.exclude=["library/core"]"#, + // We want to disallow all nightly features, to simulate a stable build + // public-dependency needs to be enabled for cargo to work + "-Zallow-features=public-dependency", + // Avoid depending on transitive rustc crates + "--no-default-features", + // Check that these crates can be compiled on "stable" + "-p", + "rustc_type_ir", + "-p", + "rustc_next_trait_solver", + "-p", + "rustc_pattern_analysis", + "-p", + "rustc_lexer", + ]) + .run(); +} From 7957140f3ef7fbbaf9696d8fbbced1ebe6128c5b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Rakic?= Date: Sat, 24 Aug 2024 20:34:46 +0000 Subject: [PATCH 0187/2194] inhibit proc-macro2 nightly detection --- tests/run-make/rustc-crates-on-stable/rmake.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/run-make/rustc-crates-on-stable/rmake.rs b/tests/run-make/rustc-crates-on-stable/rmake.rs index 67461788ee4b6..503b0c6ead445 100644 --- a/tests/run-make/rustc-crates-on-stable/rmake.rs +++ b/tests/run-make/rustc-crates-on-stable/rmake.rs @@ -9,6 +9,7 @@ fn main() { // This is required to allow using nightly cargo features (public-dependency) with beta // cargo .env("RUSTC_BOOTSTRAP", "1") + .env("RUSTC_STAGE", "0") // Ensure `proc-macro2`'s nightly detection is disabled .env("RUSTC", rustc_path()) .arg("build") .arg("--manifest-path") From d9794a9af63b5cf59bf9a7bfa65191a6d2a1e122 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Rakic?= Date: Sat, 24 Aug 2024 21:16:54 +0000 Subject: [PATCH 0188/2194] run test in tmp dir and emit artifacts there otherwise the test would build in the source root's `target` folder --- .../run-make/rustc-crates-on-stable/rmake.rs | 67 ++++++++++--------- 1 file changed, 37 insertions(+), 30 deletions(-) diff --git a/tests/run-make/rustc-crates-on-stable/rmake.rs b/tests/run-make/rustc-crates-on-stable/rmake.rs index 503b0c6ead445..66f0b2c812625 100644 --- a/tests/run-make/rustc-crates-on-stable/rmake.rs +++ b/tests/run-make/rustc-crates-on-stable/rmake.rs @@ -1,36 +1,43 @@ //! Checks if selected rustc crates can be compiled on the stable channel (or a "simulation" of it). //! These crates are designed to be used by downstream users. -use run_make_support::{cargo, rustc_path, source_root}; +use run_make_support::{cargo, run_in_tmpdir, rustc_path, source_root}; fn main() { - // Use the stage0 beta cargo for the compilation (it shouldn't really matter which cargo we use) - let cargo = cargo() - // This is required to allow using nightly cargo features (public-dependency) with beta - // cargo - .env("RUSTC_BOOTSTRAP", "1") - .env("RUSTC_STAGE", "0") // Ensure `proc-macro2`'s nightly detection is disabled - .env("RUSTC", rustc_path()) - .arg("build") - .arg("--manifest-path") - .arg(source_root().join("Cargo.toml")) - .args(&[ - "--config", - r#"workspace.exclude=["library/core"]"#, - // We want to disallow all nightly features, to simulate a stable build - // public-dependency needs to be enabled for cargo to work - "-Zallow-features=public-dependency", - // Avoid depending on transitive rustc crates - "--no-default-features", - // Check that these crates can be compiled on "stable" - "-p", - "rustc_type_ir", - "-p", - "rustc_next_trait_solver", - "-p", - "rustc_pattern_analysis", - "-p", - "rustc_lexer", - ]) - .run(); + run_in_tmpdir(|| { + // Use the stage0 beta cargo for the compilation (it shouldn't really matter which cargo we + // use) + let cargo = cargo() + // This is required to allow using nightly cargo features (public-dependency) with beta + // cargo + .env("RUSTC_BOOTSTRAP", "1") + .env("RUSTC_STAGE", "0") // Ensure `proc-macro2`'s nightly detection is disabled + .env("RUSTC", rustc_path()) + .arg("build") + .arg("--manifest-path") + .arg(source_root().join("Cargo.toml")) + .args(&[ + "--config", + r#"workspace.exclude=["library/core"]"#, + // We want to disallow all nightly features, to simulate a stable build + // public-dependency needs to be enabled for cargo to work + "-Zallow-features=public-dependency", + // Avoid depending on transitive rustc crates + "--no-default-features", + // Emit artifacts in this temporary directory, not in the source_root's `target` + // folder + "--target-dir", + ".", + // Check that these crates can be compiled on "stable" + "-p", + "rustc_type_ir", + "-p", + "rustc_next_trait_solver", + "-p", + "rustc_pattern_analysis", + "-p", + "rustc_lexer", + ]) + .run(); + }); } From 2190c288e2455bce98dde643267ce53fd3412edb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Rakic?= Date: Sun, 25 Aug 2024 10:53:28 +0000 Subject: [PATCH 0189/2194] remove use of RUSTC_BOOTSTRAP and cargo nightly features --- tests/run-make/rustc-crates-on-stable/rmake.rs | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/tests/run-make/rustc-crates-on-stable/rmake.rs b/tests/run-make/rustc-crates-on-stable/rmake.rs index 66f0b2c812625..513c128828725 100644 --- a/tests/run-make/rustc-crates-on-stable/rmake.rs +++ b/tests/run-make/rustc-crates-on-stable/rmake.rs @@ -8,20 +8,17 @@ fn main() { // Use the stage0 beta cargo for the compilation (it shouldn't really matter which cargo we // use) let cargo = cargo() - // This is required to allow using nightly cargo features (public-dependency) with beta - // cargo - .env("RUSTC_BOOTSTRAP", "1") - .env("RUSTC_STAGE", "0") // Ensure `proc-macro2`'s nightly detection is disabled + // Ensure `proc-macro2`'s nightly detection is disabled + .env("RUSTC_STAGE", "0") .env("RUSTC", rustc_path()) + // We want to disallow all nightly features to simulate a stable build + .env("RUSTFLAGS", "-Zallow-features=") .arg("build") .arg("--manifest-path") .arg(source_root().join("Cargo.toml")) .args(&[ "--config", r#"workspace.exclude=["library/core"]"#, - // We want to disallow all nightly features, to simulate a stable build - // public-dependency needs to be enabled for cargo to work - "-Zallow-features=public-dependency", // Avoid depending on transitive rustc crates "--no-default-features", // Emit artifacts in this temporary directory, not in the source_root's `target` From 057703593c9744619787f1fe93b01059247ebb2e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Rakic?= Date: Sun, 25 Aug 2024 10:59:38 +0000 Subject: [PATCH 0190/2194] separate the crates to test from the test setup it'll be easier to see and update the list: the other cmd args can just be ignored --- tests/run-make/rustc-crates-on-stable/rmake.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/run-make/rustc-crates-on-stable/rmake.rs b/tests/run-make/rustc-crates-on-stable/rmake.rs index 513c128828725..48b8551ecef7c 100644 --- a/tests/run-make/rustc-crates-on-stable/rmake.rs +++ b/tests/run-make/rustc-crates-on-stable/rmake.rs @@ -25,7 +25,9 @@ fn main() { // folder "--target-dir", ".", - // Check that these crates can be compiled on "stable" + ]) + // Check that these crates can be compiled on "stable" + .args(&[ "-p", "rustc_type_ir", "-p", From f1df0c5fdc8fce70a36bbe283c7165223056d16a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Rakic?= Date: Sun, 25 Aug 2024 22:33:18 +0000 Subject: [PATCH 0191/2194] remove unneeded type ascription --- compiler/rustc_type_ir/src/elaborate.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_type_ir/src/elaborate.rs b/compiler/rustc_type_ir/src/elaborate.rs index 433c444e701cc..f30419c801f18 100644 --- a/compiler/rustc_type_ir/src/elaborate.rs +++ b/compiler/rustc_type_ir/src/elaborate.rs @@ -237,7 +237,7 @@ pub fn supertrait_def_ids( cx: I, trait_def_id: I::DefId, ) -> impl Iterator { - let mut set: HashSet = HashSet::default(); + let mut set = HashSet::default(); let mut stack = vec![trait_def_id]; set.insert(trait_def_id); From 8756ba56b00fdc8d76a02e654a188439f1344398 Mon Sep 17 00:00:00 2001 From: Lukas Bergdoll Date: Mon, 26 Aug 2024 12:21:37 +0200 Subject: [PATCH 0192/2194] Convert cfg blocks to cfg_if --- library/core/src/slice/sort/select.rs | 28 ++++---- library/core/src/slice/sort/stable/mod.rs | 64 +++++++++---------- library/core/src/slice/sort/unstable/mod.rs | 40 ++++++------ .../core/src/slice/sort/unstable/quicksort.rs | 15 ++--- 4 files changed, 68 insertions(+), 79 deletions(-) diff --git a/library/core/src/slice/sort/select.rs b/library/core/src/slice/sort/select.rs index 2b3e14755302c..28ca9dcad39a7 100644 --- a/library/core/src/slice/sort/select.rs +++ b/library/core/src/slice/sort/select.rs @@ -42,14 +42,12 @@ where let min_idx = min_index(v, &mut is_less).unwrap(); v.swap(min_idx, index); } else { - #[cfg(not(feature = "optimize_for_size"))] - { - partition_at_index_loop(v, index, None, &mut is_less); - } - - #[cfg(feature = "optimize_for_size")] - { - median_of_medians(v, &mut is_less, index); + cfg_if! { + if #[cfg(feature = "optimize_for_size")] { + median_of_medians(v, &mut is_less, index); + } else { + partition_at_index_loop(v, index, None, &mut is_less); + } } } @@ -178,14 +176,12 @@ fn median_of_medians bool>(mut v: &mut [T], is_less: &mut loop { if v.len() <= INSERTION_SORT_THRESHOLD { if v.len() >= 2 { - #[cfg(not(feature = "optimize_for_size"))] - { - insertion_sort_shift_left(v, 1, is_less); - } - - #[cfg(feature = "optimize_for_size")] - { - bubble_sort(v, is_less); + cfg_if! { + if #[cfg(feature = "optimize_for_size")] { + bubble_sort(v, is_less); + } else { + insertion_sort_shift_left(v, 1, is_less); + } } } diff --git a/library/core/src/slice/sort/stable/mod.rs b/library/core/src/slice/sort/stable/mod.rs index a61a95a225455..3472401c4dcf8 100644 --- a/library/core/src/slice/sort/stable/mod.rs +++ b/library/core/src/slice/sort/stable/mod.rs @@ -39,40 +39,38 @@ pub fn sort bool, BufT: BufGuard>(v: &mut [T], is_less return; } - #[cfg(not(feature = "optimize_for_size"))] - { - // More advanced sorting methods than insertion sort are faster if called in - // a hot loop for small inputs, but for general-purpose code the small - // binary size of insertion sort is more important. The instruction cache in - // modern processors is very valuable, and for a single sort call in general - // purpose code any gains from an advanced method are cancelled by i-cache - // misses during the sort, and thrashing the i-cache for surrounding code. - const MAX_LEN_ALWAYS_INSERTION_SORT: usize = 20; - if intrinsics::likely(len <= MAX_LEN_ALWAYS_INSERTION_SORT) { - insertion_sort_shift_left(v, 1, is_less); - return; - } - - driftsort_main::(v, is_less); - } - - #[cfg(feature = "optimize_for_size")] - { - let alloc_len = len / 2; - - // For small inputs 4KiB of stack storage suffices, which allows us to avoid - // calling the (de-)allocator. Benchmarks showed this was quite beneficial. - let mut stack_buf = AlignedStorage::::new(); - let stack_scratch = stack_buf.as_uninit_slice_mut(); - let mut heap_buf; - let scratch = if stack_scratch.len() >= alloc_len { - stack_scratch + cfg_if! { + if #[cfg(feature = "optimize_for_size")] { + let alloc_len = len / 2; + + // For small inputs 4KiB of stack storage suffices, which allows us to avoid + // calling the (de-)allocator. Benchmarks showed this was quite beneficial. + let mut stack_buf = AlignedStorage::::new(); + let stack_scratch = stack_buf.as_uninit_slice_mut(); + let mut heap_buf; + let scratch = if stack_scratch.len() >= alloc_len { + stack_scratch + } else { + heap_buf = BufT::with_capacity(alloc_len); + heap_buf.as_uninit_slice_mut() + }; + + tiny::mergesort(v, scratch, is_less); } else { - heap_buf = BufT::with_capacity(alloc_len); - heap_buf.as_uninit_slice_mut() - }; - - tiny::mergesort(v, scratch, is_less); + // More advanced sorting methods than insertion sort are faster if called in + // a hot loop for small inputs, but for general-purpose code the small + // binary size of insertion sort is more important. The instruction cache in + // modern processors is very valuable, and for a single sort call in general + // purpose code any gains from an advanced method are cancelled by i-cache + // misses during the sort, and thrashing the i-cache for surrounding code. + const MAX_LEN_ALWAYS_INSERTION_SORT: usize = 20; + if intrinsics::likely(len <= MAX_LEN_ALWAYS_INSERTION_SORT) { + insertion_sort_shift_left(v, 1, is_less); + return; + } + + driftsort_main::(v, is_less); + } } } diff --git a/library/core/src/slice/sort/unstable/mod.rs b/library/core/src/slice/sort/unstable/mod.rs index faac97eab02b8..130be21ee3fe8 100644 --- a/library/core/src/slice/sort/unstable/mod.rs +++ b/library/core/src/slice/sort/unstable/mod.rs @@ -30,28 +30,26 @@ pub fn sort bool>(v: &mut [T], is_less: &mut F) { return; } - #[cfg(not(feature = "optimize_for_size"))] - { - // More advanced sorting methods than insertion sort are faster if called in - // a hot loop for small inputs, but for general-purpose code the small - // binary size of insertion sort is more important. The instruction cache in - // modern processors is very valuable, and for a single sort call in general - // purpose code any gains from an advanced method are cancelled by i-cache - // misses during the sort, and thrashing the i-cache for surrounding code. - const MAX_LEN_ALWAYS_INSERTION_SORT: usize = 20; - if intrinsics::likely(len <= MAX_LEN_ALWAYS_INSERTION_SORT) { - insertion_sort_shift_left(v, 1, is_less); - return; - } - - ipnsort(v, is_less); - } + cfg_if! { + if #[cfg(feature = "optimize_for_size")] { + // SAFETY: We checked that `len >= 2`. + unsafe { + heapsort::heapsort(v, is_less); + } + } else { + // More advanced sorting methods than insertion sort are faster if called in + // a hot loop for small inputs, but for general-purpose code the small + // binary size of insertion sort is more important. The instruction cache in + // modern processors is very valuable, and for a single sort call in general + // purpose code any gains from an advanced method are cancelled by i-cache + // misses during the sort, and thrashing the i-cache for surrounding code. + const MAX_LEN_ALWAYS_INSERTION_SORT: usize = 20; + if intrinsics::likely(len <= MAX_LEN_ALWAYS_INSERTION_SORT) { + insertion_sort_shift_left(v, 1, is_less); + return; + } - #[cfg(feature = "optimize_for_size")] - { - // SAFETY: We checked that `len >= 2`. - unsafe { - heapsort::heapsort(v, is_less); + ipnsort(v, is_less); } } } diff --git a/library/core/src/slice/sort/unstable/quicksort.rs b/library/core/src/slice/sort/unstable/quicksort.rs index 83751d99cc261..9c59ccdb70005 100644 --- a/library/core/src/slice/sort/unstable/quicksort.rs +++ b/library/core/src/slice/sort/unstable/quicksort.rs @@ -141,15 +141,12 @@ const fn inst_partition bool>() -> fn(&mut [T], &T, &mut if mem::size_of::() <= MAX_BRANCHLESS_PARTITION_SIZE { // Specialize for types that are relatively cheap to copy, where branchless optimizations // have large leverage e.g. `u64` and `String`. - - #[cfg(not(feature = "optimize_for_size"))] - { - partition_lomuto_branchless_cyclic:: - } - - #[cfg(feature = "optimize_for_size")] - { - partition_lomuto_branchless_simple:: + cfg_if! { + if #[cfg(feature = "optimize_for_size")] { + partition_lomuto_branchless_simple:: + } else { + partition_lomuto_branchless_cyclic:: + } } } else { partition_hoare_branchy_cyclic:: From 5ee4d3b532a4f329fdb9319453a22d5ee9c3a7b0 Mon Sep 17 00:00:00 2001 From: beetrees Date: Sat, 24 Aug 2024 20:50:16 +0100 Subject: [PATCH 0193/2194] Remove outdated comment from `mac.yml` --- .github/workflows/mac.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/mac.yml b/.github/workflows/mac.yml index 89a980c42c5a0..f98c9830a4d22 100644 --- a/.github/workflows/mac.yml +++ b/.github/workflows/mac.yml @@ -8,7 +8,6 @@ on: jobs: test: # https://help.github.com/en/actions/automating-your-workflow-with-github-actions/virtual-environments-for-github-hosted-runners#supported-runners-and-hardware-resources - # macOS Catalina 10.15 runs-on: macos-latest name: (${{ matrix.target }}, ${{ matrix.cfg_release_channel }}) env: From 494112e51f7a2b59866c835810c3e87a10912c0a Mon Sep 17 00:00:00 2001 From: Alexey Semenyuk Date: Mon, 26 Aug 2024 20:01:29 +0500 Subject: [PATCH 0194/2194] Fix manual_range_patterns case with one element at OR --- clippy_lints/src/manual_range_patterns.rs | 5 +++-- tests/ui/manual_range_patterns.fixed | 8 ++++++++ tests/ui/manual_range_patterns.rs | 8 ++++++++ 3 files changed, 19 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/manual_range_patterns.rs b/clippy_lints/src/manual_range_patterns.rs index 9afb2b5bc84cd..66d2ab6b24a4c 100644 --- a/clippy_lints/src/manual_range_patterns.rs +++ b/clippy_lints/src/manual_range_patterns.rs @@ -77,9 +77,10 @@ impl Num { impl LateLintPass<'_> for ManualRangePatterns { fn check_pat(&mut self, cx: &LateContext<'_>, pat: &'_ rustc_hir::Pat<'_>) { // a pattern like 1 | 2 seems fine, lint if there are at least 3 alternatives - // or at least one range + // or more then one range (exclude triggering on stylistic using OR with one element + // like described https://github.com/rust-lang/rust-clippy/issues/11825) if let PatKind::Or(pats) = pat.kind - && (pats.len() >= 3 || pats.iter().any(|p| matches!(p.kind, PatKind::Range(..)))) + && (pats.len() >= 3 || (pats.len() > 1 && pats.iter().any(|p| matches!(p.kind, PatKind::Range(..))))) && !in_external_macro(cx.sess(), pat.span) { let mut min = Num::dummy(i128::MAX); diff --git a/tests/ui/manual_range_patterns.fixed b/tests/ui/manual_range_patterns.fixed index f1b99637afdba..60467bf9e8848 100644 --- a/tests/ui/manual_range_patterns.fixed +++ b/tests/ui/manual_range_patterns.fixed @@ -45,4 +45,12 @@ fn main() { }; } mac!(f); + + #[rustfmt::skip] + let _ = match f { + | 2..=15 => 4, + | 241..=254 => 5, + | 255 => 6, + | _ => 7, + }; } diff --git a/tests/ui/manual_range_patterns.rs b/tests/ui/manual_range_patterns.rs index 869ffbe80b973..9cd803334499d 100644 --- a/tests/ui/manual_range_patterns.rs +++ b/tests/ui/manual_range_patterns.rs @@ -45,4 +45,12 @@ fn main() { }; } mac!(f); + + #[rustfmt::skip] + let _ = match f { + | 2..=15 => 4, + | 241..=254 => 5, + | 255 => 6, + | _ => 7, + }; } From 992b0b3fe7006f72f00ce8d673a3fca600119555 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Mon, 26 Aug 2024 14:34:24 -0700 Subject: [PATCH 0195/2194] Document the broken C ABI of `wasm32-unknown-unknown` Inspired by discussion on https://github.com/rust-lang/rust/issues/129486 this is intended to at least document the current state of the world in a more public location than throughout a series of issues. --- .../wasm32-unknown-unknown.md | 113 ++++++++++++++++++ 1 file changed, 113 insertions(+) diff --git a/src/doc/rustc/src/platform-support/wasm32-unknown-unknown.md b/src/doc/rustc/src/platform-support/wasm32-unknown-unknown.md index 12b7817c38277..6ce022e5ebba2 100644 --- a/src/doc/rustc/src/platform-support/wasm32-unknown-unknown.md +++ b/src/doc/rustc/src/platform-support/wasm32-unknown-unknown.md @@ -195,3 +195,116 @@ conditionally compile code instead. This is notably different to the way native platforms such as x86\_64 work, and this is due to the fact that WebAssembly binaries must only contain code the engine understands. Native binaries work so long as the CPU doesn't execute unknown code dynamically at runtime. + +## Broken `extern "C"` ABI + +This target has what is considered a broken `extern "C"` ABI implementation at +this time. Notably the same signature in Rust and C will compile to different +WebAssembly functions and be incompatible. This is considered a bug and it will +be fixed in a future version of Rust. + +For example this Rust code: + +```rust +#[repr(C)] +struct MyPair { + a: u32, + b: u32, +} + +extern "C" { + fn take_my_pair(pair: MyPair) -> u32; +} + +#[no_mangle] +pub unsafe extern "C" fn call_c() -> u32 { + take_my_pair(MyPair { a: 1, b: 2 }) +} +``` + +compiles to a WebAssembly module that looks like: + +```wasm +(module + (import "env" "take_my_pair" (func $take_my_pair (param i32 i32) (result i32))) + (func $call_c + i32.const 1 + i32.const 2 + call $take_my_pair + ) +) +``` + +The function when defined in C, however, looks like + +```c +struct my_pair { + unsigned a; + unsigned b; +}; + +unsigned take_my_pair(struct my_pair pair) { + return pair.a + pair.b; +} +``` + +```wasm +(module + (import "env" "__linear_memory" (memory 0)) + (func $take_my_pair (param i32) (result i32) + local.get 0 + i32.load offset=4 + local.get 0 + i32.load + i32.add + ) +) +``` + +Notice how Rust thinks `take_my_pair` takes two `i32` parameters but C thinks it +only takes one. + +The correct definition of the `extern "C"` ABI for WebAssembly is located in the +[WebAssembly/tool-conventions](https://github.com/WebAssembly/tool-conventions/blob/main/BasicCABI.md) +repository. The `wasm32-unknown-unknown` target (and only this target, not other +WebAssembly targets Rust support) does not correctly follow this document. + +Example issues in the Rust repository about this bug are: + +* [#115666](https://github.com/rust-lang/rust/issues/115666) +* [#129486](https://github.com/rust-lang/rust/issues/129486) + +This current state of the `wasm32-unknown-unknown` backend is due to an +unfortunate accident which got relied on. The `wasm-bindgen` project prior to +0.2.89 was incompatible with the "correct" definition of `extern "C"` and it was +seen as not worth the tradeoff of breaking `wasm-bindgen` historically to fix +this issue in the compiler. + +Thanks to the heroic efforts of many involved in this, however, the nightly +compiler currently supports a `-Zwasm-c-abi` implemented in +[#117919](https://github.com/rust-lang/rust/pull/117919). This nightly-only flag +can be used to indicate whether the spec-defined version of `extern "C"` should +be used instead of the "legacy" version of +whatever-the-Rust-target-originally-implemented. For example using the above +code you can see (lightly edited for clarity): + +``` +$ rustc +nightly -Zwasm-c-abi=spec foo.rs --target wasm32-unknown-unknown --crate-type lib --emit obj -O +$ wasm-tools print foo.o +(module + (import "env" "take_my_pair" (func $take_my_pair (param i32) (result i32))) + (func $call_c (result i32) + ) + ;; ... +) +``` + +which shows that the C and Rust definitions of the same function now agree like +they should. + +The `-Zwasm-c-abi` compiler flag is tracked in +[#122532](https://github.com/rust-lang/rust/issues/122532) and a lint was +implemented in [#117918](https://github.com/rust-lang/rust/issues/117918) to +help warn users about the transition. The current plan is to, in the future, +switch `-Zwasm-c-api=spec` to being the default. Some time after that the +`-Zwasm-c-abi` flag and the "legacy" implementation will all be removed. From 7815d77ee002facace45d6747e6d9b3686d55097 Mon Sep 17 00:00:00 2001 From: Lukas Bergdoll Date: Tue, 27 Aug 2024 10:01:48 +0200 Subject: [PATCH 0196/2194] Use last swap optimization in bubblesort --- library/core/src/slice/sort/select.rs | 27 ++++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/library/core/src/slice/sort/select.rs b/library/core/src/slice/sort/select.rs index 28ca9dcad39a7..7bda54e792528 100644 --- a/library/core/src/slice/sort/select.rs +++ b/library/core/src/slice/sort/select.rs @@ -317,23 +317,32 @@ fn median_idx bool>( // It's possible to re-use the insertion sort in the smallsort module, but with optimize_for_size it // would clutter that module with cfg statements and make it generally harder to read and develop. -// So to decouple things and simplify it, we use a an even smaller bubble sort. +// So to decouple things and simplify it, we use an even smaller bubble sort. #[cfg(feature = "optimize_for_size")] fn bubble_sort bool>(v: &mut [T], is_less: &mut F) { + use crate::ptr; + let mut n = v.len(); - let mut did_swap = true; - while did_swap && n > 1 { - did_swap = false; - for i in 1..n { + let v_base = v.as_mut_ptr(); + + while n > 1 { + let loop_n = n; + n = 0; + for i in 1..loop_n { // SAFETY: The loop construction implies that `i` and `i - 1` will always be in-bounds. unsafe { - if is_less(v.get_unchecked(i), v.get_unchecked(i - 1)) { - v.swap_unchecked(i - 1, i); - did_swap = true; + // Even if `is_less` erroneously always returns true, we are guaranteed that `n` + // reduces by one each out loop iteration, because `1..n` is exclusive. This + // guarantees a bounded run-time should `Ord` be implemented incorrectly. + let v_i = v_base.add(i); + let v_i_minus_one = v_base.add(i - 1); + + if is_less(&*v_i, &*v_i_minus_one) { + ptr::swap_nonoverlapping(v_i, v_i_minus_one, 1); + n = i; } } } - n -= 1; } } From 1ef4f5d9248b3885035cfd269cca050b6d94c3dc Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 27 Aug 2024 12:21:35 +0200 Subject: [PATCH 0197/2194] clarify that addr_of creates read-only pointers --- library/core/src/ptr/mod.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs index 859fad9e069ca..b83a18027193e 100644 --- a/library/core/src/ptr/mod.rs +++ b/library/core/src/ptr/mod.rs @@ -2285,6 +2285,10 @@ impl fmt::Debug for F { /// `addr_of!(expr)` is equivalent to `&raw const expr`. The macro is *soft-deprecated*; /// use `&raw const` instead. /// +/// It is still an open question whether writing through an `addr_of!`-created pointer is permitted +/// or not. Until that is decided, the same rules as for shared references apply: it is UB to write +/// through a pointer created with this operation, except for bytes located inside an `UnsafeCell`. +/// /// Creating a reference with `&`/`&mut` is only allowed if the pointer is properly aligned /// and points to initialized data. For cases where those requirements do not hold, /// raw pointers should be used instead. However, `&expr as *const _` creates a reference From 6e387a3fb1a1ab68410fc00b6a981d76b42bcbaa Mon Sep 17 00:00:00 2001 From: Ivar Scholten Date: Tue, 27 Aug 2024 13:59:01 +0200 Subject: [PATCH 0198/2194] fix: do not assume rustup is installed in xtask codegen When formatting generated code the xtask crate attempts to run `rustup run stable rustfmt`, which fails if `rustup` is not installed. This results in test failures when another source manages the compiler toolchain, for example when using Nix (or any other distro-specific packaging solution): * xtask::codegen::grammar::test * xtask::codegen::assists_doc_tests::test With this commit xtask will first attempt to run `rustup run stable rustfmt`, and if that fails just plain `rustfmt`. It still validates a stable version is being used. This allows `cargo test` to pass on systems that do not use `rustup`. --- src/tools/rust-analyzer/xtask/src/codegen.rs | 34 +++++++++++--------- 1 file changed, 19 insertions(+), 15 deletions(-) diff --git a/src/tools/rust-analyzer/xtask/src/codegen.rs b/src/tools/rust-analyzer/xtask/src/codegen.rs index aeb0c00ae6aad..09bfed19b0e97 100644 --- a/src/tools/rust-analyzer/xtask/src/codegen.rs +++ b/src/tools/rust-analyzer/xtask/src/codegen.rs @@ -126,27 +126,31 @@ impl fmt::Display for Location { } } -fn ensure_rustfmt(sh: &Shell) { - let version = cmd!(sh, "rustup run stable rustfmt --version").read().unwrap_or_default(); - if !version.contains("stable") { - panic!( - "Failed to run rustfmt from toolchain 'stable'. \ - Please run `rustup component add rustfmt --toolchain stable` to install it.", - ); +fn rustfmt_executable(sh: &Shell) -> &str { + // First try explicitly requesting the stable channel via rustup in case nightly is being used by default, + // then plain rustfmt in case rustup isn't being used to manage the compiler (e.g. when using Nix). + for executable in ["rustup run stable rustfmt", "rustfmt"] { + let version = cmd!(sh, "{executable} --version").read().unwrap_or_default(); + if version.contains("stable") { + return executable; + } } + + panic!( + "Failed to run rustfmt from toolchain 'stable'. \ + Please run `rustup component add rustfmt --toolchain stable` to install it.", + ); } fn reformat(text: String) -> String { let sh = Shell::new().unwrap(); - ensure_rustfmt(&sh); + let rustfmt_exe = rustfmt_executable(&sh); let rustfmt_toml = project_root().join("rustfmt.toml"); - let mut stdout = cmd!( - sh, - "rustup run stable rustfmt --config-path {rustfmt_toml} --config fn_single_line=true" - ) - .stdin(text) - .read() - .unwrap(); + let mut stdout = + cmd!(sh, "{rustfmt_exe} --config-path {rustfmt_toml} --config fn_single_line=true") + .stdin(text) + .read() + .unwrap(); if !stdout.ends_with('\n') { stdout.push('\n'); } From e77eb042cef5a0035a13e69072a5c8c8fc45f1af Mon Sep 17 00:00:00 2001 From: Adrian Taylor Date: Sat, 30 Mar 2024 19:25:22 +0000 Subject: [PATCH 0199/2194] Arbitrary self types v2: pointers feature gate. The main `arbitrary_self_types` feature gate will shortly be reused for a new version of arbitrary self types which we are amending per [this RFC](https://github.com/rust-lang/rfcs/blob/master/text/3519-arbitrary-self-types-v2.md). The main amendments are: * _do_ support `self` types which can't safely implement `Deref` * do _not_ support generic `self` types * do _not_ support raw pointers as `self` types. This PR relates to the last of those bullet points: this strips pointer support from the current `arbitrary_self_types` feature. We expect this to cause some amount of breakage for crates using this unstable feature to allow raw pointer self types. If that's the case, we want to know about it, and we want crate authors to know of the upcoming changes. For now, this can be resolved by adding the new `arbitrary_self_types_pointers` feature to such crates. If we determine that use of raw pointers as self types is common, then we may maintain that as an unstable feature even if we come to stabilize the rest of the `arbitrary_self_types` support in future. If we don't hear that this PR is causing breakage, then perhaps we don't need it at all, even behind an unstable feature gate. [Tracking issue](https://github.com/rust-lang/rust/issues/44874) This is [step 4 of the plan outlined here](https://github.com/rust-lang/rust/issues/44874#issuecomment-2122179688) --- compiler/rustc_feature/src/unstable.rs | 4 +- .../rustc_hir_analysis/src/check/wfcheck.rs | 84 ++++++++++++++----- compiler/rustc_hir_typeck/src/method/probe.rs | 2 +- compiler/rustc_span/src/symbol.rs | 1 + .../miri/tests/pass/dyn-arbitrary-self.rs | 2 +- .../building/receiver_ptr_mutability.rs | 2 +- ...r-to-trait-obj-different-regions-lt-ext.rs | 2 +- ...ture-gate-arbitrary-self-types-pointers.rs | 15 ++++ ...-gate-arbitrary-self-types-pointers.stderr | 36 ++++++++ ...te-arbitrary_self_types-raw-pointer.stderr | 12 +-- .../auxiliary/inference_unstable_iterator.rs | 2 +- .../auxiliary/inference_unstable_itertools.rs | 2 +- ...arbitrary_self_types_raw_pointer_struct.rs | 2 +- .../arbitrary_self_types_raw_pointer_trait.rs | 2 +- 14 files changed, 134 insertions(+), 34 deletions(-) create mode 100644 tests/ui/feature-gates/feature-gate-arbitrary-self-types-pointers.rs create mode 100644 tests/ui/feature-gates/feature-gate-arbitrary-self-types-pointers.stderr diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index 4524458023d7f..4197c89c0113a 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -348,8 +348,10 @@ declare_features! ( (unstable, adt_const_params, "1.56.0", Some(95174)), /// Allows defining an `#[alloc_error_handler]`. (unstable, alloc_error_handler, "1.29.0", Some(51540)), - /// Allows trait methods with arbitrary self types. + /// Allows inherent and trait methods with arbitrary self types. (unstable, arbitrary_self_types, "1.23.0", Some(44874)), + /// Allows inherent and trait methods with arbitrary self types that are raw pointers. + (unstable, arbitrary_self_types_pointers, "CURRENT_RUSTC_VERSION", Some(44874)), /// Enables experimental inline assembly support for additional architectures. (unstable, asm_experimental_arch, "1.58.0", Some(93335)), /// Allows using `label` operands in inline assembly. diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index fb9bcc113c64c..2ed31d837a8b5 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -1651,6 +1651,14 @@ fn check_fn_or_method<'tcx>( } } +/// The `arbitrary_self_types_pointers` feature implies `arbitrary_self_types`. +#[derive(Clone, Copy)] +enum ArbitrarySelfTypesLevel { + None, // neither arbitrary_self_types nor arbitrary_self_types_pointers + ArbitrarySelfTypes, // just arbitrary_self_types + ArbitrarySelfTypesPointers, // both arbitrary_self_types and arbitrary_self_types_pointers +} + #[instrument(level = "debug", skip(wfcx))] fn check_method_receiver<'tcx>( wfcx: &WfCheckingCtxt<'_, 'tcx>, @@ -1683,14 +1691,28 @@ fn check_method_receiver<'tcx>( return Ok(()); } - if tcx.features().arbitrary_self_types { - if !receiver_is_valid(wfcx, span, receiver_ty, self_ty, true) { - // Report error; `arbitrary_self_types` was enabled. - return Err(tcx.dcx().emit_err(errors::InvalidReceiverTy { span, receiver_ty })); - } + let arbitrary_self_types_level = if tcx.features().arbitrary_self_types_pointers { + ArbitrarySelfTypesLevel::ArbitrarySelfTypesPointers + } else if tcx.features().arbitrary_self_types { + ArbitrarySelfTypesLevel::ArbitrarySelfTypes } else { - if !receiver_is_valid(wfcx, span, receiver_ty, self_ty, false) { - return Err(if receiver_is_valid(wfcx, span, receiver_ty, self_ty, true) { + ArbitrarySelfTypesLevel::None + }; + + if !receiver_is_valid(wfcx, span, receiver_ty, self_ty, arbitrary_self_types_level) { + return Err(match arbitrary_self_types_level { + // Wherever possible, emit a message advising folks that the features + // `arbitrary_self_types` or `arbitrary_self_types_pointers` might + // have helped. + ArbitrarySelfTypesLevel::None + if receiver_is_valid( + wfcx, + span, + receiver_ty, + self_ty, + ArbitrarySelfTypesLevel::ArbitrarySelfTypes, + ) => + { // Report error; would have worked with `arbitrary_self_types`. feature_err( &tcx.sess, @@ -1698,25 +1720,49 @@ fn check_method_receiver<'tcx>( span, format!( "`{receiver_ty}` cannot be used as the type of `self` without \ - the `arbitrary_self_types` feature", + the `arbitrary_self_types` feature", ), ) .with_help(fluent::hir_analysis_invalid_receiver_ty_help) .emit() - } else { - // Report error; would not have worked with `arbitrary_self_types`. + } + ArbitrarySelfTypesLevel::ArbitrarySelfTypes | ArbitrarySelfTypesLevel::None + if receiver_is_valid( + wfcx, + span, + receiver_ty, + self_ty, + ArbitrarySelfTypesLevel::ArbitrarySelfTypesPointers, + ) => + { + // Report error; would have worked with `arbitrary_self_types_pointers`. + feature_err( + &tcx.sess, + sym::arbitrary_self_types_pointers, + span, + format!( + "`{receiver_ty}` cannot be used as the type of `self` without \ + the `arbitrary_self_types_pointers` feature", + ), + ) + .with_help(fluent::hir_analysis_invalid_receiver_ty_help) + .emit() + } + _ => + // Report error; would not have worked with `arbitrary_self_types[_pointers]`. + { tcx.dcx().emit_err(errors::InvalidReceiverTy { span, receiver_ty }) - }); - } + } + }); } Ok(()) } /// Returns whether `receiver_ty` would be considered a valid receiver type for `self_ty`. If /// `arbitrary_self_types` is enabled, `receiver_ty` must transitively deref to `self_ty`, possibly -/// through a `*const/mut T` raw pointer. If the feature is not enabled, the requirements are more -/// strict: `receiver_ty` must implement `Receiver` and directly implement -/// `Deref`. +/// through a `*const/mut T` raw pointer if `arbitrary_self_types_pointers` is also enabled. +/// If neither feature is enabled, the requirements are more strict: `receiver_ty` must implement +/// `Receiver` and directly implement `Deref`. /// /// N.B., there are cases this function returns `true` but causes an error to be emitted, /// particularly when `receiver_ty` derefs to a type that is the same as `self_ty` but has the @@ -1726,7 +1772,7 @@ fn receiver_is_valid<'tcx>( span: Span, receiver_ty: Ty<'tcx>, self_ty: Ty<'tcx>, - arbitrary_self_types_enabled: bool, + arbitrary_self_types_enabled: ArbitrarySelfTypesLevel, ) -> bool { let infcx = wfcx.infcx; let tcx = wfcx.tcx(); @@ -1744,8 +1790,8 @@ fn receiver_is_valid<'tcx>( let mut autoderef = Autoderef::new(infcx, wfcx.param_env, wfcx.body_def_id, span, receiver_ty); - // The `arbitrary_self_types` feature allows raw pointer receivers like `self: *const Self`. - if arbitrary_self_types_enabled { + // The `arbitrary_self_types_pointers` feature allows raw pointer receivers like `self: *const Self`. + if matches!(arbitrary_self_types_enabled, ArbitrarySelfTypesLevel::ArbitrarySelfTypesPointers) { autoderef = autoderef.include_raw_pointers(); } @@ -1771,7 +1817,7 @@ fn receiver_is_valid<'tcx>( // Without `feature(arbitrary_self_types)`, we require that each step in the // deref chain implement `receiver`. - if !arbitrary_self_types_enabled { + if matches!(arbitrary_self_types_enabled, ArbitrarySelfTypesLevel::None) { if !receiver_is_implemented( wfcx, receiver_trait_def_id, diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs index 28f537c87c4ee..e557cbf170103 100644 --- a/compiler/rustc_hir_typeck/src/method/probe.rs +++ b/compiler/rustc_hir_typeck/src/method/probe.rs @@ -402,7 +402,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { mode, })); } else if bad_ty.reached_raw_pointer - && !self.tcx.features().arbitrary_self_types + && !self.tcx.features().arbitrary_self_types_pointers && !self.tcx.sess.at_least_rust_2018() { // this case used to be allowed by the compiler, diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 2957105288bb3..84c87b62262d1 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -406,6 +406,7 @@ symbols! { append_const_msg, arbitrary_enum_discriminant, arbitrary_self_types, + arbitrary_self_types_pointers, args, arith_offset, arm, diff --git a/src/tools/miri/tests/pass/dyn-arbitrary-self.rs b/src/tools/miri/tests/pass/dyn-arbitrary-self.rs index 6be13b155f410..dc2b9e4491b27 100644 --- a/src/tools/miri/tests/pass/dyn-arbitrary-self.rs +++ b/src/tools/miri/tests/pass/dyn-arbitrary-self.rs @@ -1,6 +1,6 @@ //@revisions: stack tree //@[tree]compile-flags: -Zmiri-tree-borrows -#![feature(arbitrary_self_types, unsize, coerce_unsized, dispatch_from_dyn)] +#![feature(arbitrary_self_types_pointers, unsize, coerce_unsized, dispatch_from_dyn)] #![feature(rustc_attrs)] fn pin_box_dyn() { diff --git a/tests/mir-opt/building/receiver_ptr_mutability.rs b/tests/mir-opt/building/receiver_ptr_mutability.rs index 4bb3b4cade560..1ddb8b71a5a3c 100644 --- a/tests/mir-opt/building/receiver_ptr_mutability.rs +++ b/tests/mir-opt/building/receiver_ptr_mutability.rs @@ -1,7 +1,7 @@ // skip-filecheck // EMIT_MIR receiver_ptr_mutability.main.built.after.mir -#![feature(arbitrary_self_types)] +#![feature(arbitrary_self_types_pointers)] struct Test {} diff --git a/tests/ui/cast/ptr-to-trait-obj-different-regions-lt-ext.rs b/tests/ui/cast/ptr-to-trait-obj-different-regions-lt-ext.rs index 96345de01c960..be2b89aab08f2 100644 --- a/tests/ui/cast/ptr-to-trait-obj-different-regions-lt-ext.rs +++ b/tests/ui/cast/ptr-to-trait-obj-different-regions-lt-ext.rs @@ -2,7 +2,7 @@ // // issue: -#![feature(arbitrary_self_types)] +#![feature(arbitrary_self_types_pointers)] trait Static<'a> { fn proof(self: *const Self, s: &'a str) -> &'static str; diff --git a/tests/ui/feature-gates/feature-gate-arbitrary-self-types-pointers.rs b/tests/ui/feature-gates/feature-gate-arbitrary-self-types-pointers.rs new file mode 100644 index 0000000000000..79ceb05662bc4 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-arbitrary-self-types-pointers.rs @@ -0,0 +1,15 @@ +trait Foo { + fn foo(self: *const Self); //~ ERROR `*const Self` cannot be used as the type of `self` +} + +struct Bar; + +impl Foo for Bar { + fn foo(self: *const Self) {} //~ ERROR `*const Bar` cannot be used as the type of `self` +} + +impl Bar { + fn bar(self: *mut Self) {} //~ ERROR `*mut Bar` cannot be used as the type of `self` +} + +fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-arbitrary-self-types-pointers.stderr b/tests/ui/feature-gates/feature-gate-arbitrary-self-types-pointers.stderr new file mode 100644 index 0000000000000..3bb93cf2ea0b1 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-arbitrary-self-types-pointers.stderr @@ -0,0 +1,36 @@ +error[E0658]: `*const Bar` cannot be used as the type of `self` without the `arbitrary_self_types_pointers` feature + --> $DIR/feature-gate-arbitrary-self-types-pointers.rs:8:18 + | +LL | fn foo(self: *const Self) {} + | ^^^^^^^^^^^ + | + = note: see issue #44874 for more information + = help: add `#![feature(arbitrary_self_types_pointers)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + = help: consider changing to `self`, `&self`, `&mut self`, `self: Box`, `self: Rc`, `self: Arc`, or `self: Pin

` (where P is one of the previous types except `Self`) + +error[E0658]: `*mut Bar` cannot be used as the type of `self` without the `arbitrary_self_types_pointers` feature + --> $DIR/feature-gate-arbitrary-self-types-pointers.rs:12:18 + | +LL | fn bar(self: *mut Self) {} + | ^^^^^^^^^ + | + = note: see issue #44874 for more information + = help: add `#![feature(arbitrary_self_types_pointers)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + = help: consider changing to `self`, `&self`, `&mut self`, `self: Box`, `self: Rc`, `self: Arc`, or `self: Pin

` (where P is one of the previous types except `Self`) + +error[E0658]: `*const Self` cannot be used as the type of `self` without the `arbitrary_self_types_pointers` feature + --> $DIR/feature-gate-arbitrary-self-types-pointers.rs:2:18 + | +LL | fn foo(self: *const Self); + | ^^^^^^^^^^^ + | + = note: see issue #44874 for more information + = help: add `#![feature(arbitrary_self_types_pointers)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + = help: consider changing to `self`, `&self`, `&mut self`, `self: Box`, `self: Rc`, `self: Arc`, or `self: Pin

` (where P is one of the previous types except `Self`) + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-arbitrary_self_types-raw-pointer.stderr b/tests/ui/feature-gates/feature-gate-arbitrary_self_types-raw-pointer.stderr index 711025ff93b44..856e059533139 100644 --- a/tests/ui/feature-gates/feature-gate-arbitrary_self_types-raw-pointer.stderr +++ b/tests/ui/feature-gates/feature-gate-arbitrary_self_types-raw-pointer.stderr @@ -1,33 +1,33 @@ -error[E0658]: `*const Foo` cannot be used as the type of `self` without the `arbitrary_self_types` feature +error[E0658]: `*const Foo` cannot be used as the type of `self` without the `arbitrary_self_types_pointers` feature --> $DIR/feature-gate-arbitrary_self_types-raw-pointer.rs:4:18 | LL | fn foo(self: *const Self) {} | ^^^^^^^^^^^ | = note: see issue #44874 for more information - = help: add `#![feature(arbitrary_self_types)]` to the crate attributes to enable + = help: add `#![feature(arbitrary_self_types_pointers)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date = help: consider changing to `self`, `&self`, `&mut self`, `self: Box`, `self: Rc`, `self: Arc`, or `self: Pin

` (where P is one of the previous types except `Self`) -error[E0658]: `*const ()` cannot be used as the type of `self` without the `arbitrary_self_types` feature +error[E0658]: `*const ()` cannot be used as the type of `self` without the `arbitrary_self_types_pointers` feature --> $DIR/feature-gate-arbitrary_self_types-raw-pointer.rs:14:18 | LL | fn bar(self: *const Self) {} | ^^^^^^^^^^^ | = note: see issue #44874 for more information - = help: add `#![feature(arbitrary_self_types)]` to the crate attributes to enable + = help: add `#![feature(arbitrary_self_types_pointers)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date = help: consider changing to `self`, `&self`, `&mut self`, `self: Box`, `self: Rc`, `self: Arc`, or `self: Pin

` (where P is one of the previous types except `Self`) -error[E0658]: `*const Self` cannot be used as the type of `self` without the `arbitrary_self_types` feature +error[E0658]: `*const Self` cannot be used as the type of `self` without the `arbitrary_self_types_pointers` feature --> $DIR/feature-gate-arbitrary_self_types-raw-pointer.rs:9:18 | LL | fn bar(self: *const Self); | ^^^^^^^^^^^ | = note: see issue #44874 for more information - = help: add `#![feature(arbitrary_self_types)]` to the crate attributes to enable + = help: add `#![feature(arbitrary_self_types_pointers)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date = help: consider changing to `self`, `&self`, `&mut self`, `self: Box`, `self: Rc`, `self: Arc`, or `self: Pin

` (where P is one of the previous types except `Self`) diff --git a/tests/ui/inference/auxiliary/inference_unstable_iterator.rs b/tests/ui/inference/auxiliary/inference_unstable_iterator.rs index 04bc0b1a8ac4a..8ba6fc89f1606 100644 --- a/tests/ui/inference/auxiliary/inference_unstable_iterator.rs +++ b/tests/ui/inference/auxiliary/inference_unstable_iterator.rs @@ -1,5 +1,5 @@ #![feature(staged_api)] -#![feature(arbitrary_self_types)] +#![feature(arbitrary_self_types_pointers)] #![stable(feature = "ipu_iterator", since = "1.0.0")] diff --git a/tests/ui/inference/auxiliary/inference_unstable_itertools.rs b/tests/ui/inference/auxiliary/inference_unstable_itertools.rs index fa1efbcfefc5d..32ca3a4511961 100644 --- a/tests/ui/inference/auxiliary/inference_unstable_itertools.rs +++ b/tests/ui/inference/auxiliary/inference_unstable_itertools.rs @@ -1,4 +1,4 @@ -#![feature(arbitrary_self_types)] +#![feature(arbitrary_self_types_pointers)] pub trait IpuItertools { fn ipu_flatten(&self) -> u32 { diff --git a/tests/ui/self/arbitrary_self_types_raw_pointer_struct.rs b/tests/ui/self/arbitrary_self_types_raw_pointer_struct.rs index 1f45d91847f97..7f76ed7fd2a59 100644 --- a/tests/ui/self/arbitrary_self_types_raw_pointer_struct.rs +++ b/tests/ui/self/arbitrary_self_types_raw_pointer_struct.rs @@ -1,5 +1,5 @@ //@ run-pass -#![feature(arbitrary_self_types)] +#![feature(arbitrary_self_types_pointers)] use std::rc::Rc; diff --git a/tests/ui/self/arbitrary_self_types_raw_pointer_trait.rs b/tests/ui/self/arbitrary_self_types_raw_pointer_trait.rs index 43f596659b9cd..6f34c9281b074 100644 --- a/tests/ui/self/arbitrary_self_types_raw_pointer_trait.rs +++ b/tests/ui/self/arbitrary_self_types_raw_pointer_trait.rs @@ -1,5 +1,5 @@ //@ run-pass -#![feature(arbitrary_self_types)] +#![feature(arbitrary_self_types_pointers)] use std::ptr; From 94e9c4cd64f9f30e46be5a149f90205d7096c104 Mon Sep 17 00:00:00 2001 From: binarycat Date: Sun, 25 Aug 2024 13:25:27 -0400 Subject: [PATCH 0200/2194] warn the user if the upstream master branch is old fixes https://github.com/rust-lang/rust/issues/129528 --- src/bootstrap/src/core/build_steps/format.rs | 5 +-- src/tools/build_helper/src/git.rs | 34 ++++++++++++++++++++ 2 files changed, 37 insertions(+), 2 deletions(-) diff --git a/src/bootstrap/src/core/build_steps/format.rs b/src/bootstrap/src/core/build_steps/format.rs index 8c52df78ab685..1e78583476ad6 100644 --- a/src/bootstrap/src/core/build_steps/format.rs +++ b/src/bootstrap/src/core/build_steps/format.rs @@ -7,7 +7,7 @@ use std::sync::mpsc::SyncSender; use std::sync::Mutex; use build_helper::ci::CiEnv; -use build_helper::git::get_git_modified_files; +use build_helper::git::{get_git_modified_files, warn_old_master_branch}; use ignore::WalkBuilder; use crate::core::builder::Builder; @@ -93,7 +93,8 @@ fn get_modified_rs_files(build: &Builder<'_>) -> Result>, Str if !verify_rustfmt_version(build) { return Ok(None); } - + warn_old_master_branch(&build.config.git_config(), &build.config.src) + .map_err(|e| e.to_string())?; get_git_modified_files(&build.config.git_config(), Some(&build.config.src), &["rs"]) } diff --git a/src/tools/build_helper/src/git.rs b/src/tools/build_helper/src/git.rs index da84569c778a1..cc48a8964a372 100644 --- a/src/tools/build_helper/src/git.rs +++ b/src/tools/build_helper/src/git.rs @@ -159,3 +159,37 @@ pub fn get_git_untracked_files( .collect(); Ok(Some(files)) } + +/// Print a warning if the branch returned from `updated_master_branch` is old +/// +/// For certain configurations of git repository, this remote will not be +/// updated when running `git pull`. +/// +/// This can result in formatting thousands of files instead of a dozen, +/// so we should warn the user something is wrong. +pub fn warn_old_master_branch( + config: &GitConfig<'_>, + git_dir: &Path, +) -> Result<(), Box> { + use std::time::Duration; + const WARN_AFTER: Duration = Duration::from_secs(60 * 60 * 24 * 10); + let updated_master = updated_master_branch(config, Some(git_dir))?; + let branch_path = git_dir.join(".git/refs/remotes").join(&updated_master); + match std::fs::metadata(branch_path) { + Ok(meta) => { + if meta.modified()?.elapsed()? > WARN_AFTER { + eprintln!("warning: {updated_master} has not been updated in 10 days"); + } else { + return Ok(()); + } + } + Err(err) => { + eprintln!("warning: unable to check if {updated_master} is old due to error: {err}") + } + } + eprintln!( + "warning: {updated_master} is used to determine if files have been modified\n\ + warning: if it is not updated, this may cause files to be needlessly reformatted" + ); + Ok(()) +} From e8ac4ea4187498052849531b86114a1eec5314a1 Mon Sep 17 00:00:00 2001 From: y21 <30553356+y21@users.noreply.github.com> Date: Sun, 10 Sep 2023 16:14:20 +0200 Subject: [PATCH 0201/2194] new lint: `zombie_processes` --- CHANGELOG.md | 1 + clippy_dev/src/serve.rs | 3 +- clippy_lints/src/declared_lints.rs | 1 + clippy_lints/src/lib.rs | 2 + clippy_lints/src/zombie_processes.rs | 334 +++++++++++++++++++ clippy_utils/src/paths.rs | 4 + tests/ui/suspicious_command_arg_space.fixed | 1 + tests/ui/suspicious_command_arg_space.rs | 1 + tests/ui/suspicious_command_arg_space.stderr | 4 +- tests/ui/zombie_processes.rs | 138 ++++++++ tests/ui/zombie_processes.stderr | 64 ++++ tests/ui/zombie_processes_fixable.fixed | 26 ++ tests/ui/zombie_processes_fixable.rs | 26 ++ tests/ui/zombie_processes_fixable.stderr | 40 +++ 14 files changed, 642 insertions(+), 3 deletions(-) create mode 100644 clippy_lints/src/zombie_processes.rs create mode 100644 tests/ui/zombie_processes.rs create mode 100644 tests/ui/zombie_processes.stderr create mode 100644 tests/ui/zombie_processes_fixable.fixed create mode 100644 tests/ui/zombie_processes_fixable.rs create mode 100644 tests/ui/zombie_processes_fixable.stderr diff --git a/CHANGELOG.md b/CHANGELOG.md index c5d7991e073fd..21252a3f43a00 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6048,6 +6048,7 @@ Released 2018-09-13 [`zero_repeat_side_effects`]: https://rust-lang.github.io/rust-clippy/master/index.html#zero_repeat_side_effects [`zero_sized_map_values`]: https://rust-lang.github.io/rust-clippy/master/index.html#zero_sized_map_values [`zero_width_space`]: https://rust-lang.github.io/rust-clippy/master/index.html#zero_width_space +[`zombie_processes`]: https://rust-lang.github.io/rust-clippy/master/index.html#zombie_processes [`zst_offset`]: https://rust-lang.github.io/rust-clippy/master/index.html#zst_offset diff --git a/clippy_dev/src/serve.rs b/clippy_dev/src/serve.rs index 19560b31fd3e2..cc14cd8dae69e 100644 --- a/clippy_dev/src/serve.rs +++ b/clippy_dev/src/serve.rs @@ -29,7 +29,7 @@ pub fn run(port: u16, lint: Option) -> ! { } if let Some(url) = url.take() { thread::spawn(move || { - Command::new(PYTHON) + let mut child = Command::new(PYTHON) .arg("-m") .arg("http.server") .arg(port.to_string()) @@ -40,6 +40,7 @@ pub fn run(port: u16, lint: Option) -> ! { thread::sleep(Duration::from_millis(500)); // Launch browser after first export.py has completed and http.server is up let _result = opener::open(url); + child.wait().unwrap(); }); } thread::sleep(Duration::from_millis(1000)); diff --git a/clippy_lints/src/declared_lints.rs b/clippy_lints/src/declared_lints.rs index 94da5752bebf6..10e041fbc09a2 100644 --- a/clippy_lints/src/declared_lints.rs +++ b/clippy_lints/src/declared_lints.rs @@ -768,4 +768,5 @@ pub static LINTS: &[&crate::LintInfo] = &[ crate::zero_div_zero::ZERO_DIVIDED_BY_ZERO_INFO, crate::zero_repeat_side_effects::ZERO_REPEAT_SIDE_EFFECTS_INFO, crate::zero_sized_map_values::ZERO_SIZED_MAP_VALUES_INFO, + crate::zombie_processes::ZOMBIE_PROCESSES_INFO, ]; diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 2ac06b360bea4..f24933683b1a0 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -386,6 +386,7 @@ mod write; mod zero_div_zero; mod zero_repeat_side_effects; mod zero_sized_map_values; +mod zombie_processes; // end lints modules, do not remove this comment, it’s used in `update_lints` use clippy_config::{get_configuration_metadata, Conf}; @@ -933,5 +934,6 @@ pub fn register_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) { store.register_late_pass(|_| Box::new(set_contains_or_insert::SetContainsOrInsert)); store.register_early_pass(|| Box::new(byte_char_slices::ByteCharSlice)); store.register_early_pass(|| Box::new(cfg_not_test::CfgNotTest)); + store.register_late_pass(|_| Box::new(zombie_processes::ZombieProcesses)); // add lints here, do not remove this comment, it's used in `new_lint` } diff --git a/clippy_lints/src/zombie_processes.rs b/clippy_lints/src/zombie_processes.rs new file mode 100644 index 0000000000000..eda3d7820c169 --- /dev/null +++ b/clippy_lints/src/zombie_processes.rs @@ -0,0 +1,334 @@ +use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::{fn_def_id, get_enclosing_block, match_any_def_paths, match_def_path, path_to_local_id, paths}; +use rustc_ast::Mutability; +use rustc_errors::Applicability; +use rustc_hir::intravisit::{walk_block, walk_expr, walk_local, Visitor}; +use rustc_hir::{Expr, ExprKind, HirId, LetStmt, Node, PatKind, Stmt, StmtKind}; +use rustc_lint::{LateContext, LateLintPass}; +use rustc_session::declare_lint_pass; +use rustc_span::sym; +use std::ops::ControlFlow; +use ControlFlow::{Break, Continue}; + +declare_clippy_lint! { + /// ### What it does + /// Looks for code that spawns a process but never calls `wait()` on the child. + /// + /// ### Why is this bad? + /// As explained in the [standard library documentation](https://doc.rust-lang.org/stable/std/process/struct.Child.html#warning), + /// calling `wait()` is necessary on Unix platforms to properly release all OS resources associated with the process. + /// Not doing so will effectively leak process IDs and/or other limited global resources, + /// which can eventually lead to resource exhaustion, so it's recommended to call `wait()` in long-running applications. + /// Such processes are called "zombie processes". + /// + /// ### Example + /// ```rust + /// use std::process::Command; + /// + /// let _child = Command::new("ls").spawn().expect("failed to execute child"); + /// ``` + /// Use instead: + /// ```rust + /// use std::process::Command; + /// + /// let mut child = Command::new("ls").spawn().expect("failed to execute child"); + /// child.wait().expect("failed to wait on child"); + /// ``` + #[clippy::version = "1.74.0"] + pub ZOMBIE_PROCESSES, + suspicious, + "not waiting on a spawned child process" +} +declare_lint_pass!(ZombieProcesses => [ZOMBIE_PROCESSES]); + +impl<'tcx> LateLintPass<'tcx> for ZombieProcesses { + fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) { + if let ExprKind::Call(..) | ExprKind::MethodCall(..) = expr.kind + && let Some(child_adt) = cx.typeck_results().expr_ty(expr).ty_adt_def() + && match_def_path(cx, child_adt.did(), &paths::CHILD) + { + match cx.tcx.parent_hir_node(expr.hir_id) { + Node::LetStmt(local) + if let PatKind::Binding(_, local_id, ..) = local.pat.kind + && let Some(enclosing_block) = get_enclosing_block(cx, expr.hir_id) => + { + let mut vis = WaitFinder::WalkUpTo(cx, local_id); + + // If it does have a `wait()` call, we're done. Don't lint. + if let Break(BreakReason::WaitFound) = walk_block(&mut vis, enclosing_block) { + return; + } + + // Don't emit a suggestion since the binding is used later + check(cx, expr, false); + }, + Node::LetStmt(&LetStmt { pat, .. }) if let PatKind::Wild = pat.kind => { + // `let _ = child;`, also dropped immediately without `wait()`ing + check(cx, expr, true); + }, + Node::Stmt(&Stmt { + kind: StmtKind::Semi(_), + .. + }) => { + // Immediately dropped. E.g. `std::process::Command::new("echo").spawn().unwrap();` + check(cx, expr, true); + }, + _ => {}, + } + } + } +} + +enum BreakReason { + WaitFound, + EarlyReturn, +} + +/// A visitor responsible for finding a `wait()` call on a local variable. +/// +/// Conditional `wait()` calls are assumed to not call wait: +/// ```ignore +/// let mut c = Command::new("").spawn().unwrap(); +/// if true { +/// c.wait(); +/// } +/// ``` +/// +/// Note that this visitor does NOT explicitly look for `wait()` calls directly, but rather does the +/// inverse -- checking if all uses of the local are either: +/// - a field access (`child.{stderr,stdin,stdout}`) +/// - calling `id` or `kill` +/// - no use at all (e.g. `let _x = child;`) +/// - taking a shared reference (`&`), `wait()` can't go through that +/// +/// None of these are sufficient to prevent zombie processes. +/// Doing it like this means more FNs, but FNs are better than FPs. +/// +/// `return` expressions, conditional or not, short-circuit the visitor because +/// if a `wait()` call hadn't been found at that point, it might never reach one at a later point: +/// ```ignore +/// let mut c = Command::new("").spawn().unwrap(); +/// if true { +/// return; // Break(BreakReason::EarlyReturn) +/// } +/// c.wait(); // this might not be reachable +/// ``` +enum WaitFinder<'a, 'tcx> { + WalkUpTo(&'a LateContext<'tcx>, HirId), + Found(&'a LateContext<'tcx>, HirId), +} + +impl<'a, 'tcx> Visitor<'tcx> for WaitFinder<'a, 'tcx> { + type Result = ControlFlow; + + fn visit_local(&mut self, l: &'tcx LetStmt<'tcx>) -> Self::Result { + if let Self::WalkUpTo(cx, local_id) = *self + && let PatKind::Binding(_, pat_id, ..) = l.pat.kind + && local_id == pat_id + { + *self = Self::Found(cx, local_id); + } + + walk_local(self, l) + } + + fn visit_expr(&mut self, ex: &'tcx Expr<'tcx>) -> Self::Result { + let Self::Found(cx, local_id) = *self else { + return walk_expr(self, ex); + }; + + if path_to_local_id(ex, local_id) { + match cx.tcx.parent_hir_node(ex.hir_id) { + Node::Stmt(Stmt { + kind: StmtKind::Semi(_), + .. + }) => {}, + Node::Expr(expr) if let ExprKind::Field(..) = expr.kind => {}, + Node::Expr(expr) if let ExprKind::AddrOf(_, Mutability::Not, _) = expr.kind => {}, + Node::Expr(expr) + if let Some(fn_did) = fn_def_id(cx, expr) + && match_any_def_paths(cx, fn_did, &[&paths::CHILD_ID, &paths::CHILD_KILL]).is_some() => {}, + + // Conservatively assume that all other kinds of nodes call `.wait()` somehow. + _ => return Break(BreakReason::WaitFound), + } + } else { + match ex.kind { + ExprKind::Ret(..) => return Break(BreakReason::EarlyReturn), + ExprKind::If(cond, then, None) => { + walk_expr(self, cond)?; + + // A `wait()` call in an if expression with no else is not enough: + // + // let c = spawn(); + // if true { + // c.wait(); + // } + // + // This might not call wait(). However, early returns are propagated, + // because they might lead to a later wait() not being called. + if let Break(BreakReason::EarlyReturn) = walk_expr(self, then) { + return Break(BreakReason::EarlyReturn); + } + + return Continue(()); + }, + + ExprKind::If(cond, then, Some(else_)) => { + walk_expr(self, cond)?; + + #[expect(clippy::unnested_or_patterns)] + match (walk_expr(self, then), walk_expr(self, else_)) { + (Continue(()), Continue(())) + + // `wait()` in one branch but nothing in the other does not count + | (Continue(()), Break(BreakReason::WaitFound)) + | (Break(BreakReason::WaitFound), Continue(())) => {}, + + // `wait()` in both branches is ok + (Break(BreakReason::WaitFound), Break(BreakReason::WaitFound)) => { + return Break(BreakReason::WaitFound); + }, + + // Propagate early returns in either branch + (Break(BreakReason::EarlyReturn), _) | (_, Break(BreakReason::EarlyReturn)) => { + return Break(BreakReason::EarlyReturn); + }, + } + + return Continue(()); + }, + _ => {}, + } + } + + walk_expr(self, ex) + } +} + +/// This function has shared logic between the different kinds of nodes that can trigger the lint. +/// +/// In particular, `let = ;` requires some custom additional logic +/// such as checking that the binding is not used in certain ways, which isn't necessary for +/// `let _ = ;`. +/// +/// This checks if the program doesn't unconditionally exit after the spawn expression. +fn check<'tcx>(cx: &LateContext<'tcx>, spawn_expr: &'tcx Expr<'tcx>, emit_suggestion: bool) { + let Some(block) = get_enclosing_block(cx, spawn_expr.hir_id) else { + return; + }; + + let mut vis = ExitPointFinder { + cx, + state: ExitPointState::WalkUpTo(spawn_expr.hir_id), + }; + if let Break(ExitCallFound) = vis.visit_block(block) { + // Visitor found an unconditional `exit()` call, so don't lint. + return; + } + + span_lint_and_then( + cx, + ZOMBIE_PROCESSES, + spawn_expr.span, + "spawned process is never `wait()`ed on", + |diag| { + if emit_suggestion { + diag.span_suggestion( + spawn_expr.span.shrink_to_hi(), + "try", + ".wait()", + Applicability::MaybeIncorrect, + ); + } else { + diag.note("consider calling `.wait()`"); + } + + diag.note("not doing so might leave behind zombie processes") + .note("see https://doc.rust-lang.org/stable/std/process/struct.Child.html#warning"); + }, + ); +} + +/// Checks if the given expression exits the process. +fn is_exit_expression(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { + fn_def_id(cx, expr).is_some_and(|fn_did| { + cx.tcx.is_diagnostic_item(sym::process_exit, fn_did) || match_def_path(cx, fn_did, &paths::ABORT) + }) +} + +#[derive(Debug)] +enum ExitPointState { + /// Still walking up to the expression that initiated the visitor. + WalkUpTo(HirId), + /// We're inside of a control flow construct (e.g. `if`, `match`, `loop`) + /// Within this, we shouldn't accept any `exit()` calls in here, but we can leave all of these + /// constructs later and still continue looking for an `exit()` call afterwards. Example: + /// ```ignore + /// Command::new("").spawn().unwrap(); + /// + /// if true { // depth=1 + /// if true { // depth=2 + /// match () { // depth=3 + /// () => loop { // depth=4 + /// + /// std::process::exit(); + /// ^^^^^^^^^^^^^^^^^^^^^ conditional exit call, ignored + /// + /// } // depth=3 + /// } // depth=2 + /// } // depth=1 + /// } // depth=0 + /// + /// std::process::exit(); + /// ^^^^^^^^^^^^^^^^^^^^^ this exit call is accepted because we're now unconditionally calling it + /// ``` + /// We can only get into this state from `NoExit`. + InControlFlow { depth: u32 }, + /// No exit call found yet, but looking for one. + NoExit, +} + +fn expr_enters_control_flow(expr: &Expr<'_>) -> bool { + matches!(expr.kind, ExprKind::If(..) | ExprKind::Match(..) | ExprKind::Loop(..)) +} + +struct ExitPointFinder<'a, 'tcx> { + state: ExitPointState, + cx: &'a LateContext<'tcx>, +} + +struct ExitCallFound; + +impl<'a, 'tcx> Visitor<'tcx> for ExitPointFinder<'a, 'tcx> { + type Result = ControlFlow; + + fn visit_expr(&mut self, expr: &'tcx Expr<'tcx>) -> Self::Result { + match self.state { + ExitPointState::WalkUpTo(id) if expr.hir_id == id => { + self.state = ExitPointState::NoExit; + walk_expr(self, expr) + }, + ExitPointState::NoExit if expr_enters_control_flow(expr) => { + self.state = ExitPointState::InControlFlow { depth: 1 }; + walk_expr(self, expr)?; + if let ExitPointState::InControlFlow { .. } = self.state { + self.state = ExitPointState::NoExit; + } + Continue(()) + }, + ExitPointState::NoExit if is_exit_expression(self.cx, expr) => Break(ExitCallFound), + ExitPointState::InControlFlow { ref mut depth } if expr_enters_control_flow(expr) => { + *depth += 1; + walk_expr(self, expr)?; + match self.state { + ExitPointState::InControlFlow { depth: 1 } => self.state = ExitPointState::NoExit, + ExitPointState::InControlFlow { ref mut depth } => *depth -= 1, + _ => {}, + } + Continue(()) + }, + _ => Continue(()), + } + } +} diff --git a/clippy_utils/src/paths.rs b/clippy_utils/src/paths.rs index a767798a9c36e..930fb9fb6f2d5 100644 --- a/clippy_utils/src/paths.rs +++ b/clippy_utils/src/paths.rs @@ -4,6 +4,7 @@ //! Whenever possible, please consider diagnostic items over hardcoded paths. //! See for more information. +pub const ABORT: [&str; 3] = ["std", "process", "abort"]; pub const APPLICABILITY: [&str; 2] = ["rustc_lint_defs", "Applicability"]; pub const APPLICABILITY_VALUES: [[&str; 3]; 4] = [ ["rustc_lint_defs", "Applicability", "Unspecified"], @@ -23,6 +24,9 @@ pub const CORE_RESULT_OK_METHOD: [&str; 4] = ["core", "result", "Result", "ok"]; pub const CSTRING_AS_C_STR: [&str; 5] = ["alloc", "ffi", "c_str", "CString", "as_c_str"]; pub const EARLY_CONTEXT: [&str; 2] = ["rustc_lint", "EarlyContext"]; pub const EARLY_LINT_PASS: [&str; 3] = ["rustc_lint", "passes", "EarlyLintPass"]; +pub const CHILD: [&str; 3] = ["std", "process", "Child"]; +pub const CHILD_ID: [&str; 4] = ["std", "process", "Child", "id"]; +pub const CHILD_KILL: [&str; 4] = ["std", "process", "Child", "kill"]; pub const F32_EPSILON: [&str; 4] = ["core", "f32", "", "EPSILON"]; pub const F64_EPSILON: [&str; 4] = ["core", "f64", "", "EPSILON"]; pub const FILE_OPTIONS: [&str; 4] = ["std", "fs", "File", "options"]; diff --git a/tests/ui/suspicious_command_arg_space.fixed b/tests/ui/suspicious_command_arg_space.fixed index 5d7b1e0c17f25..704d6ea1bb837 100644 --- a/tests/ui/suspicious_command_arg_space.fixed +++ b/tests/ui/suspicious_command_arg_space.fixed @@ -1,3 +1,4 @@ +#![allow(clippy::zombie_processes)] fn main() { // Things it should warn about: std::process::Command::new("echo").args(["-n", "hello"]).spawn().unwrap(); diff --git a/tests/ui/suspicious_command_arg_space.rs b/tests/ui/suspicious_command_arg_space.rs index 8abd9803a0c6f..2a2a7557381c4 100644 --- a/tests/ui/suspicious_command_arg_space.rs +++ b/tests/ui/suspicious_command_arg_space.rs @@ -1,3 +1,4 @@ +#![allow(clippy::zombie_processes)] fn main() { // Things it should warn about: std::process::Command::new("echo").arg("-n hello").spawn().unwrap(); diff --git a/tests/ui/suspicious_command_arg_space.stderr b/tests/ui/suspicious_command_arg_space.stderr index d2517b66b5661..6fd07d07d7be6 100644 --- a/tests/ui/suspicious_command_arg_space.stderr +++ b/tests/ui/suspicious_command_arg_space.stderr @@ -1,5 +1,5 @@ error: single argument that looks like it should be multiple arguments - --> tests/ui/suspicious_command_arg_space.rs:3:44 + --> tests/ui/suspicious_command_arg_space.rs:4:44 | LL | std::process::Command::new("echo").arg("-n hello").spawn().unwrap(); | ^^^^^^^^^^ @@ -12,7 +12,7 @@ LL | std::process::Command::new("echo").args(["-n", "hello"]).spawn().unwrap | ~~~~ ~~~~~~~~~~~~~~~ error: single argument that looks like it should be multiple arguments - --> tests/ui/suspicious_command_arg_space.rs:6:43 + --> tests/ui/suspicious_command_arg_space.rs:7:43 | LL | std::process::Command::new("cat").arg("--number file").spawn().unwrap(); | ^^^^^^^^^^^^^^^ diff --git a/tests/ui/zombie_processes.rs b/tests/ui/zombie_processes.rs new file mode 100644 index 0000000000000..a2abc7fc3a179 --- /dev/null +++ b/tests/ui/zombie_processes.rs @@ -0,0 +1,138 @@ +#![warn(clippy::zombie_processes)] +#![allow(clippy::if_same_then_else, clippy::ifs_same_cond)] + +use std::process::{Child, Command}; + +fn main() { + { + // Check that #[expect] works + #[expect(clippy::zombie_processes)] + let mut x = Command::new("").spawn().unwrap(); + } + + { + let mut x = Command::new("").spawn().unwrap(); + //~^ ERROR: spawned process is never `wait()`ed on + x.kill(); + x.id(); + } + { + let mut x = Command::new("").spawn().unwrap(); + x.wait().unwrap(); // OK + } + { + let x = Command::new("").spawn().unwrap(); + x.wait_with_output().unwrap(); // OK + } + { + let mut x = Command::new("").spawn().unwrap(); + x.try_wait().unwrap(); // OK + } + { + let mut x = Command::new("").spawn().unwrap(); + let mut r = &mut x; + r.wait().unwrap(); // OK, not calling `.wait()` directly on `x` but through `r` -> `x` + } + { + let mut x = Command::new("").spawn().unwrap(); + process_child(x); // OK, other function might call `.wait()` so assume it does + } + { + let mut x = Command::new("").spawn().unwrap(); + //~^ ERROR: spawned process is never `wait()`ed on + let v = &x; + // (allow shared refs is fine because one cannot call `.wait()` through that) + } + + // https://github.com/rust-lang/rust-clippy/pull/11476#issuecomment-1718456033 + // Unconditionally exiting the process in various ways (should not lint) + { + let mut x = Command::new("").spawn().unwrap(); + std::process::exit(0); + } + { + let mut x = Command::new("").spawn().unwrap(); + std::process::abort(); // same as above, but abort instead of exit + } + { + let mut x = Command::new("").spawn().unwrap(); + if true { /* nothing */ } + std::process::abort(); // still unconditionally exits + } + + // Conditionally exiting + // It should assume that it might not exit and still lint + { + let mut x = Command::new("").spawn().unwrap(); + //~^ ERROR: spawned process is never `wait()`ed on + if true { + std::process::exit(0); + } + } + { + let mut x = Command::new("").spawn().unwrap(); + //~^ ERROR: spawned process is never `wait()`ed on + if true { + while false {} + // Calling `exit()` after leaving a while loop should still be linted. + std::process::exit(0); + } + } + + { + let mut x = { Command::new("").spawn().unwrap() }; + x.wait().unwrap(); + } + + { + struct S { + c: Child, + } + + let mut s = S { + c: Command::new("").spawn().unwrap(), + }; + s.c.wait().unwrap(); + } + + { + let mut x = Command::new("").spawn().unwrap(); + //~^ ERROR: spawned process is never `wait()`ed on + if true { + return; + } + x.wait().unwrap(); + } + + { + let mut x = Command::new("").spawn().unwrap(); + //~^ ERROR: spawned process is never `wait()`ed on + if true { + x.wait().unwrap(); + } + } + + { + let mut x = Command::new("").spawn().unwrap(); + if true { + x.wait().unwrap(); + } else if true { + x.wait().unwrap(); + } else { + x.wait().unwrap(); + } + } + + { + let mut x = Command::new("").spawn().unwrap(); + if true { + x.wait().unwrap(); + return; + } + x.wait().unwrap(); + } +} + +fn process_child(c: Child) { + todo!() +} diff --git a/tests/ui/zombie_processes.stderr b/tests/ui/zombie_processes.stderr new file mode 100644 index 0000000000000..eec821a4c8f18 --- /dev/null +++ b/tests/ui/zombie_processes.stderr @@ -0,0 +1,64 @@ +error: spawned process is never `wait()`ed on + --> tests/ui/zombie_processes.rs:14:21 + | +LL | let mut x = Command::new("").spawn().unwrap(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: consider calling `.wait()` + = note: not doing so might leave behind zombie processes + = note: see https://doc.rust-lang.org/stable/std/process/struct.Child.html#warning + = note: `-D clippy::zombie-processes` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::zombie_processes)]` + +error: spawned process is never `wait()`ed on + --> tests/ui/zombie_processes.rs:41:21 + | +LL | let mut x = Command::new("").spawn().unwrap(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: consider calling `.wait()` + = note: not doing so might leave behind zombie processes + = note: see https://doc.rust-lang.org/stable/std/process/struct.Child.html#warning + +error: spawned process is never `wait()`ed on + --> tests/ui/zombie_processes.rs:66:21 + | +LL | let mut x = Command::new("").spawn().unwrap(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: consider calling `.wait()` + = note: not doing so might leave behind zombie processes + = note: see https://doc.rust-lang.org/stable/std/process/struct.Child.html#warning + +error: spawned process is never `wait()`ed on + --> tests/ui/zombie_processes.rs:73:21 + | +LL | let mut x = Command::new("").spawn().unwrap(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: consider calling `.wait()` + = note: not doing so might leave behind zombie processes + = note: see https://doc.rust-lang.org/stable/std/process/struct.Child.html#warning + +error: spawned process is never `wait()`ed on + --> tests/ui/zombie_processes.rs:99:21 + | +LL | let mut x = Command::new("").spawn().unwrap(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: consider calling `.wait()` + = note: not doing so might leave behind zombie processes + = note: see https://doc.rust-lang.org/stable/std/process/struct.Child.html#warning + +error: spawned process is never `wait()`ed on + --> tests/ui/zombie_processes.rs:108:21 + | +LL | let mut x = Command::new("").spawn().unwrap(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: consider calling `.wait()` + = note: not doing so might leave behind zombie processes + = note: see https://doc.rust-lang.org/stable/std/process/struct.Child.html#warning + +error: aborting due to 6 previous errors + diff --git a/tests/ui/zombie_processes_fixable.fixed b/tests/ui/zombie_processes_fixable.fixed new file mode 100644 index 0000000000000..6045262f519a7 --- /dev/null +++ b/tests/ui/zombie_processes_fixable.fixed @@ -0,0 +1,26 @@ +#![warn(clippy::zombie_processes)] +#![allow(clippy::needless_return)] + +use std::process::{Child, Command}; + +fn main() { + let _ = Command::new("").spawn().unwrap().wait(); + //~^ ERROR: spawned process is never `wait()`ed on + Command::new("").spawn().unwrap().wait(); + //~^ ERROR: spawned process is never `wait()`ed on + spawn_proc().wait(); + //~^ ERROR: spawned process is never `wait()`ed on + spawn_proc().wait().unwrap(); // OK +} + +fn not_main() { + Command::new("").spawn().unwrap().wait(); +} + +fn spawn_proc() -> Child { + Command::new("").spawn().unwrap() +} + +fn spawn_proc_2() -> Child { + return Command::new("").spawn().unwrap(); +} diff --git a/tests/ui/zombie_processes_fixable.rs b/tests/ui/zombie_processes_fixable.rs new file mode 100644 index 0000000000000..e1ecb771641e2 --- /dev/null +++ b/tests/ui/zombie_processes_fixable.rs @@ -0,0 +1,26 @@ +#![warn(clippy::zombie_processes)] +#![allow(clippy::needless_return)] + +use std::process::{Child, Command}; + +fn main() { + let _ = Command::new("").spawn().unwrap(); + //~^ ERROR: spawned process is never `wait()`ed on + Command::new("").spawn().unwrap(); + //~^ ERROR: spawned process is never `wait()`ed on + spawn_proc(); + //~^ ERROR: spawned process is never `wait()`ed on + spawn_proc().wait().unwrap(); // OK +} + +fn not_main() { + Command::new("").spawn().unwrap(); +} + +fn spawn_proc() -> Child { + Command::new("").spawn().unwrap() +} + +fn spawn_proc_2() -> Child { + return Command::new("").spawn().unwrap(); +} diff --git a/tests/ui/zombie_processes_fixable.stderr b/tests/ui/zombie_processes_fixable.stderr new file mode 100644 index 0000000000000..e1c40472c325e --- /dev/null +++ b/tests/ui/zombie_processes_fixable.stderr @@ -0,0 +1,40 @@ +error: spawned process is never `wait()`ed on + --> tests/ui/zombie_processes_fixable.rs:7:13 + | +LL | let _ = Command::new("").spawn().unwrap(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- help: try: `.wait()` + | + = note: not doing so might leave behind zombie processes + = note: see https://doc.rust-lang.org/stable/std/process/struct.Child.html#warning + = note: `-D clippy::zombie-processes` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::zombie_processes)]` + +error: spawned process is never `wait()`ed on + --> tests/ui/zombie_processes_fixable.rs:9:5 + | +LL | Command::new("").spawn().unwrap(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- help: try: `.wait()` + | + = note: not doing so might leave behind zombie processes + = note: see https://doc.rust-lang.org/stable/std/process/struct.Child.html#warning + +error: spawned process is never `wait()`ed on + --> tests/ui/zombie_processes_fixable.rs:11:5 + | +LL | spawn_proc(); + | ^^^^^^^^^^^^- help: try: `.wait()` + | + = note: not doing so might leave behind zombie processes + = note: see https://doc.rust-lang.org/stable/std/process/struct.Child.html#warning + +error: spawned process is never `wait()`ed on + --> tests/ui/zombie_processes_fixable.rs:17:5 + | +LL | Command::new("").spawn().unwrap(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- help: try: `.wait()` + | + = note: not doing so might leave behind zombie processes + = note: see https://doc.rust-lang.org/stable/std/process/struct.Child.html#warning + +error: aborting due to 4 previous errors + From cea707d96033d5e14d3c2b287b0bedd2847db680 Mon Sep 17 00:00:00 2001 From: binarycat Date: Tue, 27 Aug 2024 16:31:40 -0400 Subject: [PATCH 0202/2194] emit old upstream warning no matter the build step --- src/bootstrap/src/core/build_steps/format.rs | 4 +--- src/bootstrap/src/core/sanity.rs | 6 ++++++ 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/bootstrap/src/core/build_steps/format.rs b/src/bootstrap/src/core/build_steps/format.rs index 1e78583476ad6..91fbc57429a96 100644 --- a/src/bootstrap/src/core/build_steps/format.rs +++ b/src/bootstrap/src/core/build_steps/format.rs @@ -7,7 +7,7 @@ use std::sync::mpsc::SyncSender; use std::sync::Mutex; use build_helper::ci::CiEnv; -use build_helper::git::{get_git_modified_files, warn_old_master_branch}; +use build_helper::git::get_git_modified_files; use ignore::WalkBuilder; use crate::core::builder::Builder; @@ -93,8 +93,6 @@ fn get_modified_rs_files(build: &Builder<'_>) -> Result>, Str if !verify_rustfmt_version(build) { return Ok(None); } - warn_old_master_branch(&build.config.git_config(), &build.config.src) - .map_err(|e| e.to_string())?; get_git_modified_files(&build.config.git_config(), Some(&build.config.src), &["rs"]) } diff --git a/src/bootstrap/src/core/sanity.rs b/src/bootstrap/src/core/sanity.rs index c42d4c56c3816..37b88ca4fa5a0 100644 --- a/src/bootstrap/src/core/sanity.rs +++ b/src/bootstrap/src/core/sanity.rs @@ -15,6 +15,8 @@ use std::ffi::{OsStr, OsString}; use std::path::PathBuf; use std::{env, fs}; +use build_helper::git::warn_old_master_branch; + #[cfg(not(feature = "bootstrap-self-test"))] use crate::builder::Builder; use crate::builder::Kind; @@ -379,4 +381,8 @@ $ pacman -R cmake && pacman -S mingw-w64-x86_64-cmake if let Some(ref s) = build.config.ccache { cmd_finder.must_have(s); } + + warn_old_master_branch(&build.config.git_config(), &build.config.src) + .map_err(|e| e.to_string()) + .unwrap(); } From 1a2ec2634e378c8e1b8c531f29c4f983b87a5764 Mon Sep 17 00:00:00 2001 From: Ben Kimock Date: Tue, 27 Aug 2024 19:10:22 -0400 Subject: [PATCH 0203/2194] Make option-like-enum.rs UB-free and portable --- tests/debuginfo/option-like-enum.rs | 39 +++++++++++------------------ 1 file changed, 14 insertions(+), 25 deletions(-) diff --git a/tests/debuginfo/option-like-enum.rs b/tests/debuginfo/option-like-enum.rs index d370796efa9d2..72a41986dcef0 100644 --- a/tests/debuginfo/option-like-enum.rs +++ b/tests/debuginfo/option-like-enum.rs @@ -8,22 +8,22 @@ // gdb-command:run // gdb-command:print some -// gdb-check:$1 = core::option::Option<&u32>::Some(0x12345678) +// gdb-check:$1 = core::option::Option<&u32>::Some(0x[...]) // gdb-command:print none // gdb-check:$2 = core::option::Option<&u32>::None // gdb-command:print full -// gdb-check:$3 = option_like_enum::MoreFields::Full(454545, 0x87654321, 9988) +// gdb-check:$3 = option_like_enum::MoreFields::Full(454545, 0x[...], 9988) -// gdb-command:print empty_gdb.discr -// gdb-check:$4 = (*mut isize) 0x1 +// gdb-command:print empty +// gdb-check:$4 = option_like_enum::MoreFields::Empty // gdb-command:print droid -// gdb-check:$5 = option_like_enum::NamedFields::Droid{id: 675675, range: 10000001, internals: 0x43218765} +// gdb-check:$5 = option_like_enum::NamedFields::Droid{id: 675675, range: 10000001, internals: 0x[...]} -// gdb-command:print void_droid_gdb.internals -// gdb-check:$6 = (*mut isize) 0x1 +// gdb-command:print void_droid +// gdb-check:$6 = option_like_enum::NamedFields::Void // gdb-command:print nested_non_zero_yep // gdb-check:$7 = option_like_enum::NestedNonZero::Yep(10.5, option_like_enum::NestedNonZeroField {a: 10, b: 20, c: 0x[...]}) @@ -39,19 +39,19 @@ // lldb-command:run // lldb-command:v some -// lldb-check:[...] Some(&0x12345678) +// lldb-check:[...] Some(&0x[...]) // lldb-command:v none // lldb-check:[...] None // lldb-command:v full -// lldb-check:[...] Full(454545, &0x87654321, 9988) +// lldb-check:[...] Full(454545, &0x[...], 9988) // lldb-command:v empty // lldb-check:[...] Empty // lldb-command:v droid -// lldb-check:[...] Droid { id: 675675, range: 10000001, internals: &0x43218765 } +// lldb-check:[...] Droid { id: 675675, range: 10000001, internals: &0x[...] } // lldb-command:v void_droid // lldb-check:[...] Void @@ -76,11 +76,6 @@ // contains a non-nullable pointer, then this value is used as the discriminator. // The test cases in this file make sure that something readable is generated for // this kind of types. -// If the non-empty variant contains a single non-nullable pointer than the whole -// item is represented as just a pointer and not wrapped in a struct. -// Unfortunately (for these test cases) the content of the non-discriminant fields -// in the null-case is not defined. So we just read the discriminator field in -// this case (by casting the value to a memory-equivalent struct). enum MoreFields<'a> { Full(u32, &'a isize, i16), @@ -120,32 +115,26 @@ fn main() { let some_str: Option<&'static str> = Some("abc"); let none_str: Option<&'static str> = None; - let some: Option<&u32> = Some(unsafe { std::mem::transmute(0x12345678_usize) }); + let some: Option<&u32> = Some(&1234); let none: Option<&u32> = None; - let full = MoreFields::Full(454545, unsafe { std::mem::transmute(0x87654321_usize) }, 9988); - + let full = MoreFields::Full(454545, &1234, 9988); let empty = MoreFields::Empty; - let empty_gdb: &MoreFieldsRepr = unsafe { std::mem::transmute(&MoreFields::Empty) }; let droid = NamedFields::Droid { id: 675675, range: 10000001, - internals: unsafe { std::mem::transmute(0x43218765_usize) } + internals: &1234, }; - let void_droid = NamedFields::Void; - let void_droid_gdb: &NamedFieldsRepr = unsafe { std::mem::transmute(&NamedFields::Void) }; - let x = 'x'; let nested_non_zero_yep = NestedNonZero::Yep( 10.5, NestedNonZeroField { a: 10, b: 20, - c: &x + c: &'x', }); - let nested_non_zero_nope = NestedNonZero::Nope; zzz(); // #break From 3743cdb0e2d93f61c934c8fc73aa13dc8e9b8ab1 Mon Sep 17 00:00:00 2001 From: binarycat Date: Tue, 27 Aug 2024 19:15:46 -0400 Subject: [PATCH 0204/2194] downgrade git error to a warning, and skip UX check in CI --- src/bootstrap/src/core/sanity.rs | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/bootstrap/src/core/sanity.rs b/src/bootstrap/src/core/sanity.rs index 37b88ca4fa5a0..cb07662482014 100644 --- a/src/bootstrap/src/core/sanity.rs +++ b/src/bootstrap/src/core/sanity.rs @@ -382,7 +382,13 @@ $ pacman -R cmake && pacman -S mingw-w64-x86_64-cmake cmd_finder.must_have(s); } - warn_old_master_branch(&build.config.git_config(), &build.config.src) - .map_err(|e| e.to_string()) - .unwrap(); + // this warning is useless in CI, + // and CI probably won't have the right branches anyway. + if !build_helper::ci::CiEnv::is_ci() { + if let Err(e) = warn_old_master_branch(&build.config.git_config(), &build.config.src) + .map_err(|e| e.to_string()) + { + eprintln!("unable to check if upstream branch is old: {e}"); + } + } } From 992dd0bbe39fc65257fd9e8bfd21a1d0779ec52e Mon Sep 17 00:00:00 2001 From: Miguel Ojeda Date: Sat, 10 Aug 2024 14:56:22 +0200 Subject: [PATCH 0205/2194] CI: rfl: add a couple comments to split the steps and document them Signed-off-by: Miguel Ojeda --- src/ci/docker/scripts/rfl-build.sh | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/ci/docker/scripts/rfl-build.sh b/src/ci/docker/scripts/rfl-build.sh index 389abb2fdd38c..90706a550174f 100755 --- a/src/ci/docker/scripts/rfl-build.sh +++ b/src/ci/docker/scripts/rfl-build.sh @@ -62,11 +62,20 @@ make -C linux LLVM=1 -j$(($(nproc) + 1)) \ defconfig \ rfl-for-rust-ci.config +# Build a few Rust targets +# +# This does not include building the C side of the kernel nor linking, +# which can find other issues, but it is much faster. +# +# This includes transforming `rustdoc` tests into KUnit ones thanks to +# `CONFIG_RUST_KERNEL_DOCTESTS=y` above (which, for the moment, uses the +# unstable `--test-builder` and `--no-run`). make -C linux LLVM=1 -j$(($(nproc) + 1)) \ samples/rust/rust_minimal.o \ samples/rust/rust_print.o \ drivers/net/phy/ax88796b_rust.o \ rust/doctests_kernel_generated.o +# Generate documentation make -C linux LLVM=1 -j$(($(nproc) + 1)) \ rustdoc From d783b1dabdcf7e61612d9ab7dde35f38251d3736 Mon Sep 17 00:00:00 2001 From: Miguel Ojeda Date: Wed, 28 Aug 2024 01:53:47 +0200 Subject: [PATCH 0206/2194] CI: rfl: switch to a stage 2 build Apparently tools like `rustfmt` require it in order to find the right `librustc_driver.so` without extra tweaks. Signed-off-by: Miguel Ojeda --- src/ci/docker/scripts/rfl-build.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ci/docker/scripts/rfl-build.sh b/src/ci/docker/scripts/rfl-build.sh index 90706a550174f..51644f2f47e77 100755 --- a/src/ci/docker/scripts/rfl-build.sh +++ b/src/ci/docker/scripts/rfl-build.sh @@ -5,7 +5,7 @@ set -euo pipefail LINUX_VERSION=4c7864e81d8bbd51036dacf92fb0a400e13aaeee # Build rustc, rustdoc and cargo -../x.py build --stage 1 library rustdoc +../x.py build --stage 2 library rustdoc ../x.py build --stage 0 cargo # Install rustup so that we can use the built toolchain easily, and also @@ -16,7 +16,7 @@ sh rustup.sh -y --default-toolchain none source /cargo/env BUILD_DIR=$(realpath ./build) -rustup toolchain link local "${BUILD_DIR}"/x86_64-unknown-linux-gnu/stage1 +rustup toolchain link local "${BUILD_DIR}"/x86_64-unknown-linux-gnu/stage2 rustup default local mkdir -p rfl From 824397ddf6536664ec91ac42c6473b7cbf8844f6 Mon Sep 17 00:00:00 2001 From: Miguel Ojeda Date: Sat, 10 Aug 2024 16:35:52 +0200 Subject: [PATCH 0207/2194] CI: rfl: add a Clippy build Signed-off-by: Miguel Ojeda --- src/ci/docker/scripts/rfl-build.sh | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/src/ci/docker/scripts/rfl-build.sh b/src/ci/docker/scripts/rfl-build.sh index 51644f2f47e77..2f9ec3c23a8e8 100755 --- a/src/ci/docker/scripts/rfl-build.sh +++ b/src/ci/docker/scripts/rfl-build.sh @@ -4,8 +4,8 @@ set -euo pipefail LINUX_VERSION=4c7864e81d8bbd51036dacf92fb0a400e13aaeee -# Build rustc, rustdoc and cargo -../x.py build --stage 2 library rustdoc +# Build rustc, rustdoc, cargo and clippy-driver +../x.py build --stage 2 library rustdoc clippy ../x.py build --stage 0 cargo # Install rustup so that we can use the built toolchain easily, and also @@ -79,3 +79,14 @@ make -C linux LLVM=1 -j$(($(nproc) + 1)) \ # Generate documentation make -C linux LLVM=1 -j$(($(nproc) + 1)) \ rustdoc + +# Re-build with Clippy enabled +# +# This should not introduce Clippy errors, since `CONFIG_WERROR` is not +# set (thus no `-Dwarnings`) and the kernel uses `-W` for all Clippy +# lints, including `clippy::all`. However, it could catch ICEs. +make -C linux LLVM=1 -j$(($(nproc) + 1)) CLIPPY=1 \ + samples/rust/rust_minimal.o \ + samples/rust/rust_print.o \ + drivers/net/phy/ax88796b_rust.o \ + rust/doctests_kernel_generated.o From d584f7099a3c17c76a38f686a9af0b1d36a686ab Mon Sep 17 00:00:00 2001 From: Miguel Ojeda Date: Sat, 10 Aug 2024 16:47:20 +0200 Subject: [PATCH 0208/2194] CI: rfl: add a `rustfmt` run This change will also remove the current warnings in the build due to `rustfmt` not being available (for `bindgen` output): error: 'rustfmt' is not installed for the custom toolchain 'local'. note: this is a custom toolchain, which cannot use `rustup component add` help: if you built this toolchain from source, and used `rustup toolchain link`, then you may be able to build the component with `x.py` Failed to run rustfmt: Internal rustfmt error (non-fatal, continuing) Signed-off-by: Miguel Ojeda --- src/ci/docker/scripts/rfl-build.sh | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/ci/docker/scripts/rfl-build.sh b/src/ci/docker/scripts/rfl-build.sh index 2f9ec3c23a8e8..030b6f6ee1763 100755 --- a/src/ci/docker/scripts/rfl-build.sh +++ b/src/ci/docker/scripts/rfl-build.sh @@ -4,8 +4,8 @@ set -euo pipefail LINUX_VERSION=4c7864e81d8bbd51036dacf92fb0a400e13aaeee -# Build rustc, rustdoc, cargo and clippy-driver -../x.py build --stage 2 library rustdoc clippy +# Build rustc, rustdoc, cargo, clippy-driver and rustfmt +../x.py build --stage 2 library rustdoc clippy rustfmt ../x.py build --stage 0 cargo # Install rustup so that we can use the built toolchain easily, and also @@ -90,3 +90,10 @@ make -C linux LLVM=1 -j$(($(nproc) + 1)) CLIPPY=1 \ samples/rust/rust_print.o \ drivers/net/phy/ax88796b_rust.o \ rust/doctests_kernel_generated.o + +# Format the code +# +# This returns successfully even if there were changes, i.e. it is not +# a check. +make -C linux LLVM=1 -j$(($(nproc) + 1)) \ + rustfmt From 5c558d3ff419fce1d74dd455bb089e26938578af Mon Sep 17 00:00:00 2001 From: Miguel Ojeda Date: Sat, 10 Aug 2024 17:08:44 +0200 Subject: [PATCH 0209/2194] CI: rfl: add macro expanded source build (`-Zunpretty=expanded`) This particular target does not expand into much code, so it is a good first candidate to see if we could keep this in the CI. Signed-off-by: Miguel Ojeda --- src/ci/docker/scripts/rfl-build.sh | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/ci/docker/scripts/rfl-build.sh b/src/ci/docker/scripts/rfl-build.sh index 030b6f6ee1763..e8b6235921db0 100755 --- a/src/ci/docker/scripts/rfl-build.sh +++ b/src/ci/docker/scripts/rfl-build.sh @@ -80,6 +80,14 @@ make -C linux LLVM=1 -j$(($(nproc) + 1)) \ make -C linux LLVM=1 -j$(($(nproc) + 1)) \ rustdoc +# Build macro expanded source (`-Zunpretty=expanded`) +# +# This target also formats the macro expanded code, thus it is also +# intended to catch ICEs with formatting `-Zunpretty=expanded` output +# like https://github.com/rust-lang/rustfmt/issues/6105. +make -C linux LLVM=1 -j$(($(nproc) + 1)) \ + samples/rust/rust_minimal.rsi + # Re-build with Clippy enabled # # This should not introduce Clippy errors, since `CONFIG_WERROR` is not From 778ff06ba6fe5d5c85604e569179100e00dd24d1 Mon Sep 17 00:00:00 2001 From: Miguel Ojeda Date: Sat, 10 Aug 2024 17:22:42 +0200 Subject: [PATCH 0210/2194] CI: rfl: factor out build targets It will make it easier to add more in the future. Signed-off-by: Miguel Ojeda --- src/ci/docker/scripts/rfl-build.sh | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/src/ci/docker/scripts/rfl-build.sh b/src/ci/docker/scripts/rfl-build.sh index e8b6235921db0..8011e07e92e60 100755 --- a/src/ci/docker/scripts/rfl-build.sh +++ b/src/ci/docker/scripts/rfl-build.sh @@ -62,6 +62,13 @@ make -C linux LLVM=1 -j$(($(nproc) + 1)) \ defconfig \ rfl-for-rust-ci.config +BUILD_TARGETS=" + samples/rust/rust_minimal.o + samples/rust/rust_print.o + drivers/net/phy/ax88796b_rust.o + rust/doctests_kernel_generated.o +" + # Build a few Rust targets # # This does not include building the C side of the kernel nor linking, @@ -71,10 +78,7 @@ make -C linux LLVM=1 -j$(($(nproc) + 1)) \ # `CONFIG_RUST_KERNEL_DOCTESTS=y` above (which, for the moment, uses the # unstable `--test-builder` and `--no-run`). make -C linux LLVM=1 -j$(($(nproc) + 1)) \ - samples/rust/rust_minimal.o \ - samples/rust/rust_print.o \ - drivers/net/phy/ax88796b_rust.o \ - rust/doctests_kernel_generated.o + $BUILD_TARGETS # Generate documentation make -C linux LLVM=1 -j$(($(nproc) + 1)) \ @@ -94,10 +98,7 @@ make -C linux LLVM=1 -j$(($(nproc) + 1)) \ # set (thus no `-Dwarnings`) and the kernel uses `-W` for all Clippy # lints, including `clippy::all`. However, it could catch ICEs. make -C linux LLVM=1 -j$(($(nproc) + 1)) CLIPPY=1 \ - samples/rust/rust_minimal.o \ - samples/rust/rust_print.o \ - drivers/net/phy/ax88796b_rust.o \ - rust/doctests_kernel_generated.o + $BUILD_TARGETS # Format the code # From 13e36cf8870a88ab0ac5651d9513b13085baa8cc Mon Sep 17 00:00:00 2001 From: Matthew Giordano Date: Tue, 27 Aug 2024 18:06:00 -0700 Subject: [PATCH 0211/2194] add new_cyclic_in for rc --- library/alloc/src/rc.rs | 60 +++++++++++++++++++++++++++++++++++++++-- 1 file changed, 58 insertions(+), 2 deletions(-) diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rc.rs index f153aa6d3be9a..151eec532613c 100644 --- a/library/alloc/src/rc.rs +++ b/library/alloc/src/rc.rs @@ -687,6 +687,54 @@ impl Rc { } } + /// TODO: document + #[cfg(not(no_global_oom_handling))] + #[unstable(feature = "allocator_api", issue = "32838")] + pub fn new_cyclic_in(data_fn: F, alloc: A) -> Rc + where + F: FnOnce(&Weak) -> T, + { + // Construct the inner in the "uninitialized" state with a single + // weak reference. + let uninit_ptr: NonNull<_> = Box::leak( + Box::new_in(RcBox { + strong: Cell::new(0), + weak: Cell::new(1), + value: mem::MaybeUninit::::uninit(), + }), + alloc, + ) + .into(); + + let init_ptr: NonNull> = uninit_ptr.cast(); + + let weak = Weak { ptr: init_ptr, alloc: Global }; + + // It's important we don't give up ownership of the weak pointer, or + // else the memory might be freed by the time `data_fn` returns. If + // we really wanted to pass ownership, we could create an additional + // weak pointer for ourselves, but this would result in additional + // updates to the weak reference count which might not be necessary + // otherwise. + let data = data_fn(&weak); + + let strong = unsafe { + let inner = init_ptr.as_ptr(); + ptr::write(ptr::addr_of_mut!((*inner).value), data); + + let prev_value = (*inner).strong.get(); + debug_assert_eq!(prev_value, 0, "No prior strong references should exist"); + (*inner).strong.set(1); + + Rc::from_inner(init_ptr) + }; + + // Strong references should collectively own a shared weak reference, + // so don't run the destructor for our old weak reference. + mem::forget(weak); + strong + } + /// Constructs a new `Rc` with uninitialized contents in the provided allocator. /// /// # Examples @@ -1662,7 +1710,11 @@ impl Rc { #[inline] #[stable(feature = "rc_unique", since = "1.4.0")] pub fn get_mut(this: &mut Self) -> Option<&mut T> { - if Rc::is_unique(this) { unsafe { Some(Rc::get_mut_unchecked(this)) } } else { None } + if Rc::is_unique(this) { + unsafe { Some(Rc::get_mut_unchecked(this)) } + } else { + None + } } /// Returns a mutable reference into the given `Rc`, @@ -3239,7 +3291,11 @@ impl Weak { #[must_use] #[stable(feature = "weak_counts", since = "1.41.0")] pub fn strong_count(&self) -> usize { - if let Some(inner) = self.inner() { inner.strong() } else { 0 } + if let Some(inner) = self.inner() { + inner.strong() + } else { + 0 + } } /// Gets the number of `Weak` pointers pointing to this allocation. From 53d5ccd5e965086f7d43d43a1eabdb7064780cb5 Mon Sep 17 00:00:00 2001 From: Caleb Cartwright Date: Thu, 1 Aug 2024 18:42:45 -0500 Subject: [PATCH 0212/2194] refactor: use style edition when loading from partial config --- src/config/config_type.rs | 2 +- src/config/mod.rs | 33 +++++++++++++++++++++++++++++++-- 2 files changed, 32 insertions(+), 3 deletions(-) diff --git a/src/config/config_type.rs b/src/config/config_type.rs index 91efb71744b7a..4b83e974932fc 100644 --- a/src/config/config_type.rs +++ b/src/config/config_type.rs @@ -210,7 +210,7 @@ macro_rules! create_config { )+ #[allow(unreachable_pub)] - pub fn default_with_style_edition(style_edition: StyleEdition) -> Config { + pub(super) fn default_with_style_edition(style_edition: StyleEdition) -> Config { Config { $( $i: ( diff --git a/src/config/mod.rs b/src/config/mod.rs index 5d6047c385d65..6462c62a35809 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -217,9 +217,37 @@ impl PartialConfig { ::toml::to_string(&cloned).map_err(ToTomlError) } + + pub(super) fn to_parsed_config( + self, + style_edition_override: Option, + edition_override: Option, + dir: &Path, + ) -> Config { + Config::default_for_possible_style_edition( + style_edition_override.or(self.style_edition), + edition_override.or(self.edition), + ) + .fill_from_parsed_config(self, dir) + } } impl Config { + pub fn default_for_possible_style_edition( + style_edition: Option, + edition: Option, + ) -> Config { + style_edition.map_or_else( + || { + edition.map_or_else( + || Config::default(), + |e| Self::default_with_style_edition(e.into()), + ) + }, + |se| Self::default_with_style_edition(se), + ) + } + pub(crate) fn version_meets_requirement(&self) -> bool { if self.was_set().required_version() { let version = env!("CARGO_PKG_VERSION"); @@ -324,12 +352,13 @@ impl Config { err.push_str(msg) } } - match parsed.try_into() { + + match parsed.try_into::() { Ok(parsed_config) => { if !err.is_empty() { eprint!("{err}"); } - Ok(Config::default().fill_from_parsed_config(parsed_config, dir)) + Ok(parsed_config.to_parsed_config(None, None, dir)) } Err(e) => { err.push_str("Error: Decoding config file failed:\n"); From c0c3dc7a25f6e4079b41acf46a513e574d9f2855 Mon Sep 17 00:00:00 2001 From: Caleb Cartwright Date: Thu, 1 Aug 2024 22:14:23 -0500 Subject: [PATCH 0213/2194] refactor: include edition & style edition in CliOptions --- src/bin/main.rs | 12 ++++++++++++ src/config/mod.rs | 10 +++++++--- src/config/options.rs | 2 ++ src/git-rustfmt/main.rs | 6 ++++++ 4 files changed, 27 insertions(+), 3 deletions(-) diff --git a/src/bin/main.rs b/src/bin/main.rs index 1185454c8e7d1..2e4877c7569d5 100644 --- a/src/bin/main.rs +++ b/src/bin/main.rs @@ -734,6 +734,18 @@ impl CliOptions for GetOptsOptions { fn config_path(&self) -> Option<&Path> { self.config_path.as_deref() } + + fn edition(&self) -> Option { + self.inline_config + .get("edition") + .map_or(self.edition, |e| Edition::from_str(e).ok()) + } + + fn style_edition(&self) -> Option { + self.inline_config + .get("style_edition") + .map_or(self.style_edition, |se| StyleEdition::from_str(se).ok()) + } } fn edition_from_edition_str(edition_str: &str) -> Result { diff --git a/src/config/mod.rs b/src/config/mod.rs index 6462c62a35809..3b77902fa2ad9 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -376,9 +376,13 @@ pub fn load_config( file_path: Option<&Path>, options: Option, ) -> Result<(Config, Option), Error> { - let over_ride = match options { - Some(ref opts) => config_path(opts)?, - None => None, + let (over_ride, _edition, _style_edition) = match options { + Some(ref opts) => ( + config_path(opts)?, + opts.edition(), + opts.style_edition(), + ), + None => (None, None, None), }; let result = if let Some(over_ride) = over_ride { diff --git a/src/config/options.rs b/src/config/options.rs index 40cfafed29d2e..f7a8c114330f7 100644 --- a/src/config/options.rs +++ b/src/config/options.rs @@ -419,6 +419,8 @@ pub trait CliOptions { /// It is ok if the returned path doesn't exist or is not canonicalized /// (i.e. the callers are expected to handle such cases). fn config_path(&self) -> Option<&Path>; + fn edition(&self) -> Option; + fn style_edition(&self) -> Option; } /// The edition of the syntax and semantics of code (RFC 2052). diff --git a/src/git-rustfmt/main.rs b/src/git-rustfmt/main.rs index 5674f40bef91f..14ac81322b9e5 100644 --- a/src/git-rustfmt/main.rs +++ b/src/git-rustfmt/main.rs @@ -89,6 +89,12 @@ impl CliOptions for NullOptions { fn config_path(&self) -> Option<&Path> { unreachable!(); } + fn edition(&self) -> Option { + unreachable!(); + } + fn style_edition(&self) -> Option { + unreachable!(); + } } fn uncommitted_files() -> Vec { From 0c6515cacc4465ae29d90f4bacc7f95ace7afe0b Mon Sep 17 00:00:00 2001 From: Caleb Cartwright Date: Thu, 1 Aug 2024 23:17:26 -0500 Subject: [PATCH 0214/2194] feat: support style edition differing defaults in config loading --- src/config/mod.rs | 61 ++++++++++++++++++++++++++++++++++------------- src/test/mod.rs | 55 +++++++++++++++++++++++++++++++++++------- 2 files changed, 90 insertions(+), 26 deletions(-) diff --git a/src/config/mod.rs b/src/config/mod.rs index 3b77902fa2ad9..da7adea5a7494 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -271,12 +271,21 @@ impl Config { /// /// Returns a `Config` if the config could be read and parsed from /// the file, otherwise errors. - pub(super) fn from_toml_path(file_path: &Path) -> Result { + pub(super) fn from_toml_path( + file_path: &Path, + edition: Option, + style_edition: Option, + ) -> Result { let mut file = File::open(&file_path)?; let mut toml = String::new(); file.read_to_string(&mut toml)?; - Config::from_toml(&toml, file_path.parent().unwrap()) - .map_err(|err| Error::new(ErrorKind::InvalidData, err)) + Config::from_toml_for_style_edition( + &toml, + file_path.parent().unwrap(), + edition, + style_edition, + ) + .map_err(|err| Error::new(ErrorKind::InvalidData, err)) } /// Resolves the config for input in `dir`. @@ -288,7 +297,11 @@ impl Config { /// /// Returns the `Config` to use, and the path of the project file if there was /// one. - pub(super) fn from_resolved_toml_path(dir: &Path) -> Result<(Config, Option), Error> { + pub(super) fn from_resolved_toml_path( + dir: &Path, + edition: Option, + style_edition: Option, + ) -> Result<(Config, Option), Error> { /// Try to find a project file in the given directory and its parents. /// Returns the path of the nearest project file if one exists, /// or `None` if no project file was found. @@ -333,12 +346,26 @@ impl Config { } match resolve_project_file(dir)? { - None => Ok((Config::default(), None)), - Some(path) => Config::from_toml_path(&path).map(|config| (config, Some(path))), + None => Ok(( + Config::default_for_possible_style_edition(style_edition, edition), + None, + )), + Some(path) => Config::from_toml_path(&path, edition, style_edition) + .map(|config| (config, Some(path))), } } - pub(crate) fn from_toml(toml: &str, dir: &Path) -> Result { + #[allow(dead_code)] + pub(super) fn from_toml(toml: &str, dir: &Path) -> Result { + Self::from_toml_for_style_edition(toml, dir, None, None) + } + + pub(crate) fn from_toml_for_style_edition( + toml: &str, + dir: &Path, + edition: Option, + style_edition: Option, + ) -> Result { let parsed: ::toml::Value = toml .parse() .map_err(|e| format!("Could not parse TOML: {}", e))?; @@ -358,7 +385,7 @@ impl Config { if !err.is_empty() { eprint!("{err}"); } - Ok(parsed_config.to_parsed_config(None, None, dir)) + Ok(parsed_config.to_parsed_config(style_edition, edition, dir)) } Err(e) => { err.push_str("Error: Decoding config file failed:\n"); @@ -376,21 +403,21 @@ pub fn load_config( file_path: Option<&Path>, options: Option, ) -> Result<(Config, Option), Error> { - let (over_ride, _edition, _style_edition) = match options { - Some(ref opts) => ( - config_path(opts)?, - opts.edition(), - opts.style_edition(), - ), + let (over_ride, edition, style_edition) = match options { + Some(ref opts) => (config_path(opts)?, opts.edition(), opts.style_edition()), None => (None, None, None), }; let result = if let Some(over_ride) = over_ride { - Config::from_toml_path(over_ride.as_ref()).map(|p| (p, Some(over_ride.to_owned()))) + Config::from_toml_path(over_ride.as_ref(), edition, style_edition) + .map(|p| (p, Some(over_ride.to_owned()))) } else if let Some(file_path) = file_path { - Config::from_resolved_toml_path(file_path) + Config::from_resolved_toml_path(file_path, edition, style_edition) } else { - Ok((Config::default(), None)) + Ok(( + Config::default_for_possible_style_edition(style_edition, edition), + None, + )) }; result.map(|(mut c, p)| { diff --git a/src/test/mod.rs b/src/test/mod.rs index 7c563801c3243..96706efb16158 100644 --- a/src/test/mod.rs +++ b/src/test/mod.rs @@ -6,14 +6,17 @@ use std::iter::Peekable; use std::mem; use std::path::{Path, PathBuf}; use std::process::{Command, Stdio}; -use std::str::Chars; +use std::str::{Chars, FromStr}; use std::thread; use crate::config::{Color, Config, EmitMode, FileName, NewlineStyle}; use crate::formatting::{ReportedErrors, SourceFile}; use crate::rustfmt_diff::{make_diff, print_diff, DiffLine, Mismatch, ModifiedChunk, OutputWriter}; use crate::source_file; -use crate::{is_nightly_channel, FormatReport, FormatReportFormatterBuilder, Input, Session}; +use crate::{ + is_nightly_channel, Edition, FormatReport, FormatReportFormatterBuilder, Input, Session, + StyleEdition, +}; use rustfmt_config_proc_macro::nightly_only_test; @@ -710,13 +713,22 @@ fn print_mismatches String>( fn read_config(filename: &Path) -> Config { let sig_comments = read_significant_comments(filename); + let (edition, style_edition) = get_editions_from_comments(&sig_comments); // Look for a config file. If there is a 'config' property in the significant comments, use // that. Otherwise, if there are no significant comments at all, look for a config file with // the same name as the test file. let mut config = if !sig_comments.is_empty() { - get_config(sig_comments.get("config").map(Path::new)) + get_config( + sig_comments.get("config").map(Path::new), + edition, + style_edition, + ) } else { - get_config(filename.with_extension("toml").file_name().map(Path::new)) + get_config( + filename.with_extension("toml").file_name().map(Path::new), + edition, + style_edition, + ) }; for (key, val) in &sig_comments { @@ -747,13 +759,28 @@ enum IdempotentCheckError { Parse, } +fn get_editions_from_comments( + comments: &HashMap, +) -> (Option, Option) { + ( + comments + .get("edition") + .map(|e| Edition::from_str(e).expect(&format!("invalid edition value: '{}'", e))), + comments.get("style_edition").map(|se| { + StyleEdition::from_str(se).expect(&format!("invalid style_edition value: '{}'", se)) + }), + ) +} + fn idempotent_check( filename: &PathBuf, opt_config: &Option, ) -> Result { let sig_comments = read_significant_comments(filename); let config = if let Some(ref config_file_path) = opt_config { - Config::from_toml_path(config_file_path).expect("`rustfmt.toml` not found") + let (edition, style_edition) = get_editions_from_comments(&sig_comments); + Config::from_toml_path(config_file_path, edition, style_edition) + .expect("`rustfmt.toml` not found") } else { read_config(filename) }; @@ -777,14 +804,18 @@ fn idempotent_check( // Reads test config file using the supplied (optional) file name. If there's no file name or the // file doesn't exist, just return the default config. Otherwise, the file must be read // successfully. -fn get_config(config_file: Option<&Path>) -> Config { +fn get_config( + config_file: Option<&Path>, + edition: Option, + style_edition: Option, +) -> Config { let config_file_name = match config_file { - None => return Default::default(), + None => return Config::default_for_possible_style_edition(style_edition, edition), Some(file_name) => { let mut full_path = PathBuf::from("tests/config/"); full_path.push(file_name); if !full_path.exists() { - return Default::default(); + return Config::default_for_possible_style_edition(style_edition, edition); }; full_path } @@ -796,7 +827,13 @@ fn get_config(config_file: Option<&Path>) -> Config { .read_to_string(&mut def_config) .expect("Couldn't read config"); - Config::from_toml(&def_config, Path::new("tests/config/")).expect("invalid TOML") + Config::from_toml_for_style_edition( + &def_config, + Path::new("tests/config/"), + edition, + style_edition, + ) + .expect("invalid TOML") } // Reads significant comments of the form: `// rustfmt-key: value` into a hash map. From 065258659db720bfbb4987fa56137450e63d3cc4 Mon Sep 17 00:00:00 2001 From: Caleb Cartwright Date: Thu, 1 Aug 2024 23:26:00 -0500 Subject: [PATCH 0215/2194] feat: implement 2024 Style Edition for expr overflows --- rustfmt.toml | 1 + src/bin/main.rs | 32 ++++ src/config/mod.rs | 2 +- src/config/options.rs | 2 +- .../style-edition/overrides/rustfmt.toml | 2 + .../style_edition/overflow_delim_expr_2015.rs | 155 ++++++++++++++++++ .../style_edition/overflow_delim_expr_2024.rs | 155 ++++++++++++++++++ .../style_edition/overflow_delim_expr_2015.rs | 135 +++++++++++++++ .../style_edition/overflow_delim_expr_2024.rs | 120 ++++++++++++++ 9 files changed, 602 insertions(+), 2 deletions(-) create mode 100644 tests/config/style-edition/overrides/rustfmt.toml create mode 100644 tests/source/configs/style_edition/overflow_delim_expr_2015.rs create mode 100644 tests/source/configs/style_edition/overflow_delim_expr_2024.rs create mode 100644 tests/target/configs/style_edition/overflow_delim_expr_2015.rs create mode 100644 tests/target/configs/style_edition/overflow_delim_expr_2024.rs diff --git a/rustfmt.toml b/rustfmt.toml index 52e4d728b641e..86447eac2e67b 100644 --- a/rustfmt.toml +++ b/rustfmt.toml @@ -1,3 +1,4 @@ error_on_line_overflow = true error_on_unformatted = true style_edition = "2024" +overflow_delimited_expr = false diff --git a/src/bin/main.rs b/src/bin/main.rs index 2e4877c7569d5..9e7476b1f8127 100644 --- a/src/bin/main.rs +++ b/src/bin/main.rs @@ -915,4 +915,36 @@ mod test { let config = get_config(config_file, Some(options)); assert_eq!(config.style_edition(), StyleEdition::Edition2021); } + + #[nightly_only_test] + #[test] + fn correct_defaults_for_style_edition_loaded() { + let mut options = GetOptsOptions::default(); + options.style_edition = Some(StyleEdition::Edition2024); + let config = get_config(None, Some(options)); + assert_eq!(config.style_edition(), StyleEdition::Edition2024); + assert_eq!(config.overflow_delimited_expr(), true); + } + + #[nightly_only_test] + #[test] + fn style_edition_defaults_overridden_from_config() { + let options = GetOptsOptions::default(); + let config_file = Some(Path::new("tests/config/style-edition/overrides")); + let config = get_config(config_file, Some(options)); + assert_eq!(config.style_edition(), StyleEdition::Edition2024); + assert_eq!(config.overflow_delimited_expr(), false); + } + + #[nightly_only_test] + #[test] + fn style_edition_defaults_overridden_from_cli() { + let mut options = GetOptsOptions::default(); + let config_file = Some(Path::new("tests/config/style-edition/just-style-edition")); + options.inline_config = + HashMap::from([("overflow_delimited_expr".to_owned(), "false".to_owned())]); + let config = get_config(config_file, Some(options)); + assert_eq!(config.style_edition(), StyleEdition::Edition2024); + assert_eq!(config.overflow_delimited_expr(), false); + } } diff --git a/src/config/mod.rs b/src/config/mod.rs index da7adea5a7494..cd6870e38902b 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -828,7 +828,7 @@ binop_separator = "Front" remove_nested_parens = true combine_control_expr = true short_array_element_width_threshold = 10 -overflow_delimited_expr = false +overflow_delimited_expr = true struct_field_align_threshold = 0 enum_discrim_align_threshold = 0 match_arm_blocks = true diff --git a/src/config/options.rs b/src/config/options.rs index f7a8c114330f7..46db5186b116e 100644 --- a/src/config/options.rs +++ b/src/config/options.rs @@ -627,7 +627,7 @@ config_option_with_style_edition_default!( RemoveNestedParens, bool, _ => true; CombineControlExpr, bool, _ => true; ShortArrayElementWidthThreshold, usize, _ => 10; - OverflowDelimitedExpr, bool, _ => false; + OverflowDelimitedExpr, bool, Edition2024 => true, _ => false; StructFieldAlignThreshold, usize, _ => 0; EnumDiscrimAlignThreshold, usize, _ => 0; MatchArmBlocks, bool, _ => true; diff --git a/tests/config/style-edition/overrides/rustfmt.toml b/tests/config/style-edition/overrides/rustfmt.toml new file mode 100644 index 0000000000000..24205692b1f5f --- /dev/null +++ b/tests/config/style-edition/overrides/rustfmt.toml @@ -0,0 +1,2 @@ +style_edition = "2024" +overflow_delimited_expr = false diff --git a/tests/source/configs/style_edition/overflow_delim_expr_2015.rs b/tests/source/configs/style_edition/overflow_delim_expr_2015.rs new file mode 100644 index 0000000000000..5cb4a870fc10a --- /dev/null +++ b/tests/source/configs/style_edition/overflow_delim_expr_2015.rs @@ -0,0 +1,155 @@ +// rustfmt-style_edition: 2015 + +fn combine_blocklike() { + do_thing( + |param| { + action(); + foo(param) + }, + ); + + do_thing( + x, + |param| { + action(); + foo(param) + }, + ); + + do_thing( + x, + + // I'll be discussing the `action` with your para(m)legal counsel + |param| { + action(); + foo(param) + }, + ); + + do_thing( + Bar { + x: value, + y: value2, + }, + ); + + do_thing( + x, + Bar { + x: value, + y: value2, + }, + ); + + do_thing( + x, + + // Let me tell you about that one time at the `Bar` + Bar { + x: value, + y: value2, + }, + ); + + do_thing( + &[ + value_with_longer_name, + value2_with_longer_name, + value3_with_longer_name, + value4_with_longer_name, + ], + ); + + do_thing( + x, + &[ + value_with_longer_name, + value2_with_longer_name, + value3_with_longer_name, + value4_with_longer_name, + ], + ); + + do_thing( + x, + + // Just admit it; my list is longer than can be folded on to one line + &[ + value_with_longer_name, + value2_with_longer_name, + value3_with_longer_name, + value4_with_longer_name, + ], + ); + + do_thing( + vec![ + value_with_longer_name, + value2_with_longer_name, + value3_with_longer_name, + value4_with_longer_name, + ], + ); + + do_thing( + x, + vec![ + value_with_longer_name, + value2_with_longer_name, + value3_with_longer_name, + value4_with_longer_name, + ], + ); + + do_thing( + x, + + // Just admit it; my list is longer than can be folded on to one line + vec![ + value_with_longer_name, + value2_with_longer_name, + value3_with_longer_name, + value4_with_longer_name, + ], + ); + + do_thing( + x, + ( + 1, + 2, + 3, + |param| { + action(); + foo(param) + }, + ), + ); +} + +fn combine_struct_sample() { + let identity = verify( + &ctx, + VerifyLogin { + type_: LoginType::Username, + username: args.username.clone(), + password: Some(args.password.clone()), + domain: None, + }, + )?; +} + +fn combine_macro_sample() { + rocket::ignite() + .mount( + "/", + routes![ + http::auth::login, + http::auth::logout, + http::cors::options, + http::action::dance, + http::action::sleep, + ], + ) + .launch(); +} diff --git a/tests/source/configs/style_edition/overflow_delim_expr_2024.rs b/tests/source/configs/style_edition/overflow_delim_expr_2024.rs new file mode 100644 index 0000000000000..66c95e71aa9a1 --- /dev/null +++ b/tests/source/configs/style_edition/overflow_delim_expr_2024.rs @@ -0,0 +1,155 @@ +// rustfmt-style_edition: 2024 + +fn combine_blocklike() { + do_thing( + |param| { + action(); + foo(param) + }, + ); + + do_thing( + x, + |param| { + action(); + foo(param) + }, + ); + + do_thing( + x, + + // I'll be discussing the `action` with your para(m)legal counsel + |param| { + action(); + foo(param) + }, + ); + + do_thing( + Bar { + x: value, + y: value2, + }, + ); + + do_thing( + x, + Bar { + x: value, + y: value2, + }, + ); + + do_thing( + x, + + // Let me tell you about that one time at the `Bar` + Bar { + x: value, + y: value2, + }, + ); + + do_thing( + &[ + value_with_longer_name, + value2_with_longer_name, + value3_with_longer_name, + value4_with_longer_name, + ], + ); + + do_thing( + x, + &[ + value_with_longer_name, + value2_with_longer_name, + value3_with_longer_name, + value4_with_longer_name, + ], + ); + + do_thing( + x, + + // Just admit it; my list is longer than can be folded on to one line + &[ + value_with_longer_name, + value2_with_longer_name, + value3_with_longer_name, + value4_with_longer_name, + ], + ); + + do_thing( + vec![ + value_with_longer_name, + value2_with_longer_name, + value3_with_longer_name, + value4_with_longer_name, + ], + ); + + do_thing( + x, + vec![ + value_with_longer_name, + value2_with_longer_name, + value3_with_longer_name, + value4_with_longer_name, + ], + ); + + do_thing( + x, + + // Just admit it; my list is longer than can be folded on to one line + vec![ + value_with_longer_name, + value2_with_longer_name, + value3_with_longer_name, + value4_with_longer_name, + ], + ); + + do_thing( + x, + ( + 1, + 2, + 3, + |param| { + action(); + foo(param) + }, + ), + ); +} + +fn combine_struct_sample() { + let identity = verify( + &ctx, + VerifyLogin { + type_: LoginType::Username, + username: args.username.clone(), + password: Some(args.password.clone()), + domain: None, + }, + )?; +} + +fn combine_macro_sample() { + rocket::ignite() + .mount( + "/", + routes![ + http::auth::login, + http::auth::logout, + http::cors::options, + http::action::dance, + http::action::sleep, + ], + ) + .launch(); +} diff --git a/tests/target/configs/style_edition/overflow_delim_expr_2015.rs b/tests/target/configs/style_edition/overflow_delim_expr_2015.rs new file mode 100644 index 0000000000000..05d4b8b6d334f --- /dev/null +++ b/tests/target/configs/style_edition/overflow_delim_expr_2015.rs @@ -0,0 +1,135 @@ +// rustfmt-style_edition: 2015 + +fn combine_blocklike() { + do_thing(|param| { + action(); + foo(param) + }); + + do_thing(x, |param| { + action(); + foo(param) + }); + + do_thing( + x, + // I'll be discussing the `action` with your para(m)legal counsel + |param| { + action(); + foo(param) + }, + ); + + do_thing(Bar { + x: value, + y: value2, + }); + + do_thing( + x, + Bar { + x: value, + y: value2, + }, + ); + + do_thing( + x, + // Let me tell you about that one time at the `Bar` + Bar { + x: value, + y: value2, + }, + ); + + do_thing(&[ + value_with_longer_name, + value2_with_longer_name, + value3_with_longer_name, + value4_with_longer_name, + ]); + + do_thing( + x, + &[ + value_with_longer_name, + value2_with_longer_name, + value3_with_longer_name, + value4_with_longer_name, + ], + ); + + do_thing( + x, + // Just admit it; my list is longer than can be folded on to one line + &[ + value_with_longer_name, + value2_with_longer_name, + value3_with_longer_name, + value4_with_longer_name, + ], + ); + + do_thing(vec![ + value_with_longer_name, + value2_with_longer_name, + value3_with_longer_name, + value4_with_longer_name, + ]); + + do_thing( + x, + vec![ + value_with_longer_name, + value2_with_longer_name, + value3_with_longer_name, + value4_with_longer_name, + ], + ); + + do_thing( + x, + // Just admit it; my list is longer than can be folded on to one line + vec![ + value_with_longer_name, + value2_with_longer_name, + value3_with_longer_name, + value4_with_longer_name, + ], + ); + + do_thing( + x, + (1, 2, 3, |param| { + action(); + foo(param) + }), + ); +} + +fn combine_struct_sample() { + let identity = verify( + &ctx, + VerifyLogin { + type_: LoginType::Username, + username: args.username.clone(), + password: Some(args.password.clone()), + domain: None, + }, + )?; +} + +fn combine_macro_sample() { + rocket::ignite() + .mount( + "/", + routes![ + http::auth::login, + http::auth::logout, + http::cors::options, + http::action::dance, + http::action::sleep, + ], + ) + .launch(); +} diff --git a/tests/target/configs/style_edition/overflow_delim_expr_2024.rs b/tests/target/configs/style_edition/overflow_delim_expr_2024.rs new file mode 100644 index 0000000000000..ecd2e8ca79708 --- /dev/null +++ b/tests/target/configs/style_edition/overflow_delim_expr_2024.rs @@ -0,0 +1,120 @@ +// rustfmt-style_edition: 2024 + +fn combine_blocklike() { + do_thing(|param| { + action(); + foo(param) + }); + + do_thing(x, |param| { + action(); + foo(param) + }); + + do_thing( + x, + // I'll be discussing the `action` with your para(m)legal counsel + |param| { + action(); + foo(param) + }, + ); + + do_thing(Bar { + x: value, + y: value2, + }); + + do_thing(x, Bar { + x: value, + y: value2, + }); + + do_thing( + x, + // Let me tell you about that one time at the `Bar` + Bar { + x: value, + y: value2, + }, + ); + + do_thing(&[ + value_with_longer_name, + value2_with_longer_name, + value3_with_longer_name, + value4_with_longer_name, + ]); + + do_thing(x, &[ + value_with_longer_name, + value2_with_longer_name, + value3_with_longer_name, + value4_with_longer_name, + ]); + + do_thing( + x, + // Just admit it; my list is longer than can be folded on to one line + &[ + value_with_longer_name, + value2_with_longer_name, + value3_with_longer_name, + value4_with_longer_name, + ], + ); + + do_thing(vec![ + value_with_longer_name, + value2_with_longer_name, + value3_with_longer_name, + value4_with_longer_name, + ]); + + do_thing(x, vec![ + value_with_longer_name, + value2_with_longer_name, + value3_with_longer_name, + value4_with_longer_name, + ]); + + do_thing( + x, + // Just admit it; my list is longer than can be folded on to one line + vec![ + value_with_longer_name, + value2_with_longer_name, + value3_with_longer_name, + value4_with_longer_name, + ], + ); + + do_thing( + x, + (1, 2, 3, |param| { + action(); + foo(param) + }), + ); +} + +fn combine_struct_sample() { + let identity = verify(&ctx, VerifyLogin { + type_: LoginType::Username, + username: args.username.clone(), + password: Some(args.password.clone()), + domain: None, + })?; +} + +fn combine_macro_sample() { + rocket::ignite() + .mount("/", routes![ + http::auth::login, + http::auth::logout, + http::cors::options, + http::action::dance, + http::action::sleep, + ]) + .launch(); +} From 46cb7d322055625c07823dea8fdfad4c07f98754 Mon Sep 17 00:00:00 2001 From: Caleb Cartwright Date: Wed, 14 Aug 2024 16:05:24 -0500 Subject: [PATCH 0216/2194] refactor: improve mapping of legacy 'version' to 'style_edition' --- src/bin/main.rs | 21 ++++++- src/config/config_type.rs | 25 -------- src/config/mod.rs | 58 +++++++++++++------ src/config/options.rs | 1 + src/git-rustfmt/main.rs | 7 ++- src/lib.rs | 2 +- src/test/mod.rs | 21 ++++--- .../style-edition/just-version/rustfmt.toml | 1 + 8 files changed, 82 insertions(+), 54 deletions(-) create mode 100644 tests/config/style-edition/just-version/rustfmt.toml diff --git a/src/bin/main.rs b/src/bin/main.rs index 9e7476b1f8127..14299434bc747 100644 --- a/src/bin/main.rs +++ b/src/bin/main.rs @@ -19,7 +19,7 @@ use getopts::{Matches, Options}; use crate::rustfmt::{ load_config, CliOptions, Color, Config, Edition, EmitMode, FileLines, FileName, - FormatReportFormatterBuilder, Input, Session, StyleEdition, Verbosity, + FormatReportFormatterBuilder, Input, Session, StyleEdition, Verbosity, Version, }; const BUG_REPORT_URL: &str = "https://github.com/rust-lang/rustfmt/issues/new?labels=bug"; @@ -746,6 +746,13 @@ impl CliOptions for GetOptsOptions { .get("style_edition") .map_or(self.style_edition, |se| StyleEdition::from_str(se).ok()) } + + fn version(&self) -> Option { + self.inline_config + .get("version") + .map(|version| Version::from_str(version).ok()) + .flatten() + } } fn edition_from_edition_str(edition_str: &str) -> Result { @@ -814,6 +821,17 @@ mod test { options.inline_config = HashMap::from([("version".to_owned(), "Two".to_owned())]); let config = get_config(None, Some(options)); assert_eq!(config.style_edition(), StyleEdition::Edition2024); + assert_eq!(config.overflow_delimited_expr(), true); + } + + #[nightly_only_test] + #[test] + fn version_config_file_sets_style_edition_override_correctly() { + let options = GetOptsOptions::default(); + let config_file = Some(Path::new("tests/config/style-edition/just-version")); + let config = get_config(config_file, Some(options)); + assert_eq!(config.style_edition(), StyleEdition::Edition2024); + assert_eq!(config.overflow_delimited_expr(), true); } #[nightly_only_test] @@ -858,6 +876,7 @@ mod test { ]); let config = get_config(None, Some(options)); assert_eq!(config.style_edition(), StyleEdition::Edition2024); + assert_eq!(config.overflow_delimited_expr(), true); } #[nightly_only_test] diff --git a/src/config/config_type.rs b/src/config/config_type.rs index 4b83e974932fc..14217caba0afe 100644 --- a/src/config/config_type.rs +++ b/src/config/config_type.rs @@ -134,7 +134,6 @@ macro_rules! create_config { "fn_args_layout" => self.0.set_fn_args_layout(), "hide_parse_errors" => self.0.set_hide_parse_errors(), "version" => self.0.set_version(), - "edition" => self.0.set_edition(), &_ => (), } } @@ -165,7 +164,6 @@ macro_rules! create_config { "fn_args_layout" => self.0.set_fn_args_layout(), "hide_parse_errors" => self.0.set_hide_parse_errors(), "version" => self.0.set_version(), - "edition" => self.0.set_edition(), &_ => (), } } @@ -264,7 +262,6 @@ macro_rules! create_config { self.set_fn_args_layout(); self.set_hide_parse_errors(); self.set_version(); - self.set_edition(); self } @@ -367,7 +364,6 @@ macro_rules! create_config { "fn_args_layout" => self.set_fn_args_layout(), "hide_parse_errors" => self.set_hide_parse_errors(), "version" => self.set_version(), - "edition" => self.set_edition(), &_ => (), } } @@ -585,30 +581,9 @@ macro_rules! create_config { option which takes precedence. \ The value of the `version` option will be ignored." ); - } else if matches!(self.version(), Version::Two) { - self.style_edition.2 = StyleEdition::Edition2024; - } else { - self.style_edition.2 = StyleEdition::Edition2015; } } - fn set_edition(&mut self) { - let style_edition_set = self.was_set().style_edition() - || self.was_set_cli().style_edition(); - - if style_edition_set || self.was_set().version() { - return; - } - - // User has explicitly specified an Edition value without - // explicitly specifying a Style Edition value, so the Style Edition - // must default to whatever value was provided for Edition - // as per: https://rust-lang.github.io/rfcs/3338-style-evolution.html#explanation - self.style_edition.2 = self.edition().into(); - } - - - #[allow(unreachable_pub)] /// Returns `true` if the config key was explicitly set and is the default value. pub fn is_default(&self, key: &str) -> bool { diff --git a/src/config/mod.rs b/src/config/mod.rs index cd6870e38902b..8a95cc55fcbb2 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -222,11 +222,13 @@ impl PartialConfig { self, style_edition_override: Option, edition_override: Option, + version_override: Option, dir: &Path, ) -> Config { Config::default_for_possible_style_edition( style_edition_override.or(self.style_edition), edition_override.or(self.edition), + version_override.or(self.version), ) .fill_from_parsed_config(self, dir) } @@ -236,16 +238,25 @@ impl Config { pub fn default_for_possible_style_edition( style_edition: Option, edition: Option, + version: Option, ) -> Config { - style_edition.map_or_else( - || { - edition.map_or_else( - || Config::default(), - |e| Self::default_with_style_edition(e.into()), - ) - }, - |se| Self::default_with_style_edition(se), - ) + // Ensures the configuration defaults associated with Style Editions + // follow the precedence set in + // https://rust-lang.github.io/rfcs/3338-style-evolution.html + // 'version' is a legacy alias for 'style_edition' that we'll support + // for some period of time + // FIXME(calebcartwright) - remove 'version' at some point + match (style_edition, version, edition) { + (Some(se), _, _) => Self::default_with_style_edition(se), + (None, Some(Version::Two), _) => { + Self::default_with_style_edition(StyleEdition::Edition2024) + } + (None, Some(Version::One), _) => { + Self::default_with_style_edition(StyleEdition::Edition2015) + } + (None, None, Some(e)) => Self::default_with_style_edition(e.into()), + (None, None, None) => Config::default(), + } } pub(crate) fn version_meets_requirement(&self) -> bool { @@ -275,6 +286,7 @@ impl Config { file_path: &Path, edition: Option, style_edition: Option, + version: Option, ) -> Result { let mut file = File::open(&file_path)?; let mut toml = String::new(); @@ -284,6 +296,7 @@ impl Config { file_path.parent().unwrap(), edition, style_edition, + version, ) .map_err(|err| Error::new(ErrorKind::InvalidData, err)) } @@ -301,6 +314,7 @@ impl Config { dir: &Path, edition: Option, style_edition: Option, + version: Option, ) -> Result<(Config, Option), Error> { /// Try to find a project file in the given directory and its parents. /// Returns the path of the nearest project file if one exists, @@ -347,17 +361,17 @@ impl Config { match resolve_project_file(dir)? { None => Ok(( - Config::default_for_possible_style_edition(style_edition, edition), + Config::default_for_possible_style_edition(style_edition, edition, version), None, )), - Some(path) => Config::from_toml_path(&path, edition, style_edition) + Some(path) => Config::from_toml_path(&path, edition, style_edition, version) .map(|config| (config, Some(path))), } } #[allow(dead_code)] pub(super) fn from_toml(toml: &str, dir: &Path) -> Result { - Self::from_toml_for_style_edition(toml, dir, None, None) + Self::from_toml_for_style_edition(toml, dir, None, None, None) } pub(crate) fn from_toml_for_style_edition( @@ -365,6 +379,7 @@ impl Config { dir: &Path, edition: Option, style_edition: Option, + version: Option, ) -> Result { let parsed: ::toml::Value = toml .parse() @@ -385,7 +400,7 @@ impl Config { if !err.is_empty() { eprint!("{err}"); } - Ok(parsed_config.to_parsed_config(style_edition, edition, dir)) + Ok(parsed_config.to_parsed_config(style_edition, edition, version, dir)) } Err(e) => { err.push_str("Error: Decoding config file failed:\n"); @@ -403,19 +418,24 @@ pub fn load_config( file_path: Option<&Path>, options: Option, ) -> Result<(Config, Option), Error> { - let (over_ride, edition, style_edition) = match options { - Some(ref opts) => (config_path(opts)?, opts.edition(), opts.style_edition()), - None => (None, None, None), + let (over_ride, edition, style_edition, version) = match options { + Some(ref opts) => ( + config_path(opts)?, + opts.edition(), + opts.style_edition(), + opts.version(), + ), + None => (None, None, None, None), }; let result = if let Some(over_ride) = over_ride { - Config::from_toml_path(over_ride.as_ref(), edition, style_edition) + Config::from_toml_path(over_ride.as_ref(), edition, style_edition, version) .map(|p| (p, Some(over_ride.to_owned()))) } else if let Some(file_path) = file_path { - Config::from_resolved_toml_path(file_path, edition, style_edition) + Config::from_resolved_toml_path(file_path, edition, style_edition, version) } else { Ok(( - Config::default_for_possible_style_edition(style_edition, edition), + Config::default_for_possible_style_edition(style_edition, edition, version), None, )) }; diff --git a/src/config/options.rs b/src/config/options.rs index 46db5186b116e..b9e79b9a7de59 100644 --- a/src/config/options.rs +++ b/src/config/options.rs @@ -421,6 +421,7 @@ pub trait CliOptions { fn config_path(&self) -> Option<&Path>; fn edition(&self) -> Option; fn style_edition(&self) -> Option; + fn version(&self) -> Option; } /// The edition of the syntax and semantics of code (RFC 2052). diff --git a/src/git-rustfmt/main.rs b/src/git-rustfmt/main.rs index 14ac81322b9e5..b5a71588e9e4e 100644 --- a/src/git-rustfmt/main.rs +++ b/src/git-rustfmt/main.rs @@ -15,7 +15,9 @@ use getopts::{Matches, Options}; use rustfmt_nightly as rustfmt; use tracing_subscriber::EnvFilter; -use crate::rustfmt::{load_config, CliOptions, FormatReportFormatterBuilder, Input, Session}; +use crate::rustfmt::{ + load_config, CliOptions, FormatReportFormatterBuilder, Input, Session, Version, +}; fn prune_files(files: Vec<&str>) -> Vec<&str> { let prefixes: Vec<_> = files @@ -95,6 +97,9 @@ impl CliOptions for NullOptions { fn style_edition(&self) -> Option { unreachable!(); } + fn version(&self) -> Option { + unreachable!(); + } } fn uncommitted_files() -> Vec { diff --git a/src/lib.rs b/src/lib.rs index 1e9efc5ce946c..7dc698dd92c42 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -48,7 +48,7 @@ use crate::utils::indent_next_line; pub use crate::config::{ load_config, CliOptions, Color, Config, Edition, EmitMode, FileLines, FileName, NewlineStyle, - Range, StyleEdition, Verbosity, + Range, StyleEdition, Verbosity, Version, }; pub use crate::format_report_formatter::{FormatReportFormatter, FormatReportFormatterBuilder}; diff --git a/src/test/mod.rs b/src/test/mod.rs index 96706efb16158..4d22f64f3526c 100644 --- a/src/test/mod.rs +++ b/src/test/mod.rs @@ -15,7 +15,7 @@ use crate::rustfmt_diff::{make_diff, print_diff, DiffLine, Mismatch, ModifiedChu use crate::source_file; use crate::{ is_nightly_channel, Edition, FormatReport, FormatReportFormatterBuilder, Input, Session, - StyleEdition, + StyleEdition, Version, }; use rustfmt_config_proc_macro::nightly_only_test; @@ -713,7 +713,7 @@ fn print_mismatches String>( fn read_config(filename: &Path) -> Config { let sig_comments = read_significant_comments(filename); - let (edition, style_edition) = get_editions_from_comments(&sig_comments); + let (edition, style_edition, version) = get_editions_from_comments(&sig_comments); // Look for a config file. If there is a 'config' property in the significant comments, use // that. Otherwise, if there are no significant comments at all, look for a config file with // the same name as the test file. @@ -722,12 +722,14 @@ fn read_config(filename: &Path) -> Config { sig_comments.get("config").map(Path::new), edition, style_edition, + version, ) } else { get_config( filename.with_extension("toml").file_name().map(Path::new), edition, style_edition, + version, ) }; @@ -761,7 +763,7 @@ enum IdempotentCheckError { fn get_editions_from_comments( comments: &HashMap, -) -> (Option, Option) { +) -> (Option, Option, Option) { ( comments .get("edition") @@ -769,6 +771,9 @@ fn get_editions_from_comments( comments.get("style_edition").map(|se| { StyleEdition::from_str(se).expect(&format!("invalid style_edition value: '{}'", se)) }), + comments + .get("version") + .map(|v| Version::from_str(v).expect(&format!("invalid version value: '{}'", v))), ) } @@ -778,8 +783,8 @@ fn idempotent_check( ) -> Result { let sig_comments = read_significant_comments(filename); let config = if let Some(ref config_file_path) = opt_config { - let (edition, style_edition) = get_editions_from_comments(&sig_comments); - Config::from_toml_path(config_file_path, edition, style_edition) + let (edition, style_edition, version) = get_editions_from_comments(&sig_comments); + Config::from_toml_path(config_file_path, edition, style_edition, version) .expect("`rustfmt.toml` not found") } else { read_config(filename) @@ -808,14 +813,15 @@ fn get_config( config_file: Option<&Path>, edition: Option, style_edition: Option, + version: Option, ) -> Config { let config_file_name = match config_file { - None => return Config::default_for_possible_style_edition(style_edition, edition), + None => return Config::default_for_possible_style_edition(style_edition, edition, version), Some(file_name) => { let mut full_path = PathBuf::from("tests/config/"); full_path.push(file_name); if !full_path.exists() { - return Config::default_for_possible_style_edition(style_edition, edition); + return Config::default_for_possible_style_edition(style_edition, edition, version); }; full_path } @@ -832,6 +838,7 @@ fn get_config( Path::new("tests/config/"), edition, style_edition, + version, ) .expect("invalid TOML") } diff --git a/tests/config/style-edition/just-version/rustfmt.toml b/tests/config/style-edition/just-version/rustfmt.toml new file mode 100644 index 0000000000000..1082fd8888942 --- /dev/null +++ b/tests/config/style-edition/just-version/rustfmt.toml @@ -0,0 +1 @@ +version = "Two" From 736ab66c62ad23b880299e1f997ff1e4d7a9ceef Mon Sep 17 00:00:00 2001 From: Wafarm Date: Mon, 19 Aug 2024 11:37:11 +0800 Subject: [PATCH 0217/2194] Don't suggest adding return type for closures with default return type --- compiler/rustc_hir_typeck/src/_match.rs | 2 +- compiler/rustc_hir_typeck/src/coercion.rs | 4 +- compiler/rustc_hir_typeck/src/expr.rs | 2 +- .../rustc_hir_typeck/src/fn_ctxt/_impl.rs | 39 +++++---------- .../rustc_hir_typeck/src/fn_ctxt/checks.rs | 2 +- .../src/fn_ctxt/suggestions.rs | 49 ++++++++++++++----- .../add_semicolon_non_block_closure.rs | 1 - .../add_semicolon_non_block_closure.stderr | 4 -- .../try-operator-dont-suggest-semicolon.rs | 1 - ...try-operator-dont-suggest-semicolon.stderr | 17 ++----- tests/ui/typeck/issue-81943.stderr | 26 +++++----- 11 files changed, 74 insertions(+), 73 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/_match.rs b/compiler/rustc_hir_typeck/src/_match.rs index 7427fb147166f..573c8d4d7119a 100644 --- a/compiler/rustc_hir_typeck/src/_match.rs +++ b/compiler/rustc_hir_typeck/src/_match.rs @@ -388,7 +388,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { { // check that the `if` expr without `else` is the fn body's expr if expr.span == sp { - return self.get_fn_decl(hir_id).map(|(_, fn_decl, _)| { + return self.get_fn_decl(hir_id).map(|(_, fn_decl)| { let (ty, span) = match fn_decl.output { hir::FnRetTy::DefaultReturn(span) => ("()".to_string(), span), hir::FnRetTy::Return(ty) => (ty_to_string(&self.tcx, ty), ty.span), diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs index dabc5a8939783..8e5d8cba5bef0 100644 --- a/compiler/rustc_hir_typeck/src/coercion.rs +++ b/compiler/rustc_hir_typeck/src/coercion.rs @@ -1859,10 +1859,10 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> { }; // If this is due to an explicit `return`, suggest adding a return type. - if let Some((fn_id, fn_decl, can_suggest)) = fcx.get_fn_decl(block_or_return_id) + if let Some((fn_id, fn_decl)) = fcx.get_fn_decl(block_or_return_id) && !due_to_block { - fcx.suggest_missing_return_type(&mut err, fn_decl, expected, found, can_suggest, fn_id); + fcx.suggest_missing_return_type(&mut err, fn_decl, expected, found, fn_id); } // If this is due to a block, then maybe we forgot a `return`/`break`. diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index dd33b947b0d06..d70c3f6a0d843 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -773,7 +773,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.ret_coercion_span.set(Some(expr.span)); } let cause = self.cause(expr.span, ObligationCauseCode::ReturnNoExpression); - if let Some((_, fn_decl, _)) = self.get_fn_decl(expr.hir_id) { + if let Some((_, fn_decl)) = self.get_fn_decl(expr.hir_id) { coercion.coerce_forced_unit( self, &cause, diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs index 2d205d1ede9cd..1c4a6fc22f797 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs @@ -31,7 +31,7 @@ use rustc_middle::{bug, span_bug}; use rustc_session::lint; use rustc_span::def_id::LocalDefId; use rustc_span::hygiene::DesugaringKind; -use rustc_span::symbol::{kw, sym}; +use rustc_span::symbol::kw; use rustc_span::Span; use rustc_target::abi::FieldIdx; use rustc_trait_selection::error_reporting::infer::need_type_info::TypeAnnotationNeeded; @@ -895,38 +895,28 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ) } - /// Given a `HirId`, return the `HirId` of the enclosing function, its `FnDecl`, and whether a - /// suggestion can be made, `None` otherwise. + /// Given a `HirId`, return the `HirId` of the enclosing function and its `FnDecl`. pub(crate) fn get_fn_decl( &self, blk_id: HirId, - ) -> Option<(LocalDefId, &'tcx hir::FnDecl<'tcx>, bool)> { + ) -> Option<(LocalDefId, &'tcx hir::FnDecl<'tcx>)> { // Get enclosing Fn, if it is a function or a trait method, unless there's a `loop` or // `while` before reaching it, as block tail returns are not available in them. self.tcx.hir().get_fn_id_for_return_block(blk_id).and_then(|item_id| { match self.tcx.hir_node(item_id) { Node::Item(&hir::Item { - ident, - kind: hir::ItemKind::Fn(ref sig, ..), - owner_id, - .. - }) => { - // This is less than ideal, it will not suggest a return type span on any - // method called `main`, regardless of whether it is actually the entry point, - // but it will still present it as the reason for the expected type. - Some((owner_id.def_id, sig.decl, ident.name != sym::main)) - } + kind: hir::ItemKind::Fn(ref sig, ..), owner_id, .. + }) => Some((owner_id.def_id, sig.decl)), Node::TraitItem(&hir::TraitItem { kind: hir::TraitItemKind::Fn(ref sig, ..), owner_id, .. - }) => Some((owner_id.def_id, sig.decl, true)), - // FIXME: Suggestable if this is not a trait implementation + }) => Some((owner_id.def_id, sig.decl)), Node::ImplItem(&hir::ImplItem { kind: hir::ImplItemKind::Fn(ref sig, ..), owner_id, .. - }) => Some((owner_id.def_id, sig.decl, false)), + }) => Some((owner_id.def_id, sig.decl)), Node::Expr(&hir::Expr { hir_id, kind: hir::ExprKind::Closure(&hir::Closure { def_id, kind, fn_decl, .. }), @@ -937,33 +927,30 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // FIXME(async_closures): Implement this. return None; } - hir::ClosureKind::Closure => Some((def_id, fn_decl, true)), + hir::ClosureKind::Closure => Some((def_id, fn_decl)), hir::ClosureKind::Coroutine(hir::CoroutineKind::Desugared( _, hir::CoroutineSource::Fn, )) => { - let (ident, sig, owner_id) = match self.tcx.parent_hir_node(hir_id) { + let (sig, owner_id) = match self.tcx.parent_hir_node(hir_id) { Node::Item(&hir::Item { - ident, kind: hir::ItemKind::Fn(ref sig, ..), owner_id, .. - }) => (ident, sig, owner_id), + }) => (sig, owner_id), Node::TraitItem(&hir::TraitItem { - ident, kind: hir::TraitItemKind::Fn(ref sig, ..), owner_id, .. - }) => (ident, sig, owner_id), + }) => (sig, owner_id), Node::ImplItem(&hir::ImplItem { - ident, kind: hir::ImplItemKind::Fn(ref sig, ..), owner_id, .. - }) => (ident, sig, owner_id), + }) => (sig, owner_id), _ => return None, }; - Some((owner_id.def_id, sig.decl, ident.name != sym::main)) + Some((owner_id.def_id, sig.decl)) } _ => None, } diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs index 5333982c42029..2a1c3b0300482 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs @@ -1841,7 +1841,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // that highlight errors inline. let mut sp = blk.span; let mut fn_span = None; - if let Some((fn_def_id, decl, _)) = self.get_fn_decl(blk.hir_id) { + if let Some((fn_def_id, decl)) = self.get_fn_decl(blk.hir_id) { let ret_sp = decl.output.span(); if let Some(block_sp) = self.parent_item_span(blk.hir_id) { // HACK: on some cases (`ui/liveness/liveness-issue-2163.rs`) the diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs index 031aa6159d2bc..8b63a6df8af00 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs @@ -78,9 +78,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // `break` type mismatches provide better context for tail `loop` expressions. return false; } - if let Some((fn_id, fn_decl, can_suggest)) = self.get_fn_decl(blk_id) { + if let Some((fn_id, fn_decl)) = self.get_fn_decl(blk_id) { pointing_at_return_type = - self.suggest_missing_return_type(err, fn_decl, expected, found, can_suggest, fn_id); + self.suggest_missing_return_type(err, fn_decl, expected, found, fn_id); self.suggest_missing_break_or_return_expr( err, expr, fn_decl, expected, found, blk_id, fn_id, ); @@ -812,7 +812,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { fn_decl: &hir::FnDecl<'tcx>, expected: Ty<'tcx>, found: Ty<'tcx>, - can_suggest: bool, fn_id: LocalDefId, ) -> bool { // Can't suggest `->` on a block-like coroutine @@ -825,28 +824,26 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let found = self.resolve_numeric_literals_with_default(self.resolve_vars_if_possible(found)); // Only suggest changing the return type for methods that - // haven't set a return type at all (and aren't `fn main()` or an impl). + // haven't set a return type at all (and aren't `fn main()`, impl or closure). match &fn_decl.output { - &hir::FnRetTy::DefaultReturn(span) if expected.is_unit() && !can_suggest => { - // `fn main()` must return `()`, do not suggest changing return type - err.subdiagnostic(errors::ExpectedReturnTypeLabel::Unit { span }); - return true; - } + // For closure with default returns, don't suggest adding return type + &hir::FnRetTy::DefaultReturn(_) if self.tcx.is_closure_like(fn_id.to_def_id()) => {} &hir::FnRetTy::DefaultReturn(span) if expected.is_unit() => { - if let Some(found) = found.make_suggestable(self.tcx, false, None) { + if !self.can_add_return_type(fn_id) { + err.subdiagnostic(errors::ExpectedReturnTypeLabel::Unit { span }); + } else if let Some(found) = found.make_suggestable(self.tcx, false, None) { err.subdiagnostic(errors::AddReturnTypeSuggestion::Add { span, found: found.to_string(), }); - return true; } else if let Some(sugg) = suggest_impl_trait(self, self.param_env, found) { err.subdiagnostic(errors::AddReturnTypeSuggestion::Add { span, found: sugg }); - return true; } else { // FIXME: if `found` could be `impl Iterator` we should suggest that. err.subdiagnostic(errors::AddReturnTypeSuggestion::MissingHere { span }); - return true; } + + return true; } hir::FnRetTy::Return(hir_ty) => { if let hir::TyKind::OpaqueDef(item_id, ..) = hir_ty.kind @@ -904,6 +901,32 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { false } + /// Checks whether we can add a return type to a function. + /// Assumes given function doesn't have a explicit return type. + fn can_add_return_type(&self, fn_id: LocalDefId) -> bool { + match self.tcx.hir_node_by_def_id(fn_id) { + Node::Item(&hir::Item { ident, .. }) => { + // This is less than ideal, it will not suggest a return type span on any + // method called `main`, regardless of whether it is actually the entry point, + // but it will still present it as the reason for the expected type. + ident.name != sym::main + } + Node::ImplItem(item) => { + // If it doesn't impl a trait, we can add a return type + let Node::Item(&hir::Item { + kind: hir::ItemKind::Impl(&hir::Impl { of_trait, .. }), + .. + }) = self.tcx.parent_hir_node(item.hir_id()) + else { + unreachable!(); + }; + + of_trait.is_none() + } + _ => true, + } + } + fn try_note_caller_chooses_ty_for_ty_param( &self, diag: &mut Diag<'_>, diff --git a/tests/ui/closures/add_semicolon_non_block_closure.rs b/tests/ui/closures/add_semicolon_non_block_closure.rs index 62c5e343cd345..3ae91be60c5a0 100644 --- a/tests/ui/closures/add_semicolon_non_block_closure.rs +++ b/tests/ui/closures/add_semicolon_non_block_closure.rs @@ -8,5 +8,4 @@ fn main() { foo(|| bar()) //~^ ERROR mismatched types [E0308] //~| HELP consider using a semicolon here - //~| HELP try adding a return type } diff --git a/tests/ui/closures/add_semicolon_non_block_closure.stderr b/tests/ui/closures/add_semicolon_non_block_closure.stderr index 7883db8f98ec5..3dd8f12d55f32 100644 --- a/tests/ui/closures/add_semicolon_non_block_closure.stderr +++ b/tests/ui/closures/add_semicolon_non_block_closure.stderr @@ -8,10 +8,6 @@ help: consider using a semicolon here | LL | foo(|| { bar(); }) | + +++ -help: try adding a return type - | -LL | foo(|| -> i32 bar()) - | ++++++ error: aborting due to 1 previous error diff --git a/tests/ui/suggestions/try-operator-dont-suggest-semicolon.rs b/tests/ui/suggestions/try-operator-dont-suggest-semicolon.rs index 35a06d396f2bb..f882a159f9834 100644 --- a/tests/ui/suggestions/try-operator-dont-suggest-semicolon.rs +++ b/tests/ui/suggestions/try-operator-dont-suggest-semicolon.rs @@ -3,7 +3,6 @@ fn main() -> Result<(), ()> { a(|| { - //~^ HELP: try adding a return type b() //~^ ERROR: mismatched types [E0308] //~| NOTE: expected `()`, found `i32` diff --git a/tests/ui/suggestions/try-operator-dont-suggest-semicolon.stderr b/tests/ui/suggestions/try-operator-dont-suggest-semicolon.stderr index 5506456afe9ca..939285498fb69 100644 --- a/tests/ui/suggestions/try-operator-dont-suggest-semicolon.stderr +++ b/tests/ui/suggestions/try-operator-dont-suggest-semicolon.stderr @@ -1,20 +1,13 @@ error[E0308]: mismatched types - --> $DIR/try-operator-dont-suggest-semicolon.rs:7:9 + --> $DIR/try-operator-dont-suggest-semicolon.rs:6:9 | LL | b() - | ^^^ expected `()`, found `i32` - | -help: consider using a semicolon here - | -LL | b(); - | + -help: try adding a return type - | -LL | a(|| -> i32 { - | ++++++ + | ^^^- help: consider using a semicolon here: `;` + | | + | expected `()`, found `i32` error[E0308]: mismatched types - --> $DIR/try-operator-dont-suggest-semicolon.rs:17:9 + --> $DIR/try-operator-dont-suggest-semicolon.rs:16:9 | LL | / if true { LL | | diff --git a/tests/ui/typeck/issue-81943.stderr b/tests/ui/typeck/issue-81943.stderr index f8da9ef0d180f..041ff10752cf0 100644 --- a/tests/ui/typeck/issue-81943.stderr +++ b/tests/ui/typeck/issue-81943.stderr @@ -2,9 +2,7 @@ error[E0308]: mismatched types --> $DIR/issue-81943.rs:7:9 | LL | f(|x| lib::d!(x)); - | -^^^^^^^^^^ expected `()`, found `i32` - | | - | help: try adding a return type: `-> i32` + | ^^^^^^^^^^ expected `()`, found `i32` | = note: this error originates in the macro `lib::d` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -12,22 +10,28 @@ error[E0308]: mismatched types --> $DIR/issue-81943.rs:8:28 | LL | f(|x| match x { tmp => { g(tmp) } }); - | ^^^^^^ expected `()`, found `i32` + | -------------------^^^^^^---- + | | | + | | expected `()`, found `i32` + | expected this to be `()` | help: consider using a semicolon here | LL | f(|x| match x { tmp => { g(tmp); } }); | + -help: try adding a return type +help: consider using a semicolon here | -LL | f(|x| -> i32 match x { tmp => { g(tmp) } }); - | ++++++ +LL | f(|x| match x { tmp => { g(tmp) } };); + | + error[E0308]: mismatched types --> $DIR/issue-81943.rs:10:38 | LL | ($e:expr) => { match $e { x => { g(x) } } } - | ^^^^ expected `()`, found `i32` + | ------------------^^^^---- + | | | + | | expected `()`, found `i32` + | expected this to be `()` LL | } LL | f(|x| d!(x)); | ----- in this macro invocation @@ -37,10 +41,10 @@ help: consider using a semicolon here | LL | ($e:expr) => { match $e { x => { g(x); } } } | + -help: try adding a return type +help: consider using a semicolon here | -LL | f(|x| -> i32 d!(x)); - | ++++++ +LL | ($e:expr) => { match $e { x => { g(x) } }; } + | + error: aborting due to 3 previous errors From b5bd0fe48a0427a82804759a5acd795851c65e4b Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 27 Aug 2024 15:08:45 +0200 Subject: [PATCH 0218/2194] addr_of on places derived from raw pointers should preserve permissions --- library/core/src/ptr/mod.rs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs index b83a18027193e..5a9c5ed5be3b4 100644 --- a/library/core/src/ptr/mod.rs +++ b/library/core/src/ptr/mod.rs @@ -2285,9 +2285,13 @@ impl fmt::Debug for F { /// `addr_of!(expr)` is equivalent to `&raw const expr`. The macro is *soft-deprecated*; /// use `&raw const` instead. /// -/// It is still an open question whether writing through an `addr_of!`-created pointer is permitted -/// or not. Until that is decided, the same rules as for shared references apply: it is UB to write -/// through a pointer created with this operation, except for bytes located inside an `UnsafeCell`. +/// It is still an open question under which conditions writing through an `addr_of!`-created +/// pointer is permitted. If the place `expr` evaluates to is based on a raw pointer, then the +/// result of `addr_of!` inherits all permissions from that raw pointer. However, if the place is +/// based on a reference, local variable, or `static`, then until all details are decided, the same +/// rules as for shared references apply: it is UB to write through a pointer created with this +/// operation, except for bytes located inside an `UnsafeCell`. Use `&raw mut` (or [`addr_of_mut`]) +/// to create a raw pointer that definitely permits mutation. /// /// Creating a reference with `&`/`&mut` is only allowed if the pointer is properly aligned /// and points to initialized data. For cases where those requirements do not hold, From 36c126f94a689e12ea5b5d0e06d55cdbce26ea8d Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Wed, 28 Aug 2024 10:25:03 +0000 Subject: [PATCH 0219/2194] Rustup to rustc 1.82.0-nightly (1f12b9b0f 2024-08-27) --- rust-toolchain | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust-toolchain b/rust-toolchain index d4781c01c8f44..2c76d34b65d3c 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1,4 +1,4 @@ [toolchain] -channel = "nightly-2024-08-22" +channel = "nightly-2024-08-28" components = ["rust-src", "rustc-dev", "llvm-tools"] profile = "minimal" From 7e4cafb653980b4dc1ca95eb67df8ac4608eab61 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Wed, 28 Aug 2024 12:21:24 +0000 Subject: [PATCH 0220/2194] Fix rustc test suite --- scripts/test_rustc_tests.sh | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/scripts/test_rustc_tests.sh b/scripts/test_rustc_tests.sh index bb5af9127b96e..fcfbaf053deec 100755 --- a/scripts/test_rustc_tests.sh +++ b/scripts/test_rustc_tests.sh @@ -59,6 +59,7 @@ rm -r tests/run-make/mismatching-target-triples # same rm tests/ui/asm/x86_64/issue-96797.rs # const and sym inline asm operands don't work entirely correctly rm tests/ui/asm/x86_64/goto.rs # inline asm labels not supported rm tests/ui/simd/simd-bitmask-notpow2.rs # non-pow-of-2 simd vector sizes +rm -r tests/run-make/embed-source-dwarf # embedding sources in debuginfo # requires LTO rm -r tests/run-make/cdylib @@ -75,6 +76,8 @@ rm -r tests/ui/instrument-coverage/ # missing f16/f128 support rm tests/ui/half-open-range-patterns/half-open-range-pats-semantics.rs +rm tests/ui/asm/aarch64/type-f16.rs +rm tests/ui/consts/const-float-bits-conv.rs # optimization tests # ================== @@ -138,6 +141,7 @@ rm tests/ui/deprecation/deprecated_inline_threshold.rs # missing deprecation war rm tests/ui/process/nofile-limit.rs # TODO some AArch64 linking issue rm tests/ui/backtrace/synchronized-panic-handler.rs # missing needs-unwind annotation rm -r tests/ui/codegen/equal-pointers-unequal # make incorrect assumptions about the location of stack variables +rm -r tests/run-make/libtest-thread-limit # doesn't work with -Zpanic-abort-tests, missing needs-unwind annotation rm tests/ui/stdio-is-blocking.rs # really slow with unoptimized libstd From 2ddcbca0e626cc3856349deeed17814ba6c272d6 Mon Sep 17 00:00:00 2001 From: tunawasabi <77270077+tunawasabi@users.noreply.github.com> Date: Sun, 25 Aug 2024 04:24:27 +0900 Subject: [PATCH 0221/2194] Suggest the struct variant pattern syntax on usage of unit variant pattern for a struct variant --- compiler/rustc_hir_typeck/src/lib.rs | 32 ++++++++++++++++++- .../ui/empty/empty-struct-braces-pat-1.stderr | 10 ++++++ .../ui/empty/empty-struct-braces-pat-3.stderr | 20 ++++++++++++ tests/ui/issues/issue-63983.stderr | 5 +++ .../recover/recover-from-bad-variant.stderr | 5 +++ tests/ui/suggestions/issue-84700.stderr | 5 +++ ...t-variant-form-through-alias-caught.stderr | 10 ++++++ 7 files changed, 86 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_hir_typeck/src/lib.rs b/compiler/rustc_hir_typeck/src/lib.rs index 9ec101196a43f..0a4df619c20f3 100644 --- a/compiler/rustc_hir_typeck/src/lib.rs +++ b/compiler/rustc_hir_typeck/src/lib.rs @@ -45,7 +45,7 @@ pub use coercion::can_coerce; use fn_ctxt::FnCtxt; use rustc_data_structures::unord::UnordSet; use rustc_errors::codes::*; -use rustc_errors::{struct_span_code_err, Applicability, ErrorGuaranteed}; +use rustc_errors::{pluralize, struct_span_code_err, Applicability, ErrorGuaranteed}; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; use rustc_hir::intravisit::Visitor; @@ -421,6 +421,36 @@ fn report_unexpected_variant_res( err.multipart_suggestion_verbose(descr, suggestion, Applicability::MaybeIncorrect); err } + Res::Def(DefKind::Variant, _) if expr.is_none() => { + err.span_label(span, format!("not a {expected}")); + + let fields = &tcx.expect_variant_res(res).fields.raw; + let span = qpath.span().shrink_to_hi().to(span.shrink_to_hi()); + let (msg, sugg) = if fields.is_empty() { + ("use the struct variant pattern syntax".to_string(), " {}".to_string()) + } else { + let msg = format!( + "the struct variant's field{s} {are} being ignored", + s = pluralize!(fields.len()), + are = pluralize!("is", fields.len()) + ); + let fields = fields + .iter() + .map(|field| format!("{}: _", field.name.to_ident_string())) + .collect::>() + .join(", "); + let sugg = format!(" {{ {} }}", fields); + (msg, sugg) + }; + + err.span_suggestion_verbose( + qpath.span().shrink_to_hi().to(span.shrink_to_hi()), + msg, + sugg, + Applicability::HasPlaceholders, + ); + err + } _ => err.with_span_label(span, format!("not a {expected}")), } .emit() diff --git a/tests/ui/empty/empty-struct-braces-pat-1.stderr b/tests/ui/empty/empty-struct-braces-pat-1.stderr index 14e09fc27a06d..c16fbc7de2b29 100644 --- a/tests/ui/empty/empty-struct-braces-pat-1.stderr +++ b/tests/ui/empty/empty-struct-braces-pat-1.stderr @@ -3,12 +3,22 @@ error[E0533]: expected unit struct, unit variant or constant, found struct varia | LL | E::Empty3 => () | ^^^^^^^^^ not a unit struct, unit variant or constant + | +help: use the struct variant pattern syntax + | +LL | E::Empty3 {} => () + | ++ error[E0533]: expected unit struct, unit variant or constant, found struct variant `XE::XEmpty3` --> $DIR/empty-struct-braces-pat-1.rs:31:9 | LL | XE::XEmpty3 => () | ^^^^^^^^^^^ not a unit struct, unit variant or constant + | +help: use the struct variant pattern syntax + | +LL | XE::XEmpty3 {} => () + | ++ error: aborting due to 2 previous errors diff --git a/tests/ui/empty/empty-struct-braces-pat-3.stderr b/tests/ui/empty/empty-struct-braces-pat-3.stderr index 00c8b12e6f984..b2ab7113347ff 100644 --- a/tests/ui/empty/empty-struct-braces-pat-3.stderr +++ b/tests/ui/empty/empty-struct-braces-pat-3.stderr @@ -3,24 +3,44 @@ error[E0164]: expected tuple struct or tuple variant, found struct variant `E::E | LL | E::Empty3() => () | ^^^^^^^^^^^ not a tuple struct or tuple variant + | +help: use the struct variant pattern syntax + | +LL | E::Empty3 {} => () + | ~~ error[E0164]: expected tuple struct or tuple variant, found struct variant `XE::XEmpty3` --> $DIR/empty-struct-braces-pat-3.rs:21:9 | LL | XE::XEmpty3() => () | ^^^^^^^^^^^^^ not a tuple struct or tuple variant + | +help: use the struct variant pattern syntax + | +LL | XE::XEmpty3 {} => () + | ~~ error[E0164]: expected tuple struct or tuple variant, found struct variant `E::Empty3` --> $DIR/empty-struct-braces-pat-3.rs:25:9 | LL | E::Empty3(..) => () | ^^^^^^^^^^^^^ not a tuple struct or tuple variant + | +help: use the struct variant pattern syntax + | +LL | E::Empty3 {} => () + | ~~ error[E0164]: expected tuple struct or tuple variant, found struct variant `XE::XEmpty3` --> $DIR/empty-struct-braces-pat-3.rs:29:9 | LL | XE::XEmpty3(..) => () | ^^^^^^^^^^^^^^^ not a tuple struct or tuple variant + | +help: use the struct variant pattern syntax + | +LL | XE::XEmpty3 {} => () + | ~~ error: aborting due to 4 previous errors diff --git a/tests/ui/issues/issue-63983.stderr b/tests/ui/issues/issue-63983.stderr index f90c81116264a..3539732451ce2 100644 --- a/tests/ui/issues/issue-63983.stderr +++ b/tests/ui/issues/issue-63983.stderr @@ -12,6 +12,11 @@ error[E0533]: expected unit struct, unit variant or constant, found struct varia | LL | MyEnum::Struct => "", | ^^^^^^^^^^^^^^ not a unit struct, unit variant or constant + | +help: the struct variant's field is being ignored + | +LL | MyEnum::Struct { s: _ } => "", + | ++++++++ error: aborting due to 2 previous errors diff --git a/tests/ui/parser/recover/recover-from-bad-variant.stderr b/tests/ui/parser/recover/recover-from-bad-variant.stderr index 04968bbdf999d..0339f86951543 100644 --- a/tests/ui/parser/recover/recover-from-bad-variant.stderr +++ b/tests/ui/parser/recover/recover-from-bad-variant.stderr @@ -19,6 +19,11 @@ error[E0164]: expected tuple struct or tuple variant, found struct variant `Enum | LL | Enum::Foo(a, b) => {} | ^^^^^^^^^^^^^^^ not a tuple struct or tuple variant + | +help: the struct variant's fields are being ignored + | +LL | Enum::Foo { a: _, b: _ } => {} + | ~~~~~~~~~~~~~~ error[E0769]: tuple variant `Enum::Bar` written as struct variant --> $DIR/recover-from-bad-variant.rs:12:9 diff --git a/tests/ui/suggestions/issue-84700.stderr b/tests/ui/suggestions/issue-84700.stderr index ac9f5ab0b0cbb..d07055826606d 100644 --- a/tests/ui/suggestions/issue-84700.stderr +++ b/tests/ui/suggestions/issue-84700.stderr @@ -12,6 +12,11 @@ error[E0164]: expected tuple struct or tuple variant, found struct variant `Farm | LL | FarmAnimal::Chicken(_) => "cluck, cluck!".to_string(), | ^^^^^^^^^^^^^^^^^^^^^^ not a tuple struct or tuple variant + | +help: the struct variant's field is being ignored + | +LL | FarmAnimal::Chicken { num_eggs: _ } => "cluck, cluck!".to_string(), + | ~~~~~~~~~~~~~~~ error: aborting due to 2 previous errors diff --git a/tests/ui/type-alias-enum-variants/incorrect-variant-form-through-alias-caught.stderr b/tests/ui/type-alias-enum-variants/incorrect-variant-form-through-alias-caught.stderr index c21c59397c79e..714b4fd7d25f6 100644 --- a/tests/ui/type-alias-enum-variants/incorrect-variant-form-through-alias-caught.stderr +++ b/tests/ui/type-alias-enum-variants/incorrect-variant-form-through-alias-caught.stderr @@ -14,12 +14,22 @@ error[E0533]: expected unit struct, unit variant or constant, found struct varia | LL | let Alias::Braced = panic!(); | ^^^^^^^^^^^^^ not a unit struct, unit variant or constant + | +help: use the struct variant pattern syntax + | +LL | let Alias::Braced {} = panic!(); + | ++ error[E0164]: expected tuple struct or tuple variant, found struct variant `Alias::Braced` --> $DIR/incorrect-variant-form-through-alias-caught.rs:12:9 | LL | let Alias::Braced(..) = panic!(); | ^^^^^^^^^^^^^^^^^ not a tuple struct or tuple variant + | +help: use the struct variant pattern syntax + | +LL | let Alias::Braced {} = panic!(); + | ~~ error[E0618]: expected function, found enum variant `Alias::Unit` --> $DIR/incorrect-variant-form-through-alias-caught.rs:15:5 From 648545276aa656019cd875e7bce4bd15509c3bd1 Mon Sep 17 00:00:00 2001 From: Ali Bektas Date: Thu, 22 Aug 2024 19:03:00 +0200 Subject: [PATCH 0222/2194] Make cargo_ workspace again --- .../crates/rust-analyzer/src/cli/scip.rs | 2 +- .../crates/rust-analyzer/src/config.rs | 275 +++++++++--------- .../crates/rust-analyzer/src/global_state.rs | 10 + .../src/handlers/notification.rs | 30 +- .../rust-analyzer/src/handlers/request.rs | 6 +- .../crates/rust-analyzer/src/main_loop.rs | 6 +- .../crates/rust-analyzer/src/reload.rs | 16 +- .../crates/rust-analyzer/src/target_spec.rs | 2 +- 8 files changed, 190 insertions(+), 157 deletions(-) diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/scip.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/scip.rs index a8a02712fe291..01bde39579a5e 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/scip.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/scip.rs @@ -51,7 +51,7 @@ impl flags::Scip { // FIXME @alibektas : What happens to errors without logging? error!(?error_sink, "Config Error(s)"); } - let cargo_config = config.cargo(); + let cargo_config = config.cargo(None); let (db, vfs, _) = load_workspace_at( root.as_path().as_ref(), &cargo_config, diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs index 2889af844b14e..9a8075043ed99 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs @@ -76,87 +76,6 @@ config_data! { /// How many worker threads to handle priming caches. The default `0` means to pick automatically. cachePriming_numThreads: NumThreads = NumThreads::Physical, - /// Pass `--all-targets` to cargo invocation. - cargo_allTargets: bool = true, - /// Automatically refresh project info via `cargo metadata` on - /// `Cargo.toml` or `.cargo/config.toml` changes. - pub(crate) cargo_autoreload: bool = true, - /// Run build scripts (`build.rs`) for more precise code analysis. - cargo_buildScripts_enable: bool = true, - /// Specifies the invocation strategy to use when running the build scripts command. - /// If `per_workspace` is set, the command will be executed for each Rust workspace with the - /// workspace as the working directory. - /// If `once` is set, the command will be executed once with the opened project as the - /// working directory. - /// This config only has an effect when `#rust-analyzer.cargo.buildScripts.overrideCommand#` - /// is set. - cargo_buildScripts_invocationStrategy: InvocationStrategy = InvocationStrategy::PerWorkspace, - /// Override the command rust-analyzer uses to run build scripts and - /// build procedural macros. The command is required to output json - /// and should therefore include `--message-format=json` or a similar - /// option. - /// - /// If there are multiple linked projects/workspaces, this command is invoked for - /// each of them, with the working directory being the workspace root - /// (i.e., the folder containing the `Cargo.toml`). This can be overwritten - /// by changing `#rust-analyzer.cargo.buildScripts.invocationStrategy#`. - /// - /// By default, a cargo invocation will be constructed for the configured - /// targets and features, with the following base command line: - /// - /// ```bash - /// cargo check --quiet --workspace --message-format=json --all-targets --keep-going - /// ``` - /// . - cargo_buildScripts_overrideCommand: Option> = None, - /// Rerun proc-macros building/build-scripts running when proc-macro - /// or build-script sources change and are saved. - cargo_buildScripts_rebuildOnSave: bool = true, - /// Use `RUSTC_WRAPPER=rust-analyzer` when running build scripts to - /// avoid checking unnecessary things. - cargo_buildScripts_useRustcWrapper: bool = true, - /// List of cfg options to enable with the given values. - cargo_cfgs: FxHashMap> = { - let mut m = FxHashMap::default(); - m.insert("debug_assertions".to_owned(), None); - m.insert("miri".to_owned(), None); - m - }, - /// Extra arguments that are passed to every cargo invocation. - cargo_extraArgs: Vec = vec![], - /// Extra environment variables that will be set when running cargo, rustc - /// or other commands within the workspace. Useful for setting RUSTFLAGS. - cargo_extraEnv: FxHashMap = FxHashMap::default(), - /// List of features to activate. - /// - /// Set this to `"all"` to pass `--all-features` to cargo. - cargo_features: CargoFeaturesDef = CargoFeaturesDef::Selected(vec![]), - /// Whether to pass `--no-default-features` to cargo. - cargo_noDefaultFeatures: bool = false, - /// Relative path to the sysroot, or "discover" to try to automatically find it via - /// "rustc --print sysroot". - /// - /// Unsetting this disables sysroot loading. - /// - /// This option does not take effect until rust-analyzer is restarted. - cargo_sysroot: Option = Some("discover".to_owned()), - /// Relative path to the sysroot library sources. If left unset, this will default to - /// `{cargo.sysroot}/lib/rustlib/src/rust/library`. - /// - /// This option does not take effect until rust-analyzer is restarted. - cargo_sysrootSrc: Option = None, - /// Compilation target override (target triple). - // FIXME(@poliorcetics): move to multiple targets here too, but this will need more work - // than `checkOnSave_target` - cargo_target: Option = None, - /// Optional path to a rust-analyzer specific target directory. - /// This prevents rust-analyzer's `cargo check` and initial build-script and proc-macro - /// building from locking the `Cargo.lock` at the expense of duplicating build artifacts. - /// - /// Set to `true` to use a subdirectory of the existing target directory or - /// set to a path relative to the workspace to use that path. - cargo_targetDir | rust_analyzerTargetDir: Option = None, - /// Run the check command for diagnostics on save. checkOnSave | checkOnSave_enable: bool = true, @@ -430,6 +349,88 @@ config_data! { config_data! { workspace: struct WorkspaceDefaultConfigData <- WorkspaceConfigInput -> { + +/// Pass `--all-targets` to cargo invocation. + cargo_allTargets: bool = true, + /// Automatically refresh project info via `cargo metadata` on + /// `Cargo.toml` or `.cargo/config.toml` changes. + pub(crate) cargo_autoreload: bool = true, + /// Run build scripts (`build.rs`) for more precise code analysis. + cargo_buildScripts_enable: bool = true, + /// Specifies the invocation strategy to use when running the build scripts command. + /// If `per_workspace` is set, the command will be executed for each Rust workspace with the + /// workspace as the working directory. + /// If `once` is set, the command will be executed once with the opened project as the + /// working directory. + /// This config only has an effect when `#rust-analyzer.cargo.buildScripts.overrideCommand#` + /// is set. + cargo_buildScripts_invocationStrategy: InvocationStrategy = InvocationStrategy::PerWorkspace, + /// Override the command rust-analyzer uses to run build scripts and + /// build procedural macros. The command is required to output json + /// and should therefore include `--message-format=json` or a similar + /// option. + /// + /// If there are multiple linked projects/workspaces, this command is invoked for + /// each of them, with the working directory being the workspace root + /// (i.e., the folder containing the `Cargo.toml`). This can be overwritten + /// by changing `#rust-analyzer.cargo.buildScripts.invocationStrategy#`. + /// + /// By default, a cargo invocation will be constructed for the configured + /// targets and features, with the following base command line: + /// + /// ```bash + /// cargo check --quiet --workspace --message-format=json --all-targets --keep-going + /// ``` + /// . + cargo_buildScripts_overrideCommand: Option> = None, + /// Rerun proc-macros building/build-scripts running when proc-macro + /// or build-script sources change and are saved. + cargo_buildScripts_rebuildOnSave: bool = true, + /// Use `RUSTC_WRAPPER=rust-analyzer` when running build scripts to + /// avoid checking unnecessary things. + cargo_buildScripts_useRustcWrapper: bool = true, + /// List of cfg options to enable with the given values. + cargo_cfgs: FxHashMap> = { + let mut m = FxHashMap::default(); + m.insert("debug_assertions".to_owned(), None); + m.insert("miri".to_owned(), None); + m + }, + /// Extra arguments that are passed to every cargo invocation. + cargo_extraArgs: Vec = vec![], + /// Extra environment variables that will be set when running cargo, rustc + /// or other commands within the workspace. Useful for setting RUSTFLAGS. + cargo_extraEnv: FxHashMap = FxHashMap::default(), + /// List of features to activate. + /// + /// Set this to `"all"` to pass `--all-features` to cargo. + cargo_features: CargoFeaturesDef = CargoFeaturesDef::Selected(vec![]), + /// Whether to pass `--no-default-features` to cargo. + cargo_noDefaultFeatures: bool = false, + /// Relative path to the sysroot, or "discover" to try to automatically find it via + /// "rustc --print sysroot". + /// + /// Unsetting this disables sysroot loading. + /// + /// This option does not take effect until rust-analyzer is restarted. + cargo_sysroot: Option = Some("discover".to_owned()), + /// Relative path to the sysroot library sources. If left unset, this will default to + /// `{cargo.sysroot}/lib/rustlib/src/rust/library`. + /// + /// This option does not take effect until rust-analyzer is restarted. + cargo_sysrootSrc: Option = None, + /// Compilation target override (target triple). + // FIXME(@poliorcetics): move to multiple targets here too, but this will need more work + // than `checkOnSave_target` + cargo_target: Option = None, + /// Optional path to a rust-analyzer specific target directory. + /// This prevents rust-analyzer's `cargo check` and initial build-script and proc-macro + /// building from locking the `Cargo.lock` at the expense of duplicating build artifacts. + /// + /// Set to `true` to use a subdirectory of the existing target directory or + /// set to a path relative to the workspace to use that path. + cargo_targetDir | rust_analyzerTargetDir: Option = None, + /// Additional arguments to `rustfmt`. rustfmt_extraArgs: Vec = vec![], /// Advanced option, fully override the command rust-analyzer uses for @@ -1728,22 +1729,22 @@ impl Config { } } - pub fn extra_args(&self) -> &Vec { - self.cargo_extraArgs() + pub fn extra_args(&self, source_root: Option) -> &Vec { + self.cargo_extraArgs(source_root) } - pub fn extra_env(&self) -> &FxHashMap { - self.cargo_extraEnv() + pub fn extra_env(&self, source_root: Option) -> &FxHashMap { + self.cargo_extraEnv(source_root) } - pub fn check_extra_args(&self) -> Vec { - let mut extra_args = self.extra_args().clone(); + pub fn check_extra_args(&self, source_root: Option) -> Vec { + let mut extra_args = self.extra_args(source_root).clone(); extra_args.extend_from_slice(self.check_extraArgs()); extra_args } - pub fn check_extra_env(&self) -> FxHashMap { - let mut extra_env = self.cargo_extraEnv().clone(); + pub fn check_extra_env(&self, source_root: Option) -> FxHashMap { + let mut extra_env = self.cargo_extraEnv(source_root).clone(); extra_env.extend(self.check_extraEnv().clone()); extra_env } @@ -1787,15 +1788,15 @@ impl Config { } } - pub fn cargo_autoreload_config(&self) -> bool { - self.cargo_autoreload().to_owned() + pub fn cargo_autoreload_config(&self, source_root: Option) -> bool { + self.cargo_autoreload(source_root).to_owned() } - pub fn run_build_scripts(&self) -> bool { - self.cargo_buildScripts_enable().to_owned() || self.procMacro_enable().to_owned() + pub fn run_build_scripts(&self, source_root: Option) -> bool { + self.cargo_buildScripts_enable(source_root).to_owned() || self.procMacro_enable().to_owned() } - pub fn cargo(&self) -> CargoConfig { + pub fn cargo(&self, source_root: Option) -> CargoConfig { let rustc_source = self.rustc_source().as_ref().map(|rustc_src| { if rustc_src == "discover" { RustLibSource::Discover @@ -1803,7 +1804,7 @@ impl Config { RustLibSource::Path(self.root_path.join(rustc_src)) } }); - let sysroot = self.cargo_sysroot().as_ref().map(|sysroot| { + let sysroot = self.cargo_sysroot(source_root).as_ref().map(|sysroot| { if sysroot == "discover" { RustLibSource::Discover } else { @@ -1811,24 +1812,24 @@ impl Config { } }); let sysroot_src = - self.cargo_sysrootSrc().as_ref().map(|sysroot| self.root_path.join(sysroot)); + self.cargo_sysrootSrc(source_root).as_ref().map(|sysroot| self.root_path.join(sysroot)); CargoConfig { - all_targets: *self.cargo_allTargets(), - features: match &self.cargo_features() { + all_targets: *self.cargo_allTargets(source_root), + features: match &self.cargo_features(source_root) { CargoFeaturesDef::All => CargoFeatures::All, CargoFeaturesDef::Selected(features) => CargoFeatures::Selected { features: features.clone(), - no_default_features: self.cargo_noDefaultFeatures().to_owned(), + no_default_features: self.cargo_noDefaultFeatures(source_root).to_owned(), }, }, - target: self.cargo_target().clone(), + target: self.cargo_target(source_root).clone(), sysroot, sysroot_src, rustc_source, cfg_overrides: project_model::CfgOverrides { global: CfgDiff::new( - self.cargo_cfgs() + self.cargo_cfgs(source_root) .iter() .map(|(key, val)| match val { Some(val) => CfgAtom::KeyValue { @@ -1843,15 +1844,15 @@ impl Config { .unwrap(), selective: Default::default(), }, - wrap_rustc_in_build_scripts: *self.cargo_buildScripts_useRustcWrapper(), - invocation_strategy: match self.cargo_buildScripts_invocationStrategy() { + wrap_rustc_in_build_scripts: *self.cargo_buildScripts_useRustcWrapper(source_root), + invocation_strategy: match self.cargo_buildScripts_invocationStrategy(source_root) { InvocationStrategy::Once => project_model::InvocationStrategy::Once, InvocationStrategy::PerWorkspace => project_model::InvocationStrategy::PerWorkspace, }, - run_build_script_command: self.cargo_buildScripts_overrideCommand().clone(), - extra_args: self.cargo_extraArgs().clone(), - extra_env: self.cargo_extraEnv().clone(), - target_dir: self.target_dir_from_config(), + run_build_script_command: self.cargo_buildScripts_overrideCommand(source_root).clone(), + extra_args: self.cargo_extraArgs(source_root).clone(), + extra_env: self.cargo_extraEnv(source_root).clone(), + target_dir: self.target_dir_from_config(source_root), } } @@ -1873,24 +1874,24 @@ impl Config { *self.check_workspace() } - pub(crate) fn cargo_test_options(&self) -> CargoOptions { + pub(crate) fn cargo_test_options(&self, source_root: Option) -> CargoOptions { CargoOptions { - target_triples: self.cargo_target().clone().into_iter().collect(), + target_triples: self.cargo_target(source_root).clone().into_iter().collect(), all_targets: false, - no_default_features: *self.cargo_noDefaultFeatures(), - all_features: matches!(self.cargo_features(), CargoFeaturesDef::All), - features: match self.cargo_features().clone() { + no_default_features: *self.cargo_noDefaultFeatures(source_root), + all_features: matches!(self.cargo_features(source_root), CargoFeaturesDef::All), + features: match self.cargo_features(source_root).clone() { CargoFeaturesDef::All => vec![], CargoFeaturesDef::Selected(it) => it, }, - extra_args: self.extra_args().clone(), + extra_args: self.extra_args(source_root).clone(), extra_test_bin_args: self.runnables_extraTestBinaryArgs().clone(), - extra_env: self.extra_env().clone(), - target_dir: self.target_dir_from_config(), + extra_env: self.extra_env(source_root).clone(), + target_dir: self.target_dir_from_config(source_root), } } - pub(crate) fn flycheck(&self) -> FlycheckConfig { + pub(crate) fn flycheck(&self, source_root: Option) -> FlycheckConfig { match &self.check_overrideCommand() { Some(args) if !args.is_empty() => { let mut args = args.clone(); @@ -1898,7 +1899,7 @@ impl Config { FlycheckConfig::CustomCommand { command, args, - extra_env: self.check_extra_env(), + extra_env: self.check_extra_env(source_root), invocation_strategy: match self.check_invocationStrategy() { InvocationStrategy::Once => crate::flycheck::InvocationStrategy::Once, InvocationStrategy::PerWorkspace => { @@ -1917,35 +1918,39 @@ impl Config { [] => None, targets => Some(targets.into()), }) - .unwrap_or_else(|| self.cargo_target().clone().into_iter().collect()), - all_targets: self.check_allTargets().unwrap_or(*self.cargo_allTargets()), + .unwrap_or_else(|| { + self.cargo_target(source_root).clone().into_iter().collect() + }), + all_targets: self + .check_allTargets() + .unwrap_or(*self.cargo_allTargets(source_root)), no_default_features: self .check_noDefaultFeatures() - .unwrap_or(*self.cargo_noDefaultFeatures()), + .unwrap_or(*self.cargo_noDefaultFeatures(source_root)), all_features: matches!( - self.check_features().as_ref().unwrap_or(self.cargo_features()), + self.check_features().as_ref().unwrap_or(self.cargo_features(source_root)), CargoFeaturesDef::All ), features: match self .check_features() .clone() - .unwrap_or_else(|| self.cargo_features().clone()) + .unwrap_or_else(|| self.cargo_features(source_root).clone()) { CargoFeaturesDef::All => vec![], CargoFeaturesDef::Selected(it) => it, }, - extra_args: self.check_extra_args(), + extra_args: self.check_extra_args(source_root), extra_test_bin_args: self.runnables_extraTestBinaryArgs().clone(), - extra_env: self.check_extra_env(), - target_dir: self.target_dir_from_config(), + extra_env: self.check_extra_env(source_root), + target_dir: self.target_dir_from_config(source_root), }, ansi_color_output: self.color_diagnostic_output(), }, } } - fn target_dir_from_config(&self) -> Option { - self.cargo_targetDir().as_ref().and_then(|target_dir| match target_dir { + fn target_dir_from_config(&self, source_root: Option) -> Option { + self.cargo_targetDir(source_root).as_ref().and_then(|target_dir| match target_dir { TargetDirectory::UseSubdirectory(true) => { Some(Utf8PathBuf::from("target/rust-analyzer")) } @@ -1959,8 +1964,8 @@ impl Config { *self.checkOnSave() } - pub fn script_rebuild_on_save(&self) -> bool { - *self.cargo_buildScripts_rebuildOnSave() + pub fn script_rebuild_on_save(&self, source_root: Option) -> bool { + *self.cargo_buildScripts_rebuildOnSave(source_root) } pub fn runnables(&self) -> RunnablesConfig { @@ -3522,9 +3527,9 @@ mod tests { })); (config, _, _) = config.apply_change(change); - assert_eq!(config.cargo_targetDir(), &None); + assert_eq!(config.cargo_targetDir(None), &None); assert!( - matches!(config.flycheck(), FlycheckConfig::CargoCommand { options, .. } if options.target_dir.is_none()) + matches!(config.flycheck(None), FlycheckConfig::CargoCommand { options, .. } if options.target_dir.is_none()) ); } @@ -3540,9 +3545,9 @@ mod tests { (config, _, _) = config.apply_change(change); - assert_eq!(config.cargo_targetDir(), &Some(TargetDirectory::UseSubdirectory(true))); + assert_eq!(config.cargo_targetDir(None), &Some(TargetDirectory::UseSubdirectory(true))); assert!( - matches!(config.flycheck(), FlycheckConfig::CargoCommand { options, .. } if options.target_dir == Some(Utf8PathBuf::from("target/rust-analyzer"))) + matches!(config.flycheck(None), FlycheckConfig::CargoCommand { options, .. } if options.target_dir == Some(Utf8PathBuf::from("target/rust-analyzer"))) ); } @@ -3559,11 +3564,11 @@ mod tests { (config, _, _) = config.apply_change(change); assert_eq!( - config.cargo_targetDir(), + config.cargo_targetDir(None), &Some(TargetDirectory::Directory(Utf8PathBuf::from("other_folder"))) ); assert!( - matches!(config.flycheck(), FlycheckConfig::CargoCommand { options, .. } if options.target_dir == Some(Utf8PathBuf::from("other_folder"))) + matches!(config.flycheck(None), FlycheckConfig::CargoCommand { options, .. } if options.target_dir == Some(Utf8PathBuf::from("other_folder"))) ); } diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/global_state.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/global_state.rs index 9d0082c370c7e..35e1da80bf673 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/global_state.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/global_state.rs @@ -631,6 +631,10 @@ impl GlobalStateSnapshot { file_id_to_url(&self.vfs_read(), id) } + pub(crate) fn vfs_path_to_file_id(&self, vfs_path: &VfsPath) -> anyhow::Result { + vfs_path_to_file_id(&self.vfs_read(), vfs_path) + } + pub(crate) fn file_line_index(&self, file_id: FileId) -> Cancellable { let endings = self.vfs.read().1[&file_id]; let index = self.analysis.file_line_index(file_id)?; @@ -725,3 +729,9 @@ pub(crate) fn url_to_file_id(vfs: &vfs::Vfs, url: &Url) -> anyhow::Result anyhow::Result { + let res = + vfs.file_id(vfs_path).ok_or_else(|| anyhow::format_err!("file not found: {vfs_path}"))?; + Ok(res) +} diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/notification.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/notification.rs index 38b88ff2d0403..1cbdb5086792b 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/notification.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/notification.rs @@ -145,14 +145,21 @@ pub(crate) fn handle_did_save_text_document( state: &mut GlobalState, params: DidSaveTextDocumentParams, ) -> anyhow::Result<()> { - if state.config.script_rebuild_on_save() && state.build_deps_changed { - state.build_deps_changed = false; - state - .fetch_build_data_queue - .request_op("build_deps_changed - save notification".to_owned(), ()); - } + let mut deps_change_processed = false; if let Ok(vfs_path) = from_proto::vfs_path(¶ms.text_document.uri) { + let snap = state.snapshot(); + let file_id = snap.vfs_path_to_file_id(&vfs_path)?; + let sr = snap.analysis.source_root_id(file_id)?; + deps_change_processed = true; + + if state.config.script_rebuild_on_save(Some(sr)) && state.build_deps_changed { + state.build_deps_changed = false; + state + .fetch_build_data_queue + .request_op("build_deps_changed - save notification".to_owned(), ()); + } + // Re-fetch workspaces if a workspace related file has changed if let Some(path) = vfs_path.as_path() { let additional_files = &state @@ -191,6 +198,17 @@ pub(crate) fn handle_did_save_text_document( flycheck.restart_workspace(None); } } + + if !deps_change_processed + && state.config.script_rebuild_on_save(None) + && state.build_deps_changed + { + state.build_deps_changed = false; + state + .fetch_build_data_queue + .request_op("build_deps_changed - save notification".to_owned(), ()); + } + Ok(()) } diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/request.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/request.rs index 1ad5ff0c8cdc1..d220809be888c 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/request.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/request.rs @@ -256,7 +256,7 @@ pub(crate) fn handle_run_test( let handle = CargoTestHandle::new( test_path, - state.config.cargo_test_options(), + state.config.cargo_test_options(None), cargo.workspace_root(), test_target, state.test_run_sender.clone(), @@ -2119,7 +2119,7 @@ fn run_rustfmt( RustfmtConfig::Rustfmt { extra_args, enable_range_formatting } => { // FIXME: Set RUSTUP_TOOLCHAIN let mut cmd = process::Command::new(toolchain::Tool::Rustfmt.path()); - cmd.envs(snap.config.extra_env()); + cmd.envs(snap.config.extra_env(source_root_id)); cmd.args(extra_args); if let Some(edition) = edition { @@ -2177,7 +2177,7 @@ fn run_rustfmt( _ => process::Command::new(cmd), }; - cmd.envs(snap.config.extra_env()); + cmd.envs(snap.config.extra_env(source_root_id)); cmd.args(args); cmd } diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/main_loop.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/main_loop.rs index 1d4ee71e5c1a0..372f060234d7f 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/main_loop.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/main_loop.rs @@ -455,7 +455,7 @@ impl GlobalState { } } - if self.config.cargo_autoreload_config() + if self.config.cargo_autoreload_config(None) || self.config.discover_workspace_config().is_some() { if let Some((cause, FetchWorkspaceRequest { path, force_crate_graph_reload })) = @@ -973,9 +973,9 @@ impl GlobalState { // When we're running multiple flychecks, we have to include a disambiguator in // the title, or the editor complains. Note that this is a user-facing string. let title = if self.flycheck.len() == 1 { - format!("{}", self.config.flycheck()) + format!("{}", self.config.flycheck(None)) } else { - format!("{} (#{})", self.config.flycheck(), id + 1) + format!("{} (#{})", self.config.flycheck(None), id + 1) }; self.report_progress( &title, diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/reload.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/reload.rs index 68366136eda60..7087d7fbd5757 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/reload.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/reload.rs @@ -100,7 +100,7 @@ impl GlobalState { { let req = FetchWorkspaceRequest { path: None, force_crate_graph_reload: false }; self.fetch_workspaces_queue.request_op("discovered projects changed".to_owned(), req) - } else if self.config.flycheck() != old_config.flycheck() { + } else if self.config.flycheck(None) != old_config.flycheck(None) { self.reload_flycheck(); } @@ -122,7 +122,7 @@ impl GlobalState { }; let mut message = String::new(); - if !self.config.cargo_autoreload() + if !self.config.cargo_autoreload(None) && self.is_quiescent() && self.fetch_workspaces_queue.op_requested() && self.config.discover_workspace_config().is_none() @@ -264,7 +264,7 @@ impl GlobalState { .map(ManifestPath::try_from) .filter_map(Result::ok) .collect(); - let cargo_config = self.config.cargo(); + let cargo_config = self.config.cargo(None); let discover_command = self.config.discover_workspace_config().cloned(); let is_quiescent = !(self.discover_workspace_queue.op_in_progress() || self.vfs_progress_config_version < self.vfs_config_version @@ -357,7 +357,7 @@ impl GlobalState { pub(crate) fn fetch_build_data(&mut self, cause: Cause) { info!(%cause, "will fetch build data"); let workspaces = Arc::clone(&self.workspaces); - let config = self.config.cargo(); + let config = self.config.cargo(None); let root_path = self.config.root_path().clone(); self.task_pool.handle.spawn_with_sender(ThreadIntent::Worker, move |sender| { @@ -507,7 +507,7 @@ impl GlobalState { // FIXME: can we abort the build scripts here if they are already running? self.workspaces = Arc::new(workspaces); - if self.config.run_build_scripts() { + if self.config.run_build_scripts(None) { self.build_deps_changed = false; self.fetch_build_data_queue.request_op("workspace updated".to_owned(), ()); } @@ -627,7 +627,7 @@ impl GlobalState { .. } => cargo_config_extra_env .iter() - .chain(self.config.extra_env()) + .chain(self.config.extra_env(None)) .map(|(a, b)| (a.clone(), b.clone())) .chain( ws.sysroot @@ -702,7 +702,7 @@ impl GlobalState { vfs.file_id(&vfs_path) }; - ws_to_crate_graph(&self.workspaces, self.config.extra_env(), load) + ws_to_crate_graph(&self.workspaces, self.config.extra_env(None), load) }; let mut change = ChangeWithProcMacros::new(); if self.config.expand_proc_macros() { @@ -791,7 +791,7 @@ impl GlobalState { fn reload_flycheck(&mut self) { let _p = tracing::info_span!("GlobalState::reload_flycheck").entered(); - let config = self.config.flycheck(); + let config = self.config.flycheck(None); let sender = self.flycheck_sender.clone(); let invocation_strategy = match config { FlycheckConfig::CargoCommand { .. } => { diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/target_spec.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/target_spec.rs index 954e13cbf2727..87e964e5a89c2 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/target_spec.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/target_spec.rs @@ -168,7 +168,7 @@ impl CargoTargetSpec { (Default::default(), Default::default()) }; - let cargo_config = snap.config.cargo(); + let cargo_config = snap.config.cargo(None); match &cargo_config.features { CargoFeatures::All => { From 15a1505551f98b54828a1f755190d3ff1ec72118 Mon Sep 17 00:00:00 2001 From: Ali Bektas Date: Thu, 22 Aug 2024 19:07:43 +0200 Subject: [PATCH 0223/2194] Make checkOnSave workspace --- .../rust-analyzer/crates/rust-analyzer/src/config.rs | 11 ++++++----- .../crates/rust-analyzer/src/handlers/notification.rs | 4 ++-- .../crates/rust-analyzer/src/main_loop.rs | 2 +- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs index 9a8075043ed99..211e91f7f0284 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs @@ -76,8 +76,6 @@ config_data! { /// How many worker threads to handle priming caches. The default `0` means to pick automatically. cachePriming_numThreads: NumThreads = NumThreads::Physical, - /// Run the check command for diagnostics on save. - checkOnSave | checkOnSave_enable: bool = true, /// Check all targets and tests (`--all-targets`). Defaults to /// `#rust-analyzer.cargo.allTargets#`. @@ -350,7 +348,7 @@ config_data! { workspace: struct WorkspaceDefaultConfigData <- WorkspaceConfigInput -> { -/// Pass `--all-targets` to cargo invocation. + /// Pass `--all-targets` to cargo invocation. cargo_allTargets: bool = true, /// Automatically refresh project info via `cargo metadata` on /// `Cargo.toml` or `.cargo/config.toml` changes. @@ -431,6 +429,9 @@ config_data! { /// set to a path relative to the workspace to use that path. cargo_targetDir | rust_analyzerTargetDir: Option = None, + /// Run the check command for diagnostics on save. + checkOnSave | checkOnSave_enable: bool = true, + /// Additional arguments to `rustfmt`. rustfmt_extraArgs: Vec = vec![], /// Advanced option, fully override the command rust-analyzer uses for @@ -1960,8 +1961,8 @@ impl Config { }) } - pub fn check_on_save(&self) -> bool { - *self.checkOnSave() + pub fn check_on_save(&self, source_root: Option) -> bool { + *self.checkOnSave(source_root) } pub fn script_rebuild_on_save(&self, source_root: Option) -> bool { diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/notification.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/notification.rs index 1cbdb5086792b..336b7ea05a62d 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/notification.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/notification.rs @@ -189,10 +189,10 @@ pub(crate) fn handle_did_save_text_document( } } - if !state.config.check_on_save() || run_flycheck(state, vfs_path) { + if !state.config.check_on_save(Some(sr)) || run_flycheck(state, vfs_path) { return Ok(()); } - } else if state.config.check_on_save() { + } else if state.config.check_on_save(None) { // No specific flycheck was triggered, so let's trigger all of them. for flycheck in state.flycheck.iter() { flycheck.restart_workspace(None); diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/main_loop.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/main_loop.rs index 372f060234d7f..a90b988907976 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/main_loop.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/main_loop.rs @@ -404,7 +404,7 @@ impl GlobalState { if self.is_quiescent() { let became_quiescent = !was_quiescent; if became_quiescent { - if self.config.check_on_save() { + if self.config.check_on_save(None) { // Project has loaded properly, kick off initial flycheck self.flycheck.iter().for_each(|flycheck| flycheck.restart_workspace(None)); } From 55078f0b8e2d277c84b26ddc8a0641ac777a9589 Mon Sep 17 00:00:00 2001 From: Ali Bektas Date: Thu, 22 Aug 2024 20:44:27 +0200 Subject: [PATCH 0224/2194] Make check workspace --- .../crates/rust-analyzer/src/config.rs | 165 +++++++++--------- .../src/handlers/notification.rs | 7 +- .../crates/rust-analyzer/src/main_loop.rs | 2 +- 3 files changed, 89 insertions(+), 85 deletions(-) diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs index 211e91f7f0284..da3dda7e29313 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs @@ -77,72 +77,6 @@ config_data! { cachePriming_numThreads: NumThreads = NumThreads::Physical, - /// Check all targets and tests (`--all-targets`). Defaults to - /// `#rust-analyzer.cargo.allTargets#`. - check_allTargets | checkOnSave_allTargets: Option = None, - /// Cargo command to use for `cargo check`. - check_command | checkOnSave_command: String = "check".to_owned(), - /// Extra arguments for `cargo check`. - check_extraArgs | checkOnSave_extraArgs: Vec = vec![], - /// Extra environment variables that will be set when running `cargo check`. - /// Extends `#rust-analyzer.cargo.extraEnv#`. - check_extraEnv | checkOnSave_extraEnv: FxHashMap = FxHashMap::default(), - /// List of features to activate. Defaults to - /// `#rust-analyzer.cargo.features#`. - /// - /// Set to `"all"` to pass `--all-features` to Cargo. - check_features | checkOnSave_features: Option = None, - /// List of `cargo check` (or other command specified in `check.command`) diagnostics to ignore. - /// - /// For example for `cargo check`: `dead_code`, `unused_imports`, `unused_variables`,... - check_ignore: FxHashSet = FxHashSet::default(), - /// Specifies the invocation strategy to use when running the check command. - /// If `per_workspace` is set, the command will be executed for each workspace. - /// If `once` is set, the command will be executed once. - /// This config only has an effect when `#rust-analyzer.check.overrideCommand#` - /// is set. - check_invocationStrategy | checkOnSave_invocationStrategy: InvocationStrategy = InvocationStrategy::PerWorkspace, - /// Whether to pass `--no-default-features` to Cargo. Defaults to - /// `#rust-analyzer.cargo.noDefaultFeatures#`. - check_noDefaultFeatures | checkOnSave_noDefaultFeatures: Option = None, - /// Override the command rust-analyzer uses instead of `cargo check` for - /// diagnostics on save. The command is required to output json and - /// should therefore include `--message-format=json` or a similar option - /// (if your client supports the `colorDiagnosticOutput` experimental - /// capability, you can use `--message-format=json-diagnostic-rendered-ansi`). - /// - /// If you're changing this because you're using some tool wrapping - /// Cargo, you might also want to change - /// `#rust-analyzer.cargo.buildScripts.overrideCommand#`. - /// - /// If there are multiple linked projects/workspaces, this command is invoked for - /// each of them, with the working directory being the workspace root - /// (i.e., the folder containing the `Cargo.toml`). This can be overwritten - /// by changing `#rust-analyzer.check.invocationStrategy#`. - /// - /// If `$saved_file` is part of the command, rust-analyzer will pass - /// the absolute path of the saved file to the provided command. This is - /// intended to be used with non-Cargo build systems. - /// Note that `$saved_file` is experimental and may be removed in the future. - /// - /// An example command would be: - /// - /// ```bash - /// cargo check --workspace --message-format=json --all-targets - /// ``` - /// . - check_overrideCommand | checkOnSave_overrideCommand: Option> = None, - /// Check for specific targets. Defaults to `#rust-analyzer.cargo.target#` if empty. - /// - /// Can be a single target, e.g. `"x86_64-unknown-linux-gnu"` or a list of targets, e.g. - /// `["aarch64-apple-darwin", "x86_64-apple-darwin"]`. - /// - /// Aliased as `"checkOnSave.targets"`. - check_targets | checkOnSave_targets | checkOnSave_target: Option = None, - /// Whether `--workspace` should be passed to `cargo check`. - /// If false, `-p ` will be passed instead. - check_workspace: bool = true, - /// List of rust-analyzer diagnostics to disable. diagnostics_disabled: FxHashSet = FxHashSet::default(), /// Whether to show native rust-analyzer diagnostics. @@ -432,6 +366,73 @@ config_data! { /// Run the check command for diagnostics on save. checkOnSave | checkOnSave_enable: bool = true, + +/// Check all targets and tests (`--all-targets`). Defaults to + /// `#rust-analyzer.cargo.allTargets#`. + check_allTargets | checkOnSave_allTargets: Option = None, + /// Cargo command to use for `cargo check`. + check_command | checkOnSave_command: String = "check".to_owned(), + /// Extra arguments for `cargo check`. + check_extraArgs | checkOnSave_extraArgs: Vec = vec![], + /// Extra environment variables that will be set when running `cargo check`. + /// Extends `#rust-analyzer.cargo.extraEnv#`. + check_extraEnv | checkOnSave_extraEnv: FxHashMap = FxHashMap::default(), + /// List of features to activate. Defaults to + /// `#rust-analyzer.cargo.features#`. + /// + /// Set to `"all"` to pass `--all-features` to Cargo. + check_features | checkOnSave_features: Option = None, + /// List of `cargo check` (or other command specified in `check.command`) diagnostics to ignore. + /// + /// For example for `cargo check`: `dead_code`, `unused_imports`, `unused_variables`,... + check_ignore: FxHashSet = FxHashSet::default(), + /// Specifies the invocation strategy to use when running the check command. + /// If `per_workspace` is set, the command will be executed for each workspace. + /// If `once` is set, the command will be executed once. + /// This config only has an effect when `#rust-analyzer.check.overrideCommand#` + /// is set. + check_invocationStrategy | checkOnSave_invocationStrategy: InvocationStrategy = InvocationStrategy::PerWorkspace, + /// Whether to pass `--no-default-features` to Cargo. Defaults to + /// `#rust-analyzer.cargo.noDefaultFeatures#`. + check_noDefaultFeatures | checkOnSave_noDefaultFeatures: Option = None, + /// Override the command rust-analyzer uses instead of `cargo check` for + /// diagnostics on save. The command is required to output json and + /// should therefore include `--message-format=json` or a similar option + /// (if your client supports the `colorDiagnosticOutput` experimental + /// capability, you can use `--message-format=json-diagnostic-rendered-ansi`). + /// + /// If you're changing this because you're using some tool wrapping + /// Cargo, you might also want to change + /// `#rust-analyzer.cargo.buildScripts.overrideCommand#`. + /// + /// If there are multiple linked projects/workspaces, this command is invoked for + /// each of them, with the working directory being the workspace root + /// (i.e., the folder containing the `Cargo.toml`). This can be overwritten + /// by changing `#rust-analyzer.check.invocationStrategy#`. + /// + /// If `$saved_file` is part of the command, rust-analyzer will pass + /// the absolute path of the saved file to the provided command. This is + /// intended to be used with non-Cargo build systems. + /// Note that `$saved_file` is experimental and may be removed in the future. + /// + /// An example command would be: + /// + /// ```bash + /// cargo check --workspace --message-format=json --all-targets + /// ``` + /// . + check_overrideCommand | checkOnSave_overrideCommand: Option> = None, + /// Check for specific targets. Defaults to `#rust-analyzer.cargo.target#` if empty. + /// + /// Can be a single target, e.g. `"x86_64-unknown-linux-gnu"` or a list of targets, e.g. + /// `["aarch64-apple-darwin", "x86_64-apple-darwin"]`. + /// + /// Aliased as `"checkOnSave.targets"`. + check_targets | checkOnSave_targets | checkOnSave_target: Option = None, + /// Whether `--workspace` should be passed to `cargo check`. + /// If false, `-p ` will be passed instead. + check_workspace: bool = true, + /// Additional arguments to `rustfmt`. rustfmt_extraArgs: Vec = vec![], /// Advanced option, fully override the command rust-analyzer uses for @@ -1018,7 +1019,7 @@ impl Config { config.source_root_parent_map = source_root_map; } - if config.check_command().is_empty() { + if config.check_command(None).is_empty() { config.validation_errors.0.push(Arc::new(ConfigErrorInner::Json { config_key: "/check/command".to_owned(), error: serde_json::Error::custom("expected a non-empty string"), @@ -1721,12 +1722,12 @@ impl Config { self.diagnostics_enable().to_owned() } - pub fn diagnostics_map(&self) -> DiagnosticsMapConfig { + pub fn diagnostics_map(&self, source_root: Option) -> DiagnosticsMapConfig { DiagnosticsMapConfig { remap_prefix: self.diagnostics_remapPrefix().clone(), warnings_as_info: self.diagnostics_warningsAsInfo().clone(), warnings_as_hint: self.diagnostics_warningsAsHint().clone(), - check_ignore: self.check_ignore().clone(), + check_ignore: self.check_ignore(source_root).clone(), } } @@ -1740,13 +1741,13 @@ impl Config { pub fn check_extra_args(&self, source_root: Option) -> Vec { let mut extra_args = self.extra_args(source_root).clone(); - extra_args.extend_from_slice(self.check_extraArgs()); + extra_args.extend_from_slice(self.check_extraArgs(source_root)); extra_args } pub fn check_extra_env(&self, source_root: Option) -> FxHashMap { let mut extra_env = self.cargo_extraEnv(source_root).clone(); - extra_env.extend(self.check_extraEnv().clone()); + extra_env.extend(self.check_extraEnv(source_root).clone()); extra_env } @@ -1871,8 +1872,8 @@ impl Config { } } - pub fn flycheck_workspace(&self) -> bool { - *self.check_workspace() + pub fn flycheck_workspace(&self, source_root: Option) -> bool { + *self.check_workspace(source_root) } pub(crate) fn cargo_test_options(&self, source_root: Option) -> CargoOptions { @@ -1893,7 +1894,7 @@ impl Config { } pub(crate) fn flycheck(&self, source_root: Option) -> FlycheckConfig { - match &self.check_overrideCommand() { + match &self.check_overrideCommand(source_root) { Some(args) if !args.is_empty() => { let mut args = args.clone(); let command = args.remove(0); @@ -1901,7 +1902,7 @@ impl Config { command, args, extra_env: self.check_extra_env(source_root), - invocation_strategy: match self.check_invocationStrategy() { + invocation_strategy: match self.check_invocationStrategy(source_root) { InvocationStrategy::Once => crate::flycheck::InvocationStrategy::Once, InvocationStrategy::PerWorkspace => { crate::flycheck::InvocationStrategy::PerWorkspace @@ -1910,10 +1911,10 @@ impl Config { } } Some(_) | None => FlycheckConfig::CargoCommand { - command: self.check_command().clone(), + command: self.check_command(source_root).clone(), options: CargoOptions { target_triples: self - .check_targets() + .check_targets(source_root) .clone() .and_then(|targets| match &targets.0[..] { [] => None, @@ -1923,17 +1924,19 @@ impl Config { self.cargo_target(source_root).clone().into_iter().collect() }), all_targets: self - .check_allTargets() + .check_allTargets(source_root) .unwrap_or(*self.cargo_allTargets(source_root)), no_default_features: self - .check_noDefaultFeatures() + .check_noDefaultFeatures(source_root) .unwrap_or(*self.cargo_noDefaultFeatures(source_root)), all_features: matches!( - self.check_features().as_ref().unwrap_or(self.cargo_features(source_root)), + self.check_features(source_root) + .as_ref() + .unwrap_or(self.cargo_features(source_root)), CargoFeaturesDef::All ), features: match self - .check_features() + .check_features(source_root) .clone() .unwrap_or_else(|| self.cargo_features(source_root).clone()) { diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/notification.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/notification.rs index 336b7ea05a62d..dc8d40e0ee075 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/notification.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/notification.rs @@ -306,6 +306,7 @@ fn run_flycheck(state: &mut GlobalState, vfs_path: VfsPath) -> bool { let file_id = state.vfs.read().0.file_id(&vfs_path); if let Some(file_id) = file_id { let world = state.snapshot(); + let source_root_id = world.analysis.source_root_id(file_id).ok(); let mut updated = false; let task = move || -> std::result::Result<(), ide::Cancelled> { // Is the target binary? If so we let flycheck run only for the workspace that contains the crate. @@ -391,9 +392,9 @@ fn run_flycheck(state: &mut GlobalState, vfs_path: VfsPath) -> bool { for (id, package) in workspace_ids.clone() { if id == flycheck.id() { updated = true; - match package - .filter(|_| !world.config.flycheck_workspace() || target.is_some()) - { + match package.filter(|_| { + !world.config.flycheck_workspace(source_root_id) || target.is_some() + }) { Some(package) => flycheck .restart_for_package(package, target.clone().map(TupleExt::head)), None => flycheck.restart_workspace(saved_file.clone()), diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/main_loop.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/main_loop.rs index a90b988907976..e034badbcbc9a 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/main_loop.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/main_loop.rs @@ -925,7 +925,7 @@ impl GlobalState { FlycheckMessage::AddDiagnostic { id, workspace_root, diagnostic } => { let snap = self.snapshot(); let diagnostics = crate::diagnostics::to_proto::map_rust_diagnostic_to_lsp( - &self.config.diagnostics_map(), + &self.config.diagnostics_map(None), &diagnostic, &workspace_root, &snap, From 2ddb4e14807691588d21d0d1ae886f2913c3ecf3 Mon Sep 17 00:00:00 2001 From: Ali Bektas Date: Thu, 22 Aug 2024 20:48:30 +0200 Subject: [PATCH 0225/2194] Make runnables workspace --- .../crates/rust-analyzer/src/config.rs | 38 +++++++++---------- .../rust-analyzer/src/handlers/request.rs | 3 +- .../crates/rust-analyzer/src/lsp/to_proto.rs | 3 +- .../crates/rust-analyzer/src/target_spec.rs | 2 +- 4 files changed, 24 insertions(+), 22 deletions(-) diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs index da3dda7e29313..675882e55f1a8 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs @@ -124,20 +124,6 @@ config_data! { /// This config takes a map of crate names with the exported proc-macro names to ignore as values. procMacro_ignored: FxHashMap, Box<[Box]>> = FxHashMap::default(), - /// Command to be executed instead of 'cargo' for runnables. - runnables_command: Option = None, - /// Additional arguments to be passed to cargo for runnables such as - /// tests or binaries. For example, it may be `--release`. - runnables_extraArgs: Vec = vec![], - /// Additional arguments to be passed through Cargo to launched tests, benchmarks, or - /// doc-tests. - /// - /// Unless the launched target uses a - /// [custom test harness](https://doc.rust-lang.org/cargo/reference/cargo-targets.html#the-harness-field), - /// they will end up being interpreted as options to - /// [`rustc`’s built-in test harness (“libtest”)](https://doc.rust-lang.org/rustc/tests/index.html#cli-arguments). - runnables_extraTestBinaryArgs: Vec = vec!["--show-output".to_owned()], - /// Path to the Cargo.toml of the rust compiler workspace, for usage in rustc_private /// projects, or "discover" to try to automatically find it if the `rustc-dev` component /// is installed. @@ -367,7 +353,7 @@ config_data! { checkOnSave | checkOnSave_enable: bool = true, -/// Check all targets and tests (`--all-targets`). Defaults to + /// Check all targets and tests (`--all-targets`). Defaults to /// `#rust-analyzer.cargo.allTargets#`. check_allTargets | checkOnSave_allTargets: Option = None, /// Cargo command to use for `cargo check`. @@ -433,6 +419,20 @@ config_data! { /// If false, `-p ` will be passed instead. check_workspace: bool = true, + /// Command to be executed instead of 'cargo' for runnables. + runnables_command: Option = None, + /// Additional arguments to be passed to cargo for runnables such as + /// tests or binaries. For example, it may be `--release`. + runnables_extraArgs: Vec = vec![], + /// Additional arguments to be passed through Cargo to launched tests, benchmarks, or + /// doc-tests. + /// + /// Unless the launched target uses a + /// [custom test harness](https://doc.rust-lang.org/cargo/reference/cargo-targets.html#the-harness-field), + /// they will end up being interpreted as options to + /// [`rustc`’s built-in test harness (“libtest”)](https://doc.rust-lang.org/rustc/tests/index.html#cli-arguments). + runnables_extraTestBinaryArgs: Vec = vec!["--show-output".to_owned()], + /// Additional arguments to `rustfmt`. rustfmt_extraArgs: Vec = vec![], /// Advanced option, fully override the command rust-analyzer uses for @@ -1972,11 +1972,11 @@ impl Config { *self.cargo_buildScripts_rebuildOnSave(source_root) } - pub fn runnables(&self) -> RunnablesConfig { + pub fn runnables(&self, source_root: Option) -> RunnablesConfig { RunnablesConfig { - override_cargo: self.runnables_command().clone(), - cargo_extra_args: self.runnables_extraArgs().clone(), - extra_test_binary_args: self.runnables_extraTestBinaryArgs().clone(), + override_cargo: self.runnables_command(source_root).clone(), + cargo_extra_args: self.runnables_extraArgs(source_root).clone(), + extra_test_binary_args: self.runnables_extraTestBinaryArgs(source_root).clone(), } } diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/request.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/request.rs index d220809be888c..b39552a172e5c 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/request.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/request.rs @@ -852,6 +852,7 @@ pub(crate) fn handle_runnables( ) -> anyhow::Result> { let _p = tracing::info_span!("handle_runnables").entered(); let file_id = from_proto::file_id(&snap, ¶ms.text_document.uri)?; + let source_root = snap.analysis.source_root_id(file_id).ok(); let line_index = snap.file_line_index(file_id)?; let offset = params.position.and_then(|it| from_proto::offset(&line_index, it).ok()); let target_spec = TargetSpec::for_file(&snap, file_id)?; @@ -894,7 +895,7 @@ pub(crate) fn handle_runnables( } // Add `cargo check` and `cargo test` for all targets of the whole package - let config = snap.config.runnables(); + let config = snap.config.runnables(source_root); match target_spec { Some(TargetSpec::Cargo(spec)) => { let is_crate_no_std = snap.analysis.is_crate_no_std(spec.crate_id)?; diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/to_proto.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/to_proto.rs index eb6bc2a9ce9b0..f5122a722ab04 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/to_proto.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/to_proto.rs @@ -1365,8 +1365,9 @@ pub(crate) fn runnable( snap: &GlobalStateSnapshot, runnable: Runnable, ) -> Cancellable> { - let config = snap.config.runnables(); let target_spec = TargetSpec::for_file(snap, runnable.nav.file_id)?; + let source_root = snap.analysis.source_root_id(runnable.nav.file_id).ok(); + let config = snap.config.runnables(source_root); match target_spec { Some(TargetSpec::Cargo(spec)) => { diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/target_spec.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/target_spec.rs index 87e964e5a89c2..b4aa73d2780d6 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/target_spec.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/target_spec.rs @@ -113,7 +113,7 @@ impl CargoTargetSpec { kind: &RunnableKind, cfg: &Option, ) -> (Vec, Vec) { - let config = snap.config.runnables(); + let config = snap.config.runnables(None); let extra_test_binary_args = config.extra_test_binary_args; let mut cargo_args = Vec::new(); From 7360dfe3f1b79acd54d3d8522bfb917d517e5866 Mon Sep 17 00:00:00 2001 From: Ali Bektas Date: Thu, 22 Aug 2024 20:49:51 +0200 Subject: [PATCH 0226/2194] Make rustc_* workspace --- .../crates/rust-analyzer/src/config.rs | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs index 675882e55f1a8..3499cf9259518 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs @@ -124,16 +124,6 @@ config_data! { /// This config takes a map of crate names with the exported proc-macro names to ignore as values. procMacro_ignored: FxHashMap, Box<[Box]>> = FxHashMap::default(), - /// Path to the Cargo.toml of the rust compiler workspace, for usage in rustc_private - /// projects, or "discover" to try to automatically find it if the `rustc-dev` component - /// is installed. - /// - /// Any project which uses rust-analyzer with the rustcPrivate - /// crates must set `[package.metadata.rust-analyzer] rustc_private=true` to use it. - /// - /// This option does not take effect until rust-analyzer is restarted. - rustc_source: Option = None, - /// Enables automatic discovery of projects using [`DiscoverWorkspaceConfig::command`]. /// @@ -433,6 +423,16 @@ config_data! { /// [`rustc`’s built-in test harness (“libtest”)](https://doc.rust-lang.org/rustc/tests/index.html#cli-arguments). runnables_extraTestBinaryArgs: Vec = vec!["--show-output".to_owned()], + /// Path to the Cargo.toml of the rust compiler workspace, for usage in rustc_private + /// projects, or "discover" to try to automatically find it if the `rustc-dev` component + /// is installed. + /// + /// Any project which uses rust-analyzer with the rustcPrivate + /// crates must set `[package.metadata.rust-analyzer] rustc_private=true` to use it. + /// + /// This option does not take effect until rust-analyzer is restarted. + rustc_source: Option = None, + /// Additional arguments to `rustfmt`. rustfmt_extraArgs: Vec = vec![], /// Advanced option, fully override the command rust-analyzer uses for @@ -1799,7 +1799,7 @@ impl Config { } pub fn cargo(&self, source_root: Option) -> CargoConfig { - let rustc_source = self.rustc_source().as_ref().map(|rustc_src| { + let rustc_source = self.rustc_source(source_root).as_ref().map(|rustc_src| { if rustc_src == "discover" { RustLibSource::Discover } else { From 887dd4e344b71bb8a126b2855847775fbc2ee94f Mon Sep 17 00:00:00 2001 From: Ali Bektas Date: Thu, 22 Aug 2024 20:51:49 +0200 Subject: [PATCH 0227/2194] Make procMacro_* workspace --- .../crates/rust-analyzer/src/config.rs | 16 ++++++++++------ .../crates/rust-analyzer/src/reload.rs | 2 +- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs index 3499cf9259518..e459e7b7f3bf9 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs @@ -119,10 +119,6 @@ config_data! { /// Sets the LRU capacity of the specified queries. lru_query_capacities: FxHashMap, u16> = FxHashMap::default(), - /// These proc-macros will be ignored when trying to expand them. - /// - /// This config takes a map of crate names with the exported proc-macro names to ignore as values. - procMacro_ignored: FxHashMap, Box<[Box]>> = FxHashMap::default(), /// Enables automatic discovery of projects using [`DiscoverWorkspaceConfig::command`]. @@ -409,6 +405,11 @@ config_data! { /// If false, `-p ` will be passed instead. check_workspace: bool = true, + /// These proc-macros will be ignored when trying to expand them. + /// + /// This config takes a map of crate names with the exported proc-macro names to ignore as values. + procMacro_ignored: FxHashMap, Box<[Box]>> = FxHashMap::default(), + /// Command to be executed instead of 'cargo' for runnables. runnables_command: Option = None, /// Additional arguments to be passed to cargo for runnables such as @@ -1764,8 +1765,11 @@ impl Config { Some(AbsPathBuf::try_from(path).unwrap_or_else(|path| self.root_path.join(path))) } - pub fn ignored_proc_macros(&self) -> &FxHashMap, Box<[Box]>> { - self.procMacro_ignored() + pub fn ignored_proc_macros( + &self, + source_root: Option, + ) -> &FxHashMap, Box<[Box]>> { + self.procMacro_ignored(source_root) } pub fn expand_proc_macros(&self) -> bool { diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/reload.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/reload.rs index 7087d7fbd5757..5d77b7aa67ef0 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/reload.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/reload.rs @@ -382,7 +382,7 @@ impl GlobalState { pub(crate) fn fetch_proc_macros(&mut self, cause: Cause, paths: Vec) { info!(%cause, "will load proc macros"); - let ignored_proc_macros = self.config.ignored_proc_macros().clone(); + let ignored_proc_macros = self.config.ignored_proc_macros(None).clone(); let proc_macro_clients = self.proc_macro_clients.clone(); self.task_pool.handle.spawn_with_sender(ThreadIntent::Worker, move |sender| { From fcf505be37c55e46a08543cf666625640fcd9f84 Mon Sep 17 00:00:00 2001 From: Ali Bektas Date: Thu, 22 Aug 2024 20:53:40 +0200 Subject: [PATCH 0228/2194] Make workspace_symbol_search_* workspace --- .../crates/rust-analyzer/src/config.rs | 28 +++++++++---------- .../rust-analyzer/src/handlers/request.rs | 2 +- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs index e459e7b7f3bf9..925d650b5b30e 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs @@ -252,8 +252,6 @@ config_data! { config_data! { workspace: struct WorkspaceDefaultConfigData <- WorkspaceConfigInput -> { - - /// Pass `--all-targets` to cargo invocation. cargo_allTargets: bool = true, /// Automatically refresh project info via `cargo metadata` on @@ -447,6 +445,16 @@ config_data! { /// available on a nightly build. rustfmt_rangeFormatting_enable: bool = false, + + /// Workspace symbol search kind. + workspace_symbol_search_kind: WorkspaceSymbolSearchKindDef = WorkspaceSymbolSearchKindDef::OnlyTypes, + /// Limits the number of items returned from a workspace symbol search (Defaults to 128). + /// Some clients like vs-code issue new searches on result filtering and don't require all results to be returned in the initial search. + /// Other clients requires all results upfront and might require a higher limit. + workspace_symbol_search_limit: usize = 128, + /// Workspace symbol search scope. + workspace_symbol_search_scope: WorkspaceSymbolSearchScopeDef = WorkspaceSymbolSearchScopeDef::Workspace, + } } @@ -731,14 +739,6 @@ config_data! { /// Whether to insert closing angle brackets when typing an opening angle bracket of a generic argument list. typing_autoClosingAngleBrackets_enable: bool = false, - /// Workspace symbol search kind. - workspace_symbol_search_kind: WorkspaceSymbolSearchKindDef = WorkspaceSymbolSearchKindDef::OnlyTypes, - /// Limits the number of items returned from a workspace symbol search (Defaults to 128). - /// Some clients like vs-code issue new searches on result filtering and don't require all results to be returned in the initial search. - /// Other clients requires all results upfront and might require a higher limit. - workspace_symbol_search_limit: usize = 128, - /// Workspace symbol search scope. - workspace_symbol_search_scope: WorkspaceSymbolSearchScopeDef = WorkspaceSymbolSearchScopeDef::Workspace, } } @@ -2019,19 +2019,19 @@ impl Config { } } - pub fn workspace_symbol(&self) -> WorkspaceSymbolConfig { + pub fn workspace_symbol(&self, source_root: Option) -> WorkspaceSymbolConfig { WorkspaceSymbolConfig { - search_scope: match self.workspace_symbol_search_scope() { + search_scope: match self.workspace_symbol_search_scope(source_root) { WorkspaceSymbolSearchScopeDef::Workspace => WorkspaceSymbolSearchScope::Workspace, WorkspaceSymbolSearchScopeDef::WorkspaceAndDependencies => { WorkspaceSymbolSearchScope::WorkspaceAndDependencies } }, - search_kind: match self.workspace_symbol_search_kind() { + search_kind: match self.workspace_symbol_search_kind(source_root) { WorkspaceSymbolSearchKindDef::OnlyTypes => WorkspaceSymbolSearchKind::OnlyTypes, WorkspaceSymbolSearchKindDef::AllSymbols => WorkspaceSymbolSearchKind::AllSymbols, }, - search_limit: *self.workspace_symbol_search_limit(), + search_limit: *self.workspace_symbol_search_limit(source_root), } } diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/request.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/request.rs index b39552a172e5c..94487bdbb2168 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/request.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/request.rs @@ -565,7 +565,7 @@ pub(crate) fn handle_workspace_symbol( ) -> anyhow::Result> { let _p = tracing::info_span!("handle_workspace_symbol").entered(); - let config = snap.config.workspace_symbol(); + let config = snap.config.workspace_symbol(None); let (all_symbols, libs) = decide_search_scope_and_kind(¶ms, &config); let query = { From 5e6bfaefbd9e6ded2ed9b7637cc1fafdd5d7eac5 Mon Sep 17 00:00:00 2001 From: Ali Bektas Date: Thu, 22 Aug 2024 20:57:08 +0200 Subject: [PATCH 0229/2194] Make diagnostics_* local --- .../crates/rust-analyzer/src/config.rs | 63 ++++++++++--------- .../crates/rust-analyzer/src/main_loop.rs | 2 +- 2 files changed, 33 insertions(+), 32 deletions(-) diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs index 925d650b5b30e..df03e679f04b9 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs @@ -77,28 +77,6 @@ config_data! { cachePriming_numThreads: NumThreads = NumThreads::Physical, - /// List of rust-analyzer diagnostics to disable. - diagnostics_disabled: FxHashSet = FxHashSet::default(), - /// Whether to show native rust-analyzer diagnostics. - diagnostics_enable: bool = true, - /// Whether to show experimental rust-analyzer diagnostics that might - /// have more false positives than usual. - diagnostics_experimental_enable: bool = false, - /// Map of prefixes to be substituted when parsing diagnostic file paths. - /// This should be the reverse mapping of what is passed to `rustc` as `--remap-path-prefix`. - diagnostics_remapPrefix: FxHashMap = FxHashMap::default(), - /// Whether to run additional style lints. - diagnostics_styleLints_enable: bool = false, - /// List of warnings that should be displayed with hint severity. - /// - /// The warnings will be indicated by faded text or three dots in code - /// and will not show up in the `Problems Panel`. - diagnostics_warningsAsHint: Vec = vec![], - /// List of warnings that should be displayed with info severity. - /// - /// The warnings will be indicated by a blue squiggly underline in code - /// and a blue icon in the `Problems Panel`. - diagnostics_warningsAsInfo: Vec = vec![], /// These directories will be ignored by rust-analyzer. They are /// relative to the workspace root, and globs are not supported. You may @@ -231,6 +209,29 @@ config_data! { /// Term search fuel in "units of work" for assists (Defaults to 1800). assist_termSearch_fuel: usize = 1800, + /// List of rust-analyzer diagnostics to disable. + diagnostics_disabled: FxHashSet = FxHashSet::default(), + /// Whether to show native rust-analyzer diagnostics. + diagnostics_enable: bool = true, + /// Whether to show experimental rust-analyzer diagnostics that might + /// have more false positives than usual. + diagnostics_experimental_enable: bool = false, + /// Map of prefixes to be substituted when parsing diagnostic file paths. + /// This should be the reverse mapping of what is passed to `rustc` as `--remap-path-prefix`. + diagnostics_remapPrefix: FxHashMap = FxHashMap::default(), + /// Whether to run additional style lints. + diagnostics_styleLints_enable: bool = false, + /// List of warnings that should be displayed with hint severity. + /// + /// The warnings will be indicated by faded text or three dots in code + /// and will not show up in the `Problems Panel`. + diagnostics_warningsAsHint: Vec = vec![], + /// List of warnings that should be displayed with info severity. + /// + /// The warnings will be indicated by a blue squiggly underline in code + /// and a blue icon in the `Problems Panel`. + diagnostics_warningsAsInfo: Vec = vec![], + /// Whether to enforce the import granularity setting for all files. If set to false rust-analyzer will try to keep import styles consistent per file. imports_granularity_enforce: bool = false, /// How imports should be grouped into use statements. @@ -1447,11 +1448,11 @@ impl Config { pub fn diagnostics(&self, source_root: Option) -> DiagnosticsConfig { DiagnosticsConfig { - enabled: *self.diagnostics_enable(), + enabled: *self.diagnostics_enable(source_root), proc_attr_macros_enabled: self.expand_proc_attr_macros(), proc_macros_enabled: *self.procMacro_enable(), - disable_experimental: !self.diagnostics_experimental_enable(), - disabled: self.diagnostics_disabled().clone(), + disable_experimental: !self.diagnostics_experimental_enable(source_root), + disabled: self.diagnostics_disabled(source_root).clone(), expr_fill_default: match self.assist_expressionFillDefault(source_root) { ExprFillDefaultDef::Todo => ExprFillDefaultMode::Todo, ExprFillDefaultDef::Default => ExprFillDefaultMode::Default, @@ -1461,7 +1462,7 @@ impl Config { prefer_no_std: self.imports_preferNoStd(source_root).to_owned(), prefer_prelude: self.imports_preferPrelude(source_root).to_owned(), prefer_absolute: self.imports_prefixExternPrelude(source_root).to_owned(), - style_lints: self.diagnostics_styleLints_enable().to_owned(), + style_lints: self.diagnostics_styleLints_enable(source_root).to_owned(), term_search_fuel: self.assist_termSearch_fuel(source_root).to_owned() as u64, term_search_borrowck: self.assist_termSearch_borrowcheck(source_root).to_owned(), } @@ -1719,15 +1720,15 @@ impl Config { self.cachePriming_enable().to_owned() } - pub fn publish_diagnostics(&self) -> bool { - self.diagnostics_enable().to_owned() + pub fn publish_diagnostics(&self, source_root: Option) -> bool { + self.diagnostics_enable(source_root).to_owned() } pub fn diagnostics_map(&self, source_root: Option) -> DiagnosticsMapConfig { DiagnosticsMapConfig { - remap_prefix: self.diagnostics_remapPrefix().clone(), - warnings_as_info: self.diagnostics_warningsAsInfo().clone(), - warnings_as_hint: self.diagnostics_warningsAsHint().clone(), + remap_prefix: self.diagnostics_remapPrefix(source_root).clone(), + warnings_as_info: self.diagnostics_warningsAsInfo(source_root).clone(), + warnings_as_hint: self.diagnostics_warningsAsHint(source_root).clone(), check_ignore: self.check_ignore(source_root).clone(), } } diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/main_loop.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/main_loop.rs index e034badbcbc9a..3e46138aa38dd 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/main_loop.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/main_loop.rs @@ -434,7 +434,7 @@ impl GlobalState { let project_or_mem_docs_changed = became_quiescent || state_changed || memdocs_added_or_removed; - if project_or_mem_docs_changed && self.config.publish_diagnostics() { + if project_or_mem_docs_changed && self.config.publish_diagnostics(None) { self.update_diagnostics(); } if project_or_mem_docs_changed && self.config.test_explorer() { From f98c12121805d96ce5d1f58539743cd89e7b2f31 Mon Sep 17 00:00:00 2001 From: Ali Bektas Date: Thu, 22 Aug 2024 20:59:14 +0200 Subject: [PATCH 0230/2194] Make completion_* local --- .../crates/rust-analyzer/src/config.rs | 148 +++++++++--------- 1 file changed, 76 insertions(+), 72 deletions(-) diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs index df03e679f04b9..ac72193be54b3 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs @@ -209,6 +209,70 @@ config_data! { /// Term search fuel in "units of work" for assists (Defaults to 1800). assist_termSearch_fuel: usize = 1800, + + /// Toggles the additional completions that automatically add imports when completed. + /// Note that your client must specify the `additionalTextEdits` LSP client capability to truly have this feature enabled. + completion_autoimport_enable: bool = true, + /// Toggles the additional completions that automatically show method calls and field accesses + /// with `self` prefixed to them when inside a method. + completion_autoself_enable: bool = true, + /// Whether to add parenthesis and argument snippets when completing function. + completion_callable_snippets: CallableCompletionDef = CallableCompletionDef::FillArguments, + /// Whether to show full function/method signatures in completion docs. + completion_fullFunctionSignatures_enable: bool = false, + /// Maximum number of completions to return. If `None`, the limit is infinite. + completion_limit: Option = None, + /// Whether to show postfix snippets like `dbg`, `if`, `not`, etc. + completion_postfix_enable: bool = true, + /// Enables completions of private items and fields that are defined in the current workspace even if they are not visible at the current position. + completion_privateEditable_enable: bool = false, + /// Custom completion snippets. + completion_snippets_custom: FxHashMap = serde_json::from_str(r#"{ + "Arc::new": { + "postfix": "arc", + "body": "Arc::new(${receiver})", + "requires": "std::sync::Arc", + "description": "Put the expression into an `Arc`", + "scope": "expr" + }, + "Rc::new": { + "postfix": "rc", + "body": "Rc::new(${receiver})", + "requires": "std::rc::Rc", + "description": "Put the expression into an `Rc`", + "scope": "expr" + }, + "Box::pin": { + "postfix": "pinbox", + "body": "Box::pin(${receiver})", + "requires": "std::boxed::Box", + "description": "Put the expression into a pinned `Box`", + "scope": "expr" + }, + "Ok": { + "postfix": "ok", + "body": "Ok(${receiver})", + "description": "Wrap the expression in a `Result::Ok`", + "scope": "expr" + }, + "Err": { + "postfix": "err", + "body": "Err(${receiver})", + "description": "Wrap the expression in a `Result::Err`", + "scope": "expr" + }, + "Some": { + "postfix": "some", + "body": "Some(${receiver})", + "description": "Wrap the expression in an `Option::Some`", + "scope": "expr" + } + }"#).unwrap(), + /// Whether to enable term search based snippets like `Some(foo.bar().baz())`. + completion_termSearch_enable: bool = false, + /// Term search fuel in "units of work" for autocompletion (Defaults to 1000). + completion_termSearch_fuel: usize = 1000, + /// List of rust-analyzer diagnostics to disable. diagnostics_disabled: FxHashSet = FxHashSet::default(), /// Whether to show native rust-analyzer diagnostics. @@ -463,68 +527,6 @@ config_data! { /// Configs that only make sense when they are set by a client. As such they can only be defined /// by setting them using client's settings (e.g `settings.json` on VS Code). client: struct ClientDefaultConfigData <- ClientConfigInput -> { - /// Toggles the additional completions that automatically add imports when completed. - /// Note that your client must specify the `additionalTextEdits` LSP client capability to truly have this feature enabled. - completion_autoimport_enable: bool = true, - /// Toggles the additional completions that automatically show method calls and field accesses - /// with `self` prefixed to them when inside a method. - completion_autoself_enable: bool = true, - /// Whether to add parenthesis and argument snippets when completing function. - completion_callable_snippets: CallableCompletionDef = CallableCompletionDef::FillArguments, - /// Whether to show full function/method signatures in completion docs. - completion_fullFunctionSignatures_enable: bool = false, - /// Maximum number of completions to return. If `None`, the limit is infinite. - completion_limit: Option = None, - /// Whether to show postfix snippets like `dbg`, `if`, `not`, etc. - completion_postfix_enable: bool = true, - /// Enables completions of private items and fields that are defined in the current workspace even if they are not visible at the current position. - completion_privateEditable_enable: bool = false, - /// Custom completion snippets. - completion_snippets_custom: FxHashMap = serde_json::from_str(r#"{ - "Arc::new": { - "postfix": "arc", - "body": "Arc::new(${receiver})", - "requires": "std::sync::Arc", - "description": "Put the expression into an `Arc`", - "scope": "expr" - }, - "Rc::new": { - "postfix": "rc", - "body": "Rc::new(${receiver})", - "requires": "std::rc::Rc", - "description": "Put the expression into an `Rc`", - "scope": "expr" - }, - "Box::pin": { - "postfix": "pinbox", - "body": "Box::pin(${receiver})", - "requires": "std::boxed::Box", - "description": "Put the expression into a pinned `Box`", - "scope": "expr" - }, - "Ok": { - "postfix": "ok", - "body": "Ok(${receiver})", - "description": "Wrap the expression in a `Result::Ok`", - "scope": "expr" - }, - "Err": { - "postfix": "err", - "body": "Err(${receiver})", - "description": "Wrap the expression in a `Result::Err`", - "scope": "expr" - }, - "Some": { - "postfix": "some", - "body": "Some(${receiver})", - "description": "Wrap the expression in an `Option::Some`", - "scope": "expr" - } - }"#).unwrap(), - /// Whether to enable term search based snippets like `Some(foo.bar().baz())`. - completion_termSearch_enable: bool = false, - /// Term search fuel in "units of work" for autocompletion (Defaults to 1000). - completion_termSearch_fuel: usize = 1000, /// Controls file watching implementation. files_watcher: FilesWatcherDef = FilesWatcherDef::Client, @@ -879,7 +881,7 @@ impl Config { // IMPORTANT : This holds as long as ` completion_snippets_custom` is declared `client`. config.snippets.clear(); - let snips = self.completion_snippets_custom().to_owned(); + let snips = self.completion_snippets_custom(None).to_owned(); for (name, def) in snips.iter() { if def.prefix.is_empty() && def.postfix.is_empty() { @@ -1417,13 +1419,15 @@ impl Config { pub fn completion(&self, source_root: Option) -> CompletionConfig { CompletionConfig { - enable_postfix_completions: self.completion_postfix_enable().to_owned(), - enable_imports_on_the_fly: self.completion_autoimport_enable().to_owned() + enable_postfix_completions: self.completion_postfix_enable(source_root).to_owned(), + enable_imports_on_the_fly: self.completion_autoimport_enable(source_root).to_owned() && self.caps.completion_item_edit_resolve(), - enable_self_on_the_fly: self.completion_autoself_enable().to_owned(), - enable_private_editable: self.completion_privateEditable_enable().to_owned(), - full_function_signatures: self.completion_fullFunctionSignatures_enable().to_owned(), - callable: match self.completion_callable_snippets() { + enable_self_on_the_fly: self.completion_autoself_enable(source_root).to_owned(), + enable_private_editable: self.completion_privateEditable_enable(source_root).to_owned(), + full_function_signatures: self + .completion_fullFunctionSignatures_enable(source_root) + .to_owned(), + callable: match self.completion_callable_snippets(source_root) { CallableCompletionDef::FillArguments => Some(CallableSnippets::FillArguments), CallableCompletionDef::AddParentheses => Some(CallableSnippets::AddParentheses), CallableCompletionDef::None => None, @@ -1434,9 +1438,9 @@ impl Config { prefer_prelude: self.imports_preferPrelude(source_root).to_owned(), prefer_absolute: self.imports_prefixExternPrelude(source_root).to_owned(), snippets: self.snippets.clone().to_vec(), - limit: self.completion_limit().to_owned(), - enable_term_search: self.completion_termSearch_enable().to_owned(), - term_search_fuel: self.completion_termSearch_fuel().to_owned() as u64, + limit: self.completion_limit(source_root).to_owned(), + enable_term_search: self.completion_termSearch_enable(source_root).to_owned(), + term_search_fuel: self.completion_termSearch_fuel(source_root).to_owned() as u64, } } From 042a932bfe1edb1edde55db0ca620f1986fa5c95 Mon Sep 17 00:00:00 2001 From: Ali Bektas Date: Thu, 22 Aug 2024 21:03:58 +0200 Subject: [PATCH 0231/2194] Make almost every client config global --- .../crates/rust-analyzer/src/config.rs | 421 +++++++++--------- 1 file changed, 211 insertions(+), 210 deletions(-) diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs index ac72193be54b3..e7c5f989d93e7 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs @@ -84,6 +84,154 @@ config_data! { files_excludeDirs: Vec = vec![], + + /// Enables highlighting of related references while the cursor is on `break`, `loop`, `while`, or `for` keywords. + highlightRelated_breakPoints_enable: bool = true, + /// Enables highlighting of all captures of a closure while the cursor is on the `|` or move keyword of a closure. + highlightRelated_closureCaptures_enable: bool = true, + /// Enables highlighting of all exit points while the cursor is on any `return`, `?`, `fn`, or return type arrow (`->`). + highlightRelated_exitPoints_enable: bool = true, + /// Enables highlighting of related references while the cursor is on any identifier. + highlightRelated_references_enable: bool = true, + /// Enables highlighting of all break points for a loop or block context while the cursor is on any `async` or `await` keywords. + highlightRelated_yieldPoints_enable: bool = true, + + /// Whether to show `Debug` action. Only applies when + /// `#rust-analyzer.hover.actions.enable#` is set. + hover_actions_debug_enable: bool = true, + /// Whether to show HoverActions in Rust files. + hover_actions_enable: bool = true, + /// Whether to show `Go to Type Definition` action. Only applies when + /// `#rust-analyzer.hover.actions.enable#` is set. + hover_actions_gotoTypeDef_enable: bool = true, + /// Whether to show `Implementations` action. Only applies when + /// `#rust-analyzer.hover.actions.enable#` is set. + hover_actions_implementations_enable: bool = true, + /// Whether to show `References` action. Only applies when + /// `#rust-analyzer.hover.actions.enable#` is set. + hover_actions_references_enable: bool = false, + /// Whether to show `Run` action. Only applies when + /// `#rust-analyzer.hover.actions.enable#` is set. + hover_actions_run_enable: bool = true, + + /// Whether to show documentation on hover. + hover_documentation_enable: bool = true, + /// Whether to show keyword hover popups. Only applies when + /// `#rust-analyzer.hover.documentation.enable#` is set. + hover_documentation_keywords_enable: bool = true, + /// Use markdown syntax for links on hover. + hover_links_enable: bool = true, + /// How to render the align information in a memory layout hover. + hover_memoryLayout_alignment: Option = Some(MemoryLayoutHoverRenderKindDef::Hexadecimal), + /// Whether to show memory layout data on hover. + hover_memoryLayout_enable: bool = true, + /// How to render the niche information in a memory layout hover. + hover_memoryLayout_niches: Option = Some(false), + /// How to render the offset information in a memory layout hover. + hover_memoryLayout_offset: Option = Some(MemoryLayoutHoverRenderKindDef::Hexadecimal), + /// How to render the size information in a memory layout hover. + hover_memoryLayout_size: Option = Some(MemoryLayoutHoverRenderKindDef::Both), + + /// How many variants of an enum to display when hovering on. Show none if empty. + hover_show_enumVariants: Option = Some(5), + /// How many fields of a struct, variant or union to display when hovering on. Show none if empty. + hover_show_fields: Option = Some(5), + /// How many associated items of a trait to display when hovering a trait. + hover_show_traitAssocItems: Option = None, + + /// Whether to show inlay type hints for binding modes. + inlayHints_bindingModeHints_enable: bool = false, + /// Whether to show inlay type hints for method chains. + inlayHints_chainingHints_enable: bool = true, + /// Whether to show inlay hints after a closing `}` to indicate what item it belongs to. + inlayHints_closingBraceHints_enable: bool = true, + /// Minimum number of lines required before the `}` until the hint is shown (set to 0 or 1 + /// to always show them). + inlayHints_closingBraceHints_minLines: usize = 25, + /// Whether to show inlay hints for closure captures. + inlayHints_closureCaptureHints_enable: bool = false, + /// Whether to show inlay type hints for return types of closures. + inlayHints_closureReturnTypeHints_enable: ClosureReturnTypeHintsDef = ClosureReturnTypeHintsDef::Never, + /// Closure notation in type and chaining inlay hints. + inlayHints_closureStyle: ClosureStyle = ClosureStyle::ImplFn, + /// Whether to show enum variant discriminant hints. + inlayHints_discriminantHints_enable: DiscriminantHintsDef = DiscriminantHintsDef::Never, + /// Whether to show inlay hints for type adjustments. + inlayHints_expressionAdjustmentHints_enable: AdjustmentHintsDef = AdjustmentHintsDef::Never, + /// Whether to hide inlay hints for type adjustments outside of `unsafe` blocks. + inlayHints_expressionAdjustmentHints_hideOutsideUnsafe: bool = false, + /// Whether to show inlay hints as postfix ops (`.*` instead of `*`, etc). + inlayHints_expressionAdjustmentHints_mode: AdjustmentHintsModeDef = AdjustmentHintsModeDef::Prefix, + /// Whether to show const generic parameter name inlay hints. + inlayHints_genericParameterHints_const_enable: bool= true, + /// Whether to show generic lifetime parameter name inlay hints. + inlayHints_genericParameterHints_lifetime_enable: bool = false, + /// Whether to show generic type parameter name inlay hints. + inlayHints_genericParameterHints_type_enable: bool = false, + /// Whether to show implicit drop hints. + inlayHints_implicitDrops_enable: bool = false, + /// Whether to show inlay type hints for elided lifetimes in function signatures. + inlayHints_lifetimeElisionHints_enable: LifetimeElisionDef = LifetimeElisionDef::Never, + /// Whether to prefer using parameter names as the name for elided lifetime hints if possible. + inlayHints_lifetimeElisionHints_useParameterNames: bool = false, + /// Maximum length for inlay hints. Set to null to have an unlimited length. + inlayHints_maxLength: Option = Some(25), + /// Whether to show function parameter name inlay hints at the call + /// site. + inlayHints_parameterHints_enable: bool = true, + /// Whether to show exclusive range inlay hints. + inlayHints_rangeExclusiveHints_enable: bool = false, + /// Whether to show inlay hints for compiler inserted reborrows. + /// This setting is deprecated in favor of #rust-analyzer.inlayHints.expressionAdjustmentHints.enable#. + inlayHints_reborrowHints_enable: ReborrowHintsDef = ReborrowHintsDef::Never, + /// Whether to render leading colons for type hints, and trailing colons for parameter hints. + inlayHints_renderColons: bool = true, + /// Whether to show inlay type hints for variables. + inlayHints_typeHints_enable: bool = true, + /// Whether to hide inlay type hints for `let` statements that initialize to a closure. + /// Only applies to closures with blocks, same as `#rust-analyzer.inlayHints.closureReturnTypeHints.enable#`. + inlayHints_typeHints_hideClosureInitialization: bool = false, + /// Whether to hide inlay type hints for constructors. + inlayHints_typeHints_hideNamedConstructor: bool = false, + + /// Enables the experimental support for interpreting tests. + interpret_tests: bool = false, + + /// Join lines merges consecutive declaration and initialization of an assignment. + joinLines_joinAssignments: bool = true, + /// Join lines inserts else between consecutive ifs. + joinLines_joinElseIf: bool = true, + /// Join lines removes trailing commas. + joinLines_removeTrailingComma: bool = true, + /// Join lines unwraps trivial blocks. + joinLines_unwrapTrivialBlock: bool = true, + + /// Whether to show `Debug` lens. Only applies when + /// `#rust-analyzer.lens.enable#` is set. + lens_debug_enable: bool = true, + /// Whether to show CodeLens in Rust files. + lens_enable: bool = true, + /// Whether to show `Implementations` lens. Only applies when + /// `#rust-analyzer.lens.enable#` is set. + lens_implementations_enable: bool = true, + /// Where to render annotations. + lens_location: AnnotationLocation = AnnotationLocation::AboveName, + /// Whether to show `References` lens for Struct, Enum, and Union. + /// Only applies when `#rust-analyzer.lens.enable#` is set. + lens_references_adt_enable: bool = false, + /// Whether to show `References` lens for Enum Variants. + /// Only applies when `#rust-analyzer.lens.enable#` is set. + lens_references_enumVariant_enable: bool = false, + /// Whether to show `Method References` lens. Only applies when + /// `#rust-analyzer.lens.enable#` is set. + lens_references_method_enable: bool = false, + /// Whether to show `References` lens for Trait. + /// Only applies when `#rust-analyzer.lens.enable#` is set. + lens_references_trait_enable: bool = false, + /// Whether to show `Run` lens. Only applies when + /// `#rust-analyzer.lens.enable#` is set. + lens_run_enable: bool = true, + /// Disable project auto-discovery in favor of explicitly specified set /// of projects. /// @@ -97,6 +245,69 @@ config_data! { /// Sets the LRU capacity of the specified queries. lru_query_capacities: FxHashMap, u16> = FxHashMap::default(), + /// Whether to show `can't find Cargo.toml` error message. + notifications_cargoTomlNotFound: bool = true, + + /// How many worker threads in the main loop. The default `null` means to pick automatically. + numThreads: Option = None, + + /// Expand attribute macros. Requires `#rust-analyzer.procMacro.enable#` to be set. + procMacro_attributes_enable: bool = true, + /// Enable support for procedural macros, implies `#rust-analyzer.cargo.buildScripts.enable#`. + procMacro_enable: bool = true, + /// Internal config, path to proc-macro server executable. + procMacro_server: Option = None, + + /// Exclude imports from find-all-references. + references_excludeImports: bool = false, + + /// Exclude tests from find-all-references. + references_excludeTests: bool = false, + + /// Inject additional highlighting into doc comments. + /// + /// When enabled, rust-analyzer will highlight rust source in doc comments as well as intra + /// doc links. + semanticHighlighting_doc_comment_inject_enable: bool = true, + /// Whether the server is allowed to emit non-standard tokens and modifiers. + semanticHighlighting_nonStandardTokens: bool = true, + /// Use semantic tokens for operators. + /// + /// When disabled, rust-analyzer will emit semantic tokens only for operator tokens when + /// they are tagged with modifiers. + semanticHighlighting_operator_enable: bool = true, + /// Use specialized semantic tokens for operators. + /// + /// When enabled, rust-analyzer will emit special token types for operator tokens instead + /// of the generic `operator` token type. + semanticHighlighting_operator_specialization_enable: bool = false, + /// Use semantic tokens for punctuation. + /// + /// When disabled, rust-analyzer will emit semantic tokens only for punctuation tokens when + /// they are tagged with modifiers or have a special role. + semanticHighlighting_punctuation_enable: bool = false, + /// When enabled, rust-analyzer will emit a punctuation semantic token for the `!` of macro + /// calls. + semanticHighlighting_punctuation_separate_macro_bang: bool = false, + /// Use specialized semantic tokens for punctuation. + /// + /// When enabled, rust-analyzer will emit special token types for punctuation tokens instead + /// of the generic `punctuation` token type. + semanticHighlighting_punctuation_specialization_enable: bool = false, + /// Use semantic tokens for strings. + /// + /// In some editors (e.g. vscode) semantic tokens override other highlighting grammars. + /// By disabling semantic tokens for strings, other grammars can be used to highlight + /// their contents. + semanticHighlighting_strings_enable: bool = true, + + /// Show full signature of the callable. Only shows parameters if disabled. + signatureInfo_detail: SignatureDetail = SignatureDetail::Full, + /// Show documentation. + signatureInfo_documentation_enable: bool = true, + + /// Whether to insert closing angle brackets when typing an opening angle bracket of a generic argument list. + typing_autoClosingAngleBrackets_enable: bool = false, /// Enables automatic discovery of projects using [`DiscoverWorkspaceConfig::command`]. @@ -531,216 +742,6 @@ config_data! { /// Controls file watching implementation. files_watcher: FilesWatcherDef = FilesWatcherDef::Client, - /// Enables highlighting of related references while the cursor is on `break`, `loop`, `while`, or `for` keywords. - highlightRelated_breakPoints_enable: bool = true, - /// Enables highlighting of all captures of a closure while the cursor is on the `|` or move keyword of a closure. - highlightRelated_closureCaptures_enable: bool = true, - /// Enables highlighting of all exit points while the cursor is on any `return`, `?`, `fn`, or return type arrow (`->`). - highlightRelated_exitPoints_enable: bool = true, - /// Enables highlighting of related references while the cursor is on any identifier. - highlightRelated_references_enable: bool = true, - /// Enables highlighting of all break points for a loop or block context while the cursor is on any `async` or `await` keywords. - highlightRelated_yieldPoints_enable: bool = true, - - /// Whether to show `Debug` action. Only applies when - /// `#rust-analyzer.hover.actions.enable#` is set. - hover_actions_debug_enable: bool = true, - /// Whether to show HoverActions in Rust files. - hover_actions_enable: bool = true, - /// Whether to show `Go to Type Definition` action. Only applies when - /// `#rust-analyzer.hover.actions.enable#` is set. - hover_actions_gotoTypeDef_enable: bool = true, - /// Whether to show `Implementations` action. Only applies when - /// `#rust-analyzer.hover.actions.enable#` is set. - hover_actions_implementations_enable: bool = true, - /// Whether to show `References` action. Only applies when - /// `#rust-analyzer.hover.actions.enable#` is set. - hover_actions_references_enable: bool = false, - /// Whether to show `Run` action. Only applies when - /// `#rust-analyzer.hover.actions.enable#` is set. - hover_actions_run_enable: bool = true, - - /// Whether to show documentation on hover. - hover_documentation_enable: bool = true, - /// Whether to show keyword hover popups. Only applies when - /// `#rust-analyzer.hover.documentation.enable#` is set. - hover_documentation_keywords_enable: bool = true, - /// Use markdown syntax for links on hover. - hover_links_enable: bool = true, - /// How to render the align information in a memory layout hover. - hover_memoryLayout_alignment: Option = Some(MemoryLayoutHoverRenderKindDef::Hexadecimal), - /// Whether to show memory layout data on hover. - hover_memoryLayout_enable: bool = true, - /// How to render the niche information in a memory layout hover. - hover_memoryLayout_niches: Option = Some(false), - /// How to render the offset information in a memory layout hover. - hover_memoryLayout_offset: Option = Some(MemoryLayoutHoverRenderKindDef::Hexadecimal), - /// How to render the size information in a memory layout hover. - hover_memoryLayout_size: Option = Some(MemoryLayoutHoverRenderKindDef::Both), - - /// How many variants of an enum to display when hovering on. Show none if empty. - hover_show_enumVariants: Option = Some(5), - /// How many fields of a struct, variant or union to display when hovering on. Show none if empty. - hover_show_fields: Option = Some(5), - /// How many associated items of a trait to display when hovering a trait. - hover_show_traitAssocItems: Option = None, - - /// Whether to show inlay type hints for binding modes. - inlayHints_bindingModeHints_enable: bool = false, - /// Whether to show inlay type hints for method chains. - inlayHints_chainingHints_enable: bool = true, - /// Whether to show inlay hints after a closing `}` to indicate what item it belongs to. - inlayHints_closingBraceHints_enable: bool = true, - /// Minimum number of lines required before the `}` until the hint is shown (set to 0 or 1 - /// to always show them). - inlayHints_closingBraceHints_minLines: usize = 25, - /// Whether to show inlay hints for closure captures. - inlayHints_closureCaptureHints_enable: bool = false, - /// Whether to show inlay type hints for return types of closures. - inlayHints_closureReturnTypeHints_enable: ClosureReturnTypeHintsDef = ClosureReturnTypeHintsDef::Never, - /// Closure notation in type and chaining inlay hints. - inlayHints_closureStyle: ClosureStyle = ClosureStyle::ImplFn, - /// Whether to show enum variant discriminant hints. - inlayHints_discriminantHints_enable: DiscriminantHintsDef = DiscriminantHintsDef::Never, - /// Whether to show inlay hints for type adjustments. - inlayHints_expressionAdjustmentHints_enable: AdjustmentHintsDef = AdjustmentHintsDef::Never, - /// Whether to hide inlay hints for type adjustments outside of `unsafe` blocks. - inlayHints_expressionAdjustmentHints_hideOutsideUnsafe: bool = false, - /// Whether to show inlay hints as postfix ops (`.*` instead of `*`, etc). - inlayHints_expressionAdjustmentHints_mode: AdjustmentHintsModeDef = AdjustmentHintsModeDef::Prefix, - /// Whether to show const generic parameter name inlay hints. - inlayHints_genericParameterHints_const_enable: bool= true, - /// Whether to show generic lifetime parameter name inlay hints. - inlayHints_genericParameterHints_lifetime_enable: bool = false, - /// Whether to show generic type parameter name inlay hints. - inlayHints_genericParameterHints_type_enable: bool = false, - /// Whether to show implicit drop hints. - inlayHints_implicitDrops_enable: bool = false, - /// Whether to show inlay type hints for elided lifetimes in function signatures. - inlayHints_lifetimeElisionHints_enable: LifetimeElisionDef = LifetimeElisionDef::Never, - /// Whether to prefer using parameter names as the name for elided lifetime hints if possible. - inlayHints_lifetimeElisionHints_useParameterNames: bool = false, - /// Maximum length for inlay hints. Set to null to have an unlimited length. - inlayHints_maxLength: Option = Some(25), - /// Whether to show function parameter name inlay hints at the call - /// site. - inlayHints_parameterHints_enable: bool = true, - /// Whether to show exclusive range inlay hints. - inlayHints_rangeExclusiveHints_enable: bool = false, - /// Whether to show inlay hints for compiler inserted reborrows. - /// This setting is deprecated in favor of #rust-analyzer.inlayHints.expressionAdjustmentHints.enable#. - inlayHints_reborrowHints_enable: ReborrowHintsDef = ReborrowHintsDef::Never, - /// Whether to render leading colons for type hints, and trailing colons for parameter hints. - inlayHints_renderColons: bool = true, - /// Whether to show inlay type hints for variables. - inlayHints_typeHints_enable: bool = true, - /// Whether to hide inlay type hints for `let` statements that initialize to a closure. - /// Only applies to closures with blocks, same as `#rust-analyzer.inlayHints.closureReturnTypeHints.enable#`. - inlayHints_typeHints_hideClosureInitialization: bool = false, - /// Whether to hide inlay type hints for constructors. - inlayHints_typeHints_hideNamedConstructor: bool = false, - - /// Enables the experimental support for interpreting tests. - interpret_tests: bool = false, - - /// Join lines merges consecutive declaration and initialization of an assignment. - joinLines_joinAssignments: bool = true, - /// Join lines inserts else between consecutive ifs. - joinLines_joinElseIf: bool = true, - /// Join lines removes trailing commas. - joinLines_removeTrailingComma: bool = true, - /// Join lines unwraps trivial blocks. - joinLines_unwrapTrivialBlock: bool = true, - - /// Whether to show `Debug` lens. Only applies when - /// `#rust-analyzer.lens.enable#` is set. - lens_debug_enable: bool = true, - /// Whether to show CodeLens in Rust files. - lens_enable: bool = true, - /// Whether to show `Implementations` lens. Only applies when - /// `#rust-analyzer.lens.enable#` is set. - lens_implementations_enable: bool = true, - /// Where to render annotations. - lens_location: AnnotationLocation = AnnotationLocation::AboveName, - /// Whether to show `References` lens for Struct, Enum, and Union. - /// Only applies when `#rust-analyzer.lens.enable#` is set. - lens_references_adt_enable: bool = false, - /// Whether to show `References` lens for Enum Variants. - /// Only applies when `#rust-analyzer.lens.enable#` is set. - lens_references_enumVariant_enable: bool = false, - /// Whether to show `Method References` lens. Only applies when - /// `#rust-analyzer.lens.enable#` is set. - lens_references_method_enable: bool = false, - /// Whether to show `References` lens for Trait. - /// Only applies when `#rust-analyzer.lens.enable#` is set. - lens_references_trait_enable: bool = false, - /// Whether to show `Run` lens. Only applies when - /// `#rust-analyzer.lens.enable#` is set. - lens_run_enable: bool = true, - - /// Whether to show `can't find Cargo.toml` error message. - notifications_cargoTomlNotFound: bool = true, - - /// How many worker threads in the main loop. The default `null` means to pick automatically. - numThreads: Option = None, - - /// Expand attribute macros. Requires `#rust-analyzer.procMacro.enable#` to be set. - procMacro_attributes_enable: bool = true, - /// Enable support for procedural macros, implies `#rust-analyzer.cargo.buildScripts.enable#`. - procMacro_enable: bool = true, - /// Internal config, path to proc-macro server executable. - procMacro_server: Option = None, - - /// Exclude imports from find-all-references. - references_excludeImports: bool = false, - - /// Exclude tests from find-all-references. - references_excludeTests: bool = false, - - /// Inject additional highlighting into doc comments. - /// - /// When enabled, rust-analyzer will highlight rust source in doc comments as well as intra - /// doc links. - semanticHighlighting_doc_comment_inject_enable: bool = true, - /// Whether the server is allowed to emit non-standard tokens and modifiers. - semanticHighlighting_nonStandardTokens: bool = true, - /// Use semantic tokens for operators. - /// - /// When disabled, rust-analyzer will emit semantic tokens only for operator tokens when - /// they are tagged with modifiers. - semanticHighlighting_operator_enable: bool = true, - /// Use specialized semantic tokens for operators. - /// - /// When enabled, rust-analyzer will emit special token types for operator tokens instead - /// of the generic `operator` token type. - semanticHighlighting_operator_specialization_enable: bool = false, - /// Use semantic tokens for punctuation. - /// - /// When disabled, rust-analyzer will emit semantic tokens only for punctuation tokens when - /// they are tagged with modifiers or have a special role. - semanticHighlighting_punctuation_enable: bool = false, - /// When enabled, rust-analyzer will emit a punctuation semantic token for the `!` of macro - /// calls. - semanticHighlighting_punctuation_separate_macro_bang: bool = false, - /// Use specialized semantic tokens for punctuation. - /// - /// When enabled, rust-analyzer will emit special token types for punctuation tokens instead - /// of the generic `punctuation` token type. - semanticHighlighting_punctuation_specialization_enable: bool = false, - /// Use semantic tokens for strings. - /// - /// In some editors (e.g. vscode) semantic tokens override other highlighting grammars. - /// By disabling semantic tokens for strings, other grammars can be used to highlight - /// their contents. - semanticHighlighting_strings_enable: bool = true, - - /// Show full signature of the callable. Only shows parameters if disabled. - signatureInfo_detail: SignatureDetail = SignatureDetail::Full, - /// Show documentation. - signatureInfo_documentation_enable: bool = true, - - /// Whether to insert closing angle brackets when typing an opening angle bracket of a generic argument list. - typing_autoClosingAngleBrackets_enable: bool = false, } } From 0e5270672d5e95460c4dfbdfd4775e106697195d Mon Sep 17 00:00:00 2001 From: Ali Bektas Date: Thu, 22 Aug 2024 21:50:40 +0200 Subject: [PATCH 0232/2194] Remove invalid tests --- .../crates/rust-analyzer/src/config.rs | 72 ------------------- 1 file changed, 72 deletions(-) diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs index e7c5f989d93e7..8e41b43bfe0b5 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs @@ -3585,76 +3585,4 @@ mod tests { matches!(config.flycheck(None), FlycheckConfig::CargoCommand { options, .. } if options.target_dir == Some(Utf8PathBuf::from("other_folder"))) ); } - - #[test] - fn toml_unknown_key() { - let config = - Config::new(AbsPathBuf::assert(project_root()), Default::default(), vec![], None); - - let mut change = ConfigChange::default(); - - change.change_user_config(Some( - toml::toml! { - [cargo.cfgs] - these = "these" - should = "should" - be = "be" - valid = "valid" - - [invalid.config] - err = "error" - - [cargo] - target = "ok" - - // FIXME: This should be an error - [cargo.sysroot] - non-table = "expected" - } - .to_string() - .into(), - )); - - let (config, e, _) = config.apply_change(change); - expect_test::expect![[r#" - ConfigErrors( - [ - Toml { - config_key: "invalid/config/err", - error: Error { - inner: Error { - inner: TomlError { - message: "unexpected field", - raw: None, - keys: [], - span: None, - }, - }, - }, - }, - ], - ) - "#]] - .assert_debug_eq(&e); - let mut change = ConfigChange::default(); - - change.change_user_config(Some( - toml::toml! { - [cargo.cfgs] - these = "these" - should = "should" - be = "be" - valid = "valid" - } - .to_string() - .into(), - )); - let (_, e, _) = config.apply_change(change); - expect_test::expect![[r#" - ConfigErrors( - [], - ) - "#]] - .assert_debug_eq(&e); - } } From 9edea1eea060e8b176164bcb05a9e1de11606b88 Mon Sep 17 00:00:00 2001 From: Ali Bektas Date: Wed, 28 Aug 2024 19:40:58 +0200 Subject: [PATCH 0233/2194] Minor errors --- src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs index 8e41b43bfe0b5..0a1bdf49bdbd2 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs @@ -1897,7 +1897,7 @@ impl Config { CargoFeaturesDef::Selected(it) => it, }, extra_args: self.extra_args(source_root).clone(), - extra_test_bin_args: self.runnables_extraTestBinaryArgs().clone(), + extra_test_bin_args: self.runnables_extraTestBinaryArgs(source_root).clone(), extra_env: self.extra_env(source_root).clone(), target_dir: self.target_dir_from_config(source_root), } @@ -1954,7 +1954,7 @@ impl Config { CargoFeaturesDef::Selected(it) => it, }, extra_args: self.check_extra_args(source_root), - extra_test_bin_args: self.runnables_extraTestBinaryArgs().clone(), + extra_test_bin_args: self.runnables_extraTestBinaryArgs(source_root).clone(), extra_env: self.check_extra_env(source_root), target_dir: self.target_dir_from_config(source_root), }, From ea6df5c147537029cb6d142abcbcb02675a03740 Mon Sep 17 00:00:00 2001 From: Rain Date: Mon, 26 Aug 2024 11:00:24 -0700 Subject: [PATCH 0234/2194] Update stacker to 0.1.17 The main new feature is support for detecting the current stack size on illumos. (See my blog post [1] for the context which led to this.) [1]: https://sunshowers.io/posts/rustc-segfault-illumos/ --- Cargo.lock | 6 +++--- compiler/rustc_data_structures/Cargo.toml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 6ea4cd8f5aca4..207117933443c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4978,15 +4978,15 @@ dependencies = [ [[package]] name = "stacker" -version = "0.1.15" +version = "0.1.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c886bd4480155fd3ef527d45e9ac8dd7118a898a46530b7b94c3e21866259fce" +checksum = "799c883d55abdb5e98af1a7b3f23b9b6de8ecada0ecac058672d7635eb48ca7b" dependencies = [ "cc", "cfg-if", "libc", "psm", - "winapi", + "windows-sys 0.59.0", ] [[package]] diff --git a/compiler/rustc_data_structures/Cargo.toml b/compiler/rustc_data_structures/Cargo.toml index 69cbf8c416105..38c6c8a8d11c7 100644 --- a/compiler/rustc_data_structures/Cargo.toml +++ b/compiler/rustc_data_structures/Cargo.toml @@ -22,7 +22,7 @@ rustc_index = { path = "../rustc_index", package = "rustc_index" } rustc_macros = { path = "../rustc_macros" } rustc_serialize = { path = "../rustc_serialize" } smallvec = { version = "1.8.1", features = ["const_generics", "union", "may_dangle"] } -stacker = "0.1.15" +stacker = "0.1.17" tempfile = "3.2" thin-vec = "0.2.12" tracing = "0.1" From e691f6d040321b9c872ab702ecf115bbd747957a Mon Sep 17 00:00:00 2001 From: Wilfred Hughes Date: Wed, 28 Aug 2024 16:29:18 -0700 Subject: [PATCH 0235/2194] internal: Add doc comments to OpQueue --- .../crates/rust-analyzer/src/op_queue.rs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/op_queue.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/op_queue.rs index eab9733872402..5c4c858e1509b 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/op_queue.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/op_queue.rs @@ -37,9 +37,13 @@ impl Default for OpQueue { } impl OpQueue { + /// Request an operation to start. pub(crate) fn request_op(&mut self, reason: Cause, args: Args) { self.op_requested = Some((reason, args)); } + + /// If there was an operation requested, mark this queue as + /// started and return the request arguments. pub(crate) fn should_start_op(&mut self) -> Option<(Cause, Args)> { if self.op_in_progress { return None; @@ -47,18 +51,25 @@ impl OpQueue { self.op_in_progress = self.op_requested.is_some(); self.op_requested.take() } + + /// Mark an operation as completed. pub(crate) fn op_completed(&mut self, result: Output) { assert!(self.op_in_progress); self.op_in_progress = false; self.last_op_result = result; } + /// Get the result of the last operation. pub(crate) fn last_op_result(&self) -> &Output { &self.last_op_result } + + // Is there an operation that has started, but hasn't yet finished? pub(crate) fn op_in_progress(&self) -> bool { self.op_in_progress } + + // Has an operation been requested? pub(crate) fn op_requested(&self) -> bool { self.op_requested.is_some() } From e759e0b7397b4343ac9dee881e177a9b8421c436 Mon Sep 17 00:00:00 2001 From: binarycat Date: Wed, 28 Aug 2024 21:30:05 -0400 Subject: [PATCH 0236/2194] add guarantee about remove_dir and remove_file error kinds approved in ACP https://github.com/rust-lang/libs-team/issues/433 --- library/std/src/fs.rs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/library/std/src/fs.rs b/library/std/src/fs.rs index 6a0d9f47960ec..14e6ee467979f 100644 --- a/library/std/src/fs.rs +++ b/library/std/src/fs.rs @@ -1989,6 +1989,11 @@ impl AsInner for DirEntry { /// * The file doesn't exist. /// * The user lacks permissions to remove the file. /// +/// This function will only ever return an error of kind `NotFound` if the given +/// path does not exist. Note that the inverse is not true, +/// ie. if a path does not exist, its removal may fail for a number of reasons, +/// such as insufficient permissions. +/// /// # Examples /// /// ```no_run @@ -2446,6 +2451,11 @@ pub fn create_dir_all>(path: P) -> io::Result<()> { /// * The user lacks permissions to remove the directory at the provided `path`. /// * The directory isn't empty. /// +/// This function will only ever return an error of kind `NotFound` if the given +/// path does not exist. Note that the inverse is not true, +/// ie. if a path does not exist, its removal may fail for a number of reasons, +/// such as insufficient permissions. +/// /// # Examples /// /// ```no_run From c6111c0e80f9b323c80b149542ca48e5634b48df Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 29 Aug 2024 10:54:08 +1000 Subject: [PATCH 0237/2194] Remove the `'body` lifetime on `FilterInformation`. It's not needed. --- compiler/rustc_mir_transform/src/dest_prop.rs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/compiler/rustc_mir_transform/src/dest_prop.rs b/compiler/rustc_mir_transform/src/dest_prop.rs index ed924761892c7..1022d218f0091 100644 --- a/compiler/rustc_mir_transform/src/dest_prop.rs +++ b/compiler/rustc_mir_transform/src/dest_prop.rs @@ -359,8 +359,8 @@ impl<'a, 'tcx> MutVisitor<'tcx> for Merger<'a, 'tcx> { // // This section enforces bullet point 2 -struct FilterInformation<'a, 'body, 'alloc, 'tcx> { - body: &'body Body<'tcx>, +struct FilterInformation<'a, 'alloc, 'tcx> { + body: &'a Body<'tcx>, points: &'a DenseLocationMap, live: &'a SparseIntervalMatrix, candidates: &'a mut Candidates<'alloc>, @@ -446,7 +446,7 @@ enum CandidateFilter { Remove, } -impl<'a, 'body, 'alloc, 'tcx> FilterInformation<'a, 'body, 'alloc, 'tcx> { +impl<'a, 'alloc, 'tcx> FilterInformation<'a, 'alloc, 'tcx> { /// Filters the set of candidates to remove those that conflict. /// /// The steps we take are exactly those that are outlined at the top of the file. For each @@ -464,12 +464,12 @@ impl<'a, 'body, 'alloc, 'tcx> FilterInformation<'a, 'body, 'alloc, 'tcx> { /// before the statement/terminator will correctly report locals that are read in the /// statement/terminator to be live. We are additionally conservative by treating all written to /// locals as also being read from. - fn filter_liveness<'b>( + fn filter_liveness( candidates: &mut Candidates<'alloc>, points: &DenseLocationMap, live: &SparseIntervalMatrix, - write_info_alloc: &'alloc mut WriteInfo, - body: &'b Body<'tcx>, + write_info: &'alloc mut WriteInfo, + body: &Body<'tcx>, ) { let mut this = FilterInformation { body, @@ -478,7 +478,7 @@ impl<'a, 'body, 'alloc, 'tcx> FilterInformation<'a, 'body, 'alloc, 'tcx> { candidates, // We don't actually store anything at this scope, we just keep things here to be able // to reuse the allocation. - write_info: write_info_alloc, + write_info, // Doesn't matter what we put here, will be overwritten before being used at: Location::START, }; @@ -820,9 +820,9 @@ fn is_local_required(local: Local, body: &Body<'_>) -> bool { ///////////////////////////////////////////////////////// // MIR Dump -fn dest_prop_mir_dump<'body, 'tcx>( +fn dest_prop_mir_dump<'tcx>( tcx: TyCtxt<'tcx>, - body: &'body Body<'tcx>, + body: &Body<'tcx>, points: &DenseLocationMap, live: &SparseIntervalMatrix, round: usize, From 0a282ea7176b000928654262d3faa67785722398 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 29 Aug 2024 11:26:13 +1000 Subject: [PATCH 0238/2194] Move `WriteInfo` out of `Allocations`. It doesn't need to be in there, and the move simplifies lifetimes. --- compiler/rustc_mir_transform/src/dest_prop.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_mir_transform/src/dest_prop.rs b/compiler/rustc_mir_transform/src/dest_prop.rs index 1022d218f0091..f7057b0a6abba 100644 --- a/compiler/rustc_mir_transform/src/dest_prop.rs +++ b/compiler/rustc_mir_transform/src/dest_prop.rs @@ -165,6 +165,7 @@ impl<'tcx> MirPass<'tcx> for DestinationPropagation { fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { let def_id = body.source.def_id(); let mut allocations = Allocations::default(); + let mut write_info = WriteInfo::default(); trace!(func = ?tcx.def_path_str(def_id)); let borrowed = rustc_mir_dataflow::impls::borrowed_locals(body); @@ -205,7 +206,7 @@ impl<'tcx> MirPass<'tcx> for DestinationPropagation { &mut candidates, &points, &live, - &mut allocations.write_info, + &mut write_info, body, ); @@ -262,7 +263,6 @@ impl<'tcx> MirPass<'tcx> for DestinationPropagation { struct Allocations { candidates: FxIndexMap>, candidates_reverse: FxIndexMap>, - write_info: WriteInfo, // PERF: Do this for `MaybeLiveLocals` allocations too. } @@ -364,7 +364,7 @@ struct FilterInformation<'a, 'alloc, 'tcx> { points: &'a DenseLocationMap, live: &'a SparseIntervalMatrix, candidates: &'a mut Candidates<'alloc>, - write_info: &'alloc mut WriteInfo, + write_info: &'a mut WriteInfo, at: Location, } @@ -468,7 +468,7 @@ impl<'a, 'alloc, 'tcx> FilterInformation<'a, 'alloc, 'tcx> { candidates: &mut Candidates<'alloc>, points: &DenseLocationMap, live: &SparseIntervalMatrix, - write_info: &'alloc mut WriteInfo, + write_info: &mut WriteInfo, body: &Body<'tcx>, ) { let mut this = FilterInformation { From ad5a6e11c75905a51146f1cd0bb036ebe7c01a29 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 29 Aug 2024 11:30:12 +1000 Subject: [PATCH 0239/2194] Remove `Allocations`. It's not necessary, and just complicates things. --- compiler/rustc_mir_transform/src/dest_prop.rs | 18 ++++-------------- 1 file changed, 4 insertions(+), 14 deletions(-) diff --git a/compiler/rustc_mir_transform/src/dest_prop.rs b/compiler/rustc_mir_transform/src/dest_prop.rs index f7057b0a6abba..f5f496acfcea0 100644 --- a/compiler/rustc_mir_transform/src/dest_prop.rs +++ b/compiler/rustc_mir_transform/src/dest_prop.rs @@ -164,7 +164,8 @@ impl<'tcx> MirPass<'tcx> for DestinationPropagation { fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { let def_id = body.source.def_id(); - let mut allocations = Allocations::default(); + let mut candidates = FxIndexMap::default(); + let mut candidates_reverse = FxIndexMap::default(); let mut write_info = WriteInfo::default(); trace!(func = ?tcx.def_path_str(def_id)); @@ -196,8 +197,8 @@ impl<'tcx> MirPass<'tcx> for DestinationPropagation { let mut candidates = find_candidates( body, &borrowed, - &mut allocations.candidates, - &mut allocations.candidates_reverse, + &mut candidates, + &mut candidates_reverse, ); trace!(?candidates); dest_prop_mir_dump(tcx, body, &points, &live, round_count); @@ -255,17 +256,6 @@ impl<'tcx> MirPass<'tcx> for DestinationPropagation { } } -/// Container for the various allocations that we need. -/// -/// We store these here and hand out `&mut` access to them, instead of dropping and recreating them -/// frequently. Everything with a `&'alloc` lifetime points into here. -#[derive(Default)] -struct Allocations { - candidates: FxIndexMap>, - candidates_reverse: FxIndexMap>, - // PERF: Do this for `MaybeLiveLocals` allocations too. -} - #[derive(Debug)] struct Candidates<'alloc> { /// The set of candidates we are considering in this optimization. From 1be2204363fed9f748860734e7d5f6f7910ecc7e Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 29 Aug 2024 11:47:00 +1000 Subject: [PATCH 0240/2194] Simplify `Candidate`. By making it own the index maps, instead of holding references to them. This requires moving the free function `find_candidate` into `Candidate::reset_and_find`. It lets the `'alloc` lifetime be removed everywhere that still has it. --- compiler/rustc_mir_transform/src/dest_prop.rs | 83 ++++++++----------- 1 file changed, 36 insertions(+), 47 deletions(-) diff --git a/compiler/rustc_mir_transform/src/dest_prop.rs b/compiler/rustc_mir_transform/src/dest_prop.rs index f5f496acfcea0..ba1e99290fb7c 100644 --- a/compiler/rustc_mir_transform/src/dest_prop.rs +++ b/compiler/rustc_mir_transform/src/dest_prop.rs @@ -164,8 +164,7 @@ impl<'tcx> MirPass<'tcx> for DestinationPropagation { fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { let def_id = body.source.def_id(); - let mut candidates = FxIndexMap::default(); - let mut candidates_reverse = FxIndexMap::default(); + let mut candidates = Candidates::default(); let mut write_info = WriteInfo::default(); trace!(func = ?tcx.def_path_str(def_id)); @@ -194,12 +193,7 @@ impl<'tcx> MirPass<'tcx> for DestinationPropagation { loop { // PERF: Can we do something smarter than recalculating the candidates and liveness // results? - let mut candidates = find_candidates( - body, - &borrowed, - &mut candidates, - &mut candidates_reverse, - ); + candidates.reset_and_find(body, &borrowed); trace!(?candidates); dest_prop_mir_dump(tcx, body, &points, &live, round_count); @@ -256,8 +250,8 @@ impl<'tcx> MirPass<'tcx> for DestinationPropagation { } } -#[derive(Debug)] -struct Candidates<'alloc> { +#[derive(Debug, Default)] +struct Candidates { /// The set of candidates we are considering in this optimization. /// /// We will always merge the key into at most one of its values. @@ -272,11 +266,12 @@ struct Candidates<'alloc> { /// /// We will still report that we would like to merge `_1` and `_2` in an attempt to allow us to /// remove that assignment. - c: &'alloc mut FxIndexMap>, + c: FxIndexMap>, + /// A reverse index of the `c` set; if the `c` set contains `a => Place { local: b, proj }`, /// then this contains `b => a`. // PERF: Possibly these should be `SmallVec`s? - reverse: &'alloc mut FxIndexMap>, + reverse: FxIndexMap>, } ////////////////////////////////////////////////////////// @@ -349,11 +344,11 @@ impl<'a, 'tcx> MutVisitor<'tcx> for Merger<'a, 'tcx> { // // This section enforces bullet point 2 -struct FilterInformation<'a, 'alloc, 'tcx> { +struct FilterInformation<'a, 'tcx> { body: &'a Body<'tcx>, points: &'a DenseLocationMap, live: &'a SparseIntervalMatrix, - candidates: &'a mut Candidates<'alloc>, + candidates: &'a mut Candidates, write_info: &'a mut WriteInfo, at: Location, } @@ -361,7 +356,28 @@ struct FilterInformation<'a, 'alloc, 'tcx> { // We first implement some utility functions which we will expose removing candidates according to // different needs. Throughout the liveness filtering, the `candidates` are only ever accessed // through these methods, and not directly. -impl<'alloc> Candidates<'alloc> { +impl Candidates { + /// Collects the candidates for merging. + /// + /// This is responsible for enforcing the first and third bullet point. + fn reset_and_find<'tcx>(&mut self, body: &Body<'tcx>, borrowed: &BitSet) { + self.c.clear(); + self.reverse.clear(); + let mut visitor = FindAssignments { body, candidates: &mut self.c, borrowed }; + visitor.visit_body(body); + // Deduplicate candidates. + for (_, cands) in self.c.iter_mut() { + cands.sort(); + cands.dedup(); + } + // Generate the reverse map. + for (src, cands) in self.c.iter() { + for dest in cands.iter().copied() { + self.reverse.entry(dest).or_default().push(*src); + } + } + } + /// Just `Vec::retain`, but the condition is inverted and we add debugging output fn vec_filter_candidates( src: Local, @@ -436,7 +452,7 @@ enum CandidateFilter { Remove, } -impl<'a, 'alloc, 'tcx> FilterInformation<'a, 'alloc, 'tcx> { +impl<'a, 'tcx> FilterInformation<'a, 'tcx> { /// Filters the set of candidates to remove those that conflict. /// /// The steps we take are exactly those that are outlined at the top of the file. For each @@ -455,7 +471,7 @@ impl<'a, 'alloc, 'tcx> FilterInformation<'a, 'alloc, 'tcx> { /// statement/terminator to be live. We are additionally conservative by treating all written to /// locals as also being read from. fn filter_liveness( - candidates: &mut Candidates<'alloc>, + candidates: &mut Candidates, points: &DenseLocationMap, live: &SparseIntervalMatrix, write_info: &mut WriteInfo, @@ -725,40 +741,13 @@ fn places_to_candidate_pair<'tcx>( Some((a, b)) } -/// Collects the candidates for merging -/// -/// This is responsible for enforcing the first and third bullet point. -fn find_candidates<'alloc, 'tcx>( - body: &Body<'tcx>, - borrowed: &BitSet, - candidates: &'alloc mut FxIndexMap>, - candidates_reverse: &'alloc mut FxIndexMap>, -) -> Candidates<'alloc> { - candidates.clear(); - candidates_reverse.clear(); - let mut visitor = FindAssignments { body, candidates, borrowed }; - visitor.visit_body(body); - // Deduplicate candidates - for (_, cands) in candidates.iter_mut() { - cands.sort(); - cands.dedup(); - } - // Generate the reverse map - for (src, cands) in candidates.iter() { - for dest in cands.iter().copied() { - candidates_reverse.entry(dest).or_default().push(*src); - } - } - Candidates { c: candidates, reverse: candidates_reverse } -} - -struct FindAssignments<'a, 'alloc, 'tcx> { +struct FindAssignments<'a, 'tcx> { body: &'a Body<'tcx>, - candidates: &'alloc mut FxIndexMap>, + candidates: &'a mut FxIndexMap>, borrowed: &'a BitSet, } -impl<'tcx> Visitor<'tcx> for FindAssignments<'_, '_, 'tcx> { +impl<'tcx> Visitor<'tcx> for FindAssignments<'_, 'tcx> { fn visit_statement(&mut self, statement: &Statement<'tcx>, _: Location) { if let StatementKind::Assign(box ( lhs, From 5bbb0d41f1637d3b6a54ded065e807a48c67aec0 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Thu, 29 Aug 2024 00:17:40 -0400 Subject: [PATCH 0241/2194] Stop using ty::GenericPredicates for non-predicates_of queries --- clippy_lints/src/implied_bounds_in_impls.rs | 2 +- clippy_lints/src/methods/type_id_on_box.rs | 3 +-- clippy_lints/src/needless_maybe_sized.rs | 2 +- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/clippy_lints/src/implied_bounds_in_impls.rs b/clippy_lints/src/implied_bounds_in_impls.rs index 67b48878ca513..6794c6cabfeef 100644 --- a/clippy_lints/src/implied_bounds_in_impls.rs +++ b/clippy_lints/src/implied_bounds_in_impls.rs @@ -246,7 +246,7 @@ fn collect_supertrait_bounds<'tcx>(cx: &LateContext<'tcx>, bounds: GenericBounds && let [.., path] = poly_trait.trait_ref.path.segments && poly_trait.bound_generic_params.is_empty() && let Some(trait_def_id) = path.res.opt_def_id() - && let predicates = cx.tcx.explicit_super_predicates_of(trait_def_id).predicates + && let predicates = cx.tcx.explicit_super_predicates_of(trait_def_id).skip_binder() // If the trait has no supertrait, there is no need to collect anything from that bound && !predicates.is_empty() { diff --git a/clippy_lints/src/methods/type_id_on_box.rs b/clippy_lints/src/methods/type_id_on_box.rs index b62ecef0069af..db8cc4595d4df 100644 --- a/clippy_lints/src/methods/type_id_on_box.rs +++ b/clippy_lints/src/methods/type_id_on_box.rs @@ -25,8 +25,7 @@ fn is_subtrait_of_any(cx: &LateContext<'_>, ty: Ty<'_>) -> bool { || cx .tcx .explicit_super_predicates_of(tr.def_id) - .predicates - .iter() + .iter_identity_copied() .any(|(clause, _)| { matches!(clause.kind().skip_binder(), ty::ClauseKind::Trait(super_tr) if cx.tcx.is_diagnostic_item(sym::Any, super_tr.def_id())) diff --git a/clippy_lints/src/needless_maybe_sized.rs b/clippy_lints/src/needless_maybe_sized.rs index a1d8ec3b32ec9..62e41088f3708 100644 --- a/clippy_lints/src/needless_maybe_sized.rs +++ b/clippy_lints/src/needless_maybe_sized.rs @@ -91,7 +91,7 @@ fn path_to_sized_bound(cx: &LateContext<'_>, trait_bound: &PolyTraitRef<'_>) -> return true; } - for &(predicate, _) in cx.tcx.explicit_super_predicates_of(trait_def_id).predicates { + for (predicate, _) in cx.tcx.explicit_super_predicates_of(trait_def_id).iter_identity_copied() { if let ClauseKind::Trait(trait_predicate) = predicate.kind().skip_binder() && trait_predicate.polarity == PredicatePolarity::Positive && !path.contains(&trait_predicate.def_id()) From 00eca77b7230732f0ba9a88b434022177de7da17 Mon Sep 17 00:00:00 2001 From: Lukas Bergdoll Date: Thu, 29 Aug 2024 10:32:59 +0200 Subject: [PATCH 0242/2194] Use simpler branchy swap logic in tiny merge sort Avoids the code duplication issue and results in smaller binary size, which after all is the purpose of the feature. --- .../core/src/slice/sort/shared/smallsort.rs | 5 ++ library/core/src/slice/sort/stable/tiny.rs | 50 +++---------------- 2 files changed, 13 insertions(+), 42 deletions(-) diff --git a/library/core/src/slice/sort/shared/smallsort.rs b/library/core/src/slice/sort/shared/smallsort.rs index 5027962ccb415..aaa9f9f1c7fd1 100644 --- a/library/core/src/slice/sort/shared/smallsort.rs +++ b/library/core/src/slice/sort/shared/smallsort.rs @@ -378,6 +378,11 @@ where /// Swap two values in the slice pointed to by `v_base` at the position `a_pos` and `b_pos` if the /// value at position `b_pos` is less than the one at position `a_pos`. +/// +/// Purposefully not marked `#[inline]`, despite us wanting it to be inlined for integers like +/// types. `is_less` could be a huge function and we want to give the compiler an option to +/// not inline this function. For the same reasons that this function is very perf critical +/// it should be in the same module as the functions that use it. unsafe fn swap_if_less(v_base: *mut T, a_pos: usize, b_pos: usize, is_less: &mut F) where F: FnMut(&T, &T) -> bool, diff --git a/library/core/src/slice/sort/stable/tiny.rs b/library/core/src/slice/sort/stable/tiny.rs index 307011f3ee8c4..071ab8e107fe3 100644 --- a/library/core/src/slice/sort/stable/tiny.rs +++ b/library/core/src/slice/sort/stable/tiny.rs @@ -1,6 +1,6 @@ //! Binary-size optimized mergesort inspired by https://github.com/voultapher/tiny-sort-rs. -use crate::mem::{ManuallyDrop, MaybeUninit}; +use crate::mem::MaybeUninit; use crate::ptr; use crate::slice::sort::stable::merge; @@ -27,49 +27,15 @@ pub fn mergesort bool>( merge::merge(v, scratch, mid, is_less); } else if len == 2 { - // Branchless swap the two elements. This reduces the recursion depth and improves - // perf significantly at a small binary-size cost. Trades ~10% perf boost for integers - // for ~50 bytes in the binary. - // SAFETY: We checked the len, the pointers we create are valid and don't overlap. unsafe { - swap_if_less(v.as_mut_ptr(), 0, 1, is_less); - } - } -} - -/// Swap two values in the slice pointed to by `v_base` at the position `a_pos` and `b_pos` if the -/// value at position `b_pos` is less than the one at position `a_pos`. -unsafe fn swap_if_less(v_base: *mut T, a_pos: usize, b_pos: usize, is_less: &mut F) -where - F: FnMut(&T, &T) -> bool, -{ - // SAFETY: the caller must guarantee that `a` and `b` each added to `v_base` yield valid - // pointers into `v_base`, and are properly aligned, and part of the same allocation. - unsafe { - let v_a = v_base.add(a_pos); - let v_b = v_base.add(b_pos); + let v_base = v.as_mut_ptr(); + let v_a = v_base; + let v_b = v_base.add(1); - // PANIC SAFETY: if is_less panics, no scratch memory was created and the slice should still be - // in a well defined state, without duplicates. - - // Important to only swap if it is more and not if it is equal. is_less should return false for - // equal, so we don't swap. - let should_swap = is_less(&*v_b, &*v_a); - - // This is a branchless version of swap if. - // The equivalent code with a branch would be: - // - // if should_swap { - // ptr::swap(left, right, 1); - // } - - // The goal is to generate cmov instructions here. - let left_swap = if should_swap { v_b } else { v_a }; - let right_swap = if should_swap { v_a } else { v_b }; - - let right_swap_tmp = ManuallyDrop::new(ptr::read(right_swap)); - ptr::copy(left_swap, v_a, 1); - ptr::copy_nonoverlapping(&*right_swap_tmp, v_b, 1); + if is_less(&*v_b, &*v_a) { + ptr::swap_nonoverlapping(v_a, v_b, 1); + } + } } } From a54a7a8a6afb6d67a5a66806068e60f55a0947e6 Mon Sep 17 00:00:00 2001 From: Shoyu Vanilla Date: Wed, 7 Aug 2024 03:16:24 +0900 Subject: [PATCH 0243/2194] feat: Implement object safety --- .../crates/hir-ty/src/chalk_db.rs | 6 +- .../crates/hir-ty/src/consteval/tests.rs | 8 +- .../hir-ty/src/consteval/tests/intrinsics.rs | 2 +- .../rust-analyzer/crates/hir-ty/src/db.rs | 6 +- .../crates/hir-ty/src/generics.rs | 17 + .../rust-analyzer/crates/hir-ty/src/lib.rs | 1 + .../rust-analyzer/crates/hir-ty/src/lower.rs | 18 +- .../crates/hir-ty/src/mir/eval/tests.rs | 2 +- .../crates/hir-ty/src/object_safety.rs | 631 ++++++++++++++++++ .../crates/hir-ty/src/object_safety/tests.rs | 363 ++++++++++ .../crates/hir-ty/src/tests/regression.rs | 2 +- .../crates/hir-ty/src/tests/traits.rs | 62 +- src/tools/rust-analyzer/crates/hir/src/lib.rs | 7 +- .../replace_filter_map_next_with_find_map.rs | 2 +- .../crates/ide/src/hover/render.rs | 74 +- .../crates/ide/src/hover/tests.rs | 24 +- .../crates/ide/src/inlay_hints/adjustment.rs | 4 +- .../crates/intern/src/symbol/symbols.rs | 1 + .../crates/test-utils/src/minicore.rs | 30 +- 19 files changed, 1194 insertions(+), 66 deletions(-) create mode 100644 src/tools/rust-analyzer/crates/hir-ty/src/object_safety.rs create mode 100644 src/tools/rust-analyzer/crates/hir-ty/src/object_safety/tests.rs diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/chalk_db.rs b/src/tools/rust-analyzer/crates/hir-ty/src/chalk_db.rs index a3e4da5d1afd7..e74e3d789883e 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/chalk_db.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/chalk_db.rs @@ -381,9 +381,9 @@ impl chalk_solve::RustIrDatabase for ChalkContext<'_> { TyKind::Error.intern(Interner) } - fn is_object_safe(&self, _trait_id: chalk_ir::TraitId) -> bool { - // FIXME: implement actual object safety - true + fn is_object_safe(&self, trait_id: chalk_ir::TraitId) -> bool { + let trait_ = from_chalk_trait_id(trait_id); + crate::object_safety::object_safety(self.db, trait_).is_none() } fn closure_kind( diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/consteval/tests.rs b/src/tools/rust-analyzer/crates/hir-ty/src/consteval/tests.rs index 86228250c2005..c4cbaaa30175b 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/consteval/tests.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/consteval/tests.rs @@ -2007,7 +2007,7 @@ fn function_traits() { ); check_number( r#" - //- minicore: coerce_unsized, fn + //- minicore: coerce_unsized, fn, dispatch_from_dyn fn add2(x: u8) -> u8 { x + 2 } @@ -2062,7 +2062,7 @@ fn function_traits() { fn dyn_trait() { check_number( r#" - //- minicore: coerce_unsized, index, slice + //- minicore: coerce_unsized, index, slice, dispatch_from_dyn trait Foo { fn foo(&self) -> u8 { 10 } } @@ -2085,7 +2085,7 @@ fn dyn_trait() { ); check_number( r#" - //- minicore: coerce_unsized, index, slice + //- minicore: coerce_unsized, index, slice, dispatch_from_dyn trait Foo { fn foo(&self) -> i32 { 10 } } @@ -2109,7 +2109,7 @@ fn dyn_trait() { ); check_number( r#" - //- minicore: coerce_unsized, index, slice + //- minicore: coerce_unsized, index, slice, dispatch_from_dyn trait A { fn x(&self) -> i32; } diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/consteval/tests/intrinsics.rs b/src/tools/rust-analyzer/crates/hir-ty/src/consteval/tests/intrinsics.rs index 5972b80d1696b..6f294494c01eb 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/consteval/tests/intrinsics.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/consteval/tests/intrinsics.rs @@ -89,7 +89,7 @@ fn size_of_val() { ); check_number( r#" - //- minicore: coerce_unsized, fmt, builtin_impls + //- minicore: coerce_unsized, fmt, builtin_impls, dispatch_from_dyn extern "rust-intrinsic" { pub fn size_of_val(_: *const T) -> usize; } diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/db.rs b/src/tools/rust-analyzer/crates/hir-ty/src/db.rs index 9a1f2158bf753..ebbe8a448cc4f 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/db.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/db.rs @@ -11,7 +11,7 @@ use base_db::{ use hir_def::{ db::DefDatabase, hir::ExprId, layout::TargetDataLayout, AdtId, BlockId, CallableDefId, ConstParamId, DefWithBodyId, EnumVariantId, FunctionId, GeneralConstId, GenericDefId, ImplId, - LifetimeParamId, LocalFieldId, StaticId, TypeAliasId, TypeOrConstParamId, VariantId, + LifetimeParamId, LocalFieldId, StaticId, TraitId, TypeAliasId, TypeOrConstParamId, VariantId, }; use la_arena::ArenaMap; use smallvec::SmallVec; @@ -24,6 +24,7 @@ use crate::{ lower::{GenericDefaults, GenericPredicates}, method_resolution::{InherentImpls, TraitImpls, TyFingerprint}, mir::{BorrowckResult, MirBody, MirLowerError}, + object_safety::ObjectSafetyViolation, Binders, ClosureId, Const, FnDefId, ImplTraitId, ImplTraits, InferenceResult, Interner, PolyFnSig, Substitution, TraitEnvironment, TraitRef, Ty, TyDefId, ValueTyDefId, }; @@ -107,6 +108,9 @@ pub trait HirDatabase: DefDatabase + Upcast { #[salsa::invoke(crate::layout::target_data_layout_query)] fn target_data_layout(&self, krate: CrateId) -> Result, Arc>; + #[salsa::invoke(crate::object_safety::object_safety_of_trait_query)] + fn object_safety_of_trait(&self, trait_: TraitId) -> Option; + #[salsa::invoke(crate::lower::ty_query)] #[salsa::cycle(crate::lower::ty_recover)] fn ty(&self, def: TyDefId) -> Binders; diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/generics.rs b/src/tools/rust-analyzer/crates/hir-ty/src/generics.rs index a96c101a388be..89ca707c2e697 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/generics.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/generics.rs @@ -225,6 +225,23 @@ impl Generics { } } +pub(crate) fn trait_self_param_idx(db: &dyn DefDatabase, def: GenericDefId) -> Option { + match def { + GenericDefId::TraitId(_) | GenericDefId::TraitAliasId(_) => { + let params = db.generic_params(def); + params.trait_self_param().map(|idx| idx.into_raw().into_u32() as usize) + } + GenericDefId::ImplId(_) => None, + _ => { + let parent_def = parent_generic_def(db, def)?; + let parent_params = db.generic_params(parent_def); + let parent_self_idx = parent_params.trait_self_param()?.into_raw().into_u32() as usize; + let self_params = db.generic_params(def); + Some(self_params.len() + parent_self_idx) + } + } +} + fn parent_generic_def(db: &dyn DefDatabase, def: GenericDefId) -> Option { let container = match def { GenericDefId::FunctionId(it) => it.lookup(db).container, diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs b/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs index 46611ae0de926..efd6e51b3704c 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs @@ -40,6 +40,7 @@ pub mod lang_items; pub mod layout; pub mod method_resolution; pub mod mir; +pub mod object_safety; pub mod primitive; pub mod traits; diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/lower.rs b/src/tools/rust-analyzer/crates/hir-ty/src/lower.rs index 370d9ba99cb0c..841e0216ae2b8 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/lower.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/lower.rs @@ -58,7 +58,7 @@ use crate::{ }, db::HirDatabase, error_lifetime, - generics::{generics, Generics}, + generics::{generics, trait_self_param_idx, Generics}, make_binders, mapping::{from_chalk_trait_id, lt_to_placeholder_idx, ToChalk}, static_lifetime, to_assoc_type_id, to_chalk_trait_id, to_placeholder_idx, @@ -1747,21 +1747,7 @@ fn implicitly_sized_clauses<'a, 'subst: 'a>( .lang_item(resolver.krate(), LangItem::Sized) .and_then(|lang_item| lang_item.as_trait().map(to_chalk_trait_id))?; - let get_trait_self_idx = |container: ItemContainerId| { - if matches!(container, ItemContainerId::TraitId(_)) { - let generics = generics(db.upcast(), def); - Some(generics.len_self()) - } else { - None - } - }; - let trait_self_idx = match def { - GenericDefId::TraitId(_) => Some(0), - GenericDefId::FunctionId(it) => get_trait_self_idx(it.lookup(db.upcast()).container), - GenericDefId::ConstId(it) => get_trait_self_idx(it.lookup(db.upcast()).container), - GenericDefId::TypeAliasId(it) => get_trait_self_idx(it.lookup(db.upcast()).container), - _ => None, - }; + let trait_self_idx = trait_self_param_idx(db.upcast(), def); Some( substitution diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/tests.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/tests.rs index 371a5278dc9a5..6825bc4862ac9 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/tests.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/tests.rs @@ -849,7 +849,7 @@ fn main() { fn regression_14966() { check_pass( r#" -//- minicore: fn, copy, coerce_unsized +//- minicore: fn, copy, coerce_unsized, dispatch_from_dyn trait A { fn a(&self) {} } diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/object_safety.rs b/src/tools/rust-analyzer/crates/hir-ty/src/object_safety.rs new file mode 100644 index 0000000000000..f3bbb6b04f973 --- /dev/null +++ b/src/tools/rust-analyzer/crates/hir-ty/src/object_safety.rs @@ -0,0 +1,631 @@ +//! Compute the object-safety of a trait + +use std::ops::ControlFlow; + +use chalk_ir::{ + cast::Cast, + visit::{TypeSuperVisitable, TypeVisitable, TypeVisitor}, + DebruijnIndex, +}; +use chalk_solve::rust_ir::InlineBound; +use hir_def::{ + lang_item::LangItem, AssocItemId, ConstId, FunctionId, GenericDefId, HasModule, TraitId, + TypeAliasId, +}; +use rustc_hash::{FxHashMap, FxHashSet}; +use smallvec::SmallVec; + +use crate::{ + all_super_traits, + db::HirDatabase, + from_assoc_type_id, from_chalk_trait_id, + generics::{generics, trait_self_param_idx}, + lower::callable_item_sig, + to_assoc_type_id, to_chalk_trait_id, + utils::elaborate_clause_supertraits, + AliasEq, AliasTy, Binders, BoundVar, CallableSig, GoalData, ImplTraitId, Interner, OpaqueTyId, + ProjectionTyExt, Solution, Substitution, TraitRef, Ty, TyKind, WhereClause, +}; + +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub enum ObjectSafetyViolation { + SizedSelf, + SelfReferential, + Method(FunctionId, MethodViolationCode), + AssocConst(ConstId), + GAT(TypeAliasId), + // This doesn't exist in rustc, but added for better visualization + HasNonSafeSuperTrait(TraitId), +} + +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub enum MethodViolationCode { + StaticMethod, + ReferencesSelfInput, + ReferencesSelfOutput, + ReferencesImplTraitInTrait, + AsyncFn, + WhereClauseReferencesSelf, + Generic, + UndispatchableReceiver, +} + +pub fn object_safety(db: &dyn HirDatabase, trait_: TraitId) -> Option { + for super_trait in all_super_traits(db.upcast(), trait_).into_iter().skip(1).rev() { + if db.object_safety_of_trait(super_trait).is_some() { + return Some(ObjectSafetyViolation::HasNonSafeSuperTrait(super_trait)); + } + } + + db.object_safety_of_trait(trait_) +} + +pub fn object_safety_with_callback( + db: &dyn HirDatabase, + trait_: TraitId, + cb: &mut F, +) -> ControlFlow<()> +where + F: FnMut(ObjectSafetyViolation) -> ControlFlow<()>, +{ + for super_trait in all_super_traits(db.upcast(), trait_).into_iter().skip(1).rev() { + if db.object_safety_of_trait(super_trait).is_some() { + cb(ObjectSafetyViolation::HasNonSafeSuperTrait(trait_))?; + } + } + + object_safety_of_trait_with_callback(db, trait_, cb) +} + +pub fn object_safety_of_trait_with_callback( + db: &dyn HirDatabase, + trait_: TraitId, + cb: &mut F, +) -> ControlFlow<()> +where + F: FnMut(ObjectSafetyViolation) -> ControlFlow<()>, +{ + // Check whether this has a `Sized` bound + if generics_require_sized_self(db, trait_.into()) { + cb(ObjectSafetyViolation::SizedSelf)?; + } + + // Check if there exist bounds that referencing self + if predicates_reference_self(db, trait_) { + cb(ObjectSafetyViolation::SelfReferential)?; + } + if bounds_reference_self(db, trait_) { + cb(ObjectSafetyViolation::SelfReferential)?; + } + + // rustc checks for non-lifetime binders here, but we don't support HRTB yet + + let trait_data = db.trait_data(trait_); + for (_, assoc_item) in &trait_data.items { + object_safety_violation_for_assoc_item(db, trait_, *assoc_item, cb)?; + } + + ControlFlow::Continue(()) +} + +pub fn object_safety_of_trait_query( + db: &dyn HirDatabase, + trait_: TraitId, +) -> Option { + let mut res = None; + object_safety_of_trait_with_callback(db, trait_, &mut |osv| { + res = Some(osv); + ControlFlow::Break(()) + }); + + res +} + +fn generics_require_sized_self(db: &dyn HirDatabase, def: GenericDefId) -> bool { + let krate = def.module(db.upcast()).krate(); + let Some(sized) = db.lang_item(krate, LangItem::Sized).and_then(|l| l.as_trait()) else { + return false; + }; + + let Some(trait_self_param_idx) = trait_self_param_idx(db.upcast(), def) else { + return false; + }; + + let predicates = &*db.generic_predicates(def); + let predicates = predicates.iter().map(|p| p.skip_binders().skip_binders().clone()); + elaborate_clause_supertraits(db, predicates).any(|pred| match pred { + WhereClause::Implemented(trait_ref) => { + if from_chalk_trait_id(trait_ref.trait_id) == sized { + if let TyKind::BoundVar(it) = + *trait_ref.self_type_parameter(Interner).kind(Interner) + { + // Since `generic_predicates` is `Binder>`, the `DebrujinIndex` of + // self-parameter is `1` + return it + .index_if_bound_at(DebruijnIndex::ONE) + .is_some_and(|idx| idx == trait_self_param_idx); + } + } + false + } + _ => false, + }) +} + +// rustc gathers all the spans that references `Self` for error rendering, +// but we don't have good way to render such locations. +// So, just return single boolean value for existence of such `Self` reference +fn predicates_reference_self(db: &dyn HirDatabase, trait_: TraitId) -> bool { + db.generic_predicates(trait_.into()) + .iter() + .any(|pred| predicate_references_self(db, trait_, pred, AllowSelfProjection::No)) +} + +// Same as the above, `predicates_reference_self` +fn bounds_reference_self(db: &dyn HirDatabase, trait_: TraitId) -> bool { + let trait_data = db.trait_data(trait_); + trait_data + .items + .iter() + .filter_map(|(_, it)| match *it { + AssocItemId::TypeAliasId(id) => { + let assoc_ty_id = to_assoc_type_id(id); + let assoc_ty_data = db.associated_ty_data(assoc_ty_id); + Some(assoc_ty_data) + } + _ => None, + }) + .any(|assoc_ty_data| { + assoc_ty_data.binders.skip_binders().bounds.iter().any(|bound| { + let def = from_assoc_type_id(assoc_ty_data.id).into(); + match bound.skip_binders() { + InlineBound::TraitBound(it) => it.args_no_self.iter().any(|arg| { + contains_illegal_self_type_reference( + db, + def, + trait_, + arg, + DebruijnIndex::ONE, + AllowSelfProjection::Yes, + ) + }), + InlineBound::AliasEqBound(it) => it.parameters.iter().any(|arg| { + contains_illegal_self_type_reference( + db, + def, + trait_, + arg, + DebruijnIndex::ONE, + AllowSelfProjection::Yes, + ) + }), + } + }) + }) +} + +#[derive(Clone, Copy)] +enum AllowSelfProjection { + Yes, + No, +} + +fn predicate_references_self( + db: &dyn HirDatabase, + trait_: TraitId, + predicate: &Binders>, + allow_self_projection: AllowSelfProjection, +) -> bool { + match predicate.skip_binders().skip_binders() { + WhereClause::Implemented(trait_ref) => { + trait_ref.substitution.iter(Interner).skip(1).any(|arg| { + contains_illegal_self_type_reference( + db, + trait_.into(), + trait_, + arg, + DebruijnIndex::ONE, + allow_self_projection, + ) + }) + } + WhereClause::AliasEq(AliasEq { alias: AliasTy::Projection(proj), .. }) => { + proj.substitution.iter(Interner).skip(1).any(|arg| { + contains_illegal_self_type_reference( + db, + trait_.into(), + trait_, + arg, + DebruijnIndex::ONE, + allow_self_projection, + ) + }) + } + _ => false, + } +} + +fn contains_illegal_self_type_reference>( + db: &dyn HirDatabase, + def: GenericDefId, + trait_: TraitId, + t: &T, + outer_binder: DebruijnIndex, + allow_self_projection: AllowSelfProjection, +) -> bool { + let Some(trait_self_param_idx) = trait_self_param_idx(db.upcast(), def) else { + return false; + }; + struct IllegalSelfTypeVisitor<'a> { + db: &'a dyn HirDatabase, + trait_: TraitId, + super_traits: Option>, + trait_self_param_idx: usize, + allow_self_projection: AllowSelfProjection, + } + impl<'a> TypeVisitor for IllegalSelfTypeVisitor<'a> { + type BreakTy = (); + + fn as_dyn(&mut self) -> &mut dyn TypeVisitor { + self + } + + fn interner(&self) -> Interner { + Interner + } + + fn visit_ty(&mut self, ty: &Ty, outer_binder: DebruijnIndex) -> ControlFlow { + match ty.kind(Interner) { + TyKind::BoundVar(BoundVar { debruijn, index }) => { + if *debruijn == outer_binder && *index == self.trait_self_param_idx { + ControlFlow::Break(()) + } else { + ty.super_visit_with(self.as_dyn(), outer_binder) + } + } + TyKind::Alias(AliasTy::Projection(proj)) => match self.allow_self_projection { + AllowSelfProjection::Yes => { + let trait_ = proj.trait_(self.db); + if self.super_traits.is_none() { + self.super_traits = + Some(all_super_traits(self.db.upcast(), self.trait_)); + } + if self.super_traits.as_ref().is_some_and(|s| s.contains(&trait_)) { + ControlFlow::Continue(()) + } else { + ty.super_visit_with(self.as_dyn(), outer_binder) + } + } + AllowSelfProjection::No => ty.super_visit_with(self.as_dyn(), outer_binder), + }, + _ => ty.super_visit_with(self.as_dyn(), outer_binder), + } + } + + fn visit_const( + &mut self, + constant: &chalk_ir::Const, + outer_binder: DebruijnIndex, + ) -> std::ops::ControlFlow { + constant.data(Interner).ty.super_visit_with(self.as_dyn(), outer_binder) + } + } + + let mut visitor = IllegalSelfTypeVisitor { + db, + trait_, + super_traits: None, + trait_self_param_idx, + allow_self_projection, + }; + t.visit_with(visitor.as_dyn(), outer_binder).is_break() +} + +fn object_safety_violation_for_assoc_item( + db: &dyn HirDatabase, + trait_: TraitId, + item: AssocItemId, + cb: &mut F, +) -> ControlFlow<()> +where + F: FnMut(ObjectSafetyViolation) -> ControlFlow<()>, +{ + // Any item that has a `Self : Sized` requisite is otherwise + // exempt from the regulations. + if generics_require_sized_self(db, item.into()) { + return ControlFlow::Continue(()); + } + + match item { + AssocItemId::ConstId(it) => cb(ObjectSafetyViolation::AssocConst(it)), + AssocItemId::FunctionId(it) => { + virtual_call_violations_for_method(db, trait_, it, &mut |mvc| { + cb(ObjectSafetyViolation::Method(it, mvc)) + }) + } + AssocItemId::TypeAliasId(it) => { + let def_map = db.crate_def_map(trait_.krate(db.upcast())); + if def_map.is_unstable_feature_enabled(&intern::sym::generic_associated_type_extended) { + ControlFlow::Continue(()) + } else { + let generic_params = db.generic_params(item.into()); + if generic_params.len_type_or_consts() > 0 { + cb(ObjectSafetyViolation::GAT(it)) + } else { + ControlFlow::Continue(()) + } + } + } + } +} + +fn virtual_call_violations_for_method( + db: &dyn HirDatabase, + trait_: TraitId, + func: FunctionId, + cb: &mut F, +) -> ControlFlow<()> +where + F: FnMut(MethodViolationCode) -> ControlFlow<()>, +{ + let func_data = db.function_data(func); + if !func_data.has_self_param() { + cb(MethodViolationCode::StaticMethod)?; + } + + if func_data.is_async() { + cb(MethodViolationCode::AsyncFn)?; + } + + let sig = callable_item_sig(db, func.into()); + if sig.skip_binders().params().iter().skip(1).any(|ty| { + contains_illegal_self_type_reference( + db, + func.into(), + trait_, + ty, + DebruijnIndex::INNERMOST, + AllowSelfProjection::Yes, + ) + }) { + cb(MethodViolationCode::ReferencesSelfInput)?; + } + + if contains_illegal_self_type_reference( + db, + func.into(), + trait_, + sig.skip_binders().ret(), + DebruijnIndex::INNERMOST, + AllowSelfProjection::Yes, + ) { + cb(MethodViolationCode::ReferencesSelfOutput)?; + } + + if !func_data.is_async() { + if let Some(mvc) = contains_illegal_impl_trait_in_trait(db, &sig) { + cb(mvc)?; + } + } + + let generic_params = db.generic_params(func.into()); + if generic_params.len_type_or_consts() > 0 { + cb(MethodViolationCode::Generic)?; + } + + if func_data.has_self_param() && !receiver_is_dispatchable(db, trait_, func, &sig) { + cb(MethodViolationCode::UndispatchableReceiver)?; + } + + let predicates = &*db.generic_predicates(func.into()); + let mut parent_predicates = (*db.generic_predicates(trait_.into())) + .iter() + .map(|b| b.skip_binders().skip_binders().clone()) + .fold(FxHashMap::default(), |mut acc, item| { + acc.entry(item) + .and_modify(|cnt| { + *cnt += 1; + }) + .or_insert(1); + acc + }); + let trait_self_idx = trait_self_param_idx(db.upcast(), func.into()); + for pred in predicates { + let pred = pred.skip_binders().skip_binders(); + + // Skip predicates from parent, i.e. the trait that contains this method + if let Some(cnt) = parent_predicates.get_mut(pred) { + if *cnt > 0 { + *cnt -= 1; + continue; + } + } + + if matches!(pred, WhereClause::TypeOutlives(_)) { + continue; + } + + // Allow `impl AutoTrait` predicates + if let WhereClause::Implemented(TraitRef { trait_id, substitution }) = pred { + let trait_data = db.trait_data(from_chalk_trait_id(*trait_id)); + if trait_data.is_auto + && substitution + .as_slice(Interner) + .first() + .and_then(|arg| arg.ty(Interner)) + .and_then(|ty| ty.bound_var(Interner)) + .is_some_and(|b| { + b.debruijn == DebruijnIndex::ONE && Some(b.index) == trait_self_idx + }) + { + continue; + } + } + + if contains_illegal_self_type_reference( + db, + func.into(), + trait_, + pred, + DebruijnIndex::ONE, + AllowSelfProjection::Yes, + ) { + cb(MethodViolationCode::WhereClauseReferencesSelf)?; + break; + } + } + + ControlFlow::Continue(()) +} + +fn receiver_is_dispatchable( + db: &dyn HirDatabase, + trait_: TraitId, + func: FunctionId, + sig: &Binders, +) -> bool { + let Some(trait_self_idx) = trait_self_param_idx(db.upcast(), func.into()) else { + return false; + }; + + // `self: Self` can't be dispatched on, but this is already considered object safe. + // See rustc's comment on https://github.com/rust-lang/rust/blob/3f121b9461cce02a703a0e7e450568849dfaa074/compiler/rustc_trait_selection/src/traits/object_safety.rs#L433-L437 + if sig + .skip_binders() + .params() + .first() + .and_then(|receiver| receiver.bound_var(Interner)) + .is_some_and(|b| { + b == BoundVar { debruijn: DebruijnIndex::INNERMOST, index: trait_self_idx } + }) + { + return true; + } + + let placeholder_subst = generics(db.upcast(), func.into()).placeholder_subst(db); + + let substituted_sig = sig.clone().substitute(Interner, &placeholder_subst); + let Some(receiver_ty) = substituted_sig.params().first() else { + return false; + }; + + let krate = func.module(db.upcast()).krate(); + let traits = ( + db.lang_item(krate, LangItem::Unsize).and_then(|it| it.as_trait()), + db.lang_item(krate, LangItem::DispatchFromDyn).and_then(|it| it.as_trait()), + ); + let (Some(unsize_did), Some(dispatch_from_dyn_did)) = traits else { + return false; + }; + + // Type `U` + let unsized_self_ty = + TyKind::Scalar(chalk_ir::Scalar::Uint(chalk_ir::UintTy::U32)).intern(Interner); + // `Receiver[Self => U]` + let Some(unsized_receiver_ty) = receiver_for_self_ty(db, func, unsized_self_ty.clone()) else { + return false; + }; + + let self_ty = placeholder_subst.as_slice(Interner)[trait_self_idx].assert_ty_ref(Interner); + let unsized_predicate = WhereClause::Implemented(TraitRef { + trait_id: to_chalk_trait_id(unsize_did), + substitution: Substitution::from_iter(Interner, [self_ty.clone(), unsized_self_ty.clone()]), + }); + let trait_predicate = WhereClause::Implemented(TraitRef { + trait_id: to_chalk_trait_id(trait_), + substitution: Substitution::from_iter( + Interner, + std::iter::once(unsized_self_ty.clone().cast(Interner)) + .chain(placeholder_subst.iter(Interner).skip(1).cloned()), + ), + }); + + let generic_predicates = &*db.generic_predicates(func.into()); + + let clauses = std::iter::once(unsized_predicate) + .chain(std::iter::once(trait_predicate)) + .chain(generic_predicates.iter().map(|pred| { + pred.clone().substitute(Interner, &placeholder_subst).into_value_and_skipped_binders().0 + })) + .map(|pred| { + pred.cast::>(Interner).into_from_env_clause(Interner) + }); + let env = chalk_ir::Environment::new(Interner).add_clauses(Interner, clauses); + + let obligation = WhereClause::Implemented(TraitRef { + trait_id: to_chalk_trait_id(dispatch_from_dyn_did), + substitution: Substitution::from_iter(Interner, [receiver_ty.clone(), unsized_receiver_ty]), + }); + let goal = GoalData::DomainGoal(chalk_ir::DomainGoal::Holds(obligation)).intern(Interner); + + let in_env = chalk_ir::InEnvironment::new(&env, goal); + + let mut table = chalk_solve::infer::InferenceTable::::new(); + let canonicalized = table.canonicalize(Interner, in_env); + let solution = db.trait_solve(krate, None, canonicalized.quantified); + + matches!(solution, Some(Solution::Unique(_))) +} + +fn receiver_for_self_ty(db: &dyn HirDatabase, func: FunctionId, ty: Ty) -> Option { + let generics = generics(db.upcast(), func.into()); + let trait_self_idx = trait_self_param_idx(db.upcast(), func.into())?; + let subst = generics.placeholder_subst(db); + let subst = Substitution::from_iter( + Interner, + subst.iter(Interner).enumerate().map(|(idx, arg)| { + if idx == trait_self_idx { + ty.clone().cast(Interner) + } else { + arg.clone() + } + }), + ); + let sig = callable_item_sig(db, func.into()); + let sig = sig.substitute(Interner, &subst); + sig.params_and_return.first().cloned() +} + +fn contains_illegal_impl_trait_in_trait( + db: &dyn HirDatabase, + sig: &Binders, +) -> Option { + struct OpaqueTypeCollector(FxHashSet); + + impl TypeVisitor for OpaqueTypeCollector { + type BreakTy = (); + + fn as_dyn(&mut self) -> &mut dyn TypeVisitor { + self + } + + fn interner(&self) -> Interner { + Interner + } + + fn visit_ty(&mut self, ty: &Ty, outer_binder: DebruijnIndex) -> ControlFlow { + if let TyKind::OpaqueType(opaque_ty_id, _) = ty.kind(Interner) { + self.0.insert(*opaque_ty_id); + } + ty.super_visit_with(self.as_dyn(), outer_binder) + } + } + + let ret = sig.skip_binders().ret(); + let mut visitor = OpaqueTypeCollector(FxHashSet::default()); + ret.visit_with(visitor.as_dyn(), DebruijnIndex::INNERMOST); + + // Since we haven't implemented RPITIT in proper way like rustc yet, + // just check whether `ret` contains RPIT for now + for opaque_ty in visitor.0 { + let impl_trait_id = db.lookup_intern_impl_trait_id(opaque_ty.into()); + if matches!(impl_trait_id, ImplTraitId::ReturnTypeImplTrait(..)) { + return Some(MethodViolationCode::ReferencesImplTraitInTrait); + } + } + + None +} + +#[cfg(test)] +mod tests; diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/object_safety/tests.rs b/src/tools/rust-analyzer/crates/hir-ty/src/object_safety/tests.rs new file mode 100644 index 0000000000000..585313e5b9bf8 --- /dev/null +++ b/src/tools/rust-analyzer/crates/hir-ty/src/object_safety/tests.rs @@ -0,0 +1,363 @@ +use std::ops::ControlFlow; + +use hir_def::db::DefDatabase; +use rustc_hash::{FxHashMap, FxHashSet}; +use syntax::ToSmolStr; +use test_fixture::WithFixture; + +use crate::{object_safety::object_safety_with_callback, test_db::TestDB}; + +use super::{ + MethodViolationCode::{self, *}, + ObjectSafetyViolation, +}; + +use ObjectSafetyViolationKind::*; + +#[allow(clippy::upper_case_acronyms)] +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +enum ObjectSafetyViolationKind { + SizedSelf, + SelfReferential, + Method(MethodViolationCode), + AssocConst, + GAT, + HasNonSafeSuperTrait, +} + +fn check_object_safety<'a>( + ra_fixture: &str, + expected: impl IntoIterator)>, +) { + let mut expected: FxHashMap<_, _> = + expected.into_iter().map(|(id, osvs)| (id, FxHashSet::from_iter(osvs))).collect(); + let (db, file_ids) = TestDB::with_many_files(ra_fixture); + for (trait_id, name) in file_ids.into_iter().flat_map(|file_id| { + let module_id = db.module_for_file(file_id); + let def_map = module_id.def_map(&db); + let scope = &def_map[module_id.local_id].scope; + scope + .declarations() + .filter_map(|def| { + if let hir_def::ModuleDefId::TraitId(trait_id) = def { + let name = + db.trait_data(trait_id).name.display_no_db(file_id.edition()).to_smolstr(); + Some((trait_id, name)) + } else { + None + } + }) + .collect::>() + }) { + let Some(expected) = expected.remove(name.as_str()) else { + continue; + }; + let mut osvs = FxHashSet::default(); + object_safety_with_callback(&db, trait_id, &mut |osv| { + osvs.insert(match osv { + ObjectSafetyViolation::SizedSelf => SizedSelf, + ObjectSafetyViolation::SelfReferential => SelfReferential, + ObjectSafetyViolation::Method(_, mvc) => Method(mvc), + ObjectSafetyViolation::AssocConst(_) => AssocConst, + ObjectSafetyViolation::GAT(_) => GAT, + ObjectSafetyViolation::HasNonSafeSuperTrait(_) => HasNonSafeSuperTrait, + }); + ControlFlow::Continue(()) + }); + assert_eq!(osvs, expected, "Object safety violations for `{name}` do not match;"); + } + + let remains: Vec<_> = expected.keys().collect(); + assert!(remains.is_empty(), "Following traits do not exist in the test fixture; {remains:?}"); +} + +#[test] +fn item_bounds_can_reference_self() { + check_object_safety( + r#" +//- minicore: eq +pub trait Foo { + type X: PartialEq; + type Y: PartialEq; + type Z: PartialEq; +} +"#, + [("Foo", vec![])], + ); +} + +#[test] +fn associated_consts() { + check_object_safety( + r#" +trait Bar { + const X: usize; +} +"#, + [("Bar", vec![AssocConst])], + ); +} + +#[test] +fn bounds_reference_self() { + check_object_safety( + r#" +//- minicore: eq +trait X { + type U: PartialEq; +} +"#, + [("X", vec![SelfReferential])], + ); +} + +#[test] +fn by_value_self() { + check_object_safety( + r#" +//- minicore: dispatch_from_dyn +trait Bar { + fn bar(self); +} + +trait Baz { + fn baz(self: Self); +} + +trait Quux { + // Legal because of the where clause: + fn baz(self: Self) where Self : Sized; +} +"#, + [("Bar", vec![]), ("Baz", vec![]), ("Quux", vec![])], + ); +} + +#[test] +fn generic_methods() { + check_object_safety( + r#" +//- minicore: dispatch_from_dyn +trait Bar { + fn bar(&self, t: T); +} + +trait Quux { + fn bar(&self, t: T) + where Self : Sized; +} + +trait Qax { + fn bar<'a>(&self, t: &'a ()); +} +"#, + [("Bar", vec![Method(Generic)]), ("Quux", vec![]), ("Qax", vec![])], + ); +} + +#[test] +fn mentions_self() { + check_object_safety( + r#" +//- minicore: dispatch_from_dyn +trait Bar { + fn bar(&self, x: &Self); +} + +trait Baz { + fn baz(&self) -> Self; +} + +trait Quux { + fn quux(&self, s: &Self) -> Self where Self : Sized; +} +"#, + [ + ("Bar", vec![Method(ReferencesSelfInput)]), + ("Baz", vec![Method(ReferencesSelfOutput)]), + ("Quux", vec![]), + ], + ); +} + +#[test] +fn no_static() { + check_object_safety( + r#" +//- minicore: dispatch_from_dyn +trait Foo { + fn foo() {} +} +"#, + [("Foo", vec![Method(StaticMethod)])], + ); +} + +#[test] +fn sized_self() { + check_object_safety( + r#" +//- minicore: dispatch_from_dyn +trait Bar: Sized { + fn bar(&self, t: T); +} +"#, + [("Bar", vec![SizedSelf])], + ); + + check_object_safety( + r#" +//- minicore: dispatch_from_dyn +trait Bar + where Self : Sized +{ + fn bar(&self, t: T); +} +"#, + [("Bar", vec![SizedSelf])], + ); +} + +#[test] +fn supertrait_gat() { + check_object_safety( + r#" +//- minicore: dispatch_from_dyn +trait GatTrait { + type Gat; +} + +trait SuperTrait: GatTrait {} +"#, + [("GatTrait", vec![GAT]), ("SuperTrait", vec![HasNonSafeSuperTrait])], + ); +} + +#[test] +fn supertrait_mentions_self() { + check_object_safety( + r#" +//- minicore: dispatch_from_dyn +trait Bar { + fn bar(&self, x: &T); +} + +trait Baz : Bar { +} +"#, + [("Bar", vec![]), ("Baz", vec![SizedSelf, SelfReferential])], + ); +} + +#[test] +fn rustc_issue_19538() { + check_object_safety( + r#" +//- minicore: dispatch_from_dyn +trait Foo { + fn foo(&self, val: T); +} + +trait Bar: Foo {} +"#, + [("Foo", vec![Method(Generic)]), ("Bar", vec![HasNonSafeSuperTrait])], + ); +} + +#[test] +fn rustc_issue_22040() { + check_object_safety( + r#" +//- minicore: fmt, eq, dispatch_from_dyn +use core::fmt::Debug; + +trait Expr: Debug + PartialEq { + fn print_element_count(&self); +} +"#, + [("Expr", vec![SelfReferential])], + ); +} + +#[test] +fn rustc_issue_102762() { + check_object_safety( + r#" +//- minicore: future, send, sync, dispatch_from_dyn, deref +use core::pin::Pin; + +struct Box {} +impl core::ops::Deref for Box { + type Target = T; + + fn deref(&self) -> &Self::Target { + loop {} + } +} +impl, U: ?Sized> DispatchFromDyn> for Box {} + +struct Vec {} + +pub trait Fetcher: Send + Sync { + fn get<'a>(self: &'a Box) -> Pin> + 'a>> + where + Self: Sync, + { + loop {} + } +} +"#, + [("Fetcher", vec![Method(UndispatchableReceiver)])], + ); +} + +#[test] +fn rustc_issue_102933() { + check_object_safety( + r#" +//- minicore: future, dispatch_from_dyn, deref +use core::future::Future; + +struct Box {} +impl core::ops::Deref for Box { + type Target = T; + + fn deref(&self) -> &Self::Target { + loop {} + } +} +impl, U: ?Sized> DispatchFromDyn> for Box {} + +pub trait Service { + type Response; + type Future: Future; +} + +pub trait A1: Service {} + +pub trait A2: Service>> + A1 { + fn foo(&self) {} +} + +pub trait B1: Service>> {} + +pub trait B2: Service + B1 { + fn foo(&self) {} +} + "#, + [("A2", vec![]), ("B2", vec![])], + ); +} + +#[test] +fn rustc_issue_106247() { + check_object_safety( + r#" +//- minicore: sync, dispatch_from_dyn +pub trait Trait { + fn method(&self) where Self: Sync; +} +"#, + [("Trait", vec![])], + ); +} diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/tests/regression.rs b/src/tools/rust-analyzer/crates/hir-ty/src/tests/regression.rs index 17fbe4db31795..98f30f0f6f749 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/tests/regression.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/tests/regression.rs @@ -1065,7 +1065,7 @@ fn test() { fn bare_dyn_trait_binders_9639() { check_no_mismatches( r#" -//- minicore: fn, coerce_unsized +//- minicore: fn, coerce_unsized, dispatch_from_dyn fn infix_parse(_state: S, _level_code: &Fn(S)) -> T { loop {} } diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/tests/traits.rs b/src/tools/rust-analyzer/crates/hir-ty/src/tests/traits.rs index a98cff2a08b26..0b2d6bdd2593f 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/tests/traits.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/tests/traits.rs @@ -1448,14 +1448,20 @@ fn foo() -> Foo> { fn dyn_trait() { check_infer( r#" -//- minicore: sized +//- minicore: deref, dispatch_from_dyn trait Trait { fn foo(&self) -> T; fn foo2(&self) -> i64; } -fn bar() -> dyn Trait {} -fn test(x: dyn Trait, y: &dyn Trait) { +struct Box {} +impl core::ops::Deref for Box { + type Target = T; +} + +fn bar() -> Box> {} + +fn test(x: Box>, y: &dyn Trait) { x; y; let z = bar(); @@ -1469,27 +1475,27 @@ fn test(x: dyn Trait, y: &dyn Trait) { expect![[r#" 29..33 'self': &'? Self 54..58 'self': &'? Self - 97..99 '{}': dyn Trait - 109..110 'x': dyn Trait - 128..129 'y': &'? dyn Trait - 148..265 '{ ...2(); }': () - 154..155 'x': dyn Trait - 161..162 'y': &'? dyn Trait - 172..173 'z': dyn Trait - 176..179 'bar': fn bar() -> dyn Trait - 176..181 'bar()': dyn Trait - 187..188 'x': dyn Trait - 187..194 'x.foo()': u64 - 200..201 'y': &'? dyn Trait - 200..207 'y.foo()': u64 - 213..214 'z': dyn Trait - 213..220 'z.foo()': u64 - 226..227 'x': dyn Trait - 226..234 'x.foo2()': i64 - 240..241 'y': &'? dyn Trait - 240..248 'y.foo2()': i64 - 254..255 'z': dyn Trait - 254..262 'z.foo2()': i64 + 198..200 '{}': Box> + 210..211 'x': Box> + 234..235 'y': &'? dyn Trait + 254..371 '{ ...2(); }': () + 260..261 'x': Box> + 267..268 'y': &'? dyn Trait + 278..279 'z': Box> + 282..285 'bar': fn bar() -> Box> + 282..287 'bar()': Box> + 293..294 'x': Box> + 293..300 'x.foo()': u64 + 306..307 'y': &'? dyn Trait + 306..313 'y.foo()': u64 + 319..320 'z': Box> + 319..326 'z.foo()': u64 + 332..333 'x': Box> + 332..340 'x.foo2()': i64 + 346..347 'y': &'? dyn Trait + 346..354 'y.foo2()': i64 + 360..361 'z': Box> + 360..368 'z.foo2()': i64 "#]], ); } @@ -1534,7 +1540,7 @@ fn test(s: S) { fn dyn_trait_bare() { check_infer( r#" -//- minicore: sized +//- minicore: sized, dispatch_from_dyn trait Trait { fn foo(&self) -> u64; } @@ -1570,7 +1576,7 @@ fn test(x: Trait, y: &Trait) -> u64 { check_infer_with_mismatches( r#" -//- minicore: fn, coerce_unsized +//- minicore: fn, coerce_unsized, dispatch_from_dyn struct S; impl S { fn foo(&self) {} @@ -3106,7 +3112,7 @@ fn dyn_fn_param_informs_call_site_closure_signature() { cov_mark::check!(dyn_fn_param_informs_call_site_closure_signature); check_types( r#" -//- minicore: fn, coerce_unsized +//- minicore: fn, coerce_unsized, dispatch_from_dyn struct S; impl S { fn inherent(&self) -> u8 { 0 } @@ -3151,7 +3157,7 @@ fn infer_box_fn_arg() { // The type mismatch is because we don't define Unsize and CoerceUnsized check_infer_with_mismatches( r#" -//- minicore: fn, deref, option +//- minicore: fn, deref, option, dispatch_from_dyn #[lang = "owned_box"] pub struct Box { inner: *mut T, diff --git a/src/tools/rust-analyzer/crates/hir/src/lib.rs b/src/tools/rust-analyzer/crates/hir/src/lib.rs index 2ff5f0d538af0..6b0cc44d769ca 100644 --- a/src/tools/rust-analyzer/crates/hir/src/lib.rs +++ b/src/tools/rust-analyzer/crates/hir/src/lib.rs @@ -66,7 +66,7 @@ use hir_ty::{ diagnostics::BodyValidationDiagnostic, error_lifetime, known_const_to_ast, layout::{Layout as TyLayout, RustcEnumVariantIdx, RustcFieldIdx, TagEncoding}, - method_resolution::{self}, + method_resolution, mir::{interpret_mir, MutBorrowKind}, primitive::UintTy, traits::FnTrait, @@ -144,6 +144,7 @@ pub use { display::{ClosureStyle, HirDisplay, HirDisplayError, HirWrite}, layout::LayoutError, mir::{MirEvalError, MirLowerError}, + object_safety::{MethodViolationCode, ObjectSafetyViolation}, FnAbi, PointerCast, Safety, }, // FIXME: Properly encapsulate mir @@ -2640,6 +2641,10 @@ impl Trait { .count() } + pub fn object_safety(&self, db: &dyn HirDatabase) -> Option { + hir_ty::object_safety::object_safety(db, self.id) + } + fn all_macro_calls(&self, db: &dyn HirDatabase) -> Box<[(AstId, MacroCallId)]> { db.trait_data(self.id) .macro_calls diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/replace_filter_map_next_with_find_map.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/replace_filter_map_next_with_find_map.rs index 87932bf989f04..18647206236c9 100644 --- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/replace_filter_map_next_with_find_map.rs +++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/replace_filter_map_next_with_find_map.rs @@ -84,7 +84,7 @@ fn foo() { fn replace_filter_map_next_dont_work_for_not_sized_issues_16596() { check_diagnostics( r#" -//- minicore: iterators +//- minicore: iterators, dispatch_from_dyn fn foo() { let mut j = [0].into_iter(); let i: &mut dyn Iterator = &mut j; diff --git a/src/tools/rust-analyzer/crates/ide/src/hover/render.rs b/src/tools/rust-analyzer/crates/ide/src/hover/render.rs index 3e41b42be44b1..ead2d45847d0d 100644 --- a/src/tools/rust-analyzer/crates/ide/src/hover/render.rs +++ b/src/tools/rust-analyzer/crates/ide/src/hover/render.rs @@ -4,7 +4,8 @@ use std::{mem, ops::Not}; use either::Either; use hir::{ Adt, AsAssocItem, AsExternAssocItem, CaptureKind, HasCrate, HasSource, HirDisplay, Layout, - LayoutError, Name, Semantics, Trait, Type, TypeInfo, + LayoutError, MethodViolationCode, Name, ObjectSafetyViolation, Semantics, Trait, Type, + TypeInfo, }; use ide_db::{ base_db::SourceDatabase, @@ -526,6 +527,14 @@ pub(super) fn definition( _ => None, }; + let object_safety_info = if let Definition::Trait(it) = def { + let mut object_safety_info = String::new(); + render_object_safety(db, &mut object_safety_info, it.object_safety(db)); + Some(object_safety_info) + } else { + None + }; + let mut desc = String::new(); if let Some(notable_traits) = render_notable_trait_comment(db, notable_traits, edition) { desc.push_str(¬able_traits); @@ -535,6 +544,10 @@ pub(super) fn definition( desc.push_str(&layout_info); desc.push('\n'); } + if let Some(object_safety_info) = object_safety_info { + desc.push_str(&object_safety_info); + desc.push('\n'); + } desc.push_str(&label); if let Some(value) = value { desc.push_str(" = "); @@ -964,3 +977,62 @@ fn keyword_hints( _ => KeywordHint::new(token.text().to_owned(), format!("{}_keyword", token.text())), } } + +fn render_object_safety( + db: &RootDatabase, + buf: &mut String, + safety: Option, +) { + let Some(osv) = safety else { + buf.push_str("// Object Safety: Yes"); + return; + }; + buf.push_str("// Object Safety: No\n// - Reason: "); + match osv { + ObjectSafetyViolation::SizedSelf => { + buf.push_str("has a `Self: Sized` bound"); + } + ObjectSafetyViolation::SelfReferential => { + buf.push_str("has a bound that references `Self`"); + } + ObjectSafetyViolation::Method(func, mvc) => { + let name = hir::Function::from(func).name(db); + format_to!( + buf, + "has a method `{}` that is non dispatchable because of:\n// - ", + name.as_str() + ); + let desc = match mvc { + MethodViolationCode::StaticMethod => "missing a receiver", + MethodViolationCode::ReferencesSelfInput => "a parameter references `Self`", + MethodViolationCode::ReferencesSelfOutput => "the return type references `Self`", + MethodViolationCode::ReferencesImplTraitInTrait => { + "the return type contains `impl Trait`" + } + MethodViolationCode::AsyncFn => "being async", + MethodViolationCode::WhereClauseReferencesSelf => { + "a where clause references `Self`" + } + MethodViolationCode::Generic => "a non-lifetime generic parameter", + MethodViolationCode::UndispatchableReceiver => "a non-dispatchable receiver type", + }; + buf.push_str(desc); + } + ObjectSafetyViolation::AssocConst(const_) => { + let name = hir::Const::from(const_).name(db); + if let Some(name) = name { + format_to!(buf, "has an associated constant `{}`", name.as_str()); + } else { + buf.push_str("has an associated constant"); + } + } + ObjectSafetyViolation::GAT(alias) => { + let name = hir::TypeAlias::from(alias).name(db); + format_to!(buf, "has a generic associated type `{}`", name.as_str()); + } + ObjectSafetyViolation::HasNonSafeSuperTrait(super_trait) => { + let name = hir::Trait::from(super_trait).name(db); + format_to!(buf, "has a object unsafe supertrait `{}`", name.as_str()); + } + } +} diff --git a/src/tools/rust-analyzer/crates/ide/src/hover/tests.rs b/src/tools/rust-analyzer/crates/ide/src/hover/tests.rs index 9585bdbe4c545..f2f83d538ccb9 100644 --- a/src/tools/rust-analyzer/crates/ide/src/hover/tests.rs +++ b/src/tools/rust-analyzer/crates/ide/src/hover/tests.rs @@ -5442,7 +5442,7 @@ const FOO$0: Option<&i32> = Some(2).as_ref(); fn hover_const_eval_dyn_trait() { check( r#" -//- minicore: fmt, coerce_unsized, builtin_impls +//- minicore: fmt, coerce_unsized, builtin_impls, dispatch_from_dyn use core::fmt::Debug; const FOO$0: &dyn Debug = &2i32; @@ -7107,6 +7107,7 @@ impl T$0 for () {} ``` ```rust + // Object Safety: Yes trait T {} ``` "#]], @@ -7126,6 +7127,7 @@ impl T$0 for () {} ``` ```rust + // Object Safety: Yes trait T {} ``` "#]], @@ -7149,6 +7151,9 @@ impl T$0 for () {} ``` ```rust + // Object Safety: No + // - Reason: has a method `func` that is non dispatchable because of: + // - missing a receiver trait T { /* … */ } ``` "#]], @@ -7172,6 +7177,9 @@ impl T$0 for () {} ``` ```rust + // Object Safety: No + // - Reason: has a method `func` that is non dispatchable because of: + // - missing a receiver trait T { fn func(); const FLAG: i32; @@ -7199,6 +7207,9 @@ impl T$0 for () {} ``` ```rust + // Object Safety: No + // - Reason: has a method `func` that is non dispatchable because of: + // - missing a receiver trait T { fn func(); const FLAG: i32; @@ -7226,6 +7237,9 @@ impl T$0 for () {} ``` ```rust + // Object Safety: No + // - Reason: has a method `func` that is non dispatchable because of: + // - missing a receiver trait T { fn func(); const FLAG: i32; @@ -8465,8 +8479,8 @@ impl Iterator for S { file_id: FileId( 1, ), - full_range: 7800..8042, - focus_range: 7865..7871, + full_range: 7801..8043, + focus_range: 7866..7872, name: "Future", kind: Trait, container_name: "future", @@ -8479,8 +8493,8 @@ impl Iterator for S { file_id: FileId( 1, ), - full_range: 8672..9171, - focus_range: 8749..8757, + full_range: 8673..9172, + focus_range: 8750..8758, name: "Iterator", kind: Trait, container_name: "iterator", diff --git a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/adjustment.rs b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/adjustment.rs index 756198d0c0110..31c1a991d53d7 100644 --- a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/adjustment.rs +++ b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/adjustment.rs @@ -288,7 +288,7 @@ mod tests { check_with_config( InlayHintsConfig { adjustment_hints: AdjustmentHints::Always, ..DISABLED_CONFIG }, r#" -//- minicore: coerce_unsized, fn, eq, index +//- minicore: coerce_unsized, fn, eq, index, dispatch_from_dyn fn main() { let _: u32 = loop {}; //^^^^^^^ @@ -428,7 +428,7 @@ impl core::ops::IndexMut for Struct {} ..DISABLED_CONFIG }, r#" -//- minicore: coerce_unsized, fn, eq, index +//- minicore: coerce_unsized, fn, eq, index, dispatch_from_dyn fn main() { Struct.consume(); diff --git a/src/tools/rust-analyzer/crates/intern/src/symbol/symbols.rs b/src/tools/rust-analyzer/crates/intern/src/symbol/symbols.rs index 7eb8e4a5e2e52..f48daba54e7b7 100644 --- a/src/tools/rust-analyzer/crates/intern/src/symbol/symbols.rs +++ b/src/tools/rust-analyzer/crates/intern/src/symbol/symbols.rs @@ -242,6 +242,7 @@ define_symbols! { future_output, Future, ge, + generic_associated_type_extended, get_context, global_allocator, global_asm, diff --git a/src/tools/rust-analyzer/crates/test-utils/src/minicore.rs b/src/tools/rust-analyzer/crates/test-utils/src/minicore.rs index 7dbc498ead196..b2f250e392237 100644 --- a/src/tools/rust-analyzer/crates/test-utils/src/minicore.rs +++ b/src/tools/rust-analyzer/crates/test-utils/src/minicore.rs @@ -33,6 +33,7 @@ //! from: sized //! future: pin //! coroutine: pin +//! dispatch_from_dyn: unsize, pin //! hash: //! include: //! index: sized @@ -821,6 +822,24 @@ pub mod ops { } pub use self::coroutine::{Coroutine, CoroutineState}; // endregion:coroutine + + // region:dispatch_from_dyn + mod dispatch_from_dyn { + use crate::marker::Unsize; + + #[lang = "dispatch_from_dyn"] + pub trait DispatchFromDyn {} + + impl<'a, T: ?Sized + Unsize, U: ?Sized> DispatchFromDyn<&'a U> for &'a T {} + + impl<'a, T: ?Sized + Unsize, U: ?Sized> DispatchFromDyn<&'a mut U> for &'a mut T {} + + impl, U: ?Sized> DispatchFromDyn<*const U> for *const T {} + + impl, U: ?Sized> DispatchFromDyn<*mut U> for *mut T {} + } + pub use self::dispatch_from_dyn::DispatchFromDyn; + // endregion:dispatch_from_dyn } // region:eq @@ -1182,6 +1201,12 @@ pub mod pin { } } // endregion:deref + // region:dispatch_from_dyn + impl crate::ops::DispatchFromDyn> for Pin where + Ptr: crate::ops::DispatchFromDyn + { + } + // endregion:dispatch_from_dyn } // endregion:pin @@ -1308,7 +1333,10 @@ pub mod iter { self } // region:iterators - fn take(self, n: usize) -> crate::iter::Take { + fn take(self, n: usize) -> crate::iter::Take + where + Self: Sized, + { loop {} } fn filter_map(self, _f: F) -> crate::iter::FilterMap From 05ffd446a9b2d2c67c450bea4180eb4790939e07 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Thu, 29 Aug 2024 16:06:20 +0200 Subject: [PATCH 0244/2194] Box validity: update for new zero-sized rules --- library/alloc/src/boxed.rs | 27 ++++++++++++--------------- 1 file changed, 12 insertions(+), 15 deletions(-) diff --git a/library/alloc/src/boxed.rs b/library/alloc/src/boxed.rs index 38b1766c17440..b3a3cf1bbeaaa 100644 --- a/library/alloc/src/boxed.rs +++ b/library/alloc/src/boxed.rs @@ -53,22 +53,19 @@ //! //! # Memory layout //! -//! For non-zero-sized values, a [`Box`] will use the [`Global`] allocator for -//! its allocation. It is valid to convert both ways between a [`Box`] and a -//! raw pointer allocated with the [`Global`] allocator, given that the -//! [`Layout`] used with the allocator is correct for the type. More precisely, -//! a `value: *mut T` that has been allocated with the [`Global`] allocator -//! with `Layout::for_value(&*value)` may be converted into a box using -//! [`Box::::from_raw(value)`]. Conversely, the memory backing a `value: *mut -//! T` obtained from [`Box::::into_raw`] may be deallocated using the -//! [`Global`] allocator with [`Layout::for_value(&*value)`]. +//! For non-zero-sized values, a [`Box`] will use the [`Global`] allocator for its allocation. It is +//! valid to convert both ways between a [`Box`] and a raw pointer allocated with the [`Global`] +//! allocator, given that the [`Layout`] used with the allocator is correct for the type and the raw +//! pointer points to a valid value of the right type. More precisely, a `value: *mut T` that has +//! been allocated with the [`Global`] allocator with `Layout::for_value(&*value)` may be converted +//! into a box using [`Box::::from_raw(value)`]. Conversely, the memory backing a `value: *mut T` +//! obtained from [`Box::::into_raw`] may be deallocated using the [`Global`] allocator with +//! [`Layout::for_value(&*value)`]. //! -//! For zero-sized values, the `Box` pointer still has to be [valid] for reads -//! and writes and sufficiently aligned. In particular, casting any aligned -//! non-zero integer literal to a raw pointer produces a valid pointer, but a -//! pointer pointing into previously allocated memory that since got freed is -//! not valid. The recommended way to build a Box to a ZST if `Box::new` cannot -//! be used is to use [`ptr::NonNull::dangling`]. +//! For zero-sized values, the `Box` pointer has to be non-null and sufficiently aligned. The +//! recommended way to build a Box to a ZST if `Box::new` cannot be used is to use +//! [`ptr::NonNull::dangling`]. Even for zero-sized types, the pointee type must be inhabited +//! to ensure that the Box points to a valid value of the given type. //! //! So long as `T: Sized`, a `Box` is guaranteed to be represented //! as a single pointer and is also ABI-compatible with C pointers From 92f27dc57df1e01186a2ab515ced9125a8ba2673 Mon Sep 17 00:00:00 2001 From: Shoyu Vanilla Date: Fri, 30 Aug 2024 02:00:38 +0900 Subject: [PATCH 0245/2194] fix: `std::error::Error` is object unsafe --- .../rust-analyzer/crates/hir-ty/src/db.rs | 3 +++ .../rust-analyzer/crates/hir-ty/src/lower.rs | 23 +++++++++++++++++++ .../crates/hir-ty/src/object_safety.rs | 23 ++----------------- .../crates/hir-ty/src/object_safety/tests.rs | 17 ++++++++++++++ 4 files changed, 45 insertions(+), 21 deletions(-) diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/db.rs b/src/tools/rust-analyzer/crates/hir-ty/src/db.rs index ebbe8a448cc4f..ce5a821ea2bc4 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/db.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/db.rs @@ -154,6 +154,9 @@ pub trait HirDatabase: DefDatabase + Upcast { #[salsa::invoke(crate::lower::generic_predicates_query)] fn generic_predicates(&self, def: GenericDefId) -> GenericPredicates; + #[salsa::invoke(crate::lower::generic_predicates_without_parent_query)] + fn generic_predicates_without_parent(&self, def: GenericDefId) -> GenericPredicates; + #[salsa::invoke(crate::lower::trait_environment_for_body_query)] #[salsa::transparent] fn trait_environment_for_body(&self, def: DefWithBodyId) -> Arc; diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/lower.rs b/src/tools/rust-analyzer/crates/hir-ty/src/lower.rs index 841e0216ae2b8..213400d04a01e 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/lower.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/lower.rs @@ -1700,6 +1700,28 @@ pub(crate) fn generic_predicates_query( db: &dyn HirDatabase, def: GenericDefId, ) -> GenericPredicates { + generic_predicates_filtered_by(db, def, |_, _| true) +} + +/// Resolve the where clause(s) of an item with generics, +/// except the ones inherited from the parent +pub(crate) fn generic_predicates_without_parent_query( + db: &dyn HirDatabase, + def: GenericDefId, +) -> GenericPredicates { + generic_predicates_filtered_by(db, def, |_, d| *d == def) +} + +/// Resolve the where clause(s) of an item with generics, +/// except the ones inherited from the parent +fn generic_predicates_filtered_by( + db: &dyn HirDatabase, + def: GenericDefId, + filter: F, +) -> GenericPredicates +where + F: Fn(&WherePredicate, &GenericDefId) -> bool, +{ let resolver = def.resolver(db.upcast()); let (impl_trait_lowering, param_lowering) = match def { GenericDefId::FunctionId(_) => { @@ -1714,6 +1736,7 @@ pub(crate) fn generic_predicates_query( let mut predicates = resolver .where_predicates_in_scope() + .filter(|(pred, def)| filter(pred, def)) .flat_map(|(pred, def)| { ctx.lower_where_predicate(pred, def, false).map(|p| make_binders(db, &generics, p)) }) diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/object_safety.rs b/src/tools/rust-analyzer/crates/hir-ty/src/object_safety.rs index f3bbb6b04f973..89bf3619a0c37 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/object_safety.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/object_safety.rs @@ -12,7 +12,7 @@ use hir_def::{ lang_item::LangItem, AssocItemId, ConstId, FunctionId, GenericDefId, HasModule, TraitId, TypeAliasId, }; -use rustc_hash::{FxHashMap, FxHashSet}; +use rustc_hash::FxHashSet; use smallvec::SmallVec; use crate::{ @@ -417,30 +417,11 @@ where cb(MethodViolationCode::UndispatchableReceiver)?; } - let predicates = &*db.generic_predicates(func.into()); - let mut parent_predicates = (*db.generic_predicates(trait_.into())) - .iter() - .map(|b| b.skip_binders().skip_binders().clone()) - .fold(FxHashMap::default(), |mut acc, item| { - acc.entry(item) - .and_modify(|cnt| { - *cnt += 1; - }) - .or_insert(1); - acc - }); + let predicates = &*db.generic_predicates_without_parent(func.into()); let trait_self_idx = trait_self_param_idx(db.upcast(), func.into()); for pred in predicates { let pred = pred.skip_binders().skip_binders(); - // Skip predicates from parent, i.e. the trait that contains this method - if let Some(cnt) = parent_predicates.get_mut(pred) { - if *cnt > 0 { - *cnt -= 1; - continue; - } - } - if matches!(pred, WhereClause::TypeOutlives(_)) { continue; } diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/object_safety/tests.rs b/src/tools/rust-analyzer/crates/hir-ty/src/object_safety/tests.rs index 585313e5b9bf8..3dc08c4619efd 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/object_safety/tests.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/object_safety/tests.rs @@ -361,3 +361,20 @@ pub trait Trait { [("Trait", vec![])], ); } + +#[test] +fn std_error_is_object_safe() { + check_object_safety( + r#" +//- minicore: fmt, dispatch_from_dyn +trait Erased<'a>: 'a {} + +pub struct Request<'a>(dyn Erased<'a> + 'a); + +pub trait Error: core::fmt::Debug + core::fmt::Display { + fn provide<'a>(&'a self, request: &mut Request<'a>); +} +"#, + [("Error", vec![])], + ); +} From 74a2344dc12b5659357272f4cd8b6e837195ab24 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 19 Mar 2024 16:51:40 +0100 Subject: [PATCH 0246/2194] Extend `implicit_saturation_sub` lint --- clippy_lints/src/implicit_saturating_sub.rs | 278 +++++++++++++++----- 1 file changed, 218 insertions(+), 60 deletions(-) diff --git a/clippy_lints/src/implicit_saturating_sub.rs b/clippy_lints/src/implicit_saturating_sub.rs index 127c73ed637b2..453ff09bf4fb2 100644 --- a/clippy_lints/src/implicit_saturating_sub.rs +++ b/clippy_lints/src/implicit_saturating_sub.rs @@ -1,11 +1,13 @@ -use clippy_utils::diagnostics::span_lint_and_sugg; -use clippy_utils::{higher, is_integer_literal, peel_blocks_with_stmt, SpanlessEq}; +use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then}; +use clippy_utils::source::snippet_opt; +use clippy_utils::{higher, is_integer_literal, path_to_local, peel_blocks, peel_blocks_with_stmt, SpanlessEq}; use rustc_ast::ast::LitKind; use rustc_data_structures::packed::Pu128; use rustc_errors::Applicability; -use rustc_hir::{BinOpKind, Expr, ExprKind, QPath}; +use rustc_hir::{BinOp, BinOpKind, Expr, ExprKind, HirId, QPath}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::declare_lint_pass; +use rustc_span::Span; declare_clippy_lint! { /// ### What it does @@ -50,73 +52,229 @@ impl<'tcx> LateLintPass<'tcx> for ImplicitSaturatingSub { // Check if the conditional expression is a binary operation && let ExprKind::Binary(ref cond_op, cond_left, cond_right) = cond.kind + { + check_with_condition(cx, expr, cond_op.node, cond_left, cond_right, then); + } else if let Some(higher::If { + cond, + then: if_block, + r#else: Some(else_block), + }) = higher::If::hir(expr) + && let ExprKind::Binary(ref cond_op, cond_left, cond_right) = cond.kind + { + check_manual_check(cx, expr, cond_op, cond_left, cond_right, if_block, else_block); + } + } +} - // Ensure that the binary operator is >, !=, or < - && (BinOpKind::Ne == cond_op.node || BinOpKind::Gt == cond_op.node || BinOpKind::Lt == cond_op.node) +fn check_manual_check<'tcx>( + cx: &LateContext<'tcx>, + expr: &Expr<'tcx>, + condition: &BinOp, + left_hand: &Expr<'tcx>, + right_hand: &Expr<'tcx>, + if_block: &Expr<'tcx>, + else_block: &Expr<'tcx>, +) { + let ty = cx.typeck_results().expr_ty(left_hand); + if ty.is_numeric() && !ty.is_signed() { + match condition.node { + BinOpKind::Gt | BinOpKind::Ge => check_gt( + cx, + condition.span, + expr.span, + left_hand, + right_hand, + if_block, + else_block, + ), + BinOpKind::Lt | BinOpKind::Le => check_gt( + cx, + condition.span, + expr.span, + right_hand, + left_hand, + if_block, + else_block, + ), + _ => {}, + } + } +} - // Check if assign operation is done - && let Some(target) = subtracts_one(cx, then) +fn check_gt( + cx: &LateContext<'_>, + condition_span: Span, + expr_span: Span, + big_var: &Expr<'_>, + little_var: &Expr<'_>, + if_block: &Expr<'_>, + else_block: &Expr<'_>, +) { + if let Some(big_var) = Var::new(big_var) + && let Some(little_var) = Var::new(little_var) + { + check_subtraction(cx, condition_span, expr_span, big_var, little_var, if_block, else_block); + } +} - // Extracting out the variable name - && let ExprKind::Path(QPath::Resolved(_, ares_path)) = target.kind +struct Var { + span: Span, + hir_id: HirId, +} + +impl Var { + fn new(expr: &Expr<'_>) -> Option { + path_to_local(expr).map(|hir_id| Self { + span: expr.span, + hir_id, + }) + } +} + +fn check_subtraction( + cx: &LateContext<'_>, + condition_span: Span, + expr_span: Span, + big_var: Var, + little_var: Var, + if_block: &Expr<'_>, + else_block: &Expr<'_>, +) { + let if_block = peel_blocks(if_block); + let else_block = peel_blocks(else_block); + if is_integer_literal(if_block, 0) { + // We need to check this case as well to prevent infinite recursion. + if is_integer_literal(else_block, 0) { + // Well, seems weird but who knows? + return; + } + // If the subtraction is done in the `else` block, then we need to also revert the two + // variables as it means that the check was reverted too. + check_subtraction(cx, condition_span, expr_span, little_var, big_var, else_block, if_block); + return; + } + if is_integer_literal(else_block, 0) + && let ExprKind::Binary(op, left, right) = if_block.kind + && let BinOpKind::Sub = op.node + { + let local_left = path_to_local(left); + let local_right = path_to_local(right); + if Some(big_var.hir_id) == local_left && Some(little_var.hir_id) == local_right { + // This part of the condition is voluntarily split from the one before to ensure that + // if `snippet_opt` fails, it won't try the next conditions. + if let Some(big_var_snippet) = snippet_opt(cx, big_var.span) + && let Some(little_var_snippet) = snippet_opt(cx, little_var.span) + { + span_lint_and_sugg( + cx, + IMPLICIT_SATURATING_SUB, + expr_span, + "manual arithmetic check found", + "replace it with", + format!("{big_var_snippet}.saturating_sub({little_var_snippet})"), + Applicability::MachineApplicable, + ); + } + } else if Some(little_var.hir_id) == local_left + && Some(big_var.hir_id) == local_right + && let Some(big_var_snippet) = snippet_opt(cx, big_var.span) + && let Some(little_var_snippet) = snippet_opt(cx, little_var.span) { - // Handle symmetric conditions in the if statement - let (cond_var, cond_num_val) = if SpanlessEq::new(cx).eq_expr(cond_left, target) { - if BinOpKind::Gt == cond_op.node || BinOpKind::Ne == cond_op.node { - (cond_left, cond_right) - } else { - return; - } - } else if SpanlessEq::new(cx).eq_expr(cond_right, target) { - if BinOpKind::Lt == cond_op.node || BinOpKind::Ne == cond_op.node { - (cond_right, cond_left) - } else { - return; - } + span_lint_and_then( + cx, + IMPLICIT_SATURATING_SUB, + condition_span, + "inverted arithmetic check before subtraction", + |diag| { + diag.span_note( + if_block.span, + format!("this subtraction underflows when `{little_var_snippet} < {big_var_snippet}`"), + ); + diag.span_suggestion( + if_block.span, + "try replacing it with", + format!("{big_var_snippet} - {little_var_snippet}"), + Applicability::MaybeIncorrect, + ); + }, + ); + } + } +} + +fn check_with_condition<'tcx>( + cx: &LateContext<'tcx>, + expr: &Expr<'tcx>, + cond_op: BinOpKind, + cond_left: &Expr<'tcx>, + cond_right: &Expr<'tcx>, + then: &Expr<'tcx>, +) { + // Ensure that the binary operator is >, !=, or < + if (BinOpKind::Ne == cond_op || BinOpKind::Gt == cond_op || BinOpKind::Lt == cond_op) + + // Check if assign operation is done + && let Some(target) = subtracts_one(cx, then) + + // Extracting out the variable name + && let ExprKind::Path(QPath::Resolved(_, ares_path)) = target.kind + { + // Handle symmetric conditions in the if statement + let (cond_var, cond_num_val) = if SpanlessEq::new(cx).eq_expr(cond_left, target) { + if BinOpKind::Gt == cond_op || BinOpKind::Ne == cond_op { + (cond_left, cond_right) } else { return; - }; - - // Check if the variable in the condition statement is an integer - if !cx.typeck_results().expr_ty(cond_var).is_integral() { + } + } else if SpanlessEq::new(cx).eq_expr(cond_right, target) { + if BinOpKind::Lt == cond_op || BinOpKind::Ne == cond_op { + (cond_right, cond_left) + } else { return; } + } else { + return; + }; - // Get the variable name - let var_name = ares_path.segments[0].ident.name.as_str(); - match cond_num_val.kind { - ExprKind::Lit(cond_lit) => { - // Check if the constant is zero - if let LitKind::Int(Pu128(0), _) = cond_lit.node { - if cx.typeck_results().expr_ty(cond_left).is_signed() { - } else { - print_lint_and_sugg(cx, var_name, expr); - }; - } - }, - ExprKind::Path(QPath::TypeRelative(_, name)) => { - if name.ident.as_str() == "MIN" - && let Some(const_id) = cx.typeck_results().type_dependent_def_id(cond_num_val.hir_id) - && let Some(impl_id) = cx.tcx.impl_of_method(const_id) - && let None = cx.tcx.impl_trait_ref(impl_id) // An inherent impl - && cx.tcx.type_of(impl_id).instantiate_identity().is_integral() - { - print_lint_and_sugg(cx, var_name, expr); - } - }, - ExprKind::Call(func, []) => { - if let ExprKind::Path(QPath::TypeRelative(_, name)) = func.kind - && name.ident.as_str() == "min_value" - && let Some(func_id) = cx.typeck_results().type_dependent_def_id(func.hir_id) - && let Some(impl_id) = cx.tcx.impl_of_method(func_id) - && let None = cx.tcx.impl_trait_ref(impl_id) // An inherent impl - && cx.tcx.type_of(impl_id).instantiate_identity().is_integral() - { + // Check if the variable in the condition statement is an integer + if !cx.typeck_results().expr_ty(cond_var).is_integral() { + return; + } + + // Get the variable name + let var_name = ares_path.segments[0].ident.name.as_str(); + match cond_num_val.kind { + ExprKind::Lit(cond_lit) => { + // Check if the constant is zero + if let LitKind::Int(Pu128(0), _) = cond_lit.node { + if cx.typeck_results().expr_ty(cond_left).is_signed() { + } else { print_lint_and_sugg(cx, var_name, expr); - } - }, - _ => (), - } + }; + } + }, + ExprKind::Path(QPath::TypeRelative(_, name)) => { + if name.ident.as_str() == "MIN" + && let Some(const_id) = cx.typeck_results().type_dependent_def_id(cond_num_val.hir_id) + && let Some(impl_id) = cx.tcx.impl_of_method(const_id) + && let None = cx.tcx.impl_trait_ref(impl_id) // An inherent impl + && cx.tcx.type_of(impl_id).instantiate_identity().is_integral() + { + print_lint_and_sugg(cx, var_name, expr); + } + }, + ExprKind::Call(func, []) => { + if let ExprKind::Path(QPath::TypeRelative(_, name)) = func.kind + && name.ident.as_str() == "min_value" + && let Some(func_id) = cx.typeck_results().type_dependent_def_id(func.hir_id) + && let Some(impl_id) = cx.tcx.impl_of_method(func_id) + && let None = cx.tcx.impl_trait_ref(impl_id) // An inherent impl + && cx.tcx.type_of(impl_id).instantiate_identity().is_integral() + { + print_lint_and_sugg(cx, var_name, expr); + } + }, + _ => (), } } } From 2622a87587ada00d6aac1d036da8a2f579a675ba Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 19 Mar 2024 16:59:08 +0100 Subject: [PATCH 0247/2194] Add ui regression tests for `implicit_saturation_sub` lint extension --- tests/ui/implicit_saturating_sub.rs | 7 +++ tests/ui/manual_arithmetic_check-2.rs | 35 +++++++++++ tests/ui/manual_arithmetic_check-2.stderr | 76 +++++++++++++++++++++++ tests/ui/manual_arithmetic_check.fixed | 16 +++++ tests/ui/manual_arithmetic_check.rs | 20 ++++++ tests/ui/manual_arithmetic_check.stderr | 29 +++++++++ 6 files changed, 183 insertions(+) create mode 100644 tests/ui/manual_arithmetic_check-2.rs create mode 100644 tests/ui/manual_arithmetic_check-2.stderr create mode 100644 tests/ui/manual_arithmetic_check.fixed create mode 100644 tests/ui/manual_arithmetic_check.rs create mode 100644 tests/ui/manual_arithmetic_check.stderr diff --git a/tests/ui/implicit_saturating_sub.rs b/tests/ui/implicit_saturating_sub.rs index 5d7b95d2c652f..05f7d85238307 100644 --- a/tests/ui/implicit_saturating_sub.rs +++ b/tests/ui/implicit_saturating_sub.rs @@ -260,4 +260,11 @@ fn main() { } else if u_32 > 0 { u_32 -= 1; } + + let result = if a < b { + println!("we shouldn't remove this"); + 0 + } else { + a - b + }; } diff --git a/tests/ui/manual_arithmetic_check-2.rs b/tests/ui/manual_arithmetic_check-2.rs new file mode 100644 index 0000000000000..e97e3bdfef769 --- /dev/null +++ b/tests/ui/manual_arithmetic_check-2.rs @@ -0,0 +1,35 @@ +//@no-rustfix +#![warn(clippy::implicit_saturating_sub)] +#![allow(arithmetic_overflow)] + +fn main() { + let a = 12u32; + let b = 13u32; + + let result = if a > b { b - a } else { 0 }; + //~^ ERROR: inverted arithmetic check before subtraction + let result = if b < a { b - a } else { 0 }; + //~^ ERROR: inverted arithmetic check before subtraction + + let result = if a > b { 0 } else { a - b }; + //~^ ERROR: inverted arithmetic check before subtraction + let result = if a >= b { 0 } else { a - b }; + //~^ ERROR: inverted arithmetic check before subtraction + let result = if b < a { 0 } else { a - b }; + //~^ ERROR: inverted arithmetic check before subtraction + let result = if b <= a { 0 } else { a - b }; + //~^ ERROR: inverted arithmetic check before subtraction + + let af = 12f32; + let bf = 13f32; + // Should not lint! + let result = if bf < af { 0. } else { af - bf }; + + // Should not lint! + let result = if a < b { + println!("we shouldn't remove this"); + 0 + } else { + a - b + }; +} diff --git a/tests/ui/manual_arithmetic_check-2.stderr b/tests/ui/manual_arithmetic_check-2.stderr new file mode 100644 index 0000000000000..d49e536ce3fbf --- /dev/null +++ b/tests/ui/manual_arithmetic_check-2.stderr @@ -0,0 +1,76 @@ +error: inverted arithmetic check before subtraction + --> tests/ui/manual_arithmetic_check-2.rs:9:23 + | +LL | let result = if a > b { b - a } else { 0 }; + | ^ ----- help: try replacing it with: `a - b` + | +note: this subtraction underflows when `b < a` + --> tests/ui/manual_arithmetic_check-2.rs:9:29 + | +LL | let result = if a > b { b - a } else { 0 }; + | ^^^^^ + = note: `-D clippy::implicit-saturating-sub` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::implicit_saturating_sub)]` + +error: inverted arithmetic check before subtraction + --> tests/ui/manual_arithmetic_check-2.rs:11:23 + | +LL | let result = if b < a { b - a } else { 0 }; + | ^ ----- help: try replacing it with: `a - b` + | +note: this subtraction underflows when `b < a` + --> tests/ui/manual_arithmetic_check-2.rs:11:29 + | +LL | let result = if b < a { b - a } else { 0 }; + | ^^^^^ + +error: inverted arithmetic check before subtraction + --> tests/ui/manual_arithmetic_check-2.rs:14:23 + | +LL | let result = if a > b { 0 } else { a - b }; + | ^ ----- help: try replacing it with: `b - a` + | +note: this subtraction underflows when `a < b` + --> tests/ui/manual_arithmetic_check-2.rs:14:40 + | +LL | let result = if a > b { 0 } else { a - b }; + | ^^^^^ + +error: inverted arithmetic check before subtraction + --> tests/ui/manual_arithmetic_check-2.rs:16:23 + | +LL | let result = if a >= b { 0 } else { a - b }; + | ^^ ----- help: try replacing it with: `b - a` + | +note: this subtraction underflows when `a < b` + --> tests/ui/manual_arithmetic_check-2.rs:16:41 + | +LL | let result = if a >= b { 0 } else { a - b }; + | ^^^^^ + +error: inverted arithmetic check before subtraction + --> tests/ui/manual_arithmetic_check-2.rs:18:23 + | +LL | let result = if b < a { 0 } else { a - b }; + | ^ ----- help: try replacing it with: `b - a` + | +note: this subtraction underflows when `a < b` + --> tests/ui/manual_arithmetic_check-2.rs:18:40 + | +LL | let result = if b < a { 0 } else { a - b }; + | ^^^^^ + +error: inverted arithmetic check before subtraction + --> tests/ui/manual_arithmetic_check-2.rs:20:23 + | +LL | let result = if b <= a { 0 } else { a - b }; + | ^^ ----- help: try replacing it with: `b - a` + | +note: this subtraction underflows when `a < b` + --> tests/ui/manual_arithmetic_check-2.rs:20:41 + | +LL | let result = if b <= a { 0 } else { a - b }; + | ^^^^^ + +error: aborting due to 6 previous errors + diff --git a/tests/ui/manual_arithmetic_check.fixed b/tests/ui/manual_arithmetic_check.fixed new file mode 100644 index 0000000000000..afb2abcbe9071 --- /dev/null +++ b/tests/ui/manual_arithmetic_check.fixed @@ -0,0 +1,16 @@ +#![warn(clippy::implicit_saturating_sub)] + +fn main() { + let a = 12u32; + let b = 13u32; + + let result = a.saturating_sub(b); + //~^ ERROR: manual arithmetic check found + let result = a.saturating_sub(b); + //~^ ERROR: manual arithmetic check found + + let result = a.saturating_sub(b); + //~^ ERROR: manual arithmetic check found + let result = a.saturating_sub(b); + //~^ ERROR: manual arithmetic check found +} diff --git a/tests/ui/manual_arithmetic_check.rs b/tests/ui/manual_arithmetic_check.rs new file mode 100644 index 0000000000000..c11ac7097fc4e --- /dev/null +++ b/tests/ui/manual_arithmetic_check.rs @@ -0,0 +1,20 @@ +#![warn(clippy::implicit_saturating_sub)] + +fn main() { + let a = 12u32; + let b = 13u32; + let c = 8u32; + + let result = if a > b { a - b } else { 0 }; + //~^ ERROR: manual arithmetic check found + let result = if b < a { a - b } else { 0 }; + //~^ ERROR: manual arithmetic check found + + let result = if a < b { 0 } else { a - b }; + //~^ ERROR: manual arithmetic check found + let result = if b > a { 0 } else { a - b }; + //~^ ERROR: manual arithmetic check found + + // Should not warn! + let result = if a > b { a - b } else { a - c }; +} diff --git a/tests/ui/manual_arithmetic_check.stderr b/tests/ui/manual_arithmetic_check.stderr new file mode 100644 index 0000000000000..153a8bb57346f --- /dev/null +++ b/tests/ui/manual_arithmetic_check.stderr @@ -0,0 +1,29 @@ +error: manual arithmetic check found + --> tests/ui/manual_arithmetic_check.rs:7:18 + | +LL | let result = if a > b { a - b } else { 0 }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `a.saturating_sub(b)` + | + = note: `-D clippy::implicit-saturating-sub` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::implicit_saturating_sub)]` + +error: manual arithmetic check found + --> tests/ui/manual_arithmetic_check.rs:9:18 + | +LL | let result = if b < a { a - b } else { 0 }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `a.saturating_sub(b)` + +error: manual arithmetic check found + --> tests/ui/manual_arithmetic_check.rs:12:18 + | +LL | let result = if a < b { 0 } else { a - b }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `a.saturating_sub(b)` + +error: manual arithmetic check found + --> tests/ui/manual_arithmetic_check.rs:14:18 + | +LL | let result = if b > a { 0 } else { a - b }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `a.saturating_sub(b)` + +error: aborting due to 4 previous errors + From 27c63433659773c70dca86a3d6f3b9bd7654c2c3 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 19 Mar 2024 17:00:31 +0100 Subject: [PATCH 0248/2194] Add ui test to ensure that if `0` is returned from both `if` and `else`, it will not break clippy --- tests/ui/implicit_saturating_sub.fixed | 13 ++++++++++--- tests/ui/implicit_saturating_sub.rs | 6 +++--- tests/ui/manual_arithmetic_check.fixed | 8 ++++++++ tests/ui/manual_arithmetic_check.rs | 4 ++++ tests/ui/manual_arithmetic_check.stderr | 8 ++++---- 5 files changed, 29 insertions(+), 10 deletions(-) diff --git a/tests/ui/implicit_saturating_sub.fixed b/tests/ui/implicit_saturating_sub.fixed index 27f679797dd9e..81cc149491442 100644 --- a/tests/ui/implicit_saturating_sub.fixed +++ b/tests/ui/implicit_saturating_sub.fixed @@ -184,18 +184,18 @@ fn main() { let mut m = Mock; let mut u_32 = 3000; let a = 200; - let mut _b = 8; + let mut b = 8; if m != 0 { m -= 1; } if a > 0 { - _b -= 1; + b -= 1; } if 0 > a { - _b -= 1; + b -= 1; } if u_32 > 0 { @@ -214,4 +214,11 @@ fn main() { } else if u_32 > 0 { u_32 -= 1; } + + let result = if a < b { + println!("we shouldn't remove this"); + 0 + } else { + a - b + }; } diff --git a/tests/ui/implicit_saturating_sub.rs b/tests/ui/implicit_saturating_sub.rs index 05f7d85238307..f73396ebd27e2 100644 --- a/tests/ui/implicit_saturating_sub.rs +++ b/tests/ui/implicit_saturating_sub.rs @@ -230,18 +230,18 @@ fn main() { let mut m = Mock; let mut u_32 = 3000; let a = 200; - let mut _b = 8; + let mut b = 8; if m != 0 { m -= 1; } if a > 0 { - _b -= 1; + b -= 1; } if 0 > a { - _b -= 1; + b -= 1; } if u_32 > 0 { diff --git a/tests/ui/manual_arithmetic_check.fixed b/tests/ui/manual_arithmetic_check.fixed index afb2abcbe9071..600fcd3765d81 100644 --- a/tests/ui/manual_arithmetic_check.fixed +++ b/tests/ui/manual_arithmetic_check.fixed @@ -1,8 +1,10 @@ #![warn(clippy::implicit_saturating_sub)] +#![allow(clippy::if_same_then_else)] fn main() { let a = 12u32; let b = 13u32; + let c = 8u32; let result = a.saturating_sub(b); //~^ ERROR: manual arithmetic check found @@ -13,4 +15,10 @@ fn main() { //~^ ERROR: manual arithmetic check found let result = a.saturating_sub(b); //~^ ERROR: manual arithmetic check found + + // Should not warn! + let result = if a > b { a - b } else { a - c }; + + // Just to check it won't break clippy. + let result = if b > a { 0 } else { 0 }; } diff --git a/tests/ui/manual_arithmetic_check.rs b/tests/ui/manual_arithmetic_check.rs index c11ac7097fc4e..33f5adafe7e40 100644 --- a/tests/ui/manual_arithmetic_check.rs +++ b/tests/ui/manual_arithmetic_check.rs @@ -1,4 +1,5 @@ #![warn(clippy::implicit_saturating_sub)] +#![allow(clippy::if_same_then_else)] fn main() { let a = 12u32; @@ -17,4 +18,7 @@ fn main() { // Should not warn! let result = if a > b { a - b } else { a - c }; + + // Just to check it won't break clippy. + let result = if b > a { 0 } else { 0 }; } diff --git a/tests/ui/manual_arithmetic_check.stderr b/tests/ui/manual_arithmetic_check.stderr index 153a8bb57346f..b0cf73cd9151d 100644 --- a/tests/ui/manual_arithmetic_check.stderr +++ b/tests/ui/manual_arithmetic_check.stderr @@ -1,5 +1,5 @@ error: manual arithmetic check found - --> tests/ui/manual_arithmetic_check.rs:7:18 + --> tests/ui/manual_arithmetic_check.rs:9:18 | LL | let result = if a > b { a - b } else { 0 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `a.saturating_sub(b)` @@ -8,19 +8,19 @@ LL | let result = if a > b { a - b } else { 0 }; = help: to override `-D warnings` add `#[allow(clippy::implicit_saturating_sub)]` error: manual arithmetic check found - --> tests/ui/manual_arithmetic_check.rs:9:18 + --> tests/ui/manual_arithmetic_check.rs:11:18 | LL | let result = if b < a { a - b } else { 0 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `a.saturating_sub(b)` error: manual arithmetic check found - --> tests/ui/manual_arithmetic_check.rs:12:18 + --> tests/ui/manual_arithmetic_check.rs:14:18 | LL | let result = if a < b { 0 } else { a - b }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `a.saturating_sub(b)` error: manual arithmetic check found - --> tests/ui/manual_arithmetic_check.rs:14:18 + --> tests/ui/manual_arithmetic_check.rs:16:18 | LL | let result = if b > a { 0 } else { a - b }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `a.saturating_sub(b)` From d20fc38f0a17561166fb57c83ff5660b3cd41392 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 19 Jul 2024 14:51:56 +0200 Subject: [PATCH 0249/2194] Create new `inverted_saturating_sub` lint --- CHANGELOG.md | 1 + clippy_lints/src/declared_lints.rs | 1 + clippy_lints/src/implicit_saturating_sub.rs | 34 +++++++++++++++++++-- tests/ui/manual_arithmetic_check-2.stderr | 3 +- tests/ui/manual_arithmetic_check.fixed | 2 +- tests/ui/manual_arithmetic_check.rs | 2 +- 6 files changed, 37 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fddc2fd994e87..0bef35529662a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5500,6 +5500,7 @@ Released 2018-09-13 [`invalid_regex`]: https://rust-lang.github.io/rust-clippy/master/index.html#invalid_regex [`invalid_upcast_comparisons`]: https://rust-lang.github.io/rust-clippy/master/index.html#invalid_upcast_comparisons [`invalid_utf8_in_unchecked`]: https://rust-lang.github.io/rust-clippy/master/index.html#invalid_utf8_in_unchecked +[`inverted_saturating_sub`]: https://rust-lang.github.io/rust-clippy/master/index.html#inverted_saturating_sub [`invisible_characters`]: https://rust-lang.github.io/rust-clippy/master/index.html#invisible_characters [`is_digit_ascii_radix`]: https://rust-lang.github.io/rust-clippy/master/index.html#is_digit_ascii_radix [`items_after_statements`]: https://rust-lang.github.io/rust-clippy/master/index.html#items_after_statements diff --git a/clippy_lints/src/declared_lints.rs b/clippy_lints/src/declared_lints.rs index 8754a4dff87b1..a6dd6ae731289 100644 --- a/clippy_lints/src/declared_lints.rs +++ b/clippy_lints/src/declared_lints.rs @@ -216,6 +216,7 @@ pub static LINTS: &[&crate::LintInfo] = &[ crate::implicit_return::IMPLICIT_RETURN_INFO, crate::implicit_saturating_add::IMPLICIT_SATURATING_ADD_INFO, crate::implicit_saturating_sub::IMPLICIT_SATURATING_SUB_INFO, + crate::implicit_saturating_sub::INVERTED_SATURATING_SUB_INFO, crate::implied_bounds_in_impls::IMPLIED_BOUNDS_IN_IMPLS_INFO, crate::incompatible_msrv::INCOMPATIBLE_MSRV_INFO, crate::inconsistent_struct_constructor::INCONSISTENT_STRUCT_CONSTRUCTOR_INFO, diff --git a/clippy_lints/src/implicit_saturating_sub.rs b/clippy_lints/src/implicit_saturating_sub.rs index 453ff09bf4fb2..04c890620396d 100644 --- a/clippy_lints/src/implicit_saturating_sub.rs +++ b/clippy_lints/src/implicit_saturating_sub.rs @@ -41,7 +41,37 @@ declare_clippy_lint! { "Perform saturating subtraction instead of implicitly checking lower bound of data type" } -declare_lint_pass!(ImplicitSaturatingSub => [IMPLICIT_SATURATING_SUB]); +declare_clippy_lint! { + /// ### What it does + /// Checks for comparisons between integers, followed by subtracting the greater value from the + /// lower one. + /// + /// ### Why is this bad? + /// This could result in an underflow and is most likely not what the user wants. If this was + /// intended to be a saturated subtraction, consider using the `saturating_sub` method directly. + /// + /// ### Example + /// ```no_run + /// let a = 12u32; + /// let b = 13u32; + /// + /// let result = if a > b { b - a } else { 0 }; + /// ``` + /// + /// Use instead: + /// ```no_run + /// let a = 12u32; + /// let b = 13u32; + /// + /// let result = a.saturating_sub(b); + /// ``` + #[clippy::version = "1.44.0"] + pub INVERTED_SATURATING_SUB, + correctness, + "Check if a variable is smaller than another one and still subtract from it even if smaller" +} + +declare_lint_pass!(ImplicitSaturatingSub => [IMPLICIT_SATURATING_SUB, INVERTED_SATURATING_SUB]); impl<'tcx> LateLintPass<'tcx> for ImplicitSaturatingSub { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) { @@ -182,7 +212,7 @@ fn check_subtraction( { span_lint_and_then( cx, - IMPLICIT_SATURATING_SUB, + INVERTED_SATURATING_SUB, condition_span, "inverted arithmetic check before subtraction", |diag| { diff --git a/tests/ui/manual_arithmetic_check-2.stderr b/tests/ui/manual_arithmetic_check-2.stderr index d49e536ce3fbf..4121aa7464f05 100644 --- a/tests/ui/manual_arithmetic_check-2.stderr +++ b/tests/ui/manual_arithmetic_check-2.stderr @@ -9,8 +9,7 @@ note: this subtraction underflows when `b < a` | LL | let result = if a > b { b - a } else { 0 }; | ^^^^^ - = note: `-D clippy::implicit-saturating-sub` implied by `-D warnings` - = help: to override `-D warnings` add `#[allow(clippy::implicit_saturating_sub)]` + = note: `#[deny(clippy::inverted_saturating_sub)]` on by default error: inverted arithmetic check before subtraction --> tests/ui/manual_arithmetic_check-2.rs:11:23 diff --git a/tests/ui/manual_arithmetic_check.fixed b/tests/ui/manual_arithmetic_check.fixed index 600fcd3765d81..29ecbb9ad2adb 100644 --- a/tests/ui/manual_arithmetic_check.fixed +++ b/tests/ui/manual_arithmetic_check.fixed @@ -1,4 +1,4 @@ -#![warn(clippy::implicit_saturating_sub)] +#![warn(clippy::implicit_saturating_sub, clippy::inverted_saturating_sub)] #![allow(clippy::if_same_then_else)] fn main() { diff --git a/tests/ui/manual_arithmetic_check.rs b/tests/ui/manual_arithmetic_check.rs index 33f5adafe7e40..69554c6b61caa 100644 --- a/tests/ui/manual_arithmetic_check.rs +++ b/tests/ui/manual_arithmetic_check.rs @@ -1,4 +1,4 @@ -#![warn(clippy::implicit_saturating_sub)] +#![warn(clippy::implicit_saturating_sub, clippy::inverted_saturating_sub)] #![allow(clippy::if_same_then_else)] fn main() { From 8bb235baa2b8c46c02557ad0500e75c81d270075 Mon Sep 17 00:00:00 2001 From: Chayim Refael Friedman Date: Thu, 29 Aug 2024 22:03:57 +0300 Subject: [PATCH 0250/2194] Add diagnostic for accessing an `extern` static --- .../hir-ty/src/diagnostics/unsafe_check.rs | 3 ++- .../src/handlers/missing_unsafe.rs | 25 +++++++++++++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/unsafe_check.rs b/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/unsafe_check.rs index 3f54cdd20cee3..1582cbba88055 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/unsafe_check.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/unsafe_check.rs @@ -87,7 +87,8 @@ fn walk_unsafe( let g = resolver.update_to_inner_scope(db.upcast(), def, current); let value_or_partial = resolver.resolve_path_in_value_ns(db.upcast(), path); if let Some(ResolveValueResult::ValueNs(ValueNs::StaticId(id), _)) = value_or_partial { - if db.static_data(id).mutable { + let static_data = db.static_data(id); + if static_data.mutable || static_data.is_extern { unsafe_expr_cb(UnsafeExpr { expr: current, inside_unsafe_block }); } } diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/missing_unsafe.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/missing_unsafe.rs index af8ac6005d7a7..7407faee350b6 100644 --- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/missing_unsafe.rs +++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/missing_unsafe.rs @@ -163,6 +163,31 @@ fn main() { ); } + #[test] + fn missing_unsafe_diagnostic_with_extern_static() { + check_diagnostics( + r#" +//- minicore: copy + +extern "C" { + static EXTERN: i32; + static mut EXTERN_MUT: i32; +} + +fn main() { + let _x = EXTERN; + //^^^^^^💡 error: this operation is unsafe and requires an unsafe function or block + let _x = EXTERN_MUT; + //^^^^^^^^^^💡 error: this operation is unsafe and requires an unsafe function or block + unsafe { + let _x = EXTERN; + let _x = EXTERN_MUT; + } +} +"#, + ); + } + #[test] fn no_missing_unsafe_diagnostic_with_safe_intrinsic() { check_diagnostics( From 21cb84763cf942dc2fa70d582cf2b8ba50163750 Mon Sep 17 00:00:00 2001 From: Matthew Giordano Date: Thu, 29 Aug 2024 12:32:33 -0700 Subject: [PATCH 0251/2194] fix fmt --- library/alloc/src/rc.rs | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rc.rs index 151eec532613c..0afb138db8ada 100644 --- a/library/alloc/src/rc.rs +++ b/library/alloc/src/rc.rs @@ -1710,11 +1710,7 @@ impl Rc { #[inline] #[stable(feature = "rc_unique", since = "1.4.0")] pub fn get_mut(this: &mut Self) -> Option<&mut T> { - if Rc::is_unique(this) { - unsafe { Some(Rc::get_mut_unchecked(this)) } - } else { - None - } + if Rc::is_unique(this) { unsafe { Some(Rc::get_mut_unchecked(this)) } } else { None } } /// Returns a mutable reference into the given `Rc`, @@ -3291,11 +3287,7 @@ impl Weak { #[must_use] #[stable(feature = "weak_counts", since = "1.41.0")] pub fn strong_count(&self) -> usize { - if let Some(inner) = self.inner() { - inner.strong() - } else { - 0 - } + if let Some(inner) = self.inner() { inner.strong() } else { 0 } } /// Gets the number of `Weak` pointers pointing to this allocation. From 9e7473f08daf4a8ab1fec5186376ad1299555344 Mon Sep 17 00:00:00 2001 From: xFrednet Date: Thu, 29 Aug 2024 21:31:46 +0200 Subject: [PATCH 0252/2194] Update version attribute for 1.81 lints --- clippy_lints/src/byte_char_slices.rs | 2 +- clippy_lints/src/cfg_not_test.rs | 2 +- clippy_lints/src/field_scoped_visibility_modifiers.rs | 2 +- clippy_lints/src/methods/mod.rs | 4 ++-- clippy_lints/src/needless_maybe_sized.rs | 2 +- clippy_lints/src/set_contains_or_insert.rs | 2 +- clippy_lints/src/string_patterns.rs | 2 +- 7 files changed, 8 insertions(+), 8 deletions(-) diff --git a/clippy_lints/src/byte_char_slices.rs b/clippy_lints/src/byte_char_slices.rs index a9fe190f1777e..dd2620b0b9df9 100644 --- a/clippy_lints/src/byte_char_slices.rs +++ b/clippy_lints/src/byte_char_slices.rs @@ -22,7 +22,7 @@ declare_clippy_lint! { /// ```ignore /// b"Hello" /// ``` - #[clippy::version = "1.68.0"] + #[clippy::version = "1.81.0"] pub BYTE_CHAR_SLICES, style, "hard to read byte char slice" diff --git a/clippy_lints/src/cfg_not_test.rs b/clippy_lints/src/cfg_not_test.rs index d820c1e0720b8..884d15cabffcb 100644 --- a/clippy_lints/src/cfg_not_test.rs +++ b/clippy_lints/src/cfg_not_test.rs @@ -22,7 +22,7 @@ declare_clippy_lint! { /// # fn important_check() {} /// important_check(); /// ``` - #[clippy::version = "1.73.0"] + #[clippy::version = "1.81.0"] pub CFG_NOT_TEST, restriction, "enforce against excluding code from test builds" diff --git a/clippy_lints/src/field_scoped_visibility_modifiers.rs b/clippy_lints/src/field_scoped_visibility_modifiers.rs index 95b8e882da792..ba2b37fbf11a3 100644 --- a/clippy_lints/src/field_scoped_visibility_modifiers.rs +++ b/clippy_lints/src/field_scoped_visibility_modifiers.rs @@ -41,7 +41,7 @@ declare_clippy_lint! { /// } /// } /// ``` - #[clippy::version = "1.78.0"] + #[clippy::version = "1.81.0"] pub FIELD_SCOPED_VISIBILITY_MODIFIERS, restriction, "checks for usage of a scoped visibility modifier, like `pub(crate)`, on fields" diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index d7126990edb1d..0420f5c7628d3 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -3964,7 +3964,7 @@ declare_clippy_lint! { /// ```no_run /// let _ = 0; /// ``` - #[clippy::version = "1.78.0"] + #[clippy::version = "1.81.0"] pub UNNECESSARY_MIN_OR_MAX, complexity, "using 'min()/max()' when there is no need for it" @@ -4099,7 +4099,7 @@ declare_clippy_lint! { /// ```no_run /// "foo".is_ascii(); /// ``` - #[clippy::version = "1.80.0"] + #[clippy::version = "1.81.0"] pub NEEDLESS_CHARACTER_ITERATION, suspicious, "is_ascii() called on a char iterator" diff --git a/clippy_lints/src/needless_maybe_sized.rs b/clippy_lints/src/needless_maybe_sized.rs index a1d8ec3b32ec9..c0847342caf12 100644 --- a/clippy_lints/src/needless_maybe_sized.rs +++ b/clippy_lints/src/needless_maybe_sized.rs @@ -26,7 +26,7 @@ declare_clippy_lint! { /// /// // or choose alternative bounds for `T` so that it can be unsized /// ``` - #[clippy::version = "1.79.0"] + #[clippy::version = "1.81.0"] pub NEEDLESS_MAYBE_SIZED, suspicious, "a `?Sized` bound that is unusable due to a `Sized` requirement" diff --git a/clippy_lints/src/set_contains_or_insert.rs b/clippy_lints/src/set_contains_or_insert.rs index e6fe76493974a..bc2a71c42b9f8 100644 --- a/clippy_lints/src/set_contains_or_insert.rs +++ b/clippy_lints/src/set_contains_or_insert.rs @@ -42,7 +42,7 @@ declare_clippy_lint! { /// println!("inserted {value:?}"); /// } /// ``` - #[clippy::version = "1.80.0"] + #[clippy::version = "1.81.0"] pub SET_CONTAINS_OR_INSERT, nursery, "call to `::contains` followed by `::insert`" diff --git a/clippy_lints/src/string_patterns.rs b/clippy_lints/src/string_patterns.rs index 7e211d64da141..8af50ca87d631 100644 --- a/clippy_lints/src/string_patterns.rs +++ b/clippy_lints/src/string_patterns.rs @@ -33,7 +33,7 @@ declare_clippy_lint! { /// ```no_run /// "Hello World!".trim_end_matches(['.', ',', '!', '?']); /// ``` - #[clippy::version = "1.80.0"] + #[clippy::version = "1.81.0"] pub MANUAL_PATTERN_CHAR_COMPARISON, style, "manual char comparison in string patterns" From 9aa23b8317de0fe68415f120b1cbf589fcf3d052 Mon Sep 17 00:00:00 2001 From: xFrednet Date: Thu, 29 Aug 2024 21:38:41 +0200 Subject: [PATCH 0253/2194] Changelog for Clippy 1.81 :beginner: --- CHANGELOG.md | 56 +++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 55 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 21252a3f43a00..4364e0f7085c0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,7 +6,61 @@ document. ## Unreleased / Beta / In Rust Nightly -[c9139bd5...master](https://github.com/rust-lang/rust-clippy/compare/c9139bd5...master) +[b794b8e0...master](https://github.com/rust-lang/rust-clippy/compare/b794b8e0...master) + +## Rust 1.81 + +Current stable, released 2024-09-05 + +### New Lints + +* Added [`cfg_not_test`] to `restriction` + [#11293](https://github.com/rust-lang/rust-clippy/pull/11293) +* Added [`byte_char_slices`] to `style` + [#10155](https://github.com/rust-lang/rust-clippy/pull/10155) +* Added [`set_contains_or_insert`] to `nursery` + [#12873](https://github.com/rust-lang/rust-clippy/pull/12873) +* Added [`manual_rotate`] to `style` + [#12983](https://github.com/rust-lang/rust-clippy/pull/12983) +* Added [`unnecessary_min_or_max`] to `complexity` + [#12368](https://github.com/rust-lang/rust-clippy/pull/12368) +* Added [`manual_inspect`] to `complexity` + [#12287](https://github.com/rust-lang/rust-clippy/pull/12287) +* Added [`field_scoped_visibility_modifiers`] to `restriction` + [#12893](https://github.com/rust-lang/rust-clippy/pull/12893) +* Added [`manual_pattern_char_comparison`] to `style` + [#12849](https://github.com/rust-lang/rust-clippy/pull/12849) +* Added [`needless_maybe_sized`] to `suspicious` + [#10632](https://github.com/rust-lang/rust-clippy/pull/10632) +* Added [`needless_character_iteration`] to `suspicious` + [#12815](https://github.com/rust-lang/rust-clippy/pull/12815) + +### Moves and Deprecations + +* [`allow_attributes`], [`allow_attributes_without_reason`]: Now work on stable + [rust#120924](https://github.com/rust-lang/rust/pull/120924) +* Renamed `overflow_check_conditional` to [`panicking_overflow_checks`] + [#12944](https://github.com/rust-lang/rust-clippy/pull/12944) +* Moved [`panicking_overflow_checks`] to `correctness` (From `complexity` now warn-by-default) + [#12944](https://github.com/rust-lang/rust-clippy/pull/12944) +* Renamed `thread_local_initializer_can_be_made_const` to [`missing_const_for_thread_local`] + [#12974](https://github.com/rust-lang/rust-clippy/pull/12974) +* Deprecated [`maybe_misused_cfg`] and [`mismatched_target_os`] as they are now caught by cargo + and rustc + [#12875](https://github.com/rust-lang/rust-clippy/pull/12875) + +### Enhancements + +* [`significant_drop_in_scrutinee`]: Now also checks scrutinies of `while let` and `for let` + expressions + [#12870](https://github.com/rust-lang/rust-clippy/pull/12870) +* [`std_instead_of_core`]: Now respects the `msrv` configuration + [#13168](https://github.com/rust-lang/rust-clippy/pull/13168) + +### ICE Fixes + +* [`suboptimal_flops`]: No longer crashes on custom `.log()` functions + [#12884](https://github.com/rust-lang/rust-clippy/pull/12884) ## Rust 1.80 From 0dfe40f0a38ed31ff9ef0e14fd24c5585bb869cd Mon Sep 17 00:00:00 2001 From: Chayim Refael Friedman Date: Thu, 29 Aug 2024 22:58:26 +0300 Subject: [PATCH 0254/2194] Do not report missing unsafe on `addr_of[_mut]!(EXTERN_OR_MUT_STATIC)` The compiler no longer does as well; see https://github.com/rust-lang/rust/pull/125834. --- .../hir-ty/src/diagnostics/unsafe_check.rs | 8 ++++++ .../src/handlers/missing_unsafe.rs | 25 +++++++++++++++++++ .../crates/ide/src/hover/tests.rs | 12 ++++----- .../crates/test-utils/src/minicore.rs | 12 +++++++++ 4 files changed, 51 insertions(+), 6 deletions(-) diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/unsafe_check.rs b/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/unsafe_check.rs index 1582cbba88055..309e208a9aa86 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/unsafe_check.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/unsafe_check.rs @@ -5,6 +5,7 @@ use hir_def::{ body::Body, hir::{Expr, ExprId, UnaryOp}, resolver::{resolver_for_expr, ResolveValueResult, Resolver, ValueNs}, + type_ref::Rawness, DefWithBodyId, }; @@ -94,6 +95,13 @@ fn walk_unsafe( } resolver.reset_to_guard(g); } + Expr::Ref { expr, rawness: Rawness::RawPtr, mutability: _ } => { + if let Expr::Path(_) = body.exprs[*expr] { + // Do not report unsafe for `addr_of[_mut]!(EXTERN_OR_MUT_STATIC)`, + // see https://github.com/rust-lang/rust/pull/125834. + return; + } + } Expr::MethodCall { .. } => { if infer .method_resolution(current) diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/missing_unsafe.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/missing_unsafe.rs index 7407faee350b6..7e70a27f789bc 100644 --- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/missing_unsafe.rs +++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/missing_unsafe.rs @@ -188,6 +188,31 @@ fn main() { ); } + #[test] + fn no_unsafe_diagnostic_with_addr_of_static() { + check_diagnostics( + r#" +//- minicore: copy, addr_of + +use core::ptr::{addr_of, addr_of_mut}; + +extern "C" { + static EXTERN: i32; + static mut EXTERN_MUT: i32; +} +static mut STATIC_MUT: i32 = 0; + +fn main() { + let _x = addr_of!(EXTERN); + let _x = addr_of!(EXTERN_MUT); + let _x = addr_of!(STATIC_MUT); + let _x = addr_of_mut!(EXTERN_MUT); + let _x = addr_of_mut!(STATIC_MUT); +} +"#, + ); + } + #[test] fn no_missing_unsafe_diagnostic_with_safe_intrinsic() { check_diagnostics( diff --git a/src/tools/rust-analyzer/crates/ide/src/hover/tests.rs b/src/tools/rust-analyzer/crates/ide/src/hover/tests.rs index f2f83d538ccb9..d7ae6c7508789 100644 --- a/src/tools/rust-analyzer/crates/ide/src/hover/tests.rs +++ b/src/tools/rust-analyzer/crates/ide/src/hover/tests.rs @@ -483,8 +483,8 @@ fn main() { file_id: FileId( 1, ), - full_range: 632..867, - focus_range: 693..699, + full_range: 633..868, + focus_range: 694..700, name: "FnOnce", kind: Trait, container_name: "function", @@ -8479,8 +8479,8 @@ impl Iterator for S { file_id: FileId( 1, ), - full_range: 7801..8043, - focus_range: 7866..7872, + full_range: 7802..8044, + focus_range: 7867..7873, name: "Future", kind: Trait, container_name: "future", @@ -8493,8 +8493,8 @@ impl Iterator for S { file_id: FileId( 1, ), - full_range: 8673..9172, - focus_range: 8750..8758, + full_range: 8674..9173, + focus_range: 8751..8759, name: "Iterator", kind: Trait, container_name: "iterator", diff --git a/src/tools/rust-analyzer/crates/test-utils/src/minicore.rs b/src/tools/rust-analyzer/crates/test-utils/src/minicore.rs index 7e1518c25c71f..4b7e23388c7e9 100644 --- a/src/tools/rust-analyzer/crates/test-utils/src/minicore.rs +++ b/src/tools/rust-analyzer/crates/test-utils/src/minicore.rs @@ -65,6 +65,7 @@ //! todo: panic //! unimplemented: panic //! column: +//! addr_of: #![rustc_coherence_is_core] @@ -421,6 +422,17 @@ pub mod ptr { } // endregion:coerce_unsized // endregion:non_null + + // region:addr_of + #[rustc_macro_transparency = "semitransparent"] + pub macro addr_of($place:expr) { + &raw const $place + } + #[rustc_macro_transparency = "semitransparent"] + pub macro addr_of_mut($place:expr) { + &raw mut $place + } + // endregion:addr_of } pub mod ops { From 29ecaa1edf1b0dc04514852404ab2e87318d502b Mon Sep 17 00:00:00 2001 From: Ivar Scholten Date: Wed, 28 Aug 2024 11:30:09 +0200 Subject: [PATCH 0255/2194] fix: consider indentation in the "Generate impl" and "Generate trait impl" assists This makes the generated impl's indentation match the ADT it targets, improving formatting when using nested modules inside of the same file or when defining types inside of a function. --- .../ide-assists/src/handlers/generate_impl.rs | 89 ++++++++++++++++--- 1 file changed, 76 insertions(+), 13 deletions(-) diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_impl.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_impl.rs index 821783c283134..7b7dac9a3d6c4 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_impl.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_impl.rs @@ -1,10 +1,22 @@ use syntax::{ - ast::{self, make, AstNode, HasName}, + ast::{self, edit_in_place::Indent, make, AstNode, HasName}, ted, }; use crate::{utils, AssistContext, AssistId, AssistKind, Assists}; +fn insert_impl(impl_: ast::Impl, nominal: &ast::Adt) { + let indent = nominal.indent_level(); + ted::insert_all_raw( + ted::Position::after(nominal.syntax()), + vec![ + // Add a blank line after the ADT, and indentation for the impl to match the ADT + make::tokens::whitespace(&format!("\n\n{indent}")).into(), + impl_.syntax().clone().into(), + ], + ); +} + // Assist: generate_impl // // Adds a new inherent impl for a type. @@ -46,12 +58,7 @@ pub(crate) fn generate_impl(acc: &mut Assists, ctx: &AssistContext<'_>) -> Optio } } - // Add the impl after the adt - let nominal = edit.make_mut(nominal); - ted::insert_all_raw( - ted::Position::after(nominal.syntax()), - vec![make::tokens::blank_line().into(), impl_.syntax().clone().into()], - ); + insert_impl(impl_, &edit.make_mut(nominal)); }, ) } @@ -97,12 +104,7 @@ pub(crate) fn generate_trait_impl(acc: &mut Assists, ctx: &AssistContext<'_>) -> } } - // Add the impl after the adt - let nominal = edit.make_mut(nominal); - ted::insert_all_raw( - ted::Position::after(nominal.syntax()), - vec![make::tokens::blank_line().into(), impl_.syntax().clone().into()], - ); + insert_impl(impl_, &edit.make_mut(nominal)); }, ) } @@ -418,4 +420,65 @@ mod tests { "/// Has a lifetime parameter\nstruct Foo<'a, T: Foo<'a>> {}", ); } + + #[test] + fn add_impl_with_indent() { + check_assist( + generate_impl, + r#" + mod foo { + struct Bar$0 {} + } + "#, + r#" + mod foo { + struct Bar {} + + impl Bar {$0} + } + "#, + ); + } + + #[test] + fn add_impl_with_multiple_indent() { + check_assist( + generate_impl, + r#" + mod foo { + fn bar() { + struct Baz$0 {} + } + } + "#, + r#" + mod foo { + fn bar() { + struct Baz {} + + impl Baz {$0} + } + } + "#, + ); + } + + #[test] + fn add_trait_impl_with_indent() { + check_assist( + generate_trait_impl, + r#" + mod foo { + struct Bar$0 {} + } + "#, + r#" + mod foo { + struct Bar {} + + impl ${0:_} for Bar {} + } + "#, + ); + } } From cbc6910c35ddb682275c9ea83d94037cacc47a77 Mon Sep 17 00:00:00 2001 From: Fridtjof Stoldt Date: Thu, 29 Aug 2024 22:15:18 +0200 Subject: [PATCH 0256/2194] Changelog: Correct lint level Co-authored-by: Timo <30553356+y21@users.noreply.github.com> --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4364e0f7085c0..2488da057b58e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -41,7 +41,7 @@ Current stable, released 2024-09-05 [rust#120924](https://github.com/rust-lang/rust/pull/120924) * Renamed `overflow_check_conditional` to [`panicking_overflow_checks`] [#12944](https://github.com/rust-lang/rust-clippy/pull/12944) -* Moved [`panicking_overflow_checks`] to `correctness` (From `complexity` now warn-by-default) +* Moved [`panicking_overflow_checks`] to `correctness` (From `complexity` now deny-by-default) [#12944](https://github.com/rust-lang/rust-clippy/pull/12944) * Renamed `thread_local_initializer_can_be_made_const` to [`missing_const_for_thread_local`] [#12974](https://github.com/rust-lang/rust-clippy/pull/12974) From 4abb8e2d0d1821a98e77109dae4001a613229074 Mon Sep 17 00:00:00 2001 From: Matthew Giordano Date: Thu, 29 Aug 2024 13:26:39 -0700 Subject: [PATCH 0257/2194] fix new_cyclic_in for rc --- library/alloc/src/rc.rs | 127 +++++++++++++++++++++++++--------------- 1 file changed, 79 insertions(+), 48 deletions(-) diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rc.rs index 0afb138db8ada..726c0f2de9f25 100644 --- a/library/alloc/src/rc.rs +++ b/library/alloc/src/rc.rs @@ -687,54 +687,6 @@ impl Rc { } } - /// TODO: document - #[cfg(not(no_global_oom_handling))] - #[unstable(feature = "allocator_api", issue = "32838")] - pub fn new_cyclic_in(data_fn: F, alloc: A) -> Rc - where - F: FnOnce(&Weak) -> T, - { - // Construct the inner in the "uninitialized" state with a single - // weak reference. - let uninit_ptr: NonNull<_> = Box::leak( - Box::new_in(RcBox { - strong: Cell::new(0), - weak: Cell::new(1), - value: mem::MaybeUninit::::uninit(), - }), - alloc, - ) - .into(); - - let init_ptr: NonNull> = uninit_ptr.cast(); - - let weak = Weak { ptr: init_ptr, alloc: Global }; - - // It's important we don't give up ownership of the weak pointer, or - // else the memory might be freed by the time `data_fn` returns. If - // we really wanted to pass ownership, we could create an additional - // weak pointer for ourselves, but this would result in additional - // updates to the weak reference count which might not be necessary - // otherwise. - let data = data_fn(&weak); - - let strong = unsafe { - let inner = init_ptr.as_ptr(); - ptr::write(ptr::addr_of_mut!((*inner).value), data); - - let prev_value = (*inner).strong.get(); - debug_assert_eq!(prev_value, 0, "No prior strong references should exist"); - (*inner).strong.set(1); - - Rc::from_inner(init_ptr) - }; - - // Strong references should collectively own a shared weak reference, - // so don't run the destructor for our old weak reference. - mem::forget(weak); - strong - } - /// Constructs a new `Rc` with uninitialized contents in the provided allocator. /// /// # Examples @@ -2312,6 +2264,85 @@ impl Clone for Rc { } } +impl Rc { + /// Constructs a new `Rc` in the given allocator while giving you a `Weak` to the allocation, + /// to allow you to construct a `T` which holds a weak pointer to itself. + /// + /// Generally, a structure circularly referencing itself, either directly or + /// indirectly, should not hold a strong reference to itself to prevent a memory leak. + /// Using this function, you get access to the weak pointer during the + /// initialization of `T`, before the `Rc` is created, such that you can + /// clone and store it inside the `T`. + /// + /// `new_cyclic` first allocates the managed allocation for the `Rc`, + /// then calls your closure, giving it a `Weak` to this allocation, + /// and only afterwards completes the construction of the `Rc` by placing + /// the `T` returned from your closure into the allocation. + /// + /// Since the new `Rc` is not fully-constructed until `Rc::new_cyclic` + /// returns, calling [`upgrade`] on the weak reference inside your closure will + /// fail and result in a `None` value. + /// + /// # Panics + /// + /// If `data_fn` panics, the panic is propagated to the caller, and the + /// temporary [`Weak`] is dropped normally. + /// + /// # Examples + /// See [`new_cyclic`]. + /// + /// [`new_cyclic`]: Rc::new_cyclic + /// [`upgrade`]: Weak::upgrade + #[cfg(not(no_global_oom_handling))] + #[unstable(feature = "allocator_api", issue = "32838")] + pub fn new_cyclic_in(data_fn: F, alloc: A) -> Rc + where + F: FnOnce(&Weak) -> T, + { + // Note: comments and implementation are copied from Rc::new_cyclic. + + // Construct the inner in the "uninitialized" state with a single + // weak reference. + let uninit_ptr: NonNull<_> = Box::leak(Box::new_in( + RcBox { + strong: Cell::new(0), + weak: Cell::new(1), + value: mem::MaybeUninit::::uninit(), + }, + alloc.clone(), + )) + .into(); + + let init_ptr: NonNull> = uninit_ptr.cast(); + + let weak = Weak { ptr: init_ptr, alloc: alloc.clone() }; + + // It's important we don't give up ownership of the weak pointer, or + // else the memory might be freed by the time `data_fn` returns. If + // we really wanted to pass ownership, we could create an additional + // weak pointer for ourselves, but this would result in additional + // updates to the weak reference count which might not be necessary + // otherwise. + let data = data_fn(&weak); + + let strong = unsafe { + let inner = init_ptr.as_ptr(); + ptr::write(ptr::addr_of_mut!((*inner).value), data); + + let prev_value = (*inner).strong.get(); + debug_assert_eq!(prev_value, 0, "No prior strong references should exist"); + (*inner).strong.set(1); + + Rc::from_inner_in(init_ptr, alloc) + }; + + // Strong references should collectively own a shared weak reference, + // so don't run the destructor for our old weak reference. + mem::forget(weak); + strong + } +} + #[cfg(not(no_global_oom_handling))] #[stable(feature = "rust1", since = "1.0.0")] impl Default for Rc { From 2383cc991020b9dd678074072fcd3ed4f459eb6c Mon Sep 17 00:00:00 2001 From: Matthew Giordano Date: Thu, 29 Aug 2024 13:41:37 -0700 Subject: [PATCH 0258/2194] improve comments --- library/alloc/src/rc.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rc.rs index 726c0f2de9f25..f6d4174f5ebb5 100644 --- a/library/alloc/src/rc.rs +++ b/library/alloc/src/rc.rs @@ -2279,7 +2279,7 @@ impl Rc { /// and only afterwards completes the construction of the `Rc` by placing /// the `T` returned from your closure into the allocation. /// - /// Since the new `Rc` is not fully-constructed until `Rc::new_cyclic` + /// Since the new `Rc` is not fully-constructed until `Rc::new_cyclic_in` /// returns, calling [`upgrade`] on the weak reference inside your closure will /// fail and result in a `None` value. /// @@ -2289,6 +2289,7 @@ impl Rc { /// temporary [`Weak`] is dropped normally. /// /// # Examples + /// /// See [`new_cyclic`]. /// /// [`new_cyclic`]: Rc::new_cyclic From 68169d3103dca63330b7e3e0e03f41b43b3b0490 Mon Sep 17 00:00:00 2001 From: Matthew Giordano Date: Thu, 29 Aug 2024 13:41:57 -0700 Subject: [PATCH 0259/2194] add new_cyclic_in for Arc --- library/alloc/src/sync.rs | 93 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 93 insertions(+) diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs index 4a3522f1a641b..f808f3313297b 100644 --- a/library/alloc/src/sync.rs +++ b/library/alloc/src/sync.rs @@ -1322,6 +1322,99 @@ impl Arc<[mem::MaybeUninit], A> { } } +impl Arc { + /// Constructs a new `Arc` in the given allocator while giving you a `Weak` to the allocation, + /// to allow you to construct a `T` which holds a weak pointer to itself. + /// + /// Generally, a structure circularly referencing itself, either directly or + /// indirectly, should not hold a strong reference to itself to prevent a memory leak. + /// Using this function, you get access to the weak pointer during the + /// initialization of `T`, before the `Arc` is created, such that you can + /// clone and store it inside the `T`. + /// + /// `new_cyclic` first allocates the managed allocation for the `Arc`, + /// then calls your closure, giving it a `Weak` to this allocation, + /// and only afterwards completes the construction of the `Arc` by placing + /// the `T` returned from your closure into the allocation. + /// + /// Since the new `Arc` is not fully-constructed until `Arc::new_cyclic_in` + /// returns, calling [`upgrade`] on the weak reference inside your closure will + /// fail and result in a `None` value. + /// + /// # Panics + /// + /// If `data_fn` panics, the panic is propagated to the caller, and the + /// temporary [`Weak`] is dropped normally. + /// + /// # Example + /// + /// See [`new_cyclic`] + /// + /// [`new_cyclic`]: Arc::new_cyclic + /// [`upgrade`]: Weak::upgrade + #[cfg(not(no_global_oom_handling))] + #[inline] + #[stable(feature = "arc_new_cyclic", since = "1.60.0")] + pub fn new_cyclic_in(data_fn: F, alloc: A) -> Arc + where + F: FnOnce(&Weak) -> T, + { + // Note: these comments and much of the implementation is copied from Arc::new_cyclic. + + // Construct the inner in the "uninitialized" state with a single + // weak reference. + let uninit_ptr: NonNull<_> = Box::leak(Box::new_in( + ArcInner { + strong: atomic::AtomicUsize::new(0), + weak: atomic::AtomicUsize::new(1), + data: mem::MaybeUninit::::uninit(), + }, + alloc.clone(), + )) + .into(); + let init_ptr: NonNull> = uninit_ptr.cast(); + + let weak = Weak { ptr: init_ptr, alloc: alloc.clone() }; + + // It's important we don't give up ownership of the weak pointer, or + // else the memory might be freed by the time `data_fn` returns. If + // we really wanted to pass ownership, we could create an additional + // weak pointer for ourselves, but this would result in additional + // updates to the weak reference count which might not be necessary + // otherwise. + let data = data_fn(&weak); + + // Now we can properly initialize the inner value and turn our weak + // reference into a strong reference. + let strong = unsafe { + let inner = init_ptr.as_ptr(); + ptr::write(ptr::addr_of_mut!((*inner).data), data); + + // The above write to the data field must be visible to any threads which + // observe a non-zero strong count. Therefore we need at least "Release" ordering + // in order to synchronize with the `compare_exchange_weak` in `Weak::upgrade`. + // + // "Acquire" ordering is not required. When considering the possible behaviours + // of `data_fn` we only need to look at what it could do with a reference to a + // non-upgradeable `Weak`: + // - It can *clone* the `Weak`, increasing the weak reference count. + // - It can drop those clones, decreasing the weak reference count (but never to zero). + // + // These side effects do not impact us in any way, and no other side effects are + // possible with safe code alone. + let prev_value = (*inner).strong.fetch_add(1, Release); + debug_assert_eq!(prev_value, 0, "No prior strong references should exist"); + + Arc::from_inner_in(init_ptr, alloc) + }; + + // Strong references should collectively own a shared weak reference, + // so don't run the destructor for our old weak reference. + mem::forget(weak); + strong + } +} + impl Arc { /// Constructs an `Arc` from a raw pointer. /// From 016a2e30a950b52ddf9da2d5f679bbc038b4be00 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 27 Aug 2024 16:29:30 +1000 Subject: [PATCH 0260/2194] Remove unused features. --- compiler/rustc_mir_transform/src/lib.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs index 88094b44edf21..cd24b4437ad16 100644 --- a/compiler/rustc_mir_transform/src/lib.rs +++ b/compiler/rustc_mir_transform/src/lib.rs @@ -3,13 +3,11 @@ #![feature(box_patterns)] #![feature(const_type_name)] #![feature(cow_is_borrowed)] -#![feature(decl_macro)] #![feature(if_let_guard)] #![feature(impl_trait_in_assoc_type)] #![feature(let_chains)] #![feature(map_try_insert)] #![feature(never_type)] -#![feature(option_get_or_insert_default)] #![feature(round_char_boundary)] #![feature(try_blocks)] #![feature(yeet_expr)] From 016a709b2451ed120cb1317fc17ac27d3b0b5df6 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 27 Aug 2024 16:32:20 +1000 Subject: [PATCH 0261/2194] Condense `use rustc_*` declarations. No reason to have two of them listed separately, after modules. --- compiler/rustc_mir_transform/src/lib.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs index cd24b4437ad16..f65d835f59b17 100644 --- a/compiler/rustc_mir_transform/src/lib.rs +++ b/compiler/rustc_mir_transform/src/lib.rs @@ -18,6 +18,7 @@ extern crate tracing; use hir::ConstContext; use required_consts::RequiredConstsVisitor; +use rustc_const_eval::check_consts::{self, ConstCx}; use rustc_const_eval::util; use rustc_data_structures::fx::FxIndexSet; use rustc_data_structures::steal::Steal; @@ -34,6 +35,7 @@ use rustc_middle::mir::{ use rustc_middle::ty::{self, TyCtxt, TypeVisitableExt}; use rustc_middle::util::Providers; use rustc_middle::{bug, query, span_bug}; +use rustc_mir_dataflow::rustc_peek; use rustc_span::source_map::Spanned; use rustc_span::{sym, DUMMY_SP}; use rustc_trait_selection::traits; @@ -108,9 +110,6 @@ mod unreachable_enum_branching; mod unreachable_prop; mod validate; -use rustc_const_eval::check_consts::{self, ConstCx}; -use rustc_mir_dataflow::rustc_peek; - rustc_fluent_macro::fluent_messages! { "../messages.ftl" } pub fn provide(providers: &mut Providers) { From fda52b8f63db5a2530f245e15b8a5695a929e886 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 28 Aug 2024 08:18:30 +1000 Subject: [PATCH 0262/2194] Simplify a provider definition. --- compiler/rustc_mir_transform/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs index f65d835f59b17..ddefc1307d8e0 100644 --- a/compiler/rustc_mir_transform/src/lib.rs +++ b/compiler/rustc_mir_transform/src/lib.rs @@ -127,7 +127,7 @@ pub fn provide(providers: &mut Providers) { mir_coroutine_witnesses: coroutine::mir_coroutine_witnesses, optimized_mir, is_mir_available, - is_ctfe_mir_available: |tcx, did| is_mir_available(tcx, did), + is_ctfe_mir_available: is_mir_available, mir_callgraph_reachable: inline::cycle::mir_callgraph_reachable, mir_inliner_callees: inline::cycle::mir_inliner_callees, promoted_mir, From 2932e097f49901bd46dca835ff7a6ac000a94876 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 28 Aug 2024 08:24:20 +1000 Subject: [PATCH 0263/2194] Simplify creation of a set. --- compiler/rustc_mir_transform/src/lib.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs index ddefc1307d8e0..0289c32cdcfca 100644 --- a/compiler/rustc_mir_transform/src/lib.rs +++ b/compiler/rustc_mir_transform/src/lib.rs @@ -220,10 +220,8 @@ fn is_mir_available(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool { /// Finds the full set of `DefId`s within the current crate that have /// MIR associated with them. fn mir_keys(tcx: TyCtxt<'_>, (): ()) -> FxIndexSet { - let mut set = FxIndexSet::default(); - // All body-owners have MIR associated with them. - set.extend(tcx.hir().body_owners()); + let mut set: FxIndexSet<_> = tcx.hir().body_owners().collect(); // Additionally, tuple struct/variant constructors have MIR, but // they don't have a BodyId, so we need to build them separately. From 66b3585145ff543687b316d8374f352821296a17 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 28 Aug 2024 08:25:52 +1000 Subject: [PATCH 0264/2194] Simplify a pattern. --- compiler/rustc_mir_transform/src/lib.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs index 0289c32cdcfca..33274fedc3cd7 100644 --- a/compiler/rustc_mir_transform/src/lib.rs +++ b/compiler/rustc_mir_transform/src/lib.rs @@ -246,8 +246,7 @@ fn mir_const_qualif(tcx: TyCtxt<'_>, def: LocalDefId) -> ConstQualifs { // No need to const-check a non-const `fn`. match const_kind { - Some(ConstContext::Const { .. } | ConstContext::Static(_)) - | Some(ConstContext::ConstFn) => {} + Some(ConstContext::Const { .. } | ConstContext::Static(_) | ConstContext::ConstFn) => {} None => span_bug!( tcx.def_span(def), "`mir_const_qualif` should only be called on const fns and const items" From 3b6af9a451fc3bfef3d11967c927a8ef62037126 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 28 Aug 2024 10:34:42 +1000 Subject: [PATCH 0265/2194] Use a local variable. --- compiler/rustc_mir_transform/src/add_moves_for_packed_drops.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_mir_transform/src/add_moves_for_packed_drops.rs b/compiler/rustc_mir_transform/src/add_moves_for_packed_drops.rs index cd850e2d73189..be8b09cfb4e70 100644 --- a/compiler/rustc_mir_transform/src/add_moves_for_packed_drops.rs +++ b/compiler/rustc_mir_transform/src/add_moves_for_packed_drops.rs @@ -85,7 +85,7 @@ fn add_move_for_packed_drop<'tcx>( let source_info = terminator.source_info; let ty = place.ty(body, tcx).ty; - let temp = patch.new_temp(ty, terminator.source_info.span); + let temp = patch.new_temp(ty, source_info.span); let storage_dead_block = patch.new_block(BasicBlockData { statements: vec![Statement { source_info, kind: StatementKind::StorageDead(temp) }], From 5331280a2b1e44f42bf5f9b6dea08a4f9d3452cf Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 28 Aug 2024 12:40:09 +1000 Subject: [PATCH 0266/2194] Merge some `if`s. For more concise code. --- .../src/check_packed_ref.rs | 29 +++++++------------ compiler/rustc_mir_transform/src/coroutine.rs | 10 +++---- 2 files changed, 15 insertions(+), 24 deletions(-) diff --git a/compiler/rustc_mir_transform/src/check_packed_ref.rs b/compiler/rustc_mir_transform/src/check_packed_ref.rs index 9902002580aed..eb76a39be57ff 100644 --- a/compiler/rustc_mir_transform/src/check_packed_ref.rs +++ b/compiler/rustc_mir_transform/src/check_packed_ref.rs @@ -37,24 +37,17 @@ impl<'tcx> Visitor<'tcx> for PackedRefChecker<'_, 'tcx> { } fn visit_place(&mut self, place: &Place<'tcx>, context: PlaceContext, _location: Location) { - if context.is_borrow() { - if util::is_disaligned(self.tcx, self.body, self.param_env, *place) { - let def_id = self.body.source.instance.def_id(); - if let Some(impl_def_id) = self.tcx.impl_of_method(def_id) - && self.tcx.is_builtin_derived(impl_def_id) - { - // If we ever reach here it means that the generated derive - // code is somehow doing an unaligned reference, which it - // shouldn't do. - span_bug!( - self.source_info.span, - "builtin derive created an unaligned reference" - ); - } else { - self.tcx - .dcx() - .emit_err(errors::UnalignedPackedRef { span: self.source_info.span }); - } + if context.is_borrow() && util::is_disaligned(self.tcx, self.body, self.param_env, *place) { + let def_id = self.body.source.instance.def_id(); + if let Some(impl_def_id) = self.tcx.impl_of_method(def_id) + && self.tcx.is_builtin_derived(impl_def_id) + { + // If we ever reach here it means that the generated derive + // code is somehow doing an unaligned reference, which it + // shouldn't do. + span_bug!(self.source_info.span, "builtin derive created an unaligned reference"); + } else { + self.tcx.dcx().emit_err(errors::UnalignedPackedRef { span: self.source_info.span }); } } } diff --git a/compiler/rustc_mir_transform/src/coroutine.rs b/compiler/rustc_mir_transform/src/coroutine.rs index d9d2abc554a65..7dbad721d6d7b 100644 --- a/compiler/rustc_mir_transform/src/coroutine.rs +++ b/compiler/rustc_mir_transform/src/coroutine.rs @@ -1182,12 +1182,10 @@ fn elaborate_coroutine_drops<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { source_info, kind: TerminatorKind::Drop { place, target, unwind, replace: _ }, } => { - if let Some(local) = place.as_local() { - if local == SELF_ARG { - (target, unwind, source_info) - } else { - continue; - } + if let Some(local) = place.as_local() + && local == SELF_ARG + { + (target, unwind, source_info) } else { continue; } From d7cb1181dc29210af3c49e7be267b3423095fd3f Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 28 Aug 2024 13:08:02 +1000 Subject: [PATCH 0267/2194] Merge `DerefArgVisitor` and `PinArgVisitor`. They are almost identical, differing only in the `ProjectionElem` they insert. This commit merges them into a new type `SelfArgVisitor`. --- compiler/rustc_mir_transform/src/coroutine.rs | 54 +++---------------- 1 file changed, 7 insertions(+), 47 deletions(-) diff --git a/compiler/rustc_mir_transform/src/coroutine.rs b/compiler/rustc_mir_transform/src/coroutine.rs index 7dbad721d6d7b..99c6eee40e9c5 100644 --- a/compiler/rustc_mir_transform/src/coroutine.rs +++ b/compiler/rustc_mir_transform/src/coroutine.rs @@ -112,11 +112,12 @@ impl<'tcx> MutVisitor<'tcx> for RenameLocalVisitor<'tcx> { } } -struct DerefArgVisitor<'tcx> { +struct SelfArgVisitor<'tcx> { + elem: ProjectionElem>, tcx: TyCtxt<'tcx>, } -impl<'tcx> MutVisitor<'tcx> for DerefArgVisitor<'tcx> { +impl<'tcx> MutVisitor<'tcx> for SelfArgVisitor<'tcx> { fn tcx(&self) -> TyCtxt<'tcx> { self.tcx } @@ -129,49 +130,7 @@ impl<'tcx> MutVisitor<'tcx> for DerefArgVisitor<'tcx> { if place.local == SELF_ARG { replace_base( place, - Place { - local: SELF_ARG, - projection: self.tcx().mk_place_elems(&[ProjectionElem::Deref]), - }, - self.tcx, - ); - } else { - self.visit_local(&mut place.local, context, location); - - for elem in place.projection.iter() { - if let PlaceElem::Index(local) = elem { - assert_ne!(local, SELF_ARG); - } - } - } - } -} - -struct PinArgVisitor<'tcx> { - ref_coroutine_ty: Ty<'tcx>, - tcx: TyCtxt<'tcx>, -} - -impl<'tcx> MutVisitor<'tcx> for PinArgVisitor<'tcx> { - fn tcx(&self) -> TyCtxt<'tcx> { - self.tcx - } - - fn visit_local(&mut self, local: &mut Local, _: PlaceContext, _: Location) { - assert_ne!(*local, SELF_ARG); - } - - fn visit_place(&mut self, place: &mut Place<'tcx>, context: PlaceContext, location: Location) { - if place.local == SELF_ARG { - replace_base( - place, - Place { - local: SELF_ARG, - projection: self.tcx().mk_place_elems(&[ProjectionElem::Field( - FieldIdx::ZERO, - self.ref_coroutine_ty, - )]), - }, + Place { local: SELF_ARG, projection: self.tcx().mk_place_elems(&[self.elem]) }, self.tcx, ); } else { @@ -568,7 +527,7 @@ fn make_coroutine_state_argument_indirect<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Bo body.local_decls.raw[1].ty = ref_coroutine_ty; // Add a deref to accesses of the coroutine state - DerefArgVisitor { tcx }.visit_body(body); + SelfArgVisitor { tcx, elem: ProjectionElem::Deref }.visit_body(body); } fn make_coroutine_state_argument_pinned<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { @@ -583,7 +542,8 @@ fn make_coroutine_state_argument_pinned<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body body.local_decls.raw[1].ty = pin_ref_coroutine_ty; // Add the Pin field access to accesses of the coroutine state - PinArgVisitor { ref_coroutine_ty, tcx }.visit_body(body); + SelfArgVisitor { tcx, elem: ProjectionElem::Field(FieldIdx::ZERO, ref_coroutine_ty) } + .visit_body(body); } /// Allocates a new local and replaces all references of `local` with it. Returns the new local. From 408481f4d876e58ab2b4d520706cfe07b223dc6f Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 28 Aug 2024 13:17:49 +1000 Subject: [PATCH 0268/2194] Remove some unnecessary constants. These are just renamings of `CoroutineArgs` constants. --- compiler/rustc_mir_transform/src/coroutine.rs | 33 +++++++++---------- 1 file changed, 15 insertions(+), 18 deletions(-) diff --git a/compiler/rustc_mir_transform/src/coroutine.rs b/compiler/rustc_mir_transform/src/coroutine.rs index 99c6eee40e9c5..b9480d31e8857 100644 --- a/compiler/rustc_mir_transform/src/coroutine.rs +++ b/compiler/rustc_mir_transform/src/coroutine.rs @@ -156,15 +156,6 @@ fn replace_base<'tcx>(place: &mut Place<'tcx>, new_base: Place<'tcx>, tcx: TyCtx const SELF_ARG: Local = Local::from_u32(1); -/// Coroutine has not been resumed yet. -const UNRESUMED: usize = CoroutineArgs::UNRESUMED; -/// Coroutine has returned / is completed. -const RETURNED: usize = CoroutineArgs::RETURNED; -/// Coroutine has panicked and is poisoned. -const POISONED: usize = CoroutineArgs::POISONED; -/// Number of reserved variants of coroutine state. -const RESERVED_VARIANTS: usize = CoroutineArgs::RESERVED_VARIANTS; - /// A `yield` point in the coroutine. struct SuspensionPoint<'tcx> { /// State discriminant used when suspending or resuming at this point. @@ -475,7 +466,7 @@ impl<'tcx> MutVisitor<'tcx> for TransformVisitor<'tcx> { self.make_state(v, source_info, is_return, &mut data.statements); let state = if let Some((resume, mut resume_arg)) = resume { // Yield - let state = RESERVED_VARIANTS + self.suspension_points.len(); + let state = CoroutineArgs::RESERVED_VARIANTS + self.suspension_points.len(); // The resume arg target location might itself be remapped if its base local is // live across a yield. @@ -508,7 +499,7 @@ impl<'tcx> MutVisitor<'tcx> for TransformVisitor<'tcx> { VariantIdx::new(state) } else { // Return - VariantIdx::new(RETURNED) // state for returned + VariantIdx::new(CoroutineArgs::RETURNED) // state for returned }; data.statements.push(self.set_discr(state, source_info)); data.terminator_mut().kind = TerminatorKind::Return; @@ -1044,10 +1035,11 @@ fn compute_layout<'tcx>( // Build the coroutine variant field list. // Create a map from local indices to coroutine struct indices. let mut variant_fields: IndexVec> = - iter::repeat(IndexVec::new()).take(RESERVED_VARIANTS).collect(); + iter::repeat(IndexVec::new()).take(CoroutineArgs::RESERVED_VARIANTS).collect(); let mut remap = IndexVec::from_elem_n(None, saved_locals.domain_size()); for (suspension_point_idx, live_locals) in live_locals_at_suspension_points.iter().enumerate() { - let variant_index = VariantIdx::from(RESERVED_VARIANTS + suspension_point_idx); + let variant_index = + VariantIdx::from(CoroutineArgs::RESERVED_VARIANTS + suspension_point_idx); let mut fields = IndexVec::new(); for (idx, saved_local) in live_locals.iter().enumerate() { fields.push(saved_local); @@ -1194,7 +1186,7 @@ fn create_coroutine_drop_shim<'tcx>( let mut cases = create_cases(&mut body, transform, Operation::Drop); - cases.insert(0, (UNRESUMED, drop_clean)); + cases.insert(0, (CoroutineArgs::UNRESUMED, drop_clean)); // The returned state and the poisoned state fall through to the default // case which is just to return @@ -1344,7 +1336,9 @@ fn create_coroutine_resume_function<'tcx>( if can_unwind { let source_info = SourceInfo::outermost(body.span); let poison_block = body.basic_blocks_mut().push(BasicBlockData { - statements: vec![transform.set_discr(VariantIdx::new(POISONED), source_info)], + statements: vec![ + transform.set_discr(VariantIdx::new(CoroutineArgs::POISONED), source_info), + ], terminator: Some(Terminator { source_info, kind: TerminatorKind::UnwindResume }), is_cleanup: true, }); @@ -1376,13 +1370,16 @@ fn create_coroutine_resume_function<'tcx>( use rustc_middle::mir::AssertKind::{ResumedAfterPanic, ResumedAfterReturn}; // Jump to the entry point on the unresumed - cases.insert(0, (UNRESUMED, START_BLOCK)); + cases.insert(0, (CoroutineArgs::UNRESUMED, START_BLOCK)); // Panic when resumed on the returned or poisoned state if can_unwind { cases.insert( 1, - (POISONED, insert_panic_block(tcx, body, ResumedAfterPanic(transform.coroutine_kind))), + ( + CoroutineArgs::POISONED, + insert_panic_block(tcx, body, ResumedAfterPanic(transform.coroutine_kind)), + ), ); } @@ -1397,7 +1394,7 @@ fn create_coroutine_resume_function<'tcx>( transform.insert_none_ret_block(body) } }; - cases.insert(1, (RETURNED, block)); + cases.insert(1, (CoroutineArgs::RETURNED, block)); } insert_switch(body, cases, &transform, TerminatorKind::Unreachable); From 590a02173bba33fd7cd50bf9ae9061727ebe24ca Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 28 Aug 2024 13:47:22 +1000 Subject: [PATCH 0269/2194] Factor out some repetitive code. --- compiler/rustc_mir_transform/src/coroutine.rs | 119 ++++++------------ 1 file changed, 38 insertions(+), 81 deletions(-) diff --git a/compiler/rustc_mir_transform/src/coroutine.rs b/compiler/rustc_mir_transform/src/coroutine.rs index b9480d31e8857..8ee2b8cbb9cdf 100644 --- a/compiler/rustc_mir_transform/src/coroutine.rs +++ b/compiler/rustc_mir_transform/src/coroutine.rs @@ -63,7 +63,9 @@ use rustc_index::bit_set::{BitMatrix, BitSet, GrowableBitSet}; use rustc_index::{Idx, IndexVec}; use rustc_middle::mir::visit::{MutVisitor, PlaceContext, Visitor}; use rustc_middle::mir::*; -use rustc_middle::ty::{self, CoroutineArgs, CoroutineArgsExt, InstanceKind, Ty, TyCtxt}; +use rustc_middle::ty::{ + self, CoroutineArgs, CoroutineArgsExt, GenericArgsRef, InstanceKind, Ty, TyCtxt, +}; use rustc_middle::{bug, span_bug}; use rustc_mir_dataflow::impls::{ MaybeBorrowedLocals, MaybeLiveLocals, MaybeRequiresStorage, MaybeStorageLive, @@ -210,14 +212,10 @@ impl<'tcx> TransformVisitor<'tcx> { // `gen` continues return `None` CoroutineKind::Desugared(CoroutineDesugaring::Gen, _) => { let option_def_id = self.tcx.require_lang_item(LangItem::Option, None); - Rvalue::Aggregate( - Box::new(AggregateKind::Adt( - option_def_id, - VariantIdx::ZERO, - self.tcx.mk_args(&[self.old_yield_ty.into()]), - None, - None, - )), + make_aggregate_adt( + option_def_id, + VariantIdx::ZERO, + self.tcx.mk_args(&[self.old_yield_ty.into()]), IndexVec::new(), ) } @@ -266,64 +264,28 @@ impl<'tcx> TransformVisitor<'tcx> { is_return: bool, statements: &mut Vec>, ) { + const ZERO: VariantIdx = VariantIdx::ZERO; + const ONE: VariantIdx = VariantIdx::from_usize(1); let rvalue = match self.coroutine_kind { CoroutineKind::Desugared(CoroutineDesugaring::Async, _) => { let poll_def_id = self.tcx.require_lang_item(LangItem::Poll, None); let args = self.tcx.mk_args(&[self.old_ret_ty.into()]); - if is_return { - // Poll::Ready(val) - Rvalue::Aggregate( - Box::new(AggregateKind::Adt( - poll_def_id, - VariantIdx::ZERO, - args, - None, - None, - )), - IndexVec::from_raw(vec![val]), - ) + let (variant_idx, operands) = if is_return { + (ZERO, IndexVec::from_raw(vec![val])) // Poll::Ready(val) } else { - // Poll::Pending - Rvalue::Aggregate( - Box::new(AggregateKind::Adt( - poll_def_id, - VariantIdx::from_usize(1), - args, - None, - None, - )), - IndexVec::new(), - ) - } + (ONE, IndexVec::new()) // Poll::Pending + }; + make_aggregate_adt(poll_def_id, variant_idx, args, operands) } CoroutineKind::Desugared(CoroutineDesugaring::Gen, _) => { let option_def_id = self.tcx.require_lang_item(LangItem::Option, None); let args = self.tcx.mk_args(&[self.old_yield_ty.into()]); - if is_return { - // None - Rvalue::Aggregate( - Box::new(AggregateKind::Adt( - option_def_id, - VariantIdx::ZERO, - args, - None, - None, - )), - IndexVec::new(), - ) + let (variant_idx, operands) = if is_return { + (ZERO, IndexVec::new()) // None } else { - // Some(val) - Rvalue::Aggregate( - Box::new(AggregateKind::Adt( - option_def_id, - VariantIdx::from_usize(1), - args, - None, - None, - )), - IndexVec::from_raw(vec![val]), - ) - } + (ONE, IndexVec::from_raw(vec![val])) // Some(val) + }; + make_aggregate_adt(option_def_id, variant_idx, args, operands) } CoroutineKind::Desugared(CoroutineDesugaring::AsyncGen, _) => { if is_return { @@ -349,31 +311,17 @@ impl<'tcx> TransformVisitor<'tcx> { let coroutine_state_def_id = self.tcx.require_lang_item(LangItem::CoroutineState, None); let args = self.tcx.mk_args(&[self.old_yield_ty.into(), self.old_ret_ty.into()]); - if is_return { - // CoroutineState::Complete(val) - Rvalue::Aggregate( - Box::new(AggregateKind::Adt( - coroutine_state_def_id, - VariantIdx::from_usize(1), - args, - None, - None, - )), - IndexVec::from_raw(vec![val]), - ) + let variant_idx = if is_return { + ONE // CoroutineState::Complete(val) } else { - // CoroutineState::Yielded(val) - Rvalue::Aggregate( - Box::new(AggregateKind::Adt( - coroutine_state_def_id, - VariantIdx::ZERO, - args, - None, - None, - )), - IndexVec::from_raw(vec![val]), - ) - } + ZERO // CoroutineState::Yielded(val) + }; + make_aggregate_adt( + coroutine_state_def_id, + variant_idx, + args, + IndexVec::from_raw(vec![val]), + ) } }; @@ -509,6 +457,15 @@ impl<'tcx> MutVisitor<'tcx> for TransformVisitor<'tcx> { } } +fn make_aggregate_adt<'tcx>( + def_id: DefId, + variant_idx: VariantIdx, + args: GenericArgsRef<'tcx>, + operands: IndexVec>, +) -> Rvalue<'tcx> { + Rvalue::Aggregate(Box::new(AggregateKind::Adt(def_id, variant_idx, args, None, None)), operands) +} + fn make_coroutine_state_argument_indirect<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { let coroutine_ty = body.local_decls.raw[1].ty; From 243109e006c0ffade939db475524c1957dcae409 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 28 Aug 2024 13:54:13 +1000 Subject: [PATCH 0270/2194] Remove an unnecessary `continue`. --- compiler/rustc_mir_transform/src/coroutine.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/compiler/rustc_mir_transform/src/coroutine.rs b/compiler/rustc_mir_transform/src/coroutine.rs index 8ee2b8cbb9cdf..84c6a60fa23f9 100644 --- a/compiler/rustc_mir_transform/src/coroutine.rs +++ b/compiler/rustc_mir_transform/src/coroutine.rs @@ -558,8 +558,6 @@ fn transform_async_context<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { let local = eliminate_get_context_call(&mut body[bb]); replace_resume_ty_local(tcx, body, local, context_mut_ref); } - } else { - continue; } } TerminatorKind::Yield { resume_arg, .. } => { From 8541b0f1f39eac7d53bd5423289422a82bd19fdd Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 28 Aug 2024 13:56:17 +1000 Subject: [PATCH 0271/2194] Use `let`/`else` to reduce some indentation. --- compiler/rustc_mir_transform/src/coroutine.rs | 33 +++++++++---------- 1 file changed, 16 insertions(+), 17 deletions(-) diff --git a/compiler/rustc_mir_transform/src/coroutine.rs b/compiler/rustc_mir_transform/src/coroutine.rs index 84c6a60fa23f9..6d5597dde6749 100644 --- a/compiler/rustc_mir_transform/src/coroutine.rs +++ b/compiler/rustc_mir_transform/src/coroutine.rs @@ -570,24 +570,23 @@ fn transform_async_context<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { fn eliminate_get_context_call<'tcx>(bb_data: &mut BasicBlockData<'tcx>) -> Local { let terminator = bb_data.terminator.take().unwrap(); - if let TerminatorKind::Call { args, destination, target, .. } = terminator.kind { - let [arg] = *Box::try_from(args).unwrap(); - let local = arg.node.place().unwrap().local; - - let arg = Rvalue::Use(arg.node); - let assign = Statement { - source_info: terminator.source_info, - kind: StatementKind::Assign(Box::new((destination, arg))), - }; - bb_data.statements.push(assign); - bb_data.terminator = Some(Terminator { - source_info: terminator.source_info, - kind: TerminatorKind::Goto { target: target.unwrap() }, - }); - local - } else { + let TerminatorKind::Call { args, destination, target, .. } = terminator.kind else { bug!(); - } + }; + let [arg] = *Box::try_from(args).unwrap(); + let local = arg.node.place().unwrap().local; + + let arg = Rvalue::Use(arg.node); + let assign = Statement { + source_info: terminator.source_info, + kind: StatementKind::Assign(Box::new((destination, arg))), + }; + bb_data.statements.push(assign); + bb_data.terminator = Some(Terminator { + source_info: terminator.source_info, + kind: TerminatorKind::Goto { target: target.unwrap() }, + }); + local } #[cfg_attr(not(debug_assertions), allow(unused))] From 1fcfd57e2fbd59d2b4edbb6e3e86846646823357 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 30 Aug 2024 13:31:05 +1000 Subject: [PATCH 0272/2194] Remove `#[macro_use] extern crate tracing` from rustfmt helpers. --- src/format-diff/main.rs | 4 +--- src/git-rustfmt/main.rs | 4 +--- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/src/format-diff/main.rs b/src/format-diff/main.rs index f9eb70f6e0466..d8616c63df9df 100644 --- a/src/format-diff/main.rs +++ b/src/format-diff/main.rs @@ -4,12 +4,10 @@ #![deny(warnings)] -#[macro_use] -extern crate tracing; - use serde::{Deserialize, Serialize}; use serde_json as json; use thiserror::Error; +use tracing::debug; use tracing_subscriber::EnvFilter; use std::collections::HashSet; diff --git a/src/git-rustfmt/main.rs b/src/git-rustfmt/main.rs index 5674f40bef91f..b8b0432aa9595 100644 --- a/src/git-rustfmt/main.rs +++ b/src/git-rustfmt/main.rs @@ -2,9 +2,6 @@ // `rustc_driver`. #![feature(rustc_private)] -#[macro_use] -extern crate tracing; - use std::env; use std::io::stdout; use std::path::{Path, PathBuf}; @@ -13,6 +10,7 @@ use std::str::FromStr; use getopts::{Matches, Options}; use rustfmt_nightly as rustfmt; +use tracing::debug; use tracing_subscriber::EnvFilter; use crate::rustfmt::{load_config, CliOptions, FormatReportFormatterBuilder, Input, Session}; From c3beb056871f477c23462c4cf838759dc214dfe2 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 30 Aug 2024 13:35:05 +1000 Subject: [PATCH 0273/2194] Remove `#[macro_use] extern crate tracing` from rustfmt. --- src/attr.rs | 1 + src/chains.rs | 1 + src/closures.rs | 1 + src/comment.rs | 1 + src/expr.rs | 1 + src/formatting.rs | 1 + src/items.rs | 1 + src/lib.rs | 4 ++-- src/macros.rs | 1 + src/matches.rs | 1 + src/missed_spans.rs | 1 + src/modules/visitor.rs | 1 + src/overflow.rs | 1 + src/test/mod.rs | 1 + src/types.rs | 1 + src/visitor.rs | 1 + 16 files changed, 17 insertions(+), 2 deletions(-) diff --git a/src/attr.rs b/src/attr.rs index 433b92562023f..a2c0a28d66e09 100644 --- a/src/attr.rs +++ b/src/attr.rs @@ -3,6 +3,7 @@ use rustc_ast::ast; use rustc_ast::HasAttrs; use rustc_span::{symbol::sym, Span}; +use tracing::debug; use self::doc_comment::DocCommentFormatter; use crate::comment::{contains_comment, rewrite_doc_comment, CommentStyle}; diff --git a/src/chains.rs b/src/chains.rs index ea23690caed57..96fbe7a963a60 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -60,6 +60,7 @@ use std::cmp::min; use rustc_ast::{ast, ptr}; use rustc_span::{symbol, BytePos, Span}; +use tracing::debug; use crate::comment::{rewrite_comment, CharClasses, FullCodeCharKind, RichChar}; use crate::config::{IndentStyle, Version}; diff --git a/src/closures.rs b/src/closures.rs index 5bf29441b5421..b5c26235e7706 100644 --- a/src/closures.rs +++ b/src/closures.rs @@ -1,6 +1,7 @@ use rustc_ast::{ast, ptr}; use rustc_span::Span; use thin_vec::thin_vec; +use tracing::debug; use crate::attr::get_attrs_from_stmt; use crate::config::lists::*; diff --git a/src/comment.rs b/src/comment.rs index 24a5a1be2c398..e76be0fd162fa 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -4,6 +4,7 @@ use std::{borrow::Cow, iter}; use itertools::{multipeek, MultiPeek}; use rustc_span::Span; +use tracing::{debug, trace}; use crate::config::Config; use crate::rewrite::RewriteContext; diff --git a/src/expr.rs b/src/expr.rs index c7c4b680b07fd..6ba5217bc920d 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -5,6 +5,7 @@ use itertools::Itertools; use rustc_ast::token::{Delimiter, Lit, LitKind}; use rustc_ast::{ast, ptr, token, ForLoopKind, MatchKind}; use rustc_span::{BytePos, Span}; +use tracing::debug; use crate::chains::rewrite_chain; use crate::closures; diff --git a/src/formatting.rs b/src/formatting.rs index 7f442230b12be..5e71fe107eb65 100644 --- a/src/formatting.rs +++ b/src/formatting.rs @@ -6,6 +6,7 @@ use std::time::{Duration, Instant}; use rustc_ast::ast; use rustc_span::Span; +use tracing::debug; use self::newline_style::apply_newline_style; use crate::comment::{CharClasses, FullCodeCharKind}; diff --git a/src/items.rs b/src/items.rs index eb11604b2771f..cbf7ce90e37a3 100644 --- a/src/items.rs +++ b/src/items.rs @@ -7,6 +7,7 @@ use regex::Regex; use rustc_ast::visit; use rustc_ast::{ast, ptr}; use rustc_span::{symbol, BytePos, Span, DUMMY_SP}; +use tracing::debug; use crate::attr::filter_inline_attrs; use crate::comment::{ diff --git a/src/lib.rs b/src/lib.rs index ff2b14af07866..4263a49fd720d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -5,8 +5,8 @@ #![allow(clippy::match_like_matches_macro)] #![allow(unreachable_pub)] -#[macro_use] -extern crate tracing; +// #[macro_use] +// extern crate tracing; // N.B. these crates are loaded from the sysroot, so they need extern crate. extern crate rustc_ast; diff --git a/src/macros.rs b/src/macros.rs index a0582b061c050..b14b74a493814 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -20,6 +20,7 @@ use rustc_span::{ symbol::{self, kw}, BytePos, Span, Symbol, DUMMY_SP, }; +use tracing::debug; use crate::comment::{ contains_comment, CharClasses, FindUncommented, FullCodeCharKind, LineClasses, diff --git a/src/matches.rs b/src/matches.rs index e4fa077073c5b..30bf6271b2eba 100644 --- a/src/matches.rs +++ b/src/matches.rs @@ -4,6 +4,7 @@ use std::iter::repeat; use rustc_ast::{ast, ptr, MatchKind}; use rustc_span::{BytePos, Span}; +use tracing::debug; use crate::comment::{combine_strs_with_missing_comments, rewrite_comment, FindUncommented}; use crate::config::lists::*; diff --git a/src/missed_spans.rs b/src/missed_spans.rs index b1a7769c21bf4..56adb2e5e6916 100644 --- a/src/missed_spans.rs +++ b/src/missed_spans.rs @@ -1,4 +1,5 @@ use rustc_span::{BytePos, Pos, Span}; +use tracing::debug; use crate::comment::{is_last_comment_block, rewrite_comment, CodeCharKind, CommentCodeSlices}; use crate::config::file_lines::FileLines; diff --git a/src/modules/visitor.rs b/src/modules/visitor.rs index 3e05b6d0c5d49..8b46899eaf2e2 100644 --- a/src/modules/visitor.rs +++ b/src/modules/visitor.rs @@ -1,6 +1,7 @@ use rustc_ast::ast; use rustc_ast::visit::Visitor; use rustc_span::Symbol; +use tracing::debug; use crate::attr::MetaVisitor; use crate::parse::macros::cfg_if::parse_cfg_if; diff --git a/src/overflow.rs b/src/overflow.rs index a1de71a35be84..cdb735be8a4ce 100644 --- a/src/overflow.rs +++ b/src/overflow.rs @@ -6,6 +6,7 @@ use itertools::Itertools; use rustc_ast::token::Delimiter; use rustc_ast::{ast, ptr}; use rustc_span::Span; +use tracing::debug; use crate::closures; use crate::config::Version; diff --git a/src/test/mod.rs b/src/test/mod.rs index 7c563801c3243..286e8b8760a97 100644 --- a/src/test/mod.rs +++ b/src/test/mod.rs @@ -16,6 +16,7 @@ use crate::source_file; use crate::{is_nightly_channel, FormatReport, FormatReportFormatterBuilder, Input, Session}; use rustfmt_config_proc_macro::nightly_only_test; +use tracing::{debug, warn}; mod configuration_snippet; mod mod_resolver; diff --git a/src/types.rs b/src/types.rs index c826547e9d001..875c61113c528 100644 --- a/src/types.rs +++ b/src/types.rs @@ -3,6 +3,7 @@ use std::ops::Deref; use rustc_ast::ast::{self, FnRetTy, Mutability, Term}; use rustc_ast::ptr; use rustc_span::{symbol::kw, BytePos, Pos, Span}; +use tracing::debug; use crate::comment::{combine_strs_with_missing_comments, contains_comment}; use crate::config::lists::*; diff --git a/src/visitor.rs b/src/visitor.rs index 1de9f5a952493..ac68fc5fecf34 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -4,6 +4,7 @@ use std::rc::Rc; use rustc_ast::{ast, token::Delimiter, visit}; use rustc_data_structures::sync::Lrc; use rustc_span::{symbol, BytePos, Pos, Span}; +use tracing::debug; use crate::attr::*; use crate::comment::{contains_comment, rewrite_comment, CodeCharKind, CommentCodeSlices}; From ac7a293336e0f7afd993725e8d91f9ae7859ed89 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 30 Aug 2024 13:18:45 +1000 Subject: [PATCH 0274/2194] Avoid repeated interning in `SelfArgVisitor`. --- compiler/rustc_mir_transform/src/coroutine.rs | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/compiler/rustc_mir_transform/src/coroutine.rs b/compiler/rustc_mir_transform/src/coroutine.rs index 6d5597dde6749..954e6f25561f2 100644 --- a/compiler/rustc_mir_transform/src/coroutine.rs +++ b/compiler/rustc_mir_transform/src/coroutine.rs @@ -115,8 +115,14 @@ impl<'tcx> MutVisitor<'tcx> for RenameLocalVisitor<'tcx> { } struct SelfArgVisitor<'tcx> { - elem: ProjectionElem>, tcx: TyCtxt<'tcx>, + new_base: Place<'tcx>, +} + +impl<'tcx> SelfArgVisitor<'tcx> { + fn new(tcx: TyCtxt<'tcx>, elem: ProjectionElem>) -> Self { + Self { tcx, new_base: Place { local: SELF_ARG, projection: tcx.mk_place_elems(&[elem]) } } + } } impl<'tcx> MutVisitor<'tcx> for SelfArgVisitor<'tcx> { @@ -130,11 +136,7 @@ impl<'tcx> MutVisitor<'tcx> for SelfArgVisitor<'tcx> { fn visit_place(&mut self, place: &mut Place<'tcx>, context: PlaceContext, location: Location) { if place.local == SELF_ARG { - replace_base( - place, - Place { local: SELF_ARG, projection: self.tcx().mk_place_elems(&[self.elem]) }, - self.tcx, - ); + replace_base(place, self.new_base, self.tcx); } else { self.visit_local(&mut place.local, context, location); @@ -475,7 +477,7 @@ fn make_coroutine_state_argument_indirect<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Bo body.local_decls.raw[1].ty = ref_coroutine_ty; // Add a deref to accesses of the coroutine state - SelfArgVisitor { tcx, elem: ProjectionElem::Deref }.visit_body(body); + SelfArgVisitor::new(tcx, ProjectionElem::Deref).visit_body(body); } fn make_coroutine_state_argument_pinned<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { @@ -490,7 +492,7 @@ fn make_coroutine_state_argument_pinned<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body body.local_decls.raw[1].ty = pin_ref_coroutine_ty; // Add the Pin field access to accesses of the coroutine state - SelfArgVisitor { tcx, elem: ProjectionElem::Field(FieldIdx::ZERO, ref_coroutine_ty) } + SelfArgVisitor::new(tcx, ProjectionElem::Field(FieldIdx::ZERO, ref_coroutine_ty)) .visit_body(body); } From f41e0bb41d5e038b3bc6fd4b0ba6d03f048df5e4 Mon Sep 17 00:00:00 2001 From: Yuri Astrakhan Date: Fri, 26 Jul 2024 17:33:59 -0400 Subject: [PATCH 0275/2194] Squashed `aarch64_unknown_nto_qnx700` support --- compiler/rustc_target/src/spec/mod.rs | 1 + .../targets/aarch64_unknown_nto_qnx700.rs | 38 +++++++++++++++++++ .../targets/aarch64_unknown_nto_qnx710.rs | 37 +++--------------- library/std/Cargo.toml | 2 +- library/std/src/sys/pal/unix/fs.rs | 2 +- .../src/sys/pal/unix/process/process_unix.rs | 11 ++++-- library/unwind/src/lib.rs | 11 +++++- src/doc/rustc/src/platform-support.md | 1 + src/doc/rustc/src/platform-support/nto-qnx.md | 18 +++++++++ tests/assembly/targets/targets-elf.rs | 3 ++ 10 files changed, 84 insertions(+), 40 deletions(-) create mode 100644 compiler/rustc_target/src/spec/targets/aarch64_unknown_nto_qnx700.rs diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index d5f227a84a4ca..3766501821957 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -1837,6 +1837,7 @@ supported_targets! { ("mips64-openwrt-linux-musl", mips64_openwrt_linux_musl), + ("aarch64-unknown-nto-qnx700", aarch64_unknown_nto_qnx700), ("aarch64-unknown-nto-qnx710", aarch64_unknown_nto_qnx710), ("x86_64-pc-nto-qnx710", x86_64_pc_nto_qnx710), ("i586-pc-nto-qnx700", i586_pc_nto_qnx700), diff --git a/compiler/rustc_target/src/spec/targets/aarch64_unknown_nto_qnx700.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_nto_qnx700.rs new file mode 100644 index 0000000000000..ac1bec02ec8ae --- /dev/null +++ b/compiler/rustc_target/src/spec/targets/aarch64_unknown_nto_qnx700.rs @@ -0,0 +1,38 @@ +use crate::spec::{base, Cc, LinkerFlavor, Lld, Target, TargetOptions}; + +pub fn target() -> Target { + // In QNX, libc does not provide a compatible ABI between versions. + // To distinguish between QNX versions, we needed a stable conditional compilation switch, + // which is why we needed to implement different targets in the compiler. + Target { + llvm_target: "aarch64-unknown-unknown".into(), + metadata: crate::spec::TargetMetadata { + description: Some("ARM64 QNX Neutrino 7.0 RTOS".into()), + tier: Some(3), + host_tools: Some(false), + std: Some(true), + }, + pointer_width: 64, + // from: https://llvm.org/docs/LangRef.html#data-layout + // e = little endian + // m:e = ELF mangling: Private symbols get a .L prefix + // i8:8:32 = 8-bit-integer, minimum_alignment=8, preferred_alignment=32 + // i16:16:32 = 16-bit-integer, minimum_alignment=16, preferred_alignment=32 + // i64:64 = 64-bit-integer, minimum_alignment=64, preferred_alignment=64 + // i128:128 = 128-bit-integer, minimum_alignment=128, preferred_alignment=128 + // n32:64 = 32 and 64 are native integer widths; Elements of this set are considered to support most general arithmetic operations efficiently. + // S128 = 128 bits are the natural alignment of the stack in bits. + data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128-Fn32".into(), + arch: "aarch64".into(), + options: TargetOptions { + features: "+v8a".into(), + max_atomic_width: Some(128), + pre_link_args: TargetOptions::link_args( + LinkerFlavor::Gnu(Cc::Yes, Lld::No), + &["-Vgcc_ntoaarch64le_cxx"], + ), + env: "nto70".into(), + ..base::nto_qnx::opts() + }, + } +} diff --git a/compiler/rustc_target/src/spec/targets/aarch64_unknown_nto_qnx710.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_nto_qnx710.rs index 0e5a0b9b9a545..65a1863eb391a 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_unknown_nto_qnx710.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_unknown_nto_qnx710.rs @@ -1,35 +1,8 @@ -use crate::spec::{base, Cc, LinkerFlavor, Lld, Target, TargetOptions}; +use crate::spec::Target; pub fn target() -> Target { - Target { - llvm_target: "aarch64-unknown-unknown".into(), - metadata: crate::spec::TargetMetadata { - description: Some("ARM64 QNX Neutrino 7.1 RTOS".into()), - tier: Some(3), - host_tools: Some(false), - std: Some(true), - }, - pointer_width: 64, - // from: https://llvm.org/docs/LangRef.html#data-layout - // e = little endian - // m:e = ELF mangling: Private symbols get a .L prefix - // i8:8:32 = 8-bit-integer, minimum_alignment=8, preferred_alignment=32 - // i16:16:32 = 16-bit-integer, minimum_alignment=16, preferred_alignment=32 - // i64:64 = 64-bit-integer, minimum_alignment=64, preferred_alignment=64 - // i128:128 = 128-bit-integer, minimum_alignment=128, preferred_alignment=128 - // n32:64 = 32 and 64 are native integer widths; Elements of this set are considered to support most general arithmetic operations efficiently. - // S128 = 128 bits are the natural alignment of the stack in bits. - data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128-Fn32".into(), - arch: "aarch64".into(), - options: TargetOptions { - features: "+v8a".into(), - max_atomic_width: Some(128), - pre_link_args: TargetOptions::link_args( - LinkerFlavor::Gnu(Cc::Yes, Lld::No), - &["-Vgcc_ntoaarch64le_cxx"], - ), - env: "nto71".into(), - ..base::nto_qnx::opts() - }, - } + let mut base = super::aarch64_unknown_nto_qnx700::target(); + base.metadata.description = Some("ARM64 QNX Neutrino 7.1 RTOS".into()); + base.options.env = "nto71".into(); + base } diff --git a/library/std/Cargo.toml b/library/std/Cargo.toml index 334c75df2315a..e8cb5734d8cea 100644 --- a/library/std/Cargo.toml +++ b/library/std/Cargo.toml @@ -35,7 +35,7 @@ miniz_oxide = { version = "0.7.0", optional = true, default-features = false } addr2line = { version = "0.22.0", optional = true, default-features = false } [target.'cfg(not(all(windows, target_env = "msvc")))'.dependencies] -libc = { version = "0.2.153", default-features = false, features = [ +libc = { version = "0.2.156", default-features = false, features = [ 'rustc-dep-of-std', ], public = true } diff --git a/library/std/src/sys/pal/unix/fs.rs b/library/std/src/sys/pal/unix/fs.rs index fc9d7e988835e..7fa147c9754b9 100644 --- a/library/std/src/sys/pal/unix/fs.rs +++ b/library/std/src/sys/pal/unix/fs.rs @@ -1717,7 +1717,7 @@ pub fn link(original: &Path, link: &Path) -> io::Result<()> { run_path_with_cstr(original, &|original| { run_path_with_cstr(link, &|link| { cfg_if::cfg_if! { - if #[cfg(any(target_os = "vxworks", target_os = "redox", target_os = "android", target_os = "espidf", target_os = "horizon", target_os = "vita"))] { + if #[cfg(any(target_os = "vxworks", target_os = "redox", target_os = "android", target_os = "espidf", target_os = "horizon", target_os = "vita", target_os = "nto"))] { // VxWorks, Redox and ESP-IDF lack `linkat`, so use `link` instead. POSIX leaves // it implementation-defined whether `link` follows symlinks, so rely on the // `symlink_hard_link` test in library/std/src/fs/tests.rs to check the behavior. diff --git a/library/std/src/sys/pal/unix/process/process_unix.rs b/library/std/src/sys/pal/unix/process/process_unix.rs index 5552e9ac97753..9d091f033e07f 100644 --- a/library/std/src/sys/pal/unix/process/process_unix.rs +++ b/library/std/src/sys/pal/unix/process/process_unix.rs @@ -19,7 +19,8 @@ use crate::sys::process::process_common::*; use crate::{fmt, mem, sys}; cfg_if::cfg_if! { - if #[cfg(all(target_os = "nto", target_env = "nto71"))] { + // This workaround is only needed for QNX 7.0 and 7.1. The bug should have been fixed in 8.0 + if #[cfg(any(target_env = "nto70", target_env = "nto71"))] { use crate::thread; use libc::{c_char, posix_spawn_file_actions_t, posix_spawnattr_t}; use crate::time::Duration; @@ -189,7 +190,8 @@ impl Command { #[cfg(not(any( target_os = "watchos", target_os = "tvos", - all(target_os = "nto", target_env = "nto71"), + target_env = "nto70", + target_env = "nto71" )))] unsafe fn do_fork(&mut self) -> Result { cvt(libc::fork()) @@ -199,7 +201,8 @@ impl Command { // or closed a file descriptor while the fork() was occurring". // Documentation says "... or try calling fork() again". This is what we do here. // See also https://www.qnx.com/developers/docs/7.1/#com.qnx.doc.neutrino.lib_ref/topic/f/fork.html - #[cfg(all(target_os = "nto", target_env = "nto71"))] + // This workaround is only needed for QNX 7.0 and 7.1. The bug should have been fixed in 8.0 + #[cfg(any(target_env = "nto70", target_env = "nto71"))] unsafe fn do_fork(&mut self) -> Result { use crate::sys::os::errno; @@ -537,7 +540,7 @@ impl Command { // or closed a file descriptor while the posix_spawn() was occurring". // Documentation says "... or try calling posix_spawn() again". This is what we do here. // See also http://www.qnx.com/developers/docs/7.1/#com.qnx.doc.neutrino.lib_ref/topic/p/posix_spawn.html - #[cfg(all(target_os = "nto", target_env = "nto71"))] + #[cfg(target_os = "nto")] unsafe fn retrying_libc_posix_spawnp( pid: *mut pid_t, file: *const c_char, diff --git a/library/unwind/src/lib.rs b/library/unwind/src/lib.rs index b3de71f29f394..250af912e072d 100644 --- a/library/unwind/src/lib.rs +++ b/library/unwind/src/lib.rs @@ -165,8 +165,15 @@ extern "C" {} extern "C" {} #[cfg(target_os = "nto")] -#[link(name = "gcc_s")] -extern "C" {} +cfg_if::cfg_if! { + if #[cfg(target_env = "nto70")] { + #[link(name = "gcc")] + extern "C" {} + } else { + #[link(name = "gcc_s")] + extern "C" {} + } +} #[cfg(target_os = "hurd")] #[link(name = "gcc_s")] diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md index 0d79e5f4114e3..a2641b227531a 100644 --- a/src/doc/rustc/src/platform-support.md +++ b/src/doc/rustc/src/platform-support.md @@ -256,6 +256,7 @@ target | std | host | notes [`aarch64-kmc-solid_asp3`](platform-support/kmc-solid.md) | ✓ | | ARM64 SOLID with TOPPERS/ASP3 [`aarch64-nintendo-switch-freestanding`](platform-support/aarch64-nintendo-switch-freestanding.md) | * | | ARM64 Nintendo Switch, Horizon [`aarch64-unknown-teeos`](platform-support/aarch64-unknown-teeos.md) | ? | | ARM64 TEEOS | +[`aarch64-unknown-nto-qnx700`](platform-support/nto-qnx.md) | ? | | ARM64 QNX Neutrino 7.0 RTOS | [`aarch64-unknown-nto-qnx710`](platform-support/nto-qnx.md) | ✓ | | ARM64 QNX Neutrino 7.1 RTOS | `aarch64-unknown-freebsd` | ✓ | ✓ | ARM64 FreeBSD [`aarch64-unknown-hermit`](platform-support/hermit.md) | ✓ | | ARM64 Hermit diff --git a/src/doc/rustc/src/platform-support/nto-qnx.md b/src/doc/rustc/src/platform-support/nto-qnx.md index 51a397a38d209..1c240d1255a3d 100644 --- a/src/doc/rustc/src/platform-support/nto-qnx.md +++ b/src/doc/rustc/src/platform-support/nto-qnx.md @@ -24,6 +24,7 @@ Currently, the following QNX Neutrino versions and compilation targets are suppo |----------------------|---------------------|:------------:|:----------------:| | 7.1 | AArch64 | ✓ | ✓ | | 7.1 | x86_64 | ✓ | ✓ | +| 7.0 | AArch64 | ? | ✓ | | 7.0 | x86 | | ✓ | Adding other architectures that are supported by QNX Neutrino is possible. @@ -43,6 +44,23 @@ When linking `no_std` applications, they must link against `libc.so` (see exampl required because applications always link against the `crt` library and `crt` depends on `libc.so`. This is done automatically when using the standard library. +### Disabling RELocation Read-Only (RELRO) + +While not recommended by default, some QNX kernel setups may require the `RELRO` to be disabled with `-C relro_level=off`, e.g. by adding it to the `.cargo/config.toml` file: + +```toml +[target.aarch64-unknown-nto-qnx700] +rustflags = ["-C", "relro_level=off"] +``` + +If your QNX kernel does not allow it, and `relro` is not disabled, running compiled binary would fail with `syntax error: ... unexpected` or similar. This is due to kernel trying to interpret compiled binary with `/bin/sh`, and obviously failing. To verify that this is really the case, run your binary with the `DL_DEBUG=all` env var, and look for this output. If you see it, you should disable `relro` as described above. + +```text +Resolution scope for Executable->/bin/sh: + Executable->/bin/sh + libc.so.4->/usr/lib/ldqnx-64.so.2 +``` + ### Small example application Small `no_std` example is shown below. Applications using the standard library work as well. diff --git a/tests/assembly/targets/targets-elf.rs b/tests/assembly/targets/targets-elf.rs index 6f0a200a08cf3..b0c5eec1fe490 100644 --- a/tests/assembly/targets/targets-elf.rs +++ b/tests/assembly/targets/targets-elf.rs @@ -54,6 +54,9 @@ //@ revisions: aarch64_unknown_none_softfloat //@ [aarch64_unknown_none_softfloat] compile-flags: --target aarch64-unknown-none-softfloat //@ [aarch64_unknown_none_softfloat] needs-llvm-components: aarch64 +//@ revisions: aarch64_unknown_nto_qnx700 +//@ [aarch64_unknown_nto_qnx700] compile-flags: --target aarch64-unknown-nto-qnx700 +//@ [aarch64_unknown_nto_qnx700] needs-llvm-components: aarch64 //@ revisions: aarch64_unknown_nto_qnx710 //@ [aarch64_unknown_nto_qnx710] compile-flags: --target aarch64-unknown-nto-qnx710 //@ [aarch64_unknown_nto_qnx710] needs-llvm-components: aarch64 From 21edc735170642d541adb5a2a4c07159e75f8cb0 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Fri, 30 Aug 2024 15:31:49 +1000 Subject: [PATCH 0276/2194] bootstrap: Try to track down why `initial_libdir` sometimes fails Determining this path occasionally fails locally for unknown reasons, resulting in the build failing with an unhelpful `StripPrefixError(())` panic message. In order to track down why that's happening, include some relevant information in the panic message when that failure occurs. --- src/bootstrap/src/lib.rs | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/src/bootstrap/src/lib.rs b/src/bootstrap/src/lib.rs index 268392c5fb118..4cb2e343730ca 100644 --- a/src/bootstrap/src/lib.rs +++ b/src/bootstrap/src/lib.rs @@ -332,14 +332,20 @@ impl Build { .trim() .to_string(); - let initial_libdir = initial_target_dir - .parent() - .unwrap() - .parent() - .unwrap() - .strip_prefix(&initial_sysroot) - .unwrap() - .to_path_buf(); + // FIXME(Zalathar): Determining this path occasionally fails locally for + // unknown reasons, so we print some extra context to help track down why. + let find_initial_libdir = || { + let initial_libdir = + initial_target_dir.parent()?.parent()?.strip_prefix(&initial_sysroot).ok()?; + Some(initial_libdir.to_path_buf()) + }; + let Some(initial_libdir) = find_initial_libdir() else { + panic!( + "couldn't determine `initial_libdir` \ + from target dir {initial_target_dir:?} \ + and sysroot {initial_sysroot:?}" + ) + }; let version = std::fs::read_to_string(src.join("src").join("version")) .expect("failed to read src/version"); From 0fba9b4dbb902617fee1e34bc2536c30c1c54e0e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Rakic?= Date: Wed, 28 Aug 2024 13:54:32 +0000 Subject: [PATCH 0277/2194] introduce `PrettyPrintMirOptions` for cosmetic MIR dump options initially starting with `-Z mir-include-spans` because we want them in the NLL mir dump pass --- src/base.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/base.rs b/src/base.rs index f1d885bf1bce8..4af4b39cc5b9e 100644 --- a/src/base.rs +++ b/src/base.rs @@ -44,8 +44,9 @@ pub(crate) fn codegen_fn<'tcx>( let _mir_guard = crate::PrintOnPanic(|| { let mut buf = Vec::new(); with_no_trimmed_paths!({ - rustc_middle::mir::pretty::write_mir_fn(tcx, mir, &mut |_, _| Ok(()), &mut buf) - .unwrap(); + use rustc_middle::mir::pretty; + let options = pretty::PrettyPrintMirOptions::from_cli(tcx); + pretty::write_mir_fn(tcx, mir, &mut |_, _| Ok(()), &mut buf, options).unwrap(); }); String::from_utf8_lossy(&buf).into_owned() }); From fff063ee77bad38ee908577e0f40c442e0ab97a3 Mon Sep 17 00:00:00 2001 From: cyrgani Date: Fri, 30 Aug 2024 12:13:33 +0200 Subject: [PATCH 0278/2194] add crashtests for several old unfixed ICEs --- tests/crashes/117460.rs | 8 +++++++ tests/crashes/119095.rs | 48 +++++++++++++++++++++++++++++++++++++++++ tests/crashes/126443.rs | 15 +++++++++++++ tests/crashes/128097.rs | 6 ++++++ 4 files changed, 77 insertions(+) create mode 100644 tests/crashes/117460.rs create mode 100644 tests/crashes/119095.rs create mode 100644 tests/crashes/126443.rs create mode 100644 tests/crashes/128097.rs diff --git a/tests/crashes/117460.rs b/tests/crashes/117460.rs new file mode 100644 index 0000000000000..4878a35ffe5fb --- /dev/null +++ b/tests/crashes/117460.rs @@ -0,0 +1,8 @@ +//@ known-bug: #117460 +#![feature(generic_const_exprs)] + +struct Matrix { + d: D, +} + +impl Matrix {} diff --git a/tests/crashes/119095.rs b/tests/crashes/119095.rs new file mode 100644 index 0000000000000..28742e0d5daea --- /dev/null +++ b/tests/crashes/119095.rs @@ -0,0 +1,48 @@ +//@ known-bug: #119095 +//@ compile-flags: --edition=2021 + +fn any() -> T { + loop {} +} + +trait Acquire { + type Connection; +} + +impl Acquire for &'static () { + type Connection = (); +} + +trait Unit {} +impl Unit for () {} + +fn get_connection() -> impl Unit +where + T: Acquire, + T::Connection: Unit, +{ + any::() +} + +fn main() { + let future = async { async { get_connection::<&'static ()>() }.await }; + + future.resolve_me(); +} + +trait ResolveMe { + fn resolve_me(self); +} + +impl ResolveMe for S +where + (): CheckSend, +{ + fn resolve_me(self) {} +} + +trait CheckSend {} +impl CheckSend for () where F: Send {} + +trait NeverImplemented {} +impl CheckSend for E where E: NeverImplemented {} diff --git a/tests/crashes/126443.rs b/tests/crashes/126443.rs new file mode 100644 index 0000000000000..fba779444f94c --- /dev/null +++ b/tests/crashes/126443.rs @@ -0,0 +1,15 @@ +//@ known-bug: #126443 +//@ compile-flags: -Copt-level=0 +#![feature(generic_const_exprs)] + +fn double_up() -> [(); M * 2] { + todo!() +} + +fn quadruple_up() -> [(); N * 2 * 2] { + double_up() +} + +fn main() { + quadruple_up::<0>(); +} diff --git a/tests/crashes/128097.rs b/tests/crashes/128097.rs new file mode 100644 index 0000000000000..6ffca640cbd6b --- /dev/null +++ b/tests/crashes/128097.rs @@ -0,0 +1,6 @@ +//@ known-bug: #128097 +#![feature(explicit_tail_calls)] +fn f(x: &mut ()) { + let _y: String; + become f(x); +} From 39e3adda53a01a90056392c1d75308a48a40024b Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Fri, 30 Aug 2024 12:27:04 +0200 Subject: [PATCH 0279/2194] Make `./x.py compiler/` aware of the crate's features --- src/bootstrap/src/core/build_steps/check.rs | 2 +- src/bootstrap/src/core/build_steps/clippy.rs | 2 +- src/bootstrap/src/core/build_steps/compile.rs | 5 +++-- src/bootstrap/src/core/build_steps/doc.rs | 2 +- src/bootstrap/src/core/build_steps/test.rs | 2 +- src/bootstrap/src/core/metadata.rs | 10 +++++++++- src/bootstrap/src/lib.rs | 19 ++++++++++++++----- 7 files changed, 30 insertions(+), 12 deletions(-) diff --git a/src/bootstrap/src/core/build_steps/check.rs b/src/bootstrap/src/core/build_steps/check.rs index 7f7faf077d047..ba12e64c4a26f 100644 --- a/src/bootstrap/src/core/build_steps/check.rs +++ b/src/bootstrap/src/core/build_steps/check.rs @@ -228,7 +228,7 @@ impl Step for Rustc { self.override_build_kind.unwrap_or(builder.kind), ); - rustc_cargo(builder, &mut cargo, target, &compiler); + rustc_cargo(builder, &mut cargo, target, &compiler, &self.crates); // For ./x.py clippy, don't run with --all-targets because // linting tests and benchmarks can produce very noisy results diff --git a/src/bootstrap/src/core/build_steps/clippy.rs b/src/bootstrap/src/core/build_steps/clippy.rs index a2bb03cd5ac81..a0992350722fe 100644 --- a/src/bootstrap/src/core/build_steps/clippy.rs +++ b/src/bootstrap/src/core/build_steps/clippy.rs @@ -197,7 +197,7 @@ impl Step for Rustc { Kind::Clippy, ); - rustc_cargo(builder, &mut cargo, target, &compiler); + rustc_cargo(builder, &mut cargo, target, &compiler, &self.crates); // Explicitly pass -p for all compiler crates -- this will force cargo // to also lint the tests/benches/examples for these crates, rather diff --git a/src/bootstrap/src/core/build_steps/compile.rs b/src/bootstrap/src/core/build_steps/compile.rs index edf18e2ebf33b..3d2f3a4b2e4ee 100644 --- a/src/bootstrap/src/core/build_steps/compile.rs +++ b/src/bootstrap/src/core/build_steps/compile.rs @@ -983,7 +983,7 @@ impl Step for Rustc { Kind::Build, ); - rustc_cargo(builder, &mut cargo, target, &compiler); + rustc_cargo(builder, &mut cargo, target, &compiler, &self.crates); // NB: all RUSTFLAGS should be added to `rustc_cargo()` so they will be // consistently applied by check/doc/test modes too. @@ -1042,10 +1042,11 @@ pub fn rustc_cargo( cargo: &mut Cargo, target: TargetSelection, compiler: &Compiler, + crates: &[String], ) { cargo .arg("--features") - .arg(builder.rustc_features(builder.kind, target)) + .arg(builder.rustc_features(builder.kind, target, crates)) .arg("--manifest-path") .arg(builder.src.join("compiler/rustc/Cargo.toml")); diff --git a/src/bootstrap/src/core/build_steps/doc.rs b/src/bootstrap/src/core/build_steps/doc.rs index ffb617c642baf..f604cdbe27914 100644 --- a/src/bootstrap/src/core/build_steps/doc.rs +++ b/src/bootstrap/src/core/build_steps/doc.rs @@ -826,7 +826,7 @@ impl Step for Rustc { // see https://github.com/rust-lang/rust/pull/122066#issuecomment-1983049222 // cargo.rustdocflag("--generate-link-to-definition"); - compile::rustc_cargo(builder, &mut cargo, target, &compiler); + compile::rustc_cargo(builder, &mut cargo, target, &compiler, &self.crates); cargo.arg("-Zskip-rustdoc-fingerprint"); // Only include compiler crates, no dependencies of those, such as `libc`. diff --git a/src/bootstrap/src/core/build_steps/test.rs b/src/bootstrap/src/core/build_steps/test.rs index cc01afd4c18c6..af5734de96944 100644 --- a/src/bootstrap/src/core/build_steps/test.rs +++ b/src/bootstrap/src/core/build_steps/test.rs @@ -2692,7 +2692,7 @@ impl Step for Crate { } } Mode::Rustc => { - compile::rustc_cargo(builder, &mut cargo, target, &compiler); + compile::rustc_cargo(builder, &mut cargo, target, &compiler, &self.crates); } _ => panic!("can only test libraries"), }; diff --git a/src/bootstrap/src/core/metadata.rs b/src/bootstrap/src/core/metadata.rs index 1016607fc8318..d665544f59339 100644 --- a/src/bootstrap/src/core/metadata.rs +++ b/src/bootstrap/src/core/metadata.rs @@ -1,3 +1,4 @@ +use std::collections::BTreeMap; use std::path::PathBuf; use serde_derive::Deserialize; @@ -21,6 +22,7 @@ struct Package { manifest_path: String, dependencies: Vec, targets: Vec, + features: BTreeMap>, } /// For more information, see the output of @@ -51,7 +53,13 @@ pub fn build(build: &mut Build) { .map(|dep| dep.name) .collect(); let has_lib = package.targets.iter().any(|t| t.kind.iter().any(|k| k == "lib")); - let krate = Crate { name: name.clone(), deps, path, has_lib }; + let krate = Crate { + name: name.clone(), + deps, + path, + has_lib, + features: package.features.keys().cloned().collect(), + }; let relative_path = krate.local_path(build); build.crates.insert(name.clone(), krate); let existing_path = build.crate_paths.insert(relative_path, name); diff --git a/src/bootstrap/src/lib.rs b/src/bootstrap/src/lib.rs index 268392c5fb118..fe013b0fd0211 100644 --- a/src/bootstrap/src/lib.rs +++ b/src/bootstrap/src/lib.rs @@ -183,6 +183,7 @@ struct Crate { deps: HashSet, path: PathBuf, has_lib: bool, + features: Vec, } impl Crate { @@ -666,16 +667,24 @@ impl Build { } /// Gets the space-separated set of activated features for the compiler. - fn rustc_features(&self, kind: Kind, target: TargetSelection) -> String { + fn rustc_features(&self, kind: Kind, target: TargetSelection, crates: &[String]) -> String { + let possible_features_by_crates: HashSet<_> = crates + .iter() + .flat_map(|krate| &self.crates[krate].features) + .map(std::ops::Deref::deref) + .collect(); + let check = |feature: &str| -> bool { + crates.is_empty() || possible_features_by_crates.contains(feature) + }; let mut features = vec![]; - if self.config.jemalloc { + if self.config.jemalloc && check("jemalloc") { features.push("jemalloc"); } - if self.config.llvm_enabled(target) || kind == Kind::Check { + if (self.config.llvm_enabled(target) || kind == Kind::Check) && check("llvm") { features.push("llvm"); } // keep in sync with `bootstrap/compile.rs:rustc_cargo_env` - if self.config.rustc_parallel { + if self.config.rustc_parallel && check("rustc_use_parallel_compiler") { features.push("rustc_use_parallel_compiler"); } @@ -684,7 +693,7 @@ impl Build { // which is everything (including debug/trace/etc.) // if its unset, if debug_assertions is on, then debug_logging will also be on // as well as tracing *ignoring* this feature when debug_assertions is on - if !self.config.rust_debug_logging { + if !self.config.rust_debug_logging && check("max_level_info") { features.push("max_level_info"); } From 9afdc3a1d21117232e73718bfb10b4d81570650b Mon Sep 17 00:00:00 2001 From: rami3l Date: Fri, 30 Aug 2024 19:46:32 +0800 Subject: [PATCH 0280/2194] fix(ide-completion): fix handling of `for` in `impl T for A` in function body --- .../ide-completion/src/completions/keyword.rs | 62 +++++++++++++++++++ .../ide-completion/src/context/analysis.rs | 24 +++++-- 2 files changed, 81 insertions(+), 5 deletions(-) diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/keyword.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/keyword.rs index 3f50cd55cb365..0acb87872f5e3 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/keyword.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/keyword.rs @@ -150,6 +150,68 @@ fn foo(a: A) { a.$0 } ); } + #[test] + fn for_in_impl() { + check_edit( + "for", + r#" +struct X; +impl X $0 {} +"#, + r#" +struct X; +impl X for $0 {} +"#, + ); + check_edit( + "for", + r#" +fn foo() { + struct X; + impl X $0 {} +} +"#, + r#" +fn foo() { + struct X; + impl X for $0 {} +} +"#, + ); + check_edit( + "for", + r#" +fn foo() { + struct X; + impl X $0 +} +"#, + r#" +fn foo() { + struct X; + impl X for $0 +} +"#, + ); + check_edit( + "for", + r#" +fn foo() { + struct X; + impl X { fn bar() { $0 } } +} +"#, + r#" +fn foo() { + struct X; + impl X { fn bar() { for $1 in $2 { + $0 +} } } +} +"#, + ); + } + #[test] fn let_semi() { cov_mark::check!(let_semi); diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/context/analysis.rs b/src/tools/rust-analyzer/crates/ide-completion/src/context/analysis.rs index ed359394f1c49..292c419498d16 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/context/analysis.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/context/analysis.rs @@ -1132,10 +1132,18 @@ fn classify_name_ref( ast::PathType(it) => make_path_kind_type(it.into()), ast::PathExpr(it) => { if let Some(p) = it.syntax().parent() { - if ast::ExprStmt::can_cast(p.kind()) { - if let Some(kind) = inbetween_body_and_decl_check(p) { - return Some(make_res(NameRefKind::Keyword(kind))); - } + let p_kind = p.kind(); + // The syntax node of interest, for which we want to check whether + // it is sandwiched between an item decl signature and its body. + let probe = if ast::ExprStmt::can_cast(p_kind) { + Some(p) + } else if ast::StmtList::can_cast(p_kind) { + Some(it.syntax().clone()) + } else { + None + }; + if let Some(kind) = probe.and_then(inbetween_body_and_decl_check) { + return Some(make_res(NameRefKind::Keyword(kind))); } } @@ -1199,7 +1207,13 @@ fn classify_name_ref( } } }, - ast::RecordExpr(it) => make_path_kind_expr(it.into()), + ast::RecordExpr(it) => { + // A record expression in this position is usually a result of parsing recovery, so check that + if let Some(kind) = inbetween_body_and_decl_check(it.syntax().clone()) { + return Some(make_res(NameRefKind::Keyword(kind))); + } + make_path_kind_expr(it.into()) + }, _ => return None, } }; From be33a2e1bd21dbb7d2a75ef949137e48d93e985e Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Fri, 30 Aug 2024 15:45:12 +0200 Subject: [PATCH 0281/2194] Improve inlay hint resolution reliability --- .../crates/ide/src/inlay_hints.rs | 398 ++++++++++-------- .../crates/ide/src/inlay_hints/adjustment.rs | 6 +- .../crates/ide/src/inlay_hints/bind_pat.rs | 1 + .../ide/src/inlay_hints/binding_mode.rs | 10 +- .../crates/ide/src/inlay_hints/chaining.rs | 1 + .../ide/src/inlay_hints/closing_brace.rs | 4 +- .../ide/src/inlay_hints/closure_captures.rs | 5 + .../crates/ide/src/inlay_hints/closure_ret.rs | 1 + .../ide/src/inlay_hints/discriminant.rs | 4 +- .../ide/src/inlay_hints/fn_lifetime_fn.rs | 8 +- .../ide/src/inlay_hints/generic_param.rs | 1 + .../ide/src/inlay_hints/implicit_drop.rs | 11 +- .../ide/src/inlay_hints/implicit_static.rs | 5 + .../crates/ide/src/inlay_hints/param_name.rs | 7 +- .../ide/src/inlay_hints/range_exclusive.rs | 5 + src/tools/rust-analyzer/crates/ide/src/lib.rs | 4 +- .../rust-analyzer/src/handlers/request.rs | 4 +- .../crates/rust-analyzer/src/lsp/ext.rs | 1 + .../crates/rust-analyzer/src/lsp/to_proto.rs | 20 +- .../rust-analyzer/docs/dev/lsp-extensions.md | 2 +- 20 files changed, 282 insertions(+), 216 deletions(-) diff --git a/src/tools/rust-analyzer/crates/ide/src/inlay_hints.rs b/src/tools/rust-analyzer/crates/ide/src/inlay_hints.rs index 6a5d5e26a4f05..93dd56a450d94 100644 --- a/src/tools/rust-analyzer/crates/ide/src/inlay_hints.rs +++ b/src/tools/rust-analyzer/crates/ide/src/inlay_hints.rs @@ -15,7 +15,7 @@ use span::{Edition, EditionedFileId}; use stdx::never; use syntax::{ ast::{self, AstNode}, - match_ast, NodeOrToken, SyntaxNode, TextRange, TextSize, + match_ast, NodeOrToken, SyntaxNode, TextRange, TextSize, WalkEvent, }; use text_edit::TextEdit; @@ -36,6 +36,192 @@ mod implicit_static; mod param_name; mod range_exclusive; +// Feature: Inlay Hints +// +// rust-analyzer shows additional information inline with the source code. +// Editors usually render this using read-only virtual text snippets interspersed with code. +// +// rust-analyzer by default shows hints for +// +// * types of local variables +// * names of function arguments +// * names of const generic parameters +// * types of chained expressions +// +// Optionally, one can enable additional hints for +// +// * return types of closure expressions +// * elided lifetimes +// * compiler inserted reborrows +// * names of generic type and lifetime parameters +// +// Note: inlay hints for function argument names are heuristically omitted to reduce noise and will not appear if +// any of the +// link:https://github.com/rust-lang/rust-analyzer/blob/6b8b8ff4c56118ddee6c531cde06add1aad4a6af/crates/ide/src/inlay_hints/param_name.rs#L92-L99[following criteria] +// are met: +// +// * the parameter name is a suffix of the function's name +// * the argument is a qualified constructing or call expression where the qualifier is an ADT +// * exact argument<->parameter match(ignoring leading underscore) or parameter is a prefix/suffix +// of argument with _ splitting it off +// * the parameter name starts with `ra_fixture` +// * the parameter name is a +// link:https://github.com/rust-lang/rust-analyzer/blob/6b8b8ff4c56118ddee6c531cde06add1aad4a6af/crates/ide/src/inlay_hints/param_name.rs#L200[well known name] +// in a unary function +// * the parameter name is a +// link:https://github.com/rust-lang/rust-analyzer/blob/6b8b8ff4c56118ddee6c531cde06add1aad4a6af/crates/ide/src/inlay_hints/param_name.rs#L201[single character] +// in a unary function +// +// image::https://user-images.githubusercontent.com/48062697/113020660-b5f98b80-917a-11eb-8d70-3be3fd558cdd.png[] +pub(crate) fn inlay_hints( + db: &RootDatabase, + file_id: FileId, + range_limit: Option, + config: &InlayHintsConfig, +) -> Vec { + let _p = tracing::info_span!("inlay_hints").entered(); + let sema = Semantics::new(db); + let file_id = sema + .attach_first_edition(file_id) + .unwrap_or_else(|| EditionedFileId::current_edition(file_id)); + let file = sema.parse(file_id); + let file = file.syntax(); + + let mut acc = Vec::new(); + + let Some(scope) = sema.scope(file) else { + return acc; + }; + let famous_defs = FamousDefs(&sema, scope.krate()); + + let parent_impl = &mut None; + let hints = |node| hints(&mut acc, parent_impl, &famous_defs, config, file_id, node); + match range_limit { + // FIXME: This can miss some hints that require the parent of the range to calculate + Some(range) => match file.covering_element(range) { + NodeOrToken::Token(_) => return acc, + NodeOrToken::Node(n) => n + .preorder() + .filter(|event| matches!(event, WalkEvent::Enter(node) if range.intersect(node.text_range()).is_some())) + .for_each(hints), + }, + None => file.preorder().for_each(hints), + }; + + acc +} + +pub(crate) fn inlay_hints_resolve( + db: &RootDatabase, + file_id: FileId, + resolve_range: TextRange, + hash: u64, + config: &InlayHintsConfig, + hasher: impl Fn(&InlayHint) -> u64, +) -> Option { + let _p = tracing::info_span!("inlay_hints_resolve").entered(); + let sema = Semantics::new(db); + let file_id = sema + .attach_first_edition(file_id) + .unwrap_or_else(|| EditionedFileId::current_edition(file_id)); + let file = sema.parse(file_id); + let file = file.syntax(); + + let scope = sema.scope(file)?; + let famous_defs = FamousDefs(&sema, scope.krate()); + let mut acc = Vec::new(); + + let parent_impl = &mut None; + let hints = |node| hints(&mut acc, parent_impl, &famous_defs, config, file_id, node); + + let mut res = file.clone(); + let res = loop { + res = match res.child_or_token_at_range(resolve_range) { + Some(NodeOrToken::Node(n)) if n.text_range() == resolve_range => break n, + Some(NodeOrToken::Node(n)) => n, + _ => break res, + }; + }; + res.preorder().for_each(hints); + acc.into_iter().find(|hint| hasher(hint) == hash) +} + +fn hints( + hints: &mut Vec, + parent_impl: &mut Option, + famous_defs @ FamousDefs(sema, _): &FamousDefs<'_, '_>, + config: &InlayHintsConfig, + file_id: EditionedFileId, + node: WalkEvent, +) { + let node = match node { + WalkEvent::Enter(node) => node, + WalkEvent::Leave(n) => { + if ast::Impl::can_cast(n.kind()) { + parent_impl.take(); + } + return; + } + }; + closing_brace::hints(hints, sema, config, file_id, node.clone()); + if let Some(any_has_generic_args) = ast::AnyHasGenericArgs::cast(node.clone()) { + generic_param::hints(hints, sema, config, any_has_generic_args); + } + + match_ast! { + match node { + ast::Expr(expr) => { + chaining::hints(hints, famous_defs, config, file_id, &expr); + adjustment::hints(hints, famous_defs, config, file_id, &expr); + match expr { + ast::Expr::CallExpr(it) => param_name::hints(hints, famous_defs, config, file_id, ast::Expr::from(it)), + ast::Expr::MethodCallExpr(it) => { + param_name::hints(hints, famous_defs, config, file_id, ast::Expr::from(it)) + } + ast::Expr::ClosureExpr(it) => { + closure_captures::hints(hints, famous_defs, config, file_id, it.clone()); + closure_ret::hints(hints, famous_defs, config, file_id, it) + }, + ast::Expr::RangeExpr(it) => range_exclusive::hints(hints, famous_defs, config, file_id, it), + _ => None, + } + }, + ast::Pat(it) => { + binding_mode::hints(hints, famous_defs, config, file_id, &it); + match it { + ast::Pat::IdentPat(it) => { + bind_pat::hints(hints, famous_defs, config, file_id, &it); + } + ast::Pat::RangePat(it) => { + range_exclusive::hints(hints, famous_defs, config, file_id, it); + } + _ => {} + } + Some(()) + }, + ast::Item(it) => match it { + // FIXME: record impl lifetimes so they aren't being reused in assoc item lifetime inlay hints + ast::Item::Impl(impl_) => { + *parent_impl = Some(impl_); + None + }, + ast::Item::Fn(it) => { + implicit_drop::hints(hints, famous_defs, config, file_id, &it); + fn_lifetime_fn::hints(hints, famous_defs, config, file_id, it) + }, + // static type elisions + ast::Item::Static(it) => implicit_static::hints(hints, famous_defs, config, file_id, Either::Left(it)), + ast::Item::Const(it) => implicit_static::hints(hints, famous_defs, config, file_id, Either::Right(it)), + ast::Item::Enum(it) => discriminant::enum_hints(hints, famous_defs, config, file_id, it), + _ => None, + }, + // FIXME: fn-ptr type, dyn fn type, and trait object type elisions + ast::Type(_) => None, + _ => None, + } + }; +} + #[derive(Clone, Debug, PartialEq, Eq)] pub struct InlayHintsConfig { pub render_colons: bool, @@ -162,6 +348,9 @@ pub struct InlayHint { pub label: InlayHintLabel, /// Text edit to apply when "accepting" this inlay hint. pub text_edit: Option, + /// Range to recompute inlay hints when trying to resolve for this hint. If this is none, the + /// hint does not support resolving. + pub resolve_parent: Option, } impl std::hash::Hash for InlayHint { @@ -186,6 +375,7 @@ impl InlayHint { position: InlayHintPosition::After, pad_left: false, pad_right: false, + resolve_parent: None, } } @@ -198,11 +388,12 @@ impl InlayHint { position: InlayHintPosition::Before, pad_left: false, pad_right: false, + resolve_parent: None, } } - pub fn needs_resolve(&self) -> bool { - self.text_edit.is_some() || self.label.needs_resolve() + pub fn needs_resolve(&self) -> Option { + self.resolve_parent.filter(|_| self.text_edit.is_some() || self.label.needs_resolve()) } } @@ -434,190 +625,6 @@ fn label_of_ty( Some(r) } -fn ty_to_text_edit( - sema: &Semantics<'_, RootDatabase>, - node_for_hint: &SyntaxNode, - ty: &hir::Type, - offset_to_insert: TextSize, - prefix: String, -) -> Option { - let scope = sema.scope(node_for_hint)?; - // FIXME: Limit the length and bail out on excess somehow? - let rendered = ty.display_source_code(scope.db, scope.module().into(), false).ok()?; - - let mut builder = TextEdit::builder(); - builder.insert(offset_to_insert, prefix); - builder.insert(offset_to_insert, rendered); - Some(builder.finish()) -} - -// Feature: Inlay Hints -// -// rust-analyzer shows additional information inline with the source code. -// Editors usually render this using read-only virtual text snippets interspersed with code. -// -// rust-analyzer by default shows hints for -// -// * types of local variables -// * names of function arguments -// * names of const generic parameters -// * types of chained expressions -// -// Optionally, one can enable additional hints for -// -// * return types of closure expressions -// * elided lifetimes -// * compiler inserted reborrows -// * names of generic type and lifetime parameters -// -// Note: inlay hints for function argument names are heuristically omitted to reduce noise and will not appear if -// any of the -// link:https://github.com/rust-lang/rust-analyzer/blob/6b8b8ff4c56118ddee6c531cde06add1aad4a6af/crates/ide/src/inlay_hints/param_name.rs#L92-L99[following criteria] -// are met: -// -// * the parameter name is a suffix of the function's name -// * the argument is a qualified constructing or call expression where the qualifier is an ADT -// * exact argument<->parameter match(ignoring leading underscore) or parameter is a prefix/suffix -// of argument with _ splitting it off -// * the parameter name starts with `ra_fixture` -// * the parameter name is a -// link:https://github.com/rust-lang/rust-analyzer/blob/6b8b8ff4c56118ddee6c531cde06add1aad4a6af/crates/ide/src/inlay_hints/param_name.rs#L200[well known name] -// in a unary function -// * the parameter name is a -// link:https://github.com/rust-lang/rust-analyzer/blob/6b8b8ff4c56118ddee6c531cde06add1aad4a6af/crates/ide/src/inlay_hints/param_name.rs#L201[single character] -// in a unary function -// -// image::https://user-images.githubusercontent.com/48062697/113020660-b5f98b80-917a-11eb-8d70-3be3fd558cdd.png[] -pub(crate) fn inlay_hints( - db: &RootDatabase, - file_id: FileId, - range_limit: Option, - config: &InlayHintsConfig, -) -> Vec { - let _p = tracing::info_span!("inlay_hints").entered(); - let sema = Semantics::new(db); - let file_id = sema - .attach_first_edition(file_id) - .unwrap_or_else(|| EditionedFileId::current_edition(file_id)); - let file = sema.parse(file_id); - let file = file.syntax(); - - let mut acc = Vec::new(); - - if let Some(scope) = sema.scope(file) { - let famous_defs = FamousDefs(&sema, scope.krate()); - - let hints = |node| hints(&mut acc, &famous_defs, config, file_id, node); - match range_limit { - Some(range) => match file.covering_element(range) { - NodeOrToken::Token(_) => return acc, - NodeOrToken::Node(n) => n - .descendants() - .filter(|descendant| range.intersect(descendant.text_range()).is_some()) - .for_each(hints), - }, - None => file.descendants().for_each(hints), - }; - } - - acc -} - -pub(crate) fn inlay_hints_resolve( - db: &RootDatabase, - file_id: FileId, - position: TextSize, - hash: u64, - config: &InlayHintsConfig, - hasher: impl Fn(&InlayHint) -> u64, -) -> Option { - let _p = tracing::info_span!("inlay_hints_resolve").entered(); - let sema = Semantics::new(db); - let file_id = sema - .attach_first_edition(file_id) - .unwrap_or_else(|| EditionedFileId::current_edition(file_id)); - let file = sema.parse(file_id); - let file = file.syntax(); - - let scope = sema.scope(file)?; - let famous_defs = FamousDefs(&sema, scope.krate()); - let mut acc = Vec::new(); - - let hints = |node| hints(&mut acc, &famous_defs, config, file_id, node); - let token = file.token_at_offset(position).left_biased()?; - if let Some(parent_block) = token.parent_ancestors().find_map(ast::BlockExpr::cast) { - parent_block.syntax().descendants().for_each(hints) - } else if let Some(parent_item) = token.parent_ancestors().find_map(ast::Item::cast) { - parent_item.syntax().descendants().for_each(hints) - } else { - return None; - } - - acc.into_iter().find(|hint| hasher(hint) == hash) -} - -fn hints( - hints: &mut Vec, - famous_defs @ FamousDefs(sema, _): &FamousDefs<'_, '_>, - config: &InlayHintsConfig, - file_id: EditionedFileId, - node: SyntaxNode, -) { - closing_brace::hints(hints, sema, config, file_id, node.clone()); - if let Some(any_has_generic_args) = ast::AnyHasGenericArgs::cast(node.clone()) { - generic_param::hints(hints, sema, config, any_has_generic_args); - } - match_ast! { - match node { - ast::Expr(expr) => { - chaining::hints(hints, famous_defs, config, file_id, &expr); - adjustment::hints(hints, sema, config, file_id, &expr); - match expr { - ast::Expr::CallExpr(it) => param_name::hints(hints, sema, config, ast::Expr::from(it)), - ast::Expr::MethodCallExpr(it) => { - param_name::hints(hints, sema, config, ast::Expr::from(it)) - } - ast::Expr::ClosureExpr(it) => { - closure_captures::hints(hints, famous_defs, config, file_id, it.clone()); - closure_ret::hints(hints, famous_defs, config, file_id, it) - }, - ast::Expr::RangeExpr(it) => range_exclusive::hints(hints, config, it), - _ => None, - } - }, - ast::Pat(it) => { - binding_mode::hints(hints, sema, config, &it); - match it { - ast::Pat::IdentPat(it) => { - bind_pat::hints(hints, famous_defs, config, file_id, &it); - } - ast::Pat::RangePat(it) => { - range_exclusive::hints(hints, config, it); - } - _ => {} - } - Some(()) - }, - ast::Item(it) => match it { - // FIXME: record impl lifetimes so they aren't being reused in assoc item lifetime inlay hints - ast::Item::Impl(_) => None, - ast::Item::Fn(it) => { - implicit_drop::hints(hints, sema, config, file_id, &it); - fn_lifetime_fn::hints(hints, config, it) - }, - // static type elisions - ast::Item::Static(it) => implicit_static::hints(hints, config, Either::Left(it)), - ast::Item::Const(it) => implicit_static::hints(hints, config, Either::Right(it)), - ast::Item::Enum(it) => discriminant::enum_hints(hints, famous_defs, config, file_id, it), - _ => None, - }, - // FIXME: fn-ptr type, dyn fn type, and trait object type elisions - ast::Type(_) => None, - _ => None, - } - }; -} - /// Checks if the type is an Iterator from std::iter and returns the iterator trait and the item type of the concrete iterator. fn hint_iterator( sema: &Semantics<'_, RootDatabase>, @@ -653,6 +660,23 @@ fn hint_iterator( None } +fn ty_to_text_edit( + sema: &Semantics<'_, RootDatabase>, + node_for_hint: &SyntaxNode, + ty: &hir::Type, + offset_to_insert: TextSize, + prefix: String, +) -> Option { + let scope = sema.scope(node_for_hint)?; + // FIXME: Limit the length and bail out on excess somehow? + let rendered = ty.display_source_code(scope.db, scope.module().into(), false).ok()?; + + let mut builder = TextEdit::builder(); + builder.insert(offset_to_insert, prefix); + builder.insert(offset_to_insert, rendered); + Some(builder.finish()) +} + fn closure_has_block_body(closure: &ast::ClosureExpr) -> bool { matches!(closure.body(), Some(ast::Expr::BlockExpr(_))) } diff --git a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/adjustment.rs b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/adjustment.rs index 31c1a991d53d7..dc390f8f67af8 100644 --- a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/adjustment.rs +++ b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/adjustment.rs @@ -6,9 +6,8 @@ use either::Either; use hir::{ Adjust, Adjustment, AutoBorrow, HirDisplay, Mutability, OverloadedDeref, PointerCast, Safety, - Semantics, }; -use ide_db::RootDatabase; +use ide_db::famous_defs::FamousDefs; use span::EditionedFileId; use stdx::never; @@ -24,7 +23,7 @@ use crate::{ pub(super) fn hints( acc: &mut Vec, - sema: &Semantics<'_, RootDatabase>, + FamousDefs(sema, _): &FamousDefs<'_, '_>, config: &InlayHintsConfig, file_id: EditionedFileId, expr: &ast::Expr, @@ -156,6 +155,7 @@ pub(super) fn hints( kind: InlayKind::Adjustment, label, text_edit: None, + resolve_parent: Some(expr.syntax().text_range()), }); } if !postfix && needs_inner_parens { diff --git a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/bind_pat.rs b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/bind_pat.rs index 82b0a6ffcf135..7a808fb4a929d 100644 --- a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/bind_pat.rs +++ b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/bind_pat.rs @@ -110,6 +110,7 @@ pub(super) fn hints( position: InlayHintPosition::After, pad_left: !render_colons, pad_right: false, + resolve_parent: Some(pat.syntax().text_range()), }); Some(()) diff --git a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/binding_mode.rs b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/binding_mode.rs index f27390ee898bb..d1c0677863db7 100644 --- a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/binding_mode.rs +++ b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/binding_mode.rs @@ -2,17 +2,19 @@ //! ```no_run //! let /* & */ (/* ref */ x,) = &(0,); //! ``` -use hir::{Mutability, Semantics}; -use ide_db::RootDatabase; +use hir::Mutability; +use ide_db::famous_defs::FamousDefs; +use span::EditionedFileId; use syntax::ast::{self, AstNode}; use crate::{InlayHint, InlayHintPosition, InlayHintsConfig, InlayKind}; pub(super) fn hints( acc: &mut Vec, - sema: &Semantics<'_, RootDatabase>, + FamousDefs(sema, _): &FamousDefs<'_, '_>, config: &InlayHintsConfig, + _file_id: EditionedFileId, pat: &ast::Pat, ) -> Option<()> { if !config.binding_mode_hints { @@ -57,6 +59,7 @@ pub(super) fn hints( position: InlayHintPosition::Before, pad_left: false, pad_right: mut_reference, + resolve_parent: Some(pat.syntax().text_range()), }); }); match pat { @@ -75,6 +78,7 @@ pub(super) fn hints( position: InlayHintPosition::Before, pad_left: false, pad_right: true, + resolve_parent: Some(pat.syntax().text_range()), }); } ast::Pat::OrPat(pat) if !pattern_adjustments.is_empty() && outer_paren_pat.is_none() => { diff --git a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/chaining.rs b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/chaining.rs index 35f4d46e187c4..df34e4aa2458d 100644 --- a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/chaining.rs +++ b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/chaining.rs @@ -67,6 +67,7 @@ pub(super) fn hints( position: InlayHintPosition::After, pad_left: true, pad_right: false, + resolve_parent: Some(expr.syntax().text_range()), }); } } diff --git a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/closing_brace.rs b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/closing_brace.rs index d78fd64bdf4dc..8af5bd5661a2d 100644 --- a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/closing_brace.rs +++ b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/closing_brace.rs @@ -18,12 +18,13 @@ pub(super) fn hints( sema: &Semantics<'_, RootDatabase>, config: &InlayHintsConfig, file_id: EditionedFileId, - mut node: SyntaxNode, + original_node: SyntaxNode, ) -> Option<()> { let min_lines = config.closing_brace_hints_min_lines?; let name = |it: ast::Name| it.syntax().text_range(); + let mut node = original_node.clone(); let mut closing_token; let (label, name_range) = if let Some(item_list) = ast::AssocItemList::cast(node.clone()) { closing_token = item_list.r_curly_token()?; @@ -145,6 +146,7 @@ pub(super) fn hints( position: InlayHintPosition::After, pad_left: true, pad_right: false, + resolve_parent: Some(original_node.text_range()), }); None diff --git a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/closure_captures.rs b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/closure_captures.rs index e87e10d8504ed..adf7cbc3656cd 100644 --- a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/closure_captures.rs +++ b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/closure_captures.rs @@ -40,6 +40,7 @@ pub(super) fn hints( position: InlayHintPosition::After, pad_left: false, pad_right: false, + resolve_parent: Some(closure.syntax().text_range()), }); range } @@ -52,6 +53,7 @@ pub(super) fn hints( position: InlayHintPosition::After, pad_left: false, pad_right: false, + resolve_parent: None, }); let last = captures.len() - 1; for (idx, capture) in captures.into_iter().enumerate() { @@ -85,6 +87,7 @@ pub(super) fn hints( position: InlayHintPosition::After, pad_left: false, pad_right: false, + resolve_parent: Some(closure.syntax().text_range()), }); if idx != last { @@ -96,6 +99,7 @@ pub(super) fn hints( position: InlayHintPosition::After, pad_left: false, pad_right: false, + resolve_parent: None, }); } } @@ -107,6 +111,7 @@ pub(super) fn hints( position: InlayHintPosition::After, pad_left: false, pad_right: true, + resolve_parent: None, }); Some(()) diff --git a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/closure_ret.rs b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/closure_ret.rs index 325c2040691b1..6827540fa82c0 100644 --- a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/closure_ret.rs +++ b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/closure_ret.rs @@ -72,6 +72,7 @@ pub(super) fn hints( position: InlayHintPosition::After, pad_left: false, pad_right: false, + resolve_parent: Some(closure.syntax().text_range()), }); Some(()) } diff --git a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/discriminant.rs b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/discriminant.rs index eca0ebe629f48..35b62878329fc 100644 --- a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/discriminant.rs +++ b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/discriminant.rs @@ -35,7 +35,7 @@ pub(super) fn enum_hints( return None; } for variant in enum_.variant_list()?.variants() { - variant_hints(acc, sema, &variant); + variant_hints(acc, sema, &enum_, &variant); } Some(()) } @@ -43,6 +43,7 @@ pub(super) fn enum_hints( fn variant_hints( acc: &mut Vec, sema: &Semantics<'_, RootDatabase>, + enum_: &ast::Enum, variant: &ast::Variant, ) -> Option<()> { if variant.expr().is_some() { @@ -90,6 +91,7 @@ fn variant_hints( position: InlayHintPosition::After, pad_left: false, pad_right: false, + resolve_parent: Some(enum_.syntax().text_range()), }); Some(()) diff --git a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/fn_lifetime_fn.rs b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/fn_lifetime_fn.rs index d3666754e2be9..4d35e71a06fe6 100644 --- a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/fn_lifetime_fn.rs +++ b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/fn_lifetime_fn.rs @@ -2,8 +2,9 @@ //! ```no_run //! fn example/* <'0> */(a: &/* '0 */()) {} //! ``` -use ide_db::{syntax_helpers::node_ext::walk_ty, FxHashMap}; +use ide_db::{famous_defs::FamousDefs, syntax_helpers::node_ext::walk_ty, FxHashMap}; use itertools::Itertools; +use span::EditionedFileId; use syntax::{ ast::{self, AstNode, HasGenericParams, HasName}, SyntaxToken, @@ -14,7 +15,9 @@ use crate::{InlayHint, InlayHintPosition, InlayHintsConfig, InlayKind, LifetimeE pub(super) fn hints( acc: &mut Vec, + FamousDefs(_, _): &FamousDefs<'_, '_>, config: &InlayHintsConfig, + _file_id: EditionedFileId, func: ast::Fn, ) -> Option<()> { if config.lifetime_elision_hints == LifetimeElisionHints::Never { @@ -29,6 +32,7 @@ pub(super) fn hints( position: InlayHintPosition::After, pad_left: false, pad_right: true, + resolve_parent: None, }; let param_list = func.param_list()?; @@ -195,6 +199,7 @@ pub(super) fn hints( position: InlayHintPosition::After, pad_left: false, pad_right: true, + resolve_parent: None, }); } (None, allocated_lifetimes) => acc.push(InlayHint { @@ -205,6 +210,7 @@ pub(super) fn hints( position: InlayHintPosition::After, pad_left: false, pad_right: false, + resolve_parent: None, }), } Some(()) diff --git a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/generic_param.rs b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/generic_param.rs index b60a80a8ac6b5..ed7ebc3b1e7ad 100644 --- a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/generic_param.rs +++ b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/generic_param.rs @@ -92,6 +92,7 @@ pub(crate) fn hints( kind: InlayKind::GenericParameter, label, text_edit: None, + resolve_parent: Some(node.syntax().text_range()), }) }); diff --git a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/implicit_drop.rs b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/implicit_drop.rs index b4695a2b3519a..dd4b3efeecfe1 100644 --- a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/implicit_drop.rs +++ b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/implicit_drop.rs @@ -8,9 +8,9 @@ use hir::{ db::{DefDatabase as _, HirDatabase as _}, mir::{MirSpan, TerminatorKind}, - ChalkTyInterner, DefWithBody, Semantics, + ChalkTyInterner, DefWithBody, }; -use ide_db::{FileRange, RootDatabase}; +use ide_db::{famous_defs::FamousDefs, FileRange}; use span::EditionedFileId; use syntax::{ @@ -22,16 +22,16 @@ use crate::{InlayHint, InlayHintLabel, InlayHintPosition, InlayHintsConfig, Inla pub(super) fn hints( acc: &mut Vec, - sema: &Semantics<'_, RootDatabase>, + FamousDefs(sema, _): &FamousDefs<'_, '_>, config: &InlayHintsConfig, file_id: EditionedFileId, - def: &ast::Fn, + node: &ast::Fn, ) -> Option<()> { if !config.implicit_drop_hints { return None; } - let def = sema.to_def(def)?; + let def = sema.to_def(node)?; let def: DefWithBody = def.into(); let (hir, source_map) = sema.db.body_with_source_map(def.into()); @@ -121,6 +121,7 @@ pub(super) fn hints( kind: InlayKind::Drop, label, text_edit: None, + resolve_parent: Some(node.syntax().text_range()), }) } } diff --git a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/implicit_static.rs b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/implicit_static.rs index 42223ddf580e3..8d422478cbfcc 100644 --- a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/implicit_static.rs +++ b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/implicit_static.rs @@ -3,6 +3,8 @@ //! static S: &/* 'static */str = ""; //! ``` use either::Either; +use ide_db::famous_defs::FamousDefs; +use span::EditionedFileId; use syntax::{ ast::{self, AstNode}, SyntaxKind, @@ -12,7 +14,9 @@ use crate::{InlayHint, InlayHintPosition, InlayHintsConfig, InlayKind, LifetimeE pub(super) fn hints( acc: &mut Vec, + FamousDefs(_sema, _): &FamousDefs<'_, '_>, config: &InlayHintsConfig, + _file_id: EditionedFileId, statik_or_const: Either, ) -> Option<()> { if config.lifetime_elision_hints != LifetimeElisionHints::Always { @@ -38,6 +42,7 @@ pub(super) fn hints( position: InlayHintPosition::After, pad_left: false, pad_right: true, + resolve_parent: None, }); } } diff --git a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/param_name.rs b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/param_name.rs index 0f3142ef3f88b..28b0fa6dd4d1a 100644 --- a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/param_name.rs +++ b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/param_name.rs @@ -7,8 +7,9 @@ use std::fmt::Display; use either::Either; use hir::{Callable, Semantics}; -use ide_db::RootDatabase; +use ide_db::{famous_defs::FamousDefs, RootDatabase}; +use span::EditionedFileId; use stdx::to_lower_snake_case; use syntax::{ ast::{self, AstNode, HasArgList, HasName, UnaryOp}, @@ -19,8 +20,9 @@ use crate::{InlayHint, InlayHintLabel, InlayHintPosition, InlayHintsConfig, Inla pub(super) fn hints( acc: &mut Vec, - sema: &Semantics<'_, RootDatabase>, + FamousDefs(sema, _): &FamousDefs<'_, '_>, config: &InlayHintsConfig, + _file_id: EditionedFileId, expr: ast::Expr, ) -> Option<()> { if !config.parameter_hints { @@ -60,6 +62,7 @@ pub(super) fn hints( position: InlayHintPosition::Before, pad_left: false, pad_right: true, + resolve_parent: Some(expr.syntax().text_range()), } }); diff --git a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/range_exclusive.rs b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/range_exclusive.rs index bfb92838857ca..de9b0e98a4beb 100644 --- a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/range_exclusive.rs +++ b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/range_exclusive.rs @@ -3,13 +3,17 @@ //! for i in 0../* < */10 {} //! if let ../* < */100 = 50 {} //! ``` +use ide_db::famous_defs::FamousDefs; +use span::EditionedFileId; use syntax::{ast, SyntaxToken, T}; use crate::{InlayHint, InlayHintsConfig}; pub(super) fn hints( acc: &mut Vec, + FamousDefs(_sema, _): &FamousDefs<'_, '_>, config: &InlayHintsConfig, + _file_id: EditionedFileId, range: impl ast::RangeItem, ) -> Option<()> { (config.range_exclusive_hints && range.end().is_some()) @@ -30,6 +34,7 @@ fn inlay_hint(token: SyntaxToken) -> InlayHint { kind: crate::InlayKind::RangeExclusive, label: crate::InlayHintLabel::from("<"), text_edit: None, + resolve_parent: None, } } diff --git a/src/tools/rust-analyzer/crates/ide/src/lib.rs b/src/tools/rust-analyzer/crates/ide/src/lib.rs index ba0aaae19c9fd..cdadfeea4b9a8 100644 --- a/src/tools/rust-analyzer/crates/ide/src/lib.rs +++ b/src/tools/rust-analyzer/crates/ide/src/lib.rs @@ -439,12 +439,12 @@ impl Analysis { &self, config: &InlayHintsConfig, file_id: FileId, - position: TextSize, + resolve_range: TextRange, hash: u64, hasher: impl Fn(&InlayHint) -> u64 + Send + UnwindSafe, ) -> Cancellable> { self.with_db(|db| { - inlay_hints::inlay_hints_resolve(db, file_id, position, hash, config, hasher) + inlay_hints::inlay_hints_resolve(db, file_id, resolve_range, hash, config, hasher) }) } diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/request.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/request.rs index 1ad5ff0c8cdc1..50df9dc876020 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/request.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/request.rs @@ -1602,14 +1602,14 @@ pub(crate) fn handle_inlay_hints_resolve( anyhow::ensure!(snap.file_exists(file_id), "Invalid LSP resolve data"); let line_index = snap.file_line_index(file_id)?; - let hint_position = from_proto::offset(&line_index, original_hint.position)?; + let range = from_proto::text_range(&line_index, resolve_data.resolve_range)?; let mut forced_resolve_inlay_hints_config = snap.config.inlay_hints(); forced_resolve_inlay_hints_config.fields_to_resolve = InlayFieldsToResolve::empty(); let resolve_hints = snap.analysis.inlay_hints_resolve( &forced_resolve_inlay_hints_config, file_id, - hint_position, + range, hash, |hint| { std::hash::BuildHasher::hash_one( diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/ext.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/ext.rs index 8d1a686dc4d41..ed6f16a17302b 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/ext.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/ext.rs @@ -819,6 +819,7 @@ pub struct InlayHintResolveData { pub file_id: u32, // This is a string instead of a u64 as javascript can't represent u64 fully pub hash: String, + pub resolve_range: lsp_types::Range, pub version: Option, } diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/to_proto.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/to_proto.rs index eb6bc2a9ce9b0..7eed9ce2f38a3 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/to_proto.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/to_proto.rs @@ -452,10 +452,13 @@ pub(crate) fn inlay_hint( file_id: FileId, mut inlay_hint: InlayHint, ) -> Cancellable { - let resolve_hash = inlay_hint.needs_resolve().then(|| { - std::hash::BuildHasher::hash_one( - &std::hash::BuildHasherDefault::::default(), - &inlay_hint, + let resolve_range_and_hash = inlay_hint.needs_resolve().map(|range| { + ( + range, + std::hash::BuildHasher::hash_one( + &std::hash::BuildHasherDefault::::default(), + &inlay_hint, + ), ) }); @@ -465,7 +468,7 @@ pub(crate) fn inlay_hint( .visual_studio_code_version() // https://github.com/microsoft/vscode/issues/193124 .map_or(true, |version| VersionReq::parse(">=1.86.0").unwrap().matches(version)) - && resolve_hash.is_some() + && resolve_range_and_hash.is_some() && fields_to_resolve.resolve_text_edits { something_to_resolve |= inlay_hint.text_edit.is_some(); @@ -477,16 +480,17 @@ pub(crate) fn inlay_hint( snap, fields_to_resolve, &mut something_to_resolve, - resolve_hash.is_some(), + resolve_range_and_hash.is_some(), inlay_hint.label, )?; - let data = match resolve_hash { - Some(hash) if something_to_resolve => Some( + let data = match resolve_range_and_hash { + Some((resolve_range, hash)) if something_to_resolve => Some( to_value(lsp_ext::InlayHintResolveData { file_id: file_id.index(), hash: hash.to_string(), version: snap.file_version(file_id), + resolve_range: range(line_index, resolve_range), }) .unwrap(), ), diff --git a/src/tools/rust-analyzer/docs/dev/lsp-extensions.md b/src/tools/rust-analyzer/docs/dev/lsp-extensions.md index 4786bd54d59be..68afacf2db5cb 100644 --- a/src/tools/rust-analyzer/docs/dev/lsp-extensions.md +++ b/src/tools/rust-analyzer/docs/dev/lsp-extensions.md @@ -1,5 +1,5 @@ tests/ui/single_match.rs:371:5 + | +LL | / match DATA { +LL | | DATA => println!(), +LL | | _ => {}, +LL | | } + | |_____^ help: try: `{ println!() }` + +error: this pattern is irrefutable, `match` is useless + --> tests/ui/single_match.rs:376:5 + | +LL | / match CONST_I32 { +LL | | CONST_I32 => println!(), +LL | | _ => {}, +LL | | } + | |_____^ help: try: `{ println!() }` + +error: this pattern is irrefutable, `match` is useless + --> tests/ui/single_match.rs:382:5 + | +LL | / match i { +LL | | i => { +LL | | let a = 1; +LL | | let b = 2; +LL | | }, +LL | | _ => {}, +LL | | } + | |_____^ + | +help: try + | +LL ~ { +LL + let a = 1; +LL + let b = 2; +LL + } + | + +error: aborting due to 23 previous errors diff --git a/tests/ui/single_match_else.fixed b/tests/ui/single_match_else.fixed index 163be16ad8be7..fb57411aaa426 100644 --- a/tests/ui/single_match_else.fixed +++ b/tests/ui/single_match_else.fixed @@ -171,3 +171,7 @@ fn issue_10808(bar: Option) { }, } } + +fn irrefutable_match() -> Option<&'static ExprNode> { + { Some(&NODE) } +} diff --git a/tests/ui/single_match_else.rs b/tests/ui/single_match_else.rs index 3f1fd2b31832f..2d9e877ee0fee 100644 --- a/tests/ui/single_match_else.rs +++ b/tests/ui/single_match_else.rs @@ -199,3 +199,13 @@ fn issue_10808(bar: Option) { }, } } + +fn irrefutable_match() -> Option<&'static ExprNode> { + match ExprNode::Butterflies { + ExprNode::Butterflies => Some(&NODE), + _ => { + let x = 5; + None + }, + } +} diff --git a/tests/ui/single_match_else.stderr b/tests/ui/single_match_else.stderr index 61c348260d05e..61209053fd0fc 100644 --- a/tests/ui/single_match_else.stderr +++ b/tests/ui/single_match_else.stderr @@ -197,5 +197,17 @@ LL + println!("None"); LL + } | -error: aborting due to 9 previous errors +error: this pattern is irrefutable, `match` is useless + --> tests/ui/single_match_else.rs:204:5 + | +LL | / match ExprNode::Butterflies { +LL | | ExprNode::Butterflies => Some(&NODE), +LL | | _ => { +LL | | let x = 5; +LL | | None +LL | | }, +LL | | } + | |_____^ help: try: `{ Some(&NODE) }` + +error: aborting due to 10 previous errors From 0d156f223a3fb389f813d8fdb0b588f95b3868aa Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 30 Aug 2024 18:27:11 +0200 Subject: [PATCH 0289/2194] Unify scraped examples with other code examples --- src/librustdoc/html/render/mod.rs | 33 ++--- src/librustdoc/html/sources.rs | 57 ++++++--- src/librustdoc/html/static/css/noscript.css | 4 + src/librustdoc/html/static/css/rustdoc.css | 115 +++++++----------- src/librustdoc/html/static/js/main.js | 9 +- .../html/static/js/scrape-examples.js | 3 +- .../html/templates/scraped_source.html | 29 +++++ src/librustdoc/html/templates/source.html | 14 +-- 8 files changed, 134 insertions(+), 130 deletions(-) create mode 100644 src/librustdoc/html/templates/scraped_source.html diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index 47f321a4c4a2a..0a18944977ff1 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -2445,28 +2445,6 @@ fn render_call_locations(mut w: W, cx: &mut Context<'_>, item: &c let needs_expansion = line_max - line_min > NUM_VISIBLE_LINES; let locations_encoded = serde_json::to_string(&line_ranges).unwrap(); - write!( - &mut w, - "

\ -
\ - {name} ({title})\ -
\ -
", - expanded_cls = if needs_expansion { "" } else { "expanded" }, - name = call_data.display_name, - url = init_url, - title = init_title, - // The locations are encoded as a data attribute, so they can be read - // later by the JS for interactions. - locations = Escape(&locations_encoded) - ) - .unwrap(); - - if line_ranges.len() > 1 { - w.write_str(r#" "#) - .unwrap(); - } - // Look for the example file in the source map if it exists, otherwise return a dummy span let file_span = (|| { let source_map = tcx.sess.source_map(); @@ -2497,9 +2475,16 @@ fn render_call_locations(mut w: W, cx: &mut Context<'_>, item: &c cx, &cx.root_path(), highlight::DecorationInfo(decoration_info), - sources::SourceContext::Embedded { offset: line_min, needs_expansion }, + sources::SourceContext::Embedded(sources::ScrapedInfo { + needs_prev_next_buttons: line_ranges.len() > 1, + needs_expansion, + offset: line_min, + name: &call_data.display_name, + url: init_url, + title: init_title, + locations: locations_encoded, + }), ); - w.write_str("
").unwrap(); true }; diff --git a/src/librustdoc/html/sources.rs b/src/librustdoc/html/sources.rs index 22f115f92cc86..2c5fc3bf66f09 100644 --- a/src/librustdoc/html/sources.rs +++ b/src/librustdoc/html/sources.rs @@ -289,9 +289,34 @@ where } } -pub(crate) enum SourceContext { +pub(crate) struct ScrapedInfo<'a> { + pub(crate) offset: usize, + pub(crate) needs_prev_next_buttons: bool, + pub(crate) name: &'a str, + pub(crate) url: &'a str, + pub(crate) title: &'a str, + pub(crate) locations: String, + pub(crate) needs_expansion: bool, +} + +#[derive(Template)] +#[template(path = "scraped_source.html")] +struct ScrapedSource<'a, Code: std::fmt::Display> { + info: ScrapedInfo<'a>, + lines: RangeInclusive, + code_html: Code, +} + +#[derive(Template)] +#[template(path = "source.html")] +struct Source { + lines: RangeInclusive, + code_html: Code, +} + +pub(crate) enum SourceContext<'a> { Standalone, - Embedded { offset: usize, needs_expansion: bool }, + Embedded(ScrapedInfo<'a>), } /// Wrapper struct to render the source code of a file. This will do things like @@ -303,23 +328,8 @@ pub(crate) fn print_src( context: &Context<'_>, root_path: &str, decoration_info: highlight::DecorationInfo, - source_context: SourceContext, + source_context: SourceContext<'_>, ) { - #[derive(Template)] - #[template(path = "source.html")] - struct Source { - embedded: bool, - needs_expansion: bool, - lines: RangeInclusive, - code_html: Code, - } - let lines = s.lines().count(); - let (embedded, needs_expansion, lines) = match source_context { - SourceContext::Standalone => (false, false, 1..=lines), - SourceContext::Embedded { offset, needs_expansion } => { - (true, needs_expansion, (1 + offset)..=(lines + offset)) - } - }; let current_href = context .href_from_span(clean::Span::new(file_span), false) .expect("only local crates should have sources emitted"); @@ -332,5 +342,14 @@ pub(crate) fn print_src( ); Ok(()) }); - Source { embedded, needs_expansion, lines, code_html: code }.render_into(&mut writer).unwrap(); + let lines = s.lines().count(); + match source_context { + SourceContext::Standalone => { + Source { lines: (1..=lines), code_html: code }.render_into(&mut writer).unwrap() + } + SourceContext::Embedded(info) => { + let lines = (1 + info.offset)..=(lines + info.offset); + ScrapedSource { info, lines, code_html: code }.render_into(&mut writer).unwrap(); + } + }; } diff --git a/src/librustdoc/html/static/css/noscript.css b/src/librustdoc/html/static/css/noscript.css index 86e8edad7032a..e62b16267f102 100644 --- a/src/librustdoc/html/static/css/noscript.css +++ b/src/librustdoc/html/static/css/noscript.css @@ -59,6 +59,8 @@ nav.sub { --copy-path-button-color: #999; --copy-path-img-filter: invert(50%); --copy-path-img-hover-filter: invert(35%); + --code-example-button-color: #7f7f7f; + --code-example-button-hover-color: #595959; --codeblock-error-hover-color: rgb(255, 0, 0); --codeblock-error-color: rgba(255, 0, 0, .5); --codeblock-ignore-hover-color: rgb(255, 142, 0); @@ -162,6 +164,8 @@ nav.sub { --copy-path-button-color: #999; --copy-path-img-filter: invert(50%); --copy-path-img-hover-filter: invert(65%); + --code-example-button-color: #7f7f7f; + --code-example-button-hover-color: #a5a5a5; --codeblock-error-hover-color: rgb(255, 0, 0); --codeblock-error-color: rgba(255, 0, 0, .5); --codeblock-ignore-hover-color: rgb(255, 142, 0); diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css index 28df8d3f011fe..1fad3cfd41e64 100644 --- a/src/librustdoc/html/static/css/rustdoc.css +++ b/src/librustdoc/html/static/css/rustdoc.css @@ -760,15 +760,30 @@ ul.block, .block li { flex-grow: 1; } -.rustdoc:not(.src) .example-wrap pre { +.scraped-example:not(.expanded) { + /* scrape-examples.js has a constant DEFAULT_MAX_LINES (call it N) for the number + * of lines shown in the un-expanded example code viewer. This pre needs to have + * a max-height equal to line-height * N. The line-height is currently 1.5em, + * and we include additional 10px for padding. */ + max-height: calc(1.5em * 5 + 10px); +} + +.rustdoc:not(.src) .scraped-example:not(.expanded) pre.src-line-numbers, +.rustdoc:not(.src) .scraped-example:not(.expanded) pre.rust { + padding-bottom: 0; + /* See above comment, should be the same max-height. */ + max-height: calc(1.5em * 5 + 10px); overflow: auto hidden; } +.rustdoc:not(.src) .example-wrap pre { + overflow: auto; +} + .rustdoc .example-wrap pre.example-line-numbers, .rustdoc .example-wrap pre.src-line-numbers { - flex-grow: 0; min-width: fit-content; /* prevent collapsing into nothing in truncated scraped examples */ - overflow: initial; + flex-grow: 0; text-align: right; -webkit-user-select: none; user-select: none; @@ -776,7 +791,7 @@ ul.block, .block li { color: var(--src-line-numbers-span-color); } -.rustdoc .example-wrap pre.src-line-numbers { +.rustdoc .scraped-example pre.src-line-numbers { padding: 14px 0; } .src-line-numbers a, .src-line-numbers span { @@ -1488,17 +1503,23 @@ instead, we check that it's not a "finger" cursor. .example-wrap .button-holder.keep-visible { visibility: visible; } -.example-wrap .button-holder .copy-button, .example-wrap .test-arrow { +.example-wrap .button-holder > * { background: var(--main-background-color); cursor: pointer; border-radius: var(--button-border-radius); height: var(--copy-path-height); width: var(--copy-path-width); + border: 0; + color: var(--code-example-button-color); } -.example-wrap .button-holder .copy-button { +.example-wrap .button-holder > *:hover { + color: var(--code-example-button-hover-color); +} +.example-wrap .button-holder > *:not(:first-child) { margin-left: var(--button-left-margin); +} +.example-wrap .button-holder .copy-button { padding: 2px 0 0 4px; - border: 0; } .example-wrap .button-holder .copy-button::before, .example-wrap .test-arrow::before { @@ -2334,99 +2355,41 @@ in src-script.js and main.js color: var(--scrape-example-help-hover-color); } -.scraped-example { - /* So .scraped-example-title can be positioned absolutely */ - position: relative; -} - -.scraped-example .code-wrapper { - position: relative; - display: flex; - flex-direction: row; - flex-wrap: wrap; - width: 100%; -} - -.scraped-example:not(.expanded) .code-wrapper { - /* scrape-examples.js has a constant DEFAULT_MAX_LINES (call it N) for the number - * of lines shown in the un-expanded example code viewer. This pre needs to have - * a max-height equal to line-height * N. The line-height is currently 1.5em, - * and we include additional 10px for padding. */ - max-height: calc(1.5em * 5 + 10px); -} - -.scraped-example:not(.expanded) .code-wrapper pre { - overflow-y: hidden; - padding-bottom: 0; - /* See above comment, should be the same max-height. */ - max-height: calc(1.5em * 5 + 10px); -} - -.more-scraped-examples .scraped-example:not(.expanded) .code-wrapper, -.more-scraped-examples .scraped-example:not(.expanded) .code-wrapper pre { - /* See above comment, except this height is based on HIDDEN_MAX_LINES. */ - max-height: calc(1.5em * 10 + 10px); -} - -.scraped-example .code-wrapper .next, -.scraped-example .code-wrapper .prev, -.scraped-example .code-wrapper .expand { - color: var(--main-color); - position: absolute; - top: 0.25em; - z-index: 1; - padding: 0; - background: none; - border: none; - /* iOS button gradient: https://stackoverflow.com/q/5438567 */ - -webkit-appearance: none; - opacity: 1; -} -.scraped-example .code-wrapper .prev { - right: 2.25em; -} -.scraped-example .code-wrapper .next { - right: 1.25em; -} -.scraped-example .code-wrapper .expand { - right: 0.25em; -} - -.scraped-example:not(.expanded) .code-wrapper::before, -.scraped-example:not(.expanded) .code-wrapper::after { +.scraped-example:not(.expanded)::before, +.scraped-example:not(.expanded)::after { content: " "; width: 100%; height: 5px; position: absolute; z-index: 1; } -.scraped-example:not(.expanded) .code-wrapper::before { +.scraped-example:not(.expanded)::before { top: 0; background: linear-gradient(to bottom, var(--scrape-example-code-wrapper-background-start), var(--scrape-example-code-wrapper-background-end)); } -.scraped-example:not(.expanded) .code-wrapper::after { +.scraped-example:not(.expanded)::after { bottom: 0; background: linear-gradient(to top, var(--scrape-example-code-wrapper-background-start), var(--scrape-example-code-wrapper-background-end)); } -.scraped-example .code-wrapper .example-wrap { +.scraped-example:not(.expanded) { width: 100%; overflow-y: hidden; margin-bottom: 0; } -.scraped-example:not(.expanded) .code-wrapper .example-wrap { +.scraped-example:not(.expanded) { overflow-x: hidden; } -.scraped-example .example-wrap .rust span.highlight { +.scraped-example .rust span.highlight { background: var(--scrape-example-code-line-highlight); } -.scraped-example .example-wrap .rust span.highlight.focus { +.scraped-example .rust span.highlight.focus { background: var(--scrape-example-code-line-highlight-focus); } @@ -2520,6 +2483,8 @@ by default. --copy-path-button-color: #999; --copy-path-img-filter: invert(50%); --copy-path-img-hover-filter: invert(35%); + --code-example-button-color: #7f7f7f; + --code-example-button-hover-color: #595959; --codeblock-error-hover-color: rgb(255, 0, 0); --codeblock-error-color: rgba(255, 0, 0, .5); --codeblock-ignore-hover-color: rgb(255, 142, 0); @@ -2622,6 +2587,8 @@ by default. --copy-path-button-color: #999; --copy-path-img-filter: invert(50%); --copy-path-img-hover-filter: invert(65%); + --code-example-button-color: #7f7f7f; + --code-example-button-hover-color: #a5a5a5; --codeblock-error-hover-color: rgb(255, 0, 0); --codeblock-error-color: rgba(255, 0, 0, .5); --codeblock-ignore-hover-color: rgb(255, 142, 0); @@ -2731,6 +2698,8 @@ Original by Dempfi (https://github.com/dempfi/ayu) --copy-path-button-color: #fff; --copy-path-img-filter: invert(70%); --copy-path-img-hover-filter: invert(100%); + --code-example-button-color: #b2b2b2; + --code-example-button-hover-color: #fff; --codeblock-error-hover-color: rgb(255, 0, 0); --codeblock-error-color: rgba(255, 0, 0, .5); --codeblock-ignore-hover-color: rgb(255, 142, 0); diff --git a/src/librustdoc/html/static/js/main.js b/src/librustdoc/html/static/js/main.js index 75f2a1418cd8f..848ffc28653bb 100644 --- a/src/librustdoc/html/static/js/main.js +++ b/src/librustdoc/html/static/js/main.js @@ -1855,8 +1855,13 @@ href="https://doc.rust-lang.org/${channel}/rustdoc/read-documentation/search.htm // Since the button will be added, no need to keep this listener around. elem.removeEventListener("mouseover", addCopyButton); - const parent = document.createElement("div"); - parent.className = "button-holder"; + // If this is a scrapped example, there will already be a "button-holder" element. + let parent = elem.querySelector(".button-holder"); + if (!parent) { + parent = document.createElement("div"); + parent.className = "button-holder"; + } + const runButton = elem.querySelector(".test-arrow"); if (runButton !== null) { // If there is a run button, we move it into the same div. diff --git a/src/librustdoc/html/static/js/scrape-examples.js b/src/librustdoc/html/static/js/scrape-examples.js index 7a3a9c5f34001..709a774892f5a 100644 --- a/src/librustdoc/html/static/js/scrape-examples.js +++ b/src/librustdoc/html/static/js/scrape-examples.js @@ -24,8 +24,7 @@ const line = Math.max(0, loc[0] - 1); scrollOffset = lines.children[line].offsetTop; } else { - const wrapper = elt.querySelector(".code-wrapper"); - const halfHeight = wrapper.offsetHeight / 2; + const halfHeight = elt.offsetHeight / 2; const offsetTop = lines.children[loc[0]].offsetTop; const lastLine = lines.children[loc[1]]; const offsetBot = lastLine.offsetTop + lastLine.offsetHeight; diff --git a/src/librustdoc/html/templates/scraped_source.html b/src/librustdoc/html/templates/scraped_source.html new file mode 100644 index 0000000000000..01abdd607e2ef --- /dev/null +++ b/src/librustdoc/html/templates/scraped_source.html @@ -0,0 +1,29 @@ +
+ {# https://developers.google.com/search/docs/crawling-indexing/robots-meta-tag#data-nosnippet-attr + Do not show "1 2 3 4 5 ..." in web search results. #} +
+        {% for line in lines.clone() %}
+            {# ~#}
+            {{line|safe}}
+        {% endfor %}
+    
{# #} +
 {# #}
+        
+            {{code_html|safe}}
+         {# #}
+    
{# #} +
+ {{info.name +}} ({{info.title}}) {# #} +
+ {% if info.needs_prev_next_buttons || info.needs_expansion %} +
+ {% if info.needs_prev_next_buttons %} + {# #} + + {% endif %} + {% if info.needs_expansion %} + + {% endif %} +
+ {% endif %} +
{# #} diff --git a/src/librustdoc/html/templates/source.html b/src/librustdoc/html/templates/source.html index 42d01277db2c2..60a47f1b5de7d 100644 --- a/src/librustdoc/html/templates/source.html +++ b/src/librustdoc/html/templates/source.html @@ -1,21 +1,15 @@ -
{# #} +
{# https://developers.google.com/search/docs/crawling-indexing/robots-meta-tag#data-nosnippet-attr Do not show "1 2 3 4 5 ..." in web search results. #}
         {% for line in lines.clone() %}
-            {% if embedded %}
-                {{line|safe}}
-            {%~ else %}
-                {{line|safe}}
-            {%~ endif %}
+            {# ~#}
+            {{line|safe}}
         {% endfor %}
     
{# #}
 {# #}
         
-            {% if needs_expansion %}
-                
-            {% endif %}
             {{code_html|safe}}
          {# #}
     
{# #} -
+
{# #} From 5b75f8a8927b2dfeaa5a35809c1d1f9a25cfc9b0 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sat, 31 Aug 2024 00:12:10 +0200 Subject: [PATCH 0290/2194] Update rustdoc GUI tests --- .../scrape-examples-button-focus.goml | 1 + tests/rustdoc-gui/scrape-examples-color.goml | 8 ++++---- tests/rustdoc-gui/scrape-examples-layout.goml | 20 +++++++++---------- 3 files changed, 15 insertions(+), 14 deletions(-) diff --git a/tests/rustdoc-gui/scrape-examples-button-focus.goml b/tests/rustdoc-gui/scrape-examples-button-focus.goml index af4293dfc0057..4950a48bf0c41 100644 --- a/tests/rustdoc-gui/scrape-examples-button-focus.goml +++ b/tests/rustdoc-gui/scrape-examples-button-focus.goml @@ -3,6 +3,7 @@ go-to: "file://" + |DOC_PATH| + "/scrape_examples/fn.test.html" // The next/prev buttons vertically scroll the code viewport between examples +move-cursor-to: ".scraped-example-list > .scraped-example" store-property: (".scraped-example-list > .scraped-example pre", {"scrollTop": initialScrollTop}) focus: ".scraped-example-list > .scraped-example .next" press-key: "Enter" diff --git a/tests/rustdoc-gui/scrape-examples-color.goml b/tests/rustdoc-gui/scrape-examples-color.goml index 588ba08a60c7a..8baf2edb79b23 100644 --- a/tests/rustdoc-gui/scrape-examples-color.goml +++ b/tests/rustdoc-gui/scrape-examples-color.goml @@ -10,10 +10,10 @@ define-function: ( block { call-function: ("switch-theme", {"theme": |theme|}) wait-for: ".more-examples-toggle" - assert-css: (".scraped-example .example-wrap .rust span.highlight:not(.focus)", { + assert-css: (".scraped-example .rust span.highlight:not(.focus)", { "background-color": |highlight|, }, ALL) - assert-css: (".scraped-example .example-wrap .rust span.highlight.focus", { + assert-css: (".scraped-example .rust span.highlight.focus", { "background-color": |highlight_focus|, }, ALL) @@ -67,11 +67,11 @@ define-function: ( [theme, background_color_start, background_color_end], block { call-function: ("switch-theme", {"theme": |theme|}) - assert-css: (".scraped-example:not(.expanded) .code-wrapper::before", { + assert-css: (".scraped-example:not(.expanded)::before", { "background-image": "linear-gradient(" + |background_color_start| + ", " + |background_color_end| + ")", }) - assert-css: (".scraped-example:not(.expanded) .code-wrapper::after", { + assert-css: (".scraped-example:not(.expanded)::after", { "background-image": "linear-gradient(to top, " + |background_color_start| + ", " + |background_color_end| + ")", }) diff --git a/tests/rustdoc-gui/scrape-examples-layout.goml b/tests/rustdoc-gui/scrape-examples-layout.goml index 4fc1c1ac065f4..036d66cc379dd 100644 --- a/tests/rustdoc-gui/scrape-examples-layout.goml +++ b/tests/rustdoc-gui/scrape-examples-layout.goml @@ -3,33 +3,33 @@ go-to: "file://" + |DOC_PATH| + "/scrape_examples/fn.test_many.html" // Check that it's not zero. assert-property-false: ( - ".more-scraped-examples .scraped-example .code-wrapper .src-line-numbers", + ".more-scraped-examples .scraped-example .src-line-numbers", {"clientWidth": "0"} ) // Check that examples with very long lines have the same width as ones that don't. store-property: ( - ".more-scraped-examples .scraped-example:nth-child(2) .code-wrapper .src-line-numbers", + ".more-scraped-examples .scraped-example:nth-child(2) .src-line-numbers", {"clientWidth": clientWidth}, ) assert-property: ( - ".more-scraped-examples .scraped-example:nth-child(3) .code-wrapper .src-line-numbers", + ".more-scraped-examples .scraped-example:nth-child(3) .src-line-numbers", {"clientWidth": |clientWidth|} ) assert-property: ( - ".more-scraped-examples .scraped-example:nth-child(4) .code-wrapper .src-line-numbers", + ".more-scraped-examples .scraped-example:nth-child(4) .src-line-numbers", {"clientWidth": |clientWidth|} ) assert-property: ( - ".more-scraped-examples .scraped-example:nth-child(5) .code-wrapper .src-line-numbers", + ".more-scraped-examples .scraped-example:nth-child(5) .src-line-numbers", {"clientWidth": |clientWidth|} ) assert-property: ( - ".more-scraped-examples .scraped-example:nth-child(6) .code-wrapper .src-line-numbers", + ".more-scraped-examples .scraped-example:nth-child(6) .src-line-numbers", {"clientWidth": |clientWidth|} ) @@ -39,10 +39,10 @@ assert-property: ( store-value: (offset_y, 4) // First with desktop -assert-position: (".scraped-example .code-wrapper", {"y": 226}) -assert-position: (".scraped-example .code-wrapper .prev", {"y": 226 + |offset_y|}) +assert-position: (".scraped-example", {"y": 226}) +assert-position: (".scraped-example .prev", {"y": 226 + |offset_y|}) // Then with mobile set-window-size: (600, 600) -assert-position: (".scraped-example .code-wrapper", {"y": 308}) -assert-position: (".scraped-example .code-wrapper .prev", {"y": 308 + |offset_y|}) +assert-position: (".scraped-example", {"y": 284}) +assert-position: (".scraped-example .prev", {"y": 284 + |offset_y|}) From 1350769f4796b88eca83568433448038178174cb Mon Sep 17 00:00:00 2001 From: Ali Bektas Date: Sat, 31 Aug 2024 03:01:54 +0200 Subject: [PATCH 0291/2194] Apply changes, fix path information in a comment in config.rs --- .../crates/rust-analyzer/src/config.rs | 8 +++----- .../rust-analyzer/src/handlers/notification.rs | 13 ------------- .../crates/rust-analyzer/src/reload.rs | 2 +- 3 files changed, 4 insertions(+), 19 deletions(-) diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs index 0a1bdf49bdbd2..c884216b3e3cd 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs @@ -62,12 +62,10 @@ mod patch_old_style; // To deprecate an option by replacing it with another name use `new_name | `old_name` so that we keep // parsing the old name. config_data! { - /// Configs that apply on a workspace-wide scope. There are 3 levels on which a global configuration can be configured - // FIXME: 1. and 3. should be split, some configs do not make sense per project + /// Configs that apply on a workspace-wide scope. There are 2 levels on which a global configuration can be configured /// - /// 1. `rust-analyzer.toml` file under user's config directory (e.g ~/.config/rust-analyzer.toml) + /// 1. `rust-analyzer.toml` file under user's config directory (e.g ~/.config/rust-analyzer/rust-analyzer.toml) /// 2. Client's own configurations (e.g `settings.json` on VS Code) - /// 3. `rust-analyzer.toml` file located at the workspace root /// /// A config is searched for by traversing a "config tree" in a bottom up fashion. It is chosen by the nearest first principle. global: struct GlobalDefaultConfigData <- GlobalConfigInput -> { @@ -532,7 +530,7 @@ config_data! { cargo_allTargets: bool = true, /// Automatically refresh project info via `cargo metadata` on /// `Cargo.toml` or `.cargo/config.toml` changes. - pub(crate) cargo_autoreload: bool = true, + cargo_autoreload: bool = true, /// Run build scripts (`build.rs`) for more precise code analysis. cargo_buildScripts_enable: bool = true, /// Specifies the invocation strategy to use when running the build scripts command. diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/notification.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/notification.rs index dc8d40e0ee075..e8d1a7e4df68f 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/notification.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/notification.rs @@ -145,13 +145,10 @@ pub(crate) fn handle_did_save_text_document( state: &mut GlobalState, params: DidSaveTextDocumentParams, ) -> anyhow::Result<()> { - let mut deps_change_processed = false; - if let Ok(vfs_path) = from_proto::vfs_path(¶ms.text_document.uri) { let snap = state.snapshot(); let file_id = snap.vfs_path_to_file_id(&vfs_path)?; let sr = snap.analysis.source_root_id(file_id)?; - deps_change_processed = true; if state.config.script_rebuild_on_save(Some(sr)) && state.build_deps_changed { state.build_deps_changed = false; @@ -199,16 +196,6 @@ pub(crate) fn handle_did_save_text_document( } } - if !deps_change_processed - && state.config.script_rebuild_on_save(None) - && state.build_deps_changed - { - state.build_deps_changed = false; - state - .fetch_build_data_queue - .request_op("build_deps_changed - save notification".to_owned(), ()); - } - Ok(()) } diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/reload.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/reload.rs index 5d77b7aa67ef0..12667e3c90dee 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/reload.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/reload.rs @@ -122,7 +122,7 @@ impl GlobalState { }; let mut message = String::new(); - if !self.config.cargo_autoreload(None) + if !self.config.cargo_autoreload_config(None) && self.is_quiescent() && self.fetch_workspaces_queue.op_requested() && self.config.discover_workspace_config().is_none() From 6c393b1e15c8a983b566c8af3a7cdab69ae65be9 Mon Sep 17 00:00:00 2001 From: Weihang Lo Date: Sat, 31 Aug 2024 09:30:22 +0800 Subject: [PATCH 0292/2194] Update cargo --- src/tools/cargo | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/cargo b/src/tools/cargo index 8f40fc59fb0c8..c1fa840a85eca 160000 --- a/src/tools/cargo +++ b/src/tools/cargo @@ -1 +1 @@ -Subproject commit 8f40fc59fb0c8df91c97405785197f3c630304ea +Subproject commit c1fa840a85eca53818895901a53fae34247448b2 From 24ad26db3b8bac3c812d797cb34df76f1bff306b Mon Sep 17 00:00:00 2001 From: ranger-ross Date: Sat, 31 Aug 2024 14:41:01 +0900 Subject: [PATCH 0293/2194] Fixed some typos in the standard library documentation/comments --- library/std/build.rs | 2 +- library/std/src/io/tests.rs | 2 +- library/std/src/rt.rs | 2 +- library/std/src/sync/mpmc/list.rs | 2 +- library/std/src/sys/pal/uefi/process.rs | 2 +- library/std/src/sys/pal/unix/net.rs | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/library/std/build.rs b/library/std/build.rs index fecdf2c3e1f43..72254cafc850d 100644 --- a/library/std/build.rs +++ b/library/std/build.rs @@ -142,7 +142,7 @@ fn main() { // Configure platforms that have reliable basics but may have unreliable math. - // LLVM is currenlty adding missing routines, + // LLVM is currently adding missing routines, let has_reliable_f16_math = has_reliable_f16 && match (target_arch.as_str(), target_os.as_str()) { // FIXME: Disabled on Miri as the intrinsics are not implemented yet. diff --git a/library/std/src/io/tests.rs b/library/std/src/io/tests.rs index bb6a53bb290f9..24e5a1dfd5c00 100644 --- a/library/std/src/io/tests.rs +++ b/library/std/src/io/tests.rs @@ -738,7 +738,7 @@ fn read_buf_full_read() { #[test] // Miri does not support signalling OOM #[cfg_attr(miri, ignore)] -// 64-bit only to be sure the allocator will fail fast on an impossible to satsify size +// 64-bit only to be sure the allocator will fail fast on an impossible to satisfy size #[cfg(target_pointer_width = "64")] fn try_oom_error() { let mut v = Vec::::new(); diff --git a/library/std/src/rt.rs b/library/std/src/rt.rs index 307a543c9d215..b6f36931ec28a 100644 --- a/library/std/src/rt.rs +++ b/library/std/src/rt.rs @@ -146,7 +146,7 @@ fn lang_start_internal( rtabort!("drop of the panic payload panicked"); }); panic::catch_unwind(cleanup).map_err(rt_abort)?; - // Guard against multple threads calling `libc::exit` concurrently. + // Guard against multiple threads calling `libc::exit` concurrently. // See the documentation for `unique_thread_exit` for more information. panic::catch_unwind(|| crate::sys::exit_guard::unique_thread_exit()).map_err(rt_abort)?; ret_code diff --git a/library/std/src/sync/mpmc/list.rs b/library/std/src/sync/mpmc/list.rs index bbe205cad04e6..88a8c75f7c8b9 100644 --- a/library/std/src/sync/mpmc/list.rs +++ b/library/std/src/sync/mpmc/list.rs @@ -551,7 +551,7 @@ impl Channel { let mut head = self.head.index.load(Ordering::Acquire); // The channel may be uninitialized, so we have to swap to avoid overwriting any sender's attempts - // to initalize the first block before noticing that the receivers disconnected. Late allocations + // to initialize the first block before noticing that the receivers disconnected. Late allocations // will be deallocated by the sender in Drop. let mut block = self.head.block.swap(ptr::null_mut(), Ordering::AcqRel); diff --git a/library/std/src/sys/pal/uefi/process.rs b/library/std/src/sys/pal/uefi/process.rs index fdc5f5d7e4fea..0cc9cecb89db0 100644 --- a/library/std/src/sys/pal/uefi/process.rs +++ b/library/std/src/sys/pal/uefi/process.rs @@ -470,7 +470,7 @@ mod uefi_command_internal { let st_size = unsafe { (*self.st.as_ptr()).hdr.header_size as usize }; let mut crc32: u32 = 0; - // Set crc to 0 before calcuation + // Set crc to 0 before calculation unsafe { (*self.st.as_mut_ptr()).hdr.crc32 = 0; } diff --git a/library/std/src/sys/pal/unix/net.rs b/library/std/src/sys/pal/unix/net.rs index bc0e3f4eeeac8..d75a666d350ff 100644 --- a/library/std/src/sys/pal/unix/net.rs +++ b/library/std/src/sys/pal/unix/net.rs @@ -215,7 +215,7 @@ impl Socket { _ => { if cfg!(target_os = "vxworks") { // VxWorks poll does not return POLLHUP or POLLERR in revents. Check if the - // connnection actually succeeded and return ok only when the socket is + // connection actually succeeded and return ok only when the socket is // ready and no errors were found. if let Some(e) = self.take_error()? { return Err(e); From 92f45900bb1ef2c8e9cbb90478a4cddc4961de9f Mon Sep 17 00:00:00 2001 From: ranger-ross Date: Sat, 31 Aug 2024 14:50:37 +0900 Subject: [PATCH 0294/2194] Fixed typos in btree map docs --- library/alloc/src/collections/btree/map.rs | 4 ++-- library/alloc/src/collections/btree/set.rs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/library/alloc/src/collections/btree/map.rs b/library/alloc/src/collections/btree/map.rs index f6f773cc42a4f..c7908578522a5 100644 --- a/library/alloc/src/collections/btree/map.rs +++ b/library/alloc/src/collections/btree/map.rs @@ -3302,7 +3302,7 @@ impl<'a, K: Ord, V, A: Allocator + Clone> CursorMutKey<'a, K, V, A> { Some(kv) } - /// Removes the precending element from the `BTreeMap`. + /// Removes the preceding element from the `BTreeMap`. /// /// The element that was removed is returned. The cursor position is /// unchanged (after the removed element). @@ -3408,7 +3408,7 @@ impl<'a, K: Ord, V, A: Allocator + Clone> CursorMut<'a, K, V, A> { self.inner.remove_next() } - /// Removes the precending element from the `BTreeMap`. + /// Removes the preceding element from the `BTreeMap`. /// /// The element that was removed is returned. The cursor position is /// unchanged (after the removed element). diff --git a/library/alloc/src/collections/btree/set.rs b/library/alloc/src/collections/btree/set.rs index 973e7c660670c..2b5bebcd8cd08 100644 --- a/library/alloc/src/collections/btree/set.rs +++ b/library/alloc/src/collections/btree/set.rs @@ -2298,7 +2298,7 @@ impl<'a, T: Ord, A: Allocator + Clone> CursorMut<'a, T, A> { self.inner.remove_next().map(|(k, _)| k) } - /// Removes the precending element from the `BTreeSet`. + /// Removes the preceding element from the `BTreeSet`. /// /// The element that was removed is returned. The cursor position is /// unchanged (after the removed element). @@ -2384,7 +2384,7 @@ impl<'a, T: Ord, A: Allocator + Clone> CursorMutKey<'a, T, A> { self.inner.remove_next().map(|(k, _)| k) } - /// Removes the precending element from the `BTreeSet`. + /// Removes the preceding element from the `BTreeSet`. /// /// The element that was removed is returned. The cursor position is /// unchanged (after the removed element). From cbf92fcf39154a25b4bb491eebc4c3a27ae4e6ce Mon Sep 17 00:00:00 2001 From: ranger-ross Date: Sat, 31 Aug 2024 14:57:38 +0900 Subject: [PATCH 0295/2194] Fixed more typos in library/core --- library/core/src/array/mod.rs | 2 +- library/core/src/future/async_drop.rs | 4 ++-- library/core/src/intrinsics/mir.rs | 2 +- library/core/src/macros/mod.rs | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/library/core/src/array/mod.rs b/library/core/src/array/mod.rs index 61c713c9e81cf..c63f261edabfa 100644 --- a/library/core/src/array/mod.rs +++ b/library/core/src/array/mod.rs @@ -37,7 +37,7 @@ pub use iter::IntoIter; /// /// # Example /// -/// Creating muliple copies of a `String`: +/// Creating multiple copies of a `String`: /// ```rust /// #![feature(array_repeat)] /// diff --git a/library/core/src/future/async_drop.rs b/library/core/src/future/async_drop.rs index 8971a2c0aafd1..16ac77fa15045 100644 --- a/library/core/src/future/async_drop.rs +++ b/library/core/src/future/async_drop.rs @@ -157,7 +157,7 @@ async unsafe fn surface_drop_in_place(ptr: *mut T) { unsafe { crate::ops::fallback_surface_drop(&mut *ptr) } } -/// Wraps a future to continue outputing `Poll::Ready(())` once after +/// Wraps a future to continue outputting `Poll::Ready(())` once after /// wrapped future completes by returning `Poll::Ready(())` on poll. This /// is useful for constructing async destructors to guarantee this /// "fuse" property @@ -223,7 +223,7 @@ where /// # Safety /// /// Same as `async_drop_in_place` except is lazy to avoid creating -/// multiple mutable refernces. +/// multiple mutable references. #[lang = "async_drop_defer"] async unsafe fn defer(to_drop: *mut T) { // SAFETY: same safety requirements as `async_drop_in_place` diff --git a/library/core/src/intrinsics/mir.rs b/library/core/src/intrinsics/mir.rs index c7cec396e1f2e..fb0aa5398a55b 100644 --- a/library/core/src/intrinsics/mir.rs +++ b/library/core/src/intrinsics/mir.rs @@ -310,7 +310,7 @@ define!( ); define!( "mir_unwind_cleanup", - /// An unwind action that continues execution in a given basic blok. + /// An unwind action that continues execution in a given basic block. fn UnwindCleanup(goto: BasicBlock) -> UnwindActionArg ); diff --git a/library/core/src/macros/mod.rs b/library/core/src/macros/mod.rs index ac51a40d9f478..888832251f6da 100644 --- a/library/core/src/macros/mod.rs +++ b/library/core/src/macros/mod.rs @@ -1072,7 +1072,7 @@ pub(crate) mod builtin { /// If the environment variable is not defined, then a compilation error /// will be emitted. To not emit a compile error, use the [`option_env!`] /// macro instead. A compilation error will also be emitted if the - /// environment variable is not a vaild Unicode string. + /// environment variable is not a valid Unicode string. /// /// # Examples /// From 5acbc4f5e1f91f8f86df85766fd6084631d5d805 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Sat, 31 Aug 2024 10:51:13 +0200 Subject: [PATCH 0296/2194] fix: Fix lifetime elision inlay hints breaking for ranged requests --- .../crates/ide/src/inlay_hints.rs | 114 +++++++++--------- .../crates/ide/src/inlay_hints/lifetime.rs | 2 +- 2 files changed, 59 insertions(+), 57 deletions(-) diff --git a/src/tools/rust-analyzer/crates/ide/src/inlay_hints.rs b/src/tools/rust-analyzer/crates/ide/src/inlay_hints.rs index be99510af2a17..2e49af49145a1 100644 --- a/src/tools/rust-analyzer/crates/ide/src/inlay_hints.rs +++ b/src/tools/rust-analyzer/crates/ide/src/inlay_hints.rs @@ -15,7 +15,7 @@ use span::{Edition, EditionedFileId}; use stdx::never; use syntax::{ ast::{self, AstNode, HasGenericParams}, - format_smolstr, match_ast, NodeOrToken, SmolStr, SyntaxNode, TextRange, TextSize, WalkEvent, + format_smolstr, match_ast, SmolStr, SyntaxNode, TextRange, TextSize, WalkEvent, }; use text_edit::TextEdit; @@ -95,26 +95,27 @@ pub(crate) fn inlay_hints( let famous_defs = FamousDefs(&sema, scope.krate()); let ctx = &mut InlayHintCtx::default(); - let hints = |node| hints(&mut acc, ctx, &famous_defs, config, file_id, node); - match range_limit { - // FIXME: This can miss some hints that require the parent of the range to calculate - Some(range) => match file.covering_element(range) { - NodeOrToken::Token(_) => return acc, - NodeOrToken::Node(n) => n - .preorder() - .filter(|event| matches!(event, WalkEvent::Enter(node) if range.intersect(node.text_range()).is_some())) - .for_each(hints), - }, - None => file.preorder().for_each(hints), + let mut hints = |event| { + if let Some(node) = handle_event(ctx, event) { + hints(&mut acc, ctx, &famous_defs, config, file_id, node); + } }; - + let mut preorder = file.preorder(); + while let Some(event) = preorder.next() { + // FIXME: This can miss some hints that require the parent of the range to calculate + if matches!((&event, range_limit), (WalkEvent::Enter(node), Some(range)) if range.intersect(node.text_range()).is_none()) + { + preorder.skip_subtree(); + continue; + } + hints(event); + } acc } #[derive(Default)] struct InlayHintCtx { lifetime_stacks: Vec>, - is_param_list: bool, } pub(crate) fn inlay_hints_resolve( @@ -138,20 +139,52 @@ pub(crate) fn inlay_hints_resolve( let mut acc = Vec::new(); let ctx = &mut InlayHintCtx::default(); - let hints = |node| hints(&mut acc, ctx, &famous_defs, config, file_id, node); - - let mut res = file.clone(); - let res = loop { - res = match res.child_or_token_at_range(resolve_range) { - Some(NodeOrToken::Node(n)) if n.text_range() == resolve_range => break n, - Some(NodeOrToken::Node(n)) => n, - _ => break res, - }; + let mut hints = |event| { + if let Some(node) = handle_event(ctx, event) { + hints(&mut acc, ctx, &famous_defs, config, file_id, node); + } }; - res.preorder().for_each(hints); + + let mut preorder = file.preorder(); + while let Some(event) = preorder.next() { + // FIXME: This can miss some hints that require the parent of the range to calculate + if matches!(&event, WalkEvent::Enter(node) if resolve_range.intersect(node.text_range()).is_none()) + { + preorder.skip_subtree(); + continue; + } + hints(event); + } acc.into_iter().find(|hint| hasher(hint) == hash) } +fn handle_event(ctx: &mut InlayHintCtx, node: WalkEvent) -> Option { + match node { + WalkEvent::Enter(node) => { + if let Some(node) = ast::AnyHasGenericParams::cast(node.clone()) { + let params = node + .generic_param_list() + .map(|it| { + it.lifetime_params() + .filter_map(|it| { + it.lifetime().map(|it| format_smolstr!("{}", &it.text()[1..])) + }) + .collect() + }) + .unwrap_or_default(); + ctx.lifetime_stacks.push(params); + } + Some(node) + } + WalkEvent::Leave(n) => { + if ast::AnyHasGenericParams::can_cast(n.kind()) { + ctx.lifetime_stacks.pop(); + } + None + } + } +} + // FIXME: At some point when our hir infra is fleshed out enough we should flip this and traverse the // HIR instead of the syntax tree. fn hints( @@ -160,35 +193,8 @@ fn hints( famous_defs @ FamousDefs(sema, _): &FamousDefs<'_, '_>, config: &InlayHintsConfig, file_id: EditionedFileId, - node: WalkEvent, + node: SyntaxNode, ) { - let node = match node { - WalkEvent::Enter(node) => node, - WalkEvent::Leave(n) => { - if ast::AnyHasGenericParams::can_cast(n.kind()) { - ctx.lifetime_stacks.pop(); - // pop - } - if ast::ParamList::can_cast(n.kind()) { - ctx.is_param_list = false; - // pop - } - return; - } - }; - - if let Some(node) = ast::AnyHasGenericParams::cast(node.clone()) { - let params = node - .generic_param_list() - .map(|it| { - it.lifetime_params() - .filter_map(|it| it.lifetime().map(|it| format_smolstr!("{}", &it.text()[1..]))) - .collect() - }) - .unwrap_or_default(); - ctx.lifetime_stacks.push(params); - } - closing_brace::hints(hints, sema, config, file_id, node.clone()); if let Some(any_has_generic_args) = ast::AnyHasGenericArgs::cast(node.clone()) { generic_param::hints(hints, sema, config, any_has_generic_args); @@ -242,10 +248,6 @@ fn hints( ast::Type::PathType(path) => lifetime::fn_path_hints(hints, ctx, famous_defs, config, file_id, path), _ => Some(()), }, - ast::ParamList(_) => { - ctx.is_param_list = true; - Some(()) - }, _ => Some(()), } }; diff --git a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/lifetime.rs b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/lifetime.rs index de463670677c2..653e3a6ef1df9 100644 --- a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/lifetime.rs +++ b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/lifetime.rs @@ -532,7 +532,7 @@ fn fn_ptr(a: fn(&()) -> &fn(&()) -> &()) {} //^^ for<'1> //^'1 //^'1 -fn fn_ptr2(a: for<'a> fn(&()) -> &())) {} +fn fn_ptr2(a: for<'a> fn(&()) -> &()) {} //^'0, $ //^'0 //^'0 From ce3ca9904869ae065eda79bab7fe9114ed0e83cd Mon Sep 17 00:00:00 2001 From: riverbl <94326797+riverbl@users.noreply.github.com> Date: Wed, 28 Aug 2024 17:26:51 +0100 Subject: [PATCH 0297/2194] Add explicit enum discriminant assist Add assist for adding explicit discriminants to all variants of an enum. --- .../crates/hir-ty/src/consteval.rs | 22 +- .../handlers/explicit_enum_discriminant.rs | 202 ++++++++++++++++++ .../crates/ide-assists/src/lib.rs | 2 + 3 files changed, 221 insertions(+), 5 deletions(-) create mode 100644 src/tools/rust-analyzer/crates/ide-assists/src/handlers/explicit_enum_discriminant.rs diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/consteval.rs b/src/tools/rust-analyzer/crates/hir-ty/src/consteval.rs index 8b6cde975f63e..3f60834e02dd2 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/consteval.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/consteval.rs @@ -11,7 +11,7 @@ use hir_def::{ ConstBlockLoc, EnumVariantId, GeneralConstId, StaticId, }; use hir_expand::Lookup; -use stdx::never; +use stdx::{never, IsNoneOr}; use triomphe::Arc; use crate::{ @@ -169,15 +169,23 @@ pub fn usize_const(db: &dyn HirDatabase, value: Option, krate: CrateId) -> } pub fn try_const_usize(db: &dyn HirDatabase, c: &Const) -> Option { + try_const_usize_sign_extend(db, c, false) +} + +pub fn try_const_usize_sign_extend( + db: &dyn HirDatabase, + c: &Const, + is_signed: bool, +) -> Option { match &c.data(Interner).value { chalk_ir::ConstValue::BoundVar(_) => None, chalk_ir::ConstValue::InferenceVar(_) => None, chalk_ir::ConstValue::Placeholder(_) => None, chalk_ir::ConstValue::Concrete(c) => match &c.interned { - ConstScalar::Bytes(it, _) => Some(u128::from_le_bytes(pad16(it, false))), + ConstScalar::Bytes(it, _) => Some(u128::from_le_bytes(pad16(it, is_signed))), ConstScalar::UnevaluatedConst(c, subst) => { let ec = db.const_eval(*c, subst.clone(), None).ok()?; - try_const_usize(db, &ec) + try_const_usize_sign_extend(db, &ec, is_signed) } _ => None, }, @@ -256,8 +264,8 @@ pub(crate) fn const_eval_discriminant_variant( ) -> Result { let def = variant_id.into(); let body = db.body(def); + let loc = variant_id.lookup(db.upcast()); if body.exprs[body.body_expr] == Expr::Missing { - let loc = variant_id.lookup(db.upcast()); let prev_idx = loc.index.checked_sub(1); let value = match prev_idx { Some(prev_idx) => { @@ -269,13 +277,17 @@ pub(crate) fn const_eval_discriminant_variant( }; return Ok(value); } + + let repr = db.enum_data(loc.parent).repr; + let is_signed = repr.and_then(|repr| repr.int).is_none_or(|int| int.is_signed()); + let mir_body = db.monomorphized_mir_body( def, Substitution::empty(Interner), db.trait_environment_for_body(def), )?; let c = interpret_mir(db, mir_body, false, None).0?; - let c = try_const_usize(db, &c).unwrap() as i128; + let c = try_const_usize_sign_extend(db, &c, is_signed).unwrap() as i128; Ok(c) } diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/explicit_enum_discriminant.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/explicit_enum_discriminant.rs new file mode 100644 index 0000000000000..b5b7da69f7529 --- /dev/null +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/explicit_enum_discriminant.rs @@ -0,0 +1,202 @@ +use hir::Semantics; +use ide_db::{ + assists::{AssistId, AssistKind}, + source_change::SourceChangeBuilder, + RootDatabase, +}; +use syntax::{ast, AstNode}; + +use crate::{AssistContext, Assists}; + +// Assist: explicit_enum_discriminant +// +// Adds explicit discriminant to all enum variants. +// +// ``` +// enum TheEnum$0 { +// Foo, +// Bar, +// Baz = 42, +// Quux, +// } +// ``` +// -> +// ``` +// enum TheEnum { +// Foo = 0, +// Bar = 1, +// Baz = 42, +// Quux = 43, +// } +// ``` +pub(crate) fn explicit_enum_discriminant(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> { + let enum_node = ctx.find_node_at_offset::()?; + let enum_def = ctx.sema.to_def(&enum_node)?; + + let is_data_carrying = enum_def.is_data_carrying(ctx.db()); + let has_primitive_repr = enum_def.repr(ctx.db()).and_then(|repr| repr.int).is_some(); + + // Data carrying enums without a primitive repr have no stable discriminants. + if is_data_carrying && !has_primitive_repr { + return None; + } + + let variant_list = enum_node.variant_list()?; + + // Don't offer the assist if the enum has no variants or if all variants already have an + // explicit discriminant. + if variant_list.variants().all(|variant_node| variant_node.expr().is_some()) { + return None; + } + + acc.add( + AssistId("explicit_enum_discriminant", AssistKind::RefactorRewrite), + "Add explicit enum discriminants", + enum_node.syntax().text_range(), + |builder| { + for variant_node in variant_list.variants() { + add_variant_discriminant(&ctx.sema, builder, &variant_node); + } + }, + ); + + Some(()) +} + +fn add_variant_discriminant( + sema: &Semantics<'_, RootDatabase>, + builder: &mut SourceChangeBuilder, + variant_node: &ast::Variant, +) { + if variant_node.expr().is_some() { + return; + } + + let Some(variant_def) = sema.to_def(variant_node) else { + return; + }; + let Ok(discriminant) = variant_def.eval(sema.db) else { + return; + }; + + let variant_range = variant_node.syntax().text_range(); + + builder.insert(variant_range.end(), format!(" = {discriminant}")); +} + +#[cfg(test)] +mod tests { + use crate::tests::{check_assist, check_assist_not_applicable}; + + use super::explicit_enum_discriminant; + + #[test] + fn non_primitive_repr_non_data_bearing_add_discriminant() { + check_assist( + explicit_enum_discriminant, + r#" +enum TheEnum$0 { + Foo, + Bar, + Baz = 42, + Quux, +} +"#, + r#" +enum TheEnum { + Foo = 0, + Bar = 1, + Baz = 42, + Quux = 43, +} +"#, + ); + } + + #[test] + fn primitive_repr_data_bearing_add_discriminant() { + check_assist( + explicit_enum_discriminant, + r#" +#[repr(u8)] +$0enum TheEnum { + Foo { x: u32 }, + Bar, + Baz(String), + Quux, +} +"#, + r#" +#[repr(u8)] +enum TheEnum { + Foo { x: u32 } = 0, + Bar = 1, + Baz(String) = 2, + Quux = 3, +} +"#, + ); + } + + #[test] + fn non_primitive_repr_data_bearing_not_applicable() { + check_assist_not_applicable( + explicit_enum_discriminant, + r#" +enum TheEnum$0 { + Foo, + Bar(u16), + Baz, +} +"#, + ); + } + + #[test] + fn primitive_repr_non_data_bearing_add_discriminant() { + check_assist( + explicit_enum_discriminant, + r#" +#[repr(i64)] +enum TheEnum { + Foo = 1 << 63, + Bar, + Baz$0 = 0x7fff_ffff_ffff_fffe, + Quux, +} +"#, + r#" +#[repr(i64)] +enum TheEnum { + Foo = 1 << 63, + Bar = -9223372036854775807, + Baz = 0x7fff_ffff_ffff_fffe, + Quux = 9223372036854775807, +} +"#, + ); + } + + #[test] + fn discriminants_already_explicit_not_applicable() { + check_assist_not_applicable( + explicit_enum_discriminant, + r#" +enum TheEnum$0 { + Foo = 0, + Bar = 4, +} +"#, + ); + } + + #[test] + fn empty_enum_not_applicable() { + check_assist_not_applicable( + explicit_enum_discriminant, + r#" +enum TheEnum$0 {} +"#, + ); + } +} diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/lib.rs b/src/tools/rust-analyzer/crates/ide-assists/src/lib.rs index c88cb3d5eaf05..b2ccd1fde815e 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/lib.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/lib.rs @@ -136,6 +136,7 @@ mod handlers { mod destructure_tuple_binding; mod desugar_doc_comment; mod expand_glob_import; + mod explicit_enum_discriminant; mod extract_expressions_from_format_string; mod extract_function; mod extract_module; @@ -266,6 +267,7 @@ mod handlers { destructure_tuple_binding::destructure_tuple_binding, destructure_struct_binding::destructure_struct_binding, expand_glob_import::expand_glob_import, + explicit_enum_discriminant::explicit_enum_discriminant, extract_expressions_from_format_string::extract_expressions_from_format_string, extract_struct_from_enum_variant::extract_struct_from_enum_variant, extract_type_alias::extract_type_alias, From 5392d56c93cf5584e4d18cfb86cc314138db1c94 Mon Sep 17 00:00:00 2001 From: riverbl <94326797+riverbl@users.noreply.github.com> Date: Wed, 28 Aug 2024 19:42:11 +0100 Subject: [PATCH 0298/2194] Update generated doctests Update generated doctests, change unit test to be different to doctest. --- .../handlers/explicit_enum_discriminant.rs | 4 ++++ .../crates/ide-assists/src/tests/generated.rs | 23 +++++++++++++++++++ 2 files changed, 27 insertions(+) diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/explicit_enum_discriminant.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/explicit_enum_discriminant.rs index b5b7da69f7529..fafc3448a87ca 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/explicit_enum_discriminant.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/explicit_enum_discriminant.rs @@ -100,6 +100,8 @@ enum TheEnum$0 { Bar, Baz = 42, Quux, + FooBar = -5, + FooBaz, } "#, r#" @@ -108,6 +110,8 @@ enum TheEnum { Bar = 1, Baz = 42, Quux = 43, + FooBar = -5, + FooBaz = -4, } "#, ); diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/tests/generated.rs b/src/tools/rust-analyzer/crates/ide-assists/src/tests/generated.rs index dce7bbf342f74..48e12a8107353 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/tests/generated.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/tests/generated.rs @@ -909,6 +909,29 @@ fn qux(bar: Bar, baz: Baz) {} ) } +#[test] +fn doctest_explicit_enum_discriminant() { + check_doc_test( + "explicit_enum_discriminant", + r#####" +enum TheEnum$0 { + Foo, + Bar, + Baz = 42, + Quux, +} +"#####, + r#####" +enum TheEnum { + Foo = 0, + Bar = 1, + Baz = 42, + Quux = 43, +} +"#####, + ) +} + #[test] fn doctest_extract_expressions_from_format_string() { check_doc_test( From d6573f9b08283a1eb732923f4ddc0899c7376e79 Mon Sep 17 00:00:00 2001 From: riverbl <94326797+riverbl@users.noreply.github.com> Date: Sat, 31 Aug 2024 10:13:08 +0100 Subject: [PATCH 0299/2194] Rename function and remove flag argument Use less confusing name for function, duplicate logic rather than taking flag as argument. --- .../crates/hir-ty/src/consteval.rs | 30 +++++++++++++------ 1 file changed, 21 insertions(+), 9 deletions(-) diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/consteval.rs b/src/tools/rust-analyzer/crates/hir-ty/src/consteval.rs index 3f60834e02dd2..e5c493ac56e1b 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/consteval.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/consteval.rs @@ -169,23 +169,31 @@ pub fn usize_const(db: &dyn HirDatabase, value: Option, krate: CrateId) -> } pub fn try_const_usize(db: &dyn HirDatabase, c: &Const) -> Option { - try_const_usize_sign_extend(db, c, false) + match &c.data(Interner).value { + chalk_ir::ConstValue::BoundVar(_) => None, + chalk_ir::ConstValue::InferenceVar(_) => None, + chalk_ir::ConstValue::Placeholder(_) => None, + chalk_ir::ConstValue::Concrete(c) => match &c.interned { + ConstScalar::Bytes(it, _) => Some(u128::from_le_bytes(pad16(it, false))), + ConstScalar::UnevaluatedConst(c, subst) => { + let ec = db.const_eval(*c, subst.clone(), None).ok()?; + try_const_usize(db, &ec) + } + _ => None, + }, + } } -pub fn try_const_usize_sign_extend( - db: &dyn HirDatabase, - c: &Const, - is_signed: bool, -) -> Option { +pub fn try_const_isize(db: &dyn HirDatabase, c: &Const) -> Option { match &c.data(Interner).value { chalk_ir::ConstValue::BoundVar(_) => None, chalk_ir::ConstValue::InferenceVar(_) => None, chalk_ir::ConstValue::Placeholder(_) => None, chalk_ir::ConstValue::Concrete(c) => match &c.interned { - ConstScalar::Bytes(it, _) => Some(u128::from_le_bytes(pad16(it, is_signed))), + ConstScalar::Bytes(it, _) => Some(i128::from_le_bytes(pad16(it, true))), ConstScalar::UnevaluatedConst(c, subst) => { let ec = db.const_eval(*c, subst.clone(), None).ok()?; - try_const_usize_sign_extend(db, &ec, is_signed) + try_const_isize(db, &ec) } _ => None, }, @@ -287,7 +295,11 @@ pub(crate) fn const_eval_discriminant_variant( db.trait_environment_for_body(def), )?; let c = interpret_mir(db, mir_body, false, None).0?; - let c = try_const_usize_sign_extend(db, &c, is_signed).unwrap() as i128; + let c = if is_signed { + try_const_isize(db, &c).unwrap() + } else { + try_const_usize(db, &c).unwrap() as i128 + }; Ok(c) } From 175238badb14beb04f6973da93fe9f883758ae7f Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Thu, 29 Aug 2024 20:49:39 -0400 Subject: [PATCH 0300/2194] Make decoding non-optional LazyArray panic if not set --- .../src/rmeta/decoder/cstore_impl.rs | 23 +++++++++++++++---- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs index a82340e3d6130..2ecad5096d5a1 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs @@ -71,8 +71,8 @@ impl<'a, 'tcx, T: Copy + Decodable>> ProcessQueryValue<' for Option> { #[inline(always)] - fn process_decoded(self, tcx: TyCtxt<'tcx>, _err: impl Fn() -> !) -> &'tcx [T] { - if let Some(iter) = self { tcx.arena.alloc_from_iter(iter) } else { &[] } + fn process_decoded(self, tcx: TyCtxt<'tcx>, err: impl Fn() -> !) -> &'tcx [T] { + if let Some(iter) = self { tcx.arena.alloc_from_iter(iter) } else { err() } } } @@ -84,12 +84,12 @@ impl<'a, 'tcx, T: Copy + Decodable>> fn process_decoded( self, tcx: TyCtxt<'tcx>, - _err: impl Fn() -> !, + err: impl Fn() -> !, ) -> ty::EarlyBinder<'tcx, &'tcx [T]> { ty::EarlyBinder::bind(if let Some(iter) = self { tcx.arena.alloc_from_iter(iter) } else { - &[] + err() }) } } @@ -301,7 +301,20 @@ provide! { tcx, def_id, other, cdata, .unwrap_or_else(|| panic!("{def_id:?} does not have eval_static_initializer"))) } trait_def => { table } - deduced_param_attrs => { table } + deduced_param_attrs => { + // FIXME: `deduced_param_attrs` has some sketchy encoding settings, + // where we don't encode unless we're optimizing, doing codegen, + // and not incremental (see `encoder.rs`). I don't think this is right! + cdata + .root + .tables + .deduced_param_attrs + .get(cdata, def_id.index) + .map(|lazy| { + &*tcx.arena.alloc_from_iter(lazy.decode((cdata, tcx))) + }) + .unwrap_or_default() + } is_type_alias_impl_trait => { debug_assert_eq!(tcx.def_kind(def_id), DefKind::OpaqueTy); cdata.root.tables.is_type_alias_impl_trait.get(cdata, def_id.index) From bb9d5c4658218f6e1c477d8c3e0224c1d708e42b Mon Sep 17 00:00:00 2001 From: Chris Denton Date: Sat, 31 Aug 2024 02:40:35 +0000 Subject: [PATCH 0301/2194] Move remove_dir_all impl into a module --- library/std/src/sys/pal/windows/api.rs | 5 +- .../std/src/sys/pal/windows/c/bindings.txt | 5 + .../std/src/sys/pal/windows/c/windows_sys.rs | 5 + library/std/src/sys/pal/windows/fs.rs | 211 ++++-------------- .../src/sys/pal/windows/fs/remove_dir_all.rs | 196 ++++++++++++++++ 5 files changed, 253 insertions(+), 169 deletions(-) create mode 100644 library/std/src/sys/pal/windows/fs/remove_dir_all.rs diff --git a/library/std/src/sys/pal/windows/api.rs b/library/std/src/sys/pal/windows/api.rs index 00c816a6c09b8..9e336ff2d473d 100644 --- a/library/std/src/sys/pal/windows/api.rs +++ b/library/std/src/sys/pal/windows/api.rs @@ -254,7 +254,7 @@ pub struct WinError { pub code: u32, } impl WinError { - const fn new(code: u32) -> Self { + pub const fn new(code: u32) -> Self { Self { code } } } @@ -272,8 +272,11 @@ impl WinError { // tidy-alphabetical-start pub const ACCESS_DENIED: Self = Self::new(c::ERROR_ACCESS_DENIED); pub const ALREADY_EXISTS: Self = Self::new(c::ERROR_ALREADY_EXISTS); + pub const BAD_NET_NAME: Self = Self::new(c::ERROR_BAD_NET_NAME); + pub const BAD_NETPATH: Self = Self::new(c::ERROR_BAD_NETPATH); pub const CANT_ACCESS_FILE: Self = Self::new(c::ERROR_CANT_ACCESS_FILE); pub const DELETE_PENDING: Self = Self::new(c::ERROR_DELETE_PENDING); + pub const DIR_NOT_EMPTY: Self = Self::new(c::ERROR_DIR_NOT_EMPTY); pub const DIRECTORY: Self = Self::new(c::ERROR_DIRECTORY); pub const FILE_NOT_FOUND: Self = Self::new(c::ERROR_FILE_NOT_FOUND); pub const INSUFFICIENT_BUFFER: Self = Self::new(c::ERROR_INSUFFICIENT_BUFFER); diff --git a/library/std/src/sys/pal/windows/c/bindings.txt b/library/std/src/sys/pal/windows/c/bindings.txt index afacc370c3420..9c2e4500da068 100644 --- a/library/std/src/sys/pal/windows/c/bindings.txt +++ b/library/std/src/sys/pal/windows/c/bindings.txt @@ -34,6 +34,7 @@ Windows.Wdk.Storage.FileSystem.FILE_WRITE_THROUGH Windows.Wdk.Storage.FileSystem.NtCreateFile Windows.Wdk.Storage.FileSystem.NTCREATEFILE_CREATE_DISPOSITION Windows.Wdk.Storage.FileSystem.NTCREATEFILE_CREATE_OPTIONS +Windows.Wdk.Storage.FileSystem.NtOpenFile Windows.Wdk.Storage.FileSystem.NtReadFile Windows.Wdk.Storage.FileSystem.NtWriteFile Windows.Wdk.Storage.FileSystem.SYMLINK_FLAG_RELATIVE @@ -1931,10 +1932,14 @@ Windows.Win32.Foundation.RtlNtStatusToDosError Windows.Win32.Foundation.SetHandleInformation Windows.Win32.Foundation.SetLastError Windows.Win32.Foundation.STATUS_DELETE_PENDING +Windows.Win32.Foundation.STATUS_DIRECTORY_NOT_EMPTY Windows.Win32.Foundation.STATUS_END_OF_FILE +Windows.Win32.Foundation.STATUS_FILE_DELETED +Windows.Win32.Foundation.STATUS_INVALID_HANDLE Windows.Win32.Foundation.STATUS_INVALID_PARAMETER Windows.Win32.Foundation.STATUS_NOT_IMPLEMENTED Windows.Win32.Foundation.STATUS_PENDING +Windows.Win32.Foundation.STATUS_SHARING_VIOLATION Windows.Win32.Foundation.STATUS_SUCCESS Windows.Win32.Foundation.TRUE Windows.Win32.Foundation.UNICODE_STRING diff --git a/library/std/src/sys/pal/windows/c/windows_sys.rs b/library/std/src/sys/pal/windows/c/windows_sys.rs index 529c96a0e1e6b..ab5f8919d7af6 100644 --- a/library/std/src/sys/pal/windows/c/windows_sys.rs +++ b/library/std/src/sys/pal/windows/c/windows_sys.rs @@ -105,6 +105,7 @@ windows_targets::link!("kernel32.dll" "system" fn WideCharToMultiByte(codepage : windows_targets::link!("kernel32.dll" "system" fn WriteConsoleW(hconsoleoutput : HANDLE, lpbuffer : PCWSTR, nnumberofcharstowrite : u32, lpnumberofcharswritten : *mut u32, lpreserved : *const core::ffi::c_void) -> BOOL); windows_targets::link!("kernel32.dll" "system" fn WriteFileEx(hfile : HANDLE, lpbuffer : *const u8, nnumberofbytestowrite : u32, lpoverlapped : *mut OVERLAPPED, lpcompletionroutine : LPOVERLAPPED_COMPLETION_ROUTINE) -> BOOL); windows_targets::link!("ntdll.dll" "system" fn NtCreateFile(filehandle : *mut HANDLE, desiredaccess : FILE_ACCESS_RIGHTS, objectattributes : *const OBJECT_ATTRIBUTES, iostatusblock : *mut IO_STATUS_BLOCK, allocationsize : *const i64, fileattributes : FILE_FLAGS_AND_ATTRIBUTES, shareaccess : FILE_SHARE_MODE, createdisposition : NTCREATEFILE_CREATE_DISPOSITION, createoptions : NTCREATEFILE_CREATE_OPTIONS, eabuffer : *const core::ffi::c_void, ealength : u32) -> NTSTATUS); +windows_targets::link!("ntdll.dll" "system" fn NtOpenFile(filehandle : *mut HANDLE, desiredaccess : u32, objectattributes : *const OBJECT_ATTRIBUTES, iostatusblock : *mut IO_STATUS_BLOCK, shareaccess : u32, openoptions : u32) -> NTSTATUS); windows_targets::link!("ntdll.dll" "system" fn NtReadFile(filehandle : HANDLE, event : HANDLE, apcroutine : PIO_APC_ROUTINE, apccontext : *const core::ffi::c_void, iostatusblock : *mut IO_STATUS_BLOCK, buffer : *mut core::ffi::c_void, length : u32, byteoffset : *const i64, key : *const u32) -> NTSTATUS); windows_targets::link!("ntdll.dll" "system" fn NtWriteFile(filehandle : HANDLE, event : HANDLE, apcroutine : PIO_APC_ROUTINE, apccontext : *const core::ffi::c_void, iostatusblock : *mut IO_STATUS_BLOCK, buffer : *const core::ffi::c_void, length : u32, byteoffset : *const i64, key : *const u32) -> NTSTATUS); windows_targets::link!("ntdll.dll" "system" fn RtlNtStatusToDosError(status : NTSTATUS) -> u32); @@ -2982,10 +2983,14 @@ pub struct STARTUPINFOW { } pub type STARTUPINFOW_FLAGS = u32; pub const STATUS_DELETE_PENDING: NTSTATUS = 0xC0000056_u32 as _; +pub const STATUS_DIRECTORY_NOT_EMPTY: NTSTATUS = 0xC0000101_u32 as _; pub const STATUS_END_OF_FILE: NTSTATUS = 0xC0000011_u32 as _; +pub const STATUS_FILE_DELETED: NTSTATUS = 0xC0000123_u32 as _; +pub const STATUS_INVALID_HANDLE: NTSTATUS = 0xC0000008_u32 as _; pub const STATUS_INVALID_PARAMETER: NTSTATUS = 0xC000000D_u32 as _; pub const STATUS_NOT_IMPLEMENTED: NTSTATUS = 0xC0000002_u32 as _; pub const STATUS_PENDING: NTSTATUS = 0x103_u32 as _; +pub const STATUS_SHARING_VIOLATION: NTSTATUS = 0xC0000043_u32 as _; pub const STATUS_SUCCESS: NTSTATUS = 0x0_u32 as _; pub const STD_ERROR_HANDLE: STD_HANDLE = 4294967284u32; pub type STD_HANDLE = u32; diff --git a/library/std/src/sys/pal/windows/fs.rs b/library/std/src/sys/pal/windows/fs.rs index 2134152ea93f1..5b360640c4e67 100644 --- a/library/std/src/sys/pal/windows/fs.rs +++ b/library/std/src/sys/pal/windows/fs.rs @@ -14,8 +14,11 @@ use crate::sys::handle::Handle; use crate::sys::path::maybe_verbatim; use crate::sys::time::SystemTime; use crate::sys::{c, cvt, Align8}; -use crate::sys_common::{ignore_notfound, AsInner, FromInner, IntoInner}; -use crate::{fmt, ptr, slice, thread}; +use crate::sys_common::{AsInner, FromInner, IntoInner}; +use crate::{fmt, ptr, slice}; + +mod remove_dir_all; +use remove_dir_all::remove_dir_all_iterative; pub struct File { handle: Handle, @@ -646,6 +649,22 @@ impl File { Ok(info) } } + + /// Deletes the file, consuming the file handle to ensure the delete occurs + /// as immediately as possible. + /// This attempts to use `posix_delete` but falls back to `win32_delete` + /// if that is not supported by the filesystem. + #[allow(unused)] + fn delete(self) -> Result<(), WinError> { + // If POSIX delete is not supported for this filesystem then fallback to win32 delete. + match self.posix_delete() { + Err(WinError::INVALID_PARAMETER) + | Err(WinError::NOT_SUPPORTED) + | Err(WinError::INVALID_FUNCTION) => self.win32_delete(), + result => result, + } + } + /// Delete using POSIX semantics. /// /// Files will be deleted as soon as the handle is closed. This is supported @@ -654,21 +673,23 @@ impl File { /// /// If the operation is not supported for this filesystem or OS version /// then errors will be `ERROR_NOT_SUPPORTED` or `ERROR_INVALID_PARAMETER`. - fn posix_delete(&self) -> io::Result<()> { + #[allow(unused)] + fn posix_delete(&self) -> Result<(), WinError> { let info = c::FILE_DISPOSITION_INFO_EX { Flags: c::FILE_DISPOSITION_FLAG_DELETE | c::FILE_DISPOSITION_FLAG_POSIX_SEMANTICS | c::FILE_DISPOSITION_FLAG_IGNORE_READONLY_ATTRIBUTE, }; - api::set_file_information_by_handle(self.handle.as_raw_handle(), &info).io_result() + api::set_file_information_by_handle(self.handle.as_raw_handle(), &info) } /// Delete a file using win32 semantics. The file won't actually be deleted /// until all file handles are closed. However, marking a file for deletion /// will prevent anyone from opening a new handle to the file. - fn win32_delete(&self) -> io::Result<()> { + #[allow(unused)] + fn win32_delete(&self) -> Result<(), WinError> { let info = c::FILE_DISPOSITION_INFO { DeleteFile: c::TRUE as _ }; - api::set_file_information_by_handle(self.handle.as_raw_handle(), &info).io_result() + api::set_file_information_by_handle(self.handle.as_raw_handle(), &info) } /// Fill the given buffer with as many directory entries as will fit. @@ -684,21 +705,23 @@ impl File { /// A symlink directory is simply an empty directory with some "reparse" metadata attached. /// So if you open a link (not its target) and iterate the directory, /// you will always iterate an empty directory regardless of the target. - fn fill_dir_buff(&self, buffer: &mut DirBuff, restart: bool) -> io::Result { + #[allow(unused)] + fn fill_dir_buff(&self, buffer: &mut DirBuff, restart: bool) -> Result { let class = if restart { c::FileIdBothDirectoryRestartInfo } else { c::FileIdBothDirectoryInfo }; unsafe { - let result = cvt(c::GetFileInformationByHandleEx( - self.handle.as_raw_handle(), + let result = c::GetFileInformationByHandleEx( + self.as_raw_handle(), class, buffer.as_mut_ptr().cast(), buffer.capacity() as _, - )); - match result { - Ok(_) => Ok(true), - Err(e) if e.raw_os_error() == Some(c::ERROR_NO_MORE_FILES as _) => Ok(false), - Err(e) => Err(e), + ); + if result == 0 { + let err = api::get_last_error(); + if err.code == c::ERROR_NO_MORE_FILES { Ok(false) } else { Err(err) } + } else { + Ok(true) } } } @@ -804,62 +827,6 @@ unsafe fn from_maybe_unaligned<'a>(p: *const u16, len: usize) -> Cow<'a, [u16]> } } -/// Open a link relative to the parent directory, ensure no symlinks are followed. -fn open_link_no_reparse(parent: &File, name: &[u16], access: u32) -> io::Result { - // This is implemented using the lower level `NtCreateFile` function as - // unfortunately opening a file relative to a parent is not supported by - // win32 functions. It is however a fundamental feature of the NT kernel. - // - // See https://docs.microsoft.com/en-us/windows/win32/api/winternl/nf-winternl-ntcreatefile - unsafe { - let mut handle = ptr::null_mut(); - let mut io_status = c::IO_STATUS_BLOCK::PENDING; - let mut name_str = c::UNICODE_STRING::from_ref(name); - use crate::sync::atomic::{AtomicU32, Ordering}; - // The `OBJ_DONT_REPARSE` attribute ensures that we haven't been - // tricked into following a symlink. However, it may not be available in - // earlier versions of Windows. - static ATTRIBUTES: AtomicU32 = AtomicU32::new(c::OBJ_DONT_REPARSE); - let object = c::OBJECT_ATTRIBUTES { - ObjectName: &mut name_str, - RootDirectory: parent.as_raw_handle(), - Attributes: ATTRIBUTES.load(Ordering::Relaxed), - ..c::OBJECT_ATTRIBUTES::default() - }; - let status = c::NtCreateFile( - &mut handle, - access, - &object, - &mut io_status, - crate::ptr::null_mut(), - 0, - c::FILE_SHARE_DELETE | c::FILE_SHARE_READ | c::FILE_SHARE_WRITE, - c::FILE_OPEN, - // If `name` is a symlink then open the link rather than the target. - c::FILE_OPEN_REPARSE_POINT, - crate::ptr::null_mut(), - 0, - ); - // Convert an NTSTATUS to the more familiar Win32 error codes (aka "DosError") - if c::nt_success(status) { - Ok(File::from_raw_handle(handle)) - } else if status == c::STATUS_DELETE_PENDING { - // We make a special exception for `STATUS_DELETE_PENDING` because - // otherwise this will be mapped to `ERROR_ACCESS_DENIED` which is - // very unhelpful. - Err(io::Error::from_raw_os_error(c::ERROR_DELETE_PENDING as i32)) - } else if status == c::STATUS_INVALID_PARAMETER - && ATTRIBUTES.load(Ordering::Relaxed) == c::OBJ_DONT_REPARSE - { - // Try without `OBJ_DONT_REPARSE`. See above. - ATTRIBUTES.store(0, Ordering::Relaxed); - open_link_no_reparse(parent, name, access) - } else { - Err(io::Error::from_raw_os_error(c::RtlNtStatusToDosError(status) as _)) - } - } -} - impl AsInner for File { #[inline] fn as_inner(&self) -> &Handle { @@ -1142,114 +1109,22 @@ pub fn rmdir(p: &Path) -> io::Result<()> { Ok(()) } -/// Open a file or directory without following symlinks. -fn open_link(path: &Path, access_mode: u32) -> io::Result { +pub fn remove_dir_all(path: &Path) -> io::Result<()> { + // Open a file or directory without following symlinks. let mut opts = OpenOptions::new(); - opts.access_mode(access_mode); + opts.access_mode(c::FILE_LIST_DIRECTORY); // `FILE_FLAG_BACKUP_SEMANTICS` allows opening directories. // `FILE_FLAG_OPEN_REPARSE_POINT` opens a link instead of its target. opts.custom_flags(c::FILE_FLAG_BACKUP_SEMANTICS | c::FILE_FLAG_OPEN_REPARSE_POINT); - File::open(path, &opts) -} - -pub fn remove_dir_all(path: &Path) -> io::Result<()> { - let file = open_link(path, c::DELETE | c::FILE_LIST_DIRECTORY)?; + let file = File::open(path, &opts)?; // Test if the file is not a directory or a symlink to a directory. if (file.basic_info()?.FileAttributes & c::FILE_ATTRIBUTE_DIRECTORY) == 0 { return Err(io::Error::from_raw_os_error(c::ERROR_DIRECTORY as _)); } - match ignore_notfound(remove_dir_all_iterative(&file, File::posix_delete)) { - Err(e) => { - if let Some(code) = e.raw_os_error() { - match code as u32 { - // If POSIX delete is not supported for this filesystem then fallback to win32 delete. - c::ERROR_NOT_SUPPORTED - | c::ERROR_INVALID_FUNCTION - | c::ERROR_INVALID_PARAMETER => { - remove_dir_all_iterative(&file, File::win32_delete) - } - _ => Err(e), - } - } else { - Err(e) - } - } - ok => ok, - } -} - -fn remove_dir_all_iterative(f: &File, delete: fn(&File) -> io::Result<()>) -> io::Result<()> { - // When deleting files we may loop this many times when certain error conditions occur. - // This allows remove_dir_all to succeed when the error is temporary. - const MAX_RETRIES: u32 = 10; - - let mut buffer = DirBuff::new(); - let mut dirlist = vec![f.duplicate()?]; - - // FIXME: This is a hack so we can push to the dirlist vec after borrowing from it. - fn copy_handle(f: &File) -> mem::ManuallyDrop { - unsafe { mem::ManuallyDrop::new(File::from_raw_handle(f.as_raw_handle())) } - } - - let mut restart = true; - while let Some(dir) = dirlist.last() { - let dir = copy_handle(dir); - - // Fill the buffer and iterate the entries. - let more_data = dir.fill_dir_buff(&mut buffer, restart)?; - restart = false; - for (name, is_directory) in buffer.iter() { - if is_directory { - let child_dir = open_link_no_reparse( - &dir, - &name, - c::SYNCHRONIZE | c::DELETE | c::FILE_LIST_DIRECTORY, - ); - // On success, add the handle to the queue. - // If opening the directory fails we treat it the same as a file - if let Ok(child_dir) = child_dir { - dirlist.push(child_dir); - continue; - } - } - for i in 1..=MAX_RETRIES { - let result = open_link_no_reparse(&dir, &name, c::SYNCHRONIZE | c::DELETE); - match result { - Ok(f) => delete(&f)?, - // Already deleted, so skip. - Err(e) if e.kind() == io::ErrorKind::NotFound => break, - // Retry a few times if the file is locked or a delete is already in progress. - Err(e) - if i < MAX_RETRIES - && (e.raw_os_error() == Some(c::ERROR_DELETE_PENDING as _) - || e.raw_os_error() == Some(c::ERROR_SHARING_VIOLATION as _)) => {} - // Otherwise return the error. - Err(e) => return Err(e), - } - thread::yield_now(); - } - } - // If there were no more files then delete the directory. - if !more_data { - if let Some(dir) = dirlist.pop() { - // Retry deleting a few times in case we need to wait for a file to be deleted. - for i in 1..=MAX_RETRIES { - let result = delete(&dir); - if let Err(e) = result { - if i == MAX_RETRIES || e.kind() != io::ErrorKind::DirectoryNotEmpty { - return Err(e); - } - thread::yield_now(); - } else { - break; - } - } - } - } - } - Ok(()) + // Remove the directory and all its contents. + remove_dir_all_iterative(file).io_result() } pub fn readlink(path: &Path) -> io::Result { diff --git a/library/std/src/sys/pal/windows/fs/remove_dir_all.rs b/library/std/src/sys/pal/windows/fs/remove_dir_all.rs new file mode 100644 index 0000000000000..e7234ed8e5f56 --- /dev/null +++ b/library/std/src/sys/pal/windows/fs/remove_dir_all.rs @@ -0,0 +1,196 @@ +//! The Windows implementation of std::fs::remove_dir_all. +//! +//! This needs to address two issues: +//! +//! - It must not be possible to trick this into deleting files outside of +//! the parent directory (see CVE-2022-21658). +//! - It should not fail if many threads or processes call `remove_dir_all` +//! on the same path. +//! +//! The first is handled by using the low-level `NtOpenFile` API to open a file +//! relative to a parent directory. +//! +//! The second is trickier. Deleting a file works by setting its "disposition" +//! to delete. However, it isn't actually deleted until the file is closed. +//! During the gap between these two events, the file is in a kind of limbo +//! state where it still exists in the filesystem but anything trying to open +//! it fails with an error. +//! +//! The mitigations we use here are: +//! +//! - When attempting to open the file, we treat ERROR_DELETE_PENDING as a +//! successful delete. +//! - If the file still hasn't been removed from the filesystem by the time we +//! attempt to delete the parent directory, we try to wait for it to finish. +//! We can't wait indefinitely though so after some number of spins, we give +//! up and return an error. +//! +//! In short, we can't guarantee this will always succeed in the event of a +//! race but we do make a best effort such that it *should* do so. + +use core::ptr; +use core::sync::atomic::{AtomicU32, Ordering}; + +use super::{AsRawHandle, DirBuff, File, FromRawHandle}; +use crate::sys::c; +use crate::sys::pal::windows::api::WinError; +use crate::thread; + +// The maximum number of times to spin when waiting for deletes to complete. +const MAX_RETRIES: usize = 50; + +/// A wrapper around a raw NtOpenFile call. +/// +/// This isn't completely safe because `OBJECT_ATTRIBUTES` contains raw pointers. +unsafe fn nt_open_file( + access: u32, + object_attribute: &c::OBJECT_ATTRIBUTES, + share: u32, + options: u32, +) -> Result { + unsafe { + let mut handle = ptr::null_mut(); + let mut io_status = c::IO_STATUS_BLOCK::PENDING; + let status = + c::NtOpenFile(&mut handle, access, object_attribute, &mut io_status, share, options); + if c::nt_success(status) { + Ok(File::from_raw_handle(handle)) + } else { + // Convert an NTSTATUS to the more familiar Win32 error code (aka "DosError") + let win_error = if status == c::STATUS_DELETE_PENDING { + // We make a special exception for `STATUS_DELETE_PENDING` because + // otherwise this will be mapped to `ERROR_ACCESS_DENIED` which is + // very unhelpful because that can also mean a permission error. + WinError::DELETE_PENDING + } else { + WinError::new(c::RtlNtStatusToDosError(status)) + }; + Err(win_error) + } + } +} + +/// Open the file `path` in the directory `parent`, requesting the given `access` rights. +fn open_link_no_reparse( + parent: &File, + path: &[u16], + access: u32, +) -> Result, WinError> { + // This is implemented using the lower level `NtOpenFile` function as + // unfortunately opening a file relative to a parent is not supported by + // win32 functions. + // + // See https://learn.microsoft.com/windows/win32/api/winternl/nf-winternl-ntopenfile + + // The `OBJ_DONT_REPARSE` attribute ensures that we haven't been + // tricked into following a symlink. However, it may not be available in + // earlier versions of Windows. + static ATTRIBUTES: AtomicU32 = AtomicU32::new(c::OBJ_DONT_REPARSE); + + let result = unsafe { + let mut path_str = c::UNICODE_STRING::from_ref(path); + let mut object = c::OBJECT_ATTRIBUTES { + ObjectName: &mut path_str, + RootDirectory: parent.as_raw_handle(), + Attributes: ATTRIBUTES.load(Ordering::Relaxed), + ..c::OBJECT_ATTRIBUTES::default() + }; + let share = c::FILE_SHARE_DELETE | c::FILE_SHARE_READ | c::FILE_SHARE_WRITE; + let options = c::FILE_OPEN_REPARSE_POINT; + let result = nt_open_file(access, &object, share, options); + + // Retry without OBJ_DONT_REPARSE if it's not supported. + if matches!(result, Err(WinError::INVALID_PARAMETER)) + && ATTRIBUTES.load(Ordering::Relaxed) == c::OBJ_DONT_REPARSE + { + ATTRIBUTES.store(0, Ordering::Relaxed); + object.Attributes = 0; + nt_open_file(access, &object, share, options) + } else { + result + } + }; + + // Ignore not found errors + match result { + Ok(f) => Ok(Some(f)), + Err( + WinError::FILE_NOT_FOUND + | WinError::PATH_NOT_FOUND + | WinError::BAD_NETPATH + | WinError::BAD_NET_NAME + // `DELETE_PENDING` means something else is already trying to delete it + // so we assume that will eventually succeed. + | WinError::DELETE_PENDING, + ) => Ok(None), + Err(e) => Err(e), + } +} + +fn open_dir(parent: &File, name: &[u16]) -> Result, WinError> { + open_link_no_reparse(parent, name, c::SYNCHRONIZE | c::FILE_LIST_DIRECTORY) +} + +fn delete(parent: &File, name: &[u16]) -> Result<(), WinError> { + // Note that the `delete` function consumes the opened file to ensure it's + // dropped immediately. See module comments for why this is important. + match open_link_no_reparse(parent, name, c::SYNCHRONIZE | c::DELETE) { + Ok(Some(f)) => f.delete(), + Ok(None) => Ok(()), + Err(e) => Err(e), + } +} + +/// A simple retry loop that keeps running `f` while it fails with the given +/// error code or until `MAX_RETRIES` is reached. +fn retry( + mut f: impl FnMut() -> Result, + ignore: WinError, +) -> Result { + let mut i = MAX_RETRIES; + loop { + i -= 1; + if i == 0 { + return f(); + } else { + let result = f(); + if result != Err(ignore) { + return result; + } + } + thread::yield_now(); + } +} + +pub fn remove_dir_all_iterative(dir: File) -> Result<(), WinError> { + let mut buffer = DirBuff::new(); + let mut dirlist = vec![dir]; + + let mut restart = true; + 'outer: while let Some(dir) = dirlist.pop() { + let more_data = dir.fill_dir_buff(&mut buffer, restart)?; + for (name, is_directory) in buffer.iter() { + if is_directory { + let Some(subdir) = open_dir(&dir, &name)? else { continue }; + dirlist.push(dir); + dirlist.push(subdir); + continue 'outer; + } else { + // Attempt to delete, retrying on sharing violation errors as these + // can often be very temporary. E.g. if something takes just a + // bit longer than expected to release a file handle. + retry(|| delete(&dir, &name), WinError::SHARING_VIOLATION)?; + } + } + if more_data { + dirlist.push(dir); + restart = false; + } else { + // Attempt to delete, retrying on not empty errors because we may + // need to wait some time for files to be removed from the filesystem. + retry(|| delete(&dir, &[]), WinError::DIR_NOT_EMPTY)?; + restart = true; + } + } + Ok(()) +} From 467dbcba60bb109636a31af3d298e253850422dc Mon Sep 17 00:00:00 2001 From: Kappa322 Date: Sat, 20 Jul 2024 13:05:55 +0200 Subject: [PATCH 0302/2194] Improve documentation for ::from_str_radix Two improvements to the documentation: - Document `-` as a valid character for signed integer destinations - Make the documentation even more clear that extra whitespace and non-digit characters is invalid. Many other languages, e.g. c++, are very permissive in string to integer routines and simply try to consume as much as they can, ignoring the rest. This is trying to make the transition for developers who are used to the conversion semantics in these languages a bit easier. --- library/core/src/num/mod.rs | 69 +++++++++++++++++++++------- library/core/src/num/nonzero.rs | 10 ---- library/core/tests/num/int_macros.rs | 2 + 3 files changed, 55 insertions(+), 26 deletions(-) diff --git a/library/core/src/num/mod.rs b/library/core/src/num/mod.rs index e9e5324666ada..2bcfe43a55b83 100644 --- a/library/core/src/num/mod.rs +++ b/library/core/src/num/mod.rs @@ -23,6 +23,16 @@ macro_rules! unlikely { }; } +// Use this when the generated code should differ between signed and unsigned types. +macro_rules! sign_dependent_expr { + (signed ? if signed { $signed_case:expr } if unsigned { $unsigned_case:expr } ) => { + $signed_case + }; + (unsigned ? if signed { $signed_case:expr } if unsigned { $unsigned_case:expr } ) => { + $unsigned_case + }; +} + // All these modules are technically private and only exposed for coretests: #[cfg(not(no_fp_fmt_parse))] pub mod bignum; @@ -1410,15 +1420,25 @@ const fn from_str_radix_panic(radix: u32) { } macro_rules! from_str_radix { - ($($int_ty:ty)+) => {$( + ($signedness:ident $($int_ty:ty)+) => {$( impl $int_ty { /// Converts a string slice in a given base to an integer. /// - /// The string is expected to be an optional `+` sign - /// followed by digits. - /// Leading and trailing whitespace represent an error. - /// Digits are a subset of these characters, depending on `radix`: + /// The string is expected to be an optional + #[doc = sign_dependent_expr!{ + $signedness ? + if signed { + " `+` or `-` " + } + if unsigned { + " `+` " + } + }] + /// sign followed by only digits. Leading and trailing non-digit characters (including + /// whitespace) represent an error. Underscores (which are accepted in rust literals) + /// also represent an error. /// + /// Digits are a subset of these characters, depending on `radix`: /// * `0-9` /// * `a-z` /// * `A-Z` @@ -1430,10 +1450,13 @@ macro_rules! from_str_radix { /// # Examples /// /// Basic usage: - /// /// ``` #[doc = concat!("assert_eq!(", stringify!($int_ty), "::from_str_radix(\"A\", 16), Ok(10));")] /// ``` + /// Trailing space returns error: + /// ``` + #[doc = concat!("assert!(", stringify!($int_ty), "::from_str_radix(\"1 \", 10).is_err());")] + /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_stable(feature = "const_int_from_str", since = "CURRENT_RUSTC_VERSION")] pub const fn from_str_radix(src: &str, radix: u32) -> Result<$int_ty, ParseIntError> { @@ -1535,20 +1558,31 @@ macro_rules! from_str_radix { )+} } -from_str_radix! { i8 u8 i16 u16 i32 u32 i64 u64 i128 u128 } +from_str_radix! { unsigned u8 u16 u32 u64 u128 } +from_str_radix! { signed i8 i16 i32 i64 i128 } // Re-use the relevant implementation of from_str_radix for isize and usize to avoid outputting two // identical functions. macro_rules! from_str_radix_size_impl { - ($($t:ident $size:ty),*) => {$( + ($($signedness:ident $t:ident $size:ty),*) => {$( impl $size { /// Converts a string slice in a given base to an integer. /// - /// The string is expected to be an optional `+` sign - /// followed by digits. - /// Leading and trailing whitespace represent an error. - /// Digits are a subset of these characters, depending on `radix`: + /// The string is expected to be an optional + #[doc = sign_dependent_expr!{ + $signedness ? + if signed { + " `+` or `-` " + } + if unsigned { + " `+` " + } + }] + /// sign followed by only digits. Leading and trailing non-digit characters (including + /// whitespace) represent an error. Underscores (which are accepted in rust literals) + /// also represent an error. /// + /// Digits are a subset of these characters, depending on `radix`: /// * `0-9` /// * `a-z` /// * `A-Z` @@ -1560,10 +1594,13 @@ macro_rules! from_str_radix_size_impl { /// # Examples /// /// Basic usage: - /// /// ``` #[doc = concat!("assert_eq!(", stringify!($size), "::from_str_radix(\"A\", 16), Ok(10));")] /// ``` + /// Trailing space returns error: + /// ``` + #[doc = concat!("assert!(", stringify!($size), "::from_str_radix(\"1 \", 10).is_err());")] + /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_stable(feature = "const_int_from_str", since = "CURRENT_RUSTC_VERSION")] pub const fn from_str_radix(src: &str, radix: u32) -> Result<$size, ParseIntError> { @@ -1576,8 +1613,8 @@ macro_rules! from_str_radix_size_impl { } #[cfg(target_pointer_width = "16")] -from_str_radix_size_impl! { i16 isize, u16 usize } +from_str_radix_size_impl! { signed i16 isize, unsigned u16 usize } #[cfg(target_pointer_width = "32")] -from_str_radix_size_impl! { i32 isize, u32 usize } +from_str_radix_size_impl! { signed i32 isize, unsigned u32 usize } #[cfg(target_pointer_width = "64")] -from_str_radix_size_impl! { i64 isize, u64 usize } +from_str_radix_size_impl! { signed i64 isize, unsigned u64 usize } diff --git a/library/core/src/num/nonzero.rs b/library/core/src/num/nonzero.rs index 8b888f12da0b1..e5c9a7e086ac9 100644 --- a/library/core/src/num/nonzero.rs +++ b/library/core/src/num/nonzero.rs @@ -1972,16 +1972,6 @@ macro_rules! nonzero_integer_signedness_dependent_methods { }; } -// Use this when the generated code should differ between signed and unsigned types. -macro_rules! sign_dependent_expr { - (signed ? if signed { $signed_case:expr } if unsigned { $unsigned_case:expr } ) => { - $signed_case - }; - (unsigned ? if signed { $signed_case:expr } if unsigned { $unsigned_case:expr } ) => { - $unsigned_case - }; -} - nonzero_integer! { Self = NonZeroU8, Primitive = unsigned u8, diff --git a/library/core/tests/num/int_macros.rs b/library/core/tests/num/int_macros.rs index 830a96204ca03..6a26bd15a663d 100644 --- a/library/core/tests/num/int_macros.rs +++ b/library/core/tests/num/int_macros.rs @@ -244,6 +244,8 @@ macro_rules! int_module { assert_eq!($T::from_str_radix("Z", 35).ok(), None::<$T>); assert_eq!($T::from_str_radix("-9", 2).ok(), None::<$T>); + assert_eq!($T::from_str_radix("10_0", 10).ok(), None::<$T>); + assert_eq!(u32::from_str_radix("-9", 10).ok(), None::); } #[test] From 5d044724611983620c9c1ce52c6eef80be28633d Mon Sep 17 00:00:00 2001 From: Pavel Grigorenko Date: Thu, 15 Aug 2024 18:05:59 +0300 Subject: [PATCH 0303/2194] Implement `elided_named_lifetimes` lint --- compiler/rustc_ast_lowering/src/lib.rs | 6 +- .../src/lifetime_collector.rs | 2 +- compiler/rustc_hir/src/def.rs | 9 ++- compiler/rustc_lint/messages.ftl | 4 + .../rustc_lint/src/context/diagnostics.rs | 13 +++ compiler/rustc_lint/src/lints.rs | 10 +++ compiler/rustc_lint_defs/src/builtin.rs | 33 ++++++++ compiler/rustc_lint_defs/src/lib.rs | 7 ++ compiler/rustc_resolve/src/late.rs | 79 ++++++++++++++++--- .../rustc_resolve/src/late/diagnostics.rs | 11 ++- 10 files changed, 154 insertions(+), 20 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index bcc2c29a2ff79..9b46e7c46b666 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -837,7 +837,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { (hir::ParamName::Fresh, hir::LifetimeParamKind::Elided(kind)) } - LifetimeRes::Static | LifetimeRes::Error => return None, + LifetimeRes::Static { .. } | LifetimeRes::Error => return None, res => panic!( "Unexpected lifetime resolution {:?} for {:?} at {:?}", res, ident, ident.span @@ -1656,7 +1656,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } // Opaques do not capture `'static` - LifetimeRes::Static | LifetimeRes::Error => { + LifetimeRes::Static { .. } | LifetimeRes::Error => { continue; } @@ -2069,7 +2069,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { hir::LifetimeName::Param(param) } LifetimeRes::Infer => hir::LifetimeName::Infer, - LifetimeRes::Static => hir::LifetimeName::Static, + LifetimeRes::Static { .. } => hir::LifetimeName::Static, LifetimeRes::Error => hir::LifetimeName::Error, res => panic!( "Unexpected lifetime resolution {:?} for {:?} at {:?}", diff --git a/compiler/rustc_ast_lowering/src/lifetime_collector.rs b/compiler/rustc_ast_lowering/src/lifetime_collector.rs index 77cc2a36a531d..76c957afa5461 100644 --- a/compiler/rustc_ast_lowering/src/lifetime_collector.rs +++ b/compiler/rustc_ast_lowering/src/lifetime_collector.rs @@ -27,7 +27,7 @@ impl<'ast> LifetimeCollectVisitor<'ast> { self.collected_lifetimes.insert(lifetime); } } - LifetimeRes::Static | LifetimeRes::Error => { + LifetimeRes::Static { .. } | LifetimeRes::Error => { self.collected_lifetimes.insert(lifetime); } LifetimeRes::Infer => {} diff --git a/compiler/rustc_hir/src/def.rs b/compiler/rustc_hir/src/def.rs index 36e29d2dcb2cc..c5dc4dacab650 100644 --- a/compiler/rustc_hir/src/def.rs +++ b/compiler/rustc_hir/src/def.rs @@ -863,8 +863,13 @@ pub enum LifetimeRes { /// This variant is used for anonymous lifetimes that we did not resolve during /// late resolution. Those lifetimes will be inferred by typechecking. Infer, - /// Explicit `'static` lifetime. - Static, + /// `'static` lifetime. + Static { + /// We do not want to emit `elided_named_lifetimes` + /// when we are inside of a const item or a static, + /// because it would get too annoying. + suppress_elision_warning: bool, + }, /// Resolution failure. Error, /// HACK: This is used to recover the NodeId of an elided lifetime. diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl index 08a50050a36d5..31b7eb5ee7df3 100644 --- a/compiler/rustc_lint/messages.ftl +++ b/compiler/rustc_lint/messages.ftl @@ -252,6 +252,10 @@ lint_duplicate_macro_attribute = lint_duplicate_matcher_binding = duplicate matcher binding +lint_elided_named_lifetime = elided lifetime has a name + .label_elided = this elided lifetime gets resolved as `{$name}` + .label_named = lifetime `{$name}` declared here + lint_enum_intrinsics_mem_discriminant = the return value of `mem::discriminant` is unspecified when called with a non-enum type .note = the argument to `discriminant` should be a reference to an enum, but it was passed a reference to a `{$ty_param}`, which is not an enum diff --git a/compiler/rustc_lint/src/context/diagnostics.rs b/compiler/rustc_lint/src/context/diagnostics.rs index f289d4c81b3c1..fd43afa174383 100644 --- a/compiler/rustc_lint/src/context/diagnostics.rs +++ b/compiler/rustc_lint/src/context/diagnostics.rs @@ -10,6 +10,7 @@ use rustc_errors::{ use rustc_middle::middle::stability; use rustc_session::lint::BuiltinLintDiag; use rustc_session::Session; +use rustc_span::symbol::kw; use rustc_span::BytePos; use tracing::debug; @@ -441,5 +442,17 @@ pub(super) fn decorate_lint(sess: &Session, diagnostic: BuiltinLintDiag, diag: & BuiltinLintDiag::UnexpectedBuiltinCfg { cfg, cfg_name, controlled_by } => { lints::UnexpectedBuiltinCfg { cfg, cfg_name, controlled_by }.decorate_lint(diag) } + BuiltinLintDiag::ElidedIsStatic { elided } => { + lints::ElidedNamedLifetime { elided, name: kw::StaticLifetime, named_declaration: None } + .decorate_lint(diag) + } + BuiltinLintDiag::ElidedIsParam { elided, param: (param_name, param_span) } => { + lints::ElidedNamedLifetime { + elided, + name: param_name, + named_declaration: Some(param_span), + } + .decorate_lint(diag) + } } } diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index c6bcb1f3e8334..2712e25668a48 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -2611,6 +2611,16 @@ pub(crate) struct ElidedLifetimesInPaths { pub subdiag: ElidedLifetimeInPathSubdiag, } +#[derive(LintDiagnostic)] +#[diag(lint_elided_named_lifetime)] +pub(crate) struct ElidedNamedLifetime { + #[label(lint_label_elided)] + pub elided: Span, + pub name: Symbol, + #[label(lint_label_named)] + pub named_declaration: Option, +} + #[derive(LintDiagnostic)] #[diag(lint_invalid_crate_type_value)] pub(crate) struct UnknownCrateTypes { diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index 44c72e0c4fe33..3e8b180e78b78 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs @@ -42,6 +42,7 @@ declare_lint_pass! { DUPLICATE_MACRO_ATTRIBUTES, ELIDED_LIFETIMES_IN_ASSOCIATED_CONSTANT, ELIDED_LIFETIMES_IN_PATHS, + ELIDED_NAMED_LIFETIMES, EXPLICIT_BUILTIN_CFGS_IN_FLAGS, EXPORTED_PRIVATE_DEPENDENCIES, FFI_UNWIND_CALLS, @@ -1862,6 +1863,38 @@ declare_lint! { "hidden lifetime parameters in types are deprecated" } +declare_lint! { + /// The `elided_named_lifetimes` lint detects when an elided + /// lifetime ends up being a named lifetime, such as `'static` + /// or some lifetime parameter `'a`. + /// + /// ### Example + /// + /// ```rust,compile_fail + /// #![deny(elided_named_lifetimes)] + /// struct Foo; + /// impl Foo { + /// pub fn get_mut(&'static self, x: &mut u8) -> &mut u8 { + /// unsafe { &mut *(x as *mut _) } + /// } + /// } + /// ``` + /// + /// {{produces}} + /// + /// ### Explanation + /// + /// Lifetime elision is quite useful, because it frees you from having + /// to give each lifetime its own name, but sometimes it can produce + /// somewhat surprising resolutions. In safe code, it is mostly okay, + /// because the borrow checker prevents any unsoundness, so the worst + /// case scenario is you get a confusing error message in some other place. + /// But with `unsafe` code, such unexpected resolutions may lead to unsound code. + pub ELIDED_NAMED_LIFETIMES, + Warn, + "detects when an elided lifetime gets resolved to be `'static` or some named parameter" +} + declare_lint! { /// The `bare_trait_objects` lint suggests using `dyn Trait` for trait /// objects. diff --git a/compiler/rustc_lint_defs/src/lib.rs b/compiler/rustc_lint_defs/src/lib.rs index c17b85db3b044..8ddbff284cc2e 100644 --- a/compiler/rustc_lint_defs/src/lib.rs +++ b/compiler/rustc_lint_defs/src/lib.rs @@ -589,6 +589,13 @@ pub enum BuiltinLintDiag { }, MacroExpandedMacroExportsAccessedByAbsolutePaths(Span), ElidedLifetimesInPaths(usize, Span, bool, Span), + ElidedIsStatic { + elided: Span, + }, + ElidedIsParam { + elided: Span, + param: (Symbol, Span), + }, UnknownCrateTypes { span: Span, candidate: Option, diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 40fdb01a72c0e..8ec0469ed6d87 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -1557,14 +1557,14 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { if ident.name == kw::StaticLifetime { self.record_lifetime_res( lifetime.id, - LifetimeRes::Static, + LifetimeRes::Static { suppress_elision_warning: false }, LifetimeElisionCandidate::Named, ); return; } if ident.name == kw::UnderscoreLifetime { - return self.resolve_anonymous_lifetime(lifetime, false); + return self.resolve_anonymous_lifetime(lifetime, lifetime.id, false); } let mut lifetime_rib_iter = self.lifetime_ribs.iter().rev(); @@ -1667,13 +1667,23 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { } #[instrument(level = "debug", skip(self))] - fn resolve_anonymous_lifetime(&mut self, lifetime: &Lifetime, elided: bool) { + fn resolve_anonymous_lifetime( + &mut self, + lifetime: &Lifetime, + id_for_lint: NodeId, + elided: bool, + ) { debug_assert_eq!(lifetime.ident.name, kw::UnderscoreLifetime); let kind = if elided { MissingLifetimeKind::Ampersand } else { MissingLifetimeKind::Underscore }; - let missing_lifetime = - MissingLifetime { id: lifetime.id, span: lifetime.ident.span, kind, count: 1 }; + let missing_lifetime = MissingLifetime { + id: lifetime.id, + span: lifetime.ident.span, + kind, + count: 1, + id_for_lint, + }; let elision_candidate = LifetimeElisionCandidate::Missing(missing_lifetime); for (i, rib) in self.lifetime_ribs.iter().enumerate().rev() { debug!(?rib.kind); @@ -1697,7 +1707,8 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { if lifetimes_in_scope.is_empty() { self.record_lifetime_res( lifetime.id, - LifetimeRes::Static, + // We are inside a const item, so do not warn. + LifetimeRes::Static { suppress_elision_warning: true }, elision_candidate, ); return; @@ -1800,7 +1811,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { LifetimeRes::ElidedAnchor { start: id, end: NodeId::from_u32(id.as_u32() + 1) }, LifetimeElisionCandidate::Ignore, ); - self.resolve_anonymous_lifetime(<, true); + self.resolve_anonymous_lifetime(<, anchor_id, true); } #[instrument(level = "debug", skip(self))] @@ -1916,6 +1927,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { }; let missing_lifetime = MissingLifetime { id: node_ids.start, + id_for_lint: segment_id, span: elided_lifetime_span, kind, count: expected_lifetimes, @@ -2039,8 +2051,44 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { if let Some(prev_res) = self.r.lifetimes_res_map.insert(id, res) { panic!("lifetime {id:?} resolved multiple times ({prev_res:?} before, {res:?} now)") } + + match candidate { + LifetimeElisionCandidate::Missing(missing @ MissingLifetime { .. }) => { + debug_assert_eq!(id, missing.id); + match res { + LifetimeRes::Static { suppress_elision_warning } => { + if !suppress_elision_warning { + self.r.lint_buffer.buffer_lint( + lint::builtin::ELIDED_NAMED_LIFETIMES, + missing.id_for_lint, + missing.span, + BuiltinLintDiag::ElidedIsStatic { elided: missing.span }, + ); + } + } + LifetimeRes::Param { param, binder: _ } => { + let tcx = self.r.tcx(); + self.r.lint_buffer.buffer_lint( + lint::builtin::ELIDED_NAMED_LIFETIMES, + missing.id_for_lint, + missing.span, + BuiltinLintDiag::ElidedIsParam { + elided: missing.span, + param: (tcx.item_name(param.into()), tcx.source_span(param)), + }, + ); + } + LifetimeRes::Fresh { .. } + | LifetimeRes::Infer + | LifetimeRes::Error + | LifetimeRes::ElidedAnchor { .. } => {} + } + } + LifetimeElisionCandidate::Ignore | LifetimeElisionCandidate::Named => {} + } + match res { - LifetimeRes::Param { .. } | LifetimeRes::Fresh { .. } | LifetimeRes::Static => { + LifetimeRes::Param { .. } | LifetimeRes::Fresh { .. } | LifetimeRes::Static { .. } => { if let Some(ref mut candidates) = self.lifetime_elision_candidates { candidates.push((res, candidate)); } @@ -2558,9 +2606,14 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { ItemKind::Static(box ast::StaticItem { ref ty, ref expr, .. }) => { self.with_static_rib(def_kind, |this| { - this.with_lifetime_rib(LifetimeRibKind::Elided(LifetimeRes::Static), |this| { - this.visit_ty(ty); - }); + this.with_lifetime_rib( + LifetimeRibKind::Elided(LifetimeRes::Static { + suppress_elision_warning: true, + }), + |this| { + this.visit_ty(ty); + }, + ); if let Some(expr) = expr { // We already forbid generic params because of the above item rib, // so it doesn't matter whether this is a trivial constant. @@ -2589,7 +2642,9 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { this.visit_generics(generics); this.with_lifetime_rib( - LifetimeRibKind::Elided(LifetimeRes::Static), + LifetimeRibKind::Elided(LifetimeRes::Static { + suppress_elision_warning: true, + }), |this| this.visit_ty(ty), ); diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index f778b0ee3acc0..8f516c2db0900 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -102,6 +102,13 @@ fn import_candidate_to_enum_paths(suggestion: &ImportSuggestion) -> (String, Str pub(super) struct MissingLifetime { /// Used to overwrite the resolution with the suggestion, to avoid cascading errors. pub id: NodeId, + /// As we cannot yet emit lints in this crate and have to buffer them instead, + /// we need to associate each lint with some `NodeId`, + /// however for some `MissingLifetime`s their `NodeId`s are "fake", + /// in a sense that they are temporary and not get preserved down the line, + /// which means that the lints for those nodes will not get emitted. + /// To combat this, we can try to use some other `NodeId`s as a fallback option. + pub id_for_lint: NodeId, /// Where to suggest adding the lifetime. pub span: Span, /// How the lifetime was introduced, to have the correct space and comma. @@ -3028,7 +3035,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { maybe_static = true; in_scope_lifetimes = vec![( Ident::with_dummy_span(kw::StaticLifetime), - (DUMMY_NODE_ID, LifetimeRes::Static), + (DUMMY_NODE_ID, LifetimeRes::Static { suppress_elision_warning: false }), )]; } } else if elided_len == 0 { @@ -3040,7 +3047,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { maybe_static = true; in_scope_lifetimes = vec![( Ident::with_dummy_span(kw::StaticLifetime), - (DUMMY_NODE_ID, LifetimeRes::Static), + (DUMMY_NODE_ID, LifetimeRes::Static { suppress_elision_warning: false }), )]; } } else if num_params == 1 { From f7b0b221373e7de22191fccbced9942a21af924f Mon Sep 17 00:00:00 2001 From: Pavel Grigorenko Date: Sat, 17 Aug 2024 23:47:37 +0300 Subject: [PATCH 0304/2194] Fix `elided_named_lifetimes` in code --- library/alloc/src/string.rs | 2 +- library/core/src/fmt/rt.rs | 20 +++++++++---------- .../rust-analyzer/crates/hir-def/src/attr.rs | 4 ++-- .../rust-analyzer/crates/hir-def/src/body.rs | 2 +- 4 files changed, 14 insertions(+), 14 deletions(-) diff --git a/library/alloc/src/string.rs b/library/alloc/src/string.rs index e628be1546f76..bc8b7e24bf12b 100644 --- a/library/alloc/src/string.rs +++ b/library/alloc/src/string.rs @@ -2313,7 +2313,7 @@ impl<'b> Pattern for &'b String { } #[inline] - fn strip_suffix_of<'a>(self, haystack: &'a str) -> Option<&str> + fn strip_suffix_of<'a>(self, haystack: &'a str) -> Option<&'a str> where Self::Searcher<'a>: core::str::pattern::ReverseSearcher<'a>, { diff --git a/library/core/src/fmt/rt.rs b/library/core/src/fmt/rt.rs index f29ac99b29255..eee4a9e4c6c89 100644 --- a/library/core/src/fmt/rt.rs +++ b/library/core/src/fmt/rt.rs @@ -110,43 +110,43 @@ impl<'a> Argument<'a> { } #[inline(always)] - pub fn new_display<'b, T: Display>(x: &'b T) -> Argument<'_> { + pub fn new_display<'b, T: Display>(x: &'b T) -> Argument<'b> { Self::new(x, Display::fmt) } #[inline(always)] - pub fn new_debug<'b, T: Debug>(x: &'b T) -> Argument<'_> { + pub fn new_debug<'b, T: Debug>(x: &'b T) -> Argument<'b> { Self::new(x, Debug::fmt) } #[inline(always)] - pub fn new_debug_noop<'b, T: Debug>(x: &'b T) -> Argument<'_> { + pub fn new_debug_noop<'b, T: Debug>(x: &'b T) -> Argument<'b> { Self::new(x, |_, _| Ok(())) } #[inline(always)] - pub fn new_octal<'b, T: Octal>(x: &'b T) -> Argument<'_> { + pub fn new_octal<'b, T: Octal>(x: &'b T) -> Argument<'b> { Self::new(x, Octal::fmt) } #[inline(always)] - pub fn new_lower_hex<'b, T: LowerHex>(x: &'b T) -> Argument<'_> { + pub fn new_lower_hex<'b, T: LowerHex>(x: &'b T) -> Argument<'b> { Self::new(x, LowerHex::fmt) } #[inline(always)] - pub fn new_upper_hex<'b, T: UpperHex>(x: &'b T) -> Argument<'_> { + pub fn new_upper_hex<'b, T: UpperHex>(x: &'b T) -> Argument<'b> { Self::new(x, UpperHex::fmt) } #[inline(always)] - pub fn new_pointer<'b, T: Pointer>(x: &'b T) -> Argument<'_> { + pub fn new_pointer<'b, T: Pointer>(x: &'b T) -> Argument<'b> { Self::new(x, Pointer::fmt) } #[inline(always)] - pub fn new_binary<'b, T: Binary>(x: &'b T) -> Argument<'_> { + pub fn new_binary<'b, T: Binary>(x: &'b T) -> Argument<'b> { Self::new(x, Binary::fmt) } #[inline(always)] - pub fn new_lower_exp<'b, T: LowerExp>(x: &'b T) -> Argument<'_> { + pub fn new_lower_exp<'b, T: LowerExp>(x: &'b T) -> Argument<'b> { Self::new(x, LowerExp::fmt) } #[inline(always)] - pub fn new_upper_exp<'b, T: UpperExp>(x: &'b T) -> Argument<'_> { + pub fn new_upper_exp<'b, T: UpperExp>(x: &'b T) -> Argument<'b> { Self::new(x, UpperExp::fmt) } #[inline(always)] diff --git a/src/tools/rust-analyzer/crates/hir-def/src/attr.rs b/src/tools/rust-analyzer/crates/hir-def/src/attr.rs index 198dc93f6b141..c0547bc3c8d12 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/attr.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/attr.rs @@ -117,7 +117,7 @@ impl Attrs { } impl Attrs { - pub fn by_key<'attrs>(&'attrs self, key: &'attrs Symbol) -> AttrQuery<'_> { + pub fn by_key<'attrs>(&'attrs self, key: &'attrs Symbol) -> AttrQuery<'attrs> { AttrQuery { attrs: self, key } } @@ -594,7 +594,7 @@ impl<'attr> AttrQuery<'attr> { /// #[doc(html_root_url = "url")] /// ^^^^^^^^^^^^^ key /// ``` - pub fn find_string_value_in_tt(self, key: &'attr Symbol) -> Option<&str> { + pub fn find_string_value_in_tt(self, key: &'attr Symbol) -> Option<&'attr str> { self.tt_values().find_map(|tt| { let name = tt.token_trees.iter() .skip_while(|tt| !matches!(tt, tt::TokenTree::Leaf(tt::Leaf::Ident(tt::Ident { sym, ..} )) if *sym == *key)) diff --git a/src/tools/rust-analyzer/crates/hir-def/src/body.rs b/src/tools/rust-analyzer/crates/hir-def/src/body.rs index a988317e046ef..d390a9cd2d747 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/body.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/body.rs @@ -197,7 +197,7 @@ impl Body { pub fn blocks<'a>( &'a self, db: &'a dyn DefDatabase, - ) -> impl Iterator)> + '_ { + ) -> impl Iterator)> + 'a { self.block_scopes.iter().map(move |&block| (block, db.block_def_map(block))) } From a9b959a020cc156ef57a972c83381aabc43b1174 Mon Sep 17 00:00:00 2001 From: Pavel Grigorenko Date: Sat, 31 Aug 2024 15:31:31 +0300 Subject: [PATCH 0305/2194] elided_named_lifetimes: bless & add tests --- .../clippy/tests/ui/needless_lifetimes.stderr | 13 +++++- src/tools/clippy/tests/ui/ptr_arg.stderr | 11 ++++- tests/ui/async-await/issues/issue-63388-1.rs | 2 +- .../async-await/issues/issue-63388-1.stderr | 13 +++++- .../type-dependent/issue-71348.full.stderr | 10 ++++ .../type-dependent/issue-71348.min.stderr | 10 +++- .../type-dependent/issue-71348.rs | 1 + tests/ui/consts/min_const_fn/min_const_fn.rs | 4 +- .../consts/min_const_fn/min_const_fn.stderr | 22 ++++++++- tests/ui/generics/generic-no-mangle.fixed | 2 +- tests/ui/generics/generic-no-mangle.rs | 2 +- tests/ui/impl-trait/impl-fn-hrtb-bounds.rs | 1 + .../ui/impl-trait/impl-fn-hrtb-bounds.stderr | 12 ++++- .../impl-fn-predefined-lifetimes.rs | 1 + .../impl-fn-predefined-lifetimes.stderr | 14 ++++-- .../rpit-assoc-pair-with-lifetime.rs | 1 + .../rpit-assoc-pair-with-lifetime.stderr | 10 ++++ ...-return-type-requires-explicit-lifetime.rs | 1 + ...urn-type-requires-explicit-lifetime.stderr | 12 ++++- ...-one-existing-name-if-else-using-impl-3.rs | 1 + ...-existing-name-if-else-using-impl-3.stderr | 16 +++++-- .../example-from-issue48686.rs | 12 +++++ .../example-from-issue48686.stderr | 14 ++++++ .../missing-lifetime-kind.rs | 27 +++++++++++ .../missing-lifetime-kind.stderr | 40 ++++++++++++++++ .../not-tied-to-crate.rs | 17 +++++++ .../not-tied-to-crate.stderr | 26 +++++++++++ .../ui/lint/elided-named-lifetimes/static.rs | 46 +++++++++++++++++++ .../lint/elided-named-lifetimes/static.stderr | 32 +++++++++++++ .../object-lifetime-default-elision.rs | 2 + .../object-lifetime-default-elision.stderr | 14 +++++- .../elision/ignore-non-reference-lifetimes.rs | 2 + .../ignore-non-reference-lifetimes.stderr | 16 +++++++ tests/ui/self/elision/lt-ref-self-async.fixed | 2 +- tests/ui/self/elision/lt-ref-self-async.rs | 2 +- tests/ui/self/self_lifetime-async.rs | 2 + tests/ui/self/self_lifetime-async.stderr | 18 ++++++++ tests/ui/self/self_lifetime.rs | 2 + tests/ui/self/self_lifetime.stderr | 18 ++++++++ .../impl-trait-missing-lifetime-gated.rs | 1 + .../impl-trait-missing-lifetime-gated.stderr | 10 +++- .../missing-lifetimes-in-signature.rs | 1 + .../missing-lifetimes-in-signature.stderr | 10 +++- .../missing_lifetime_bound.rs | 2 +- .../missing_lifetime_bound.stderr | 12 ++++- 45 files changed, 460 insertions(+), 27 deletions(-) create mode 100644 tests/ui/const-generics/type-dependent/issue-71348.full.stderr create mode 100644 tests/ui/impl-trait/rpit-assoc-pair-with-lifetime.stderr create mode 100644 tests/ui/lint/elided-named-lifetimes/example-from-issue48686.rs create mode 100644 tests/ui/lint/elided-named-lifetimes/example-from-issue48686.stderr create mode 100644 tests/ui/lint/elided-named-lifetimes/missing-lifetime-kind.rs create mode 100644 tests/ui/lint/elided-named-lifetimes/missing-lifetime-kind.stderr create mode 100644 tests/ui/lint/elided-named-lifetimes/not-tied-to-crate.rs create mode 100644 tests/ui/lint/elided-named-lifetimes/not-tied-to-crate.stderr create mode 100644 tests/ui/lint/elided-named-lifetimes/static.rs create mode 100644 tests/ui/lint/elided-named-lifetimes/static.stderr create mode 100644 tests/ui/self/elision/ignore-non-reference-lifetimes.stderr create mode 100644 tests/ui/self/self_lifetime-async.stderr create mode 100644 tests/ui/self/self_lifetime.stderr diff --git a/src/tools/clippy/tests/ui/needless_lifetimes.stderr b/src/tools/clippy/tests/ui/needless_lifetimes.stderr index f325d27b8c753..50f845e2d9291 100644 --- a/src/tools/clippy/tests/ui/needless_lifetimes.stderr +++ b/src/tools/clippy/tests/ui/needless_lifetimes.stderr @@ -1,3 +1,14 @@ +error: elided lifetime has a name + --> tests/ui/needless_lifetimes.rs:266:52 + | +LL | fn named_input_elided_output<'a>(_arg: &'a str) -> &str { + | -- ^ this elided lifetime gets resolved as `'a` + | | + | lifetime `'a` declared here + | + = note: `-D elided-named-lifetimes` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(elided_named_lifetimes)]` + error: the following explicit lifetimes could be elided: 'a, 'b --> tests/ui/needless_lifetimes.rs:17:23 | @@ -553,5 +564,5 @@ LL - fn one_input<'a>(x: &'a u8) -> &'a u8 { LL + fn one_input(x: &u8) -> &u8 { | -error: aborting due to 46 previous errors +error: aborting due to 47 previous errors diff --git a/src/tools/clippy/tests/ui/ptr_arg.stderr b/src/tools/clippy/tests/ui/ptr_arg.stderr index 1848ef80fc495..4246453e64ca7 100644 --- a/src/tools/clippy/tests/ui/ptr_arg.stderr +++ b/src/tools/clippy/tests/ui/ptr_arg.stderr @@ -1,3 +1,12 @@ +error: elided lifetime has a name + --> tests/ui/ptr_arg.rs:295:56 + | +LL | fn cow_good_ret_ty<'a>(input: &'a Cow<'a, str>) -> &str { + | -- lifetime `'a` declared here ^ this elided lifetime gets resolved as `'a` + | + = note: `-D elided-named-lifetimes` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(elided_named_lifetimes)]` + error: writing `&Vec` instead of `&[_]` involves a new object where a slice will do --> tests/ui/ptr_arg.rs:13:14 | @@ -212,5 +221,5 @@ error: using a reference to `Cow` is not recommended LL | fn cow_bad_ret_ty_2<'a, 'b>(input: &'a Cow<'a, str>) -> &'b str { | ^^^^^^^^^^^^^^^^ help: change this to: `&str` -error: aborting due to 24 previous errors +error: aborting due to 25 previous errors diff --git a/tests/ui/async-await/issues/issue-63388-1.rs b/tests/ui/async-await/issues/issue-63388-1.rs index 32026a22a1616..a6f499ba94e29 100644 --- a/tests/ui/async-await/issues/issue-63388-1.rs +++ b/tests/ui/async-await/issues/issue-63388-1.rs @@ -9,7 +9,7 @@ trait Foo {} impl Xyz { async fn do_sth<'a>( &'a self, foo: &dyn Foo - ) -> &dyn Foo + ) -> &dyn Foo //~ WARNING elided lifetime has a name { //~^ ERROR explicit lifetime required in the type of `foo` [E0621] foo diff --git a/tests/ui/async-await/issues/issue-63388-1.stderr b/tests/ui/async-await/issues/issue-63388-1.stderr index f7f285ad0ccda..ef74bfe32375e 100644 --- a/tests/ui/async-await/issues/issue-63388-1.stderr +++ b/tests/ui/async-await/issues/issue-63388-1.stderr @@ -1,3 +1,14 @@ +warning: elided lifetime has a name + --> $DIR/issue-63388-1.rs:12:10 + | +LL | async fn do_sth<'a>( + | -- lifetime `'a` declared here +LL | &'a self, foo: &dyn Foo +LL | ) -> &dyn Foo + | ^ this elided lifetime gets resolved as `'a` + | + = note: `#[warn(elided_named_lifetimes)]` on by default + error[E0621]: explicit lifetime required in the type of `foo` --> $DIR/issue-63388-1.rs:13:5 | @@ -10,6 +21,6 @@ LL | | foo LL | | } | |_____^ lifetime `'a` required -error: aborting due to 1 previous error +error: aborting due to 1 previous error; 1 warning emitted For more information about this error, try `rustc --explain E0621`. diff --git a/tests/ui/const-generics/type-dependent/issue-71348.full.stderr b/tests/ui/const-generics/type-dependent/issue-71348.full.stderr new file mode 100644 index 0000000000000..177ff20fbf9ea --- /dev/null +++ b/tests/ui/const-generics/type-dependent/issue-71348.full.stderr @@ -0,0 +1,10 @@ +warning: elided lifetime has a name + --> $DIR/issue-71348.rs:18:68 + | +LL | fn ask<'a, const N: &'static str>(&'a self) -> &'a >::Target + | -- lifetime `'a` declared here ^ this elided lifetime gets resolved as `'a` + | + = note: `#[warn(elided_named_lifetimes)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/const-generics/type-dependent/issue-71348.min.stderr b/tests/ui/const-generics/type-dependent/issue-71348.min.stderr index 858900a500d84..5aee282952aa2 100644 --- a/tests/ui/const-generics/type-dependent/issue-71348.min.stderr +++ b/tests/ui/const-generics/type-dependent/issue-71348.min.stderr @@ -1,3 +1,11 @@ +warning: elided lifetime has a name + --> $DIR/issue-71348.rs:18:68 + | +LL | fn ask<'a, const N: &'static str>(&'a self) -> &'a >::Target + | -- lifetime `'a` declared here ^ this elided lifetime gets resolved as `'a` + | + = note: `#[warn(elided_named_lifetimes)]` on by default + error: `&'static str` is forbidden as the type of a const generic parameter --> $DIR/issue-71348.rs:10:24 | @@ -30,5 +38,5 @@ help: add `#![feature(unsized_const_params)]` to the crate attributes to enable LL + #![feature(unsized_const_params)] | -error: aborting due to 2 previous errors +error: aborting due to 2 previous errors; 1 warning emitted diff --git a/tests/ui/const-generics/type-dependent/issue-71348.rs b/tests/ui/const-generics/type-dependent/issue-71348.rs index 2ffbd015485aa..97e786405fe39 100644 --- a/tests/ui/const-generics/type-dependent/issue-71348.rs +++ b/tests/ui/const-generics/type-dependent/issue-71348.rs @@ -17,6 +17,7 @@ trait Get<'a, const N: &'static str> { impl Foo { fn ask<'a, const N: &'static str>(&'a self) -> &'a >::Target //[min]~^ ERROR `&'static str` is forbidden as the type of a const generic parameter + //~^^ WARNING elided lifetime has a name where Self: Get<'a, N>, { diff --git a/tests/ui/consts/min_const_fn/min_const_fn.rs b/tests/ui/consts/min_const_fn/min_const_fn.rs index 76245c08ffc8c..f7663f6044eef 100644 --- a/tests/ui/consts/min_const_fn/min_const_fn.rs +++ b/tests/ui/consts/min_const_fn/min_const_fn.rs @@ -44,8 +44,8 @@ impl Foo { impl<'a, T> Foo { const fn new_lt(t: T) -> Self { Foo(t) } const fn into_inner_lt(self) -> T { self.0 } //~ destructor of - const fn get_lt(&'a self) -> &T { &self.0 } - const fn get_mut_lt(&'a mut self) -> &mut T { &mut self.0 } + const fn get_lt(&'a self) -> &T { &self.0 } //~ WARNING elided lifetime has a name + const fn get_mut_lt(&'a mut self) -> &mut T { &mut self.0 } //~ WARNING elided lifetime has a name //~^ mutable references //~| mutable references //~| mutable references diff --git a/tests/ui/consts/min_const_fn/min_const_fn.stderr b/tests/ui/consts/min_const_fn/min_const_fn.stderr index daa0ab2614fb1..4b348a182b87f 100644 --- a/tests/ui/consts/min_const_fn/min_const_fn.stderr +++ b/tests/ui/consts/min_const_fn/min_const_fn.stderr @@ -1,3 +1,23 @@ +warning: elided lifetime has a name + --> $DIR/min_const_fn.rs:47:34 + | +LL | impl<'a, T> Foo { + | -- lifetime `'a` declared here +... +LL | const fn get_lt(&'a self) -> &T { &self.0 } + | ^ this elided lifetime gets resolved as `'a` + | + = note: `#[warn(elided_named_lifetimes)]` on by default + +warning: elided lifetime has a name + --> $DIR/min_const_fn.rs:48:42 + | +LL | impl<'a, T> Foo { + | -- lifetime `'a` declared here +... +LL | const fn get_mut_lt(&'a mut self) -> &mut T { &mut self.0 } + | ^ this elided lifetime gets resolved as `'a` + error[E0493]: destructor of `Foo` cannot be evaluated at compile-time --> $DIR/min_const_fn.rs:37:25 | @@ -228,7 +248,7 @@ LL | const fn no_apit(_x: impl std::fmt::Debug) {} | | | the destructor for this type cannot be evaluated in constant functions -error: aborting due to 24 previous errors +error: aborting due to 24 previous errors; 2 warnings emitted Some errors have detailed explanations: E0493, E0658. For more information about an error, try `rustc --explain E0493`. diff --git a/tests/ui/generics/generic-no-mangle.fixed b/tests/ui/generics/generic-no-mangle.fixed index 69db712f9dc65..2776848c45fff 100644 --- a/tests/ui/generics/generic-no-mangle.fixed +++ b/tests/ui/generics/generic-no-mangle.fixed @@ -1,5 +1,5 @@ //@ run-rustfix -#![allow(dead_code)] +#![allow(dead_code, elided_named_lifetimes)] #![deny(no_mangle_generic_items)] pub fn foo() {} //~ ERROR functions generic over types or consts must be mangled diff --git a/tests/ui/generics/generic-no-mangle.rs b/tests/ui/generics/generic-no-mangle.rs index 2288b5bbe70df..5314005d31fa1 100644 --- a/tests/ui/generics/generic-no-mangle.rs +++ b/tests/ui/generics/generic-no-mangle.rs @@ -1,5 +1,5 @@ //@ run-rustfix -#![allow(dead_code)] +#![allow(dead_code, elided_named_lifetimes)] #![deny(no_mangle_generic_items)] #[no_mangle] diff --git a/tests/ui/impl-trait/impl-fn-hrtb-bounds.rs b/tests/ui/impl-trait/impl-fn-hrtb-bounds.rs index da7530b4e7a8c..a7f38b5c16af2 100644 --- a/tests/ui/impl-trait/impl-fn-hrtb-bounds.rs +++ b/tests/ui/impl-trait/impl-fn-hrtb-bounds.rs @@ -13,6 +13,7 @@ fn b() -> impl for<'a> Fn(&'a u8) -> (impl Debug + 'a) { fn c() -> impl for<'a> Fn(&'a u8) -> (impl Debug + '_) { //~^ ERROR `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait` + //~| WARNING elided lifetime has a name |x| x } diff --git a/tests/ui/impl-trait/impl-fn-hrtb-bounds.stderr b/tests/ui/impl-trait/impl-fn-hrtb-bounds.stderr index 7d108b30b76ed..d0f8f7689d17c 100644 --- a/tests/ui/impl-trait/impl-fn-hrtb-bounds.stderr +++ b/tests/ui/impl-trait/impl-fn-hrtb-bounds.stderr @@ -1,5 +1,5 @@ error[E0106]: missing lifetime specifier - --> $DIR/impl-fn-hrtb-bounds.rs:19:38 + --> $DIR/impl-fn-hrtb-bounds.rs:20:38 | LL | fn d() -> impl Fn() -> (impl Debug + '_) { | ^^ expected named lifetime parameter @@ -10,6 +10,14 @@ help: consider using the `'static` lifetime, but this is uncommon unless you're LL | fn d() -> impl Fn() -> (impl Debug + 'static) { | ~~~~~~~ +warning: elided lifetime has a name + --> $DIR/impl-fn-hrtb-bounds.rs:14:52 + | +LL | fn c() -> impl for<'a> Fn(&'a u8) -> (impl Debug + '_) { + | -- lifetime `'a` declared here ^^ this elided lifetime gets resolved as `'a` + | + = note: `#[warn(elided_named_lifetimes)]` on by default + error[E0657]: `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait` --> $DIR/impl-fn-hrtb-bounds.rs:4:41 | @@ -46,7 +54,7 @@ note: lifetime declared here LL | fn c() -> impl for<'a> Fn(&'a u8) -> (impl Debug + '_) { | ^^ -error: aborting due to 4 previous errors +error: aborting due to 4 previous errors; 1 warning emitted Some errors have detailed explanations: E0106, E0657. For more information about an error, try `rustc --explain E0106`. diff --git a/tests/ui/impl-trait/impl-fn-predefined-lifetimes.rs b/tests/ui/impl-trait/impl-fn-predefined-lifetimes.rs index 8aba3de530b8e..2f17c0ff50861 100644 --- a/tests/ui/impl-trait/impl-fn-predefined-lifetimes.rs +++ b/tests/ui/impl-trait/impl-fn-predefined-lifetimes.rs @@ -3,6 +3,7 @@ use std::fmt::Debug; fn a<'a>() -> impl Fn(&'a u8) -> (impl Debug + '_) { //~^ ERROR cannot resolve opaque type + //~| WARNING elided lifetime has a name |x| x //~^ ERROR expected generic lifetime parameter, found `'_` } diff --git a/tests/ui/impl-trait/impl-fn-predefined-lifetimes.stderr b/tests/ui/impl-trait/impl-fn-predefined-lifetimes.stderr index c2386e8c88be0..50a9f3ebeabb8 100644 --- a/tests/ui/impl-trait/impl-fn-predefined-lifetimes.stderr +++ b/tests/ui/impl-trait/impl-fn-predefined-lifetimes.stderr @@ -1,9 +1,17 @@ +warning: elided lifetime has a name + --> $DIR/impl-fn-predefined-lifetimes.rs:4:48 + | +LL | fn a<'a>() -> impl Fn(&'a u8) -> (impl Debug + '_) { + | -- lifetime `'a` declared here ^^ this elided lifetime gets resolved as `'a` + | + = note: `#[warn(elided_named_lifetimes)]` on by default + error[E0792]: expected generic lifetime parameter, found `'_` - --> $DIR/impl-fn-predefined-lifetimes.rs:6:9 + --> $DIR/impl-fn-predefined-lifetimes.rs:7:9 | LL | fn a<'a>() -> impl Fn(&'a u8) -> (impl Debug + '_) { | -- this generic parameter must be used with a generic lifetime parameter -LL | +... LL | |x| x | ^ @@ -13,7 +21,7 @@ error[E0720]: cannot resolve opaque type LL | fn a<'a>() -> impl Fn(&'a u8) -> (impl Debug + '_) { | ^^^^^^^^^^^^^^^ cannot resolve opaque type -error: aborting due to 2 previous errors +error: aborting due to 2 previous errors; 1 warning emitted Some errors have detailed explanations: E0720, E0792. For more information about an error, try `rustc --explain E0720`. diff --git a/tests/ui/impl-trait/rpit-assoc-pair-with-lifetime.rs b/tests/ui/impl-trait/rpit-assoc-pair-with-lifetime.rs index 73c8a6c0aed9f..e48441f533d7c 100644 --- a/tests/ui/impl-trait/rpit-assoc-pair-with-lifetime.rs +++ b/tests/ui/impl-trait/rpit-assoc-pair-with-lifetime.rs @@ -1,6 +1,7 @@ //@ check-pass pub fn iter<'a>(v: Vec<(u32, &'a u32)>) -> impl DoubleEndedIterator { + //~^ WARNING elided lifetime has a name v.into_iter() } diff --git a/tests/ui/impl-trait/rpit-assoc-pair-with-lifetime.stderr b/tests/ui/impl-trait/rpit-assoc-pair-with-lifetime.stderr new file mode 100644 index 0000000000000..bff3ffd934ac6 --- /dev/null +++ b/tests/ui/impl-trait/rpit-assoc-pair-with-lifetime.stderr @@ -0,0 +1,10 @@ +warning: elided lifetime has a name + --> $DIR/rpit-assoc-pair-with-lifetime.rs:3:82 + | +LL | pub fn iter<'a>(v: Vec<(u32, &'a u32)>) -> impl DoubleEndedIterator { + | -- lifetime `'a` declared here ^ this elided lifetime gets resolved as `'a` + | + = note: `#[warn(elided_named_lifetimes)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/lifetimes/lifetime-elision-return-type-requires-explicit-lifetime.rs b/tests/ui/lifetimes/lifetime-elision-return-type-requires-explicit-lifetime.rs index d0a8fe795efd0..63a2c9be9ebad 100644 --- a/tests/ui/lifetimes/lifetime-elision-return-type-requires-explicit-lifetime.rs +++ b/tests/ui/lifetimes/lifetime-elision-return-type-requires-explicit-lifetime.rs @@ -47,5 +47,6 @@ fn l<'a>(_: &'a str, _: &'a str) -> &str { "" } // This is ok because both `'a` are for the same parameter. fn m<'a>(_: &'a Foo<'a>) -> &str { "" } +//~^ WARNING elided lifetime has a name fn main() {} diff --git a/tests/ui/lifetimes/lifetime-elision-return-type-requires-explicit-lifetime.stderr b/tests/ui/lifetimes/lifetime-elision-return-type-requires-explicit-lifetime.stderr index 23ef36888f079..f835d2655bb01 100644 --- a/tests/ui/lifetimes/lifetime-elision-return-type-requires-explicit-lifetime.stderr +++ b/tests/ui/lifetimes/lifetime-elision-return-type-requires-explicit-lifetime.stderr @@ -105,6 +105,16 @@ help: consider using the `'a` lifetime LL | fn l<'a>(_: &'a str, _: &'a str) -> &'a str { "" } | ++ -error: aborting due to 7 previous errors +warning: elided lifetime has a name + --> $DIR/lifetime-elision-return-type-requires-explicit-lifetime.rs:49:29 + | +LL | fn m<'a>(_: &'a Foo<'a>) -> &str { "" } + | -- ^ this elided lifetime gets resolved as `'a` + | | + | lifetime `'a` declared here + | + = note: `#[warn(elided_named_lifetimes)]` on by default + +error: aborting due to 7 previous errors; 1 warning emitted For more information about this error, try `rustc --explain E0106`. diff --git a/tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-3.rs b/tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-3.rs index a1126d6bb1543..598633d75768e 100644 --- a/tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-3.rs +++ b/tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-3.rs @@ -4,6 +4,7 @@ struct Foo { impl Foo { fn foo<'a>(&'a self, x: &i32) -> &i32 { + //~^ WARNING elided lifetime has a name if true { &self.field } else { x } //~ ERROR explicit lifetime diff --git a/tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-3.stderr b/tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-3.stderr index 6dda9e61a79ca..2d5d4fb0e72ec 100644 --- a/tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-3.stderr +++ b/tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-3.stderr @@ -1,12 +1,22 @@ +warning: elided lifetime has a name + --> $DIR/ex1-return-one-existing-name-if-else-using-impl-3.rs:6:36 + | +LL | fn foo<'a>(&'a self, x: &i32) -> &i32 { + | -- ^ this elided lifetime gets resolved as `'a` + | | + | lifetime `'a` declared here + | + = note: `#[warn(elided_named_lifetimes)]` on by default + error[E0621]: explicit lifetime required in the type of `x` - --> $DIR/ex1-return-one-existing-name-if-else-using-impl-3.rs:8:36 + --> $DIR/ex1-return-one-existing-name-if-else-using-impl-3.rs:9:36 | LL | fn foo<'a>(&'a self, x: &i32) -> &i32 { | ---- help: add explicit lifetime `'a` to the type of `x`: `&'a i32` -LL | +... LL | if true { &self.field } else { x } | ^ lifetime `'a` required -error: aborting due to 1 previous error +error: aborting due to 1 previous error; 1 warning emitted For more information about this error, try `rustc --explain E0621`. diff --git a/tests/ui/lint/elided-named-lifetimes/example-from-issue48686.rs b/tests/ui/lint/elided-named-lifetimes/example-from-issue48686.rs new file mode 100644 index 0000000000000..eac7c32a9aac6 --- /dev/null +++ b/tests/ui/lint/elided-named-lifetimes/example-from-issue48686.rs @@ -0,0 +1,12 @@ +#![deny(elided_named_lifetimes)] + +struct Foo; + +impl Foo { + pub fn get_mut(&'static self, x: &mut u8) -> &mut u8 { + //~^ ERROR elided lifetime has a name + unsafe { &mut *(x as *mut _) } + } +} + +fn main() {} diff --git a/tests/ui/lint/elided-named-lifetimes/example-from-issue48686.stderr b/tests/ui/lint/elided-named-lifetimes/example-from-issue48686.stderr new file mode 100644 index 0000000000000..8c5426a60cb72 --- /dev/null +++ b/tests/ui/lint/elided-named-lifetimes/example-from-issue48686.stderr @@ -0,0 +1,14 @@ +error: elided lifetime has a name + --> $DIR/example-from-issue48686.rs:6:50 + | +LL | pub fn get_mut(&'static self, x: &mut u8) -> &mut u8 { + | ^ this elided lifetime gets resolved as `'static` + | +note: the lint level is defined here + --> $DIR/example-from-issue48686.rs:1:9 + | +LL | #![deny(elided_named_lifetimes)] + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + diff --git a/tests/ui/lint/elided-named-lifetimes/missing-lifetime-kind.rs b/tests/ui/lint/elided-named-lifetimes/missing-lifetime-kind.rs new file mode 100644 index 0000000000000..2f9083ed65f6e --- /dev/null +++ b/tests/ui/lint/elided-named-lifetimes/missing-lifetime-kind.rs @@ -0,0 +1,27 @@ +#![deny(elided_named_lifetimes)] + +fn ampersand<'a>(x: &'a u8) -> &u8 { + //~^ ERROR elided lifetime has a name + x +} + +struct Brackets<'a>(&'a u8); + +fn brackets<'a>(x: &'a u8) -> Brackets { + //~^ ERROR elided lifetime has a name + Brackets(x) +} + +struct Comma<'a, T>(&'a T); + +fn comma<'a>(x: &'a u8) -> Comma { + //~^ ERROR elided lifetime has a name + Comma(x) +} + +fn underscore<'a>(x: &'a u8) -> &'_ u8 { + //~^ ERROR elided lifetime has a name + x +} + +fn main() {} diff --git a/tests/ui/lint/elided-named-lifetimes/missing-lifetime-kind.stderr b/tests/ui/lint/elided-named-lifetimes/missing-lifetime-kind.stderr new file mode 100644 index 0000000000000..249ae146b1675 --- /dev/null +++ b/tests/ui/lint/elided-named-lifetimes/missing-lifetime-kind.stderr @@ -0,0 +1,40 @@ +error: elided lifetime has a name + --> $DIR/missing-lifetime-kind.rs:3:32 + | +LL | fn ampersand<'a>(x: &'a u8) -> &u8 { + | -- ^ this elided lifetime gets resolved as `'a` + | | + | lifetime `'a` declared here + | +note: the lint level is defined here + --> $DIR/missing-lifetime-kind.rs:1:9 + | +LL | #![deny(elided_named_lifetimes)] + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: elided lifetime has a name + --> $DIR/missing-lifetime-kind.rs:10:31 + | +LL | fn brackets<'a>(x: &'a u8) -> Brackets { + | -- ^^^^^^^^ this elided lifetime gets resolved as `'a` + | | + | lifetime `'a` declared here + +error: elided lifetime has a name + --> $DIR/missing-lifetime-kind.rs:17:33 + | +LL | fn comma<'a>(x: &'a u8) -> Comma { + | -- ^ this elided lifetime gets resolved as `'a` + | | + | lifetime `'a` declared here + +error: elided lifetime has a name + --> $DIR/missing-lifetime-kind.rs:22:34 + | +LL | fn underscore<'a>(x: &'a u8) -> &'_ u8 { + | -- ^^ this elided lifetime gets resolved as `'a` + | | + | lifetime `'a` declared here + +error: aborting due to 4 previous errors + diff --git a/tests/ui/lint/elided-named-lifetimes/not-tied-to-crate.rs b/tests/ui/lint/elided-named-lifetimes/not-tied-to-crate.rs new file mode 100644 index 0000000000000..4f9218130fbc1 --- /dev/null +++ b/tests/ui/lint/elided-named-lifetimes/not-tied-to-crate.rs @@ -0,0 +1,17 @@ +#![allow(elided_named_lifetimes)] + +#[warn(elided_named_lifetimes)] +mod foo { + fn bar(x: &'static u8) -> &u8 { + //~^ WARNING elided lifetime has a name + x + } + + #[deny(elided_named_lifetimes)] + fn baz(x: &'static u8) -> &u8 { + //~^ ERROR elided lifetime has a name + x + } +} + +fn main() {} diff --git a/tests/ui/lint/elided-named-lifetimes/not-tied-to-crate.stderr b/tests/ui/lint/elided-named-lifetimes/not-tied-to-crate.stderr new file mode 100644 index 0000000000000..c465aab1a03d2 --- /dev/null +++ b/tests/ui/lint/elided-named-lifetimes/not-tied-to-crate.stderr @@ -0,0 +1,26 @@ +warning: elided lifetime has a name + --> $DIR/not-tied-to-crate.rs:5:31 + | +LL | fn bar(x: &'static u8) -> &u8 { + | ^ this elided lifetime gets resolved as `'static` + | +note: the lint level is defined here + --> $DIR/not-tied-to-crate.rs:3:8 + | +LL | #[warn(elided_named_lifetimes)] + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: elided lifetime has a name + --> $DIR/not-tied-to-crate.rs:11:31 + | +LL | fn baz(x: &'static u8) -> &u8 { + | ^ this elided lifetime gets resolved as `'static` + | +note: the lint level is defined here + --> $DIR/not-tied-to-crate.rs:10:12 + | +LL | #[deny(elided_named_lifetimes)] + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error; 1 warning emitted + diff --git a/tests/ui/lint/elided-named-lifetimes/static.rs b/tests/ui/lint/elided-named-lifetimes/static.rs new file mode 100644 index 0000000000000..dc8222c6e6e48 --- /dev/null +++ b/tests/ui/lint/elided-named-lifetimes/static.rs @@ -0,0 +1,46 @@ +#![deny(elided_named_lifetimes)] + +use std::borrow::Cow; + +const A: &[u8] = &[]; +static B: &str = "hello"; + +trait Trait { + const C: &u8 = &0; +} + +impl Trait for () { + const C: &u8 = &1; +} + +fn ampersand(x: &'static u8) -> &u8 { + //~^ ERROR elided lifetime has a name + x +} + +struct Brackets<'a>(&'a u8); + +fn brackets(x: &'static u8) -> Brackets { + //~^ ERROR elided lifetime has a name + Brackets(x) +} + +struct Comma<'a, T>(&'a T); + +fn comma(x: &'static u8) -> Comma { + //~^ ERROR elided lifetime has a name + Comma(x) +} + +fn underscore(x: &'static u8) -> &'_ u8 { + //~^ ERROR elided lifetime has a name + x +} + +const NESTED: &Vec<&Box>> = &vec![]; + +fn main() { + const HELLO: &str = "Hello"; + static WORLD: &str = "world"; + println!("{HELLO}, {WORLD}!") +} diff --git a/tests/ui/lint/elided-named-lifetimes/static.stderr b/tests/ui/lint/elided-named-lifetimes/static.stderr new file mode 100644 index 0000000000000..d2e9776cb4f0e --- /dev/null +++ b/tests/ui/lint/elided-named-lifetimes/static.stderr @@ -0,0 +1,32 @@ +error: elided lifetime has a name + --> $DIR/static.rs:16:33 + | +LL | fn ampersand(x: &'static u8) -> &u8 { + | ^ this elided lifetime gets resolved as `'static` + | +note: the lint level is defined here + --> $DIR/static.rs:1:9 + | +LL | #![deny(elided_named_lifetimes)] + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: elided lifetime has a name + --> $DIR/static.rs:23:32 + | +LL | fn brackets(x: &'static u8) -> Brackets { + | ^^^^^^^^ this elided lifetime gets resolved as `'static` + +error: elided lifetime has a name + --> $DIR/static.rs:30:34 + | +LL | fn comma(x: &'static u8) -> Comma { + | ^ this elided lifetime gets resolved as `'static` + +error: elided lifetime has a name + --> $DIR/static.rs:35:35 + | +LL | fn underscore(x: &'static u8) -> &'_ u8 { + | ^^ this elided lifetime gets resolved as `'static` + +error: aborting due to 4 previous errors + diff --git a/tests/ui/object-lifetime/object-lifetime-default-elision.rs b/tests/ui/object-lifetime/object-lifetime-default-elision.rs index f7c0261cfbb9c..ede6af51174b2 100644 --- a/tests/ui/object-lifetime/object-lifetime-default-elision.rs +++ b/tests/ui/object-lifetime/object-lifetime-default-elision.rs @@ -46,6 +46,8 @@ fn load1(ss: &dyn SomeTrait) -> &dyn SomeTrait { } fn load2<'a>(ss: &'a dyn SomeTrait) -> &dyn SomeTrait { + //~^ WARNING elided lifetime has a name + // Same as `load1` but with an explicit name thrown in for fun. ss diff --git a/tests/ui/object-lifetime/object-lifetime-default-elision.stderr b/tests/ui/object-lifetime/object-lifetime-default-elision.stderr index b59956879275a..b44a184c6848f 100644 --- a/tests/ui/object-lifetime/object-lifetime-default-elision.stderr +++ b/tests/ui/object-lifetime/object-lifetime-default-elision.stderr @@ -1,5 +1,15 @@ +warning: elided lifetime has a name + --> $DIR/object-lifetime-default-elision.rs:48:40 + | +LL | fn load2<'a>(ss: &'a dyn SomeTrait) -> &dyn SomeTrait { + | -- ^ this elided lifetime gets resolved as `'a` + | | + | lifetime `'a` declared here + | + = note: `#[warn(elided_named_lifetimes)]` on by default + error: lifetime may not live long enough - --> $DIR/object-lifetime-default-elision.rs:71:5 + --> $DIR/object-lifetime-default-elision.rs:73:5 | LL | fn load3<'a,'b>(ss: &'a dyn SomeTrait) -> &'b dyn SomeTrait { | -- -- lifetime `'b` defined here @@ -11,5 +21,5 @@ LL | ss | = help: consider adding the following bound: `'a: 'b` -error: aborting due to 1 previous error +error: aborting due to 1 previous error; 1 warning emitted diff --git a/tests/ui/self/elision/ignore-non-reference-lifetimes.rs b/tests/ui/self/elision/ignore-non-reference-lifetimes.rs index f7f61b8c81063..cedc6f0f9bc62 100644 --- a/tests/ui/self/elision/ignore-non-reference-lifetimes.rs +++ b/tests/ui/self/elision/ignore-non-reference-lifetimes.rs @@ -4,9 +4,11 @@ struct Foo<'a>(&'a str); impl<'b> Foo<'b> { fn a<'a>(self: Self, a: &'a str) -> &str { + //~^ WARNING elided lifetime has a name a } fn b<'a>(self: Foo<'b>, a: &'a str) -> &str { + //~^ WARNING elided lifetime has a name a } } diff --git a/tests/ui/self/elision/ignore-non-reference-lifetimes.stderr b/tests/ui/self/elision/ignore-non-reference-lifetimes.stderr new file mode 100644 index 0000000000000..4465dbae52989 --- /dev/null +++ b/tests/ui/self/elision/ignore-non-reference-lifetimes.stderr @@ -0,0 +1,16 @@ +warning: elided lifetime has a name + --> $DIR/ignore-non-reference-lifetimes.rs:6:41 + | +LL | fn a<'a>(self: Self, a: &'a str) -> &str { + | -- lifetime `'a` declared here ^ this elided lifetime gets resolved as `'a` + | + = note: `#[warn(elided_named_lifetimes)]` on by default + +warning: elided lifetime has a name + --> $DIR/ignore-non-reference-lifetimes.rs:10:44 + | +LL | fn b<'a>(self: Foo<'b>, a: &'a str) -> &str { + | -- lifetime `'a` declared here ^ this elided lifetime gets resolved as `'a` + +warning: 2 warnings emitted + diff --git a/tests/ui/self/elision/lt-ref-self-async.fixed b/tests/ui/self/elision/lt-ref-self-async.fixed index aa1d62012da03..914511641b894 100644 --- a/tests/ui/self/elision/lt-ref-self-async.fixed +++ b/tests/ui/self/elision/lt-ref-self-async.fixed @@ -1,6 +1,6 @@ //@ edition:2018 //@ run-rustfix -#![allow(non_snake_case, dead_code)] +#![allow(non_snake_case, dead_code, elided_named_lifetimes)] use std::pin::Pin; diff --git a/tests/ui/self/elision/lt-ref-self-async.rs b/tests/ui/self/elision/lt-ref-self-async.rs index 38de0fd39f086..0c11b271c35a7 100644 --- a/tests/ui/self/elision/lt-ref-self-async.rs +++ b/tests/ui/self/elision/lt-ref-self-async.rs @@ -1,6 +1,6 @@ //@ edition:2018 //@ run-rustfix -#![allow(non_snake_case, dead_code)] +#![allow(non_snake_case, dead_code, elided_named_lifetimes)] use std::pin::Pin; diff --git a/tests/ui/self/self_lifetime-async.rs b/tests/ui/self/self_lifetime-async.rs index 7d6eb3f5eaf02..fd6902071188c 100644 --- a/tests/ui/self/self_lifetime-async.rs +++ b/tests/ui/self/self_lifetime-async.rs @@ -4,11 +4,13 @@ struct Foo<'a>(&'a ()); impl<'a> Foo<'a> { async fn foo<'b>(self: &'b Foo<'a>) -> &() { self.0 } + //~^ WARNING elided lifetime has a name } type Alias = Foo<'static>; impl Alias { async fn bar<'a>(self: &Alias, arg: &'a ()) -> &() { arg } + //~^ WARNING elided lifetime has a name } fn main() {} diff --git a/tests/ui/self/self_lifetime-async.stderr b/tests/ui/self/self_lifetime-async.stderr new file mode 100644 index 0000000000000..32de3fd18c97f --- /dev/null +++ b/tests/ui/self/self_lifetime-async.stderr @@ -0,0 +1,18 @@ +warning: elided lifetime has a name + --> $DIR/self_lifetime-async.rs:6:44 + | +LL | async fn foo<'b>(self: &'b Foo<'a>) -> &() { self.0 } + | -- ^ this elided lifetime gets resolved as `'b` + | | + | lifetime `'b` declared here + | + = note: `#[warn(elided_named_lifetimes)]` on by default + +warning: elided lifetime has a name + --> $DIR/self_lifetime-async.rs:12:52 + | +LL | async fn bar<'a>(self: &Alias, arg: &'a ()) -> &() { arg } + | -- lifetime `'a` declared here ^ this elided lifetime gets resolved as `'a` + +warning: 2 warnings emitted + diff --git a/tests/ui/self/self_lifetime.rs b/tests/ui/self/self_lifetime.rs index 3f655b960b163..0607c3b9317f1 100644 --- a/tests/ui/self/self_lifetime.rs +++ b/tests/ui/self/self_lifetime.rs @@ -5,11 +5,13 @@ struct Foo<'a>(&'a ()); impl<'a> Foo<'a> { fn foo<'b>(self: &'b Foo<'a>) -> &() { self.0 } + //~^ WARNING elided lifetime has a name } type Alias = Foo<'static>; impl Alias { fn bar<'a>(self: &Alias, arg: &'a ()) -> &() { arg } + //~^ WARNING elided lifetime has a name } fn main() {} diff --git a/tests/ui/self/self_lifetime.stderr b/tests/ui/self/self_lifetime.stderr new file mode 100644 index 0000000000000..cd8f4d8adf8b1 --- /dev/null +++ b/tests/ui/self/self_lifetime.stderr @@ -0,0 +1,18 @@ +warning: elided lifetime has a name + --> $DIR/self_lifetime.rs:7:38 + | +LL | fn foo<'b>(self: &'b Foo<'a>) -> &() { self.0 } + | -- ^ this elided lifetime gets resolved as `'b` + | | + | lifetime `'b` declared here + | + = note: `#[warn(elided_named_lifetimes)]` on by default + +warning: elided lifetime has a name + --> $DIR/self_lifetime.rs:13:46 + | +LL | fn bar<'a>(self: &Alias, arg: &'a ()) -> &() { arg } + | -- lifetime `'a` declared here ^ this elided lifetime gets resolved as `'a` + +warning: 2 warnings emitted + diff --git a/tests/ui/suggestions/impl-trait-missing-lifetime-gated.rs b/tests/ui/suggestions/impl-trait-missing-lifetime-gated.rs index 735efe89cba5b..daec66709b654 100644 --- a/tests/ui/suggestions/impl-trait-missing-lifetime-gated.rs +++ b/tests/ui/suggestions/impl-trait-missing-lifetime-gated.rs @@ -64,6 +64,7 @@ mod in_path { // This must not err, as the `&` actually resolves to `'a`. fn resolved_anonymous<'a, T: 'a>(f: impl Fn(&'a str) -> &T) { + //~^ WARNING elided lifetime has a name f("f"); } diff --git a/tests/ui/suggestions/impl-trait-missing-lifetime-gated.stderr b/tests/ui/suggestions/impl-trait-missing-lifetime-gated.stderr index 61a2925f582b2..30f4509d49dee 100644 --- a/tests/ui/suggestions/impl-trait-missing-lifetime-gated.stderr +++ b/tests/ui/suggestions/impl-trait-missing-lifetime-gated.stderr @@ -124,6 +124,14 @@ LL - fn g(mut x: impl Foo<()>) -> Option<&()> { x.next() } LL + fn g(mut x: impl Foo<()>) -> Option<()> { x.next() } | +warning: elided lifetime has a name + --> $DIR/impl-trait-missing-lifetime-gated.rs:66:57 + | +LL | fn resolved_anonymous<'a, T: 'a>(f: impl Fn(&'a str) -> &T) { + | -- lifetime `'a` declared here ^ this elided lifetime gets resolved as `'a` + | + = note: `#[warn(elided_named_lifetimes)]` on by default + error[E0658]: anonymous lifetimes in `impl Trait` are unstable --> $DIR/impl-trait-missing-lifetime-gated.rs:6:35 | @@ -244,7 +252,7 @@ help: consider introducing a named lifetime parameter LL | fn g<'a>(mut x: impl Foo<'a, ()>) -> Option<&()> { x.next() } | ++++ +++ -error: aborting due to 16 previous errors +error: aborting due to 16 previous errors; 1 warning emitted Some errors have detailed explanations: E0106, E0658. For more information about an error, try `rustc --explain E0106`. diff --git a/tests/ui/suggestions/lifetimes/missing-lifetimes-in-signature.rs b/tests/ui/suggestions/lifetimes/missing-lifetimes-in-signature.rs index b641f5941dcef..b61bea16e3bc8 100644 --- a/tests/ui/suggestions/lifetimes/missing-lifetimes-in-signature.rs +++ b/tests/ui/suggestions/lifetimes/missing-lifetimes-in-signature.rs @@ -100,6 +100,7 @@ where // This also works. The `'_` isn't necessary but it's where we arrive to following the suggestions: fn ok2<'a, G: 'a, T>(g: G, dest: &'a mut T) -> impl FnOnce() + '_ + 'a +//~^ WARNING elided lifetime has a name where G: Get, { diff --git a/tests/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr b/tests/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr index 88a18e9d06da2..ea01dcd5020cf 100644 --- a/tests/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr +++ b/tests/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr @@ -6,6 +6,14 @@ LL | fn baz(g: G, dest: &mut T) -> impl FnOnce() + '_ | | | help: consider introducing lifetime `'a` here: `'a,` +warning: elided lifetime has a name + --> $DIR/missing-lifetimes-in-signature.rs:102:64 + | +LL | fn ok2<'a, G: 'a, T>(g: G, dest: &'a mut T) -> impl FnOnce() + '_ + 'a + | -- lifetime `'a` declared here ^^ this elided lifetime gets resolved as `'a` + | + = note: `#[warn(elided_named_lifetimes)]` on by default + error[E0700]: hidden type for `impl FnOnce()` captures lifetime that does not appear in bounds --> $DIR/missing-lifetimes-in-signature.rs:19:5 | @@ -125,7 +133,7 @@ help: consider adding an explicit lifetime bound LL | G: Get + 'a, | ++++ -error: aborting due to 8 previous errors +error: aborting due to 8 previous errors; 1 warning emitted Some errors have detailed explanations: E0261, E0309, E0311, E0621, E0700. For more information about an error, try `rustc --explain E0261`. diff --git a/tests/ui/type-alias-impl-trait/missing_lifetime_bound.rs b/tests/ui/type-alias-impl-trait/missing_lifetime_bound.rs index c584a58cb32e7..c178fcf5a9142 100644 --- a/tests/ui/type-alias-impl-trait/missing_lifetime_bound.rs +++ b/tests/ui/type-alias-impl-trait/missing_lifetime_bound.rs @@ -2,7 +2,7 @@ type Opaque2 = impl Sized; type Opaque<'a, T> = Opaque2; -fn defining<'a, T>(x: &'a i32) -> Opaque { x } +fn defining<'a, T>(x: &'a i32) -> Opaque { x } //~ WARNING elided lifetime has a name //~^ ERROR: hidden type for `Opaque2` captures lifetime that does not appear in bounds fn main() {} diff --git a/tests/ui/type-alias-impl-trait/missing_lifetime_bound.stderr b/tests/ui/type-alias-impl-trait/missing_lifetime_bound.stderr index 03cc943d50995..e2c21f1636b0c 100644 --- a/tests/ui/type-alias-impl-trait/missing_lifetime_bound.stderr +++ b/tests/ui/type-alias-impl-trait/missing_lifetime_bound.stderr @@ -1,3 +1,13 @@ +warning: elided lifetime has a name + --> $DIR/missing_lifetime_bound.rs:5:41 + | +LL | fn defining<'a, T>(x: &'a i32) -> Opaque { x } + | -- ^ this elided lifetime gets resolved as `'a` + | | + | lifetime `'a` declared here + | + = note: `#[warn(elided_named_lifetimes)]` on by default + error[E0700]: hidden type for `Opaque2` captures lifetime that does not appear in bounds --> $DIR/missing_lifetime_bound.rs:5:47 | @@ -9,6 +19,6 @@ LL | fn defining<'a, T>(x: &'a i32) -> Opaque { x } | | | hidden type `&'a i32` captures the lifetime `'a` as defined here -error: aborting due to 1 previous error +error: aborting due to 1 previous error; 1 warning emitted For more information about this error, try `rustc --explain E0700`. From 9957101f3afd0d1dedfdc9eab81b9aa95cec7771 Mon Sep 17 00:00:00 2001 From: Pavel Grigorenko Date: Sat, 31 Aug 2024 15:31:31 +0300 Subject: [PATCH 0306/2194] elided_named_lifetimes: bless & add tests --- tests/ui/needless_lifetimes.stderr | 13 ++++++++++++- tests/ui/ptr_arg.stderr | 11 ++++++++++- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/tests/ui/needless_lifetimes.stderr b/tests/ui/needless_lifetimes.stderr index f325d27b8c753..50f845e2d9291 100644 --- a/tests/ui/needless_lifetimes.stderr +++ b/tests/ui/needless_lifetimes.stderr @@ -1,3 +1,14 @@ +error: elided lifetime has a name + --> tests/ui/needless_lifetimes.rs:266:52 + | +LL | fn named_input_elided_output<'a>(_arg: &'a str) -> &str { + | -- ^ this elided lifetime gets resolved as `'a` + | | + | lifetime `'a` declared here + | + = note: `-D elided-named-lifetimes` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(elided_named_lifetimes)]` + error: the following explicit lifetimes could be elided: 'a, 'b --> tests/ui/needless_lifetimes.rs:17:23 | @@ -553,5 +564,5 @@ LL - fn one_input<'a>(x: &'a u8) -> &'a u8 { LL + fn one_input(x: &u8) -> &u8 { | -error: aborting due to 46 previous errors +error: aborting due to 47 previous errors diff --git a/tests/ui/ptr_arg.stderr b/tests/ui/ptr_arg.stderr index 1848ef80fc495..4246453e64ca7 100644 --- a/tests/ui/ptr_arg.stderr +++ b/tests/ui/ptr_arg.stderr @@ -1,3 +1,12 @@ +error: elided lifetime has a name + --> tests/ui/ptr_arg.rs:295:56 + | +LL | fn cow_good_ret_ty<'a>(input: &'a Cow<'a, str>) -> &str { + | -- lifetime `'a` declared here ^ this elided lifetime gets resolved as `'a` + | + = note: `-D elided-named-lifetimes` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(elided_named_lifetimes)]` + error: writing `&Vec` instead of `&[_]` involves a new object where a slice will do --> tests/ui/ptr_arg.rs:13:14 | @@ -212,5 +221,5 @@ error: using a reference to `Cow` is not recommended LL | fn cow_bad_ret_ty_2<'a, 'b>(input: &'a Cow<'a, str>) -> &'b str { | ^^^^^^^^^^^^^^^^ help: change this to: `&str` -error: aborting due to 24 previous errors +error: aborting due to 25 previous errors From 4928b22fa8a429f128d5992dc273a39be9ac7a37 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Thu, 4 Jul 2024 06:31:07 +0000 Subject: [PATCH 0307/2194] Use AttrId key for unstable<->stable expectation map. --- compiler/rustc_errors/src/diagnostic.rs | 19 +++++++------------ compiler/rustc_errors/src/lib.rs | 10 +++++----- compiler/rustc_lint/src/levels.rs | 9 ++++----- 3 files changed, 16 insertions(+), 22 deletions(-) diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs index 3303e4ee752c2..7e4698a94a9f6 100644 --- a/compiler/rustc_errors/src/diagnostic.rs +++ b/compiler/rustc_errors/src/diagnostic.rs @@ -12,7 +12,7 @@ use rustc_lint_defs::{Applicability, LintExpectationId}; use rustc_macros::{Decodable, Encodable}; use rustc_span::source_map::Spanned; use rustc_span::symbol::Symbol; -use rustc_span::{Span, DUMMY_SP}; +use rustc_span::{AttrId, Span, DUMMY_SP}; use tracing::debug; use crate::snippet::Style; @@ -356,24 +356,19 @@ impl DiagInner { pub(crate) fn update_unstable_expectation_id( &mut self, - unstable_to_stable: &FxIndexMap, + unstable_to_stable: &FxIndexMap, ) { if let Level::Expect(expectation_id) | Level::ForceWarning(Some(expectation_id)) = &mut self.level + && let LintExpectationId::Unstable { attr_id, lint_index } = *expectation_id { - if expectation_id.is_stable() { - return; - } - // The unstable to stable map only maps the unstable `AttrId` to a stable `HirId` with an attribute index. // The lint index inside the attribute is manually transferred here. - let lint_index = expectation_id.get_lint_index(); - expectation_id.set_lint_index(None); - let mut stable_id = unstable_to_stable - .get(expectation_id) - .expect("each unstable `LintExpectationId` must have a matching stable id") - .normalize(); + let Some(stable_id) = unstable_to_stable.get(&attr_id) else { + panic!("{expectation_id:?} must have a matching stable id") + }; + let mut stable_id = stable_id.normalize(); stable_id.set_lint_index(lint_index); *expectation_id = stable_id; } diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index 99ee8fb17d7dc..967e64c2d9f74 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -69,7 +69,7 @@ use rustc_macros::{Decodable, Encodable}; pub use rustc_span::fatal_error::{FatalError, FatalErrorMarker}; use rustc_span::source_map::SourceMap; pub use rustc_span::ErrorGuaranteed; -use rustc_span::{Loc, Span, DUMMY_SP}; +use rustc_span::{AttrId, Loc, Span, DUMMY_SP}; pub use snippet::Style; // Used by external projects such as `rust-gpu`. // See https://github.com/rust-lang/rust/pull/115393. @@ -1096,7 +1096,7 @@ impl<'a> DiagCtxtHandle<'a> { pub fn update_unstable_expectation_id( &self, - unstable_to_stable: &FxIndexMap, + unstable_to_stable: FxIndexMap, ) { let mut inner = self.inner.borrow_mut(); let diags = std::mem::take(&mut inner.unstable_expect_diagnostics); @@ -1105,7 +1105,7 @@ impl<'a> DiagCtxtHandle<'a> { if !diags.is_empty() { inner.suppressed_expected_diag = true; for mut diag in diags.into_iter() { - diag.update_unstable_expectation_id(unstable_to_stable); + diag.update_unstable_expectation_id(&unstable_to_stable); // Here the diagnostic is given back to `emit_diagnostic` where it was first // intercepted. Now it should be processed as usual, since the unstable expectation @@ -1117,11 +1117,11 @@ impl<'a> DiagCtxtHandle<'a> { inner .stashed_diagnostics .values_mut() - .for_each(|(diag, _guar)| diag.update_unstable_expectation_id(unstable_to_stable)); + .for_each(|(diag, _guar)| diag.update_unstable_expectation_id(&unstable_to_stable)); inner .future_breakage_diagnostics .iter_mut() - .for_each(|diag| diag.update_unstable_expectation_id(unstable_to_stable)); + .for_each(|diag| diag.update_unstable_expectation_id(&unstable_to_stable)); } /// This methods steals all [`LintExpectationId`]s that are stored inside diff --git a/compiler/rustc_lint/src/levels.rs b/compiler/rustc_lint/src/levels.rs index 07ac63ec96cf1..aa7042ff6255d 100644 --- a/compiler/rustc_lint/src/levels.rs +++ b/compiler/rustc_lint/src/levels.rs @@ -20,7 +20,7 @@ use rustc_session::lint::builtin::{ use rustc_session::lint::{Level, Lint, LintExpectationId, LintId}; use rustc_session::Session; use rustc_span::symbol::{sym, Symbol}; -use rustc_span::{Span, DUMMY_SP}; +use rustc_span::{AttrId, Span, DUMMY_SP}; use tracing::{debug, instrument}; use {rustc_ast as ast, rustc_hir as hir}; @@ -138,7 +138,7 @@ fn lint_expectations(tcx: TyCtxt<'_>, (): ()) -> Vec<(LintExpectationId, LintExp builder.add_id(hir::CRATE_HIR_ID); tcx.hir().walk_toplevel_module(&mut builder); - tcx.dcx().update_unstable_expectation_id(&builder.provider.unstable_to_stable_ids); + tcx.dcx().update_unstable_expectation_id(builder.provider.unstable_to_stable_ids); builder.provider.expectations } @@ -252,7 +252,7 @@ struct QueryMapExpectationsWrapper<'tcx> { /// Level map for `cur`. specs: ShallowLintLevelMap, expectations: Vec<(LintExpectationId, LintExpectation)>, - unstable_to_stable_ids: FxIndexMap, + unstable_to_stable_ids: FxIndexMap, /// Empty hash map to simplify code. empty: FxIndexMap, } @@ -274,9 +274,8 @@ impl LintLevelsProvider for QueryMapExpectationsWrapper<'_> { else { bug!("unstable expectation id should already be mapped") }; - let key = LintExpectationId::Unstable { attr_id, lint_index: None }; - self.unstable_to_stable_ids.entry(key).or_insert(LintExpectationId::Stable { + self.unstable_to_stable_ids.entry(attr_id).or_insert(LintExpectationId::Stable { hir_id, attr_index, lint_index: None, From 111b0a97b4c849d7abac396fc4c6dd6a159c8560 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Thu, 4 Jul 2024 09:55:42 +0000 Subject: [PATCH 0308/2194] Rewrite lint_expectations in a single pass. --- compiler/rustc_lint/src/expect.rs | 54 ++++++- compiler/rustc_lint/src/levels.rs | 150 +----------------- compiler/rustc_middle/src/lint.rs | 3 +- tests/ui/error-codes/E0602.stderr | 7 +- tests/ui/lint/cli-unknown-force-warn.stderr | 7 +- .../ui/lint/lint-removed-cmdline-deny.stderr | 7 +- tests/ui/lint/lint-removed-cmdline.stderr | 7 +- .../ui/lint/lint-renamed-cmdline-deny.stderr | 8 +- tests/ui/lint/lint-renamed-cmdline.stderr | 8 +- .../ui/lint/lint-unexported-no-mangle.stderr | 12 +- .../lint-unknown-lint-cmdline-deny.stderr | 13 +- .../ui/lint/lint-unknown-lint-cmdline.stderr | 13 +- 12 files changed, 67 insertions(+), 222 deletions(-) diff --git a/compiler/rustc_lint/src/expect.rs b/compiler/rustc_lint/src/expect.rs index 42b33f9882d76..d9fab1d00aa5b 100644 --- a/compiler/rustc_lint/src/expect.rs +++ b/compiler/rustc_lint/src/expect.rs @@ -1,21 +1,67 @@ +use rustc_data_structures::fx::FxIndexMap; +use rustc_hir::{HirId, CRATE_OWNER_ID}; +use rustc_middle::lint::LintExpectation; use rustc_middle::query::Providers; use rustc_middle::ty::TyCtxt; use rustc_session::lint::builtin::UNFULFILLED_LINT_EXPECTATIONS; -use rustc_session::lint::LintExpectationId; +use rustc_session::lint::{Level, LintExpectationId}; use rustc_span::Symbol; use crate::lints::{Expectation, ExpectationNote}; pub(crate) fn provide(providers: &mut Providers) { - *providers = Providers { check_expectations, ..*providers }; + *providers = Providers { lint_expectations, check_expectations, ..*providers }; +} + +fn lint_expectations(tcx: TyCtxt<'_>, (): ()) -> Vec<(LintExpectationId, LintExpectation)> { + let krate = tcx.hir_crate_items(()); + + let mut expectations = Vec::new(); + let mut unstable_to_stable_ids = FxIndexMap::default(); + + let mut record_stable = |attr_id, hir_id, attr_index| { + let expect_id = + LintExpectationId::Stable { hir_id, attr_index, lint_index: None, attr_id: None }; + unstable_to_stable_ids.entry(attr_id).or_insert(expect_id); + }; + let mut push_expectations = |owner| { + let lints = tcx.shallow_lint_levels_on(owner); + if lints.expectations.is_empty() { + return; + } + + expectations.extend_from_slice(&lints.expectations); + + let attrs = tcx.hir_attrs(owner); + for &(local_id, attrs) in attrs.map.iter() { + // Some attributes appear multiple times in HIR, to ensure they are correctly taken + // into account where they matter. This means we cannot just associate the AttrId to + // the first HirId where we see it, but need to check it actually appears in a lint + // level. + // FIXME(cjgillot): Can this cause an attribute to appear in multiple expectation ids? + if !lints.specs.contains_key(&local_id) { + continue; + } + for (attr_index, attr) in attrs.iter().enumerate() { + let Some(Level::Expect(_)) = Level::from_attr(attr) else { continue }; + record_stable(attr.id, HirId { owner, local_id }, attr_index.try_into().unwrap()); + } + } + }; + + push_expectations(CRATE_OWNER_ID); + for owner in krate.owners() { + push_expectations(owner); + } + + tcx.dcx().update_unstable_expectation_id(unstable_to_stable_ids); + expectations } fn check_expectations(tcx: TyCtxt<'_>, tool_filter: Option) { let lint_expectations = tcx.lint_expectations(()); let fulfilled_expectations = tcx.dcx().steal_fulfilled_expectation_ids(); - tracing::debug!(?lint_expectations, ?fulfilled_expectations); - for (id, expectation) in lint_expectations { // This check will always be true, since `lint_expectations` only // holds stable ids diff --git a/compiler/rustc_lint/src/levels.rs b/compiler/rustc_lint/src/levels.rs index aa7042ff6255d..dfbc61d50e8df 100644 --- a/compiler/rustc_lint/src/levels.rs +++ b/compiler/rustc_lint/src/levels.rs @@ -20,7 +20,7 @@ use rustc_session::lint::builtin::{ use rustc_session::lint::{Level, Lint, LintExpectationId, LintId}; use rustc_session::Session; use rustc_span::symbol::{sym, Symbol}; -use rustc_span::{AttrId, Span, DUMMY_SP}; +use rustc_span::{Span, DUMMY_SP}; use tracing::{debug, instrument}; use {rustc_ast as ast, rustc_hir as hir}; @@ -115,34 +115,6 @@ impl LintLevelSets { } } -fn lint_expectations(tcx: TyCtxt<'_>, (): ()) -> Vec<(LintExpectationId, LintExpectation)> { - let store = unerased_lint_store(tcx.sess); - - let mut builder = LintLevelsBuilder { - sess: tcx.sess, - features: tcx.features(), - provider: QueryMapExpectationsWrapper { - tcx, - cur: hir::CRATE_HIR_ID, - specs: ShallowLintLevelMap::default(), - expectations: Vec::new(), - unstable_to_stable_ids: FxIndexMap::default(), - empty: FxIndexMap::default(), - }, - lint_added_lints: false, - store, - registered_tools: tcx.registered_tools(()), - }; - - builder.add_command_line(); - builder.add_id(hir::CRATE_HIR_ID); - tcx.hir().walk_toplevel_module(&mut builder); - - tcx.dcx().update_unstable_expectation_id(builder.provider.unstable_to_stable_ids); - - builder.provider.expectations -} - #[instrument(level = "trace", skip(tcx), ret)] fn shallow_lint_levels_on(tcx: TyCtxt<'_>, owner: hir::OwnerId) -> ShallowLintLevelMap { let store = unerased_lint_store(tcx.sess); @@ -207,7 +179,7 @@ pub trait LintLevelsProvider { fn current_specs(&self) -> &FxIndexMap; fn insert(&mut self, id: LintId, lvl: LevelAndSource); fn get_lint_level(&self, lint: &'static Lint, sess: &Session) -> LevelAndSource; - fn push_expectation(&mut self, _id: LintExpectationId, _expectation: LintExpectation) {} + fn push_expectation(&mut self, id: LintExpectationId, expectation: LintExpectation); } impl LintLevelsProvider for TopDown { @@ -222,6 +194,8 @@ impl LintLevelsProvider for TopDown { fn get_lint_level(&self, lint: &'static Lint, sess: &Session) -> LevelAndSource { self.sets.get_lint_level(lint, self.cur, Some(self.current_specs()), sess) } + + fn push_expectation(&mut self, _: LintExpectationId, _: LintExpectation) {} } struct LintLevelQueryMap<'tcx> { @@ -243,46 +217,8 @@ impl LintLevelsProvider for LintLevelQueryMap<'_> { fn get_lint_level(&self, lint: &'static Lint, _: &Session) -> LevelAndSource { self.specs.lint_level_id_at_node(self.tcx, LintId::of(lint), self.cur) } -} - -struct QueryMapExpectationsWrapper<'tcx> { - tcx: TyCtxt<'tcx>, - /// HirId of the currently investigated element. - cur: HirId, - /// Level map for `cur`. - specs: ShallowLintLevelMap, - expectations: Vec<(LintExpectationId, LintExpectation)>, - unstable_to_stable_ids: FxIndexMap, - /// Empty hash map to simplify code. - empty: FxIndexMap, -} - -impl LintLevelsProvider for QueryMapExpectationsWrapper<'_> { - fn current_specs(&self) -> &FxIndexMap { - self.specs.specs.get(&self.cur.local_id).unwrap_or(&self.empty) - } - fn insert(&mut self, id: LintId, lvl: LevelAndSource) { - self.specs.specs.get_mut_or_insert_default(self.cur.local_id).insert(id, lvl); - } - fn get_lint_level(&self, lint: &'static Lint, _: &Session) -> LevelAndSource { - // We cannot use `tcx.lint_level_at_node` because we want to know in which order the - // attributes have been inserted, in particular whether an `expect` follows a `forbid`. - self.specs.lint_level_id_at_node(self.tcx, LintId::of(lint), self.cur) - } fn push_expectation(&mut self, id: LintExpectationId, expectation: LintExpectation) { - let LintExpectationId::Stable { attr_id: Some(attr_id), hir_id, attr_index, .. } = id - else { - bug!("unstable expectation id should already be mapped") - }; - - self.unstable_to_stable_ids.entry(attr_id).or_insert(LintExpectationId::Stable { - hir_id, - attr_index, - lint_index: None, - attr_id: None, - }); - - self.expectations.push((id.normalize(), expectation)); + self.specs.expectations.push((id.normalize(), expectation)) } } @@ -367,80 +303,6 @@ impl<'tcx> Visitor<'tcx> for LintLevelsBuilder<'_, LintLevelQueryMap<'tcx>> { } } -impl<'tcx> LintLevelsBuilder<'_, QueryMapExpectationsWrapper<'tcx>> { - fn add_id(&mut self, hir_id: HirId) { - // Change both the `HirId` and the associated specs. - self.provider.cur = hir_id; - self.provider.specs.specs.clear(); - self.add(self.provider.tcx.hir().attrs(hir_id), hir_id == hir::CRATE_HIR_ID, Some(hir_id)); - } -} - -impl<'tcx> Visitor<'tcx> for LintLevelsBuilder<'_, QueryMapExpectationsWrapper<'tcx>> { - type NestedFilter = nested_filter::All; - - fn nested_visit_map(&mut self) -> Self::Map { - self.provider.tcx.hir() - } - - fn visit_param(&mut self, param: &'tcx hir::Param<'tcx>) { - self.add_id(param.hir_id); - intravisit::walk_param(self, param); - } - - fn visit_item(&mut self, it: &'tcx hir::Item<'tcx>) { - self.add_id(it.hir_id()); - intravisit::walk_item(self, it); - } - - fn visit_foreign_item(&mut self, it: &'tcx hir::ForeignItem<'tcx>) { - self.add_id(it.hir_id()); - intravisit::walk_foreign_item(self, it); - } - - fn visit_stmt(&mut self, e: &'tcx hir::Stmt<'tcx>) { - // We will call `add_id` when we walk - // the `StmtKind`. The outer statement itself doesn't - // define the lint levels. - intravisit::walk_stmt(self, e); - } - - fn visit_expr(&mut self, e: &'tcx hir::Expr<'tcx>) { - self.add_id(e.hir_id); - intravisit::walk_expr(self, e); - } - - fn visit_field_def(&mut self, s: &'tcx hir::FieldDef<'tcx>) { - self.add_id(s.hir_id); - intravisit::walk_field_def(self, s); - } - - fn visit_variant(&mut self, v: &'tcx hir::Variant<'tcx>) { - self.add_id(v.hir_id); - intravisit::walk_variant(self, v); - } - - fn visit_local(&mut self, l: &'tcx hir::LetStmt<'tcx>) { - self.add_id(l.hir_id); - intravisit::walk_local(self, l); - } - - fn visit_arm(&mut self, a: &'tcx hir::Arm<'tcx>) { - self.add_id(a.hir_id); - intravisit::walk_arm(self, a); - } - - fn visit_trait_item(&mut self, trait_item: &'tcx hir::TraitItem<'tcx>) { - self.add_id(trait_item.hir_id()); - intravisit::walk_trait_item(self, trait_item); - } - - fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem<'tcx>) { - self.add_id(impl_item.hir_id()); - intravisit::walk_impl_item(self, impl_item); - } -} - pub struct LintLevelsBuilder<'s, P> { sess: &'s Session, features: &'s Features, @@ -1099,7 +961,7 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> { } pub(crate) fn provide(providers: &mut Providers) { - *providers = Providers { shallow_lint_levels_on, lint_expectations, ..*providers }; + *providers = Providers { shallow_lint_levels_on, ..*providers }; } pub(crate) fn parse_lint_and_tool_name(lint_name: &str) -> (Option, &str) { diff --git a/compiler/rustc_middle/src/lint.rs b/compiler/rustc_middle/src/lint.rs index 8c27cac1ea858..70da66af64be8 100644 --- a/compiler/rustc_middle/src/lint.rs +++ b/compiler/rustc_middle/src/lint.rs @@ -6,7 +6,7 @@ use rustc_errors::{Diag, MultiSpan}; use rustc_hir::{HirId, ItemLocalId}; use rustc_macros::HashStable; use rustc_session::lint::builtin::{self, FORBIDDEN_LINT_GROUPS}; -use rustc_session::lint::{FutureIncompatibilityReason, Level, Lint, LintId}; +use rustc_session::lint::{FutureIncompatibilityReason, Level, Lint, LintExpectationId, LintId}; use rustc_session::Session; use rustc_span::hygiene::{ExpnKind, MacroKind}; use rustc_span::{symbol, DesugaringKind, Span, Symbol, DUMMY_SP}; @@ -61,6 +61,7 @@ pub type LevelAndSource = (Level, LintLevelSource); /// by the attributes for *a single HirId*. #[derive(Default, Debug, HashStable)] pub struct ShallowLintLevelMap { + pub expectations: Vec<(LintExpectationId, LintExpectation)>, pub specs: SortedMap>, } diff --git a/tests/ui/error-codes/E0602.stderr b/tests/ui/error-codes/E0602.stderr index b0b6033aadd2c..b6b5cd5c3d3e6 100644 --- a/tests/ui/error-codes/E0602.stderr +++ b/tests/ui/error-codes/E0602.stderr @@ -13,11 +13,6 @@ warning[E0602]: unknown lint: `bogus` = note: requested on the command line with `-D bogus` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -warning[E0602]: unknown lint: `bogus` - | - = note: requested on the command line with `-D bogus` - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -warning: 4 warnings emitted +warning: 3 warnings emitted For more information about this error, try `rustc --explain E0602`. diff --git a/tests/ui/lint/cli-unknown-force-warn.stderr b/tests/ui/lint/cli-unknown-force-warn.stderr index cfff190b54aff..5084b4a40013a 100644 --- a/tests/ui/lint/cli-unknown-force-warn.stderr +++ b/tests/ui/lint/cli-unknown-force-warn.stderr @@ -13,11 +13,6 @@ warning[E0602]: unknown lint: `foo_qux` = note: requested on the command line with `--force-warn foo_qux` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -warning[E0602]: unknown lint: `foo_qux` - | - = note: requested on the command line with `--force-warn foo_qux` - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -warning: 4 warnings emitted +warning: 3 warnings emitted For more information about this error, try `rustc --explain E0602`. diff --git a/tests/ui/lint/lint-removed-cmdline-deny.stderr b/tests/ui/lint/lint-removed-cmdline-deny.stderr index 2a24e795f4438..3321afa7fcd75 100644 --- a/tests/ui/lint/lint-removed-cmdline-deny.stderr +++ b/tests/ui/lint/lint-removed-cmdline-deny.stderr @@ -26,10 +26,5 @@ LL | #[deny(warnings)] | ^^^^^^^^ = note: `#[deny(unused_variables)]` implied by `#[deny(warnings)]` -error: lint `raw_pointer_derive` has been removed: using derive with raw pointers is ok - | - = note: requested on the command line with `-D raw_pointer_derive` - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error: aborting due to 5 previous errors +error: aborting due to 4 previous errors diff --git a/tests/ui/lint/lint-removed-cmdline.stderr b/tests/ui/lint/lint-removed-cmdline.stderr index 78ae2fd8fbffe..fd63433c30867 100644 --- a/tests/ui/lint/lint-removed-cmdline.stderr +++ b/tests/ui/lint/lint-removed-cmdline.stderr @@ -26,10 +26,5 @@ LL | #[deny(warnings)] | ^^^^^^^^ = note: `#[deny(unused_variables)]` implied by `#[deny(warnings)]` -warning: lint `raw_pointer_derive` has been removed: using derive with raw pointers is ok - | - = note: requested on the command line with `-D raw_pointer_derive` - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error: aborting due to 1 previous error; 4 warnings emitted +error: aborting due to 1 previous error; 3 warnings emitted diff --git a/tests/ui/lint/lint-renamed-cmdline-deny.stderr b/tests/ui/lint/lint-renamed-cmdline-deny.stderr index 3c1a59ec1e1c0..0e182a4e5dea0 100644 --- a/tests/ui/lint/lint-renamed-cmdline-deny.stderr +++ b/tests/ui/lint/lint-renamed-cmdline-deny.stderr @@ -29,11 +29,5 @@ LL | #[deny(unused)] | ^^^^^^ = note: `#[deny(unused_variables)]` implied by `#[deny(unused)]` -error: lint `bare_trait_object` has been renamed to `bare_trait_objects` - | - = help: use the new name `bare_trait_objects` - = note: requested on the command line with `-D bare_trait_object` - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error: aborting due to 5 previous errors +error: aborting due to 4 previous errors diff --git a/tests/ui/lint/lint-renamed-cmdline.stderr b/tests/ui/lint/lint-renamed-cmdline.stderr index 6544416f61149..d6bb72f34dce2 100644 --- a/tests/ui/lint/lint-renamed-cmdline.stderr +++ b/tests/ui/lint/lint-renamed-cmdline.stderr @@ -29,11 +29,5 @@ LL | #[deny(unused)] | ^^^^^^ = note: `#[deny(unused_variables)]` implied by `#[deny(unused)]` -warning: lint `bare_trait_object` has been renamed to `bare_trait_objects` - | - = help: use the new name `bare_trait_objects` - = note: requested on the command line with `-D bare_trait_object` - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error: aborting due to 1 previous error; 4 warnings emitted +error: aborting due to 1 previous error; 3 warnings emitted diff --git a/tests/ui/lint/lint-unexported-no-mangle.stderr b/tests/ui/lint/lint-unexported-no-mangle.stderr index 39377b6fe8465..0efec51abaf6d 100644 --- a/tests/ui/lint/lint-unexported-no-mangle.stderr +++ b/tests/ui/lint/lint-unexported-no-mangle.stderr @@ -45,15 +45,5 @@ LL | pub const PUB_FOO: u64 = 1; | | | help: try a static value: `pub static` -warning: lint `private_no_mangle_fns` has been removed: no longer a warning, `#[no_mangle]` functions always exported - | - = note: requested on the command line with `-F private_no_mangle_fns` - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -warning: lint `private_no_mangle_statics` has been removed: no longer a warning, `#[no_mangle]` statics always exported - | - = note: requested on the command line with `-F private_no_mangle_statics` - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error: aborting due to 2 previous errors; 8 warnings emitted +error: aborting due to 2 previous errors; 6 warnings emitted diff --git a/tests/ui/lint/lint-unknown-lint-cmdline-deny.stderr b/tests/ui/lint/lint-unknown-lint-cmdline-deny.stderr index 1ce55706d7651..f12ce03ddfcef 100644 --- a/tests/ui/lint/lint-unknown-lint-cmdline-deny.stderr +++ b/tests/ui/lint/lint-unknown-lint-cmdline-deny.stderr @@ -30,17 +30,6 @@ error[E0602]: unknown lint: `dead_cod` = note: requested on the command line with `-D dead_cod` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -error[E0602]: unknown lint: `bogus` - | - = note: requested on the command line with `-D bogus` - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error[E0602]: unknown lint: `dead_cod` - | - = help: did you mean: `dead_code` - = note: requested on the command line with `-D dead_cod` - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error: aborting due to 8 previous errors +error: aborting due to 6 previous errors For more information about this error, try `rustc --explain E0602`. diff --git a/tests/ui/lint/lint-unknown-lint-cmdline.stderr b/tests/ui/lint/lint-unknown-lint-cmdline.stderr index 4e0c5dbcb0730..f452fc9eb943c 100644 --- a/tests/ui/lint/lint-unknown-lint-cmdline.stderr +++ b/tests/ui/lint/lint-unknown-lint-cmdline.stderr @@ -30,17 +30,6 @@ warning[E0602]: unknown lint: `dead_cod` = note: requested on the command line with `-D dead_cod` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -warning[E0602]: unknown lint: `bogus` - | - = note: requested on the command line with `-D bogus` - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -warning[E0602]: unknown lint: `dead_cod` - | - = help: did you mean: `dead_code` - = note: requested on the command line with `-D dead_cod` - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -warning: 8 warnings emitted +warning: 6 warnings emitted For more information about this error, try `rustc --explain E0602`. From 5f1f45b095f0980acd02bd3bbdc2a3ba9e8b8a38 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Thu, 4 Jul 2024 10:12:39 +0000 Subject: [PATCH 0309/2194] Remove attr_id from stable lint ids. --- compiler/rustc_errors/src/diagnostic.rs | 2 +- compiler/rustc_errors/src/lib.rs | 2 +- compiler/rustc_lint/src/expect.rs | 3 +-- compiler/rustc_lint/src/levels.rs | 18 +++++--------- compiler/rustc_lint_defs/src/lib.rs | 31 ++++--------------------- 5 files changed, 14 insertions(+), 42 deletions(-) diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs index 7e4698a94a9f6..34aebadfdadc5 100644 --- a/compiler/rustc_errors/src/diagnostic.rs +++ b/compiler/rustc_errors/src/diagnostic.rs @@ -368,7 +368,7 @@ impl DiagInner { panic!("{expectation_id:?} must have a matching stable id") }; - let mut stable_id = stable_id.normalize(); + let mut stable_id = *stable_id; stable_id.set_lint_index(lint_index); *expectation_id = stable_id; } diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index 967e64c2d9f74..e08d28a156c71 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -1567,7 +1567,7 @@ impl DiagCtxtInner { if let LintExpectationId::Unstable { .. } = expect_id { unreachable!(); // this case was handled at the top of this function } - self.fulfilled_expectations.insert(expect_id.normalize()); + self.fulfilled_expectations.insert(expect_id); if let Expect(_) = diagnostic.level { // Nothing emitted here for expected lints. TRACK_DIAGNOSTIC(diagnostic, &mut |_| None); diff --git a/compiler/rustc_lint/src/expect.rs b/compiler/rustc_lint/src/expect.rs index d9fab1d00aa5b..d8afba3d5053c 100644 --- a/compiler/rustc_lint/src/expect.rs +++ b/compiler/rustc_lint/src/expect.rs @@ -20,8 +20,7 @@ fn lint_expectations(tcx: TyCtxt<'_>, (): ()) -> Vec<(LintExpectationId, LintExp let mut unstable_to_stable_ids = FxIndexMap::default(); let mut record_stable = |attr_id, hir_id, attr_index| { - let expect_id = - LintExpectationId::Stable { hir_id, attr_index, lint_index: None, attr_id: None }; + let expect_id = LintExpectationId::Stable { hir_id, attr_index, lint_index: None }; unstable_to_stable_ids.entry(attr_id).or_insert(expect_id); }; let mut push_expectations = |owner| { diff --git a/compiler/rustc_lint/src/levels.rs b/compiler/rustc_lint/src/levels.rs index dfbc61d50e8df..43682ad5a5607 100644 --- a/compiler/rustc_lint/src/levels.rs +++ b/compiler/rustc_lint/src/levels.rs @@ -218,7 +218,7 @@ impl LintLevelsProvider for LintLevelQueryMap<'_> { self.specs.lint_level_id_at_node(self.tcx, LintId::of(lint), self.cur) } fn push_expectation(&mut self, id: LintExpectationId, expectation: LintExpectation) { - self.specs.expectations.push((id.normalize(), expectation)) + self.specs.expectations.push((id, expectation)) } } @@ -486,13 +486,9 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> { /// Attempts to insert the `id` to `level_src` map entry. If unsuccessful /// (e.g. if a forbid was already inserted on the same scope), then emits a /// diagnostic with no change to `specs`. - fn insert_spec(&mut self, id: LintId, (mut level, src): LevelAndSource) { + fn insert_spec(&mut self, id: LintId, (level, src): LevelAndSource) { let (old_level, old_src) = self.provider.get_lint_level(id.lint, self.sess); - if let Level::Expect(id) = &mut level - && let LintExpectationId::Stable { .. } = id - { - *id = id.normalize(); - } + // Setting to a non-forbid level is an error if the lint previously had // a forbid level. Note that this is not necessarily true even with a // `#[forbid(..)]` attribute present, as that is overridden by `--cap-lints`. @@ -604,17 +600,15 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> { // This is the only lint level with a `LintExpectationId` that can be created from // an attribute. Some(Level::Expect(unstable_id)) if let Some(hir_id) = source_hir_id => { - let LintExpectationId::Unstable { attr_id, lint_index } = unstable_id else { + let LintExpectationId::Unstable { lint_index: None, attr_id: _ } = unstable_id + else { bug!("stable id Level::from_attr") }; let stable_id = LintExpectationId::Stable { hir_id, attr_index: attr_index.try_into().unwrap(), - lint_index, - // We pass the previous unstable attr_id such that we can trace the ast id - // when building a map to go from unstable to stable id. - attr_id: Some(attr_id), + lint_index: None, }; Level::Expect(stable_id) diff --git a/compiler/rustc_lint_defs/src/lib.rs b/compiler/rustc_lint_defs/src/lib.rs index c17b85db3b044..d318f7aedb4be 100644 --- a/compiler/rustc_lint_defs/src/lib.rs +++ b/compiler/rustc_lint_defs/src/lib.rs @@ -98,7 +98,7 @@ pub enum LintExpectationId { /// stable and can be cached. The additional index ensures that nodes with /// several expectations can correctly match diagnostics to the individual /// expectation. - Stable { hir_id: HirId, attr_index: u16, lint_index: Option, attr_id: Option }, + Stable { hir_id: HirId, attr_index: u16, lint_index: Option }, } impl LintExpectationId { @@ -122,31 +122,13 @@ impl LintExpectationId { *lint_index = new_lint_index } - - /// Prepares the id for hashing. Removes references to the ast. - /// Should only be called when the id is stable. - pub fn normalize(self) -> Self { - match self { - Self::Stable { hir_id, attr_index, lint_index, .. } => { - Self::Stable { hir_id, attr_index, lint_index, attr_id: None } - } - Self::Unstable { .. } => { - unreachable!("`normalize` called when `ExpectationId` is unstable") - } - } - } } impl HashStable for LintExpectationId { #[inline] fn hash_stable(&self, hcx: &mut HCX, hasher: &mut StableHasher) { match self { - LintExpectationId::Stable { - hir_id, - attr_index, - lint_index: Some(lint_index), - attr_id: _, - } => { + LintExpectationId::Stable { hir_id, attr_index, lint_index: Some(lint_index) } => { hir_id.hash_stable(hcx, hasher); attr_index.hash_stable(hcx, hasher); lint_index.hash_stable(hcx, hasher); @@ -166,12 +148,9 @@ impl ToStableHashKey for LintExpectation #[inline] fn to_stable_hash_key(&self, _: &HCX) -> Self::KeyType { match self { - LintExpectationId::Stable { - hir_id, - attr_index, - lint_index: Some(lint_index), - attr_id: _, - } => (*hir_id, *attr_index, *lint_index), + LintExpectationId::Stable { hir_id, attr_index, lint_index: Some(lint_index) } => { + (*hir_id, *attr_index, *lint_index) + } _ => { unreachable!("HashStable should only be called for a filled `LintExpectationId`") } From ff1fc68c11b04e7336c6deef210418f73efd6680 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Thu, 4 Jul 2024 10:33:42 +0000 Subject: [PATCH 0310/2194] Simplify lint source computation. --- compiler/rustc_lint/src/levels.rs | 188 +++++++++++++----------------- 1 file changed, 83 insertions(+), 105 deletions(-) diff --git a/compiler/rustc_lint/src/levels.rs b/compiler/rustc_lint/src/levels.rs index 43682ad5a5607..65289de980e13 100644 --- a/compiler/rustc_lint/src/levels.rs +++ b/compiler/rustc_lint/src/levels.rs @@ -695,59 +695,20 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> { let name = pprust::path_to_string(&meta_item.path); let lint_result = self.store.check_lint_name(&name, tool_name, self.registered_tools); - match &lint_result { + + let (ids, name) = match lint_result { CheckLintNameResult::Ok(ids) => { - // This checks for instances where the user writes - // `#[expect(unfulfilled_lint_expectations)]` in that case we want to avoid - // overriding the lint level but instead add an expectation that can't be - // fulfilled. The lint message will include an explanation, that the - // `unfulfilled_lint_expectations` lint can't be expected. - if let Level::Expect(expect_id) = level { - // The `unfulfilled_lint_expectations` lint is not part of any lint - // groups. Therefore. we only need to check the slice if it contains a - // single lint. - let is_unfulfilled_lint_expectations = match ids { - [lint] => *lint == LintId::of(UNFULFILLED_LINT_EXPECTATIONS), - _ => false, - }; - self.provider.push_expectation( - expect_id, - LintExpectation::new( - reason, - sp, - is_unfulfilled_lint_expectations, - tool_name, - ), - ); - } - let src = LintLevelSource::Node { - name: meta_item - .path - .segments - .last() - .expect("empty lint name") - .ident - .name, - span: sp, - reason, - }; - for &id in *ids { - if self.check_gated_lint(id, attr.span, false) { - self.insert_spec(id, (level, src)); - } - } + let name = + meta_item.path.segments.last().expect("empty lint name").ident.name; + (ids, name) } CheckLintNameResult::Tool(ids, new_lint_name) => { - let src = match new_lint_name { + let name = match new_lint_name { None => { let complete_name = &format!("{}::{}", tool_ident.unwrap().name, name); - LintLevelSource::Node { - name: Symbol::intern(complete_name), - span: sp, - reason, - } + Symbol::intern(complete_name) } Some(new_lint_name) => { self.emit_span_lint( @@ -756,27 +717,13 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> { DeprecatedLintName { name, suggestion: sp, - replace: new_lint_name, + replace: &new_lint_name, }, ); - LintLevelSource::Node { - name: Symbol::intern(new_lint_name), - span: sp, - reason, - } + Symbol::intern(&new_lint_name) } }; - for &id in *ids { - if self.check_gated_lint(id, attr.span, false) { - self.insert_spec(id, (level, src)); - } - } - if let Level::Expect(expect_id) = level { - self.provider.push_expectation( - expect_id, - LintExpectation::new(reason, sp, false, tool_name), - ); - } + (ids, name) } CheckLintNameResult::MissingTool => { @@ -784,9 +731,10 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> { // exist in the tool or the code was not compiled with the tool and // therefore the lint was never added to the `LintStore`. To detect // this is the responsibility of the lint tool. + continue; } - &CheckLintNameResult::NoTool => { + CheckLintNameResult::NoTool => { sess.dcx().emit_err(UnknownToolInScopedLint { span: tool_ident.map(|ident| ident.span), tool_name: tool_name.unwrap(), @@ -796,58 +744,88 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> { continue; } - _ if !self.lint_added_lints => {} - CheckLintNameResult::Renamed(ref replace) => { - let suggestion = - RenamedLintSuggestion::WithSpan { suggestion: sp, replace }; - let name = tool_ident.map(|tool| format!("{tool}::{name}")).unwrap_or(name); - let lint = RenamedLint { name: name.as_str(), suggestion }; - self.emit_span_lint(RENAMED_AND_REMOVED_LINTS, sp.into(), lint); + if self.lint_added_lints { + let suggestion = + RenamedLintSuggestion::WithSpan { suggestion: sp, replace }; + let name = + tool_ident.map(|tool| format!("{tool}::{name}")).unwrap_or(name); + let lint = RenamedLint { name: name.as_str(), suggestion }; + self.emit_span_lint(RENAMED_AND_REMOVED_LINTS, sp.into(), lint); + } + + // If this lint was renamed, apply the new lint instead of ignoring the + // attribute. Ignore any errors or warnings that happen because the new + // name is inaccurate. + // NOTE: `new_name` already includes the tool name, so we don't + // have to add it again. + let CheckLintNameResult::Ok(ids) = + self.store.check_lint_name(replace, None, self.registered_tools) + else { + panic!("renamed lint does not exist: {replace}"); + }; + + (ids, Symbol::intern(&replace)) } CheckLintNameResult::Removed(ref reason) => { - let name = tool_ident.map(|tool| format!("{tool}::{name}")).unwrap_or(name); - let lint = RemovedLint { name: name.as_str(), reason }; - self.emit_span_lint(RENAMED_AND_REMOVED_LINTS, sp.into(), lint); + if self.lint_added_lints { + let name = + tool_ident.map(|tool| format!("{tool}::{name}")).unwrap_or(name); + let lint = RemovedLint { name: name.as_str(), reason }; + self.emit_span_lint(RENAMED_AND_REMOVED_LINTS, sp.into(), lint); + } + continue; } CheckLintNameResult::NoLint(suggestion) => { - let name = tool_ident.map(|tool| format!("{tool}::{name}")).unwrap_or(name); - let suggestion = suggestion.map(|(replace, from_rustc)| { - UnknownLintSuggestion::WithSpan { suggestion: sp, replace, from_rustc } - }); - let lint = UnknownLint { name, suggestion }; - self.emit_span_lint(UNKNOWN_LINTS, sp.into(), lint); - } - } - // If this lint was renamed, apply the new lint instead of ignoring the attribute. - // This happens outside of the match because the new lint should be applied even if - // we don't warn about the name change. - if let CheckLintNameResult::Renamed(new_name) = lint_result { - // Ignore any errors or warnings that happen because the new name is inaccurate - // NOTE: `new_name` already includes the tool name, so we don't have to add it - // again. - let CheckLintNameResult::Ok(ids) = - self.store.check_lint_name(&new_name, None, self.registered_tools) - else { - panic!("renamed lint does not exist: {new_name}"); - }; - - let src = - LintLevelSource::Node { name: Symbol::intern(&new_name), span: sp, reason }; - for &id in ids { - if self.check_gated_lint(id, attr.span, false) { - self.insert_spec(id, (level, src)); + if self.lint_added_lints { + let name = + tool_ident.map(|tool| format!("{tool}::{name}")).unwrap_or(name); + let suggestion = suggestion.map(|(replace, from_rustc)| { + UnknownLintSuggestion::WithSpan { + suggestion: sp, + replace, + from_rustc, + } + }); + let lint = UnknownLint { name, suggestion }; + self.emit_span_lint(UNKNOWN_LINTS, sp.into(), lint); } + continue; } - if let Level::Expect(expect_id) = level { - self.provider.push_expectation( - expect_id, - LintExpectation::new(reason, sp, false, tool_name), - ); + }; + + let src = LintLevelSource::Node { name, span: sp, reason }; + for &id in ids { + if self.check_gated_lint(id, attr.span, false) { + self.insert_spec(id, (level, src)); } } + + // This checks for instances where the user writes + // `#[expect(unfulfilled_lint_expectations)]` in that case we want to avoid + // overriding the lint level but instead add an expectation that can't be + // fulfilled. The lint message will include an explanation, that the + // `unfulfilled_lint_expectations` lint can't be expected. + if let Level::Expect(expect_id) = level { + // The `unfulfilled_lint_expectations` lint is not part of any lint + // groups. Therefore. we only need to check the slice if it contains a + // single lint. + let is_unfulfilled_lint_expectations = match ids { + [lint] => *lint == LintId::of(UNFULFILLED_LINT_EXPECTATIONS), + _ => false, + }; + self.provider.push_expectation( + expect_id, + LintExpectation::new( + reason, + sp, + is_unfulfilled_lint_expectations, + tool_name, + ), + ); + } } } From e845366c82ada0466a9801363064357ad22daf12 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 22 Jul 2024 11:44:40 +0200 Subject: [PATCH 0311/2194] Add MSRV check for `saturating_sub` lints in const contexts --- clippy_config/src/msrvs.rs | 2 +- clippy_lints/src/implicit_saturating_sub.rs | 27 ++++++++++++++++++--- clippy_lints/src/lib.rs | 2 +- 3 files changed, 26 insertions(+), 5 deletions(-) diff --git a/clippy_config/src/msrvs.rs b/clippy_config/src/msrvs.rs index 5b9707efd2634..db4c13fe33a29 100644 --- a/clippy_config/src/msrvs.rs +++ b/clippy_config/src/msrvs.rs @@ -35,7 +35,7 @@ msrv_aliases! { 1,52,0 { STR_SPLIT_ONCE, REM_EUCLID_CONST } 1,51,0 { BORROW_AS_PTR, SEEK_FROM_CURRENT, UNSIGNED_ABS } 1,50,0 { BOOL_THEN, CLAMP } - 1,47,0 { TAU, IS_ASCII_DIGIT_CONST, ARRAY_IMPL_ANY_LEN } + 1,47,0 { TAU, IS_ASCII_DIGIT_CONST, ARRAY_IMPL_ANY_LEN, SATURATING_SUB_CONST } 1,46,0 { CONST_IF_MATCH } 1,45,0 { STR_STRIP_PREFIX } 1,43,0 { LOG2_10, LOG10_2, NUMERIC_ASSOCIATED_CONSTANTS } diff --git a/clippy_lints/src/implicit_saturating_sub.rs b/clippy_lints/src/implicit_saturating_sub.rs index 04c890620396d..5a42802e6bbda 100644 --- a/clippy_lints/src/implicit_saturating_sub.rs +++ b/clippy_lints/src/implicit_saturating_sub.rs @@ -1,12 +1,16 @@ +use clippy_config::msrvs::{self, Msrv}; +use clippy_config::Conf; use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then}; use clippy_utils::source::snippet_opt; -use clippy_utils::{higher, is_integer_literal, path_to_local, peel_blocks, peel_blocks_with_stmt, SpanlessEq}; +use clippy_utils::{ + higher, in_constant, is_integer_literal, path_to_local, peel_blocks, peel_blocks_with_stmt, SpanlessEq, +}; use rustc_ast::ast::LitKind; use rustc_data_structures::packed::Pu128; use rustc_errors::Applicability; use rustc_hir::{BinOp, BinOpKind, Expr, ExprKind, HirId, QPath}; use rustc_lint::{LateContext, LateLintPass}; -use rustc_session::declare_lint_pass; +use rustc_session::impl_lint_pass; use rustc_span::Span; declare_clippy_lint! { @@ -71,13 +75,28 @@ declare_clippy_lint! { "Check if a variable is smaller than another one and still subtract from it even if smaller" } -declare_lint_pass!(ImplicitSaturatingSub => [IMPLICIT_SATURATING_SUB, INVERTED_SATURATING_SUB]); +pub struct ImplicitSaturatingSub { + msrv: Msrv, +} + +impl_lint_pass!(ImplicitSaturatingSub => [IMPLICIT_SATURATING_SUB, INVERTED_SATURATING_SUB]); + +impl ImplicitSaturatingSub { + pub fn new(conf: &'static Conf) -> Self { + Self { + msrv: conf.msrv.clone(), + } + } +} impl<'tcx> LateLintPass<'tcx> for ImplicitSaturatingSub { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) { if expr.span.from_expansion() { return; } + if in_constant(cx, expr.hir_id) && !self.msrv.meets(msrvs::SATURATING_SUB_CONST) { + return; + } if let Some(higher::If { cond, then, r#else: None }) = higher::If::hir(expr) // Check if the conditional expression is a binary operation @@ -94,6 +113,8 @@ impl<'tcx> LateLintPass<'tcx> for ImplicitSaturatingSub { check_manual_check(cx, expr, cond_op, cond_left, cond_right, if_block, else_block); } } + + extract_msrv_attr!(LateContext); } fn check_manual_check<'tcx>( diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 2ac06b360bea4..80e314dd402da 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -623,7 +623,7 @@ pub fn register_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) { store.register_late_pass(|_| Box::new(unit_return_expecting_ord::UnitReturnExpectingOrd)); store.register_late_pass(|_| Box::new(strings::StringAdd)); store.register_late_pass(|_| Box::new(implicit_return::ImplicitReturn)); - store.register_late_pass(|_| Box::new(implicit_saturating_sub::ImplicitSaturatingSub)); + store.register_late_pass(move |_| Box::new(implicit_saturating_sub::ImplicitSaturatingSub::new(conf))); store.register_late_pass(|_| Box::new(default_numeric_fallback::DefaultNumericFallback)); store.register_late_pass(|_| Box::new(inconsistent_struct_constructor::InconsistentStructConstructor)); store.register_late_pass(|_| Box::new(non_octal_unix_permissions::NonOctalUnixPermissions)); From 2832faf8959932a25fda883ed3f7dfde8b2d2817 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 2 Aug 2024 11:17:14 +0200 Subject: [PATCH 0312/2194] Move MSRV check later in `implicit_saturating_sub` --- clippy_lints/src/implicit_saturating_sub.rs | 40 +++++++++++++++++---- 1 file changed, 33 insertions(+), 7 deletions(-) diff --git a/clippy_lints/src/implicit_saturating_sub.rs b/clippy_lints/src/implicit_saturating_sub.rs index 5a42802e6bbda..3536309d83ca0 100644 --- a/clippy_lints/src/implicit_saturating_sub.rs +++ b/clippy_lints/src/implicit_saturating_sub.rs @@ -3,7 +3,7 @@ use clippy_config::Conf; use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then}; use clippy_utils::source::snippet_opt; use clippy_utils::{ - higher, in_constant, is_integer_literal, path_to_local, peel_blocks, peel_blocks_with_stmt, SpanlessEq, + higher, is_in_const_context, is_integer_literal, path_to_local, peel_blocks, peel_blocks_with_stmt, SpanlessEq, }; use rustc_ast::ast::LitKind; use rustc_data_structures::packed::Pu128; @@ -94,9 +94,6 @@ impl<'tcx> LateLintPass<'tcx> for ImplicitSaturatingSub { if expr.span.from_expansion() { return; } - if in_constant(cx, expr.hir_id) && !self.msrv.meets(msrvs::SATURATING_SUB_CONST) { - return; - } if let Some(higher::If { cond, then, r#else: None }) = higher::If::hir(expr) // Check if the conditional expression is a binary operation @@ -110,13 +107,16 @@ impl<'tcx> LateLintPass<'tcx> for ImplicitSaturatingSub { }) = higher::If::hir(expr) && let ExprKind::Binary(ref cond_op, cond_left, cond_right) = cond.kind { - check_manual_check(cx, expr, cond_op, cond_left, cond_right, if_block, else_block); + check_manual_check( + cx, expr, cond_op, cond_left, cond_right, if_block, else_block, &self.msrv, + ); } } extract_msrv_attr!(LateContext); } +#[allow(clippy::too_many_arguments)] fn check_manual_check<'tcx>( cx: &LateContext<'tcx>, expr: &Expr<'tcx>, @@ -125,6 +125,7 @@ fn check_manual_check<'tcx>( right_hand: &Expr<'tcx>, if_block: &Expr<'tcx>, else_block: &Expr<'tcx>, + msrv: &Msrv, ) { let ty = cx.typeck_results().expr_ty(left_hand); if ty.is_numeric() && !ty.is_signed() { @@ -137,6 +138,7 @@ fn check_manual_check<'tcx>( right_hand, if_block, else_block, + msrv, ), BinOpKind::Lt | BinOpKind::Le => check_gt( cx, @@ -146,12 +148,14 @@ fn check_manual_check<'tcx>( left_hand, if_block, else_block, + msrv, ), _ => {}, } } } +#[allow(clippy::too_many_arguments)] fn check_gt( cx: &LateContext<'_>, condition_span: Span, @@ -160,11 +164,21 @@ fn check_gt( little_var: &Expr<'_>, if_block: &Expr<'_>, else_block: &Expr<'_>, + msrv: &Msrv, ) { if let Some(big_var) = Var::new(big_var) && let Some(little_var) = Var::new(little_var) { - check_subtraction(cx, condition_span, expr_span, big_var, little_var, if_block, else_block); + check_subtraction( + cx, + condition_span, + expr_span, + big_var, + little_var, + if_block, + else_block, + msrv, + ); } } @@ -182,6 +196,7 @@ impl Var { } } +#[allow(clippy::too_many_arguments)] fn check_subtraction( cx: &LateContext<'_>, condition_span: Span, @@ -190,6 +205,7 @@ fn check_subtraction( little_var: Var, if_block: &Expr<'_>, else_block: &Expr<'_>, + msrv: &Msrv, ) { let if_block = peel_blocks(if_block); let else_block = peel_blocks(else_block); @@ -201,7 +217,16 @@ fn check_subtraction( } // If the subtraction is done in the `else` block, then we need to also revert the two // variables as it means that the check was reverted too. - check_subtraction(cx, condition_span, expr_span, little_var, big_var, else_block, if_block); + check_subtraction( + cx, + condition_span, + expr_span, + little_var, + big_var, + else_block, + if_block, + msrv, + ); return; } if is_integer_literal(else_block, 0) @@ -215,6 +240,7 @@ fn check_subtraction( // if `snippet_opt` fails, it won't try the next conditions. if let Some(big_var_snippet) = snippet_opt(cx, big_var.span) && let Some(little_var_snippet) = snippet_opt(cx, little_var.span) + && (!is_in_const_context(cx) || msrv.meets(msrvs::SATURATING_SUB_CONST)) { span_lint_and_sugg( cx, From 989ebae2ba5b79e259ee6267a390acd446cb5bff Mon Sep 17 00:00:00 2001 From: alexey semenyuk Date: Thu, 29 Aug 2024 10:55:42 +0500 Subject: [PATCH 0313/2194] Provide more clear example for WRONG_SELF_CONVENTION --- clippy_lints/src/methods/mod.rs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index d7126990edb1d..e1f1df4eecba4 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -441,6 +441,17 @@ declare_clippy_lint! { /// } /// } /// ``` + /// + /// Use instead: + /// ```no_run + /// # struct X; + /// impl X { + /// fn as_str(&self) -> &'static str { + /// // .. + /// # "" + /// } + /// } + /// ``` #[clippy::version = "pre 1.29.0"] pub WRONG_SELF_CONVENTION, style, From d4e708f1bc92cb6e284fb8c8f9fe043fb90e226b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Eduardo=20S=C3=A1nchez=20Mu=C3=B1oz?= Date: Sat, 31 Aug 2024 21:54:29 +0200 Subject: [PATCH 0314/2194] Remove stray dot in `std::char::from_u32_unchecked` documentation --- library/core/src/char/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/core/src/char/mod.rs b/library/core/src/char/mod.rs index e6574ac3c7278..fa3c2075423bc 100644 --- a/library/core/src/char/mod.rs +++ b/library/core/src/char/mod.rs @@ -122,7 +122,7 @@ pub const fn from_u32(i: u32) -> Option { self::convert::from_u32(i) } -/// Converts a `u32` to a `char`, ignoring validity. Use [`char::from_u32_unchecked`]. +/// Converts a `u32` to a `char`, ignoring validity. Use [`char::from_u32_unchecked`] /// instead. #[stable(feature = "char_from_unchecked", since = "1.5.0")] #[rustc_const_stable(feature = "const_char_from_u32_unchecked", since = "1.81.0")] From c3f9c4f4d4bbc83c7de79a09c7ec0e7fda8efc5e Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 20 Aug 2024 11:35:05 -0400 Subject: [PATCH 0315/2194] Use equality when relating formal and expected type in arg checking --- .../rustc_hir_typeck/src/fn_ctxt/checks.rs | 9 ++++----- .../coercion/constrain-expectation-in-arg.rs | 19 +++++++++++++++++++ 2 files changed, 23 insertions(+), 5 deletions(-) create mode 100644 tests/ui/coercion/constrain-expectation-in-arg.rs diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs index eebb0217990df..16d65726128c3 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs @@ -292,21 +292,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let coerce_error = self.coerce(provided_arg, checked_ty, coerced_ty, AllowTwoPhase::Yes, None).err(); - if coerce_error.is_some() { return Compatibility::Incompatible(coerce_error); } - // 3. Check if the formal type is a supertype of the checked one - // and register any such obligations for future type checks - let supertype_error = self.at(&self.misc(provided_arg.span), self.param_env).sup( + // 3. Check if the formal type is actually equal to the checked one + // and register any such obligations for future type checks. + let formal_ty_error = self.at(&self.misc(provided_arg.span), self.param_env).eq( DefineOpaqueTypes::Yes, formal_input_ty, coerced_ty, ); // If neither check failed, the types are compatible - match supertype_error { + match formal_ty_error { Ok(InferOk { obligations, value: () }) => { self.register_predicates(obligations); Compatibility::Compatible diff --git a/tests/ui/coercion/constrain-expectation-in-arg.rs b/tests/ui/coercion/constrain-expectation-in-arg.rs new file mode 100644 index 0000000000000..858c3a0bdb572 --- /dev/null +++ b/tests/ui/coercion/constrain-expectation-in-arg.rs @@ -0,0 +1,19 @@ +//@ check-pass + +trait Trait { + type Item; +} + +struct Struct, B> { + pub field: A, +} + +fn identity(x: T) -> T { + x +} + +fn test, B>(x: &Struct) { + let x: &Struct<_, _> = identity(x); +} + +fn main() {} From 95b9ecd6d671637e9e3db55ed31d06882d3cad4d Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sun, 25 Aug 2024 12:45:58 -0400 Subject: [PATCH 0316/2194] Inline expected_inputs_for_expected_output into check_argument_types/check_expr_struct_fields --- compiler/rustc_hir_typeck/src/callee.rs | 21 ++----- compiler/rustc_hir_typeck/src/expr.rs | 25 +++++--- .../rustc_hir_typeck/src/fn_ctxt/_impl.rs | 39 +------------ .../rustc_hir_typeck/src/fn_ctxt/checks.rs | 58 ++++++++++++++----- .../coercion/constrain-expectation-in-arg.rs | 5 ++ 5 files changed, 71 insertions(+), 77 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/callee.rs b/compiler/rustc_hir_typeck/src/callee.rs index a4eec5f05a8ff..9863d0364498e 100644 --- a/compiler/rustc_hir_typeck/src/callee.rs +++ b/compiler/rustc_hir_typeck/src/callee.rs @@ -503,18 +503,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let fn_sig = self.instantiate_binder_with_fresh_vars(call_expr.span, infer::FnCall, fn_sig); let fn_sig = self.normalize(call_expr.span, fn_sig); - // Call the generic checker. - let expected_arg_tys = self.expected_inputs_for_expected_output( - call_expr.span, - expected, - fn_sig.output(), - fn_sig.inputs(), - ); self.check_argument_types( call_expr.span, call_expr, fn_sig.inputs(), - expected_arg_tys, + fn_sig.output(), + expected, arg_exprs, fn_sig.c_variadic, TupleArgumentsFlag::DontTupleArguments, @@ -866,19 +860,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // don't know the full details yet (`Fn` vs `FnMut` etc), but we // do know the types expected for each argument and the return // type. - - let expected_arg_tys = self.expected_inputs_for_expected_output( - call_expr.span, - expected, - fn_sig.output(), - fn_sig.inputs(), - ); - self.check_argument_types( call_expr.span, call_expr, fn_sig.inputs(), - expected_arg_tys, + fn_sig.output(), + expected, arg_exprs, fn_sig.c_variadic, TupleArgumentsFlag::TupleArguments, diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index 1362d3626efd4..f0d47e584ac28 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -1673,15 +1673,22 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ) { let tcx = self.tcx; - let expected_inputs = - self.expected_inputs_for_expected_output(span, expected, adt_ty, &[adt_ty]); - let adt_ty_hint = if let Some(expected_inputs) = expected_inputs { - expected_inputs.get(0).cloned().unwrap_or(adt_ty) - } else { - adt_ty - }; - // re-link the regions that EIfEO can erase. - self.demand_eqtype(span, adt_ty_hint, adt_ty); + let adt_ty = self.resolve_vars_with_obligations(adt_ty); + let adt_ty_hint = expected.only_has_type(self).and_then(|expected| { + self.fudge_inference_if_ok(|| { + let ocx = ObligationCtxt::new(self); + ocx.sup(&self.misc(span), self.param_env, expected, adt_ty)?; + if !ocx.select_where_possible().is_empty() { + return Err(TypeError::Mismatch); + } + Ok(self.resolve_vars_if_possible(adt_ty)) + }) + .ok() + }); + if let Some(adt_ty_hint) = adt_ty_hint { + // re-link the variables that the fudging above can create. + self.demand_eqtype(span, adt_ty_hint, adt_ty); + } let ty::Adt(adt, args) = adt_ty.kind() else { span_bug!(span, "non-ADT passed to check_expr_struct_fields"); diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs index 97c27680959f0..19f7950287f93 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs @@ -20,7 +20,6 @@ use rustc_infer::infer::canonical::{Canonical, OriginalQueryValues, QueryRespons use rustc_infer::infer::{DefineOpaqueTypes, InferResult}; use rustc_lint::builtin::SELF_CONSTRUCTOR_FROM_OUTER_ITEM; use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow, AutoBorrowMutability}; -use rustc_middle::ty::error::TypeError; use rustc_middle::ty::fold::TypeFoldable; use rustc_middle::ty::visit::{TypeVisitable, TypeVisitableExt}; use rustc_middle::ty::{ @@ -36,7 +35,7 @@ use rustc_span::Span; use rustc_target::abi::FieldIdx; use rustc_trait_selection::error_reporting::infer::need_type_info::TypeAnnotationNeeded; use rustc_trait_selection::traits::{ - self, NormalizeExt, ObligationCauseCode, ObligationCtxt, StructurallyNormalizeExt, + self, NormalizeExt, ObligationCauseCode, StructurallyNormalizeExt, }; use tracing::{debug, instrument}; @@ -689,42 +688,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { vec![ty_error; len] } - /// Unifies the output type with the expected type early, for more coercions - /// and forward type information on the input expressions. - #[instrument(skip(self, call_span), level = "debug")] - pub(crate) fn expected_inputs_for_expected_output( - &self, - call_span: Span, - expected_ret: Expectation<'tcx>, - formal_ret: Ty<'tcx>, - formal_args: &[Ty<'tcx>], - ) -> Option>> { - let formal_ret = self.resolve_vars_with_obligations(formal_ret); - let ret_ty = expected_ret.only_has_type(self)?; - - let expect_args = self - .fudge_inference_if_ok(|| { - let ocx = ObligationCtxt::new(self); - - // Attempt to apply a subtyping relationship between the formal - // return type (likely containing type variables if the function - // is polymorphic) and the expected return type. - // No argument expectations are produced if unification fails. - let origin = self.misc(call_span); - ocx.sup(&origin, self.param_env, ret_ty, formal_ret)?; - if !ocx.select_where_possible().is_empty() { - return Err(TypeError::Mismatch); - } - - // Record all the argument types, with the args - // produced from the above subtyping unification. - Ok(Some(formal_args.iter().map(|&ty| self.resolve_vars_if_possible(ty)).collect())) - }) - .unwrap_or_default(); - debug!(?formal_args, ?formal_ret, ?expect_args, ?expected_ret); - expect_args - } - pub(crate) fn resolve_lang_item_path( &self, lang_item: hir::LangItem, diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs index 16d65726128c3..bdf84f332166d 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs @@ -17,6 +17,7 @@ use rustc_hir_analysis::hir_ty_lowering::HirTyLowerer; use rustc_index::IndexVec; use rustc_infer::infer::{DefineOpaqueTypes, InferOk, TypeTrace}; use rustc_middle::ty::adjustment::AllowTwoPhase; +use rustc_middle::ty::error::TypeError; use rustc_middle::ty::visit::TypeVisitableExt; use rustc_middle::ty::{self, IsSuggestable, Ty, TyCtxt}; use rustc_middle::{bug, span_bug}; @@ -25,7 +26,7 @@ use rustc_span::symbol::{kw, Ident}; use rustc_span::{sym, Span, DUMMY_SP}; use rustc_trait_selection::error_reporting::infer::{FailureCode, ObligationCauseExt}; use rustc_trait_selection::infer::InferCtxtExt; -use rustc_trait_selection::traits::{self, ObligationCauseCode, SelectionContext}; +use rustc_trait_selection::traits::{self, ObligationCauseCode, ObligationCtxt, SelectionContext}; use tracing::debug; use {rustc_ast as ast, rustc_hir as hir}; @@ -124,6 +125,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }; if let Err(guar) = has_error { let err_inputs = self.err_args(args_no_rcvr.len(), guar); + let err_output = Ty::new_error(self.tcx, guar); let err_inputs = match tuple_arguments { DontTupleArguments => err_inputs, @@ -134,28 +136,23 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { sp, expr, &err_inputs, - None, + err_output, + NoExpectation, args_no_rcvr, false, tuple_arguments, method.ok().map(|method| method.def_id), ); - return Ty::new_error(self.tcx, guar); + return err_output; } let method = method.unwrap(); - // HACK(eddyb) ignore self in the definition (see above). - let expected_input_tys = self.expected_inputs_for_expected_output( - sp, - expected, - method.sig.output(), - &method.sig.inputs()[1..], - ); self.check_argument_types( sp, expr, &method.sig.inputs()[1..], - expected_input_tys, + method.sig.output(), + expected, args_no_rcvr, method.sig.c_variadic, tuple_arguments, @@ -175,8 +172,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { call_expr: &'tcx hir::Expr<'tcx>, // Types (as defined in the *signature* of the target function) formal_input_tys: &[Ty<'tcx>], - // More specific expected types, after unifying with caller output types - expected_input_tys: Option>>, + formal_output: Ty<'tcx>, + // Expected output from the parent expression or statement + expectation: Expectation<'tcx>, // The expressions for each provided argument provided_args: &'tcx [hir::Expr<'tcx>], // Whether the function is variadic, for example when imported from C @@ -210,6 +208,40 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ); } + // First, let's unify the formal method signature with the expectation eagerly. + // We use this to guide coercion inference; it's output is "fudged" which means + // any remaining type variables are assigned to new, unrelated variables. This + // is because the inference guidance here is only speculative. + let formal_output = self.resolve_vars_with_obligations(formal_output); + let expected_input_tys: Option> = expectation + .only_has_type(self) + .and_then(|expected_output| { + self.fudge_inference_if_ok(|| { + let ocx = ObligationCtxt::new(self); + + // Attempt to apply a subtyping relationship between the formal + // return type (likely containing type variables if the function + // is polymorphic) and the expected return type. + // No argument expectations are produced if unification fails. + let origin = self.misc(call_span); + ocx.sup(&origin, self.param_env, expected_output, formal_output)?; + if !ocx.select_where_possible().is_empty() { + return Err(TypeError::Mismatch); + } + + // Record all the argument types, with the args + // produced from the above subtyping unification. + Ok(Some( + formal_input_tys + .iter() + .map(|&ty| self.resolve_vars_if_possible(ty)) + .collect(), + )) + }) + .ok() + }) + .unwrap_or_default(); + let mut err_code = E0061; // If the arguments should be wrapped in a tuple (ex: closures), unwrap them here diff --git a/tests/ui/coercion/constrain-expectation-in-arg.rs b/tests/ui/coercion/constrain-expectation-in-arg.rs index 858c3a0bdb572..c515dedc4bb4d 100644 --- a/tests/ui/coercion/constrain-expectation-in-arg.rs +++ b/tests/ui/coercion/constrain-expectation-in-arg.rs @@ -1,5 +1,10 @@ //@ check-pass +// Regression test for for #129286. +// Makes sure that we don't have unconstrained type variables that come from +// bivariant type parameters due to the way that we construct expectation types +// when checking call expressions in HIR typeck. + trait Trait { type Item; } From f68f66538a88a377b3510723950e97373796c5c8 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Sat, 24 Aug 2024 01:44:52 +0000 Subject: [PATCH 0317/2194] Create opaque definitions in resolver. --- compiler/rustc_ast/src/visit.rs | 16 ++- compiler/rustc_ast_lowering/src/lib.rs | 30 +---- .../rustc_ast_passes/src/ast_validation.rs | 2 +- compiler/rustc_resolve/src/def_collector.rs | 116 ++++++++++-------- compiler/rustc_resolve/src/late.rs | 2 +- ...await.b-{closure#0}.coroutine_resume.0.mir | 8 +- .../print/coroutine-print-verbose-1.stderr | 6 +- .../ty-outlives/impl-trait-captures.stderr | 8 +- 8 files changed, 91 insertions(+), 97 deletions(-) diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs index fe07ec48f1f2b..7b041768983e6 100644 --- a/compiler/rustc_ast/src/visit.rs +++ b/compiler/rustc_ast/src/visit.rs @@ -69,14 +69,14 @@ pub enum FnKind<'a> { Fn(FnCtxt, Ident, &'a FnSig, &'a Visibility, &'a Generics, Option<&'a Block>), /// E.g., `|x, y| body`. - Closure(&'a ClosureBinder, &'a FnDecl, &'a Expr), + Closure(&'a ClosureBinder, &'a Option, &'a FnDecl, &'a Expr), } impl<'a> FnKind<'a> { pub fn header(&self) -> Option<&'a FnHeader> { match *self { FnKind::Fn(_, _, sig, _, _, _) => Some(&sig.header), - FnKind::Closure(_, _, _) => None, + FnKind::Closure(..) => None, } } @@ -90,7 +90,7 @@ impl<'a> FnKind<'a> { pub fn decl(&self) -> &'a FnDecl { match self { FnKind::Fn(_, _, sig, _, _, _) => &sig.decl, - FnKind::Closure(_, decl, _) => decl, + FnKind::Closure(_, _, decl, _) => decl, } } @@ -839,7 +839,7 @@ pub fn walk_fn<'a, V: Visitor<'a>>(visitor: &mut V, kind: FnKind<'a>) -> V::Resu try_visit!(walk_fn_decl(visitor, decl)); visit_opt!(visitor, visit_block, body); } - FnKind::Closure(binder, decl, body) => { + FnKind::Closure(binder, _coroutine_kind, decl, body) => { try_visit!(visitor.visit_closure_binder(binder)); try_visit!(walk_fn_decl(visitor, decl)); try_visit!(visitor.visit_expr(body)); @@ -1107,7 +1107,7 @@ pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) -> V ExprKind::Closure(box Closure { binder, capture_clause, - coroutine_kind: _, + coroutine_kind, constness: _, movability: _, fn_decl, @@ -1116,7 +1116,11 @@ pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) -> V fn_arg_span: _, }) => { try_visit!(visitor.visit_capture_by(capture_clause)); - try_visit!(visitor.visit_fn(FnKind::Closure(binder, fn_decl, body), *span, *id)) + try_visit!(visitor.visit_fn( + FnKind::Closure(binder, coroutine_kind, fn_decl, body), + *span, + *id + )) } ExprKind::Block(block, opt_label) => { visit_opt!(visitor, visit_label, opt_label); diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index bcc2c29a2ff79..cc91e55cb07e6 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -45,7 +45,6 @@ use std::collections::hash_map::Entry; use rustc_ast::node_id::NodeMap; use rustc_ast::ptr::P; use rustc_ast::{self as ast, *}; -use rustc_ast_pretty::pprust; use rustc_data_structures::captures::Captures; use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::fx::FxIndexSet; @@ -1399,24 +1398,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { self.tcx.dcx().emit_err(errors::NoPreciseCapturesOnApit { span }); } - let span = t.span; - - // HACK: pprust breaks strings with newlines when the type - // gets too long. We don't want these to show up in compiler - // output or built artifacts, so replace them here... - // Perhaps we should instead format APITs more robustly. - let ident = Ident::from_str_and_span( - &pprust::ty_to_string(t).replace('\n', " "), - span, - ); - - self.create_def( - self.current_hir_id_owner.def_id, // FIXME: should this use self.current_def_id_parent? - *def_node_id, - ident.name, - DefKind::TyParam, - span, - ); + let def_id = self.local_def_id(*def_node_id); + let name = self.tcx.item_name(def_id.to_def_id()); + let ident = Ident::new(name, span); let (param, bounds, path) = self.lower_universal_param_and_bounds( *def_node_id, span, @@ -1618,13 +1602,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { opaque_ty_span: Span, lower_item_bounds: impl FnOnce(&mut Self) -> &'hir [hir::GenericBound<'hir>], ) -> hir::TyKind<'hir> { - let opaque_ty_def_id = self.create_def( - self.current_hir_id_owner.def_id, // FIXME: should this use self.current_def_id_parent? - opaque_ty_node_id, - kw::Empty, - DefKind::OpaqueTy, - opaque_ty_span, - ); + let opaque_ty_def_id = self.local_def_id(opaque_ty_node_id); debug!(?opaque_ty_def_id); // Map from captured (old) lifetime to synthetic (new) lifetime. diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index a9b65456b8c63..ed9672a9e79b3 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -1485,7 +1485,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { let disallowed = (!tilde_const_allowed).then(|| match fk { FnKind::Fn(_, ident, _, _, _, _) => TildeConstReason::Function { ident: ident.span }, - FnKind::Closure(_, _, _) => TildeConstReason::Closure, + FnKind::Closure(..) => TildeConstReason::Closure, }); self.with_tilde_const(disallowed, |this| visit::walk_fn(this, fk)); } diff --git a/compiler/rustc_resolve/src/def_collector.rs b/compiler/rustc_resolve/src/def_collector.rs index 3595db78e9328..a70d51606f7d3 100644 --- a/compiler/rustc_resolve/src/def_collector.rs +++ b/compiler/rustc_resolve/src/def_collector.rs @@ -2,6 +2,7 @@ use std::mem; use rustc_ast::visit::FnKind; use rustc_ast::*; +use rustc_ast_pretty::pprust; use rustc_expand::expand::AstFragment; use rustc_hir as hir; use rustc_hir::def::{CtorKind, CtorOf, DefKind}; @@ -120,8 +121,6 @@ impl<'a, 'b, 'tcx> DefCollector<'a, 'b, 'tcx> { impl<'a, 'b, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'b, 'tcx> { fn visit_item(&mut self, i: &'a Item) { - debug!("visit_item: {:?}", i); - // Pick the def data. This need not be unique, but the more // information we encapsulate into, the better let mut opt_macro_data = None; @@ -183,38 +182,51 @@ impl<'a, 'b, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'b, 'tcx> { } fn visit_fn(&mut self, fn_kind: FnKind<'a>, span: Span, _: NodeId) { - if let FnKind::Fn(_, _, sig, _, generics, body) = fn_kind { - match sig.header.coroutine_kind { - Some(coroutine_kind) => { - self.visit_generics(generics); - - // For async functions, we need to create their inner defs inside of a - // closure to match their desugared representation. Besides that, - // we must mirror everything that `visit::walk_fn` below does. - self.visit_fn_header(&sig.header); - for param in &sig.decl.inputs { - self.visit_param(param); - } - self.visit_fn_ret_ty(&sig.decl.output); - // If this async fn has no body (i.e. it's an async fn signature in a trait) - // then the closure_def will never be used, and we should avoid generating a - // def-id for it. - if let Some(body) = body { - let closure_def = self.create_def( - coroutine_kind.closure_id(), - kw::Empty, - DefKind::Closure, - span, - ); - self.with_parent(closure_def, |this| this.visit_block(body)); - } - return; + match fn_kind { + FnKind::Fn(_ctxt, _ident, FnSig { header, decl, span: _ }, _vis, generics, body) + if let Some(coroutine_kind) = header.coroutine_kind => + { + self.visit_fn_header(header); + self.visit_generics(generics); + + // For async functions, we need to create their inner defs inside of a + // closure to match their desugared representation. Besides that, + // we must mirror everything that `visit::walk_fn` below does. + let FnDecl { inputs, output } = &**decl; + for param in inputs { + self.visit_param(param); + } + + let (return_id, return_span) = coroutine_kind.return_id(); + let return_def = + self.create_def(return_id, kw::Empty, DefKind::OpaqueTy, return_span); + self.with_parent(return_def, |this| this.visit_fn_ret_ty(output)); + + // If this async fn has no body (i.e. it's an async fn signature in a trait) + // then the closure_def will never be used, and we should avoid generating a + // def-id for it. + if let Some(body) = body { + let closure_def = self.create_def( + coroutine_kind.closure_id(), + kw::Empty, + DefKind::Closure, + span, + ); + self.with_parent(closure_def, |this| this.visit_block(body)); } - None => {} } - } + FnKind::Closure(binder, Some(coroutine_kind), decl, body) => { + self.visit_closure_binder(binder); + visit::walk_fn_decl(self, decl); - visit::walk_fn(self, fn_kind); + // Async closures desugar to closures inside of closures, so + // we must create two defs. + let coroutine_def = + self.create_def(coroutine_kind.closure_id(), kw::Empty, DefKind::Closure, span); + self.with_parent(coroutine_def, |this| visit::walk_expr(this, body)); + } + _ => visit::walk_fn(self, fn_kind), + } } fn visit_use_tree(&mut self, use_tree: &'a UseTree, id: NodeId, _nested: bool) { @@ -334,27 +346,7 @@ impl<'a, 'b, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'b, 'tcx> { fn visit_expr(&mut self, expr: &'a Expr) { let parent_def = match expr.kind { ExprKind::MacCall(..) => return self.visit_macro_invoc(expr.id), - ExprKind::Closure(ref closure) => { - // Async closures desugar to closures inside of closures, so - // we must create two defs. - let closure_def = self.create_def(expr.id, kw::Empty, DefKind::Closure, expr.span); - match closure.coroutine_kind { - Some(coroutine_kind) => { - self.with_parent(closure_def, |this| { - let coroutine_def = this.create_def( - coroutine_kind.closure_id(), - kw::Empty, - DefKind::Closure, - expr.span, - ); - this.with_parent(coroutine_def, |this| visit::walk_expr(this, expr)); - }); - return; - } - None => closure_def, - } - } - ExprKind::Gen(_, _, _, _) => { + ExprKind::Closure(..) | ExprKind::Gen(..) => { self.create_def(expr.id, kw::Empty, DefKind::Closure, expr.span) } ExprKind::ConstBlock(ref constant) => { @@ -381,6 +373,26 @@ impl<'a, 'b, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'b, 'tcx> { TyKind::MacCall(..) => self.visit_macro_invoc(ty.id), // Anonymous structs or unions are visited later after defined. TyKind::AnonStruct(..) | TyKind::AnonUnion(..) => {} + TyKind::ImplTrait(id, _) => { + // HACK: pprust breaks strings with newlines when the type + // gets too long. We don't want these to show up in compiler + // output or built artifacts, so replace them here... + // Perhaps we should instead format APITs more robustly. + let name = Symbol::intern(&pprust::ty_to_string(ty).replace('\n', " ")); + let kind = match self.impl_trait_context { + ImplTraitContext::Universal => DefKind::TyParam, + ImplTraitContext::Existential => DefKind::OpaqueTy, + }; + let id = self.create_def(*id, name, kind, ty.span); + match self.impl_trait_context { + // Do not nest APIT, as we desugar them as `impl_trait: bounds`, + // so the `impl_trait` node is not a parent to `bounds`. + ImplTraitContext::Universal => visit::walk_ty(self, ty), + ImplTraitContext::Existential => { + self.with_parent(id, |this| visit::walk_ty(this, ty)) + } + }; + } _ => visit::walk_ty(self, ty), } } diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 40fdb01a72c0e..af3d16aa4857f 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -1010,7 +1010,7 @@ impl<'a: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast, this.in_func_body = previous_state; } } - FnKind::Closure(binder, declaration, body) => { + FnKind::Closure(binder, _, declaration, body) => { this.visit_closure_binder(binder); this.with_lifetime_rib( diff --git a/tests/mir-opt/building/async_await.b-{closure#0}.coroutine_resume.0.mir b/tests/mir-opt/building/async_await.b-{closure#0}.coroutine_resume.0.mir index c1c2fdcfa949e..109a41d1ef907 100644 --- a/tests/mir-opt/building/async_await.b-{closure#0}.coroutine_resume.0.mir +++ b/tests/mir-opt/building/async_await.b-{closure#0}.coroutine_resume.0.mir @@ -3,14 +3,14 @@ field_tys: { _0: CoroutineSavedTy { ty: Coroutine( - DefId(0:4 ~ async_await[ccf8]::a::{closure#0}), + DefId(0:5 ~ async_await[ccf8]::a::{closure#0}), [ (), std::future::ResumeTy, (), (), CoroutineWitness( - DefId(0:4 ~ async_await[ccf8]::a::{closure#0}), + DefId(0:5 ~ async_await[ccf8]::a::{closure#0}), [], ), (), @@ -24,14 +24,14 @@ }, _1: CoroutineSavedTy { ty: Coroutine( - DefId(0:4 ~ async_await[ccf8]::a::{closure#0}), + DefId(0:5 ~ async_await[ccf8]::a::{closure#0}), [ (), std::future::ResumeTy, (), (), CoroutineWitness( - DefId(0:4 ~ async_await[ccf8]::a::{closure#0}), + DefId(0:5 ~ async_await[ccf8]::a::{closure#0}), [], ), (), diff --git a/tests/ui/coroutine/print/coroutine-print-verbose-1.stderr b/tests/ui/coroutine/print/coroutine-print-verbose-1.stderr index 934ab08cf178d..daf88fc1f2390 100644 --- a/tests/ui/coroutine/print/coroutine-print-verbose-1.stderr +++ b/tests/ui/coroutine/print/coroutine-print-verbose-1.stderr @@ -10,7 +10,7 @@ note: coroutine is not `Send` as this value is used across a yield --> $DIR/coroutine-print-verbose-1.rs:35:9 | LL | let _non_send_gen = make_non_send_coroutine(); - | ------------- has type `Opaque(DefId(0:34 ~ coroutine_print_verbose_1[75fb]::make_non_send_coroutine::{opaque#0}), [])` which is not `Send` + | ------------- has type `Opaque(DefId(0:24 ~ coroutine_print_verbose_1[75fb]::make_non_send_coroutine::{opaque#0}), [])` which is not `Send` LL | yield; | ^^^^^ yield occurs here, with `_non_send_gen` maybe used later note: required by a bound in `require_send` @@ -33,12 +33,12 @@ note: required because it's used within this coroutine | LL | #[coroutine] || { | ^^ -note: required because it appears within the type `Opaque(DefId(0:35 ~ coroutine_print_verbose_1[75fb]::make_gen2::{opaque#0}), [Arc>])` +note: required because it appears within the type `Opaque(DefId(0:29 ~ coroutine_print_verbose_1[75fb]::make_gen2::{opaque#0}), [Arc>])` --> $DIR/coroutine-print-verbose-1.rs:41:30 | LL | pub fn make_gen2(t: T) -> impl Coroutine { | ^^^^^^^^^^^^^^^^^^^^^^^^^^ -note: required because it appears within the type `Opaque(DefId(0:36 ~ coroutine_print_verbose_1[75fb]::make_non_send_coroutine2::{opaque#0}), [])` +note: required because it appears within the type `Opaque(DefId(0:32 ~ coroutine_print_verbose_1[75fb]::make_non_send_coroutine2::{opaque#0}), [])` --> $DIR/coroutine-print-verbose-1.rs:47:34 | LL | fn make_non_send_coroutine2() -> impl Coroutine>> { diff --git a/tests/ui/nll/ty-outlives/impl-trait-captures.stderr b/tests/ui/nll/ty-outlives/impl-trait-captures.stderr index 3ceefbc40660c..87bbd50a15c27 100644 --- a/tests/ui/nll/ty-outlives/impl-trait-captures.stderr +++ b/tests/ui/nll/ty-outlives/impl-trait-captures.stderr @@ -1,16 +1,16 @@ -error[E0700]: hidden type for `Opaque(DefId(0:13 ~ impl_trait_captures[aeb9]::foo::{opaque#0}), ['a/#0, T, 'a/#0])` captures lifetime that does not appear in bounds +error[E0700]: hidden type for `Opaque(DefId(0:11 ~ impl_trait_captures[aeb9]::foo::{opaque#0}), ['a/#0, T, 'a/#0])` captures lifetime that does not appear in bounds --> $DIR/impl-trait-captures.rs:11:5 | LL | fn foo<'a, T>(x: &T) -> impl Foo<'a> { | -- ------------ opaque type defined here | | - | hidden type `&ReLateParam(DefId(0:8 ~ impl_trait_captures[aeb9]::foo), BrNamed(DefId(0:12 ~ impl_trait_captures[aeb9]::foo::'_), '_)) T` captures the anonymous lifetime defined here + | hidden type `&ReLateParam(DefId(0:8 ~ impl_trait_captures[aeb9]::foo), BrNamed(DefId(0:13 ~ impl_trait_captures[aeb9]::foo::'_), '_)) T` captures the anonymous lifetime defined here LL | x | ^ | -help: add a `use<...>` bound to explicitly capture `ReLateParam(DefId(0:8 ~ impl_trait_captures[aeb9]::foo), BrNamed(DefId(0:12 ~ impl_trait_captures[aeb9]::foo::'_), '_))` +help: add a `use<...>` bound to explicitly capture `ReLateParam(DefId(0:8 ~ impl_trait_captures[aeb9]::foo), BrNamed(DefId(0:13 ~ impl_trait_captures[aeb9]::foo::'_), '_))` | -LL | fn foo<'a, T>(x: &T) -> impl Foo<'a> + use<'a, ReLateParam(DefId(0:8 ~ impl_trait_captures[aeb9]::foo), BrNamed(DefId(0:12 ~ impl_trait_captures[aeb9]::foo::'_), '_)), T> { +LL | fn foo<'a, T>(x: &T) -> impl Foo<'a> + use<'a, ReLateParam(DefId(0:8 ~ impl_trait_captures[aeb9]::foo), BrNamed(DefId(0:13 ~ impl_trait_captures[aeb9]::foo::'_), '_)), T> { | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ error: aborting due to 1 previous error From 121e9f4cc86104da0209afd3f681dc82da9e3928 Mon Sep 17 00:00:00 2001 From: The 8472 Date: Fri, 2 Sep 2022 20:15:26 +0200 Subject: [PATCH 0318/2194] Add rust.randomize-layout config to build artifacts with -Zrandomize-layout Additionally teach compiletest to ignore tests that rely on deterministic layout. Tests themselves aren't built with randomization but they can still observe slight changes in std or rustc --- config.example.toml | 3 +++ src/bootstrap/src/core/build_steps/test.rs | 3 +++ src/bootstrap/src/core/builder.rs | 4 ++++ src/bootstrap/src/core/config/config.rs | 7 +++++++ src/tools/compiletest/src/command-list.rs | 1 + src/tools/compiletest/src/common.rs | 3 +++ src/tools/compiletest/src/header/needs.rs | 5 +++++ src/tools/compiletest/src/lib.rs | 6 ++++++ 8 files changed, 32 insertions(+) diff --git a/config.example.toml b/config.example.toml index f1dc32234ccf2..897857f286c11 100644 --- a/config.example.toml +++ b/config.example.toml @@ -512,6 +512,9 @@ # are disabled statically" because `max_level_info` is enabled, set this value to `true`. #debug-logging = rust.debug-assertions (boolean) +# Whether or not to build rustc, tools and the libraries with randomized type layout +#randomize-layout = false + # Whether or not overflow checks are enabled for the compiler and standard # library. # diff --git a/src/bootstrap/src/core/build_steps/test.rs b/src/bootstrap/src/core/build_steps/test.rs index 84a6b26a491ed..a8e1254047363 100644 --- a/src/bootstrap/src/core/build_steps/test.rs +++ b/src/bootstrap/src/core/build_steps/test.rs @@ -1810,6 +1810,9 @@ NOTE: if you're sure you want to do this, please open an issue as to why. In the if builder.config.rust_optimize_tests { cmd.arg("--optimize-tests"); } + if builder.config.rust_randomize_layout { + cmd.arg("--rust-randomized-layout"); + } if builder.config.cmd.only_modified() { cmd.arg("--only-modified"); } diff --git a/src/bootstrap/src/core/builder.rs b/src/bootstrap/src/core/builder.rs index ff0d1f3a725d2..5df962e939ed6 100644 --- a/src/bootstrap/src/core/builder.rs +++ b/src/bootstrap/src/core/builder.rs @@ -1614,6 +1614,10 @@ impl<'a> Builder<'a> { rustflags.arg("-Csymbol-mangling-version=legacy"); } + if self.config.rust_randomize_layout { + rustflags.arg("-Zrandomize-layout"); + } + // Enable compile-time checking of `cfg` names, values and Cargo `features`. // // Note: `std`, `alloc` and `core` imports some dependencies by #[path] (like diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs index bdfee55d8d183..547e338e049fc 100644 --- a/src/bootstrap/src/core/config/config.rs +++ b/src/bootstrap/src/core/config/config.rs @@ -280,6 +280,7 @@ pub struct Config { pub rust_codegen_backends: Vec, pub rust_verify_llvm_ir: bool, pub rust_thin_lto_import_instr_limit: Option, + pub rust_randomize_layout: bool, pub rust_remap_debuginfo: bool, pub rust_new_symbol_mangling: Option, pub rust_profile_use: Option, @@ -1088,6 +1089,7 @@ define_config! { codegen_units: Option = "codegen-units", codegen_units_std: Option = "codegen-units-std", debug_assertions: Option = "debug-assertions", + randomize_layout: Option = "randomize-layout", debug_assertions_std: Option = "debug-assertions-std", overflow_checks: Option = "overflow-checks", overflow_checks_std: Option = "overflow-checks-std", @@ -1179,6 +1181,7 @@ impl Config { backtrace: true, rust_optimize: RustOptimize::Bool(true), rust_optimize_tests: true, + rust_randomize_layout: false, submodules: None, docs: true, docs_minification: true, @@ -1629,6 +1632,7 @@ impl Config { backtrace, incremental, parallel_compiler, + randomize_layout, default_linker, channel, description, @@ -1718,6 +1722,7 @@ impl Config { set(&mut config.lld_mode, lld_mode); set(&mut config.llvm_bitcode_linker_enabled, llvm_bitcode_linker); + config.rust_randomize_layout = randomize_layout.unwrap_or_default(); config.llvm_tools_enabled = llvm_tools.unwrap_or(true); config.rustc_parallel = parallel_compiler.unwrap_or(config.channel == "dev" || config.channel == "nightly"); @@ -2889,6 +2894,7 @@ fn check_incompatible_options_for_ci_rustc( let Rust { // Following options are the CI rustc incompatible ones. optimize, + randomize_layout, debug_logging, debuginfo_level_rustc, llvm_tools, @@ -2953,6 +2959,7 @@ fn check_incompatible_options_for_ci_rustc( // otherwise, we just print a warning with `warn` macro. err!(current_rust_config.optimize, optimize); + err!(current_rust_config.randomize_layout, randomize_layout); err!(current_rust_config.debug_logging, debug_logging); err!(current_rust_config.debuginfo_level_rustc, debuginfo_level_rustc); err!(current_rust_config.rpath, rpath); diff --git a/src/tools/compiletest/src/command-list.rs b/src/tools/compiletest/src/command-list.rs index a559d6f81a240..865aa76ddb0c7 100644 --- a/src/tools/compiletest/src/command-list.rs +++ b/src/tools/compiletest/src/command-list.rs @@ -136,6 +136,7 @@ const KNOWN_DIRECTIVE_NAMES: &[&str] = &[ "min-llvm-version", "min-system-llvm-version", "needs-asm-support", + "needs-deterministic-layouts", "needs-dlltool", "needs-dynamic-linking", "needs-force-clang-based-tests", diff --git a/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs index 5831f7c3cf283..773d795f75a72 100644 --- a/src/tools/compiletest/src/common.rs +++ b/src/tools/compiletest/src/common.rs @@ -274,6 +274,9 @@ pub struct Config { /// Flags to pass to the compiler when building for the target pub target_rustcflags: Vec, + /// Whether the compiler and stdlib has been built with randomized struct layouts + pub rust_randomized_layout: bool, + /// Whether tests should be optimized by default. Individual test-suites and test files may /// override this setting. pub optimize_tests: bool, diff --git a/src/tools/compiletest/src/header/needs.rs b/src/tools/compiletest/src/header/needs.rs index 72b1b9c6d480a..e903f60ceb37f 100644 --- a/src/tools/compiletest/src/header/needs.rs +++ b/src/tools/compiletest/src/header/needs.rs @@ -134,6 +134,11 @@ pub(super) fn handle_needs( condition: config.target_cfg().relocation_model == "pic", ignore_reason: "ignored on targets without PIC relocation model", }, + Need { + name: "needs-deterministic-layouts", + condition: !config.rust_randomized_layout, + ignore_reason: "ignored when randomizing layouts", + }, Need { name: "needs-wasmtime", condition: config.runner.as_ref().is_some_and(|r| r.contains("wasmtime")), diff --git a/src/tools/compiletest/src/lib.rs b/src/tools/compiletest/src/lib.rs index 7018362af5410..5402e69bc664e 100644 --- a/src/tools/compiletest/src/lib.rs +++ b/src/tools/compiletest/src/lib.rs @@ -99,6 +99,11 @@ pub fn parse_config(args: Vec) -> Config { ) .optmulti("", "host-rustcflags", "flags to pass to rustc for host", "FLAGS") .optmulti("", "target-rustcflags", "flags to pass to rustc for target", "FLAGS") + .optflag( + "", + "rust-randomized-layout", + "set this when rustc/stdlib were compiled with randomized layouts", + ) .optflag("", "optimize-tests", "run tests with optimizations enabled") .optflag("", "verbose", "run tests verbosely, showing all output") .optflag( @@ -286,6 +291,7 @@ pub fn parse_config(args: Vec) -> Config { host_rustcflags: matches.opt_strs("host-rustcflags"), target_rustcflags: matches.opt_strs("target-rustcflags"), optimize_tests: matches.opt_present("optimize-tests"), + rust_randomized_layout: matches.opt_present("rust-randomized-layout"), target, host: opt_str2(matches.opt_str("host")), cdb, From f3bc08adbd120a12571373b982b39049cbbed93f Mon Sep 17 00:00:00 2001 From: The 8472 Date: Fri, 2 Sep 2022 20:15:53 +0200 Subject: [PATCH 0319/2194] ignore/fix layout-sensitive tests --- tests/codegen/issues/issue-86106.rs | 1 + tests/codegen/mem-replace-big-type.rs | 1 + tests/codegen/slice-iter-nonnull.rs | 1 + tests/codegen/vecdeque-drain.rs | 1 + .../mir-opt/pre-codegen/issue_117368_print_invalid_constant.rs | 1 + tests/ui/stats/hir-stats.rs | 3 +++ tests/ui/structs-enums/type-sizes.rs | 1 + 7 files changed, 9 insertions(+) diff --git a/tests/codegen/issues/issue-86106.rs b/tests/codegen/issues/issue-86106.rs index e8164c5c38021..8d1ce116d26cc 100644 --- a/tests/codegen/issues/issue-86106.rs +++ b/tests/codegen/issues/issue-86106.rs @@ -1,5 +1,6 @@ //@ only-64bit llvm appears to use stores instead of memset on 32bit //@ compile-flags: -C opt-level=3 -Z merge-functions=disabled +//@ needs-deterministic-layouts // The below two functions ensure that both `String::new()` and `"".to_string()` // produce the identical code. diff --git a/tests/codegen/mem-replace-big-type.rs b/tests/codegen/mem-replace-big-type.rs index d5eadda4469f6..e62f1a953dfd0 100644 --- a/tests/codegen/mem-replace-big-type.rs +++ b/tests/codegen/mem-replace-big-type.rs @@ -5,6 +5,7 @@ //@ compile-flags: -C no-prepopulate-passes -Zinline-mir=no //@ ignore-debug: precondition checks in ptr::read make them a bad candidate for MIR inlining +//@ needs-deterministic-layouts #![crate_type = "lib"] diff --git a/tests/codegen/slice-iter-nonnull.rs b/tests/codegen/slice-iter-nonnull.rs index c960688b00c18..eda807d36822d 100644 --- a/tests/codegen/slice-iter-nonnull.rs +++ b/tests/codegen/slice-iter-nonnull.rs @@ -1,4 +1,5 @@ //@ compile-flags: -O +//@ needs-deterministic-layouts #![crate_type = "lib"] #![feature(exact_size_is_empty)] diff --git a/tests/codegen/vecdeque-drain.rs b/tests/codegen/vecdeque-drain.rs index 31fcf035f1154..fca1ed367e6fc 100644 --- a/tests/codegen/vecdeque-drain.rs +++ b/tests/codegen/vecdeque-drain.rs @@ -1,6 +1,7 @@ // Check that draining at the front or back doesn't copy memory. //@ compile-flags: -O +//@ needs-deterministic-layouts //@ ignore-debug: FIXME: checks for call detect scoped noalias metadata #![crate_type = "lib"] diff --git a/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.rs b/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.rs index c92424f298314..08347f71b4239 100644 --- a/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.rs +++ b/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.rs @@ -1,3 +1,4 @@ +//@needs-deterministic-layouts // Verify that we do not ICE when printing an invalid constant. // EMIT_MIR_FOR_EACH_BIT_WIDTH // EMIT_MIR_FOR_EACH_PANIC_STRATEGY diff --git a/tests/ui/stats/hir-stats.rs b/tests/ui/stats/hir-stats.rs index 249413d80e82a..7c5da8cf554b6 100644 --- a/tests/ui/stats/hir-stats.rs +++ b/tests/ui/stats/hir-stats.rs @@ -1,12 +1,15 @@ //@ check-pass //@ compile-flags: -Zhir-stats //@ only-x86_64 +// layout randomization affects the hir stat output +//@ needs-deterministic-layouts // Type layouts sometimes change. When that happens, until the next bootstrap // bump occurs, stage1 and stage2 will give different outputs for this test. // Add an `ignore-stage1` comment marker to work around that problem during // that time. + // The aim here is to include at least one of every different type of top-level // AST/HIR node reported by `-Zhir-stats`. diff --git a/tests/ui/structs-enums/type-sizes.rs b/tests/ui/structs-enums/type-sizes.rs index 9c933a9ef1c4f..5ca9c8678b790 100644 --- a/tests/ui/structs-enums/type-sizes.rs +++ b/tests/ui/structs-enums/type-sizes.rs @@ -1,4 +1,5 @@ //@ run-pass +//@ needs-deterministic-layouts #![allow(non_camel_case_types)] #![allow(dead_code)] From 5bf8eeb9f34a738ebf49328c08d40951374cce18 Mon Sep 17 00:00:00 2001 From: The 8472 Date: Fri, 2 Sep 2022 20:17:20 +0200 Subject: [PATCH 0320/2194] disable size asserts in the compiler when randomizing layouts --- Cargo.lock | 1 + compiler/rustc/Cargo.toml | 1 + compiler/rustc_driver_impl/Cargo.toml | 5 +++++ compiler/rustc_index/Cargo.toml | 1 + compiler/rustc_index/src/lib.rs | 11 +++++++++++ compiler/rustc_middle/Cargo.toml | 1 + compiler/rustc_middle/src/query/plumbing.rs | 1 + src/bootstrap/src/lib.rs | 3 +++ 8 files changed, 24 insertions(+) diff --git a/Cargo.lock b/Cargo.lock index 6ea4cd8f5aca4..ec3b95d0d98fa 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3569,6 +3569,7 @@ dependencies = [ "rustc_hir_pretty", "rustc_hir_typeck", "rustc_incremental", + "rustc_index", "rustc_infer", "rustc_interface", "rustc_lint", diff --git a/compiler/rustc/Cargo.toml b/compiler/rustc/Cargo.toml index 5008069542f1f..a2fc9d5c408e3 100644 --- a/compiler/rustc/Cargo.toml +++ b/compiler/rustc/Cargo.toml @@ -30,5 +30,6 @@ features = ['unprefixed_malloc_on_supported_platforms'] jemalloc = ['dep:jemalloc-sys'] llvm = ['rustc_driver_impl/llvm'] max_level_info = ['rustc_driver_impl/max_level_info'] +rustc_randomized_layouts = ['rustc_driver_impl/rustc_randomized_layouts'] rustc_use_parallel_compiler = ['rustc_driver_impl/rustc_use_parallel_compiler'] # tidy-alphabetical-end diff --git a/compiler/rustc_driver_impl/Cargo.toml b/compiler/rustc_driver_impl/Cargo.toml index 91cbffcd7072b..6d6d3f35a4b1b 100644 --- a/compiler/rustc_driver_impl/Cargo.toml +++ b/compiler/rustc_driver_impl/Cargo.toml @@ -23,6 +23,7 @@ rustc_hir_analysis = { path = "../rustc_hir_analysis" } rustc_hir_pretty = { path = "../rustc_hir_pretty" } rustc_hir_typeck = { path = "../rustc_hir_typeck" } rustc_incremental = { path = "../rustc_incremental" } +rustc_index = { path = "../rustc_index" } rustc_infer = { path = "../rustc_infer" } rustc_interface = { path = "../rustc_interface" } rustc_lint = { path = "../rustc_lint" } @@ -72,6 +73,10 @@ ctrlc = "3.4.4" # tidy-alphabetical-start llvm = ['rustc_interface/llvm'] max_level_info = ['rustc_log/max_level_info'] +rustc_randomized_layouts = [ + 'rustc_index/rustc_randomized_layouts', + 'rustc_middle/rustc_randomized_layouts' +] rustc_use_parallel_compiler = [ 'rustc_data_structures/rustc_use_parallel_compiler', 'rustc_interface/rustc_use_parallel_compiler', diff --git a/compiler/rustc_index/Cargo.toml b/compiler/rustc_index/Cargo.toml index 92ea3f278dc43..f7d18f84e3452 100644 --- a/compiler/rustc_index/Cargo.toml +++ b/compiler/rustc_index/Cargo.toml @@ -20,4 +20,5 @@ nightly = [ "dep:rustc_macros", "rustc_index_macros/nightly", ] +rustc_randomized_layouts = [] # tidy-alphabetical-end diff --git a/compiler/rustc_index/src/lib.rs b/compiler/rustc_index/src/lib.rs index f773b5b46adae..52f354b8ecaff 100644 --- a/compiler/rustc_index/src/lib.rs +++ b/compiler/rustc_index/src/lib.rs @@ -33,8 +33,19 @@ pub use vec::IndexVec; /// /// #[macro_export] +#[cfg(not(feature = "rustc_randomized_layouts"))] macro_rules! static_assert_size { ($ty:ty, $size:expr) => { const _: [(); $size] = [(); ::std::mem::size_of::<$ty>()]; }; } + +#[macro_export] +#[cfg(feature = "rustc_randomized_layouts")] +macro_rules! static_assert_size { + ($ty:ty, $size:expr) => { + // no effect other than using the statements. + // struct sizes are not deterministic under randomized layouts + const _: (usize, usize) = ($size, ::std::mem::size_of::<$ty>()); + }; +} diff --git a/compiler/rustc_middle/Cargo.toml b/compiler/rustc_middle/Cargo.toml index 69e3b703ccee1..b23589afb5874 100644 --- a/compiler/rustc_middle/Cargo.toml +++ b/compiler/rustc_middle/Cargo.toml @@ -40,5 +40,6 @@ tracing = "0.1" [features] # tidy-alphabetical-start +rustc_randomized_layouts = [] rustc_use_parallel_compiler = ["dep:rustc-rayon-core"] # tidy-alphabetical-end diff --git a/compiler/rustc_middle/src/query/plumbing.rs b/compiler/rustc_middle/src/query/plumbing.rs index c9bd702cce340..0320a91d142b7 100644 --- a/compiler/rustc_middle/src/query/plumbing.rs +++ b/compiler/rustc_middle/src/query/plumbing.rs @@ -337,6 +337,7 @@ macro_rules! define_callbacks { // Ensure that values grow no larger than 64 bytes by accident. // Increase this limit if necessary, but do try to keep the size low if possible #[cfg(target_pointer_width = "64")] + #[cfg(not(feature = "rustc_randomized_layouts"))] const _: () = { if mem::size_of::>() > 64 { panic!("{}", concat!( diff --git a/src/bootstrap/src/lib.rs b/src/bootstrap/src/lib.rs index 268392c5fb118..dc852e894a013 100644 --- a/src/bootstrap/src/lib.rs +++ b/src/bootstrap/src/lib.rs @@ -678,6 +678,9 @@ impl Build { if self.config.rustc_parallel { features.push("rustc_use_parallel_compiler"); } + if self.config.rust_randomize_layout { + features.push("rustc_randomized_layouts"); + } // If debug logging is on, then we want the default for tracing: // https://github.com/tokio-rs/tracing/blob/3dd5c03d907afdf2c39444a29931833335171554/tracing/src/level_filters.rs#L26 From e3169f76e6597bc3b582070436ce513b5db2dab8 Mon Sep 17 00:00:00 2001 From: The 8472 Date: Fri, 2 Sep 2022 20:18:19 +0200 Subject: [PATCH 0321/2194] when -Zrandomize-layout is enabled disable alloc test testing internal struct sizes --- library/alloc/Cargo.toml | 1 + library/alloc/src/collections/btree/node/tests.rs | 2 +- src/bootstrap/src/core/builder.rs | 3 +++ 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/library/alloc/Cargo.toml b/library/alloc/Cargo.toml index 4365bcc4ad022..1bd4434d4f7e9 100644 --- a/library/alloc/Cargo.toml +++ b/library/alloc/Cargo.toml @@ -52,4 +52,5 @@ check-cfg = [ 'cfg(no_global_oom_handling)', 'cfg(no_rc)', 'cfg(no_sync)', + 'cfg(randomized_layouts)', ] diff --git a/library/alloc/src/collections/btree/node/tests.rs b/library/alloc/src/collections/btree/node/tests.rs index d230749d71231..4d2fa0f094171 100644 --- a/library/alloc/src/collections/btree/node/tests.rs +++ b/library/alloc/src/collections/btree/node/tests.rs @@ -90,7 +90,7 @@ fn test_partial_eq() { #[test] #[cfg(target_arch = "x86_64")] -#[cfg_attr(miri, ignore)] // We'd like to run Miri with layout randomization +#[cfg_attr(any(miri, randomized_layouts), ignore)] // We'd like to run Miri with layout randomization fn test_sizes() { assert_eq!(core::mem::size_of::>(), 16); assert_eq!(core::mem::size_of::>(), 16 + CAPACITY * 2 * 8); diff --git a/src/bootstrap/src/core/builder.rs b/src/bootstrap/src/core/builder.rs index 5df962e939ed6..3043fd09ed19c 100644 --- a/src/bootstrap/src/core/builder.rs +++ b/src/bootstrap/src/core/builder.rs @@ -2193,6 +2193,9 @@ impl<'a> Builder<'a> { rustflags.arg("-Zvalidate-mir"); rustflags.arg(&format!("-Zmir-opt-level={mir_opt_level}")); } + if self.config.rust_randomize_layout { + rustflags.arg("--cfg=randomized_layouts"); + } // Always enable inlining MIR when building the standard library. // Without this flag, MIR inlining is disabled when incremental compilation is enabled. // That causes some mir-opt tests which inline functions from the standard library to From 1e377c5b9fd820d97d7fa3f0447c1c45b5fb64c7 Mon Sep 17 00:00:00 2001 From: The 8472 Date: Fri, 2 Sep 2022 22:44:39 +0200 Subject: [PATCH 0322/2194] enable layout randomization in x86_64-gnu-llvm-17 CI job --- src/ci/docker/host-x86_64/x86_64-gnu-llvm-17/Dockerfile | 1 + 1 file changed, 1 insertion(+) diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-llvm-17/Dockerfile b/src/ci/docker/host-x86_64/x86_64-gnu-llvm-17/Dockerfile index 275acb47c33a7..3acc2ceb135ef 100644 --- a/src/ci/docker/host-x86_64/x86_64-gnu-llvm-17/Dockerfile +++ b/src/ci/docker/host-x86_64/x86_64-gnu-llvm-17/Dockerfile @@ -50,6 +50,7 @@ ENV RUST_CONFIGURE_ARGS \ --build=x86_64-unknown-linux-gnu \ --llvm-root=/usr/lib/llvm-17 \ --enable-llvm-link-shared \ + --set rust.randomize-layout=true \ --set rust.thin-lto-import-instr-limit=10 COPY host-x86_64/dist-x86_64-linux/shared.sh /scripts/ From df20808f4dc7828c0f78cd17c3bd9edbd499d6f3 Mon Sep 17 00:00:00 2001 From: The 8472 Date: Sat, 31 Aug 2024 14:43:23 +0200 Subject: [PATCH 0323/2194] inhibit layout randomization for Box --- compiler/rustc_abi/src/layout.rs | 11 +++++++---- compiler/rustc_abi/src/lib.rs | 15 +++++++++++---- compiler/rustc_middle/src/ty/mod.rs | 10 +++++++++- 3 files changed, 27 insertions(+), 9 deletions(-) diff --git a/compiler/rustc_abi/src/layout.rs b/compiler/rustc_abi/src/layout.rs index 5160b4ed0a2ac..7432768be4a58 100644 --- a/compiler/rustc_abi/src/layout.rs +++ b/compiler/rustc_abi/src/layout.rs @@ -968,8 +968,8 @@ fn univariant< let mut align = if pack.is_some() { dl.i8_align } else { dl.aggregate_align }; let mut max_repr_align = repr.align; let mut inverse_memory_index: IndexVec = fields.indices().collect(); - let optimize = !repr.inhibit_struct_field_reordering(); - if optimize && fields.len() > 1 { + let optimize_field_order = !repr.inhibit_struct_field_reordering(); + if optimize_field_order && fields.len() > 1 { let end = if let StructKind::MaybeUnsized = kind { fields.len() - 1 } else { fields.len() }; let optimizing = &mut inverse_memory_index.raw[..end]; let fields_excluding_tail = &fields.raw[..end]; @@ -1176,7 +1176,7 @@ fn univariant< // If field 5 has offset 0, offsets[0] is 5, and memory_index[5] should be 0. // Field 5 would be the first element, so memory_index is i: // Note: if we didn't optimize, it's already right. - let memory_index = if optimize { + let memory_index = if optimize_field_order { inverse_memory_index.invert_bijective_mapping() } else { debug_assert!(inverse_memory_index.iter().copied().eq(fields.indices())); @@ -1189,6 +1189,9 @@ fn univariant< } let mut layout_of_single_non_zst_field = None; let mut abi = Abi::Aggregate { sized }; + + let optimize_abi = !repr.inhibit_newtype_abi_optimization(); + // Try to make this a Scalar/ScalarPair. if sized && size.bytes() > 0 { // We skip *all* ZST here and later check if we are good in terms of alignment. @@ -1205,7 +1208,7 @@ fn univariant< match field.abi { // For plain scalars, or vectors of them, we can't unpack // newtypes for `#[repr(C)]`, as that affects C ABIs. - Abi::Scalar(_) | Abi::Vector { .. } if optimize => { + Abi::Scalar(_) | Abi::Vector { .. } if optimize_abi => { abi = field.abi; } // But scalar pairs are Rust-specific and get diff --git a/compiler/rustc_abi/src/lib.rs b/compiler/rustc_abi/src/lib.rs index df29b3d54f0fb..be42bc8493243 100644 --- a/compiler/rustc_abi/src/lib.rs +++ b/compiler/rustc_abi/src/lib.rs @@ -43,14 +43,17 @@ bitflags! { const IS_SIMD = 1 << 1; const IS_TRANSPARENT = 1 << 2; // Internal only for now. If true, don't reorder fields. + // On its own it does not prevent ABI optimizations. const IS_LINEAR = 1 << 3; - // If true, the type's layout can be randomized using - // the seed stored in `ReprOptions.field_shuffle_seed` + // If true, the type's crate has opted into layout randomization. + // Other flags can still inhibit reordering and thus randomization. + // The seed stored in `ReprOptions.field_shuffle_seed`. const RANDOMIZE_LAYOUT = 1 << 4; // Any of these flags being set prevent field reordering optimisation. - const IS_UNOPTIMISABLE = ReprFlags::IS_C.bits() + const FIELD_ORDER_UNOPTIMIZABLE = ReprFlags::IS_C.bits() | ReprFlags::IS_SIMD.bits() | ReprFlags::IS_LINEAR.bits(); + const ABI_UNOPTIMIZABLE = ReprFlags::IS_C.bits() | ReprFlags::IS_SIMD.bits(); } } @@ -139,10 +142,14 @@ impl ReprOptions { self.c() || self.int.is_some() } + pub fn inhibit_newtype_abi_optimization(&self) -> bool { + self.flags.intersects(ReprFlags::ABI_UNOPTIMIZABLE) + } + /// Returns `true` if this `#[repr()]` guarantees a fixed field order, /// e.g. `repr(C)` or `repr()`. pub fn inhibit_struct_field_reordering(&self) -> bool { - self.flags.intersects(ReprFlags::IS_UNOPTIMISABLE) || self.int.is_some() + self.flags.intersects(ReprFlags::FIELD_ORDER_UNOPTIMIZABLE) || self.int.is_some() } /// Returns `true` if this type is valid for reordering and `-Z randomize-layout` diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index e41ea7507efff..874e75f717905 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -35,6 +35,7 @@ use rustc_data_structures::tagged_ptr::CopyTaggedPtr; use rustc_errors::{Diag, ErrorGuaranteed, StashKey}; use rustc_hir::def::{CtorKind, CtorOf, DefKind, DocLinkResMap, LifetimeRes, Res}; use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LocalDefId, LocalDefIdMap}; +use rustc_hir::LangItem; use rustc_index::IndexVec; use rustc_macros::{ extension, Decodable, Encodable, HashStable, TyDecodable, TyEncodable, TypeFoldable, @@ -1570,8 +1571,15 @@ impl<'tcx> TyCtxt<'tcx> { flags.insert(ReprFlags::RANDOMIZE_LAYOUT); } + // box is special, on the one hand the compiler assumes an ordered layout, with the pointer + // always at offset zero. On the other hand we want scalar abi optimizations. + let is_box = self.is_lang_item(did.to_def_id(), LangItem::OwnedBox); + // This is here instead of layout because the choice must make it into metadata. - if !self.consider_optimizing(|| format!("Reorder fields of {:?}", self.def_path_str(did))) { + if is_box + || !self + .consider_optimizing(|| format!("Reorder fields of {:?}", self.def_path_str(did))) + { flags.insert(ReprFlags::IS_LINEAR); } From c218c754568351e44a8c8f07702c090c6c2ae945 Mon Sep 17 00:00:00 2001 From: The 8472 Date: Sat, 31 Aug 2024 18:02:01 +0200 Subject: [PATCH 0324/2194] exclude tools with deps that have size asserts --- src/bootstrap/src/core/builder.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/bootstrap/src/core/builder.rs b/src/bootstrap/src/core/builder.rs index 3043fd09ed19c..a4474046fb8ab 100644 --- a/src/bootstrap/src/core/builder.rs +++ b/src/bootstrap/src/core/builder.rs @@ -1614,7 +1614,12 @@ impl<'a> Builder<'a> { rustflags.arg("-Csymbol-mangling-version=legacy"); } - if self.config.rust_randomize_layout { + // FIXME: the following components don't build with `-Zrandomize-layout` yet: + // - wasm-component-ld, due to the `wast`crate + // - rust-analyzer, due to the rowan crate + // so we exclude entire categories of steps here due to lack of fine-grained control over + // rustflags. + if self.config.rust_randomize_layout && mode != Mode::ToolStd && mode != Mode::ToolRustc { rustflags.arg("-Zrandomize-layout"); } From 8116b62fd2eab008dcbffc6b22f1fb2b07f6deea Mon Sep 17 00:00:00 2001 From: Chayim Refael Friedman Date: Sun, 1 Sep 2024 01:04:21 +0300 Subject: [PATCH 0325/2194] Provide an option to hide deprecated items from completion --- .../rust-analyzer/crates/rust-analyzer/src/config.rs | 6 ++++++ .../crates/rust-analyzer/src/lsp/to_proto.rs | 6 +++++- .../rust-analyzer/docs/user/generated_config.adoc | 5 +++++ src/tools/rust-analyzer/editors/code/package.json | 10 ++++++++++ 4 files changed, 26 insertions(+), 1 deletion(-) diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs index c884216b3e3cd..714c835812f33 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs @@ -429,6 +429,8 @@ config_data! { completion_callable_snippets: CallableCompletionDef = CallableCompletionDef::FillArguments, /// Whether to show full function/method signatures in completion docs. completion_fullFunctionSignatures_enable: bool = false, + /// Whether to omit deprecated items from autocompletion. By default they are marked as deprecated but not hidden. + completion_hideDeprecated: bool = false, /// Maximum number of completions to return. If `None`, the limit is infinite. completion_limit: Option = None, /// Whether to show postfix snippets like `dbg`, `if`, `not`, etc. @@ -1443,6 +1445,10 @@ impl Config { } } + pub fn completion_hide_deprecated(&self) -> bool { + *self.completion_hideDeprecated(None) + } + pub fn detached_files(&self) -> &Vec { // FIXME @alibektas : This is the only config that is confusing. If it's a proper configuration // why is it not among the others? If it's client only which I doubt it is current state should be alright diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/to_proto.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/to_proto.rs index 6dff8abb0f825..b29268f133f3a 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/to_proto.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/to_proto.rs @@ -228,8 +228,12 @@ pub(crate) fn completion_items( line_index: &LineIndex, version: Option, tdpp: lsp_types::TextDocumentPositionParams, - items: Vec, + mut items: Vec, ) -> Vec { + if config.completion_hide_deprecated() { + items.retain(|item| !item.deprecated); + } + let max_relevance = items.iter().map(|it| it.relevance.score()).max().unwrap_or_default(); let mut res = Vec::with_capacity(items.len()); for item in items { diff --git a/src/tools/rust-analyzer/docs/user/generated_config.adoc b/src/tools/rust-analyzer/docs/user/generated_config.adoc index e4a8c6493a883..4fcf580e75f5a 100644 --- a/src/tools/rust-analyzer/docs/user/generated_config.adoc +++ b/src/tools/rust-analyzer/docs/user/generated_config.adoc @@ -283,6 +283,11 @@ Whether to add parenthesis and argument snippets when completing function. -- Whether to show full function/method signatures in completion docs. -- +[[rust-analyzer.completion.hideDeprecated]]rust-analyzer.completion.hideDeprecated (default: `false`):: ++ +-- +Whether to omit deprecated items from autocompletion. By default they are marked as deprecated but not hidden. +-- [[rust-analyzer.completion.limit]]rust-analyzer.completion.limit (default: `null`):: + -- diff --git a/src/tools/rust-analyzer/editors/code/package.json b/src/tools/rust-analyzer/editors/code/package.json index 98e8bbf02aa55..0b029460b3220 100644 --- a/src/tools/rust-analyzer/editors/code/package.json +++ b/src/tools/rust-analyzer/editors/code/package.json @@ -1077,6 +1077,16 @@ } } }, + { + "title": "completion", + "properties": { + "rust-analyzer.completion.hideDeprecated": { + "markdownDescription": "Whether to omit deprecated items from autocompletion. By default they are marked as deprecated but not hidden.", + "default": false, + "type": "boolean" + } + } + }, { "title": "completion", "properties": { From f78979e687a3105f33be30f94a597ae9f5a18f4d Mon Sep 17 00:00:00 2001 From: Alona Enraght-Moony Date: Sat, 31 Aug 2024 22:08:38 +0000 Subject: [PATCH 0326/2194] Actually parse stdout json, instead of using hacky contains logic. --- tests/run-make/rustdoc-output-stdout/rmake.rs | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/tests/run-make/rustdoc-output-stdout/rmake.rs b/tests/run-make/rustdoc-output-stdout/rmake.rs index dbc9892f3f59a..bcf5e4d97239f 100644 --- a/tests/run-make/rustdoc-output-stdout/rmake.rs +++ b/tests/run-make/rustdoc-output-stdout/rmake.rs @@ -4,17 +4,28 @@ use std::path::PathBuf; use run_make_support::path_helpers::{cwd, has_extension, read_dir_entries_recursive}; -use run_make_support::rustdoc; +use run_make_support::{rustdoc, serde_json}; fn main() { - // First we check that we generate the JSON in the stdout. - rustdoc() + let json_string = rustdoc() .input("foo.rs") .out_dir("-") .arg("-Zunstable-options") .output_format("json") .run() - .assert_stdout_contains("{\""); + .stdout_utf8(); + + // First we check that we generate the JSON in the stdout. + let json_value: serde_json::Value = + serde_json::from_str(&json_string).expect("stdout should be valid json"); + + // We don't care to test the specifics of the JSON, as that's done + // elsewhere, just check that it has a format_version (as all JSON output + // should). + let format_version = json_value["format_version"] + .as_i64() + .expect("json output should contain format_version field"); + assert!(format_version > 30); // Then we check it didn't generate any JSON file. read_dir_entries_recursive(cwd(), |path| { From 89a39d918f396c30fe3d0cb8f8f3cf6319736c14 Mon Sep 17 00:00:00 2001 From: Chayim Refael Friedman Date: Sun, 1 Sep 2024 02:07:05 +0300 Subject: [PATCH 0327/2194] Handle attributes correctly in "Flip comma" Attributes often contain path followed by a token tree (e.g. `align(2)`, and the previous code handled them as two separate items, which led to results such as `#[repr(alignC, (2))]`. An alternative is to just make the assist unavailable in attributes, like we do in macros. But contrary to macros, attributes often have a fixed form, so this seems useful. --- .../ide-assists/src/handlers/flip_comma.rs | 64 ++++++++++++++++++- 1 file changed, 61 insertions(+), 3 deletions(-) diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/flip_comma.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/flip_comma.rs index f40f2713ad131..af2c2c759ec78 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/flip_comma.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/flip_comma.rs @@ -1,4 +1,8 @@ -use syntax::{algo::non_trivia_sibling, Direction, SyntaxKind, T}; +use ide_db::base_db::SourceDatabase; +use syntax::TextSize; +use syntax::{ + algo::non_trivia_sibling, ast, AstNode, Direction, SyntaxKind, SyntaxToken, TextRange, T, +}; use crate::{AssistContext, AssistId, AssistKind, Assists}; @@ -21,6 +25,8 @@ pub(crate) fn flip_comma(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<( let comma = ctx.find_token_syntax_at_offset(T![,])?; let prev = non_trivia_sibling(comma.clone().into(), Direction::Prev)?; let next = non_trivia_sibling(comma.clone().into(), Direction::Next)?; + let (mut prev_text, mut next_text) = (prev.to_string(), next.to_string()); + let (mut prev_range, mut next_range) = (prev.text_range(), next.text_range()); // Don't apply a "flip" in case of a last comma // that typically comes before punctuation @@ -34,17 +40,55 @@ pub(crate) fn flip_comma(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<( return None; } + if let Some(parent) = comma.parent().and_then(ast::TokenTree::cast) { + // An attribute. It often contains a path followed by a token tree (e.g. `align(2)`), so we have + // to be smarter. + let prev_start = + match comma.siblings_with_tokens(Direction::Prev).skip(1).find(|it| it.kind() == T![,]) + { + Some(it) => position_after_token(it.as_token().unwrap()), + None => position_after_token(&parent.left_delimiter_token()?), + }; + let prev_end = prev.text_range().end(); + let next_start = next.text_range().start(); + let next_end = + match comma.siblings_with_tokens(Direction::Next).skip(1).find(|it| it.kind() == T![,]) + { + Some(it) => position_before_token(it.as_token().unwrap()), + None => position_before_token(&parent.right_delimiter_token()?), + }; + prev_range = TextRange::new(prev_start, prev_end); + next_range = TextRange::new(next_start, next_end); + let file_text = ctx.db().file_text(ctx.file_id().file_id()); + prev_text = file_text[prev_range].to_owned(); + next_text = file_text[next_range].to_owned(); + } + acc.add( AssistId("flip_comma", AssistKind::RefactorRewrite), "Flip comma", comma.text_range(), |edit| { - edit.replace(prev.text_range(), next.to_string()); - edit.replace(next.text_range(), prev.to_string()); + edit.replace(prev_range, next_text); + edit.replace(next_range, prev_text); }, ) } +fn position_before_token(token: &SyntaxToken) -> TextSize { + match non_trivia_sibling(token.clone().into(), Direction::Prev) { + Some(prev_token) => prev_token.text_range().end(), + None => token.text_range().start(), + } +} + +fn position_after_token(token: &SyntaxToken) -> TextSize { + match non_trivia_sibling(token.clone().into(), Direction::Next) { + Some(prev_token) => prev_token.text_range().start(), + None => token.text_range().end(), + } +} + #[cfg(test)] mod tests { use super::*; @@ -89,4 +133,18 @@ mod tests { // See https://github.com/rust-lang/rust-analyzer/issues/7693 check_assist_not_applicable(flip_comma, r#"bar!(a,$0 b)"#); } + + #[test] + fn flip_comma_attribute() { + check_assist( + flip_comma, + r#"#[repr(align(2),$0 C)] struct Foo;"#, + r#"#[repr(C, align(2))] struct Foo;"#, + ); + check_assist( + flip_comma, + r#"#[foo(bar, baz(1 + 1),$0 qux, other)] struct Foo;"#, + r#"#[foo(bar, qux, baz(1 + 1), other)] struct Foo;"#, + ); + } } From de7a14e97730905c2fee7cda5728255f1f596d04 Mon Sep 17 00:00:00 2001 From: Huang Qi Date: Sun, 1 Sep 2024 09:59:09 +0800 Subject: [PATCH 0328/2194] Fix LLVM ABI NAME for riscv64imac-unknown-nuttx-elf This patch fix https://github.com/rust-lang/rust/issues/129825 For the riscv64imac target, the LLVM ABI NAME should be "lp64", which is the default ABI if not specified for the riscv64imac target. --- .../src/spec/targets/riscv64imac_unknown_nuttx_elf.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/compiler/rustc_target/src/spec/targets/riscv64imac_unknown_nuttx_elf.rs b/compiler/rustc_target/src/spec/targets/riscv64imac_unknown_nuttx_elf.rs index 215c0724f91de..80d58e5baceac 100644 --- a/compiler/rustc_target/src/spec/targets/riscv64imac_unknown_nuttx_elf.rs +++ b/compiler/rustc_target/src/spec/targets/riscv64imac_unknown_nuttx_elf.rs @@ -21,7 +21,6 @@ pub fn target() -> Target { os: "nuttx".into(), linker_flavor: LinkerFlavor::Gnu(Cc::No, Lld::Yes), linker: Some("rust-lld".into()), - llvm_abiname: "lp64d".into(), cpu: "generic-rv64".into(), max_atomic_width: Some(64), features: "+m,+a,+c".into(), From a0073104ad92fe07e9174b47125da19c64fcf621 Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Sat, 31 Aug 2024 21:24:47 -0500 Subject: [PATCH 0329/2194] Mark myself as on vacation for triagebot --- triagebot.toml | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/triagebot.toml b/triagebot.toml index d3333b67d155b..651d27f034108 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -913,7 +913,14 @@ cc = ["@kobzol"] [assign] warn_non_default_branch = true contributing_url = "https://rustc-dev-guide.rust-lang.org/getting-started.html" -users_on_vacation = ["jyn514", "jhpratt", "oli-obk", "kobzol", "joboet"] +users_on_vacation = [ + "jhpratt", + "joboet", + "jyn514", + "kobzol", + "oli-obk", + "tgross35", +] [assign.adhoc_groups] compiler-team = [ From 3a693f247b81b4538ff1e634d4cfffa30d0a3cfc Mon Sep 17 00:00:00 2001 From: The Miri Cronjob Bot Date: Sun, 1 Sep 2024 04:55:50 +0000 Subject: [PATCH 0330/2194] Preparing for merge from rustc --- src/tools/miri/rust-version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/miri/rust-version b/src/tools/miri/rust-version index c33d9ad86149b..5a435a9f55bd3 100644 --- a/src/tools/miri/rust-version +++ b/src/tools/miri/rust-version @@ -1 +1 @@ -0d634185dfddefe09047881175f35c65d68dcff1 +43eaa5c6246057b1675f42631967ad500eaf47d5 From b71297f670299f54118de07b2e63af309a80b198 Mon Sep 17 00:00:00 2001 From: The Miri Cronjob Bot Date: Sun, 1 Sep 2024 05:04:43 +0000 Subject: [PATCH 0331/2194] fmt --- src/tools/miri/src/alloc_addresses/mod.rs | 24 ++++++++++++++----- src/tools/miri/src/concurrency/thread.rs | 9 +++++-- src/tools/miri/src/machine.rs | 6 ++--- src/tools/miri/src/shims/native_lib.rs | 7 ++++-- .../tests/native-lib/pass/ptr_read_access.rs | 12 ++++------ 5 files changed, 37 insertions(+), 21 deletions(-) diff --git a/src/tools/miri/src/alloc_addresses/mod.rs b/src/tools/miri/src/alloc_addresses/mod.rs index 76c68add8cdc9..cb3929959f697 100644 --- a/src/tools/miri/src/alloc_addresses/mod.rs +++ b/src/tools/miri/src/alloc_addresses/mod.rs @@ -185,8 +185,11 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { panic!("Miri ran out of memory: cannot create allocation of {size:?} bytes") }); let ptr = prepared_bytes.as_ptr(); - // Store prepared allocation space to be picked up for use later. - global_state.prepared_alloc_bytes.try_insert(alloc_id, prepared_bytes).unwrap(); + // Store prepared allocation space to be picked up for use later. + global_state + .prepared_alloc_bytes + .try_insert(alloc_id, prepared_bytes) + .unwrap(); ptr } else { ecx.get_alloc_bytes_unchecked_raw(alloc_id)? @@ -196,16 +199,19 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { } AllocKind::Function | AllocKind::VTable => { // Allocate some dummy memory to get a unique address for this function/vtable. - let alloc_bytes = MiriAllocBytes::from_bytes(&[0u8; 1], Align::from_bytes(1).unwrap()); + let alloc_bytes = MiriAllocBytes::from_bytes( + &[0u8; 1], + Align::from_bytes(1).unwrap(), + ); // We don't need to expose these bytes as nobody is allowed to access them. let addr = alloc_bytes.as_ptr().addr().try_into().unwrap(); // Leak the underlying memory to ensure it remains unique. std::mem::forget(alloc_bytes); addr } - AllocKind::Dead => unreachable!() + AllocKind::Dead => unreachable!(), } - } else if let Some((reuse_addr, clock)) = global_state.reuse.take_addr( + } else if let Some((reuse_addr, clock)) = global_state.reuse.take_addr( &mut *rng, size, align, @@ -359,7 +365,13 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // This returns some prepared `MiriAllocBytes`, either because `addr_from_alloc_id` reserved // memory space in the past, or by doing the pre-allocation right upon being called. - fn get_global_alloc_bytes(&self, id: AllocId, kind: MemoryKind, bytes: &[u8], align: Align) -> InterpResult<'tcx, MiriAllocBytes> { + fn get_global_alloc_bytes( + &self, + id: AllocId, + kind: MemoryKind, + bytes: &[u8], + align: Align, + ) -> InterpResult<'tcx, MiriAllocBytes> { let ecx = self.eval_context_ref(); Ok(if ecx.machine.native_lib.is_some() { // In native lib mode, MiriAllocBytes for global allocations are handled via `prepared_alloc_bytes`. diff --git a/src/tools/miri/src/concurrency/thread.rs b/src/tools/miri/src/concurrency/thread.rs index 79f292f696599..306245a843bf4 100644 --- a/src/tools/miri/src/concurrency/thread.rs +++ b/src/tools/miri/src/concurrency/thread.rs @@ -888,8 +888,13 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { } let alloc = this.ctfe_query(|tcx| tcx.eval_static_initializer(def_id))?; // We make a full copy of this allocation. - let mut alloc = - alloc.inner().adjust_from_tcx(&this.tcx, |bytes, align| Ok(MiriAllocBytes::from_bytes(std::borrow::Cow::Borrowed(bytes), align)), |ptr| this.global_root_pointer(ptr))?; + let mut alloc = alloc.inner().adjust_from_tcx( + &this.tcx, + |bytes, align| { + Ok(MiriAllocBytes::from_bytes(std::borrow::Cow::Borrowed(bytes), align)) + }, + |ptr| this.global_root_pointer(ptr), + )?; // This allocation will be deallocated when the thread dies, so it is not in read-only memory. alloc.mutability = Mutability::Mut; // Create a fresh allocation with this content. diff --git a/src/tools/miri/src/machine.rs b/src/tools/miri/src/machine.rs index 66c6966d1a6c3..331edf9c7ea31 100644 --- a/src/tools/miri/src/machine.rs +++ b/src/tools/miri/src/machine.rs @@ -1277,12 +1277,12 @@ impl<'tcx> Machine<'tcx> for MiriMachine<'tcx> { ) -> InterpResult<'tcx, Cow<'b, Allocation>> { let kind = Self::GLOBAL_KIND.unwrap().into(); - let alloc = alloc.adjust_from_tcx(&ecx.tcx, + let alloc = alloc.adjust_from_tcx( + &ecx.tcx, |bytes, align| ecx.get_global_alloc_bytes(id, kind, bytes, align), |ptr| ecx.global_root_pointer(ptr), )?; - let extra = - Self::init_alloc_extra(ecx, id, kind, alloc.size(), alloc.align)?; + let extra = Self::init_alloc_extra(ecx, id, kind, alloc.size(), alloc.align)?; Ok(Cow::Owned(alloc.with_extra(extra))) } diff --git a/src/tools/miri/src/shims/native_lib.rs b/src/tools/miri/src/shims/native_lib.rs index 25d96fbd7331f..e4998c37f3fe6 100644 --- a/src/tools/miri/src/shims/native_lib.rs +++ b/src/tools/miri/src/shims/native_lib.rs @@ -240,13 +240,16 @@ fn imm_to_carg<'tcx>(v: ImmTy<'tcx>, cx: &impl HasDataLayout) -> InterpResult<'t ty::RawPtr(_, mutability) => { // Arbitrary mutable pointer accesses are not currently supported in Miri. if mutability.is_mut() { - throw_unsup_format!("unsupported mutable pointer type for native call: {}", v.layout.ty); + throw_unsup_format!( + "unsupported mutable pointer type for native call: {}", + v.layout.ty + ); } else { let s = v.to_scalar().to_pointer(cx)?.addr(); // This relies on the `expose_provenance` in `addr_from_alloc_id`. CArg::RawPtr(std::ptr::with_exposed_provenance_mut(s.bytes_usize())) } - }, + } _ => throw_unsup_format!("unsupported argument type for native call: {}", v.layout.ty), }) } diff --git a/src/tools/miri/tests/native-lib/pass/ptr_read_access.rs b/src/tools/miri/tests/native-lib/pass/ptr_read_access.rs index d8e6209839e2a..77a73deddedb8 100644 --- a/src/tools/miri/tests/native-lib/pass/ptr_read_access.rs +++ b/src/tools/miri/tests/native-lib/pass/ptr_read_access.rs @@ -26,7 +26,7 @@ fn test_pointer() { fn test_simple() { #[repr(C)] struct Simple { - field: i32 + field: i32, } extern "C" { @@ -41,7 +41,7 @@ fn test_simple() { // Test function that dereferences nested struct pointers and accesses fields. fn test_nested() { use std::ptr::NonNull; - + #[derive(Debug, PartialEq, Eq)] #[repr(C)] struct Nested { @@ -62,7 +62,6 @@ fn test_nested() { // Test function that dereferences static struct pointers and accesses fields. fn test_static() { - #[repr(C)] struct Static { value: i32, @@ -72,11 +71,8 @@ fn test_static() { extern "C" { fn access_static(n_ptr: *const Static) -> i32; } - - static STATIC: Static = Static { - value: 9001, - recurse: &STATIC, - }; + + static STATIC: Static = Static { value: 9001, recurse: &STATIC }; assert_eq!(unsafe { access_static(&STATIC) }, 9001); } From f558be0359b41e74c09f6f171f149498d1b27cde Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Sun, 1 Sep 2024 10:02:41 +0200 Subject: [PATCH 0332/2194] minor: Downgrade cyclic deps error to warning --- .../rust-analyzer/crates/base-db/src/input.rs | 54 +++---------------- .../crates/project-model/src/workspace.rs | 2 +- 2 files changed, 8 insertions(+), 48 deletions(-) diff --git a/src/tools/rust-analyzer/crates/base-db/src/input.rs b/src/tools/rust-analyzer/crates/base-db/src/input.rs index 3616fa9fd8684..032e4a8e4a733 100644 --- a/src/tools/rust-analyzer/crates/base-db/src/input.rs +++ b/src/tools/rust-analyzer/crates/base-db/src/input.rs @@ -374,37 +374,6 @@ impl CrateGraph { self.arena.alloc(data) } - /// Remove the crate from crate graph. If any crates depend on this crate, the dependency would be replaced - /// with the second input. - pub fn remove_and_replace( - &mut self, - id: CrateId, - replace_with: CrateId, - ) -> Result<(), CyclicDependenciesError> { - for (x, data) in self.arena.iter() { - if x == id { - continue; - } - for edge in &data.dependencies { - if edge.crate_id == id { - self.check_cycle_after_dependency(edge.crate_id, replace_with)?; - } - } - } - // if everything was ok, start to replace - for (x, data) in self.arena.iter_mut() { - if x == id { - continue; - } - for edge in &mut data.dependencies { - if edge.crate_id == id { - edge.crate_id = replace_with; - } - } - } - Ok(()) - } - pub fn add_dep( &mut self, from: CrateId, @@ -412,26 +381,17 @@ impl CrateGraph { ) -> Result<(), CyclicDependenciesError> { let _p = tracing::info_span!("add_dep").entered(); - self.check_cycle_after_dependency(from, dep.crate_id)?; - - self.arena[from].add_dep(dep); - Ok(()) - } - - /// Check if adding a dep from `from` to `to` creates a cycle. To figure - /// that out, look for a path in the *opposite* direction, from `to` to - /// `from`. - fn check_cycle_after_dependency( - &self, - from: CrateId, - to: CrateId, - ) -> Result<(), CyclicDependenciesError> { - if let Some(path) = self.find_path(&mut FxHashSet::default(), to, from) { + // Check if adding a dep from `from` to `to` creates a cycle. To figure + // that out, look for a path in the *opposite* direction, from `to` to + // `from`. + if let Some(path) = self.find_path(&mut FxHashSet::default(), dep.crate_id, from) { let path = path.into_iter().map(|it| (it, self[it].display_name.clone())).collect(); let err = CyclicDependenciesError { path }; - assert!(err.from().0 == from && err.to().0 == to); + assert!(err.from().0 == from && err.to().0 == dep.crate_id); return Err(err); } + + self.arena[from].add_dep(dep); Ok(()) } diff --git a/src/tools/rust-analyzer/crates/project-model/src/workspace.rs b/src/tools/rust-analyzer/crates/project-model/src/workspace.rs index 7834238acefdf..4fc9ef3d36b66 100644 --- a/src/tools/rust-analyzer/crates/project-model/src/workspace.rs +++ b/src/tools/rust-analyzer/crates/project-model/src/workspace.rs @@ -1554,6 +1554,6 @@ fn add_proc_macro_dep(crate_graph: &mut CrateGraph, from: CrateId, to: CrateId, fn add_dep_inner(graph: &mut CrateGraph, from: CrateId, dep: Dependency) { if let Err(err) = graph.add_dep(from, dep) { - tracing::error!("{}", err) + tracing::warn!("{}", err) } } From fc9ff795199f24b40a19e11735b1956462107d0c Mon Sep 17 00:00:00 2001 From: Yunfei Date: Mon, 29 Jul 2024 22:42:31 +0800 Subject: [PATCH 0333/2194] feat(ide-completion): extra sugar auto-completion `async fn ...` in `impl trait` for `async fn in trait` that's defined in desugar form --- src/tools/rust-analyzer/crates/hir/src/lib.rs | 47 +++++++++++++++++++ .../src/completions/item_list/trait_impl.rs | 38 ++++++++++++++- 2 files changed, 84 insertions(+), 1 deletion(-) diff --git a/src/tools/rust-analyzer/crates/hir/src/lib.rs b/src/tools/rust-analyzer/crates/hir/src/lib.rs index 96a6e6f1f128e..74ec5227b0ec6 100644 --- a/src/tools/rust-analyzer/crates/hir/src/lib.rs +++ b/src/tools/rust-analyzer/crates/hir/src/lib.rs @@ -2207,6 +2207,53 @@ impl Function { db.function_data(self.id).is_async() } + /// Whether this function is a `fn` that returns `impl Future`. + pub fn is_desugar_async(self, db: &dyn HirDatabase) -> bool { + if self.is_async(db) || self.is_const(db) { + return false; + } + + let Some(impl_traits) = self.ret_type(db).as_impl_traits(db) else { return false }; + + let Some(future_trait_id) = + db.lang_item(self.ty(db).env.krate, LangItem::Future).and_then(|t| t.as_trait()) + else { + return false; + }; + + let Some(size_trait_id) = + db.lang_item(self.ty(db).env.krate, LangItem::Sized).and_then(|t| t.as_trait()) + else { + return false; + }; + + let Some(sync_trait_id) = + db.lang_item(self.ty(db).env.krate, LangItem::Sync).and_then(|t| t.as_trait()) + else { + return false; + }; + + // TODO: There's no `LangItem::Send`. How do we get the id of `Send` trait? + // let Some(send_trait_id) = db.lang_item(self.ty(db).env.krate, LangItem::Send).and_then(|t| t.as_trait()) else { + // eprint!("no future_trait_id\n"); + // return false + // }; + + let allowed_to_leaked_types = vec![size_trait_id, sync_trait_id]; + + let mut has_impl_future = false; + let mut has_types_not_allow_to_leaked = false; + for impl_trait in impl_traits { + if impl_trait.id == future_trait_id { + has_impl_future = true; + } else if !allowed_to_leaked_types.contains(&impl_trait.id) { + has_types_not_allow_to_leaked = true; + } + } + + has_impl_future && !has_types_not_allow_to_leaked + } + /// Does this function have `#[test]` attribute? pub fn is_test(self, db: &dyn HirDatabase) -> bool { db.function_data(self.id).attrs.is_test() diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/item_list/trait_impl.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/item_list/trait_impl.rs index fc6e1ebf05fc6..7887a87448e2f 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/item_list/trait_impl.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/item_list/trait_impl.rs @@ -210,7 +210,7 @@ fn add_function_impl( ast::AssocItem::Fn(func) => func, _ => unreachable!(), }; - + // TODO: need `function_decl` that unwraps future in the return type let function_decl = function_declaration(&transformed_fn, source.file_id.is_macro()); match ctx.config.snippet_cap { Some(cap) => { @@ -225,6 +225,42 @@ fn add_function_impl( item.add_to(acc, ctx.db); } } + + eprint!("is_desugar_async: {}", func.is_desugar_async(ctx.db)); + if func.is_desugar_async(ctx.db) { + let label = format_smolstr!( + "async fn {}({})", + fn_name.display(ctx.db), + if func.assoc_fn_params(ctx.db).is_empty() { "" } else { ".." } + ); + let mut item = CompletionItem::new(completion_kind, replacement_range, label); + item.lookup_by(format!("async fn {}", fn_name.display(ctx.db))) + .set_documentation(func.docs(ctx.db)) + .set_relevance(CompletionRelevance { is_item_from_trait: true, ..Default::default() }); + if let Some(source) = ctx.sema.source(func) { + let assoc_item = ast::AssocItem::Fn(source.value); + if let Some(transformed_item) = get_transformed_assoc_item(ctx, assoc_item, impl_def) { + let transformed_fn = match transformed_item { + ast::AssocItem::Fn(func) => func, + _ => unreachable!(), + }; + + let function_decl = + function_declaration(&transformed_fn, source.file_id.is_macro()); + match ctx.config.snippet_cap { + Some(cap) => { + let snippet = format!("{function_decl} {{\n $0\n}}"); + item.snippet_edit(cap, TextEdit::replace(replacement_range, snippet)); + } + None => { + let header = format!("{function_decl} {{"); + item.text_edit(TextEdit::replace(replacement_range, header)); + } + }; + item.add_to(acc, ctx.db); + } + } + } } /// Transform a relevant associated item to inline generics from the impl, remove attrs and docs, etc. From 53451c2b76169532d5398614c5778c7bc4f68985 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 1 Sep 2024 11:10:13 +0200 Subject: [PATCH 0334/2194] move addr_from_alloc_id logic into its own function --- src/tools/miri/src/alloc_addresses/mod.rs | 211 +++++++++++----------- 1 file changed, 106 insertions(+), 105 deletions(-) diff --git a/src/tools/miri/src/alloc_addresses/mod.rs b/src/tools/miri/src/alloc_addresses/mod.rs index cb3929959f697..c19a962e6523e 100644 --- a/src/tools/miri/src/alloc_addresses/mod.rs +++ b/src/tools/miri/src/alloc_addresses/mod.rs @@ -5,7 +5,6 @@ mod reuse_pool; use std::cell::RefCell; use std::cmp::max; -use std::collections::hash_map::Entry; use rand::Rng; @@ -151,6 +150,95 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { } } + fn addr_from_alloc_id_uncached( + &self, + global_state: &mut GlobalStateInner, + alloc_id: AllocId, + memory_kind: MemoryKind, + ) -> InterpResult<'tcx, u64> { + let ecx = self.eval_context_ref(); + let mut rng = ecx.machine.rng.borrow_mut(); + let (size, align, kind) = ecx.get_alloc_info(alloc_id); + // This is either called immediately after allocation (and then cached), or when + // adjusting `tcx` pointers (which never get freed). So assert that we are looking + // at a live allocation. This also ensures that we never re-assign an address to an + // allocation that previously had an address, but then was freed and the address + // information was removed. + assert!(!matches!(kind, AllocKind::Dead)); + + // This allocation does not have a base address yet, pick or reuse one. + if ecx.machine.native_lib.is_some() { + // In native lib mode, we use the "real" address of the bytes for this allocation. + // This ensures the interpreted program and native code have the same view of memory. + let base_ptr = match kind { + AllocKind::LiveData => { + if ecx.tcx.try_get_global_alloc(alloc_id).is_some() { + // For new global allocations, we always pre-allocate the memory to be able use the machine address directly. + let prepared_bytes = MiriAllocBytes::zeroed(size, align) + .unwrap_or_else(|| { + panic!("Miri ran out of memory: cannot create allocation of {size:?} bytes") + }); + let ptr = prepared_bytes.as_ptr(); + // Store prepared allocation space to be picked up for use later. + global_state + .prepared_alloc_bytes + .try_insert(alloc_id, prepared_bytes) + .unwrap(); + ptr + } else { + ecx.get_alloc_bytes_unchecked_raw(alloc_id)? + } + } + AllocKind::Function | AllocKind::VTable => { + // Allocate some dummy memory to get a unique address for this function/vtable. + let alloc_bytes = + MiriAllocBytes::from_bytes(&[0u8; 1], Align::from_bytes(1).unwrap()); + let ptr = alloc_bytes.as_ptr(); + // Leak the underlying memory to ensure it remains unique. + std::mem::forget(alloc_bytes); + ptr + } + AllocKind::Dead => unreachable!(), + }; + // Ensure this pointer's provenance is exposed, so that it can be used by FFI code. + return Ok(base_ptr.expose_provenance().try_into().unwrap()); + } + // We are not in native lib mode, so we control the addresses ourselves. + if let Some((reuse_addr, clock)) = + global_state.reuse.take_addr(&mut *rng, size, align, memory_kind, ecx.active_thread()) + { + if let Some(clock) = clock { + ecx.acquire_clock(&clock); + } + Ok(reuse_addr) + } else { + // We have to pick a fresh address. + // Leave some space to the previous allocation, to give it some chance to be less aligned. + // We ensure that `(global_state.next_base_addr + slack) % 16` is uniformly distributed. + let slack = rng.gen_range(0..16); + // From next_base_addr + slack, round up to adjust for alignment. + let base_addr = global_state + .next_base_addr + .checked_add(slack) + .ok_or_else(|| err_exhaust!(AddressSpaceFull))?; + let base_addr = align_addr(base_addr, align.bytes()); + + // Remember next base address. If this allocation is zero-sized, leave a gap of at + // least 1 to avoid two allocations having the same base address. (The logic in + // `alloc_id_from_addr` assumes unique addresses, and different function/vtable pointers + // need to be distinguishable!) + global_state.next_base_addr = base_addr + .checked_add(max(size.bytes(), 1)) + .ok_or_else(|| err_exhaust!(AddressSpaceFull))?; + // Even if `Size` didn't overflow, we might still have filled up the address space. + if global_state.next_base_addr > ecx.target_usize_max() { + throw_exhaust!(AddressSpaceFull); + } + + Ok(base_addr) + } + } + fn addr_from_alloc_id( &self, alloc_id: AllocId, @@ -160,104 +248,16 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { let mut global_state = ecx.machine.alloc_addresses.borrow_mut(); let global_state = &mut *global_state; - Ok(match global_state.base_addr.entry(alloc_id) { - Entry::Occupied(entry) => *entry.get(), - Entry::Vacant(entry) => { - let mut rng = ecx.machine.rng.borrow_mut(); - let (size, align, kind) = ecx.get_alloc_info(alloc_id); - // This is either called immediately after allocation (and then cached), or when - // adjusting `tcx` pointers (which never get freed). So assert that we are looking - // at a live allocation. This also ensures that we never re-assign an address to an - // allocation that previously had an address, but then was freed and the address - // information was removed. - assert!(!matches!(kind, AllocKind::Dead)); - - // This allocation does not have a base address yet, pick or reuse one. - let base_addr = if ecx.machine.native_lib.is_some() { - // In native lib mode, we use the "real" address of the bytes for this allocation. - // This ensures the interpreted program and native code have the same view of memory. - match kind { - AllocKind::LiveData => { - let ptr = if ecx.tcx.try_get_global_alloc(alloc_id).is_some() { - // For new global allocations, we always pre-allocate the memory to be able use the machine address directly. - let prepared_bytes = MiriAllocBytes::zeroed(size, align) - .unwrap_or_else(|| { - panic!("Miri ran out of memory: cannot create allocation of {size:?} bytes") - }); - let ptr = prepared_bytes.as_ptr(); - // Store prepared allocation space to be picked up for use later. - global_state - .prepared_alloc_bytes - .try_insert(alloc_id, prepared_bytes) - .unwrap(); - ptr - } else { - ecx.get_alloc_bytes_unchecked_raw(alloc_id)? - }; - // Ensure this pointer's provenance is exposed, so that it can be used by FFI code. - ptr.expose_provenance().try_into().unwrap() - } - AllocKind::Function | AllocKind::VTable => { - // Allocate some dummy memory to get a unique address for this function/vtable. - let alloc_bytes = MiriAllocBytes::from_bytes( - &[0u8; 1], - Align::from_bytes(1).unwrap(), - ); - // We don't need to expose these bytes as nobody is allowed to access them. - let addr = alloc_bytes.as_ptr().addr().try_into().unwrap(); - // Leak the underlying memory to ensure it remains unique. - std::mem::forget(alloc_bytes); - addr - } - AllocKind::Dead => unreachable!(), - } - } else if let Some((reuse_addr, clock)) = global_state.reuse.take_addr( - &mut *rng, - size, - align, - memory_kind, - ecx.active_thread(), - ) { - if let Some(clock) = clock { - ecx.acquire_clock(&clock); - } - reuse_addr - } else { - // We have to pick a fresh address. - // Leave some space to the previous allocation, to give it some chance to be less aligned. - // We ensure that `(global_state.next_base_addr + slack) % 16` is uniformly distributed. - let slack = rng.gen_range(0..16); - // From next_base_addr + slack, round up to adjust for alignment. - let base_addr = global_state - .next_base_addr - .checked_add(slack) - .ok_or_else(|| err_exhaust!(AddressSpaceFull))?; - let base_addr = align_addr(base_addr, align.bytes()); - - // Remember next base address. If this allocation is zero-sized, leave a gap - // of at least 1 to avoid two allocations having the same base address. - // (The logic in `alloc_id_from_addr` assumes unique addresses, and different - // function/vtable pointers need to be distinguishable!) - global_state.next_base_addr = base_addr - .checked_add(max(size.bytes(), 1)) - .ok_or_else(|| err_exhaust!(AddressSpaceFull))?; - // Even if `Size` didn't overflow, we might still have filled up the address space. - if global_state.next_base_addr > ecx.target_usize_max() { - throw_exhaust!(AddressSpaceFull); - } - - base_addr - }; - trace!( - "Assigning base address {:#x} to allocation {:?} (size: {}, align: {})", - base_addr, - alloc_id, - size.bytes(), - align.bytes(), - ); + match global_state.base_addr.get(&alloc_id) { + Some(&addr) => Ok(addr), + None => { + // First time we're looking for the absolute address of this allocation. + let base_addr = + self.addr_from_alloc_id_uncached(global_state, alloc_id, memory_kind)?; + trace!("Assigning base address {:#x} to allocation {:?}", base_addr, alloc_id); // Store address in cache. - entry.insert(base_addr); + global_state.base_addr.try_insert(alloc_id, base_addr).unwrap(); // Also maintain the opposite mapping in `int_to_ptr_map`, ensuring we keep it sorted. // We have a fast-path for the common case that this address is bigger than all previous ones. @@ -275,9 +275,9 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { }; global_state.int_to_ptr_map.insert(pos, (base_addr, alloc_id)); - base_addr + Ok(base_addr) } - }) + } } } @@ -373,14 +373,15 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { align: Align, ) -> InterpResult<'tcx, MiriAllocBytes> { let ecx = self.eval_context_ref(); - Ok(if ecx.machine.native_lib.is_some() { + if ecx.machine.native_lib.is_some() { // In native lib mode, MiriAllocBytes for global allocations are handled via `prepared_alloc_bytes`. - // This additional call ensures that some `MiriAllocBytes` are always prepared. + // This additional call ensures that some `MiriAllocBytes` are always prepared, just in case + // this function gets called before the first time `addr_from_alloc_id` gets called. ecx.addr_from_alloc_id(id, kind)?; - let mut global_state = ecx.machine.alloc_addresses.borrow_mut(); // The memory we need here will have already been allocated during an earlier call to // `addr_from_alloc_id` for this allocation. So don't create a new `MiriAllocBytes` here, instead // fetch the previously prepared bytes from `prepared_alloc_bytes`. + let mut global_state = ecx.machine.alloc_addresses.borrow_mut(); let mut prepared_alloc_bytes = global_state .prepared_alloc_bytes .remove(&id) @@ -390,10 +391,10 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { assert_eq!(prepared_alloc_bytes.len(), bytes.len()); // Copy allocation contents into prepared memory. prepared_alloc_bytes.copy_from_slice(bytes); - prepared_alloc_bytes + Ok(prepared_alloc_bytes) } else { - MiriAllocBytes::from_bytes(std::borrow::Cow::Borrowed(&*bytes), align) - }) + Ok(MiriAllocBytes::from_bytes(std::borrow::Cow::Borrowed(bytes), align)) + } } /// When a pointer is used for a memory access, this computes where in which allocation the From 0e5628d7de217454052d5246e994590fa7b75a93 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 1 Sep 2024 11:21:37 +0200 Subject: [PATCH 0335/2194] tweak wording regarding Box validity --- library/alloc/src/boxed.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/library/alloc/src/boxed.rs b/library/alloc/src/boxed.rs index b3a3cf1bbeaaa..a924feaf15f2a 100644 --- a/library/alloc/src/boxed.rs +++ b/library/alloc/src/boxed.rs @@ -64,8 +64,9 @@ //! //! For zero-sized values, the `Box` pointer has to be non-null and sufficiently aligned. The //! recommended way to build a Box to a ZST if `Box::new` cannot be used is to use -//! [`ptr::NonNull::dangling`]. Even for zero-sized types, the pointee type must be inhabited -//! to ensure that the Box points to a valid value of the given type. +//! [`ptr::NonNull::dangling`]. +//! +//! On top of these basic layout requirements, a `Box` must point to a valid value of `T`. //! //! So long as `T: Sized`, a `Box` is guaranteed to be represented //! as a single pointer and is also ABI-compatible with C pointers From e233c3ae22ed5b2020b8b79e97d2fe6f1da6852e Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Sun, 1 Sep 2024 11:04:45 +0200 Subject: [PATCH 0336/2194] Complete desugared and resugared async fn in trait impls --- src/tools/rust-analyzer/crates/hir/src/lib.rs | 44 +-- .../src/completions/item_list/trait_impl.rs | 302 ++++++++++++++---- .../ide-completion/src/tests/item_list.rs | 1 + .../crates/syntax/src/ast/make.rs | 2 +- .../rust-analyzer/crates/syntax/src/ted.rs | 5 + 5 files changed, 267 insertions(+), 87 deletions(-) diff --git a/src/tools/rust-analyzer/crates/hir/src/lib.rs b/src/tools/rust-analyzer/crates/hir/src/lib.rs index 74ec5227b0ec6..9536f12558430 100644 --- a/src/tools/rust-analyzer/crates/hir/src/lib.rs +++ b/src/tools/rust-analyzer/crates/hir/src/lib.rs @@ -2207,51 +2207,33 @@ impl Function { db.function_data(self.id).is_async() } - /// Whether this function is a `fn` that returns `impl Future`. - pub fn is_desugar_async(self, db: &dyn HirDatabase) -> bool { - if self.is_async(db) || self.is_const(db) { - return false; + pub fn returns_impl_future(self, db: &dyn HirDatabase) -> bool { + if self.is_async(db) { + return true; } let Some(impl_traits) = self.ret_type(db).as_impl_traits(db) else { return false }; - let Some(future_trait_id) = db.lang_item(self.ty(db).env.krate, LangItem::Future).and_then(|t| t.as_trait()) else { return false; }; - - let Some(size_trait_id) = + let Some(sized_trait_id) = db.lang_item(self.ty(db).env.krate, LangItem::Sized).and_then(|t| t.as_trait()) else { return false; }; - let Some(sync_trait_id) = - db.lang_item(self.ty(db).env.krate, LangItem::Sync).and_then(|t| t.as_trait()) - else { - return false; - }; - - // TODO: There's no `LangItem::Send`. How do we get the id of `Send` trait? - // let Some(send_trait_id) = db.lang_item(self.ty(db).env.krate, LangItem::Send).and_then(|t| t.as_trait()) else { - // eprint!("no future_trait_id\n"); - // return false - // }; - - let allowed_to_leaked_types = vec![size_trait_id, sync_trait_id]; - let mut has_impl_future = false; - let mut has_types_not_allow_to_leaked = false; - for impl_trait in impl_traits { - if impl_trait.id == future_trait_id { - has_impl_future = true; - } else if !allowed_to_leaked_types.contains(&impl_trait.id) { - has_types_not_allow_to_leaked = true; - } - } - - has_impl_future && !has_types_not_allow_to_leaked + impl_traits + .filter(|t| { + let fut = t.id == future_trait_id; + has_impl_future |= fut; + !fut && t.id != sized_trait_id + }) + // all traits but the future trait must be auto traits + .all(|t| t.is_auto(db)) + && has_impl_future } /// Does this function have `#[test]` attribute? diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/item_list/trait_impl.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/item_list/trait_impl.rs index 7887a87448e2f..e93bb8db716f1 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/item_list/trait_impl.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/item_list/trait_impl.rs @@ -31,14 +31,14 @@ //! } //! ``` -use hir::HasAttrs; +use hir::{HasAttrs, Name}; use ide_db::{ documentation::HasDocs, path_transform::PathTransform, syntax_helpers::insert_whitespace_into_node, traits::get_missing_assoc_items, SymbolKind, }; use syntax::{ - ast::{self, edit_in_place::AttrsOwnerEdit, HasTypeBounds}, - format_smolstr, AstNode, SmolStr, SyntaxElement, SyntaxKind, TextRange, ToSmolStr, T, + ast::{self, edit_in_place::AttrsOwnerEdit, make, HasGenericArgs, HasTypeBounds}, + format_smolstr, ted, AstNode, SmolStr, SyntaxElement, SyntaxKind, TextRange, ToSmolStr, T, }; use text_edit::TextEdit; @@ -178,12 +178,36 @@ fn add_function_impl( func: hir::Function, impl_def: hir::Impl, ) { - let fn_name = func.name(ctx.db); + let fn_name = &func.name(ctx.db); + let sugar: &[_] = if func.is_async(ctx.db) { + &[AsyncSugaring::Async, AsyncSugaring::Desugar] + } else if func.returns_impl_future(ctx.db) { + &[AsyncSugaring::Plain, AsyncSugaring::Resugar] + } else { + &[AsyncSugaring::Plain] + }; + for &sugaring in sugar { + add_function_impl_(acc, ctx, replacement_range, func, impl_def, fn_name, sugaring); + } +} - let is_async = func.is_async(ctx.db); +fn add_function_impl_( + acc: &mut Completions, + ctx: &CompletionContext<'_>, + replacement_range: TextRange, + func: hir::Function, + impl_def: hir::Impl, + fn_name: &Name, + async_sugaring: AsyncSugaring, +) { + let async_ = if let AsyncSugaring::Async | AsyncSugaring::Resugar = async_sugaring { + "async " + } else { + "" + }; let label = format_smolstr!( "{}fn {}({})", - if is_async { "async " } else { "" }, + async_, fn_name.display(ctx.db, ctx.edition), if func.assoc_fn_params(ctx.db).is_empty() { "" } else { ".." } ); @@ -195,22 +219,14 @@ fn add_function_impl( }); let mut item = CompletionItem::new(completion_kind, replacement_range, label, ctx.edition); - item.lookup_by(format!( - "{}fn {}", - if is_async { "async " } else { "" }, - fn_name.display(ctx.db, ctx.edition) - )) - .set_documentation(func.docs(ctx.db)) - .set_relevance(CompletionRelevance { is_item_from_trait: true, ..Default::default() }); + item.lookup_by(format!("{}fn {}", async_, fn_name.display(ctx.db, ctx.edition))) + .set_documentation(func.docs(ctx.db)) + .set_relevance(CompletionRelevance { is_item_from_trait: true, ..Default::default() }); if let Some(source) = ctx.sema.source(func) { - let assoc_item = ast::AssocItem::Fn(source.value); - if let Some(transformed_item) = get_transformed_assoc_item(ctx, assoc_item, impl_def) { - let transformed_fn = match transformed_item { - ast::AssocItem::Fn(func) => func, - _ => unreachable!(), - }; - // TODO: need `function_decl` that unwraps future in the return type + if let Some(transformed_fn) = + get_transformed_fn(ctx, source.value, impl_def, async_sugaring) + { let function_decl = function_declaration(&transformed_fn, source.file_id.is_macro()); match ctx.config.snippet_cap { Some(cap) => { @@ -225,42 +241,14 @@ fn add_function_impl( item.add_to(acc, ctx.db); } } +} - eprint!("is_desugar_async: {}", func.is_desugar_async(ctx.db)); - if func.is_desugar_async(ctx.db) { - let label = format_smolstr!( - "async fn {}({})", - fn_name.display(ctx.db), - if func.assoc_fn_params(ctx.db).is_empty() { "" } else { ".." } - ); - let mut item = CompletionItem::new(completion_kind, replacement_range, label); - item.lookup_by(format!("async fn {}", fn_name.display(ctx.db))) - .set_documentation(func.docs(ctx.db)) - .set_relevance(CompletionRelevance { is_item_from_trait: true, ..Default::default() }); - if let Some(source) = ctx.sema.source(func) { - let assoc_item = ast::AssocItem::Fn(source.value); - if let Some(transformed_item) = get_transformed_assoc_item(ctx, assoc_item, impl_def) { - let transformed_fn = match transformed_item { - ast::AssocItem::Fn(func) => func, - _ => unreachable!(), - }; - - let function_decl = - function_declaration(&transformed_fn, source.file_id.is_macro()); - match ctx.config.snippet_cap { - Some(cap) => { - let snippet = format!("{function_decl} {{\n $0\n}}"); - item.snippet_edit(cap, TextEdit::replace(replacement_range, snippet)); - } - None => { - let header = format!("{function_decl} {{"); - item.text_edit(TextEdit::replace(replacement_range, header)); - } - }; - item.add_to(acc, ctx.db); - } - } - } +#[derive(Copy, Clone)] +enum AsyncSugaring { + Desugar, + Resugar, + Async, + Plain, } /// Transform a relevant associated item to inline generics from the impl, remove attrs and docs, etc. @@ -287,6 +275,82 @@ fn get_transformed_assoc_item( Some(assoc_item) } +/// Transform a relevant associated item to inline generics from the impl, remove attrs and docs, etc. +fn get_transformed_fn( + ctx: &CompletionContext<'_>, + fn_: ast::Fn, + impl_def: hir::Impl, + async_: AsyncSugaring, +) -> Option { + let trait_ = impl_def.trait_(ctx.db)?; + let source_scope = &ctx.sema.scope(fn_.syntax())?; + let target_scope = &ctx.sema.scope(ctx.sema.source(impl_def)?.syntax().value)?; + let transform = PathTransform::trait_impl( + target_scope, + source_scope, + trait_, + ctx.sema.source(impl_def)?.value, + ); + + let fn_ = fn_.clone_for_update(); + // FIXME: Paths in nested macros are not handled well. See + // `macro_generated_assoc_item2` test. + transform.apply(fn_.syntax()); + fn_.remove_attrs_and_docs(); + match async_ { + AsyncSugaring::Desugar => { + match fn_.ret_type() { + Some(ret_ty) => { + let ty = ret_ty.ty()?; + ted::replace( + ty.syntax(), + make::ty(&format!("impl Future")) + .syntax() + .clone_for_update(), + ); + } + None => ted::append_child( + fn_.param_list()?.syntax(), + make::ret_type(make::ty("impl Future")) + .syntax() + .clone_for_update(), + ), + } + fn_.async_token().unwrap().detach(); + } + AsyncSugaring::Resugar => { + let ty = fn_.ret_type()?.ty()?; + match &ty { + // best effort guessing here + ast::Type::ImplTraitType(t) => { + let output = t.type_bound_list()?.bounds().find_map(|b| match b.ty()? { + ast::Type::PathType(p) => { + let p = p.path()?.segment()?; + if p.name_ref()?.text() != "Future" { + return None; + } + match p.generic_arg_list()?.generic_args().next()? { + ast::GenericArg::AssocTypeArg(a) + if a.name_ref()?.text() == "Output" => + { + a.ty() + } + _ => None, + } + } + _ => None, + })?; + ted::replace(ty.syntax(), output.syntax()); + } + _ => (), + } + ted::prepend_child(fn_.syntax(), make::token(T![async])); + } + AsyncSugaring::Async | AsyncSugaring::Plain => (), + } + Some(fn_) +} + fn add_type_alias_impl( acc: &mut Completions, ctx: &CompletionContext<'_>, @@ -1437,6 +1501,134 @@ trait Tr { impl Tr for () { type Item = $0; } +"#, + ); + } + + #[test] + fn impl_fut() { + check_edit( + "fn foo", + r#" +//- minicore: future, send, sized +use core::future::Future; + +trait DesugaredAsyncTrait { + fn foo(&self) -> impl Future + Send; +} + +impl DesugaredAsyncTrait for () { + $0 +} +"#, + r#" +use core::future::Future; + +trait DesugaredAsyncTrait { + fn foo(&self) -> impl Future + Send; +} + +impl DesugaredAsyncTrait for () { + fn foo(&self) -> impl Future + Send { + $0 +} +} +"#, + ); + } + + #[test] + fn impl_fut_resugared() { + check_edit( + "async fn foo", + r#" +//- minicore: future, send, sized +use core::future::Future; + +trait DesugaredAsyncTrait { + fn foo(&self) -> impl Future + Send; +} + +impl DesugaredAsyncTrait for () { + $0 +} +"#, + r#" +use core::future::Future; + +trait DesugaredAsyncTrait { + fn foo(&self) -> impl Future + Send; +} + +impl DesugaredAsyncTrait for () { + async fn foo(&self) -> usize { + $0 +} +} +"#, + ); + } + + #[test] + fn async_desugared() { + check_edit( + "fn foo", + r#" +//- minicore: future, send, sized +use core::future::Future; + +trait DesugaredAsyncTrait { + async fn foo(&self) -> usize; +} + +impl DesugaredAsyncTrait for () { + $0 +} +"#, + r#" +use core::future::Future; + +trait DesugaredAsyncTrait { + async fn foo(&self) -> usize; +} + +impl DesugaredAsyncTrait for () { + fn foo(&self) -> impl Future { + $0 +} +} +"#, + ); + } + + #[test] + fn async_() { + check_edit( + "async fn foo", + r#" +//- minicore: future, send, sized +use core::future::Future; + +trait DesugaredAsyncTrait { + async fn foo(&self) -> usize; +} + +impl DesugaredAsyncTrait for () { + $0 +} +"#, + r#" +use core::future::Future; + +trait DesugaredAsyncTrait { + async fn foo(&self) -> usize; +} + +impl DesugaredAsyncTrait for () { + async fn foo(&self) -> usize { + $0 +} +} "#, ); } diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/tests/item_list.rs b/src/tools/rust-analyzer/crates/ide-completion/src/tests/item_list.rs index 8aad7bfc3adc9..532d4928eff99 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/tests/item_list.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/tests/item_list.rs @@ -313,6 +313,7 @@ impl Test for () { ct const CONST1: () = fn async fn function2() fn fn function1() + fn fn function2() ma makro!(…) macro_rules! makro md module ta type Type1 = diff --git a/src/tools/rust-analyzer/crates/syntax/src/ast/make.rs b/src/tools/rust-analyzer/crates/syntax/src/ast/make.rs index abf1a1f38207f..2eb9c1ec5a54b 100644 --- a/src/tools/rust-analyzer/crates/syntax/src/ast/make.rs +++ b/src/tools/rust-analyzer/crates/syntax/src/ast/make.rs @@ -1162,7 +1162,7 @@ pub mod tokens { pub(super) static SOURCE_FILE: LazyLock> = LazyLock::new(|| { SourceFile::parse( - "const C: <()>::Item = ( true && true , true || true , 1 != 1, 2 == 2, 3 < 3, 4 <= 4, 5 > 5, 6 >= 6, !true, *p, &p , &mut p, { let _ @ [] })\n;\n\nimpl A for B where: {}", Edition::CURRENT, + "const C: <()>::Item = ( true && true , true || true , 1 != 1, 2 == 2, 3 < 3, 4 <= 4, 5 > 5, 6 >= 6, !true, *p, &p , &mut p, async { let _ @ [] })\n;\n\nimpl A for B where: {}", Edition::CURRENT, ) }); diff --git a/src/tools/rust-analyzer/crates/syntax/src/ted.rs b/src/tools/rust-analyzer/crates/syntax/src/ted.rs index 29788d05e845f..8592df1597551 100644 --- a/src/tools/rust-analyzer/crates/syntax/src/ted.rs +++ b/src/tools/rust-analyzer/crates/syntax/src/ted.rs @@ -147,6 +147,11 @@ pub fn append_child_raw(node: &(impl Into + Clone), child: impl Elem insert_raw(position, child); } +pub fn prepend_child(node: &(impl Into + Clone), child: impl Element) { + let position = Position::first_child_of(node); + insert(position, child); +} + fn ws_before(position: &Position, new: &SyntaxElement) -> Option { let prev = match &position.repr { PositionRepr::FirstChild(_) => return None, From 61b0374cc43b75786e069c75f5fe92342fce4621 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Mon, 26 Aug 2024 10:07:11 +0200 Subject: [PATCH 0337/2194] minor: Reduce friction for updating minicore --- .../crates/ide/src/hover/tests.rs | 85 +++++++++++++------ 1 file changed, 58 insertions(+), 27 deletions(-) diff --git a/src/tools/rust-analyzer/crates/ide/src/hover/tests.rs b/src/tools/rust-analyzer/crates/ide/src/hover/tests.rs index d7ae6c7508789..9b934044ac0b7 100644 --- a/src/tools/rust-analyzer/crates/ide/src/hover/tests.rs +++ b/src/tools/rust-analyzer/crates/ide/src/hover/tests.rs @@ -182,13 +182,26 @@ fn check_hover_no_markdown(ra_fixture: &str, expect: Expect) { fn check_actions(ra_fixture: &str, expect: Expect) { let (analysis, file_id, position) = fixture::range_or_position(ra_fixture); - let hover = analysis + let mut hover = analysis .hover( &HoverConfig { links_in_hover: true, ..HOVER_BASE_CONFIG }, FileRange { file_id, range: position.range_or_empty() }, ) .unwrap() .unwrap(); + // stub out ranges into minicore as they can change every now and then + hover.info.actions.iter_mut().for_each(|action| match action { + super::HoverAction::GoToType(act) => act.iter_mut().for_each(|data| { + if data.nav.file_id == file_id { + return; + } + data.nav.full_range = TextRange::empty(span::TextSize::new(!0)); + if let Some(range) = &mut data.nav.focus_range { + *range = TextRange::empty(span::TextSize::new(!0)); + } + }), + _ => (), + }); expect.assert_debug_eq(&hover.info.actions) } @@ -200,10 +213,23 @@ fn check_hover_range(ra_fixture: &str, expect: Expect) { fn check_hover_range_actions(ra_fixture: &str, expect: Expect) { let (analysis, range) = fixture::range(ra_fixture); - let hover = analysis + let mut hover = analysis .hover(&HoverConfig { links_in_hover: true, ..HOVER_BASE_CONFIG }, range) .unwrap() .unwrap(); + // stub out ranges into minicore as they can change every now and then + hover.info.actions.iter_mut().for_each(|action| match action { + super::HoverAction::GoToType(act) => act.iter_mut().for_each(|data| { + if data.nav.file_id == range.file_id { + return; + } + data.nav.full_range = TextRange::empty(span::TextSize::new(!0)); + if let Some(range) = &mut data.nav.focus_range { + *range = TextRange::empty(span::TextSize::new(!0)); + } + }), + _ => (), + }); expect.assert_debug_eq(&hover.info.actions); } @@ -483,8 +509,13 @@ fn main() { file_id: FileId( 1, ), +<<<<<<< HEAD full_range: 633..868, focus_range: 694..700, +======= + full_range: 4294967295..4294967295, + focus_range: 4294967295..4294967295, +>>>>>>> 33e4a08d5b (minor: Reduce friction for updating minicore) name: "FnOnce", kind: Trait, container_name: "function", @@ -3104,26 +3135,26 @@ struct S{ f1: u32 } fn main() { let s$0t = S{ f1:0 }; } "#, expect![[r#" - [ - GoToType( - [ - HoverGotoTypeData { - mod_path: "test::S", - nav: NavigationTarget { - file_id: FileId( - 0, - ), - full_range: 0..19, - focus_range: 7..8, - name: "S", - kind: Struct, - description: "struct S", - }, + [ + GoToType( + [ + HoverGotoTypeData { + mod_path: "test::S", + nav: NavigationTarget { + file_id: FileId( + 0, + ), + full_range: 0..19, + focus_range: 7..8, + name: "S", + kind: Struct, + description: "struct S", }, - ], - ), - ] - "#]], + }, + ], + ), + ] + "#]], ); } @@ -3616,8 +3647,8 @@ pub mod future { file_id: FileId( 1, ), - full_range: 21..69, - focus_range: 60..66, + full_range: 4294967295..4294967295, + focus_range: 4294967295..4294967295, name: "Future", kind: Trait, container_name: "future", @@ -8479,8 +8510,8 @@ impl Iterator for S { file_id: FileId( 1, ), - full_range: 7802..8044, - focus_range: 7867..7873, + full_range: 4294967295..4294967295, + focus_range: 4294967295..4294967295, name: "Future", kind: Trait, container_name: "future", @@ -8493,8 +8524,8 @@ impl Iterator for S { file_id: FileId( 1, ), - full_range: 8674..9173, - focus_range: 8751..8759, + full_range: 4294967295..4294967295, + focus_range: 4294967295..4294967295, name: "Iterator", kind: Trait, container_name: "iterator", From 384aed834cd83bdd0e93a2ef5690d3e44bf15856 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sun, 1 Sep 2024 05:33:02 -0400 Subject: [PATCH 0338/2194] Do not call query to compute coroutine layout for synthetic body of async closure --- compiler/rustc_mir_transform/src/validate.rs | 13 ++++++++++++- .../async-closures/validate-synthetic-body.rs | 19 +++++++++++++++++++ 2 files changed, 31 insertions(+), 1 deletion(-) create mode 100644 tests/ui/async-await/async-closures/validate-synthetic-body.rs diff --git a/compiler/rustc_mir_transform/src/validate.rs b/compiler/rustc_mir_transform/src/validate.rs index 99e06f59dd04d..80410c6d690dd 100644 --- a/compiler/rustc_mir_transform/src/validate.rs +++ b/compiler/rustc_mir_transform/src/validate.rs @@ -1,6 +1,7 @@ //! Validates the MIR to ensure that invariants are upheld. use rustc_data_structures::fx::{FxHashMap, FxHashSet}; +use rustc_hir as hir; use rustc_hir::LangItem; use rustc_index::bit_set::BitSet; use rustc_index::IndexVec; @@ -714,7 +715,17 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { // since we may be in the process of computing this MIR in the // first place. let layout = if def_id == self.caller_body.source.def_id() { - // FIXME: This is not right for async closures. + self.caller_body.coroutine_layout_raw() + } else if let Some(hir::CoroutineKind::Desugared( + _, + hir::CoroutineSource::Closure, + )) = self.tcx.coroutine_kind(def_id) + && let ty::ClosureKind::FnOnce = + args.as_coroutine().kind_ty().to_opt_closure_kind().unwrap() + && self.caller_body.source.def_id() + == self.tcx.coroutine_by_move_body_def_id(def_id) + { + // Same if this is the by-move body of a coroutine-closure. self.caller_body.coroutine_layout_raw() } else { self.tcx.coroutine_layout(def_id, args.as_coroutine().kind_ty()) diff --git a/tests/ui/async-await/async-closures/validate-synthetic-body.rs b/tests/ui/async-await/async-closures/validate-synthetic-body.rs new file mode 100644 index 0000000000000..67e683ac08a22 --- /dev/null +++ b/tests/ui/async-await/async-closures/validate-synthetic-body.rs @@ -0,0 +1,19 @@ +//@ check-pass +//@ edition: 2021 + +#![feature(async_closure)] + +// Make sure that we don't hit a query cycle when validating +// the by-move coroutine body for an async closure. + +use std::future::Future; + +async fn test(operation: impl Fn() -> Fut) { + operation().await; +} + +pub async fn orchestrate_simple_crud() { + test(async || async {}.await).await; +} + +fn main() {} From 4ee58db2f10d370f8e7ccc4b1409440342f01c3e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Miku=C5=82a?= Date: Sun, 25 Aug 2024 13:33:50 +0200 Subject: [PATCH 0339/2194] Upgrade CI's mingw-w64 toolchain --- src/ci/scripts/install-mingw.sh | 4 ++-- tests/debuginfo/by-value-non-immediate-argument.rs | 1 + tests/debuginfo/method-on-enum.rs | 2 ++ 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/ci/scripts/install-mingw.sh b/src/ci/scripts/install-mingw.sh index 31aa3785bc369..91eab2e7a0816 100755 --- a/src/ci/scripts/install-mingw.sh +++ b/src/ci/scripts/install-mingw.sh @@ -6,8 +6,8 @@ IFS=$'\n\t' source "$(cd "$(dirname "$0")" && pwd)/../shared.sh" -MINGW_ARCHIVE_32="i686-12.2.0-release-posix-dwarf-rt_v10-rev0.7z" -MINGW_ARCHIVE_64="x86_64-12.2.0-release-posix-seh-rt_v10-rev0.7z" +MINGW_ARCHIVE_32="i686-14.1.0-release-posix-dwarf-msvcrt-rt_v12-rev0.7z" +MINGW_ARCHIVE_64="x86_64-14.1.0-release-posix-seh-msvcrt-rt_v12-rev0.7z" if isWindows && isKnownToBeMingwBuild; then case "${CI_JOB_NAME}" in diff --git a/tests/debuginfo/by-value-non-immediate-argument.rs b/tests/debuginfo/by-value-non-immediate-argument.rs index f0a39a45195a1..192f6efe7db6c 100644 --- a/tests/debuginfo/by-value-non-immediate-argument.rs +++ b/tests/debuginfo/by-value-non-immediate-argument.rs @@ -1,6 +1,7 @@ //@ min-lldb-version: 1800 //@ min-gdb-version: 13.0 //@ compile-flags:-g +//@ ignore-windows-gnu: #128973 // === GDB TESTS =================================================================================== diff --git a/tests/debuginfo/method-on-enum.rs b/tests/debuginfo/method-on-enum.rs index a570144450d70..754b4a2dc26c5 100644 --- a/tests/debuginfo/method-on-enum.rs +++ b/tests/debuginfo/method-on-enum.rs @@ -3,6 +3,8 @@ //@ compile-flags:-g +//@ ignore-windows-gnu: #128973 + // === GDB TESTS =================================================================================== // gdb-command:run From 19908ff7a37a9a431399bb6f2868efc22820f2b6 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 25 Aug 2024 15:15:15 +0200 Subject: [PATCH 0340/2194] stabilize const_float_bits_conv --- library/core/src/lib.rs | 3 +- library/core/src/num/f128.rs | 16 +-- library/core/src/num/f16.rs | 16 +-- library/core/src/num/f32.rs | 16 +-- library/core/src/num/f64.rs | 16 +-- .../clippy/clippy_lints/src/transmute/mod.rs | 6 +- .../src/transmute/transmute_float_to_int.rs | 3 +- .../src/transmute/transmute_int_to_float.rs | 3 +- .../src/transmute/transmute_num_to_bytes.rs | 6 - src/tools/clippy/tests/ui/transmute.rs | 12 ++ src/tools/clippy/tests/ui/transmute.stderr | 112 ++++++++++++++---- .../tests/ui/transmute_float_to_int.fixed | 28 +++-- .../clippy/tests/ui/transmute_float_to_int.rs | 12 +- .../tests/ui/transmute_float_to_int.stderr | 50 +++++++- tests/ui/consts/const-float-bits-conv.rs | 5 +- tests/ui/consts/const-float-classify.rs | 1 - tests/ui/consts/const-float-classify.stderr | 2 +- 17 files changed, 223 insertions(+), 84 deletions(-) diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index 06a745b690a4b..c3797c6adc990 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -122,7 +122,6 @@ #![feature(const_cell_into_inner)] #![feature(const_eval_select)] #![feature(const_exact_div)] -#![feature(const_float_bits_conv)] #![feature(const_float_classify)] #![feature(const_fmt_arguments_new)] #![feature(const_hash)] @@ -166,6 +165,8 @@ #![feature(coverage_attribute)] #![feature(do_not_recommend)] #![feature(duration_consts_float)] +#![feature(f128_const)] +#![feature(f16_const)] #![feature(internal_impls_macro)] #![feature(ip)] #![feature(is_ascii_octdigit)] diff --git a/library/core/src/num/f128.rs b/library/core/src/num/f128.rs index d4236e47bfe3b..1959628bd8f59 100644 --- a/library/core/src/num/f128.rs +++ b/library/core/src/num/f128.rs @@ -914,7 +914,7 @@ impl f128 { /// ``` #[inline] #[unstable(feature = "f128", issue = "116909")] - #[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")] + #[rustc_const_unstable(feature = "f128_const", issue = "116909")] #[must_use = "this returns the result of the operation, without modifying the original"] pub const fn to_bits(self) -> u128 { // SAFETY: `u128` is a plain old datatype so we can always transmute to it. @@ -963,7 +963,7 @@ impl f128 { #[inline] #[must_use] #[unstable(feature = "f128", issue = "116909")] - #[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")] + #[rustc_const_unstable(feature = "f128_const", issue = "116909")] pub const fn from_bits(v: u128) -> Self { // It turns out the safety issues with sNaN were overblown! Hooray! // SAFETY: `u128` is a plain old datatype so we can always transmute from it. @@ -990,7 +990,7 @@ impl f128 { /// ``` #[inline] #[unstable(feature = "f128", issue = "116909")] - #[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")] + #[rustc_const_unstable(feature = "f128_const", issue = "116909")] #[must_use = "this returns the result of the operation, without modifying the original"] pub const fn to_be_bytes(self) -> [u8; 16] { self.to_bits().to_be_bytes() @@ -1016,7 +1016,7 @@ impl f128 { /// ``` #[inline] #[unstable(feature = "f128", issue = "116909")] - #[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")] + #[rustc_const_unstable(feature = "f128_const", issue = "116909")] #[must_use = "this returns the result of the operation, without modifying the original"] pub const fn to_le_bytes(self) -> [u8; 16] { self.to_bits().to_le_bytes() @@ -1053,7 +1053,7 @@ impl f128 { /// ``` #[inline] #[unstable(feature = "f128", issue = "116909")] - #[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")] + #[rustc_const_unstable(feature = "f128_const", issue = "116909")] #[must_use = "this returns the result of the operation, without modifying the original"] pub const fn to_ne_bytes(self) -> [u8; 16] { self.to_bits().to_ne_bytes() @@ -1081,7 +1081,7 @@ impl f128 { #[inline] #[must_use] #[unstable(feature = "f128", issue = "116909")] - #[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")] + #[rustc_const_unstable(feature = "f128_const", issue = "116909")] pub const fn from_be_bytes(bytes: [u8; 16]) -> Self { Self::from_bits(u128::from_be_bytes(bytes)) } @@ -1108,7 +1108,7 @@ impl f128 { #[inline] #[must_use] #[unstable(feature = "f128", issue = "116909")] - #[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")] + #[rustc_const_unstable(feature = "f128_const", issue = "116909")] pub const fn from_le_bytes(bytes: [u8; 16]) -> Self { Self::from_bits(u128::from_le_bytes(bytes)) } @@ -1145,7 +1145,7 @@ impl f128 { #[inline] #[must_use] #[unstable(feature = "f128", issue = "116909")] - #[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")] + #[rustc_const_unstable(feature = "f128_const", issue = "116909")] pub const fn from_ne_bytes(bytes: [u8; 16]) -> Self { Self::from_bits(u128::from_ne_bytes(bytes)) } diff --git a/library/core/src/num/f16.rs b/library/core/src/num/f16.rs index 1e2f841aca733..9252e8c601558 100644 --- a/library/core/src/num/f16.rs +++ b/library/core/src/num/f16.rs @@ -925,7 +925,7 @@ impl f16 { /// ``` #[inline] #[unstable(feature = "f16", issue = "116909")] - #[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")] + #[rustc_const_unstable(feature = "f16_const", issue = "116909")] #[must_use = "this returns the result of the operation, without modifying the original"] pub const fn to_bits(self) -> u16 { // SAFETY: `u16` is a plain old datatype so we can always transmute to it. @@ -973,7 +973,7 @@ impl f16 { #[inline] #[must_use] #[unstable(feature = "f16", issue = "116909")] - #[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")] + #[rustc_const_unstable(feature = "f16_const", issue = "116909")] pub const fn from_bits(v: u16) -> Self { // It turns out the safety issues with sNaN were overblown! Hooray! // SAFETY: `u16` is a plain old datatype so we can always transmute from it. @@ -999,7 +999,7 @@ impl f16 { /// ``` #[inline] #[unstable(feature = "f16", issue = "116909")] - #[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")] + #[rustc_const_unstable(feature = "f16_const", issue = "116909")] #[must_use = "this returns the result of the operation, without modifying the original"] pub const fn to_be_bytes(self) -> [u8; 2] { self.to_bits().to_be_bytes() @@ -1024,7 +1024,7 @@ impl f16 { /// ``` #[inline] #[unstable(feature = "f16", issue = "116909")] - #[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")] + #[rustc_const_unstable(feature = "f16_const", issue = "116909")] #[must_use = "this returns the result of the operation, without modifying the original"] pub const fn to_le_bytes(self) -> [u8; 2] { self.to_bits().to_le_bytes() @@ -1062,7 +1062,7 @@ impl f16 { /// ``` #[inline] #[unstable(feature = "f16", issue = "116909")] - #[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")] + #[rustc_const_unstable(feature = "f16_const", issue = "116909")] #[must_use = "this returns the result of the operation, without modifying the original"] pub const fn to_ne_bytes(self) -> [u8; 2] { self.to_bits().to_ne_bytes() @@ -1086,7 +1086,7 @@ impl f16 { #[inline] #[must_use] #[unstable(feature = "f16", issue = "116909")] - #[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")] + #[rustc_const_unstable(feature = "f16_const", issue = "116909")] pub const fn from_be_bytes(bytes: [u8; 2]) -> Self { Self::from_bits(u16::from_be_bytes(bytes)) } @@ -1109,7 +1109,7 @@ impl f16 { #[inline] #[must_use] #[unstable(feature = "f16", issue = "116909")] - #[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")] + #[rustc_const_unstable(feature = "f16_const", issue = "116909")] pub const fn from_le_bytes(bytes: [u8; 2]) -> Self { Self::from_bits(u16::from_le_bytes(bytes)) } @@ -1143,7 +1143,7 @@ impl f16 { #[inline] #[must_use] #[unstable(feature = "f16", issue = "116909")] - #[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")] + #[rustc_const_unstable(feature = "f16_const", issue = "116909")] pub const fn from_ne_bytes(bytes: [u8; 2]) -> Self { Self::from_bits(u16::from_ne_bytes(bytes)) } diff --git a/library/core/src/num/f32.rs b/library/core/src/num/f32.rs index c1adcc753f2e5..2bc897224970d 100644 --- a/library/core/src/num/f32.rs +++ b/library/core/src/num/f32.rs @@ -1115,7 +1115,7 @@ impl f32 { #[must_use = "this returns the result of the operation, \ without modifying the original"] #[stable(feature = "float_bits_conv", since = "1.20.0")] - #[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")] + #[rustc_const_stable(feature = "const_float_bits_conv", since = "CURRENT_RUSTC_VERSION")] #[inline] pub const fn to_bits(self) -> u32 { // SAFETY: `u32` is a plain old datatype so we can always transmute to it. @@ -1159,7 +1159,7 @@ impl f32 { /// assert_eq!(v, 12.5); /// ``` #[stable(feature = "float_bits_conv", since = "1.20.0")] - #[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")] + #[rustc_const_stable(feature = "const_float_bits_conv", since = "CURRENT_RUSTC_VERSION")] #[must_use] #[inline] pub const fn from_bits(v: u32) -> Self { @@ -1183,7 +1183,7 @@ impl f32 { #[must_use = "this returns the result of the operation, \ without modifying the original"] #[stable(feature = "float_to_from_bytes", since = "1.40.0")] - #[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")] + #[rustc_const_stable(feature = "const_float_bits_conv", since = "CURRENT_RUSTC_VERSION")] #[inline] pub const fn to_be_bytes(self) -> [u8; 4] { self.to_bits().to_be_bytes() @@ -1204,7 +1204,7 @@ impl f32 { #[must_use = "this returns the result of the operation, \ without modifying the original"] #[stable(feature = "float_to_from_bytes", since = "1.40.0")] - #[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")] + #[rustc_const_stable(feature = "const_float_bits_conv", since = "CURRENT_RUSTC_VERSION")] #[inline] pub const fn to_le_bytes(self) -> [u8; 4] { self.to_bits().to_le_bytes() @@ -1238,7 +1238,7 @@ impl f32 { #[must_use = "this returns the result of the operation, \ without modifying the original"] #[stable(feature = "float_to_from_bytes", since = "1.40.0")] - #[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")] + #[rustc_const_stable(feature = "const_float_bits_conv", since = "CURRENT_RUSTC_VERSION")] #[inline] pub const fn to_ne_bytes(self) -> [u8; 4] { self.to_bits().to_ne_bytes() @@ -1256,7 +1256,7 @@ impl f32 { /// assert_eq!(value, 12.5); /// ``` #[stable(feature = "float_to_from_bytes", since = "1.40.0")] - #[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")] + #[rustc_const_stable(feature = "const_float_bits_conv", since = "CURRENT_RUSTC_VERSION")] #[must_use] #[inline] pub const fn from_be_bytes(bytes: [u8; 4]) -> Self { @@ -1275,7 +1275,7 @@ impl f32 { /// assert_eq!(value, 12.5); /// ``` #[stable(feature = "float_to_from_bytes", since = "1.40.0")] - #[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")] + #[rustc_const_stable(feature = "const_float_bits_conv", since = "CURRENT_RUSTC_VERSION")] #[must_use] #[inline] pub const fn from_le_bytes(bytes: [u8; 4]) -> Self { @@ -1305,7 +1305,7 @@ impl f32 { /// assert_eq!(value, 12.5); /// ``` #[stable(feature = "float_to_from_bytes", since = "1.40.0")] - #[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")] + #[rustc_const_stable(feature = "const_float_bits_conv", since = "CURRENT_RUSTC_VERSION")] #[must_use] #[inline] pub const fn from_ne_bytes(bytes: [u8; 4]) -> Self { diff --git a/library/core/src/num/f64.rs b/library/core/src/num/f64.rs index e6406771ad333..b3f5be9fc8a46 100644 --- a/library/core/src/num/f64.rs +++ b/library/core/src/num/f64.rs @@ -1111,7 +1111,7 @@ impl f64 { #[must_use = "this returns the result of the operation, \ without modifying the original"] #[stable(feature = "float_bits_conv", since = "1.20.0")] - #[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")] + #[rustc_const_stable(feature = "const_float_bits_conv", since = "CURRENT_RUSTC_VERSION")] #[inline] pub const fn to_bits(self) -> u64 { // SAFETY: `u64` is a plain old datatype so we can always transmute to it. @@ -1155,7 +1155,7 @@ impl f64 { /// assert_eq!(v, 12.5); /// ``` #[stable(feature = "float_bits_conv", since = "1.20.0")] - #[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")] + #[rustc_const_stable(feature = "const_float_bits_conv", since = "CURRENT_RUSTC_VERSION")] #[must_use] #[inline] pub const fn from_bits(v: u64) -> Self { @@ -1179,7 +1179,7 @@ impl f64 { #[must_use = "this returns the result of the operation, \ without modifying the original"] #[stable(feature = "float_to_from_bytes", since = "1.40.0")] - #[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")] + #[rustc_const_stable(feature = "const_float_bits_conv", since = "CURRENT_RUSTC_VERSION")] #[inline] pub const fn to_be_bytes(self) -> [u8; 8] { self.to_bits().to_be_bytes() @@ -1200,7 +1200,7 @@ impl f64 { #[must_use = "this returns the result of the operation, \ without modifying the original"] #[stable(feature = "float_to_from_bytes", since = "1.40.0")] - #[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")] + #[rustc_const_stable(feature = "const_float_bits_conv", since = "CURRENT_RUSTC_VERSION")] #[inline] pub const fn to_le_bytes(self) -> [u8; 8] { self.to_bits().to_le_bytes() @@ -1234,7 +1234,7 @@ impl f64 { #[must_use = "this returns the result of the operation, \ without modifying the original"] #[stable(feature = "float_to_from_bytes", since = "1.40.0")] - #[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")] + #[rustc_const_stable(feature = "const_float_bits_conv", since = "CURRENT_RUSTC_VERSION")] #[inline] pub const fn to_ne_bytes(self) -> [u8; 8] { self.to_bits().to_ne_bytes() @@ -1252,7 +1252,7 @@ impl f64 { /// assert_eq!(value, 12.5); /// ``` #[stable(feature = "float_to_from_bytes", since = "1.40.0")] - #[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")] + #[rustc_const_stable(feature = "const_float_bits_conv", since = "CURRENT_RUSTC_VERSION")] #[must_use] #[inline] pub const fn from_be_bytes(bytes: [u8; 8]) -> Self { @@ -1271,7 +1271,7 @@ impl f64 { /// assert_eq!(value, 12.5); /// ``` #[stable(feature = "float_to_from_bytes", since = "1.40.0")] - #[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")] + #[rustc_const_stable(feature = "const_float_bits_conv", since = "CURRENT_RUSTC_VERSION")] #[must_use] #[inline] pub const fn from_le_bytes(bytes: [u8; 8]) -> Self { @@ -1301,7 +1301,7 @@ impl f64 { /// assert_eq!(value, 12.5); /// ``` #[stable(feature = "float_to_from_bytes", since = "1.40.0")] - #[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")] + #[rustc_const_stable(feature = "const_float_bits_conv", since = "CURRENT_RUSTC_VERSION")] #[must_use] #[inline] pub const fn from_ne_bytes(bytes: [u8; 8]) -> Self { diff --git a/src/tools/clippy/clippy_lints/src/transmute/mod.rs b/src/tools/clippy/clippy_lints/src/transmute/mod.rs index 373bf61d8ff94..a2ae36cc484ad 100644 --- a/src/tools/clippy/clippy_lints/src/transmute/mod.rs +++ b/src/tools/clippy/clippy_lints/src/transmute/mod.rs @@ -619,10 +619,10 @@ impl<'tcx> LateLintPass<'tcx> for Transmute { | transmute_ref_to_ref::check(cx, e, from_ty, to_ty, arg, const_context) | transmute_ptr_to_ptr::check(cx, e, from_ty, to_ty, arg, &self.msrv) | transmute_int_to_bool::check(cx, e, from_ty, to_ty, arg) - | transmute_int_to_float::check(cx, e, from_ty, to_ty, arg, const_context) + | transmute_int_to_float::check(cx, e, from_ty, to_ty, arg) | transmute_int_to_non_zero::check(cx, e, from_ty, to_ty, arg) - | transmute_float_to_int::check(cx, e, from_ty, to_ty, arg, const_context) - | transmute_num_to_bytes::check(cx, e, from_ty, to_ty, arg, const_context) + | transmute_float_to_int::check(cx, e, from_ty, to_ty, arg) + | transmute_num_to_bytes::check(cx, e, from_ty, to_ty, arg) | (unsound_collection_transmute::check(cx, e, from_ty, to_ty) || transmute_undefined_repr::check(cx, e, from_ty, to_ty)) | (eager_transmute::check(cx, e, arg, from_ty, to_ty)); diff --git a/src/tools/clippy/clippy_lints/src/transmute/transmute_float_to_int.rs b/src/tools/clippy/clippy_lints/src/transmute/transmute_float_to_int.rs index ab3bb5e1062d3..cb46109c27e2f 100644 --- a/src/tools/clippy/clippy_lints/src/transmute/transmute_float_to_int.rs +++ b/src/tools/clippy/clippy_lints/src/transmute/transmute_float_to_int.rs @@ -15,10 +15,9 @@ pub(super) fn check<'tcx>( from_ty: Ty<'tcx>, to_ty: Ty<'tcx>, mut arg: &'tcx Expr<'_>, - const_context: bool, ) -> bool { match (&from_ty.kind(), &to_ty.kind()) { - (ty::Float(float_ty), ty::Int(_) | ty::Uint(_)) if !const_context => { + (ty::Float(float_ty), ty::Int(_) | ty::Uint(_)) => { span_lint_and_then( cx, TRANSMUTE_FLOAT_TO_INT, diff --git a/src/tools/clippy/clippy_lints/src/transmute/transmute_int_to_float.rs b/src/tools/clippy/clippy_lints/src/transmute/transmute_int_to_float.rs index d51888e30971b..e00fb90c3074e 100644 --- a/src/tools/clippy/clippy_lints/src/transmute/transmute_int_to_float.rs +++ b/src/tools/clippy/clippy_lints/src/transmute/transmute_int_to_float.rs @@ -14,10 +14,9 @@ pub(super) fn check<'tcx>( from_ty: Ty<'tcx>, to_ty: Ty<'tcx>, arg: &'tcx Expr<'_>, - const_context: bool, ) -> bool { match (&from_ty.kind(), &to_ty.kind()) { - (ty::Int(_) | ty::Uint(_), ty::Float(_)) if !const_context => { + (ty::Int(_) | ty::Uint(_), ty::Float(_)) => { span_lint_and_then( cx, TRANSMUTE_INT_TO_FLOAT, diff --git a/src/tools/clippy/clippy_lints/src/transmute/transmute_num_to_bytes.rs b/src/tools/clippy/clippy_lints/src/transmute/transmute_num_to_bytes.rs index 88b0ac5a36887..362f2bb6960a2 100644 --- a/src/tools/clippy/clippy_lints/src/transmute/transmute_num_to_bytes.rs +++ b/src/tools/clippy/clippy_lints/src/transmute/transmute_num_to_bytes.rs @@ -14,18 +14,12 @@ pub(super) fn check<'tcx>( from_ty: Ty<'tcx>, to_ty: Ty<'tcx>, arg: &'tcx Expr<'_>, - const_context: bool, ) -> bool { match (&from_ty.kind(), &to_ty.kind()) { (ty::Int(_) | ty::Uint(_) | ty::Float(_), ty::Array(arr_ty, _)) => { if !matches!(arr_ty.kind(), ty::Uint(UintTy::U8)) { return false; } - if matches!(from_ty.kind(), ty::Float(_)) && const_context { - // TODO: Remove when const_float_bits_conv is stabilized - // rust#72447 - return false; - } span_lint_and_then( cx, diff --git a/src/tools/clippy/tests/ui/transmute.rs b/src/tools/clippy/tests/ui/transmute.rs index 46629526367ec..eeea3f080b1c9 100644 --- a/src/tools/clippy/tests/ui/transmute.rs +++ b/src/tools/clippy/tests/ui/transmute.rs @@ -140,24 +140,32 @@ mod int_to_float { mod issue_5747 { const VALUE16: f16 = unsafe { std::mem::transmute(0_u16) }; + //~^ ERROR: transmute from a `u16` to a `f16` const VALUE32: f32 = unsafe { std::mem::transmute(0_u32) }; + //~^ ERROR: transmute from a `u32` to a `f32` const VALUE64: f64 = unsafe { std::mem::transmute(0_i64) }; + //~^ ERROR: transmute from a `i64` to a `f64` const VALUE128: f128 = unsafe { std::mem::transmute(0_i128) }; + //~^ ERROR: transmute from a `i128` to a `f128` const fn from_bits_16(v: i16) -> f16 { unsafe { std::mem::transmute(v) } + //~^ ERROR: transmute from a `i16` to a `f16` } const fn from_bits_32(v: i32) -> f32 { unsafe { std::mem::transmute(v) } + //~^ ERROR: transmute from a `i32` to a `f32` } const fn from_bits_64(v: u64) -> f64 { unsafe { std::mem::transmute(v) } + //~^ ERROR: transmute from a `u64` to a `f64` } const fn from_bits_128(v: u128) -> f128 { unsafe { std::mem::transmute(v) } + //~^ ERROR: transmute from a `u128` to a `f128` } } } @@ -205,9 +213,13 @@ mod num_to_bytes { //~^ ERROR: transmute from a `i128` to a `[u8; 16]` let _: [u8; 2] = std::mem::transmute(0.0f16); + //~^ ERROR: transmute from a `f16` to a `[u8; 2]` let _: [u8; 4] = std::mem::transmute(0.0f32); + //~^ ERROR: transmute from a `f32` to a `[u8; 4]` let _: [u8; 8] = std::mem::transmute(0.0f64); + //~^ ERROR: transmute from a `f64` to a `[u8; 8]` let _: [u8; 16] = std::mem::transmute(0.0f128); + //~^ ERROR: transmute from a `f128` to a `[u8; 16]` } } } diff --git a/src/tools/clippy/tests/ui/transmute.stderr b/src/tools/clippy/tests/ui/transmute.stderr index 0072f62962a7d..41a10f381dc53 100644 --- a/src/tools/clippy/tests/ui/transmute.stderr +++ b/src/tools/clippy/tests/ui/transmute.stderr @@ -148,8 +148,56 @@ error: transmute from a `i128` to a `f128` LL | let _: f128 = unsafe { std::mem::transmute(0_i128) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `f128::from_bits(0_i128 as u128)` +error: transmute from a `u16` to a `f16` + --> tests/ui/transmute.rs:142:39 + | +LL | const VALUE16: f16 = unsafe { std::mem::transmute(0_u16) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `f16::from_bits(0_u16)` + +error: transmute from a `u32` to a `f32` + --> tests/ui/transmute.rs:144:39 + | +LL | const VALUE32: f32 = unsafe { std::mem::transmute(0_u32) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `f32::from_bits(0_u32)` + +error: transmute from a `i64` to a `f64` + --> tests/ui/transmute.rs:146:39 + | +LL | const VALUE64: f64 = unsafe { std::mem::transmute(0_i64) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `f64::from_bits(0_i64 as u64)` + +error: transmute from a `i128` to a `f128` + --> tests/ui/transmute.rs:148:41 + | +LL | const VALUE128: f128 = unsafe { std::mem::transmute(0_i128) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `f128::from_bits(0_i128 as u128)` + +error: transmute from a `i16` to a `f16` + --> tests/ui/transmute.rs:152:22 + | +LL | unsafe { std::mem::transmute(v) } + | ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `f16::from_bits(v as u16)` + +error: transmute from a `i32` to a `f32` + --> tests/ui/transmute.rs:157:22 + | +LL | unsafe { std::mem::transmute(v) } + | ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `f32::from_bits(v as u32)` + +error: transmute from a `u64` to a `f64` + --> tests/ui/transmute.rs:162:22 + | +LL | unsafe { std::mem::transmute(v) } + | ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `f64::from_bits(v)` + +error: transmute from a `u128` to a `f128` + --> tests/ui/transmute.rs:167:22 + | +LL | unsafe { std::mem::transmute(v) } + | ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `f128::from_bits(v)` + error: transmute from a `u8` to a `[u8; 1]` - --> tests/ui/transmute.rs:168:30 + --> tests/ui/transmute.rs:176:30 | LL | let _: [u8; 1] = std::mem::transmute(0u8); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0u8.to_ne_bytes()` @@ -158,97 +206,121 @@ LL | let _: [u8; 1] = std::mem::transmute(0u8); = help: to override `-D warnings` add `#[allow(clippy::transmute_num_to_bytes)]` error: transmute from a `u32` to a `[u8; 4]` - --> tests/ui/transmute.rs:171:30 + --> tests/ui/transmute.rs:179:30 | LL | let _: [u8; 4] = std::mem::transmute(0u32); | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0u32.to_ne_bytes()` error: transmute from a `u128` to a `[u8; 16]` - --> tests/ui/transmute.rs:173:31 + --> tests/ui/transmute.rs:181:31 | LL | let _: [u8; 16] = std::mem::transmute(0u128); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0u128.to_ne_bytes()` error: transmute from a `i8` to a `[u8; 1]` - --> tests/ui/transmute.rs:175:30 + --> tests/ui/transmute.rs:183:30 | LL | let _: [u8; 1] = std::mem::transmute(0i8); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0i8.to_ne_bytes()` error: transmute from a `i32` to a `[u8; 4]` - --> tests/ui/transmute.rs:177:30 + --> tests/ui/transmute.rs:185:30 | LL | let _: [u8; 4] = std::mem::transmute(0i32); | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0i32.to_ne_bytes()` error: transmute from a `i128` to a `[u8; 16]` - --> tests/ui/transmute.rs:179:31 + --> tests/ui/transmute.rs:187:31 | LL | let _: [u8; 16] = std::mem::transmute(0i128); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0i128.to_ne_bytes()` error: transmute from a `f16` to a `[u8; 2]` - --> tests/ui/transmute.rs:182:30 + --> tests/ui/transmute.rs:190:30 | LL | let _: [u8; 2] = std::mem::transmute(0.0f16); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0.0f16.to_ne_bytes()` error: transmute from a `f32` to a `[u8; 4]` - --> tests/ui/transmute.rs:184:30 + --> tests/ui/transmute.rs:192:30 | LL | let _: [u8; 4] = std::mem::transmute(0.0f32); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0.0f32.to_ne_bytes()` error: transmute from a `f64` to a `[u8; 8]` - --> tests/ui/transmute.rs:186:30 + --> tests/ui/transmute.rs:194:30 | LL | let _: [u8; 8] = std::mem::transmute(0.0f64); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0.0f64.to_ne_bytes()` error: transmute from a `f128` to a `[u8; 16]` - --> tests/ui/transmute.rs:188:31 + --> tests/ui/transmute.rs:196:31 | LL | let _: [u8; 16] = std::mem::transmute(0.0f128); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0.0f128.to_ne_bytes()` error: transmute from a `u8` to a `[u8; 1]` - --> tests/ui/transmute.rs:194:30 + --> tests/ui/transmute.rs:202:30 | LL | let _: [u8; 1] = std::mem::transmute(0u8); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0u8.to_ne_bytes()` error: transmute from a `u32` to a `[u8; 4]` - --> tests/ui/transmute.rs:196:30 + --> tests/ui/transmute.rs:204:30 | LL | let _: [u8; 4] = std::mem::transmute(0u32); | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0u32.to_ne_bytes()` error: transmute from a `u128` to a `[u8; 16]` - --> tests/ui/transmute.rs:198:31 + --> tests/ui/transmute.rs:206:31 | LL | let _: [u8; 16] = std::mem::transmute(0u128); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0u128.to_ne_bytes()` error: transmute from a `i8` to a `[u8; 1]` - --> tests/ui/transmute.rs:200:30 + --> tests/ui/transmute.rs:208:30 | LL | let _: [u8; 1] = std::mem::transmute(0i8); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0i8.to_ne_bytes()` error: transmute from a `i32` to a `[u8; 4]` - --> tests/ui/transmute.rs:202:30 + --> tests/ui/transmute.rs:210:30 | LL | let _: [u8; 4] = std::mem::transmute(0i32); | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0i32.to_ne_bytes()` error: transmute from a `i128` to a `[u8; 16]` - --> tests/ui/transmute.rs:204:31 + --> tests/ui/transmute.rs:212:31 | LL | let _: [u8; 16] = std::mem::transmute(0i128); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0i128.to_ne_bytes()` +error: transmute from a `f16` to a `[u8; 2]` + --> tests/ui/transmute.rs:215:30 + | +LL | let _: [u8; 2] = std::mem::transmute(0.0f16); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0.0f16.to_ne_bytes()` + +error: transmute from a `f32` to a `[u8; 4]` + --> tests/ui/transmute.rs:217:30 + | +LL | let _: [u8; 4] = std::mem::transmute(0.0f32); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0.0f32.to_ne_bytes()` + +error: transmute from a `f64` to a `[u8; 8]` + --> tests/ui/transmute.rs:219:30 + | +LL | let _: [u8; 8] = std::mem::transmute(0.0f64); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0.0f64.to_ne_bytes()` + +error: transmute from a `f128` to a `[u8; 16]` + --> tests/ui/transmute.rs:221:31 + | +LL | let _: [u8; 16] = std::mem::transmute(0.0f128); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0.0f128.to_ne_bytes()` + error: transmute from a `&[u8]` to a `&str` - --> tests/ui/transmute.rs:218:28 + --> tests/ui/transmute.rs:230:28 | LL | let _: &str = unsafe { std::mem::transmute(B) }; | ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::str::from_utf8(B).unwrap()` @@ -257,16 +329,16 @@ LL | let _: &str = unsafe { std::mem::transmute(B) }; = help: to override `-D warnings` add `#[allow(clippy::transmute_bytes_to_str)]` error: transmute from a `&mut [u8]` to a `&mut str` - --> tests/ui/transmute.rs:221:32 + --> tests/ui/transmute.rs:233:32 | LL | let _: &mut str = unsafe { std::mem::transmute(mb) }; | ^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::str::from_utf8_mut(mb).unwrap()` error: transmute from a `&[u8]` to a `&str` - --> tests/ui/transmute.rs:223:30 + --> tests/ui/transmute.rs:235:30 | LL | const _: &str = unsafe { std::mem::transmute(B) }; | ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::str::from_utf8_unchecked(B)` -error: aborting due to 42 previous errors +error: aborting due to 54 previous errors diff --git a/src/tools/clippy/tests/ui/transmute_float_to_int.fixed b/src/tools/clippy/tests/ui/transmute_float_to_int.fixed index 4361a7407d115..83814ca43b96d 100644 --- a/src/tools/clippy/tests/ui/transmute_float_to_int.fixed +++ b/src/tools/clippy/tests/ui/transmute_float_to_int.fixed @@ -1,7 +1,7 @@ #![warn(clippy::transmute_float_to_int)] #![allow(clippy::missing_transmute_annotations)] -#![feature(f128)] -#![feature(f16)] +#![feature(f128, f128_const)] +#![feature(f16, f16_const)] fn float_to_int() { let _: u32 = unsafe { 1f32.to_bits() }; @@ -20,25 +20,33 @@ fn float_to_int() { } mod issue_5747 { - const VALUE16: i16 = unsafe { std::mem::transmute(1f16) }; - const VALUE32: i32 = unsafe { std::mem::transmute(1f32) }; - const VALUE64: u64 = unsafe { std::mem::transmute(1f64) }; - const VALUE128: u128 = unsafe { std::mem::transmute(1f128) }; + const VALUE16: i16 = unsafe { 1f16.to_bits() as i16 }; + //~^ ERROR: transmute from a `f16` to a `i16` + const VALUE32: i32 = unsafe { 1f32.to_bits() as i32 }; + //~^ ERROR: transmute from a `f32` to a `i32` + const VALUE64: u64 = unsafe { 1f64.to_bits() }; + //~^ ERROR: transmute from a `f64` to a `u64` + const VALUE128: u128 = unsafe { 1f128.to_bits() }; + //~^ ERROR: transmute from a `f128` to a `u128` const fn to_bits_16(v: f16) -> u16 { - unsafe { std::mem::transmute(v) } + unsafe { v.to_bits() } + //~^ ERROR: transmute from a `f16` to a `u16` } const fn to_bits_32(v: f32) -> u32 { - unsafe { std::mem::transmute(v) } + unsafe { v.to_bits() } + //~^ ERROR: transmute from a `f32` to a `u32` } const fn to_bits_64(v: f64) -> i64 { - unsafe { std::mem::transmute(v) } + unsafe { v.to_bits() as i64 } + //~^ ERROR: transmute from a `f64` to a `i64` } const fn to_bits_128(v: f128) -> i128 { - unsafe { std::mem::transmute(v) } + unsafe { v.to_bits() as i128 } + //~^ ERROR: transmute from a `f128` to a `i128` } } diff --git a/src/tools/clippy/tests/ui/transmute_float_to_int.rs b/src/tools/clippy/tests/ui/transmute_float_to_int.rs index 363ce0bcb16d0..64d6e9172039d 100644 --- a/src/tools/clippy/tests/ui/transmute_float_to_int.rs +++ b/src/tools/clippy/tests/ui/transmute_float_to_int.rs @@ -1,7 +1,7 @@ #![warn(clippy::transmute_float_to_int)] #![allow(clippy::missing_transmute_annotations)] -#![feature(f128)] -#![feature(f16)] +#![feature(f128, f128_const)] +#![feature(f16, f16_const)] fn float_to_int() { let _: u32 = unsafe { std::mem::transmute(1f32) }; @@ -21,24 +21,32 @@ fn float_to_int() { mod issue_5747 { const VALUE16: i16 = unsafe { std::mem::transmute(1f16) }; + //~^ ERROR: transmute from a `f16` to a `i16` const VALUE32: i32 = unsafe { std::mem::transmute(1f32) }; + //~^ ERROR: transmute from a `f32` to a `i32` const VALUE64: u64 = unsafe { std::mem::transmute(1f64) }; + //~^ ERROR: transmute from a `f64` to a `u64` const VALUE128: u128 = unsafe { std::mem::transmute(1f128) }; + //~^ ERROR: transmute from a `f128` to a `u128` const fn to_bits_16(v: f16) -> u16 { unsafe { std::mem::transmute(v) } + //~^ ERROR: transmute from a `f16` to a `u16` } const fn to_bits_32(v: f32) -> u32 { unsafe { std::mem::transmute(v) } + //~^ ERROR: transmute from a `f32` to a `u32` } const fn to_bits_64(v: f64) -> i64 { unsafe { std::mem::transmute(v) } + //~^ ERROR: transmute from a `f64` to a `i64` } const fn to_bits_128(v: f128) -> i128 { unsafe { std::mem::transmute(v) } + //~^ ERROR: transmute from a `f128` to a `i128` } } diff --git a/src/tools/clippy/tests/ui/transmute_float_to_int.stderr b/src/tools/clippy/tests/ui/transmute_float_to_int.stderr index 9cac75f72cdd7..0cabab58ab08c 100644 --- a/src/tools/clippy/tests/ui/transmute_float_to_int.stderr +++ b/src/tools/clippy/tests/ui/transmute_float_to_int.stderr @@ -37,5 +37,53 @@ error: transmute from a `f64` to a `u64` LL | let _: u64 = unsafe { std::mem::transmute(-1.0) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `(-1.0f64).to_bits()` -error: aborting due to 6 previous errors +error: transmute from a `f16` to a `i16` + --> tests/ui/transmute_float_to_int.rs:23:35 + | +LL | const VALUE16: i16 = unsafe { std::mem::transmute(1f16) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `1f16.to_bits() as i16` + +error: transmute from a `f32` to a `i32` + --> tests/ui/transmute_float_to_int.rs:25:35 + | +LL | const VALUE32: i32 = unsafe { std::mem::transmute(1f32) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `1f32.to_bits() as i32` + +error: transmute from a `f64` to a `u64` + --> tests/ui/transmute_float_to_int.rs:27:35 + | +LL | const VALUE64: u64 = unsafe { std::mem::transmute(1f64) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `1f64.to_bits()` + +error: transmute from a `f128` to a `u128` + --> tests/ui/transmute_float_to_int.rs:29:37 + | +LL | const VALUE128: u128 = unsafe { std::mem::transmute(1f128) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `1f128.to_bits()` + +error: transmute from a `f16` to a `u16` + --> tests/ui/transmute_float_to_int.rs:33:18 + | +LL | unsafe { std::mem::transmute(v) } + | ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `v.to_bits()` + +error: transmute from a `f32` to a `u32` + --> tests/ui/transmute_float_to_int.rs:38:18 + | +LL | unsafe { std::mem::transmute(v) } + | ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `v.to_bits()` + +error: transmute from a `f64` to a `i64` + --> tests/ui/transmute_float_to_int.rs:43:18 + | +LL | unsafe { std::mem::transmute(v) } + | ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `v.to_bits() as i64` + +error: transmute from a `f128` to a `i128` + --> tests/ui/transmute_float_to_int.rs:48:18 + | +LL | unsafe { std::mem::transmute(v) } + | ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `v.to_bits() as i128` + +error: aborting due to 14 previous errors diff --git a/tests/ui/consts/const-float-bits-conv.rs b/tests/ui/consts/const-float-bits-conv.rs index 3a526c54dc376..869498d107612 100644 --- a/tests/ui/consts/const-float-bits-conv.rs +++ b/tests/ui/consts/const-float-bits-conv.rs @@ -1,10 +1,9 @@ //@ compile-flags: -Zmir-opt-level=0 //@ run-pass -#![feature(const_float_bits_conv)] #![feature(const_float_classify)] -#![feature(f16)] -#![feature(f128)] +#![feature(f16, f16_const)] +#![feature(f128, f128_const)] #![allow(unused_macro_rules)] // Don't promote const fn nop(x: T) -> T { x } diff --git a/tests/ui/consts/const-float-classify.rs b/tests/ui/consts/const-float-classify.rs index c64d31a5c60ae..6e5097f7f2b9c 100644 --- a/tests/ui/consts/const-float-classify.rs +++ b/tests/ui/consts/const-float-classify.rs @@ -2,7 +2,6 @@ //@ known-bug: #110395 // FIXME(effects) run-pass -#![feature(const_float_bits_conv)] #![feature(const_float_classify)] #![feature(const_trait_impl, effects)] #![allow(incomplete_features)] diff --git a/tests/ui/consts/const-float-classify.stderr b/tests/ui/consts/const-float-classify.stderr index 38acb8a228104..a35de8ad0eabd 100644 --- a/tests/ui/consts/const-float-classify.stderr +++ b/tests/ui/consts/const-float-classify.stderr @@ -1,5 +1,5 @@ error: const `impl` for trait `PartialEq` which is not marked with `#[const_trait]` - --> $DIR/const-float-classify.rs:13:12 + --> $DIR/const-float-classify.rs:12:12 | LL | impl const PartialEq for bool { | ^^^^^^^^^^^^^^^^^ From ba2577f23c0014c171235692ca4d8b6b71fbce7e Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 25 Aug 2024 15:15:15 +0200 Subject: [PATCH 0341/2194] stabilize const_float_bits_conv --- clippy_lints/src/transmute/mod.rs | 6 +- .../src/transmute/transmute_float_to_int.rs | 3 +- .../src/transmute/transmute_int_to_float.rs | 3 +- .../src/transmute/transmute_num_to_bytes.rs | 6 - tests/ui/transmute.rs | 12 ++ tests/ui/transmute.stderr | 112 ++++++++++++++---- tests/ui/transmute_float_to_int.fixed | 28 +++-- tests/ui/transmute_float_to_int.rs | 12 +- tests/ui/transmute_float_to_int.stderr | 50 +++++++- 9 files changed, 186 insertions(+), 46 deletions(-) diff --git a/clippy_lints/src/transmute/mod.rs b/clippy_lints/src/transmute/mod.rs index 373bf61d8ff94..a2ae36cc484ad 100644 --- a/clippy_lints/src/transmute/mod.rs +++ b/clippy_lints/src/transmute/mod.rs @@ -619,10 +619,10 @@ impl<'tcx> LateLintPass<'tcx> for Transmute { | transmute_ref_to_ref::check(cx, e, from_ty, to_ty, arg, const_context) | transmute_ptr_to_ptr::check(cx, e, from_ty, to_ty, arg, &self.msrv) | transmute_int_to_bool::check(cx, e, from_ty, to_ty, arg) - | transmute_int_to_float::check(cx, e, from_ty, to_ty, arg, const_context) + | transmute_int_to_float::check(cx, e, from_ty, to_ty, arg) | transmute_int_to_non_zero::check(cx, e, from_ty, to_ty, arg) - | transmute_float_to_int::check(cx, e, from_ty, to_ty, arg, const_context) - | transmute_num_to_bytes::check(cx, e, from_ty, to_ty, arg, const_context) + | transmute_float_to_int::check(cx, e, from_ty, to_ty, arg) + | transmute_num_to_bytes::check(cx, e, from_ty, to_ty, arg) | (unsound_collection_transmute::check(cx, e, from_ty, to_ty) || transmute_undefined_repr::check(cx, e, from_ty, to_ty)) | (eager_transmute::check(cx, e, arg, from_ty, to_ty)); diff --git a/clippy_lints/src/transmute/transmute_float_to_int.rs b/clippy_lints/src/transmute/transmute_float_to_int.rs index ab3bb5e1062d3..cb46109c27e2f 100644 --- a/clippy_lints/src/transmute/transmute_float_to_int.rs +++ b/clippy_lints/src/transmute/transmute_float_to_int.rs @@ -15,10 +15,9 @@ pub(super) fn check<'tcx>( from_ty: Ty<'tcx>, to_ty: Ty<'tcx>, mut arg: &'tcx Expr<'_>, - const_context: bool, ) -> bool { match (&from_ty.kind(), &to_ty.kind()) { - (ty::Float(float_ty), ty::Int(_) | ty::Uint(_)) if !const_context => { + (ty::Float(float_ty), ty::Int(_) | ty::Uint(_)) => { span_lint_and_then( cx, TRANSMUTE_FLOAT_TO_INT, diff --git a/clippy_lints/src/transmute/transmute_int_to_float.rs b/clippy_lints/src/transmute/transmute_int_to_float.rs index d51888e30971b..e00fb90c3074e 100644 --- a/clippy_lints/src/transmute/transmute_int_to_float.rs +++ b/clippy_lints/src/transmute/transmute_int_to_float.rs @@ -14,10 +14,9 @@ pub(super) fn check<'tcx>( from_ty: Ty<'tcx>, to_ty: Ty<'tcx>, arg: &'tcx Expr<'_>, - const_context: bool, ) -> bool { match (&from_ty.kind(), &to_ty.kind()) { - (ty::Int(_) | ty::Uint(_), ty::Float(_)) if !const_context => { + (ty::Int(_) | ty::Uint(_), ty::Float(_)) => { span_lint_and_then( cx, TRANSMUTE_INT_TO_FLOAT, diff --git a/clippy_lints/src/transmute/transmute_num_to_bytes.rs b/clippy_lints/src/transmute/transmute_num_to_bytes.rs index 88b0ac5a36887..362f2bb6960a2 100644 --- a/clippy_lints/src/transmute/transmute_num_to_bytes.rs +++ b/clippy_lints/src/transmute/transmute_num_to_bytes.rs @@ -14,18 +14,12 @@ pub(super) fn check<'tcx>( from_ty: Ty<'tcx>, to_ty: Ty<'tcx>, arg: &'tcx Expr<'_>, - const_context: bool, ) -> bool { match (&from_ty.kind(), &to_ty.kind()) { (ty::Int(_) | ty::Uint(_) | ty::Float(_), ty::Array(arr_ty, _)) => { if !matches!(arr_ty.kind(), ty::Uint(UintTy::U8)) { return false; } - if matches!(from_ty.kind(), ty::Float(_)) && const_context { - // TODO: Remove when const_float_bits_conv is stabilized - // rust#72447 - return false; - } span_lint_and_then( cx, diff --git a/tests/ui/transmute.rs b/tests/ui/transmute.rs index 46629526367ec..eeea3f080b1c9 100644 --- a/tests/ui/transmute.rs +++ b/tests/ui/transmute.rs @@ -140,24 +140,32 @@ mod int_to_float { mod issue_5747 { const VALUE16: f16 = unsafe { std::mem::transmute(0_u16) }; + //~^ ERROR: transmute from a `u16` to a `f16` const VALUE32: f32 = unsafe { std::mem::transmute(0_u32) }; + //~^ ERROR: transmute from a `u32` to a `f32` const VALUE64: f64 = unsafe { std::mem::transmute(0_i64) }; + //~^ ERROR: transmute from a `i64` to a `f64` const VALUE128: f128 = unsafe { std::mem::transmute(0_i128) }; + //~^ ERROR: transmute from a `i128` to a `f128` const fn from_bits_16(v: i16) -> f16 { unsafe { std::mem::transmute(v) } + //~^ ERROR: transmute from a `i16` to a `f16` } const fn from_bits_32(v: i32) -> f32 { unsafe { std::mem::transmute(v) } + //~^ ERROR: transmute from a `i32` to a `f32` } const fn from_bits_64(v: u64) -> f64 { unsafe { std::mem::transmute(v) } + //~^ ERROR: transmute from a `u64` to a `f64` } const fn from_bits_128(v: u128) -> f128 { unsafe { std::mem::transmute(v) } + //~^ ERROR: transmute from a `u128` to a `f128` } } } @@ -205,9 +213,13 @@ mod num_to_bytes { //~^ ERROR: transmute from a `i128` to a `[u8; 16]` let _: [u8; 2] = std::mem::transmute(0.0f16); + //~^ ERROR: transmute from a `f16` to a `[u8; 2]` let _: [u8; 4] = std::mem::transmute(0.0f32); + //~^ ERROR: transmute from a `f32` to a `[u8; 4]` let _: [u8; 8] = std::mem::transmute(0.0f64); + //~^ ERROR: transmute from a `f64` to a `[u8; 8]` let _: [u8; 16] = std::mem::transmute(0.0f128); + //~^ ERROR: transmute from a `f128` to a `[u8; 16]` } } } diff --git a/tests/ui/transmute.stderr b/tests/ui/transmute.stderr index 0072f62962a7d..41a10f381dc53 100644 --- a/tests/ui/transmute.stderr +++ b/tests/ui/transmute.stderr @@ -148,8 +148,56 @@ error: transmute from a `i128` to a `f128` LL | let _: f128 = unsafe { std::mem::transmute(0_i128) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `f128::from_bits(0_i128 as u128)` +error: transmute from a `u16` to a `f16` + --> tests/ui/transmute.rs:142:39 + | +LL | const VALUE16: f16 = unsafe { std::mem::transmute(0_u16) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `f16::from_bits(0_u16)` + +error: transmute from a `u32` to a `f32` + --> tests/ui/transmute.rs:144:39 + | +LL | const VALUE32: f32 = unsafe { std::mem::transmute(0_u32) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `f32::from_bits(0_u32)` + +error: transmute from a `i64` to a `f64` + --> tests/ui/transmute.rs:146:39 + | +LL | const VALUE64: f64 = unsafe { std::mem::transmute(0_i64) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `f64::from_bits(0_i64 as u64)` + +error: transmute from a `i128` to a `f128` + --> tests/ui/transmute.rs:148:41 + | +LL | const VALUE128: f128 = unsafe { std::mem::transmute(0_i128) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `f128::from_bits(0_i128 as u128)` + +error: transmute from a `i16` to a `f16` + --> tests/ui/transmute.rs:152:22 + | +LL | unsafe { std::mem::transmute(v) } + | ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `f16::from_bits(v as u16)` + +error: transmute from a `i32` to a `f32` + --> tests/ui/transmute.rs:157:22 + | +LL | unsafe { std::mem::transmute(v) } + | ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `f32::from_bits(v as u32)` + +error: transmute from a `u64` to a `f64` + --> tests/ui/transmute.rs:162:22 + | +LL | unsafe { std::mem::transmute(v) } + | ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `f64::from_bits(v)` + +error: transmute from a `u128` to a `f128` + --> tests/ui/transmute.rs:167:22 + | +LL | unsafe { std::mem::transmute(v) } + | ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `f128::from_bits(v)` + error: transmute from a `u8` to a `[u8; 1]` - --> tests/ui/transmute.rs:168:30 + --> tests/ui/transmute.rs:176:30 | LL | let _: [u8; 1] = std::mem::transmute(0u8); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0u8.to_ne_bytes()` @@ -158,97 +206,121 @@ LL | let _: [u8; 1] = std::mem::transmute(0u8); = help: to override `-D warnings` add `#[allow(clippy::transmute_num_to_bytes)]` error: transmute from a `u32` to a `[u8; 4]` - --> tests/ui/transmute.rs:171:30 + --> tests/ui/transmute.rs:179:30 | LL | let _: [u8; 4] = std::mem::transmute(0u32); | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0u32.to_ne_bytes()` error: transmute from a `u128` to a `[u8; 16]` - --> tests/ui/transmute.rs:173:31 + --> tests/ui/transmute.rs:181:31 | LL | let _: [u8; 16] = std::mem::transmute(0u128); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0u128.to_ne_bytes()` error: transmute from a `i8` to a `[u8; 1]` - --> tests/ui/transmute.rs:175:30 + --> tests/ui/transmute.rs:183:30 | LL | let _: [u8; 1] = std::mem::transmute(0i8); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0i8.to_ne_bytes()` error: transmute from a `i32` to a `[u8; 4]` - --> tests/ui/transmute.rs:177:30 + --> tests/ui/transmute.rs:185:30 | LL | let _: [u8; 4] = std::mem::transmute(0i32); | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0i32.to_ne_bytes()` error: transmute from a `i128` to a `[u8; 16]` - --> tests/ui/transmute.rs:179:31 + --> tests/ui/transmute.rs:187:31 | LL | let _: [u8; 16] = std::mem::transmute(0i128); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0i128.to_ne_bytes()` error: transmute from a `f16` to a `[u8; 2]` - --> tests/ui/transmute.rs:182:30 + --> tests/ui/transmute.rs:190:30 | LL | let _: [u8; 2] = std::mem::transmute(0.0f16); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0.0f16.to_ne_bytes()` error: transmute from a `f32` to a `[u8; 4]` - --> tests/ui/transmute.rs:184:30 + --> tests/ui/transmute.rs:192:30 | LL | let _: [u8; 4] = std::mem::transmute(0.0f32); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0.0f32.to_ne_bytes()` error: transmute from a `f64` to a `[u8; 8]` - --> tests/ui/transmute.rs:186:30 + --> tests/ui/transmute.rs:194:30 | LL | let _: [u8; 8] = std::mem::transmute(0.0f64); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0.0f64.to_ne_bytes()` error: transmute from a `f128` to a `[u8; 16]` - --> tests/ui/transmute.rs:188:31 + --> tests/ui/transmute.rs:196:31 | LL | let _: [u8; 16] = std::mem::transmute(0.0f128); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0.0f128.to_ne_bytes()` error: transmute from a `u8` to a `[u8; 1]` - --> tests/ui/transmute.rs:194:30 + --> tests/ui/transmute.rs:202:30 | LL | let _: [u8; 1] = std::mem::transmute(0u8); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0u8.to_ne_bytes()` error: transmute from a `u32` to a `[u8; 4]` - --> tests/ui/transmute.rs:196:30 + --> tests/ui/transmute.rs:204:30 | LL | let _: [u8; 4] = std::mem::transmute(0u32); | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0u32.to_ne_bytes()` error: transmute from a `u128` to a `[u8; 16]` - --> tests/ui/transmute.rs:198:31 + --> tests/ui/transmute.rs:206:31 | LL | let _: [u8; 16] = std::mem::transmute(0u128); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0u128.to_ne_bytes()` error: transmute from a `i8` to a `[u8; 1]` - --> tests/ui/transmute.rs:200:30 + --> tests/ui/transmute.rs:208:30 | LL | let _: [u8; 1] = std::mem::transmute(0i8); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0i8.to_ne_bytes()` error: transmute from a `i32` to a `[u8; 4]` - --> tests/ui/transmute.rs:202:30 + --> tests/ui/transmute.rs:210:30 | LL | let _: [u8; 4] = std::mem::transmute(0i32); | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0i32.to_ne_bytes()` error: transmute from a `i128` to a `[u8; 16]` - --> tests/ui/transmute.rs:204:31 + --> tests/ui/transmute.rs:212:31 | LL | let _: [u8; 16] = std::mem::transmute(0i128); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0i128.to_ne_bytes()` +error: transmute from a `f16` to a `[u8; 2]` + --> tests/ui/transmute.rs:215:30 + | +LL | let _: [u8; 2] = std::mem::transmute(0.0f16); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0.0f16.to_ne_bytes()` + +error: transmute from a `f32` to a `[u8; 4]` + --> tests/ui/transmute.rs:217:30 + | +LL | let _: [u8; 4] = std::mem::transmute(0.0f32); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0.0f32.to_ne_bytes()` + +error: transmute from a `f64` to a `[u8; 8]` + --> tests/ui/transmute.rs:219:30 + | +LL | let _: [u8; 8] = std::mem::transmute(0.0f64); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0.0f64.to_ne_bytes()` + +error: transmute from a `f128` to a `[u8; 16]` + --> tests/ui/transmute.rs:221:31 + | +LL | let _: [u8; 16] = std::mem::transmute(0.0f128); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0.0f128.to_ne_bytes()` + error: transmute from a `&[u8]` to a `&str` - --> tests/ui/transmute.rs:218:28 + --> tests/ui/transmute.rs:230:28 | LL | let _: &str = unsafe { std::mem::transmute(B) }; | ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::str::from_utf8(B).unwrap()` @@ -257,16 +329,16 @@ LL | let _: &str = unsafe { std::mem::transmute(B) }; = help: to override `-D warnings` add `#[allow(clippy::transmute_bytes_to_str)]` error: transmute from a `&mut [u8]` to a `&mut str` - --> tests/ui/transmute.rs:221:32 + --> tests/ui/transmute.rs:233:32 | LL | let _: &mut str = unsafe { std::mem::transmute(mb) }; | ^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::str::from_utf8_mut(mb).unwrap()` error: transmute from a `&[u8]` to a `&str` - --> tests/ui/transmute.rs:223:30 + --> tests/ui/transmute.rs:235:30 | LL | const _: &str = unsafe { std::mem::transmute(B) }; | ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::str::from_utf8_unchecked(B)` -error: aborting due to 42 previous errors +error: aborting due to 54 previous errors diff --git a/tests/ui/transmute_float_to_int.fixed b/tests/ui/transmute_float_to_int.fixed index 4361a7407d115..83814ca43b96d 100644 --- a/tests/ui/transmute_float_to_int.fixed +++ b/tests/ui/transmute_float_to_int.fixed @@ -1,7 +1,7 @@ #![warn(clippy::transmute_float_to_int)] #![allow(clippy::missing_transmute_annotations)] -#![feature(f128)] -#![feature(f16)] +#![feature(f128, f128_const)] +#![feature(f16, f16_const)] fn float_to_int() { let _: u32 = unsafe { 1f32.to_bits() }; @@ -20,25 +20,33 @@ fn float_to_int() { } mod issue_5747 { - const VALUE16: i16 = unsafe { std::mem::transmute(1f16) }; - const VALUE32: i32 = unsafe { std::mem::transmute(1f32) }; - const VALUE64: u64 = unsafe { std::mem::transmute(1f64) }; - const VALUE128: u128 = unsafe { std::mem::transmute(1f128) }; + const VALUE16: i16 = unsafe { 1f16.to_bits() as i16 }; + //~^ ERROR: transmute from a `f16` to a `i16` + const VALUE32: i32 = unsafe { 1f32.to_bits() as i32 }; + //~^ ERROR: transmute from a `f32` to a `i32` + const VALUE64: u64 = unsafe { 1f64.to_bits() }; + //~^ ERROR: transmute from a `f64` to a `u64` + const VALUE128: u128 = unsafe { 1f128.to_bits() }; + //~^ ERROR: transmute from a `f128` to a `u128` const fn to_bits_16(v: f16) -> u16 { - unsafe { std::mem::transmute(v) } + unsafe { v.to_bits() } + //~^ ERROR: transmute from a `f16` to a `u16` } const fn to_bits_32(v: f32) -> u32 { - unsafe { std::mem::transmute(v) } + unsafe { v.to_bits() } + //~^ ERROR: transmute from a `f32` to a `u32` } const fn to_bits_64(v: f64) -> i64 { - unsafe { std::mem::transmute(v) } + unsafe { v.to_bits() as i64 } + //~^ ERROR: transmute from a `f64` to a `i64` } const fn to_bits_128(v: f128) -> i128 { - unsafe { std::mem::transmute(v) } + unsafe { v.to_bits() as i128 } + //~^ ERROR: transmute from a `f128` to a `i128` } } diff --git a/tests/ui/transmute_float_to_int.rs b/tests/ui/transmute_float_to_int.rs index 363ce0bcb16d0..64d6e9172039d 100644 --- a/tests/ui/transmute_float_to_int.rs +++ b/tests/ui/transmute_float_to_int.rs @@ -1,7 +1,7 @@ #![warn(clippy::transmute_float_to_int)] #![allow(clippy::missing_transmute_annotations)] -#![feature(f128)] -#![feature(f16)] +#![feature(f128, f128_const)] +#![feature(f16, f16_const)] fn float_to_int() { let _: u32 = unsafe { std::mem::transmute(1f32) }; @@ -21,24 +21,32 @@ fn float_to_int() { mod issue_5747 { const VALUE16: i16 = unsafe { std::mem::transmute(1f16) }; + //~^ ERROR: transmute from a `f16` to a `i16` const VALUE32: i32 = unsafe { std::mem::transmute(1f32) }; + //~^ ERROR: transmute from a `f32` to a `i32` const VALUE64: u64 = unsafe { std::mem::transmute(1f64) }; + //~^ ERROR: transmute from a `f64` to a `u64` const VALUE128: u128 = unsafe { std::mem::transmute(1f128) }; + //~^ ERROR: transmute from a `f128` to a `u128` const fn to_bits_16(v: f16) -> u16 { unsafe { std::mem::transmute(v) } + //~^ ERROR: transmute from a `f16` to a `u16` } const fn to_bits_32(v: f32) -> u32 { unsafe { std::mem::transmute(v) } + //~^ ERROR: transmute from a `f32` to a `u32` } const fn to_bits_64(v: f64) -> i64 { unsafe { std::mem::transmute(v) } + //~^ ERROR: transmute from a `f64` to a `i64` } const fn to_bits_128(v: f128) -> i128 { unsafe { std::mem::transmute(v) } + //~^ ERROR: transmute from a `f128` to a `i128` } } diff --git a/tests/ui/transmute_float_to_int.stderr b/tests/ui/transmute_float_to_int.stderr index 9cac75f72cdd7..0cabab58ab08c 100644 --- a/tests/ui/transmute_float_to_int.stderr +++ b/tests/ui/transmute_float_to_int.stderr @@ -37,5 +37,53 @@ error: transmute from a `f64` to a `u64` LL | let _: u64 = unsafe { std::mem::transmute(-1.0) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `(-1.0f64).to_bits()` -error: aborting due to 6 previous errors +error: transmute from a `f16` to a `i16` + --> tests/ui/transmute_float_to_int.rs:23:35 + | +LL | const VALUE16: i16 = unsafe { std::mem::transmute(1f16) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `1f16.to_bits() as i16` + +error: transmute from a `f32` to a `i32` + --> tests/ui/transmute_float_to_int.rs:25:35 + | +LL | const VALUE32: i32 = unsafe { std::mem::transmute(1f32) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `1f32.to_bits() as i32` + +error: transmute from a `f64` to a `u64` + --> tests/ui/transmute_float_to_int.rs:27:35 + | +LL | const VALUE64: u64 = unsafe { std::mem::transmute(1f64) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `1f64.to_bits()` + +error: transmute from a `f128` to a `u128` + --> tests/ui/transmute_float_to_int.rs:29:37 + | +LL | const VALUE128: u128 = unsafe { std::mem::transmute(1f128) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `1f128.to_bits()` + +error: transmute from a `f16` to a `u16` + --> tests/ui/transmute_float_to_int.rs:33:18 + | +LL | unsafe { std::mem::transmute(v) } + | ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `v.to_bits()` + +error: transmute from a `f32` to a `u32` + --> tests/ui/transmute_float_to_int.rs:38:18 + | +LL | unsafe { std::mem::transmute(v) } + | ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `v.to_bits()` + +error: transmute from a `f64` to a `i64` + --> tests/ui/transmute_float_to_int.rs:43:18 + | +LL | unsafe { std::mem::transmute(v) } + | ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `v.to_bits() as i64` + +error: transmute from a `f128` to a `i128` + --> tests/ui/transmute_float_to_int.rs:48:18 + | +LL | unsafe { std::mem::transmute(v) } + | ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `v.to_bits() as i128` + +error: aborting due to 14 previous errors From 01b7676fe7ab67f5c56bc94790ad903f712bb5ff Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Mon, 26 Aug 2024 10:59:04 +0200 Subject: [PATCH 0342/2194] internal: Lay basic ground work for standalone mbe tests --- src/tools/rust-analyzer/Cargo.lock | 1 + .../hir-def/src/macro_expansion_tests/mbe.rs | 38 ++-- .../macro_expansion_tests/mbe/regression.rs | 32 ++-- .../hir-def/src/macro_expansion_tests/mod.rs | 6 +- .../src/macro_expansion_tests/proc_macros.rs | 12 +- .../crates/hir-expand/src/lib.rs | 1 + src/tools/rust-analyzer/crates/hir/src/lib.rs | 1 + .../rust-analyzer/crates/ide-db/src/lib.rs | 2 +- .../crates/ide/src/hover/tests.rs | 5 - src/tools/rust-analyzer/crates/mbe/Cargo.toml | 1 + src/tools/rust-analyzer/crates/mbe/src/lib.rs | 2 + .../rust-analyzer/crates/mbe/src/tests.rs | 179 ++++++++++++++++++ .../src}/insert_whitespace_into_node.rs | 2 - .../crates/syntax-bridge/src/lib.rs | 1 + src/tools/rust-analyzer/crates/vfs/src/lib.rs | 2 +- 15 files changed, 233 insertions(+), 52 deletions(-) create mode 100644 src/tools/rust-analyzer/crates/mbe/src/tests.rs rename src/tools/rust-analyzer/crates/{ide-db/src/syntax_helpers => syntax-bridge/src}/insert_whitespace_into_node.rs (97%) diff --git a/src/tools/rust-analyzer/Cargo.lock b/src/tools/rust-analyzer/Cargo.lock index 4e9319f13aa83..8733508be746b 100644 --- a/src/tools/rust-analyzer/Cargo.lock +++ b/src/tools/rust-analyzer/Cargo.lock @@ -1029,6 +1029,7 @@ version = "0.0.0" dependencies = [ "arrayvec", "cov-mark", + "expect-test", "intern", "parser", "rustc-hash", diff --git a/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mbe.rs b/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mbe.rs index fc1460870ceaf..85fb90fdfb69f 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mbe.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mbe.rs @@ -389,7 +389,7 @@ m! { foo# bar } m! { Foo,# Bar } "#, - expect![[r##" + expect![[r#" macro_rules! m { ($($i:ident),*) => ($(mod $i {} )*); ($($i:ident)#*) => ($(fn $i() {} )*); @@ -404,27 +404,29 @@ fn bar() {} struct Foo; struct Bar; -"##]], +"#]], ); } #[test] fn test_match_group_pattern_with_multiple_defs() { + // FIXME: The pretty printer breaks by leaving whitespace here, +syntaxctxt is used to avoid that check( r#" macro_rules! m { ($($i:ident),*) => ( impl Bar { $(fn $i() {})* } ); } +// +syntaxctxt m! { foo, bar } "#, expect![[r#" macro_rules! m { ($($i:ident),*) => ( impl Bar { $(fn $i() {})* } ); } -impl Bar { - fn foo() {} - fn bar() {} -} +impl#\1# Bar#\1# {#\1# + fn#\1# foo#\0#(#\1#)#\1# {#\1#}#\1# + fn#\1# bar#\0#(#\1#)#\1# {#\1#}#\1# +}#\1# "#]], ); } @@ -480,12 +482,12 @@ macro_rules! m { } m!{#abc} "#, - expect![[r##" + expect![[r#" macro_rules! m { ($($i:ident)* #abc) => ( fn baz() { $($i ();)* } ); } fn baz() {} -"##]], +"#]], ) } @@ -1189,13 +1191,13 @@ macro_rules! m { m! { cfg(target_os = "windows") } m! { hello::world } "#, - expect![[r##" + expect![[r#" macro_rules! m { ($m:meta) => ( #[$m] fn bar() {} ) } #[cfg(target_os = "windows")] fn bar() {} #[hello::world] fn bar() {} -"##]], +"#]], ); } @@ -1213,7 +1215,7 @@ m! { */ } "#, - expect![[r##" + expect![[r#" macro_rules! m { ($(#[$m:meta])+) => ( $(#[$m])+ fn bar() {} ) } @@ -1221,7 +1223,7 @@ macro_rules! m { #[doc = r" MultiLines Doc "] fn bar() {} -"##]], +"#]], ); } @@ -1234,12 +1236,12 @@ macro_rules! m { } m! { #[doc = concat!("The `", "bla", "` lang item.")] } "#, - expect![[r##" + expect![[r#" macro_rules! m { (#[$m:meta]) => ( #[$m] fn bar() {} ) } #[doc = concat!("The `", "bla", "` lang item.")] fn bar() {} -"##]], +"#]], ); } @@ -1257,7 +1259,7 @@ m! { */ } "#, - expect![[r##" + expect![[r#" macro_rules! m { ($(#[$ m:meta])+) => ( $(#[$m])+ fn bar() {} ) } @@ -1265,7 +1267,7 @@ macro_rules! m { #[doc = r" 莊生曉夢迷蝴蝶,望帝春心託杜鵑。 "] fn bar() {} -"##]], +"#]], ); } @@ -1342,10 +1344,10 @@ fn test_tt_composite2() { macro_rules! m { ($($tt:tt)*) => { abs!(=> $($tt)*); } } m! {#} "#, - expect![[r##" + expect![[r#" macro_rules! m { ($($tt:tt)*) => { abs!(=> $($tt)*); } } abs!( = > #); -"##]], +"#]], ); } diff --git a/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mbe/regression.rs b/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mbe/regression.rs index 485f72e92ce1c..894ef1d73e22d 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mbe/regression.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mbe/regression.rs @@ -139,7 +139,7 @@ STRUCT!{struct D3DVSHADERCAPS2_0 {Caps: u8,}} STRUCT!{#[cfg_attr(target_arch = "x86", repr(packed))] struct D3DCONTENTPROTECTIONCAPS {Caps : u8 ,}} "#, - expect![[r##" + expect![[r#" macro_rules! STRUCT { ($(#[$attrs:meta])* struct $name:ident { $($field:ident: $ftype:ty,)+ @@ -194,7 +194,7 @@ impl Clone for D3DCONTENTPROTECTIONCAPS { } } } -"##]], +"#]], ); } @@ -214,7 +214,7 @@ macro_rules! int_base { } int_base!{Binary for isize as usize -> Binary} "#, - expect![[r##" + expect![[r#" macro_rules! int_base { ($Trait:ident for $T:ident as $U:ident -> $Radix:ident) => { #[stable(feature = "rust1", since = "1.0.0")] @@ -230,7 +230,7 @@ macro_rules! int_base { Binary.fmt_int(*self as usize, f) } } -"##]], +"#]], ); } @@ -318,7 +318,7 @@ impl_fn_for_zst ! { } "#, - expect![[r##" + expect![[r#" macro_rules! impl_fn_for_zst { {$( $( #[$attr: meta] )* struct $Name: ident impl$( <$( $lifetime : lifetime ),+> )? Fn = @@ -410,7 +410,7 @@ impl FnOnce<(char, )> for CharEscapeDefault { } } -"##]], +"#]], ); } @@ -511,7 +511,7 @@ cfg_if! { @__apply cfg(all(not(any(not(any(target_os = "solaris", target_os = "illumos")))))), } "#, - expect![[r##" + expect![[r#" macro_rules! cfg_if { ($(if #[cfg($($meta:meta),*)] { $($it:item)* } )else* else { $($it2:item)* }) => { @@ -534,7 +534,7 @@ __cfg_if_items! { } -"##]], +"#]], ); } @@ -618,7 +618,7 @@ RIDL!{interface ID3D11Asynchronous(ID3D11AsynchronousVtbl): ID3D11DeviceChild(ID fn GetDataSize(&mut self) -> UINT }} "#, - expect![[r##" + expect![[r#" #[macro_export] macro_rules! RIDL { (interface $interface:ident ($vtbl:ident) : $pinterface:ident ($pvtbl:ident) @@ -639,7 +639,7 @@ impl ID3D11Asynchronous { ((*self .lpVtbl).GetDataSize)(self ) } } -"##]], +"#]], ); } @@ -676,7 +676,7 @@ quick_error ! ( ); "#, - expect![[r##" + expect![[r#" macro_rules! quick_error { (SORT [enum $name:ident $( #[$meta:meta] )*] items [$($( #[$imeta:meta] )* @@ -697,7 +697,7 @@ macro_rules! quick_error { } quick_error!(ENUMINITION[enum Wrapped#[derive(Debug)]]body[]queue[ = > One: UNIT[] = > Two: TUPLE[s: String]]); -"##]], +"#]], ) } @@ -746,7 +746,7 @@ delegate_impl ! { [G, &'a mut G, deref] pub trait Data: GraphBase {@section type type NodeWeight;} } "#, - expect![[r##" + expect![[r#" macro_rules! delegate_impl { ([$self_type:ident, $self_wrap:ty, $self_map:ident] pub trait $name:ident $(: $sup:ident)* $(+ $more_sup:ident)* { @@ -785,7 +785,7 @@ macro_rules! delegate_impl { } } impl <> Data for &'amut G where G: Data {} -"##]], +"#]], ); } @@ -959,14 +959,14 @@ macro_rules! with_std { with_std! {mod m;mod f;} "#, - expect![[r##" + expect![[r#" macro_rules! with_std { ($($i:item)*) => ($(#[cfg(feature = "std")]$i)*) } #[cfg(feature = "std")] mod m; #[cfg(feature = "std")] mod f; -"##]], +"#]], ) } diff --git a/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mod.rs b/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mod.rs index 7f761192517c4..f9ccb06ce84a4 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mod.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mod.rs @@ -1,6 +1,6 @@ -//! This module contains tests for macro expansion. Effectively, it covers `tt`, -//! `mbe`, `proc_macro_api` and `hir_expand` crates. This might seem like a -//! wrong architecture at the first glance, but is intentional. +//! This module contains integration tests for macro expansion with name resolution. Effectively, it +//! covers `tt`, `mbe`, `proc_macro_api` and `hir_expand` crates. This might seem like a wrong +//! architecture at the first glance, but is intentional. //! //! Physically, macro expansion process is intertwined with name resolution. You //! can not expand *just* the syntax. So, to be able to write integration tests diff --git a/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/proc_macros.rs b/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/proc_macros.rs index 6f605c0cb33db..c0178adc9a63a 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/proc_macros.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/proc_macros.rs @@ -16,12 +16,12 @@ fn attribute_macro_attr_censoring() { #[attr1] #[proc_macros::identity] #[attr2] struct S; "#, - expect![[r##" + expect![[r#" #[attr1] #[proc_macros::identity] #[attr2] struct S; #[attr1] -#[attr2] struct S;"##]], +#[attr2] struct S;"#]], ); } @@ -39,7 +39,7 @@ fn derive_censoring() { #[attr2] struct S; "#, - expect![[r##" + expect![[r#" #[attr1] #[derive(Foo)] #[derive(proc_macros::DeriveIdentity)] @@ -49,7 +49,7 @@ struct S; #[attr1] #[derive(Bar)] -#[attr2] struct S;"##]], +#[attr2] struct S;"#]], ); } @@ -62,14 +62,14 @@ fn attribute_macro_syntax_completion_1() { #[proc_macros::identity_when_valid] fn foo() { bar.baz(); blub } "#, - expect![[r##" + expect![[r#" #[proc_macros::identity_when_valid] fn foo() { bar.baz(); blub } fn foo() { bar.baz(); blub -}"##]], +}"#]], ); } diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/lib.rs b/src/tools/rust-analyzer/crates/hir-expand/src/lib.rs index 19c3c9c43f104..7ae2fa1e39cd0 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/lib.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/lib.rs @@ -55,6 +55,7 @@ pub use crate::files::{AstId, ErasedAstId, FileRange, InFile, InMacroFile, InRea pub use mbe::{DeclarativeMacro, ValueResult}; pub use span::{HirFileId, MacroCallId, MacroFileId}; +pub use syntax_bridge::insert_whitespace_into_node; pub mod tt { pub use span::Span; diff --git a/src/tools/rust-analyzer/crates/hir/src/lib.rs b/src/tools/rust-analyzer/crates/hir/src/lib.rs index 96a6e6f1f128e..527ecf04c3e56 100644 --- a/src/tools/rust-analyzer/crates/hir/src/lib.rs +++ b/src/tools/rust-analyzer/crates/hir/src/lib.rs @@ -136,6 +136,7 @@ pub use { }, hygiene::{marks_rev, SyntaxContextExt}, inert_attr_macro::AttributeTemplate, + insert_whitespace_into_node, name::Name, proc_macro::{ProcMacros, ProcMacrosBuilder}, tt, ExpandResult, HirFileId, HirFileIdExt, MacroFileId, MacroFileIdExt, diff --git a/src/tools/rust-analyzer/crates/ide-db/src/lib.rs b/src/tools/rust-analyzer/crates/ide-db/src/lib.rs index 3cf29987fa14c..8a2068e9039fc 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/lib.rs +++ b/src/tools/rust-analyzer/crates/ide-db/src/lib.rs @@ -36,7 +36,7 @@ pub mod generated { pub mod syntax_helpers { pub mod format_string; pub mod format_string_exprs; - pub mod insert_whitespace_into_node; + pub use hir::insert_whitespace_into_node; pub mod node_ext; pub use parser::LexedStr; diff --git a/src/tools/rust-analyzer/crates/ide/src/hover/tests.rs b/src/tools/rust-analyzer/crates/ide/src/hover/tests.rs index 9b934044ac0b7..f4528dd754c21 100644 --- a/src/tools/rust-analyzer/crates/ide/src/hover/tests.rs +++ b/src/tools/rust-analyzer/crates/ide/src/hover/tests.rs @@ -509,13 +509,8 @@ fn main() { file_id: FileId( 1, ), -<<<<<<< HEAD - full_range: 633..868, - focus_range: 694..700, -======= full_range: 4294967295..4294967295, focus_range: 4294967295..4294967295, ->>>>>>> 33e4a08d5b (minor: Reduce friction for updating minicore) name: "FnOnce", kind: Trait, container_name: "function", diff --git a/src/tools/rust-analyzer/crates/mbe/Cargo.toml b/src/tools/rust-analyzer/crates/mbe/Cargo.toml index 756d42ef573fc..413a0254a6162 100644 --- a/src/tools/rust-analyzer/crates/mbe/Cargo.toml +++ b/src/tools/rust-analyzer/crates/mbe/Cargo.toml @@ -30,6 +30,7 @@ syntax-bridge.workspace = true [dev-dependencies] test-utils.workspace = true +expect-test.workspace = true [features] in-rust-tree = ["parser/in-rust-tree", "tt/in-rust-tree", "syntax/in-rust-tree"] diff --git a/src/tools/rust-analyzer/crates/mbe/src/lib.rs b/src/tools/rust-analyzer/crates/mbe/src/lib.rs index 88785537c7d20..f7b6e8f54b572 100644 --- a/src/tools/rust-analyzer/crates/mbe/src/lib.rs +++ b/src/tools/rust-analyzer/crates/mbe/src/lib.rs @@ -11,6 +11,8 @@ mod parser; #[cfg(test)] mod benchmark; +#[cfg(test)] +mod tests; use span::{Edition, Span, SyntaxContextId}; use syntax_bridge::to_parser_input; diff --git a/src/tools/rust-analyzer/crates/mbe/src/tests.rs b/src/tools/rust-analyzer/crates/mbe/src/tests.rs new file mode 100644 index 0000000000000..5422c9ae644b0 --- /dev/null +++ b/src/tools/rust-analyzer/crates/mbe/src/tests.rs @@ -0,0 +1,179 @@ +//! Tests specific to declarative macros, aka macros by example. This covers +//! both stable `macro_rules!` macros as well as unstable `macro` macros. +// FIXME: Move more of the nameres independent tests from +// crates\hir-def\src\macro_expansion_tests\mod.rs to this +use expect_test::expect; +use span::{Edition, EditionedFileId, ErasedFileAstId, FileId, Span, SpanAnchor, SyntaxContextId}; +use stdx::format_to; +use syntax_bridge::insert_whitespace_into_node::insert_ws_into; +use tt::{TextRange, TextSize}; + +use crate::DeclarativeMacro; + +fn check_( + def_edition: Edition, + call_edition: Edition, + macro2: bool, + decl: &str, + arg: &str, + render_debug: bool, + expect: expect_test::Expect, + parse: parser::TopEntryPoint, +) { + let decl_tt = &syntax_bridge::parse_to_token_tree( + def_edition, + SpanAnchor { + file_id: EditionedFileId::new(FileId::from_raw(0), def_edition), + ast_id: ErasedFileAstId::from_raw(0), + }, + SyntaxContextId::ROOT, + decl, + ) + .unwrap(); + let mac = if macro2 { + DeclarativeMacro::parse_macro2(None, decl_tt, |_| def_edition) + } else { + DeclarativeMacro::parse_macro_rules(decl_tt, |_| def_edition) + }; + let call_anchor = SpanAnchor { + file_id: EditionedFileId::new(FileId::from_raw(1), call_edition), + ast_id: ErasedFileAstId::from_raw(0), + }; + let arg_tt = + syntax_bridge::parse_to_token_tree(call_edition, call_anchor, SyntaxContextId::ROOT, arg) + .unwrap(); + let res = mac.expand( + &arg_tt, + |_| (), + Span { + range: TextRange::up_to(TextSize::of(arg)), + anchor: call_anchor, + ctx: SyntaxContextId::ROOT, + }, + def_edition, + ); + let mut expect_res = String::new(); + if let Some(err) = res.err { + format_to!(expect_res, "{err:#?}\n\n",); + } + if render_debug { + format_to!(expect_res, "{:#?}\n\n", res.value.0); + } + let (node, _) = syntax_bridge::token_tree_to_syntax_node(&res.value.0, parse, def_edition); + format_to!(expect_res, "{}", insert_ws_into(node.syntax_node())); + expect.assert_eq(&expect_res); +} + +fn check( + def_edition: Edition, + call_edition: Edition, + decl: &str, + arg: &str, + expect: expect_test::Expect, +) { + check_( + def_edition, + call_edition, + false, + decl, + arg, + true, + expect, + parser::TopEntryPoint::SourceFile, + ); +} + +#[test] +fn token_mapping_smoke_test() { + check( + Edition::CURRENT, + Edition::CURRENT, + r#" +( struct $ident:ident ) => { + struct $ident { + map: ::std::collections::HashSet<()>, + } +}; +"#, + r#" +struct MyTraitMap2 +"#, + expect![[r#" + SUBTREE $$ 1:0@0..20#0 1:0@0..20#0 + IDENT struct 0:0@34..40#0 + IDENT MyTraitMap2 1:0@8..19#0 + SUBTREE {} 0:0@48..49#0 0:0@100..101#0 + IDENT map 0:0@58..61#0 + PUNCH : [alone] 0:0@61..62#0 + PUNCH : [joint] 0:0@63..64#0 + PUNCH : [alone] 0:0@64..65#0 + IDENT std 0:0@65..68#0 + PUNCH : [joint] 0:0@68..69#0 + PUNCH : [alone] 0:0@69..70#0 + IDENT collections 0:0@70..81#0 + PUNCH : [joint] 0:0@81..82#0 + PUNCH : [alone] 0:0@82..83#0 + IDENT HashSet 0:0@83..90#0 + PUNCH < [alone] 0:0@90..91#0 + SUBTREE () 0:0@91..92#0 0:0@92..93#0 + PUNCH > [joint] 0:0@93..94#0 + PUNCH , [alone] 0:0@94..95#0 + + struct MyTraitMap2 { + map: ::std::collections::HashSet<()>, + }"#]], + ); +} + +#[test] +fn token_mapping_floats() { + // Regression test for https://github.com/rust-lang/rust-analyzer/issues/12216 + // (and related issues) + check( + Edition::CURRENT, + Edition::CURRENT, + r#" +($($tt:tt)*) => { + $($tt)* +}; +"#, + r#" +fn main() { + 1; + 1.0; + ((1,),).0.0; + let x = 1; +} +"#, + expect![[r#" + SUBTREE $$ 1:0@0..63#0 1:0@0..63#0 + IDENT fn 1:0@1..3#0 + IDENT main 1:0@4..8#0 + SUBTREE () 1:0@8..9#0 1:0@9..10#0 + SUBTREE {} 1:0@11..12#0 1:0@61..62#0 + LITERAL Integer 1 1:0@17..18#0 + PUNCH ; [alone] 1:0@18..19#0 + LITERAL Float 1.0 1:0@24..27#0 + PUNCH ; [alone] 1:0@27..28#0 + SUBTREE () 1:0@33..34#0 1:0@39..40#0 + SUBTREE () 1:0@34..35#0 1:0@37..38#0 + LITERAL Integer 1 1:0@35..36#0 + PUNCH , [alone] 1:0@36..37#0 + PUNCH , [alone] 1:0@38..39#0 + PUNCH . [alone] 1:0@40..41#0 + LITERAL Float 0.0 1:0@41..44#0 + PUNCH ; [alone] 1:0@44..45#0 + IDENT let 1:0@50..53#0 + IDENT x 1:0@54..55#0 + PUNCH = [alone] 1:0@56..57#0 + LITERAL Integer 1 1:0@58..59#0 + PUNCH ; [alone] 1:0@59..60#0 + + fn main(){ + 1; + 1.0; + ((1,),).0.0; + let x = 1; + }"#]], + ); +} diff --git a/src/tools/rust-analyzer/crates/ide-db/src/syntax_helpers/insert_whitespace_into_node.rs b/src/tools/rust-analyzer/crates/syntax-bridge/src/insert_whitespace_into_node.rs similarity index 97% rename from src/tools/rust-analyzer/crates/ide-db/src/syntax_helpers/insert_whitespace_into_node.rs rename to src/tools/rust-analyzer/crates/syntax-bridge/src/insert_whitespace_into_node.rs index dd4a665e8eb4f..a61fca9ec520c 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/syntax_helpers/insert_whitespace_into_node.rs +++ b/src/tools/rust-analyzer/crates/syntax-bridge/src/insert_whitespace_into_node.rs @@ -7,8 +7,6 @@ use syntax::{ SyntaxNode, SyntaxToken, WalkEvent, T, }; -// FIXME: It would also be cool to share logic here and in the mbe tests, -// which are pretty unreadable at the moment. /// Renders a [`SyntaxNode`] with whitespace inserted between tokens that require them. pub fn insert_ws_into(syn: SyntaxNode) -> SyntaxNode { let mut indent = 0; diff --git a/src/tools/rust-analyzer/crates/syntax-bridge/src/lib.rs b/src/tools/rust-analyzer/crates/syntax-bridge/src/lib.rs index 56e43e82ed27a..f23b33127fe49 100644 --- a/src/tools/rust-analyzer/crates/syntax-bridge/src/lib.rs +++ b/src/tools/rust-analyzer/crates/syntax-bridge/src/lib.rs @@ -17,6 +17,7 @@ use tt::{ token_to_literal, }; +pub mod insert_whitespace_into_node; mod to_parser_input; pub use to_parser_input::to_parser_input; // FIXME: we probably should re-think `token_tree_to_syntax_node` interfaces diff --git a/src/tools/rust-analyzer/crates/vfs/src/lib.rs b/src/tools/rust-analyzer/crates/vfs/src/lib.rs index bc40e03c5a246..a26444e9ea230 100644 --- a/src/tools/rust-analyzer/crates/vfs/src/lib.rs +++ b/src/tools/rust-analyzer/crates/vfs/src/lib.rs @@ -67,7 +67,7 @@ pub struct FileId(u32); // pub struct FileId(NonMaxU32); impl FileId { - pub const MAX: u32 = 0x7fff_ffff; + const MAX: u32 = 0x7fff_ffff; #[inline] pub const fn from_raw(raw: u32) -> FileId { From 193051438d7083f465f68c5fdca86c5e02b00a8f Mon Sep 17 00:00:00 2001 From: ding-young Date: Wed, 28 Aug 2024 13:24:17 +0900 Subject: [PATCH 0343/2194] update rewrite_assignment to return RewriteResult --- src/expr.rs | 70 +++++++++++++++++++++++++++++---------------------- src/items.rs | 18 +++++++------ src/macros.rs | 21 +++++++--------- src/types.rs | 5 ++-- 4 files changed, 63 insertions(+), 51 deletions(-) diff --git a/src/expr.rs b/src/expr.rs index 02372e7be130a..35b7bada92d4c 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -194,10 +194,10 @@ pub(crate) fn format_expr( rewrite_path(context, PathContext::Expr, qself, path, shape).ok() } ast::ExprKind::Assign(ref lhs, ref rhs, _) => { - rewrite_assignment(context, lhs, rhs, None, shape) + rewrite_assignment(context, lhs, rhs, None, shape).ok() } ast::ExprKind::AssignOp(ref op, ref lhs, ref rhs) => { - rewrite_assignment(context, lhs, rhs, Some(op), shape) + rewrite_assignment(context, lhs, rhs, Some(op), shape).ok() } ast::ExprKind::Continue(ref opt_label) => { let id_str = match *opt_label { @@ -2050,15 +2050,21 @@ fn rewrite_assignment( rhs: &ast::Expr, op: Option<&ast::BinOp>, shape: Shape, -) -> Option { +) -> RewriteResult { let operator_str = match op { Some(op) => context.snippet(op.span), None => "=", }; // 1 = space between lhs and operator. - let lhs_shape = shape.sub_width(operator_str.len() + 1)?; - let lhs_str = format!("{} {}", lhs.rewrite(context, lhs_shape)?, operator_str); + let lhs_shape = shape + .sub_width(operator_str.len() + 1) + .max_width_error(shape.width, lhs.span())?; + let lhs_str = format!( + "{} {}", + lhs.rewrite_result(context, lhs_shape)?, + operator_str + ); rewrite_assign_rhs( context, @@ -2089,7 +2095,7 @@ pub(crate) fn rewrite_assign_rhs, R: Rewrite>( ex: &R, rhs_kind: &RhsAssignKind<'_>, shape: Shape, -) -> Option { +) -> RewriteResult { rewrite_assign_rhs_with(context, lhs, ex, shape, rhs_kind, RhsTactics::Default) } @@ -2100,7 +2106,7 @@ pub(crate) fn rewrite_assign_rhs_expr( shape: Shape, rhs_kind: &RhsAssignKind<'_>, rhs_tactics: RhsTactics, -) -> Option { +) -> RewriteResult { let last_line_width = last_line_width(lhs).saturating_sub(if lhs.contains('\n') { shape.indent.width() } else { @@ -2122,7 +2128,7 @@ pub(crate) fn rewrite_assign_rhs_expr( context, ex, orig_shape, - ex.rewrite(context, orig_shape), + ex.rewrite_result(context, orig_shape), rhs_kind, rhs_tactics, has_rhs_comment, @@ -2136,10 +2142,10 @@ pub(crate) fn rewrite_assign_rhs_with, R: Rewrite>( shape: Shape, rhs_kind: &RhsAssignKind<'_>, rhs_tactics: RhsTactics, -) -> Option { +) -> RewriteResult { let lhs = lhs.into(); let rhs = rewrite_assign_rhs_expr(context, &lhs, ex, shape, rhs_kind, rhs_tactics)?; - Some(lhs + &rhs) + Ok(lhs + &rhs) } pub(crate) fn rewrite_assign_rhs_with_comments, R: Rewrite + Spanned>( @@ -2161,8 +2167,7 @@ pub(crate) fn rewrite_assign_rhs_with_comments, R: Rewrite + Spa } else { shape }; - let rhs = - rewrite_assign_rhs_expr(context, &lhs, ex, shape, rhs_kind, rhs_tactics).unknown_error()?; + let rhs = rewrite_assign_rhs_expr(context, &lhs, ex, shape, rhs_kind, rhs_tactics)?; if contains_comment { let rhs = rhs.trim_start(); combine_strs_with_missing_comments(context, &lhs, rhs, between_span, shape, allow_extend) @@ -2175,23 +2180,25 @@ fn choose_rhs( context: &RewriteContext<'_>, expr: &R, shape: Shape, - orig_rhs: Option, + orig_rhs: RewriteResult, _rhs_kind: &RhsAssignKind<'_>, rhs_tactics: RhsTactics, has_rhs_comment: bool, -) -> Option { +) -> RewriteResult { match orig_rhs { - Some(ref new_str) if new_str.is_empty() => Some(String::new()), - Some(ref new_str) - if !new_str.contains('\n') && unicode_str_width(new_str) <= shape.width => - { - Some(format!(" {new_str}")) + Ok(ref new_str) if new_str.is_empty() => Ok(String::new()), + Ok(ref new_str) if !new_str.contains('\n') && unicode_str_width(new_str) <= shape.width => { + Ok(format!(" {new_str}")) } _ => { // Expression did not fit on the same line as the identifier. // Try splitting the line and see if that works better. - let new_shape = shape_from_rhs_tactic(context, shape, rhs_tactics)?; - let new_rhs = expr.rewrite(context, new_shape); + let new_shape = shape_from_rhs_tactic(context, shape, rhs_tactics) + // TODO(ding-young) Ideally, we can replace unknown_error() with max_width_error(), + // but this requires either implementing the Spanned trait for ast::GenericBounds + // or grabbing the span from the call site. + .unknown_error()?; + let new_rhs = expr.rewrite_result(context, new_shape); let new_indent_str = &shape .indent .block_indent(context.config) @@ -2199,24 +2206,27 @@ fn choose_rhs( let before_space_str = if has_rhs_comment { "" } else { " " }; match (orig_rhs, new_rhs) { - (Some(ref orig_rhs), Some(ref new_rhs)) + (Ok(ref orig_rhs), Ok(ref new_rhs)) if !filtered_str_fits(&new_rhs, context.config.max_width(), new_shape) => { - Some(format!("{before_space_str}{orig_rhs}")) + Ok(format!("{before_space_str}{orig_rhs}")) } - (Some(ref orig_rhs), Some(ref new_rhs)) + (Ok(ref orig_rhs), Ok(ref new_rhs)) if prefer_next_line(orig_rhs, new_rhs, rhs_tactics) => { - Some(format!("{new_indent_str}{new_rhs}")) + Ok(format!("{new_indent_str}{new_rhs}")) } - (None, Some(ref new_rhs)) => Some(format!("{new_indent_str}{new_rhs}")), - (None, None) if rhs_tactics == RhsTactics::AllowOverflow => { + (Err(_), Ok(ref new_rhs)) => Ok(format!("{new_indent_str}{new_rhs}")), + (Err(_), Err(_)) if rhs_tactics == RhsTactics::AllowOverflow => { let shape = shape.infinite_width(); - expr.rewrite(context, shape) + expr.rewrite_result(context, shape) .map(|s| format!("{}{}", before_space_str, s)) } - (None, None) => None, - (Some(orig_rhs), _) => Some(format!("{before_space_str}{orig_rhs}")), + // When both orig_rhs and new_rhs result in errors, we currently propagate + // the error from the second attempt since it is more generous with + // width constraints. This decision is somewhat arbitrary and is open to change. + (Err(_), Err(new_rhs_err)) => Err(new_rhs_err), + (Ok(orig_rhs), _) => Ok(format!("{before_space_str}{orig_rhs}")), } } } diff --git a/src/items.rs b/src/items.rs index 3894ee2cdf8c8..4ea9751e81660 100644 --- a/src/items.rs +++ b/src/items.rs @@ -137,8 +137,7 @@ impl Rewrite for ast::Local { init, &RhsAssignKind::Expr(&init.kind, init.span), nested_shape, - ) - .max_width_error(shape.width, self.span())?; + )?; if let Some(block) = else_block { let else_kw_span = init.span.between(block.span); @@ -711,7 +710,8 @@ impl<'a> FmtVisitor<'a> { shape, &RhsAssignKind::Expr(&ex.kind, ex.span), RhsTactics::AllowOverflow, - )? + ) + .ok()? } else { variant_body }; @@ -1206,7 +1206,8 @@ pub(crate) fn format_trait( shape, &RhsAssignKind::Bounds, RhsTactics::ForceNextLineWithoutIndent, - )?; + ) + .ok()?; } // Rewrite where-clause. @@ -1396,6 +1397,7 @@ pub(crate) fn format_trait_alias( shape.sub_width(1)?, ) .map(|s| s + ";") + .ok() } fn format_unit_struct( @@ -1835,7 +1837,9 @@ fn rewrite_ty( // 1 = `;` let shape = Shape::indented(indent, context.config).sub_width(1)?; - rewrite_assign_rhs(context, lhs, &*ty, &RhsAssignKind::Ty, shape).map(|s| s + ";") + rewrite_assign_rhs(context, lhs, &*ty, &RhsAssignKind::Ty, shape) + .map(|s| s + ";") + .ok() } else { Some(format!("{result};")) } @@ -1931,8 +1935,7 @@ pub(crate) fn rewrite_struct_field( let is_prefix_empty = prefix.is_empty(); // We must use multiline. We are going to put attributes and a field on different lines. - let field_str = rewrite_assign_rhs(context, prefix, &*field.ty, &RhsAssignKind::Ty, shape) - .unknown_error()?; + let field_str = rewrite_assign_rhs(context, prefix, &*field.ty, &RhsAssignKind::Ty, shape)?; // Remove a leading white-space from `rewrite_assign_rhs()` when rewriting a tuple struct. let field_str = if is_prefix_empty { field_str.trim_start() @@ -3421,6 +3424,7 @@ impl Rewrite for ast::ForeignItem { shape.sub_width(1)?, ) .map(|s| s + ";") + .ok() } ast::ForeignItemKind::TyAlias(ref ty_alias) => { let (kind, span) = (&ItemVisitorKind::ForeignItem(self), self.span); diff --git a/src/macros.rs b/src/macros.rs index 51ded8692296b..5e537002324f8 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -1437,18 +1437,15 @@ fn format_lazy_static( id, ty.rewrite_result(context, nested_shape)? )); - result.push_str( - &rewrite_assign_rhs( - context, - stmt, - &*expr, - &RhsAssignKind::Expr(&expr.kind, expr.span), - nested_shape - .sub_width(1) - .max_width_error(nested_shape.width, expr.span)?, - ) - .unknown_error()?, - ); + result.push_str(&rewrite_assign_rhs( + context, + stmt, + &*expr, + &RhsAssignKind::Expr(&expr.kind, expr.span), + nested_shape + .sub_width(1) + .max_width_error(nested_shape.width, expr.span)?, + )?); result.push(';'); if i != last { result.push_str(&nested_shape.indent.to_string_with_newline(context.config)); diff --git a/src/types.rs b/src/types.rs index 76eb0ea0529cb..d1cd291d51f58 100644 --- a/src/types.rs +++ b/src/types.rs @@ -475,7 +475,7 @@ impl Rewrite for ast::WherePredicate { format!("{type_str}{colon}") }; - rewrite_assign_rhs(context, lhs, bounds, &RhsAssignKind::Bounds, shape)? + rewrite_assign_rhs(context, lhs, bounds, &RhsAssignKind::Bounds, shape).ok()? } ast::WherePredicate::RegionPredicate(ast::WhereRegionPredicate { ref lifetime, @@ -488,7 +488,8 @@ impl Rewrite for ast::WherePredicate { .. }) => { let lhs_ty_str = lhs_ty.rewrite(context, shape).map(|lhs| lhs + " =")?; - rewrite_assign_rhs(context, lhs_ty_str, &**rhs_ty, &RhsAssignKind::Ty, shape)? + rewrite_assign_rhs(context, lhs_ty_str, &**rhs_ty, &RhsAssignKind::Ty, shape) + .ok()? } }; From 35b3889c77fd98b2c9ec8ab93ffd516187bdd7f6 Mon Sep 17 00:00:00 2001 From: ding-young Date: Fri, 23 Aug 2024 18:29:59 +0900 Subject: [PATCH 0344/2194] impl rewrite_result for ControlFlow, Stmt, update rewrite_index --- src/comment.rs | 7 ++-- src/expr.rs | 85 +++++++++++++++++++++++++++++-------------------- src/items.rs | 2 +- src/overflow.rs | 11 ++++--- src/stmt.rs | 30 ++++++++++++----- src/types.rs | 26 +++++++++------ 6 files changed, 101 insertions(+), 60 deletions(-) diff --git a/src/comment.rs b/src/comment.rs index 5bf3c1a725c89..c8cadf364daf8 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -1703,12 +1703,11 @@ impl<'a> Iterator for CommentCodeSlices<'a> { } /// Checks is `new` didn't miss any comment from `span`, if it removed any, return previous text -/// (if it fits in the width/offset, else return `None`), else return `new` pub(crate) fn recover_comment_removed( new: String, span: Span, context: &RewriteContext<'_>, -) -> Option { +) -> String { let snippet = context.snippet(span); if snippet != new && changed_comment_content(snippet, &new) { // We missed some comments. Warn and keep the original text. @@ -1722,9 +1721,9 @@ pub(crate) fn recover_comment_removed( )], ); } - Some(snippet.to_owned()) + snippet.to_owned() } else { - Some(new) + new } } diff --git a/src/expr.rs b/src/expr.rs index 35b7bada92d4c..8381e3ab0835e 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -278,7 +278,7 @@ pub(crate) fn format_expr( ) .ok(), ast::ExprKind::Index(ref expr, ref index, _) => { - rewrite_index(&**expr, &**index, context, shape) + rewrite_index(&**expr, &**index, context, shape).ok() } ast::ExprKind::Repeat(ref expr, ref repeats) => rewrite_pair( &**expr, @@ -435,7 +435,7 @@ pub(crate) fn format_expr( }; expr_rw - .and_then(|expr_str| recover_comment_removed(expr_str, expr.span, context)) + .map(|expr_str| recover_comment_removed(expr_str, expr.span, context)) .and_then(|expr_str| { let attrs = outer_attributes(&expr.attrs); let attrs_str = attrs.rewrite(context, shape)?; @@ -672,6 +672,7 @@ pub(crate) fn rewrite_cond( String::from("\n") + &shape.indent.block_only().to_string(context.config); control_flow .rewrite_cond(context, shape, &alt_block_sep) + .ok() .map(|rw| rw.0) }), } @@ -896,10 +897,12 @@ impl<'a> ControlFlow<'a> { expr: &ast::Expr, shape: Shape, offset: usize, - ) -> Option { + ) -> RewriteResult { debug!("rewrite_pat_expr {:?} {:?} {:?}", shape, self.pat, expr); - let cond_shape = shape.offset_left(offset)?; + let cond_shape = shape + .offset_left(offset) + .max_width_error(shape.width, expr.span)?; if let Some(pat) = self.pat { let matcher = if self.matcher.is_empty() { self.matcher.to_owned() @@ -907,9 +910,10 @@ impl<'a> ControlFlow<'a> { format!("{} ", self.matcher) }; let pat_shape = cond_shape - .offset_left(matcher.len())? - .sub_width(self.connector.len())?; - let pat_string = pat.rewrite(context, pat_shape)?; + .offset_left(matcher.len()) + .and_then(|s| s.sub_width(self.connector.len())) + .max_width_error(cond_shape.width, pat.span)?; + let pat_string = pat.rewrite_result(context, pat_shape)?; let comments_lo = context .snippet_provider .span_after(self.span.with_lo(pat.span.hi()), self.connector.trim()); @@ -923,14 +927,13 @@ impl<'a> ControlFlow<'a> { RhsTactics::Default, comments_span, true, - ) - .ok(); + ); } - let expr_rw = expr.rewrite(context, cond_shape); + let expr_rw = expr.rewrite_result(context, cond_shape); // The expression may (partially) fit on the current line. // We do not allow splitting between `if` and condition. - if self.keyword == "if" || expr_rw.is_some() { + if self.keyword == "if" || expr_rw.is_ok() { return expr_rw; } @@ -939,7 +942,7 @@ impl<'a> ControlFlow<'a> { .block_indent(context.config.tab_spaces()) .with_max_width(context.config); let nested_indent_str = nested_shape.indent.to_string_with_newline(context.config); - expr.rewrite(context, nested_shape) + expr.rewrite_result(context, nested_shape) .map(|expr_rw| format!("{}{}", nested_indent_str, expr_rw)) } @@ -948,7 +951,7 @@ impl<'a> ControlFlow<'a> { context: &RewriteContext<'_>, shape: Shape, alt_block_sep: &str, - ) -> Option<(String, usize)> { + ) -> Result<(String, usize), RewriteError> { // Do not take the rhs overhead from the upper expressions into account // when rewriting pattern. let new_width = context.budget(shape.used_width()); @@ -959,7 +962,9 @@ impl<'a> ControlFlow<'a> { let constr_shape = if self.nested_if { // We are part of an if-elseif-else chain. Our constraints are tightened. // 7 = "} else " .len() - fresh_shape.offset_left(7)? + fresh_shape + .offset_left(7) + .max_width_error(fresh_shape.width, self.span)? } else { fresh_shape }; @@ -995,7 +1000,7 @@ impl<'a> ControlFlow<'a> { if let Some(cond_str) = trial { if cond_str.len() <= context.config.single_line_if_else_max_width() { - return Some((cond_str, 0)); + return Ok((cond_str, 0)); } } } @@ -1048,7 +1053,7 @@ impl<'a> ControlFlow<'a> { label_string.len() + self.keyword.len() + pat_expr_string.len() + 2 }; - Some(( + Ok(( format!( "{}{}{}{}{}", label_string, @@ -1114,13 +1119,17 @@ pub(crate) fn rewrite_else_kw_with_comments( impl<'a> Rewrite for ControlFlow<'a> { fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option { + self.rewrite_result(context, shape).ok() + } + + fn rewrite_result(&self, context: &RewriteContext<'_>, shape: Shape) -> RewriteResult { debug!("ControlFlow::rewrite {:?} {:?}", self, shape); let alt_block_sep = &shape.indent.to_string_with_newline(context.config); let (cond_str, used_width) = self.rewrite_cond(context, shape, alt_block_sep)?; // If `used_width` is 0, it indicates that whole control flow is written in a single line. if used_width == 0 { - return Some(cond_str); + return Ok(cond_str); } let block_width = shape.width.saturating_sub(used_width); @@ -1138,8 +1147,7 @@ impl<'a> Rewrite for ControlFlow<'a> { let block_str = { let old_val = context.is_if_else_block.replace(self.else_block.is_some()); let result = - rewrite_block_with_visitor(context, "", self.block, None, None, block_shape, true) - .ok(); + rewrite_block_with_visitor(context, "", self.block, None, None, block_shape, true); context.is_if_else_block.replace(old_val); result? }; @@ -1165,7 +1173,7 @@ impl<'a> Rewrite for ControlFlow<'a> { true, mk_sp(else_block.span.lo(), self.span.hi()), ) - .rewrite(context, shape) + .rewrite_result(context, shape) } _ => { last_in_chain = true; @@ -1176,6 +1184,7 @@ impl<'a> Rewrite for ControlFlow<'a> { ..shape }; format_expr(else_block, ExprType::Statement, context, else_shape) + .unknown_error() } }; @@ -1190,7 +1199,7 @@ impl<'a> Rewrite for ControlFlow<'a> { result.push_str(&rewrite?); } - Some(result) + Ok(result) } } @@ -1567,8 +1576,8 @@ fn rewrite_index( index: &ast::Expr, context: &RewriteContext<'_>, shape: Shape, -) -> Option { - let expr_str = expr.rewrite(context, shape)?; +) -> RewriteResult { + let expr_str = expr.rewrite_result(context, shape)?; let offset = last_line_width(&expr_str) + 1; let rhs_overhead = shape.rhs_overhead(context.config); @@ -1583,37 +1592,45 @@ fn rewrite_index( .and_then(|shape| shape.sub_width(1)), IndentStyle::Visual => shape.visual_indent(offset).sub_width(offset + 1), } - }; - let orig_index_rw = index_shape.and_then(|s| index.rewrite(context, s)); + } + .max_width_error(shape.width, index.span()); + let orig_index_rw = index_shape.and_then(|s| index.rewrite_result(context, s)); // Return if index fits in a single line. match orig_index_rw { - Some(ref index_str) if !index_str.contains('\n') => { - return Some(format!("{expr_str}[{index_str}]")); + Ok(ref index_str) if !index_str.contains('\n') => { + return Ok(format!("{expr_str}[{index_str}]")); } _ => (), } // Try putting index on the next line and see if it fits in a single line. let indent = shape.indent.block_indent(context.config); - let index_shape = Shape::indented(indent, context.config).offset_left(1)?; - let index_shape = index_shape.sub_width(1 + rhs_overhead)?; - let new_index_rw = index.rewrite(context, index_shape); + let index_shape = Shape::indented(indent, context.config) + .offset_left(1) + .max_width_error(shape.width, index.span())?; + let index_shape = index_shape + .sub_width(1 + rhs_overhead) + .max_width_error(index_shape.width, index.span())?; + let new_index_rw = index.rewrite_result(context, index_shape); match (orig_index_rw, new_index_rw) { - (_, Some(ref new_index_str)) if !new_index_str.contains('\n') => Some(format!( + (_, Ok(ref new_index_str)) if !new_index_str.contains('\n') => Ok(format!( "{}{}[{}]", expr_str, indent.to_string_with_newline(context.config), new_index_str, )), - (None, Some(ref new_index_str)) => Some(format!( + (Err(_), Ok(ref new_index_str)) => Ok(format!( "{}{}[{}]", expr_str, indent.to_string_with_newline(context.config), new_index_str, )), - (Some(ref index_str), _) => Some(format!("{expr_str}[{index_str}]")), - _ => None, + (Ok(ref index_str), _) => Ok(format!("{expr_str}[{index_str}]")), + // When both orig_index_rw and new_index_rw result in errors, we currently propagate the + // error from the second attempt since it is more generous with width constraints. + // This decision is somewhat arbitrary and is open to change. + (Err(_), Err(new_index_rw_err)) => Err(new_index_rw_err), } } diff --git a/src/items.rs b/src/items.rs index 4ea9751e81660..89fb9bda9dfca 100644 --- a/src/items.rs +++ b/src/items.rs @@ -2077,7 +2077,7 @@ fn rewrite_static( true, ) .ok() - .and_then(|res| recover_comment_removed(res, static_parts.span, context)) + .map(|res| recover_comment_removed(res, static_parts.span, context)) .map(|s| if s.ends_with(';') { s } else { s + ";" }) } else { Some(format!("{prefix}{ty_str};")) diff --git a/src/overflow.rs b/src/overflow.rs index 510ad3c642e6c..dc4716a81af9b 100644 --- a/src/overflow.rs +++ b/src/overflow.rs @@ -19,7 +19,7 @@ use crate::lists::{ }; use crate::macros::MacroArg; use crate::patterns::{can_be_overflowed_pat, TuplePatField}; -use crate::rewrite::{Rewrite, RewriteContext, RewriteErrorExt, RewriteResult}; +use crate::rewrite::{Rewrite, RewriteContext, RewriteError, RewriteErrorExt, RewriteResult}; use crate::shape::Shape; use crate::source_map::SpanUtils; use crate::spanned::Spanned; @@ -90,6 +90,10 @@ impl<'a> Rewrite for OverflowableItem<'a> { fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option { self.map(|item| item.rewrite(context, shape)) } + + fn rewrite_result(&self, context: &RewriteContext<'_>, shape: Shape) -> RewriteResult { + self.map(|item| item.rewrite_result(context, shape)) + } } impl<'a> Spanned for OverflowableItem<'a> { @@ -617,7 +621,7 @@ impl<'a> Context<'a> { tactic } - fn rewrite_items(&self) -> Option<(bool, String)> { + fn rewrite_items(&self) -> Result<(bool, String), RewriteError> { let span = self.items_span(); debug!("items: {:?}", self.items); @@ -661,7 +665,6 @@ impl<'a> Context<'a> { .ends_with_newline(ends_with_newline); write_list(&list_items, &fmt) - .ok() .map(|items_str| (tactic == DefinitiveListTactic::Horizontal, items_str)) } @@ -718,7 +721,7 @@ impl<'a> Context<'a> { } fn rewrite(&self, shape: Shape) -> RewriteResult { - let (extendable, items_str) = self.rewrite_items().unknown_error()?; + let (extendable, items_str) = self.rewrite_items()?; // If we are using visual indent style and failed to format, retry with block indent. if !self.context.use_block_indent() diff --git a/src/stmt.rs b/src/stmt.rs index 38433433c6b5e..4f31705295eb1 100644 --- a/src/stmt.rs +++ b/src/stmt.rs @@ -4,7 +4,7 @@ use rustc_span::Span; use crate::comment::recover_comment_removed; use crate::config::StyleEdition; use crate::expr::{format_expr, is_simple_block, ExprType}; -use crate::rewrite::{Rewrite, RewriteContext}; +use crate::rewrite::{Rewrite, RewriteContext, RewriteError, RewriteErrorExt, RewriteResult}; use crate::shape::Shape; use crate::source_map::LineRangeUtils; use crate::spanned::Spanned; @@ -90,6 +90,14 @@ impl<'a> Stmt<'a> { impl<'a> Rewrite for Stmt<'a> { fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option { + self.rewrite_result(context, shape).ok() + } + + fn rewrite_result( + &self, + context: &RewriteContext<'_>, + shape: Shape, + ) -> crate::rewrite::RewriteResult { let expr_type = if context.config.style_edition() >= StyleEdition::Edition2024 && self.is_last_expr() { ExprType::SubExpression @@ -112,11 +120,11 @@ fn format_stmt( stmt: &ast::Stmt, expr_type: ExprType, is_last_expr: bool, -) -> Option { - skip_out_of_file_lines_range!(context, stmt.span()); +) -> RewriteResult { + skip_out_of_file_lines_range_err!(context, stmt.span()); let result = match stmt.kind { - ast::StmtKind::Let(ref local) => local.rewrite(context, shape), + ast::StmtKind::Let(ref local) => local.rewrite_result(context, shape), ast::StmtKind::Expr(ref ex) | ast::StmtKind::Semi(ref ex) => { let suffix = if semicolon_for_stmt(context, stmt, is_last_expr) { ";" @@ -124,10 +132,16 @@ fn format_stmt( "" }; - let shape = shape.sub_width(suffix.len())?; - format_expr(ex, expr_type, context, shape).map(|s| s + suffix) + let shape = shape + .sub_width(suffix.len()) + .max_width_error(shape.width, ex.span())?; + format_expr(ex, expr_type, context, shape) + .map(|s| s + suffix) + .unknown_error() + } + ast::StmtKind::MacCall(..) | ast::StmtKind::Item(..) | ast::StmtKind::Empty => { + Err(RewriteError::Unknown) } - ast::StmtKind::MacCall(..) | ast::StmtKind::Item(..) | ast::StmtKind::Empty => None, }; - result.and_then(|res| recover_comment_removed(res, stmt.span(), context)) + result.map(|res| recover_comment_removed(res, stmt.span(), context)) } diff --git a/src/types.rs b/src/types.rs index d1cd291d51f58..af57a5843dbe6 100644 --- a/src/types.rs +++ b/src/types.rs @@ -480,8 +480,8 @@ impl Rewrite for ast::WherePredicate { ast::WherePredicate::RegionPredicate(ast::WhereRegionPredicate { ref lifetime, ref bounds, - .. - }) => rewrite_bounded_lifetime(lifetime, bounds, context, shape)?, + span, + }) => rewrite_bounded_lifetime(lifetime, bounds, span, context, shape).ok()?, ast::WherePredicate::EqPredicate(ast::WhereEqPredicate { ref lhs_ty, ref rhs_ty, @@ -553,23 +553,27 @@ fn rewrite_generic_args( fn rewrite_bounded_lifetime( lt: &ast::Lifetime, bounds: &[ast::GenericBound], + span: Span, context: &RewriteContext<'_>, shape: Shape, -) -> Option { - let result = lt.rewrite(context, shape)?; +) -> RewriteResult { + let result = lt.rewrite_result(context, shape)?; if bounds.is_empty() { - Some(result) + Ok(result) } else { let colon = type_bound_colon(context); let overhead = last_line_width(&result) + colon.len(); + let shape = shape + .sub_width(overhead) + .max_width_error(shape.width, span)?; let result = format!( "{}{}{}", result, colon, - join_bounds(context, shape.sub_width(overhead)?, bounds, true).ok()? + join_bounds(context, shape, bounds, true)? ); - Some(result) + Ok(result) } } @@ -580,8 +584,12 @@ impl Rewrite for ast::AnonConst { } impl Rewrite for ast::Lifetime { - fn rewrite(&self, context: &RewriteContext<'_>, _: Shape) -> Option { - Some(rewrite_ident(context, self.ident).to_owned()) + fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option { + self.rewrite_result(context, shape).ok() + } + + fn rewrite_result(&self, context: &RewriteContext<'_>, _: Shape) -> RewriteResult { + Ok(rewrite_ident(context, self.ident).to_owned()) } } From 47e6b5deed5cc79c677def8d1a165658fa79d810 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Sun, 1 Sep 2024 16:35:53 +0200 Subject: [PATCH 0345/2194] Revert "Auto merge of #127537 - veluca93:struct_tf, r=BoxyUwU" This reverts commit acb4e8b6251f1d8da36f08e7a70fa23fc581839e, reversing changes made to 100fde5246bf56f22fb5cc85374dd841296fce0e. --- .../rustc_codegen_ssa/src/codegen_attrs.rs | 125 ++---------------- compiler/rustc_feature/src/unstable.rs | 2 - compiler/rustc_hir/src/def.rs | 35 ----- compiler/rustc_hir_typeck/src/coercion.rs | 2 - .../src/rmeta/decoder/cstore_impl.rs | 1 - compiler/rustc_metadata/src/rmeta/encoder.rs | 3 - compiler/rustc_metadata/src/rmeta/mod.rs | 3 +- .../src/middle/codegen_fn_attrs.rs | 8 +- compiler/rustc_middle/src/query/mod.rs | 7 +- compiler/rustc_middle/src/ty/parameterized.rs | 1 - compiler/rustc_mir_build/messages.ftl | 16 --- .../rustc_mir_build/src/check_unsafety.rs | 46 +------ compiler/rustc_mir_build/src/errors.rs | 35 ----- compiler/rustc_passes/messages.ftl | 4 - compiler/rustc_passes/src/check_attr.rs | 33 +---- compiler/rustc_passes/src/errors.rs | 9 -- compiler/rustc_span/src/symbol.rs | 1 - .../traits/fulfillment_errors.rs | 2 - .../src/traits/select/candidate_assembly.rs | 2 - .../struct-target-features.md | 7 - tests/assembly/struct-target-features.rs | 37 ------ .../feature-gate-struct-target-features.rs | 4 - ...feature-gate-struct-target-features.stderr | 10 -- .../target-feature/struct-target-features.rs | 98 -------------- .../struct-target-features.stderr | 47 ------- 25 files changed, 27 insertions(+), 511 deletions(-) delete mode 100644 src/doc/unstable-book/src/language-features/struct-target-features.md delete mode 100644 tests/assembly/struct-target-features.rs delete mode 100644 tests/ui/feature-gates/feature-gate-struct-target-features.rs delete mode 100644 tests/ui/feature-gates/feature-gate-struct-target-features.stderr delete mode 100644 tests/ui/target-feature/struct-target-features.rs delete mode 100644 tests/ui/target-feature/struct-target-features.stderr diff --git a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs index 209750d6ba612..4ab20c154ccd0 100644 --- a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs +++ b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs @@ -1,6 +1,5 @@ use rustc_ast::{ast, attr, MetaItemKind, NestedMetaItem}; use rustc_attr::{list_contains_name, InlineAttr, InstructionSetAttr, OptimizeAttr}; -use rustc_data_structures::fx::FxHashSet; use rustc_errors::codes::*; use rustc_errors::{struct_span_code_err, DiagMessage, SubdiagMessage}; use rustc_hir as hir; @@ -9,7 +8,7 @@ use rustc_hir::def_id::{DefId, LocalDefId, LOCAL_CRATE}; use rustc_hir::weak_lang_items::WEAK_LANG_ITEMS; use rustc_hir::{lang_items, LangItem}; use rustc_middle::middle::codegen_fn_attrs::{ - CodegenFnAttrFlags, CodegenFnAttrs, PatchableFunctionEntry, TargetFeature, + CodegenFnAttrFlags, CodegenFnAttrs, PatchableFunctionEntry, }; use rustc_middle::mir::mono::Linkage; use rustc_middle::query::Providers; @@ -18,7 +17,6 @@ use rustc_session::lint; use rustc_session::parse::feature_err; use rustc_span::symbol::Ident; use rustc_span::{sym, Span}; -use rustc_target::abi::VariantIdx; use rustc_target::spec::{abi, SanitizerSet}; use crate::errors; @@ -80,13 +78,6 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs { let mut link_ordinal_span = None; let mut no_sanitize_span = None; - let fn_sig_outer = || { - use DefKind::*; - - let def_kind = tcx.def_kind(did); - if let Fn | AssocFn | Variant | Ctor(..) = def_kind { Some(tcx.fn_sig(did)) } else { None } - }; - for attr in attrs.iter() { // In some cases, attribute are only valid on functions, but it's the `check_attr` // pass that check that they aren't used anywhere else, rather this module. @@ -94,12 +85,16 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs { // functions (such as calling `fn_sig`, which ICEs if given a non-function). We also // report a delayed bug, just in case `check_attr` isn't doing its job. let fn_sig = || { - let sig = fn_sig_outer(); - if sig.is_none() { + use DefKind::*; + + let def_kind = tcx.def_kind(did); + if let Fn | AssocFn | Variant | Ctor(..) = def_kind { + Some(tcx.fn_sig(did)) + } else { tcx.dcx() .span_delayed_bug(attr.span, "this attribute can only be applied to functions"); + None } - sig }; let Some(Ident { name, .. }) = attr.ident() else { @@ -618,93 +613,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs { } } - if let Some(sig) = fn_sig_outer() { - // Collect target features from types reachable from arguments. - // We define a type as "reachable" if: - // - it is a function argument - // - it is a field of a reachable struct - // - there is a reachable reference to it - // FIXME(struct_target_features): we may want to cache the result of this computation. - let mut visited_types = FxHashSet::default(); - let mut reachable_types: Vec<_> = sig.skip_binder().inputs().skip_binder().to_owned(); - let mut additional_tf = vec![]; - - while let Some(ty) = reachable_types.pop() { - if visited_types.contains(&ty) { - continue; - } - visited_types.insert(ty); - match ty.kind() { - ty::Alias(..) => { - if let Ok(t) = - tcx.try_normalize_erasing_regions(tcx.param_env(did.to_def_id()), ty) - { - reachable_types.push(t) - } - } - - ty::Ref(_, inner, _) => reachable_types.push(*inner), - ty::Tuple(tys) => reachable_types.extend(tys.iter()), - ty::Adt(adt_def, args) => { - additional_tf.extend_from_slice(tcx.struct_target_features(adt_def.did())); - // This only recurses into structs as i.e. an Option is an ADT - // that doesn't actually always contain a TargetFeature. - if adt_def.is_struct() { - reachable_types.extend( - adt_def - .variant(VariantIdx::from_usize(0)) - .fields - .iter() - .map(|field| field.ty(tcx, args)), - ); - } - } - ty::Bool - | ty::Char - | ty::Int(..) - | ty::Uint(..) - | ty::Float(..) - | ty::Foreign(..) - | ty::Str - | ty::Array(..) - | ty::Pat(..) - | ty::Slice(..) - | ty::RawPtr(..) - | ty::FnDef(..) - | ty::FnPtr(..) - | ty::Dynamic(..) - | ty::Closure(..) - | ty::CoroutineClosure(..) - | ty::Coroutine(..) - | ty::CoroutineWitness(..) - | ty::Never - | ty::Param(..) - | ty::Bound(..) - | ty::Placeholder(..) - | ty::Infer(..) - | ty::Error(..) => (), - } - } - - // FIXME(struct_target_features): is this really necessary? - if !additional_tf.is_empty() && sig.skip_binder().abi() != abi::Abi::Rust { - tcx.dcx().span_err( - tcx.hir().span(tcx.local_def_id_to_hir_id(did)), - "cannot use a struct with target features in a function with non-Rust ABI", - ); - } - if !additional_tf.is_empty() && codegen_fn_attrs.inline == InlineAttr::Always { - tcx.dcx().span_err( - tcx.hir().span(tcx.local_def_id_to_hir_id(did)), - "cannot use a struct with target features in a #[inline(always)] function", - ); - } - codegen_fn_attrs - .target_features - .extend(additional_tf.iter().map(|tf| TargetFeature { implied: true, ..*tf })); - } - - // If a function uses non-default target_features it can't be inlined into general + // If a function uses #[target_feature] it can't be inlined into general // purpose functions as they wouldn't have the right target features // enabled. For that reason we also forbid #[inline(always)] as it can't be // respected. @@ -849,20 +758,6 @@ fn check_link_name_xor_ordinal( } } -fn struct_target_features(tcx: TyCtxt<'_>, def_id: LocalDefId) -> &[TargetFeature] { - let mut features = vec![]; - let supported_features = tcx.supported_target_features(LOCAL_CRATE); - for attr in tcx.get_attrs(def_id, sym::target_feature) { - from_target_feature(tcx, attr, supported_features, &mut features); - } - tcx.arena.alloc_slice(&features) -} - pub fn provide(providers: &mut Providers) { - *providers = Providers { - codegen_fn_attrs, - should_inherit_track_caller, - struct_target_features, - ..*providers - }; + *providers = Providers { codegen_fn_attrs, should_inherit_track_caller, ..*providers }; } diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index 7ea037ca8b2b6..ffeaa861220b2 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -597,8 +597,6 @@ declare_features! ( (unstable, strict_provenance, "1.61.0", Some(95228)), /// Allows string patterns to dereference values to match them. (unstable, string_deref_patterns, "1.67.0", Some(87121)), - /// Allows structs to carry target_feature information. - (incomplete, struct_target_features, "CURRENT_RUSTC_VERSION", Some(129107)), /// Allows the use of `#[target_feature]` on safe functions. (unstable, target_feature_11, "1.45.0", Some(69098)), /// Allows using `#[thread_local]` on `static` items. diff --git a/compiler/rustc_hir/src/def.rs b/compiler/rustc_hir/src/def.rs index c5dc4dacab650..bd55617d84ea2 100644 --- a/compiler/rustc_hir/src/def.rs +++ b/compiler/rustc_hir/src/def.rs @@ -326,41 +326,6 @@ impl DefKind { | DefKind::ExternCrate => false, } } - - /// Whether `query struct_target_features` should be used with this definition. - pub fn has_struct_target_features(self) -> bool { - match self { - DefKind::Struct | DefKind::Union | DefKind::Enum => true, - DefKind::Fn - | DefKind::AssocFn - | DefKind::Ctor(..) - | DefKind::Closure - | DefKind::Static { .. } - | DefKind::Mod - | DefKind::Variant - | DefKind::Trait - | DefKind::TyAlias - | DefKind::ForeignTy - | DefKind::TraitAlias - | DefKind::AssocTy - | DefKind::Const - | DefKind::AssocConst - | DefKind::Macro(..) - | DefKind::Use - | DefKind::ForeignMod - | DefKind::OpaqueTy - | DefKind::Impl { .. } - | DefKind::Field - | DefKind::TyParam - | DefKind::ConstParam - | DefKind::LifetimeParam - | DefKind::AnonConst - | DefKind::InlineConst - | DefKind::SyntheticCoroutineBody - | DefKind::GlobalAsm - | DefKind::ExternCrate => false, - } - } } /// The resolution of a path or export. diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs index 865e9be0a67dd..d97c590bd4109 100644 --- a/compiler/rustc_hir_typeck/src/coercion.rs +++ b/compiler/rustc_hir_typeck/src/coercion.rs @@ -851,8 +851,6 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { } // Safe `#[target_feature]` functions are not assignable to safe fn pointers (RFC 2396). - // FIXME(struct_target_features): should this be true also for functions that inherit - // target features from structs? if b_hdr.safety == hir::Safety::Safe && !self.tcx.codegen_fn_attrs(def_id).target_features.is_empty() diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs index a82340e3d6130..0f46cacc27a1a 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs @@ -254,7 +254,6 @@ provide! { tcx, def_id, other, cdata, variances_of => { table } fn_sig => { table } codegen_fn_attrs => { table } - struct_target_features => { table } impl_trait_header => { table } const_param_default => { table } object_lifetime_default => { table } diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 919623cff609c..88256c4db04ec 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -1392,9 +1392,6 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { if def_kind.has_codegen_attrs() { record!(self.tables.codegen_fn_attrs[def_id] <- self.tcx.codegen_fn_attrs(def_id)); } - if def_kind.has_struct_target_features() { - record_array!(self.tables.struct_target_features[def_id] <- self.tcx.struct_target_features(def_id)); - } if should_encode_visibility(def_kind) { let vis = self.tcx.local_visibility(local_id).map_id(|def_id| def_id.local_def_index); diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs index 987ee3f07e924..a84923130c3ab 100644 --- a/compiler/rustc_metadata/src/rmeta/mod.rs +++ b/compiler/rustc_metadata/src/rmeta/mod.rs @@ -19,7 +19,7 @@ use rustc_macros::{ Decodable, Encodable, MetadataDecodable, MetadataEncodable, TyDecodable, TyEncodable, }; use rustc_middle::metadata::ModChild; -use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrs, TargetFeature}; +use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrs; use rustc_middle::middle::debugger_visualizer::DebuggerVisualizerFile; use rustc_middle::middle::exported_symbols::{ExportedSymbol, SymbolExportInfo}; use rustc_middle::middle::lib_features::FeatureStability; @@ -427,7 +427,6 @@ define_tables! { variances_of: Table>, fn_sig: Table>>>, codegen_fn_attrs: Table>, - struct_target_features: Table>, impl_trait_header: Table>>, const_param_default: Table>>>, object_lifetime_default: Table>, diff --git a/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs b/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs index c098a73959230..b7d290e58d22b 100644 --- a/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs +++ b/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs @@ -26,8 +26,8 @@ pub struct CodegenFnAttrs { /// be set when `link_name` is set. This is for foreign items with the /// "raw-dylib" kind. pub link_ordinal: Option, - /// All the target features that are enabled for this function. Some features might be enabled - /// implicitly. + /// The `#[target_feature(enable = "...")]` attribute and the enabled + /// features (only enabled features are supported right now). pub target_features: Vec, /// The `#[linkage = "..."]` attribute on Rust-defined items and the value we found. pub linkage: Option, @@ -55,8 +55,8 @@ pub struct CodegenFnAttrs { pub struct TargetFeature { /// The name of the target feature (e.g. "avx") pub name: Symbol, - /// The feature is implied by another feature or by an argument, rather than explicitly - /// added by the `#[target_feature]` attribute + /// The feature is implied by another feature, rather than explicitly added by the + /// `#[target_feature]` attribute pub implied: bool, } diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index b6443778c936b..d6bdc1af0d2ca 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -47,7 +47,7 @@ use {rustc_ast as ast, rustc_attr as attr, rustc_hir as hir}; use crate::infer::canonical::{self, Canonical}; use crate::lint::LintExpectation; use crate::metadata::ModChild; -use crate::middle::codegen_fn_attrs::{CodegenFnAttrs, TargetFeature}; +use crate::middle::codegen_fn_attrs::CodegenFnAttrs; use crate::middle::debugger_visualizer::DebuggerVisualizerFile; use crate::middle::exported_symbols::{ExportedSymbol, SymbolExportInfo}; use crate::middle::lib_features::LibFeatures; @@ -1249,11 +1249,6 @@ rustc_queries! { feedable } - query struct_target_features(def_id: DefId) -> &'tcx [TargetFeature] { - separate_provide_extern - desc { |tcx| "computing target features for struct `{}`", tcx.def_path_str(def_id) } - } - query asm_target_features(def_id: DefId) -> &'tcx FxIndexSet { desc { |tcx| "computing target features for inline asm of `{}`", tcx.def_path_str(def_id) } } diff --git a/compiler/rustc_middle/src/ty/parameterized.rs b/compiler/rustc_middle/src/ty/parameterized.rs index be611e19b49a7..7e1255f606c35 100644 --- a/compiler/rustc_middle/src/ty/parameterized.rs +++ b/compiler/rustc_middle/src/ty/parameterized.rs @@ -59,7 +59,6 @@ trivially_parameterized_over_tcx! { std::string::String, crate::metadata::ModChild, crate::middle::codegen_fn_attrs::CodegenFnAttrs, - crate::middle::codegen_fn_attrs::TargetFeature, crate::middle::debugger_visualizer::DebuggerVisualizerFile, crate::middle::exported_symbols::SymbolExportInfo, crate::middle::lib_features::FeatureStability, diff --git a/compiler/rustc_mir_build/messages.ftl b/compiler/rustc_mir_build/messages.ftl index a42e8ff0168b2..7a10e627ccd89 100644 --- a/compiler/rustc_mir_build/messages.ftl +++ b/compiler/rustc_mir_build/messages.ftl @@ -125,17 +125,6 @@ mir_build_initializing_type_with_requires_unsafe_unsafe_op_in_unsafe_fn_allowed .note = initializing a layout restricted type's field with a value outside the valid range is undefined behavior .label = initializing type with `rustc_layout_scalar_valid_range` attr -mir_build_initializing_type_with_target_feature_requires_unsafe = - initializing type with `target_feature` attr is unsafe and requires unsafe block - .note = this struct can only be constructed if the corresponding `target_feature`s are available - .label = initializing type with `target_feature` attr - -mir_build_initializing_type_with_target_feature_requires_unsafe_unsafe_op_in_unsafe_fn_allowed = - initializing type with `target_feature` attr is unsafe and requires unsafe function or block - .note = this struct can only be constructed if the corresponding `target_feature`s are available - .label = initializing type with `target_feature` attr - - mir_build_inline_assembly_requires_unsafe = use of inline assembly is unsafe and requires unsafe block .note = inline assembly is entirely unchecked and can cause undefined behavior @@ -398,11 +387,6 @@ mir_build_unsafe_op_in_unsafe_fn_initializing_type_with_requires_unsafe = .note = initializing a layout restricted type's field with a value outside the valid range is undefined behavior .label = initializing type with `rustc_layout_scalar_valid_range` attr -mir_build_unsafe_op_in_unsafe_fn_initializing_type_with_target_feature_requires_unsafe = - initializing type with `target_feature` attr is unsafe and requires unsafe block - .note = this struct can only be constructed if the corresponding `target_feature`s are available - .label = initializing type with `target_feature` attr - mir_build_unsafe_op_in_unsafe_fn_inline_assembly_requires_unsafe = use of inline assembly is unsafe and requires unsafe block .note = inline assembly is entirely unchecked and can cause undefined behavior diff --git a/compiler/rustc_mir_build/src/check_unsafety.rs b/compiler/rustc_mir_build/src/check_unsafety.rs index 4ce796cea7ad3..c7fcfe3ce2aa0 100644 --- a/compiler/rustc_mir_build/src/check_unsafety.rs +++ b/compiler/rustc_mir_build/src/check_unsafety.rs @@ -461,18 +461,14 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> { }; self.requires_unsafe(expr.span, CallToUnsafeFunction(func_id)); } else if let &ty::FnDef(func_did, _) = self.thir[fun].ty.kind() { - // If the called function has explicit target features the calling function hasn't, + // If the called function has target features the calling function hasn't, // the call requires `unsafe`. Don't check this on wasm // targets, though. For more information on wasm see the // is_like_wasm check in hir_analysis/src/collect.rs - // Implicit target features are OK because they are either a consequence of some - // explicit target feature (which is checked to be present in the caller) or - // come from a witness argument. let callee_features = &self.tcx.codegen_fn_attrs(func_did).target_features; if !self.tcx.sess.target.options.is_like_wasm && !callee_features.iter().all(|feature| { - feature.implied - || self.body_target_features.iter().any(|f| f.name == feature.name) + self.body_target_features.iter().any(|f| f.name == feature.name) }) { let missing: Vec<_> = callee_features @@ -546,16 +542,10 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> { user_ty: _, fields: _, base: _, - }) => { - match self.tcx.layout_scalar_valid_range(adt_def.did()) { - (Bound::Unbounded, Bound::Unbounded) => {} - _ => self.requires_unsafe(expr.span, InitializingTypeWith), - } - if !self.tcx.struct_target_features(adt_def.did()).is_empty() { - self.requires_unsafe(expr.span, ConstructingTargetFeaturesType) - } - } - + }) => match self.tcx.layout_scalar_valid_range(adt_def.did()) { + (Bound::Unbounded, Bound::Unbounded) => {} + _ => self.requires_unsafe(expr.span, InitializingTypeWith), + }, ExprKind::Closure(box ClosureExpr { closure_id, args: _, @@ -657,7 +647,6 @@ enum UnsafeOpKind { CallToUnsafeFunction(Option), UseOfInlineAssembly, InitializingTypeWith, - ConstructingTargetFeaturesType, UseOfMutableStatic, UseOfExternStatic, DerefOfRawPointer, @@ -739,15 +728,6 @@ impl UnsafeOpKind { unsafe_not_inherited_note, }, ), - ConstructingTargetFeaturesType => tcx.emit_node_span_lint( - UNSAFE_OP_IN_UNSAFE_FN, - hir_id, - span, - UnsafeOpInUnsafeFnInitializingTypeWithTargetFeatureRequiresUnsafe { - span, - unsafe_not_inherited_note, - }, - ), UseOfMutableStatic => tcx.emit_node_span_lint( UNSAFE_OP_IN_UNSAFE_FN, hir_id, @@ -905,20 +885,6 @@ impl UnsafeOpKind { unsafe_not_inherited_note, }); } - ConstructingTargetFeaturesType if unsafe_op_in_unsafe_fn_allowed => { - dcx.emit_err( - InitializingTypeWithTargetFeatureRequiresUnsafeUnsafeOpInUnsafeFnAllowed { - span, - unsafe_not_inherited_note, - }, - ); - } - ConstructingTargetFeaturesType => { - dcx.emit_err(InitializingTypeWithTargetFeatureRequiresUnsafe { - span, - unsafe_not_inherited_note, - }); - } UseOfMutableStatic if unsafe_op_in_unsafe_fn_allowed => { dcx.emit_err(UseOfMutableStaticRequiresUnsafeUnsafeOpInUnsafeFnAllowed { span, diff --git a/compiler/rustc_mir_build/src/errors.rs b/compiler/rustc_mir_build/src/errors.rs index e7d6239aa9bf6..7f9eefd1d52e3 100644 --- a/compiler/rustc_mir_build/src/errors.rs +++ b/compiler/rustc_mir_build/src/errors.rs @@ -86,16 +86,6 @@ pub(crate) struct UnsafeOpInUnsafeFnInitializingTypeWithRequiresUnsafe { pub(crate) unsafe_not_inherited_note: Option, } -#[derive(LintDiagnostic)] -#[diag(mir_build_unsafe_op_in_unsafe_fn_initializing_type_with_target_feature_requires_unsafe, code = E0133)] -#[note] -pub(crate) struct UnsafeOpInUnsafeFnInitializingTypeWithTargetFeatureRequiresUnsafe { - #[label] - pub(crate) span: Span, - #[subdiagnostic] - pub(crate) unsafe_not_inherited_note: Option, -} - #[derive(LintDiagnostic)] #[diag(mir_build_unsafe_op_in_unsafe_fn_mutable_static_requires_unsafe, code = E0133)] #[note] @@ -260,17 +250,6 @@ pub(crate) struct InitializingTypeWithRequiresUnsafe { pub(crate) unsafe_not_inherited_note: Option, } -#[derive(Diagnostic)] -#[diag(mir_build_initializing_type_with_target_feature_requires_unsafe, code = E0133)] -#[note] -pub(crate) struct InitializingTypeWithTargetFeatureRequiresUnsafe { - #[primary_span] - #[label] - pub(crate) span: Span, - #[subdiagnostic] - pub(crate) unsafe_not_inherited_note: Option, -} - #[derive(Diagnostic)] #[diag( mir_build_initializing_type_with_requires_unsafe_unsafe_op_in_unsafe_fn_allowed, @@ -285,20 +264,6 @@ pub(crate) struct InitializingTypeWithRequiresUnsafeUnsafeOpInUnsafeFnAllowed { pub(crate) unsafe_not_inherited_note: Option, } -#[derive(Diagnostic)] -#[diag( - mir_build_initializing_type_with_target_feature_requires_unsafe_unsafe_op_in_unsafe_fn_allowed, - code = E0133 -)] -#[note] -pub(crate) struct InitializingTypeWithTargetFeatureRequiresUnsafeUnsafeOpInUnsafeFnAllowed { - #[primary_span] - #[label] - pub(crate) span: Span, - #[subdiagnostic] - pub(crate) unsafe_not_inherited_note: Option, -} - #[derive(Diagnostic)] #[diag(mir_build_mutable_static_requires_unsafe, code = E0133)] #[note] diff --git a/compiler/rustc_passes/messages.ftl b/compiler/rustc_passes/messages.ftl index 38450fc288a1f..e7f208d5ad544 100644 --- a/compiler/rustc_passes/messages.ftl +++ b/compiler/rustc_passes/messages.ftl @@ -672,10 +672,6 @@ passes_should_be_applied_to_fn = *[false] not a function definition } -passes_should_be_applied_to_fn_or_unit_struct = - attribute should be applied to a function definition or unit struct - .label = not a function definition or a unit struct - passes_should_be_applied_to_static = attribute should be applied to a static .label = not a static diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 5dbb3854c8f80..21478a44b0e14 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -747,35 +747,12 @@ impl<'tcx> CheckAttrVisitor<'tcx> { Target::Field | Target::Arm | Target::MacroDef => { self.inline_attr_str_error_with_macro_def(hir_id, attr, "target_feature"); } - Target::Struct if self.tcx.features().struct_target_features => { - let ty = self.tcx.hir_node(hir_id).expect_item(); - match ty.kind { - ItemKind::Struct(data, _) => { - if data.fields().len() != 0 { - self.dcx().emit_err(errors::AttrShouldBeAppliedToFnOrUnitStruct { - attr_span: attr.span, - defn_span: span, - }); - } - } - _ => { - panic!("Target::Struct for a non-struct"); - } - } - } _ => { - if self.tcx.features().struct_target_features { - self.dcx().emit_err(errors::AttrShouldBeAppliedToFnOrUnitStruct { - attr_span: attr.span, - defn_span: span, - }); - } else { - self.dcx().emit_err(errors::AttrShouldBeAppliedToFn { - attr_span: attr.span, - defn_span: span, - on_crate: hir_id == CRATE_HIR_ID, - }); - } + self.dcx().emit_err(errors::AttrShouldBeAppliedToFn { + attr_span: attr.span, + defn_span: span, + on_crate: hir_id == CRATE_HIR_ID, + }); } } } diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs index 1e9ab7af9becc..f5d982e1a5cd1 100644 --- a/compiler/rustc_passes/src/errors.rs +++ b/compiler/rustc_passes/src/errors.rs @@ -82,15 +82,6 @@ pub(crate) struct AttrShouldBeAppliedToFn { pub on_crate: bool, } -#[derive(Diagnostic)] -#[diag(passes_should_be_applied_to_fn_or_unit_struct)] -pub(crate) struct AttrShouldBeAppliedToFnOrUnitStruct { - #[primary_span] - pub attr_span: Span, - #[label] - pub defn_span: Span, -} - #[derive(Diagnostic)] #[diag(passes_should_be_applied_to_fn, code = E0739)] pub(crate) struct TrackedCallerWrongLocation { diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 16f5e55835ea7..3476520960585 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1858,7 +1858,6 @@ symbols! { stringify, struct_field_attributes, struct_inherit, - struct_target_features, struct_variant, structural_match, structural_peq, diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs index 3fdfca50dceba..effd9f8cb0c44 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs @@ -439,8 +439,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { let is_target_feature_fn = if let ty::FnDef(def_id, _) = *leaf_trait_ref.skip_binder().self_ty().kind() { - // FIXME(struct_target_features): should a function that inherits - // target_features through arguments implement Fn traits? !self.tcx.codegen_fn_attrs(def_id).target_features.is_empty() } else { false diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs index 7895a420476fe..96faa5236b198 100644 --- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs +++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs @@ -546,8 +546,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // Provide an impl for suitable functions, rejecting `#[target_feature]` functions (RFC 2396). ty::FnDef(def_id, args) => { let tcx = self.tcx(); - // FIXME(struct_target_features): should a function that inherits target_features - // through an argument implement Fn traits? if tcx.fn_sig(def_id).skip_binder().is_fn_trait_compatible() && tcx.codegen_fn_attrs(def_id).target_features.is_empty() { diff --git a/src/doc/unstable-book/src/language-features/struct-target-features.md b/src/doc/unstable-book/src/language-features/struct-target-features.md deleted file mode 100644 index e814fe9007240..0000000000000 --- a/src/doc/unstable-book/src/language-features/struct-target-features.md +++ /dev/null @@ -1,7 +0,0 @@ -# `struct_target_features` - -The tracking issue for this feature is: [#129107] - -[#129107]: https://github.com/rust-lang/rust/issues/129107 - ------------------------- diff --git a/tests/assembly/struct-target-features.rs b/tests/assembly/struct-target-features.rs deleted file mode 100644 index cc86fbaa84064..0000000000000 --- a/tests/assembly/struct-target-features.rs +++ /dev/null @@ -1,37 +0,0 @@ -//@ compile-flags: -O -//@ assembly-output: emit-asm -//@ only-x86_64 - -#![crate_type = "lib"] -#![feature(struct_target_features)] - -// Check that a struct_target_features type causes the compiler to effectively inline intrinsics. - -use std::arch::x86_64::*; - -#[target_feature(enable = "avx")] -struct Avx {} - -#[target_feature(enable = "fma")] -struct Fma {} - -pub fn add_simple(_: Avx, v: __m256) -> __m256 { - // CHECK-NOT: call - // CHECK: vaddps - unsafe { _mm256_add_ps(v, v) } -} - -pub fn add_complex_type(_: (&Avx, ()), v: __m256) -> __m256 { - // CHECK-NOT: call - // CHECK: vaddps - unsafe { _mm256_add_ps(v, v) } -} - -pub fn add_fma_combined(_: (&Avx, &Fma), v: __m256) -> (__m256, __m256) { - // CHECK-NOT: call - // CHECK-DAG: vaddps - let r1 = unsafe { _mm256_add_ps(v, v) }; - // CHECK-DAG: vfmadd213ps - let r2 = unsafe { _mm256_fmadd_ps(v, v, v) }; - (r1, r2) -} diff --git a/tests/ui/feature-gates/feature-gate-struct-target-features.rs b/tests/ui/feature-gates/feature-gate-struct-target-features.rs deleted file mode 100644 index 854948811469b..0000000000000 --- a/tests/ui/feature-gates/feature-gate-struct-target-features.rs +++ /dev/null @@ -1,4 +0,0 @@ -#[target_feature(enable = "avx")] //~ ERROR attribute should be applied to a function definition -struct Avx {} - -fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-struct-target-features.stderr b/tests/ui/feature-gates/feature-gate-struct-target-features.stderr deleted file mode 100644 index 1e18d3ee1e18d..0000000000000 --- a/tests/ui/feature-gates/feature-gate-struct-target-features.stderr +++ /dev/null @@ -1,10 +0,0 @@ -error: attribute should be applied to a function definition - --> $DIR/feature-gate-struct-target-features.rs:1:1 - | -LL | #[target_feature(enable = "avx")] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -LL | struct Avx {} - | ------------- not a function definition - -error: aborting due to 1 previous error - diff --git a/tests/ui/target-feature/struct-target-features.rs b/tests/ui/target-feature/struct-target-features.rs deleted file mode 100644 index feb479b6dc816..0000000000000 --- a/tests/ui/target-feature/struct-target-features.rs +++ /dev/null @@ -1,98 +0,0 @@ -//@ only-x86_64 -#![feature(struct_target_features)] -//~^ WARNING the feature `struct_target_features` is incomplete and may not be safe to use and/or cause compiler crashes -#![feature(target_feature_11)] - -use std::arch::x86_64::*; - -#[target_feature(enable = "avx")] -//~^ ERROR attribute should be applied to a function definition or unit struct -struct Invalid(u32); - -#[target_feature(enable = "avx")] -struct Avx {} - -#[target_feature(enable = "sse")] -struct Sse(); - -#[target_feature(enable = "avx")] -fn avx() {} - -trait TFAssociatedType { - type Assoc; -} - -impl TFAssociatedType for () { - type Assoc = Avx; -} - -fn avx_self(_: <() as TFAssociatedType>::Assoc) { - avx(); -} - -fn avx_avx(_: Avx) { - avx(); -} - -extern "C" fn bad_fun(_: Avx) {} -//~^ ERROR cannot use a struct with target features in a function with non-Rust ABI - -#[inline(always)] -//~^ ERROR cannot use `#[inline(always)]` with `#[target_feature]` -fn inline_fun(_: Avx) {} -//~^ ERROR cannot use a struct with target features in a #[inline(always)] function - -trait Simd { - fn do_something(&self); -} - -impl Simd for Avx { - fn do_something(&self) { - unsafe { - println!("{:?}", _mm256_setzero_ps()); - } - } -} - -impl Simd for Sse { - fn do_something(&self) { - unsafe { - println!("{:?}", _mm_setzero_ps()); - } - } -} - -struct WithAvx { - #[allow(dead_code)] - avx: Avx, -} - -impl Simd for WithAvx { - fn do_something(&self) { - unsafe { - println!("{:?}", _mm256_setzero_ps()); - } - } -} - -#[inline(never)] -fn dosomething(simd: &S) { - simd.do_something(); -} - -fn avxfn(_: &Avx) {} - -fn main() { - Avx {}; - //~^ ERROR initializing type with `target_feature` attr is unsafe and requires unsafe function or block [E0133] - - if is_x86_feature_detected!("avx") { - let avx = unsafe { Avx {} }; - avxfn(&avx); - dosomething(&avx); - dosomething(&WithAvx { avx }); - } - if is_x86_feature_detected!("sse") { - dosomething(&unsafe { Sse {} }) - } -} diff --git a/tests/ui/target-feature/struct-target-features.stderr b/tests/ui/target-feature/struct-target-features.stderr deleted file mode 100644 index 5ef863f504ee1..0000000000000 --- a/tests/ui/target-feature/struct-target-features.stderr +++ /dev/null @@ -1,47 +0,0 @@ -warning: the feature `struct_target_features` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/struct-target-features.rs:2:12 - | -LL | #![feature(struct_target_features)] - | ^^^^^^^^^^^^^^^^^^^^^^ - | - = note: see issue #129107 for more information - = note: `#[warn(incomplete_features)]` on by default - -error: attribute should be applied to a function definition or unit struct - --> $DIR/struct-target-features.rs:8:1 - | -LL | #[target_feature(enable = "avx")] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -LL | -LL | struct Invalid(u32); - | -------------------- not a function definition or a unit struct - -error: cannot use a struct with target features in a function with non-Rust ABI - --> $DIR/struct-target-features.rs:37:1 - | -LL | extern "C" fn bad_fun(_: Avx) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: cannot use a struct with target features in a #[inline(always)] function - --> $DIR/struct-target-features.rs:42:1 - | -LL | fn inline_fun(_: Avx) {} - | ^^^^^^^^^^^^^^^^^^^^^ - -error: cannot use `#[inline(always)]` with `#[target_feature]` - --> $DIR/struct-target-features.rs:40:1 - | -LL | #[inline(always)] - | ^^^^^^^^^^^^^^^^^ - -error[E0133]: initializing type with `target_feature` attr is unsafe and requires unsafe function or block - --> $DIR/struct-target-features.rs:86:5 - | -LL | Avx {}; - | ^^^^^^ initializing type with `target_feature` attr - | - = note: this struct can only be constructed if the corresponding `target_feature`s are available - -error: aborting due to 5 previous errors; 1 warning emitted - -For more information about this error, try `rustc --explain E0133`. From 32a30dd00551dfb6ac36fd2b29b97f0933283b02 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 1 Sep 2024 16:46:11 +0200 Subject: [PATCH 0346/2194] compiler_fence documentation: emphasize synchronization, not reordering --- library/core/src/sync/atomic.rs | 58 ++++++++++++++++----------------- 1 file changed, 29 insertions(+), 29 deletions(-) diff --git a/library/core/src/sync/atomic.rs b/library/core/src/sync/atomic.rs index 495d9191a9f85..b06a3bd4487d3 100644 --- a/library/core/src/sync/atomic.rs +++ b/library/core/src/sync/atomic.rs @@ -3570,10 +3570,9 @@ unsafe fn atomic_umin(dst: *mut T, val: T, order: Ordering) -> T { /// An atomic fence. /// -/// Depending on the specified order, a fence prevents the compiler and CPU from -/// reordering certain types of memory operations around it. -/// That creates synchronizes-with relationships between it and atomic operations -/// or fences in other threads. +/// Fences create synchronization between themselves and atomic operations or fences in other +/// threads. To achieve this, a fence prevents the compiler and CPU from reordering certain types of +/// memory operations around it. /// /// A fence 'A' which has (at least) [`Release`] ordering semantics, synchronizes /// with a fence 'B' with (at least) [`Acquire`] semantics, if and only if there @@ -3594,6 +3593,12 @@ unsafe fn atomic_umin(dst: *mut T, val: T, order: Ordering) -> T { /// } /// ``` /// +/// Note that in the example above, it is crucial that the accesses to `x` are atomic. Fences cannot +/// be used to establish synchronization among non-atomic accesses in different threads. However, +/// thanks to the happens-before relationship between A and B, any non-atomic accesses that +/// happen-before A are now also properly synchronized with any non-atomic accesses that +/// happen-after B. +/// /// Atomic operations with [`Release`] or [`Acquire`] semantics can also synchronize /// with a fence. /// @@ -3659,33 +3664,30 @@ pub fn fence(order: Ordering) { } } -/// A compiler memory fence. +/// A "compiler-only" atomic fence. /// -/// `compiler_fence` does not emit any machine code, but restricts the kinds -/// of memory re-ordering the compiler is allowed to do. Specifically, depending on -/// the given [`Ordering`] semantics, the compiler may be disallowed from moving reads -/// or writes from before or after the call to the other side of the call to -/// `compiler_fence`. Note that it does **not** prevent the *hardware* -/// from doing such re-ordering. This is not a problem in a single-threaded, -/// execution context, but when other threads may modify memory at the same -/// time, stronger synchronization primitives such as [`fence`] are required. +/// Like [`fence`], this function establishes synchronization with other atomic operations and +/// fences. However, unlike [`fence`], `compiler_fence` only establishes synchronization with +/// operations *in the same thread*. This may at first sound rather useless, since code within a +/// thread is typically already totally ordered and does not need any further synchronization. +/// However, there are cases where code can run on the same thread without being ordered: +/// - The most common case is that of a *signal handler*: a signal handler runs in the same thread +/// as the code it interrupted, but it is not ordered with respect to that code. `compiler_fence` +/// can be used to establish synchronization between a thread and its signal handler, the same way +/// that `fence` can be used to establish synchronization across threads. +/// - Similar situations can arise in embedded programming with interrupt handlers, or in custom +/// implementations of preemptive green threads. In general, `compiler_fence` can establish +/// synchronization with code that is guaranteed to run on the same hardware CPU. /// -/// The re-ordering prevented by the different ordering semantics are: +/// See [`fence`] for how a fence can be used to achieve synchronization. Note that just like +/// [`fence`], synchronization still requires atomic operations to be used in both threads -- it is +/// not possible to perform synchronization entirely with fences and non-atomic operations. /// -/// - with [`SeqCst`], no re-ordering of reads and writes across this point is allowed. -/// - with [`Release`], preceding reads and writes cannot be moved past subsequent writes. -/// - with [`Acquire`], subsequent reads and writes cannot be moved ahead of preceding reads. -/// - with [`AcqRel`], both of the above rules are enforced. +/// `compiler_fence` does not emit any machine code, but restricts the kinds of memory re-ordering +/// the compiler is allowed to do. `compiler_fence` corresponds to [`atomic_signal_fence`] in C and +/// C++. /// -/// `compiler_fence` is generally only useful for preventing a thread from -/// racing *with itself*. That is, if a given thread is executing one piece -/// of code, and is then interrupted, and starts executing code elsewhere -/// (while still in the same thread, and conceptually still on the same -/// core). In traditional programs, this can only occur when a signal -/// handler is registered. In more low-level code, such situations can also -/// arise when handling interrupts, when implementing green threads with -/// pre-emption, etc. Curious readers are encouraged to read the Linux kernel's -/// discussion of [memory barriers]. +/// [`atomic_signal_fence`]: https://en.cppreference.com/w/cpp/atomic/atomic_signal_fence /// /// # Panics /// @@ -3723,8 +3725,6 @@ pub fn fence(order: Ordering) { /// } /// } /// ``` -/// -/// [memory barriers]: https://www.kernel.org/doc/Documentation/memory-barriers.txt #[inline] #[stable(feature = "compiler_fences", since = "1.21.0")] #[rustc_diagnostic_item = "compiler_fence"] From 40909b4331a7bc481f5bcef149efa388f46222f7 Mon Sep 17 00:00:00 2001 From: Mattias Wallin Date: Sun, 1 Sep 2024 08:34:52 +0200 Subject: [PATCH 0347/2194] Fix `test_editions_2015_2018_2021_identical` Was comparing unit type. --- src/config/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/config/mod.rs b/src/config/mod.rs index 8a95cc55fcbb2..d35a249a80a31 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -900,7 +900,7 @@ make_backup = false Config::default_with_style_edition(style_edition) .all_options() .to_toml() - .unwrap(); + .unwrap() }; let edition2015 = get_edition_toml(StyleEdition::Edition2015); let edition2018 = get_edition_toml(StyleEdition::Edition2018); From 7ab44cddc9320f1dfdef40916f33c6f3e83876e6 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sun, 1 Sep 2024 11:16:50 -0400 Subject: [PATCH 0348/2194] Replace walk with visit so we dont skip outermost expr kind in def collector --- compiler/rustc_resolve/src/def_collector.rs | 2 +- tests/ui/async-await/async-closures/mac-body.rs | 12 ++++++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) create mode 100644 tests/ui/async-await/async-closures/mac-body.rs diff --git a/compiler/rustc_resolve/src/def_collector.rs b/compiler/rustc_resolve/src/def_collector.rs index a70d51606f7d3..0fedb998463a2 100644 --- a/compiler/rustc_resolve/src/def_collector.rs +++ b/compiler/rustc_resolve/src/def_collector.rs @@ -223,7 +223,7 @@ impl<'a, 'b, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'b, 'tcx> { // we must create two defs. let coroutine_def = self.create_def(coroutine_kind.closure_id(), kw::Empty, DefKind::Closure, span); - self.with_parent(coroutine_def, |this| visit::walk_expr(this, body)); + self.with_parent(coroutine_def, |this| this.visit_expr(body)); } _ => visit::walk_fn(self, fn_kind), } diff --git a/tests/ui/async-await/async-closures/mac-body.rs b/tests/ui/async-await/async-closures/mac-body.rs new file mode 100644 index 0000000000000..a416227c3904f --- /dev/null +++ b/tests/ui/async-await/async-closures/mac-body.rs @@ -0,0 +1,12 @@ +//@ edition: 2021 +//@ check-pass + +#![feature(async_closure)] + +// Make sure we don't ICE if an async closure has a macro body. +// This happened because we were calling walk instead of visit +// in the def collector, oops! + +fn main() { + let _ = async || println!(); +} From 0bdc5ffd685db3d1506dbf21c8df5daaf68aeaac Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Sun, 1 Sep 2024 11:23:24 -0400 Subject: [PATCH 0349/2194] Support the weak variable attribute --- Cargo.lock | 6 ++---- Cargo.toml | 3 ++- src/consts.rs | 7 ++++++- src/mono_item.rs | 2 +- 4 files changed, 11 insertions(+), 7 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 915229f7e7eef..42528419a2533 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -80,8 +80,7 @@ dependencies = [ [[package]] name = "gccjit" version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62e0ba949ebee07c5cc21f02cb48f28f2c8db7fcbc15fdc5120476a6c43b4636" +source = "git+https://github.com/rust-lang/gccjit.rs#4fbe2023250357378fb2faf6f484b34cb8f8ebc3" dependencies = [ "gccjit_sys", ] @@ -89,8 +88,7 @@ dependencies = [ [[package]] name = "gccjit_sys" version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5bbf85e12c2593772329a9d4e8310271f6706e6045ce4f41b041dd34fba6603" +source = "git+https://github.com/rust-lang/gccjit.rs#4fbe2023250357378fb2faf6f484b34cb8f8ebc3" dependencies = [ "libc", ] diff --git a/Cargo.toml b/Cargo.toml index 5caca63f63480..67a90cc34ee4a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -22,7 +22,8 @@ master = ["gccjit/master"] default = ["master"] [dependencies] -gccjit = "2.1" +#gccjit = "2.1" +gccjit = { git = "https://github.com/rust-lang/gccjit.rs" } # Local copy. #gccjit = { path = "../gccjit.rs" } diff --git a/src/consts.rs b/src/consts.rs index e5673cddc4a4f..53dbb35d711ec 100644 --- a/src/consts.rs +++ b/src/consts.rs @@ -7,6 +7,7 @@ use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs} use rustc_middle::mir::interpret::{ self, read_target_uint, ConstAllocation, ErrorHandled, Scalar as InterpScalar, }; +use rustc_middle::mir::mono::Linkage; use rustc_middle::ty::layout::LayoutOf; use rustc_middle::ty::{self, Instance}; use rustc_middle::{bug, span_bug}; @@ -256,7 +257,7 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { if !self.tcx.is_reachable_non_generic(def_id) { #[cfg(feature = "master")] - global.add_string_attribute(VarAttribute::Visibility(Visibility::Hidden)); + global.add_attribute(VarAttribute::Visibility(Visibility::Hidden)); } global @@ -384,6 +385,10 @@ fn check_and_apply_linkage<'gcc, 'tcx>( let global1 = cx.declare_global_with_linkage(sym, cx.type_i8(), base::global_linkage_to_gcc(linkage)); + if linkage == Linkage::ExternalWeak { + global1.add_attribute(VarAttribute::Weak); + } + // Declare an internal global `extern_with_linkage_foo` which // is initialized with the address of `foo`. If `foo` is // discarded during linking (for example, if `foo` has weak diff --git a/src/mono_item.rs b/src/mono_item.rs index e6b22d5187147..ba81dea49d542 100644 --- a/src/mono_item.rs +++ b/src/mono_item.rs @@ -37,7 +37,7 @@ impl<'gcc, 'tcx> PreDefineMethods<'tcx> for CodegenCx<'gcc, 'tcx> { let is_tls = attrs.flags.contains(CodegenFnAttrFlags::THREAD_LOCAL); let global = self.define_global(symbol_name, gcc_type, is_tls, attrs.link_section); #[cfg(feature = "master")] - global.add_string_attribute(VarAttribute::Visibility(base::visibility_to_gcc(visibility))); + global.add_attribute(VarAttribute::Visibility(base::visibility_to_gcc(visibility))); // TODO(antoyo): set linkage. self.instances.borrow_mut().insert(instance, global); From d30b5f00035bf55b18d576f9f2014e28e40f04bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Rakic?= Date: Sun, 1 Sep 2024 12:21:04 +0000 Subject: [PATCH 0350/2194] update `object` dependency to deduplicate `wasmparser` --- Cargo.lock | 37 ++++++++++++++----------------------- 1 file changed, 14 insertions(+), 23 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 7244ae14fb8da..ce78d921244fc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -199,7 +199,7 @@ version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "01667f6f40216b9a0b2945e05fed5f1ad0ab6470e69cb9378001e37b1c0668e4" dependencies = [ - "object 0.36.3", + "object 0.36.4", ] [[package]] @@ -2453,9 +2453,9 @@ dependencies = [ [[package]] name = "object" -version = "0.36.3" +version = "0.36.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "27b64972346851a39438c60b341ebc01bba47464ae329e55cf343eb93964efd9" +checksum = "084f1a5821ac4c651660a94a7153d27ac9d8a53736203f58b31945ded098070a" dependencies = [ "crc32fast", "flate2", @@ -2463,7 +2463,7 @@ dependencies = [ "indexmap", "memchr", "ruzstd 0.7.0", - "wasmparser 0.215.0", + "wasmparser", ] [[package]] @@ -3129,11 +3129,11 @@ dependencies = [ "build_helper", "gimli 0.31.0", "libc", - "object 0.36.3", + "object 0.36.4", "regex", "serde_json", "similar", - "wasmparser 0.216.0", + "wasmparser", ] [[package]] @@ -3408,7 +3408,7 @@ dependencies = [ "itertools", "libc", "measureme", - "object 0.36.3", + "object 0.36.4", "rustc-demangle", "rustc_ast", "rustc_attr", @@ -3447,7 +3447,7 @@ dependencies = [ "itertools", "jobserver", "libc", - "object 0.36.3", + "object 0.36.4", "pathdiff", "regex", "rustc_arena", @@ -4431,7 +4431,7 @@ name = "rustc_target" version = "0.0.0" dependencies = [ "bitflags 2.6.0", - "object 0.36.3", + "object 0.36.4", "rustc_abi", "rustc_data_structures", "rustc_feature", @@ -5849,7 +5849,7 @@ dependencies = [ "lexopt", "tempfile", "wasi-preview1-component-adapter-provider", - "wasmparser 0.216.0", + "wasmparser", "wat", "wit-component", "wit-parser", @@ -5869,7 +5869,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "04c23aebea22c8a75833ae08ed31ccc020835b12a41999e58c31464271b94a88" dependencies = [ "leb128", - "wasmparser 0.216.0", + "wasmparser", ] [[package]] @@ -5885,16 +5885,7 @@ dependencies = [ "serde_json", "spdx", "wasm-encoder", - "wasmparser 0.216.0", -] - -[[package]] -name = "wasmparser" -version = "0.215.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53fbde0881f24199b81cf49b6ff8f9c145ac8eb1b7fc439adb5c099734f7d90e" -dependencies = [ - "bitflags 2.6.0", + "wasmparser", ] [[package]] @@ -6228,7 +6219,7 @@ dependencies = [ "serde_json", "wasm-encoder", "wasm-metadata", - "wasmparser 0.216.0", + "wasmparser", "wit-parser", ] @@ -6247,7 +6238,7 @@ dependencies = [ "serde_derive", "serde_json", "unicode-xid", - "wasmparser 0.216.0", + "wasmparser", ] [[package]] From 91854453f233c2b7084e665c2cf36f5494b26b76 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 28 Aug 2024 00:14:41 -0400 Subject: [PATCH 0351/2194] Deny imports of rustc_type_ir::inherent outside of type ir + new trait solver --- compiler/rustc_lint/messages.ftl | 3 ++ compiler/rustc_lint/src/internal.rs | 30 ++++++++++++++++-- compiler/rustc_lint/src/lints.rs | 5 +++ compiler/rustc_next_trait_solver/src/lib.rs | 1 + compiler/rustc_type_ir/src/lib.rs | 1 + .../import-of-type-ir-inherent.rs | 18 +++++++++++ .../import-of-type-ir-inherent.stderr | 31 +++++++++++++++++++ 7 files changed, 87 insertions(+), 2 deletions(-) create mode 100644 tests/ui-fulldeps/internal-lints/import-of-type-ir-inherent.rs create mode 100644 tests/ui-fulldeps/internal-lints/import-of-type-ir-inherent.stderr diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl index 31b7eb5ee7df3..353345958337c 100644 --- a/compiler/rustc_lint/messages.ftl +++ b/compiler/rustc_lint/messages.ftl @@ -783,6 +783,9 @@ lint_tykind = usage of `ty::TyKind` lint_tykind_kind = usage of `ty::TyKind::` .suggestion = try using `ty::` directly +lint_type_ir_inherent_usage = do not use `rustc_type_ir::inherent` unless you're inside of the trait solver + .note = the method or struct you're looking for is likely defined somewhere else downstream in the compiler + lint_undropped_manually_drops = calls to `std::mem::drop` with `std::mem::ManuallyDrop` instead of the inner value does nothing .label = argument has type `{$arg_ty}` .suggestion = use `std::mem::ManuallyDrop::into_inner` to get the inner value diff --git a/compiler/rustc_lint/src/internal.rs b/compiler/rustc_lint/src/internal.rs index 65571815019ea..2e8116b8ba892 100644 --- a/compiler/rustc_lint/src/internal.rs +++ b/compiler/rustc_lint/src/internal.rs @@ -18,7 +18,7 @@ use tracing::debug; use crate::lints::{ BadOptAccessDiag, DefaultHashTypesDiag, DiagOutOfImpl, LintPassByHand, NonExistentDocKeyword, NonGlobImportTypeIrInherent, QueryInstability, SpanUseEqCtxtDiag, TyQualified, TykindDiag, - TykindKind, UntranslatableDiag, + TykindKind, TypeIrInherentUsage, UntranslatableDiag, }; use crate::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext}; @@ -277,13 +277,39 @@ declare_tool_lint! { report_in_external_macro: true } -declare_lint_pass!(TypeIr => [NON_GLOB_IMPORT_OF_TYPE_IR_INHERENT]); +declare_tool_lint! { + /// The `usage_of_type_ir_inherent` lint detects usage `rustc_type_ir::inherent`. + /// + /// This module should only be used within the trait solver. + pub rustc::USAGE_OF_TYPE_IR_INHERENT, + Allow, + "usage `rustc_type_ir::inherent` outside of trait system", + report_in_external_macro: true +} + +declare_lint_pass!(TypeIr => [NON_GLOB_IMPORT_OF_TYPE_IR_INHERENT, USAGE_OF_TYPE_IR_INHERENT]); impl<'tcx> LateLintPass<'tcx> for TypeIr { fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'tcx>) { let rustc_hir::ItemKind::Use(path, kind) = item.kind else { return }; let is_mod_inherent = |def_id| cx.tcx.is_diagnostic_item(sym::type_ir_inherent, def_id); + + // Path segments except for the final. + if let Some(seg) = + path.segments.iter().find(|seg| seg.res.opt_def_id().is_some_and(is_mod_inherent)) + { + cx.emit_span_lint(USAGE_OF_TYPE_IR_INHERENT, seg.ident.span, TypeIrInherentUsage); + } + // Final path resolutions, like `use rustc_type_ir::inherent` + else if path.res.iter().any(|res| res.opt_def_id().is_some_and(is_mod_inherent)) { + cx.emit_span_lint( + USAGE_OF_TYPE_IR_INHERENT, + path.segments.last().unwrap().ident.span, + TypeIrInherentUsage, + ); + } + let (lo, hi, snippet) = match path.segments { [.., penultimate, segment] if penultimate.res.opt_def_id().is_some_and(is_mod_inherent) => diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index 2712e25668a48..7ca282b7c8541 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -918,6 +918,11 @@ pub(crate) struct TyQualified { pub suggestion: Span, } +#[derive(LintDiagnostic)] +#[diag(lint_type_ir_inherent_usage)] +#[note] +pub(crate) struct TypeIrInherentUsage; + #[derive(LintDiagnostic)] #[diag(lint_non_glob_import_type_ir_inherent)] pub(crate) struct NonGlobImportTypeIrInherent { diff --git a/compiler/rustc_next_trait_solver/src/lib.rs b/compiler/rustc_next_trait_solver/src/lib.rs index ea244b5107ad6..ca140500e2cd3 100644 --- a/compiler/rustc_next_trait_solver/src/lib.rs +++ b/compiler/rustc_next_trait_solver/src/lib.rs @@ -5,6 +5,7 @@ //! So if you got to this crate from the old solver, it's totally normal. // tidy-alphabetical-start +#![cfg_attr(not(bootstrap), allow(rustc::usage_of_type_ir_inherent))] #![warn(unreachable_pub)] // tidy-alphabetical-end diff --git a/compiler/rustc_type_ir/src/lib.rs b/compiler/rustc_type_ir/src/lib.rs index de41d2f3cc512..f763153a5fc88 100644 --- a/compiler/rustc_type_ir/src/lib.rs +++ b/compiler/rustc_type_ir/src/lib.rs @@ -5,6 +5,7 @@ feature(associated_type_defaults, never_type, rustc_attrs, negative_impls) )] #![cfg_attr(feature = "nightly", allow(internal_features))] +#![cfg_attr(not(bootstrap), allow(rustc::usage_of_type_ir_inherent))] // tidy-alphabetical-end extern crate self as rustc_type_ir; diff --git a/tests/ui-fulldeps/internal-lints/import-of-type-ir-inherent.rs b/tests/ui-fulldeps/internal-lints/import-of-type-ir-inherent.rs new file mode 100644 index 0000000000000..08d86606a6bab --- /dev/null +++ b/tests/ui-fulldeps/internal-lints/import-of-type-ir-inherent.rs @@ -0,0 +1,18 @@ +//@ compile-flags: -Z unstable-options + +// #[cfg(bootstrap)]: We can stop ignoring next beta bump; afterward this ALWAYS should run. +//@ ignore-stage1 + +#![feature(rustc_private)] +#![deny(rustc::usage_of_type_ir_inherent)] + +extern crate rustc_type_ir; + +use rustc_type_ir::inherent::*; +//~^ ERROR do not use `rustc_type_ir::inherent` unless you're inside of the trait solver +use rustc_type_ir::inherent; +//~^ ERROR do not use `rustc_type_ir::inherent` unless you're inside of the trait solver +use rustc_type_ir::inherent::Predicate; +//~^ ERROR do not use `rustc_type_ir::inherent` unless you're inside of the trait solver + +fn main() {} diff --git a/tests/ui-fulldeps/internal-lints/import-of-type-ir-inherent.stderr b/tests/ui-fulldeps/internal-lints/import-of-type-ir-inherent.stderr new file mode 100644 index 0000000000000..cc6cb9170c0d4 --- /dev/null +++ b/tests/ui-fulldeps/internal-lints/import-of-type-ir-inherent.stderr @@ -0,0 +1,31 @@ +error: do not use `rustc_type_ir::inherent` unless you're inside of the trait solver + --> $DIR/import-of-type-ir-inherent.rs:11:20 + | +LL | use rustc_type_ir::inherent::*; + | ^^^^^^^^ + | + = note: the method or struct you're looking for is likely defined somewhere else downstream in the compiler +note: the lint level is defined here + --> $DIR/import-of-type-ir-inherent.rs:7:9 + | +LL | #![deny(rustc::usage_of_type_ir_inherent)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: do not use `rustc_type_ir::inherent` unless you're inside of the trait solver + --> $DIR/import-of-type-ir-inherent.rs:13:20 + | +LL | use rustc_type_ir::inherent; + | ^^^^^^^^ + | + = note: the method or struct you're looking for is likely defined somewhere else downstream in the compiler + +error: do not use `rustc_type_ir::inherent` unless you're inside of the trait solver + --> $DIR/import-of-type-ir-inherent.rs:15:20 + | +LL | use rustc_type_ir::inherent::Predicate; + | ^^^^^^^^ + | + = note: the method or struct you're looking for is likely defined somewhere else downstream in the compiler + +error: aborting due to 3 previous errors + From 4dd288cecf8b8fc24921f45413b7609ab55a066d Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Sun, 1 Sep 2024 11:59:27 -0400 Subject: [PATCH 0352/2194] Fix tests --- build_system/src/test.rs | 3 +- libgccjit.version | 2 +- ...022-core-Disable-not-compiling-tests.patch | 30 +++++++++---------- src/consts.rs | 1 + src/intrinsic/llvm.rs | 2 ++ tests/failing-ice-tests.txt | 4 +++ tests/failing-ui-tests.txt | 26 ++++++++++++++++ 7 files changed, 51 insertions(+), 17 deletions(-) diff --git a/build_system/src/test.rs b/build_system/src/test.rs index 303a2e518cf7a..dd09de24aa34f 100644 --- a/build_system/src/test.rs +++ b/build_system/src/test.rs @@ -637,7 +637,8 @@ fn test_projects(env: &Env, args: &TestArg) -> Result<(), String> { "https://github.com/BurntSushi/memchr", "https://github.com/dtolnay/itoa", "https://github.com/rust-lang/cfg-if", - "https://github.com/rust-lang-nursery/lazy-static.rs", + //"https://github.com/rust-lang-nursery/lazy-static.rs", // TODO: re-enable when the + //failing test is fixed upstream. //"https://github.com/marshallpierce/rust-base64", // FIXME: one test is OOM-killed. // TODO: ignore the base64 test that is OOM-killed. "https://github.com/time-rs/time", diff --git a/libgccjit.version b/libgccjit.version index 23ca7f022155e..fa2bacc2c8e72 100644 --- a/libgccjit.version +++ b/libgccjit.version @@ -1 +1 @@ -341be3b7d7ac6976cfed8ed59da3573c040d0776 +bcafd46296f7898dac02d127e441b1d838ef2afc diff --git a/patches/0022-core-Disable-not-compiling-tests.patch b/patches/0022-core-Disable-not-compiling-tests.patch index 08e2f1a762841..b2ab05691ecbf 100644 --- a/patches/0022-core-Disable-not-compiling-tests.patch +++ b/patches/0022-core-Disable-not-compiling-tests.patch @@ -1,26 +1,24 @@ -From f6befc4bb51d84f5f1cf35938a168c953d421350 Mon Sep 17 00:00:00 2001 -From: bjorn3 -Date: Sun, 24 Nov 2019 15:10:23 +0100 +From 18793c6109890493ceb3ff36549849a36e3d8022 Mon Sep 17 00:00:00 2001 +From: None +Date: Sun, 1 Sep 2024 11:42:17 -0400 Subject: [PATCH] [core] Disable not compiling tests --- - library/core/tests/Cargo.toml | 8 ++++++++ - library/core/tests/num/flt2dec/mod.rs | 1 - - library/core/tests/num/int_macros.rs | 2 ++ - library/core/tests/num/uint_macros.rs | 2 ++ - library/core/tests/ptr.rs | 2 ++ - library/core/tests/slice.rs | 2 ++ - 6 files changed, 16 insertions(+), 1 deletion(-) + library/core/tests/Cargo.toml | 14 ++++++++++++++ + library/core/tests/lib.rs | 1 + + 2 files changed, 15 insertions(+) create mode 100644 library/core/tests/Cargo.toml diff --git a/library/core/tests/Cargo.toml b/library/core/tests/Cargo.toml new file mode 100644 -index 0000000..46fd999 +index 0000000..ca326ac --- /dev/null +++ b/library/core/tests/Cargo.toml -@@ -0,0 +1,12 @@ +@@ -0,0 +1,14 @@ ++[workspace] ++ +[package] -+name = "core" ++name = "coretests" +version = "0.0.0" +edition = "2021" + @@ -32,12 +30,14 @@ index 0000000..46fd999 +rand = { version = "0.8.5", default-features = false } +rand_xorshift = { version = "0.3.0", default-features = false } diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs -index 42a26ae..5ac1042 100644 +index 1e336bf..5800ebb 100644 --- a/library/core/tests/lib.rs +++ b/library/core/tests/lib.rs -@@ -2,4 +2,5 @@ +@@ -1,4 +1,5 @@ // tidy-alphabetical-start +#![cfg(test)] #![cfg_attr(bootstrap, feature(offset_of_nested))] #![cfg_attr(target_has_atomic = "128", feature(integer_atomics))] #![cfg_attr(test, feature(cfg_match))] +-- +2.46.0 diff --git a/src/consts.rs b/src/consts.rs index 53dbb35d711ec..483b2355c529f 100644 --- a/src/consts.rs +++ b/src/consts.rs @@ -386,6 +386,7 @@ fn check_and_apply_linkage<'gcc, 'tcx>( cx.declare_global_with_linkage(sym, cx.type_i8(), base::global_linkage_to_gcc(linkage)); if linkage == Linkage::ExternalWeak { + #[cfg(feature = "master")] global1.add_attribute(VarAttribute::Weak); } diff --git a/src/intrinsic/llvm.rs b/src/intrinsic/llvm.rs index 554e57250e6d8..2287c96b41b8f 100644 --- a/src/intrinsic/llvm.rs +++ b/src/intrinsic/llvm.rs @@ -985,6 +985,8 @@ pub fn intrinsic<'gcc, 'tcx>(name: &str, cx: &CodegenCx<'gcc, 'tcx>) -> Function "llvm.x86.avx512.vpdpbusds.512" => "__builtin_ia32_vpdpbusds_v16si", "llvm.x86.avx512.vpdpbusds.256" => "__builtin_ia32_vpdpbusds_v8si", "llvm.x86.avx512.vpdpbusds.128" => "__builtin_ia32_vpdpbusds_v4si", + "llvm.x86.xsave" => "__builtin_ia32_xsave", + "llvm.x86.xsaveopt" => "__builtin_ia32_xsaveopt", // NOTE: this file is generated by https://github.com/GuillaumeGomez/llvmint/blob/master/generate_list.py _ => include!("archs.rs"), diff --git a/tests/failing-ice-tests.txt b/tests/failing-ice-tests.txt index 2084f86b62e19..ff1b6f1489468 100644 --- a/tests/failing-ice-tests.txt +++ b/tests/failing-ice-tests.txt @@ -34,3 +34,7 @@ tests/ui/sepcomp/sepcomp-unwind.rs tests/ui/extern/issue-64655-extern-rust-must-allow-unwind.rs tests/ui/extern/issue-64655-allow-unwind-when-calling-panic-directly.rs tests/ui/unwind-no-uwtable.rs +tests/ui/delegation/fn-header.rs +tests/ui/simd/intrinsic/generic-arithmetic-pass.rs +tests/ui/simd/masked-load-store.rs +tests/ui/rfcs/rfc-2632-const-trait-impl/effects/minicore.rs diff --git a/tests/failing-ui-tests.txt b/tests/failing-ui-tests.txt index 5a55bdb156e39..56b51275a53b2 100644 --- a/tests/failing-ui-tests.txt +++ b/tests/failing-ui-tests.txt @@ -95,3 +95,29 @@ tests/ui/simd/intrinsic/generic-arithmetic-pass.rs tests/ui/backtrace/backtrace.rs tests/ui/lifetimes/tail-expr-lock-poisoning.rs tests/ui/runtime/rt-explody-panic-payloads.rs +tests/ui/codegen/equal-pointers-unequal/as-cast/function.rs +tests/ui/codegen/equal-pointers-unequal/as-cast/basic.rs +tests/ui/codegen/equal-pointers-unequal/as-cast/inline1.rs +tests/ui/codegen/equal-pointers-unequal/as-cast/print.rs +tests/ui/codegen/equal-pointers-unequal/as-cast/inline2.rs +tests/ui/codegen/equal-pointers-unequal/as-cast/print3.rs +tests/ui/codegen/equal-pointers-unequal/as-cast/segfault.rs +tests/ui/codegen/equal-pointers-unequal/exposed-provenance/function.rs +tests/ui/codegen/equal-pointers-unequal/exposed-provenance/basic.rs +tests/ui/codegen/equal-pointers-unequal/as-cast/zero.rs +tests/ui/codegen/equal-pointers-unequal/exposed-provenance/inline1.rs +tests/ui/codegen/equal-pointers-unequal/exposed-provenance/print.rs +tests/ui/codegen/equal-pointers-unequal/exposed-provenance/print3.rs +tests/ui/codegen/equal-pointers-unequal/exposed-provenance/inline2.rs +tests/ui/codegen/equal-pointers-unequal/exposed-provenance/segfault.rs +tests/ui/codegen/equal-pointers-unequal/exposed-provenance/zero.rs +tests/ui/codegen/equal-pointers-unequal/strict-provenance/basic.rs +tests/ui/codegen/equal-pointers-unequal/strict-provenance/function.rs +tests/ui/codegen/equal-pointers-unequal/strict-provenance/print.rs +tests/ui/codegen/equal-pointers-unequal/strict-provenance/inline1.rs +tests/ui/codegen/equal-pointers-unequal/strict-provenance/print3.rs +tests/ui/codegen/equal-pointers-unequal/strict-provenance/inline2.rs +tests/ui/codegen/equal-pointers-unequal/strict-provenance/segfault.rs +tests/ui/codegen/equal-pointers-unequal/strict-provenance/zero.rs +tests/ui/sanitizer/cfi-sized-associated-ty.rs +tests/ui/sanitizer/cfi-can-reveal-opaques.rs From 5afc4619d446fe7d7ad54e1cd192a23207bad3de Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sat, 31 Aug 2024 22:28:40 +0200 Subject: [PATCH 0353/2194] Fix wrong rounded corners when line numbers are displayed on code examples --- src/librustdoc/html/static/css/rustdoc.css | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css index 1fad3cfd41e64..afa3970f20776 100644 --- a/src/librustdoc/html/static/css/rustdoc.css +++ b/src/librustdoc/html/static/css/rustdoc.css @@ -745,10 +745,26 @@ ul.block, .block li { margin-bottom: 10px; } -.rustdoc .example-wrap > pre { +.rustdoc .example-wrap > pre, +.rustdoc .scraped-example .src-line-numbers { border-radius: 6px; } +/* +If the code example line numbers are displayed, there will be a weird radius in the middle from +both the code example and the line numbers, so we need to remove the radius in this case. +*/ +.rustdoc .example-wrap > .example-line-numbers, +.rustdoc .scraped-example .src-line-numbers { + border-top-right-radius: 0; + border-bottom-right-radius: 0; +} +.rustdoc .example-wrap > .example-line-numbers + pre, +.rustdoc .scraped-example .rust { + border-top-left-radius: 0; + border-bottom-left-radius: 0; +} + /* For the last child of a div, the margin will be taken care of by the margin-top of the next item. */ .rustdoc .example-wrap:last-child { From 84259ff23b7e935abb6acabe2fb9eb9c964d0b37 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sat, 31 Aug 2024 22:28:56 +0200 Subject: [PATCH 0354/2194] Add GUI tests to ensure that rounded corners on code blocks are working as expected --- .../docblock-code-block-line-number.goml | 62 +++++++++++++++++++ 1 file changed, 62 insertions(+) diff --git a/tests/rustdoc-gui/docblock-code-block-line-number.goml b/tests/rustdoc-gui/docblock-code-block-line-number.goml index 348ce0c992fd9..36a17b1c8339e 100644 --- a/tests/rustdoc-gui/docblock-code-block-line-number.goml +++ b/tests/rustdoc-gui/docblock-code-block-line-number.goml @@ -5,6 +5,18 @@ go-to: "file://" + |DOC_PATH| + "/test_docs/fn.foo.html" // We check that without this setting, there is no line number displayed. assert-false: "pre.example-line-numbers" +// All corners should be rounded. +assert-css: ( + ".example-wrap .rust", + { + "border-top-left-radius": "6px", + "border-bottom-left-radius": "6px", + "border-top-right-radius": "6px", + "border-bottom-right-radius": "6px", + }, + ALL, +) + // We set the setting to show the line numbers on code examples. set-local-storage: {"rustdoc-line-numbers": "true"} reload: @@ -29,9 +41,21 @@ define-function: ( "margin": "0px", "padding": "14px 8px", "text-align": "right", + // There should not be a radius on the right of the line numbers. + "border-top-left-radius": "6px", + "border-bottom-left-radius": "6px", + "border-top-right-radius": "0px", + "border-bottom-right-radius": "0px", }, ALL, ) + // There should not be a radius on the left of the line numbers. + assert-css: ("pre.example-line-numbers + .rust", { + "border-top-left-radius": "0px", + "border-bottom-left-radius": "0px", + "border-top-right-radius": "6px", + "border-bottom-right-radius": "6px", + }) }, ) call-function: ("check-colors", { @@ -64,7 +88,45 @@ wait-for: 100 // wait-for-false does not exist assert-false: "pre.example-line-numbers" assert-local-storage: {"rustdoc-line-numbers": "false" } +// Check that the rounded corners are back. +assert-css: ( + ".example-wrap .rust", + { + "border-top-left-radius": "6px", + "border-bottom-left-radius": "6px", + "border-top-right-radius": "6px", + "border-bottom-right-radius": "6px", + }, + ALL, +) + // Finally, turn it on again. click: "input#line-numbers" wait-for: "pre.example-line-numbers" assert-local-storage: {"rustdoc-line-numbers": "true" } + +// Same check with scraped examples line numbers. +go-to: "file://" + |DOC_PATH| + "/scrape_examples/fn.test_many.html" + +assert-css: ( + ".scraped-example pre.src-line-numbers", + { + // There should not be a radius on the right of the line numbers. + "border-top-left-radius": "6px", + "border-bottom-left-radius": "6px", + "border-top-right-radius": "0px", + "border-bottom-right-radius": "0px", + }, + ALL, +) +assert-css: ( + ".scraped-example .rust", + { + // There should not be a radius on the left of the code. + "border-top-left-radius": "0px", + "border-bottom-left-radius": "0px", + "border-top-right-radius": "6px", + "border-bottom-right-radius": "6px", + }, + ALL, +) From 35a7c1b8da2a2af5af9f7c1233d3a2538d57c73c Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sun, 1 Sep 2024 15:00:34 +0200 Subject: [PATCH 0355/2194] Fix position of scraped examples title on mobile devices --- src/librustdoc/html/static/css/rustdoc.css | 11 +++++++++++ src/librustdoc/html/templates/scraped_source.html | 6 +++--- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css index afa3970f20776..874994457675f 100644 --- a/src/librustdoc/html/static/css/rustdoc.css +++ b/src/librustdoc/html/static/css/rustdoc.css @@ -2267,6 +2267,17 @@ in src-script.js and main.js margin: 0; padding: var(--nav-sub-mobile-padding); } + + .example-wrap.scraped-example { + flex-wrap: wrap; + } + .example-wrap .scraped-example-title { + width: 100%; + } + .example-wrap.scraped-example .rust { + /* Dirty hacky to force it to remain on the same line as the line numbers. */ + width: 10px; + } } /* Should have min-width: (N + 1)px where N is the mobile breakpoint above. */ diff --git a/src/librustdoc/html/templates/scraped_source.html b/src/librustdoc/html/templates/scraped_source.html index 01abdd607e2ef..4b5d3f2d10aa7 100644 --- a/src/librustdoc/html/templates/scraped_source.html +++ b/src/librustdoc/html/templates/scraped_source.html @@ -1,4 +1,7 @@
+
+ {{info.name +}} ({{info.title}}) {# #} +
{# https://developers.google.com/search/docs/crawling-indexing/robots-meta-tag#data-nosnippet-attr Do not show "1 2 3 4 5 ..." in web search results. #}
@@ -12,9 +15,6 @@
             {{code_html|safe}}
          {# #}
     
{# #} -
- {{info.name +}} ({{info.title}}) {# #} -
{% if info.needs_prev_next_buttons || info.needs_expansion %}
{% if info.needs_prev_next_buttons %} From dd5f7bc6280ed3355fe1d2c04af7e5e59c921974 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sun, 1 Sep 2024 15:00:51 +0200 Subject: [PATCH 0356/2194] Add GUI regression test for scraped examples title position on mobile --- tests/rustdoc-gui/scrape-examples-layout.goml | 43 +++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/tests/rustdoc-gui/scrape-examples-layout.goml b/tests/rustdoc-gui/scrape-examples-layout.goml index 036d66cc379dd..b0d22cba0059b 100644 --- a/tests/rustdoc-gui/scrape-examples-layout.goml +++ b/tests/rustdoc-gui/scrape-examples-layout.goml @@ -1,6 +1,8 @@ // Check that the line number column has the correct layout. go-to: "file://" + |DOC_PATH| + "/scrape_examples/fn.test_many.html" +set-window-size: (1000, 1000) + // Check that it's not zero. assert-property-false: ( ".more-scraped-examples .scraped-example .src-line-numbers", @@ -33,6 +35,18 @@ assert-property: ( {"clientWidth": |clientWidth|} ) +// The "title" should be located at the right bottom corner of the code example. +store-position: (".example-wrap.scraped-example", {"x": x, "y": y}) +store-size: (".example-wrap.scraped-example", {"width": width, "height": height}) +store-size: (".example-wrap.scraped-example .scraped-example-title", { + "width": title_width, + "height": title_height, +}) +assert-position: (".example-wrap.scraped-example .scraped-example-title", { + "x": |x| + |width| - |title_width| - 5, + "y": |y| + |height| - |title_height| - 8, +}) + // Check that for both mobile and desktop sizes, the buttons in scraped examples are displayed // correctly. @@ -46,3 +60,32 @@ assert-position: (".scraped-example .prev", {"y": 226 + |offset_y|}) set-window-size: (600, 600) assert-position: (".scraped-example", {"y": 284}) assert-position: (".scraped-example .prev", {"y": 284 + |offset_y|}) + +define-function: ( + "check_title_and_code_position", + [], + block { + // Title should be above the code. + store-position: (".example-wrap.scraped-example .src-line-numbers", {"x": x, "y": y}) + store-size: (".example-wrap.scraped-example .scraped-example-title", { "height": title_height }) + + assert-position: (".example-wrap.scraped-example .scraped-example-title", { + "x": |x|, // same X position. + "y": |y| - |title_height|, + }) + + // Line numbers should be right beside the code. + compare-elements-position: ( + ".example-wrap.scraped-example .src-line-numbers", + ".example-wrap.scraped-example .rust", + ["y"], + ) + } +) + +// Check that the title is now above the code. +call-function: ("check_title_and_code_position", {}) + +// Then with small mobile +set-window-size: (300, 300) +call-function: ("check_title_and_code_position", {}) From 4825fb198f9abb58ddc877d9bbf49c8834a68a68 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sun, 1 Sep 2024 15:02:03 +0200 Subject: [PATCH 0357/2194] Add missing CSS variables in GUI test for `custom-theme.css` --- tests/rustdoc-gui/src/theme_css/custom-theme.css | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/rustdoc-gui/src/theme_css/custom-theme.css b/tests/rustdoc-gui/src/theme_css/custom-theme.css index a56c31ab9d26f..366f09f22b230 100644 --- a/tests/rustdoc-gui/src/theme_css/custom-theme.css +++ b/tests/rustdoc-gui/src/theme_css/custom-theme.css @@ -23,6 +23,8 @@ --copy-path-button-color: #999; --copy-path-img-filter: invert(50%); --copy-path-img-hover-filter: invert(35%); + --code-example-button-color: #7f7f7f; + --code-example-button-hover-color: #a5a5a5; --codeblock-error-hover-color: rgb(255, 0, 0); --codeblock-error-color: rgba(255, 0, 0, .5); --codeblock-ignore-hover-color: rgb(255, 142, 0); From 4a93071aa1317d6da7e2db41cd0629c9ec4589e5 Mon Sep 17 00:00:00 2001 From: cyrgani Date: Sun, 1 Sep 2024 22:28:23 +0200 Subject: [PATCH 0358/2194] add a few more crashtests --- tests/crashes/123629.rs | 10 ++++++++ tests/crashes/127033.rs | 18 ++++++++++++++ tests/crashes/129372.rs | 52 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 80 insertions(+) create mode 100644 tests/crashes/123629.rs create mode 100644 tests/crashes/127033.rs create mode 100644 tests/crashes/129372.rs diff --git a/tests/crashes/123629.rs b/tests/crashes/123629.rs new file mode 100644 index 0000000000000..615323218067d --- /dev/null +++ b/tests/crashes/123629.rs @@ -0,0 +1,10 @@ +//@ known-bug: #123629 +#![feature(generic_assert)] + +fn foo() +where + for ():, +{ +} + +fn main() {} diff --git a/tests/crashes/127033.rs b/tests/crashes/127033.rs new file mode 100644 index 0000000000000..919c9dfd30e89 --- /dev/null +++ b/tests/crashes/127033.rs @@ -0,0 +1,18 @@ +//@ known-bug: #127033 +//@ compile-flags: --edition=2021 + +pub trait RaftLogStorage { + fn save_vote(vote: ()) -> impl std::future::Future + Send; +} + +struct X; +impl RaftLogStorage for X { + fn save_vote(vote: ()) -> impl std::future::Future { + loop {} + async { + vote + } + } +} + +fn main() {} diff --git a/tests/crashes/129372.rs b/tests/crashes/129372.rs new file mode 100644 index 0000000000000..43be01b35df29 --- /dev/null +++ b/tests/crashes/129372.rs @@ -0,0 +1,52 @@ +//@ known-bug: #129372 +//@ compile-flags: -Cdebuginfo=2 -Copt-level=0 + +pub struct Wrapper(T); +struct Struct; + +pub trait TraitA { + type AssocA<'t>; +} +pub trait TraitB { + type AssocB; +} + +pub fn helper(v: impl MethodTrait) { + let _local_that_causes_ice = v.method(); +} + +pub fn main() { + helper(Wrapper(Struct)); +} + +pub trait MethodTrait { + type Assoc<'a>; + + fn method(self) -> impl for<'a> FnMut(&'a ()) -> Self::Assoc<'a>; +} + +impl MethodTrait for T +where + ::AssocB: TraitA, +{ + type Assoc<'a> = ::AssocA<'a>; + + fn method(self) -> impl for<'a> FnMut(&'a ()) -> Self::Assoc<'a> { + move |_| loop {} + } +} + +impl TraitB for Wrapper +where + B: TraitB, +{ + type AssocB = T; +} + +impl TraitB for Struct { + type AssocB = Struct; +} + +impl TraitA for Struct { + type AssocA<'t> = Self; +} From f2696ab4d3095bb6ad6197e55855ebdf00f50b80 Mon Sep 17 00:00:00 2001 From: schvv31n Date: Mon, 5 Aug 2024 00:44:35 +0100 Subject: [PATCH 0359/2194] rustdoc: normalise type/field names in rustdoc-json-types/jsondoclint --- src/librustdoc/json/conversions.rs | 102 +++++++++--------- src/librustdoc/json/mod.rs | 4 +- src/rustdoc-json-types/lib.rs | 86 ++++++++------- src/rustdoc-json-types/tests.rs | 4 +- src/tools/jsondoclint/src/item_kind.rs | 22 ++-- src/tools/jsondoclint/src/validator.rs | 49 ++++----- tests/rustdoc-json/assoc_items.rs | 8 +- tests/rustdoc-json/blanket_impls.rs | 4 +- tests/rustdoc-json/enums/kind.rs | 4 +- .../rustdoc-json/enums/struct_field_hidden.rs | 2 +- tests/rustdoc-json/enums/use_glob.rs | 6 +- tests/rustdoc-json/enums/use_variant.rs | 4 +- .../rustdoc-json/enums/use_variant_foreign.rs | 2 +- tests/rustdoc-json/fn_pointer/generics.rs | 8 +- tests/rustdoc-json/fn_pointer/qualifiers.rs | 12 +-- tests/rustdoc-json/fns/async_return.rs | 24 ++--- tests/rustdoc-json/fns/extern_c_variadic.rs | 4 +- tests/rustdoc-json/fns/generic_args.rs | 22 ++-- tests/rustdoc-json/fns/generic_returns.rs | 6 +- tests/rustdoc-json/fns/generics.rs | 12 +-- tests/rustdoc-json/fns/pattern_arg.rs | 4 +- tests/rustdoc-json/fns/qualifiers.rs | 36 +++---- tests/rustdoc-json/fns/return_type_alias.rs | 2 +- .../generic-associated-types/gats.rs | 16 +-- tests/rustdoc-json/glob_import.rs | 2 +- .../rustdoc-json/impl-trait-in-assoc-type.rs | 10 +- .../impl-trait-precise-capturing.rs | 6 +- tests/rustdoc-json/impls/auto.rs | 2 +- tests/rustdoc-json/impls/foreign_for_local.rs | 2 +- .../rustdoc-json/impls/import_from_private.rs | 4 +- tests/rustdoc-json/impls/local_for_foreign.rs | 2 +- tests/rustdoc-json/lifetime/longest.rs | 24 ++--- tests/rustdoc-json/lifetime/outlives.rs | 10 +- tests/rustdoc-json/methods/qualifiers.rs | 36 +++---- tests/rustdoc-json/nested.rs | 10 +- tests/rustdoc-json/non_lifetime_binders.rs | 2 +- .../rustdoc-json/primitives/use_primitive.rs | 4 +- .../reexport/extern_crate_glob.rs | 4 +- tests/rustdoc-json/reexport/glob_collision.rs | 8 +- tests/rustdoc-json/reexport/glob_empty_mod.rs | 2 +- tests/rustdoc-json/reexport/glob_extern.rs | 6 +- tests/rustdoc-json/reexport/glob_private.rs | 4 +- .../rustdoc-json/reexport/in_root_and_mod.rs | 4 +- .../reexport/in_root_and_mod_pub.rs | 4 +- .../rustdoc-json/reexport/mod_not_included.rs | 2 +- .../reexport/private_twice_one_inline.rs | 6 +- .../reexport/private_two_names.rs | 8 +- .../reexport/reexport_of_hidden.rs | 2 +- tests/rustdoc-json/reexport/rename_private.rs | 2 +- tests/rustdoc-json/reexport/rename_public.rs | 4 +- .../reexport/same_name_different_types.rs | 8 +- .../same_type_reexported_more_than_once.rs | 4 +- tests/rustdoc-json/reexport/simple_private.rs | 6 +- tests/rustdoc-json/reexport/simple_public.rs | 2 +- tests/rustdoc-json/return_private.rs | 2 +- tests/rustdoc-json/structs/plain_all_pub.rs | 2 +- .../rustdoc-json/structs/plain_doc_hidden.rs | 2 +- tests/rustdoc-json/structs/plain_empty.rs | 2 +- tests/rustdoc-json/structs/plain_pub_priv.rs | 2 +- tests/rustdoc-json/structs/with_generics.rs | 2 +- tests/rustdoc-json/structs/with_primitives.rs | 2 +- tests/rustdoc-json/trait_alias.rs | 4 +- tests/rustdoc-json/traits/self.rs | 30 +++--- tests/rustdoc-json/traits/trait_alias.rs | 4 +- tests/rustdoc-json/type/dyn.rs | 4 +- tests/rustdoc-json/type/extern.rs | 2 +- tests/rustdoc-json/type/fn_lifetime.rs | 12 +-- tests/rustdoc-json/type/generic_default.rs | 2 +- tests/rustdoc-json/type/hrtb.rs | 8 +- .../type/inherent_associated_type.rs | 8 +- .../type/inherent_associated_type_bound.rs | 16 +-- .../inherent_associated_type_projections.rs | 12 +-- tests/rustdoc-json/type_alias.rs | 4 +- tests/rustdoc-json/unions/union.rs | 4 +- 74 files changed, 382 insertions(+), 375 deletions(-) diff --git a/src/librustdoc/json/conversions.rs b/src/librustdoc/json/conversions.rs index b97d710c007ce..59e4b072a12d2 100644 --- a/src/librustdoc/json/conversions.rs +++ b/src/librustdoc/json/conversions.rs @@ -156,7 +156,7 @@ impl FromWithTcx for GenericArgs { match args { AngleBracketed { args, constraints } => GenericArgs::AngleBracketed { args: args.into_vec().into_tcx(tcx), - bindings: constraints.into_tcx(tcx), + constraints: constraints.into_tcx(tcx), }, Parenthesized { inputs, output } => GenericArgs::Parenthesized { inputs: inputs.into_vec().into_tcx(tcx), @@ -198,9 +198,9 @@ impl FromWithTcx for Constant { } } -impl FromWithTcx for TypeBinding { +impl FromWithTcx for AssocItemConstraint { fn from_tcx(constraint: clean::AssocItemConstraint, tcx: TyCtxt<'_>) -> Self { - TypeBinding { + AssocItemConstraint { name: constraint.assoc.name.to_string(), args: constraint.assoc.args.into_tcx(tcx), binding: constraint.kind.into_tcx(tcx), @@ -208,12 +208,12 @@ impl FromWithTcx for TypeBinding { } } -impl FromWithTcx for TypeBindingKind { +impl FromWithTcx for AssocItemConstraintKind { fn from_tcx(kind: clean::AssocItemConstraintKind, tcx: TyCtxt<'_>) -> Self { use clean::AssocItemConstraintKind::*; match kind { - Equality { term } => TypeBindingKind::Equality(term.into_tcx(tcx)), - Bound { bounds } => TypeBindingKind::Constraint(bounds.into_tcx(tcx)), + Equality { term } => AssocItemConstraintKind::Equality(term.into_tcx(tcx)), + Bound { bounds } => AssocItemConstraintKind::Constraint(bounds.into_tcx(tcx)), } } } @@ -314,7 +314,7 @@ fn from_clean_item(item: clean::Item, tcx: TyCtxt<'_>) -> ItemEnum { ModuleItem(m) => { ItemEnum::Module(Module { is_crate, items: ids(m.items, tcx), is_stripped: false }) } - ImportItem(i) => ItemEnum::Import(i.into_tcx(tcx)), + ImportItem(i) => ItemEnum::Use(i.into_tcx(tcx)), StructItem(s) => ItemEnum::Struct(s.into_tcx(tcx)), UnionItem(u) => ItemEnum::Union(u.into_tcx(tcx)), StructFieldItem(f) => ItemEnum::StructField(f.into_tcx(tcx)), @@ -331,7 +331,7 @@ fn from_clean_item(item: clean::Item, tcx: TyCtxt<'_>) -> ItemEnum { ImplItem(i) => ItemEnum::Impl((*i).into_tcx(tcx)), StaticItem(s) => ItemEnum::Static(s.into_tcx(tcx)), ForeignStaticItem(s, _) => ItemEnum::Static(s.into_tcx(tcx)), - ForeignTypeItem => ItemEnum::ForeignType, + ForeignTypeItem => ItemEnum::ExternType, TypeAliasItem(t) => ItemEnum::TypeAlias(t.into_tcx(tcx)), // FIXME(generic_const_items): Add support for generic free consts ConstantItem(ci) => { @@ -347,21 +347,19 @@ fn from_clean_item(item: clean::Item, tcx: TyCtxt<'_>) -> ItemEnum { } // FIXME(generic_const_items): Add support for generic associated consts. TyAssocConstItem(_generics, ty) => { - ItemEnum::AssocConst { type_: (*ty).into_tcx(tcx), default: None } + ItemEnum::AssocConst { type_: (*ty).into_tcx(tcx), value: None } } // FIXME(generic_const_items): Add support for generic associated consts. AssocConstItem(ci) => { - ItemEnum::AssocConst { type_: ci.type_.into_tcx(tcx), default: Some(ci.kind.expr(tcx)) } + ItemEnum::AssocConst { type_: ci.type_.into_tcx(tcx), value: Some(ci.kind.expr(tcx)) } + } + TyAssocTypeItem(g, b) => { + ItemEnum::AssocType { generics: g.into_tcx(tcx), bounds: b.into_tcx(tcx), type_: None } } - TyAssocTypeItem(g, b) => ItemEnum::AssocType { - generics: g.into_tcx(tcx), - bounds: b.into_tcx(tcx), - default: None, - }, AssocTypeItem(t, b) => ItemEnum::AssocType { generics: t.generics.into_tcx(tcx), bounds: b.into_tcx(tcx), - default: Some(t.item_type.unwrap_or(t.type_).into_tcx(tcx)), + type_: Some(t.item_type.unwrap_or(t.type_).into_tcx(tcx)), }, // `convert_item` early returns `None` for stripped items and keywords. KeywordItem => unreachable!(), @@ -385,7 +383,7 @@ fn from_clean_item(item: clean::Item, tcx: TyCtxt<'_>) -> ItemEnum { impl FromWithTcx for Struct { fn from_tcx(struct_: clean::Struct, tcx: TyCtxt<'_>) -> Self { - let fields_stripped = struct_.has_stripped_entries(); + let has_stripped_fields = struct_.has_stripped_entries(); let clean::Struct { ctor_kind, generics, fields } = struct_; let kind = match ctor_kind { @@ -394,7 +392,7 @@ impl FromWithTcx for Struct { assert!(fields.is_empty()); StructKind::Unit } - None => StructKind::Plain { fields: ids(fields, tcx), fields_stripped }, + None => StructKind::Plain { fields: ids(fields, tcx), has_stripped_fields }, }; Struct { @@ -407,22 +405,22 @@ impl FromWithTcx for Struct { impl FromWithTcx for Union { fn from_tcx(union_: clean::Union, tcx: TyCtxt<'_>) -> Self { - let fields_stripped = union_.has_stripped_entries(); + let has_stripped_fields = union_.has_stripped_entries(); let clean::Union { generics, fields } = union_; Union { generics: generics.into_tcx(tcx), - fields_stripped, + has_stripped_fields, fields: ids(fields, tcx), impls: Vec::new(), // Added in JsonRenderer::item } } } -pub(crate) fn from_fn_header(header: &rustc_hir::FnHeader) -> Header { - Header { - async_: header.is_async(), - const_: header.is_const(), - unsafe_: header.is_unsafe(), +pub(crate) fn from_fn_header(header: &rustc_hir::FnHeader) -> FunctionHeader { + FunctionHeader { + is_async: header.is_async(), + is_const: header.is_const(), + is_unsafe: header.is_unsafe(), abi: convert_abi(header.abi), } } @@ -474,7 +472,7 @@ impl FromWithTcx for GenericParamDefKind { Type { bounds, default, synthetic } => GenericParamDefKind::Type { bounds: bounds.into_tcx(tcx), default: default.map(|x| (*x).into_tcx(tcx)), - synthetic, + is_synthetic: synthetic, }, Const { ty, default, synthetic: _ } => GenericParamDefKind::Const { type_: (*ty).into_tcx(tcx), @@ -508,7 +506,7 @@ impl FromWithTcx for WherePredicate { .map(|bound| bound.into_tcx(tcx)) .collect(), default: default.map(|ty| (*ty).into_tcx(tcx)), - synthetic, + is_synthetic: synthetic, } } clean::GenericParamDefKind::Const { ty, default, synthetic: _ } => { @@ -602,12 +600,12 @@ impl FromWithTcx for Type { ImplTrait(g) => Type::ImplTrait(g.into_tcx(tcx)), Infer => Type::Infer, RawPointer(mutability, type_) => Type::RawPointer { - mutable: mutability == ast::Mutability::Mut, + is_mutable: mutability == ast::Mutability::Mut, type_: Box::new((*type_).into_tcx(tcx)), }, BorrowedRef { lifetime, mutability, type_ } => Type::BorrowedRef { lifetime: lifetime.map(convert_lifetime), - mutable: mutability == ast::Mutability::Mut, + is_mutable: mutability == ast::Mutability::Mut, type_: Box::new((*type_).into_tcx(tcx)), }, QPath(box clean::QPathData { assoc, self_type, trait_, .. }) => Type::QualifiedPath { @@ -643,29 +641,29 @@ impl FromWithTcx for FunctionPointer { fn from_tcx(bare_decl: clean::BareFunctionDecl, tcx: TyCtxt<'_>) -> Self { let clean::BareFunctionDecl { safety, generic_params, decl, abi } = bare_decl; FunctionPointer { - header: Header { - unsafe_: matches!(safety, rustc_hir::Safety::Unsafe), - const_: false, - async_: false, + header: FunctionHeader { + is_unsafe: matches!(safety, rustc_hir::Safety::Unsafe), + is_const: false, + is_async: false, abi: convert_abi(abi), }, generic_params: generic_params.into_tcx(tcx), - decl: decl.into_tcx(tcx), + sig: decl.into_tcx(tcx), } } } -impl FromWithTcx for FnDecl { +impl FromWithTcx for FunctionSignature { fn from_tcx(decl: clean::FnDecl, tcx: TyCtxt<'_>) -> Self { let clean::FnDecl { inputs, output, c_variadic } = decl; - FnDecl { + FunctionSignature { inputs: inputs .values .into_iter() .map(|arg| (arg.name.to_string(), arg.type_.into_tcx(tcx))) .collect(), output: if output.is_unit() { None } else { Some(output.into_tcx(tcx)) }, - c_variadic, + is_c_variadic: c_variadic, } } } @@ -702,12 +700,12 @@ impl FromWithTcx for Impl { let provided_trait_methods = impl_.provided_trait_methods(tcx); let clean::Impl { safety, generics, trait_, for_, items, polarity, kind } = impl_; // FIXME: use something like ImplKind in JSON? - let (synthetic, blanket_impl) = match kind { + let (is_synthetic, blanket_impl) = match kind { clean::ImplKind::Normal | clean::ImplKind::FakeVariadic => (false, None), clean::ImplKind::Auto => (true, None), clean::ImplKind::Blanket(ty) => (false, Some(*ty)), }; - let negative_polarity = match polarity { + let is_negative = match polarity { ty::ImplPolarity::Positive | ty::ImplPolarity::Reservation => false, ty::ImplPolarity::Negative => true, }; @@ -721,8 +719,8 @@ impl FromWithTcx for Impl { trait_: trait_.map(|path| path.into_tcx(tcx)), for_: for_.into_tcx(tcx), items: ids(items, tcx), - negative: negative_polarity, - synthetic, + is_negative, + is_synthetic, blanket_impl: blanket_impl.map(|x| x.into_tcx(tcx)), } } @@ -736,7 +734,7 @@ pub(crate) fn from_function( ) -> Function { let clean::Function { decl, generics } = *function; Function { - decl: decl.into_tcx(tcx), + sig: decl.into_tcx(tcx), generics: generics.into_tcx(tcx), header: from_fn_header(&header), has_body, @@ -745,11 +743,11 @@ pub(crate) fn from_function( impl FromWithTcx for Enum { fn from_tcx(enum_: clean::Enum, tcx: TyCtxt<'_>) -> Self { - let variants_stripped = enum_.has_stripped_entries(); + let has_stripped_variants = enum_.has_stripped_entries(); let clean::Enum { variants, generics } = enum_; Enum { generics: generics.into_tcx(tcx), - variants_stripped, + has_stripped_variants, variants: ids(variants, tcx), impls: Vec::new(), // Added in JsonRenderer::item } @@ -766,7 +764,7 @@ impl FromWithTcx for Variant { CLike => VariantKind::Plain, Tuple(fields) => VariantKind::Tuple(ids_keeping_stripped(fields, tcx)), Struct(s) => VariantKind::Struct { - fields_stripped: s.has_stripped_entries(), + has_stripped_fields: s.has_stripped_entries(), fields: ids(s.fields, tcx), }, }; @@ -787,21 +785,21 @@ impl FromWithTcx for Discriminant { } } -impl FromWithTcx for Import { +impl FromWithTcx for Use { fn from_tcx(import: clean::Import, tcx: TyCtxt<'_>) -> Self { use clean::ImportKind::*; - let (name, glob) = match import.kind { + let (name, is_glob) = match import.kind { Simple(s) => (s.to_string(), false), Glob => ( import.source.path.last_opt().unwrap_or_else(|| Symbol::intern("*")).to_string(), true, ), }; - Import { + Use { source: import.source.path.whole_name(), name, id: import.source.did.map(ItemId::from).map(|i| id_from_item_default(i, tcx)), - glob, + is_glob, } } } @@ -835,7 +833,7 @@ impl FromWithTcx for Static { fn from_tcx(stat: clean::Static, tcx: TyCtxt<'_>) -> Self { Static { type_: (*stat.type_).into_tcx(tcx), - mutable: stat.mutability == ast::Mutability::Mut, + is_mutable: stat.mutability == ast::Mutability::Mut, expr: stat .expr .map(|e| rendered_const(tcx, tcx.hir().body(e), tcx.hir().body_owner_def_id(e))) @@ -856,7 +854,7 @@ impl FromWithTcx for ItemKind { match kind { Module => ItemKind::Module, ExternCrate => ItemKind::ExternCrate, - Import => ItemKind::Import, + Import => ItemKind::Use, Struct => ItemKind::Struct, Union => ItemKind::Union, Enum => ItemKind::Enum, @@ -872,7 +870,7 @@ impl FromWithTcx for ItemKind { Primitive => ItemKind::Primitive, AssocConst => ItemKind::AssocConst, AssocType => ItemKind::AssocType, - ForeignType => ItemKind::ForeignType, + ForeignType => ItemKind::ExternType, Keyword => ItemKind::Keyword, TraitAlias => ItemKind::TraitAlias, ProcAttribute => ItemKind::ProcAttribute, diff --git a/src/librustdoc/json/mod.rs b/src/librustdoc/json/mod.rs index 1b2d61a763797..03a012864efd3 100644 --- a/src/librustdoc/json/mod.rs +++ b/src/librustdoc/json/mod.rs @@ -197,7 +197,7 @@ impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> { types::ItemEnum::Function(_) | types::ItemEnum::Module(_) - | types::ItemEnum::Import(_) + | types::ItemEnum::Use(_) | types::ItemEnum::AssocConst { .. } | types::ItemEnum::AssocType { .. } => true, types::ItemEnum::ExternCrate { .. } @@ -208,7 +208,7 @@ impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> { | types::ItemEnum::TypeAlias(_) | types::ItemEnum::Constant { .. } | types::ItemEnum::Static(_) - | types::ItemEnum::ForeignType + | types::ItemEnum::ExternType | types::ItemEnum::Macro(_) | types::ItemEnum::ProcMacro(_) => false, }; diff --git a/src/rustdoc-json-types/lib.rs b/src/rustdoc-json-types/lib.rs index 40a90c1a56504..ef21779b09931 100644 --- a/src/rustdoc-json-types/lib.rs +++ b/src/rustdoc-json-types/lib.rs @@ -13,7 +13,7 @@ use serde::{Deserialize, Serialize}; /// This integer is incremented with every breaking change to the API, /// and is returned along with the JSON blob as [`Crate::format_version`]. /// Consuming code should assert that this value matches the format version(s) that it supports. -pub const FORMAT_VERSION: u32 = 33; +pub const FORMAT_VERSION: u32 = 34; /// The root of the emitted JSON blob. /// @@ -194,7 +194,7 @@ pub enum GenericArgs { /// ``` args: Vec, /// Associated type or constant bindings (e.g. `Item=i32` or `Item: Clone`) for this type. - bindings: Vec, + constraints: Vec, }, /// `Fn(A, B) -> C` Parenthesized { @@ -258,19 +258,19 @@ pub struct Constant { /// ^^^^^^^^^^ ^^^^^^^^^^^^^^^ /// ``` #[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] -pub struct TypeBinding { +pub struct AssocItemConstraint { /// The name of the associated type/constant. pub name: String, /// Arguments provided to the associated type/constant. pub args: GenericArgs, /// The kind of bound applied to the associated type/constant. - pub binding: TypeBindingKind, + pub binding: AssocItemConstraintKind, } /// The way in which an associate type/constant is bound. #[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] #[serde(rename_all = "snake_case")] -pub enum TypeBindingKind { +pub enum AssocItemConstraintKind { /// The required value/type is specified exactly. e.g. /// ```text /// Iterator @@ -311,7 +311,7 @@ pub enum ItemKind { /// A crate imported via the `extern crate` syntax. ExternCrate, /// An import of 1 or more items into scope, using the `use` keyword. - Import, + Use, /// A `struct` declaration. Struct, /// A field of a struct. @@ -341,7 +341,7 @@ pub enum ItemKind { /// `type`s from an `extern` block. /// /// See [the tracking issue](https://github.com/rust-lang/rust/issues/43467) - ForeignType, + ExternType, /// A macro declaration. /// /// Corresponds to either `ItemEnum::Macro(_)` @@ -386,7 +386,7 @@ pub enum ItemEnum { rename: Option, }, /// An import of 1 or more items into scope, using the `use` keyword. - Import(Import), + Use(Use), /// A `union` declaration. Union(Union), @@ -429,7 +429,7 @@ pub enum ItemEnum { /// `type`s from an `extern` block. /// /// See [the tracking issue](https://github.com/rust-lang/rust/issues/43467) - ForeignType, + ExternType, /// A macro_rules! declarative macro. Contains a single string with the source /// representation of the macro with the patterns stripped. @@ -447,12 +447,19 @@ pub enum ItemEnum { /// The type of the constant. #[serde(rename = "type")] type_: Type, - /// The stringified expression for the default value, if provided, e.g. + /// Inside a trait declaration, this is the default value for the associated constant, + /// if provided. + /// Inside an `impl` block, this is the value assigned to the associated constant, + /// and will always be present. + /// + /// The representation is implementation-defined and not guaranteed to be representative of + /// either the resulting value or of the source code. + /// /// ```rust /// const X: usize = 640 * 1024; /// // ^^^^^^^^^^ /// ``` - default: Option, + value: Option, }, /// An associated type of a trait or a type. AssocType { @@ -467,12 +474,16 @@ pub enum ItemEnum { /// } /// ``` bounds: Vec, - /// The default for this type, if provided, e.g. + /// Inside a trait declaration, this is the default for the associated type, if provided. + /// Inside an impl block, this is the type assigned to the associated type, and will always + /// be present. + /// /// ```rust /// type X = usize; /// // ^^^^^ /// ``` - default: Option, + #[serde(rename = "type")] + type_: Option, }, } @@ -497,7 +508,7 @@ pub struct Union { /// The generic parameters and where clauses on this union. pub generics: Generics, /// Whether any fields have been removed from the result, due to being private or hidden. - pub fields_stripped: bool, + pub has_stripped_fields: bool, /// The list of fields in the union. /// /// All of the corresponding [`Item`]s are of kind [`ItemEnum::StructField`]. @@ -554,7 +565,7 @@ pub enum StructKind { /// All of the corresponding [`Item`]s are of kind [`ItemEnum::StructField`]. fields: Vec, /// Whether any fields have been removed from the result, due to being private or hidden. - fields_stripped: bool, + has_stripped_fields: bool, }, } @@ -564,7 +575,7 @@ pub struct Enum { /// Information about the type parameters and `where` clauses of the enum. pub generics: Generics, /// Whether any variants have been removed from the result, due to being private or hidden. - pub variants_stripped: bool, + pub has_stripped_variants: bool, /// The list of variants in the enum. /// /// All of the corresponding [`Item`]s are of kind [`ItemEnum::Variant`] @@ -621,7 +632,7 @@ pub enum VariantKind { /// All of the corresponding [`Item`]s are of kind [`ItemEnum::Variant`]. fields: Vec, /// Whether any variants have been removed from the result, due to being private or hidden. - fields_stripped: bool, + has_stripped_fields: bool, }, } @@ -645,16 +656,13 @@ pub struct Discriminant { /// A set of fundamental properties of a function. #[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] -pub struct Header { +pub struct FunctionHeader { /// Is this function marked as `const`? - #[serde(rename = "const")] - pub const_: bool, + pub is_const: bool, /// Is this function unsafe? - #[serde(rename = "unsafe")] - pub unsafe_: bool, + pub is_unsafe: bool, /// Is this function async? - #[serde(rename = "async")] - pub async_: bool, + pub is_async: bool, /// The ABI used by the function. pub abi: Abi, } @@ -697,11 +705,11 @@ pub enum Abi { #[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] pub struct Function { /// Information about the function signature, or declaration. - pub decl: FnDecl, + pub sig: FunctionSignature, /// Information about the function’s type parameters and `where` clauses. pub generics: Generics, /// Information about core properties of the function, e.g. whether it's `const`, its ABI, etc. - pub header: Header, + pub header: FunctionHeader, /// Whether the function has a body, i.e. an implementation. pub has_body: bool, } @@ -784,7 +792,7 @@ pub enum GenericParamDefKind { /// In this example, the generic parameter named `impl Trait` (and which /// is bound by `Trait`) is synthetic, because it was not originally in /// the Rust source text. - synthetic: bool, + is_synthetic: bool, }, /// Denotes a constant parameter. @@ -894,7 +902,7 @@ pub enum TraitBoundModifier { } /// Either a type or a constant, usually stored as the right-hand side of an equation in places like -/// [`TypeBinding`] +/// [`AssocItemConstraint`] #[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] #[serde(rename_all = "snake_case")] pub enum Term { @@ -963,7 +971,7 @@ pub enum Type { /// A raw pointer type, e.g. `*mut u32`, `*const u8`, etc. RawPointer { /// This is `true` for `*mut _` and `false` for `*const _`. - mutable: bool, + is_mutable: bool, /// The type of the pointee. #[serde(rename = "type")] type_: Box, @@ -973,7 +981,7 @@ pub enum Type { /// The name of the lifetime of the reference, if provided. lifetime: Option, /// This is `true` for `&mut i32` and `false` for `&i32` - mutable: bool, + is_mutable: bool, /// The type of the pointee, e.g. the `i32` in `&'a mut i32` #[serde(rename = "type")] type_: Box, @@ -1036,7 +1044,7 @@ pub struct Path { #[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] pub struct FunctionPointer { /// The signature of the function. - pub decl: FnDecl, + pub sig: FunctionSignature, /// Used for Higher-Rank Trait Bounds (HRTBs) /// /// ```ignore (incomplete expression) @@ -1045,12 +1053,12 @@ pub struct FunctionPointer { /// ``` pub generic_params: Vec, /// The core properties of the function, such as the ABI it conforms to, whether it's unsafe, etc. - pub header: Header, + pub header: FunctionHeader, } /// The signature of a function. #[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] -pub struct FnDecl { +pub struct FunctionSignature { /// List of argument names and their type. /// /// Note that not all names will be valid identifiers, as some of @@ -1063,7 +1071,7 @@ pub struct FnDecl { /// ```ignore (incomplete code) /// fn printf(fmt: &str, ...); /// ``` - pub c_variadic: bool, + pub is_c_variadic: bool, } /// A `trait` declaration. @@ -1127,10 +1135,10 @@ pub struct Impl { /// The list of associated items contained in this impl block. pub items: Vec, /// Whether this is a negative impl (e.g. `!Sized` or `!Send`). - pub negative: bool, + pub is_negative: bool, /// Whether this is an impl that’s implied by the compiler /// (for autotraits, e.g. `Send` or `Sync`). - pub synthetic: bool, + pub is_synthetic: bool, // FIXME: document this pub blanket_impl: Option, } @@ -1138,7 +1146,7 @@ pub struct Impl { /// A `use` statement. #[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] #[serde(rename_all = "snake_case")] -pub struct Import { +pub struct Use { /// The full path being imported. pub source: String, /// May be different from the last segment of `source` when renaming imports: @@ -1150,7 +1158,7 @@ pub struct Import { /// ``` pub id: Option, /// Whether this statement is a wildcard `use`, e.g. `use source::*;` - pub glob: bool, + pub is_glob: bool, } /// A procedural macro. @@ -1205,7 +1213,7 @@ pub struct Static { #[serde(rename = "type")] pub type_: Type, /// This is `true` for mutable statics, declared as `static mut X: T = f();` - pub mutable: bool, + pub is_mutable: bool, /// The stringified expression for the initial value. /// /// It's not guaranteed that it'll match the actual source code for the initial value. diff --git a/src/rustdoc-json-types/tests.rs b/src/rustdoc-json-types/tests.rs index 1126d5f786f4d..b9363fcf1b714 100644 --- a/src/rustdoc-json-types/tests.rs +++ b/src/rustdoc-json-types/tests.rs @@ -4,7 +4,7 @@ use super::*; fn test_struct_info_roundtrip() { let s = ItemEnum::Struct(Struct { generics: Generics { params: vec![], where_predicates: vec![] }, - kind: StructKind::Plain { fields: vec![], fields_stripped: false }, + kind: StructKind::Plain { fields: vec![], has_stripped_fields: false }, impls: vec![], }); @@ -23,7 +23,7 @@ fn test_struct_info_roundtrip() { fn test_union_info_roundtrip() { let u = ItemEnum::Union(Union { generics: Generics { params: vec![], where_predicates: vec![] }, - fields_stripped: false, + has_stripped_fields: false, fields: vec![], impls: vec![], }); diff --git a/src/tools/jsondoclint/src/item_kind.rs b/src/tools/jsondoclint/src/item_kind.rs index 7d6ec475badd4..51146831efa40 100644 --- a/src/tools/jsondoclint/src/item_kind.rs +++ b/src/tools/jsondoclint/src/item_kind.rs @@ -5,7 +5,7 @@ use rustdoc_json_types::{Item, ItemEnum, ItemKind, ItemSummary}; pub(crate) enum Kind { Module, ExternCrate, - Import, + Use, Struct, StructField, Union, @@ -18,7 +18,7 @@ pub(crate) enum Kind { TraitAlias, Impl, Static, - ForeignType, + ExternType, Macro, ProcAttribute, ProcDerive, @@ -36,7 +36,7 @@ impl Kind { match self { Module => true, ExternCrate => true, - Import => true, + Use => true, Union => true, Struct => true, Enum => true, @@ -50,7 +50,7 @@ impl Kind { Macro => true, ProcMacro => true, Primitive => true, - ForeignType => true, + ExternType => true, // FIXME(adotinthevoid): I'm not sure if these are correct Keyword => false, @@ -69,7 +69,7 @@ impl Kind { pub fn can_appear_in_import(self) -> bool { match self { Kind::Variant => true, - Kind::Import => false, + Kind::Use => false, other => other.can_appear_in_mod(), } } @@ -90,7 +90,7 @@ impl Kind { Kind::Module => false, Kind::ExternCrate => false, - Kind::Import => false, + Kind::Use => false, Kind::Struct => false, Kind::StructField => false, Kind::Union => false, @@ -102,7 +102,7 @@ impl Kind { Kind::TraitAlias => false, Kind::Impl => false, Kind::Static => false, - Kind::ForeignType => false, + Kind::ExternType => false, Kind::Macro => false, Kind::ProcAttribute => false, Kind::ProcDerive => false, @@ -135,7 +135,7 @@ impl Kind { use Kind::*; match i.inner { ItemEnum::Module(_) => Module, - ItemEnum::Import(_) => Import, + ItemEnum::Use(_) => Use, ItemEnum::Union(_) => Union, ItemEnum::Struct(_) => Struct, ItemEnum::StructField(_) => StructField, @@ -151,7 +151,7 @@ impl Kind { ItemEnum::Macro(_) => Macro, ItemEnum::ProcMacro(_) => ProcMacro, ItemEnum::Primitive(_) => Primitive, - ItemEnum::ForeignType => ForeignType, + ItemEnum::ExternType => ExternType, ItemEnum::ExternCrate { .. } => ExternCrate, ItemEnum::AssocConst { .. } => AssocConst, ItemEnum::AssocType { .. } => AssocType, @@ -166,10 +166,10 @@ impl Kind { ItemKind::Constant => Constant, ItemKind::Enum => Enum, ItemKind::ExternCrate => ExternCrate, - ItemKind::ForeignType => ForeignType, + ItemKind::ExternType => ExternType, ItemKind::Function => Function, ItemKind::Impl => Impl, - ItemKind::Import => Import, + ItemKind::Use => Use, ItemKind::Keyword => Keyword, ItemKind::Macro => Macro, ItemKind::Module => Module, diff --git a/src/tools/jsondoclint/src/validator.rs b/src/tools/jsondoclint/src/validator.rs index 0ffb96bef29ba..10ab62cb24aa8 100644 --- a/src/tools/jsondoclint/src/validator.rs +++ b/src/tools/jsondoclint/src/validator.rs @@ -2,10 +2,11 @@ use std::collections::HashSet; use std::hash::Hash; use rustdoc_json_types::{ - Constant, Crate, DynTrait, Enum, FnDecl, Function, FunctionPointer, GenericArg, GenericArgs, - GenericBound, GenericParamDef, Generics, Id, Impl, Import, ItemEnum, ItemSummary, Module, Path, - Primitive, ProcMacro, Static, Struct, StructKind, Term, Trait, TraitAlias, Type, TypeAlias, - TypeBinding, TypeBindingKind, Union, Variant, VariantKind, WherePredicate, + AssocItemConstraint, AssocItemConstraintKind, Constant, Crate, DynTrait, Enum, Function, + FunctionPointer, FunctionSignature, GenericArg, GenericArgs, GenericBound, GenericParamDef, + Generics, Id, Impl, ItemEnum, ItemSummary, Module, Path, Primitive, ProcMacro, Static, Struct, + StructKind, Term, Trait, TraitAlias, Type, TypeAlias, Union, Use, Variant, VariantKind, + WherePredicate, }; use serde_json::Value; @@ -90,7 +91,7 @@ impl<'a> Validator<'a> { item.links.values().for_each(|id| self.add_any_id(id)); match &item.inner { - ItemEnum::Import(x) => self.check_import(x), + ItemEnum::Use(x) => self.check_use(x), ItemEnum::Union(x) => self.check_union(x), ItemEnum::Struct(x) => self.check_struct(x), ItemEnum::StructField(x) => self.check_struct_field(x), @@ -106,18 +107,18 @@ impl<'a> Validator<'a> { self.check_constant(const_); } ItemEnum::Static(x) => self.check_static(x), - ItemEnum::ForeignType => {} // nop + ItemEnum::ExternType => {} // nop ItemEnum::Macro(x) => self.check_macro(x), ItemEnum::ProcMacro(x) => self.check_proc_macro(x), ItemEnum::Primitive(x) => self.check_primitive_type(x), ItemEnum::Module(x) => self.check_module(x, id), // FIXME: Why don't these have their own structs? ItemEnum::ExternCrate { .. } => {} - ItemEnum::AssocConst { type_, default: _ } => self.check_type(type_), - ItemEnum::AssocType { generics, bounds, default } => { + ItemEnum::AssocConst { type_, value: _ } => self.check_type(type_), + ItemEnum::AssocType { generics, bounds, type_ } => { self.check_generics(generics); bounds.iter().for_each(|b| self.check_generic_bound(b)); - if let Some(ty) = default { + if let Some(ty) = type_ { self.check_type(ty); } } @@ -133,8 +134,8 @@ impl<'a> Validator<'a> { module.items.iter().for_each(|i| self.add_mod_item_id(i)); } - fn check_import(&mut self, x: &'a Import) { - if x.glob { + fn check_use(&mut self, x: &'a Use) { + if x.is_glob { self.add_glob_import_item_id(x.id.as_ref().unwrap()); } else if let Some(id) = &x.id { self.add_import_item_id(id); @@ -152,7 +153,7 @@ impl<'a> Validator<'a> { match &x.kind { StructKind::Unit => {} StructKind::Tuple(fields) => fields.iter().flatten().for_each(|f| self.add_field_id(f)), - StructKind::Plain { fields, fields_stripped: _ } => { + StructKind::Plain { fields, has_stripped_fields: _ } => { fields.iter().for_each(|f| self.add_field_id(f)) } } @@ -187,7 +188,7 @@ impl<'a> Validator<'a> { match kind { VariantKind::Plain => {} VariantKind::Tuple(tys) => tys.iter().flatten().for_each(|t| self.add_field_id(t)), - VariantKind::Struct { fields, fields_stripped: _ } => { + VariantKind::Struct { fields, has_stripped_fields: _ } => { fields.iter().for_each(|f| self.add_field_id(f)) } } @@ -195,7 +196,7 @@ impl<'a> Validator<'a> { fn check_function(&mut self, x: &'a Function) { self.check_generics(&x.generics); - self.check_fn_decl(&x.decl); + self.check_function_signature(&x.sig); } fn check_trait(&mut self, x: &'a Trait, id: &Id) { @@ -267,8 +268,8 @@ impl<'a> Validator<'a> { Type::Array { type_, len: _ } => self.check_type(&**type_), Type::ImplTrait(bounds) => bounds.iter().for_each(|b| self.check_generic_bound(b)), Type::Infer => {} - Type::RawPointer { mutable: _, type_ } => self.check_type(&**type_), - Type::BorrowedRef { lifetime: _, mutable: _, type_ } => self.check_type(&**type_), + Type::RawPointer { is_mutable: _, type_ } => self.check_type(&**type_), + Type::BorrowedRef { lifetime: _, is_mutable: _, type_ } => self.check_type(&**type_), Type::QualifiedPath { name: _, args, self_type, trait_ } => { self.check_generic_args(&**args); self.check_type(&**self_type); @@ -279,7 +280,7 @@ impl<'a> Validator<'a> { } } - fn check_fn_decl(&mut self, x: &'a FnDecl) { + fn check_function_signature(&mut self, x: &'a FunctionSignature) { x.inputs.iter().for_each(|(_name, ty)| self.check_type(ty)); if let Some(output) = &x.output { self.check_type(output); @@ -309,9 +310,9 @@ impl<'a> Validator<'a> { fn check_generic_args(&mut self, x: &'a GenericArgs) { match x { - GenericArgs::AngleBracketed { args, bindings } => { + GenericArgs::AngleBracketed { args, constraints } => { args.iter().for_each(|arg| self.check_generic_arg(arg)); - bindings.iter().for_each(|bind| self.check_type_binding(bind)); + constraints.iter().for_each(|bind| self.check_assoc_item_constraint(bind)); } GenericArgs::Parenthesized { inputs, output } => { inputs.iter().for_each(|ty| self.check_type(ty)); @@ -325,7 +326,7 @@ impl<'a> Validator<'a> { fn check_generic_param_def(&mut self, gpd: &'a GenericParamDef) { match &gpd.kind { rustdoc_json_types::GenericParamDefKind::Lifetime { outlives: _ } => {} - rustdoc_json_types::GenericParamDefKind::Type { bounds, default, synthetic: _ } => { + rustdoc_json_types::GenericParamDefKind::Type { bounds, default, is_synthetic: _ } => { bounds.iter().for_each(|b| self.check_generic_bound(b)); if let Some(ty) = default { self.check_type(ty); @@ -346,11 +347,11 @@ impl<'a> Validator<'a> { } } - fn check_type_binding(&mut self, bind: &'a TypeBinding) { + fn check_assoc_item_constraint(&mut self, bind: &'a AssocItemConstraint) { self.check_generic_args(&bind.args); match &bind.binding { - TypeBindingKind::Equality(term) => self.check_term(term), - TypeBindingKind::Constraint(bounds) => { + AssocItemConstraintKind::Equality(term) => self.check_term(term), + AssocItemConstraintKind::Constraint(bounds) => { bounds.iter().for_each(|b| self.check_generic_bound(b)) } } @@ -388,7 +389,7 @@ impl<'a> Validator<'a> { } fn check_function_pointer(&mut self, fp: &'a FunctionPointer) { - self.check_fn_decl(&fp.decl); + self.check_function_signature(&fp.sig); fp.generic_params.iter().for_each(|gpd| self.check_generic_param_def(gpd)); } diff --git a/tests/rustdoc-json/assoc_items.rs b/tests/rustdoc-json/assoc_items.rs index 7fd0fe2b89878..f315f37966d0b 100644 --- a/tests/rustdoc-json/assoc_items.rs +++ b/tests/rustdoc-json/assoc_items.rs @@ -9,12 +9,12 @@ impl Simple { pub trait EasyToImpl { //@ has "$.index[*][?(@.docs=='ToDeclare trait')].inner.assoc_type" - //@ is "$.index[*][?(@.docs=='ToDeclare trait')].inner.assoc_type.default" null + //@ is "$.index[*][?(@.docs=='ToDeclare trait')].inner.assoc_type.type" null //@ is "$.index[*][?(@.docs=='ToDeclare trait')].inner.assoc_type.bounds" [] /// ToDeclare trait type ToDeclare; //@ has "$.index[*][?(@.docs=='AN_ATTRIBUTE trait')].inner.assoc_const" - //@ is "$.index[*][?(@.docs=='AN_ATTRIBUTE trait')].inner.assoc_const.default" null + //@ is "$.index[*][?(@.docs=='AN_ATTRIBUTE trait')].inner.assoc_const.value" null //@ is "$.index[*][?(@.docs=='AN_ATTRIBUTE trait')].inner.assoc_const.type.primitive" '"usize"' /// AN_ATTRIBUTE trait const AN_ATTRIBUTE: usize; @@ -22,13 +22,13 @@ pub trait EasyToImpl { impl EasyToImpl for Simple { //@ has "$.index[*][?(@.docs=='ToDeclare impl')].inner.assoc_type" - //@ is "$.index[*][?(@.docs=='ToDeclare impl')].inner.assoc_type.default.primitive" \"usize\" + //@ is "$.index[*][?(@.docs=='ToDeclare impl')].inner.assoc_type.type.primitive" \"usize\" /// ToDeclare impl type ToDeclare = usize; //@ has "$.index[*][?(@.docs=='AN_ATTRIBUTE impl')].inner.assoc_const" //@ is "$.index[*][?(@.docs=='AN_ATTRIBUTE impl')].inner.assoc_const.type.primitive" \"usize\" - //@ is "$.index[*][?(@.docs=='AN_ATTRIBUTE impl')].inner.assoc_const.default" \"12\" + //@ is "$.index[*][?(@.docs=='AN_ATTRIBUTE impl')].inner.assoc_const.value" \"12\" /// AN_ATTRIBUTE impl const AN_ATTRIBUTE: usize = 12; } diff --git a/tests/rustdoc-json/blanket_impls.rs b/tests/rustdoc-json/blanket_impls.rs index bc2c98dcbb7ca..f2acabbe37254 100644 --- a/tests/rustdoc-json/blanket_impls.rs +++ b/tests/rustdoc-json/blanket_impls.rs @@ -3,6 +3,6 @@ #![no_std] //@ has "$.index[*][?(@.name=='Error')].inner.assoc_type" -//@ has "$.index[*][?(@.name=='Error')].inner.assoc_type.default.resolved_path" -//@ has "$.index[*][?(@.name=='Error')].inner.assoc_type.default.resolved_path.name" \"Infallible\" +//@ has "$.index[*][?(@.name=='Error')].inner.assoc_type.type.resolved_path" +//@ has "$.index[*][?(@.name=='Error')].inner.assoc_type.type.resolved_path.name" \"Infallible\" pub struct ForBlanketTryFromImpl; diff --git a/tests/rustdoc-json/enums/kind.rs b/tests/rustdoc-json/enums/kind.rs index ef3d9363d647a..2e0fb3101a31f 100644 --- a/tests/rustdoc-json/enums/kind.rs +++ b/tests/rustdoc-json/enums/kind.rs @@ -5,7 +5,7 @@ pub enum Foo { //@ is "$.index[*][?(@.name=='Unit')].inner.variant.kind" '"plain"' Unit, //@ set Named = "$.index[*][?(@.name=='Named')].id" - //@ is "$.index[*][?(@.name=='Named')].inner.variant.kind.struct" '{"fields": [], "fields_stripped": false}' + //@ is "$.index[*][?(@.name=='Named')].inner.variant.kind.struct" '{"fields": [], "has_stripped_fields": false}' Named {}, //@ set Tuple = "$.index[*][?(@.name=='Tuple')].id" //@ is "$.index[*][?(@.name=='Tuple')].inner.variant.kind.tuple" [] @@ -13,7 +13,7 @@ pub enum Foo { //@ set NamedField = "$.index[*][?(@.name=='NamedField')].id" //@ set x = "$.index[*][?(@.name=='x' && @.inner.struct_field)].id" //@ is "$.index[*][?(@.name=='NamedField')].inner.variant.kind.struct.fields[*]" $x - //@ is "$.index[*][?(@.name=='NamedField')].inner.variant.kind.struct.fields_stripped" false + //@ is "$.index[*][?(@.name=='NamedField')].inner.variant.kind.struct.has_stripped_fields" false NamedField { x: i32 }, //@ set TupleField = "$.index[*][?(@.name=='TupleField')].id" //@ set tup_field = "$.index[*][?(@.name=='0' && @.inner.struct_field)].id" diff --git a/tests/rustdoc-json/enums/struct_field_hidden.rs b/tests/rustdoc-json/enums/struct_field_hidden.rs index b724f9abb71b1..2184f58b1da80 100644 --- a/tests/rustdoc-json/enums/struct_field_hidden.rs +++ b/tests/rustdoc-json/enums/struct_field_hidden.rs @@ -9,7 +9,7 @@ pub enum Foo { //@ set y = "$.index[*][?(@.name=='y')].id" y: i32, }, - //@ is "$.index[*][?(@.name=='Variant')].inner.variant.kind.struct.fields_stripped" true + //@ is "$.index[*][?(@.name=='Variant')].inner.variant.kind.struct.has_stripped_fields" true //@ is "$.index[*][?(@.name=='Variant')].inner.variant.kind.struct.fields[0]" $b //@ is "$.index[*][?(@.name=='Variant')].inner.variant.kind.struct.fields[1]" $y //@ count "$.index[*][?(@.name=='Variant')].inner.variant.kind.struct.fields[*]" 2 diff --git a/tests/rustdoc-json/enums/use_glob.rs b/tests/rustdoc-json/enums/use_glob.rs index 61766d2a62982..2631b43da8e0e 100644 --- a/tests/rustdoc-json/enums/use_glob.rs +++ b/tests/rustdoc-json/enums/use_glob.rs @@ -7,9 +7,9 @@ pub enum Color { Blue, } -//@ set use_Color = "$.index[*][?(@.inner.import)].id" -//@ is "$.index[*][?(@.inner.import)].inner.import.id" $Color -//@ is "$.index[*][?(@.inner.import)].inner.import.glob" true +//@ set use_Color = "$.index[*][?(@.inner.use)].id" +//@ is "$.index[*][?(@.inner.use)].inner.use.id" $Color +//@ is "$.index[*][?(@.inner.use)].inner.use.is_glob" true pub use Color::*; //@ ismany "$.index[*][?(@.name == 'use_glob')].inner.module.items[*]" $Color $use_Color diff --git a/tests/rustdoc-json/enums/use_variant.rs b/tests/rustdoc-json/enums/use_variant.rs index 9010d61649396..6d3322e0ba9a1 100644 --- a/tests/rustdoc-json/enums/use_variant.rs +++ b/tests/rustdoc-json/enums/use_variant.rs @@ -5,8 +5,8 @@ pub enum AlwaysNone { } //@ is "$.index[*][?(@.name == 'AlwaysNone')].inner.enum.variants[*]" $None -//@ set use_None = "$.index[*][?(@.inner.import)].id" -//@ is "$.index[*][?(@.inner.import)].inner.import.id" $None +//@ set use_None = "$.index[*][?(@.inner.use)].id" +//@ is "$.index[*][?(@.inner.use)].inner.use.id" $None pub use AlwaysNone::None; //@ ismany "$.index[*][?(@.name == 'use_variant')].inner.module.items[*]" $AlwaysNone $use_None diff --git a/tests/rustdoc-json/enums/use_variant_foreign.rs b/tests/rustdoc-json/enums/use_variant_foreign.rs index 0f3f16ff83576..a9ad61b9fe35e 100644 --- a/tests/rustdoc-json/enums/use_variant_foreign.rs +++ b/tests/rustdoc-json/enums/use_variant_foreign.rs @@ -2,7 +2,7 @@ extern crate color; -//@ has "$.index[*].inner.import[?(@.name == 'Red')]" +//@ has "$.index[*].inner.use[?(@.name == 'Red')]" pub use color::Color::Red; //@ !has "$.index[*][?(@.name == 'Red')]" diff --git a/tests/rustdoc-json/fn_pointer/generics.rs b/tests/rustdoc-json/fn_pointer/generics.rs index 9f5d23ae421eb..7d64e490a2220 100644 --- a/tests/rustdoc-json/fn_pointer/generics.rs +++ b/tests/rustdoc-json/fn_pointer/generics.rs @@ -1,9 +1,9 @@ // ignore-tidy-linelength -//@ count "$.index[*][?(@.name=='WithHigherRankTraitBounds')].inner.type_alias.type.function_pointer.decl.inputs[*]" 1 -//@ is "$.index[*][?(@.name=='WithHigherRankTraitBounds')].inner.type_alias.type.function_pointer.decl.inputs[0][0]" '"val"' -//@ is "$.index[*][?(@.name=='WithHigherRankTraitBounds')].inner.type_alias.type.function_pointer.decl.inputs[0][1].borrowed_ref.lifetime" \"\'c\" -//@ is "$.index[*][?(@.name=='WithHigherRankTraitBounds')].inner.type_alias.type.function_pointer.decl.output.primitive" \"i32\" +//@ count "$.index[*][?(@.name=='WithHigherRankTraitBounds')].inner.type_alias.type.function_pointer.sig.inputs[*]" 1 +//@ is "$.index[*][?(@.name=='WithHigherRankTraitBounds')].inner.type_alias.type.function_pointer.sig.inputs[0][0]" '"val"' +//@ is "$.index[*][?(@.name=='WithHigherRankTraitBounds')].inner.type_alias.type.function_pointer.sig.inputs[0][1].borrowed_ref.lifetime" \"\'c\" +//@ is "$.index[*][?(@.name=='WithHigherRankTraitBounds')].inner.type_alias.type.function_pointer.sig.output.primitive" \"i32\" //@ count "$.index[*][?(@.name=='WithHigherRankTraitBounds')].inner.type_alias.type.function_pointer.generic_params[*]" 1 //@ is "$.index[*][?(@.name=='WithHigherRankTraitBounds')].inner.type_alias.type.function_pointer.generic_params[0].name" \"\'c\" //@ is "$.index[*][?(@.name=='WithHigherRankTraitBounds')].inner.type_alias.type.function_pointer.generic_params[0].kind" '{ "lifetime": { "outlives": [] } }' diff --git a/tests/rustdoc-json/fn_pointer/qualifiers.rs b/tests/rustdoc-json/fn_pointer/qualifiers.rs index 9c0e6c0ccf1e6..6f03cf58522e4 100644 --- a/tests/rustdoc-json/fn_pointer/qualifiers.rs +++ b/tests/rustdoc-json/fn_pointer/qualifiers.rs @@ -1,11 +1,11 @@ // ignore-tidy-linelength -//@ is "$.index[*][?(@.name=='FnPointer')].inner.type_alias.type.function_pointer.header.unsafe" false -//@ is "$.index[*][?(@.name=='FnPointer')].inner.type_alias.type.function_pointer.header.const" false -//@ is "$.index[*][?(@.name=='FnPointer')].inner.type_alias.type.function_pointer.header.async" false +//@ is "$.index[*][?(@.name=='FnPointer')].inner.type_alias.type.function_pointer.header.is_unsafe" false +//@ is "$.index[*][?(@.name=='FnPointer')].inner.type_alias.type.function_pointer.header.is_const" false +//@ is "$.index[*][?(@.name=='FnPointer')].inner.type_alias.type.function_pointer.header.is_async" false pub type FnPointer = fn(); -//@ is "$.index[*][?(@.name=='UnsafePointer')].inner.type_alias.type.function_pointer.header.unsafe" true -//@ is "$.index[*][?(@.name=='UnsafePointer')].inner.type_alias.type.function_pointer.header.const" false -//@ is "$.index[*][?(@.name=='UnsafePointer')].inner.type_alias.type.function_pointer.header.async" false +//@ is "$.index[*][?(@.name=='UnsafePointer')].inner.type_alias.type.function_pointer.header.is_unsafe" true +//@ is "$.index[*][?(@.name=='UnsafePointer')].inner.type_alias.type.function_pointer.header.is_const" false +//@ is "$.index[*][?(@.name=='UnsafePointer')].inner.type_alias.type.function_pointer.header.is_async" false pub type UnsafePointer = unsafe fn(); diff --git a/tests/rustdoc-json/fns/async_return.rs b/tests/rustdoc-json/fns/async_return.rs index e029c72df212f..18a8a586e76d9 100644 --- a/tests/rustdoc-json/fns/async_return.rs +++ b/tests/rustdoc-json/fns/async_return.rs @@ -5,30 +5,30 @@ use std::future::Future; -//@ is "$.index[*][?(@.name=='get_int')].inner.function.decl.output.primitive" \"i32\" -//@ is "$.index[*][?(@.name=='get_int')].inner.function.header.async" false +//@ is "$.index[*][?(@.name=='get_int')].inner.function.sig.output.primitive" \"i32\" +//@ is "$.index[*][?(@.name=='get_int')].inner.function.header.is_async" false pub fn get_int() -> i32 { 42 } -//@ is "$.index[*][?(@.name=='get_int_async')].inner.function.decl.output.primitive" \"i32\" -//@ is "$.index[*][?(@.name=='get_int_async')].inner.function.header.async" true +//@ is "$.index[*][?(@.name=='get_int_async')].inner.function.sig.output.primitive" \"i32\" +//@ is "$.index[*][?(@.name=='get_int_async')].inner.function.header.is_async" true pub async fn get_int_async() -> i32 { 42 } -//@ is "$.index[*][?(@.name=='get_int_future')].inner.function.decl.output.impl_trait[0].trait_bound.trait.name" '"Future"' -//@ is "$.index[*][?(@.name=='get_int_future')].inner.function.decl.output.impl_trait[0].trait_bound.trait.args.angle_bracketed.bindings[0].name" '"Output"' -//@ is "$.index[*][?(@.name=='get_int_future')].inner.function.decl.output.impl_trait[0].trait_bound.trait.args.angle_bracketed.bindings[0].binding.equality.type.primitive" \"i32\" -//@ is "$.index[*][?(@.name=='get_int_future')].inner.function.header.async" false +//@ is "$.index[*][?(@.name=='get_int_future')].inner.function.sig.output.impl_trait[0].trait_bound.trait.name" '"Future"' +//@ is "$.index[*][?(@.name=='get_int_future')].inner.function.sig.output.impl_trait[0].trait_bound.trait.args.angle_bracketed.constraints[0].name" '"Output"' +//@ is "$.index[*][?(@.name=='get_int_future')].inner.function.sig.output.impl_trait[0].trait_bound.trait.args.angle_bracketed.constraints[0].binding.equality.type.primitive" \"i32\" +//@ is "$.index[*][?(@.name=='get_int_future')].inner.function.header.is_async" false pub fn get_int_future() -> impl Future { async { 42 } } -//@ is "$.index[*][?(@.name=='get_int_future_async')].inner.function.decl.output.impl_trait[0].trait_bound.trait.name" '"Future"' -//@ is "$.index[*][?(@.name=='get_int_future_async')].inner.function.decl.output.impl_trait[0].trait_bound.trait.args.angle_bracketed.bindings[0].name" '"Output"' -//@ is "$.index[*][?(@.name=='get_int_future_async')].inner.function.decl.output.impl_trait[0].trait_bound.trait.args.angle_bracketed.bindings[0].binding.equality.type.primitive" \"i32\" -//@ is "$.index[*][?(@.name=='get_int_future_async')].inner.function.header.async" true +//@ is "$.index[*][?(@.name=='get_int_future_async')].inner.function.sig.output.impl_trait[0].trait_bound.trait.name" '"Future"' +//@ is "$.index[*][?(@.name=='get_int_future_async')].inner.function.sig.output.impl_trait[0].trait_bound.trait.args.angle_bracketed.constraints[0].name" '"Output"' +//@ is "$.index[*][?(@.name=='get_int_future_async')].inner.function.sig.output.impl_trait[0].trait_bound.trait.args.angle_bracketed.constraints[0].binding.equality.type.primitive" \"i32\" +//@ is "$.index[*][?(@.name=='get_int_future_async')].inner.function.header.is_async" true pub async fn get_int_future_async() -> impl Future { async { 42 } } diff --git a/tests/rustdoc-json/fns/extern_c_variadic.rs b/tests/rustdoc-json/fns/extern_c_variadic.rs index defe66345e83c..8e9085640e041 100644 --- a/tests/rustdoc-json/fns/extern_c_variadic.rs +++ b/tests/rustdoc-json/fns/extern_c_variadic.rs @@ -1,6 +1,6 @@ extern "C" { - //@ is "$.index[*][?(@.name == 'not_variadic')].inner.function.decl.c_variadic" false + //@ is "$.index[*][?(@.name == 'not_variadic')].inner.function.sig.is_c_variadic" false pub fn not_variadic(_: i32); - //@ is "$.index[*][?(@.name == 'variadic')].inner.function.decl.c_variadic" true + //@ is "$.index[*][?(@.name == 'variadic')].inner.function.sig.is_c_variadic" true pub fn variadic(_: i32, ...); } diff --git a/tests/rustdoc-json/fns/generic_args.rs b/tests/rustdoc-json/fns/generic_args.rs index 75c5fcbb01f6c..b5412446ab42a 100644 --- a/tests/rustdoc-json/fns/generic_args.rs +++ b/tests/rustdoc-json/fns/generic_args.rs @@ -12,27 +12,27 @@ pub trait GenericFoo<'a> {} //@ is "$.index[*][?(@.name=='generics')].inner.function.generics.params[0].kind.type.default" 'null' //@ count "$.index[*][?(@.name=='generics')].inner.function.generics.params[0].kind.type.bounds[*]" 1 //@ is "$.index[*][?(@.name=='generics')].inner.function.generics.params[0].kind.type.bounds[0].trait_bound.trait.id" '$foo' -//@ count "$.index[*][?(@.name=='generics')].inner.function.decl.inputs[*]" 1 -//@ is "$.index[*][?(@.name=='generics')].inner.function.decl.inputs[0][0]" '"f"' -//@ is "$.index[*][?(@.name=='generics')].inner.function.decl.inputs[0][1].generic" '"F"' +//@ count "$.index[*][?(@.name=='generics')].inner.function.sig.inputs[*]" 1 +//@ is "$.index[*][?(@.name=='generics')].inner.function.sig.inputs[0][0]" '"f"' +//@ is "$.index[*][?(@.name=='generics')].inner.function.sig.inputs[0][1].generic" '"F"' pub fn generics(f: F) {} //@ is "$.index[*][?(@.name=='impl_trait')].inner.function.generics.where_predicates" "[]" //@ count "$.index[*][?(@.name=='impl_trait')].inner.function.generics.params[*]" 1 //@ is "$.index[*][?(@.name=='impl_trait')].inner.function.generics.params[0].name" '"impl Foo"' //@ is "$.index[*][?(@.name=='impl_trait')].inner.function.generics.params[0].kind.type.bounds[0].trait_bound.trait.id" $foo -//@ count "$.index[*][?(@.name=='impl_trait')].inner.function.decl.inputs[*]" 1 -//@ is "$.index[*][?(@.name=='impl_trait')].inner.function.decl.inputs[0][0]" '"f"' -//@ count "$.index[*][?(@.name=='impl_trait')].inner.function.decl.inputs[0][1].impl_trait[*]" 1 -//@ is "$.index[*][?(@.name=='impl_trait')].inner.function.decl.inputs[0][1].impl_trait[0].trait_bound.trait.id" $foo +//@ count "$.index[*][?(@.name=='impl_trait')].inner.function.sig.inputs[*]" 1 +//@ is "$.index[*][?(@.name=='impl_trait')].inner.function.sig.inputs[0][0]" '"f"' +//@ count "$.index[*][?(@.name=='impl_trait')].inner.function.sig.inputs[0][1].impl_trait[*]" 1 +//@ is "$.index[*][?(@.name=='impl_trait')].inner.function.sig.inputs[0][1].impl_trait[0].trait_bound.trait.id" $foo pub fn impl_trait(f: impl Foo) {} //@ count "$.index[*][?(@.name=='where_clase')].inner.function.generics.params[*]" 3 //@ is "$.index[*][?(@.name=='where_clase')].inner.function.generics.params[0].name" '"F"' -//@ is "$.index[*][?(@.name=='where_clase')].inner.function.generics.params[0].kind" '{"type": {"bounds": [], "default": null, "synthetic": false}}' -//@ count "$.index[*][?(@.name=='where_clase')].inner.function.decl.inputs[*]" 3 -//@ is "$.index[*][?(@.name=='where_clase')].inner.function.decl.inputs[0][0]" '"f"' -//@ is "$.index[*][?(@.name=='where_clase')].inner.function.decl.inputs[0][1].generic" '"F"' +//@ is "$.index[*][?(@.name=='where_clase')].inner.function.generics.params[0].kind" '{"type": {"bounds": [], "default": null, "is_synthetic": false}}' +//@ count "$.index[*][?(@.name=='where_clase')].inner.function.sig.inputs[*]" 3 +//@ is "$.index[*][?(@.name=='where_clase')].inner.function.sig.inputs[0][0]" '"f"' +//@ is "$.index[*][?(@.name=='where_clase')].inner.function.sig.inputs[0][1].generic" '"F"' //@ count "$.index[*][?(@.name=='where_clase')].inner.function.generics.where_predicates[*]" 3 //@ is "$.index[*][?(@.name=='where_clase')].inner.function.generics.where_predicates[0].bound_predicate.type.generic" \"F\" diff --git a/tests/rustdoc-json/fns/generic_returns.rs b/tests/rustdoc-json/fns/generic_returns.rs index 07dc691b933f5..2f23801fc3f8f 100644 --- a/tests/rustdoc-json/fns/generic_returns.rs +++ b/tests/rustdoc-json/fns/generic_returns.rs @@ -5,9 +5,9 @@ //@ set foo = "$.index[*][?(@.name=='Foo')].id" pub trait Foo {} -//@ is "$.index[*][?(@.name=='get_foo')].inner.function.decl.inputs" [] -//@ count "$.index[*][?(@.name=='get_foo')].inner.function.decl.output.impl_trait[*]" 1 -//@ is "$.index[*][?(@.name=='get_foo')].inner.function.decl.output.impl_trait[0].trait_bound.trait.id" $foo +//@ is "$.index[*][?(@.name=='get_foo')].inner.function.sig.inputs" [] +//@ count "$.index[*][?(@.name=='get_foo')].inner.function.sig.output.impl_trait[*]" 1 +//@ is "$.index[*][?(@.name=='get_foo')].inner.function.sig.output.impl_trait[0].trait_bound.trait.id" $foo pub fn get_foo() -> impl Foo { Fooer {} } diff --git a/tests/rustdoc-json/fns/generics.rs b/tests/rustdoc-json/fns/generics.rs index 43fc7279ded57..f2064fd1e93df 100644 --- a/tests/rustdoc-json/fns/generics.rs +++ b/tests/rustdoc-json/fns/generics.rs @@ -6,17 +6,17 @@ pub trait Wham {} //@ is "$.index[*][?(@.name=='one_generic_param_fn')].inner.function.generics.where_predicates" [] //@ count "$.index[*][?(@.name=='one_generic_param_fn')].inner.function.generics.params[*]" 1 //@ is "$.index[*][?(@.name=='one_generic_param_fn')].inner.function.generics.params[0].name" '"T"' -//@ is "$.index[*][?(@.name=='one_generic_param_fn')].inner.function.generics.params[0].kind.type.synthetic" false +//@ is "$.index[*][?(@.name=='one_generic_param_fn')].inner.function.generics.params[0].kind.type.is_synthetic" false //@ is "$.index[*][?(@.name=='one_generic_param_fn')].inner.function.generics.params[0].kind.type.bounds[0].trait_bound.trait.id" $wham_id -//@ is "$.index[*][?(@.name=='one_generic_param_fn')].inner.function.decl.inputs" '[["w", {"generic": "T"}]]' +//@ is "$.index[*][?(@.name=='one_generic_param_fn')].inner.function.sig.inputs" '[["w", {"generic": "T"}]]' pub fn one_generic_param_fn(w: T) {} //@ is "$.index[*][?(@.name=='one_synthetic_generic_param_fn')].inner.function.generics.where_predicates" [] //@ count "$.index[*][?(@.name=='one_synthetic_generic_param_fn')].inner.function.generics.params[*]" 1 //@ is "$.index[*][?(@.name=='one_synthetic_generic_param_fn')].inner.function.generics.params[0].name" '"impl Wham"' -//@ is "$.index[*][?(@.name=='one_synthetic_generic_param_fn')].inner.function.generics.params[0].kind.type.synthetic" true +//@ is "$.index[*][?(@.name=='one_synthetic_generic_param_fn')].inner.function.generics.params[0].kind.type.is_synthetic" true //@ is "$.index[*][?(@.name=='one_synthetic_generic_param_fn')].inner.function.generics.params[0].kind.type.bounds[0].trait_bound.trait.id" $wham_id -//@ count "$.index[*][?(@.name=='one_synthetic_generic_param_fn')].inner.function.decl.inputs[*]" 1 -//@ is "$.index[*][?(@.name=='one_synthetic_generic_param_fn')].inner.function.decl.inputs[0][0]" '"w"' -//@ is "$.index[*][?(@.name=='one_synthetic_generic_param_fn')].inner.function.decl.inputs[0][1].impl_trait[0].trait_bound.trait.id" $wham_id +//@ count "$.index[*][?(@.name=='one_synthetic_generic_param_fn')].inner.function.sig.inputs[*]" 1 +//@ is "$.index[*][?(@.name=='one_synthetic_generic_param_fn')].inner.function.sig.inputs[0][0]" '"w"' +//@ is "$.index[*][?(@.name=='one_synthetic_generic_param_fn')].inner.function.sig.inputs[0][1].impl_trait[0].trait_bound.trait.id" $wham_id pub fn one_synthetic_generic_param_fn(w: impl Wham) {} diff --git a/tests/rustdoc-json/fns/pattern_arg.rs b/tests/rustdoc-json/fns/pattern_arg.rs index 3fa423bcefd27..d2a00f47438e2 100644 --- a/tests/rustdoc-json/fns/pattern_arg.rs +++ b/tests/rustdoc-json/fns/pattern_arg.rs @@ -1,7 +1,7 @@ -//@ is "$.index[*][?(@.name=='fst')].inner.function.decl.inputs[0][0]" '"(x, _)"' +//@ is "$.index[*][?(@.name=='fst')].inner.function.sig.inputs[0][0]" '"(x, _)"' pub fn fst((x, _): (X, Y)) -> X { x } -//@ is "$.index[*][?(@.name=='drop_int')].inner.function.decl.inputs[0][0]" '"_"' +//@ is "$.index[*][?(@.name=='drop_int')].inner.function.sig.inputs[0][0]" '"_"' pub fn drop_int(_: i32) {} diff --git a/tests/rustdoc-json/fns/qualifiers.rs b/tests/rustdoc-json/fns/qualifiers.rs index beb1b4ccd10c5..67e49f0780ae1 100644 --- a/tests/rustdoc-json/fns/qualifiers.rs +++ b/tests/rustdoc-json/fns/qualifiers.rs @@ -1,33 +1,33 @@ //@ edition:2018 -//@ is "$.index[*][?(@.name=='nothing_fn')].inner.function.header.async" false -//@ is "$.index[*][?(@.name=='nothing_fn')].inner.function.header.const" false -//@ is "$.index[*][?(@.name=='nothing_fn')].inner.function.header.unsafe" false +//@ is "$.index[*][?(@.name=='nothing_fn')].inner.function.header.is_async" false +//@ is "$.index[*][?(@.name=='nothing_fn')].inner.function.header.is_const" false +//@ is "$.index[*][?(@.name=='nothing_fn')].inner.function.header.is_unsafe" false pub fn nothing_fn() {} -//@ is "$.index[*][?(@.name=='unsafe_fn')].inner.function.header.async" false -//@ is "$.index[*][?(@.name=='unsafe_fn')].inner.function.header.const" false -//@ is "$.index[*][?(@.name=='unsafe_fn')].inner.function.header.unsafe" true +//@ is "$.index[*][?(@.name=='unsafe_fn')].inner.function.header.is_async" false +//@ is "$.index[*][?(@.name=='unsafe_fn')].inner.function.header.is_const" false +//@ is "$.index[*][?(@.name=='unsafe_fn')].inner.function.header.is_unsafe" true pub unsafe fn unsafe_fn() {} -//@ is "$.index[*][?(@.name=='const_fn')].inner.function.header.async" false -//@ is "$.index[*][?(@.name=='const_fn')].inner.function.header.const" true -//@ is "$.index[*][?(@.name=='const_fn')].inner.function.header.unsafe" false +//@ is "$.index[*][?(@.name=='const_fn')].inner.function.header.is_async" false +//@ is "$.index[*][?(@.name=='const_fn')].inner.function.header.is_const" true +//@ is "$.index[*][?(@.name=='const_fn')].inner.function.header.is_unsafe" false pub const fn const_fn() {} -//@ is "$.index[*][?(@.name=='async_fn')].inner.function.header.async" true -//@ is "$.index[*][?(@.name=='async_fn')].inner.function.header.const" false -//@ is "$.index[*][?(@.name=='async_fn')].inner.function.header.unsafe" false +//@ is "$.index[*][?(@.name=='async_fn')].inner.function.header.is_async" true +//@ is "$.index[*][?(@.name=='async_fn')].inner.function.header.is_const" false +//@ is "$.index[*][?(@.name=='async_fn')].inner.function.header.is_unsafe" false pub async fn async_fn() {} -//@ is "$.index[*][?(@.name=='async_unsafe_fn')].inner.function.header.async" true -//@ is "$.index[*][?(@.name=='async_unsafe_fn')].inner.function.header.const" false -//@ is "$.index[*][?(@.name=='async_unsafe_fn')].inner.function.header.unsafe" true +//@ is "$.index[*][?(@.name=='async_unsafe_fn')].inner.function.header.is_async" true +//@ is "$.index[*][?(@.name=='async_unsafe_fn')].inner.function.header.is_const" false +//@ is "$.index[*][?(@.name=='async_unsafe_fn')].inner.function.header.is_unsafe" true pub async unsafe fn async_unsafe_fn() {} -//@ is "$.index[*][?(@.name=='const_unsafe_fn')].inner.function.header.async" false -//@ is "$.index[*][?(@.name=='const_unsafe_fn')].inner.function.header.const" true -//@ is "$.index[*][?(@.name=='const_unsafe_fn')].inner.function.header.unsafe" true +//@ is "$.index[*][?(@.name=='const_unsafe_fn')].inner.function.header.is_async" false +//@ is "$.index[*][?(@.name=='const_unsafe_fn')].inner.function.header.is_const" true +//@ is "$.index[*][?(@.name=='const_unsafe_fn')].inner.function.header.is_unsafe" true pub const unsafe fn const_unsafe_fn() {} // It's impossible for a function to be both const and async, so no test for that diff --git a/tests/rustdoc-json/fns/return_type_alias.rs b/tests/rustdoc-json/fns/return_type_alias.rs index 67bc46a874064..d60c4b6825894 100644 --- a/tests/rustdoc-json/fns/return_type_alias.rs +++ b/tests/rustdoc-json/fns/return_type_alias.rs @@ -3,7 +3,7 @@ ///@ set foo = "$.index[*][?(@.name=='Foo')].id" pub type Foo = i32; -//@ is "$.index[*][?(@.name=='demo')].inner.function.decl.output.resolved_path.id" $foo +//@ is "$.index[*][?(@.name=='demo')].inner.function.sig.output.resolved_path.id" $foo pub fn demo() -> Foo { 42 } diff --git a/tests/rustdoc-json/generic-associated-types/gats.rs b/tests/rustdoc-json/generic-associated-types/gats.rs index 8a38230bb5d22..fdf605e928715 100644 --- a/tests/rustdoc-json/generic-associated-types/gats.rs +++ b/tests/rustdoc-json/generic-associated-types/gats.rs @@ -13,10 +13,10 @@ pub trait LendingIterator { where Self: 'a; - //@ count "$.index[*][?(@.name=='lending_next')].inner.function.decl.output.qualified_path.args.angle_bracketed.args[*]" 1 - //@ count "$.index[*][?(@.name=='lending_next')].inner.function.decl.output.qualified_path.args.angle_bracketed.bindings[*]" 0 - //@ is "$.index[*][?(@.name=='lending_next')].inner.function.decl.output.qualified_path.self_type.generic" \"Self\" - //@ is "$.index[*][?(@.name=='lending_next')].inner.function.decl.output.qualified_path.name" \"LendingItem\" + //@ count "$.index[*][?(@.name=='lending_next')].inner.function.sig.output.qualified_path.args.angle_bracketed.args[*]" 1 + //@ count "$.index[*][?(@.name=='lending_next')].inner.function.sig.output.qualified_path.args.angle_bracketed.bindings[*]" 0 + //@ is "$.index[*][?(@.name=='lending_next')].inner.function.sig.output.qualified_path.self_type.generic" \"Self\" + //@ is "$.index[*][?(@.name=='lending_next')].inner.function.sig.output.qualified_path.name" \"LendingItem\" fn lending_next<'a>(&'a self) -> Self::LendingItem<'a>; } @@ -26,9 +26,9 @@ pub trait Iterator { //@ count "$.index[*][?(@.name=='Item')].inner.assoc_type.bounds[*]" 1 type Item: Display; - //@ count "$.index[*][?(@.name=='next')].inner.function.decl.output.qualified_path.args.angle_bracketed.args[*]" 0 - //@ count "$.index[*][?(@.name=='next')].inner.function.decl.output.qualified_path.args.angle_bracketed.bindings[*]" 0 - //@ is "$.index[*][?(@.name=='next')].inner.function.decl.output.qualified_path.self_type.generic" \"Self\" - //@ is "$.index[*][?(@.name=='next')].inner.function.decl.output.qualified_path.name" \"Item\" + //@ count "$.index[*][?(@.name=='next')].inner.function.sig.output.qualified_path.args.angle_bracketed.args[*]" 0 + //@ count "$.index[*][?(@.name=='next')].inner.function.sig.output.qualified_path.args.angle_bracketed.bindings[*]" 0 + //@ is "$.index[*][?(@.name=='next')].inner.function.sig.output.qualified_path.self_type.generic" \"Self\" + //@ is "$.index[*][?(@.name=='next')].inner.function.sig.output.qualified_path.name" \"Item\" fn next<'a>(&'a self) -> Self::Item; } diff --git a/tests/rustdoc-json/glob_import.rs b/tests/rustdoc-json/glob_import.rs index a67a99a37cbc7..b63e5dadd9e74 100644 --- a/tests/rustdoc-json/glob_import.rs +++ b/tests/rustdoc-json/glob_import.rs @@ -3,7 +3,7 @@ #![no_std] //@ has "$.index[*][?(@.name=='glob')]" -//@ has "$.index[*][?(@.inner.import)].inner.import.name" \"*\" +//@ has "$.index[*][?(@.inner.use)].inner.use.name" \"*\" mod m1 { pub fn f() {} diff --git a/tests/rustdoc-json/impl-trait-in-assoc-type.rs b/tests/rustdoc-json/impl-trait-in-assoc-type.rs index f02e38ca393de..907a0f6c603e0 100644 --- a/tests/rustdoc-json/impl-trait-in-assoc-type.rs +++ b/tests/rustdoc-json/impl-trait-in-assoc-type.rs @@ -9,11 +9,11 @@ impl IntoIterator for AlwaysTrue { /// type Item type Item = bool; - //@ count '$.index[*][?(@.docs=="type IntoIter")].inner.assoc_type.default.impl_trait[*]' 1 - //@ is '$.index[*][?(@.docs=="type IntoIter")].inner.assoc_type.default.impl_trait[0].trait_bound.trait.name' '"Iterator"' - //@ count '$.index[*][?(@.docs=="type IntoIter")].inner.assoc_type.default.impl_trait[0].trait_bound.trait.args.angle_bracketed.bindings[*]' 1 - //@ is '$.index[*][?(@.docs=="type IntoIter")].inner.assoc_type.default.impl_trait[0].trait_bound.trait.args.angle_bracketed.bindings[0].name' '"Item"' - //@ is '$.index[*][?(@.docs=="type IntoIter")].inner.assoc_type.default.impl_trait[0].trait_bound.trait.args.angle_bracketed.bindings[0].binding.equality.type.primitive' '"bool"' + //@ count '$.index[*][?(@.docs=="type IntoIter")].inner.assoc_type.type.impl_trait[*]' 1 + //@ is '$.index[*][?(@.docs=="type IntoIter")].inner.assoc_type.type.impl_trait[0].trait_bound.trait.name' '"Iterator"' + //@ count '$.index[*][?(@.docs=="type IntoIter")].inner.assoc_type.type.impl_trait[0].trait_bound.trait.args.angle_bracketed.constraints[*]' 1 + //@ is '$.index[*][?(@.docs=="type IntoIter")].inner.assoc_type.type.impl_trait[0].trait_bound.trait.args.angle_bracketed.constraints[0].name' '"Item"' + //@ is '$.index[*][?(@.docs=="type IntoIter")].inner.assoc_type.type.impl_trait[0].trait_bound.trait.args.angle_bracketed.constraints[0].binding.equality.type.primitive' '"bool"' //@ set IntoIter = '$.index[*][?(@.docs=="type IntoIter")].id' /// type IntoIter diff --git a/tests/rustdoc-json/impl-trait-precise-capturing.rs b/tests/rustdoc-json/impl-trait-precise-capturing.rs index 0c116a1029019..52252560e6fda 100644 --- a/tests/rustdoc-json/impl-trait-precise-capturing.rs +++ b/tests/rustdoc-json/impl-trait-precise-capturing.rs @@ -1,4 +1,4 @@ -//@ is "$.index[*][?(@.name=='hello')].inner.function.decl.output.impl_trait[1].use[0]" \"\'a\" -//@ is "$.index[*][?(@.name=='hello')].inner.function.decl.output.impl_trait[1].use[1]" \"T\" -//@ is "$.index[*][?(@.name=='hello')].inner.function.decl.output.impl_trait[1].use[2]" \"N\" +//@ is "$.index[*][?(@.name=='hello')].inner.function.sig.output.impl_trait[1].use[0]" \"\'a\" +//@ is "$.index[*][?(@.name=='hello')].inner.function.sig.output.impl_trait[1].use[1]" \"T\" +//@ is "$.index[*][?(@.name=='hello')].inner.function.sig.output.impl_trait[1].use[2]" \"N\" pub fn hello<'a, T, const N: usize>() -> impl Sized + use<'a, T, N> {} diff --git a/tests/rustdoc-json/impls/auto.rs b/tests/rustdoc-json/impls/auto.rs index 84a1e6ed7d564..e14c935b23b87 100644 --- a/tests/rustdoc-json/impls/auto.rs +++ b/tests/rustdoc-json/impls/auto.rs @@ -18,5 +18,5 @@ impl Foo { //@ is "$.index[*][?(@.docs=='has span')].span.begin" "[13, 0]" //@ is "$.index[*][?(@.docs=='has span')].span.end" "[15, 1]" // FIXME: this doesn't work due to https://github.com/freestrings/jsonpath/issues/91 -// is "$.index[*][?(@.inner.impl.synthetic==true)].span" null +// is "$.index[*][?(@.inner.impl.is_synthetic==true)].span" null pub struct Foo; diff --git a/tests/rustdoc-json/impls/foreign_for_local.rs b/tests/rustdoc-json/impls/foreign_for_local.rs index 20690f26851be..1347f954cade8 100644 --- a/tests/rustdoc-json/impls/foreign_for_local.rs +++ b/tests/rustdoc-json/impls/foreign_for_local.rs @@ -3,7 +3,7 @@ extern crate foreign_trait; /// ForeignTrait id hack pub use foreign_trait::ForeignTrait as _; -//@ set ForeignTrait = "$.index[*][?(@.docs=='ForeignTrait id hack')].inner.import.id" +//@ set ForeignTrait = "$.index[*][?(@.docs=='ForeignTrait id hack')].inner.use.id" pub struct LocalStruct; //@ set LocalStruct = "$.index[*][?(@.name=='LocalStruct')].id" diff --git a/tests/rustdoc-json/impls/import_from_private.rs b/tests/rustdoc-json/impls/import_from_private.rs index e386252e83b51..32b9abb0717cc 100644 --- a/tests/rustdoc-json/impls/import_from_private.rs +++ b/tests/rustdoc-json/impls/import_from_private.rs @@ -11,10 +11,10 @@ mod bar { } } -//@ set import = "$.index[*][?(@.inner.import)].id" +//@ set import = "$.index[*][?(@.inner.use)].id" pub use bar::Baz; //@ is "$.index[*].inner.module.items[*]" $import -//@ is "$.index[*].inner.import.id" $baz +//@ is "$.index[*].inner.use.id" $baz //@ has "$.index[*][?(@.name == 'Baz')].inner.struct.impls[*]" $impl //@ is "$.index[*][?(@.docs=='impl')].inner.impl.items[*]" $doit diff --git a/tests/rustdoc-json/impls/local_for_foreign.rs b/tests/rustdoc-json/impls/local_for_foreign.rs index bd49269104fb7..cd89c47534881 100644 --- a/tests/rustdoc-json/impls/local_for_foreign.rs +++ b/tests/rustdoc-json/impls/local_for_foreign.rs @@ -3,7 +3,7 @@ extern crate foreign_struct; /// ForeignStruct id hack pub use foreign_struct::ForeignStruct as _; -//@ set ForeignStruct = "$.index[*][?(@.docs=='ForeignStruct id hack')].inner.import.id" +//@ set ForeignStruct = "$.index[*][?(@.docs=='ForeignStruct id hack')].inner.use.id" pub trait LocalTrait {} //@ set LocalTrait = "$.index[*][?(@.name=='LocalTrait')].id" diff --git a/tests/rustdoc-json/lifetime/longest.rs b/tests/rustdoc-json/lifetime/longest.rs index 39f791d2b0935..8ac60be0fefdb 100644 --- a/tests/rustdoc-json/lifetime/longest.rs +++ b/tests/rustdoc-json/lifetime/longest.rs @@ -6,21 +6,21 @@ //@ count "$.index[*][?(@.name=='longest')].inner.function.generics.params[*]" 1 //@ is "$.index[*][?(@.name=='longest')].inner.function.generics.where_predicates" [] -//@ count "$.index[*][?(@.name=='longest')].inner.function.decl.inputs[*]" 2 -//@ is "$.index[*][?(@.name=='longest')].inner.function.decl.inputs[0][0]" '"l"' -//@ is "$.index[*][?(@.name=='longest')].inner.function.decl.inputs[1][0]" '"r"' +//@ count "$.index[*][?(@.name=='longest')].inner.function.sig.inputs[*]" 2 +//@ is "$.index[*][?(@.name=='longest')].inner.function.sig.inputs[0][0]" '"l"' +//@ is "$.index[*][?(@.name=='longest')].inner.function.sig.inputs[1][0]" '"r"' -//@ is "$.index[*][?(@.name=='longest')].inner.function.decl.inputs[0][1].borrowed_ref.lifetime" \"\'a\" -//@ is "$.index[*][?(@.name=='longest')].inner.function.decl.inputs[0][1].borrowed_ref.mutable" false -//@ is "$.index[*][?(@.name=='longest')].inner.function.decl.inputs[0][1].borrowed_ref.type.primitive" \"str\" +//@ is "$.index[*][?(@.name=='longest')].inner.function.sig.inputs[0][1].borrowed_ref.lifetime" \"\'a\" +//@ is "$.index[*][?(@.name=='longest')].inner.function.sig.inputs[0][1].borrowed_ref.is_mutable" false +//@ is "$.index[*][?(@.name=='longest')].inner.function.sig.inputs[0][1].borrowed_ref.type.primitive" \"str\" -//@ is "$.index[*][?(@.name=='longest')].inner.function.decl.inputs[1][1].borrowed_ref.lifetime" \"\'a\" -//@ is "$.index[*][?(@.name=='longest')].inner.function.decl.inputs[1][1].borrowed_ref.mutable" false -//@ is "$.index[*][?(@.name=='longest')].inner.function.decl.inputs[1][1].borrowed_ref.type.primitive" \"str\" +//@ is "$.index[*][?(@.name=='longest')].inner.function.sig.inputs[1][1].borrowed_ref.lifetime" \"\'a\" +//@ is "$.index[*][?(@.name=='longest')].inner.function.sig.inputs[1][1].borrowed_ref.is_mutable" false +//@ is "$.index[*][?(@.name=='longest')].inner.function.sig.inputs[1][1].borrowed_ref.type.primitive" \"str\" -//@ is "$.index[*][?(@.name=='longest')].inner.function.decl.output.borrowed_ref.lifetime" \"\'a\" -//@ is "$.index[*][?(@.name=='longest')].inner.function.decl.output.borrowed_ref.mutable" false -//@ is "$.index[*][?(@.name=='longest')].inner.function.decl.output.borrowed_ref.type.primitive" \"str\" +//@ is "$.index[*][?(@.name=='longest')].inner.function.sig.output.borrowed_ref.lifetime" \"\'a\" +//@ is "$.index[*][?(@.name=='longest')].inner.function.sig.output.borrowed_ref.is_mutable" false +//@ is "$.index[*][?(@.name=='longest')].inner.function.sig.output.borrowed_ref.type.primitive" \"str\" pub fn longest<'a>(l: &'a str, r: &'a str) -> &'a str { if l.len() > r.len() { l } else { r } diff --git a/tests/rustdoc-json/lifetime/outlives.rs b/tests/rustdoc-json/lifetime/outlives.rs index c98555d5737ad..99d14296f9998 100644 --- a/tests/rustdoc-json/lifetime/outlives.rs +++ b/tests/rustdoc-json/lifetime/outlives.rs @@ -10,9 +10,9 @@ //@ is "$.index[*][?(@.name=='foo')].inner.function.generics.params[2].kind.type.default" null //@ count "$.index[*][?(@.name=='foo')].inner.function.generics.params[2].kind.type.bounds[*]" 1 //@ is "$.index[*][?(@.name=='foo')].inner.function.generics.params[2].kind.type.bounds[0].outlives" \"\'b\" -//@ is "$.index[*][?(@.name=='foo')].inner.function.decl.inputs[0][1].borrowed_ref.lifetime" \"\'a\" -//@ is "$.index[*][?(@.name=='foo')].inner.function.decl.inputs[0][1].borrowed_ref.mutable" false -//@ is "$.index[*][?(@.name=='foo')].inner.function.decl.inputs[0][1].borrowed_ref.type.borrowed_ref.lifetime" \"\'b\" -//@ is "$.index[*][?(@.name=='foo')].inner.function.decl.inputs[0][1].borrowed_ref.type.borrowed_ref.mutable" false -//@ is "$.index[*][?(@.name=='foo')].inner.function.decl.inputs[0][1].borrowed_ref.type.borrowed_ref.type.generic" \"T\" +//@ is "$.index[*][?(@.name=='foo')].inner.function.sig.inputs[0][1].borrowed_ref.lifetime" \"\'a\" +//@ is "$.index[*][?(@.name=='foo')].inner.function.sig.inputs[0][1].borrowed_ref.is_mutable" false +//@ is "$.index[*][?(@.name=='foo')].inner.function.sig.inputs[0][1].borrowed_ref.type.borrowed_ref.lifetime" \"\'b\" +//@ is "$.index[*][?(@.name=='foo')].inner.function.sig.inputs[0][1].borrowed_ref.type.borrowed_ref.is_mutable" false +//@ is "$.index[*][?(@.name=='foo')].inner.function.sig.inputs[0][1].borrowed_ref.type.borrowed_ref.type.generic" \"T\" pub fn foo<'a, 'b: 'a, T: 'b>(_: &'a &'b T) {} diff --git a/tests/rustdoc-json/methods/qualifiers.rs b/tests/rustdoc-json/methods/qualifiers.rs index 8de8cfd4c15d3..ba7c2e60936b3 100644 --- a/tests/rustdoc-json/methods/qualifiers.rs +++ b/tests/rustdoc-json/methods/qualifiers.rs @@ -3,34 +3,34 @@ pub struct Foo; impl Foo { - //@ is "$.index[*][?(@.name=='const_meth')].inner.function.header.async" false - //@ is "$.index[*][?(@.name=='const_meth')].inner.function.header.const" true - //@ is "$.index[*][?(@.name=='const_meth')].inner.function.header.unsafe" false + //@ is "$.index[*][?(@.name=='const_meth')].inner.function.header.is_async" false + //@ is "$.index[*][?(@.name=='const_meth')].inner.function.header.is_const" true + //@ is "$.index[*][?(@.name=='const_meth')].inner.function.header.is_unsafe" false pub const fn const_meth() {} - //@ is "$.index[*][?(@.name=='nothing_meth')].inner.function.header.async" false - //@ is "$.index[*][?(@.name=='nothing_meth')].inner.function.header.const" false - //@ is "$.index[*][?(@.name=='nothing_meth')].inner.function.header.unsafe" false + //@ is "$.index[*][?(@.name=='nothing_meth')].inner.function.header.is_async" false + //@ is "$.index[*][?(@.name=='nothing_meth')].inner.function.header.is_const" false + //@ is "$.index[*][?(@.name=='nothing_meth')].inner.function.header.is_unsafe" false pub fn nothing_meth() {} - //@ is "$.index[*][?(@.name=='unsafe_meth')].inner.function.header.async" false - //@ is "$.index[*][?(@.name=='unsafe_meth')].inner.function.header.const" false - //@ is "$.index[*][?(@.name=='unsafe_meth')].inner.function.header.unsafe" true + //@ is "$.index[*][?(@.name=='unsafe_meth')].inner.function.header.is_async" false + //@ is "$.index[*][?(@.name=='unsafe_meth')].inner.function.header.is_const" false + //@ is "$.index[*][?(@.name=='unsafe_meth')].inner.function.header.is_unsafe" true pub unsafe fn unsafe_meth() {} - //@ is "$.index[*][?(@.name=='async_meth')].inner.function.header.async" true - //@ is "$.index[*][?(@.name=='async_meth')].inner.function.header.const" false - //@ is "$.index[*][?(@.name=='async_meth')].inner.function.header.unsafe" false + //@ is "$.index[*][?(@.name=='async_meth')].inner.function.header.is_async" true + //@ is "$.index[*][?(@.name=='async_meth')].inner.function.header.is_const" false + //@ is "$.index[*][?(@.name=='async_meth')].inner.function.header.is_unsafe" false pub async fn async_meth() {} - //@ is "$.index[*][?(@.name=='async_unsafe_meth')].inner.function.header.async" true - //@ is "$.index[*][?(@.name=='async_unsafe_meth')].inner.function.header.const" false - //@ is "$.index[*][?(@.name=='async_unsafe_meth')].inner.function.header.unsafe" true + //@ is "$.index[*][?(@.name=='async_unsafe_meth')].inner.function.header.is_async" true + //@ is "$.index[*][?(@.name=='async_unsafe_meth')].inner.function.header.is_const" false + //@ is "$.index[*][?(@.name=='async_unsafe_meth')].inner.function.header.is_unsafe" true pub async unsafe fn async_unsafe_meth() {} - //@ is "$.index[*][?(@.name=='const_unsafe_meth')].inner.function.header.async" false - //@ is "$.index[*][?(@.name=='const_unsafe_meth')].inner.function.header.const" true - //@ is "$.index[*][?(@.name=='const_unsafe_meth')].inner.function.header.unsafe" true + //@ is "$.index[*][?(@.name=='const_unsafe_meth')].inner.function.header.is_async" false + //@ is "$.index[*][?(@.name=='const_unsafe_meth')].inner.function.header.is_const" true + //@ is "$.index[*][?(@.name=='const_unsafe_meth')].inner.function.header.is_unsafe" true pub const unsafe fn const_unsafe_meth() {} // It's impossible for a method to be both const and async, so no test for that diff --git a/tests/rustdoc-json/nested.rs b/tests/rustdoc-json/nested.rs index ae2d9fe0ac55b..10ec2831c212c 100644 --- a/tests/rustdoc-json/nested.rs +++ b/tests/rustdoc-json/nested.rs @@ -22,11 +22,11 @@ pub mod l1 { //@ ismany "$.index[*][?(@.name=='l3')].inner.module.items[*]" $l4_id pub struct L4; } - //@ is "$.index[*][?(@.inner.import)].inner.import.glob" false - //@ is "$.index[*][?(@.inner.import)].inner.import.source" '"l3::L4"' - //@ is "$.index[*][?(@.inner.import)].inner.import.glob" false - //@ is "$.index[*][?(@.inner.import)].inner.import.id" $l4_id - //@ set l4_use_id = "$.index[*][?(@.inner.import)].id" + //@ is "$.index[*][?(@.inner.use)].inner.use.is_glob" false + //@ is "$.index[*][?(@.inner.use)].inner.use.source" '"l3::L4"' + //@ is "$.index[*][?(@.inner.use)].inner.use.is_glob" false + //@ is "$.index[*][?(@.inner.use)].inner.use.id" $l4_id + //@ set l4_use_id = "$.index[*][?(@.inner.use)].id" pub use l3::L4; } //@ ismany "$.index[*][?(@.name=='l1')].inner.module.items[*]" $l3_id $l4_use_id diff --git a/tests/rustdoc-json/non_lifetime_binders.rs b/tests/rustdoc-json/non_lifetime_binders.rs index 06f6e10aa85c2..8443141fecd50 100644 --- a/tests/rustdoc-json/non_lifetime_binders.rs +++ b/tests/rustdoc-json/non_lifetime_binders.rs @@ -11,7 +11,7 @@ pub struct Wrapper(std::marker::PhantomData); //@ is "$.index[*][?(@.name=='foo')].inner.function.generics.where_predicates[0].bound_predicate.generic_params[0].name" \"\'a\" //@ is "$.index[*][?(@.name=='foo')].inner.function.generics.where_predicates[0].bound_predicate.generic_params[0].kind" '{ "lifetime": { "outlives": [] } }' //@ is "$.index[*][?(@.name=='foo')].inner.function.generics.where_predicates[0].bound_predicate.generic_params[1].name" \"T\" -//@ is "$.index[*][?(@.name=='foo')].inner.function.generics.where_predicates[0].bound_predicate.generic_params[1].kind" '{ "type": { "bounds": [], "default": null, "synthetic": false } }' +//@ is "$.index[*][?(@.name=='foo')].inner.function.generics.where_predicates[0].bound_predicate.generic_params[1].kind" '{ "type": { "bounds": [], "default": null, "is_synthetic": false } }' pub fn foo() where for<'a, T> &'a Wrapper: Trait, diff --git a/tests/rustdoc-json/primitives/use_primitive.rs b/tests/rustdoc-json/primitives/use_primitive.rs index 27394a688c4b5..d4cdef84de845 100644 --- a/tests/rustdoc-json/primitives/use_primitive.rs +++ b/tests/rustdoc-json/primitives/use_primitive.rs @@ -13,7 +13,7 @@ mod usize {} //@ !is "$.index[*][?(@.name=='checked_add')]" $local_crate_id //@ !has "$.index[*][?(@.name=='is_ascii_uppercase')]" -//@ is "$.index[*].inner.import[?(@.name=='my_i32')].id" null +//@ is "$.index[*].inner.use[?(@.name=='my_i32')].id" null pub use i32 as my_i32; -//@ is "$.index[*].inner.import[?(@.name=='u32')].id" null +//@ is "$.index[*].inner.use[?(@.name=='u32')].id" null pub use u32; diff --git a/tests/rustdoc-json/reexport/extern_crate_glob.rs b/tests/rustdoc-json/reexport/extern_crate_glob.rs index a0b4cb8ab2cdc..dfe6e7a03b153 100644 --- a/tests/rustdoc-json/reexport/extern_crate_glob.rs +++ b/tests/rustdoc-json/reexport/extern_crate_glob.rs @@ -6,6 +6,6 @@ extern crate enum_with_discriminant; pub use enum_with_discriminant::*; //@ !has '$.index[*][?(@.docs == "Should not be inlined")]' -//@ is '$.index[*][?(@.inner.import)].inner.import.name' \"enum_with_discriminant\" -//@ set use = '$.index[*][?(@.inner.import)].id' +//@ is '$.index[*][?(@.inner.use)].inner.use.name' \"enum_with_discriminant\" +//@ set use = '$.index[*][?(@.inner.use)].id' //@ is '$.index[*][?(@.name == "extern_crate_glob")].inner.module.items[*]' $use diff --git a/tests/rustdoc-json/reexport/glob_collision.rs b/tests/rustdoc-json/reexport/glob_collision.rs index 3a034afab65f1..8142c35f4c712 100644 --- a/tests/rustdoc-json/reexport/glob_collision.rs +++ b/tests/rustdoc-json/reexport/glob_collision.rs @@ -14,13 +14,13 @@ mod m2 { } //@ set m1_use = "$.index[*][?(@.docs=='m1 re-export')].id" -//@ is "$.index[*].inner.import[?(@.name=='m1')].id" $m1 -//@ is "$.index[*].inner.import[?(@.name=='m1')].glob" true +//@ is "$.index[*].inner.use[?(@.name=='m1')].id" $m1 +//@ is "$.index[*].inner.use[?(@.name=='m1')].is_glob" true /// m1 re-export pub use m1::*; //@ set m2_use = "$.index[*][?(@.docs=='m2 re-export')].id" -//@ is "$.index[*].inner.import[?(@.name=='m2')].id" $m2 -//@ is "$.index[*].inner.import[?(@.name=='m2')].glob" true +//@ is "$.index[*].inner.use[?(@.name=='m2')].id" $m2 +//@ is "$.index[*].inner.use[?(@.name=='m2')].is_glob" true /// m2 re-export pub use m2::*; diff --git a/tests/rustdoc-json/reexport/glob_empty_mod.rs b/tests/rustdoc-json/reexport/glob_empty_mod.rs index 326df5fdb6198..ee1779407f404 100644 --- a/tests/rustdoc-json/reexport/glob_empty_mod.rs +++ b/tests/rustdoc-json/reexport/glob_empty_mod.rs @@ -4,5 +4,5 @@ //@ set m1 = "$.index[*][?(@.name=='m1')].id" mod m1 {} -//@ is "$.index[*][?(@.inner.import)].inner.import.id" $m1 +//@ is "$.index[*][?(@.inner.use)].inner.use.id" $m1 pub use m1::*; diff --git a/tests/rustdoc-json/reexport/glob_extern.rs b/tests/rustdoc-json/reexport/glob_extern.rs index ff5d986d377f4..98be47739413e 100644 --- a/tests/rustdoc-json/reexport/glob_extern.rs +++ b/tests/rustdoc-json/reexport/glob_extern.rs @@ -12,8 +12,8 @@ mod mod1 { //@ set mod1_id = "$.index[*][?(@.name=='mod1')].id" } -//@ is "$.index[*][?(@.inner.import)].inner.import.glob" true -//@ is "$.index[*][?(@.inner.import)].inner.import.id" $mod1_id -//@ set use_id = "$.index[*][?(@.inner.import)].id" +//@ is "$.index[*][?(@.inner.use)].inner.use.is_glob" true +//@ is "$.index[*][?(@.inner.use)].inner.use.id" $mod1_id +//@ set use_id = "$.index[*][?(@.inner.use)].id" //@ ismany "$.index[*][?(@.name=='glob_extern')].inner.module.items[*]" $use_id pub use mod1::*; diff --git a/tests/rustdoc-json/reexport/glob_private.rs b/tests/rustdoc-json/reexport/glob_private.rs index 0a88910759206..2084ffc356e2a 100644 --- a/tests/rustdoc-json/reexport/glob_private.rs +++ b/tests/rustdoc-json/reexport/glob_private.rs @@ -12,7 +12,7 @@ mod mod1 { } //@ set mod2_use_id = "$.index[*][?(@.docs=='Mod2 re-export')].id" - //@ is "$.index[*][?(@.docs=='Mod2 re-export')].inner.import.name" \"mod2\" + //@ is "$.index[*][?(@.docs=='Mod2 re-export')].inner.use.name" \"mod2\" /// Mod2 re-export pub use self::mod2::*; @@ -23,7 +23,7 @@ mod mod1 { } //@ set mod1_use_id = "$.index[*][?(@.docs=='Mod1 re-export')].id" -//@ is "$.index[*][?(@.docs=='Mod1 re-export')].inner.import.name" \"mod1\" +//@ is "$.index[*][?(@.docs=='Mod1 re-export')].inner.use.name" \"mod1\" /// Mod1 re-export pub use mod1::*; diff --git a/tests/rustdoc-json/reexport/in_root_and_mod.rs b/tests/rustdoc-json/reexport/in_root_and_mod.rs index f94e416c00f58..a1d2080c06887 100644 --- a/tests/rustdoc-json/reexport/in_root_and_mod.rs +++ b/tests/rustdoc-json/reexport/in_root_and_mod.rs @@ -4,10 +4,10 @@ mod foo { pub struct Foo; } -//@ has "$.index[*].inner[?(@.import.source=='foo::Foo')]" +//@ has "$.index[*].inner[?(@.use.source=='foo::Foo')]" pub use foo::Foo; pub mod bar { - //@ has "$.index[*].inner[?(@.import.source=='crate::foo::Foo')]" + //@ has "$.index[*].inner[?(@.use.source=='crate::foo::Foo')]" pub use crate::foo::Foo; } diff --git a/tests/rustdoc-json/reexport/in_root_and_mod_pub.rs b/tests/rustdoc-json/reexport/in_root_and_mod_pub.rs index 13dee32354224..7d26d2a970d4a 100644 --- a/tests/rustdoc-json/reexport/in_root_and_mod_pub.rs +++ b/tests/rustdoc-json/reexport/in_root_and_mod_pub.rs @@ -5,14 +5,14 @@ pub mod foo { } //@ set root_import_id = "$.index[*][?(@.docs=='Outer re-export')].id" -//@ is "$.index[*].inner[?(@.import.source=='foo::Bar')].import.id" $bar_id +//@ is "$.index[*].inner[?(@.use.source=='foo::Bar')].use.id" $bar_id //@ has "$.index[*][?(@.name=='in_root_and_mod_pub')].inner.module.items[*]" $root_import_id /// Outer re-export pub use foo::Bar; pub mod baz { //@ set baz_import_id = "$.index[*][?(@.docs=='Inner re-export')].id" - //@ is "$.index[*].inner[?(@.import.source=='crate::foo::Bar')].import.id" $bar_id + //@ is "$.index[*].inner[?(@.use.source=='crate::foo::Bar')].use.id" $bar_id //@ ismany "$.index[*][?(@.name=='baz')].inner.module.items[*]" $baz_import_id /// Inner re-export pub use crate::foo::Bar; diff --git a/tests/rustdoc-json/reexport/mod_not_included.rs b/tests/rustdoc-json/reexport/mod_not_included.rs index 7e0c0118e8462..d0ce95749f1b4 100644 --- a/tests/rustdoc-json/reexport/mod_not_included.rs +++ b/tests/rustdoc-json/reexport/mod_not_included.rs @@ -7,5 +7,5 @@ mod m1 { pub use m1::x; //@ has "$.index[*][?(@.name=='x' && @.inner.function)]" -//@ has "$.index[*].inner[?(@.import.name=='x')].import.source" '"m1::x"' +//@ has "$.index[*].inner[?(@.use.name=='x')].use.source" '"m1::x"' //@ !has "$.index[*][?(@.name=='m1')]" diff --git a/tests/rustdoc-json/reexport/private_twice_one_inline.rs b/tests/rustdoc-json/reexport/private_twice_one_inline.rs index be66ad522da86..87b97e65c0ac2 100644 --- a/tests/rustdoc-json/reexport/private_twice_one_inline.rs +++ b/tests/rustdoc-json/reexport/private_twice_one_inline.rs @@ -7,18 +7,18 @@ extern crate pub_struct as foo; #[doc(inline)] //@ set crate_use_id = "$.index[*][?(@.docs=='Hack A')].id" -//@ set foo_id = "$.index[*][?(@.docs=='Hack A')].inner.import.id" +//@ set foo_id = "$.index[*][?(@.docs=='Hack A')].inner.use.id" /// Hack A pub use foo::Foo; //@ set bar_id = "$.index[*][?(@.name=='bar')].id" pub mod bar { - //@ is "$.index[*][?(@.docs=='Hack B')].inner.import.id" $foo_id + //@ is "$.index[*][?(@.docs=='Hack B')].inner.use.id" $foo_id //@ set bar_use_id = "$.index[*][?(@.docs=='Hack B')].id" //@ ismany "$.index[*][?(@.name=='bar')].inner.module.items[*]" $bar_use_id /// Hack B pub use foo::Foo; } -//@ ismany "$.index[*][?(@.inner.import)].id" $crate_use_id $bar_use_id +//@ ismany "$.index[*][?(@.inner.use)].id" $crate_use_id $bar_use_id //@ ismany "$.index[*][?(@.name=='private_twice_one_inline')].inner.module.items[*]" $bar_id $crate_use_id diff --git a/tests/rustdoc-json/reexport/private_two_names.rs b/tests/rustdoc-json/reexport/private_two_names.rs index 1e5466dba5e4e..1ed54f15fdc36 100644 --- a/tests/rustdoc-json/reexport/private_two_names.rs +++ b/tests/rustdoc-json/reexport/private_two_names.rs @@ -9,13 +9,13 @@ mod style { pub struct Color; } -//@ is "$.index[*][?(@.docs=='First re-export')].inner.import.id" $color_struct_id -//@ is "$.index[*][?(@.docs=='First re-export')].inner.import.name" \"Color\" +//@ is "$.index[*][?(@.docs=='First re-export')].inner.use.id" $color_struct_id +//@ is "$.index[*][?(@.docs=='First re-export')].inner.use.name" \"Color\" //@ set color_export_id = "$.index[*][?(@.docs=='First re-export')].id" /// First re-export pub use style::Color; -//@ is "$.index[*][?(@.docs=='Second re-export')].inner.import.id" $color_struct_id -//@ is "$.index[*][?(@.docs=='Second re-export')].inner.import.name" \"Colour\" +//@ is "$.index[*][?(@.docs=='Second re-export')].inner.use.id" $color_struct_id +//@ is "$.index[*][?(@.docs=='Second re-export')].inner.use.name" \"Colour\" //@ set colour_export_id = "$.index[*][?(@.docs=='Second re-export')].id" /// Second re-export pub use style::Color as Colour; diff --git a/tests/rustdoc-json/reexport/reexport_of_hidden.rs b/tests/rustdoc-json/reexport/reexport_of_hidden.rs index 07ce1f5c20a1b..80f171da888e3 100644 --- a/tests/rustdoc-json/reexport/reexport_of_hidden.rs +++ b/tests/rustdoc-json/reexport/reexport_of_hidden.rs @@ -1,6 +1,6 @@ //@ compile-flags: --document-hidden-items -//@ has "$.index[*].inner[?(@.import.name=='UsedHidden')]" +//@ has "$.index[*].inner[?(@.use.name=='UsedHidden')]" //@ has "$.index[*][?(@.name=='Hidden')]" pub mod submodule { #[doc(hidden)] diff --git a/tests/rustdoc-json/reexport/rename_private.rs b/tests/rustdoc-json/reexport/rename_private.rs index 3335d18e27b1f..3f13f305d6448 100644 --- a/tests/rustdoc-json/reexport/rename_private.rs +++ b/tests/rustdoc-json/reexport/rename_private.rs @@ -6,5 +6,5 @@ mod inner { pub struct Public; } -//@ is "$.index[*][?(@.inner.import)].inner.import.name" \"NewName\" +//@ is "$.index[*][?(@.inner.use)].inner.use.name" \"NewName\" pub use inner::Public as NewName; diff --git a/tests/rustdoc-json/reexport/rename_public.rs b/tests/rustdoc-json/reexport/rename_public.rs index e534f458f9378..81c003a51c4af 100644 --- a/tests/rustdoc-json/reexport/rename_public.rs +++ b/tests/rustdoc-json/reexport/rename_public.rs @@ -7,8 +7,8 @@ pub mod inner { pub struct Public; } //@ set import_id = "$.index[*][?(@.docs=='Re-export')].id" -//@ !has "$.index[*].inner[?(@.import.name=='Public')]" -//@ is "$.index[*].inner[?(@.import.name=='NewName')].import.source" \"inner::Public\" +//@ !has "$.index[*].inner[?(@.use.name=='Public')]" +//@ is "$.index[*].inner[?(@.use.name=='NewName')].use.source" \"inner::Public\" /// Re-export pub use inner::Public as NewName; diff --git a/tests/rustdoc-json/reexport/same_name_different_types.rs b/tests/rustdoc-json/reexport/same_name_different_types.rs index b0a06d4ecfab5..e9bc4a5ac406d 100644 --- a/tests/rustdoc-json/reexport/same_name_different_types.rs +++ b/tests/rustdoc-json/reexport/same_name_different_types.rs @@ -13,10 +13,10 @@ pub mod nested { pub fn Foo() {} } -//@ ismany "$.index[*].inner[?(@.import.name == 'Foo')].import.id" $foo_fn $foo_struct -//@ ismany "$.index[*].inner[?(@.import.name == 'Bar')].import.id" $foo_fn $foo_struct +//@ ismany "$.index[*].inner[?(@.use.name == 'Foo')].use.id" $foo_fn $foo_struct +//@ ismany "$.index[*].inner[?(@.use.name == 'Bar')].use.id" $foo_fn $foo_struct -//@ count "$.index[*].inner[?(@.import.name == 'Foo')]" 2 +//@ count "$.index[*].inner[?(@.use.name == 'Foo')]" 2 pub use nested::Foo; -//@ count "$.index[*].inner[?(@.import.name == 'Bar')]" 2 +//@ count "$.index[*].inner[?(@.use.name == 'Bar')]" 2 pub use Foo as Bar; diff --git a/tests/rustdoc-json/reexport/same_type_reexported_more_than_once.rs b/tests/rustdoc-json/reexport/same_type_reexported_more_than_once.rs index c533b9ba7709c..27e2827d08ddb 100644 --- a/tests/rustdoc-json/reexport/same_type_reexported_more_than_once.rs +++ b/tests/rustdoc-json/reexport/same_type_reexported_more_than_once.rs @@ -10,11 +10,11 @@ mod inner { } //@ set export_id = "$.index[*][?(@.docs=='First re-export')].id" -//@ is "$.index[*].inner[?(@.import.name=='Trait')].import.id" $trait_id +//@ is "$.index[*].inner[?(@.use.name=='Trait')].use.id" $trait_id /// First re-export pub use inner::Trait; //@ set reexport_id = "$.index[*][?(@.docs=='Second re-export')].id" -//@ is "$.index[*].inner[?(@.import.name=='Reexport')].import.id" $trait_id +//@ is "$.index[*].inner[?(@.use.name=='Reexport')].use.id" $trait_id /// Second re-export pub use inner::Trait as Reexport; diff --git a/tests/rustdoc-json/reexport/simple_private.rs b/tests/rustdoc-json/reexport/simple_private.rs index 9af0157818b4f..8a936f5da1b9e 100644 --- a/tests/rustdoc-json/reexport/simple_private.rs +++ b/tests/rustdoc-json/reexport/simple_private.rs @@ -6,9 +6,9 @@ mod inner { pub struct Public; } -//@ is "$.index[*][?(@.inner.import)].inner.import.name" \"Public\" -//@ is "$.index[*][?(@.inner.import)].inner.import.id" $pub_id -//@ set use_id = "$.index[*][?(@.inner.import)].id" +//@ is "$.index[*][?(@.inner.use)].inner.use.name" \"Public\" +//@ is "$.index[*][?(@.inner.use)].inner.use.id" $pub_id +//@ set use_id = "$.index[*][?(@.inner.use)].id" pub use inner::Public; //@ ismany "$.index[*][?(@.name=='simple_private')].inner.module.items[*]" $use_id diff --git a/tests/rustdoc-json/reexport/simple_public.rs b/tests/rustdoc-json/reexport/simple_public.rs index d7b44b2f9877f..e5a8dc7d2ad00 100644 --- a/tests/rustdoc-json/reexport/simple_public.rs +++ b/tests/rustdoc-json/reexport/simple_public.rs @@ -9,7 +9,7 @@ pub mod inner { } //@ set import_id = "$.index[*][?(@.docs=='Outer')].id" -//@ is "$.index[*][?(@.docs=='Outer')].inner.import.source" \"inner::Public\" +//@ is "$.index[*][?(@.docs=='Outer')].inner.use.source" \"inner::Public\" /// Outer pub use inner::Public; diff --git a/tests/rustdoc-json/return_private.rs b/tests/rustdoc-json/return_private.rs index 4a1922e15e5fe..0b341e2bda7d2 100644 --- a/tests/rustdoc-json/return_private.rs +++ b/tests/rustdoc-json/return_private.rs @@ -6,7 +6,7 @@ mod secret { } //@ has "$.index[*][?(@.name=='get_secret')].inner.function" -//@ is "$.index[*][?(@.name=='get_secret')].inner.function.decl.output.resolved_path.name" \"secret::Secret\" +//@ is "$.index[*][?(@.name=='get_secret')].inner.function.sig.output.resolved_path.name" \"secret::Secret\" pub fn get_secret() -> secret::Secret { secret::Secret } diff --git a/tests/rustdoc-json/structs/plain_all_pub.rs b/tests/rustdoc-json/structs/plain_all_pub.rs index aa53b59726a9d..67d2a4a7a8cf8 100644 --- a/tests/rustdoc-json/structs/plain_all_pub.rs +++ b/tests/rustdoc-json/structs/plain_all_pub.rs @@ -8,4 +8,4 @@ pub struct Demo { //@ is "$.index[*][?(@.name=='Demo')].inner.struct.kind.plain.fields[0]" $x //@ is "$.index[*][?(@.name=='Demo')].inner.struct.kind.plain.fields[1]" $y //@ count "$.index[*][?(@.name=='Demo')].inner.struct.kind.plain.fields[*]" 2 -//@ is "$.index[*][?(@.name=='Demo')].inner.struct.kind.plain.fields_stripped" false +//@ is "$.index[*][?(@.name=='Demo')].inner.struct.kind.plain.has_stripped_fields" false diff --git a/tests/rustdoc-json/structs/plain_doc_hidden.rs b/tests/rustdoc-json/structs/plain_doc_hidden.rs index 39f9367cb935f..4573adc73fa1f 100644 --- a/tests/rustdoc-json/structs/plain_doc_hidden.rs +++ b/tests/rustdoc-json/structs/plain_doc_hidden.rs @@ -8,4 +8,4 @@ pub struct Demo { //@ !has "$.index[*][?(@.name=='y')].id" //@ is "$.index[*][?(@.name=='Demo')].inner.struct.kind.plain.fields[0]" $x //@ count "$.index[*][?(@.name=='Demo')].inner.struct.kind.plain.fields[*]" 1 -//@ is "$.index[*][?(@.name=='Demo')].inner.struct.kind.plain.fields_stripped" true +//@ is "$.index[*][?(@.name=='Demo')].inner.struct.kind.plain.has_stripped_fields" true diff --git a/tests/rustdoc-json/structs/plain_empty.rs b/tests/rustdoc-json/structs/plain_empty.rs index 00b4b05ebddd1..30013021abef2 100644 --- a/tests/rustdoc-json/structs/plain_empty.rs +++ b/tests/rustdoc-json/structs/plain_empty.rs @@ -1,5 +1,5 @@ //@ is "$.index[*][?(@.name=='PlainEmpty')].visibility" \"public\" //@ has "$.index[*][?(@.name=='PlainEmpty')].inner.struct" -//@ is "$.index[*][?(@.name=='PlainEmpty')].inner.struct.kind.plain.fields_stripped" false +//@ is "$.index[*][?(@.name=='PlainEmpty')].inner.struct.kind.plain.has_stripped_fields" false //@ is "$.index[*][?(@.name=='PlainEmpty')].inner.struct.kind.plain.fields" [] pub struct PlainEmpty {} diff --git a/tests/rustdoc-json/structs/plain_pub_priv.rs b/tests/rustdoc-json/structs/plain_pub_priv.rs index f9ab8714f81a6..91079a30d42ea 100644 --- a/tests/rustdoc-json/structs/plain_pub_priv.rs +++ b/tests/rustdoc-json/structs/plain_pub_priv.rs @@ -6,4 +6,4 @@ pub struct Demo { //@ set x = "$.index[*][?(@.name=='x')].id" //@ is "$.index[*][?(@.name=='Demo')].inner.struct.kind.plain.fields[0]" $x //@ count "$.index[*][?(@.name=='Demo')].inner.struct.kind.plain.fields[*]" 1 -//@ is "$.index[*][?(@.name=='Demo')].inner.struct.kind.plain.fields_stripped" true +//@ is "$.index[*][?(@.name=='Demo')].inner.struct.kind.plain.has_stripped_fields" true diff --git a/tests/rustdoc-json/structs/with_generics.rs b/tests/rustdoc-json/structs/with_generics.rs index 6e13dae9ebffb..3e7f175a5a1a5 100644 --- a/tests/rustdoc-json/structs/with_generics.rs +++ b/tests/rustdoc-json/structs/with_generics.rs @@ -6,7 +6,7 @@ use std::collections::HashMap; //@ is "$.index[*][?(@.name=='WithGenerics')].inner.struct.generics.params[0].kind.type.bounds" [] //@ is "$.index[*][?(@.name=='WithGenerics')].inner.struct.generics.params[1].name" \"U\" //@ is "$.index[*][?(@.name=='WithGenerics')].inner.struct.generics.params[1].kind.type.bounds" [] -//@ is "$.index[*][?(@.name=='WithGenerics')].inner.struct.kind.plain.fields_stripped" true +//@ is "$.index[*][?(@.name=='WithGenerics')].inner.struct.kind.plain.has_stripped_fields" true //@ is "$.index[*][?(@.name=='WithGenerics')].inner.struct.kind.plain.fields" [] pub struct WithGenerics { stuff: Vec, diff --git a/tests/rustdoc-json/structs/with_primitives.rs b/tests/rustdoc-json/structs/with_primitives.rs index 2ca11b50608f8..7202ab9af9c28 100644 --- a/tests/rustdoc-json/structs/with_primitives.rs +++ b/tests/rustdoc-json/structs/with_primitives.rs @@ -4,7 +4,7 @@ //@ has "$.index[*][?(@.name=='WithPrimitives')].inner.struct" //@ is "$.index[*][?(@.name=='WithPrimitives')].inner.struct.generics.params[0].name" \"\'a\" //@ is "$.index[*][?(@.name=='WithPrimitives')].inner.struct.generics.params[0].kind.lifetime.outlives" [] -//@ is "$.index[*][?(@.name=='WithPrimitives')].inner.struct.kind.plain.fields_stripped" true +//@ is "$.index[*][?(@.name=='WithPrimitives')].inner.struct.kind.plain.has_stripped_fields" true //@ is "$.index[*][?(@.name=='WithPrimitives')].inner.struct.kind.plain.fields" [] pub struct WithPrimitives<'a> { num: u32, diff --git a/tests/rustdoc-json/trait_alias.rs b/tests/rustdoc-json/trait_alias.rs index ca9e5edfdf7e0..3ae5fad8accd7 100644 --- a/tests/rustdoc-json/trait_alias.rs +++ b/tests/rustdoc-json/trait_alias.rs @@ -7,12 +7,12 @@ //@ is "$.index[*][?(@.name=='StrLike')].span.filename" $FILE pub trait StrLike = AsRef; -//@ is "$.index[*][?(@.name=='f')].inner.function.decl.output.impl_trait[0].trait_bound.trait.id" $StrLike +//@ is "$.index[*][?(@.name=='f')].inner.function.sig.output.impl_trait[0].trait_bound.trait.id" $StrLike pub fn f() -> impl StrLike { "heya" } -//@ !is "$.index[*][?(@.name=='g')].inner.function.decl.output.impl_trait[0].trait_bound.trait.id" $StrLike +//@ !is "$.index[*][?(@.name=='g')].inner.function.sig.output.impl_trait[0].trait_bound.trait.id" $StrLike pub fn g() -> impl AsRef { "heya" } diff --git a/tests/rustdoc-json/traits/self.rs b/tests/rustdoc-json/traits/self.rs index c7d952ae567d4..060bc37f2d5ea 100644 --- a/tests/rustdoc-json/traits/self.rs +++ b/tests/rustdoc-json/traits/self.rs @@ -9,29 +9,29 @@ pub struct Foo; // Each assertion matches 3 times, and should be the same each time. impl Foo { - //@ ismany '$.index[*][?(@.name=="by_ref")].inner.function.decl.inputs[0][0]' '"self"' '"self"' '"self"' - //@ ismany '$.index[*][?(@.name=="by_ref")].inner.function.decl.inputs[0][1].borrowed_ref.type.generic' '"Self"' '"Self"' '"Self"' - //@ ismany '$.index[*][?(@.name=="by_ref")].inner.function.decl.inputs[0][1].borrowed_ref.lifetime' null null null - //@ ismany '$.index[*][?(@.name=="by_ref")].inner.function.decl.inputs[0][1].borrowed_ref.mutable' false false false + //@ ismany '$.index[*][?(@.name=="by_ref")].inner.function.sig.inputs[0][0]' '"self"' '"self"' '"self"' + //@ ismany '$.index[*][?(@.name=="by_ref")].inner.function.sig.inputs[0][1].borrowed_ref.type.generic' '"Self"' '"Self"' '"Self"' + //@ ismany '$.index[*][?(@.name=="by_ref")].inner.function.sig.inputs[0][1].borrowed_ref.lifetime' null null null + //@ ismany '$.index[*][?(@.name=="by_ref")].inner.function.sig.inputs[0][1].borrowed_ref.is_mutable' false false false pub fn by_ref(&self) {} - //@ ismany '$.index[*][?(@.name=="by_exclusive_ref")].inner.function.decl.inputs[0][0]' '"self"' '"self"' '"self"' - //@ ismany '$.index[*][?(@.name=="by_exclusive_ref")].inner.function.decl.inputs[0][1].borrowed_ref.type.generic' '"Self"' '"Self"' '"Self"' - //@ ismany '$.index[*][?(@.name=="by_exclusive_ref")].inner.function.decl.inputs[0][1].borrowed_ref.lifetime' null null null - //@ ismany '$.index[*][?(@.name=="by_exclusive_ref")].inner.function.decl.inputs[0][1].borrowed_ref.mutable' true true true + //@ ismany '$.index[*][?(@.name=="by_exclusive_ref")].inner.function.sig.inputs[0][0]' '"self"' '"self"' '"self"' + //@ ismany '$.index[*][?(@.name=="by_exclusive_ref")].inner.function.sig.inputs[0][1].borrowed_ref.type.generic' '"Self"' '"Self"' '"Self"' + //@ ismany '$.index[*][?(@.name=="by_exclusive_ref")].inner.function.sig.inputs[0][1].borrowed_ref.lifetime' null null null + //@ ismany '$.index[*][?(@.name=="by_exclusive_ref")].inner.function.sig.inputs[0][1].borrowed_ref.is_mutable' true true true pub fn by_exclusive_ref(&mut self) {} - //@ ismany '$.index[*][?(@.name=="by_value")].inner.function.decl.inputs[0][0]' '"self"' '"self"' '"self"' - //@ ismany '$.index[*][?(@.name=="by_value")].inner.function.decl.inputs[0][1].generic' '"Self"' '"Self"' '"Self"' + //@ ismany '$.index[*][?(@.name=="by_value")].inner.function.sig.inputs[0][0]' '"self"' '"self"' '"self"' + //@ ismany '$.index[*][?(@.name=="by_value")].inner.function.sig.inputs[0][1].generic' '"Self"' '"Self"' '"Self"' pub fn by_value(self) {} - //@ ismany '$.index[*][?(@.name=="with_lifetime")].inner.function.decl.inputs[0][0]' '"self"' '"self"' '"self"' - //@ ismany '$.index[*][?(@.name=="with_lifetime")].inner.function.decl.inputs[0][1].borrowed_ref.type.generic' '"Self"' '"Self"' '"Self"' - //@ ismany '$.index[*][?(@.name=="with_lifetime")].inner.function.decl.inputs[0][1].borrowed_ref.lifetime' \"\'a\" \"\'a\" \"\'a\" - //@ ismany '$.index[*][?(@.name=="with_lifetime")].inner.function.decl.inputs[0][1].borrowed_ref.mutable' false false false + //@ ismany '$.index[*][?(@.name=="with_lifetime")].inner.function.sig.inputs[0][0]' '"self"' '"self"' '"self"' + //@ ismany '$.index[*][?(@.name=="with_lifetime")].inner.function.sig.inputs[0][1].borrowed_ref.type.generic' '"Self"' '"Self"' '"Self"' + //@ ismany '$.index[*][?(@.name=="with_lifetime")].inner.function.sig.inputs[0][1].borrowed_ref.lifetime' \"\'a\" \"\'a\" \"\'a\" + //@ ismany '$.index[*][?(@.name=="with_lifetime")].inner.function.sig.inputs[0][1].borrowed_ref.is_mutable' false false false pub fn with_lifetime<'a>(&'a self) {} - //@ ismany '$.index[*][?(@.name=="build")].inner.function.decl.output.generic' '"Self"' '"Self"' '"Self"' + //@ ismany '$.index[*][?(@.name=="build")].inner.function.sig.output.generic' '"Self"' '"Self"' '"Self"' pub fn build() -> Self { Self } diff --git a/tests/rustdoc-json/traits/trait_alias.rs b/tests/rustdoc-json/traits/trait_alias.rs index a1ab039692bed..17c83ddc353ce 100644 --- a/tests/rustdoc-json/traits/trait_alias.rs +++ b/tests/rustdoc-json/traits/trait_alias.rs @@ -19,8 +19,8 @@ pub struct Struct; impl Orig for Struct {} -//@ has "$.index[*][?(@.name=='takes_alias')].inner.function.decl.inputs[0][1].impl_trait" -//@ is "$.index[*][?(@.name=='takes_alias')].inner.function.decl.inputs[0][1].impl_trait[0].trait_bound.trait.id" $Alias +//@ has "$.index[*][?(@.name=='takes_alias')].inner.function.sig.inputs[0][1].impl_trait" +//@ is "$.index[*][?(@.name=='takes_alias')].inner.function.sig.inputs[0][1].impl_trait[0].trait_bound.trait.id" $Alias //@ is "$.index[*][?(@.name=='takes_alias')].inner.function.generics.params[0].kind.type.bounds[0].trait_bound.trait.id" $Alias pub fn takes_alias(_: impl Alias) {} // FIXME: Should the trait be mentioned in both the decl and generics? diff --git a/tests/rustdoc-json/type/dyn.rs b/tests/rustdoc-json/type/dyn.rs index 86ea1c2b5f220..97c8689a7c80a 100644 --- a/tests/rustdoc-json/type/dyn.rs +++ b/tests/rustdoc-json/type/dyn.rs @@ -11,7 +11,7 @@ use std::fmt::Debug; //@ is "$.index[*][?(@.name=='SyncIntGen')].inner.type_alias.generics" '{"params": [], "where_predicates": []}' //@ has "$.index[*][?(@.name=='SyncIntGen')].inner.type_alias.type.resolved_path" //@ is "$.index[*][?(@.name=='SyncIntGen')].inner.type_alias.type.resolved_path.name" \"Box\" -//@ is "$.index[*][?(@.name=='SyncIntGen')].inner.type_alias.type.resolved_path.args.angle_bracketed.bindings" [] +//@ is "$.index[*][?(@.name=='SyncIntGen')].inner.type_alias.type.resolved_path.args.angle_bracketed.constraints" [] //@ count "$.index[*][?(@.name=='SyncIntGen')].inner.type_alias.type.resolved_path.args.angle_bracketed.args" 1 //@ has "$.index[*][?(@.name=='SyncIntGen')].inner.type_alias.type.resolved_path.args.angle_bracketed.args[0].type.dyn_trait" //@ is "$.index[*][?(@.name=='SyncIntGen')].inner.type_alias.type.resolved_path.args.angle_bracketed.args[0].type.dyn_trait.lifetime" \"\'static\" @@ -28,7 +28,7 @@ pub type SyncIntGen = Box i32 + Send + Sync + 'static>; //@ has "$.index[*][?(@.name=='RefFn')].inner.type_alias" //@ is "$.index[*][?(@.name=='RefFn')].inner.type_alias.generics" '{"params": [{"kind": {"lifetime": {"outlives": []}},"name": "'\''a"}],"where_predicates": []}' //@ has "$.index[*][?(@.name=='RefFn')].inner.type_alias.type.borrowed_ref" -//@ is "$.index[*][?(@.name=='RefFn')].inner.type_alias.type.borrowed_ref.mutable" 'false' +//@ is "$.index[*][?(@.name=='RefFn')].inner.type_alias.type.borrowed_ref.is_mutable" 'false' //@ is "$.index[*][?(@.name=='RefFn')].inner.type_alias.type.borrowed_ref.lifetime" "\"'a\"" //@ has "$.index[*][?(@.name=='RefFn')].inner.type_alias.type.borrowed_ref.type.dyn_trait" //@ is "$.index[*][?(@.name=='RefFn')].inner.type_alias.type.borrowed_ref.type.dyn_trait.lifetime" null diff --git a/tests/rustdoc-json/type/extern.rs b/tests/rustdoc-json/type/extern.rs index fda5d5ab970e0..97e1c3760ee5f 100644 --- a/tests/rustdoc-json/type/extern.rs +++ b/tests/rustdoc-json/type/extern.rs @@ -6,4 +6,4 @@ extern "C" { } //@ is "$.index[*][?(@.docs=='No inner information')].name" '"Foo"' -//@ is "$.index[*][?(@.docs=='No inner information')].inner" \"foreign_type\" +//@ is "$.index[*][?(@.docs=='No inner information')].inner" \"extern_type\" diff --git a/tests/rustdoc-json/type/fn_lifetime.rs b/tests/rustdoc-json/type/fn_lifetime.rs index 2893b37319ffb..7fa12dad54e9b 100644 --- a/tests/rustdoc-json/type/fn_lifetime.rs +++ b/tests/rustdoc-json/type/fn_lifetime.rs @@ -7,9 +7,9 @@ //@ count "$.index[*][?(@.name=='GenericFn')].inner.type_alias.generics.params[*].kind.lifetime.outlives[*]" 0 //@ count "$.index[*][?(@.name=='GenericFn')].inner.type_alias.generics.where_predicates[*]" 0 //@ count "$.index[*][?(@.name=='GenericFn')].inner.type_alias.type.function_pointer.generic_params[*]" 0 -//@ count "$.index[*][?(@.name=='GenericFn')].inner.type_alias.type.function_pointer.decl.inputs[*]" 1 -//@ is "$.index[*][?(@.name=='GenericFn')].inner.type_alias.type.function_pointer.decl.inputs[*][1].borrowed_ref.lifetime" \"\'a\" -//@ is "$.index[*][?(@.name=='GenericFn')].inner.type_alias.type.function_pointer.decl.output.borrowed_ref.lifetime" \"\'a\" +//@ count "$.index[*][?(@.name=='GenericFn')].inner.type_alias.type.function_pointer.sig.inputs[*]" 1 +//@ is "$.index[*][?(@.name=='GenericFn')].inner.type_alias.type.function_pointer.sig.inputs[*][1].borrowed_ref.lifetime" \"\'a\" +//@ is "$.index[*][?(@.name=='GenericFn')].inner.type_alias.type.function_pointer.sig.output.borrowed_ref.lifetime" \"\'a\" pub type GenericFn<'a> = fn(&'a i32) -> &'a i32; @@ -20,7 +20,7 @@ pub type GenericFn<'a> = fn(&'a i32) -> &'a i32; //@ is "$.index[*][?(@.name=='ForAll')].inner.type_alias.type.function_pointer.generic_params[*].name" \"\'a\" //@ has "$.index[*][?(@.name=='ForAll')].inner.type_alias.type.function_pointer.generic_params[*].kind.lifetime" //@ count "$.index[*][?(@.name=='ForAll')].inner.type_alias.type.function_pointer.generic_params[*].kind.lifetime.outlives[*]" 0 -//@ count "$.index[*][?(@.name=='ForAll')].inner.type_alias.type.function_pointer.decl.inputs[*]" 1 -//@ is "$.index[*][?(@.name=='ForAll')].inner.type_alias.type.function_pointer.decl.inputs[*][1].borrowed_ref.lifetime" \"\'a\" -//@ is "$.index[*][?(@.name=='ForAll')].inner.type_alias.type.function_pointer.decl.output.borrowed_ref.lifetime" \"\'a\" +//@ count "$.index[*][?(@.name=='ForAll')].inner.type_alias.type.function_pointer.sig.inputs[*]" 1 +//@ is "$.index[*][?(@.name=='ForAll')].inner.type_alias.type.function_pointer.sig.inputs[*][1].borrowed_ref.lifetime" \"\'a\" +//@ is "$.index[*][?(@.name=='ForAll')].inner.type_alias.type.function_pointer.sig.output.borrowed_ref.lifetime" \"\'a\" pub type ForAll = for<'a> fn(&'a i32) -> &'a i32; diff --git a/tests/rustdoc-json/type/generic_default.rs b/tests/rustdoc-json/type/generic_default.rs index 306376354cef2..c1a05805014a9 100644 --- a/tests/rustdoc-json/type/generic_default.rs +++ b/tests/rustdoc-json/type/generic_default.rs @@ -25,7 +25,7 @@ pub struct MyError {} //@ has "$.index[*][?(@.name=='MyResult')].inner.type_alias.type.resolved_path" //@ is "$.index[*][?(@.name=='MyResult')].inner.type_alias.type.resolved_path.id" $result //@ is "$.index[*][?(@.name=='MyResult')].inner.type_alias.type.resolved_path.name" \"Result\" -//@ is "$.index[*][?(@.name=='MyResult')].inner.type_alias.type.resolved_path.args.angle_bracketed.bindings" [] +//@ is "$.index[*][?(@.name=='MyResult')].inner.type_alias.type.resolved_path.args.angle_bracketed.constraints" [] //@ has "$.index[*][?(@.name=='MyResult')].inner.type_alias.type.resolved_path.args.angle_bracketed.args[0].type.generic" //@ has "$.index[*][?(@.name=='MyResult')].inner.type_alias.type.resolved_path.args.angle_bracketed.args[1].type.generic" //@ is "$.index[*][?(@.name=='MyResult')].inner.type_alias.type.resolved_path.args.angle_bracketed.args[0].type.generic" \"T\" diff --git a/tests/rustdoc-json/type/hrtb.rs b/tests/rustdoc-json/type/hrtb.rs index a28b2fddf469b..825720e9198b6 100644 --- a/tests/rustdoc-json/type/hrtb.rs +++ b/tests/rustdoc-json/type/hrtb.rs @@ -12,10 +12,10 @@ where //@ is "$.index[*][?(@.name=='dynfn')].inner.function.generics" '{"params": [], "where_predicates": []}' //@ is "$.index[*][?(@.name=='dynfn')].inner.function.generics" '{"params": [], "where_predicates": []}' -//@ is "$.index[*][?(@.name=='dynfn')].inner.function.decl.inputs[0][1].borrowed_ref.type.dyn_trait.lifetime" null -//@ count "$.index[*][?(@.name=='dynfn')].inner.function.decl.inputs[0][1].borrowed_ref.type.dyn_trait.traits[*]" 1 -//@ is "$.index[*][?(@.name=='dynfn')].inner.function.decl.inputs[0][1].borrowed_ref.type.dyn_trait.traits[0].generic_params" '[{"kind": {"lifetime": {"outlives": []}},"name": "'\''a"},{"kind": {"lifetime": {"outlives": []}},"name": "'\''b"}]' -//@ is "$.index[*][?(@.name=='dynfn')].inner.function.decl.inputs[0][1].borrowed_ref.type.dyn_trait.traits[0].trait.name" '"Fn"' +//@ is "$.index[*][?(@.name=='dynfn')].inner.function.sig.inputs[0][1].borrowed_ref.type.dyn_trait.lifetime" null +//@ count "$.index[*][?(@.name=='dynfn')].inner.function.sig.inputs[0][1].borrowed_ref.type.dyn_trait.traits[*]" 1 +//@ is "$.index[*][?(@.name=='dynfn')].inner.function.sig.inputs[0][1].borrowed_ref.type.dyn_trait.traits[0].generic_params" '[{"kind": {"lifetime": {"outlives": []}},"name": "'\''a"},{"kind": {"lifetime": {"outlives": []}},"name": "'\''b"}]' +//@ is "$.index[*][?(@.name=='dynfn')].inner.function.sig.inputs[0][1].borrowed_ref.type.dyn_trait.traits[0].trait.name" '"Fn"' pub fn dynfn(f: &dyn for<'a, 'b> Fn(&'a i32, &'b i32)) { let zero = 0; f(&zero, &zero); diff --git a/tests/rustdoc-json/type/inherent_associated_type.rs b/tests/rustdoc-json/type/inherent_associated_type.rs index 386c7c80d7fa9..b8ce11fc6e196 100644 --- a/tests/rustdoc-json/type/inherent_associated_type.rs +++ b/tests/rustdoc-json/type/inherent_associated_type.rs @@ -10,9 +10,9 @@ pub struct Owner; pub fn create() -> Owner::Metadata { OwnerMetadata } -//@ is '$.index[*][?(@.name=="create")].inner.function.decl.output.qualified_path.name' '"Metadata"' -//@ is '$.index[*][?(@.name=="create")].inner.function.decl.output.qualified_path.trait' null -//@ is '$.index[*][?(@.name=="create")].inner.function.decl.output.qualified_path.self_type.resolved_path.id' $Owner +//@ is '$.index[*][?(@.name=="create")].inner.function.sig.output.qualified_path.name' '"Metadata"' +//@ is '$.index[*][?(@.name=="create")].inner.function.sig.output.qualified_path.trait' null +//@ is '$.index[*][?(@.name=="create")].inner.function.sig.output.qualified_path.self_type.resolved_path.id' $Owner /// impl impl Owner { @@ -21,4 +21,4 @@ impl Owner { } //@ set iat = '$.index[*][?(@.docs=="iat")].id' //@ is '$.index[*][?(@.docs=="impl")].inner.impl.items[*]' $iat -//@ is '$.index[*][?(@.docs=="iat")].inner.assoc_type.default.resolved_path.id' $OwnerMetadata +//@ is '$.index[*][?(@.docs=="iat")].inner.assoc_type.type.resolved_path.id' $OwnerMetadata diff --git a/tests/rustdoc-json/type/inherent_associated_type_bound.rs b/tests/rustdoc-json/type/inherent_associated_type_bound.rs index 45fe19bf4673d..d0a88b1970fe3 100644 --- a/tests/rustdoc-json/type/inherent_associated_type_bound.rs +++ b/tests/rustdoc-json/type/inherent_associated_type_bound.rs @@ -5,14 +5,14 @@ //@ set Carrier = '$.index[*][?(@.name=="Carrier")].id' pub struct Carrier<'a>(&'a ()); -//@ count "$.index[*][?(@.name=='user')].inner.function.decl.inputs[*]" 1 -//@ is "$.index[*][?(@.name=='user')].inner.function.decl.inputs[0][0]" '"_"' -//@ is '$.index[*][?(@.name=="user")].inner.function.decl.inputs[0][1].function_pointer.generic_params[*].name' \""'b"\" -//@ is '$.index[*][?(@.name=="user")].inner.function.decl.inputs[0][1].function_pointer.decl.inputs[0][1].qualified_path.self_type.resolved_path.id' $Carrier -//@ is '$.index[*][?(@.name=="user")].inner.function.decl.inputs[0][1].function_pointer.decl.inputs[0][1].qualified_path.self_type.resolved_path.args.angle_bracketed.args[0].lifetime' \""'b"\" -//@ is '$.index[*][?(@.name=="user")].inner.function.decl.inputs[0][1].function_pointer.decl.inputs[0][1].qualified_path.name' '"Focus"' -//@ is '$.index[*][?(@.name=="user")].inner.function.decl.inputs[0][1].function_pointer.decl.inputs[0][1].qualified_path.trait' null -//@ is '$.index[*][?(@.name=="user")].inner.function.decl.inputs[0][1].function_pointer.decl.inputs[0][1].qualified_path.args.angle_bracketed.args[0].type.primitive' '"i32"' +//@ count "$.index[*][?(@.name=='user')].inner.function.sig.inputs[*]" 1 +//@ is "$.index[*][?(@.name=='user')].inner.function.sig.inputs[0][0]" '"_"' +//@ is '$.index[*][?(@.name=="user")].inner.function.sig.inputs[0][1].function_pointer.generic_params[*].name' \""'b"\" +//@ is '$.index[*][?(@.name=="user")].inner.function.sig.inputs[0][1].function_pointer.sig.inputs[0][1].qualified_path.self_type.resolved_path.id' $Carrier +//@ is '$.index[*][?(@.name=="user")].inner.function.sig.inputs[0][1].function_pointer.sig.inputs[0][1].qualified_path.self_type.resolved_path.args.angle_bracketed.args[0].lifetime' \""'b"\" +//@ is '$.index[*][?(@.name=="user")].inner.function.sig.inputs[0][1].function_pointer.sig.inputs[0][1].qualified_path.name' '"Focus"' +//@ is '$.index[*][?(@.name=="user")].inner.function.sig.inputs[0][1].function_pointer.sig.inputs[0][1].qualified_path.trait' null +//@ is '$.index[*][?(@.name=="user")].inner.function.sig.inputs[0][1].function_pointer.sig.inputs[0][1].qualified_path.args.angle_bracketed.args[0].type.primitive' '"i32"' pub fn user(_: for<'b> fn(Carrier<'b>::Focus)) {} impl<'a> Carrier<'a> { diff --git a/tests/rustdoc-json/type/inherent_associated_type_projections.rs b/tests/rustdoc-json/type/inherent_associated_type_projections.rs index 9b827a9841951..e73e86d5817fe 100644 --- a/tests/rustdoc-json/type/inherent_associated_type_projections.rs +++ b/tests/rustdoc-json/type/inherent_associated_type_projections.rs @@ -5,12 +5,12 @@ //@ set Parametrized = '$.index[*][?(@.name=="Parametrized")].id' pub struct Parametrized(T); -//@ count "$.index[*][?(@.name=='test')].inner.function.decl.inputs[*]" 1 -//@ is "$.index[*][?(@.name=='test')].inner.function.decl.inputs[0][0]" '"_"' -//@ is '$.index[*][?(@.name=="test")].inner.function.decl.inputs[0][1].qualified_path.self_type.resolved_path.id' $Parametrized -//@ is '$.index[*][?(@.name=="test")].inner.function.decl.inputs[0][1].qualified_path.self_type.resolved_path.args.angle_bracketed.args[0].type.primitive' \"i32\" -//@ is '$.index[*][?(@.name=="test")].inner.function.decl.inputs[0][1].qualified_path.name' '"Proj"' -//@ is '$.index[*][?(@.name=="test")].inner.function.decl.inputs[0][1].qualified_path.trait' null +//@ count "$.index[*][?(@.name=='test')].inner.function.sig.inputs[*]" 1 +//@ is "$.index[*][?(@.name=='test')].inner.function.sig.inputs[0][0]" '"_"' +//@ is '$.index[*][?(@.name=="test")].inner.function.sig.inputs[0][1].qualified_path.self_type.resolved_path.id' $Parametrized +//@ is '$.index[*][?(@.name=="test")].inner.function.sig.inputs[0][1].qualified_path.self_type.resolved_path.args.angle_bracketed.args[0].type.primitive' \"i32\" +//@ is '$.index[*][?(@.name=="test")].inner.function.sig.inputs[0][1].qualified_path.name' '"Proj"' +//@ is '$.index[*][?(@.name=="test")].inner.function.sig.inputs[0][1].qualified_path.trait' null pub fn test(_: Parametrized::Proj) {} /// param_bool diff --git a/tests/rustdoc-json/type_alias.rs b/tests/rustdoc-json/type_alias.rs index ecf35c5987ab5..2f2b4c42d441d 100644 --- a/tests/rustdoc-json/type_alias.rs +++ b/tests/rustdoc-json/type_alias.rs @@ -4,12 +4,12 @@ //@ is "$.index[*][?(@.name=='IntVec')].span.filename" $FILE pub type IntVec = Vec; -//@ is "$.index[*][?(@.name=='f')].inner.function.decl.output.resolved_path.id" $IntVec +//@ is "$.index[*][?(@.name=='f')].inner.function.sig.output.resolved_path.id" $IntVec pub fn f() -> IntVec { vec![0; 32] } -//@ !is "$.index[*][?(@.name=='g')].inner.function.decl.output.resolved_path.id" $IntVec +//@ !is "$.index[*][?(@.name=='g')].inner.function.sig.output.resolved_path.id" $IntVec pub fn g() -> Vec { vec![0; 32] } diff --git a/tests/rustdoc-json/unions/union.rs b/tests/rustdoc-json/unions/union.rs index 4a97b5d4fb8f0..7f135a72dec63 100644 --- a/tests/rustdoc-json/unions/union.rs +++ b/tests/rustdoc-json/unions/union.rs @@ -7,8 +7,8 @@ pub union Union { float: f32, } -//@ has "$.index[*][?(@.name=='make_int_union')].inner.function.decl.output.resolved_path" -//@ is "$.index[*][?(@.name=='make_int_union')].inner.function.decl.output.resolved_path.id" $Union +//@ has "$.index[*][?(@.name=='make_int_union')].inner.function.sig.output.resolved_path" +//@ is "$.index[*][?(@.name=='make_int_union')].inner.function.sig.output.resolved_path.id" $Union pub fn make_int_union(int: i32) -> Union { Union { int } } From 0064bd1b994b22093c6e7960818351ae65e0d183 Mon Sep 17 00:00:00 2001 From: binarycat Date: Fri, 30 Aug 2024 16:01:22 -0400 Subject: [PATCH 0360/2194] add extra linebreaks so rustdoc can identify the first sentence there should probably be a lint against this in rustdoc, it causes too many lines to be shown in the short documentation overviews expecially noticable for the slice primative type: https://doc.rust-lang.org/std/index.html --- library/core/src/hint.rs | 1 + library/core/src/primitive_docs.rs | 5 +++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/library/core/src/hint.rs b/library/core/src/hint.rs index 6ca5e53df3b01..a69f0afdb0a59 100644 --- a/library/core/src/hint.rs +++ b/library/core/src/hint.rs @@ -1,6 +1,7 @@ #![stable(feature = "core_hint", since = "1.27.0")] //! Hints to compiler that affects how code should be emitted or optimized. +//! //! Hints may be compile time or runtime. use crate::{intrinsics, ub_checks}; diff --git a/library/core/src/primitive_docs.rs b/library/core/src/primitive_docs.rs index fe6ed7e0cf368..ce6e6aec7ff6b 100644 --- a/library/core/src/primitive_docs.rs +++ b/library/core/src/primitive_docs.rs @@ -832,8 +832,9 @@ mod prim_array {} #[doc(alias = "[")] #[doc(alias = "]")] #[doc(alias = "[]")] -/// A dynamically-sized view into a contiguous sequence, `[T]`. Contiguous here -/// means that elements are laid out so that every element is the same +/// A dynamically-sized view into a contiguous sequence, `[T]`. +/// +/// Contiguous here means that elements are laid out so that every element is the same /// distance from its neighbors. /// /// *[See also the `std::slice` module](crate::slice).* From 5a8563262342d89da0899b2fda4436cb6f367660 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sun, 1 Sep 2024 23:43:27 +0200 Subject: [PATCH 0361/2194] Correctly handle code examples buttons position --- src/librustdoc/html/static/css/rustdoc.css | 6 +++++- tests/rustdoc-gui/code-example-buttons.goml | 21 +++++++++++++++++++++ 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css index 874994457675f..9d3a8c6bc14ae 100644 --- a/src/librustdoc/html/static/css/rustdoc.css +++ b/src/librustdoc/html/static/css/rustdoc.css @@ -34,6 +34,7 @@ xmlns="http://www.w3.org/2000/svg" fill="black" height="18px">\ '); --button-left-margin: 4px; --button-border-radius: 2px; + --pre-line-height: 1.5rem; } /* See FiraSans-LICENSE.txt for the Fira Sans license. */ @@ -365,7 +366,7 @@ code, pre, .code-header { } pre { padding: 14px; - line-height: 1.5; /* https://github.com/rust-lang/rust/issues/105906 */ + line-height: var(--pre-line-height); /* https://github.com/rust-lang/rust/issues/105906 */ } pre.item-decl { overflow-x: auto; @@ -2278,6 +2279,9 @@ in src-script.js and main.js /* Dirty hacky to force it to remain on the same line as the line numbers. */ width: 10px; } + .example-wrap.scraped-example .button-holder { + top: calc(var(--pre-line-height) + 4px); + } } /* Should have min-width: (N + 1)px where N is the mobile breakpoint above. */ diff --git a/tests/rustdoc-gui/code-example-buttons.goml b/tests/rustdoc-gui/code-example-buttons.goml index 4f037ec79f5e2..a6c8a862d1ab4 100644 --- a/tests/rustdoc-gui/code-example-buttons.goml +++ b/tests/rustdoc-gui/code-example-buttons.goml @@ -94,3 +94,24 @@ call-function: ("check-buttons",{ "filter": "invert(0.5)", "filter_hover": "invert(0.35)", }) + +define-function: ( + "check-buttons-position", + [pre_selector], + block { + move-cursor-to: |pre_selector| + " .rust:not(.item-decl)" + store-position: (|pre_selector| + " .rust:not(.item-decl)", {"x": x, "y": y}) + assert-position: (|pre_selector| + " .rust:not(.item-decl) + .button-holder", { + "y": |y| + 4, + }) + } +) + +call-function: ("check-buttons-position", {"pre_selector": ".example-wrap"}) + +go-to: "file://" + |DOC_PATH| + "/scrape_examples/fn.test_many.html" +// We should work as well for scraped examples. +call-function: ("check-buttons-position", {"pre_selector": ".example-wrap.scraped-example"}) +// And also when the scraped example "title" goes above. +set-window-size: (600, 600) +call-function: ("check-buttons-position", {"pre_selector": ".example-wrap.scraped-example"}) From 01d8235ae1f388f896bf5a504077cd5101ae8fca Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sun, 1 Sep 2024 23:59:46 +0200 Subject: [PATCH 0362/2194] Fix scraped examples background gradient --- src/librustdoc/html/static/css/rustdoc.css | 12 +++++++++++- tests/rustdoc-gui/scrape-examples-layout.goml | 11 ++++++++++- 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css index 9d3a8c6bc14ae..6b31c596c4097 100644 --- a/src/librustdoc/html/static/css/rustdoc.css +++ b/src/librustdoc/html/static/css/rustdoc.css @@ -2282,8 +2282,13 @@ in src-script.js and main.js .example-wrap.scraped-example .button-holder { top: calc(var(--pre-line-height) + 4px); } + .scraped-example:not(.expanded)::before { + /* The gradient effect needs to be moved under the title */ + top: var(--pre-line-height); + } } + /* Should have min-width: (N + 1)px where N is the mobile breakpoint above. */ @media (min-width: 701px) { /* Places file-link for a scraped example on top of the example to save space. @@ -2305,6 +2310,12 @@ in src-script.js and main.js .item-table > li > div { overflow-wrap: anywhere; } + + /* Starting this width, the "title" of scraped example will be in the code block so we can + put the background gradient at the top. */ + .scraped-example:not(.expanded)::before { + top: 0; + } } @media print { @@ -2395,7 +2406,6 @@ in src-script.js and main.js z-index: 1; } .scraped-example:not(.expanded)::before { - top: 0; background: linear-gradient(to bottom, var(--scrape-example-code-wrapper-background-start), var(--scrape-example-code-wrapper-background-end)); diff --git a/tests/rustdoc-gui/scrape-examples-layout.goml b/tests/rustdoc-gui/scrape-examples-layout.goml index b0d22cba0059b..063e103458d37 100644 --- a/tests/rustdoc-gui/scrape-examples-layout.goml +++ b/tests/rustdoc-gui/scrape-examples-layout.goml @@ -56,10 +56,19 @@ store-value: (offset_y, 4) assert-position: (".scraped-example", {"y": 226}) assert-position: (".scraped-example .prev", {"y": 226 + |offset_y|}) +// Gradient background should be at the top of the code block. +assert-css: (".scraped-example::before", {"top": "0px"}) +assert-css: (".scraped-example::after", {"bottom": "0px"}) + // Then with mobile set-window-size: (600, 600) +store-size: (".example-wrap.scraped-example .scraped-example-title", {"height": title_height}) assert-position: (".scraped-example", {"y": 284}) -assert-position: (".scraped-example .prev", {"y": 284 + |offset_y|}) +assert-position: (".scraped-example .prev", {"y": 284 + |offset_y| + |title_height|}) + +// Gradient background should be at the top of the code block, which is now below the "title". +assert-css: (".scraped-example::before", {"top": |title_height| + "px"}) +assert-css: (".scraped-example::after", {"bottom": "0px"}) define-function: ( "check_title_and_code_position", From 92b8b5676682fe8cc50b4145a6bd25075454d283 Mon Sep 17 00:00:00 2001 From: Ivar Scholten Date: Sat, 31 Aug 2024 00:56:16 +0200 Subject: [PATCH 0363/2194] fix: use Result type aliases in "Wrap return type in Result" assist This commit makes the "Wrap return type in Result" assist prefer type aliases of standard library type when the are in scope, use at least one generic parameter, and have the name "Result". The last restriction was made in an attempt to avoid false assumptions about which type the user is referring to, but that might be overly strict. We could also do something like this, in order of priority: * Use the alias named "Result". * Use any alias if only a single one is in scope, otherwise: * Use the standard library type. This is easy to add if others feel differently that is appropriate, just let me know. --- .../rust-analyzer/crates/hir/src/semantics.rs | 17 +- .../handlers/wrap_return_type_in_result.rs | 293 +++++++++++++++++- 2 files changed, 294 insertions(+), 16 deletions(-) diff --git a/src/tools/rust-analyzer/crates/hir/src/semantics.rs b/src/tools/rust-analyzer/crates/hir/src/semantics.rs index 763f53031e4c5..c78b59826c955 100644 --- a/src/tools/rust-analyzer/crates/hir/src/semantics.rs +++ b/src/tools/rust-analyzer/crates/hir/src/semantics.rs @@ -14,6 +14,7 @@ use hir_def::{ hir::Expr, lower::LowerCtx, nameres::MacroSubNs, + path::ModPath, resolver::{self, HasResolver, Resolver, TypeNs}, type_ref::Mutability, AsMacroCall, DefWithBodyId, FunctionId, MacroId, TraitId, VariantId, @@ -46,9 +47,9 @@ use crate::{ source_analyzer::{resolve_hir_path, SourceAnalyzer}, Access, Adjust, Adjustment, Adt, AutoBorrow, BindingMode, BuiltinAttr, Callable, Const, ConstParam, Crate, DeriveHelper, Enum, Field, Function, HasSource, HirFileId, Impl, InFile, - Label, LifetimeParam, Local, Macro, Module, ModuleDef, Name, OverloadedDeref, Path, ScopeDef, - Static, Struct, ToolModule, Trait, TraitAlias, TupleField, Type, TypeAlias, TypeParam, Union, - Variant, VariantDef, + ItemInNs, Label, LifetimeParam, Local, Macro, Module, ModuleDef, Name, OverloadedDeref, Path, + ScopeDef, Static, Struct, ToolModule, Trait, TraitAlias, TupleField, Type, TypeAlias, + TypeParam, Union, Variant, VariantDef, }; const CONTINUE_NO_BREAKS: ControlFlow = ControlFlow::Continue(()); @@ -1384,6 +1385,16 @@ impl<'db> SemanticsImpl<'db> { self.analyze(path.syntax())?.resolve_path(self.db, path) } + pub fn resolve_mod_path( + &self, + scope: &SyntaxNode, + path: &ModPath, + ) -> Option> { + let analyze = self.analyze(scope)?; + let items = analyze.resolver.resolve_module_path_in_items(self.db.upcast(), path); + Some(items.iter_items().map(|(item, _)| item.into())) + } + fn resolve_variant(&self, record_lit: ast::RecordExpr) -> Option { self.analyze(record_lit.syntax())?.resolve_variant(self.db, record_lit) } diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/wrap_return_type_in_result.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/wrap_return_type_in_result.rs index b68ed00f77210..8f0e9b4fe09d5 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/wrap_return_type_in_result.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/wrap_return_type_in_result.rs @@ -1,12 +1,14 @@ use std::iter; +use hir::HasSource; use ide_db::{ famous_defs::FamousDefs, syntax_helpers::node_ext::{for_each_tail_expr, walk_expr}, }; +use itertools::Itertools; use syntax::{ - ast::{self, make, Expr}, - match_ast, ted, AstNode, + ast::{self, make, Expr, HasGenericParams}, + match_ast, ted, AstNode, ToSmolStr, }; use crate::{AssistContext, AssistId, AssistKind, Assists}; @@ -39,25 +41,22 @@ pub(crate) fn wrap_return_type_in_result(acc: &mut Assists, ctx: &AssistContext< }; let type_ref = &ret_type.ty()?; - let ty = ctx.sema.resolve_type(type_ref)?.as_adt(); - let result_enum = + let core_result = FamousDefs(&ctx.sema, ctx.sema.scope(type_ref.syntax())?.krate()).core_result_Result()?; - if matches!(ty, Some(hir::Adt::Enum(ret_type)) if ret_type == result_enum) { + let ty = ctx.sema.resolve_type(type_ref)?.as_adt(); + if matches!(ty, Some(hir::Adt::Enum(ret_type)) if ret_type == core_result) { + // The return type is already wrapped in a Result cov_mark::hit!(wrap_return_type_in_result_simple_return_type_already_result); return None; } - let new_result_ty = - make::ext::ty_result(type_ref.clone(), make::ty_placeholder()).clone_for_update(); - let generic_args = new_result_ty.syntax().descendants().find_map(ast::GenericArgList::cast)?; - let last_genarg = generic_args.generic_args().last()?; - acc.add( AssistId("wrap_return_type_in_result", AssistKind::RefactorRewrite), "Wrap return type in Result", type_ref.syntax().text_range(), |edit| { + let new_result_ty = result_type(ctx, &core_result, type_ref).clone_for_update(); let body = edit.make_mut(ast::Expr::BlockExpr(body)); let mut exprs_to_wrap = Vec::new(); @@ -81,16 +80,72 @@ pub(crate) fn wrap_return_type_in_result(acc: &mut Assists, ctx: &AssistContext< } let old_result_ty = edit.make_mut(type_ref.clone()); - ted::replace(old_result_ty.syntax(), new_result_ty.syntax()); - if let Some(cap) = ctx.config.snippet_cap { - edit.add_placeholder_snippet(cap, last_genarg); + // Add a placeholder snippet at the first generic argument that doesn't equal the return type. + // This is normally the error type, but that may not be the case when we inserted a type alias. + let args = new_result_ty.syntax().descendants().find_map(ast::GenericArgList::cast); + let error_type_arg = args.and_then(|list| { + list.generic_args().find(|arg| match arg { + ast::GenericArg::TypeArg(_) => arg.syntax().text() != type_ref.syntax().text(), + ast::GenericArg::LifetimeArg(_) => false, + _ => true, + }) + }); + if let Some(error_type_arg) = error_type_arg { + if let Some(cap) = ctx.config.snippet_cap { + edit.add_placeholder_snippet(cap, error_type_arg); + } } }, ) } +fn result_type( + ctx: &AssistContext<'_>, + core_result: &hir::Enum, + ret_type: &ast::Type, +) -> ast::Type { + // Try to find a Result type alias in the current scope (shadowing the default). + let result_path = hir::ModPath::from_segments( + hir::PathKind::Plain, + iter::once(hir::Name::new_symbol_root(hir::sym::Result.clone())), + ); + let alias = ctx.sema.resolve_mod_path(ret_type.syntax(), &result_path).and_then(|def| { + def.filter_map(|def| match def.as_module_def()? { + hir::ModuleDef::TypeAlias(alias) => { + let enum_ty = alias.ty(ctx.db()).as_adt()?.as_enum()?; + (&enum_ty == core_result).then_some(alias) + } + _ => None, + }) + .find_map(|alias| { + let mut inserted_ret_type = false; + let generic_params = alias + .source(ctx.db())? + .value + .generic_param_list()? + .generic_params() + .map(|param| match param { + // Replace the very first type parameter with the functions return type. + ast::GenericParam::TypeParam(_) if !inserted_ret_type => { + inserted_ret_type = true; + ret_type.to_smolstr() + } + ast::GenericParam::LifetimeParam(_) => make::lifetime("'_").to_smolstr(), + _ => make::ty_placeholder().to_smolstr(), + }) + .join(", "); + + let name = alias.name(ctx.db()); + let name = name.as_str(); + Some(make::ty(&format!("{name}<{generic_params}>"))) + }) + }); + // If there is no applicable alias in scope use the default Result type. + alias.unwrap_or_else(|| make::ext::ty_result(ret_type.clone(), make::ty_placeholder())) +} + fn tail_cb_impl(acc: &mut Vec, e: &ast::Expr) { match e { Expr::BreakExpr(break_expr) => { @@ -998,4 +1053,216 @@ fn foo(the_field: u32) -> Result { "#, ); } + + #[test] + fn wrap_return_type_in_local_result_type() { + check_assist( + wrap_return_type_in_result, + r#" +//- minicore: result +type Result = core::result::Result; + +fn foo() -> i3$02 { + return 42i32; +} +"#, + r#" +type Result = core::result::Result; + +fn foo() -> Result { + return Ok(42i32); +} +"#, + ); + + check_assist( + wrap_return_type_in_result, + r#" +//- minicore: result +type Result2 = core::result::Result; + +fn foo() -> i3$02 { + return 42i32; +} +"#, + r#" +type Result2 = core::result::Result; + +fn foo() -> Result { + return Ok(42i32); +} +"#, + ); + } + + #[test] + fn wrap_return_type_in_imported_local_result_type() { + check_assist( + wrap_return_type_in_result, + r#" +//- minicore: result +mod some_module { + pub type Result = core::result::Result; +} + +use some_module::Result; + +fn foo() -> i3$02 { + return 42i32; +} +"#, + r#" +mod some_module { + pub type Result = core::result::Result; +} + +use some_module::Result; + +fn foo() -> Result { + return Ok(42i32); +} +"#, + ); + + check_assist( + wrap_return_type_in_result, + r#" +//- minicore: result +mod some_module { + pub type Result = core::result::Result; +} + +use some_module::*; + +fn foo() -> i3$02 { + return 42i32; +} +"#, + r#" +mod some_module { + pub type Result = core::result::Result; +} + +use some_module::*; + +fn foo() -> Result { + return Ok(42i32); +} +"#, + ); + } + + #[test] + fn wrap_return_type_in_local_result_type_from_function_body() { + check_assist( + wrap_return_type_in_result, + r#" +//- minicore: result +fn foo() -> i3$02 { + type Result = core::result::Result; + 0 +} +"#, + r#" +fn foo() -> Result { + type Result = core::result::Result; + Ok(0) +} +"#, + ); + } + + #[test] + fn wrap_return_type_in_local_result_type_already_using_alias() { + check_assist_not_applicable( + wrap_return_type_in_result, + r#" +//- minicore: result +pub type Result = core::result::Result; + +fn foo() -> Result { + return Ok(42i32); +} +"#, + ); + } + + #[test] + fn wrap_return_type_in_local_result_type_multiple_generics() { + check_assist( + wrap_return_type_in_result, + r#" +//- minicore: result +type Result = core::result::Result; + +fn foo() -> i3$02 { + 0 +} +"#, + r#" +type Result = core::result::Result; + +fn foo() -> Result { + Ok(0) +} +"#, + ); + + check_assist( + wrap_return_type_in_result, + r#" +//- minicore: result +type Result = core::result::Result, ()>; + +fn foo() -> i3$02 { + 0 +} + "#, + r#" +type Result = core::result::Result, ()>; + +fn foo() -> Result { + Ok(0) +} + "#, + ); + + check_assist( + wrap_return_type_in_result, + r#" +//- minicore: result +type Result<'a, T, E> = core::result::Result, &'a ()>; + +fn foo() -> i3$02 { + 0 +} + "#, + r#" +type Result<'a, T, E> = core::result::Result, &'a ()>; + +fn foo() -> Result<'_, i32, ${0:_}> { + Ok(0) +} + "#, + ); + + check_assist( + wrap_return_type_in_result, + r#" +//- minicore: result +type Result = core::result::Result, Bar>; + +fn foo() -> i3$02 { + 0 +} + "#, + r#" +type Result = core::result::Result, Bar>; + +fn foo() -> Result { + Ok(0) +} + "#, + ); + } } From cd28176025ef5f00ed58680ac4c346c3b0c19020 Mon Sep 17 00:00:00 2001 From: Yuri Astrakhan Date: Sun, 1 Sep 2024 20:58:14 -0400 Subject: [PATCH 0364/2194] Minor code simplification --- .../attrs/allow_attributes_without_reason.rs | 2 +- clippy_utils/src/sugg.rs | 38 ++++++++----------- 2 files changed, 17 insertions(+), 23 deletions(-) diff --git a/clippy_lints/src/attrs/allow_attributes_without_reason.rs b/clippy_lints/src/attrs/allow_attributes_without_reason.rs index 4ab97118df1d4..4c7e07478c129 100644 --- a/clippy_lints/src/attrs/allow_attributes_without_reason.rs +++ b/clippy_lints/src/attrs/allow_attributes_without_reason.rs @@ -26,7 +26,7 @@ pub(super) fn check<'cx>(cx: &LateContext<'cx>, name: Symbol, items: &[NestedMet cx, ALLOW_ATTRIBUTES_WITHOUT_REASON, attr.span, - format!("`{}` attribute without specifying a reason", name.as_str()), + format!("`{name}` attribute without specifying a reason"), |diag| { diag.help("try adding a reason at the end with `, reason = \"..\"`"); }, diff --git a/clippy_utils/src/sugg.rs b/clippy_utils/src/sugg.rs index 0f86d89c980d7..3255c51d009ca 100644 --- a/clippy_utils/src/sugg.rs +++ b/clippy_utils/src/sugg.rs @@ -180,8 +180,10 @@ impl<'a> Sugg<'a> { ) -> Self { use rustc_ast::ast::RangeLimits; + let mut snippet = |span: Span| snippet_with_context(cx, span, ctxt, default, app).0; + match expr.kind { - _ if expr.span.ctxt() != ctxt => Sugg::NonParen(snippet_with_context(cx, expr.span, ctxt, default, app).0), + _ if expr.span.ctxt() != ctxt => Sugg::NonParen(snippet(expr.span)), ast::ExprKind::AddrOf(..) | ast::ExprKind::Closure { .. } | ast::ExprKind::If(..) @@ -224,46 +226,38 @@ impl<'a> Sugg<'a> { | ast::ExprKind::While(..) | ast::ExprKind::Await(..) | ast::ExprKind::Err(_) - | ast::ExprKind::Dummy => Sugg::NonParen(snippet_with_context(cx, expr.span, ctxt, default, app).0), + | ast::ExprKind::Dummy => Sugg::NonParen(snippet(expr.span)), ast::ExprKind::Range(ref lhs, ref rhs, RangeLimits::HalfOpen) => Sugg::BinOp( AssocOp::DotDot, - lhs.as_ref().map_or("".into(), |lhs| { - snippet_with_context(cx, lhs.span, ctxt, default, app).0 - }), - rhs.as_ref().map_or("".into(), |rhs| { - snippet_with_context(cx, rhs.span, ctxt, default, app).0 - }), + lhs.as_ref().map_or("".into(), |lhs| snippet(lhs.span)), + rhs.as_ref().map_or("".into(), |rhs| snippet(rhs.span)), ), ast::ExprKind::Range(ref lhs, ref rhs, RangeLimits::Closed) => Sugg::BinOp( AssocOp::DotDotEq, - lhs.as_ref().map_or("".into(), |lhs| { - snippet_with_context(cx, lhs.span, ctxt, default, app).0 - }), - rhs.as_ref().map_or("".into(), |rhs| { - snippet_with_context(cx, rhs.span, ctxt, default, app).0 - }), + lhs.as_ref().map_or("".into(), |lhs| snippet(lhs.span)), + rhs.as_ref().map_or("".into(), |rhs| snippet(rhs.span)), ), ast::ExprKind::Assign(ref lhs, ref rhs, _) => Sugg::BinOp( AssocOp::Assign, - snippet_with_context(cx, lhs.span, ctxt, default, app).0, - snippet_with_context(cx, rhs.span, ctxt, default, app).0, + snippet(lhs.span), + snippet(rhs.span), ), ast::ExprKind::AssignOp(op, ref lhs, ref rhs) => Sugg::BinOp( astbinop2assignop(op), - snippet_with_context(cx, lhs.span, ctxt, default, app).0, - snippet_with_context(cx, rhs.span, ctxt, default, app).0, + snippet(lhs.span), + snippet(rhs.span), ), ast::ExprKind::Binary(op, ref lhs, ref rhs) => Sugg::BinOp( AssocOp::from_ast_binop(op.node), - snippet_with_context(cx, lhs.span, ctxt, default, app).0, - snippet_with_context(cx, rhs.span, ctxt, default, app).0, + snippet(lhs.span), + snippet(rhs.span), ), ast::ExprKind::Cast(ref lhs, ref ty) | //FIXME(chenyukang), remove this after type ascription is removed from AST ast::ExprKind::Type(ref lhs, ref ty) => Sugg::BinOp( AssocOp::As, - snippet_with_context(cx, lhs.span, ctxt, default, app).0, - snippet_with_context(cx, ty.span, ctxt, default, app).0, + snippet(lhs.span), + snippet(ty.span), ), } } From 2311e96ca872abf3844fc15b81c20bb3f51809a5 Mon Sep 17 00:00:00 2001 From: DropDemBits Date: Sat, 27 Jul 2024 17:09:53 -0400 Subject: [PATCH 0365/2194] wip: new syntax tree editor --- .../rust-analyzer/crates/syntax/src/lib.rs | 1 + .../crates/syntax/src/syntax_editor.rs | 333 ++++++++++++++++++ .../syntax/src/syntax_editor/edit_algo.rs | 215 +++++++++++ .../syntax/src/syntax_editor/mapping.rs | 174 +++++++++ 4 files changed, 723 insertions(+) create mode 100644 src/tools/rust-analyzer/crates/syntax/src/syntax_editor.rs create mode 100644 src/tools/rust-analyzer/crates/syntax/src/syntax_editor/edit_algo.rs create mode 100644 src/tools/rust-analyzer/crates/syntax/src/syntax_editor/mapping.rs diff --git a/src/tools/rust-analyzer/crates/syntax/src/lib.rs b/src/tools/rust-analyzer/crates/syntax/src/lib.rs index b68374848b90c..dbbb290b4f107 100644 --- a/src/tools/rust-analyzer/crates/syntax/src/lib.rs +++ b/src/tools/rust-analyzer/crates/syntax/src/lib.rs @@ -40,6 +40,7 @@ pub mod ast; #[doc(hidden)] pub mod fuzz; pub mod hacks; +pub mod syntax_editor; pub mod ted; pub mod utils; diff --git a/src/tools/rust-analyzer/crates/syntax/src/syntax_editor.rs b/src/tools/rust-analyzer/crates/syntax/src/syntax_editor.rs new file mode 100644 index 0000000000000..3ec5abcaeafe3 --- /dev/null +++ b/src/tools/rust-analyzer/crates/syntax/src/syntax_editor.rs @@ -0,0 +1,333 @@ +//! Syntax Tree editor +//! +//! Inspired by Roslyn's [`SyntaxEditor`], but is temporarily built upon mutable syntax tree editing. +//! +//! [`SyntaxEditor`]: https://github.com/dotnet/roslyn/blob/43b0b05cc4f492fd5de00f6f6717409091df8daa/src/Workspaces/Core/Portable/Editing/SyntaxEditor.cs + +use std::{ + num::NonZeroU32, + sync::atomic::{AtomicU32, Ordering}, +}; + +use rowan::TextRange; +use rustc_hash::FxHashMap; + +use crate::{SyntaxElement, SyntaxNode, SyntaxToken}; + +mod edit_algo; +mod mapping; + +pub use mapping::{SyntaxMapping, SyntaxMappingBuilder}; + +#[derive(Debug)] +pub struct SyntaxEditor { + root: SyntaxNode, + changes: Vec, + mappings: SyntaxMapping, + annotations: Vec<(SyntaxElement, SyntaxAnnotation)>, +} + +impl SyntaxEditor { + /// Creates a syntax editor to start editing from `root` + pub fn new(root: SyntaxNode) -> Self { + Self { root, changes: vec![], mappings: SyntaxMapping::new(), annotations: vec![] } + } + + pub fn add_annotation(&mut self, element: impl Element, annotation: SyntaxAnnotation) { + self.annotations.push((element.syntax_element(), annotation)) + } + + pub fn combine(&mut self, other: SyntaxEditor) { + todo!() + } + + pub fn delete(&mut self, element: impl Element) { + self.changes.push(Change::Replace(element.syntax_element(), None)); + } + + pub fn replace(&mut self, old: impl Element, new: impl Element) { + self.changes.push(Change::Replace(old.syntax_element(), Some(new.syntax_element()))); + } + + pub fn finish(self) -> SyntaxEdit { + edit_algo::apply_edits(self) + } +} + +pub struct SyntaxEdit { + root: SyntaxNode, + changed_elements: Vec, + annotations: FxHashMap>, +} + +impl SyntaxEdit { + pub fn root(&self) -> &SyntaxNode { + &self.root + } + + pub fn changed_elements(&self) -> &[SyntaxElement] { + self.changed_elements.as_slice() + } + + pub fn find_annotation(&self, annotation: SyntaxAnnotation) -> Option<&[SyntaxElement]> { + self.annotations.get(&annotation).as_ref().map(|it| it.as_slice()) + } +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] +#[repr(transparent)] +pub struct SyntaxAnnotation(NonZeroU32); + +impl SyntaxAnnotation { + /// Creates a unique syntax annotation to attach data to. + pub fn new() -> Self { + static COUNTER: AtomicU32 = AtomicU32::new(1); + + // We want the id to be unique across threads, but we don't want to + // tie it to other `SeqCst` operations. + let id = COUNTER.fetch_add(1, Ordering::AcqRel); + + Self(NonZeroU32::new(id).expect("syntax annotation id overflow")) + } +} + +/// Position describing where to insert elements +#[derive(Debug)] +pub struct Position { + repr: PositionRepr, +} + +#[derive(Debug)] +enum PositionRepr { + FirstChild(SyntaxNode), + After(SyntaxElement), +} + +impl Position { + pub fn after(elem: impl Element) -> Position { + let repr = PositionRepr::After(elem.syntax_element()); + Position { repr } + } + + pub fn before(elem: impl Element) -> Position { + let elem = elem.syntax_element(); + let repr = match elem.prev_sibling_or_token() { + Some(it) => PositionRepr::After(it), + None => PositionRepr::FirstChild(elem.parent().unwrap()), + }; + Position { repr } + } + + pub fn first_child_of(node: &(impl Into + Clone)) -> Position { + let repr = PositionRepr::FirstChild(node.clone().into()); + Position { repr } + } + + pub fn last_child_of(node: &(impl Into + Clone)) -> Position { + let node = node.clone().into(); + let repr = match node.last_child_or_token() { + Some(it) => PositionRepr::After(it), + None => PositionRepr::FirstChild(node), + }; + Position { repr } + } +} + +#[derive(Debug)] +enum Change { + /// Represents both a replace single element and a delete element operation. + Replace(SyntaxElement, Option), +} + +impl Change { + fn target_range(&self) -> TextRange { + match self { + Change::Replace(target, _) => target.text_range(), + } + } + + fn target_parent(&self) -> SyntaxNode { + match self { + Change::Replace(target, _) => target.parent().unwrap(), + } + } + + fn change_kind(&self) -> ChangeKind { + match self { + Change::Replace(_, _) => ChangeKind::Replace, + } + } +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] +enum ChangeKind { + Insert, + // TODO: deal with replace spans + Replace, +} + +/// Utility trait to allow calling syntax editor functions with references or owned +/// nodes. Do not use outside of this module. +pub trait Element { + fn syntax_element(self) -> SyntaxElement; +} + +impl Element for &'_ E { + fn syntax_element(self) -> SyntaxElement { + self.clone().syntax_element() + } +} + +impl Element for SyntaxElement { + fn syntax_element(self) -> SyntaxElement { + self + } +} + +impl Element for SyntaxNode { + fn syntax_element(self) -> SyntaxElement { + self.into() + } +} + +impl Element for SyntaxToken { + fn syntax_element(self) -> SyntaxElement { + self.into() + } +} + +#[cfg(test)] +mod tests { + use expect_test::expect; + use itertools::Itertools; + + use crate::{ + ast::{self, make, HasName}, + AstNode, + }; + + use super::*; + + fn make_ident_pat( + editor: Option<&mut SyntaxEditor>, + ref_: bool, + mut_: bool, + name: ast::Name, + ) -> ast::IdentPat { + let ast = make::ident_pat(ref_, mut_, name.clone()).clone_for_update(); + + if let Some(editor) = editor { + let mut mapping = SyntaxMappingBuilder::new(ast.syntax().clone()); + mapping.map_node(name.syntax().clone(), ast.name().unwrap().syntax().clone()); + mapping.finish(editor); + } + + ast + } + + fn make_let_stmt( + editor: Option<&mut SyntaxEditor>, + pattern: ast::Pat, + ty: Option, + initializer: Option, + ) -> ast::LetStmt { + let ast = + make::let_stmt(pattern.clone(), ty.clone(), initializer.clone()).clone_for_update(); + + if let Some(editor) = editor { + let mut mapping = SyntaxMappingBuilder::new(ast.syntax().clone()); + mapping.map_node(pattern.syntax().clone(), ast.pat().unwrap().syntax().clone()); + if let Some(input) = ty { + mapping.map_node(input.syntax().clone(), ast.ty().unwrap().syntax().clone()); + } + if let Some(input) = initializer { + mapping + .map_node(input.syntax().clone(), ast.initializer().unwrap().syntax().clone()); + } + mapping.finish(editor); + } + + ast + } + + fn make_block_expr( + editor: Option<&mut SyntaxEditor>, + stmts: impl IntoIterator, + tail_expr: Option, + ) -> ast::BlockExpr { + let stmts = stmts.into_iter().collect_vec(); + let input = stmts.iter().map(|it| it.syntax().clone()).collect_vec(); + + let ast = make::block_expr(stmts, tail_expr.clone()).clone_for_update(); + + if let Some((editor, stmt_list)) = editor.zip(ast.stmt_list()) { + let mut mapping = SyntaxMappingBuilder::new(stmt_list.syntax().clone()); + + mapping.map_children( + input.into_iter(), + stmt_list.statements().map(|it| it.syntax().clone()), + ); + + if let Some((input, output)) = tail_expr.zip(stmt_list.tail_expr()) { + mapping.map_node(input.syntax().clone(), output.syntax().clone()); + } + + mapping.finish(editor); + } + + ast + } + + #[test] + fn it() { + let root = make::match_arm( + [make::wildcard_pat().into()], + None, + make::expr_tuple([ + make::expr_bin_op( + make::expr_literal("2").into(), + ast::BinaryOp::ArithOp(ast::ArithOp::Add), + make::expr_literal("2").into(), + ), + make::expr_literal("true").into(), + ]), + ); + + let to_wrap = root.syntax().descendants().find_map(ast::TupleExpr::cast).unwrap(); + let to_replace = root.syntax().descendants().find_map(ast::BinExpr::cast).unwrap(); + + let mut editor = SyntaxEditor::new(root.syntax().clone()); + + let name = make::name("var_name"); + let name_ref = make::name_ref("var_name").clone_for_update(); + + let placeholder_snippet = SyntaxAnnotation::new(); + editor.add_annotation(name.syntax(), placeholder_snippet); + editor.add_annotation(name_ref.syntax(), placeholder_snippet); + + let make_ident_pat = make_ident_pat(Some(&mut editor), false, false, name); + let make_let_stmt = make_let_stmt( + Some(&mut editor), + make_ident_pat.into(), + None, + Some(to_replace.clone().into()), + ); + let new_block = make_block_expr( + Some(&mut editor), + [make_let_stmt.into()], + Some(to_wrap.clone().into()), + ); + + // should die: + editor.replace(to_replace.syntax(), name_ref.syntax()); + editor.replace(to_wrap.syntax(), new_block.syntax()); + // editor.replace(to_replace.syntax(), name_ref.syntax()); + + // dbg!(&editor.mappings); + let edit = editor.finish(); + + let expect = expect![]; + expect.assert_eq(&edit.root.to_string()); + assert_eq!(edit.find_annotation(placeholder_snippet).map(|it| it.len()), Some(2)); + } +} diff --git a/src/tools/rust-analyzer/crates/syntax/src/syntax_editor/edit_algo.rs b/src/tools/rust-analyzer/crates/syntax/src/syntax_editor/edit_algo.rs new file mode 100644 index 0000000000000..f8354c5eb67cd --- /dev/null +++ b/src/tools/rust-analyzer/crates/syntax/src/syntax_editor/edit_algo.rs @@ -0,0 +1,215 @@ +use std::{collections::VecDeque, ops::RangeInclusive}; + +use rowan::TextRange; + +use crate::{ + syntax_editor::{Change, ChangeKind}, + ted, SyntaxElement, SyntaxNode, SyntaxNodePtr, +}; + +use super::{SyntaxEdit, SyntaxEditor}; + +pub(super) fn apply_edits(editor: SyntaxEditor) -> SyntaxEdit { + // Algorithm overview: + // + // - Sort changes by (range, type) + // - Ensures that parent edits are before child edits + // - Ensures that inserts will be guaranteed to be inserted at the right range + // - Validate changes + // - Checking for invalid changes is easy since the changes will be sorted by range + // - Fixup change targets + // - standalone change? map to original syntax tree + // - dependent change? + // - try to map to parent change (either independent or another dependent) + // - note: need to keep track of a parent change stack, since a change can be a parent of multiple changes + // - Apply changes + // - find changes to apply to real tree by applying nested changes first + // - changed nodes become part of the changed node set (useful for the formatter to only change those parts) + // - Propagate annotations + + let SyntaxEditor { root, mut changes, mappings, annotations } = editor; + + dbg!(("initial: ", &root)); + dbg!(&changes); + + // Sort changes by range then change kind, so that we can: + // - ensure that parent edits are ordered before child edits + // - ensure that inserts will be guaranteed to be inserted at the right range + // - easily check for disjoint replace ranges + changes.sort_by(|a, b| { + a.target_range() + .start() + .cmp(&b.target_range().start()) + .then(a.change_kind().cmp(&b.change_kind())) + }); + + let disjoint_replaces_ranges = changes.iter().zip(changes.iter().skip(1)).all(|(l, r)| { + l.change_kind() == ChangeKind::Replace + && r.change_kind() == ChangeKind::Replace + && (l.target_parent() != r.target_parent() + || l.target_range().intersect(r.target_range()).is_none()) + }); + + if stdx::never!( + !disjoint_replaces_ranges, + "some replace change ranges intersect: {:?}", + changes + ) { + return SyntaxEdit { root, annotations: Default::default(), changed_elements: vec![] }; + } + + #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] + struct DependentChange { + parent: u32, + child: u32, + } + + // Build change tree + let mut changed_ancestors: VecDeque = VecDeque::new(); + let mut dependent_changes = vec![]; + let mut independent_changes = vec![]; + + for (change_index, change) in changes.iter().enumerate() { + // Check if this change is dependent on another change (i.e. it's contained within another range) + if let Some(index) = changed_ancestors + .iter() + .rev() + .position(|ancestor| ancestor.affected_range().contains_range(change.target_range())) + { + // Pop off any ancestors that aren't applicable + changed_ancestors.drain((index + 1)..); + + let ancestor = &changed_ancestors[index]; + + dependent_changes.push(DependentChange { + parent: ancestor.change_index as u32, + child: change_index as u32, + }); + } else { + // This change is independent of any other change + + // Drain the changed ancestors since we're no longer in a set of dependent changes + changed_ancestors.drain(..); + + independent_changes.push(change_index as u32); + } + + // Add to changed ancestors, if applicable + match change { + Change::Replace(target, _) => { + changed_ancestors.push_back(ChangedAncestor::single(target, change_index)) + } + } + } + + dbg!(("before: ", &changes, &dependent_changes, &independent_changes)); + + // Map change targets to the correct syntax nodes + let tree_mutator = TreeMutator::new(&root); + + for index in independent_changes { + match &mut changes[index as usize] { + Change::Replace(target, _) => { + *target = tree_mutator.make_element_mut(target); + } + } + } + + for DependentChange { parent, child } in dependent_changes.into_iter() { + let (input_ancestor, output_ancestor) = match &changes[parent as usize] { + // insert? unreachable + Change::Replace(target, Some(new_target)) => { + (to_owning_node(target), to_owning_node(new_target)) + } + Change::Replace(_, None) => continue, // silently drop outdated change + }; + + match &mut changes[child as usize] { + Change::Replace(target, _) => { + *target = mappings.upmap_child_element(target, &input_ancestor, output_ancestor) + } + } + } + + dbg!(("after: ", &changes)); + + // Apply changes + for change in changes { + match change { + Change::Replace(target, None) => ted::remove(target), + Change::Replace(target, Some(new_target)) => ted::replace(target, new_target), + } + } + + dbg!(("modified:", tree_mutator.mutable_clone)); + + todo!("draw the rest of the owl") +} + +fn to_owning_node(element: &SyntaxElement) -> SyntaxNode { + match element { + SyntaxElement::Node(node) => node.clone(), + SyntaxElement::Token(token) => token.parent().unwrap().clone(), + } +} + +struct ChangedAncestor { + kind: ChangedAncestorKind, + change_index: usize, +} + +enum ChangedAncestorKind { + Single { node: SyntaxNode }, + Range { changed_nodes: RangeInclusive, in_parent: SyntaxNode }, +} + +impl ChangedAncestor { + fn single(element: &SyntaxElement, change_index: usize) -> Self { + let kind = match element { + SyntaxElement::Node(node) => ChangedAncestorKind::Single { node: node.clone() }, + SyntaxElement::Token(token) => { + ChangedAncestorKind::Single { node: token.parent().unwrap() } + } + }; + + Self { kind, change_index } + } + + fn affected_range(&self) -> TextRange { + match &self.kind { + ChangedAncestorKind::Single { node } => node.text_range(), + ChangedAncestorKind::Range { changed_nodes, in_parent: _ } => TextRange::new( + changed_nodes.start().text_range().start(), + changed_nodes.end().text_range().end(), + ), + } + } +} + +struct TreeMutator { + immutable: SyntaxNode, + mutable_clone: SyntaxNode, +} + +impl TreeMutator { + fn new(immutable: &SyntaxNode) -> TreeMutator { + let immutable = immutable.clone(); + let mutable_clone = immutable.clone_for_update(); + TreeMutator { immutable, mutable_clone } + } + + fn make_element_mut(&self, element: &SyntaxElement) -> SyntaxElement { + match element { + SyntaxElement::Node(node) => SyntaxElement::Node(self.make_syntax_mut(&node)), + SyntaxElement::Token(token) => { + let parent = self.make_syntax_mut(&token.parent().unwrap()); + parent.children_with_tokens().nth(token.index()).unwrap() + } + } + } + + fn make_syntax_mut(&self, node: &SyntaxNode) -> SyntaxNode { + let ptr = SyntaxNodePtr::new(node); + ptr.to_node(&self.mutable_clone) + } +} diff --git a/src/tools/rust-analyzer/crates/syntax/src/syntax_editor/mapping.rs b/src/tools/rust-analyzer/crates/syntax/src/syntax_editor/mapping.rs new file mode 100644 index 0000000000000..11c7b395b37c9 --- /dev/null +++ b/src/tools/rust-analyzer/crates/syntax/src/syntax_editor/mapping.rs @@ -0,0 +1,174 @@ +use itertools::Itertools; +use rustc_hash::FxHashMap; + +use crate::{SyntaxElement, SyntaxNode}; + +use super::SyntaxEditor; + +#[derive(Debug, Default)] +pub struct SyntaxMapping { + // important information to keep track of: + // node -> node + // token -> token (implicit in mappings) + // input parent -> output parent (for deep lookups) + + // mappings -> parents + entry_parents: Vec, + node_mappings: FxHashMap, +} + +impl SyntaxMapping { + pub fn new() -> Self { + Self::default() + } + + pub fn upmap_child_element( + &self, + child: &SyntaxElement, + input_ancestor: &SyntaxNode, + output_ancestor: SyntaxNode, + ) -> SyntaxElement { + match child { + SyntaxElement::Node(node) => { + SyntaxElement::Node(self.upmap_child(node, input_ancestor, output_ancestor)) + } + SyntaxElement::Token(token) => { + let upmap_parent = + self.upmap_child(&token.parent().unwrap(), input_ancestor, output_ancestor); + + let element = upmap_parent.children_with_tokens().nth(token.index()).unwrap(); + debug_assert!( + element.as_token().is_some_and(|it| it.kind() == token.kind()), + "token upmapping mapped to the wrong node ({token:?} -> {element:?})" + ); + + element + } + } + } + + pub fn upmap_child( + &self, + child: &SyntaxNode, + input_ancestor: &SyntaxNode, + output_ancestor: SyntaxNode, + ) -> SyntaxNode { + debug_assert!(child.ancestors().any(|ancestor| &ancestor == input_ancestor)); + + // Build a list mapping up to the first mappable ancestor + let to_first_upmap = + std::iter::successors(Some((child.index(), child.clone())), |(_, current)| { + let parent = current.parent().unwrap(); + + if &parent == input_ancestor { + return None; + } + + Some((parent.index(), parent)) + }) + .map(|(i, _)| i) + .collect::>(); + + // Progressively up-map the input ancestor until we get to the output ancestor + let to_output_ancestor = if input_ancestor != &output_ancestor { + std::iter::successors(Some((input_ancestor.index(), self.upmap_node(input_ancestor).unwrap_or_else(|| input_ancestor.clone()))), |(_, current)| { + let Some(parent) = current.parent() else { + unreachable!("no mappings exist between {current:?} (ancestor of {input_ancestor:?}) and {output_ancestor:?}") + }; + + if &parent == &output_ancestor { + return None; + } + + if let Some(next) = self.upmap_node(&parent) { + Some((parent.index(), next)) + } else { + Some((parent.index(), parent)) + } + }).map(|(i, _)| i).collect::>() + } else { + vec![] + }; + + let to_map_down = + to_output_ancestor.into_iter().rev().chain(to_first_upmap.into_iter().rev()); + + let mut target = output_ancestor; + + for index in to_map_down { + target = target + .children_with_tokens() + .nth(index) + .and_then(|it| it.into_node()) + .expect("yep"); + } + + debug_assert_eq!(child.kind(), target.kind()); + + target + } + + pub fn upmap_node(&self, input: &SyntaxNode) -> Option { + let (parent, child_slot) = self.node_mappings.get(input)?; + + let output = self.entry_parents[*parent as usize] + .children_with_tokens() + .nth(*child_slot as usize) + .and_then(SyntaxElement::into_node) + .unwrap(); + + debug_assert_eq!(input.kind(), output.kind()); + Some(output) + } + + fn add_mapping(&mut self, syntax_mapping: SyntaxMappingBuilder) { + let SyntaxMappingBuilder { parent_node, node_mappings } = syntax_mapping; + + let parent_entry: u32 = self.entry_parents.len() as u32; + self.entry_parents.push(parent_node); + + let node_entries = + node_mappings.into_iter().map(|(node, slot)| (node, (parent_entry, slot))); + + self.node_mappings.extend(node_entries); + } +} + +#[derive(Debug)] +pub struct SyntaxMappingBuilder { + parent_node: SyntaxNode, + node_mappings: Vec<(SyntaxNode, u32)>, +} + +impl SyntaxMappingBuilder { + pub fn new(parent_node: SyntaxNode) -> Self { + Self { parent_node, node_mappings: vec![] } + } + + pub fn map_node(&mut self, input: SyntaxNode, output: SyntaxNode) { + debug_assert_eq!(output.parent().as_ref(), Some(&self.parent_node)); + self.node_mappings.push((input, output.index() as u32)); + } + + pub fn map_children( + &mut self, + input: impl Iterator, + output: impl Iterator, + ) { + for pairs in input.zip_longest(output) { + let (input, output) = match pairs { + itertools::EitherOrBoth::Both(l, r) => (l, r), + itertools::EitherOrBoth::Left(_) => { + unreachable!("mapping more input nodes than there are output nodes") + } + itertools::EitherOrBoth::Right(_) => break, + }; + + self.map_node(input, output); + } + } + + pub fn finish(self, editor: &mut SyntaxEditor) { + editor.mappings.add_mapping(self); + } +} From 5e33650b7277543d793a9abe69b298e73b7531e7 Mon Sep 17 00:00:00 2001 From: DropDemBits Date: Sun, 1 Sep 2024 23:48:14 -0400 Subject: [PATCH 0366/2194] elaborate SyntaxEdit comments --- .../crates/syntax/src/syntax_editor.rs | 23 ++++++++++++++----- 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/src/tools/rust-analyzer/crates/syntax/src/syntax_editor.rs b/src/tools/rust-analyzer/crates/syntax/src/syntax_editor.rs index 3ec5abcaeafe3..240bba7b4838b 100644 --- a/src/tools/rust-analyzer/crates/syntax/src/syntax_editor.rs +++ b/src/tools/rust-analyzer/crates/syntax/src/syntax_editor.rs @@ -61,16 +61,28 @@ pub struct SyntaxEdit { } impl SyntaxEdit { + /// Root of the modified syntax tree pub fn root(&self) -> &SyntaxNode { &self.root } + /// Which syntax elements in the modified syntax tree were modified as part + /// of the edit. + /// + /// Note that for syntax nodes, only the upper-most parent of a set of + /// changes is included, not any child elements that may have been modified. pub fn changed_elements(&self) -> &[SyntaxElement] { self.changed_elements.as_slice() } - pub fn find_annotation(&self, annotation: SyntaxAnnotation) -> Option<&[SyntaxElement]> { - self.annotations.get(&annotation).as_ref().map(|it| it.as_slice()) + /// Finds which syntax elements have been annotated with the given + /// annotation. + /// + /// Note that an annotation might not appear in the modified syntax tree if + /// the syntax elements that were annotated did not make it into the final + /// syntax tree. + pub fn find_annotation(&self, annotation: SyntaxAnnotation) -> &[SyntaxElement] { + self.annotations.get(&annotation).as_ref().map_or(&[], |it| it.as_slice()) } } @@ -83,9 +95,8 @@ impl SyntaxAnnotation { pub fn new() -> Self { static COUNTER: AtomicU32 = AtomicU32::new(1); - // We want the id to be unique across threads, but we don't want to - // tie it to other `SeqCst` operations. - let id = COUNTER.fetch_add(1, Ordering::AcqRel); + // Only consistency within a thread matters, as SyntaxElements are !Send + let id = COUNTER.fetch_add(1, Ordering::Relaxed); Self(NonZeroU32::new(id).expect("syntax annotation id overflow")) } @@ -328,6 +339,6 @@ mod tests { let expect = expect![]; expect.assert_eq(&edit.root.to_string()); - assert_eq!(edit.find_annotation(placeholder_snippet).map(|it| it.len()), Some(2)); + assert_eq!(edit.find_annotation(placeholder_snippet).len(), 2); } } From 2094a2b117fa0a00a3dcb0a239954b84eeda031c Mon Sep 17 00:00:00 2001 From: DropDemBits Date: Mon, 2 Sep 2024 00:01:24 -0400 Subject: [PATCH 0367/2194] handle merging two syntax editors together --- .../crates/syntax/src/syntax_editor.rs | 15 ++++++-- .../syntax/src/syntax_editor/mapping.rs | 38 +++++++++++++------ 2 files changed, 39 insertions(+), 14 deletions(-) diff --git a/src/tools/rust-analyzer/crates/syntax/src/syntax_editor.rs b/src/tools/rust-analyzer/crates/syntax/src/syntax_editor.rs index 240bba7b4838b..42373eba827d2 100644 --- a/src/tools/rust-analyzer/crates/syntax/src/syntax_editor.rs +++ b/src/tools/rust-analyzer/crates/syntax/src/syntax_editor.rs @@ -37,8 +37,17 @@ impl SyntaxEditor { self.annotations.push((element.syntax_element(), annotation)) } - pub fn combine(&mut self, other: SyntaxEditor) { - todo!() + pub fn merge(&mut self, mut other: SyntaxEditor) { + debug_assert!( + self.root == other.root || other.root.ancestors().any(|node| node == self.root), + "{:?} is not in the same tree as {:?}", + other.root, + self.root + ); + + self.changes.append(&mut other.changes); + self.mappings.merge(other.mappings); + self.annotations.append(&mut other.annotations); } pub fn delete(&mut self, element: impl Element) { @@ -290,7 +299,7 @@ mod tests { } #[test] - fn it() { + fn basic_usage() { let root = make::match_arm( [make::wildcard_pat().into()], None, diff --git a/src/tools/rust-analyzer/crates/syntax/src/syntax_editor/mapping.rs b/src/tools/rust-analyzer/crates/syntax/src/syntax_editor/mapping.rs index 11c7b395b37c9..8a79f7e186eda 100644 --- a/src/tools/rust-analyzer/crates/syntax/src/syntax_editor/mapping.rs +++ b/src/tools/rust-analyzer/crates/syntax/src/syntax_editor/mapping.rs @@ -14,7 +14,7 @@ pub struct SyntaxMapping { // mappings -> parents entry_parents: Vec, - node_mappings: FxHashMap, + node_mappings: FxHashMap, } impl SyntaxMapping { @@ -80,11 +80,10 @@ impl SyntaxMapping { return None; } - if let Some(next) = self.upmap_node(&parent) { - Some((parent.index(), next)) - } else { - Some((parent.index(), parent)) - } + Some((parent.index(), match self.upmap_node(&parent) { + Some(next) => next, + None => parent + })) }).map(|(i, _)| i).collect::>() } else { vec![] @@ -100,7 +99,7 @@ impl SyntaxMapping { .children_with_tokens() .nth(index) .and_then(|it| it.into_node()) - .expect("yep"); + .expect("equivalent ancestor node should be present in target tree"); } debug_assert_eq!(child.kind(), target.kind()); @@ -109,7 +108,7 @@ impl SyntaxMapping { } pub fn upmap_node(&self, input: &SyntaxNode) -> Option { - let (parent, child_slot) = self.node_mappings.get(input)?; + let MappingEntry { parent, child_slot } = self.node_mappings.get(input)?; let output = self.entry_parents[*parent as usize] .children_with_tokens() @@ -121,14 +120,25 @@ impl SyntaxMapping { Some(output) } + pub fn merge(&mut self, mut other: SyntaxMapping) { + // Remap other's entry parents to be after the current list of entry parents + let remap_base: u32 = self.entry_parents.len().try_into().unwrap(); + + self.entry_parents.append(&mut other.entry_parents); + self.node_mappings.extend(other.node_mappings.into_iter().map(|(node, entry)| { + (node, MappingEntry { parent: entry.parent + remap_base, ..entry }) + })); + } + fn add_mapping(&mut self, syntax_mapping: SyntaxMappingBuilder) { let SyntaxMappingBuilder { parent_node, node_mappings } = syntax_mapping; - let parent_entry: u32 = self.entry_parents.len() as u32; + let parent_entry: u32 = self.entry_parents.len().try_into().unwrap(); self.entry_parents.push(parent_node); - let node_entries = - node_mappings.into_iter().map(|(node, slot)| (node, (parent_entry, slot))); + let node_entries = node_mappings + .into_iter() + .map(|(node, slot)| (node, MappingEntry { parent: parent_entry, child_slot: slot })); self.node_mappings.extend(node_entries); } @@ -172,3 +182,9 @@ impl SyntaxMappingBuilder { editor.mappings.add_mapping(self); } } + +#[derive(Debug, Clone, Copy)] +struct MappingEntry { + parent: u32, + child_slot: u32, +} From 6c09243724aae85f3109a12913347d8affb1939b Mon Sep 17 00:00:00 2001 From: The Miri Cronjob Bot Date: Mon, 2 Sep 2024 05:04:59 +0000 Subject: [PATCH 0368/2194] Preparing for merge from rustc --- src/tools/miri/rust-version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/miri/rust-version b/src/tools/miri/rust-version index 5a435a9f55bd3..4f14caf0e56c3 100644 --- a/src/tools/miri/rust-version +++ b/src/tools/miri/rust-version @@ -1 +1 @@ -43eaa5c6246057b1675f42631967ad500eaf47d5 +e71f9529121ca8f687e4b725e3c9adc3f1ebab4d From 5780c1ca5ec96036ab579da6c245d62b34491237 Mon Sep 17 00:00:00 2001 From: Alexander Cyon Date: Mon, 2 Sep 2024 07:33:41 +0200 Subject: [PATCH 0369/2194] chore: Fix typos in 'compiler' (batch 3) --- compiler/rustc_symbol_mangling/src/hashed.rs | 2 +- compiler/rustc_target/src/abi/call/xtensa.rs | 2 +- compiler/rustc_target/src/spec/base/windows_msvc.rs | 2 +- compiler/rustc_target/src/spec/mod.rs | 2 +- compiler/rustc_target/src/spec/targets/wasm32_wasip2.rs | 2 +- .../src/error_reporting/traits/fulfillment_errors.rs | 4 ++-- .../src/error_reporting/traits/on_unimplemented.rs | 6 +++--- .../src/error_reporting/traits/suggestions.rs | 2 +- compiler/rustc_trait_selection/src/traits/coherence.rs | 2 +- compiler/rustc_trait_selection/src/traits/fulfill.rs | 2 +- compiler/rustc_trait_selection/src/traits/select/mod.rs | 2 +- compiler/rustc_transmute/src/maybe_transmutable/mod.rs | 2 +- compiler/rustc_type_ir/src/binder.rs | 2 +- compiler/rustc_type_ir/src/inherent.rs | 2 +- compiler/rustc_type_ir/src/relate.rs | 2 +- compiler/rustc_type_ir/src/solve/mod.rs | 2 +- compiler/stable_mir/src/abi.rs | 2 +- compiler/stable_mir/src/ty.rs | 2 +- 18 files changed, 21 insertions(+), 21 deletions(-) diff --git a/compiler/rustc_symbol_mangling/src/hashed.rs b/compiler/rustc_symbol_mangling/src/hashed.rs index 8e2f94991cf90..07c5f54479232 100644 --- a/compiler/rustc_symbol_mangling/src/hashed.rs +++ b/compiler/rustc_symbol_mangling/src/hashed.rs @@ -14,7 +14,7 @@ pub(super) fn mangle<'tcx>( ) -> 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 + // generic function 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. diff --git a/compiler/rustc_target/src/abi/call/xtensa.rs b/compiler/rustc_target/src/abi/call/xtensa.rs index addbe6989254c..0994ff4798805 100644 --- a/compiler/rustc_target/src/abi/call/xtensa.rs +++ b/compiler/rustc_target/src/abi/call/xtensa.rs @@ -26,7 +26,7 @@ where // so defer to `classify_arg_ty`. let mut arg_gprs_left = NUM_RET_GPRS; classify_arg_ty(arg, &mut arg_gprs_left, MAX_RET_IN_REGS_SIZE); - // Ret args cannot be passed via stack, we lower to indirect and let the backend handle the invisble reference + // Ret args cannot be passed via stack, we lower to indirect and let the backend handle the invisible reference match arg.mode { super::PassMode::Indirect { attrs: _, meta_attrs: _, ref mut on_stack } => { *on_stack = false; diff --git a/compiler/rustc_target/src/spec/base/windows_msvc.rs b/compiler/rustc_target/src/spec/base/windows_msvc.rs index bd0318f31832a..6f886ec8a250f 100644 --- a/compiler/rustc_target/src/spec/base/windows_msvc.rs +++ b/compiler/rustc_target/src/spec/base/windows_msvc.rs @@ -29,7 +29,7 @@ pub fn opts() -> TargetOptions { // they bring in. // // See also https://learn.microsoft.com/en-us/cpp/preprocessor/comment-c-cpp?view=msvc-170#lib - // for documention on including library dependencies in C/C++ code. + // for documentation on including library dependencies in C/C++ code. no_default_libraries: false, has_thread_local: true, diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index d5f227a84a4ca..a7305ca05626a 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -2148,7 +2148,7 @@ pub struct TargetOptions { pub is_like_aix: bool, /// Whether the target toolchain is like macOS's. Only useful for compiling against iOS/macOS, /// in particular running dsymutil and some other stuff like `-dead_strip`. Defaults to false. - /// Also indiates whether to use Apple-specific ABI changes, such as extending function + /// Also indicates whether to use Apple-specific ABI changes, such as extending function /// parameters to 32-bits. pub is_like_osx: bool, /// Whether the target toolchain is like Solaris's. diff --git a/compiler/rustc_target/src/spec/targets/wasm32_wasip2.rs b/compiler/rustc_target/src/spec/targets/wasm32_wasip2.rs index 489bae4fedf17..1a2533ecd7475 100644 --- a/compiler/rustc_target/src/spec/targets/wasm32_wasip2.rs +++ b/compiler/rustc_target/src/spec/targets/wasm32_wasip2.rs @@ -53,7 +53,7 @@ pub fn target() -> Target { options.entry_name = "__main_void".into(); // Default to PIC unlike base wasm. This makes precompiled objects such as - // the standard library more suitable to be used with shared libaries a la + // the standard library more suitable to be used with shared libraries a la // emscripten's dynamic linking convention. options.relocation_model = RelocModel::Pic; diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs index 3fdfca50dceba..de93434bd6011 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs @@ -170,7 +170,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { { return guar; } - // Silence redundant errors on binding acccess that are already + // Silence redundant errors on binding access that are already // reported on the binding definition (#56607). if let Err(guar) = self.fn_arg_obligation(&obligation) { return guar; @@ -900,7 +900,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { let mut suggested = false; let mut chain = vec![]; - // The following logic is simlar to `point_at_chain`, but that's focused on associated types + // The following logic is similar to `point_at_chain`, but that's focused on associated types let mut expr = expr; while let hir::ExprKind::MethodCall(path_segment, rcvr_expr, args, span) = expr.kind { // Point at every method call in the chain with the `Result` type. diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented.rs index efbc2695fd95e..41b0ee56a4cb5 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented.rs @@ -878,7 +878,7 @@ impl<'tcx> OnUnimplementedFormatString { } } // we cannot return errors from processing the format string as hard error here - // as the diagnostic namespace gurantees that malformed input cannot cause an error + // as the diagnostic namespace guarantees that malformed input cannot cause an error // // if we encounter any error while processing we nevertheless want to show it as warning // so that users are aware that something is not correct @@ -986,10 +986,10 @@ impl<'tcx> OnUnimplementedFormatString { }) .collect(); // we cannot return errors from processing the format string as hard error here - // as the diagnostic namespace gurantees that malformed input cannot cause an error + // as the diagnostic namespace guarantees that malformed input cannot cause an error // // if we encounter any error while processing the format string - // we don't want to show the potentially half assembled formated string, + // we don't want to show the potentially half assembled formatted string, // therefore we fall back to just showing the input string in this case // // The actual parser errors are emitted earlier diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs index f2c457aa377fb..5c663e0bf4b5b 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs @@ -4663,7 +4663,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { // because this suggest adding both return type in // the `FnSig` and a default return value in the body, so it // is not suitable for foreign function without a local body, - // and neighter for trait method which may be also implemented + // and neither for trait method which may be also implemented // in other place, so shouldn't change it's FnSig. fn choose_suggest_items<'tcx, 'hir>( tcx: TyCtxt<'tcx>, diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs index bf4b0482081d9..4acbca994aaa3 100644 --- a/compiler/rustc_trait_selection/src/traits/coherence.rs +++ b/compiler/rustc_trait_selection/src/traits/coherence.rs @@ -723,7 +723,7 @@ impl<'a, 'tcx> ProofTreeVisitor<'tcx> for AmbiguityCausesVisitor<'a, 'tcx> { // FIXME: While this matches the behavior of the // old solver, it is not the only way in which the unknowable // candidates *weaken* coherence, they can also force otherwise - // sucessful normalization to be ambiguous. + // successful normalization to be ambiguous. Ok(Certainty::Maybe(_) | Certainty::Yes) => { ambiguity_cause = None; break; diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs index f72ae94fffc7a..16ba06f8667ff 100644 --- a/compiler/rustc_trait_selection/src/traits/fulfill.rs +++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs @@ -472,7 +472,7 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> { }; match infcx.at(&obligation.cause, obligation.param_env).eq( - // Only really excercised by generic_const_exprs + // Only really exercised by generic_const_exprs DefineOpaqueTypes::Yes, ct_ty, ty, diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 91fe19c20f77b..12497e32b2db4 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -991,7 +991,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { }; match self.infcx.at(&obligation.cause, obligation.param_env).eq( - // Only really excercised by generic_const_exprs + // Only really exercised by generic_const_exprs DefineOpaqueTypes::Yes, ct_ty, ty, diff --git a/compiler/rustc_transmute/src/maybe_transmutable/mod.rs b/compiler/rustc_transmute/src/maybe_transmutable/mod.rs index 2762b4e638405..a76ef7f0d189b 100644 --- a/compiler/rustc_transmute/src/maybe_transmutable/mod.rs +++ b/compiler/rustc_transmute/src/maybe_transmutable/mod.rs @@ -242,7 +242,7 @@ where // } // ...if `refs_answer` was computed lazily. The below early // returns can be deleted without impacting the correctness of - // the algoritm; only its performance. + // the algorithm; only its performance. debug!(?bytes_answer); match bytes_answer { Answer::No(_) if !self.assume.validity => return bytes_answer, diff --git a/compiler/rustc_type_ir/src/binder.rs b/compiler/rustc_type_ir/src/binder.rs index d42efbc91e196..f20beb797500e 100644 --- a/compiler/rustc_type_ir/src/binder.rs +++ b/compiler/rustc_type_ir/src/binder.rs @@ -776,7 +776,7 @@ impl<'a, I: Interner> ArgFolder<'a, I> { } /// It is sometimes necessary to adjust the De Bruijn indices during instantiation. This occurs - /// when we are instantating a type with escaping bound vars into a context where we have + /// when we are instantiating a type with escaping bound vars into a context where we have /// passed through binders. That's quite a mouthful. Let's see an example: /// /// ``` diff --git a/compiler/rustc_type_ir/src/inherent.rs b/compiler/rustc_type_ir/src/inherent.rs index 958360faede57..59a83ea5412d5 100644 --- a/compiler/rustc_type_ir/src/inherent.rs +++ b/compiler/rustc_type_ir/src/inherent.rs @@ -162,7 +162,7 @@ pub trait Ty>: /// Returns `true` when the outermost type cannot be further normalized, /// resolved, or instantiated. This includes all primitive types, but also - /// things like ADTs and trait objects, sice even if their arguments or + /// things like ADTs and trait objects, since even if their arguments or /// nested types may be further simplified, the outermost [`ty::TyKind`] or /// type constructor remains the same. fn is_known_rigid(self) -> bool { diff --git a/compiler/rustc_type_ir/src/relate.rs b/compiler/rustc_type_ir/src/relate.rs index 578436b622a87..9c725f34d8e5b 100644 --- a/compiler/rustc_type_ir/src/relate.rs +++ b/compiler/rustc_type_ir/src/relate.rs @@ -550,7 +550,7 @@ pub fn structurally_relate_tys>( /// Any semantic equality, e.g. of unevaluated consts, and inference variables have /// to be handled by the caller. /// -/// FIXME: This is not totally structual, which probably should be fixed. +/// FIXME: This is not totally structural, which probably should be fixed. /// See the HACKs below. pub fn structurally_relate_consts>( relation: &mut R, diff --git a/compiler/rustc_type_ir/src/solve/mod.rs b/compiler/rustc_type_ir/src/solve/mod.rs index 00fc6ba1c5c8f..96c939a898bd9 100644 --- a/compiler/rustc_type_ir/src/solve/mod.rs +++ b/compiler/rustc_type_ir/src/solve/mod.rs @@ -132,7 +132,7 @@ pub enum GoalSource { /// results in better error messages by avoiding spurious errors. /// We do not erase overflow constraints in `normalizes-to` goals unless /// they are from an impl where-clause. This is necessary due to - /// backwards compatability, cc trait-system-refactor-initiatitive#70. + /// backwards compatibility, cc trait-system-refactor-initiatitive#70. ImplWhereBound, /// Instantiating a higher-ranked goal and re-proving it. InstantiateHigherRanked, diff --git a/compiler/stable_mir/src/abi.rs b/compiler/stable_mir/src/abi.rs index 9d3b40e5eea7b..317bec3050c74 100644 --- a/compiler/stable_mir/src/abi.rs +++ b/compiler/stable_mir/src/abi.rs @@ -70,7 +70,7 @@ pub struct TyAndLayout { /// The layout of a type in memory. #[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize)] pub struct LayoutShape { - /// The fields location withing the layout + /// The fields location within the layout pub fields: FieldsShape, /// Encodes information about multi-variant layouts. diff --git a/compiler/stable_mir/src/ty.rs b/compiler/stable_mir/src/ty.rs index 2f36aa5182965..5bad3d5ae7a3c 100644 --- a/compiler/stable_mir/src/ty.rs +++ b/compiler/stable_mir/src/ty.rs @@ -267,7 +267,7 @@ impl Span { with(|c| c.get_filename(self)) } - /// Return lines that corespond to this `Span` + /// Return lines that correspond to this `Span` pub fn get_lines(&self) -> LineInfo { with(|c| c.get_lines(self)) } From 747f68091aa1c53ed4229b26a315ccd0ca2e267f Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 2 Sep 2024 13:59:12 +1000 Subject: [PATCH 0370/2194] Use sysroot crates maximally in `rustc_codegen_gcc`. This shrinks `compiler/rustc_codegen_gcc/Cargo.lock` quite a bit. The only remaining dependencies in `compiler/rustc_codegen_gcc/Cargo.lock` are `gccjit`, `lang_tester`, and `boml`, all of which aren't used in any other compiler crates. The commit also reorders and adds comments to the `extern crate` items so they match those in miri. --- compiler/rustc_codegen_gcc/Cargo.lock | 176 -------------------------- compiler/rustc_codegen_gcc/Cargo.toml | 10 -- compiler/rustc_codegen_gcc/src/lib.rs | 10 +- 3 files changed, 8 insertions(+), 188 deletions(-) diff --git a/compiler/rustc_codegen_gcc/Cargo.lock b/compiler/rustc_codegen_gcc/Cargo.lock index 915229f7e7eef..0eb264f99eb08 100644 --- a/compiler/rustc_codegen_gcc/Cargo.lock +++ b/compiler/rustc_codegen_gcc/Cargo.lock @@ -11,63 +11,12 @@ dependencies = [ "memchr", ] -[[package]] -name = "bitflags" -version = "1.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" - -[[package]] -name = "bitflags" -version = "2.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4682ae6287fcf752ecaabbfcc7b6f9b72aa33933dc23a554d853aea8eea8635" - [[package]] name = "boml" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "85fdb93f04c73bff54305fa437ffea5449c41edcaadfe882f35836206b166ac5" -[[package]] -name = "cc" -version = "1.0.79" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f" - -[[package]] -name = "cfg-if" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" - -[[package]] -name = "errno" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4bcfec3a70f97c962c307b2d2c56e358cf1d00b558d74262b5f929ee8cc7e73a" -dependencies = [ - "errno-dragonfly", - "libc", - "windows-sys", -] - -[[package]] -name = "errno-dragonfly" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf" -dependencies = [ - "cc", - "libc", -] - -[[package]] -name = "fastrand" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6999dc1837253364c2ebb0704ba97994bd874e8f195d665c50b7548f6ea92764" - [[package]] name = "fm" version = "0.2.2" @@ -132,12 +81,6 @@ version = "0.2.150" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "89d92a4743f9a61002fae18374ed11e7973f530cb3a3255fb354818118b2203c" -[[package]] -name = "linux-raw-sys" -version = "0.4.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57bcfdad1b858c2db7c38303a6d2ad4dfaf5eb53dfeb0910128b2c26d6158503" - [[package]] name = "memchr" version = "2.5.0" @@ -154,24 +97,6 @@ dependencies = [ "libc", ] -[[package]] -name = "object" -version = "0.30.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03b4680b86d9cfafba8fc491dc9b6df26b68cf40e9e6cd73909194759a63c385" -dependencies = [ - "memchr", -] - -[[package]] -name = "redox_syscall" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" -dependencies = [ - "bitflags 1.3.2", -] - [[package]] name = "regex" version = "1.8.4" @@ -196,22 +121,6 @@ dependencies = [ "boml", "gccjit", "lang_tester", - "object", - "smallvec", - "tempfile", -] - -[[package]] -name = "rustix" -version = "0.38.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19ed4fa021d81c8392ce04db050a3da9a60299050b7ae1cf482d862b54a7218f" -dependencies = [ - "bitflags 2.4.0", - "errno", - "libc", - "linux-raw-sys", - "windows-sys", ] [[package]] @@ -223,25 +132,6 @@ dependencies = [ "winapi-util", ] -[[package]] -name = "smallvec" -version = "1.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" - -[[package]] -name = "tempfile" -version = "3.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc02fddf48964c42031a0b3fe0428320ecf3a73c401040fc0096f97794310651" -dependencies = [ - "cfg-if", - "fastrand", - "redox_syscall", - "rustix", - "windows-sys", -] - [[package]] name = "termcolor" version = "1.2.0" @@ -315,69 +205,3 @@ name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" - -[[package]] -name = "windows-sys" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" -dependencies = [ - "windows-targets", -] - -[[package]] -name = "windows-targets" -version = "0.48.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05d4b17490f70499f20b9e791dcf6a299785ce8af4d709018206dc5b4953e95f" -dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", -] - -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3" - -[[package]] -name = "windows_i686_gnu" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241" - -[[package]] -name = "windows_i686_msvc" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" diff --git a/compiler/rustc_codegen_gcc/Cargo.toml b/compiler/rustc_codegen_gcc/Cargo.toml index 5caca63f63480..44fb5eef04a57 100644 --- a/compiler/rustc_codegen_gcc/Cargo.toml +++ b/compiler/rustc_codegen_gcc/Cargo.toml @@ -23,21 +23,11 @@ default = ["master"] [dependencies] gccjit = "2.1" - # Local copy. #gccjit = { path = "../gccjit.rs" } -object = { version = "0.30.1", default-features = false, features = [ - "std", - "read", -] } -smallvec = { version = "1.6.1", features = ["union", "may_dangle"] } -# TODO(antoyo): make tempfile optional. -tempfile = "3.7.1" - [dev-dependencies] lang_tester = "0.8.0" -tempfile = "3.1.0" boml = "0.3.1" [profile.dev] diff --git a/compiler/rustc_codegen_gcc/src/lib.rs b/compiler/rustc_codegen_gcc/src/lib.rs index 94f016234f921..4de671ac4a062 100644 --- a/compiler/rustc_codegen_gcc/src/lib.rs +++ b/compiler/rustc_codegen_gcc/src/lib.rs @@ -24,6 +24,14 @@ #![deny(clippy::pattern_type_mismatch)] #![allow(clippy::needless_lifetimes)] +// Some "regular" crates we want to share with rustc +extern crate object; +extern crate smallvec; +extern crate tempfile; +#[macro_use] +extern crate tracing; + +// The rustc crates we need extern crate rustc_apfloat; extern crate rustc_ast; extern crate rustc_attr; @@ -42,8 +50,6 @@ extern crate rustc_middle; extern crate rustc_session; extern crate rustc_span; extern crate rustc_target; -#[macro_use] -extern crate tracing; // This prevents duplicating functions and statics that are already part of the host rustc process. #[allow(unused_extern_crates)] From ac69544a175d692dd623fb854261ca64b1b9b802 Mon Sep 17 00:00:00 2001 From: Alexander Cyon Date: Mon, 2 Sep 2024 07:42:38 +0200 Subject: [PATCH 0371/2194] chore: Fix typos in 'compiler' (batch 1) --- compiler/rustc_ast_lowering/src/delegation.rs | 4 ++-- .../rustc_borrowck/src/diagnostics/conflict_errors.rs | 2 +- compiler/rustc_borrowck/src/type_check/liveness/trace.rs | 2 +- compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs | 2 +- compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs | 2 +- compiler/rustc_const_eval/src/interpret/call.rs | 4 ++-- compiler/rustc_const_eval/src/interpret/eval_context.rs | 2 +- compiler/rustc_const_eval/src/interpret/memory.rs | 2 +- compiler/rustc_const_eval/src/interpret/place.rs | 2 +- compiler/rustc_const_eval/src/interpret/stack.rs | 2 +- compiler/rustc_data_structures/src/base_n.rs | 2 +- compiler/rustc_data_structures/src/graph/scc/mod.rs | 2 +- compiler/rustc_data_structures/src/hashes.rs | 4 ++-- compiler/rustc_data_structures/src/sync/worker_local.rs | 8 ++++---- compiler/rustc_error_codes/src/error_codes/E0582.md | 2 +- compiler/rustc_errors/src/diagnostic.rs | 2 +- compiler/rustc_errors/src/emitter.rs | 2 +- compiler/rustc_errors/src/lib.rs | 2 +- compiler/rustc_errors/src/markdown/parse.rs | 2 +- compiler/rustc_feature/src/unstable.rs | 2 +- compiler/rustc_hir_analysis/src/check/wfcheck.rs | 2 +- compiler/rustc_hir_analysis/src/coherence/builtin.rs | 2 +- compiler/rustc_hir_analysis/src/collect.rs | 4 ++-- compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs | 2 +- compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs | 2 +- compiler/rustc_hir_typeck/src/cast.rs | 2 +- compiler/rustc_hir_typeck/src/method/confirm.rs | 6 +++--- compiler/rustc_hir_typeck/src/upvar.rs | 2 +- compiler/rustc_infer/src/infer/canonical/canonicalizer.rs | 2 +- compiler/rustc_infer/src/infer/opaque_types/mod.rs | 2 +- compiler/rustc_infer/src/infer/relate/combine.rs | 2 +- compiler/rustc_infer/src/infer/relate/generalize.rs | 2 +- compiler/rustc_interface/src/passes.rs | 2 +- compiler/rustc_lint/src/non_local_def.rs | 2 +- compiler/rustc_lint/src/unused.rs | 2 +- 35 files changed, 44 insertions(+), 44 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/delegation.rs b/compiler/rustc_ast_lowering/src/delegation.rs index 800773482041a..ac527df474aff 100644 --- a/compiler/rustc_ast_lowering/src/delegation.rs +++ b/compiler/rustc_ast_lowering/src/delegation.rs @@ -72,7 +72,7 @@ impl<'hir> LoweringContext<'_, 'hir> { fn has_self(&self, def_id: DefId, span: Span) -> bool { if let Some(local_sig_id) = def_id.as_local() { // The value may be missing due to recursive delegation. - // Error will be emmited later during HIR ty lowering. + // Error will be emitted later during HIR ty lowering. self.resolver.delegation_fn_sigs.get(&local_sig_id).map_or(false, |sig| sig.has_self) } else { match self.tcx.def_kind(def_id) { @@ -139,7 +139,7 @@ impl<'hir> LoweringContext<'_, 'hir> { fn param_count(&self, sig_id: DefId) -> (usize, bool /*c_variadic*/) { if let Some(local_sig_id) = sig_id.as_local() { // Map may be filled incorrectly due to recursive delegation. - // Error will be emmited later during HIR ty lowering. + // Error will be emitted later during HIR ty lowering. match self.resolver.delegation_fn_sigs.get(&local_sig_id) { Some(sig) => (sig.param_count, sig.c_variadic), None => (0, false), diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index 9951f9fcda69c..c817b6fac7134 100644 --- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs @@ -1179,7 +1179,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, '_, 'infcx, 'tcx> { for field in &variant.fields { // In practice unless there are more than one field with the same type, we'll be // suggesting a single field at a type, because we don't aggregate multiple borrow - // checker errors involving the functional record update sytnax into a single one. + // checker errors involving the functional record update syntax into a single one. let field_ty = field.ty(self.infcx.tcx, args); let ident = field.ident(self.infcx.tcx); if field_ty == ty && fields.iter().all(|field| field.ident.name != ident.name) { diff --git a/compiler/rustc_borrowck/src/type_check/liveness/trace.rs b/compiler/rustc_borrowck/src/type_check/liveness/trace.rs index de3ff8378bcc7..6186904e5fbb6 100644 --- a/compiler/rustc_borrowck/src/type_check/liveness/trace.rs +++ b/compiler/rustc_borrowck/src/type_check/liveness/trace.rs @@ -218,7 +218,7 @@ impl<'a, 'me, 'typeck, 'flow, 'tcx> LivenessResults<'a, 'me, 'typeck, 'flow, 'tc // This collect is more necessary than immediately apparent // because these facts go into `add_drop_live_facts_for()`, // which also writes to `all_facts`, and so this is genuinely - // a simulatneous overlapping mutable borrow. + // a simultaneous overlapping mutable borrow. // FIXME for future hackers: investigate whether this is // actually necessary; these facts come from Polonius // and probably maybe plausibly does not need to go back in. diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs index 069b62af5e748..b5acfabfde25e 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs @@ -422,7 +422,7 @@ fn prepare_usage_sets<'tcx>(tcx: TyCtxt<'tcx>) -> UsageSets<'tcx> { (instance.def_id(), body) }); - // Functions whose coverage statments were found inlined into other functions. + // Functions whose coverage statements were found inlined into other functions. let mut used_via_inlining = FxHashSet::default(); // Functions that were instrumented, but had all of their coverage statements // removed by later MIR transforms (e.g. UnreachablePropagation). diff --git a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs index f0bc4354f9a75..5103b2f31582b 100644 --- a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs +++ b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs @@ -701,7 +701,7 @@ fn push_const_param<'tcx>(tcx: TyCtxt<'tcx>, ct: ty::Const<'tcx>, output: &mut S match ty.kind() { ty::Int(ity) => { // FIXME: directly extract the bits from a valtree instead of evaluating an - // alreay evaluated `Const` in order to get the bits. + // already evaluated `Const` in order to get the bits. let bits = ct.eval_bits(tcx, ty::ParamEnv::reveal_all()); let val = Integer::from_int_ty(&tcx, *ity).size().sign_extend(bits) as i128; write!(output, "{val}") diff --git a/compiler/rustc_const_eval/src/interpret/call.rs b/compiler/rustc_const_eval/src/interpret/call.rs index 61e8007e10ecf..82438eb5e7828 100644 --- a/compiler/rustc_const_eval/src/interpret/call.rs +++ b/compiler/rustc_const_eval/src/interpret/call.rs @@ -20,7 +20,7 @@ use super::{ }; use crate::fluent_generated as fluent; -/// An argment passed to a function. +/// An argument passed to a function. #[derive(Clone, Debug)] pub enum FnArg<'tcx, Prov: Provenance = CtfeProvenance> { /// Pass a copy of the given operand. @@ -123,7 +123,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { self.tcx.has_attr(def.did(), sym::rustc_nonnull_optimization_guaranteed) }; let inner = self.unfold_transparent(inner, /* may_unfold */ |def| { - // Stop at NPO tpyes so that we don't miss that attribute in the check below! + // Stop at NPO types so that we don't miss that attribute in the check below! def.is_struct() && !is_npo(def) }); Ok(match inner.ty.kind() { diff --git a/compiler/rustc_const_eval/src/interpret/eval_context.rs b/compiler/rustc_const_eval/src/interpret/eval_context.rs index 7a6bbdfdcb5e5..dd744c51f23be 100644 --- a/compiler/rustc_const_eval/src/interpret/eval_context.rs +++ b/compiler/rustc_const_eval/src/interpret/eval_context.rs @@ -574,7 +574,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { // be computed as the type references non-existing names. // See . } else { - // Looks like the const is not captued by `required_consts`, that's bad. + // Looks like the const is not captured by `required_consts`, that's bad. span_bug!(span, "interpret const eval failure of {val:?} which is not in required_consts"); } } diff --git a/compiler/rustc_const_eval/src/interpret/memory.rs b/compiler/rustc_const_eval/src/interpret/memory.rs index 97326fe99a21a..45a5eb9bd52fc 100644 --- a/compiler/rustc_const_eval/src/interpret/memory.rs +++ b/compiler/rustc_const_eval/src/interpret/memory.rs @@ -827,7 +827,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { let (size, align) = if nested { // Nested anonymous statics are untyped, so let's get their - // size and alignment from the allocaiton itself. This always + // size and alignment from the allocation itself. This always // succeeds, as the query is fed at DefId creation time, so no // evaluation actually occurs. let alloc = self.tcx.eval_static_initializer(def_id).unwrap(); diff --git a/compiler/rustc_const_eval/src/interpret/place.rs b/compiler/rustc_const_eval/src/interpret/place.rs index ede6a51c712b9..d7d033e516295 100644 --- a/compiler/rustc_const_eval/src/interpret/place.rs +++ b/compiler/rustc_const_eval/src/interpret/place.rs @@ -186,7 +186,7 @@ pub(super) enum Place { /// `Local` places always refer to the current stack frame, so they are unstable under /// function calls/returns and switching betweens stacks of different threads! /// We carry around the address of the `locals` buffer of the correct stack frame as a sanity - /// chec to be able to catch some cases of using a dangling `Place`. + /// check to be able to catch some cases of using a dangling `Place`. /// /// This variant shall not be used for unsized types -- those must always live in memory. Local { local: mir::Local, offset: Option, locals_addr: usize }, diff --git a/compiler/rustc_const_eval/src/interpret/stack.rs b/compiler/rustc_const_eval/src/interpret/stack.rs index 0f6bf5c03364c..b6e83715e3989 100644 --- a/compiler/rustc_const_eval/src/interpret/stack.rs +++ b/compiler/rustc_const_eval/src/interpret/stack.rs @@ -1,5 +1,5 @@ //! Manages the low-level pushing and popping of stack frames and the (de)allocation of local variables. -//! For hadling of argument passing and return values, see the `call` module. +//! For handling of argument passing and return values, see the `call` module. use std::cell::Cell; use std::{fmt, mem}; diff --git a/compiler/rustc_data_structures/src/base_n.rs b/compiler/rustc_data_structures/src/base_n.rs index 1c2321623e491..0c3d7613d4f1f 100644 --- a/compiler/rustc_data_structures/src/base_n.rs +++ b/compiler/rustc_data_structures/src/base_n.rs @@ -42,7 +42,7 @@ impl fmt::Display for BaseNString { } // This trait just lets us reserve the exact right amount of space when doing fixed-length -// case-insensitve encoding. Add any impls you need. +// case-insensitive encoding. Add any impls you need. pub trait ToBaseN: Into { fn encoded_len(base: usize) -> usize; diff --git a/compiler/rustc_data_structures/src/graph/scc/mod.rs b/compiler/rustc_data_structures/src/graph/scc/mod.rs index 2a457ffb70b08..06fedef00fc3f 100644 --- a/compiler/rustc_data_structures/src/graph/scc/mod.rs +++ b/compiler/rustc_data_structures/src/graph/scc/mod.rs @@ -477,7 +477,7 @@ where // will know when we hit the state where previous_node == node. loop { // Back at the beginning, we can return. Note that we return the root state. - // This is becuse for components being explored, we would otherwise get a + // This is because for components being explored, we would otherwise get a // `node_state[n] = InCycleWith{ parent: n }` and that's wrong. if previous_node == node { return root_state; diff --git a/compiler/rustc_data_structures/src/hashes.rs b/compiler/rustc_data_structures/src/hashes.rs index f98c8de1eb097..8f4639fc2e666 100644 --- a/compiler/rustc_data_structures/src/hashes.rs +++ b/compiler/rustc_data_structures/src/hashes.rs @@ -3,11 +3,11 @@ //! or 16 bytes of the hash. //! //! The types in this module represent 64-bit or 128-bit hashes produced by a `StableHasher`. -//! `Hash64` and `Hash128` expose some utilty functions to encourage users to not extract the inner +//! `Hash64` and `Hash128` expose some utility functions to encourage users to not extract the inner //! hash value as an integer type and accidentally apply varint encoding to it. //! //! In contrast with `Fingerprint`, users of these types cannot and should not attempt to construct -//! and decompose these types into constitutent pieces. The point of these types is only to +//! and decompose these types into constituent pieces. The point of these types is only to //! connect the fact that they can only be produced by a `StableHasher` to their //! `Encode`/`Decode` impls. diff --git a/compiler/rustc_data_structures/src/sync/worker_local.rs b/compiler/rustc_data_structures/src/sync/worker_local.rs index 4950481d311f0..b6efcada10b77 100644 --- a/compiler/rustc_data_structures/src/sync/worker_local.rs +++ b/compiler/rustc_data_structures/src/sync/worker_local.rs @@ -19,7 +19,7 @@ impl RegistryId { /// index within the registry. This panics if the current thread is not associated with this /// registry. /// - /// Note that there's a race possible where the identifer in `THREAD_DATA` could be reused + /// Note that there's a race possible where the identifier in `THREAD_DATA` could be reused /// so this can succeed from a different registry. #[cfg(parallel_compiler)] fn verify(self) -> usize { @@ -50,7 +50,7 @@ struct ThreadData { } thread_local! { - /// A thread local which contains the identifer of `REGISTRY` but allows for faster access. + /// A thread local which contains the identifier of `REGISTRY` but allows for faster access. /// It also holds the index of the current thread. static THREAD_DATA: ThreadData = const { ThreadData { registry_id: Cell::new(RegistryId(ptr::null())), @@ -66,7 +66,7 @@ impl Registry { /// Gets the registry associated with the current thread. Panics if there's no such registry. pub fn current() -> Self { - REGISTRY.with(|registry| registry.get().cloned().expect("No assocated registry")) + REGISTRY.with(|registry| registry.get().cloned().expect("No associated registry")) } /// Registers the current thread with the registry so worker locals can be used on it. @@ -92,7 +92,7 @@ impl Registry { } } - /// Gets the identifer of this registry. + /// Gets the identifier of this registry. fn id(&self) -> RegistryId { RegistryId(&*self.0) } diff --git a/compiler/rustc_error_codes/src/error_codes/E0582.md b/compiler/rustc_error_codes/src/error_codes/E0582.md index b2cdb509c95c0..c4aaa17706add 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0582.md +++ b/compiler/rustc_error_codes/src/error_codes/E0582.md @@ -44,7 +44,7 @@ where ``` The latter scenario encounters this error because `Foo::Assoc<'a>` could be implemented by a type that does not use the `'a` parameter, so there is no -guarentee that `X::Assoc<'a>` actually uses `'a`. +guarantee that `X::Assoc<'a>` actually uses `'a`. To fix this we can pass a dummy parameter: ``` diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs index 3303e4ee752c2..41a94cc2b6fde 100644 --- a/compiler/rustc_errors/src/diagnostic.rs +++ b/compiler/rustc_errors/src/diagnostic.rs @@ -484,7 +484,7 @@ pub struct Subdiag { /// - The `EmissionGuarantee`, which determines the type returned from `emit`. /// /// Each constructed `Diag` must be consumed by a function such as `emit`, -/// `cancel`, `delay_as_bug`, or `into_diag`. A panic occurrs if a `Diag` +/// `cancel`, `delay_as_bug`, or `into_diag`. A panic occurs if a `Diag` /// is dropped without being consumed by one of these functions. /// /// If there is some state in a downstream crate you would like to access in diff --git a/compiler/rustc_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs index 2bc29dabd18a1..2b135df91a4bb 100644 --- a/compiler/rustc_errors/src/emitter.rs +++ b/compiler/rustc_errors/src/emitter.rs @@ -2300,7 +2300,7 @@ impl HumanEmitter { // For example, for the following: // | // 2 - .await - // 2 + (note the left over whitepsace) + // 2 + (note the left over whitespace) // | // We really want // | diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index 99ee8fb17d7dc..27f9e2249b337 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -817,7 +817,7 @@ impl<'a> DiagCtxtHandle<'a> { ); } // We delay a bug here so that `-Ztreat-err-as-bug -Zeagerly-emit-delayed-bugs` - // can be used to create a backtrace at the stashing site insted of whenever the + // can be used to create a backtrace at the stashing site instead of whenever the // diagnostic context is dropped and thus delayed bugs are emitted. Error => Some(self.span_delayed_bug(span, format!("stashing {key:?}"))), DelayedBug => { diff --git a/compiler/rustc_errors/src/markdown/parse.rs b/compiler/rustc_errors/src/markdown/parse.rs index b1db44dd215b8..8dd146c1c337f 100644 --- a/compiler/rustc_errors/src/markdown/parse.rs +++ b/compiler/rustc_errors/src/markdown/parse.rs @@ -487,7 +487,7 @@ fn is_break_ty(val: &MdTree<'_>) -> bool { || matches!(val, MdTree::PlainText(txt) if txt.trim().is_empty()) } -/// Perform tranformations to text. This splits paragraphs, replaces patterns, +/// Perform transformations to text. This splits paragraphs, replaces patterns, /// and corrects newlines. /// /// To avoid allocating strings (and using a different heavier tt type), our diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index 7ea037ca8b2b6..64dd2cbb9894f 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -585,7 +585,7 @@ declare_features! ( (unstable, rust_cold_cc, "1.63.0", Some(97544)), /// Allows use of x86 SHA512, SM3 and SM4 target-features and intrinsics (unstable, sha512_sm_x86, "CURRENT_RUSTC_VERSION", Some(126624)), - /// Shortern the tail expression lifetime + /// Shorten the tail expression lifetime (unstable, shorter_tail_lifetimes, "1.79.0", Some(123739)), /// Allows the use of SIMD types in functions declared in `extern` blocks. (unstable, simd_ffi, "1.0.0", Some(27731)), diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index 359b4729e50a6..f83eac7cd6c4d 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -1016,7 +1016,7 @@ fn check_param_wf(tcx: TyCtxt<'_>, param: &hir::GenericParam<'_>) -> Result<(), sym::adt_const_params, )]) } - // Implments `ConstParamTy`, suggest adding the feature to enable. + // Implements `ConstParamTy`, suggest adding the feature to enable. Ok(..) => Some(vec![(adt_const_params_feature_string, sym::adt_const_params)]), }; if let Some(features) = may_suggest_feature { diff --git a/compiler/rustc_hir_analysis/src/coherence/builtin.rs b/compiler/rustc_hir_analysis/src/coherence/builtin.rs index 9f01f7be80af4..30fc06829ed8e 100644 --- a/compiler/rustc_hir_analysis/src/coherence/builtin.rs +++ b/compiler/rustc_hir_analysis/src/coherence/builtin.rs @@ -219,7 +219,7 @@ fn visit_implementation_of_dispatch_from_dyn(checker: &Checker<'_>) -> Result<() // Later parts of the compiler rely on all DispatchFromDyn types to be ABI-compatible with raw // pointers. This is enforced here: we only allow impls for references, raw pointers, and things // that are effectively repr(transparent) newtypes around types that already hav a - // DispatchedFromDyn impl. We cannot literally use repr(transparent) on those tpyes since some + // DispatchedFromDyn impl. We cannot literally use repr(transparent) on those types since some // of them support an allocator, but we ensure that for the cases where the type implements this // trait, they *do* satisfy the repr(transparent) rules, and then we assume that everything else // in the compiler (in particular, all the call ABI logic) will treat them as repr(transparent) diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index 53105f337c4a8..92111805ab422 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -1037,7 +1037,7 @@ impl<'tcx> FieldUniquenessCheckContext<'tcx> { /// Check the uniqueness of fields in a struct variant, and recursively /// check the nested fields if it is an unnamed field with type of an - /// annoymous adt. + /// anonymous adt. fn check_field(&mut self, field: &hir::FieldDef<'_>) { if field.ident.name != kw::Underscore { self.check_field_decl(field.ident, field.span.into()); @@ -1491,7 +1491,7 @@ fn infer_return_ty_for_fn_sig<'tcx>( Some(ty) => { let fn_sig = tcx.typeck(def_id).liberated_fn_sigs()[hir_id]; // Typeck doesn't expect erased regions to be returned from `type_of`. - // This is a heuristic approach. If the scope has region paramters, + // This is a heuristic approach. If the scope has region parameters, // we should change fn_sig's lifetime from `ReErased` to `ReError`, // otherwise to `ReStatic`. let has_region_params = generics.params.iter().any(|param| match param.kind { diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs index 70a3c744c78a2..bffe68f9b745f 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs @@ -529,7 +529,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { /// Detect and reject early-bound & escaping late-bound generic params in the type of assoc const bindings. /// -/// FIXME(const_generics): This is a temporary and semi-artifical restriction until the +/// FIXME(const_generics): This is a temporary and semi-artificial restriction until the /// arrival of *generic const generics*[^1]. /// /// It might actually be possible that we can already support early-bound generic params diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs index 36c26f91089c3..ac5bd825b18dd 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -986,7 +986,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { /// We **don't** support paths whose self type is an arbitrary type like `Struct::Ty` where /// struct `Struct` impls an in-scope trait that defines an associated type called `Ty`. /// For the latter case, we report ambiguity. - /// While desirable to support, the implemention would be non-trivial. Tracked in [#22519]. + /// While desirable to support, the implementation would be non-trivial. Tracked in [#22519]. /// /// At the time of writing, *inherent associated types* are also resolved here. This however /// is [problematic][iat]. A proper implementation would be as non-trivial as the one diff --git a/compiler/rustc_hir_typeck/src/cast.rs b/compiler/rustc_hir_typeck/src/cast.rs index 1db2c865b4077..1e1e007862e1c 100644 --- a/compiler/rustc_hir_typeck/src/cast.rs +++ b/compiler/rustc_hir_typeck/src/cast.rs @@ -650,7 +650,7 @@ impl<'a, 'tcx> CastCheck<'tcx> { // cannot distinguish. This would cause us to erroneously discard a cast which will // lead to a borrowck error like #113257. // We still did a coercion above to unify inference variables for `ptr as _` casts. - // This does cause us to miss some trivial casts in the trival cast lint. + // This does cause us to miss some trivial casts in the trivial cast lint. debug!(" -> PointerCast"); } else { self.trivial_cast_lint(fcx); diff --git a/compiler/rustc_hir_typeck/src/method/confirm.rs b/compiler/rustc_hir_typeck/src/method/confirm.rs index faeabdc082109..10a22eee7b74a 100644 --- a/compiler/rustc_hir_typeck/src/method/confirm.rs +++ b/compiler/rustc_hir_typeck/src/method/confirm.rs @@ -249,7 +249,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> { } /// Returns a set of generic parameters for the method *receiver* where all type and region - /// parameters are instantiated with fresh variables. This generic paramters does not include any + /// parameters are instantiated with fresh variables. This generic parameters does not include any /// parameters declared on the method itself. /// /// Note that this generic parameters may include late-bound regions from the impl level. If so, @@ -375,7 +375,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> { IsMethodCall::Yes, ); - // Create generic paramters for early-bound lifetime parameters, + // Create generic parameters for early-bound lifetime parameters, // combining parameters from the type and those from the method. assert_eq!(generics.parent_count, parent_args.len()); @@ -546,7 +546,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> { debug!("instantiate_method_sig(pick={:?}, all_args={:?})", pick, all_args); // Instantiate the bounds on the method with the - // type/early-bound-regions instatiations performed. There can + // type/early-bound-regions instantiations performed. There can // be no late-bound regions appearing here. let def_id = pick.item.def_id; let method_predicates = self.tcx.predicates_of(def_id).instantiate(self.tcx, all_args); diff --git a/compiler/rustc_hir_typeck/src/upvar.rs b/compiler/rustc_hir_typeck/src/upvar.rs index 986453397ffcc..5789e60ebbebe 100644 --- a/compiler/rustc_hir_typeck/src/upvar.rs +++ b/compiler/rustc_hir_typeck/src/upvar.rs @@ -228,7 +228,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // coroutine bodies can't borrow from their parent closure. To fix this, // we force the inner coroutine to also be `move`. This only matters for // coroutine-closures that are `move` since otherwise they themselves will - // be borrowing from the outer environment, so there's no self-borrows occuring. + // be borrowing from the outer environment, so there's no self-borrows occurring. if let UpvarArgs::Coroutine(..) = args && let hir::CoroutineKind::Desugared(_, hir::CoroutineSource::Closure) = self.tcx.coroutine_kind(closure_def_id).expect("coroutine should have kind") diff --git a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs index 9d77afa5d2f03..1930e357fc9cc 100644 --- a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs +++ b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs @@ -51,7 +51,7 @@ impl<'tcx> InferCtxt<'tcx> { query_state, |tcx, param_env, query_state| { // FIXME(#118965): We don't canonicalize the static lifetimes that appear in the - // `param_env` beacause they are treated differently by trait selection. + // `param_env` because they are treated differently by trait selection. Canonicalizer::canonicalize( param_env, None, diff --git a/compiler/rustc_infer/src/infer/opaque_types/mod.rs b/compiler/rustc_infer/src/infer/opaque_types/mod.rs index 88db7237647cd..5ceaaf1a3c4fe 100644 --- a/compiler/rustc_infer/src/infer/opaque_types/mod.rs +++ b/compiler/rustc_infer/src/infer/opaque_types/mod.rs @@ -213,7 +213,7 @@ impl<'tcx> InferCtxt<'tcx> { /// ``` /// /// As indicating in the comments above, each of those references - /// is (in the compiler) basically generic paramters (`args`) + /// is (in the compiler) basically generic parameters (`args`) /// applied to the type of a suitable `def_id` (which identifies /// `Foo1` or `Foo2`). /// diff --git a/compiler/rustc_infer/src/infer/relate/combine.rs b/compiler/rustc_infer/src/infer/relate/combine.rs index 70b59322f5bee..f2ec1dd3df74a 100644 --- a/compiler/rustc_infer/src/infer/relate/combine.rs +++ b/compiler/rustc_infer/src/infer/relate/combine.rs @@ -153,7 +153,7 @@ impl<'tcx> InferCtxt<'tcx> { // During coherence, opaque types should be treated as *possibly* // equal to any other type (except for possibly itself). This is an - // extremely heavy hammer, but can be relaxed in a fowards-compatible + // extremely heavy hammer, but can be relaxed in a forwards-compatible // way later. (&ty::Alias(ty::Opaque, _), _) | (_, &ty::Alias(ty::Opaque, _)) if self.intercrate => { relation.register_predicates([ty::Binder::dummy(ty::PredicateKind::Ambiguous)]); diff --git a/compiler/rustc_infer/src/infer/relate/generalize.rs b/compiler/rustc_infer/src/infer/relate/generalize.rs index f257141ea6581..f2a511d7a886b 100644 --- a/compiler/rustc_infer/src/infer/relate/generalize.rs +++ b/compiler/rustc_infer/src/infer/relate/generalize.rs @@ -120,7 +120,7 @@ impl<'tcx> InferCtxt<'tcx> { } else { // NOTE: The `instantiation_variance` is not the same variance as // used by the relation. When instantiating `b`, `target_is_expected` - // is flipped and the `instantion_variance` is also flipped. To + // is flipped and the `instantiation_variance` is also flipped. To // constrain the `generalized_ty` while using the original relation, // we therefore only have to flip the arguments. // diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index 779b98d073dab..c4a38047b5e3b 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -435,7 +435,7 @@ fn write_out_deps(tcx: TyCtxt<'_>, outputs: &OutputFilenames, out_filenames: &[P escape_dep_filename(&file.prefer_local().to_string()) }; - // The entries will be used to declare dependencies beween files in a + // The entries will be used to declare dependencies between files in a // Makefile-like output, so the iteration order does not matter. #[allow(rustc::potential_query_instability)] let extra_tracked_files = diff --git a/compiler/rustc_lint/src/non_local_def.rs b/compiler/rustc_lint/src/non_local_def.rs index 13a3c741fe39b..1546d79e4fd91 100644 --- a/compiler/rustc_lint/src/non_local_def.rs +++ b/compiler/rustc_lint/src/non_local_def.rs @@ -126,7 +126,7 @@ impl<'tcx> LateLintPass<'tcx> for NonLocalDefinitions { // > same expression-containing item. // // To achieve this we get try to get the paths of the _Trait_ and - // _Type_, and we look inside thoses paths to try a find in one + // _Type_, and we look inside those paths to try a find in one // of them a type whose parent is the same as the impl definition. // // If that's the case this means that this impl block declaration diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs index c3b80e01c3624..761d30bac715a 100644 --- a/compiler/rustc_lint/src/unused.rs +++ b/compiler/rustc_lint/src/unused.rs @@ -734,7 +734,7 @@ trait UnusedDelimLint { return false; } - // Check if we need parens for `match &( Struct { feild: }) {}`. + // Check if we need parens for `match &( Struct { field: }) {}`. { let mut innermost = inner; loop { From 00de006f22f2304bddabb2d00a13af242ea21c17 Mon Sep 17 00:00:00 2001 From: Alexander Cyon Date: Mon, 2 Sep 2024 07:50:22 +0200 Subject: [PATCH 0372/2194] chore: Fix typos in 'compiler' (batch 2) --- .../src/context/diagnostics/check_cfg.rs | 2 +- compiler/rustc_middle/src/mir/consts.rs | 2 +- .../rustc_middle/src/mir/interpret/error.rs | 6 +++--- compiler/rustc_middle/src/query/mod.rs | 2 +- compiler/rustc_middle/src/ty/context.rs | 2 +- compiler/rustc_middle/src/ty/instance.rs | 2 +- compiler/rustc_middle/src/ty/mod.rs | 2 +- compiler/rustc_middle/src/ty/sty.rs | 2 +- .../src/dead_store_elimination.rs | 2 +- compiler/rustc_mir_transform/src/dest_prop.rs | 2 +- .../src/known_panics_lint.rs | 2 +- .../rustc_mir_transform/src/match_branches.rs | 20 +++++++++---------- .../rustc_mir_transform/src/promote_consts.rs | 2 +- compiler/rustc_mir_transform/src/ref_prop.rs | 2 +- compiler/rustc_monomorphize/src/collector.rs | 2 +- .../src/solve/eval_ctxt/canonical.rs | 2 +- .../rustc_next_trait_solver/src/solve/mod.rs | 2 +- .../src/solve/trait_goals.rs | 2 +- compiler/rustc_parse/src/parser/pat.rs | 2 +- compiler/rustc_passes/src/dead.rs | 4 ++-- .../rustc_pattern_analysis/src/constructor.rs | 2 +- .../tests/exhaustiveness.rs | 2 +- .../rustc_query_system/src/dep_graph/graph.rs | 2 +- compiler/rustc_resolve/messages.ftl | 2 +- compiler/rustc_resolve/src/errors.rs | 2 +- compiler/rustc_resolve/src/ident.rs | 2 +- compiler/rustc_resolve/src/late.rs | 4 ++-- compiler/rustc_resolve/src/rustdoc.rs | 2 +- .../cfi/typeid/itanium_cxx_abi/transform.rs | 6 +++--- compiler/rustc_serialize/src/opaque.rs | 2 +- compiler/rustc_session/src/config.rs | 10 +++++----- compiler/rustc_smir/src/rustc_internal/mod.rs | 2 +- compiler/rustc_span/src/hygiene.rs | 2 +- compiler/rustc_span/src/lib.rs | 4 ++-- 34 files changed, 54 insertions(+), 54 deletions(-) diff --git a/compiler/rustc_lint/src/context/diagnostics/check_cfg.rs b/compiler/rustc_lint/src/context/diagnostics/check_cfg.rs index fb3f40aa27108..ddaa819df1413 100644 --- a/compiler/rustc_lint/src/context/diagnostics/check_cfg.rs +++ b/compiler/rustc_lint/src/context/diagnostics/check_cfg.rs @@ -267,7 +267,7 @@ pub(super) fn unexpected_cfg_value( // encouraged to do so. let can_suggest_adding_value = !sess.psess.check_config.well_known_names.contains(&name) // Except when working on rustc or the standard library itself, in which case we want to - // suggest adding these cfgs to the "normal" place because of bootstraping reasons. As a + // suggest adding these cfgs to the "normal" place because of bootstrapping reasons. As a // basic heuristic, we use the "cheat" unstable feature enable method and the // non-ui-testing enabled option. || (matches!(sess.psess.unstable_features, rustc_feature::UnstableFeatures::Cheat) diff --git a/compiler/rustc_middle/src/mir/consts.rs b/compiler/rustc_middle/src/mir/consts.rs index 563647ad4e678..c6105d1f383b1 100644 --- a/compiler/rustc_middle/src/mir/consts.rs +++ b/compiler/rustc_middle/src/mir/consts.rs @@ -240,7 +240,7 @@ impl<'tcx> Const<'tcx> { match self { Const::Ty(ty, ct) => { match ct.kind() { - // Dont use the outter ty as on invalid code we can wind up with them not being the same. + // Dont use the outer ty as on invalid code we can wind up with them not being the same. // this then results in allowing const eval to add `1_i64 + 1_usize` in cases where the mir // was originally `({N: usize} + 1_usize)` under `generic_const_exprs`. ty::ConstKind::Value(ty, _) => ty, diff --git a/compiler/rustc_middle/src/mir/interpret/error.rs b/compiler/rustc_middle/src/mir/interpret/error.rs index 69ce3e087350b..8c89c15f9611d 100644 --- a/compiler/rustc_middle/src/mir/interpret/error.rs +++ b/compiler/rustc_middle/src/mir/interpret/error.rs @@ -91,9 +91,9 @@ pub type EvalToAllocationRawResult<'tcx> = Result, ErrorHandled pub type EvalStaticInitializerRawResult<'tcx> = Result, ErrorHandled>; pub type EvalToConstValueResult<'tcx> = Result, ErrorHandled>; /// `Ok(Err(ty))` indicates the constant was fine, but the valtree couldn't be constructed -/// because the value containts something of type `ty` that is not valtree-compatible. +/// because the value contains something of type `ty` that is not valtree-compatible. /// The caller can then show an appropriate error; the query does not have the -/// necssary context to give good user-facing errors for this case. +/// necessary context to give good user-facing errors for this case. pub type EvalToValTreeResult<'tcx> = Result, Ty<'tcx>>, ErrorHandled>; #[cfg(target_pointer_width = "64")] @@ -231,7 +231,7 @@ pub enum CheckInAllocMsg { pub enum CheckAlignMsg { /// The accessed pointer did not have proper alignment. AccessedPtr, - /// The access ocurred with a place that was based on a misaligned pointer. + /// The access occurred with a place that was based on a misaligned pointer. BasedOn, } diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index b6443778c936b..71b8cfcc46e3d 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -327,7 +327,7 @@ rustc_queries! { } } - /// Returns the list of bounds that are required to be satsified + /// Returns the list of bounds that are required to be satisfied /// by a implementation or definition. For associated types, these /// must be satisfied for an implementation to be well-formed, /// and for opaque types, these are required to be satisfied by diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 43dda252f835e..20828067c469c 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -1475,7 +1475,7 @@ impl<'tcx> TyCtxt<'tcx> { /// provides a `TyCtxt`. /// /// By only providing the `TyCtxt` inside of the closure we enforce that the type - /// context and any interned alue (types, args, etc.) can only be used while `ty::tls` + /// context and any interned value (types, args, etc.) can only be used while `ty::tls` /// has a valid reference to the context, to allow formatting values that need it. pub fn create_global_ctxt( s: &'tcx Session, diff --git a/compiler/rustc_middle/src/ty/instance.rs b/compiler/rustc_middle/src/ty/instance.rs index 7d5f0f1e9c415..072951d131917 100644 --- a/compiler/rustc_middle/src/ty/instance.rs +++ b/compiler/rustc_middle/src/ty/instance.rs @@ -38,7 +38,7 @@ pub struct Instance<'tcx> { pub args: GenericArgsRef<'tcx>, } -/// Describes why a `ReifyShim` was created. This is needed to distingish a ReifyShim created to +/// Describes why a `ReifyShim` was created. This is needed to distinguish a ReifyShim created to /// adjust for things like `#[track_caller]` in a vtable from a `ReifyShim` created to produce a /// function pointer from a vtable entry. /// Currently, this is only used when KCFI is enabled, as only KCFI needs to treat those two diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index e41ea7507efff..cd94c0afad0a9 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -1819,7 +1819,7 @@ impl<'tcx> TyCtxt<'tcx> { self.get_attrs(did, attr).next().is_some() } - /// Determines whether an item is annotated with a multi-segement attribute + /// Determines whether an item is annotated with a multi-segment attribute pub fn has_attrs_with_path(self, did: impl Into, attrs: &[Symbol]) -> bool { self.get_attrs_by_path(did.into(), attrs).next().is_some() } diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index b144fd0feb00e..89ef30fa768e0 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -1930,7 +1930,7 @@ impl<'tcx> Ty<'tcx> { /// Returns `true` when the outermost type cannot be further normalized, /// resolved, or instantiated. This includes all primitive types, but also - /// things like ADTs and trait objects, sice even if their arguments or + /// things like ADTs and trait objects, since even if their arguments or /// nested types may be further simplified, the outermost [`TyKind`] or /// type constructor remains the same. pub fn is_known_rigid(self) -> bool { diff --git a/compiler/rustc_mir_transform/src/dead_store_elimination.rs b/compiler/rustc_mir_transform/src/dead_store_elimination.rs index f473073083af4..39c8db184a5a2 100644 --- a/compiler/rustc_mir_transform/src/dead_store_elimination.rs +++ b/compiler/rustc_mir_transform/src/dead_store_elimination.rs @@ -32,7 +32,7 @@ pub fn eliminate<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { let borrowed_locals = borrowed_locals(body); // If the user requests complete debuginfo, mark the locals that appear in it as live, so - // we don't remove assignements to them. + // we don't remove assignments to them. let mut always_live = debuginfo_locals(body); always_live.union(&borrowed_locals); diff --git a/compiler/rustc_mir_transform/src/dest_prop.rs b/compiler/rustc_mir_transform/src/dest_prop.rs index a530dccf96b27..a6d626d3f8ff5 100644 --- a/compiler/rustc_mir_transform/src/dest_prop.rs +++ b/compiler/rustc_mir_transform/src/dest_prop.rs @@ -38,7 +38,7 @@ //! not contain any indirection through a pointer or any indexing projections. //! //! * `p` and `q` must have the **same type**. If we replace a local with a subtype or supertype, -//! we may end up with a differnet vtable for that local. See the `subtyping-impacts-selection` +//! we may end up with a different vtable for that local. See the `subtyping-impacts-selection` //! tests for an example where that causes issues. //! //! * We need to make sure that the goal of "merging the memory" is actually structurally possible diff --git a/compiler/rustc_mir_transform/src/known_panics_lint.rs b/compiler/rustc_mir_transform/src/known_panics_lint.rs index 443d97d004e16..15d71ee2ac81f 100644 --- a/compiler/rustc_mir_transform/src/known_panics_lint.rs +++ b/compiler/rustc_mir_transform/src/known_panics_lint.rs @@ -914,7 +914,7 @@ impl<'tcx> Visitor<'tcx> for CanConstProp { fn visit_place(&mut self, place: &Place<'tcx>, mut context: PlaceContext, loc: Location) { use rustc_middle::mir::visit::PlaceContext::*; - // Dereferencing just read the addess of `place.local`. + // Dereferencing just read the address of `place.local`. if place.projection.first() == Some(&PlaceElem::Deref) { context = NonMutatingUse(NonMutatingUseContext::Copy); } diff --git a/compiler/rustc_mir_transform/src/match_branches.rs b/compiler/rustc_mir_transform/src/match_branches.rs index 47758b56f8c90..5240f1c887c5c 100644 --- a/compiler/rustc_mir_transform/src/match_branches.rs +++ b/compiler/rustc_mir_transform/src/match_branches.rs @@ -289,7 +289,7 @@ fn can_cast( #[derive(Default)] struct SimplifyToExp { - transfrom_kinds: Vec, + transform_kinds: Vec, } #[derive(Clone, Copy)] @@ -302,17 +302,17 @@ enum ExpectedTransformKind<'tcx, 'a> { Cast { place: &'a Place<'tcx>, ty: Ty<'tcx> }, } -enum TransfromKind { +enum TransformKind { Same, Cast, } -impl From> for TransfromKind { +impl From> for TransformKind { fn from(compare_type: ExpectedTransformKind<'_, '_>) -> Self { match compare_type { - ExpectedTransformKind::Same(_) => TransfromKind::Same, - ExpectedTransformKind::SameByEq { .. } => TransfromKind::Same, - ExpectedTransformKind::Cast { .. } => TransfromKind::Cast, + ExpectedTransformKind::Same(_) => TransformKind::Same, + ExpectedTransformKind::SameByEq { .. } => TransformKind::Same, + ExpectedTransformKind::Cast { .. } => TransformKind::Cast, } } } @@ -475,7 +475,7 @@ impl<'tcx> SimplifyMatch<'tcx> for SimplifyToExp { } } } - self.transfrom_kinds = expected_transform_kinds.into_iter().map(|c| c.into()).collect(); + self.transform_kinds = expected_transform_kinds.into_iter().map(|c| c.into()).collect(); Some(()) } @@ -493,13 +493,13 @@ impl<'tcx> SimplifyMatch<'tcx> for SimplifyToExp { let (_, first) = targets.iter().next().unwrap(); let first = &bbs[first]; - for (t, s) in iter::zip(&self.transfrom_kinds, &first.statements) { + for (t, s) in iter::zip(&self.transform_kinds, &first.statements) { match (t, &s.kind) { - (TransfromKind::Same, _) => { + (TransformKind::Same, _) => { patch.add_statement(parent_end, s.kind.clone()); } ( - TransfromKind::Cast, + TransformKind::Cast, StatementKind::Assign(box (lhs, Rvalue::Use(Operand::Constant(f_c)))), ) => { let operand = Operand::Copy(Place::from(discr_local)); diff --git a/compiler/rustc_mir_transform/src/promote_consts.rs b/compiler/rustc_mir_transform/src/promote_consts.rs index f2610fd52bc12..0c940bac13c0b 100644 --- a/compiler/rustc_mir_transform/src/promote_consts.rs +++ b/compiler/rustc_mir_transform/src/promote_consts.rs @@ -498,7 +498,7 @@ impl<'tcx> Validator<'_, 'tcx> { Some(x) if x != 0 => {} // okay _ => return Err(Unpromotable), // value not known or 0 -- not okay } - // Furthermore, for signed divison, we also have to exclude `int::MIN / -1`. + // Furthermore, for signed division, we also have to exclude `int::MIN / -1`. if lhs_ty.is_signed() { match rhs_val.map(|x| x.to_int(sz)) { Some(-1) | None => { diff --git a/compiler/rustc_mir_transform/src/ref_prop.rs b/compiler/rustc_mir_transform/src/ref_prop.rs index 2b07c04a12130..8d0b47cb34a8f 100644 --- a/compiler/rustc_mir_transform/src/ref_prop.rs +++ b/compiler/rustc_mir_transform/src/ref_prop.rs @@ -345,7 +345,7 @@ fn fully_replacable_locals(ssa: &SsaLocals) -> BitSet { replacable } -/// Utility to help performing subtitution of `*pattern` by `target`. +/// Utility to help performing substitution of `*pattern` by `target`. struct Replacer<'tcx> { tcx: TyCtxt<'tcx>, targets: IndexVec>, diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs index 9c820b888d910..8515ab45de217 100644 --- a/compiler/rustc_monomorphize/src/collector.rs +++ b/compiler/rustc_monomorphize/src/collector.rs @@ -397,7 +397,7 @@ fn collect_items_rec<'tcx>( MonoItem::Static(def_id) => { recursion_depth_reset = None; - // Statics always get evaluted (which is possible because they can't be generic), so for + // Statics always get evaluated (which is possible because they can't be generic), so for // `MentionedItems` collection there's nothing to do here. if mode == CollectionMode::UsedItems { let instance = Instance::mono(tcx, def_id); diff --git a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/canonical.rs b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/canonical.rs index 2e521ddcec322..1c00f5f8b4173 100644 --- a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/canonical.rs +++ b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/canonical.rs @@ -238,7 +238,7 @@ where (normalization_nested_goals.clone(), certainty) } - /// This returns the canoncial variable values to instantiate the bound variables of + /// This returns the canonical variable values to instantiate the bound variables of /// the canonical response. This depends on the `original_values` for the /// bound variables. fn compute_query_response_instantiation_values>( diff --git a/compiler/rustc_next_trait_solver/src/solve/mod.rs b/compiler/rustc_next_trait_solver/src/solve/mod.rs index c65c5851e9b4f..536b502136ad3 100644 --- a/compiler/rustc_next_trait_solver/src/solve/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/mod.rs @@ -164,7 +164,7 @@ where // - `Bound` cannot exist as we don't have a binder around the self Type // - `Expr` is part of `feature(generic_const_exprs)` and is not implemented yet ty::ConstKind::Param(_) | ty::ConstKind::Bound(_, _) | ty::ConstKind::Expr(_) => { - panic!("unexpect const kind: {:?}", ct) + panic!("unexpected const kind: {:?}", ct) } } } diff --git a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs index 1314b7eb6ffc6..67b001d0cceda 100644 --- a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs +++ b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs @@ -628,7 +628,7 @@ where } // FIXME: This actually should destructure the `Result` we get from transmutability and - // register candiates. We probably need to register >1 since we may have an OR of ANDs. + // register candidates. We probably need to register >1 since we may have an OR of ANDs. ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| { let certainty = ecx.is_transmutable( goal.param_env, diff --git a/compiler/rustc_parse/src/parser/pat.rs b/compiler/rustc_parse/src/parser/pat.rs index 8233f9a79435f..f87b564965469 100644 --- a/compiler/rustc_parse/src/parser/pat.rs +++ b/compiler/rustc_parse/src/parser/pat.rs @@ -402,7 +402,7 @@ impl<'a> Parser<'a> { let non_assoc_span = expr.span; // Parse an associative expression such as `+ expr`, `% expr`, ... - // Assignements, ranges and `|` are disabled by [`Restrictions::IS_PAT`]. + // Assignments, ranges and `|` are disabled by [`Restrictions::IS_PAT`]. if let Ok((expr, _)) = snapshot.parse_expr_assoc_rest_with(0, false, expr).map_err(|err| err.cancel()) { diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs index 7ae5c9040042c..7f1e906ffd737 100644 --- a/compiler/rustc_passes/src/dead.rs +++ b/compiler/rustc_passes/src/dead.rs @@ -439,7 +439,7 @@ impl<'tcx> MarkSymbolVisitor<'tcx> { _ => intravisit::walk_item(self, item), }, Node::TraitItem(trait_item) => { - // mark corresponing ImplTerm live + // mark corresponding ImplTerm live let trait_item_id = trait_item.owner_id.to_def_id(); if let Some(trait_id) = self.tcx.trait_of_item(trait_item_id) { // mark the trait live @@ -1035,7 +1035,7 @@ impl<'tcx> DeadVisitor<'tcx> { }; let encl_def_id = parent_item.unwrap_or(first_item.def_id); - // If parent of encl_def_id is an enum, use the parent ID intead. + // If parent of encl_def_id is an enum, use the parent ID instead. let encl_def_id = get_parent_if_enum_variant(tcx, encl_def_id); let ignored_derived_impls = diff --git a/compiler/rustc_pattern_analysis/src/constructor.rs b/compiler/rustc_pattern_analysis/src/constructor.rs index 3a2a75a638f79..e4edd7befb76f 100644 --- a/compiler/rustc_pattern_analysis/src/constructor.rs +++ b/compiler/rustc_pattern_analysis/src/constructor.rs @@ -288,7 +288,7 @@ impl IntRange { /// Best effort; will not know that e.g. `255u8..` is a singleton. pub fn is_singleton(&self) -> bool { // Since `lo` and `hi` can't be the same `Infinity` and `plus_one` never changes from finite - // to infinite, this correctly only detects ranges that contain exacly one `Finite(x)`. + // to infinite, this correctly only detects ranges that contain exactly one `Finite(x)`. self.lo.plus_one() == Some(self.hi) } diff --git a/compiler/rustc_pattern_analysis/tests/exhaustiveness.rs b/compiler/rustc_pattern_analysis/tests/exhaustiveness.rs index 2192940d4d716..af093db782cde 100644 --- a/compiler/rustc_pattern_analysis/tests/exhaustiveness.rs +++ b/compiler/rustc_pattern_analysis/tests/exhaustiveness.rs @@ -22,7 +22,7 @@ fn check(patterns: Vec>) -> Vec> { fn assert_exhaustive(patterns: Vec>) { let witnesses = check(patterns); if !witnesses.is_empty() { - panic!("non-exaustive match: missing {witnesses:?}"); + panic!("non-exhaustive match: missing {witnesses:?}"); } } diff --git a/compiler/rustc_query_system/src/dep_graph/graph.rs b/compiler/rustc_query_system/src/dep_graph/graph.rs index b6aa1d5a43bb8..eb3eddf34aa3e 100644 --- a/compiler/rustc_query_system/src/dep_graph/graph.rs +++ b/compiler/rustc_query_system/src/dep_graph/graph.rs @@ -1405,7 +1405,7 @@ fn panic_on_forbidden_read(data: &DepGraphData, dep_node_index: DepN "Error: trying to record dependency on DepNode {dep_node} in a \ context that does not allow it (e.g. during query deserialization). \ The most common case of recording a dependency on a DepNode `foo` is \ - when the correspondng query `foo` is invoked. Invoking queries is not \ + when the corresponding query `foo` is invoked. Invoking queries is not \ allowed as part of loading something from the incremental on-disk cache. \ See ." ) diff --git a/compiler/rustc_resolve/messages.ftl b/compiler/rustc_resolve/messages.ftl index 73d1a2ea49a13..6602c7889691f 100644 --- a/compiler/rustc_resolve/messages.ftl +++ b/compiler/rustc_resolve/messages.ftl @@ -11,7 +11,7 @@ resolve_added_macro_use = resolve_ancestor_only = visibilities can only be restricted to ancestor modules -resolve_anonymous_livetime_non_gat_report_error = +resolve_anonymous_lifetime_non_gat_report_error = in the trait associated type is declared without lifetime parameters, so using a borrowed type for them requires that lifetime to come from the implemented type .label = this lifetime must come from the implemented type diff --git a/compiler/rustc_resolve/src/errors.rs b/compiler/rustc_resolve/src/errors.rs index 662b772413b86..58834d0a2b3a6 100644 --- a/compiler/rustc_resolve/src/errors.rs +++ b/compiler/rustc_resolve/src/errors.rs @@ -894,7 +894,7 @@ pub(crate) struct LendingIteratorReportError { } #[derive(Diagnostic)] -#[diag(resolve_anonymous_livetime_non_gat_report_error)] +#[diag(resolve_anonymous_lifetime_non_gat_report_error)] pub(crate) struct AnonymousLivetimeNonGatReportError { #[primary_span] #[label] diff --git a/compiler/rustc_resolve/src/ident.rs b/compiler/rustc_resolve/src/ident.rs index 149c639efab86..87f8e51f28231 100644 --- a/compiler/rustc_resolve/src/ident.rs +++ b/compiler/rustc_resolve/src/ident.rs @@ -445,7 +445,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } } Scope::DeriveHelpersCompat => { - // FIXME: Try running this logic eariler, to allocate name bindings for + // FIXME: Try running this logic earlier, to allocate name bindings for // legacy derive helpers when creating an attribute invocation with // following derives. Legacy derive helpers are not common, so it shouldn't // affect performance. It should also allow to remove the `derives` diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index a0386ddcbb37e..79c42456cf8c9 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -133,7 +133,7 @@ pub(crate) enum NoConstantGenericsReason { /// Const arguments are only allowed to use generic parameters when: /// - `feature(generic_const_exprs)` is enabled /// or - /// - the const argument is a sole const generic paramater, i.e. `foo::<{ N }>()` + /// - the const argument is a sole const generic parameter, i.e. `foo::<{ N }>()` /// /// If neither of the above are true then this is used as the cause. NonTrivialConstArg, @@ -4486,7 +4486,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { /// There are a few places that we need to resolve an anon const but we did not parse an /// anon const so cannot provide an `&'ast AnonConst`. Right now this is just unbraced - /// const arguments that were parsed as type arguments, and `legact_const_generics` which + /// const arguments that were parsed as type arguments, and `legacy_const_generics` which /// parse as normal function argument expressions. To avoid duplicating the code for resolving /// an anon const we have this function which lets the caller manually call `resolve_expr` or /// `smart_resolve_path`. diff --git a/compiler/rustc_resolve/src/rustdoc.rs b/compiler/rustc_resolve/src/rustdoc.rs index de4fc5c27d40a..976c4acb212f5 100644 --- a/compiler/rustc_resolve/src/rustdoc.rs +++ b/compiler/rustc_resolve/src/rustdoc.rs @@ -417,7 +417,7 @@ pub(crate) fn attrs_to_preprocessed_links(attrs: &[ast::Attribute]) -> Vec(doc: &'md str) -> Vec> { let mut broken_link_callback = |link: BrokenLink<'md>| Some((link.reference, "".into())); diff --git a/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/transform.rs b/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/transform.rs index 2f43199796cc6..5b2062e0b0ab3 100644 --- a/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/transform.rs +++ b/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/transform.rs @@ -262,7 +262,7 @@ fn trait_object_ty<'tcx>(tcx: TyCtxt<'tcx>, poly_trait_ref: ty::PolyTraitRef<'tc /// mangling. /// /// typeid_for_instance is called at two locations, initially when declaring/defining functions and -/// methods, and later during code generation at call sites, after type erasure might have ocurred. +/// methods, and later during code generation at call sites, after type erasure might have occurred. /// /// In the first call (i.e., when declaring/defining functions and methods), it encodes type ids for /// an FnAbi or Instance, and these type ids are attached to functions and methods. (These type ids @@ -270,7 +270,7 @@ fn trait_object_ty<'tcx>(tcx: TyCtxt<'tcx>, poly_trait_ref: ty::PolyTraitRef<'tc /// these type ids.) /// /// In the second call (i.e., during code generation at call sites), it encodes a type id for an -/// FnAbi or Instance, after type erasure might have occured, and this type id is used for testing +/// FnAbi or Instance, after type erasure might have occurred, and this type id is used for testing /// if a function is member of the group derived from this type id. Therefore, in the first call to /// typeid_for_fnabi (when type ids are attached to functions and methods), it can only include at /// most as much information that would be available in the second call (i.e., during code @@ -365,7 +365,7 @@ pub fn transform_instance<'tcx>( // of the trait that defines the method. if let Some((trait_ref, method_id, ancestor)) = implemented_method(tcx, instance) { // Trait methods will have a Self polymorphic parameter, where the concreteized - // implementatation will not. We need to walk back to the more general trait method + // implementation will not. We need to walk back to the more general trait method let trait_ref = tcx.instantiate_and_normalize_erasing_regions( instance.args, ty::ParamEnv::reveal_all(), diff --git a/compiler/rustc_serialize/src/opaque.rs b/compiler/rustc_serialize/src/opaque.rs index d8609ccfe429f..c7c561156e35b 100644 --- a/compiler/rustc_serialize/src/opaque.rs +++ b/compiler/rustc_serialize/src/opaque.rs @@ -159,7 +159,7 @@ impl FileEncoder { // We produce a post-mono error if N > BUF_SIZE. let buf = unsafe { self.buffer_empty().first_chunk_mut::().unwrap_unchecked() }; let written = visitor(buf); - // We have to ensure that an errant visitor cannot cause self.buffered to exeed BUF_SIZE. + // We have to ensure that an errant visitor cannot cause self.buffered to exceed BUF_SIZE. if written > N { Self::panic_invalid_write::(written); } diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index 945bab6887e69..908d50a041ef1 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -251,7 +251,7 @@ pub struct LinkSelfContained { pub explicitly_set: Option, /// The components that are enabled on the CLI, using the `+component` syntax or one of the - /// `true` shorcuts. + /// `true` shortcuts. enabled_components: LinkSelfContainedComponents, /// The components that are disabled on the CLI, using the `-component` syntax or one of the @@ -313,13 +313,13 @@ impl LinkSelfContained { } /// Returns whether the self-contained linker component was enabled on the CLI, using the - /// `-C link-self-contained=+linker` syntax, or one of the `true` shorcuts. + /// `-C link-self-contained=+linker` syntax, or one of the `true` shortcuts. pub fn is_linker_enabled(&self) -> bool { self.enabled_components.contains(LinkSelfContainedComponents::LINKER) } /// Returns whether the self-contained linker component was disabled on the CLI, using the - /// `-C link-self-contained=-linker` syntax, or one of the `false` shorcuts. + /// `-C link-self-contained=-linker` syntax, or one of the `false` shortcuts. pub fn is_linker_disabled(&self) -> bool { self.disabled_components.contains(LinkSelfContainedComponents::LINKER) } @@ -360,7 +360,7 @@ impl LinkerFeaturesCli { // Duplicate flags are reduced as we go, the last occurrence wins: // `+feature,-feature,+feature` only enables the feature, and does not record it as both // enabled and disabled on the CLI. - // We also only expose `+/-lld` at the moment, as it's currenty the only implemented linker + // We also only expose `+/-lld` at the moment, as it's currently the only implemented linker // feature and toggling `LinkerFeatures::CC` would be a noop. match feature { "+lld" => { @@ -1102,7 +1102,7 @@ bitflags::bitflags! { const MACRO = 1 << 0; /// Apply remappings to printed compiler diagnostics const DIAGNOSTICS = 1 << 1; - /// Apply remappings to debug informations + /// Apply remappings to debug information const DEBUGINFO = 1 << 3; /// An alias for `macro` and `debuginfo`. This ensures all paths in compiled diff --git a/compiler/rustc_smir/src/rustc_internal/mod.rs b/compiler/rustc_smir/src/rustc_internal/mod.rs index e997ea25ec863..a3aa589cb643e 100644 --- a/compiler/rustc_smir/src/rustc_internal/mod.rs +++ b/compiler/rustc_smir/src/rustc_internal/mod.rs @@ -397,7 +397,7 @@ macro_rules! run_driver { }}; } -/// Simmilar to rustc's `FxIndexMap`, `IndexMap` with extra +/// Similar to rustc's `FxIndexMap`, `IndexMap` with extra /// safety features added. pub struct IndexMap { index_map: fx::FxIndexMap, diff --git a/compiler/rustc_span/src/hygiene.rs b/compiler/rustc_span/src/hygiene.rs index 5e1b1b44bc2a2..463e0dbc30ce5 100644 --- a/compiler/rustc_span/src/hygiene.rs +++ b/compiler/rustc_span/src/hygiene.rs @@ -1358,7 +1358,7 @@ pub fn decode_syntax_context SyntaxContext let mut inner = context.inner.lock(); if let Some(ctxt) = inner.remapped_ctxts.get(raw_id as usize).copied().flatten() { - // This has already beeen decoded. + // This has already been decoded. return ctxt; } diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs index 7b020f11cdda0..a6ec15d5d3641 100644 --- a/compiler/rustc_span/src/lib.rs +++ b/compiler/rustc_span/src/lib.rs @@ -271,7 +271,7 @@ impl RealFileName { } } - /// Return the path remmapped or not depending on the [`FileNameDisplayPreference`]. + /// Return the path remapped or not depending on the [`FileNameDisplayPreference`]. /// /// For the purpose of this function, local and short preference are equal. pub fn to_path(&self, display_pref: FileNameDisplayPreference) -> &Path { @@ -1683,7 +1683,7 @@ impl fmt::Debug for SourceFile { /// is because SourceFiles for the local crate are allocated very early in the /// compilation process when the `StableCrateId` is not yet known. If, due to /// some refactoring of the compiler, the `StableCrateId` of the local crate -/// were to become available, it would be better to uniformely make this a +/// were to become available, it would be better to uniformly make this a /// hash of `(filename, stable_crate_id)`. /// /// When `SourceFile`s are exported in crate metadata, the `StableSourceFileId` From 59b42b92e7fe506a083e194aee2281525f8199c4 Mon Sep 17 00:00:00 2001 From: Alexander Cyon Date: Mon, 2 Sep 2024 07:54:55 +0200 Subject: [PATCH 0373/2194] chore: Fix some typos --- src/debuginfo.rs | 4 ++-- src/lib.rs | 2 +- tools/generate_intrinsics.py | 10 +++++----- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/debuginfo.rs b/src/debuginfo.rs index 3d9ea278a6399..876386428835f 100644 --- a/src/debuginfo.rs +++ b/src/debuginfo.rs @@ -50,7 +50,7 @@ impl<'a, 'gcc, 'tcx> DebugInfoBuilderMethods for Builder<'a, 'gcc, 'tcx> { } /// Generate the `debug_context` in an MIR Body. -/// # Souce of Origin +/// # Source of Origin /// Copied from `create_scope_map.rs` of rustc_codegen_llvm fn compute_mir_scopes<'gcc, 'tcx>( cx: &CodegenCx<'gcc, 'tcx>, @@ -85,7 +85,7 @@ fn compute_mir_scopes<'gcc, 'tcx>( /// Update the `debug_context`, adding new scope to it, /// if it's not added as is denoted in `instantiated`. /// -/// # Souce of Origin +/// # Source of Origin /// Copied from `create_scope_map.rs` of rustc_codegen_llvm /// FIXME(tempdragon/?): Add Scope Support Here. fn make_mir_scope<'gcc, 'tcx>( diff --git a/src/lib.rs b/src/lib.rs index 1132b0cd2f5ab..c11a183acde52 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -360,7 +360,7 @@ impl Deref for SyncContext { unsafe impl Send for SyncContext {} // FIXME(antoyo): that shouldn't be Sync. Parallel compilation is currently disabled with "-Zno-parallel-llvm". -// TODO: disable it here by returing false in CodegenBackend::supports_parallel(). +// TODO: disable it here by returning false in CodegenBackend::supports_parallel(). unsafe impl Sync for SyncContext {} impl WriteBackendMethods for GccCodegenBackend { diff --git a/tools/generate_intrinsics.py b/tools/generate_intrinsics.py index 90fb7bfad27c3..8efed3e43af85 100644 --- a/tools/generate_intrinsics.py +++ b/tools/generate_intrinsics.py @@ -45,7 +45,7 @@ def convert_to_string(content): return content -def extract_instrinsics_from_llvm(llvm_path, intrinsics): +def extract_intrinsics_from_llvm(llvm_path, intrinsics): command = ["llvm-tblgen", "llvm/IR/Intrinsics.td"] cwd = os.path.join(llvm_path, "llvm/include") print("=> Running command `{}` from `{}`".format(command, cwd)) @@ -88,7 +88,7 @@ def append_translation(json_data, p, array): append_intrinsic(array, content[1], content[3]) -def extract_instrinsics_from_llvmint(llvmint, intrinsics): +def extract_intrinsics_from_llvmint(llvmint, intrinsics): archs = [ "AMDGPU", "aarch64", @@ -152,9 +152,9 @@ def update_intrinsics(llvm_path, llvmint, llvmint2): intrinsics_llvmint = {} all_intrinsics = {} - extract_instrinsics_from_llvm(llvm_path, intrinsics_llvm) - extract_instrinsics_from_llvmint(llvmint, intrinsics_llvmint) - extract_instrinsics_from_llvmint(llvmint2, intrinsics_llvmint) + extract_intrinsics_from_llvm(llvm_path, intrinsics_llvm) + extract_intrinsics_from_llvmint(llvmint, intrinsics_llvmint) + extract_intrinsics_from_llvmint(llvmint2, intrinsics_llvmint) intrinsics = {} # We give priority to translations from LLVM over the ones from llvmint. From a178559a03a11b5f6e716045e1b486ca29b2d543 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Rakic?= Date: Mon, 2 Sep 2024 08:37:55 +0000 Subject: [PATCH 0374/2194] address review comments --- .../run-make/rustc-crates-on-stable/rmake.rs | 66 +++++++++---------- 1 file changed, 30 insertions(+), 36 deletions(-) diff --git a/tests/run-make/rustc-crates-on-stable/rmake.rs b/tests/run-make/rustc-crates-on-stable/rmake.rs index 48b8551ecef7c..81cc775c91997 100644 --- a/tests/run-make/rustc-crates-on-stable/rmake.rs +++ b/tests/run-make/rustc-crates-on-stable/rmake.rs @@ -1,42 +1,36 @@ //! Checks if selected rustc crates can be compiled on the stable channel (or a "simulation" of it). //! These crates are designed to be used by downstream users. -use run_make_support::{cargo, run_in_tmpdir, rustc_path, source_root}; +use run_make_support::{cargo, rustc_path, source_root}; fn main() { - run_in_tmpdir(|| { - // Use the stage0 beta cargo for the compilation (it shouldn't really matter which cargo we - // use) - let cargo = cargo() - // Ensure `proc-macro2`'s nightly detection is disabled - .env("RUSTC_STAGE", "0") - .env("RUSTC", rustc_path()) - // We want to disallow all nightly features to simulate a stable build - .env("RUSTFLAGS", "-Zallow-features=") - .arg("build") - .arg("--manifest-path") - .arg(source_root().join("Cargo.toml")) - .args(&[ - "--config", - r#"workspace.exclude=["library/core"]"#, - // Avoid depending on transitive rustc crates - "--no-default-features", - // Emit artifacts in this temporary directory, not in the source_root's `target` - // folder - "--target-dir", - ".", - ]) - // Check that these crates can be compiled on "stable" - .args(&[ - "-p", - "rustc_type_ir", - "-p", - "rustc_next_trait_solver", - "-p", - "rustc_pattern_analysis", - "-p", - "rustc_lexer", - ]) - .run(); - }); + // Use the stage0 beta cargo for the compilation (it shouldn't really matter which cargo we use) + cargo() + // Ensure `proc-macro2`'s nightly detection is disabled + .env("RUSTC_STAGE", "0") + .env("RUSTC", rustc_path()) + // We want to disallow all nightly features to simulate a stable build + .env("RUSTFLAGS", "-Zallow-features=") + .arg("build") + .arg("--manifest-path") + .arg(source_root().join("Cargo.toml")) + .args(&[ + // Avoid depending on transitive rustc crates + "--no-default-features", + // Emit artifacts in this temporary directory, not in the source_root's `target` folder + "--target-dir", + "target", + ]) + // Check that these crates can be compiled on "stable" + .args(&[ + "-p", + "rustc_type_ir", + "-p", + "rustc_next_trait_solver", + "-p", + "rustc_pattern_analysis", + "-p", + "rustc_lexer", + ]) + .run(); } From ddb1e41e5034ccc519873c93e7f0efd8b85e6b90 Mon Sep 17 00:00:00 2001 From: cuishuang Date: Mon, 2 Sep 2024 18:21:19 +0800 Subject: [PATCH 0375/2194] chore: fix some comments Signed-off-by: cuishuang --- .../rust-analyzer/crates/hir/src/semantics/source_to_def.rs | 2 +- src/tools/rust-analyzer/crates/intern/src/symbol/symbols.rs | 2 +- src/tools/rust-analyzer/crates/rust-analyzer/src/cli/scip.rs | 2 +- src/tools/rust-analyzer/crates/span/src/hygiene.rs | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/tools/rust-analyzer/crates/hir/src/semantics/source_to_def.rs b/src/tools/rust-analyzer/crates/hir/src/semantics/source_to_def.rs index 09df639d4a810..edeb19030ac00 100644 --- a/src/tools/rust-analyzer/crates/hir/src/semantics/source_to_def.rs +++ b/src/tools/rust-analyzer/crates/hir/src/semantics/source_to_def.rs @@ -281,7 +281,7 @@ impl SourceToDefCtx<'_, '_> { let (body, source_map) = self.db.body_with_source_map(container); let src = src.cloned().map(ast::Pat::from); let pat_id = source_map.node_pat(src.as_ref())?; - // the pattern could resolve to a constant, verify that that is not the case + // the pattern could resolve to a constant, verify that this is not the case if let crate::Pat::Bind { id, .. } = body[pat_id] { Some((container, id)) } else { diff --git a/src/tools/rust-analyzer/crates/intern/src/symbol/symbols.rs b/src/tools/rust-analyzer/crates/intern/src/symbol/symbols.rs index f48daba54e7b7..60070b8850f0d 100644 --- a/src/tools/rust-analyzer/crates/intern/src/symbol/symbols.rs +++ b/src/tools/rust-analyzer/crates/intern/src/symbol/symbols.rs @@ -15,7 +15,7 @@ macro_rules! define_symbols { (@WITH_NAME: $($alias:ident = $value:literal,)* @PLAIN: $($name:ident,)*) => { // Ideally we would be emitting `const` here, but then we no longer have stable addresses // which is what we are relying on for equality! In the future if consts can refer to - // statics we should swap these for `const`s and have the the string literal being pointed + // statics we should swap these for `const`s and have the string literal being pointed // to be statics to refer to such that their address is stable. $( pub static $name: Symbol = Symbol { repr: TaggedArcPtr::non_arc(&stringify!($name)) }; diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/scip.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/scip.rs index b92713129df07..e9198977dea50 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/scip.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/scip.rs @@ -142,7 +142,7 @@ impl flags::Scip { let mut symbol_roles = Default::default(); if let Some(def) = token.definition { - // if the the range of the def and the range of the token are the same, this must be the definition. + // if the range of the def and the range of the token are the same, this must be the definition. // they also must be in the same file. See https://github.com/rust-lang/rust-analyzer/pull/17988 if def.file_id == file_id && def.range == text_range { symbol_roles |= scip_types::SymbolRole::Definition as i32; diff --git a/src/tools/rust-analyzer/crates/span/src/hygiene.rs b/src/tools/rust-analyzer/crates/span/src/hygiene.rs index 874480c59fbf3..cb9c092f5fcd0 100644 --- a/src/tools/rust-analyzer/crates/span/src/hygiene.rs +++ b/src/tools/rust-analyzer/crates/span/src/hygiene.rs @@ -81,7 +81,7 @@ pub struct SyntaxContextData { /// Invariant: Only [`SyntaxContextId::ROOT`] has a [`None`] outer expansion. // FIXME: The None case needs to encode the context crate id. We can encode that as the MSB of // MacroCallId is reserved anyways so we can do bit tagging here just fine. - // The bigger issue is that that will cause interning to now create completely separate chains + // The bigger issue is that this will cause interning to now create completely separate chains // per crate. Though that is likely not a problem as `MacroCallId`s are already crate calling dependent. pub outer_expn: Option, pub outer_transparency: Transparency, From 25c4aa8979a39ea7c6e7af57093be64c36936b2b Mon Sep 17 00:00:00 2001 From: cuishuang Date: Mon, 2 Sep 2024 18:14:06 +0800 Subject: [PATCH 0376/2194] chore: remove repetitive words Signed-off-by: cuishuang --- library/core/src/mem/transmutability.rs | 2 +- library/std/src/sync/reentrant_lock.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/library/core/src/mem/transmutability.rs b/library/core/src/mem/transmutability.rs index 049b32ede9c3d..cda999a7f0c91 100644 --- a/library/core/src/mem/transmutability.rs +++ b/library/core/src/mem/transmutability.rs @@ -149,7 +149,7 @@ where #[derive(PartialEq, Eq, Clone, Copy, Debug)] pub struct Assume { /// When `false`, [`TransmuteFrom`] is not implemented for transmutations - /// that might violate the the alignment requirements of references; e.g.: + /// that might violate the alignment requirements of references; e.g.: /// #[cfg_attr(bootstrap, doc = "```rust,ignore not runnable on bootstrap")] #[cfg_attr(not(bootstrap), doc = "```compile_fail,E0277")] diff --git a/library/std/src/sync/reentrant_lock.rs b/library/std/src/sync/reentrant_lock.rs index 84a0b36db1798..0b23681e90726 100644 --- a/library/std/src/sync/reentrant_lock.rs +++ b/library/std/src/sync/reentrant_lock.rs @@ -136,7 +136,7 @@ cfg_if!( // match do we read out the actual TID. // Note also that we can use relaxed atomic operations here, because // we only ever read from the tid if `tls_addr` matches the current - // TLS address. In that case, either the the tid has been set by + // TLS address. In that case, either the tid has been set by // the current thread, or by a thread that has terminated before // the current thread was created. In either case, no further // synchronization is needed (as per ) From f5ccde6d458507e4e17141667ffdae5abbf982a2 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Mon, 2 Sep 2024 11:49:11 +0200 Subject: [PATCH 0377/2194] Simplify CompletionRelevance --- .../src/completions/item_list/trait_impl.rs | 6 +- .../crates/ide-completion/src/item.rs | 79 +++++++++++-------- .../crates/ide-completion/src/render.rs | 73 +++++++---------- .../ide-completion/src/render/function.rs | 17 ++-- 4 files changed, 85 insertions(+), 90 deletions(-) diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/item_list/trait_impl.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/item_list/trait_impl.rs index e93bb8db716f1..b5bc5533c79c8 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/item_list/trait_impl.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/item_list/trait_impl.rs @@ -221,7 +221,7 @@ fn add_function_impl_( let mut item = CompletionItem::new(completion_kind, replacement_range, label, ctx.edition); item.lookup_by(format!("{}fn {}", async_, fn_name.display(ctx.db, ctx.edition))) .set_documentation(func.docs(ctx.db)) - .set_relevance(CompletionRelevance { is_item_from_trait: true, ..Default::default() }); + .set_relevance(CompletionRelevance { exact_name_match: true, ..Default::default() }); if let Some(source) = ctx.sema.source(func) { if let Some(transformed_fn) = @@ -366,7 +366,7 @@ fn add_type_alias_impl( CompletionItem::new(SymbolKind::TypeAlias, replacement_range, label, ctx.edition); item.lookup_by(format!("type {alias_name}")) .set_documentation(type_alias.docs(ctx.db)) - .set_relevance(CompletionRelevance { is_item_from_trait: true, ..Default::default() }); + .set_relevance(CompletionRelevance { exact_name_match: true, ..Default::default() }); if let Some(source) = ctx.sema.source(type_alias) { let assoc_item = ast::AssocItem::TypeAlias(source.value); @@ -440,7 +440,7 @@ fn add_const_impl( item.lookup_by(format_smolstr!("const {const_name}")) .set_documentation(const_.docs(ctx.db)) .set_relevance(CompletionRelevance { - is_item_from_trait: true, + exact_name_match: true, ..Default::default() }); match ctx.config.snippet_cap { diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/item.rs b/src/tools/rust-analyzer/crates/ide-completion/src/item.rs index a30a115da1f1b..df30750b8fec6 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/item.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/item.rs @@ -19,8 +19,10 @@ use crate::{ }; /// `CompletionItem` describes a single completion entity which expands to 1 or more entries in the -/// editor pop-up. It is basically a POD with various properties. To construct a -/// [`CompletionItem`], use [`Builder::new`] method and the [`Builder`] struct. +/// editor pop-up. +/// +/// It is basically a POD with various properties. To construct a [`CompletionItem`], +/// use [`Builder::new`] method and the [`Builder`] struct. #[derive(Clone)] #[non_exhaustive] pub struct CompletionItem { @@ -129,7 +131,8 @@ impl fmt::Debug for CompletionItem { #[derive(Debug, Clone, Copy, Eq, PartialEq, Default)] pub struct CompletionRelevance { - /// This is set in cases like these: + /// This is set when the identifier being completed matches up with the name that is expected, + /// like in a function argument. /// /// ``` /// fn f(spam: String) {} @@ -139,9 +142,9 @@ pub struct CompletionRelevance { /// } /// ``` pub exact_name_match: bool, - /// See CompletionRelevanceTypeMatch doc comments for cases where this is set. + /// See [`CompletionRelevanceTypeMatch`]. pub type_match: Option, - /// This is set in cases like these: + /// Set for local variables. /// /// ``` /// fn foo(a: u32) { @@ -150,25 +153,26 @@ pub struct CompletionRelevance { /// } /// ``` pub is_local: bool, - /// This is set when trait items are completed in an impl of that trait. - pub is_item_from_trait: bool, - /// This is set for when trait items are from traits with `#[doc(notable_trait)]` - pub is_item_from_notable_trait: bool, - /// This is set when an import is suggested whose name is already imported. + /// Populated when the completion item comes from a trait (impl). + pub trait_: Option, + /// This is set when an import is suggested in a use item whose name is already imported. pub is_name_already_imported: bool, /// This is set for completions that will insert a `use` item. pub requires_import: bool, - /// Set for method completions of the `core::ops` and `core::cmp` family. - pub is_op_method: bool, /// Set for item completions that are private but in the workspace. pub is_private_editable: bool, /// Set for postfix snippet item completions pub postfix_match: Option, - /// This is set for type inference results - pub is_definite: bool, /// This is set for items that are function (associated or method) pub function: Option, } +#[derive(Debug, Clone, Copy, Eq, PartialEq)] +pub struct CompletionRelevanceTraitInfo { + /// The trait this item is from is a `#[doc(notable_trait)]` + pub notable_trait: bool, + /// Set for method completions of the `core::ops` and `core::cmp` family. + pub is_op_method: bool, +} #[derive(Debug, Clone, Copy, Eq, PartialEq)] pub enum CompletionRelevanceTypeMatch { @@ -182,7 +186,7 @@ pub enum CompletionRelevanceTypeMatch { /// } /// ``` CouldUnify, - /// This is set in cases like these: + /// This is set in cases where the type matches the expected type, like: /// /// ``` /// fn f(spam: String) {} @@ -243,14 +247,11 @@ impl CompletionRelevance { exact_name_match, type_match, is_local, - is_item_from_trait, is_name_already_imported, requires_import, - is_op_method, is_private_editable, postfix_match, - is_definite, - is_item_from_notable_trait, + trait_, function, } = self; @@ -258,8 +259,17 @@ impl CompletionRelevance { if !is_private_editable { score += 1; } - // lower rank trait op methods - if !is_op_method { + + if let Some(trait_) = trait_ { + if trait_.notable_trait { + score += 1; + } + // lower rank trait op methods + if !trait_.is_op_method { + score += 10; + } + } else { + // lower rank trait op methods score += 10; } // lower rank for conflicting import names @@ -287,16 +297,6 @@ impl CompletionRelevance { if is_local { score += 1; } - if is_item_from_trait { - score += 1; - } - if is_item_from_notable_trait { - score += 1; - } - if is_definite { - score += 10; - } - score += function .map(|asf| { let mut fn_score = match asf.return_type { @@ -701,8 +701,21 @@ mod tests { // that any items in the same vec have the same score. let expected_relevance_order = vec![ vec![], - vec![Cr { is_op_method: true, is_private_editable: true, ..default }], - vec![Cr { is_op_method: true, ..default }], + vec![Cr { + trait_: Some(crate::item::CompletionRelevanceTraitInfo { + notable_trait: false, + is_op_method: true, + }), + is_private_editable: true, + ..default + }], + vec![Cr { + trait_: Some(crate::item::CompletionRelevanceTraitInfo { + notable_trait: false, + is_op_method: true, + }), + ..default + }], vec![Cr { postfix_match: Some(CompletionRelevancePostfixMatch::NonExact), ..default }], vec![Cr { is_private_editable: true, ..default }], vec![default], diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/render.rs b/src/tools/rust-analyzer/crates/ide-completion/src/render.rs index ff5ec3a29f3e1..2bec2eb87bc4b 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/render.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/render.rs @@ -249,7 +249,11 @@ pub(crate) fn render_type_inference( ty_string, ctx.edition, ); - builder.set_relevance(CompletionRelevance { is_definite: true, ..Default::default() }); + builder.set_relevance(CompletionRelevance { + type_match: Some(CompletionRelevanceTypeMatch::Exact), + exact_name_match: true, + ..Default::default() + }); builder.build(ctx.db) } @@ -756,7 +760,7 @@ mod tests { relevance.postfix_match == Some(CompletionRelevancePostfixMatch::Exact), "snippet", ), - (relevance.is_op_method, "op_method"), + (relevance.trait_.map_or(false, |it| it.is_op_method), "op_method"), (relevance.requires_import, "requires_import"), ] .into_iter() @@ -1272,14 +1276,11 @@ fn main() { let _: m::Spam = S$0 } Exact, ), is_local: false, - is_item_from_trait: false, - is_item_from_notable_trait: false, + trait_: None, is_name_already_imported: false, requires_import: false, - is_op_method: false, is_private_editable: false, postfix_match: None, - is_definite: false, function: None, }, trigger_call_info: true, @@ -1300,14 +1301,11 @@ fn main() { let _: m::Spam = S$0 } Exact, ), is_local: false, - is_item_from_trait: false, - is_item_from_notable_trait: false, + trait_: None, is_name_already_imported: false, requires_import: false, - is_op_method: false, is_private_editable: false, postfix_match: None, - is_definite: false, function: None, }, trigger_call_info: true, @@ -1380,14 +1378,11 @@ fn foo() { A { the$0 } } CouldUnify, ), is_local: false, - is_item_from_trait: false, - is_item_from_notable_trait: false, + trait_: None, is_name_already_imported: false, requires_import: false, - is_op_method: false, is_private_editable: false, postfix_match: None, - is_definite: false, function: None, }, }, @@ -1431,14 +1426,11 @@ impl S { exact_name_match: false, type_match: None, is_local: false, - is_item_from_trait: false, - is_item_from_notable_trait: false, + trait_: None, is_name_already_imported: false, requires_import: false, - is_op_method: false, is_private_editable: false, postfix_match: None, - is_definite: false, function: Some( CompletionRelevanceFn { has_params: true, @@ -1558,14 +1550,11 @@ fn foo(s: S) { s.$0 } exact_name_match: false, type_match: None, is_local: false, - is_item_from_trait: false, - is_item_from_notable_trait: false, + trait_: None, is_name_already_imported: false, requires_import: false, - is_op_method: false, is_private_editable: false, postfix_match: None, - is_definite: false, function: Some( CompletionRelevanceFn { has_params: true, @@ -1774,14 +1763,11 @@ fn f() -> i32 { Exact, ), is_local: false, - is_item_from_trait: false, - is_item_from_notable_trait: false, + trait_: None, is_name_already_imported: false, requires_import: false, - is_op_method: false, is_private_editable: false, postfix_match: None, - is_definite: false, function: None, }, }, @@ -2492,14 +2478,11 @@ fn foo(f: Foo) { let _: &u32 = f.b$0 } exact_name_match: false, type_match: None, is_local: false, - is_item_from_trait: false, - is_item_from_notable_trait: false, + trait_: None, is_name_already_imported: false, requires_import: false, - is_op_method: false, is_private_editable: false, postfix_match: None, - is_definite: false, function: Some( CompletionRelevanceFn { has_params: true, @@ -2574,14 +2557,11 @@ fn foo() { Exact, ), is_local: false, - is_item_from_trait: false, - is_item_from_notable_trait: false, + trait_: None, is_name_already_imported: false, requires_import: false, - is_op_method: false, is_private_editable: false, postfix_match: None, - is_definite: false, function: None, }, }, @@ -2624,14 +2604,11 @@ fn main() { exact_name_match: false, type_match: None, is_local: false, - is_item_from_trait: false, - is_item_from_notable_trait: false, + trait_: None, is_name_already_imported: false, requires_import: false, - is_op_method: false, is_private_editable: false, postfix_match: None, - is_definite: false, function: Some( CompletionRelevanceFn { has_params: false, @@ -2996,14 +2973,16 @@ fn main() { exact_name_match: false, type_match: None, is_local: false, - is_item_from_trait: false, - is_item_from_notable_trait: true, + trait_: Some( + CompletionRelevanceTraitInfo { + notable_trait: true, + is_op_method: false, + }, + ), is_name_already_imported: false, requires_import: false, - is_op_method: false, is_private_editable: false, postfix_match: None, - is_definite: false, function: None, }, }, @@ -3021,14 +3000,16 @@ fn main() { exact_name_match: false, type_match: None, is_local: false, - is_item_from_trait: false, - is_item_from_notable_trait: true, + trait_: Some( + CompletionRelevanceTraitInfo { + notable_trait: true, + is_op_method: false, + }, + ), is_name_already_imported: false, requires_import: false, - is_op_method: false, is_private_editable: false, postfix_match: None, - is_definite: false, function: None, }, }, diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/render/function.rs b/src/tools/rust-analyzer/crates/ide-completion/src/render/function.rs index 74092b53f523f..29820cb2036de 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/render/function.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/render/function.rs @@ -10,7 +10,7 @@ use crate::{ context::{CompletionContext, DotAccess, DotAccessKind, PathCompletionCtx, PathKind}, item::{ Builder, CompletionItem, CompletionItemKind, CompletionRelevance, CompletionRelevanceFn, - CompletionRelevanceReturnType, + CompletionRelevanceReturnType, CompletionRelevanceTraitInfo, }, render::{ compute_exact_name_match, compute_ref_match, compute_type_match, match_types, RenderContext, @@ -88,11 +88,13 @@ fn render( let ret_type = func.ret_type(db); let assoc_item = func.as_assoc_item(db); - let trait_ = assoc_item.and_then(|trait_| trait_.container_or_implemented_trait(db)); - let is_op_method = trait_.map_or(false, |trait_| completion.is_ops_trait(trait_)); - - let is_item_from_notable_trait = - trait_.map_or(false, |trait_| completion.is_doc_notable_trait(trait_)); + let trait_info = + assoc_item.and_then(|trait_| trait_.container_or_implemented_trait(db)).map(|trait_| { + CompletionRelevanceTraitInfo { + notable_trait: completion.is_doc_notable_trait(trait_), + is_op_method: completion.is_ops_trait(trait_), + } + }); let (has_dot_receiver, has_call_parens, cap) = match func_kind { FuncKind::Function(&PathCompletionCtx { @@ -129,8 +131,7 @@ fn render( }, exact_name_match: compute_exact_name_match(completion, &call), function, - is_op_method, - is_item_from_notable_trait, + trait_: trait_info, ..ctx.completion_relevance() }); From 3414a9e94fb23d13f5409d51f6a129c771af96b6 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Mon, 2 Sep 2024 12:59:51 +0200 Subject: [PATCH 0378/2194] Adjust completions scoring --- .../crates/ide-completion/src/item.rs | 96 +++++++++---------- 1 file changed, 46 insertions(+), 50 deletions(-) diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/item.rs b/src/tools/rust-analyzer/crates/ide-completion/src/item.rs index df30750b8fec6..f8c8b12bd25af 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/item.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/item.rs @@ -242,7 +242,7 @@ impl CompletionRelevance { /// See is_relevant if you need to make some judgement about score /// in an absolute sense. pub fn score(self) -> u32 { - let mut score = 0; + let mut score = !0 / 2; let CompletionRelevance { exact_name_match, type_match, @@ -255,73 +255,69 @@ impl CompletionRelevance { function, } = self; + // only applicable for completions within use items + // lower rank for conflicting import names + if is_name_already_imported { + score -= 1; + } + // slightly prefer locals + if is_local { + score += 1; + } + // lower rank private things if !is_private_editable { score += 1; } if let Some(trait_) = trait_ { - if trait_.notable_trait { - score += 1; + // lower rank trait methods unless its notable + if !trait_.notable_trait { + score -= 5; } // lower rank trait op methods - if !trait_.is_op_method { - score += 10; + if trait_.is_op_method { + score -= 5; } - } else { - // lower rank trait op methods - score += 10; } - // lower rank for conflicting import names - if !is_name_already_imported { - score += 1; - } - // lower rank for items that don't need an import - if !requires_import { - score += 1; + // lower rank for items that need an import + if requires_import { + score -= 1; } if exact_name_match { - score += 10; + score += 20; } - score += match postfix_match { - Some(CompletionRelevancePostfixMatch::Exact) => 100, - Some(CompletionRelevancePostfixMatch::NonExact) => 0, - None => 3, + match postfix_match { + Some(CompletionRelevancePostfixMatch::Exact) => score += 100, + Some(CompletionRelevancePostfixMatch::NonExact) => score -= 5, + None => (), }; score += match type_match { - Some(CompletionRelevanceTypeMatch::Exact) => 8, - Some(CompletionRelevanceTypeMatch::CouldUnify) => 3, + Some(CompletionRelevanceTypeMatch::Exact) => 18, + Some(CompletionRelevanceTypeMatch::CouldUnify) => 5, None => 0, }; - // slightly prefer locals - if is_local { - score += 1; - } - score += function - .map(|asf| { - let mut fn_score = match asf.return_type { - CompletionRelevanceReturnType::DirectConstructor => 15, - CompletionRelevanceReturnType::Builder => 10, - CompletionRelevanceReturnType::Constructor => 5, - CompletionRelevanceReturnType::Other => 0, - }; - - // When a fn is bumped due to return type: - // Bump Constructor or Builder methods with no arguments, - // over them than with self arguments - if fn_score > 0 { - if !asf.has_params { - // bump associated functions - fn_score += 1; - } else if asf.has_self_param { - // downgrade methods (below Constructor) - fn_score = 1; - } - } + if let Some(function) = function { + let mut fn_score = match function.return_type { + CompletionRelevanceReturnType::DirectConstructor => 15, + CompletionRelevanceReturnType::Builder => 10, + CompletionRelevanceReturnType::Constructor => 5, + CompletionRelevanceReturnType::Other => 0u32, + }; + + // When a fn is bumped due to return type: + // Bump Constructor or Builder methods with no arguments, + // over them than with self arguments + if function.has_params { + // bump associated functions + fn_score = fn_score.saturating_sub(1); + } else if function.has_self_param { + // downgrade methods (below Constructor) + fn_score = fn_score.min(1); + } - fn_score - }) - .unwrap_or_default(); + score += fn_score; + }; score } From 06e3552ad0adec05fad5aabb549ad117c8d2461d Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Mon, 2 Sep 2024 09:44:03 -0400 Subject: [PATCH 0379/2194] Remove stray word in a comment --- library/std/src/sync/once_lock.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/std/src/sync/once_lock.rs b/library/std/src/sync/once_lock.rs index a51e5c1b76b23..be615a5a8ef37 100644 --- a/library/std/src/sync/once_lock.rs +++ b/library/std/src/sync/once_lock.rs @@ -517,7 +517,7 @@ impl OnceLock { res = Err(e); // Treat the underlying `Once` as poisoned since we - // failed to initialize our value. Calls + // failed to initialize our value. p.poison(); } } From 7494224e74682a7dff39747ef5007ad7df889e2b Mon Sep 17 00:00:00 2001 From: oskgo Date: Mon, 2 Sep 2024 15:49:18 +0200 Subject: [PATCH 0380/2194] clarify language around non-null ptrs in slice::raw --- library/core/src/slice/raw.rs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/library/core/src/slice/raw.rs b/library/core/src/slice/raw.rs index 85507eb8a7381..2cf3fecb47542 100644 --- a/library/core/src/slice/raw.rs +++ b/library/core/src/slice/raw.rs @@ -11,13 +11,13 @@ use crate::{array, ptr, ub_checks}; /// /// Behavior is undefined if any of the following conditions are violated: /// -/// * `data` must be [valid] for reads for `len * mem::size_of::()` many bytes, +/// * `data` must be non-null, [valid] for reads for `len * mem::size_of::()` many bytes, /// and it must be properly aligned. This means in particular: /// /// * The entire memory range of this slice must be contained within a single allocated object! /// Slices can never span across multiple allocated objects. See [below](#incorrect-usage) /// for an example incorrectly not taking this into account. -/// * `data` must be non-null and aligned even for zero-length slices. One +/// * `data` must be non-null and aligned even for zero-length slices or slices of ZSTs. One /// reason for this is that enum layout optimizations may rely on references /// (including slices of any length) being aligned and non-null to distinguish /// them from other data. You can obtain a pointer that is usable as `data` @@ -146,12 +146,12 @@ pub const unsafe fn from_raw_parts<'a, T>(data: *const T, len: usize) -> &'a [T] /// /// Behavior is undefined if any of the following conditions are violated: /// -/// * `data` must be [valid] for both reads and writes for `len * mem::size_of::()` many bytes, +/// * `data` must be non-null, [valid] for both reads and writes for `len * mem::size_of::()` many bytes, /// and it must be properly aligned. This means in particular: /// /// * The entire memory range of this slice must be contained within a single allocated object! /// Slices can never span across multiple allocated objects. -/// * `data` must be non-null and aligned even for zero-length slices. One +/// * `data` must be non-null and aligned even for zero-length slices or slices of ZSTs. One /// reason for this is that enum layout optimizations may rely on references /// (including slices of any length) being aligned and non-null to distinguish /// them from other data. You can obtain a pointer that is usable as `data` @@ -219,7 +219,7 @@ pub const fn from_mut(s: &mut T) -> &mut [T] { /// /// Behavior is undefined if any of the following conditions are violated: /// -/// * The `start` pointer of the range must be a [valid] and properly aligned pointer +/// * The `start` pointer of the range must be a non-null, [valid] and properly aligned pointer /// to the first element of a slice. /// /// * The `end` pointer must be a [valid] and properly aligned pointer to *one past* @@ -235,7 +235,7 @@ pub const fn from_mut(s: &mut T) -> &mut [T] { /// of lifetime `'a`, except inside an `UnsafeCell`. /// /// * The total length of the range must be no larger than `isize::MAX`, -/// and adding that size to `data` must not "wrap around" the address space. +/// and adding that size to `start` must not "wrap around" the address space. /// See the safety documentation of [`pointer::offset`]. /// /// Note that a range created from [`slice::as_ptr_range`] fulfills these requirements. @@ -288,7 +288,7 @@ pub const unsafe fn from_ptr_range<'a, T>(range: Range<*const T>) -> &'a [T] { /// /// Behavior is undefined if any of the following conditions are violated: /// -/// * The `start` pointer of the range must be a [valid] and properly aligned pointer +/// * The `start` pointer of the range must be a non-null, [valid] and properly aligned pointer /// to the first element of a slice. /// /// * The `end` pointer must be a [valid] and properly aligned pointer to *one past* @@ -305,7 +305,7 @@ pub const unsafe fn from_ptr_range<'a, T>(range: Range<*const T>) -> &'a [T] { /// Both read and write accesses are forbidden. /// /// * The total length of the range must be no larger than `isize::MAX`, -/// and adding that size to `data` must not "wrap around" the address space. +/// and adding that size to `start` must not "wrap around" the address space. /// See the safety documentation of [`pointer::offset`]. /// /// Note that a range created from [`slice::as_mut_ptr_range`] fulfills these requirements. From e3af6dc23915f027b9de0721aae86f794a053627 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 2 Sep 2024 15:59:00 +0200 Subject: [PATCH 0381/2194] Simplify CSS but wrapping scraped example into a div and move the title out of the code block --- src/librustdoc/html/static/css/rustdoc.css | 51 ++++++------------ .../html/static/js/scrape-examples.js | 4 +- .../html/templates/scraped_source.html | 54 ++++++++++--------- tests/rustdoc-gui/code-example-buttons.goml | 4 +- .../docblock-code-block-line-number.goml | 2 +- .../scrape-examples-button-focus.goml | 37 ++++++++++--- tests/rustdoc-gui/scrape-examples-color.goml | 4 +- tests/rustdoc-gui/scrape-examples-layout.goml | 28 +++++----- 8 files changed, 93 insertions(+), 91 deletions(-) diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css index 6b31c596c4097..fa5a936d3f452 100644 --- a/src/librustdoc/html/static/css/rustdoc.css +++ b/src/librustdoc/html/static/css/rustdoc.css @@ -34,7 +34,6 @@ xmlns="http://www.w3.org/2000/svg" fill="black" height="18px">\ '); --button-left-margin: 4px; --button-border-radius: 2px; - --pre-line-height: 1.5rem; } /* See FiraSans-LICENSE.txt for the Fira Sans license. */ @@ -366,7 +365,7 @@ code, pre, .code-header { } pre { padding: 14px; - line-height: var(--pre-line-height); /* https://github.com/rust-lang/rust/issues/105906 */ + line-height: 1.5; /* https://github.com/rust-lang/rust/issues/105906 */ } pre.item-decl { overflow-x: auto; @@ -379,7 +378,7 @@ pre.item-decl { .src .content pre { padding: 20px; } -.rustdoc.src .example-wrap pre.src-line-numbers { +.rustdoc.src .example-wrap .src-line-numbers { padding: 20px 0 20px 4px; } @@ -766,6 +765,10 @@ both the code example and the line numbers, so we need to remove the radius in t border-bottom-left-radius: 0; } +.rustdoc .scraped-example { + position: relative; +} + /* For the last child of a div, the margin will be taken care of by the margin-top of the next item. */ .rustdoc .example-wrap:last-child { @@ -777,7 +780,7 @@ both the code example and the line numbers, so we need to remove the radius in t flex-grow: 1; } -.scraped-example:not(.expanded) { +.scraped-example:not(.expanded) .example-wrap { /* scrape-examples.js has a constant DEFAULT_MAX_LINES (call it N) for the number * of lines shown in the un-expanded example code viewer. This pre needs to have * a max-height equal to line-height * N. The line-height is currently 1.5em, @@ -785,11 +788,10 @@ both the code example and the line numbers, so we need to remove the radius in t max-height: calc(1.5em * 5 + 10px); } -.rustdoc:not(.src) .scraped-example:not(.expanded) pre.src-line-numbers, +.rustdoc:not(.src) .scraped-example:not(.expanded) .src-line-numbers, .rustdoc:not(.src) .scraped-example:not(.expanded) pre.rust { padding-bottom: 0; /* See above comment, should be the same max-height. */ - max-height: calc(1.5em * 5 + 10px); overflow: auto hidden; } @@ -798,7 +800,7 @@ both the code example and the line numbers, so we need to remove the radius in t } .rustdoc .example-wrap pre.example-line-numbers, -.rustdoc .example-wrap pre.src-line-numbers { +.rustdoc .example-wrap .src-line-numbers { min-width: fit-content; /* prevent collapsing into nothing in truncated scraped examples */ flex-grow: 0; text-align: right; @@ -808,7 +810,7 @@ both the code example and the line numbers, so we need to remove the radius in t color: var(--src-line-numbers-span-color); } -.rustdoc .scraped-example pre.src-line-numbers { +.rustdoc .scraped-example .src-line-numbers { padding: 14px 0; } .src-line-numbers a, .src-line-numbers span { @@ -2268,24 +2270,6 @@ in src-script.js and main.js margin: 0; padding: var(--nav-sub-mobile-padding); } - - .example-wrap.scraped-example { - flex-wrap: wrap; - } - .example-wrap .scraped-example-title { - width: 100%; - } - .example-wrap.scraped-example .rust { - /* Dirty hacky to force it to remain on the same line as the line numbers. */ - width: 10px; - } - .example-wrap.scraped-example .button-holder { - top: calc(var(--pre-line-height) + 4px); - } - .scraped-example:not(.expanded)::before { - /* The gradient effect needs to be moved under the title */ - top: var(--pre-line-height); - } } @@ -2310,12 +2294,6 @@ in src-script.js and main.js .item-table > li > div { overflow-wrap: anywhere; } - - /* Starting this width, the "title" of scraped example will be in the code block so we can - put the background gradient at the top. */ - .scraped-example:not(.expanded)::before { - top: 0; - } } @media print { @@ -2397,20 +2375,21 @@ in src-script.js and main.js color: var(--scrape-example-help-hover-color); } -.scraped-example:not(.expanded)::before, -.scraped-example:not(.expanded)::after { +.scraped-example:not(.expanded) .example-wrap::before, +.scraped-example:not(.expanded) .example-wrap::after { content: " "; width: 100%; height: 5px; position: absolute; z-index: 1; } -.scraped-example:not(.expanded)::before { +.scraped-example:not(.expanded) .example-wrap::before { + top: 0; background: linear-gradient(to bottom, var(--scrape-example-code-wrapper-background-start), var(--scrape-example-code-wrapper-background-end)); } -.scraped-example:not(.expanded)::after { +.scraped-example:not(.expanded) .example-wrap::after { bottom: 0; background: linear-gradient(to top, var(--scrape-example-code-wrapper-background-start), diff --git a/src/librustdoc/html/static/js/scrape-examples.js b/src/librustdoc/html/static/js/scrape-examples.js index 709a774892f5a..06e42814d33b0 100644 --- a/src/librustdoc/html/static/js/scrape-examples.js +++ b/src/librustdoc/html/static/js/scrape-examples.js @@ -13,7 +13,7 @@ // Scroll code block to the given code location function scrollToLoc(elt, loc, isHidden) { - const lines = elt.querySelector(".src-line-numbers"); + const lines = elt.querySelector(".src-line-numbers > pre"); let scrollOffset; // If the block is greater than the size of the viewer, @@ -32,7 +32,7 @@ scrollOffset = offsetMid - halfHeight; } - lines.scrollTo(0, scrollOffset); + lines.parentElement.scrollTo(0, scrollOffset); elt.querySelector(".rust").scrollTo(0, scrollOffset); } diff --git a/src/librustdoc/html/templates/scraped_source.html b/src/librustdoc/html/templates/scraped_source.html index 4b5d3f2d10aa7..e1fc2e6937820 100644 --- a/src/librustdoc/html/templates/scraped_source.html +++ b/src/librustdoc/html/templates/scraped_source.html @@ -1,29 +1,33 @@ -
+
{# #}
{{info.name +}} ({{info.title}}) {# #}
- {# https://developers.google.com/search/docs/crawling-indexing/robots-meta-tag#data-nosnippet-attr - Do not show "1 2 3 4 5 ..." in web search results. #} -
-        {% for line in lines.clone() %}
-            {# ~#}
-            {{line|safe}}
-        {% endfor %}
-    
{# #} -
 {# #}
-        
-            {{code_html|safe}}
-         {# #}
-    
{# #} - {% if info.needs_prev_next_buttons || info.needs_expansion %} -
- {% if info.needs_prev_next_buttons %} - {# #} - - {% endif %} - {% if info.needs_expansion %} - - {% endif %} -
- {% endif %} +
{# #} + {# https://developers.google.com/search/docs/crawling-indexing/robots-meta-tag#data-nosnippet-attr + Do not show "1 2 3 4 5 ..." in web search results. #} +
{# #} +
+                {% for line in lines.clone() %}
+                    {# ~#}
+                    {{line|safe}}
+                {% endfor %}
+            
{# #} +
{# #} +
 {# #}
+            
+                {{code_html|safe}}
+             {# #}
+        
{# #} + {% if info.needs_prev_next_buttons || info.needs_expansion %} +
+ {% if info.needs_prev_next_buttons %} + {# #} + + {% endif %} + {% if info.needs_expansion %} + + {% endif %} +
+ {% endif %} +
{# #}
{# #} diff --git a/tests/rustdoc-gui/code-example-buttons.goml b/tests/rustdoc-gui/code-example-buttons.goml index a6c8a862d1ab4..c62683b45da9e 100644 --- a/tests/rustdoc-gui/code-example-buttons.goml +++ b/tests/rustdoc-gui/code-example-buttons.goml @@ -111,7 +111,7 @@ call-function: ("check-buttons-position", {"pre_selector": ".example-wrap"}) go-to: "file://" + |DOC_PATH| + "/scrape_examples/fn.test_many.html" // We should work as well for scraped examples. -call-function: ("check-buttons-position", {"pre_selector": ".example-wrap.scraped-example"}) +call-function: ("check-buttons-position", {"pre_selector": ".scraped-example .example-wrap"}) // And also when the scraped example "title" goes above. set-window-size: (600, 600) -call-function: ("check-buttons-position", {"pre_selector": ".example-wrap.scraped-example"}) +call-function: ("check-buttons-position", {"pre_selector": ".scraped-example .example-wrap"}) diff --git a/tests/rustdoc-gui/docblock-code-block-line-number.goml b/tests/rustdoc-gui/docblock-code-block-line-number.goml index 36a17b1c8339e..71ef041c684cb 100644 --- a/tests/rustdoc-gui/docblock-code-block-line-number.goml +++ b/tests/rustdoc-gui/docblock-code-block-line-number.goml @@ -109,7 +109,7 @@ assert-local-storage: {"rustdoc-line-numbers": "true" } go-to: "file://" + |DOC_PATH| + "/scrape_examples/fn.test_many.html" assert-css: ( - ".scraped-example pre.src-line-numbers", + ".scraped-example .src-line-numbers", { // There should not be a radius on the right of the line numbers. "border-top-left-radius": "6px", diff --git a/tests/rustdoc-gui/scrape-examples-button-focus.goml b/tests/rustdoc-gui/scrape-examples-button-focus.goml index 4950a48bf0c41..442a3a4dcad10 100644 --- a/tests/rustdoc-gui/scrape-examples-button-focus.goml +++ b/tests/rustdoc-gui/scrape-examples-button-focus.goml @@ -4,29 +4,52 @@ go-to: "file://" + |DOC_PATH| + "/scrape_examples/fn.test.html" // The next/prev buttons vertically scroll the code viewport between examples move-cursor-to: ".scraped-example-list > .scraped-example" -store-property: (".scraped-example-list > .scraped-example pre", {"scrollTop": initialScrollTop}) +store-property: (".scraped-example-list > .scraped-example .src-line-numbers", { + "scrollTop": initialScrollTop, +}) +assert-property: (".scraped-example-list > .scraped-example .rust", { + "scrollTop": |initialScrollTop|, +}) focus: ".scraped-example-list > .scraped-example .next" press-key: "Enter" -assert-property-false: (".scraped-example-list > .scraped-example pre", { +assert-property-false: (".scraped-example-list > .scraped-example .src-line-numbers", { + "scrollTop": |initialScrollTop| +}, NEAR) +assert-property-false: (".scraped-example-list > .scraped-example .rust", { "scrollTop": |initialScrollTop| }, NEAR) focus: ".scraped-example-list > .scraped-example .prev" press-key: "Enter" -assert-property: (".scraped-example-list > .scraped-example pre", { +assert-property: (".scraped-example-list > .scraped-example .src-line-numbers", { + "scrollTop": |initialScrollTop| +}, NEAR) +assert-property: (".scraped-example-list > .scraped-example .rust", { "scrollTop": |initialScrollTop| }, NEAR) // The expand button increases the scrollHeight of the minimized code viewport store-property: (".scraped-example-list > .scraped-example pre", {"offsetHeight": smallOffsetHeight}) -assert-property-false: (".scraped-example-list > .scraped-example pre", { +assert-property-false: (".scraped-example-list > .scraped-example .src-line-numbers", { + "scrollHeight": |smallOffsetHeight| +}, NEAR) +assert-property-false: (".scraped-example-list > .scraped-example .rust", { "scrollHeight": |smallOffsetHeight| }, NEAR) focus: ".scraped-example-list > .scraped-example .expand" press-key: "Enter" -assert-property-false: (".scraped-example-list > .scraped-example pre", { +assert-property-false: (".scraped-example-list > .scraped-example .src-line-numbers", { + "offsetHeight": |smallOffsetHeight| +}, NEAR) +assert-property-false: (".scraped-example-list > .scraped-example .rust", { "offsetHeight": |smallOffsetHeight| }, NEAR) -store-property: (".scraped-example-list > .scraped-example pre", {"offsetHeight": fullOffsetHeight}) -assert-property: (".scraped-example-list > .scraped-example pre", { +store-property: (".scraped-example-list > .scraped-example .src-line-numbers", { + "offsetHeight": fullOffsetHeight, +}) +assert-property: (".scraped-example-list > .scraped-example .rust", { + "offsetHeight": |fullOffsetHeight|, + "scrollHeight": |fullOffsetHeight|, +}) +assert-property: (".scraped-example-list > .scraped-example .src-line-numbers", { "scrollHeight": |fullOffsetHeight| }, NEAR) diff --git a/tests/rustdoc-gui/scrape-examples-color.goml b/tests/rustdoc-gui/scrape-examples-color.goml index 8baf2edb79b23..b0faca190a578 100644 --- a/tests/rustdoc-gui/scrape-examples-color.goml +++ b/tests/rustdoc-gui/scrape-examples-color.goml @@ -67,11 +67,11 @@ define-function: ( [theme, background_color_start, background_color_end], block { call-function: ("switch-theme", {"theme": |theme|}) - assert-css: (".scraped-example:not(.expanded)::before", { + assert-css: (".scraped-example:not(.expanded) .example-wrap::before", { "background-image": "linear-gradient(" + |background_color_start| + ", " + |background_color_end| + ")", }) - assert-css: (".scraped-example:not(.expanded)::after", { + assert-css: (".scraped-example:not(.expanded) .example-wrap::after", { "background-image": "linear-gradient(to top, " + |background_color_start| + ", " + |background_color_end| + ")", }) diff --git a/tests/rustdoc-gui/scrape-examples-layout.goml b/tests/rustdoc-gui/scrape-examples-layout.goml index 063e103458d37..f0023f7022a69 100644 --- a/tests/rustdoc-gui/scrape-examples-layout.goml +++ b/tests/rustdoc-gui/scrape-examples-layout.goml @@ -36,13 +36,13 @@ assert-property: ( ) // The "title" should be located at the right bottom corner of the code example. -store-position: (".example-wrap.scraped-example", {"x": x, "y": y}) -store-size: (".example-wrap.scraped-example", {"width": width, "height": height}) -store-size: (".example-wrap.scraped-example .scraped-example-title", { +store-position: (".scraped-example .example-wrap", {"x": x, "y": y}) +store-size: (".scraped-example .example-wrap", {"width": width, "height": height}) +store-size: (".scraped-example .scraped-example-title", { "width": title_width, "height": title_height, }) -assert-position: (".example-wrap.scraped-example .scraped-example-title", { +assert-position: (".scraped-example .scraped-example-title", { "x": |x| + |width| - |title_width| - 5, "y": |y| + |height| - |title_height| - 8, }) @@ -57,36 +57,32 @@ assert-position: (".scraped-example", {"y": 226}) assert-position: (".scraped-example .prev", {"y": 226 + |offset_y|}) // Gradient background should be at the top of the code block. -assert-css: (".scraped-example::before", {"top": "0px"}) -assert-css: (".scraped-example::after", {"bottom": "0px"}) +assert-css: (".scraped-example .example-wrap::before", {"top": "0px"}) +assert-css: (".scraped-example .example-wrap::after", {"bottom": "0px"}) // Then with mobile set-window-size: (600, 600) -store-size: (".example-wrap.scraped-example .scraped-example-title", {"height": title_height}) +store-size: (".scraped-example .scraped-example-title", {"height": title_height}) assert-position: (".scraped-example", {"y": 284}) assert-position: (".scraped-example .prev", {"y": 284 + |offset_y| + |title_height|}) -// Gradient background should be at the top of the code block, which is now below the "title". -assert-css: (".scraped-example::before", {"top": |title_height| + "px"}) -assert-css: (".scraped-example::after", {"bottom": "0px"}) - define-function: ( "check_title_and_code_position", [], block { // Title should be above the code. - store-position: (".example-wrap.scraped-example .src-line-numbers", {"x": x, "y": y}) - store-size: (".example-wrap.scraped-example .scraped-example-title", { "height": title_height }) + store-position: (".scraped-example .example-wrap .src-line-numbers", {"x": x, "y": y}) + store-size: (".scraped-example .scraped-example-title", { "height": title_height }) - assert-position: (".example-wrap.scraped-example .scraped-example-title", { + assert-position: (".scraped-example .scraped-example-title", { "x": |x|, // same X position. "y": |y| - |title_height|, }) // Line numbers should be right beside the code. compare-elements-position: ( - ".example-wrap.scraped-example .src-line-numbers", - ".example-wrap.scraped-example .rust", + ".scraped-example .example-wrap .src-line-numbers", + ".scraped-example .example-wrap .rust", ["y"], ) } From 265cd14cd46e740bf2ac0fa68f0eeafcd83984e0 Mon Sep 17 00:00:00 2001 From: Veera Date: Sun, 1 Sep 2024 22:27:43 -0400 Subject: [PATCH 0382/2194] Update Tests --- .../parser/misspelled-keywords/assoc-type.rs | 6 ++++++ .../misspelled-keywords/assoc-type.stderr | 13 ++++++++++++ .../parser/misspelled-keywords/async-move.rs | 6 ++++++ .../misspelled-keywords/async-move.stderr | 8 ++++++++ .../ui/parser/misspelled-keywords/const-fn.rs | 5 +++++ .../misspelled-keywords/const-fn.stderr | 8 ++++++++ .../misspelled-keywords/const-generics.rs | 4 ++++ .../misspelled-keywords/const-generics.stderr | 8 ++++++++ tests/ui/parser/misspelled-keywords/const.rs | 4 ++++ .../parser/misspelled-keywords/const.stderr | 8 ++++++++ .../ui/parser/misspelled-keywords/for-loop.rs | 4 ++++ .../misspelled-keywords/for-loop.stderr | 8 ++++++++ tests/ui/parser/misspelled-keywords/hrdt.rs | 16 +++++++++++++++ .../ui/parser/misspelled-keywords/hrdt.stderr | 8 ++++++++ .../parser/misspelled-keywords/impl-block.rs | 6 ++++++ .../misspelled-keywords/impl-block.stderr | 8 ++++++++ .../parser/misspelled-keywords/impl-return.rs | 4 ++++ .../misspelled-keywords/impl-return.stderr | 8 ++++++++ .../misspelled-keywords/impl-trait-for.rs | 6 ++++++ .../misspelled-keywords/impl-trait-for.stderr | 8 ++++++++ .../parser/misspelled-keywords/impl-trait.rs | 4 ++++ .../misspelled-keywords/impl-trait.stderr | 13 ++++++++++++ .../ui/parser/misspelled-keywords/let-else.rs | 4 ++++ .../misspelled-keywords/let-else.stderr | 8 ++++++++ .../ui/parser/misspelled-keywords/let-mut.rs | 4 ++++ .../parser/misspelled-keywords/let-mut.stderr | 8 ++++++++ tests/ui/parser/misspelled-keywords/let.rs | 9 +++++++++ .../ui/parser/misspelled-keywords/let.stderr | 14 +++++++++++++ tests/ui/parser/misspelled-keywords/match.rs | 5 +++++ .../parser/misspelled-keywords/match.stderr | 8 ++++++++ tests/ui/parser/misspelled-keywords/mod.rs | 4 ++++ .../ui/parser/misspelled-keywords/mod.stderr | 8 ++++++++ tests/ui/parser/misspelled-keywords/pub-fn.rs | 5 +++++ .../parser/misspelled-keywords/pub-fn.stderr | 8 ++++++++ tests/ui/parser/misspelled-keywords/ref.rs | 9 +++++++++ .../ui/parser/misspelled-keywords/ref.stderr | 20 +++++++++++++++++++ tests/ui/parser/misspelled-keywords/return.rs | 7 +++++++ .../parser/misspelled-keywords/return.stderr | 8 ++++++++ .../parser/misspelled-keywords/static-mut.rs | 5 +++++ .../misspelled-keywords/static-mut.stderr | 19 ++++++++++++++++++ tests/ui/parser/misspelled-keywords/static.rs | 4 ++++ .../parser/misspelled-keywords/static.stderr | 8 ++++++++ tests/ui/parser/misspelled-keywords/struct.rs | 4 ++++ .../parser/misspelled-keywords/struct.stderr | 8 ++++++++ .../parser/misspelled-keywords/unsafe-fn.rs | 4 ++++ .../misspelled-keywords/unsafe-fn.stderr | 8 ++++++++ tests/ui/parser/misspelled-keywords/use.rs | 4 ++++ .../ui/parser/misspelled-keywords/use.stderr | 8 ++++++++ .../misspelled-keywords/where-clause.rs | 8 ++++++++ .../misspelled-keywords/where-clause.stderr | 10 ++++++++++ .../parser/misspelled-keywords/while-loop.rs | 7 +++++++ .../misspelled-keywords/while-loop.stderr | 8 ++++++++ .../while-without-identifiers.rs | 4 ++++ .../while-without-identifiers.stderr | 8 ++++++++ 54 files changed, 409 insertions(+) create mode 100644 tests/ui/parser/misspelled-keywords/assoc-type.rs create mode 100644 tests/ui/parser/misspelled-keywords/assoc-type.stderr create mode 100644 tests/ui/parser/misspelled-keywords/async-move.rs create mode 100644 tests/ui/parser/misspelled-keywords/async-move.stderr create mode 100644 tests/ui/parser/misspelled-keywords/const-fn.rs create mode 100644 tests/ui/parser/misspelled-keywords/const-fn.stderr create mode 100644 tests/ui/parser/misspelled-keywords/const-generics.rs create mode 100644 tests/ui/parser/misspelled-keywords/const-generics.stderr create mode 100644 tests/ui/parser/misspelled-keywords/const.rs create mode 100644 tests/ui/parser/misspelled-keywords/const.stderr create mode 100644 tests/ui/parser/misspelled-keywords/for-loop.rs create mode 100644 tests/ui/parser/misspelled-keywords/for-loop.stderr create mode 100644 tests/ui/parser/misspelled-keywords/hrdt.rs create mode 100644 tests/ui/parser/misspelled-keywords/hrdt.stderr create mode 100644 tests/ui/parser/misspelled-keywords/impl-block.rs create mode 100644 tests/ui/parser/misspelled-keywords/impl-block.stderr create mode 100644 tests/ui/parser/misspelled-keywords/impl-return.rs create mode 100644 tests/ui/parser/misspelled-keywords/impl-return.stderr create mode 100644 tests/ui/parser/misspelled-keywords/impl-trait-for.rs create mode 100644 tests/ui/parser/misspelled-keywords/impl-trait-for.stderr create mode 100644 tests/ui/parser/misspelled-keywords/impl-trait.rs create mode 100644 tests/ui/parser/misspelled-keywords/impl-trait.stderr create mode 100644 tests/ui/parser/misspelled-keywords/let-else.rs create mode 100644 tests/ui/parser/misspelled-keywords/let-else.stderr create mode 100644 tests/ui/parser/misspelled-keywords/let-mut.rs create mode 100644 tests/ui/parser/misspelled-keywords/let-mut.stderr create mode 100644 tests/ui/parser/misspelled-keywords/let.rs create mode 100644 tests/ui/parser/misspelled-keywords/let.stderr create mode 100644 tests/ui/parser/misspelled-keywords/match.rs create mode 100644 tests/ui/parser/misspelled-keywords/match.stderr create mode 100644 tests/ui/parser/misspelled-keywords/mod.rs create mode 100644 tests/ui/parser/misspelled-keywords/mod.stderr create mode 100644 tests/ui/parser/misspelled-keywords/pub-fn.rs create mode 100644 tests/ui/parser/misspelled-keywords/pub-fn.stderr create mode 100644 tests/ui/parser/misspelled-keywords/ref.rs create mode 100644 tests/ui/parser/misspelled-keywords/ref.stderr create mode 100644 tests/ui/parser/misspelled-keywords/return.rs create mode 100644 tests/ui/parser/misspelled-keywords/return.stderr create mode 100644 tests/ui/parser/misspelled-keywords/static-mut.rs create mode 100644 tests/ui/parser/misspelled-keywords/static-mut.stderr create mode 100644 tests/ui/parser/misspelled-keywords/static.rs create mode 100644 tests/ui/parser/misspelled-keywords/static.stderr create mode 100644 tests/ui/parser/misspelled-keywords/struct.rs create mode 100644 tests/ui/parser/misspelled-keywords/struct.stderr create mode 100644 tests/ui/parser/misspelled-keywords/unsafe-fn.rs create mode 100644 tests/ui/parser/misspelled-keywords/unsafe-fn.stderr create mode 100644 tests/ui/parser/misspelled-keywords/use.rs create mode 100644 tests/ui/parser/misspelled-keywords/use.stderr create mode 100644 tests/ui/parser/misspelled-keywords/where-clause.rs create mode 100644 tests/ui/parser/misspelled-keywords/where-clause.stderr create mode 100644 tests/ui/parser/misspelled-keywords/while-loop.rs create mode 100644 tests/ui/parser/misspelled-keywords/while-loop.stderr create mode 100644 tests/ui/parser/misspelled-keywords/while-without-identifiers.rs create mode 100644 tests/ui/parser/misspelled-keywords/while-without-identifiers.stderr diff --git a/tests/ui/parser/misspelled-keywords/assoc-type.rs b/tests/ui/parser/misspelled-keywords/assoc-type.rs new file mode 100644 index 0000000000000..a6b694a2abe6b --- /dev/null +++ b/tests/ui/parser/misspelled-keywords/assoc-type.rs @@ -0,0 +1,6 @@ +trait Animal { + Type Result = u8; + //~^ ERROR expected one of +} + +fn main() {} diff --git a/tests/ui/parser/misspelled-keywords/assoc-type.stderr b/tests/ui/parser/misspelled-keywords/assoc-type.stderr new file mode 100644 index 0000000000000..1318bee3da83d --- /dev/null +++ b/tests/ui/parser/misspelled-keywords/assoc-type.stderr @@ -0,0 +1,13 @@ +error: expected one of `!` or `::`, found `Result` + --> $DIR/assoc-type.rs:2:10 + | +LL | trait Animal { + | - while parsing this item list starting here +LL | Type Result = u8; + | ^^^^^^ expected one of `!` or `::` +LL | +LL | } + | - the item list ends here + +error: aborting due to 1 previous error + diff --git a/tests/ui/parser/misspelled-keywords/async-move.rs b/tests/ui/parser/misspelled-keywords/async-move.rs new file mode 100644 index 0000000000000..702a905e918c3 --- /dev/null +++ b/tests/ui/parser/misspelled-keywords/async-move.rs @@ -0,0 +1,6 @@ +//@ edition: 2018 + +fn main() { + async Move {} + //~^ ERROR expected one of +} diff --git a/tests/ui/parser/misspelled-keywords/async-move.stderr b/tests/ui/parser/misspelled-keywords/async-move.stderr new file mode 100644 index 0000000000000..a98bb23f5d65e --- /dev/null +++ b/tests/ui/parser/misspelled-keywords/async-move.stderr @@ -0,0 +1,8 @@ +error: expected one of `move`, `|`, or `||`, found `Move` + --> $DIR/async-move.rs:4:11 + | +LL | async Move {} + | ^^^^ expected one of `move`, `|`, or `||` + +error: aborting due to 1 previous error + diff --git a/tests/ui/parser/misspelled-keywords/const-fn.rs b/tests/ui/parser/misspelled-keywords/const-fn.rs new file mode 100644 index 0000000000000..c4174b6a2efb5 --- /dev/null +++ b/tests/ui/parser/misspelled-keywords/const-fn.rs @@ -0,0 +1,5 @@ +cnst fn code() {} +//~^ ERROR expected one of + +fn main() { +} diff --git a/tests/ui/parser/misspelled-keywords/const-fn.stderr b/tests/ui/parser/misspelled-keywords/const-fn.stderr new file mode 100644 index 0000000000000..bdca2657ef39b --- /dev/null +++ b/tests/ui/parser/misspelled-keywords/const-fn.stderr @@ -0,0 +1,8 @@ +error: expected one of `!` or `::`, found keyword `fn` + --> $DIR/const-fn.rs:1:6 + | +LL | cnst fn code() {} + | ^^ expected one of `!` or `::` + +error: aborting due to 1 previous error + diff --git a/tests/ui/parser/misspelled-keywords/const-generics.rs b/tests/ui/parser/misspelled-keywords/const-generics.rs new file mode 100644 index 0000000000000..2df64a87e2776 --- /dev/null +++ b/tests/ui/parser/misspelled-keywords/const-generics.rs @@ -0,0 +1,4 @@ +fn foo(_arr: [i32; N]) {} +//~^ ERROR expected one of + +fn main() {} diff --git a/tests/ui/parser/misspelled-keywords/const-generics.stderr b/tests/ui/parser/misspelled-keywords/const-generics.stderr new file mode 100644 index 0000000000000..f52544ac45ce2 --- /dev/null +++ b/tests/ui/parser/misspelled-keywords/const-generics.stderr @@ -0,0 +1,8 @@ +error: expected one of `,`, `:`, `=`, or `>`, found `N` + --> $DIR/const-generics.rs:1:15 + | +LL | fn foo(_arr: [i32; N]) {} + | ^ expected one of `,`, `:`, `=`, or `>` + +error: aborting due to 1 previous error + diff --git a/tests/ui/parser/misspelled-keywords/const.rs b/tests/ui/parser/misspelled-keywords/const.rs new file mode 100644 index 0000000000000..b481408cb62d2 --- /dev/null +++ b/tests/ui/parser/misspelled-keywords/const.rs @@ -0,0 +1,4 @@ +cons A: u8 = 10; +//~^ ERROR expected one of + +fn main() {} diff --git a/tests/ui/parser/misspelled-keywords/const.stderr b/tests/ui/parser/misspelled-keywords/const.stderr new file mode 100644 index 0000000000000..de1ad9d2bf76d --- /dev/null +++ b/tests/ui/parser/misspelled-keywords/const.stderr @@ -0,0 +1,8 @@ +error: expected one of `!` or `::`, found `A` + --> $DIR/const.rs:1:6 + | +LL | cons A: u8 = 10; + | ^ expected one of `!` or `::` + +error: aborting due to 1 previous error + diff --git a/tests/ui/parser/misspelled-keywords/for-loop.rs b/tests/ui/parser/misspelled-keywords/for-loop.rs new file mode 100644 index 0000000000000..6aba581cf17fa --- /dev/null +++ b/tests/ui/parser/misspelled-keywords/for-loop.rs @@ -0,0 +1,4 @@ +fn main() { + form i in 1..10 {} + //~^ ERROR expected one of +} diff --git a/tests/ui/parser/misspelled-keywords/for-loop.stderr b/tests/ui/parser/misspelled-keywords/for-loop.stderr new file mode 100644 index 0000000000000..cbf3b43fa585b --- /dev/null +++ b/tests/ui/parser/misspelled-keywords/for-loop.stderr @@ -0,0 +1,8 @@ +error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, `}`, or an operator, found `i` + --> $DIR/for-loop.rs:2:10 + | +LL | form i in 1..10 {} + | ^ expected one of 8 possible tokens + +error: aborting due to 1 previous error + diff --git a/tests/ui/parser/misspelled-keywords/hrdt.rs b/tests/ui/parser/misspelled-keywords/hrdt.rs new file mode 100644 index 0000000000000..9ca9e1bfbeecc --- /dev/null +++ b/tests/ui/parser/misspelled-keywords/hrdt.rs @@ -0,0 +1,16 @@ +struct Closure { + data: (u8, u16), + func: F, +} + +impl Closure + Where for<'a> F: Fn(&'a (u8, u16)) -> &'a u8, +//~^ ERROR expected one of +{ + fn call(&self) -> &u8 { + (self.func)(&self.data) + } +} + + +fn main() {} diff --git a/tests/ui/parser/misspelled-keywords/hrdt.stderr b/tests/ui/parser/misspelled-keywords/hrdt.stderr new file mode 100644 index 0000000000000..102ce7014e470 --- /dev/null +++ b/tests/ui/parser/misspelled-keywords/hrdt.stderr @@ -0,0 +1,8 @@ +error: expected one of `!`, `(`, `+`, `::`, `<`, `where`, or `{`, found keyword `for` + --> $DIR/hrdt.rs:7:11 + | +LL | Where for<'a> F: Fn(&'a (u8, u16)) -> &'a u8, + | ^^^ expected one of 7 possible tokens + +error: aborting due to 1 previous error + diff --git a/tests/ui/parser/misspelled-keywords/impl-block.rs b/tests/ui/parser/misspelled-keywords/impl-block.rs new file mode 100644 index 0000000000000..dc2570c22c5df --- /dev/null +++ b/tests/ui/parser/misspelled-keywords/impl-block.rs @@ -0,0 +1,6 @@ +struct Human; + +ipml Human {} +//~^ ERROR expected one of + +fn main() {} diff --git a/tests/ui/parser/misspelled-keywords/impl-block.stderr b/tests/ui/parser/misspelled-keywords/impl-block.stderr new file mode 100644 index 0000000000000..e0f0f8ed18f91 --- /dev/null +++ b/tests/ui/parser/misspelled-keywords/impl-block.stderr @@ -0,0 +1,8 @@ +error: expected one of `!` or `::`, found `Human` + --> $DIR/impl-block.rs:3:6 + | +LL | ipml Human {} + | ^^^^^ expected one of `!` or `::` + +error: aborting due to 1 previous error + diff --git a/tests/ui/parser/misspelled-keywords/impl-return.rs b/tests/ui/parser/misspelled-keywords/impl-return.rs new file mode 100644 index 0000000000000..c9d1973179e47 --- /dev/null +++ b/tests/ui/parser/misspelled-keywords/impl-return.rs @@ -0,0 +1,4 @@ +fn code() -> Impl Display {} +//~^ ERROR expected one of + +fn main() {} diff --git a/tests/ui/parser/misspelled-keywords/impl-return.stderr b/tests/ui/parser/misspelled-keywords/impl-return.stderr new file mode 100644 index 0000000000000..bdcf831a88a39 --- /dev/null +++ b/tests/ui/parser/misspelled-keywords/impl-return.stderr @@ -0,0 +1,8 @@ +error: expected one of `!`, `(`, `+`, `::`, `<`, `where`, or `{`, found `Display` + --> $DIR/impl-return.rs:1:19 + | +LL | fn code() -> Impl Display {} + | ^^^^^^^ expected one of 7 possible tokens + +error: aborting due to 1 previous error + diff --git a/tests/ui/parser/misspelled-keywords/impl-trait-for.rs b/tests/ui/parser/misspelled-keywords/impl-trait-for.rs new file mode 100644 index 0000000000000..c6f3fcda5ad71 --- /dev/null +++ b/tests/ui/parser/misspelled-keywords/impl-trait-for.rs @@ -0,0 +1,6 @@ +struct Human; + +impl Debug form Human {} +//~^ ERROR expected one of + +fn main() {} diff --git a/tests/ui/parser/misspelled-keywords/impl-trait-for.stderr b/tests/ui/parser/misspelled-keywords/impl-trait-for.stderr new file mode 100644 index 0000000000000..64ca66794adba --- /dev/null +++ b/tests/ui/parser/misspelled-keywords/impl-trait-for.stderr @@ -0,0 +1,8 @@ +error: expected one of `!`, `(`, `+`, `::`, `<`, `where`, or `{`, found `Human` + --> $DIR/impl-trait-for.rs:3:17 + | +LL | impl Debug form Human {} + | ^^^^^ expected one of 7 possible tokens + +error: aborting due to 1 previous error + diff --git a/tests/ui/parser/misspelled-keywords/impl-trait.rs b/tests/ui/parser/misspelled-keywords/impl-trait.rs new file mode 100644 index 0000000000000..99380b8ac0ecd --- /dev/null +++ b/tests/ui/parser/misspelled-keywords/impl-trait.rs @@ -0,0 +1,4 @@ +fn code() -> u8 {} +//~^ ERROR expected one of + +fn main() {} diff --git a/tests/ui/parser/misspelled-keywords/impl-trait.stderr b/tests/ui/parser/misspelled-keywords/impl-trait.stderr new file mode 100644 index 0000000000000..ca0918e820f87 --- /dev/null +++ b/tests/ui/parser/misspelled-keywords/impl-trait.stderr @@ -0,0 +1,13 @@ +error: expected one of `(`, `+`, `,`, `::`, `<`, `=`, or `>`, found `Debug` + --> $DIR/impl-trait.rs:1:18 + | +LL | fn code() -> u8 {} + | ^^^^^ expected one of 7 possible tokens + | +help: you might have meant to end the type parameters here + | +LL | fn code Debug>() -> u8 {} + | + + +error: aborting due to 1 previous error + diff --git a/tests/ui/parser/misspelled-keywords/let-else.rs b/tests/ui/parser/misspelled-keywords/let-else.rs new file mode 100644 index 0000000000000..0d5a03e3e43e4 --- /dev/null +++ b/tests/ui/parser/misspelled-keywords/let-else.rs @@ -0,0 +1,4 @@ +fn main() { + let Some(a) = Some(10) elze {} + //~^ ERROR expected one of +} diff --git a/tests/ui/parser/misspelled-keywords/let-else.stderr b/tests/ui/parser/misspelled-keywords/let-else.stderr new file mode 100644 index 0000000000000..826e7de4b11a5 --- /dev/null +++ b/tests/ui/parser/misspelled-keywords/let-else.stderr @@ -0,0 +1,8 @@ +error: expected one of `.`, `;`, `?`, `else`, or an operator, found `elze` + --> $DIR/let-else.rs:2:28 + | +LL | let Some(a) = Some(10) elze {} + | ^^^^ expected one of `.`, `;`, `?`, `else`, or an operator + +error: aborting due to 1 previous error + diff --git a/tests/ui/parser/misspelled-keywords/let-mut.rs b/tests/ui/parser/misspelled-keywords/let-mut.rs new file mode 100644 index 0000000000000..83228fe8c6682 --- /dev/null +++ b/tests/ui/parser/misspelled-keywords/let-mut.rs @@ -0,0 +1,4 @@ +fn main() { + let muta a = 10; + //~^ ERROR expected one of +} diff --git a/tests/ui/parser/misspelled-keywords/let-mut.stderr b/tests/ui/parser/misspelled-keywords/let-mut.stderr new file mode 100644 index 0000000000000..449f0133d6536 --- /dev/null +++ b/tests/ui/parser/misspelled-keywords/let-mut.stderr @@ -0,0 +1,8 @@ +error: expected one of `:`, `;`, `=`, `@`, or `|`, found `a` + --> $DIR/let-mut.rs:2:14 + | +LL | let muta a = 10; + | ^ expected one of `:`, `;`, `=`, `@`, or `|` + +error: aborting due to 1 previous error + diff --git a/tests/ui/parser/misspelled-keywords/let.rs b/tests/ui/parser/misspelled-keywords/let.rs new file mode 100644 index 0000000000000..461c3e518db82 --- /dev/null +++ b/tests/ui/parser/misspelled-keywords/let.rs @@ -0,0 +1,9 @@ +fn main() { + Let a = 10; + //~^ ERROR expected one of +} + +fn code() { + lett a = 10; + //~^ ERROR expected one of +} diff --git a/tests/ui/parser/misspelled-keywords/let.stderr b/tests/ui/parser/misspelled-keywords/let.stderr new file mode 100644 index 0000000000000..77aeb21369c13 --- /dev/null +++ b/tests/ui/parser/misspelled-keywords/let.stderr @@ -0,0 +1,14 @@ +error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, `}`, or an operator, found `a` + --> $DIR/let.rs:2:9 + | +LL | Let a = 10; + | ^ expected one of 8 possible tokens + +error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, `}`, or an operator, found `a` + --> $DIR/let.rs:7:10 + | +LL | lett a = 10; + | ^ expected one of 8 possible tokens + +error: aborting due to 2 previous errors + diff --git a/tests/ui/parser/misspelled-keywords/match.rs b/tests/ui/parser/misspelled-keywords/match.rs new file mode 100644 index 0000000000000..a31840a2d7111 --- /dev/null +++ b/tests/ui/parser/misspelled-keywords/match.rs @@ -0,0 +1,5 @@ +fn main() { + let a = 10; + matche a {} + //~^ ERROR expected one of +} diff --git a/tests/ui/parser/misspelled-keywords/match.stderr b/tests/ui/parser/misspelled-keywords/match.stderr new file mode 100644 index 0000000000000..bc3eece1c9d9a --- /dev/null +++ b/tests/ui/parser/misspelled-keywords/match.stderr @@ -0,0 +1,8 @@ +error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, `}`, or an operator, found `a` + --> $DIR/match.rs:3:12 + | +LL | matche a {} + | ^ expected one of 8 possible tokens + +error: aborting due to 1 previous error + diff --git a/tests/ui/parser/misspelled-keywords/mod.rs b/tests/ui/parser/misspelled-keywords/mod.rs new file mode 100644 index 0000000000000..24f0101bc5aaa --- /dev/null +++ b/tests/ui/parser/misspelled-keywords/mod.rs @@ -0,0 +1,4 @@ +mode parser; +//~^ ERROR expected one of + +fn main() {} diff --git a/tests/ui/parser/misspelled-keywords/mod.stderr b/tests/ui/parser/misspelled-keywords/mod.stderr new file mode 100644 index 0000000000000..135f70ccfcbba --- /dev/null +++ b/tests/ui/parser/misspelled-keywords/mod.stderr @@ -0,0 +1,8 @@ +error: expected one of `!` or `::`, found `parser` + --> $DIR/mod.rs:1:6 + | +LL | mode parser; + | ^^^^^^ expected one of `!` or `::` + +error: aborting due to 1 previous error + diff --git a/tests/ui/parser/misspelled-keywords/pub-fn.rs b/tests/ui/parser/misspelled-keywords/pub-fn.rs new file mode 100644 index 0000000000000..50d7129ce51ee --- /dev/null +++ b/tests/ui/parser/misspelled-keywords/pub-fn.rs @@ -0,0 +1,5 @@ +puB fn code() {} +//~^ ERROR expected one of + +fn main() { +} diff --git a/tests/ui/parser/misspelled-keywords/pub-fn.stderr b/tests/ui/parser/misspelled-keywords/pub-fn.stderr new file mode 100644 index 0000000000000..15715514e6651 --- /dev/null +++ b/tests/ui/parser/misspelled-keywords/pub-fn.stderr @@ -0,0 +1,8 @@ +error: expected one of `#`, `async`, `auto`, `const`, `default`, `enum`, `extern`, `fn`, `gen`, `impl`, `macro_rules`, `macro`, `mod`, `pub`, `safe`, `static`, `struct`, `trait`, `type`, `unsafe`, or `use`, found `puB` + --> $DIR/pub-fn.rs:1:1 + | +LL | puB fn code() {} + | ^^^ expected one of 21 possible tokens + +error: aborting due to 1 previous error + diff --git a/tests/ui/parser/misspelled-keywords/ref.rs b/tests/ui/parser/misspelled-keywords/ref.rs new file mode 100644 index 0000000000000..76b367ae99b75 --- /dev/null +++ b/tests/ui/parser/misspelled-keywords/ref.rs @@ -0,0 +1,9 @@ +fn main() { + let a = Some(vec![1, 2]); + match a { + Some(refe list) => println!("{list:?}"), + //~^ ERROR expected one of + //~| ERROR this pattern has 2 fields, + _ => println!("none"), + } +} diff --git a/tests/ui/parser/misspelled-keywords/ref.stderr b/tests/ui/parser/misspelled-keywords/ref.stderr new file mode 100644 index 0000000000000..2c23fe7a0afe8 --- /dev/null +++ b/tests/ui/parser/misspelled-keywords/ref.stderr @@ -0,0 +1,20 @@ +error: expected one of `)`, `,`, `@`, or `|`, found `list` + --> $DIR/ref.rs:4:19 + | +LL | Some(refe list) => println!("{list:?}"), + | -^^^^ expected one of `)`, `,`, `@`, or `|` + | | + | help: missing `,` + +error[E0023]: this pattern has 2 fields, but the corresponding tuple variant has 1 field + --> $DIR/ref.rs:4:14 + | +LL | Some(refe list) => println!("{list:?}"), + | ^^^^ ^^^^ expected 1 field, found 2 + --> $SRC_DIR/core/src/option.rs:LL:COL + | + = note: tuple variant has 1 field + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0023`. diff --git a/tests/ui/parser/misspelled-keywords/return.rs b/tests/ui/parser/misspelled-keywords/return.rs new file mode 100644 index 0000000000000..4bbe55d37da72 --- /dev/null +++ b/tests/ui/parser/misspelled-keywords/return.rs @@ -0,0 +1,7 @@ +fn code() -> u8 { + let a = 10; + returnn a; + //~^ ERROR expected one of +} + +fn main() {} diff --git a/tests/ui/parser/misspelled-keywords/return.stderr b/tests/ui/parser/misspelled-keywords/return.stderr new file mode 100644 index 0000000000000..94789e7a92cd8 --- /dev/null +++ b/tests/ui/parser/misspelled-keywords/return.stderr @@ -0,0 +1,8 @@ +error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, `}`, or an operator, found `a` + --> $DIR/return.rs:3:13 + | +LL | returnn a; + | ^ expected one of 8 possible tokens + +error: aborting due to 1 previous error + diff --git a/tests/ui/parser/misspelled-keywords/static-mut.rs b/tests/ui/parser/misspelled-keywords/static-mut.rs new file mode 100644 index 0000000000000..6509f62470a9c --- /dev/null +++ b/tests/ui/parser/misspelled-keywords/static-mut.rs @@ -0,0 +1,5 @@ +static muta a: u8 = 0; +//~^ ERROR expected one of +//~| ERROR missing type for + +fn main() {} diff --git a/tests/ui/parser/misspelled-keywords/static-mut.stderr b/tests/ui/parser/misspelled-keywords/static-mut.stderr new file mode 100644 index 0000000000000..1e5d25c709e7d --- /dev/null +++ b/tests/ui/parser/misspelled-keywords/static-mut.stderr @@ -0,0 +1,19 @@ +error: expected one of `:`, `;`, or `=`, found `a` + --> $DIR/static-mut.rs:1:13 + | +LL | static muta a: u8 = 0; + | ^ expected one of `:`, `;`, or `=` + +error: missing type for `static` item + --> $DIR/static-mut.rs:1:12 + | +LL | static muta a: u8 = 0; + | ^ + | +help: provide a type for the item + | +LL | static muta: a: u8 = 0; + | ++++++++ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/parser/misspelled-keywords/static.rs b/tests/ui/parser/misspelled-keywords/static.rs new file mode 100644 index 0000000000000..240f4f52c8dc8 --- /dev/null +++ b/tests/ui/parser/misspelled-keywords/static.rs @@ -0,0 +1,4 @@ +Static a = 0; +//~^ ERROR expected one of + +fn main() {} diff --git a/tests/ui/parser/misspelled-keywords/static.stderr b/tests/ui/parser/misspelled-keywords/static.stderr new file mode 100644 index 0000000000000..698cd47b16972 --- /dev/null +++ b/tests/ui/parser/misspelled-keywords/static.stderr @@ -0,0 +1,8 @@ +error: expected one of `!` or `::`, found `a` + --> $DIR/static.rs:1:8 + | +LL | Static a = 0; + | ^ expected one of `!` or `::` + +error: aborting due to 1 previous error + diff --git a/tests/ui/parser/misspelled-keywords/struct.rs b/tests/ui/parser/misspelled-keywords/struct.rs new file mode 100644 index 0000000000000..0f64dec6f56b3 --- /dev/null +++ b/tests/ui/parser/misspelled-keywords/struct.rs @@ -0,0 +1,4 @@ +Struct Foor { +//~^ ERROR expected one of + hello: String, +} diff --git a/tests/ui/parser/misspelled-keywords/struct.stderr b/tests/ui/parser/misspelled-keywords/struct.stderr new file mode 100644 index 0000000000000..8f678f4ad2e03 --- /dev/null +++ b/tests/ui/parser/misspelled-keywords/struct.stderr @@ -0,0 +1,8 @@ +error: expected one of `!` or `::`, found `Foor` + --> $DIR/struct.rs:1:8 + | +LL | Struct Foor { + | ^^^^ expected one of `!` or `::` + +error: aborting due to 1 previous error + diff --git a/tests/ui/parser/misspelled-keywords/unsafe-fn.rs b/tests/ui/parser/misspelled-keywords/unsafe-fn.rs new file mode 100644 index 0000000000000..49a1322ad637f --- /dev/null +++ b/tests/ui/parser/misspelled-keywords/unsafe-fn.rs @@ -0,0 +1,4 @@ +unsafee fn code() {} +//~^ ERROR expected one of + +fn main() {} diff --git a/tests/ui/parser/misspelled-keywords/unsafe-fn.stderr b/tests/ui/parser/misspelled-keywords/unsafe-fn.stderr new file mode 100644 index 0000000000000..2013df1c34aa8 --- /dev/null +++ b/tests/ui/parser/misspelled-keywords/unsafe-fn.stderr @@ -0,0 +1,8 @@ +error: expected one of `!` or `::`, found keyword `fn` + --> $DIR/unsafe-fn.rs:1:9 + | +LL | unsafee fn code() {} + | ^^ expected one of `!` or `::` + +error: aborting due to 1 previous error + diff --git a/tests/ui/parser/misspelled-keywords/use.rs b/tests/ui/parser/misspelled-keywords/use.rs new file mode 100644 index 0000000000000..f4911654354e2 --- /dev/null +++ b/tests/ui/parser/misspelled-keywords/use.rs @@ -0,0 +1,4 @@ +usee a::b; +//~^ ERROR expected one of + +fn main() {} diff --git a/tests/ui/parser/misspelled-keywords/use.stderr b/tests/ui/parser/misspelled-keywords/use.stderr new file mode 100644 index 0000000000000..4ca01dedd6b28 --- /dev/null +++ b/tests/ui/parser/misspelled-keywords/use.stderr @@ -0,0 +1,8 @@ +error: expected one of `!` or `::`, found `a` + --> $DIR/use.rs:1:6 + | +LL | usee a::b; + | ^ expected one of `!` or `::` + +error: aborting due to 1 previous error + diff --git a/tests/ui/parser/misspelled-keywords/where-clause.rs b/tests/ui/parser/misspelled-keywords/where-clause.rs new file mode 100644 index 0000000000000..c03d04d5fee50 --- /dev/null +++ b/tests/ui/parser/misspelled-keywords/where-clause.rs @@ -0,0 +1,8 @@ +fn code() -> u8 +wheree +//~^ ERROR expected one of + T: Debug, +{ +} + +fn main() {} diff --git a/tests/ui/parser/misspelled-keywords/where-clause.stderr b/tests/ui/parser/misspelled-keywords/where-clause.stderr new file mode 100644 index 0000000000000..4b3f996c11254 --- /dev/null +++ b/tests/ui/parser/misspelled-keywords/where-clause.stderr @@ -0,0 +1,10 @@ +error: expected one of `!`, `(`, `+`, `::`, `<`, `where`, or `{`, found `wheree` + --> $DIR/where-clause.rs:2:1 + | +LL | fn code() -> u8 + | - expected one of 7 possible tokens +LL | wheree + | ^^^^^^ unexpected token + +error: aborting due to 1 previous error + diff --git a/tests/ui/parser/misspelled-keywords/while-loop.rs b/tests/ui/parser/misspelled-keywords/while-loop.rs new file mode 100644 index 0000000000000..8d19b3c572264 --- /dev/null +++ b/tests/ui/parser/misspelled-keywords/while-loop.rs @@ -0,0 +1,7 @@ +fn main() { + whilee a < b { + //~^ ERROR expected one of + + } +} + diff --git a/tests/ui/parser/misspelled-keywords/while-loop.stderr b/tests/ui/parser/misspelled-keywords/while-loop.stderr new file mode 100644 index 0000000000000..8147a5de69673 --- /dev/null +++ b/tests/ui/parser/misspelled-keywords/while-loop.stderr @@ -0,0 +1,8 @@ +error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, `}`, or an operator, found `a` + --> $DIR/while-loop.rs:2:12 + | +LL | whilee a < b { + | ^ expected one of 8 possible tokens + +error: aborting due to 1 previous error + diff --git a/tests/ui/parser/misspelled-keywords/while-without-identifiers.rs b/tests/ui/parser/misspelled-keywords/while-without-identifiers.rs new file mode 100644 index 0000000000000..203db8306af9c --- /dev/null +++ b/tests/ui/parser/misspelled-keywords/while-without-identifiers.rs @@ -0,0 +1,4 @@ +fn main() { + whilee 2 > 1 {} + //~^ ERROR expected one of +} diff --git a/tests/ui/parser/misspelled-keywords/while-without-identifiers.stderr b/tests/ui/parser/misspelled-keywords/while-without-identifiers.stderr new file mode 100644 index 0000000000000..121e39313148a --- /dev/null +++ b/tests/ui/parser/misspelled-keywords/while-without-identifiers.stderr @@ -0,0 +1,8 @@ +error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, `}`, or an operator, found `2` + --> $DIR/while-without-identifiers.rs:2:12 + | +LL | whilee 2 > 1 {} + | ^ expected one of 8 possible tokens + +error: aborting due to 1 previous error + From 011a1fc41f22a2b07062bb8b94656dd3acc756fa Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Mon, 2 Sep 2024 16:51:18 +0200 Subject: [PATCH 0383/2194] fix: lifetime hint panic in non generic defs --- .../crates/ide/src/inlay_hints/lifetime.rs | 20 ++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/lifetime.rs b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/lifetime.rs index 653e3a6ef1df9..2163c959b18ae 100644 --- a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/lifetime.rs +++ b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/lifetime.rs @@ -389,7 +389,9 @@ fn hints_( } (None, allocated_lifetimes) => on_missing_gpl(acc, allocated_lifetimes), } - ctx.lifetime_stacks.last_mut().unwrap().extend(allocated_lifetimes); + if let Some(stack) = ctx.lifetime_stacks.last_mut() { + stack.extend(allocated_lifetimes); + } Some(()) } @@ -542,6 +544,22 @@ fn fn_trait(a: &impl Fn(&()) -> &()) {} // ^^ for<'1> //^'1 // ^'1 +"#, + ); + } + + #[test] + fn hints_in_non_gen_defs() { + check_with_config( + InlayHintsConfig { + lifetime_elision_hints: LifetimeElisionHints::Always, + ..TEST_CONFIG + }, + r#" +const _: fn(&()) -> &(); + //^^ for<'0> + //^'0 + //^'0 "#, ); } From c51953f4d8618c9db6ef383a537814ee37977b58 Mon Sep 17 00:00:00 2001 From: Bryanskiy Date: Sun, 4 Aug 2024 19:52:15 +0300 Subject: [PATCH 0384/2194] Use `DeepRejectCtxt` to quickly reject `ParamEnv` candidates --- .../src/coherence/inherent_impls.rs | 5 +- compiler/rustc_hir_typeck/src/method/probe.rs | 2 +- .../rustc_hir_typeck/src/method/suggest.rs | 9 +- compiler/rustc_metadata/src/rmeta/encoder.rs | 2 +- compiler/rustc_middle/src/ty/context.rs | 2 +- compiler/rustc_middle/src/ty/fast_reject.rs | 10 +- compiler/rustc_middle/src/ty/trait_def.rs | 12 +- .../src/solve/normalizes_to/mod.rs | 10 +- .../src/solve/trait_goals.rs | 11 +- .../error_reporting/infer/note_and_explain.rs | 8 +- .../src/traits/coherence.rs | 4 +- .../src/traits/project.rs | 8 + .../src/traits/select/candidate_assembly.rs | 12 +- .../traits/specialize/specialization_graph.rs | 6 +- compiler/rustc_type_ir/src/fast_reject.rs | 319 +++++++++++------- src/librustdoc/html/render/write_shared.rs | 4 +- 16 files changed, 272 insertions(+), 152 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs b/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs index 89acb778d6c29..3ca43955e3102 100644 --- a/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs +++ b/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs @@ -90,7 +90,8 @@ impl<'tcx> InherentCollect<'tcx> { } } - if let Some(simp) = simplify_type(self.tcx, self_ty, TreatParams::AsCandidateKey) { + if let Some(simp) = simplify_type(self.tcx, self_ty, TreatParams::InstantiateWithInfer) + { self.impls_map.incoherent_impls.entry(simp).or_default().push(impl_def_id); } else { bug!("unexpected self type: {:?}", self_ty); @@ -129,7 +130,7 @@ impl<'tcx> InherentCollect<'tcx> { } } - if let Some(simp) = simplify_type(self.tcx, ty, TreatParams::AsCandidateKey) { + if let Some(simp) = simplify_type(self.tcx, ty, TreatParams::InstantiateWithInfer) { self.impls_map.incoherent_impls.entry(simp).or_default().push(impl_def_id); } else { bug!("unexpected primitive type: {:?}", ty); diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs index 28f537c87c4ee..a566759091209 100644 --- a/compiler/rustc_hir_typeck/src/method/probe.rs +++ b/compiler/rustc_hir_typeck/src/method/probe.rs @@ -714,7 +714,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { } fn assemble_inherent_candidates_for_incoherent_ty(&mut self, self_ty: Ty<'tcx>) { - let Some(simp) = simplify_type(self.tcx, self_ty, TreatParams::AsCandidateKey) else { + let Some(simp) = simplify_type(self.tcx, self_ty, TreatParams::InstantiateWithInfer) else { bug!("unexpected incoherent type: {:?}", self_ty) }; for &impl_def_id in self.tcx.incoherent_impls(simp).into_iter().flatten() { diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index 3df32dd85052b..e5c4fcaa8a0f2 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -2234,8 +2234,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let target_ty = self .autoderef(sugg_span, rcvr_ty) .find(|(rcvr_ty, _)| { - DeepRejectCtxt::new(self.tcx, TreatParams::ForLookup) - .types_may_unify(*rcvr_ty, impl_ty) + DeepRejectCtxt::relate_rigid_infer(self.tcx).types_may_unify(*rcvr_ty, impl_ty) }) .map_or(impl_ty, |(ty, _)| ty) .peel_refs(); @@ -2497,7 +2496,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .into_iter() .any(|info| self.associated_value(info.def_id, item_name).is_some()); let found_assoc = |ty: Ty<'tcx>| { - simplify_type(tcx, ty, TreatParams::AsCandidateKey) + simplify_type(tcx, ty, TreatParams::InstantiateWithInfer) .and_then(|simp| { tcx.incoherent_impls(simp) .into_iter() @@ -3962,7 +3961,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // cases where a positive bound implies a negative impl. (candidates, Vec::new()) } else if let Some(simp_rcvr_ty) = - simplify_type(self.tcx, rcvr_ty, TreatParams::ForLookup) + simplify_type(self.tcx, rcvr_ty, TreatParams::AsRigid) { let mut potential_candidates = Vec::new(); let mut explicitly_negative = Vec::new(); @@ -3980,7 +3979,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .any(|header| { let imp = header.trait_ref.instantiate_identity(); let imp_simp = - simplify_type(self.tcx, imp.self_ty(), TreatParams::ForLookup); + simplify_type(self.tcx, imp.self_ty(), TreatParams::AsRigid); imp_simp.is_some_and(|s| s == simp_rcvr_ty) }) { diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 0d83f8c6c5c93..f8128e988e257 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -2017,7 +2017,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { let simplified_self_ty = fast_reject::simplify_type( self.tcx, trait_ref.self_ty(), - TreatParams::AsCandidateKey, + TreatParams::InstantiateWithInfer, ); trait_impls .entry(trait_ref.def_id) diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index cad3515f06809..3f49c8d9b44f2 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -428,7 +428,7 @@ impl<'tcx> Interner for TyCtxt<'tcx> { let simp = ty::fast_reject::simplify_type( tcx, self_ty, - ty::fast_reject::TreatParams::ForLookup, + ty::fast_reject::TreatParams::AsRigid, ) .unwrap(); consider_impls_for_simplified_type(simp); diff --git a/compiler/rustc_middle/src/ty/fast_reject.rs b/compiler/rustc_middle/src/ty/fast_reject.rs index 91344c4e39c8b..2945a0be424f8 100644 --- a/compiler/rustc_middle/src/ty/fast_reject.rs +++ b/compiler/rustc_middle/src/ty/fast_reject.rs @@ -3,6 +3,14 @@ pub use rustc_type_ir::fast_reject::*; use super::TyCtxt; -pub type DeepRejectCtxt<'tcx> = rustc_type_ir::fast_reject::DeepRejectCtxt>; +pub type DeepRejectCtxt< + 'tcx, + const INSTANTIATE_LHS_WITH_INFER: bool, + const INSTANTIATE_RHS_WITH_INFER: bool, +> = rustc_type_ir::fast_reject::DeepRejectCtxt< + TyCtxt<'tcx>, + INSTANTIATE_LHS_WITH_INFER, + INSTANTIATE_RHS_WITH_INFER, +>; pub type SimplifiedType = rustc_type_ir::fast_reject::SimplifiedType; diff --git a/compiler/rustc_middle/src/ty/trait_def.rs b/compiler/rustc_middle/src/ty/trait_def.rs index dfb137f738f1e..82690f70e5f18 100644 --- a/compiler/rustc_middle/src/ty/trait_def.rs +++ b/compiler/rustc_middle/src/ty/trait_def.rs @@ -168,9 +168,9 @@ impl<'tcx> TyCtxt<'tcx> { // whose outer level is not a parameter or projection. Especially for things like // `T: Clone` this is incredibly useful as we would otherwise look at all the impls // of `Clone` for `Option`, `Vec`, `ConcreteType` and so on. - // Note that we're using `TreatParams::ForLookup` to query `non_blanket_impls` while using - // `TreatParams::AsCandidateKey` while actually adding them. - if let Some(simp) = fast_reject::simplify_type(self, self_ty, TreatParams::ForLookup) { + // Note that we're using `TreatParams::AsRigid` to query `non_blanket_impls` while using + // `TreatParams::InstantiateWithInfer` while actually adding them. + if let Some(simp) = fast_reject::simplify_type(self, self_ty, TreatParams::AsRigid) { if let Some(impls) = impls.non_blanket_impls.get(&simp) { for &impl_def_id in impls { f(impl_def_id); @@ -190,7 +190,9 @@ impl<'tcx> TyCtxt<'tcx> { self_ty: Ty<'tcx>, ) -> impl Iterator + 'tcx { let impls = self.trait_impls_of(trait_def_id); - if let Some(simp) = fast_reject::simplify_type(self, self_ty, TreatParams::AsCandidateKey) { + if let Some(simp) = + fast_reject::simplify_type(self, self_ty, TreatParams::InstantiateWithInfer) + { if let Some(impls) = impls.non_blanket_impls.get(&simp) { return impls.iter().copied(); } @@ -239,7 +241,7 @@ pub(super) fn trait_impls_of_provider(tcx: TyCtxt<'_>, trait_id: DefId) -> Trait let impl_self_ty = tcx.type_of(impl_def_id).instantiate_identity(); if let Some(simplified_self_ty) = - fast_reject::simplify_type(tcx, impl_self_ty, TreatParams::AsCandidateKey) + fast_reject::simplify_type(tcx, impl_self_ty, TreatParams::InstantiateWithInfer) { impls.non_blanket_impls.entry(simplified_self_ty).or_default().push(impl_def_id); } else { diff --git a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs index 5738173c7a804..1865791fef058 100644 --- a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs @@ -3,7 +3,7 @@ mod inherent; mod opaque_types; mod weak_types; -use rustc_type_ir::fast_reject::{DeepRejectCtxt, TreatParams}; +use rustc_type_ir::fast_reject::DeepRejectCtxt; use rustc_type_ir::inherent::*; use rustc_type_ir::lang_items::TraitSolverLangItem; use rustc_type_ir::{self as ty, Interner, NormalizesTo, Upcast as _}; @@ -106,6 +106,12 @@ where if let Some(projection_pred) = assumption.as_projection_clause() { if projection_pred.projection_def_id() == goal.predicate.def_id() { let cx = ecx.cx(); + if !DeepRejectCtxt::relate_rigid_rigid(ecx.cx()).args_may_unify( + goal.predicate.alias.args, + projection_pred.skip_binder().projection_term.args, + ) { + return Err(NoSolution); + } ecx.probe_trait_candidate(source).enter(|ecx| { let assumption_projection_pred = ecx.instantiate_binder_with_infer(projection_pred); @@ -144,7 +150,7 @@ where let goal_trait_ref = goal.predicate.alias.trait_ref(cx); let impl_trait_ref = cx.impl_trait_ref(impl_def_id); - if !DeepRejectCtxt::new(ecx.cx(), TreatParams::ForLookup).args_may_unify( + if !DeepRejectCtxt::relate_rigid_infer(ecx.cx()).args_may_unify( goal.predicate.alias.trait_ref(cx).args, impl_trait_ref.skip_binder().args, ) { diff --git a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs index 1314b7eb6ffc6..997e98a010592 100644 --- a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs +++ b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs @@ -2,7 +2,7 @@ use rustc_ast_ir::Movability; use rustc_type_ir::data_structures::IndexSet; -use rustc_type_ir::fast_reject::{DeepRejectCtxt, TreatParams}; +use rustc_type_ir::fast_reject::DeepRejectCtxt; use rustc_type_ir::inherent::*; use rustc_type_ir::lang_items::TraitSolverLangItem; use rustc_type_ir::visit::TypeVisitableExt as _; @@ -47,7 +47,7 @@ where let cx = ecx.cx(); let impl_trait_ref = cx.impl_trait_ref(impl_def_id); - if !DeepRejectCtxt::new(ecx.cx(), TreatParams::ForLookup) + if !DeepRejectCtxt::relate_rigid_infer(ecx.cx()) .args_may_unify(goal.predicate.trait_ref.args, impl_trait_ref.skip_binder().args) { return Err(NoSolution); @@ -124,6 +124,13 @@ where if trait_clause.def_id() == goal.predicate.def_id() && trait_clause.polarity() == goal.predicate.polarity { + if !DeepRejectCtxt::relate_rigid_rigid(ecx.cx()).args_may_unify( + goal.predicate.trait_ref.args, + trait_clause.skip_binder().trait_ref.args, + ) { + return Err(NoSolution); + } + ecx.probe_trait_candidate(source).enter(|ecx| { let assumption_trait_pred = ecx.instantiate_binder_with_infer(trait_clause); ecx.eq( diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/note_and_explain.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/note_and_explain.rs index 05c79170902de..b56f2775139c9 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/note_and_explain.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/note_and_explain.rs @@ -4,7 +4,7 @@ use rustc_hir as hir; use rustc_hir::def::DefKind; use rustc_middle::traits::{ObligationCause, ObligationCauseCode}; use rustc_middle::ty::error::{ExpectedFound, TypeError}; -use rustc_middle::ty::fast_reject::{DeepRejectCtxt, TreatParams}; +use rustc_middle::ty::fast_reject::DeepRejectCtxt; use rustc_middle::ty::print::{FmtPrinter, Printer}; use rustc_middle::ty::{self, suggest_constraining_type_param, Ty}; use rustc_span::def_id::DefId; @@ -316,7 +316,7 @@ impl Trait for X { { let mut has_matching_impl = false; tcx.for_each_relevant_impl(def_id, values.found, |did| { - if DeepRejectCtxt::new(tcx, TreatParams::ForLookup) + if DeepRejectCtxt::relate_rigid_infer(tcx) .types_may_unify(values.found, tcx.type_of(did).skip_binder()) { has_matching_impl = true; @@ -337,7 +337,7 @@ impl Trait for X { { let mut has_matching_impl = false; tcx.for_each_relevant_impl(def_id, values.expected, |did| { - if DeepRejectCtxt::new(tcx, TreatParams::ForLookup) + if DeepRejectCtxt::relate_rigid_infer(tcx) .types_may_unify(values.expected, tcx.type_of(did).skip_binder()) { has_matching_impl = true; @@ -357,7 +357,7 @@ impl Trait for X { { let mut has_matching_impl = false; tcx.for_each_relevant_impl(def_id, values.found, |did| { - if DeepRejectCtxt::new(tcx, TreatParams::ForLookup) + if DeepRejectCtxt::relate_rigid_infer(tcx) .types_may_unify(values.found, tcx.type_of(did).skip_binder()) { has_matching_impl = true; diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs index 2d843d8f17406..4fac3f1aedf9f 100644 --- a/compiler/rustc_trait_selection/src/traits/coherence.rs +++ b/compiler/rustc_trait_selection/src/traits/coherence.rs @@ -15,7 +15,7 @@ use rustc_middle::bug; use rustc_middle::traits::query::NoSolution; use rustc_middle::traits::solve::{CandidateSource, Certainty, Goal}; use rustc_middle::traits::specialization_graph::OverlapMode; -use rustc_middle::ty::fast_reject::{DeepRejectCtxt, TreatParams}; +use rustc_middle::ty::fast_reject::DeepRejectCtxt; use rustc_middle::ty::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor}; use rustc_middle::ty::{self, Ty, TyCtxt}; pub use rustc_next_trait_solver::coherence::*; @@ -94,7 +94,7 @@ pub fn overlapping_impls( // Before doing expensive operations like entering an inference context, do // a quick check via fast_reject to tell if the impl headers could possibly // unify. - let drcx = DeepRejectCtxt::new(tcx, TreatParams::AsCandidateKey); + let drcx = DeepRejectCtxt::relate_infer_infer(tcx); let impl1_ref = tcx.impl_trait_ref(impl1_def_id); let impl2_ref = tcx.impl_trait_ref(impl2_def_id); let may_overlap = match (impl1_ref, impl2_ref) { diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index 568214fe02298..a15860181e45e 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -13,6 +13,7 @@ use rustc_infer::traits::ObligationCauseCode; use rustc_middle::traits::select::OverflowError; pub use rustc_middle::traits::Reveal; use rustc_middle::traits::{BuiltinImplSource, ImplSource, ImplSourceUserDefinedData}; +use rustc_middle::ty::fast_reject::DeepRejectCtxt; use rustc_middle::ty::fold::TypeFoldable; use rustc_middle::ty::visit::{MaxUniverse, TypeVisitable, TypeVisitableExt}; use rustc_middle::ty::{self, Term, Ty, TyCtxt, Upcast}; @@ -885,6 +886,7 @@ fn assemble_candidates_from_predicates<'cx, 'tcx>( potentially_unnormalized_candidates: bool, ) { let infcx = selcx.infcx; + let drcx = DeepRejectCtxt::relate_rigid_rigid(selcx.tcx()); for predicate in env_predicates { let bound_predicate = predicate.kind(); if let ty::ClauseKind::Projection(data) = predicate.kind().skip_binder() { @@ -893,6 +895,12 @@ fn assemble_candidates_from_predicates<'cx, 'tcx>( continue; } + if !drcx + .args_may_unify(obligation.predicate.args, data.skip_binder().projection_term.args) + { + continue; + } + let is_match = infcx.probe(|_| { selcx.match_projection_projections( obligation, diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs index cb8deeaedb66f..b03d8f8dc5f87 100644 --- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs +++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs @@ -13,7 +13,7 @@ use hir::LangItem; use rustc_data_structures::fx::{FxHashSet, FxIndexSet}; use rustc_hir as hir; use rustc_infer::traits::{Obligation, ObligationCause, PolyTraitObligation, SelectionError}; -use rustc_middle::ty::fast_reject::{DeepRejectCtxt, TreatParams}; +use rustc_middle::ty::fast_reject::DeepRejectCtxt; use rustc_middle::ty::{self, ToPolyTraitRef, Ty, TypeVisitableExt}; use rustc_middle::{bug, span_bug}; @@ -247,11 +247,17 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { .filter(|p| p.def_id() == stack.obligation.predicate.def_id()) .filter(|p| p.polarity() == stack.obligation.predicate.polarity()); + let drcx = DeepRejectCtxt::relate_rigid_rigid(self.tcx()); + let obligation_args = stack.obligation.predicate.skip_binder().trait_ref.args; // Keep only those bounds which may apply, and propagate overflow if it occurs. for bound in bounds { + let bound_trait_ref = bound.map_bound(|t| t.trait_ref); + if !drcx.args_may_unify(obligation_args, bound_trait_ref.skip_binder().args) { + continue; + } // FIXME(oli-obk): it is suspicious that we are dropping the constness and // polarity here. - let wc = self.where_clause_may_apply(stack, bound.map_bound(|t| t.trait_ref))?; + let wc = self.where_clause_may_apply(stack, bound_trait_ref)?; if wc.may_apply() { candidates.vec.push(ParamCandidate(bound)); } @@ -580,7 +586,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { return; } - let drcx = DeepRejectCtxt::new(self.tcx(), TreatParams::ForLookup); + let drcx = DeepRejectCtxt::relate_rigid_infer(self.tcx()); let obligation_args = obligation.predicate.skip_binder().trait_ref.args; self.tcx().for_each_relevant_impl( obligation.predicate.def_id(), diff --git a/compiler/rustc_trait_selection/src/traits/specialize/specialization_graph.rs b/compiler/rustc_trait_selection/src/traits/specialize/specialization_graph.rs index 732f1b0a3d7cc..c0a712cbf9fd8 100644 --- a/compiler/rustc_trait_selection/src/traits/specialize/specialization_graph.rs +++ b/compiler/rustc_trait_selection/src/traits/specialize/specialization_graph.rs @@ -40,7 +40,7 @@ impl<'tcx> Children { fn insert_blindly(&mut self, tcx: TyCtxt<'tcx>, impl_def_id: DefId) { let trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap().skip_binder(); if let Some(st) = - fast_reject::simplify_type(tcx, trait_ref.self_ty(), TreatParams::AsCandidateKey) + fast_reject::simplify_type(tcx, trait_ref.self_ty(), TreatParams::InstantiateWithInfer) { debug!("insert_blindly: impl_def_id={:?} st={:?}", impl_def_id, st); self.non_blanket_impls.entry(st).or_default().push(impl_def_id) @@ -57,7 +57,7 @@ impl<'tcx> Children { let trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap().skip_binder(); let vec: &mut Vec; if let Some(st) = - fast_reject::simplify_type(tcx, trait_ref.self_ty(), TreatParams::AsCandidateKey) + fast_reject::simplify_type(tcx, trait_ref.self_ty(), TreatParams::InstantiateWithInfer) { debug!("remove_existing: impl_def_id={:?} st={:?}", impl_def_id, st); vec = self.non_blanket_impls.get_mut(&st).unwrap(); @@ -278,7 +278,7 @@ impl<'tcx> Graph { let mut parent = trait_def_id; let mut last_lint = None; let simplified = - fast_reject::simplify_type(tcx, trait_ref.self_ty(), TreatParams::AsCandidateKey); + fast_reject::simplify_type(tcx, trait_ref.self_ty(), TreatParams::InstantiateWithInfer); // Descend the specialization tree, where `parent` is the current parent node. loop { diff --git a/compiler/rustc_type_ir/src/fast_reject.rs b/compiler/rustc_type_ir/src/fast_reject.rs index fab4a0991175d..2c8e47bcbca2a 100644 --- a/compiler/rustc_type_ir/src/fast_reject.rs +++ b/compiler/rustc_type_ir/src/fast_reject.rs @@ -74,13 +74,13 @@ impl> ToStableHashKey for SimplifiedType pub enum TreatParams { /// Treat parameters as infer vars. This is the correct mode for caching /// an impl's type for lookup. - AsCandidateKey, + InstantiateWithInfer, /// Treat parameters as placeholders in the given environment. This is the /// correct mode for *lookup*, as during candidate selection. /// /// This also treats projections with inference variables as infer vars /// since they could be further normalized. - ForLookup, + AsRigid, } /// Tries to simplify a type by only returning the outermost injective¹ layer, if one exists. @@ -140,18 +140,16 @@ pub fn simplify_type( } ty::Placeholder(..) => Some(SimplifiedType::Placeholder), ty::Param(_) => match treat_params { - TreatParams::ForLookup => Some(SimplifiedType::Placeholder), - TreatParams::AsCandidateKey => None, + TreatParams::AsRigid => Some(SimplifiedType::Placeholder), + TreatParams::InstantiateWithInfer => None, }, ty::Alias(..) => match treat_params { // When treating `ty::Param` as a placeholder, projections also // don't unify with anything else as long as they are fully normalized. // FIXME(-Znext-solver): Can remove this `if` and always simplify to `Placeholder` // when the new solver is enabled by default. - TreatParams::ForLookup if !ty.has_non_region_infer() => { - Some(SimplifiedType::Placeholder) - } - TreatParams::ForLookup | TreatParams::AsCandidateKey => None, + TreatParams::AsRigid if !ty.has_non_region_infer() => Some(SimplifiedType::Placeholder), + TreatParams::AsRigid | TreatParams::InstantiateWithInfer => None, }, ty::Foreign(def_id) => Some(SimplifiedType::Foreign(def_id)), ty::Error(_) => Some(SimplifiedType::Error), @@ -173,29 +171,49 @@ impl SimplifiedType { } } -/// Given generic arguments from an obligation and an impl, -/// could these two be unified after replacing parameters in the -/// the impl with inference variables. +/// Given generic arguments, could they be unified after +/// replacing parameters with inference variables or placeholders. +/// This behavior is toggled using the const generics. /// -/// For obligations, parameters won't be replaced by inference -/// variables and only unify with themselves. We treat them -/// the same way we treat placeholders. +/// We use this to quickly reject impl/wc candidates without needing +/// to instantiate generic arguments/having to enter a probe. /// /// We also use this function during coherence. For coherence the /// impls only have to overlap for some value, so we treat parameters -/// on both sides like inference variables. This behavior is toggled -/// using the `treat_obligation_params` field. +/// on both sides like inference variables. #[derive(Debug, Clone, Copy)] -pub struct DeepRejectCtxt { - treat_obligation_params: TreatParams, +pub struct DeepRejectCtxt< + I: Interner, + const INSTANTIATE_LHS_WITH_INFER: bool, + const INSTANTIATE_RHS_WITH_INFER: bool, +> { _interner: PhantomData, } -impl DeepRejectCtxt { - pub fn new(_interner: I, treat_obligation_params: TreatParams) -> Self { - DeepRejectCtxt { treat_obligation_params, _interner: PhantomData } +impl DeepRejectCtxt { + /// Treat parameters in both the lhs and the rhs as rigid. + pub fn relate_rigid_rigid(_interner: I) -> DeepRejectCtxt { + DeepRejectCtxt { _interner: PhantomData } + } +} + +impl DeepRejectCtxt { + /// Treat parameters in both the lhs and the rhs as infer vars. + pub fn relate_infer_infer(_interner: I) -> DeepRejectCtxt { + DeepRejectCtxt { _interner: PhantomData } } +} +impl DeepRejectCtxt { + /// Treat parameters in the lhs as rigid, and in rhs as infer vars. + pub fn relate_rigid_infer(_interner: I) -> DeepRejectCtxt { + DeepRejectCtxt { _interner: PhantomData } + } +} + +impl + DeepRejectCtxt +{ pub fn args_may_unify( self, obligation_args: I::GenericArgs, @@ -216,11 +234,18 @@ impl DeepRejectCtxt { }) } - pub fn types_may_unify(self, obligation_ty: I::Ty, impl_ty: I::Ty) -> bool { - match impl_ty.kind() { - // Start by checking whether the type in the impl may unify with + pub fn types_may_unify(self, lhs: I::Ty, rhs: I::Ty) -> bool { + match rhs.kind() { + // Start by checking whether the `rhs` type may unify with // pretty much everything. Just return `true` in that case. - ty::Param(_) | ty::Error(_) | ty::Alias(..) => return true, + ty::Param(_) => { + if INSTANTIATE_RHS_WITH_INFER { + return true; + } + } + ty::Error(_) | ty::Alias(..) | ty::Bound(..) => return true, + ty::Infer(var) => return self.var_and_ty_may_unify(var, lhs), + // These types only unify with inference variables or their own // variant. ty::Bool @@ -238,159 +263,217 @@ impl DeepRejectCtxt { | ty::Ref(..) | ty::Never | ty::Tuple(..) + | ty::FnDef(..) | ty::FnPtr(..) - | ty::Foreign(..) => debug_assert!(impl_ty.is_known_rigid()), - ty::FnDef(..) | ty::Closure(..) | ty::CoroutineClosure(..) | ty::Coroutine(..) | ty::CoroutineWitness(..) - | ty::Placeholder(..) - | ty::Bound(..) - | ty::Infer(_) => panic!("unexpected impl_ty: {impl_ty:?}"), - } + | ty::Foreign(_) + | ty::Placeholder(_) => {} + }; - let k = impl_ty.kind(); - match obligation_ty.kind() { - // Purely rigid types, use structural equivalence. - ty::Bool - | ty::Char - | ty::Int(_) - | ty::Uint(_) - | ty::Float(_) - | ty::Str - | ty::Never - | ty::Foreign(_) => obligation_ty == impl_ty, - ty::Ref(_, obl_ty, obl_mutbl) => match k { - ty::Ref(_, impl_ty, impl_mutbl) => { - obl_mutbl == impl_mutbl && self.types_may_unify(obl_ty, impl_ty) + // For purely rigid types, use structural equivalence. + match lhs.kind() { + ty::Ref(_, lhs_ty, lhs_mutbl) => match rhs.kind() { + ty::Ref(_, rhs_ty, rhs_mutbl) => { + lhs_mutbl == rhs_mutbl && self.types_may_unify(lhs_ty, rhs_ty) } _ => false, }, - ty::Adt(obl_def, obl_args) => match k { - ty::Adt(impl_def, impl_args) => { - obl_def == impl_def && self.args_may_unify(obl_args, impl_args) + + ty::Adt(lhs_def, lhs_args) => match rhs.kind() { + ty::Adt(rhs_def, rhs_args) => { + lhs_def == rhs_def && self.args_may_unify(lhs_args, rhs_args) } _ => false, }, - ty::Pat(obl_ty, _) => { - // FIXME(pattern_types): take pattern into account - matches!(k, ty::Pat(impl_ty, _) if self.types_may_unify(obl_ty, impl_ty)) + + // Depending on the value of const generics, we either treat generic parameters + // like placeholders or like inference variables. + ty::Param(lhs) => { + INSTANTIATE_LHS_WITH_INFER + || match rhs.kind() { + ty::Param(rhs) => lhs == rhs, + _ => false, + } } - ty::Slice(obl_ty) => { - matches!(k, ty::Slice(impl_ty) if self.types_may_unify(obl_ty, impl_ty)) + + // Placeholder types don't unify with anything on their own. + ty::Placeholder(lhs) => { + matches!(rhs.kind(), ty::Placeholder(rhs) if lhs == rhs) } - ty::Array(obl_ty, obl_len) => match k { - ty::Array(impl_ty, impl_len) => { - self.types_may_unify(obl_ty, impl_ty) - && self.consts_may_unify(obl_len, impl_len) + + ty::Infer(var) => self.var_and_ty_may_unify(var, rhs), + + // As we're walking the whole type, it may encounter projections + // inside of binders and what not, so we're just going to assume that + // projections can unify with other stuff. + // + // Looking forward to lazy normalization this is the safer strategy anyways. + ty::Alias(..) => true, + + ty::Int(_) + | ty::Uint(_) + | ty::Float(_) + | ty::Str + | ty::Bool + | ty::Char + | ty::Never + | ty::Foreign(_) => lhs == rhs, + + ty::Tuple(lhs) => match rhs.kind() { + ty::Tuple(rhs) => { + lhs.len() == rhs.len() + && iter::zip(lhs.iter(), rhs.iter()) + .all(|(lhs, rhs)| self.types_may_unify(lhs, rhs)) } _ => false, }, - ty::Tuple(obl) => match k { - ty::Tuple(imp) => { - obl.len() == imp.len() - && iter::zip(obl.iter(), imp.iter()) - .all(|(obl, imp)| self.types_may_unify(obl, imp)) + + ty::Array(lhs_ty, lhs_len) => match rhs.kind() { + ty::Array(rhs_ty, rhs_len) => { + self.types_may_unify(lhs_ty, rhs_ty) && self.consts_may_unify(lhs_len, rhs_len) } _ => false, }, - ty::RawPtr(obl_ty, obl_mutbl) => match k { - ty::RawPtr(imp_ty, imp_mutbl) => { - obl_mutbl == imp_mutbl && self.types_may_unify(obl_ty, imp_ty) + + ty::RawPtr(lhs_ty, lhs_mutbl) => match rhs.kind() { + ty::RawPtr(rhs_ty, rhs_mutbl) => { + lhs_mutbl == rhs_mutbl && self.types_may_unify(lhs_ty, rhs_ty) } _ => false, }, - ty::Dynamic(obl_preds, ..) => { + + ty::Slice(lhs_ty) => { + matches!(rhs.kind(), ty::Slice(rhs_ty) if self.types_may_unify(lhs_ty, rhs_ty)) + } + + ty::Dynamic(lhs_preds, ..) => { // Ideally we would walk the existential predicates here or at least // compare their length. But considering that the relevant `Relate` impl // actually sorts and deduplicates these, that doesn't work. - matches!(k, ty::Dynamic(impl_preds, ..) if - obl_preds.principal_def_id() == impl_preds.principal_def_id() + matches!(rhs.kind(), ty::Dynamic(rhs_preds, ..) if + lhs_preds.principal_def_id() == rhs_preds.principal_def_id() ) } - ty::FnPtr(obl_sig_tys, obl_hdr) => match k { - ty::FnPtr(impl_sig_tys, impl_hdr) => { - let obl_sig_tys = obl_sig_tys.skip_binder().inputs_and_output; - let impl_sig_tys = impl_sig_tys.skip_binder().inputs_and_output; - - obl_hdr == impl_hdr - && obl_sig_tys.len() == impl_sig_tys.len() - && iter::zip(obl_sig_tys.iter(), impl_sig_tys.iter()) - .all(|(obl, imp)| self.types_may_unify(obl, imp)) + + ty::FnPtr(lhs_sig_tys, lhs_hdr) => match rhs.kind() { + ty::FnPtr(rhs_sig_tys, rhs_hdr) => { + let lhs_sig_tys = lhs_sig_tys.skip_binder().inputs_and_output; + let rhs_sig_tys = rhs_sig_tys.skip_binder().inputs_and_output; + + lhs_hdr == rhs_hdr + && lhs_sig_tys.len() == rhs_sig_tys.len() + && iter::zip(lhs_sig_tys.iter(), rhs_sig_tys.iter()) + .all(|(lhs, rhs)| self.types_may_unify(lhs, rhs)) } _ => false, }, - // Impls cannot contain these types as these cannot be named directly. - ty::FnDef(..) | ty::Closure(..) | ty::CoroutineClosure(..) | ty::Coroutine(..) => false, - - // Placeholder types don't unify with anything on their own - ty::Placeholder(..) | ty::Bound(..) => false, + ty::Bound(..) => true, - // Depending on the value of `treat_obligation_params`, we either - // treat generic parameters like placeholders or like inference variables. - ty::Param(_) => match self.treat_obligation_params { - TreatParams::ForLookup => false, - TreatParams::AsCandidateKey => true, + ty::FnDef(lhs_def_id, lhs_args) => match rhs.kind() { + ty::FnDef(rhs_def_id, rhs_args) => { + lhs_def_id == rhs_def_id && self.args_may_unify(lhs_args, rhs_args) + } + _ => false, }, - ty::Infer(ty::IntVar(_)) => impl_ty.is_integral(), - - ty::Infer(ty::FloatVar(_)) => impl_ty.is_floating_point(), + ty::Closure(lhs_def_id, lhs_args) => match rhs.kind() { + ty::Closure(rhs_def_id, rhs_args) => { + lhs_def_id == rhs_def_id && self.args_may_unify(lhs_args, rhs_args) + } + _ => false, + }, - ty::Infer(_) => true, + ty::CoroutineClosure(lhs_def_id, lhs_args) => match rhs.kind() { + ty::CoroutineClosure(rhs_def_id, rhs_args) => { + lhs_def_id == rhs_def_id && self.args_may_unify(lhs_args, rhs_args) + } + _ => false, + }, - // As we're walking the whole type, it may encounter projections - // inside of binders and what not, so we're just going to assume that - // projections can unify with other stuff. - // - // Looking forward to lazy normalization this is the safer strategy anyways. - ty::Alias(..) => true, + ty::Coroutine(lhs_def_id, lhs_args) => match rhs.kind() { + ty::Coroutine(rhs_def_id, rhs_args) => { + lhs_def_id == rhs_def_id && self.args_may_unify(lhs_args, rhs_args) + } + _ => false, + }, - ty::Error(_) => true, + ty::CoroutineWitness(lhs_def_id, lhs_args) => match rhs.kind() { + ty::CoroutineWitness(rhs_def_id, rhs_args) => { + lhs_def_id == rhs_def_id && self.args_may_unify(lhs_args, rhs_args) + } + _ => false, + }, - ty::CoroutineWitness(..) => { - panic!("unexpected obligation type: {:?}", obligation_ty) + ty::Pat(lhs_ty, _) => { + // FIXME(pattern_types): take pattern into account + matches!(rhs.kind(), ty::Pat(rhs_ty, _) if self.types_may_unify(lhs_ty, rhs_ty)) } + + ty::Error(..) => true, } } - pub fn consts_may_unify(self, obligation_ct: I::Const, impl_ct: I::Const) -> bool { - let impl_val = match impl_ct.kind() { + pub fn consts_may_unify(self, lhs: I::Const, rhs: I::Const) -> bool { + match rhs.kind() { + ty::ConstKind::Param(_) => { + if INSTANTIATE_RHS_WITH_INFER { + return true; + } + } + ty::ConstKind::Expr(_) - | ty::ConstKind::Param(_) | ty::ConstKind::Unevaluated(_) - | ty::ConstKind::Error(_) => { + | ty::ConstKind::Error(_) + | ty::ConstKind::Infer(_) + | ty::ConstKind::Bound(..) => { return true; } - ty::ConstKind::Value(_, impl_val) => impl_val, - ty::ConstKind::Infer(_) | ty::ConstKind::Bound(..) | ty::ConstKind::Placeholder(_) => { - panic!("unexpected impl arg: {:?}", impl_ct) - } + + ty::ConstKind::Value(..) | ty::ConstKind::Placeholder(_) => {} }; - match obligation_ct.kind() { - ty::ConstKind::Param(_) => match self.treat_obligation_params { - TreatParams::ForLookup => false, - TreatParams::AsCandidateKey => true, + match lhs.kind() { + ty::ConstKind::Value(_, lhs_val) => match rhs.kind() { + ty::ConstKind::Value(_, rhs_val) => lhs_val == rhs_val, + _ => false, }, + ty::ConstKind::Param(lhs) => { + INSTANTIATE_LHS_WITH_INFER + || match rhs.kind() { + ty::ConstKind::Param(rhs) => lhs == rhs, + _ => false, + } + } + // Placeholder consts don't unify with anything on their own - ty::ConstKind::Placeholder(_) => false, + ty::ConstKind::Placeholder(lhs) => { + matches!(rhs.kind(), ty::ConstKind::Placeholder(rhs) if lhs == rhs) + } // As we don't necessarily eagerly evaluate constants, // they might unify with any value. ty::ConstKind::Expr(_) | ty::ConstKind::Unevaluated(_) | ty::ConstKind::Error(_) => { true } - ty::ConstKind::Value(_, obl_val) => obl_val == impl_val, - ty::ConstKind::Infer(_) => true, + ty::ConstKind::Infer(_) | ty::ConstKind::Bound(..) => true, + } + } - ty::ConstKind::Bound(..) => { - panic!("unexpected obl const: {:?}", obligation_ct) - } + fn var_and_ty_may_unify(self, var: ty::InferTy, ty: I::Ty) -> bool { + if !ty.is_known_rigid() { + return true; + } + + match var { + ty::IntVar(_) => ty.is_integral(), + ty::FloatVar(_) => ty.is_floating_point(), + _ => true, } } } diff --git a/src/librustdoc/html/render/write_shared.rs b/src/librustdoc/html/render/write_shared.rs index a18b7a252a402..b68d7d8759cb1 100644 --- a/src/librustdoc/html/render/write_shared.rs +++ b/src/librustdoc/html/render/write_shared.rs @@ -29,7 +29,7 @@ use itertools::Itertools; use regex::Regex; use rustc_data_structures::flock; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; -use rustc_middle::ty::fast_reject::{DeepRejectCtxt, TreatParams}; +use rustc_middle::ty::fast_reject::DeepRejectCtxt; use rustc_middle::ty::TyCtxt; use rustc_span::def_id::DefId; use rustc_span::Symbol; @@ -826,7 +826,7 @@ impl<'cx, 'cache> DocVisitor for TypeImplCollector<'cx, 'cache> { // Be aware of `tests/rustdoc/type-alias/deeply-nested-112515.rs` which might regress. let Some(impl_did) = impl_item_id.as_def_id() else { continue }; let for_ty = self.cx.tcx().type_of(impl_did).skip_binder(); - let reject_cx = DeepRejectCtxt::new(self.cx.tcx(), TreatParams::AsCandidateKey); + let reject_cx = DeepRejectCtxt::relate_infer_infer(self.cx.tcx()); if !reject_cx.types_may_unify(aliased_ty, for_ty) { continue; } From 42ed30f0c6a5f175fc6591e5c9f028b1110b9f95 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lauren=C8=9Biu=20Nicola?= Date: Mon, 2 Sep 2024 20:04:35 +0300 Subject: [PATCH 0385/2194] Avoid Option::is_none_or for a while --- src/tools/rust-analyzer/crates/hir-ty/src/consteval.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/consteval.rs b/src/tools/rust-analyzer/crates/hir-ty/src/consteval.rs index e5c493ac56e1b..968a828e9dfef 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/consteval.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/consteval.rs @@ -287,7 +287,7 @@ pub(crate) fn const_eval_discriminant_variant( } let repr = db.enum_data(loc.parent).repr; - let is_signed = repr.and_then(|repr| repr.int).is_none_or(|int| int.is_signed()); + let is_signed = IsNoneOr::is_none_or(repr.and_then(|repr| repr.int), |int| int.is_signed()); let mir_body = db.monomorphized_mir_body( def, From 2f8ef4c8878c1505b71973275532ef38288554be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lauren=C8=9Biu=20Nicola?= Date: Mon, 2 Sep 2024 20:05:35 +0300 Subject: [PATCH 0386/2194] Merge some strings --- .../ide-assists/src/handlers/toggle_macro_delimiter.rs | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/toggle_macro_delimiter.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/toggle_macro_delimiter.rs index eedb2ea3b9ada..e452b5f77870c 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/toggle_macro_delimiter.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/toggle_macro_delimiter.rs @@ -64,12 +64,9 @@ pub(crate) fn toggle_macro_delimiter(acc: &mut Assists, ctx: &AssistContext<'_>) acc.add( AssistId("toggle_macro_delimiter", AssistKind::Refactor), match token { - MacroDelims::LPar => "Replace delimiters with braces", - MacroDelims::RPar => "Replace delimiters with braces", - MacroDelims::LBra => "Replace delimiters with parentheses", - MacroDelims::RBra => "Replace delimiters with parentheses", - MacroDelims::LCur => "Replace delimiters with brackets", - MacroDelims::RCur => "Replace delimiters with brackets", + MacroDelims::LPar | MacroDelims::RPar => "Replace delimiters with braces", + MacroDelims::LBra | MacroDelims::RBra => "Replace delimiters with parentheses", + MacroDelims::LCur | MacroDelims::RCur => "Replace delimiters with brackets", }, token_tree.syntax().text_range(), |builder| { From 7ac5fdaf99efbc74a9e351ab3018a86ea6b64c5d Mon Sep 17 00:00:00 2001 From: David Wood Date: Mon, 2 Sep 2024 18:12:20 +0100 Subject: [PATCH 0387/2194] mailmap: add new email for davidtwco Signed-off-by: David Wood --- .mailmap | 1 + 1 file changed, 1 insertion(+) diff --git a/.mailmap b/.mailmap index 4d93792422c23..975684947fa54 100644 --- a/.mailmap +++ b/.mailmap @@ -146,6 +146,7 @@ David Klein David Manescu David Ross David Wood +David Wood Deadbeef Deadbeef dependabot[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com> From 5d47b4d198a6b57033ba924fab0b0808a57843d0 Mon Sep 17 00:00:00 2001 From: Boxy Date: Mon, 2 Sep 2024 18:15:20 +0100 Subject: [PATCH 0388/2194] mailmapper? --- .mailmap | 1 + 1 file changed, 1 insertion(+) diff --git a/.mailmap b/.mailmap index 4d93792422c23..73cde3c065ca7 100644 --- a/.mailmap +++ b/.mailmap @@ -81,6 +81,7 @@ boolean_coercion Boris Egorov bors bors[bot] <26634292+bors[bot]@users.noreply.github.com> bors bors[bot] +Boxy Braden Nelson Brandon Sanderson Brandon Sanderson Brett Cannon Brett Cannon From fa77b9d21c2ef3997552dda59b31b29e571c2223 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Sun, 1 Sep 2024 22:31:17 +0200 Subject: [PATCH 0389/2194] Remove kobzol vacation status --- triagebot.toml | 1 - 1 file changed, 1 deletion(-) diff --git a/triagebot.toml b/triagebot.toml index 651d27f034108..1afcad7d1315c 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -917,7 +917,6 @@ users_on_vacation = [ "jhpratt", "joboet", "jyn514", - "kobzol", "oli-obk", "tgross35", ] From 8be9fed672e361a0e591d996a1c4fb96671c6d02 Mon Sep 17 00:00:00 2001 From: Ben Kimock Date: Mon, 2 Sep 2024 14:57:55 -0400 Subject: [PATCH 0390/2194] Fix compile error in solid's remove_dir_all --- library/std/src/sys/pal/solid/fs.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/std/src/sys/pal/solid/fs.rs b/library/std/src/sys/pal/solid/fs.rs index 591be66fcb463..bce9aa6d99cd1 100644 --- a/library/std/src/sys/pal/solid/fs.rs +++ b/library/std/src/sys/pal/solid/fs.rs @@ -538,7 +538,7 @@ pub fn remove_dir_all(path: &Path) -> io::Result<()> { } }; // ignore internal NotFound errors - if let Err(err) = result + if let Err(err) = &result && err.kind() != io::ErrorKind::NotFound { return result; From 111c690426ac42e3f8c2db011fc74dfbb91d81d3 Mon Sep 17 00:00:00 2001 From: Shoyu Vanilla Date: Thu, 29 Aug 2024 00:12:16 +0900 Subject: [PATCH 0391/2194] feat: Implement cast typechecks --- .../crates/hir-def/src/data/adt.rs | 22 + .../crates/hir-ty/src/consteval/tests.rs | 21 +- .../hir-ty/src/consteval/tests/intrinsics.rs | 1 + .../rust-analyzer/crates/hir-ty/src/infer.rs | 32 +- .../crates/hir-ty/src/infer/cast.rs | 417 ++++++- .../crates/hir-ty/src/infer/expr.rs | 7 +- .../crates/hir-ty/src/infer/unify.rs | 30 +- .../rust-analyzer/crates/hir-ty/src/lib.rs | 1 + .../rust-analyzer/crates/hir-ty/src/mir.rs | 4 +- .../crates/hir-ty/src/mir/eval.rs | 3 +- .../crates/hir-ty/src/mir/eval/tests.rs | 3 +- .../crates/hir-ty/src/mir/lower.rs | 79 +- .../hir-ty/src/tests/method_resolution.rs | 1 + .../crates/hir-ty/src/tests/regression.rs | 2 + .../crates/hir-ty/src/tests/simple.rs | 1 + .../crates/hir/src/diagnostics.rs | 30 +- src/tools/rust-analyzer/crates/hir/src/lib.rs | 2 +- .../ide-assists/src/handlers/inline_call.rs | 1 + .../src/handlers/inline_local_variable.rs | 5 +- .../src/handlers/invalid_cast.rs | 1007 +++++++++++++++++ .../src/handlers/missing_unsafe.rs | 19 +- .../src/handlers/moved_out_of_ref.rs | 12 + .../crates/ide-diagnostics/src/lib.rs | 3 + .../crates/ide/src/inlay_hints/adjustment.rs | 3 + .../ide/src/syntax_highlighting/tests.rs | 1 + 25 files changed, 1614 insertions(+), 93 deletions(-) create mode 100644 src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/invalid_cast.rs diff --git a/src/tools/rust-analyzer/crates/hir-def/src/data/adt.rs b/src/tools/rust-analyzer/crates/hir-def/src/data/adt.rs index a70710e565c27..ba54451e594f7 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/data/adt.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/data/adt.rs @@ -14,6 +14,7 @@ use triomphe::Arc; use crate::{ builtin_type::{BuiltinInt, BuiltinUint}, db::DefDatabase, + hir::Expr, item_tree::{ AttrOwner, Field, FieldParent, FieldsShape, ItemTree, ModItem, RawVisibilityId, TreeId, }, @@ -317,6 +318,27 @@ impl EnumData { _ => IntegerType::Pointer(true), } } + + // [Adopted from rustc](https://github.com/rust-lang/rust/blob/bd53aa3bf7a24a70d763182303bd75e5fc51a9af/compiler/rustc_middle/src/ty/adt.rs#L446-L448) + pub fn is_payload_free(&self, db: &dyn DefDatabase) -> bool { + self.variants.iter().all(|(v, _)| { + // The condition check order is slightly modified from rustc + // to improve performance by early returning with relatively fast checks + let variant = &db.enum_variant_data(*v).variant_data; + if !variant.fields().is_empty() { + return false; + } + // The outer if condition is whether this variant has const ctor or not + if !matches!(variant.kind(), StructKind::Unit) { + let body = db.body((*v).into()); + // A variant with explicit discriminant + if body.exprs[body.body_expr] != Expr::Missing { + return false; + } + } + true + }) + } } impl EnumVariantData { diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/consteval/tests.rs b/src/tools/rust-analyzer/crates/hir-ty/src/consteval/tests.rs index c4cbaaa30175b..203e21302cdda 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/consteval/tests.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/consteval/tests.rs @@ -186,7 +186,13 @@ fn floating_point() { #[test] fn casts() { - check_number(r#"const GOAL: usize = 12 as *const i32 as usize"#, 12); + check_number( + r#" + //- minicore: sized + const GOAL: usize = 12 as *const i32 as usize + "#, + 12, + ); check_number( r#" //- minicore: coerce_unsized, index, slice @@ -204,7 +210,7 @@ fn casts() { r#" //- minicore: coerce_unsized, index, slice const GOAL: i16 = { - let a = &mut 5; + let a = &mut 5_i16; let z = a as *mut _; unsafe { *z } }; @@ -244,7 +250,13 @@ fn casts() { "#, 4, ); - check_number(r#"const GOAL: i32 = -12i8 as i32"#, -12); + check_number( + r#" + //- minicore: sized + const GOAL: i32 = -12i8 as i32 + "#, + -12, + ); } #[test] @@ -1911,6 +1923,7 @@ fn function_pointer() { ); check_number( r#" + //- minicore: sized fn add2(x: u8) -> u8 { x + 2 } @@ -2422,6 +2435,7 @@ fn statics() { fn extern_weak_statics() { check_number( r#" + //- minicore: sized extern "C" { #[linkage = "extern_weak"] static __dso_handle: *mut u8; @@ -2716,6 +2730,7 @@ fn const_trait_assoc() { ); check_number( r#" + //- minicore: sized struct S(*mut T); trait MySized: Sized { diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/consteval/tests/intrinsics.rs b/src/tools/rust-analyzer/crates/hir-ty/src/consteval/tests/intrinsics.rs index 6f294494c01eb..c5706172b20c4 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/consteval/tests/intrinsics.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/consteval/tests/intrinsics.rs @@ -311,6 +311,7 @@ fn saturating() { fn allocator() { check_number( r#" + //- minicore: sized extern "Rust" { #[rustc_allocator] fn __rust_alloc(size: usize, align: usize) -> *mut u8; diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer.rs index 062ea278151bb..0e68ab4bfec5c 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/infer.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer.rs @@ -13,7 +13,7 @@ //! to certain types. To record this, we use the union-find implementation from //! the `ena` crate, which is extracted from rustc. -mod cast; +pub(crate) mod cast; pub(crate) mod closure; mod coerce; mod expr; @@ -76,7 +76,7 @@ pub use coerce::could_coerce; #[allow(unreachable_pub)] pub use unify::{could_unify, could_unify_deeply}; -use cast::CastCheck; +use cast::{CastCheck, CastError}; pub(crate) use closure::{CaptureKind, CapturedItem, CapturedItemWithoutTy}; /// The entry point of type inference. @@ -254,6 +254,16 @@ pub enum InferenceDiagnostic { expr: ExprId, expected: Ty, }, + CastToUnsized { + expr: ExprId, + cast_ty: Ty, + }, + InvalidCast { + expr: ExprId, + error: CastError, + expr_ty: Ty, + cast_ty: Ty, + }, } /// A mismatch between an expected and an inferred type. @@ -456,6 +466,7 @@ pub struct InferenceResult { pub(crate) closure_info: FxHashMap, FnTrait)>, // FIXME: remove this field pub mutated_bindings_in_closure: FxHashSet, + pub coercion_casts: FxHashSet, } impl InferenceResult { @@ -666,7 +677,7 @@ impl<'a> InferenceContext<'a> { let InferenceContext { mut table, mut result, - deferred_cast_checks, + mut deferred_cast_checks, tuple_field_accesses_rev, .. } = self; @@ -695,6 +706,7 @@ impl<'a> InferenceContext<'a> { closure_info: _, mutated_bindings_in_closure: _, tuple_field_access_types: _, + coercion_casts, } = &mut result; table.fallback_if_possible(); @@ -702,8 +714,18 @@ impl<'a> InferenceContext<'a> { // Comment from rustc: // Even though coercion casts provide type hints, we check casts after fallback for // backwards compatibility. This makes fallback a stronger type hint than a cast coercion. - for cast in deferred_cast_checks { - cast.check(&mut table); + let mut apply_adjustments = |expr, adj| { + expr_adjustments.insert(expr, adj); + }; + let mut set_coercion_cast = |expr| { + coercion_casts.insert(expr); + }; + for cast in deferred_cast_checks.iter_mut() { + if let Err(diag) = + cast.check(&mut table, &mut apply_adjustments, &mut set_coercion_cast) + { + diagnostics.push(diag); + } } // FIXME resolve obligations as well (use Guidance if necessary) diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer/cast.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer/cast.rs index 060b5f36f292d..ae914044368ca 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/infer/cast.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer/cast.rs @@ -1,47 +1,412 @@ //! Type cast logic. Basically coercion + additional casts. -use crate::{infer::unify::InferenceTable, Interner, Ty, TyExt, TyKind}; +use chalk_ir::{Mutability, Scalar, TyVariableKind, UintTy}; +use hir_def::{hir::ExprId, AdtId}; +use stdx::never; + +use crate::{ + infer::unify::InferenceTable, Adjustment, Binders, DynTy, InferenceDiagnostic, Interner, + PlaceholderIndex, QuantifiedWhereClauses, Ty, TyExt, TyKind, TypeFlags, WhereClause, +}; + +#[derive(Debug)] +pub(crate) enum Int { + I, + U(UintTy), + Bool, + Char, + CEnum, + InferenceVar, +} + +#[derive(Debug)] +pub(crate) enum CastTy { + Int(Int), + Float, + FnPtr, + Ptr(Ty, Mutability), + // `DynStar` is Not supported yet in r-a +} + +impl CastTy { + pub(crate) fn from_ty(table: &mut InferenceTable<'_>, t: &Ty) -> Option { + match t.kind(Interner) { + TyKind::Scalar(Scalar::Bool) => Some(Self::Int(Int::Bool)), + TyKind::Scalar(Scalar::Char) => Some(Self::Int(Int::Char)), + TyKind::Scalar(Scalar::Int(_)) => Some(Self::Int(Int::I)), + TyKind::Scalar(Scalar::Uint(it)) => Some(Self::Int(Int::U(*it))), + TyKind::InferenceVar(_, TyVariableKind::Integer) => Some(Self::Int(Int::InferenceVar)), + TyKind::InferenceVar(_, TyVariableKind::Float) => Some(Self::Float), + TyKind::Scalar(Scalar::Float(_)) => Some(Self::Float), + TyKind::Adt(..) => { + let (AdtId::EnumId(id), _) = t.as_adt()? else { + return None; + }; + let enum_data = table.db.enum_data(id); + if enum_data.is_payload_free(table.db.upcast()) { + Some(Self::Int(Int::CEnum)) + } else { + None + } + } + TyKind::Raw(m, ty) => Some(Self::Ptr(table.resolve_ty_shallow(ty), *m)), + TyKind::Function(_) => Some(Self::FnPtr), + _ => None, + } + } +} + +#[derive(Debug, PartialEq, Eq, Clone, Copy)] +pub enum CastError { + Unknown, + CastToBool, + CastToChar, + DifferingKinds, + SizedUnsizedCast, + IllegalCast, + IntToFatCast, + NeedDeref, + NeedViaPtr, + NeedViaThinPtr, + NeedViaInt, + NonScalar, + UnknownCastPtrKind, + UnknownExprPtrKind, +} + +impl CastError { + fn into_diagnostic(self, expr: ExprId, expr_ty: Ty, cast_ty: Ty) -> InferenceDiagnostic { + InferenceDiagnostic::InvalidCast { expr, error: self, expr_ty, cast_ty } + } +} #[derive(Clone, Debug)] pub(super) struct CastCheck { + expr: ExprId, + source_expr: ExprId, expr_ty: Ty, cast_ty: Ty, } impl CastCheck { - pub(super) fn new(expr_ty: Ty, cast_ty: Ty) -> Self { - Self { expr_ty, cast_ty } + pub(super) fn new(expr: ExprId, source_expr: ExprId, expr_ty: Ty, cast_ty: Ty) -> Self { + Self { expr, source_expr, expr_ty, cast_ty } + } + + pub(super) fn check( + &mut self, + table: &mut InferenceTable<'_>, + apply_adjustments: &mut F, + set_coercion_cast: &mut G, + ) -> Result<(), InferenceDiagnostic> + where + F: FnMut(ExprId, Vec), + G: FnMut(ExprId), + { + table.resolve_obligations_as_possible(); + self.expr_ty = table.resolve_ty_shallow(&self.expr_ty); + self.cast_ty = table.resolve_ty_shallow(&self.cast_ty); + + if self.expr_ty.contains_unknown() || self.cast_ty.contains_unknown() { + return Ok(()); + } + + if !self.cast_ty.data(Interner).flags.contains(TypeFlags::HAS_TY_INFER) + && !table.is_sized(&self.cast_ty) + { + return Err(InferenceDiagnostic::CastToUnsized { + expr: self.expr, + cast_ty: self.cast_ty.clone(), + }); + } + + if let Ok((adj, _)) = table.coerce(&self.expr_ty, &self.cast_ty) { + apply_adjustments(self.source_expr, adj); + set_coercion_cast(self.source_expr); + return Ok(()); + } + + self.do_check(table, apply_adjustments) + .map_err(|e| e.into_diagnostic(self.expr, self.expr_ty.clone(), self.cast_ty.clone())) + } + + fn do_check( + &self, + table: &mut InferenceTable<'_>, + apply_adjustments: &mut F, + ) -> Result<(), CastError> + where + F: FnMut(ExprId, Vec), + { + let (t_from, t_cast) = + match (CastTy::from_ty(table, &self.expr_ty), CastTy::from_ty(table, &self.cast_ty)) { + (Some(t_from), Some(t_cast)) => (t_from, t_cast), + (None, Some(t_cast)) => match self.expr_ty.kind(Interner) { + TyKind::FnDef(..) => { + let sig = self.expr_ty.callable_sig(table.db).expect("FnDef had no sig"); + let sig = table.normalize_associated_types_in(sig); + let fn_ptr = TyKind::Function(sig.to_fn_ptr()).intern(Interner); + if let Ok((adj, _)) = table.coerce(&self.expr_ty, &fn_ptr) { + apply_adjustments(self.source_expr, adj); + } else { + return Err(CastError::IllegalCast); + } + + (CastTy::FnPtr, t_cast) + } + TyKind::Ref(mutbl, _, inner_ty) => { + let inner_ty = table.resolve_ty_shallow(inner_ty); + return match t_cast { + CastTy::Int(_) | CastTy::Float => match inner_ty.kind(Interner) { + TyKind::Scalar( + Scalar::Int(_) | Scalar::Uint(_) | Scalar::Float(_), + ) + | TyKind::InferenceVar( + _, + TyVariableKind::Integer | TyVariableKind::Float, + ) => Err(CastError::NeedDeref), + + _ => Err(CastError::NeedViaPtr), + }, + // array-ptr-cast + CastTy::Ptr(t, m) => { + let t = table.resolve_ty_shallow(&t); + if !table.is_sized(&t) { + return Err(CastError::IllegalCast); + } + self.check_ref_cast( + table, + &inner_ty, + *mutbl, + &t, + m, + apply_adjustments, + ) + } + _ => Err(CastError::NonScalar), + }; + } + _ => return Err(CastError::NonScalar), + }, + _ => return Err(CastError::NonScalar), + }; + + // rustc checks whether the `expr_ty` is foreign adt with `non_exhaustive` sym + + match (t_from, t_cast) { + (_, CastTy::Int(Int::CEnum) | CastTy::FnPtr) => Err(CastError::NonScalar), + (_, CastTy::Int(Int::Bool)) => Err(CastError::CastToBool), + (CastTy::Int(Int::U(UintTy::U8)), CastTy::Int(Int::Char)) => Ok(()), + (_, CastTy::Int(Int::Char)) => Err(CastError::CastToChar), + (CastTy::Int(Int::Bool | Int::CEnum | Int::Char), CastTy::Float) => { + Err(CastError::NeedViaInt) + } + (CastTy::Int(Int::Bool | Int::CEnum | Int::Char) | CastTy::Float, CastTy::Ptr(..)) + | (CastTy::Ptr(..) | CastTy::FnPtr, CastTy::Float) => Err(CastError::IllegalCast), + (CastTy::Ptr(src, _), CastTy::Ptr(dst, _)) => { + self.check_ptr_ptr_cast(table, &src, &dst) + } + (CastTy::Ptr(src, _), CastTy::Int(_)) => self.check_ptr_addr_cast(table, &src), + (CastTy::Int(_), CastTy::Ptr(dst, _)) => self.check_addr_ptr_cast(table, &dst), + (CastTy::FnPtr, CastTy::Ptr(dst, _)) => self.check_fptr_ptr_cast(table, &dst), + (CastTy::Int(Int::CEnum), CastTy::Int(_)) => Ok(()), + (CastTy::Int(Int::Char | Int::Bool), CastTy::Int(_)) => Ok(()), + (CastTy::Int(_) | CastTy::Float, CastTy::Int(_) | CastTy::Float) => Ok(()), + (CastTy::FnPtr, CastTy::Int(_)) => Ok(()), + } } - pub(super) fn check(self, table: &mut InferenceTable<'_>) { - // FIXME: This function currently only implements the bits that influence the type - // inference. We should return the adjustments on success and report diagnostics on error. - let expr_ty = table.resolve_ty_shallow(&self.expr_ty); - let cast_ty = table.resolve_ty_shallow(&self.cast_ty); + fn check_ref_cast( + &self, + table: &mut InferenceTable<'_>, + t_expr: &Ty, + m_expr: Mutability, + t_cast: &Ty, + m_cast: Mutability, + apply_adjustments: &mut F, + ) -> Result<(), CastError> + where + F: FnMut(ExprId, Vec), + { + // Mutability order is opposite to rustc. `Mut < Not` + if m_expr <= m_cast { + if let TyKind::Array(ety, _) = t_expr.kind(Interner) { + // Coerce to a raw pointer so that we generate RawPtr in MIR. + let array_ptr_type = TyKind::Raw(m_expr, t_expr.clone()).intern(Interner); + if let Ok((adj, _)) = table.coerce(&self.expr_ty, &array_ptr_type) { + apply_adjustments(self.source_expr, adj); + } else { + never!( + "could not cast from reference to array to pointer to array ({:?} to {:?})", + self.expr_ty, + array_ptr_type + ); + } - if table.coerce(&expr_ty, &cast_ty).is_ok() { - return; + // This is a less strict condition than rustc's `demand_eqtype`, + // but false negative is better than false positive + if table.coerce(ety, t_cast).is_ok() { + return Ok(()); + } + } } - if check_ref_to_ptr_cast(expr_ty, cast_ty, table) { - // Note that this type of cast is actually split into a coercion to a - // pointer type and a cast: - // &[T; N] -> *[T; N] -> *T + Err(CastError::IllegalCast) + } + + fn check_ptr_ptr_cast( + &self, + table: &mut InferenceTable<'_>, + src: &Ty, + dst: &Ty, + ) -> Result<(), CastError> { + let src_kind = pointer_kind(src, table).map_err(|_| CastError::Unknown)?; + let dst_kind = pointer_kind(dst, table).map_err(|_| CastError::Unknown)?; + + match (src_kind, dst_kind) { + (Some(PointerKind::Error), _) | (_, Some(PointerKind::Error)) => Ok(()), + (_, None) => Err(CastError::UnknownCastPtrKind), + (_, Some(PointerKind::Thin)) => Ok(()), + (None, _) => Err(CastError::UnknownExprPtrKind), + (Some(PointerKind::Thin), _) => Err(CastError::SizedUnsizedCast), + (Some(PointerKind::VTable(src_tty)), Some(PointerKind::VTable(dst_tty))) => { + let principal = |tty: &Binders| { + tty.skip_binders().as_slice(Interner).first().and_then(|pred| { + if let WhereClause::Implemented(tr) = pred.skip_binders() { + Some(tr.trait_id) + } else { + None + } + }) + }; + match (principal(&src_tty), principal(&dst_tty)) { + (Some(src_principal), Some(dst_principal)) => { + if src_principal == dst_principal { + return Ok(()); + } + let src_principal = + table.db.trait_datum(table.trait_env.krate, src_principal); + let dst_principal = + table.db.trait_datum(table.trait_env.krate, dst_principal); + if src_principal.is_auto_trait() && dst_principal.is_auto_trait() { + Ok(()) + } else { + Err(CastError::DifferingKinds) + } + } + _ => Err(CastError::Unknown), + } + } + (Some(src_kind), Some(dst_kind)) if src_kind == dst_kind => Ok(()), + (_, _) => Err(CastError::DifferingKinds), + } + } + + fn check_ptr_addr_cast( + &self, + table: &mut InferenceTable<'_>, + expr_ty: &Ty, + ) -> Result<(), CastError> { + match pointer_kind(expr_ty, table).map_err(|_| CastError::Unknown)? { + None => Err(CastError::UnknownExprPtrKind), + Some(PointerKind::Error) => Ok(()), + Some(PointerKind::Thin) => Ok(()), + _ => Err(CastError::NeedViaThinPtr), + } + } + + fn check_addr_ptr_cast( + &self, + table: &mut InferenceTable<'_>, + cast_ty: &Ty, + ) -> Result<(), CastError> { + match pointer_kind(cast_ty, table).map_err(|_| CastError::Unknown)? { + None => Err(CastError::UnknownCastPtrKind), + Some(PointerKind::Error) => Ok(()), + Some(PointerKind::Thin) => Ok(()), + Some(PointerKind::VTable(_)) => Err(CastError::IntToFatCast), + Some(PointerKind::Length) => Err(CastError::IntToFatCast), + Some(PointerKind::OfAlias | PointerKind::OfParam(_)) => Err(CastError::IntToFatCast), } + } - // FIXME: Check other kinds of non-coercion casts and report error if any? + fn check_fptr_ptr_cast( + &self, + table: &mut InferenceTable<'_>, + cast_ty: &Ty, + ) -> Result<(), CastError> { + match pointer_kind(cast_ty, table).map_err(|_| CastError::Unknown)? { + None => Err(CastError::UnknownCastPtrKind), + Some(PointerKind::Error) => Ok(()), + Some(PointerKind::Thin) => Ok(()), + _ => Err(CastError::IllegalCast), + } } } -fn check_ref_to_ptr_cast(expr_ty: Ty, cast_ty: Ty, table: &mut InferenceTable<'_>) -> bool { - let Some((expr_inner_ty, _, _)) = expr_ty.as_reference() else { - return false; - }; - let Some((cast_inner_ty, _)) = cast_ty.as_raw_ptr() else { - return false; - }; - let TyKind::Array(expr_elt_ty, _) = expr_inner_ty.kind(Interner) else { - return false; - }; - table.coerce(expr_elt_ty, cast_inner_ty).is_ok() +#[derive(PartialEq, Eq)] +enum PointerKind { + // thin pointer + Thin, + // trait object + VTable(Binders), + // slice + Length, + OfAlias, + OfParam(PlaceholderIndex), + Error, +} + +fn pointer_kind(ty: &Ty, table: &mut InferenceTable<'_>) -> Result, ()> { + let ty = table.resolve_ty_shallow(ty); + + if table.is_sized(&ty) { + return Ok(Some(PointerKind::Thin)); + } + + match ty.kind(Interner) { + TyKind::Slice(_) | TyKind::Str => Ok(Some(PointerKind::Length)), + TyKind::Dyn(DynTy { bounds, .. }) => Ok(Some(PointerKind::VTable(bounds.clone()))), + TyKind::Adt(chalk_ir::AdtId(id), subst) => { + let AdtId::StructId(id) = *id else { + never!("`{:?}` should be sized but is not?", ty); + return Err(()); + }; + + let struct_data = table.db.struct_data(id); + if let Some((last_field, _)) = struct_data.variant_data.fields().iter().last() { + let last_field_ty = + table.db.field_types(id.into())[last_field].clone().substitute(Interner, subst); + pointer_kind(&last_field_ty, table) + } else { + Ok(Some(PointerKind::Thin)) + } + } + TyKind::Tuple(_, subst) => { + match subst.iter(Interner).last().and_then(|arg| arg.ty(Interner)) { + None => Ok(Some(PointerKind::Thin)), + Some(ty) => pointer_kind(ty, table), + } + } + TyKind::Foreign(_) => Ok(Some(PointerKind::Thin)), + TyKind::Alias(_) | TyKind::AssociatedType(..) | TyKind::OpaqueType(..) => { + Ok(Some(PointerKind::OfAlias)) + } + TyKind::Error => Ok(Some(PointerKind::Error)), + TyKind::Placeholder(idx) => Ok(Some(PointerKind::OfParam(*idx))), + TyKind::BoundVar(_) | TyKind::InferenceVar(..) => Ok(None), + TyKind::Scalar(_) + | TyKind::Array(..) + | TyKind::CoroutineWitness(..) + | TyKind::Raw(..) + | TyKind::Ref(..) + | TyKind::FnDef(..) + | TyKind::Function(_) + | TyKind::Closure(..) + | TyKind::Coroutine(..) + | TyKind::Never => { + never!("`{:?}` should be sized but is not?", ty); + Err(()) + } + } } diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer/expr.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer/expr.rs index 89d92ea9af0b9..b1c793a1e38f6 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/infer/expr.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer/expr.rs @@ -610,7 +610,12 @@ impl InferenceContext<'_> { Expr::Cast { expr, type_ref } => { let cast_ty = self.make_ty(type_ref); let expr_ty = self.infer_expr(*expr, &Expectation::Castable(cast_ty.clone())); - self.deferred_cast_checks.push(CastCheck::new(expr_ty, cast_ty.clone())); + self.deferred_cast_checks.push(CastCheck::new( + tgt_expr, + *expr, + expr_ty, + cast_ty.clone(), + )); cast_ty } Expr::Ref { expr, rawness, mutability } => { diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer/unify.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer/unify.rs index c0f5ddddcbe3e..99ad678980987 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/infer/unify.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer/unify.rs @@ -9,6 +9,7 @@ use chalk_ir::{ use chalk_solve::infer::ParameterEnaVariableExt; use either::Either; use ena::unify::UnifyKey; +use hir_def::{lang_item::LangItem, AdtId}; use hir_expand::name::Name; use intern::sym; use rustc_hash::FxHashMap; @@ -21,7 +22,7 @@ use crate::{ to_chalk_trait_id, traits::FnTrait, AliasEq, AliasTy, BoundVar, Canonical, Const, ConstValue, DebruijnIndex, DomainGoal, GenericArg, GenericArgData, Goal, GoalData, Guidance, InEnvironment, InferenceVar, Interner, Lifetime, OpaqueTyId, ParamKind, ProjectionTy, ProjectionTyExt, Scalar, - Solution, Substitution, TraitEnvironment, Ty, TyBuilder, TyExt, TyKind, VariableKind, + Solution, Substitution, TraitEnvironment, TraitRef, Ty, TyBuilder, TyExt, TyKind, VariableKind, WhereClause, }; @@ -898,6 +899,33 @@ impl<'a> InferenceTable<'a> { _ => c, } } + + /// Check if given type is `Sized` or not + pub(crate) fn is_sized(&mut self, ty: &Ty) -> bool { + if let Some((AdtId::StructId(id), subst)) = ty.as_adt() { + let struct_data = self.db.struct_data(id); + if let Some((last_field, _)) = struct_data.variant_data.fields().iter().last() { + let last_field_ty = + self.db.field_types(id.into())[last_field].clone().substitute(Interner, subst); + // Structs can have DST as its last field and such cases are not handled + // as unsized by the chalk, so we do this manually + return self.is_sized(&last_field_ty); + } + } + let Some(sized) = self + .db + .lang_item(self.trait_env.krate, LangItem::Sized) + .and_then(|sized| sized.as_trait()) + else { + return false; + }; + let sized_pred = WhereClause::Implemented(TraitRef { + trait_id: to_chalk_trait_id(sized), + substitution: Substitution::from1(Interner, ty.clone()), + }); + let goal = GoalData::DomainGoal(chalk_ir::DomainGoal::Holds(sized_pred)).intern(Interner); + matches!(self.try_obligation(goal), Some(Solution::Unique(_))) + } } impl fmt::Debug for InferenceTable<'_> { diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs b/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs index a316de2b48d25..79ee9e97871f7 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs @@ -83,6 +83,7 @@ pub use autoderef::autoderef; pub use builder::{ParamKind, TyBuilder}; pub use chalk_ext::*; pub use infer::{ + cast::CastError, closure::{CaptureKind, CapturedItem}, could_coerce, could_unify, could_unify_deeply, Adjust, Adjustment, AutoBorrow, BindingMode, InferenceDiagnostic, InferenceResult, OverloadedDeref, PointerCast, diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir.rs index 22d4da0e755ae..8cd6ae1232691 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/mir.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir.rs @@ -837,7 +837,9 @@ pub enum CastKind { PointerFromExposedAddress, /// All sorts of pointer-to-pointer casts. Note that reference-to-raw-ptr casts are /// translated into `&raw mut/const *r`, i.e., they are not actually casts. - Pointer(PointerCast), + PtrToPtr, + /// Pointer related casts that are done by coercions. + PointerCoercion(PointerCast), /// Cast into a dyn* object. DynStar, IntToInt, diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval.rs index 1bb0c1886857a..89b2ecb1a63e5 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval.rs @@ -1475,7 +1475,7 @@ impl Evaluator<'_> { } } Rvalue::Cast(kind, operand, target_ty) => match kind { - CastKind::Pointer(cast) => match cast { + CastKind::PointerCoercion(cast) => match cast { PointerCast::ReifyFnPointer | PointerCast::ClosureFnPointer(_) => { let current_ty = self.operand_ty(operand, locals)?; if let TyKind::FnDef(_, _) | TyKind::Closure(_, _) = @@ -1506,6 +1506,7 @@ impl Evaluator<'_> { }, CastKind::DynStar => not_supported!("dyn star cast"), CastKind::IntToInt + | CastKind::PtrToPtr | CastKind::PointerExposeAddress | CastKind::PointerFromExposedAddress => { let current_ty = self.operand_ty(operand, locals)?; diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/tests.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/tests.rs index 6825bc4862ac9..595a78da10fb9 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/tests.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/tests.rs @@ -399,7 +399,7 @@ extern "C" { fn memcmp(s1: *const u8, s2: *const u8, n: usize) -> i32; } -fn my_cmp(x: &[u8], y: &[u8]) -> i32 { +fn my_cmp(x: &[u8; 3], y: &[u8; 3]) -> i32 { memcmp(x as *const u8, y as *const u8, x.len()) } @@ -779,6 +779,7 @@ fn main() { fn posix_getenv() { check_pass( r#" +//- minicore: sized //- /main.rs env:foo=bar type c_char = u8; diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower.rs index 9e235504519e2..9cee494bbe743 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower.rs @@ -31,7 +31,7 @@ use crate::{ display::HirDisplay, error_lifetime, generics::generics, - infer::{CaptureKind, CapturedItem, TypeMismatch}, + infer::{cast::CastTy, unify::InferenceTable, CaptureKind, CapturedItem, TypeMismatch}, inhabitedness::is_ty_uninhabited_from, layout::LayoutError, mapping::ToChalk, @@ -362,7 +362,7 @@ impl<'ctx> MirLowerCtx<'ctx> { current, place, Rvalue::Cast( - CastKind::Pointer(*cast), + CastKind::PointerCoercion(*cast), Operand::Copy(p), last.target.clone(), ), @@ -898,14 +898,26 @@ impl<'ctx> MirLowerCtx<'ctx> { let Some((it, current)) = self.lower_expr_to_some_operand(*expr, current)? else { return Ok(None); }; - let source_ty = self.infer[*expr].clone(); - let target_ty = self.infer[expr_id].clone(); - self.push_assignment( - current, - place, - Rvalue::Cast(cast_kind(&source_ty, &target_ty)?, it, target_ty), - expr_id.into(), - ); + // Since we don't have THIR, this is the "zipped" version of [rustc's HIR lowering](https://github.com/rust-lang/rust/blob/e71f9529121ca8f687e4b725e3c9adc3f1ebab4d/compiler/rustc_mir_build/src/thir/cx/expr.rs#L165-L178) + // and [THIR lowering as RValue](https://github.com/rust-lang/rust/blob/a4601859ae3875732797873612d424976d9e3dd0/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs#L193-L313) + let rvalue = if self.infer.coercion_casts.contains(expr) { + Rvalue::Use(it) + } else { + let source_ty = self.infer[*expr].clone(); + let target_ty = self.infer[expr_id].clone(); + let cast_kind = if source_ty.as_reference().is_some() { + CastKind::PointerCoercion(PointerCast::ArrayToPointer) + } else { + let mut table = InferenceTable::new( + self.db, + self.db.trait_environment_for_body(self.owner), + ); + cast_kind(&mut table, &source_ty, &target_ty)? + }; + + Rvalue::Cast(cast_kind, it, target_ty) + }; + self.push_assignment(current, place, rvalue, expr_id.into()); Ok(Some(current)) } Expr::Ref { expr, rawness: _, mutability } => { @@ -2005,40 +2017,21 @@ impl<'ctx> MirLowerCtx<'ctx> { } } -fn cast_kind(source_ty: &Ty, target_ty: &Ty) -> Result { - Ok(match (source_ty.kind(Interner), target_ty.kind(Interner)) { - (TyKind::FnDef(..), TyKind::Function(_)) => CastKind::Pointer(PointerCast::ReifyFnPointer), - (TyKind::Scalar(s), TyKind::Scalar(t)) => match (s, t) { - (chalk_ir::Scalar::Float(_), chalk_ir::Scalar::Float(_)) => CastKind::FloatToFloat, - (chalk_ir::Scalar::Float(_), _) => CastKind::FloatToInt, - (_, chalk_ir::Scalar::Float(_)) => CastKind::IntToFloat, - (_, _) => CastKind::IntToInt, - }, - (TyKind::Scalar(_), TyKind::Raw(..)) => CastKind::PointerFromExposedAddress, - (TyKind::Raw(..), TyKind::Scalar(_)) => CastKind::PointerExposeAddress, - (TyKind::Raw(_, a) | TyKind::Ref(_, _, a), TyKind::Raw(_, b) | TyKind::Ref(_, _, b)) => { - CastKind::Pointer(if a == b { - PointerCast::MutToConstPointer - } else if matches!(b.kind(Interner), TyKind::Slice(_)) - && matches!(a.kind(Interner), TyKind::Array(_, _)) - || matches!(b.kind(Interner), TyKind::Dyn(_)) - { - PointerCast::Unsize - } else if matches!(a.kind(Interner), TyKind::Slice(s) if s == b) { - PointerCast::ArrayToPointer - } else { - // cast between two sized pointer, like *const i32 to *const i8, or two unsized pointer, like - // slice to slice, slice to str, ... . These are no-ops (even in the unsized case, no metadata - // will be touched) but there is no specific variant - // for it in `PointerCast` so we use `MutToConstPointer` - PointerCast::MutToConstPointer - }) - } - // Enum to int casts - (TyKind::Scalar(_), TyKind::Adt(..)) | (TyKind::Adt(..), TyKind::Scalar(_)) => { - CastKind::IntToInt +fn cast_kind(table: &mut InferenceTable<'_>, source_ty: &Ty, target_ty: &Ty) -> Result { + let from = CastTy::from_ty(table, source_ty); + let cast = CastTy::from_ty(table, target_ty); + Ok(match (from, cast) { + (Some(CastTy::Ptr(..) | CastTy::FnPtr), Some(CastTy::Int(_))) => { + CastKind::PointerExposeAddress } - (a, b) => not_supported!("Unknown cast between {a:?} and {b:?}"), + (Some(CastTy::Int(_)), Some(CastTy::Ptr(..))) => CastKind::PointerFromExposedAddress, + (Some(CastTy::Int(_)), Some(CastTy::Int(_))) => CastKind::IntToInt, + (Some(CastTy::FnPtr), Some(CastTy::Ptr(..))) => CastKind::FnPtrToPtr, + (Some(CastTy::Float), Some(CastTy::Int(_))) => CastKind::FloatToInt, + (Some(CastTy::Int(_)), Some(CastTy::Float)) => CastKind::IntToFloat, + (Some(CastTy::Float), Some(CastTy::Float)) => CastKind::FloatToFloat, + (Some(CastTy::Ptr(..)), Some(CastTy::Ptr(..))) => CastKind::PtrToPtr, + _ => not_supported!("Unknown cast between {source_ty:?} and {target_ty:?}"), }) } diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/tests/method_resolution.rs b/src/tools/rust-analyzer/crates/hir-ty/src/tests/method_resolution.rs index 610fc9b6b4562..74acf23b75ab6 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/tests/method_resolution.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/tests/method_resolution.rs @@ -1286,6 +1286,7 @@ fn main() { fn method_on_dyn_impl() { check_types( r#" +//- minicore: coerce_unsized trait Foo {} impl Foo for u32 {} diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/tests/regression.rs b/src/tools/rust-analyzer/crates/hir-ty/src/tests/regression.rs index 98f30f0f6f749..4df10025f80fb 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/tests/regression.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/tests/regression.rs @@ -1907,6 +1907,7 @@ fn dont_unify_on_casts() { // #15246 check_types( r#" +//- minicore: sized fn unify(_: [bool; 1]) {} fn casted(_: *const bool) {} fn default() -> T { loop {} } @@ -1926,6 +1927,7 @@ fn test() { fn rustc_test_issue_52437() { check_types( r#" + //- minicore: sized fn main() { let x = [(); &(&'static: loop { |x| {}; }) as *const _ as usize] //^ [(); _] diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/tests/simple.rs b/src/tools/rust-analyzer/crates/hir-ty/src/tests/simple.rs index 1c6fa62e30ceb..37280f81b8696 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/tests/simple.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/tests/simple.rs @@ -3572,6 +3572,7 @@ fn f(t: Ark) { fn ref_to_array_to_ptr_cast() { check_types( r#" +//- minicore: sized fn default() -> T { loop {} } fn foo() { let arr = [default()]; diff --git a/src/tools/rust-analyzer/crates/hir/src/diagnostics.rs b/src/tools/rust-analyzer/crates/hir/src/diagnostics.rs index ffb972475f8f7..4d90df63b9b9f 100644 --- a/src/tools/rust-analyzer/crates/hir/src/diagnostics.rs +++ b/src/tools/rust-analyzer/crates/hir/src/diagnostics.rs @@ -4,7 +4,9 @@ //! This probably isn't the best way to do this -- ideally, diagnostics should //! be expressed in terms of hir types themselves. pub use hir_ty::diagnostics::{CaseType, IncorrectCase}; -use hir_ty::{db::HirDatabase, diagnostics::BodyValidationDiagnostic, InferenceDiagnostic}; +use hir_ty::{ + db::HirDatabase, diagnostics::BodyValidationDiagnostic, CastError, InferenceDiagnostic, +}; use cfg::{CfgExpr, CfgOptions}; use either::Either; @@ -50,10 +52,12 @@ macro_rules! diagnostics { diagnostics![ AwaitOutsideOfAsync, BreakOutsideOfLoop, + CastToUnsized, ExpectedFunction, InactiveCode, IncoherentImpl, IncorrectCase, + InvalidCast, InvalidDeriveTarget, MacroDefError, MacroError, @@ -364,6 +368,20 @@ pub struct RemoveUnnecessaryElse { pub if_expr: InFile>, } +#[derive(Debug)] +pub struct CastToUnsized { + pub expr: InFile>, + pub cast_ty: Type, +} + +#[derive(Debug)] +pub struct InvalidCast { + pub expr: InFile>, + pub error: CastError, + pub expr_ty: Type, + pub cast_ty: Type, +} + impl AnyDiagnostic { pub(crate) fn body_validation_diagnostic( db: &dyn HirDatabase, @@ -620,6 +638,16 @@ impl AnyDiagnostic { }; MismatchedTupleStructPatArgCount { expr_or_pat, expected, found }.into() } + InferenceDiagnostic::CastToUnsized { expr, cast_ty } => { + let expr = expr_syntax(*expr)?; + CastToUnsized { expr, cast_ty: Type::new(db, def, cast_ty.clone()) }.into() + } + InferenceDiagnostic::InvalidCast { expr, error, expr_ty, cast_ty } => { + let expr = expr_syntax(*expr)?; + let expr_ty = Type::new(db, def, expr_ty.clone()); + let cast_ty = Type::new(db, def, cast_ty.clone()); + InvalidCast { expr, error: *error, expr_ty, cast_ty }.into() + } }) } } diff --git a/src/tools/rust-analyzer/crates/hir/src/lib.rs b/src/tools/rust-analyzer/crates/hir/src/lib.rs index 6328a3c3d0d9e..81d6466c2f31d 100644 --- a/src/tools/rust-analyzer/crates/hir/src/lib.rs +++ b/src/tools/rust-analyzer/crates/hir/src/lib.rs @@ -147,7 +147,7 @@ pub use { layout::LayoutError, mir::{MirEvalError, MirLowerError}, object_safety::{MethodViolationCode, ObjectSafetyViolation}, - FnAbi, PointerCast, Safety, + CastError, FnAbi, PointerCast, Safety, }, // FIXME: Properly encapsulate mir hir_ty::{mir, Interner as ChalkTyInterner}, diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/inline_call.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/inline_call.rs index 5bd204dd573b9..906e9a9891a72 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/inline_call.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/inline_call.rs @@ -1020,6 +1020,7 @@ fn main() { check_assist( inline_call, r#" +//- minicore: sized fn foo(x: *const u32) -> u32 { x as u32 } diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/inline_local_variable.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/inline_local_variable.rs index 6a1f7f26c92cc..b9fc075ae8382 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/inline_local_variable.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/inline_local_variable.rs @@ -333,7 +333,8 @@ fn foo() { check_assist( inline_local_variable, r" -fn bar(a: usize): usize { a } +//- minicore: sized +fn bar(a: usize) -> usize { a } fn foo() { let a$0 = bar(1) as u64; a + 1; @@ -347,7 +348,7 @@ fn foo() { bar(a); }", r" -fn bar(a: usize): usize { a } +fn bar(a: usize) -> usize { a } fn foo() { (bar(1) as u64) + 1; if (bar(1) as u64) > 10 { diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/invalid_cast.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/invalid_cast.rs new file mode 100644 index 0000000000000..2f6f033f25c7e --- /dev/null +++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/invalid_cast.rs @@ -0,0 +1,1007 @@ +use hir::{CastError, ClosureStyle, HirDisplay}; + +use crate::{Diagnostic, DiagnosticCode, DiagnosticsContext}; + +macro_rules! format_ty { + ($ctx:expr, $fmt:literal, $($arg:expr),* $(,)?) => {{ + std::format!( + $fmt, + $( + $arg + .display($ctx.sema.db, $ctx.edition) + .with_closure_style(ClosureStyle::ClosureWithId) + ),* + ) + }} +} + +// Diagnostic: invalid-cast +// +// This diagnostic is triggered if the code contains an illegal cast +pub(crate) fn invalid_cast(ctx: &DiagnosticsContext<'_>, d: &hir::InvalidCast) -> Diagnostic { + let display_range = ctx.sema.diagnostics_display_range(d.expr.map(|it| it.into())); + let (code, message) = match d.error { + CastError::CastToBool => ( + DiagnosticCode::RustcHardError("E0054"), + format_ty!(ctx, "cannot cast `{}` as `bool`", d.expr_ty), + ), + CastError::CastToChar => ( + DiagnosticCode::RustcHardError("E0604"), + format_ty!(ctx, "only `u8` can be cast as `char`, not {}", d.expr_ty), + ), + CastError::DifferingKinds => ( + DiagnosticCode::RustcHardError("E0606"), + format_ty!( + ctx, + "casting `{}` as `{}` is invalid: vtable kinds may not match", + d.expr_ty, + d.cast_ty + ), + ), + CastError::SizedUnsizedCast => ( + DiagnosticCode::RustcHardError("E0607"), + format_ty!( + ctx, + "cannot cast thin pointer `{}` to fat pointer `{}`", + d.expr_ty, + d.cast_ty + ), + ), + CastError::Unknown | CastError::IllegalCast => ( + DiagnosticCode::RustcHardError("E0606"), + format_ty!(ctx, "casting `{}` as `{}` is invalid", d.expr_ty, d.cast_ty), + ), + CastError::IntToFatCast => ( + DiagnosticCode::RustcHardError("E0606"), + format_ty!(ctx, "cannot cast `{}` to a fat pointer `{}`", d.expr_ty, d.cast_ty), + ), + CastError::NeedDeref => ( + DiagnosticCode::RustcHardError("E0606"), + format_ty!( + ctx, + "casting `{}` as `{}` is invalid: needs defererence or removal of unneeded borrow", + d.expr_ty, + d.cast_ty + ), + ), + CastError::NeedViaPtr => ( + DiagnosticCode::RustcHardError("E0606"), + format_ty!( + ctx, + "casting `{}` as `{}` is invalid: needs casting through a raw pointer first", + d.expr_ty, + d.cast_ty + ), + ), + CastError::NeedViaThinPtr => ( + DiagnosticCode::RustcHardError("E0606"), + format_ty!( + ctx, + "casting `{}` as `{}` is invalid: needs casting through a thin pointer first", + d.expr_ty, + d.cast_ty + ), + ), + CastError::NeedViaInt => ( + DiagnosticCode::RustcHardError("E0606"), + format_ty!( + ctx, + "casting `{}` as `{}` is invalid: needs casting through an integer first", + d.expr_ty, + d.cast_ty + ), + ), + CastError::NonScalar => ( + DiagnosticCode::RustcHardError("E0605"), + format_ty!(ctx, "non-primitive cast: `{}` as `{}`", d.expr_ty, d.cast_ty), + ), + CastError::UnknownCastPtrKind | CastError::UnknownExprPtrKind => ( + DiagnosticCode::RustcHardError("E0641"), + "cannot cast to a pointer of an unknown kind".to_owned(), + ), + }; + Diagnostic::new(code, message, display_range) +} + +// Diagnostic: cast-to-unsized +// +// This diagnostic is triggered when casting to an unsized type +pub(crate) fn cast_to_unsized(ctx: &DiagnosticsContext<'_>, d: &hir::CastToUnsized) -> Diagnostic { + let display_range = ctx.sema.diagnostics_display_range(d.expr.map(|it| it.into())); + Diagnostic::new( + DiagnosticCode::RustcHardError("E0620"), + format_ty!(ctx, "cast to unsized type: `{}`", d.cast_ty), + display_range, + ) +} + +#[cfg(test)] +mod tests { + use crate::tests::{check_diagnostics, check_diagnostics_with_disabled}; + + #[test] + fn cast_as_bool() { + check_diagnostics( + r#" +//- minicore: sized +fn main() { + let u = 5 as bool; + //^^^^^^^^^ error: cannot cast `i32` as `bool` + + let t = (1 + 2) as bool; + //^^^^^^^^^^^^^^^ error: cannot cast `i32` as `bool` + + let _ = 5_u32 as bool; + //^^^^^^^^^^^^^ error: cannot cast `u32` as `bool` + + let _ = 64.0_f64 as bool; + //^^^^^^^^^^^^^^^^ error: cannot cast `f64` as `bool` + + enum IntEnum { + Zero, + One, + Two + } + let _ = IntEnum::One as bool; + //^^^^^^^^^^^^^^^^^^^^ error: cannot cast `IntEnum` as `bool` + + fn uwu(_: u8) -> i32 { + 5 + } + + unsafe fn owo() {} + + let _ = uwu as bool; + //^^^^^^^^^^^ error: cannot cast `fn uwu(u8) -> i32` as `bool` + let _ = owo as bool; + //^^^^^^^^^^^ error: cannot cast `unsafe fn owo()` as `bool` + + let _ = uwu as fn(u8) -> i32 as bool; + //^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: cannot cast `fn(u8) -> i32` as `bool` + let _ = 'x' as bool; + //^^^^^^^^^^^ error: cannot cast `char` as `bool` + + let ptr = 1 as *const (); + + let _ = ptr as bool; + //^^^^^^^^^^^ error: cannot cast `*const ()` as `bool` + let v = "hello" as bool; + //^^^^^^^^^^^^^^^ error: casting `&str` as `bool` is invalid: needs casting through a raw pointer first +} +"#, + ); + } + + #[test] + fn cast_pointee_projection() { + check_diagnostics( + r#" +//- minicore: sized +trait Tag<'a> { + type Type: ?Sized; +} + +trait IntoRaw: for<'a> Tag<'a> { + fn into_raw(this: *const >::Type) -> *mut >::Type; +} + +impl Tag<'a>> IntoRaw for T { + fn into_raw(this: *const >::Type) -> *mut >::Type { + this as *mut T::Type + } +} + +fn main() {} +"#, + ); + } + + #[test] + fn cast_region_to_int() { + check_diagnostics( + r#" +//- minicore: sized +fn main() { + let x: isize = 3; + let _ = &x as *const isize as usize; +} +"#, + ); + } + + #[test] + fn cast_to_bare_fn() { + check_diagnostics( + r#" +//- minicore: sized +fn foo(_x: isize) { } + +fn main() { + let v: u64 = 5; + let x = foo as extern "C" fn() -> isize; + //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: non-primitive cast: `fn foo(isize)` as `fn() -> isize` + let y = v as extern "Rust" fn(isize) -> (isize, isize); + //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: non-primitive cast: `u64` as `fn(isize) -> (isize, isize)` + y(x()); +} +"#, + ); + } + + #[test] + fn cast_to_unit() { + check_diagnostics( + r#" +//- minicore: sized +fn main() { + let _ = 0u32 as (); + //^^^^^^^^^^ error: non-primitive cast: `u32` as `()` +} +"#, + ); + } + + #[test] + fn cast_to_slice() { + check_diagnostics_with_disabled( + r#" +//- minicore: sized +fn as_bytes(_: &str) -> &[u8] { + loop {} +} + +fn main() { + as_bytes("example") as [char]; + //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: cast to unsized type: `[char]` + + let arr: &[u8] = &[0, 2, 3]; + arr as [char]; + //^^^^^^^^^^^^^ error: cast to unsized type: `[char]` +} +"#, + &["E0308"], + ); + } + + #[test] + fn cast() { + check_diagnostics( + r#" +//- minicore: sized +fn null_mut() -> *mut T { + loop {} +} + +pub fn main() { + let i: isize = 'Q' as isize; + let _u: u32 = i as u32; + + // Test that `_` is correctly inferred. + let x = &"hello"; + let mut y = x as *const _; + y = null_mut(); +} +"#, + ); + } + + #[test] + fn dyn_tail_need_normalization() { + check_diagnostics( + r#" +//- minicore: dispatch_from_dyn +trait Trait { + type Associated; +} + +impl Trait for i32 { + type Associated = i64; +} + +trait Generic {} + +type TraitObject = dyn Generic<::Associated>; + +struct Wrap(TraitObject); + +fn cast(x: *mut TraitObject) { + x as *mut Wrap; +} +"#, + ); + } + + #[test] + fn enum_to_numeric_cast() { + check_diagnostics( + r#" +//- minicore: sized +pub enum UnitOnly { + Foo, + Bar, + Baz, +} + +pub enum Fieldless { + Tuple(), + Struct{}, + Unit, +} + +pub enum NotUnitOnlyOrFieldless { + Foo, + Bar(u8), + Baz +} + +fn main() { + let unit_only = UnitOnly::Foo; + + let _ = unit_only as isize; + let _ = unit_only as i32; + let _ = unit_only as usize; + let _ = unit_only as u32; + + + let fieldless = Fieldless::Struct{}; + + let _ = fieldless as isize; + let _ = fieldless as i32; + let _ = fieldless as usize; + let _ = fieldless as u32; + + + let not_unit_only_or_fieldless = NotUnitOnlyOrFieldless::Foo; + + let _ = not_unit_only_or_fieldless as isize; + //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: non-primitive cast: `NotUnitOnlyOrFieldless` as `isize` + let _ = not_unit_only_or_fieldless as i32; + //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: non-primitive cast: `NotUnitOnlyOrFieldless` as `i32` + let _ = not_unit_only_or_fieldless as usize; + //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: non-primitive cast: `NotUnitOnlyOrFieldless` as `usize` + let _ = not_unit_only_or_fieldless as u32; + //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: non-primitive cast: `NotUnitOnlyOrFieldless` as `u32` +} +"#, + ); + } + + #[test] + fn fat_ptr_cast() { + check_diagnostics_with_disabled( + r#" +//- minicore: sized +trait Foo { + fn foo(&self) {} //~ WARN method `foo` is never used +} + +struct Bar; + +impl Foo for Bar {} + +fn to_raw(_: *mut T) -> *mut () { + loop {} +} + +fn main() { + // Test we can turn a fat pointer to array back into a thin pointer. + let a: *const [i32] = &[1, 2, 3]; + let b = a as *const [i32; 2]; + + // Test conversion to an address (usize). + let a: *const [i32; 3] = &[1, 2, 3]; + let b: *const [i32] = a; + + // And conversion to a void pointer/address for trait objects too. + let a: *mut dyn Foo = &mut Bar; + let b = a as *mut () as usize; + let c = a as *const () as usize; + let d = to_raw(a) as usize; +} +"#, + &["E0308"], + ); + + check_diagnostics_with_disabled( + r#" +//- minicore: sized +trait Trait {} + +struct Box; + +impl Box { + fn new(_: T) -> Self { + loop {} + } +} + +fn as_ptr(_: &[i32]) -> *const i32 { + loop {} +} + +fn main() { + let a: &[i32] = &[1, 2, 3]; + let b: Box<[i32]> = Box::new([1, 2, 3]); + let p = a as *const [i32]; + let q = as_ptr(a); + + a as usize; + //^^^^^^^^^^ error: casting `&[i32]` as `usize` is invalid: needs casting through a raw pointer first + a as isize; + //^^^^^^^^^^ error: casting `&[i32]` as `isize` is invalid: needs casting through a raw pointer first + a as i16; + //^^^^^^^^ error: casting `&[i32]` as `i16` is invalid: needs casting through a raw pointer first + a as u32; + //^^^^^^^^ error: casting `&[i32]` as `u32` is invalid: needs casting through a raw pointer first + b as usize; + //^^^^^^^^^^ error: non-primitive cast: `Box<[i32]>` as `usize` + p as usize; + //^^^^^^^^^^ error: casting `*const [i32]` as `usize` is invalid: needs casting through a thin pointer first + q as *const [i32]; + //^^^^^^^^^^^^^^^^^ error: cannot cast thin pointer `*const i32` to fat pointer `*const [i32]` + + let t: *mut (dyn Trait + 'static) = 0 as *mut _; + //^^^^^^^^^^^ error: cannot cast `i32` to a fat pointer `*mut _` + let mut fail: *const str = 0 as *const str; + //^^^^^^^^^^^^^^^ error: cannot cast `i32` to a fat pointer `*const str` + let mut fail2: *const str = 0isize as *const str; + //^^^^^^^^^^^^^^^^^^^^ error: cannot cast `isize` to a fat pointer `*const str` +} + +fn foo() { + let s = 0 as *const T; + //^^^^^^^^^^^^^ error: cannot cast `i32` to a fat pointer `*const T` +} +"#, + &["E0308", "unused_variables"], + ); + } + + #[test] + fn order_dependent_cast_inference() { + check_diagnostics( + r#" +//- minicore: sized +fn main() { + let x = &"hello"; + let mut y = 0 as *const _; + //^^^^^^^^^^^^^ error: cannot cast to a pointer of an unknown kind + y = x as *const _; +} +"#, + ); + } + + #[test] + fn ptr_to_ptr_different_regions() { + check_diagnostics( + r#" +//- minicore: sized +struct Foo<'a> { a: &'a () } + +fn extend_lifetime_very_very_safely<'a>(v: *const Foo<'a>) -> *const Foo<'static> { + // This should pass because raw pointer casts can do anything they want. + v as *const Foo<'static> +} + +trait Trait {} + +fn assert_static<'a>(ptr: *mut (dyn Trait + 'a)) -> *mut (dyn Trait + 'static) { + ptr as _ +} + +fn main() { + let unit = (); + let foo = Foo { a: &unit }; + let _long: *const Foo<'static> = extend_lifetime_very_very_safely(&foo); +} +"#, + ); + } + + #[test] + fn ptr_to_trait_obj_add_auto() { + check_diagnostics( + r#" +//- minicore: pointee +trait Trait<'a> {} + +fn add_auto<'a>(x: *mut dyn Trait<'a>) -> *mut (dyn Trait<'a> + Send) { + x as _ +} + +// (to test diagnostic list formatting) +fn add_multiple_auto<'a>(x: *mut dyn Trait<'a>) -> *mut (dyn Trait<'a> + Send + Sync + Unpin) { + x as _ +} +"#, + ); + } + + #[test] + fn ptr_to_trait_obj_add_super_auto() { + check_diagnostics( + r#" +//- minicore: pointee +trait Trait: Send {} +impl Trait for () {} + +fn main() { + // This is OK: `Trait` has `Send` super trait. + &() as *const dyn Trait as *const (dyn Trait + Send); +} +"#, + ); + } + + #[test] + fn ptr_to_trait_obj_ok() { + check_diagnostics( + r#" +//- minicore: pointee +trait Trait<'a> {} + +fn remove_auto<'a>(x: *mut (dyn Trait<'a> + Send)) -> *mut dyn Trait<'a> { + x as _ +} + +fn cast_inherent_lt<'a, 'b>(x: *mut (dyn Trait<'static> + 'a)) -> *mut (dyn Trait<'static> + 'b) { + x as _ +} + +fn unprincipled<'a, 'b>(x: *mut (dyn Send + 'a)) -> *mut (dyn Sync + 'b) { + x as _ +} +"#, + ); + } + + #[test] + fn ptr_to_trait_obj_wrap_upcast() { + check_diagnostics( + r#" +//- minicore: sized +trait Super {} +trait Sub: Super {} + +struct Wrapper(T); + +// This cast should not compile. +// Upcasting can't work here, because we are also changing the type (`Wrapper`), +// and reinterpreting would be confusing/surprising. +// See +fn cast(ptr: *const dyn Sub) -> *const Wrapper { + ptr as _ + //^^^^^^^^ error: casting `*const dyn Sub` as `*const Wrapper` is invalid: vtable kinds may not match +} +"#, + ); + } + + #[test] + fn supported_cast() { + check_diagnostics( + r#" +//- minicore: sized +pub fn main() { + struct String; + + let f = 1_usize as *const String; + + let _ = f as isize; + let _ = f as usize; + let _ = f as i8; + let _ = f as i16; + let _ = f as i32; + let _ = f as i64; + let _ = f as u8; + let _ = f as u16; + let _ = f as u32; + let _ = f as u64; + + let _ = 1 as isize; + let _ = 1 as usize; + let _ = 1 as *const String; + let _ = 1 as i8; + let _ = 1 as i16; + let _ = 1 as i32; + let _ = 1 as i64; + let _ = 1 as u8; + let _ = 1 as u16; + let _ = 1 as u32; + let _ = 1 as u64; + let _ = 1 as f32; + let _ = 1 as f64; + + let _ = 1_usize as isize; + let _ = 1_usize as usize; + let _ = 1_usize as *const String; + let _ = 1_usize as i8; + let _ = 1_usize as i16; + let _ = 1_usize as i32; + let _ = 1_usize as i64; + let _ = 1_usize as u8; + let _ = 1_usize as u16; + let _ = 1_usize as u32; + let _ = 1_usize as u64; + let _ = 1_usize as f32; + let _ = 1_usize as f64; + + let _ = 1i8 as isize; + let _ = 1i8 as usize; + let _ = 1i8 as *const String; + let _ = 1i8 as i8; + let _ = 1i8 as i16; + let _ = 1i8 as i32; + let _ = 1i8 as i64; + let _ = 1i8 as u8; + let _ = 1i8 as u16; + let _ = 1i8 as u32; + let _ = 1i8 as u64; + let _ = 1i8 as f32; + let _ = 1i8 as f64; + + let _ = 1u8 as isize; + let _ = 1u8 as usize; + let _ = 1u8 as *const String; + let _ = 1u8 as i8; + let _ = 1u8 as i16; + let _ = 1u8 as i32; + let _ = 1u8 as i64; + let _ = 1u8 as u8; + let _ = 1u8 as u16; + let _ = 1u8 as u32; + let _ = 1u8 as u64; + let _ = 1u8 as f32; + let _ = 1u8 as f64; + + let _ = 1i16 as isize; + let _ = 1i16 as usize; + let _ = 1i16 as *const String; + let _ = 1i16 as i8; + let _ = 1i16 as i16; + let _ = 1i16 as i32; + let _ = 1i16 as i64; + let _ = 1i16 as u8; + let _ = 1i16 as u16; + let _ = 1i16 as u32; + let _ = 1i16 as u64; + let _ = 1i16 as f32; + let _ = 1i16 as f64; + + let _ = 1u16 as isize; + let _ = 1u16 as usize; + let _ = 1u16 as *const String; + let _ = 1u16 as i8; + let _ = 1u16 as i16; + let _ = 1u16 as i32; + let _ = 1u16 as i64; + let _ = 1u16 as u8; + let _ = 1u16 as u16; + let _ = 1u16 as u32; + let _ = 1u16 as u64; + let _ = 1u16 as f32; + let _ = 1u16 as f64; + + let _ = 1i32 as isize; + let _ = 1i32 as usize; + let _ = 1i32 as *const String; + let _ = 1i32 as i8; + let _ = 1i32 as i16; + let _ = 1i32 as i32; + let _ = 1i32 as i64; + let _ = 1i32 as u8; + let _ = 1i32 as u16; + let _ = 1i32 as u32; + let _ = 1i32 as u64; + let _ = 1i32 as f32; + let _ = 1i32 as f64; + + let _ = 1u32 as isize; + let _ = 1u32 as usize; + let _ = 1u32 as *const String; + let _ = 1u32 as i8; + let _ = 1u32 as i16; + let _ = 1u32 as i32; + let _ = 1u32 as i64; + let _ = 1u32 as u8; + let _ = 1u32 as u16; + let _ = 1u32 as u32; + let _ = 1u32 as u64; + let _ = 1u32 as f32; + let _ = 1u32 as f64; + + let _ = 1i64 as isize; + let _ = 1i64 as usize; + let _ = 1i64 as *const String; + let _ = 1i64 as i8; + let _ = 1i64 as i16; + let _ = 1i64 as i32; + let _ = 1i64 as i64; + let _ = 1i64 as u8; + let _ = 1i64 as u16; + let _ = 1i64 as u32; + let _ = 1i64 as u64; + let _ = 1i64 as f32; + let _ = 1i64 as f64; + + let _ = 1u64 as isize; + let _ = 1u64 as usize; + let _ = 1u64 as *const String; + let _ = 1u64 as i8; + let _ = 1u64 as i16; + let _ = 1u64 as i32; + let _ = 1u64 as i64; + let _ = 1u64 as u8; + let _ = 1u64 as u16; + let _ = 1u64 as u32; + let _ = 1u64 as u64; + let _ = 1u64 as f32; + let _ = 1u64 as f64; + + let _ = 1u64 as isize; + let _ = 1u64 as usize; + let _ = 1u64 as *const String; + let _ = 1u64 as i8; + let _ = 1u64 as i16; + let _ = 1u64 as i32; + let _ = 1u64 as i64; + let _ = 1u64 as u8; + let _ = 1u64 as u16; + let _ = 1u64 as u32; + let _ = 1u64 as u64; + let _ = 1u64 as f32; + let _ = 1u64 as f64; + + let _ = true as isize; + let _ = true as usize; + let _ = true as i8; + let _ = true as i16; + let _ = true as i32; + let _ = true as i64; + let _ = true as u8; + let _ = true as u16; + let _ = true as u32; + let _ = true as u64; + + let _ = 1f32 as isize; + let _ = 1f32 as usize; + let _ = 1f32 as i8; + let _ = 1f32 as i16; + let _ = 1f32 as i32; + let _ = 1f32 as i64; + let _ = 1f32 as u8; + let _ = 1f32 as u16; + let _ = 1f32 as u32; + let _ = 1f32 as u64; + let _ = 1f32 as f32; + let _ = 1f32 as f64; + + let _ = 1f64 as isize; + let _ = 1f64 as usize; + let _ = 1f64 as i8; + let _ = 1f64 as i16; + let _ = 1f64 as i32; + let _ = 1f64 as i64; + let _ = 1f64 as u8; + let _ = 1f64 as u16; + let _ = 1f64 as u32; + let _ = 1f64 as u64; + let _ = 1f64 as f32; + let _ = 1f64 as f64; +} +"#, + ); + } + + #[test] + fn unsized_struct_cast() { + check_diagnostics( + r#" +//- minicore: sized +pub struct Data([u8]); + +fn foo(x: &[u8]) { + let _: *const Data = x as *const Data; + //^^^^^^^^^^^^^^^^ error: casting `&[u8]` as `*const Data` is invalid +} +"#, + ); + } + + #[test] + fn unsupported_cast() { + check_diagnostics( + r#" +//- minicore: sized +struct A; + +fn main() { + let _ = 1.0 as *const A; + //^^^^^^^^^^^^^^^ error: casting `f64` as `*const A` is invalid +} +"#, + ); + } + + #[test] + fn issue_17897() { + check_diagnostics( + r#" +//- minicore: sized +fn main() { + _ = ((), ()) as (); + //^^^^^^^^^^^^^^ error: non-primitive cast: `(_, _)` as `()` +} +"#, + ); + } + + #[test] + fn rustc_issue_10991() { + check_diagnostics( + r#" +//- minicore: sized +fn main() { + let nil = (); + let _t = nil as usize; + //^^^^^^^^^^^^ error: non-primitive cast: `()` as `usize` +} +"#, + ); + } + + #[test] + fn rustc_issue_17444() { + check_diagnostics( + r#" +//- minicore: sized +enum Test { + Foo = 0 +} + +fn main() { + let _x = Test::Foo as *const isize; + //^^^^^^^^^^^^^^^^^^^^^^^^^ error: casting `Test` as `*const isize` is invalid +} +"#, + ); + } + + #[test] + fn rustc_issue_43825() { + check_diagnostics( + r#" +//- minicore: sized +fn main() { + let error = error; + //^^^^^ error: no such value in this scope + + 0 as f32; + 0.0 as u32; +} +"#, + ); + } + + #[test] + fn rustc_issue_84213() { + check_diagnostics( + r#" +//- minicore: sized +struct Something { + pub field: u32, +} + +fn main() { + let mut something = Something { field: 1337 }; + let _ = something.field; + + let _pointer_to_something = something as *const Something; + //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: non-primitive cast: `Something` as `*const Something` + + let _mut_pointer_to_something = something as *mut Something; + //^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: non-primitive cast: `Something` as `*mut Something` +} +"#, + ); + + // Fixed + check_diagnostics( + r#" +//- minicore: sized +struct Something { + pub field: u32, +} + +fn main() { + let mut something = Something { field: 1337 }; + let _ = something.field; + + let _pointer_to_something = &something as *const Something; + + let _mut_pointer_to_something = &mut something as *mut Something; +} +"#, + ); + } + + #[test] + fn rustc_issue_88621() { + check_diagnostics( + r#" +//- minicore: sized +#[repr(u8)] +enum Kind2 { + Foo() = 1, + Bar{} = 2, + Baz = 3, +} + +fn main() { + let _ = Kind2::Foo() as u8; + //^^^^^^^^^^^^^^^^^^ error: non-primitive cast: `Kind2` as `u8` +} +"#, + ); + } + + #[test] + fn rustc_issue_89497() { + check_diagnostics( + r#" +//- minicore: sized +fn main() { + let pointer: usize = &1_i32 as *const i32 as usize; + let _reference: &'static i32 = unsafe { pointer as *const i32 as &'static i32 }; + //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: non-primitive cast: `*const i32` as `&i32` +} +"#, + ); + + // Fixed + check_diagnostics( + r#" +//- minicore: sized +fn main() { + let pointer: usize = &1_i32 as *const i32 as usize; + let _reference: &'static i32 = unsafe { &*(pointer as *const i32) }; +} +"#, + ); + } + + #[test] + fn rustc_issue_106883() { + check_diagnostics_with_disabled( + r#" +//- minicore: sized, deref +use core::ops::Deref; + +struct Foo; + +impl Deref for Foo { + type Target = [u8]; + + fn deref(&self) -> &Self::Target { + &[] + } +} + +fn main() { + let _ = "foo" as bool; + //^^^^^^^^^^^^^ error: casting `&str` as `bool` is invalid: needs casting through a raw pointer first + + let _ = Foo as bool; + //^^^^^^^^^^^ error: non-primitive cast: `Foo` as `bool` +} + +fn _slice(bar: &[i32]) -> bool { + bar as bool + //^^^^^^^^^^^ error: casting `&[i32]` as `bool` is invalid: needs casting through a raw pointer first +} +"#, + &["E0308"], + ); + } +} diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/missing_unsafe.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/missing_unsafe.rs index 7e70a27f789bc..9a9bab091d289 100644 --- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/missing_unsafe.rs +++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/missing_unsafe.rs @@ -99,8 +99,9 @@ mod tests { fn missing_unsafe_diagnostic_with_raw_ptr() { check_diagnostics( r#" +//- minicore: sized fn main() { - let x = &5 as *const usize; + let x = &5_usize as *const usize; unsafe { let _y = *x; } let _z = *x; } //^^💡 error: this operation is unsafe and requires an unsafe function or block @@ -112,17 +113,18 @@ fn main() { fn missing_unsafe_diagnostic_with_unsafe_call() { check_diagnostics( r#" +//- minicore: sized struct HasUnsafe; impl HasUnsafe { unsafe fn unsafe_fn(&self) { - let x = &5 as *const usize; + let x = &5_usize as *const usize; let _y = *x; } } unsafe fn unsafe_fn() { - let x = &5 as *const usize; + let x = &5_usize as *const usize; let _y = *x; } @@ -250,14 +252,15 @@ fn main() { fn add_unsafe_block_when_dereferencing_a_raw_pointer() { check_fix( r#" +//- minicore: sized fn main() { - let x = &5 as *const usize; + let x = &5_usize as *const usize; let _z = *x$0; } "#, r#" fn main() { - let x = &5 as *const usize; + let x = &5_usize as *const usize; let _z = unsafe { *x }; } "#, @@ -268,8 +271,9 @@ fn main() { fn add_unsafe_block_when_calling_unsafe_function() { check_fix( r#" +//- minicore: sized unsafe fn func() { - let x = &5 as *const usize; + let x = &5_usize as *const usize; let z = *x; } fn main() { @@ -278,7 +282,7 @@ fn main() { "#, r#" unsafe fn func() { - let x = &5 as *const usize; + let x = &5_usize as *const usize; let z = *x; } fn main() { @@ -292,6 +296,7 @@ fn main() { fn add_unsafe_block_when_calling_unsafe_method() { check_fix( r#" +//- minicore: sized struct S(usize); impl S { unsafe fn func(&self) { diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/moved_out_of_ref.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/moved_out_of_ref.rs index 06c6b0f3e4c38..a9ff06fb0ab1e 100644 --- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/moved_out_of_ref.rs +++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/moved_out_of_ref.rs @@ -190,4 +190,16 @@ fn foo(mut slice: &[u32]) -> usize { "#, ); } + + #[test] + fn regression_16564() { + check_diagnostics( + r#" +//- minicore: copy +fn test() { + let _x = (&(&mut (),)).0 as *const (); +} + "#, + ) + } } diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/lib.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/lib.rs index 9b50a435e4c3a..4749718f1b17c 100644 --- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/lib.rs +++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/lib.rs @@ -30,6 +30,7 @@ mod handlers { pub(crate) mod inactive_code; pub(crate) mod incoherent_impl; pub(crate) mod incorrect_case; + pub(crate) mod invalid_cast; pub(crate) mod invalid_derive_target; pub(crate) mod macro_error; pub(crate) mod malformed_derive; @@ -390,6 +391,7 @@ pub fn semantic_diagnostics( for diag in diags { let d = match diag { AnyDiagnostic::AwaitOutsideOfAsync(d) => handlers::await_outside_of_async::await_outside_of_async(&ctx, &d), + AnyDiagnostic::CastToUnsized(d) => handlers::invalid_cast::cast_to_unsized(&ctx, &d), AnyDiagnostic::ExpectedFunction(d) => handlers::expected_function::expected_function(&ctx, &d), AnyDiagnostic::InactiveCode(d) => match handlers::inactive_code::inactive_code(&ctx, &d) { Some(it) => it, @@ -397,6 +399,7 @@ pub fn semantic_diagnostics( } AnyDiagnostic::IncoherentImpl(d) => handlers::incoherent_impl::incoherent_impl(&ctx, &d), AnyDiagnostic::IncorrectCase(d) => handlers::incorrect_case::incorrect_case(&ctx, &d), + AnyDiagnostic::InvalidCast(d) => handlers::invalid_cast::invalid_cast(&ctx, &d), AnyDiagnostic::InvalidDeriveTarget(d) => handlers::invalid_derive_target::invalid_derive_target(&ctx, &d), AnyDiagnostic::MacroDefError(d) => handlers::macro_error::macro_def_error(&ctx, &d), AnyDiagnostic::MacroError(d) => handlers::macro_error::macro_error(&ctx, &d), diff --git a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/adjustment.rs b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/adjustment.rs index dc390f8f67af8..c37c469dff4e1 100644 --- a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/adjustment.rs +++ b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/adjustment.rs @@ -313,6 +313,7 @@ fn main() { //^^^^^^^^^^^^ //^^^^^^^^^^^^( //^^^^^^^^^^^^) + //^^^^ let _: fn() = || {}; //^^^^^ let _: unsafe fn() = || {}; @@ -321,6 +322,8 @@ fn main() { //^^^^^^^^^^^^^^^^^^^^^ //^^^^^^^^^^^^^^^^^^^^^( //^^^^^^^^^^^^^^^^^^^^^) + //^^^^^^^^^&raw mut $ + //^^^^^^^^^* let _: &mut [_] = &mut [0; 0]; //^^^^^^^^^^^ //^^^^^^^^^^^&mut $ diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/tests.rs b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/tests.rs index 2070022d4183c..ad7fbb00e5c66 100644 --- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/tests.rs +++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/tests.rs @@ -554,6 +554,7 @@ fn main() { fn test_unsafe_highlighting() { check_highlighting( r#" +//- minicore: sized macro_rules! id { ($($tt:tt)*) => { $($tt)* From 6f6a6bc710e538741aa06d40df6492471e4be8af Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Sat, 10 Aug 2024 19:06:26 +0200 Subject: [PATCH 0392/2194] Non-exhaustive structs may be empty --- .../rustc_middle/src/ty/inhabitedness/mod.rs | 4 -- compiler/rustc_pattern_analysis/src/rustc.rs | 8 +-- .../uninhabited/auxiliary/uninhabited.rs | 10 ++- .../uninhabited/indirect_match.stderr | 8 +-- ...rect_match_with_exhaustive_patterns.stderr | 8 +-- .../issue-65157-repeated-match-arm.rs | 9 +-- .../issue-65157-repeated-match-arm.stderr | 19 ++++-- .../uninhabited/match.rs | 21 +++--- .../uninhabited/match.stderr | 66 ++++--------------- .../match_with_exhaustive_patterns.rs | 26 ++++---- .../match_with_exhaustive_patterns.stderr | 65 +----------------- ...tch_with_exhaustive_patterns_same_crate.rs | 21 +++--- .../uninhabited/patterns.rs | 23 +++---- .../uninhabited/patterns.stderr | 39 +++++++++++ .../uninhabited/patterns_same_crate.rs | 5 +- .../uninhabited/patterns_same_crate.stderr | 10 +-- 16 files changed, 135 insertions(+), 207 deletions(-) create mode 100644 tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/patterns.stderr diff --git a/compiler/rustc_middle/src/ty/inhabitedness/mod.rs b/compiler/rustc_middle/src/ty/inhabitedness/mod.rs index 698104b0462e3..dd00db8635f4d 100644 --- a/compiler/rustc_middle/src/ty/inhabitedness/mod.rs +++ b/compiler/rustc_middle/src/ty/inhabitedness/mod.rs @@ -81,10 +81,6 @@ impl<'tcx> VariantDef { adt: ty::AdtDef<'_>, ) -> InhabitedPredicate<'tcx> { debug_assert!(!adt.is_union()); - if self.is_field_list_non_exhaustive() && !self.def_id.is_local() { - // Non-exhaustive variants from other crates are always considered inhabited. - return InhabitedPredicate::True; - } InhabitedPredicate::all( tcx, self.fields.iter().map(|field| { diff --git a/compiler/rustc_pattern_analysis/src/rustc.rs b/compiler/rustc_pattern_analysis/src/rustc.rs index d7885e05a2ffc..6c09f97bfe731 100644 --- a/compiler/rustc_pattern_analysis/src/rustc.rs +++ b/compiler/rustc_pattern_analysis/src/rustc.rs @@ -229,17 +229,11 @@ impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> { } else { let variant = &adt.variant(RustcPatCtxt::variant_index_for_adt(&ctor, *adt)); - - // In the cases of either a `#[non_exhaustive]` field list or a non-public - // field, we skip uninhabited fields in order not to reveal the - // uninhabitedness of the whole variant. - let is_non_exhaustive = - variant.is_field_list_non_exhaustive() && !adt.did().is_local(); let tys = cx.variant_sub_tys(ty, variant).map(|(field, ty)| { let is_visible = adt.is_enum() || field.vis.is_accessible_from(cx.module, cx.tcx); let is_uninhabited = cx.is_uninhabited(*ty); - let skip = is_uninhabited && (!is_visible || is_non_exhaustive); + let skip = is_uninhabited && !is_visible; (ty, PrivateUninhabitedField(skip)) }); cx.dropless_arena.alloc_from_iter(tys) diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/auxiliary/uninhabited.rs b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/auxiliary/uninhabited.rs index a2735d4cbfb29..e1799761b6961 100644 --- a/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/auxiliary/uninhabited.rs +++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/auxiliary/uninhabited.rs @@ -7,11 +7,17 @@ pub enum UninhabitedEnum { #[non_exhaustive] pub struct UninhabitedStruct { - _priv: !, + pub never: !, + _priv: (), } #[non_exhaustive] -pub struct UninhabitedTupleStruct(!); +pub struct PrivatelyUninhabitedStruct { + never: !, +} + +#[non_exhaustive] +pub struct UninhabitedTupleStruct(pub !); pub enum UninhabitedVariants { #[non_exhaustive] Tuple(!), diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/indirect_match.stderr b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/indirect_match.stderr index 66e93291c72a0..f332e6deeb82c 100644 --- a/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/indirect_match.stderr +++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/indirect_match.stderr @@ -5,7 +5,7 @@ LL | match x {} | ^ | note: `IndirectUninhabitedEnum` defined here - --> $DIR/auxiliary/uninhabited.rs:26:1 + --> $DIR/auxiliary/uninhabited.rs:32:1 | LL | pub struct IndirectUninhabitedEnum(UninhabitedEnum); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -24,7 +24,7 @@ LL | match x {} | ^ | note: `IndirectUninhabitedStruct` defined here - --> $DIR/auxiliary/uninhabited.rs:28:1 + --> $DIR/auxiliary/uninhabited.rs:34:1 | LL | pub struct IndirectUninhabitedStruct(UninhabitedStruct); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -43,7 +43,7 @@ LL | match x {} | ^ | note: `IndirectUninhabitedTupleStruct` defined here - --> $DIR/auxiliary/uninhabited.rs:30:1 + --> $DIR/auxiliary/uninhabited.rs:36:1 | LL | pub struct IndirectUninhabitedTupleStruct(UninhabitedTupleStruct); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -62,7 +62,7 @@ LL | match x {} | ^ | note: `IndirectUninhabitedVariants` defined here - --> $DIR/auxiliary/uninhabited.rs:32:1 + --> $DIR/auxiliary/uninhabited.rs:38:1 | LL | pub struct IndirectUninhabitedVariants(UninhabitedVariants); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/indirect_match_with_exhaustive_patterns.stderr b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/indirect_match_with_exhaustive_patterns.stderr index 745b196a0e3ad..48f3857bfa7f8 100644 --- a/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/indirect_match_with_exhaustive_patterns.stderr +++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/indirect_match_with_exhaustive_patterns.stderr @@ -5,7 +5,7 @@ LL | match x {} | ^ | note: `IndirectUninhabitedEnum` defined here - --> $DIR/auxiliary/uninhabited.rs:26:1 + --> $DIR/auxiliary/uninhabited.rs:32:1 | LL | pub struct IndirectUninhabitedEnum(UninhabitedEnum); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -24,7 +24,7 @@ LL | match x {} | ^ | note: `IndirectUninhabitedStruct` defined here - --> $DIR/auxiliary/uninhabited.rs:28:1 + --> $DIR/auxiliary/uninhabited.rs:34:1 | LL | pub struct IndirectUninhabitedStruct(UninhabitedStruct); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -43,7 +43,7 @@ LL | match x {} | ^ | note: `IndirectUninhabitedTupleStruct` defined here - --> $DIR/auxiliary/uninhabited.rs:30:1 + --> $DIR/auxiliary/uninhabited.rs:36:1 | LL | pub struct IndirectUninhabitedTupleStruct(UninhabitedTupleStruct); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -62,7 +62,7 @@ LL | match x {} | ^ | note: `IndirectUninhabitedVariants` defined here - --> $DIR/auxiliary/uninhabited.rs:32:1 + --> $DIR/auxiliary/uninhabited.rs:38:1 | LL | pub struct IndirectUninhabitedVariants(UninhabitedVariants); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/issue-65157-repeated-match-arm.rs b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/issue-65157-repeated-match-arm.rs index fd77fab8738d3..6bee019e89782 100644 --- a/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/issue-65157-repeated-match-arm.rs +++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/issue-65157-repeated-match-arm.rs @@ -11,11 +11,12 @@ use uninhabited::PartiallyInhabitedVariants; pub fn foo(x: PartiallyInhabitedVariants) { match x { - PartiallyInhabitedVariants::Struct { .. } => {}, - PartiallyInhabitedVariants::Struct { .. } => {}, + PartiallyInhabitedVariants::Struct { .. } => {} //~^ ERROR unreachable pattern - _ => {}, + PartiallyInhabitedVariants::Struct { .. } => {} + //~^ ERROR unreachable pattern + _ => {} } } -fn main() { } +fn main() {} diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/issue-65157-repeated-match-arm.stderr b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/issue-65157-repeated-match-arm.stderr index 956725fc10eb9..4fa53101a55f1 100644 --- a/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/issue-65157-repeated-match-arm.stderr +++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/issue-65157-repeated-match-arm.stderr @@ -1,16 +1,23 @@ error: unreachable pattern - --> $DIR/issue-65157-repeated-match-arm.rs:15:9 + --> $DIR/issue-65157-repeated-match-arm.rs:14:9 | -LL | PartiallyInhabitedVariants::Struct { .. } => {}, - | ----------------------------------------- matches all the relevant values -LL | PartiallyInhabitedVariants::Struct { .. } => {}, - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ no value can reach this +LL | PartiallyInhabitedVariants::Struct { .. } => {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ matches no values because `PartiallyInhabitedVariants` is uninhabited | + = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types note: the lint level is defined here --> $DIR/issue-65157-repeated-match-arm.rs:2:9 | LL | #![deny(unreachable_patterns)] | ^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 1 previous error +error: unreachable pattern + --> $DIR/issue-65157-repeated-match-arm.rs:16:9 + | +LL | PartiallyInhabitedVariants::Struct { .. } => {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ matches no values because `PartiallyInhabitedVariants` is uninhabited + | + = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types + +error: aborting due to 2 previous errors diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/match.rs b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/match.rs index c330f3aa05c4b..58d7bbd2c1730 100644 --- a/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/match.rs +++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/match.rs @@ -3,12 +3,7 @@ extern crate uninhabited; -use uninhabited::{ - UninhabitedEnum, - UninhabitedStruct, - UninhabitedTupleStruct, - UninhabitedVariants, -}; +use uninhabited::*; struct A; @@ -19,16 +14,20 @@ fn cannot_empty_match_on_empty_enum_to_anything(x: UninhabitedEnum) -> A { match x {} //~ ERROR non-exhaustive patterns } -fn cannot_empty_match_on_empty_struct_to_anything(x: UninhabitedStruct) -> A { - match x {} //~ ERROR non-exhaustive patterns +fn empty_match_on_empty_struct(x: UninhabitedStruct) -> A { + match x {} } -fn cannot_empty_match_on_empty_tuple_struct_to_anything(x: UninhabitedTupleStruct) -> A { +fn cannot_empty_match_on_privately_empty_struct(x: PrivatelyUninhabitedStruct) -> A { match x {} //~ ERROR non-exhaustive patterns } -fn cannot_empty_match_on_enum_with_empty_variants_struct_to_anything(x: UninhabitedVariants) -> A { - match x {} //~ ERROR non-exhaustive patterns +fn empty_match_on_empty_tuple_struct(x: UninhabitedTupleStruct) -> A { + match x {} +} + +fn empty_match_on_enum_with_empty_variants_struct(x: UninhabitedVariants) -> A { + match x {} } fn main() {} diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/match.stderr b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/match.stderr index c125756a646d5..0232e7106aab7 100644 --- a/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/match.stderr +++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/match.stderr @@ -1,15 +1,15 @@ -error[E0004]: non-exhaustive patterns: type `UninhabitedEnum` is non-empty - --> $DIR/match.rs:19:11 +error[E0004]: non-exhaustive patterns: type `uninhabited::UninhabitedEnum` is non-empty + --> $DIR/match.rs:14:11 | LL | match x {} | ^ | -note: `UninhabitedEnum` defined here +note: `uninhabited::UninhabitedEnum` defined here --> $DIR/auxiliary/uninhabited.rs:5:1 | LL | pub enum UninhabitedEnum { | ^^^^^^^^^^^^^^^^^^^^^^^^ - = note: the matched value is of type `UninhabitedEnum`, which is marked as non-exhaustive + = note: the matched value is of type `uninhabited::UninhabitedEnum`, which is marked as non-exhaustive help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown | LL ~ match x { @@ -17,18 +17,18 @@ LL + _ => todo!(), LL ~ } | -error[E0004]: non-exhaustive patterns: type `UninhabitedStruct` is non-empty - --> $DIR/match.rs:23:11 +error[E0004]: non-exhaustive patterns: type `uninhabited::PrivatelyUninhabitedStruct` is non-empty + --> $DIR/match.rs:22:11 | LL | match x {} | ^ | -note: `UninhabitedStruct` defined here - --> $DIR/auxiliary/uninhabited.rs:9:1 +note: `uninhabited::PrivatelyUninhabitedStruct` defined here + --> $DIR/auxiliary/uninhabited.rs:15:1 | -LL | pub struct UninhabitedStruct { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - = note: the matched value is of type `UninhabitedStruct` +LL | pub struct PrivatelyUninhabitedStruct { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: the matched value is of type `uninhabited::PrivatelyUninhabitedStruct` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown | LL ~ match x { @@ -36,48 +36,6 @@ LL + _ => todo!(), LL ~ } | -error[E0004]: non-exhaustive patterns: type `UninhabitedTupleStruct` is non-empty - --> $DIR/match.rs:27:11 - | -LL | match x {} - | ^ - | -note: `UninhabitedTupleStruct` defined here - --> $DIR/auxiliary/uninhabited.rs:14:1 - | -LL | pub struct UninhabitedTupleStruct(!); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - = note: the matched value is of type `UninhabitedTupleStruct` -help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown - | -LL ~ match x { -LL + _ => todo!(), -LL ~ } - | - -error[E0004]: non-exhaustive patterns: `UninhabitedVariants::Tuple(_)` and `UninhabitedVariants::Struct { .. }` not covered - --> $DIR/match.rs:31:11 - | -LL | match x {} - | ^ patterns `UninhabitedVariants::Tuple(_)` and `UninhabitedVariants::Struct { .. }` not covered - | -note: `UninhabitedVariants` defined here - --> $DIR/auxiliary/uninhabited.rs:16:1 - | -LL | pub enum UninhabitedVariants { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -LL | #[non_exhaustive] Tuple(!), - | ----- not covered -LL | #[non_exhaustive] Struct { x: ! } - | ------ not covered - = note: the matched value is of type `UninhabitedVariants` -help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms - | -LL ~ match x { -LL + UninhabitedVariants::Tuple(_) | UninhabitedVariants::Struct { .. } => todo!(), -LL ~ } - | - -error: aborting due to 4 previous errors +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0004`. diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/match_with_exhaustive_patterns.rs b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/match_with_exhaustive_patterns.rs index 108cac7099ebf..c214581549cd7 100644 --- a/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/match_with_exhaustive_patterns.rs +++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/match_with_exhaustive_patterns.rs @@ -5,32 +5,28 @@ extern crate uninhabited; use uninhabited::{ - UninhabitedEnum, - UninhabitedStruct, - UninhabitedTupleStruct, - UninhabitedVariants, + UninhabitedEnum, UninhabitedStruct, UninhabitedTupleStruct, UninhabitedVariants, }; struct A; -// This test checks that an empty match on a non-exhaustive uninhabited type from an extern crate -// will not compile. In particular, this enables the `exhaustive_patterns` feature as this can -// change the branch used in the compiler to determine this. - -fn cannot_empty_match_on_empty_enum_to_anything(x: UninhabitedEnum) -> A { +// This test checks that non-exhaustive enums are never considered uninhabited outside their +// defining crate, and non-exhaustive structs are considered uninhabited the same way as normal +// ones. +fn cannot_empty_match_on_non_exhaustive_empty_enum(x: UninhabitedEnum) -> A { match x {} //~ ERROR non-exhaustive patterns } -fn cannot_empty_match_on_empty_struct_to_anything(x: UninhabitedStruct) -> A { - match x {} //~ ERROR non-exhaustive patterns +fn empty_match_on_empty_struct(x: UninhabitedStruct) -> A { + match x {} } -fn cannot_empty_match_on_empty_tuple_struct_to_anything(x: UninhabitedTupleStruct) -> A { - match x {} //~ ERROR non-exhaustive patterns +fn empty_match_on_empty_tuple_struct(x: UninhabitedTupleStruct) -> A { + match x {} } -fn cannot_empty_match_on_enum_with_empty_variants_struct_to_anything(x: UninhabitedVariants) -> A { - match x {} //~ ERROR non-exhaustive patterns +fn empty_match_on_enum_with_empty_variants_struct(x: UninhabitedVariants) -> A { + match x {} } fn main() {} diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/match_with_exhaustive_patterns.stderr b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/match_with_exhaustive_patterns.stderr index 0c8b14ab69df0..d6f0bc724a98d 100644 --- a/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/match_with_exhaustive_patterns.stderr +++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/match_with_exhaustive_patterns.stderr @@ -1,5 +1,5 @@ error[E0004]: non-exhaustive patterns: type `UninhabitedEnum` is non-empty - --> $DIR/match_with_exhaustive_patterns.rs:21:11 + --> $DIR/match_with_exhaustive_patterns.rs:17:11 | LL | match x {} | ^ @@ -17,67 +17,6 @@ LL + _ => todo!(), LL ~ } | -error[E0004]: non-exhaustive patterns: type `UninhabitedStruct` is non-empty - --> $DIR/match_with_exhaustive_patterns.rs:25:11 - | -LL | match x {} - | ^ - | -note: `UninhabitedStruct` defined here - --> $DIR/auxiliary/uninhabited.rs:9:1 - | -LL | pub struct UninhabitedStruct { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - = note: the matched value is of type `UninhabitedStruct` -help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown - | -LL ~ match x { -LL + _ => todo!(), -LL ~ } - | - -error[E0004]: non-exhaustive patterns: type `UninhabitedTupleStruct` is non-empty - --> $DIR/match_with_exhaustive_patterns.rs:29:11 - | -LL | match x {} - | ^ - | -note: `UninhabitedTupleStruct` defined here - --> $DIR/auxiliary/uninhabited.rs:14:1 - | -LL | pub struct UninhabitedTupleStruct(!); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - = note: the matched value is of type `UninhabitedTupleStruct` -help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown - | -LL ~ match x { -LL + _ => todo!(), -LL ~ } - | - -error[E0004]: non-exhaustive patterns: `UninhabitedVariants::Tuple(_)` and `UninhabitedVariants::Struct { .. }` not covered - --> $DIR/match_with_exhaustive_patterns.rs:33:11 - | -LL | match x {} - | ^ patterns `UninhabitedVariants::Tuple(_)` and `UninhabitedVariants::Struct { .. }` not covered - | -note: `UninhabitedVariants` defined here - --> $DIR/auxiliary/uninhabited.rs:16:1 - | -LL | pub enum UninhabitedVariants { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -LL | #[non_exhaustive] Tuple(!), - | ----- not covered -LL | #[non_exhaustive] Struct { x: ! } - | ------ not covered - = note: the matched value is of type `UninhabitedVariants` -help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms - | -LL ~ match x { -LL + UninhabitedVariants::Tuple(_) | UninhabitedVariants::Struct { .. } => todo!(), -LL ~ } - | - -error: aborting due to 4 previous errors +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0004`. diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/match_with_exhaustive_patterns_same_crate.rs b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/match_with_exhaustive_patterns_same_crate.rs index 468703c78e068..9662016221278 100644 --- a/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/match_with_exhaustive_patterns_same_crate.rs +++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/match_with_exhaustive_patterns_same_crate.rs @@ -1,5 +1,4 @@ //@ check-pass - #![deny(unreachable_patterns)] #![feature(never_type)] @@ -9,11 +8,12 @@ pub enum UninhabitedEnum { #[non_exhaustive] pub struct UninhabitedStruct { - _priv: !, + pub never: !, + _priv: (), } #[non_exhaustive] -pub struct UninhabitedTupleStruct(!); +pub struct UninhabitedTupleStruct(pub !); pub enum UninhabitedVariants { #[non_exhaustive] Tuple(!), @@ -22,24 +22,21 @@ pub enum UninhabitedVariants { struct A; -// This test checks that an empty match on a non-exhaustive uninhabited type from the defining crate -// will compile. In particular, this enables the `exhaustive_patterns` feature as this can -// change the branch used in the compiler to determine this. -// Codegen is skipped because tests with long names can cause issues on Windows CI, see #60648. - -fn cannot_empty_match_on_empty_enum_to_anything(x: UninhabitedEnum) -> A { +// This checks that `non_exhaustive` annotations do not affect exhaustiveness checking within the +// defining crate. +fn empty_match_on_empty_enum(x: UninhabitedEnum) -> A { match x {} } -fn cannot_empty_match_on_empty_struct_to_anything(x: UninhabitedStruct) -> A { +fn empty_match_on_empty_struct(x: UninhabitedStruct) -> A { match x {} } -fn cannot_empty_match_on_empty_tuple_struct_to_anything(x: UninhabitedTupleStruct) -> A { +fn empty_match_on_empty_tuple_struct(x: UninhabitedTupleStruct) -> A { match x {} } -fn cannot_empty_match_on_enum_with_empty_variants_struct_to_anything(x: UninhabitedVariants) -> A { +fn empty_match_on_enum_with_empty_variants_struct(x: UninhabitedVariants) -> A { match x {} } diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/patterns.rs b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/patterns.rs index be55ad51578be..edc588777eb98 100644 --- a/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/patterns.rs +++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/patterns.rs @@ -1,14 +1,10 @@ //@ aux-build:uninhabited.rs -//@ build-pass (FIXME(62277): could be check-pass?) #![deny(unreachable_patterns)] extern crate uninhabited; use uninhabited::{ - PartiallyInhabitedVariants, - UninhabitedEnum, - UninhabitedStruct, - UninhabitedTupleStruct, + PartiallyInhabitedVariants, UninhabitedEnum, UninhabitedStruct, UninhabitedTupleStruct, UninhabitedVariants, }; @@ -32,27 +28,26 @@ fn uninhabited_tuple_struct() -> Option { None } -// This test checks that non-exhaustive types that would normally be considered uninhabited within -// the defining crate are not considered uninhabited from extern crates. - +// This test checks that non-exhaustive enums are never considered uninhabited outside their +// defining crate, and non-exhaustive structs are considered uninhabited the same way as normal +// ones. fn main() { match uninhabited_enum() { - Some(_x) => (), // This line would normally error. + Some(_x) => (), // This would error without `non_exhaustive` None => (), } match uninhabited_variant() { - Some(_x) => (), // This line would normally error. + Some(_x) => (), //~ ERROR unreachable None => (), } // This line would normally error. - while let PartiallyInhabitedVariants::Struct { x, .. } = partially_inhabited_variant() { - } + while let PartiallyInhabitedVariants::Struct { x, .. } = partially_inhabited_variant() {} //~ ERROR unreachable - while let Some(_x) = uninhabited_struct() { // This line would normally error. + while let Some(_x) = uninhabited_struct() { //~ ERROR unreachable } - while let Some(_x) = uninhabited_tuple_struct() { // This line would normally error. + while let Some(_x) = uninhabited_tuple_struct() { //~ ERROR unreachable } } diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/patterns.stderr b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/patterns.stderr new file mode 100644 index 0000000000000..deaa2ffd92720 --- /dev/null +++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/patterns.stderr @@ -0,0 +1,39 @@ +error: unreachable pattern + --> $DIR/patterns.rs:41:9 + | +LL | Some(_x) => (), + | ^^^^^^^^ matches no values because `UninhabitedVariants` is uninhabited + | + = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types +note: the lint level is defined here + --> $DIR/patterns.rs:2:9 + | +LL | #![deny(unreachable_patterns)] + | ^^^^^^^^^^^^^^^^^^^^ + +error: unreachable pattern + --> $DIR/patterns.rs:46:15 + | +LL | while let PartiallyInhabitedVariants::Struct { x, .. } = partially_inhabited_variant() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ matches no values because `!` is uninhabited + | + = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types + +error: unreachable pattern + --> $DIR/patterns.rs:48:15 + | +LL | while let Some(_x) = uninhabited_struct() { + | ^^^^^^^^ matches no values because `UninhabitedStruct` is uninhabited + | + = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types + +error: unreachable pattern + --> $DIR/patterns.rs:51:15 + | +LL | while let Some(_x) = uninhabited_tuple_struct() { + | ^^^^^^^^ matches no values because `UninhabitedTupleStruct` is uninhabited + | + = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types + +error: aborting due to 4 previous errors + diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/patterns_same_crate.rs b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/patterns_same_crate.rs index 1194d7b858d60..58cced3d23d61 100644 --- a/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/patterns_same_crate.rs +++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/patterns_same_crate.rs @@ -6,11 +6,12 @@ pub enum UninhabitedEnum { } #[non_exhaustive] -pub struct UninhabitedTupleStruct(!); +pub struct UninhabitedTupleStruct(pub !); #[non_exhaustive] pub struct UninhabitedStruct { - _priv: !, + pub never: !, + _priv: (), } pub enum UninhabitedVariants { diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/patterns_same_crate.stderr b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/patterns_same_crate.stderr index 7e7dc802e7fbf..38524bf5b952e 100644 --- a/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/patterns_same_crate.stderr +++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/patterns_same_crate.stderr @@ -1,5 +1,5 @@ error: unreachable pattern - --> $DIR/patterns_same_crate.rs:51:9 + --> $DIR/patterns_same_crate.rs:52:9 | LL | Some(_x) => (), | ^^^^^^^^ matches no values because `UninhabitedEnum` is uninhabited @@ -12,7 +12,7 @@ LL | #![deny(unreachable_patterns)] | ^^^^^^^^^^^^^^^^^^^^ error: unreachable pattern - --> $DIR/patterns_same_crate.rs:56:9 + --> $DIR/patterns_same_crate.rs:57:9 | LL | Some(_x) => (), | ^^^^^^^^ matches no values because `UninhabitedVariants` is uninhabited @@ -20,7 +20,7 @@ LL | Some(_x) => (), = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern - --> $DIR/patterns_same_crate.rs:60:15 + --> $DIR/patterns_same_crate.rs:61:15 | LL | while let PartiallyInhabitedVariants::Struct { x } = partially_inhabited_variant() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ matches no values because `!` is uninhabited @@ -28,7 +28,7 @@ LL | while let PartiallyInhabitedVariants::Struct { x } = partially_inhabite = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern - --> $DIR/patterns_same_crate.rs:64:15 + --> $DIR/patterns_same_crate.rs:65:15 | LL | while let Some(_x) = uninhabited_struct() { | ^^^^^^^^ matches no values because `UninhabitedStruct` is uninhabited @@ -36,7 +36,7 @@ LL | while let Some(_x) = uninhabited_struct() { = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern - --> $DIR/patterns_same_crate.rs:67:15 + --> $DIR/patterns_same_crate.rs:68:15 | LL | while let Some(_x) = uninhabited_tuple_struct() { | ^^^^^^^^ matches no values because `UninhabitedTupleStruct` is uninhabited From fcb7d3fdf3216ba50167ff8d7ae63e63932d9d06 Mon Sep 17 00:00:00 2001 From: Ben Kimock Date: Mon, 2 Sep 2024 16:14:28 -0400 Subject: [PATCH 0393/2194] Add missing read_buf stub for x86_64-unknown-l5re-uclibc --- library/std/src/sys/pal/unix/l4re.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/library/std/src/sys/pal/unix/l4re.rs b/library/std/src/sys/pal/unix/l4re.rs index fe9559f2a569f..52d39dcfb16fb 100644 --- a/library/std/src/sys/pal/unix/l4re.rs +++ b/library/std/src/sys/pal/unix/l4re.rs @@ -54,6 +54,10 @@ pub mod net { unimpl!(); } + pub fn read_buf(&self, _: BorrowedCursor<'_>) -> io::Result<()> { + unimpl!(); + } + pub fn read_vectored(&self, _: &mut [IoSliceMut<'_>]) -> io::Result { unimpl!(); } From 0a89f72065445fff15678f66fc6c7eb0d40375e5 Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Mon, 2 Sep 2024 22:36:25 +0200 Subject: [PATCH 0394/2194] process.rs: remove "Basic usage" text where not useful Is not useful because just a single example is given. --- library/std/src/process.rs | 36 ------------------------------------ 1 file changed, 36 deletions(-) diff --git a/library/std/src/process.rs b/library/std/src/process.rs index bbea27ebc1056..a155855029e70 100644 --- a/library/std/src/process.rs +++ b/library/std/src/process.rs @@ -617,8 +617,6 @@ impl Command { /// /// # Examples /// - /// Basic usage: - /// /// ```no_run /// use std::process::Command; /// @@ -699,8 +697,6 @@ impl Command { /// /// # Examples /// - /// Basic usage: - /// /// ```no_run /// use std::process::Command; /// @@ -748,8 +744,6 @@ impl Command { /// /// # Examples /// - /// Basic usage: - /// /// ```no_run /// use std::process::Command; /// @@ -786,8 +780,6 @@ impl Command { /// /// # Examples /// - /// Basic usage: - /// /// ```no_run /// use std::process::Command; /// @@ -822,8 +814,6 @@ impl Command { /// /// # Examples /// - /// Basic usage: - /// /// ```no_run /// use std::process::{Command, Stdio}; /// use std::env; @@ -870,8 +860,6 @@ impl Command { /// /// # Examples /// - /// Basic usage: - /// /// ```no_run /// use std::process::Command; /// @@ -900,8 +888,6 @@ impl Command { /// /// # Examples /// - /// Basic usage: - /// /// ```no_run /// use std::process::Command; /// @@ -928,8 +914,6 @@ impl Command { /// /// # Examples /// - /// Basic usage: - /// /// ```no_run /// use std::process::Command; /// @@ -959,8 +943,6 @@ impl Command { /// /// # Examples /// - /// Basic usage: - /// /// ```no_run /// use std::process::{Command, Stdio}; /// @@ -988,8 +970,6 @@ impl Command { /// /// # Examples /// - /// Basic usage: - /// /// ```no_run /// use std::process::{Command, Stdio}; /// @@ -1017,8 +997,6 @@ impl Command { /// /// # Examples /// - /// Basic usage: - /// /// ```no_run /// use std::process::{Command, Stdio}; /// @@ -1039,8 +1017,6 @@ impl Command { /// /// # Examples /// - /// Basic usage: - /// /// ```no_run /// use std::process::Command; /// @@ -2105,8 +2081,6 @@ impl Child { /// /// # Examples /// - /// Basic usage: - /// /// ```no_run /// use std::process::Command; /// @@ -2129,8 +2103,6 @@ impl Child { /// /// # Examples /// - /// Basic usage: - /// /// ```no_run /// use std::process::Command; /// @@ -2158,8 +2130,6 @@ impl Child { /// /// # Examples /// - /// Basic usage: - /// /// ```no_run /// use std::process::Command; /// @@ -2194,8 +2164,6 @@ impl Child { /// /// # Examples /// - /// Basic usage: - /// /// ```no_run /// use std::process::Command; /// @@ -2398,15 +2366,11 @@ pub fn abort() -> ! { /// /// # Examples /// -/// Basic usage: -/// /// ```no_run /// use std::process; /// /// println!("My pid is {}", process::id()); /// ``` -/// -/// #[must_use] #[stable(feature = "getpid", since = "1.26.0")] pub fn id() -> u32 { From f1e5191807dfa68b3cc477fe4b9eb4bb928b800d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Mon, 2 Sep 2024 23:16:15 +0200 Subject: [PATCH 0395/2194] Fix parsing of beta version in dry-run mode --- src/bootstrap/src/lib.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/bootstrap/src/lib.rs b/src/bootstrap/src/lib.rs index 268392c5fb118..82b640f54234d 100644 --- a/src/bootstrap/src/lib.rs +++ b/src/bootstrap/src/lib.rs @@ -1501,6 +1501,7 @@ Executed at: {executed_at}"#, "refs/remotes/origin/{}..HEAD", self.config.stage0_metadata.config.nightly_branch )) + .run_always() .run_capture(self) .stdout() }); From b880890e598062ad671cc11d1dcf61a550293509 Mon Sep 17 00:00:00 2001 From: roife Date: Tue, 3 Sep 2024 05:01:56 +0800 Subject: [PATCH 0396/2194] refactor: move ide_assist::utils::suggest_name to ide-db --- .../ide-assists/src/handlers/extract_variable.rs | 3 ++- .../src/handlers/generate_delegate_trait.rs | 3 ++- .../src/handlers/introduce_named_generic.rs | 3 ++- .../replace_is_method_with_if_let_method.rs | 3 ++- .../rust-analyzer/crates/ide-assists/src/utils.rs | 1 - src/tools/rust-analyzer/crates/ide-db/src/lib.rs | 1 + .../src/syntax_helpers}/suggest_name.rs | 15 +++++++-------- 7 files changed, 16 insertions(+), 13 deletions(-) rename src/tools/rust-analyzer/crates/{ide-assists/src/utils => ide-db/src/syntax_helpers}/suggest_name.rs (97%) diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_variable.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_variable.rs index 5ae75bb1ff8e0..a43a4b5e1a060 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_variable.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_variable.rs @@ -1,4 +1,5 @@ use hir::TypeInfo; +use ide_db::syntax_helpers::suggest_name; use syntax::{ ast::{self, edit::IndentLevel, edit_in_place::Indent, make, AstNode, HasName}, ted, NodeOrToken, @@ -6,7 +7,7 @@ use syntax::{ SyntaxNode, T, }; -use crate::{utils::suggest_name, AssistContext, AssistId, AssistKind, Assists}; +use crate::{AssistContext, AssistId, AssistKind, Assists}; // Assist: extract_variable // diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_delegate_trait.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_delegate_trait.rs index bf4ce5c907e80..c22d19574fb49 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_delegate_trait.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_delegate_trait.rs @@ -2,13 +2,14 @@ use std::ops::Not; use crate::{ assist_context::{AssistContext, Assists}, - utils::{convert_param_list_to_arg_list, suggest_name}, + utils::convert_param_list_to_arg_list, }; use either::Either; use hir::{db::HirDatabase, HasVisibility}; use ide_db::{ assists::{AssistId, GroupLabel}, path_transform::PathTransform, + syntax_helpers::suggest_name, FxHashMap, FxHashSet, }; use itertools::Itertools; diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/introduce_named_generic.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/introduce_named_generic.rs index 543b7f7ab6329..a734a6cc2bc88 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/introduce_named_generic.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/introduce_named_generic.rs @@ -1,9 +1,10 @@ +use ide_db::syntax_helpers::suggest_name; use syntax::{ ast::{self, edit_in_place::GenericParamsOwnerEdit, make, AstNode, HasGenericParams}, ted, }; -use crate::{utils::suggest_name, AssistContext, AssistId, AssistKind, Assists}; +use crate::{AssistContext, AssistId, AssistKind, Assists}; // Assist: introduce_named_generic // diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_is_method_with_if_let_method.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_is_method_with_if_let_method.rs index 59bb0c45e1439..a856da0921537 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_is_method_with_if_let_method.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_is_method_with_if_let_method.rs @@ -1,9 +1,10 @@ +use ide_db::syntax_helpers::suggest_name; use syntax::{ ast::{self, make, AstNode}, ted, }; -use crate::{utils::suggest_name, AssistContext, AssistId, AssistKind, Assists}; +use crate::{AssistContext, AssistId, AssistKind, Assists}; // Assist: replace_is_some_with_if_let_some // diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/utils.rs b/src/tools/rust-analyzer/crates/ide-assists/src/utils.rs index b8a6f3b6dbeb2..19d1ef3157d19 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/utils.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/utils.rs @@ -23,7 +23,6 @@ use crate::assist_context::{AssistContext, SourceChangeBuilder}; mod gen_trait_fn_body; pub(crate) mod ref_field_expr; -pub(crate) mod suggest_name; pub(crate) fn unwrap_trivial_block(block_expr: ast::BlockExpr) -> ast::Expr { extract_trivial_expression(&block_expr) diff --git a/src/tools/rust-analyzer/crates/ide-db/src/lib.rs b/src/tools/rust-analyzer/crates/ide-db/src/lib.rs index 8a2068e9039fc..ab161f0ce5712 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/lib.rs +++ b/src/tools/rust-analyzer/crates/ide-db/src/lib.rs @@ -38,6 +38,7 @@ pub mod syntax_helpers { pub mod format_string_exprs; pub use hir::insert_whitespace_into_node; pub mod node_ext; + pub mod suggest_name; pub use parser::LexedStr; } diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/utils/suggest_name.rs b/src/tools/rust-analyzer/crates/ide-db/src/syntax_helpers/suggest_name.rs similarity index 97% rename from src/tools/rust-analyzer/crates/ide-assists/src/utils/suggest_name.rs rename to src/tools/rust-analyzer/crates/ide-db/src/syntax_helpers/suggest_name.rs index 3130ef0695577..14128e74438bc 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/utils/suggest_name.rs +++ b/src/tools/rust-analyzer/crates/ide-db/src/syntax_helpers/suggest_name.rs @@ -1,14 +1,16 @@ //! This module contains functions to suggest names for expressions, functions and other items use hir::Semantics; -use ide_db::{FxHashSet, RootDatabase}; use itertools::Itertools; +use rustc_hash::FxHashSet; use stdx::to_lower_snake_case; use syntax::{ ast::{self, HasName}, match_ast, AstNode, Edition, SmolStr, }; +use crate::RootDatabase; + /// Trait names, that will be ignored when in `impl Trait` and `dyn Trait` const USELESS_TRAITS: &[&str] = &["Send", "Sync", "Copy", "Clone", "Eq", "PartialEq"]; @@ -66,10 +68,7 @@ const USELESS_METHODS: &[&str] = &[ /// The function checks if the name conflicts with existing generic parameters. /// If so, it will try to resolve the conflict by adding a number suffix, e.g. /// `T`, `T0`, `T1`, ... -pub(crate) fn for_unique_generic_name( - name: &str, - existing_params: &ast::GenericParamList, -) -> SmolStr { +pub fn for_unique_generic_name(name: &str, existing_params: &ast::GenericParamList) -> SmolStr { let param_names = existing_params .generic_params() .map(|param| match param { @@ -101,7 +100,7 @@ pub(crate) fn for_unique_generic_name( /// /// If the name conflicts with existing generic parameters, it will try to /// resolve the conflict with `for_unique_generic_name`. -pub(crate) fn for_impl_trait_as_generic( +pub fn for_impl_trait_as_generic( ty: &ast::ImplTraitType, existing_params: &ast::GenericParamList, ) -> SmolStr { @@ -132,7 +131,7 @@ pub(crate) fn for_impl_trait_as_generic( /// /// Currently it sticks to the first name found. // FIXME: Microoptimize and return a `SmolStr` here. -pub(crate) fn for_variable(expr: &ast::Expr, sema: &Semantics<'_, RootDatabase>) -> String { +pub fn for_variable(expr: &ast::Expr, sema: &Semantics<'_, RootDatabase>) -> String { // `from_param` does not benefit from stripping // it need the largest context possible // so we check firstmost @@ -184,7 +183,7 @@ fn normalize(name: &str) -> Option { fn is_valid_name(name: &str) -> bool { matches!( - ide_db::syntax_helpers::LexedStr::single_token(syntax::Edition::CURRENT_FIXME, name), + super::LexedStr::single_token(syntax::Edition::CURRENT_FIXME, name), Some((syntax::SyntaxKind::IDENT, _error)) ) } From 5f7fcbe0d4dbd34c01dc6ae16e19a0f00035ba2f Mon Sep 17 00:00:00 2001 From: roife Date: Tue, 3 Sep 2024 05:15:21 +0800 Subject: [PATCH 0397/2194] feat: suggest name in let_stmt and fn_param --- .../crates/ide-completion/src/completions.rs | 10 ++++++++++ .../ide-completion/src/completions/pattern.rs | 13 +++++++++++++ .../crates/ide-completion/src/context.rs | 1 + .../ide-completion/src/context/analysis.rs | 13 +++++++++++++ .../ide-db/src/syntax_helpers/suggest_name.rs | 18 ++++++++++++++++-- 5 files changed, 53 insertions(+), 2 deletions(-) diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions.rs index b537150608bb0..414627fbabae1 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/completions.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions.rs @@ -617,6 +617,16 @@ impl Completions { } self.add_opt(render_struct_pat(RenderContext::new(ctx), pattern_ctx, strukt, local_name)); } + + pub(crate) fn suggest_name(&mut self, ctx: &CompletionContext<'_>, name: &str) { + let item = CompletionItem::new( + CompletionItemKind::Binding, + ctx.source_range(), + SmolStr::from(name), + ctx.edition, + ); + item.add_to(self, ctx.db); + } } /// Calls the callback for each variant of the provided enum with the path to the variant. diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/pattern.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/pattern.rs index 60cfb7e5a8c5a..2a06fc4017557 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/pattern.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/pattern.rs @@ -1,6 +1,7 @@ //! Completes constants and paths in unqualified patterns. use hir::{db::DefDatabase, AssocItem, ScopeDef}; +use ide_db::syntax_helpers::suggest_name; use syntax::ast::Pat; use crate::{ @@ -45,6 +46,18 @@ pub(crate) fn complete_pattern( return; } + // Suggest name only in let-stmt and fn param + if pattern_ctx.should_suggest_name { + if let Some(suggested) = ctx + .expected_type + .as_ref() + .map(|ty| ty.strip_references()) + .and_then(|ty| suggest_name::for_type(&ty, ctx.db, ctx.edition)) + { + acc.suggest_name(ctx, &suggested); + } + } + let refutable = pattern_ctx.refutability == PatternRefutability::Refutable; let single_variant_enum = |enum_: hir::Enum| ctx.db.enum_data(enum_.into()).variants.len() == 1; diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/context.rs b/src/tools/rust-analyzer/crates/ide-completion/src/context.rs index bcd9df941947f..d457ba32bf003 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/context.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/context.rs @@ -264,6 +264,7 @@ pub(crate) struct PatternContext { pub(crate) refutability: PatternRefutability, pub(crate) param_ctx: Option, pub(crate) has_type_ascription: bool, + pub(crate) should_suggest_name: bool, pub(crate) parent_pat: Option, pub(crate) ref_token: Option, pub(crate) mut_token: Option, diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/context/analysis.rs b/src/tools/rust-analyzer/crates/ide-completion/src/context/analysis.rs index 292c419498d16..1f9e3edf625d1 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/context/analysis.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/context/analysis.rs @@ -1430,10 +1430,23 @@ fn pattern_context_for( _ => (None, None), }; + // Only suggest name in let-stmt or fn param + let should_suggest_name = matches!( + &pat, + ast::Pat::IdentPat(it) + if it.syntax() + .parent() + .map_or(false, |node| { + let kind = node.kind(); + ast::LetStmt::can_cast(kind) || ast::Param::can_cast(kind) + }) + ); + PatternContext { refutability, param_ctx, has_type_ascription, + should_suggest_name, parent_pat: pat.syntax().parent().and_then(ast::Pat::cast), mut_token, ref_token, diff --git a/src/tools/rust-analyzer/crates/ide-db/src/syntax_helpers/suggest_name.rs b/src/tools/rust-analyzer/crates/ide-db/src/syntax_helpers/suggest_name.rs index 14128e74438bc..6ee526a67ea56 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/syntax_helpers/suggest_name.rs +++ b/src/tools/rust-analyzer/crates/ide-db/src/syntax_helpers/suggest_name.rs @@ -60,6 +60,21 @@ const USELESS_METHODS: &[&str] = &[ "into_future", ]; +/// Suggest a name for given type. +/// +/// The function will strip references first, and suggest name from the inner type. +/// +/// - If `ty` is an ADT, it will suggest the name of the ADT. +/// + If `ty` is wrapped in `Box`, `Option` or `Result`, it will suggest the name from the inner type. +/// - If `ty` is a trait, it will suggest the name of the trait. +/// - If `ty` is an `impl Trait`, it will suggest the name of the first trait. +/// +/// If the suggested name conflicts with reserved keywords, it will return `None`. +pub fn for_type(ty: &hir::Type, db: &RootDatabase, edition: Edition) -> Option { + let ty = ty.strip_references(); + name_of_type(&ty, db, edition) +} + /// Suggest a unique name for generic parameter. /// /// `existing_params` is used to check if the name conflicts with existing @@ -269,10 +284,9 @@ fn var_name_from_pat(pat: &ast::Pat) -> Option { fn from_type(expr: &ast::Expr, sema: &Semantics<'_, RootDatabase>) -> Option { let ty = sema.type_of_expr(expr)?.adjusted(); - let ty = ty.remove_ref().unwrap_or(ty); let edition = sema.scope(expr.syntax())?.krate().edition(sema.db); - name_of_type(&ty, sema.db, edition) + for_type(&ty, sema.db, edition) } fn name_of_type(ty: &hir::Type, db: &RootDatabase, edition: Edition) -> Option { From ef491f22999bb964ac92b64935d7ffe722e9c5a8 Mon Sep 17 00:00:00 2001 From: roife Date: Tue, 3 Sep 2024 05:16:02 +0800 Subject: [PATCH 0398/2194] tests: suggesting names in completions for let_stmt and fn_param --- .../ide-completion/src/tests/pattern.rs | 73 +++++++++++++++++++ 1 file changed, 73 insertions(+) diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/tests/pattern.rs b/src/tools/rust-analyzer/crates/ide-completion/src/tests/pattern.rs index 6a0b67e291af8..bd3e7c72bcd65 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/tests/pattern.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/tests/pattern.rs @@ -198,6 +198,7 @@ fn foo(a$0: Tuple) { st Unit bn Record {…} Record { field$1 }$0 bn Tuple(…) Tuple($1)$0 + bn tuple kw mut kw ref "#]], @@ -850,3 +851,75 @@ fn foo() { "#, ); } + +#[test] +fn suggest_name_for_pattern() { + check_edit( + "s1", + r#" +struct S1; + +fn foo() { + let $0 = S1; +} +"#, + r#" +struct S1; + +fn foo() { + let s1 = S1; +} +"#, + ); + + check_edit( + "s1", + r#" +struct S1; + +fn foo(s$0: S1) { +} +"#, + r#" +struct S1; + +fn foo(s1: S1) { +} +"#, + ); + + // Tests for &adt + check_edit( + "s1", + r#" +struct S1; + +fn foo() { + let $0 = &S1; +} +"#, + r#" +struct S1; + +fn foo() { + let s1 = &S1; +} +"#, + ); + + // Do not suggest reserved keywords + check_empty( + r#" +struct Struct; + +fn foo() { + let $0 = Struct; +} +"#, + expect![[r#" + st Struct + kw mut + kw ref + "#]], + ); +} From e4bce9866e661bd875f135cc4ba027ca58c20f7a Mon Sep 17 00:00:00 2001 From: DropDemBits Date: Mon, 2 Sep 2024 18:24:47 -0400 Subject: [PATCH 0399/2194] propagate annotations to mapped elements --- .../crates/syntax/src/syntax_editor.rs | 19 ++- .../syntax/src/syntax_editor/edit_algo.rs | 50 ++++-- .../syntax/src/syntax_editor/mapping.rs | 151 +++++++++++++----- 3 files changed, 168 insertions(+), 52 deletions(-) diff --git a/src/tools/rust-analyzer/crates/syntax/src/syntax_editor.rs b/src/tools/rust-analyzer/crates/syntax/src/syntax_editor.rs index 42373eba827d2..75347aeeed909 100644 --- a/src/tools/rust-analyzer/crates/syntax/src/syntax_editor.rs +++ b/src/tools/rust-analyzer/crates/syntax/src/syntax_editor.rs @@ -75,8 +75,8 @@ impl SyntaxEdit { &self.root } - /// Which syntax elements in the modified syntax tree were modified as part - /// of the edit. + /// Which syntax elements in the modified syntax tree were inserted or + /// modified as part of the edit. /// /// Note that for syntax nodes, only the upper-most parent of a set of /// changes is included, not any child elements that may have been modified. @@ -343,11 +343,22 @@ mod tests { editor.replace(to_wrap.syntax(), new_block.syntax()); // editor.replace(to_replace.syntax(), name_ref.syntax()); - // dbg!(&editor.mappings); let edit = editor.finish(); - let expect = expect![]; + dbg!(&edit.annotations); + + let expect = expect![[r#" + _ => { + let var_name = 2 + 2; + (var_name, true) + }"#]]; expect.assert_eq(&edit.root.to_string()); + assert_eq!(edit.find_annotation(placeholder_snippet).len(), 2); + assert!(edit + .annotations + .iter() + .flat_map(|(_, elements)| elements) + .all(|element| element.ancestors().any(|it| &it == edit.root()))) } } diff --git a/src/tools/rust-analyzer/crates/syntax/src/syntax_editor/edit_algo.rs b/src/tools/rust-analyzer/crates/syntax/src/syntax_editor/edit_algo.rs index f8354c5eb67cd..734a26b60033d 100644 --- a/src/tools/rust-analyzer/crates/syntax/src/syntax_editor/edit_algo.rs +++ b/src/tools/rust-analyzer/crates/syntax/src/syntax_editor/edit_algo.rs @@ -1,9 +1,10 @@ use std::{collections::VecDeque, ops::RangeInclusive}; use rowan::TextRange; +use rustc_hash::{FxHashMap, FxHashSet}; use crate::{ - syntax_editor::{Change, ChangeKind}, + syntax_editor::{mapping::MissingMapping, Change, ChangeKind}, ted, SyntaxElement, SyntaxNode, SyntaxNodePtr, }; @@ -29,9 +30,6 @@ pub(super) fn apply_edits(editor: SyntaxEditor) -> SyntaxEdit { let SyntaxEditor { root, mut changes, mappings, annotations } = editor; - dbg!(("initial: ", &root)); - dbg!(&changes); - // Sort changes by range then change kind, so that we can: // - ensure that parent edits are ordered before child edits // - ensure that inserts will be guaranteed to be inserted at the right range @@ -102,15 +100,18 @@ pub(super) fn apply_edits(editor: SyntaxEditor) -> SyntaxEdit { } } - dbg!(("before: ", &changes, &dependent_changes, &independent_changes)); - // Map change targets to the correct syntax nodes let tree_mutator = TreeMutator::new(&root); + let mut changed_elements = vec![]; for index in independent_changes { match &mut changes[index as usize] { - Change::Replace(target, _) => { + Change::Replace(target, new_node) => { *target = tree_mutator.make_element_mut(target); + + if let Some(new_node) = new_node { + changed_elements.push(new_node.clone()); + } } } } @@ -124,15 +125,20 @@ pub(super) fn apply_edits(editor: SyntaxEditor) -> SyntaxEdit { Change::Replace(_, None) => continue, // silently drop outdated change }; + let upmap_target = |target: &SyntaxElement| { + match mappings.upmap_child_element(target, &input_ancestor, &output_ancestor) { + Ok(it) => it, + Err(MissingMapping(current)) => unreachable!("no mappings exist between {current:?} (ancestor of {input_ancestor:?}) and {output_ancestor:?}"), + } + }; + match &mut changes[child as usize] { Change::Replace(target, _) => { - *target = mappings.upmap_child_element(target, &input_ancestor, output_ancestor) + *target = upmap_target(&target); } } } - dbg!(("after: ", &changes)); - // Apply changes for change in changes { match change { @@ -141,9 +147,29 @@ pub(super) fn apply_edits(editor: SyntaxEditor) -> SyntaxEdit { } } - dbg!(("modified:", tree_mutator.mutable_clone)); + // Propagate annotations + let annotations = annotations.into_iter().filter_map(|(element, annotation)| { + match mappings.upmap_element(&element, &tree_mutator.mutable_clone) { + // Needed to follow the new tree to find the resulting element + Some(Ok(mapped)) => Some((mapped, annotation)), + // Element did not need to be mapped + None => Some((element, annotation)), + // Element did not make it to the final tree + Some(Err(_)) => None, + } + }); + + let mut annotation_groups = FxHashMap::default(); - todo!("draw the rest of the owl") + for (element, annotation) in annotations { + annotation_groups.entry(annotation).or_insert(vec![]).push(element); + } + + SyntaxEdit { + root: tree_mutator.mutable_clone, + changed_elements, + annotations: annotation_groups, + } } fn to_owning_node(element: &SyntaxElement) -> SyntaxNode { diff --git a/src/tools/rust-analyzer/crates/syntax/src/syntax_editor/mapping.rs b/src/tools/rust-analyzer/crates/syntax/src/syntax_editor/mapping.rs index 8a79f7e186eda..f14d0b347d780 100644 --- a/src/tools/rust-analyzer/crates/syntax/src/syntax_editor/mapping.rs +++ b/src/tools/rust-analyzer/crates/syntax/src/syntax_editor/mapping.rs @@ -22,19 +22,20 @@ impl SyntaxMapping { Self::default() } + /// Like [`SyntaxMapping::upmap_child`] but for syntax elements. pub fn upmap_child_element( &self, child: &SyntaxElement, input_ancestor: &SyntaxNode, - output_ancestor: SyntaxNode, - ) -> SyntaxElement { + output_ancestor: &SyntaxNode, + ) -> Result { match child { SyntaxElement::Node(node) => { - SyntaxElement::Node(self.upmap_child(node, input_ancestor, output_ancestor)) + self.upmap_child(node, input_ancestor, output_ancestor).map(SyntaxElement::Node) } SyntaxElement::Token(token) => { let upmap_parent = - self.upmap_child(&token.parent().unwrap(), input_ancestor, output_ancestor); + self.upmap_child(&token.parent().unwrap(), input_ancestor, output_ancestor)?; let element = upmap_parent.children_with_tokens().nth(token.index()).unwrap(); debug_assert!( @@ -42,21 +43,26 @@ impl SyntaxMapping { "token upmapping mapped to the wrong node ({token:?} -> {element:?})" ); - element + Ok(element) } } } + /// Maps a child node of the input ancestor to the corresponding node in + /// the output ancestor. pub fn upmap_child( &self, child: &SyntaxNode, input_ancestor: &SyntaxNode, - output_ancestor: SyntaxNode, - ) -> SyntaxNode { - debug_assert!(child.ancestors().any(|ancestor| &ancestor == input_ancestor)); + output_ancestor: &SyntaxNode, + ) -> Result { + debug_assert!( + child == input_ancestor + || child.ancestors().any(|ancestor| &ancestor == input_ancestor) + ); // Build a list mapping up to the first mappable ancestor - let to_first_upmap = + let to_first_upmap = if child != input_ancestor { std::iter::successors(Some((child.index(), child.clone())), |(_, current)| { let parent = current.parent().unwrap(); @@ -67,24 +73,14 @@ impl SyntaxMapping { Some((parent.index(), parent)) }) .map(|(i, _)| i) - .collect::>(); + .collect::>() + } else { + vec![] + }; // Progressively up-map the input ancestor until we get to the output ancestor - let to_output_ancestor = if input_ancestor != &output_ancestor { - std::iter::successors(Some((input_ancestor.index(), self.upmap_node(input_ancestor).unwrap_or_else(|| input_ancestor.clone()))), |(_, current)| { - let Some(parent) = current.parent() else { - unreachable!("no mappings exist between {current:?} (ancestor of {input_ancestor:?}) and {output_ancestor:?}") - }; - - if &parent == &output_ancestor { - return None; - } - - Some((parent.index(), match self.upmap_node(&parent) { - Some(next) => next, - None => parent - })) - }).map(|(i, _)| i).collect::>() + let to_output_ancestor = if input_ancestor != output_ancestor { + self.upmap_to_ancestor(input_ancestor, output_ancestor)? } else { vec![] }; @@ -92,7 +88,7 @@ impl SyntaxMapping { let to_map_down = to_output_ancestor.into_iter().rev().chain(to_first_upmap.into_iter().rev()); - let mut target = output_ancestor; + let mut target = output_ancestor.clone(); for index in to_map_down { target = target @@ -104,20 +100,86 @@ impl SyntaxMapping { debug_assert_eq!(child.kind(), target.kind()); - target + Ok(target) } - pub fn upmap_node(&self, input: &SyntaxNode) -> Option { - let MappingEntry { parent, child_slot } = self.node_mappings.get(input)?; + fn upmap_to_ancestor( + &self, + input_ancestor: &SyntaxNode, + output_ancestor: &SyntaxNode, + ) -> Result, MissingMapping> { + eprintln!("mapping ancestor {input_ancestor:#?} to {output_ancestor:#?}"); + let mut current = + self.upmap_node_single(input_ancestor).unwrap_or_else(|| input_ancestor.clone()); + let mut upmap_chain = vec![current.index()]; + + loop { + let Some(parent) = current.parent() else { break }; + + if &parent == output_ancestor { + return Ok(upmap_chain); + } - let output = self.entry_parents[*parent as usize] - .children_with_tokens() - .nth(*child_slot as usize) - .and_then(SyntaxElement::into_node) - .unwrap(); + current = match self.upmap_node_single(&parent) { + Some(next) => next, + None => parent, + }; + upmap_chain.push(current.index()); + } - debug_assert_eq!(input.kind(), output.kind()); - Some(output) + Err(MissingMapping(current)) + } + + pub fn upmap_element( + &self, + input: &SyntaxElement, + output_root: &SyntaxNode, + ) -> Option> { + match input { + SyntaxElement::Node(node) => { + Some(self.upmap_node(node, output_root)?.map(SyntaxElement::Node)) + } + SyntaxElement::Token(token) => { + let upmap_parent = match self.upmap_node(&token.parent().unwrap(), output_root)? { + Ok(it) => it, + Err(err) => return Some(Err(err)), + }; + + let element = upmap_parent.children_with_tokens().nth(token.index()).unwrap(); + debug_assert!( + element.as_token().is_some_and(|it| it.kind() == token.kind()), + "token upmapping mapped to the wrong node ({token:?} -> {element:?})" + ); + + Some(Ok(element)) + } + } + } + + pub fn upmap_node( + &self, + input: &SyntaxNode, + output_root: &SyntaxNode, + ) -> Option> { + // Try to follow the mapping tree, if it exists + let input_mapping = self.upmap_node_single(input); + let input_ancestor = + input.ancestors().find_map(|ancestor| self.upmap_node_single(&ancestor)); + + match (input_mapping, input_ancestor) { + (Some(input_mapping), _) => { + // A mapping exists at the input, follow along the tree + Some(self.upmap_child(&input_mapping, &input_mapping, &output_root)) + } + (None, Some(input_ancestor)) => { + // A mapping exists at an ancestor, follow along the tree + Some(self.upmap_child(input, &input_ancestor, &output_root)) + } + (None, None) => { + // No mapping exists at all, is the same position in the final tree + None + } + } } pub fn merge(&mut self, mut other: SyntaxMapping) { @@ -130,6 +192,20 @@ impl SyntaxMapping { })); } + /// Follows the input one step along the syntax mapping tree + fn upmap_node_single(&self, input: &SyntaxNode) -> Option { + let MappingEntry { parent, child_slot } = self.node_mappings.get(input)?; + + let output = self.entry_parents[*parent as usize] + .children_with_tokens() + .nth(*child_slot as usize) + .and_then(SyntaxElement::into_node) + .unwrap(); + + debug_assert_eq!(input.kind(), output.kind()); + Some(output) + } + fn add_mapping(&mut self, syntax_mapping: SyntaxMappingBuilder) { let SyntaxMappingBuilder { parent_node, node_mappings } = syntax_mapping; @@ -183,6 +259,9 @@ impl SyntaxMappingBuilder { } } +#[derive(Debug)] +pub struct MissingMapping(pub SyntaxNode); + #[derive(Debug, Clone, Copy)] struct MappingEntry { parent: u32, From 19843bba64adda8194aa983fd7d1397517f5efe6 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 30 Aug 2024 10:28:52 +1000 Subject: [PATCH 0400/2194] Add `warn(unreachable_pub)` to `rustc_sanitizers`. --- .../src/cfi/typeid/itanium_cxx_abi/encode.rs | 6 +++--- .../src/cfi/typeid/itanium_cxx_abi/transform.rs | 6 +++--- compiler/rustc_sanitizers/src/lib.rs | 1 + 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/encode.rs b/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/encode.rs index a4e4f50e8f2d4..45057a3530c3e 100644 --- a/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/encode.rs +++ b/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/encode.rs @@ -26,11 +26,11 @@ use crate::cfi::typeid::itanium_cxx_abi::transform::{TransformTy, TransformTyOpt use crate::cfi::typeid::TypeIdOptions; /// Options for encode_ty. -pub type EncodeTyOptions = TypeIdOptions; +pub(crate) type EncodeTyOptions = TypeIdOptions; /// Substitution dictionary key. #[derive(Eq, Hash, PartialEq)] -pub enum DictKey<'tcx> { +pub(crate) enum DictKey<'tcx> { Ty(Ty<'tcx>, TyQ), Region(Region<'tcx>), Const(Const<'tcx>), @@ -39,7 +39,7 @@ pub enum DictKey<'tcx> { /// Type and extended type qualifiers. #[derive(Eq, Hash, PartialEq)] -pub enum TyQ { +pub(crate) enum TyQ { None, Const, Mut, diff --git a/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/transform.rs b/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/transform.rs index 2f43199796cc6..8db0d3585378f 100644 --- a/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/transform.rs +++ b/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/transform.rs @@ -23,16 +23,16 @@ use crate::cfi::typeid::itanium_cxx_abi::encode::EncodeTyOptions; use crate::cfi::typeid::TypeIdOptions; /// Options for transform_ty. -pub type TransformTyOptions = TypeIdOptions; +pub(crate) type TransformTyOptions = TypeIdOptions; -pub struct TransformTy<'tcx> { +pub(crate) struct TransformTy<'tcx> { tcx: TyCtxt<'tcx>, options: TransformTyOptions, parents: Vec>, } impl<'tcx> TransformTy<'tcx> { - pub fn new(tcx: TyCtxt<'tcx>, options: TransformTyOptions) -> Self { + pub(crate) fn new(tcx: TyCtxt<'tcx>, options: TransformTyOptions) -> Self { TransformTy { tcx, options, parents: Vec::new() } } } diff --git a/compiler/rustc_sanitizers/src/lib.rs b/compiler/rustc_sanitizers/src/lib.rs index e4792563e71ea..55be931bcd6d4 100644 --- a/compiler/rustc_sanitizers/src/lib.rs +++ b/compiler/rustc_sanitizers/src/lib.rs @@ -5,6 +5,7 @@ // tidy-alphabetical-start #![feature(let_chains)] +#![warn(unreachable_pub)] // tidy-alphabetical-end pub mod cfi; From 21a37da26840ae34a02246ea9141b28efd6e8ce5 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 30 Aug 2024 10:45:32 +1000 Subject: [PATCH 0401/2194] Add `warn(unreachable_pub)` to `rustc_serialize`. --- compiler/rustc_serialize/src/lib.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/compiler/rustc_serialize/src/lib.rs b/compiler/rustc_serialize/src/lib.rs index f0e1630c65009..b7977a848ce00 100644 --- a/compiler/rustc_serialize/src/lib.rs +++ b/compiler/rustc_serialize/src/lib.rs @@ -16,6 +16,7 @@ #![feature(never_type)] #![feature(ptr_sub_ptr)] #![feature(rustdoc_internals)] +#![warn(unreachable_pub)] // tidy-alphabetical-end pub use self::serialize::{Decodable, Decoder, Encodable, Encoder}; From 19ff6e6e63a22dbccc86ee0c78d2baddb91bda03 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 30 Aug 2024 11:02:18 +1000 Subject: [PATCH 0402/2194] Add `warn(unreachable_pub)` to `rustc_session`. --- compiler/rustc_session/src/lib.rs | 1 + compiler/rustc_session/src/options.rs | 142 +++++++++++++------------- 2 files changed, 74 insertions(+), 69 deletions(-) diff --git a/compiler/rustc_session/src/lib.rs b/compiler/rustc_session/src/lib.rs index d93b3eac08040..7e059a88c2790 100644 --- a/compiler/rustc_session/src/lib.rs +++ b/compiler/rustc_session/src/lib.rs @@ -5,6 +5,7 @@ #![feature(map_many_mut)] #![feature(option_get_or_insert_default)] #![feature(rustc_attrs)] +#![warn(unreachable_pub)] // tidy-alphabetical-end pub mod errors; diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index 37077901e0c34..45339c23ea3ef 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -358,94 +358,98 @@ fn build_options( #[allow(non_upper_case_globals)] mod desc { - pub const parse_no_flag: &str = "no value"; - pub const parse_bool: &str = "one of: `y`, `yes`, `on`, `true`, `n`, `no`, `off` or `false`"; - pub const parse_opt_bool: &str = parse_bool; - pub const parse_string: &str = "a string"; - pub const parse_opt_string: &str = parse_string; - pub const parse_string_push: &str = parse_string; - pub const parse_opt_langid: &str = "a language identifier"; - pub const parse_opt_pathbuf: &str = "a path"; - pub const parse_list: &str = "a space-separated list of strings"; - pub const parse_list_with_polarity: &str = + pub(crate) const parse_no_flag: &str = "no value"; + pub(crate) const parse_bool: &str = + "one of: `y`, `yes`, `on`, `true`, `n`, `no`, `off` or `false`"; + pub(crate) const parse_opt_bool: &str = parse_bool; + pub(crate) const parse_string: &str = "a string"; + pub(crate) const parse_opt_string: &str = parse_string; + pub(crate) const parse_string_push: &str = parse_string; + pub(crate) const parse_opt_langid: &str = "a language identifier"; + pub(crate) const parse_opt_pathbuf: &str = "a path"; + pub(crate) const parse_list: &str = "a space-separated list of strings"; + pub(crate) const parse_list_with_polarity: &str = "a comma-separated list of strings, with elements beginning with + or -"; - pub const parse_comma_list: &str = "a comma-separated list of strings"; - pub const parse_opt_comma_list: &str = parse_comma_list; - pub const parse_number: &str = "a number"; - pub const parse_opt_number: &str = parse_number; - pub const parse_frame_pointer: &str = "one of `true`/`yes`/`on`, `false`/`no`/`off`, or (with -Zunstable-options) `non-leaf` or `always`"; - pub const parse_threads: &str = parse_number; - pub const parse_time_passes_format: &str = "`text` (default) or `json`"; - pub const parse_passes: &str = "a space-separated list of passes, or `all`"; - pub const parse_panic_strategy: &str = "either `unwind` or `abort`"; - pub const parse_on_broken_pipe: &str = "either `kill`, `error`, or `inherit`"; - pub const parse_patchable_function_entry: &str = "either two comma separated integers (total_nops,prefix_nops), with prefix_nops <= total_nops, or one integer (total_nops)"; - pub const parse_opt_panic_strategy: &str = parse_panic_strategy; - pub const parse_oom_strategy: &str = "either `panic` or `abort`"; - pub const parse_relro_level: &str = "one of: `full`, `partial`, or `off`"; - pub const parse_sanitizers: &str = "comma separated list of sanitizers: `address`, `cfi`, `dataflow`, `hwaddress`, `kcfi`, `kernel-address`, `leak`, `memory`, `memtag`, `safestack`, `shadow-call-stack`, or `thread`"; - pub const parse_sanitizer_memory_track_origins: &str = "0, 1, or 2"; - pub const parse_cfguard: &str = + pub(crate) const parse_comma_list: &str = "a comma-separated list of strings"; + pub(crate) const parse_opt_comma_list: &str = parse_comma_list; + pub(crate) const parse_number: &str = "a number"; + pub(crate) const parse_opt_number: &str = parse_number; + pub(crate) const parse_frame_pointer: &str = "one of `true`/`yes`/`on`, `false`/`no`/`off`, or (with -Zunstable-options) `non-leaf` or `always`"; + pub(crate) const parse_threads: &str = parse_number; + pub(crate) const parse_time_passes_format: &str = "`text` (default) or `json`"; + pub(crate) const parse_passes: &str = "a space-separated list of passes, or `all`"; + pub(crate) const parse_panic_strategy: &str = "either `unwind` or `abort`"; + pub(crate) const parse_on_broken_pipe: &str = "either `kill`, `error`, or `inherit`"; + pub(crate) const parse_patchable_function_entry: &str = "either two comma separated integers (total_nops,prefix_nops), with prefix_nops <= total_nops, or one integer (total_nops)"; + pub(crate) const parse_opt_panic_strategy: &str = parse_panic_strategy; + pub(crate) const parse_oom_strategy: &str = "either `panic` or `abort`"; + pub(crate) const parse_relro_level: &str = "one of: `full`, `partial`, or `off`"; + pub(crate) const parse_sanitizers: &str = "comma separated list of sanitizers: `address`, `cfi`, `dataflow`, `hwaddress`, `kcfi`, `kernel-address`, `leak`, `memory`, `memtag`, `safestack`, `shadow-call-stack`, or `thread`"; + pub(crate) const parse_sanitizer_memory_track_origins: &str = "0, 1, or 2"; + pub(crate) const parse_cfguard: &str = "either a boolean (`yes`, `no`, `on`, `off`, etc), `checks`, or `nochecks`"; - pub const parse_cfprotection: &str = "`none`|`no`|`n` (default), `branch`, `return`, or `full`|`yes`|`y` (equivalent to `branch` and `return`)"; - pub const parse_debuginfo: &str = "either an integer (0, 1, 2), `none`, `line-directives-only`, `line-tables-only`, `limited`, or `full`"; - pub const parse_debuginfo_compression: &str = "one of `none`, `zlib`, or `zstd`"; - pub const parse_collapse_macro_debuginfo: &str = "one of `no`, `external`, or `yes`"; - pub const parse_strip: &str = "either `none`, `debuginfo`, or `symbols`"; - pub const parse_linker_flavor: &str = ::rustc_target::spec::LinkerFlavorCli::one_of(); - pub const parse_optimization_fuel: &str = "crate=integer"; - pub const parse_dump_mono_stats: &str = "`markdown` (default) or `json`"; - pub const parse_instrument_coverage: &str = parse_bool; - pub const parse_coverage_options: &str = + pub(crate) const parse_cfprotection: &str = "`none`|`no`|`n` (default), `branch`, `return`, or `full`|`yes`|`y` (equivalent to `branch` and `return`)"; + pub(crate) const parse_debuginfo: &str = "either an integer (0, 1, 2), `none`, `line-directives-only`, `line-tables-only`, `limited`, or `full`"; + pub(crate) const parse_debuginfo_compression: &str = "one of `none`, `zlib`, or `zstd`"; + pub(crate) const parse_collapse_macro_debuginfo: &str = "one of `no`, `external`, or `yes`"; + pub(crate) const parse_strip: &str = "either `none`, `debuginfo`, or `symbols`"; + pub(crate) const parse_linker_flavor: &str = ::rustc_target::spec::LinkerFlavorCli::one_of(); + pub(crate) const parse_optimization_fuel: &str = "crate=integer"; + pub(crate) const parse_dump_mono_stats: &str = "`markdown` (default) or `json`"; + pub(crate) const parse_instrument_coverage: &str = parse_bool; + pub(crate) const parse_coverage_options: &str = "`block` | `branch` | `condition` | `mcdc` | `no-mir-spans`"; - pub const parse_instrument_xray: &str = "either a boolean (`yes`, `no`, `on`, `off`, etc), or a comma separated list of settings: `always` or `never` (mutually exclusive), `ignore-loops`, `instruction-threshold=N`, `skip-entry`, `skip-exit`"; - pub const parse_unpretty: &str = "`string` or `string=string`"; - pub const parse_treat_err_as_bug: &str = "either no value or a non-negative number"; - pub const parse_next_solver_config: &str = + pub(crate) const parse_instrument_xray: &str = "either a boolean (`yes`, `no`, `on`, `off`, etc), or a comma separated list of settings: `always` or `never` (mutually exclusive), `ignore-loops`, `instruction-threshold=N`, `skip-entry`, `skip-exit`"; + pub(crate) const parse_unpretty: &str = "`string` or `string=string`"; + pub(crate) const parse_treat_err_as_bug: &str = "either no value or a non-negative number"; + pub(crate) const parse_next_solver_config: &str = "a comma separated list of solver configurations: `globally` (default), and `coherence`"; - pub const parse_lto: &str = + pub(crate) const parse_lto: &str = "either a boolean (`yes`, `no`, `on`, `off`, etc), `thin`, `fat`, or omitted"; - pub const parse_linker_plugin_lto: &str = + pub(crate) const parse_linker_plugin_lto: &str = "either a boolean (`yes`, `no`, `on`, `off`, etc), or the path to the linker plugin"; - pub const parse_location_detail: &str = "either `none`, or a comma separated list of location details to track: `file`, `line`, or `column`"; - pub const parse_fmt_debug: &str = "either `full`, `shallow`, or `none`"; - pub const parse_switch_with_opt_path: &str = + pub(crate) const parse_location_detail: &str = "either `none`, or a comma separated list of location details to track: `file`, `line`, or `column`"; + pub(crate) const parse_fmt_debug: &str = "either `full`, `shallow`, or `none`"; + pub(crate) 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 = + pub(crate) const parse_merge_functions: &str = + "one of: `disabled`, `trampolines`, or `aliases`"; + pub(crate) 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 = + pub(crate) const parse_src_file_hash: &str = "either `md5` or `sha1`"; + pub(crate) const parse_relocation_model: &str = "one of supported relocation models (`rustc --print relocation-models`)"; - pub const parse_code_model: &str = "one of supported code models (`rustc --print code-models`)"; - pub const parse_tls_model: &str = "one of supported TLS models (`rustc --print tls-models`)"; - pub const parse_target_feature: &str = parse_string; - pub const parse_terminal_url: &str = + pub(crate) const parse_code_model: &str = + "one of supported code models (`rustc --print code-models`)"; + pub(crate) const parse_tls_model: &str = + "one of supported TLS models (`rustc --print tls-models`)"; + pub(crate) const parse_target_feature: &str = parse_string; + pub(crate) const parse_terminal_url: &str = "either a boolean (`yes`, `no`, `on`, `off`, etc), or `auto`"; - pub const parse_wasi_exec_model: &str = "either `command` or `reactor`"; - pub const parse_split_debuginfo: &str = + pub(crate) const parse_wasi_exec_model: &str = "either `command` or `reactor`"; + pub(crate) const parse_split_debuginfo: &str = "one of supported split-debuginfo modes (`off`, `packed`, or `unpacked`)"; - pub const parse_split_dwarf_kind: &str = + pub(crate) const parse_split_dwarf_kind: &str = "one of supported split dwarf modes (`split` or `single`)"; - pub const parse_link_self_contained: &str = "one of: `y`, `yes`, `on`, `n`, `no`, `off`, or a list of enabled (`+` prefix) and disabled (`-` prefix) \ + pub(crate) const parse_link_self_contained: &str = "one of: `y`, `yes`, `on`, `n`, `no`, `off`, or a list of enabled (`+` prefix) and disabled (`-` prefix) \ components: `crto`, `libc`, `unwind`, `linker`, `sanitizers`, `mingw`"; - pub const parse_linker_features: &str = + pub(crate) const parse_linker_features: &str = "a list of enabled (`+` prefix) and disabled (`-` prefix) features: `lld`"; - pub const parse_polonius: &str = "either no value or `legacy` (the default), or `next`"; - pub const parse_stack_protector: &str = + pub(crate) const parse_polonius: &str = "either no value or `legacy` (the default), or `next`"; + pub(crate) const parse_stack_protector: &str = "one of (`none` (default), `basic`, `strong`, or `all`)"; - pub const parse_branch_protection: &str = + pub(crate) const parse_branch_protection: &str = "a `,` separated combination of `bti`, `b-key`, `pac-ret`, or `leaf`"; - pub const parse_proc_macro_execution_strategy: &str = + pub(crate) const parse_proc_macro_execution_strategy: &str = "one of supported execution strategies (`same-thread`, or `cross-thread`)"; - pub const parse_remap_path_scope: &str = + pub(crate) const parse_remap_path_scope: &str = "comma separated list of scopes: `macro`, `diagnostics`, `debuginfo`, `object`, `all`"; - pub const parse_inlining_threshold: &str = + pub(crate) const parse_inlining_threshold: &str = "either a boolean (`yes`, `no`, `on`, `off`, etc), or a non-negative number"; - pub const parse_llvm_module_flag: &str = ":::. Type must currently be `u32`. Behavior should be one of (`error`, `warning`, `require`, `override`, `append`, `appendunique`, `max`, `min`)"; - pub const parse_function_return: &str = "`keep` or `thunk-extern`"; - pub const parse_wasm_c_abi: &str = "`legacy` or `spec`"; - pub const parse_mir_include_spans: &str = + pub(crate) const parse_llvm_module_flag: &str = ":::. Type must currently be `u32`. Behavior should be one of (`error`, `warning`, `require`, `override`, `append`, `appendunique`, `max`, `min`)"; + pub(crate) const parse_function_return: &str = "`keep` or `thunk-extern`"; + pub(crate) const parse_wasm_c_abi: &str = "`legacy` or `spec`"; + pub(crate) const parse_mir_include_spans: &str = "either a boolean (`yes`, `no`, `on`, `off`, etc), or `nll` (default: `nll`)"; } From b457ab31860b9c92fd2a52c7a2ca328a04cdfa23 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 30 Aug 2024 12:59:35 +1000 Subject: [PATCH 0403/2194] Add `warn(unreachable_pub)` to `rustc_smir`. --- compiler/rustc_smir/src/lib.rs | 1 + compiler/rustc_smir/src/rustc_smir/alloc.rs | 4 ++-- compiler/rustc_smir/src/rustc_smir/builder.rs | 6 +++--- compiler/rustc_smir/src/rustc_smir/context.rs | 2 +- compiler/rustc_smir/src/rustc_smir/convert/mod.rs | 2 +- compiler/rustc_smir/src/rustc_smir/convert/ty.rs | 2 +- 6 files changed, 9 insertions(+), 8 deletions(-) diff --git a/compiler/rustc_smir/src/lib.rs b/compiler/rustc_smir/src/lib.rs index 9f88887530614..2215e2f01ade0 100644 --- a/compiler/rustc_smir/src/lib.rs +++ b/compiler/rustc_smir/src/lib.rs @@ -15,6 +15,7 @@ )] #![doc(rust_logo)] #![feature(rustdoc_internals)] +#![warn(unreachable_pub)] // tidy-alphabetical-end pub mod rustc_internal; diff --git a/compiler/rustc_smir/src/rustc_smir/alloc.rs b/compiler/rustc_smir/src/rustc_smir/alloc.rs index 677b4c7a9c0e3..11fbc005e37da 100644 --- a/compiler/rustc_smir/src/rustc_smir/alloc.rs +++ b/compiler/rustc_smir/src/rustc_smir/alloc.rs @@ -20,7 +20,7 @@ fn new_empty_allocation(align: rustc_target::abi::Align) -> Allocation { // because we need to get `Ty` of the const we are trying to create, to do that // we need to have access to `ConstantKind` but we can't access that inside Stable impl. #[allow(rustc::usage_of_qualified_ty)] -pub fn new_allocation<'tcx>( +pub(crate) fn new_allocation<'tcx>( ty: rustc_middle::ty::Ty<'tcx>, const_value: ConstValue<'tcx>, tables: &mut Tables<'tcx>, @@ -30,7 +30,7 @@ pub fn new_allocation<'tcx>( } #[allow(rustc::usage_of_qualified_ty)] -pub fn try_new_allocation<'tcx>( +pub(crate) fn try_new_allocation<'tcx>( ty: rustc_middle::ty::Ty<'tcx>, const_value: ConstValue<'tcx>, tables: &mut Tables<'tcx>, diff --git a/compiler/rustc_smir/src/rustc_smir/builder.rs b/compiler/rustc_smir/src/rustc_smir/builder.rs index 883ab7c18b485..cd91fc26c1018 100644 --- a/compiler/rustc_smir/src/rustc_smir/builder.rs +++ b/compiler/rustc_smir/src/rustc_smir/builder.rs @@ -12,13 +12,13 @@ use rustc_middle::ty::{self, TyCtxt}; use crate::rustc_smir::{Stable, Tables}; /// Builds a monomorphic body for a given instance. -pub struct BodyBuilder<'tcx> { +pub(crate) struct BodyBuilder<'tcx> { tcx: TyCtxt<'tcx>, instance: ty::Instance<'tcx>, } impl<'tcx> BodyBuilder<'tcx> { - pub fn new(tcx: TyCtxt<'tcx>, instance: ty::Instance<'tcx>) -> Self { + pub(crate) fn new(tcx: TyCtxt<'tcx>, instance: ty::Instance<'tcx>) -> Self { let instance = match instance.def { // To get the fallback body of an intrinsic, we need to convert it to an item. ty::InstanceKind::Intrinsic(def_id) => ty::Instance::new(def_id, instance.args), @@ -30,7 +30,7 @@ impl<'tcx> BodyBuilder<'tcx> { /// Build a stable monomorphic body for a given instance based on the MIR body. /// /// All constants are also evaluated. - pub fn build(mut self, tables: &mut Tables<'tcx>) -> stable_mir::mir::Body { + pub(crate) fn build(mut self, tables: &mut Tables<'tcx>) -> stable_mir::mir::Body { let body = tables.tcx.instance_mir(self.instance.def).clone(); let mono_body = if !self.instance.args.is_empty() // Without the `generic_const_exprs` feature gate, anon consts in signatures do not diff --git a/compiler/rustc_smir/src/rustc_smir/context.rs b/compiler/rustc_smir/src/rustc_smir/context.rs index f9663f2dd30d9..a4ede374a19dc 100644 --- a/compiler/rustc_smir/src/rustc_smir/context.rs +++ b/compiler/rustc_smir/src/rustc_smir/context.rs @@ -784,7 +784,7 @@ impl<'tcx> Context for TablesWrapper<'tcx> { } } -pub struct TablesWrapper<'tcx>(pub RefCell>); +pub(crate) struct TablesWrapper<'tcx>(pub RefCell>); /// Implement error handling for extracting function ABI information. impl<'tcx> FnAbiOfHelpers<'tcx> for Tables<'tcx> { diff --git a/compiler/rustc_smir/src/rustc_smir/convert/mod.rs b/compiler/rustc_smir/src/rustc_smir/convert/mod.rs index 50687935473a7..c9795fca3993a 100644 --- a/compiler/rustc_smir/src/rustc_smir/convert/mod.rs +++ b/compiler/rustc_smir/src/rustc_smir/convert/mod.rs @@ -9,7 +9,7 @@ mod error; mod mir; mod ty; -pub use ty::mir_const_from_ty_const; +pub(crate) use ty::mir_const_from_ty_const; impl<'tcx> Stable<'tcx> for rustc_hir::Safety { type T = stable_mir::mir::Safety; diff --git a/compiler/rustc_smir/src/rustc_smir/convert/ty.rs b/compiler/rustc_smir/src/rustc_smir/convert/ty.rs index 9afd732486c28..efbb0f244fc8f 100644 --- a/compiler/rustc_smir/src/rustc_smir/convert/ty.rs +++ b/compiler/rustc_smir/src/rustc_smir/convert/ty.rs @@ -411,7 +411,7 @@ impl<'tcx> Stable<'tcx> for ty::Pattern<'tcx> { } } -pub fn mir_const_from_ty_const<'tcx>( +pub(crate) fn mir_const_from_ty_const<'tcx>( tables: &mut Tables<'tcx>, ty_const: ty::Const<'tcx>, ty: Ty<'tcx>, From b0f22ff98ff345aa7daf8c2f67d5b55f721c366a Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 30 Aug 2024 13:15:02 +1000 Subject: [PATCH 0404/2194] Add `warn(unreachable_pub)` to `rustc_span`. --- compiler/rustc_span/src/analyze_source_file.rs | 2 +- compiler/rustc_span/src/lib.rs | 1 + compiler/rustc_span/src/span_encoding.rs | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_span/src/analyze_source_file.rs b/compiler/rustc_span/src/analyze_source_file.rs index ba7e0cec5bd80..28ce883daee9a 100644 --- a/compiler/rustc_span/src/analyze_source_file.rs +++ b/compiler/rustc_span/src/analyze_source_file.rs @@ -8,7 +8,7 @@ mod tests; /// /// This function will use an SSE2 enhanced implementation if hardware support /// is detected at runtime. -pub fn analyze_source_file(src: &str) -> (Vec, Vec) { +pub(crate) fn analyze_source_file(src: &str) -> (Vec, Vec) { let mut lines = vec![RelativeBytePos::from_u32(0)]; let mut multi_byte_chars = vec![]; diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs index 7b020f11cdda0..45dca3af6c07d 100644 --- a/compiler/rustc_span/src/lib.rs +++ b/compiler/rustc_span/src/lib.rs @@ -30,6 +30,7 @@ #![feature(round_char_boundary)] #![feature(rustc_attrs)] #![feature(rustdoc_internals)] +#![warn(unreachable_pub)] // tidy-alphabetical-end // The code produced by the `Encodable`/`Decodable` derive macros refer to diff --git a/compiler/rustc_span/src/span_encoding.rs b/compiler/rustc_span/src/span_encoding.rs index 8988becb17126..3047abfbb5cb0 100644 --- a/compiler/rustc_span/src/span_encoding.rs +++ b/compiler/rustc_span/src/span_encoding.rs @@ -424,7 +424,7 @@ impl Span { } #[derive(Default)] -pub struct SpanInterner { +pub(crate) struct SpanInterner { spans: FxIndexSet, } From 89deb3c7420bf5a3643a53132cca4e1d9e0ebc80 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 30 Aug 2024 13:21:53 +1000 Subject: [PATCH 0405/2194] Add `warn(unreachable_pub)` to `rustc_symbol_mangling`. --- compiler/rustc_symbol_mangling/src/lib.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/compiler/rustc_symbol_mangling/src/lib.rs b/compiler/rustc_symbol_mangling/src/lib.rs index dea4eb08c7615..0c97cda81c8af 100644 --- a/compiler/rustc_symbol_mangling/src/lib.rs +++ b/compiler/rustc_symbol_mangling/src/lib.rs @@ -93,6 +93,7 @@ #![doc(rust_logo)] #![feature(let_chains)] #![feature(rustdoc_internals)] +#![warn(unreachable_pub)] // tidy-alphabetical-end use rustc_hir::def::DefKind; From 0fb3a509cf437610b4329003de5bc1552aa7e540 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 30 Aug 2024 14:22:46 +1000 Subject: [PATCH 0406/2194] Add `warn(unreachable_pub)` to `rustc_target`. --- compiler/rustc_target/src/abi/call/aarch64.rs | 4 +-- compiler/rustc_target/src/abi/call/amdgpu.rs | 2 +- compiler/rustc_target/src/abi/call/arm.rs | 2 +- compiler/rustc_target/src/abi/call/avr.rs | 2 +- compiler/rustc_target/src/abi/call/bpf.rs | 2 +- compiler/rustc_target/src/abi/call/csky.rs | 2 +- compiler/rustc_target/src/abi/call/hexagon.rs | 2 +- .../rustc_target/src/abi/call/loongarch.rs | 2 +- compiler/rustc_target/src/abi/call/m68k.rs | 2 +- compiler/rustc_target/src/abi/call/mips.rs | 2 +- compiler/rustc_target/src/abi/call/mips64.rs | 2 +- compiler/rustc_target/src/abi/call/msp430.rs | 2 +- compiler/rustc_target/src/abi/call/nvptx64.rs | 4 +-- compiler/rustc_target/src/abi/call/powerpc.rs | 2 +- .../rustc_target/src/abi/call/powerpc64.rs | 2 +- compiler/rustc_target/src/abi/call/riscv.rs | 2 +- compiler/rustc_target/src/abi/call/s390x.rs | 2 +- compiler/rustc_target/src/abi/call/sparc.rs | 2 +- compiler/rustc_target/src/abi/call/sparc64.rs | 4 +-- compiler/rustc_target/src/abi/call/wasm.rs | 4 +-- compiler/rustc_target/src/abi/call/x86.rs | 4 +-- compiler/rustc_target/src/abi/call/x86_64.rs | 2 +- .../rustc_target/src/abi/call/x86_win64.rs | 2 +- compiler/rustc_target/src/abi/call/xtensa.rs | 2 +- compiler/rustc_target/src/asm/aarch64.rs | 2 +- compiler/rustc_target/src/lib.rs | 1 + compiler/rustc_target/src/spec/base/aix.rs | 2 +- .../rustc_target/src/spec/base/android.rs | 2 +- .../rustc_target/src/spec/base/apple/mod.rs | 30 +++++++++---------- .../rustc_target/src/spec/base/avr_gnu.rs | 2 +- compiler/rustc_target/src/spec/base/bpf.rs | 2 +- .../rustc_target/src/spec/base/dragonfly.rs | 2 +- .../rustc_target/src/spec/base/freebsd.rs | 2 +- .../rustc_target/src/spec/base/fuchsia.rs | 2 +- compiler/rustc_target/src/spec/base/haiku.rs | 2 +- compiler/rustc_target/src/spec/base/hermit.rs | 2 +- compiler/rustc_target/src/spec/base/hurd.rs | 2 +- .../rustc_target/src/spec/base/hurd_gnu.rs | 2 +- .../rustc_target/src/spec/base/illumos.rs | 2 +- compiler/rustc_target/src/spec/base/l4re.rs | 2 +- compiler/rustc_target/src/spec/base/linux.rs | 2 +- .../rustc_target/src/spec/base/linux_gnu.rs | 2 +- .../rustc_target/src/spec/base/linux_musl.rs | 2 +- .../rustc_target/src/spec/base/linux_ohos.rs | 2 +- .../src/spec/base/linux_uclibc.rs | 2 +- compiler/rustc_target/src/spec/base/msvc.rs | 2 +- compiler/rustc_target/src/spec/base/netbsd.rs | 2 +- .../rustc_target/src/spec/base/nto_qnx.rs | 2 +- .../rustc_target/src/spec/base/openbsd.rs | 2 +- compiler/rustc_target/src/spec/base/redox.rs | 2 +- .../rustc_target/src/spec/base/solaris.rs | 2 +- compiler/rustc_target/src/spec/base/solid.rs | 2 +- compiler/rustc_target/src/spec/base/teeos.rs | 2 +- compiler/rustc_target/src/spec/base/thumb.rs | 2 +- .../rustc_target/src/spec/base/uefi_msvc.rs | 2 +- .../src/spec/base/unikraft_linux_musl.rs | 2 +- .../rustc_target/src/spec/base/vxworks.rs | 2 +- compiler/rustc_target/src/spec/base/wasm.rs | 2 +- .../rustc_target/src/spec/base/windows_gnu.rs | 2 +- .../src/spec/base/windows_gnullvm.rs | 2 +- .../src/spec/base/windows_msvc.rs | 2 +- .../src/spec/base/windows_uwp_gnu.rs | 2 +- .../src/spec/base/windows_uwp_msvc.rs | 2 +- compiler/rustc_target/src/spec/base/xtensa.rs | 2 +- .../src/spec/targets/aarch64_apple_darwin.rs | 2 +- .../src/spec/targets/aarch64_apple_ios.rs | 2 +- .../spec/targets/aarch64_apple_ios_macabi.rs | 2 +- .../src/spec/targets/aarch64_apple_ios_sim.rs | 2 +- .../src/spec/targets/aarch64_apple_tvos.rs | 2 +- .../spec/targets/aarch64_apple_tvos_sim.rs | 2 +- .../spec/targets/aarch64_apple_visionos.rs | 2 +- .../targets/aarch64_apple_visionos_sim.rs | 2 +- .../src/spec/targets/aarch64_apple_watchos.rs | 2 +- .../spec/targets/aarch64_apple_watchos_sim.rs | 2 +- .../targets/aarch64_be_unknown_linux_gnu.rs | 2 +- .../aarch64_be_unknown_linux_gnu_ilp32.rs | 2 +- .../spec/targets/aarch64_be_unknown_netbsd.rs | 2 +- .../src/spec/targets/aarch64_fuchsia.rs | 2 +- .../spec/targets/aarch64_kmc_solid_asp3.rs | 2 +- .../src/spec/targets/aarch64_linux_android.rs | 2 +- .../aarch64_nintendo_switch_freestanding.rs | 2 +- .../targets/aarch64_pc_windows_gnullvm.rs | 2 +- .../spec/targets/aarch64_pc_windows_msvc.rs | 2 +- .../spec/targets/aarch64_unknown_freebsd.rs | 2 +- .../spec/targets/aarch64_unknown_fuchsia.rs | 2 +- .../spec/targets/aarch64_unknown_hermit.rs | 2 +- .../spec/targets/aarch64_unknown_illumos.rs | 2 +- .../spec/targets/aarch64_unknown_linux_gnu.rs | 2 +- .../aarch64_unknown_linux_gnu_ilp32.rs | 2 +- .../targets/aarch64_unknown_linux_musl.rs | 2 +- .../targets/aarch64_unknown_linux_ohos.rs | 2 +- .../spec/targets/aarch64_unknown_netbsd.rs | 2 +- .../src/spec/targets/aarch64_unknown_none.rs | 2 +- .../targets/aarch64_unknown_none_softfloat.rs | 2 +- .../targets/aarch64_unknown_nto_qnx700.rs | 2 +- .../targets/aarch64_unknown_nto_qnx710.rs | 2 +- .../spec/targets/aarch64_unknown_openbsd.rs | 2 +- .../src/spec/targets/aarch64_unknown_redox.rs | 2 +- .../src/spec/targets/aarch64_unknown_teeos.rs | 2 +- .../spec/targets/aarch64_unknown_trusty.rs | 2 +- .../src/spec/targets/aarch64_unknown_uefi.rs | 2 +- .../spec/targets/aarch64_uwp_windows_msvc.rs | 2 +- .../src/spec/targets/aarch64_wrs_vxworks.rs | 2 +- .../spec/targets/arm64_32_apple_watchos.rs | 2 +- .../src/spec/targets/arm64e_apple_darwin.rs | 2 +- .../src/spec/targets/arm64e_apple_ios.rs | 2 +- .../spec/targets/arm64ec_pc_windows_msvc.rs | 2 +- .../src/spec/targets/arm_linux_androideabi.rs | 2 +- .../spec/targets/arm_unknown_linux_gnueabi.rs | 2 +- .../targets/arm_unknown_linux_gnueabihf.rs | 2 +- .../targets/arm_unknown_linux_musleabi.rs | 2 +- .../targets/arm_unknown_linux_musleabihf.rs | 2 +- .../targets/armeb_unknown_linux_gnueabi.rs | 2 +- .../src/spec/targets/armebv7r_none_eabi.rs | 2 +- .../src/spec/targets/armebv7r_none_eabihf.rs | 2 +- .../src/spec/targets/armv4t_none_eabi.rs | 2 +- .../targets/armv4t_unknown_linux_gnueabi.rs | 2 +- .../src/spec/targets/armv5te_none_eabi.rs | 2 +- .../targets/armv5te_unknown_linux_gnueabi.rs | 2 +- .../targets/armv5te_unknown_linux_musleabi.rs | 2 +- .../armv5te_unknown_linux_uclibceabi.rs | 2 +- .../src/spec/targets/armv6_unknown_freebsd.rs | 2 +- .../targets/armv6_unknown_netbsd_eabihf.rs | 2 +- .../src/spec/targets/armv6k_nintendo_3ds.rs | 2 +- .../spec/targets/armv7_linux_androideabi.rs | 2 +- .../targets/armv7_sony_vita_newlibeabihf.rs | 2 +- .../src/spec/targets/armv7_unknown_freebsd.rs | 2 +- .../targets/armv7_unknown_linux_gnueabi.rs | 2 +- .../targets/armv7_unknown_linux_gnueabihf.rs | 2 +- .../targets/armv7_unknown_linux_musleabi.rs | 2 +- .../targets/armv7_unknown_linux_musleabihf.rs | 2 +- .../spec/targets/armv7_unknown_linux_ohos.rs | 2 +- .../targets/armv7_unknown_linux_uclibceabi.rs | 2 +- .../armv7_unknown_linux_uclibceabihf.rs | 2 +- .../targets/armv7_unknown_netbsd_eabihf.rs | 2 +- .../src/spec/targets/armv7_unknown_trusty.rs | 2 +- .../spec/targets/armv7_wrs_vxworks_eabihf.rs | 2 +- .../targets/armv7a_kmc_solid_asp3_eabi.rs | 2 +- .../targets/armv7a_kmc_solid_asp3_eabihf.rs | 2 +- .../src/spec/targets/armv7a_none_eabi.rs | 2 +- .../src/spec/targets/armv7a_none_eabihf.rs | 2 +- .../src/spec/targets/armv7k_apple_watchos.rs | 2 +- .../src/spec/targets/armv7r_none_eabi.rs | 2 +- .../src/spec/targets/armv7r_none_eabihf.rs | 2 +- .../src/spec/targets/armv7s_apple_ios.rs | 2 +- .../src/spec/targets/armv8r_none_eabihf.rs | 2 +- .../spec/targets/avr_unknown_gnu_atmega328.rs | 2 +- .../src/spec/targets/bpfeb_unknown_none.rs | 2 +- .../src/spec/targets/bpfel_unknown_none.rs | 2 +- .../targets/csky_unknown_linux_gnuabiv2.rs | 2 +- .../targets/csky_unknown_linux_gnuabiv2hf.rs | 2 +- .../targets/hexagon_unknown_linux_musl.rs | 2 +- .../spec/targets/hexagon_unknown_none_elf.rs | 2 +- .../src/spec/targets/i386_apple_ios.rs | 2 +- .../src/spec/targets/i586_pc_nto_qnx700.rs | 2 +- .../src/spec/targets/i586_pc_windows_msvc.rs | 2 +- .../spec/targets/i586_unknown_linux_gnu.rs | 2 +- .../spec/targets/i586_unknown_linux_musl.rs | 2 +- .../src/spec/targets/i586_unknown_netbsd.rs | 2 +- .../src/spec/targets/i686_apple_darwin.rs | 2 +- .../src/spec/targets/i686_linux_android.rs | 2 +- .../src/spec/targets/i686_pc_windows_gnu.rs | 2 +- .../spec/targets/i686_pc_windows_gnullvm.rs | 2 +- .../src/spec/targets/i686_pc_windows_msvc.rs | 2 +- .../src/spec/targets/i686_unknown_freebsd.rs | 2 +- .../src/spec/targets/i686_unknown_haiku.rs | 2 +- .../src/spec/targets/i686_unknown_hurd_gnu.rs | 2 +- .../spec/targets/i686_unknown_linux_gnu.rs | 2 +- .../spec/targets/i686_unknown_linux_musl.rs | 2 +- .../src/spec/targets/i686_unknown_netbsd.rs | 2 +- .../src/spec/targets/i686_unknown_openbsd.rs | 2 +- .../src/spec/targets/i686_unknown_redox.rs | 2 +- .../src/spec/targets/i686_unknown_uefi.rs | 2 +- .../src/spec/targets/i686_uwp_windows_gnu.rs | 2 +- .../src/spec/targets/i686_uwp_windows_msvc.rs | 2 +- .../spec/targets/i686_win7_windows_msvc.rs | 2 +- .../src/spec/targets/i686_wrs_vxworks.rs | 2 +- .../targets/loongarch64_unknown_linux_gnu.rs | 2 +- .../targets/loongarch64_unknown_linux_musl.rs | 2 +- .../spec/targets/loongarch64_unknown_none.rs | 2 +- .../loongarch64_unknown_none_softfloat.rs | 2 +- .../spec/targets/m68k_unknown_linux_gnu.rs | 2 +- .../spec/targets/mips64_openwrt_linux_musl.rs | 2 +- .../targets/mips64_unknown_linux_gnuabi64.rs | 2 +- .../targets/mips64_unknown_linux_muslabi64.rs | 2 +- .../mips64el_unknown_linux_gnuabi64.rs | 2 +- .../mips64el_unknown_linux_muslabi64.rs | 2 +- .../spec/targets/mips_unknown_linux_gnu.rs | 2 +- .../spec/targets/mips_unknown_linux_musl.rs | 2 +- .../spec/targets/mips_unknown_linux_uclibc.rs | 2 +- .../src/spec/targets/mipsel_sony_psp.rs | 2 +- .../src/spec/targets/mipsel_sony_psx.rs | 2 +- .../spec/targets/mipsel_unknown_linux_gnu.rs | 2 +- .../spec/targets/mipsel_unknown_linux_musl.rs | 2 +- .../targets/mipsel_unknown_linux_uclibc.rs | 2 +- .../src/spec/targets/mipsel_unknown_netbsd.rs | 2 +- .../src/spec/targets/mipsel_unknown_none.rs | 2 +- .../targets/mipsisa32r6_unknown_linux_gnu.rs | 2 +- .../mipsisa32r6el_unknown_linux_gnu.rs | 2 +- .../mipsisa64r6_unknown_linux_gnuabi64.rs | 2 +- .../mipsisa64r6el_unknown_linux_gnuabi64.rs | 2 +- .../src/spec/targets/msp430_none_elf.rs | 2 +- .../src/spec/targets/nvptx64_nvidia_cuda.rs | 2 +- .../src/spec/targets/powerpc64_ibm_aix.rs | 2 +- .../spec/targets/powerpc64_unknown_freebsd.rs | 2 +- .../targets/powerpc64_unknown_linux_gnu.rs | 2 +- .../targets/powerpc64_unknown_linux_musl.rs | 2 +- .../spec/targets/powerpc64_unknown_openbsd.rs | 2 +- .../src/spec/targets/powerpc64_wrs_vxworks.rs | 2 +- .../targets/powerpc64le_unknown_freebsd.rs | 2 +- .../targets/powerpc64le_unknown_linux_gnu.rs | 2 +- .../targets/powerpc64le_unknown_linux_musl.rs | 2 +- .../spec/targets/powerpc_unknown_freebsd.rs | 2 +- .../spec/targets/powerpc_unknown_linux_gnu.rs | 2 +- .../targets/powerpc_unknown_linux_gnuspe.rs | 2 +- .../targets/powerpc_unknown_linux_musl.rs | 2 +- .../targets/powerpc_unknown_linux_muslspe.rs | 2 +- .../spec/targets/powerpc_unknown_netbsd.rs | 2 +- .../spec/targets/powerpc_unknown_openbsd.rs | 2 +- .../src/spec/targets/powerpc_wrs_vxworks.rs | 2 +- .../spec/targets/powerpc_wrs_vxworks_spe.rs | 2 +- .../targets/riscv32gc_unknown_linux_gnu.rs | 2 +- .../targets/riscv32gc_unknown_linux_musl.rs | 2 +- .../spec/targets/riscv32i_unknown_none_elf.rs | 2 +- .../spec/targets/riscv32im_risc0_zkvm_elf.rs | 2 +- .../targets/riscv32im_unknown_none_elf.rs | 2 +- .../targets/riscv32ima_unknown_none_elf.rs | 2 +- .../spec/targets/riscv32imac_esp_espidf.rs | 2 +- .../targets/riscv32imac_unknown_none_elf.rs | 2 +- .../targets/riscv32imac_unknown_nuttx_elf.rs | 2 +- .../targets/riscv32imac_unknown_xous_elf.rs | 2 +- .../spec/targets/riscv32imafc_esp_espidf.rs | 2 +- .../targets/riscv32imafc_unknown_none_elf.rs | 2 +- .../targets/riscv32imafc_unknown_nuttx_elf.rs | 2 +- .../src/spec/targets/riscv32imc_esp_espidf.rs | 2 +- .../targets/riscv32imc_unknown_none_elf.rs | 2 +- .../targets/riscv32imc_unknown_nuttx_elf.rs | 2 +- .../src/spec/targets/riscv64_linux_android.rs | 2 +- .../spec/targets/riscv64gc_unknown_freebsd.rs | 2 +- .../spec/targets/riscv64gc_unknown_fuchsia.rs | 2 +- .../spec/targets/riscv64gc_unknown_hermit.rs | 2 +- .../targets/riscv64gc_unknown_linux_gnu.rs | 2 +- .../targets/riscv64gc_unknown_linux_musl.rs | 2 +- .../spec/targets/riscv64gc_unknown_netbsd.rs | 2 +- .../targets/riscv64gc_unknown_none_elf.rs | 2 +- .../targets/riscv64gc_unknown_nuttx_elf.rs | 2 +- .../spec/targets/riscv64gc_unknown_openbsd.rs | 2 +- .../targets/riscv64imac_unknown_none_elf.rs | 2 +- .../targets/riscv64imac_unknown_nuttx_elf.rs | 2 +- .../spec/targets/s390x_unknown_linux_gnu.rs | 2 +- .../spec/targets/s390x_unknown_linux_musl.rs | 2 +- .../spec/targets/sparc64_unknown_linux_gnu.rs | 2 +- .../spec/targets/sparc64_unknown_netbsd.rs | 2 +- .../spec/targets/sparc64_unknown_openbsd.rs | 2 +- .../spec/targets/sparc_unknown_linux_gnu.rs | 2 +- .../spec/targets/sparc_unknown_none_elf.rs | 2 +- .../src/spec/targets/sparcv9_sun_solaris.rs | 2 +- .../src/spec/targets/thumbv4t_none_eabi.rs | 2 +- .../src/spec/targets/thumbv5te_none_eabi.rs | 2 +- .../src/spec/targets/thumbv6m_none_eabi.rs | 2 +- .../src/spec/targets/thumbv6m_nuttx_eabi.rs | 2 +- .../spec/targets/thumbv7a_pc_windows_msvc.rs | 2 +- .../spec/targets/thumbv7a_uwp_windows_msvc.rs | 2 +- .../src/spec/targets/thumbv7em_none_eabi.rs | 2 +- .../src/spec/targets/thumbv7em_none_eabihf.rs | 2 +- .../src/spec/targets/thumbv7em_nuttx_eabi.rs | 2 +- .../spec/targets/thumbv7em_nuttx_eabihf.rs | 2 +- .../src/spec/targets/thumbv7m_none_eabi.rs | 2 +- .../src/spec/targets/thumbv7m_nuttx_eabi.rs | 2 +- .../targets/thumbv7neon_linux_androideabi.rs | 2 +- .../thumbv7neon_unknown_linux_gnueabihf.rs | 2 +- .../thumbv7neon_unknown_linux_musleabihf.rs | 2 +- .../spec/targets/thumbv8m_base_none_eabi.rs | 2 +- .../spec/targets/thumbv8m_base_nuttx_eabi.rs | 2 +- .../spec/targets/thumbv8m_main_none_eabi.rs | 2 +- .../spec/targets/thumbv8m_main_none_eabihf.rs | 2 +- .../spec/targets/thumbv8m_main_nuttx_eabi.rs | 2 +- .../targets/thumbv8m_main_nuttx_eabihf.rs | 2 +- .../spec/targets/wasm32_unknown_emscripten.rs | 2 +- .../spec/targets/wasm32_unknown_unknown.rs | 2 +- .../src/spec/targets/wasm32_wasi.rs | 2 +- .../src/spec/targets/wasm32_wasip1.rs | 2 +- .../src/spec/targets/wasm32_wasip1_threads.rs | 2 +- .../src/spec/targets/wasm32_wasip2.rs | 2 +- .../spec/targets/wasm64_unknown_unknown.rs | 2 +- .../src/spec/targets/x86_64_apple_darwin.rs | 2 +- .../src/spec/targets/x86_64_apple_ios.rs | 2 +- .../spec/targets/x86_64_apple_ios_macabi.rs | 2 +- .../src/spec/targets/x86_64_apple_tvos.rs | 2 +- .../spec/targets/x86_64_apple_watchos_sim.rs | 2 +- .../targets/x86_64_fortanix_unknown_sgx.rs | 2 +- .../src/spec/targets/x86_64_fuchsia.rs | 2 +- .../src/spec/targets/x86_64_linux_android.rs | 2 +- .../src/spec/targets/x86_64_pc_nto_qnx710.rs | 2 +- .../src/spec/targets/x86_64_pc_solaris.rs | 2 +- .../src/spec/targets/x86_64_pc_windows_gnu.rs | 2 +- .../spec/targets/x86_64_pc_windows_gnullvm.rs | 2 +- .../spec/targets/x86_64_pc_windows_msvc.rs | 2 +- .../targets/x86_64_unikraft_linux_musl.rs | 2 +- .../spec/targets/x86_64_unknown_dragonfly.rs | 2 +- .../spec/targets/x86_64_unknown_freebsd.rs | 2 +- .../spec/targets/x86_64_unknown_fuchsia.rs | 2 +- .../src/spec/targets/x86_64_unknown_haiku.rs | 2 +- .../src/spec/targets/x86_64_unknown_hermit.rs | 2 +- .../spec/targets/x86_64_unknown_illumos.rs | 2 +- .../targets/x86_64_unknown_l4re_uclibc.rs | 2 +- .../spec/targets/x86_64_unknown_linux_gnu.rs | 2 +- .../targets/x86_64_unknown_linux_gnux32.rs | 2 +- .../spec/targets/x86_64_unknown_linux_musl.rs | 2 +- .../spec/targets/x86_64_unknown_linux_none.rs | 2 +- .../spec/targets/x86_64_unknown_linux_ohos.rs | 2 +- .../src/spec/targets/x86_64_unknown_netbsd.rs | 2 +- .../src/spec/targets/x86_64_unknown_none.rs | 2 +- .../spec/targets/x86_64_unknown_openbsd.rs | 2 +- .../src/spec/targets/x86_64_unknown_redox.rs | 2 +- .../src/spec/targets/x86_64_unknown_uefi.rs | 2 +- .../spec/targets/x86_64_uwp_windows_gnu.rs | 2 +- .../spec/targets/x86_64_uwp_windows_msvc.rs | 2 +- .../spec/targets/x86_64_win7_windows_msvc.rs | 2 +- .../src/spec/targets/x86_64_wrs_vxworks.rs | 2 +- .../src/spec/targets/x86_64h_apple_darwin.rs | 2 +- .../src/spec/targets/xtensa_esp32_espidf.rs | 2 +- .../src/spec/targets/xtensa_esp32_none_elf.rs | 2 +- .../src/spec/targets/xtensa_esp32s2_espidf.rs | 2 +- .../spec/targets/xtensa_esp32s2_none_elf.rs | 2 +- .../src/spec/targets/xtensa_esp32s3_espidf.rs | 2 +- .../spec/targets/xtensa_esp32s3_none_elf.rs | 2 +- 327 files changed, 346 insertions(+), 345 deletions(-) diff --git a/compiler/rustc_target/src/abi/call/aarch64.rs b/compiler/rustc_target/src/abi/call/aarch64.rs index 04020d13f22f9..55b65fb1caaaf 100644 --- a/compiler/rustc_target/src/abi/call/aarch64.rs +++ b/compiler/rustc_target/src/abi/call/aarch64.rs @@ -6,7 +6,7 @@ use crate::abi::{HasDataLayout, TyAbiInterface}; /// /// Corresponds to Clang's `AArch64ABIInfo::ABIKind`. #[derive(Copy, Clone, PartialEq)] -pub enum AbiKind { +pub(crate) enum AbiKind { AAPCS, DarwinPCS, Win64, @@ -109,7 +109,7 @@ where arg.make_indirect(); } -pub fn compute_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>, kind: AbiKind) +pub(crate) fn compute_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>, kind: AbiKind) where Ty: TyAbiInterface<'a, C> + Copy, C: HasDataLayout, diff --git a/compiler/rustc_target/src/abi/call/amdgpu.rs b/compiler/rustc_target/src/abi/call/amdgpu.rs index e30dead63cbf8..3007a729a8b8a 100644 --- a/compiler/rustc_target/src/abi/call/amdgpu.rs +++ b/compiler/rustc_target/src/abi/call/amdgpu.rs @@ -17,7 +17,7 @@ where arg.extend_integer_width_to(32); } -pub fn compute_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>) +pub(crate) fn compute_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>) where Ty: TyAbiInterface<'a, C> + Copy, C: HasDataLayout, diff --git a/compiler/rustc_target/src/abi/call/arm.rs b/compiler/rustc_target/src/abi/call/arm.rs index 9371e1b395865..bd6f781fb8120 100644 --- a/compiler/rustc_target/src/abi/call/arm.rs +++ b/compiler/rustc_target/src/abi/call/arm.rs @@ -81,7 +81,7 @@ where arg.cast_to(Uniform::consecutive(if align <= 4 { Reg::i32() } else { Reg::i64() }, total)); } -pub fn compute_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>) +pub(crate) fn compute_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>) where Ty: TyAbiInterface<'a, C> + Copy, C: HasDataLayout + HasTargetSpec, diff --git a/compiler/rustc_target/src/abi/call/avr.rs b/compiler/rustc_target/src/abi/call/avr.rs index b01dac8c70d7e..dfc991e09543a 100644 --- a/compiler/rustc_target/src/abi/call/avr.rs +++ b/compiler/rustc_target/src/abi/call/avr.rs @@ -44,7 +44,7 @@ fn classify_arg_ty(arg: &mut ArgAbi<'_, Ty>) { } } -pub fn compute_abi_info(fty: &mut FnAbi<'_, Ty>) { +pub(crate) fn compute_abi_info(fty: &mut FnAbi<'_, Ty>) { if !fty.ret.is_ignore() { classify_ret_ty(&mut fty.ret); } diff --git a/compiler/rustc_target/src/abi/call/bpf.rs b/compiler/rustc_target/src/abi/call/bpf.rs index 780e7df438373..f19772ac70918 100644 --- a/compiler/rustc_target/src/abi/call/bpf.rs +++ b/compiler/rustc_target/src/abi/call/bpf.rs @@ -17,7 +17,7 @@ fn classify_arg(arg: &mut ArgAbi<'_, Ty>) { } } -pub fn compute_abi_info(fn_abi: &mut FnAbi<'_, Ty>) { +pub(crate) fn compute_abi_info(fn_abi: &mut FnAbi<'_, Ty>) { if !fn_abi.ret.is_ignore() { classify_ret(&mut fn_abi.ret); } diff --git a/compiler/rustc_target/src/abi/call/csky.rs b/compiler/rustc_target/src/abi/call/csky.rs index 7951f28beeaff..b1c1ae814a7ed 100644 --- a/compiler/rustc_target/src/abi/call/csky.rs +++ b/compiler/rustc_target/src/abi/call/csky.rs @@ -47,7 +47,7 @@ fn classify_arg(arg: &mut ArgAbi<'_, Ty>) { } } -pub fn compute_abi_info(fn_abi: &mut FnAbi<'_, Ty>) { +pub(crate) fn compute_abi_info(fn_abi: &mut FnAbi<'_, Ty>) { if !fn_abi.ret.is_ignore() { classify_ret(&mut fn_abi.ret); } diff --git a/compiler/rustc_target/src/abi/call/hexagon.rs b/compiler/rustc_target/src/abi/call/hexagon.rs index 80a442048d53c..0a0688880c019 100644 --- a/compiler/rustc_target/src/abi/call/hexagon.rs +++ b/compiler/rustc_target/src/abi/call/hexagon.rs @@ -16,7 +16,7 @@ fn classify_arg(arg: &mut ArgAbi<'_, Ty>) { } } -pub fn compute_abi_info(fn_abi: &mut FnAbi<'_, Ty>) { +pub(crate) fn compute_abi_info(fn_abi: &mut FnAbi<'_, Ty>) { if !fn_abi.ret.is_ignore() { classify_ret(&mut fn_abi.ret); } diff --git a/compiler/rustc_target/src/abi/call/loongarch.rs b/compiler/rustc_target/src/abi/call/loongarch.rs index 893818af77c30..4a21935623b92 100644 --- a/compiler/rustc_target/src/abi/call/loongarch.rs +++ b/compiler/rustc_target/src/abi/call/loongarch.rs @@ -325,7 +325,7 @@ fn extend_integer_width(arg: &mut ArgAbi<'_, Ty>, xlen: u64) { arg.extend_integer_width_to(xlen); } -pub fn compute_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>) +pub(crate) fn compute_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>) where Ty: TyAbiInterface<'a, C> + Copy, C: HasDataLayout + HasTargetSpec, diff --git a/compiler/rustc_target/src/abi/call/m68k.rs b/compiler/rustc_target/src/abi/call/m68k.rs index 06697bdd83ee7..b6bd68b66fcc4 100644 --- a/compiler/rustc_target/src/abi/call/m68k.rs +++ b/compiler/rustc_target/src/abi/call/m68k.rs @@ -20,7 +20,7 @@ fn classify_arg(arg: &mut ArgAbi<'_, Ty>) { } } -pub fn compute_abi_info(fn_abi: &mut FnAbi<'_, Ty>) { +pub(crate) fn compute_abi_info(fn_abi: &mut FnAbi<'_, Ty>) { if !fn_abi.ret.is_ignore() { classify_ret(&mut fn_abi.ret); } diff --git a/compiler/rustc_target/src/abi/call/mips.rs b/compiler/rustc_target/src/abi/call/mips.rs index 0e5a7f37a094c..37980a91c7601 100644 --- a/compiler/rustc_target/src/abi/call/mips.rs +++ b/compiler/rustc_target/src/abi/call/mips.rs @@ -35,7 +35,7 @@ where *offset = offset.align_to(align) + size.align_to(align); } -pub fn compute_abi_info(cx: &C, fn_abi: &mut FnAbi<'_, Ty>) +pub(crate) fn compute_abi_info(cx: &C, fn_abi: &mut FnAbi<'_, Ty>) where C: HasDataLayout, { diff --git a/compiler/rustc_target/src/abi/call/mips64.rs b/compiler/rustc_target/src/abi/call/mips64.rs index 5b52ebbdedd1a..2c3258c8d42d4 100644 --- a/compiler/rustc_target/src/abi/call/mips64.rs +++ b/compiler/rustc_target/src/abi/call/mips64.rs @@ -149,7 +149,7 @@ where }); } -pub fn compute_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>) +pub(crate) fn compute_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>) where Ty: TyAbiInterface<'a, C> + Copy, C: HasDataLayout, diff --git a/compiler/rustc_target/src/abi/call/msp430.rs b/compiler/rustc_target/src/abi/call/msp430.rs index 33ef47be00993..4f613aa6c1549 100644 --- a/compiler/rustc_target/src/abi/call/msp430.rs +++ b/compiler/rustc_target/src/abi/call/msp430.rs @@ -25,7 +25,7 @@ fn classify_arg(arg: &mut ArgAbi<'_, Ty>) { } } -pub fn compute_abi_info(fn_abi: &mut FnAbi<'_, Ty>) { +pub(crate) fn compute_abi_info(fn_abi: &mut FnAbi<'_, Ty>) { if !fn_abi.ret.is_ignore() { classify_ret(&mut fn_abi.ret); } diff --git a/compiler/rustc_target/src/abi/call/nvptx64.rs b/compiler/rustc_target/src/abi/call/nvptx64.rs index 27d197af7925b..2e8b16d3a938e 100644 --- a/compiler/rustc_target/src/abi/call/nvptx64.rs +++ b/compiler/rustc_target/src/abi/call/nvptx64.rs @@ -71,7 +71,7 @@ where } } -pub fn compute_abi_info(fn_abi: &mut FnAbi<'_, Ty>) { +pub(crate) fn compute_abi_info(fn_abi: &mut FnAbi<'_, Ty>) { if !fn_abi.ret.is_ignore() { classify_ret(&mut fn_abi.ret); } @@ -84,7 +84,7 @@ pub fn compute_abi_info(fn_abi: &mut FnAbi<'_, Ty>) { } } -pub fn compute_ptx_kernel_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>) +pub(crate) fn compute_ptx_kernel_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>) where Ty: TyAbiInterface<'a, C> + Copy, C: HasDataLayout, diff --git a/compiler/rustc_target/src/abi/call/powerpc.rs b/compiler/rustc_target/src/abi/call/powerpc.rs index 8f67f57cd2b3e..f3b05c4817301 100644 --- a/compiler/rustc_target/src/abi/call/powerpc.rs +++ b/compiler/rustc_target/src/abi/call/powerpc.rs @@ -27,7 +27,7 @@ fn classify_arg(cx: &impl HasTargetSpec, arg: &mut ArgAbi<'_, Ty>) { } } -pub fn compute_abi_info(cx: &impl HasTargetSpec, fn_abi: &mut FnAbi<'_, Ty>) { +pub(crate) fn compute_abi_info(cx: &impl HasTargetSpec, fn_abi: &mut FnAbi<'_, Ty>) { if !fn_abi.ret.is_ignore() { classify_ret(&mut fn_abi.ret); } diff --git a/compiler/rustc_target/src/abi/call/powerpc64.rs b/compiler/rustc_target/src/abi/call/powerpc64.rs index 749eea0ef6350..b9767bf906bd0 100644 --- a/compiler/rustc_target/src/abi/call/powerpc64.rs +++ b/compiler/rustc_target/src/abi/call/powerpc64.rs @@ -86,7 +86,7 @@ where }; } -pub fn compute_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>) +pub(crate) fn compute_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>) where Ty: TyAbiInterface<'a, C> + Copy, C: HasDataLayout + HasTargetSpec, diff --git a/compiler/rustc_target/src/abi/call/riscv.rs b/compiler/rustc_target/src/abi/call/riscv.rs index 84f13f8cc5da9..be6bc701b497e 100644 --- a/compiler/rustc_target/src/abi/call/riscv.rs +++ b/compiler/rustc_target/src/abi/call/riscv.rs @@ -331,7 +331,7 @@ fn extend_integer_width(arg: &mut ArgAbi<'_, Ty>, xlen: u64) { arg.extend_integer_width_to(xlen); } -pub fn compute_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>) +pub(crate) fn compute_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>) where Ty: TyAbiInterface<'a, C> + Copy, C: HasDataLayout + HasTargetSpec, diff --git a/compiler/rustc_target/src/abi/call/s390x.rs b/compiler/rustc_target/src/abi/call/s390x.rs index 901ce139c7be1..502e733126777 100644 --- a/compiler/rustc_target/src/abi/call/s390x.rs +++ b/compiler/rustc_target/src/abi/call/s390x.rs @@ -54,7 +54,7 @@ where } } -pub fn compute_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>) +pub(crate) fn compute_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>) where Ty: TyAbiInterface<'a, C> + Copy, C: HasDataLayout + HasTargetSpec, diff --git a/compiler/rustc_target/src/abi/call/sparc.rs b/compiler/rustc_target/src/abi/call/sparc.rs index 0e5a7f37a094c..37980a91c7601 100644 --- a/compiler/rustc_target/src/abi/call/sparc.rs +++ b/compiler/rustc_target/src/abi/call/sparc.rs @@ -35,7 +35,7 @@ where *offset = offset.align_to(align) + size.align_to(align); } -pub fn compute_abi_info(cx: &C, fn_abi: &mut FnAbi<'_, Ty>) +pub(crate) fn compute_abi_info(cx: &C, fn_abi: &mut FnAbi<'_, Ty>) where C: HasDataLayout, { diff --git a/compiler/rustc_target/src/abi/call/sparc64.rs b/compiler/rustc_target/src/abi/call/sparc64.rs index 311691d8efb9b..2954d9642df95 100644 --- a/compiler/rustc_target/src/abi/call/sparc64.rs +++ b/compiler/rustc_target/src/abi/call/sparc64.rs @@ -7,7 +7,7 @@ use crate::abi::{self, HasDataLayout, Scalar, Size, TyAbiInterface, TyAndLayout} use crate::spec::HasTargetSpec; #[derive(Clone, Debug)] -pub struct Sdata { +struct Sdata { pub prefix: [Option; 8], pub prefix_index: usize, pub last_offset: Size, @@ -209,7 +209,7 @@ where arg.cast_to(Uniform::new(Reg::i64(), total)); } -pub fn compute_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>) +pub(crate) fn compute_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>) where Ty: TyAbiInterface<'a, C> + Copy, C: HasDataLayout + HasTargetSpec, diff --git a/compiler/rustc_target/src/abi/call/wasm.rs b/compiler/rustc_target/src/abi/call/wasm.rs index a773fb1e814e0..4ae8b9490ddab 100644 --- a/compiler/rustc_target/src/abi/call/wasm.rs +++ b/compiler/rustc_target/src/abi/call/wasm.rs @@ -45,7 +45,7 @@ where } /// The purpose of this ABI is to match the C ABI (aka clang) exactly. -pub fn compute_c_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>) +pub(crate) fn compute_c_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>) where Ty: TyAbiInterface<'a, C> + Copy, C: HasDataLayout, @@ -69,7 +69,7 @@ where /// This ABI is *bad*! It uses `PassMode::Direct` for `abi::Aggregate` types, which leaks LLVM /// implementation details into the ABI. It's just hard to fix because ABIs are hard to change. /// Also see . -pub fn compute_wasm_abi_info(fn_abi: &mut FnAbi<'_, Ty>) { +pub(crate) fn compute_wasm_abi_info(fn_abi: &mut FnAbi<'_, Ty>) { if !fn_abi.ret.is_ignore() { classify_ret_wasm_abi(&mut fn_abi.ret); } diff --git a/compiler/rustc_target/src/abi/call/x86.rs b/compiler/rustc_target/src/abi/call/x86.rs index e9aedc3d28a1e..bdb14350ded4b 100644 --- a/compiler/rustc_target/src/abi/call/x86.rs +++ b/compiler/rustc_target/src/abi/call/x86.rs @@ -3,12 +3,12 @@ use crate::abi::{Abi, Align, HasDataLayout, TyAbiInterface, TyAndLayout}; use crate::spec::HasTargetSpec; #[derive(PartialEq)] -pub enum Flavor { +pub(crate) enum Flavor { General, FastcallOrVectorcall, } -pub fn compute_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>, flavor: Flavor) +pub(crate) fn compute_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>, flavor: Flavor) where Ty: TyAbiInterface<'a, C> + Copy, C: HasDataLayout + HasTargetSpec, diff --git a/compiler/rustc_target/src/abi/call/x86_64.rs b/compiler/rustc_target/src/abi/call/x86_64.rs index fcd712489fa40..1209204debfa3 100644 --- a/compiler/rustc_target/src/abi/call/x86_64.rs +++ b/compiler/rustc_target/src/abi/call/x86_64.rs @@ -170,7 +170,7 @@ fn cast_target(cls: &[Option], size: Size) -> CastTarget { const MAX_INT_REGS: usize = 6; // RDI, RSI, RDX, RCX, R8, R9 const MAX_SSE_REGS: usize = 8; // XMM0-7 -pub fn compute_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>) +pub(crate) fn compute_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>) where Ty: TyAbiInterface<'a, C> + Copy, C: HasDataLayout, diff --git a/compiler/rustc_target/src/abi/call/x86_win64.rs b/compiler/rustc_target/src/abi/call/x86_win64.rs index 720707ef53f95..e5a20b248e43b 100644 --- a/compiler/rustc_target/src/abi/call/x86_win64.rs +++ b/compiler/rustc_target/src/abi/call/x86_win64.rs @@ -4,7 +4,7 @@ use crate::spec::HasTargetSpec; // Win64 ABI: https://docs.microsoft.com/en-us/cpp/build/parameter-passing -pub fn compute_abi_info(cx: &impl HasTargetSpec, fn_abi: &mut FnAbi<'_, Ty>) { +pub(crate) fn compute_abi_info(cx: &impl HasTargetSpec, fn_abi: &mut FnAbi<'_, Ty>) { let fixup = |a: &mut ArgAbi<'_, Ty>| { match a.layout.abi { Abi::Uninhabited | Abi::Aggregate { sized: false } => {} diff --git a/compiler/rustc_target/src/abi/call/xtensa.rs b/compiler/rustc_target/src/abi/call/xtensa.rs index addbe6989254c..a1c5e8230cc15 100644 --- a/compiler/rustc_target/src/abi/call/xtensa.rs +++ b/compiler/rustc_target/src/abi/call/xtensa.rs @@ -96,7 +96,7 @@ where } } -pub fn compute_abi_info<'a, Ty, C>(_cx: &C, fn_abi: &mut FnAbi<'a, Ty>) +pub(crate) fn compute_abi_info<'a, Ty, C>(_cx: &C, fn_abi: &mut FnAbi<'a, Ty>) where Ty: TyAbiInterface<'a, C> + Copy, C: HasDataLayout + HasTargetSpec, diff --git a/compiler/rustc_target/src/asm/aarch64.rs b/compiler/rustc_target/src/asm/aarch64.rs index daf5162e8ac10..74970a26b23bf 100644 --- a/compiler/rustc_target/src/asm/aarch64.rs +++ b/compiler/rustc_target/src/asm/aarch64.rs @@ -70,7 +70,7 @@ impl AArch64InlineAsmRegClass { } } -pub fn target_reserves_x18(target: &Target) -> bool { +pub(crate) fn target_reserves_x18(target: &Target) -> bool { target.os == "android" || target.os == "fuchsia" || target.is_like_osx || target.is_like_windows } diff --git a/compiler/rustc_target/src/lib.rs b/compiler/rustc_target/src/lib.rs index b2116c5121695..d7c66d6f5e3d6 100644 --- a/compiler/rustc_target/src/lib.rs +++ b/compiler/rustc_target/src/lib.rs @@ -17,6 +17,7 @@ #![feature(let_chains)] #![feature(rustc_attrs)] #![feature(rustdoc_internals)] +#![warn(unreachable_pub)] // tidy-alphabetical-end use std::path::{Path, PathBuf}; diff --git a/compiler/rustc_target/src/spec/base/aix.rs b/compiler/rustc_target/src/spec/base/aix.rs index c71c4ba2cc902..e7e9ec663c4c8 100644 --- a/compiler/rustc_target/src/spec/base/aix.rs +++ b/compiler/rustc_target/src/spec/base/aix.rs @@ -1,7 +1,7 @@ use crate::abi::Endian; use crate::spec::{crt_objects, cvs, Cc, CodeModel, LinkOutputKind, LinkerFlavor, TargetOptions}; -pub fn opts() -> TargetOptions { +pub(crate) fn opts() -> TargetOptions { TargetOptions { abi: "vec-extabi".into(), code_model: Some(CodeModel::Small), diff --git a/compiler/rustc_target/src/spec/base/android.rs b/compiler/rustc_target/src/spec/base/android.rs index 5320f1b4bbbea..dfa0e3fe9899a 100644 --- a/compiler/rustc_target/src/spec/base/android.rs +++ b/compiler/rustc_target/src/spec/base/android.rs @@ -1,6 +1,6 @@ use crate::spec::{base, SanitizerSet, TargetOptions, TlsModel}; -pub fn opts() -> TargetOptions { +pub(crate) fn opts() -> TargetOptions { let mut base = base::linux::opts(); base.os = "android".into(); base.is_like_android = true; diff --git a/compiler/rustc_target/src/spec/base/apple/mod.rs b/compiler/rustc_target/src/spec/base/apple/mod.rs index 39d7cf7d0971c..b752a34439537 100644 --- a/compiler/rustc_target/src/spec/base/apple/mod.rs +++ b/compiler/rustc_target/src/spec/base/apple/mod.rs @@ -12,7 +12,7 @@ mod tests; use Arch::*; #[allow(non_camel_case_types)] #[derive(Copy, Clone, PartialEq)] -pub enum Arch { +pub(crate) enum Arch { Armv7k, Armv7s, Arm64, @@ -25,7 +25,7 @@ pub enum Arch { } impl Arch { - pub fn target_name(self) -> &'static str { + fn target_name(self) -> &'static str { match self { Armv7k => "armv7k", Armv7s => "armv7s", @@ -39,7 +39,7 @@ impl Arch { } } - pub fn target_arch(self) -> Cow<'static, str> { + pub(crate) fn target_arch(self) -> Cow<'static, str> { Cow::Borrowed(match self { Armv7k | Armv7s => "arm", Arm64 | Arm64e | Arm64_32 => "aarch64", @@ -80,7 +80,7 @@ impl Arch { } #[derive(Copy, Clone, PartialEq)] -pub enum TargetAbi { +pub(crate) enum TargetAbi { Normal, Simulator, MacCatalyst, @@ -142,7 +142,7 @@ fn pre_link_args(os: &'static str, arch: Arch, abi: TargetAbi) -> LinkArgs { args } -pub fn opts(os: &'static str, arch: Arch, abi: TargetAbi) -> TargetOptions { +pub(crate) fn opts(os: &'static str, arch: Arch, abi: TargetAbi) -> TargetOptions { TargetOptions { abi: abi.target_abi().into(), os: os.into(), @@ -279,7 +279,7 @@ fn macos_deployment_target(arch: Arch) -> (u32, u32) { .unwrap_or_else(|| macos_default_deployment_target(arch)) } -pub fn macos_llvm_target(arch: Arch) -> String { +pub(crate) fn macos_llvm_target(arch: Arch) -> String { let (major, minor) = macos_deployment_target(arch); format!("{}-apple-macosx{}.{}.0", arch.target_name(), major, minor) } @@ -333,7 +333,7 @@ fn ios_deployment_target(arch: Arch, abi: &str) -> (u32, u32) { from_set_deployment_target("IPHONEOS_DEPLOYMENT_TARGET").unwrap_or((major, minor)) } -pub fn ios_llvm_target(arch: Arch) -> String { +pub(crate) fn ios_llvm_target(arch: Arch) -> String { // Modern iOS tooling extracts information about deployment target // from LC_BUILD_VERSION. This load command will only be emitted when // we build with a version specific `llvm_target`, with the version @@ -344,12 +344,12 @@ pub fn ios_llvm_target(arch: Arch) -> String { format!("{}-apple-ios{}.{}.0", arch.target_name(), major, minor) } -pub fn mac_catalyst_llvm_target(arch: Arch) -> String { +pub(crate) fn mac_catalyst_llvm_target(arch: Arch) -> String { let (major, minor) = ios_deployment_target(arch, "macabi"); format!("{}-apple-ios{}.{}.0-macabi", arch.target_name(), major, minor) } -pub fn ios_sim_llvm_target(arch: Arch) -> String { +pub(crate) fn ios_sim_llvm_target(arch: Arch) -> String { let (major, minor) = ios_deployment_target(arch, "sim"); format!("{}-apple-ios{}.{}.0-simulator", arch.target_name(), major, minor) } @@ -360,12 +360,12 @@ fn tvos_deployment_target() -> (u32, u32) { from_set_deployment_target("TVOS_DEPLOYMENT_TARGET").unwrap_or((10, 0)) } -pub fn tvos_llvm_target(arch: Arch) -> String { +pub(crate) fn tvos_llvm_target(arch: Arch) -> String { let (major, minor) = tvos_deployment_target(); format!("{}-apple-tvos{}.{}.0", arch.target_name(), major, minor) } -pub fn tvos_sim_llvm_target(arch: Arch) -> String { +pub(crate) fn tvos_sim_llvm_target(arch: Arch) -> String { let (major, minor) = tvos_deployment_target(); format!("{}-apple-tvos{}.{}.0-simulator", arch.target_name(), major, minor) } @@ -376,12 +376,12 @@ fn watchos_deployment_target() -> (u32, u32) { from_set_deployment_target("WATCHOS_DEPLOYMENT_TARGET").unwrap_or((5, 0)) } -pub fn watchos_llvm_target(arch: Arch) -> String { +pub(crate) fn watchos_llvm_target(arch: Arch) -> String { let (major, minor) = watchos_deployment_target(); format!("{}-apple-watchos{}.{}.0", arch.target_name(), major, minor) } -pub fn watchos_sim_llvm_target(arch: Arch) -> String { +pub(crate) fn watchos_sim_llvm_target(arch: Arch) -> String { let (major, minor) = watchos_deployment_target(); format!("{}-apple-watchos{}.{}.0-simulator", arch.target_name(), major, minor) } @@ -392,12 +392,12 @@ fn visionos_deployment_target() -> (u32, u32) { from_set_deployment_target("XROS_DEPLOYMENT_TARGET").unwrap_or((1, 0)) } -pub fn visionos_llvm_target(arch: Arch) -> String { +pub(crate) fn visionos_llvm_target(arch: Arch) -> String { let (major, minor) = visionos_deployment_target(); format!("{}-apple-visionos{}.{}.0", arch.target_name(), major, minor) } -pub fn visionos_sim_llvm_target(arch: Arch) -> String { +pub(crate) fn visionos_sim_llvm_target(arch: Arch) -> String { let (major, minor) = visionos_deployment_target(); format!("{}-apple-visionos{}.{}.0-simulator", arch.target_name(), major, minor) } diff --git a/compiler/rustc_target/src/spec/base/avr_gnu.rs b/compiler/rustc_target/src/spec/base/avr_gnu.rs index c3d0344ea6c13..dd9fc32b69e6c 100644 --- a/compiler/rustc_target/src/spec/base/avr_gnu.rs +++ b/compiler/rustc_target/src/spec/base/avr_gnu.rs @@ -6,7 +6,7 @@ use crate::spec::{Cc, LinkerFlavor, Lld, RelocModel, Target, TargetOptions}; /// /// Requires GNU avr-gcc and avr-binutils on the host system. /// FIXME: Remove the second parameter when const string concatenation is possible. -pub fn target(target_cpu: &'static str, mmcu: &'static str) -> Target { +pub(crate) fn target(target_cpu: &'static str, mmcu: &'static str) -> Target { Target { arch: "avr".into(), metadata: crate::spec::TargetMetadata { diff --git a/compiler/rustc_target/src/spec/base/bpf.rs b/compiler/rustc_target/src/spec/base/bpf.rs index 4d03747d0165f..17d5e75ef6d01 100644 --- a/compiler/rustc_target/src/spec/base/bpf.rs +++ b/compiler/rustc_target/src/spec/base/bpf.rs @@ -1,7 +1,7 @@ use crate::abi::Endian; use crate::spec::{LinkerFlavor, MergeFunctions, PanicStrategy, TargetOptions}; -pub fn opts(endian: Endian) -> TargetOptions { +pub(crate) fn opts(endian: Endian) -> TargetOptions { TargetOptions { allow_asm: true, endian, diff --git a/compiler/rustc_target/src/spec/base/dragonfly.rs b/compiler/rustc_target/src/spec/base/dragonfly.rs index 3c1846696f7a4..5da23f2b8fda1 100644 --- a/compiler/rustc_target/src/spec/base/dragonfly.rs +++ b/compiler/rustc_target/src/spec/base/dragonfly.rs @@ -1,6 +1,6 @@ use crate::spec::{cvs, RelroLevel, TargetOptions}; -pub fn opts() -> TargetOptions { +pub(crate) fn opts() -> TargetOptions { TargetOptions { os: "dragonfly".into(), dynamic_linking: true, diff --git a/compiler/rustc_target/src/spec/base/freebsd.rs b/compiler/rustc_target/src/spec/base/freebsd.rs index c772754aa8ddc..a016489e52dcd 100644 --- a/compiler/rustc_target/src/spec/base/freebsd.rs +++ b/compiler/rustc_target/src/spec/base/freebsd.rs @@ -1,6 +1,6 @@ use crate::spec::{cvs, RelroLevel, TargetOptions}; -pub fn opts() -> TargetOptions { +pub(crate) fn opts() -> TargetOptions { TargetOptions { os: "freebsd".into(), dynamic_linking: true, diff --git a/compiler/rustc_target/src/spec/base/fuchsia.rs b/compiler/rustc_target/src/spec/base/fuchsia.rs index d1ac22f3a098c..fc3d9f6fb9ff6 100644 --- a/compiler/rustc_target/src/spec/base/fuchsia.rs +++ b/compiler/rustc_target/src/spec/base/fuchsia.rs @@ -2,7 +2,7 @@ use crate::spec::{ crt_objects, cvs, Cc, FramePointer, LinkOutputKind, LinkerFlavor, Lld, TargetOptions, }; -pub fn opts() -> TargetOptions { +pub(crate) fn opts() -> TargetOptions { // This mirrors the linker options provided by clang. We presume lld for // now. When using clang as the linker it will supply these options for us, // so we only list them for ld/lld. diff --git a/compiler/rustc_target/src/spec/base/haiku.rs b/compiler/rustc_target/src/spec/base/haiku.rs index 8ab874410aa1c..d90e4c99f93e3 100644 --- a/compiler/rustc_target/src/spec/base/haiku.rs +++ b/compiler/rustc_target/src/spec/base/haiku.rs @@ -1,6 +1,6 @@ use crate::spec::{cvs, RelroLevel, TargetOptions}; -pub fn opts() -> TargetOptions { +pub(crate) fn opts() -> TargetOptions { TargetOptions { os: "haiku".into(), dynamic_linking: true, diff --git a/compiler/rustc_target/src/spec/base/hermit.rs b/compiler/rustc_target/src/spec/base/hermit.rs index c6e98fc1a115f..971abef80d9b1 100644 --- a/compiler/rustc_target/src/spec/base/hermit.rs +++ b/compiler/rustc_target/src/spec/base/hermit.rs @@ -1,6 +1,6 @@ use crate::spec::{Cc, LinkerFlavor, Lld, PanicStrategy, TargetOptions, TlsModel}; -pub fn opts() -> TargetOptions { +pub(crate) fn opts() -> TargetOptions { TargetOptions { os: "hermit".into(), linker: Some("rust-lld".into()), diff --git a/compiler/rustc_target/src/spec/base/hurd.rs b/compiler/rustc_target/src/spec/base/hurd.rs index 76f8223c0e4ed..d464d50ecc28c 100644 --- a/compiler/rustc_target/src/spec/base/hurd.rs +++ b/compiler/rustc_target/src/spec/base/hurd.rs @@ -1,6 +1,6 @@ use crate::spec::{cvs, RelroLevel, TargetOptions}; -pub fn opts() -> TargetOptions { +pub(crate) fn opts() -> TargetOptions { TargetOptions { os: "hurd".into(), dynamic_linking: true, diff --git a/compiler/rustc_target/src/spec/base/hurd_gnu.rs b/compiler/rustc_target/src/spec/base/hurd_gnu.rs index 3501dbdea1b59..70d423217a60c 100644 --- a/compiler/rustc_target/src/spec/base/hurd_gnu.rs +++ b/compiler/rustc_target/src/spec/base/hurd_gnu.rs @@ -1,5 +1,5 @@ use crate::spec::{base, TargetOptions}; -pub fn opts() -> TargetOptions { +pub(crate) fn opts() -> TargetOptions { TargetOptions { env: "gnu".into(), ..base::hurd::opts() } } diff --git a/compiler/rustc_target/src/spec/base/illumos.rs b/compiler/rustc_target/src/spec/base/illumos.rs index f0a648b93ad04..fa743a0c66d8d 100644 --- a/compiler/rustc_target/src/spec/base/illumos.rs +++ b/compiler/rustc_target/src/spec/base/illumos.rs @@ -1,6 +1,6 @@ use crate::spec::{cvs, Cc, FramePointer, LinkerFlavor, TargetOptions}; -pub fn opts() -> TargetOptions { +pub(crate) fn opts() -> TargetOptions { let late_link_args = TargetOptions::link_args( LinkerFlavor::Unix(Cc::Yes), &[ diff --git a/compiler/rustc_target/src/spec/base/l4re.rs b/compiler/rustc_target/src/spec/base/l4re.rs index 3a4d83fad1751..dbe9e78a193b9 100644 --- a/compiler/rustc_target/src/spec/base/l4re.rs +++ b/compiler/rustc_target/src/spec/base/l4re.rs @@ -1,6 +1,6 @@ use crate::spec::{cvs, Cc, LinkerFlavor, PanicStrategy, RelocModel, TargetOptions}; -pub fn opts() -> TargetOptions { +pub(crate) fn opts() -> TargetOptions { TargetOptions { os: "l4re".into(), env: "uclibc".into(), diff --git a/compiler/rustc_target/src/spec/base/linux.rs b/compiler/rustc_target/src/spec/base/linux.rs index 34b2eb0f64174..2e30364525e6b 100644 --- a/compiler/rustc_target/src/spec/base/linux.rs +++ b/compiler/rustc_target/src/spec/base/linux.rs @@ -2,7 +2,7 @@ use std::borrow::Cow; use crate::spec::{cvs, RelroLevel, SplitDebuginfo, TargetOptions}; -pub fn opts() -> TargetOptions { +pub(crate) fn opts() -> TargetOptions { TargetOptions { os: "linux".into(), dynamic_linking: true, diff --git a/compiler/rustc_target/src/spec/base/linux_gnu.rs b/compiler/rustc_target/src/spec/base/linux_gnu.rs index 3491277c44077..1200add4fe1e2 100644 --- a/compiler/rustc_target/src/spec/base/linux_gnu.rs +++ b/compiler/rustc_target/src/spec/base/linux_gnu.rs @@ -1,5 +1,5 @@ use crate::spec::{base, TargetOptions}; -pub fn opts() -> TargetOptions { +pub(crate) fn opts() -> TargetOptions { TargetOptions { env: "gnu".into(), ..base::linux::opts() } } diff --git a/compiler/rustc_target/src/spec/base/linux_musl.rs b/compiler/rustc_target/src/spec/base/linux_musl.rs index 42aa1e1a6daf4..a29635112fffa 100644 --- a/compiler/rustc_target/src/spec/base/linux_musl.rs +++ b/compiler/rustc_target/src/spec/base/linux_musl.rs @@ -1,6 +1,6 @@ use crate::spec::{base, crt_objects, LinkSelfContainedDefault, TargetOptions}; -pub fn opts() -> TargetOptions { +pub(crate) fn opts() -> TargetOptions { let mut base = base::linux::opts(); base.env = "musl".into(); diff --git a/compiler/rustc_target/src/spec/base/linux_ohos.rs b/compiler/rustc_target/src/spec/base/linux_ohos.rs index 8272cda05e791..2372bc2c71814 100644 --- a/compiler/rustc_target/src/spec/base/linux_ohos.rs +++ b/compiler/rustc_target/src/spec/base/linux_ohos.rs @@ -1,6 +1,6 @@ use crate::spec::{base, TargetOptions, TlsModel}; -pub fn opts() -> TargetOptions { +pub(crate) fn opts() -> TargetOptions { let mut base = base::linux::opts(); base.env = "ohos".into(); diff --git a/compiler/rustc_target/src/spec/base/linux_uclibc.rs b/compiler/rustc_target/src/spec/base/linux_uclibc.rs index 540344e9e94d1..80a6479bb5f9a 100644 --- a/compiler/rustc_target/src/spec/base/linux_uclibc.rs +++ b/compiler/rustc_target/src/spec/base/linux_uclibc.rs @@ -1,5 +1,5 @@ use crate::spec::{base, TargetOptions}; -pub fn opts() -> TargetOptions { +pub(crate) fn opts() -> TargetOptions { TargetOptions { env: "uclibc".into(), ..base::linux::opts() } } diff --git a/compiler/rustc_target/src/spec/base/msvc.rs b/compiler/rustc_target/src/spec/base/msvc.rs index 720cf03005a5e..b0fb2ef4b27f2 100644 --- a/compiler/rustc_target/src/spec/base/msvc.rs +++ b/compiler/rustc_target/src/spec/base/msvc.rs @@ -2,7 +2,7 @@ use std::borrow::Cow; use crate::spec::{DebuginfoKind, LinkerFlavor, Lld, SplitDebuginfo, TargetOptions}; -pub fn opts() -> TargetOptions { +pub(crate) fn opts() -> TargetOptions { // Suppress the verbose logo and authorship debugging output, which would needlessly // clog any log files. let pre_link_args = TargetOptions::link_args(LinkerFlavor::Msvc(Lld::No), &["/NOLOGO"]); diff --git a/compiler/rustc_target/src/spec/base/netbsd.rs b/compiler/rustc_target/src/spec/base/netbsd.rs index 495e3d10fbccd..1ae81eb0633ef 100644 --- a/compiler/rustc_target/src/spec/base/netbsd.rs +++ b/compiler/rustc_target/src/spec/base/netbsd.rs @@ -1,6 +1,6 @@ use crate::spec::{cvs, RelroLevel, TargetOptions}; -pub fn opts() -> TargetOptions { +pub(crate) fn opts() -> TargetOptions { TargetOptions { os: "netbsd".into(), dynamic_linking: true, diff --git a/compiler/rustc_target/src/spec/base/nto_qnx.rs b/compiler/rustc_target/src/spec/base/nto_qnx.rs index f1405e9b44667..47177415b3942 100644 --- a/compiler/rustc_target/src/spec/base/nto_qnx.rs +++ b/compiler/rustc_target/src/spec/base/nto_qnx.rs @@ -1,6 +1,6 @@ use crate::spec::{cvs, RelroLevel, TargetOptions}; -pub fn opts() -> TargetOptions { +pub(crate) fn opts() -> TargetOptions { TargetOptions { crt_static_respected: true, dynamic_linking: true, diff --git a/compiler/rustc_target/src/spec/base/openbsd.rs b/compiler/rustc_target/src/spec/base/openbsd.rs index bc3aecb5c1e83..942ac4a393c5c 100644 --- a/compiler/rustc_target/src/spec/base/openbsd.rs +++ b/compiler/rustc_target/src/spec/base/openbsd.rs @@ -1,6 +1,6 @@ use crate::spec::{cvs, FramePointer, RelroLevel, TargetOptions, TlsModel}; -pub fn opts() -> TargetOptions { +pub(crate) fn opts() -> TargetOptions { TargetOptions { os: "openbsd".into(), dynamic_linking: true, diff --git a/compiler/rustc_target/src/spec/base/redox.rs b/compiler/rustc_target/src/spec/base/redox.rs index 9070791e9dfc4..3f13f1f884195 100644 --- a/compiler/rustc_target/src/spec/base/redox.rs +++ b/compiler/rustc_target/src/spec/base/redox.rs @@ -1,6 +1,6 @@ use crate::spec::{cvs, Cc, LinkerFlavor, Lld, RelroLevel, TargetOptions}; -pub fn opts() -> TargetOptions { +pub(crate) fn opts() -> TargetOptions { TargetOptions { os: "redox".into(), env: "relibc".into(), diff --git a/compiler/rustc_target/src/spec/base/solaris.rs b/compiler/rustc_target/src/spec/base/solaris.rs index f97cdb4fb2842..1529cd65b28c4 100644 --- a/compiler/rustc_target/src/spec/base/solaris.rs +++ b/compiler/rustc_target/src/spec/base/solaris.rs @@ -1,6 +1,6 @@ use crate::spec::{cvs, Cc, LinkerFlavor, TargetOptions}; -pub fn opts() -> TargetOptions { +pub(crate) fn opts() -> TargetOptions { TargetOptions { os: "solaris".into(), dynamic_linking: true, diff --git a/compiler/rustc_target/src/spec/base/solid.rs b/compiler/rustc_target/src/spec/base/solid.rs index ce4a8869001bc..fd55e1d150141 100644 --- a/compiler/rustc_target/src/spec/base/solid.rs +++ b/compiler/rustc_target/src/spec/base/solid.rs @@ -1,6 +1,6 @@ use crate::spec::{FramePointer, TargetOptions}; -pub fn opts(kernel: &str) -> TargetOptions { +pub(crate) fn opts(kernel: &str) -> TargetOptions { TargetOptions { os: format!("solid_{kernel}").into(), vendor: "kmc".into(), diff --git a/compiler/rustc_target/src/spec/base/teeos.rs b/compiler/rustc_target/src/spec/base/teeos.rs index 38d0a6d73140a..94eb946dda46b 100644 --- a/compiler/rustc_target/src/spec/base/teeos.rs +++ b/compiler/rustc_target/src/spec/base/teeos.rs @@ -1,6 +1,6 @@ use crate::spec::{add_link_args, Cc, LinkerFlavor, Lld, PanicStrategy, RelroLevel, TargetOptions}; -pub fn opts() -> TargetOptions { +pub(crate) fn opts() -> TargetOptions { let lld_args = &["-zmax-page-size=4096", "-znow", "-ztext", "--execute-only"]; let cc_args = &["-Wl,-zmax-page-size=4096", "-Wl,-znow", "-Wl,-ztext", "-mexecute-only"]; diff --git a/compiler/rustc_target/src/spec/base/thumb.rs b/compiler/rustc_target/src/spec/base/thumb.rs index 0decfecb4cd1d..03ec679038c08 100644 --- a/compiler/rustc_target/src/spec/base/thumb.rs +++ b/compiler/rustc_target/src/spec/base/thumb.rs @@ -29,7 +29,7 @@ use crate::spec::{Cc, FramePointer, LinkerFlavor, Lld, PanicStrategy, RelocModel, TargetOptions}; -pub fn opts() -> TargetOptions { +pub(crate) fn opts() -> TargetOptions { // See rust-lang/rfcs#1645 for a discussion about these defaults TargetOptions { linker_flavor: LinkerFlavor::Gnu(Cc::No, Lld::Yes), diff --git a/compiler/rustc_target/src/spec/base/uefi_msvc.rs b/compiler/rustc_target/src/spec/base/uefi_msvc.rs index e8acd6078e2ad..0020106f40e87 100644 --- a/compiler/rustc_target/src/spec/base/uefi_msvc.rs +++ b/compiler/rustc_target/src/spec/base/uefi_msvc.rs @@ -11,7 +11,7 @@ use crate::spec::{base, LinkerFlavor, Lld, PanicStrategy, StackProbeType, TargetOptions}; -pub fn opts() -> TargetOptions { +pub(crate) fn opts() -> TargetOptions { let mut base = base::msvc::opts(); base.add_pre_link_args( diff --git a/compiler/rustc_target/src/spec/base/unikraft_linux_musl.rs b/compiler/rustc_target/src/spec/base/unikraft_linux_musl.rs index 9ccd0a1e7caec..fd81381572438 100644 --- a/compiler/rustc_target/src/spec/base/unikraft_linux_musl.rs +++ b/compiler/rustc_target/src/spec/base/unikraft_linux_musl.rs @@ -1,6 +1,6 @@ use crate::spec::{cvs, PanicStrategy, RelocModel, TargetOptions}; -pub fn opts() -> TargetOptions { +pub(crate) fn opts() -> TargetOptions { TargetOptions { os: "linux".into(), env: "musl".into(), diff --git a/compiler/rustc_target/src/spec/base/vxworks.rs b/compiler/rustc_target/src/spec/base/vxworks.rs index aa4784b63e7aa..425dd3c8cc232 100644 --- a/compiler/rustc_target/src/spec/base/vxworks.rs +++ b/compiler/rustc_target/src/spec/base/vxworks.rs @@ -1,6 +1,6 @@ use crate::spec::{cvs, TargetOptions}; -pub fn opts() -> TargetOptions { +pub(crate) fn opts() -> TargetOptions { TargetOptions { os: "vxworks".into(), env: "gnu".into(), diff --git a/compiler/rustc_target/src/spec/base/wasm.rs b/compiler/rustc_target/src/spec/base/wasm.rs index f237391016e77..e417137ced1b1 100644 --- a/compiler/rustc_target/src/spec/base/wasm.rs +++ b/compiler/rustc_target/src/spec/base/wasm.rs @@ -3,7 +3,7 @@ use crate::spec::{ TargetOptions, TlsModel, }; -pub fn options() -> TargetOptions { +pub(crate) fn options() -> TargetOptions { macro_rules! args { ($prefix:literal) => { &[ diff --git a/compiler/rustc_target/src/spec/base/windows_gnu.rs b/compiler/rustc_target/src/spec/base/windows_gnu.rs index 7346e42dd9100..1393b1591842f 100644 --- a/compiler/rustc_target/src/spec/base/windows_gnu.rs +++ b/compiler/rustc_target/src/spec/base/windows_gnu.rs @@ -5,7 +5,7 @@ use crate::spec::{ Lld, SplitDebuginfo, TargetOptions, }; -pub fn opts() -> TargetOptions { +pub(crate) fn opts() -> TargetOptions { let mut pre_link_args = TargetOptions::link_args( LinkerFlavor::Gnu(Cc::No, Lld::No), &[ diff --git a/compiler/rustc_target/src/spec/base/windows_gnullvm.rs b/compiler/rustc_target/src/spec/base/windows_gnullvm.rs index 88c3b8a81ad22..9e89a3c75fead 100644 --- a/compiler/rustc_target/src/spec/base/windows_gnullvm.rs +++ b/compiler/rustc_target/src/spec/base/windows_gnullvm.rs @@ -2,7 +2,7 @@ use std::borrow::Cow; use crate::spec::{cvs, Cc, DebuginfoKind, LinkerFlavor, Lld, SplitDebuginfo, TargetOptions}; -pub fn opts() -> TargetOptions { +pub(crate) fn opts() -> TargetOptions { // We cannot use `-nodefaultlibs` because compiler-rt has to be passed // as a path since it's not added to linker search path by the default. // There were attempts to make it behave like libgcc (so one can just use -l) diff --git a/compiler/rustc_target/src/spec/base/windows_msvc.rs b/compiler/rustc_target/src/spec/base/windows_msvc.rs index bd0318f31832a..5301e3ff65441 100644 --- a/compiler/rustc_target/src/spec/base/windows_msvc.rs +++ b/compiler/rustc_target/src/spec/base/windows_msvc.rs @@ -1,6 +1,6 @@ use crate::spec::{base, cvs, TargetOptions}; -pub fn opts() -> TargetOptions { +pub(crate) fn opts() -> TargetOptions { let base = base::msvc::opts(); TargetOptions { diff --git a/compiler/rustc_target/src/spec/base/windows_uwp_gnu.rs b/compiler/rustc_target/src/spec/base/windows_uwp_gnu.rs index 17256e18e24e3..8134b5feade9f 100644 --- a/compiler/rustc_target/src/spec/base/windows_uwp_gnu.rs +++ b/compiler/rustc_target/src/spec/base/windows_uwp_gnu.rs @@ -1,6 +1,6 @@ use crate::spec::{add_link_args, base, Cc, LinkArgs, LinkerFlavor, Lld, TargetOptions}; -pub fn opts() -> TargetOptions { +pub(crate) fn opts() -> TargetOptions { let base = base::windows_gnu::opts(); // FIXME: This should be updated for the exception machinery changes from #67502 diff --git a/compiler/rustc_target/src/spec/base/windows_uwp_msvc.rs b/compiler/rustc_target/src/spec/base/windows_uwp_msvc.rs index 59a7616712541..f4f712145047e 100644 --- a/compiler/rustc_target/src/spec/base/windows_uwp_msvc.rs +++ b/compiler/rustc_target/src/spec/base/windows_uwp_msvc.rs @@ -1,6 +1,6 @@ use crate::spec::{base, LinkerFlavor, Lld, TargetOptions}; -pub fn opts() -> TargetOptions { +pub(crate) fn opts() -> TargetOptions { let mut opts = base::windows_msvc::opts(); opts.abi = "uwp".into(); diff --git a/compiler/rustc_target/src/spec/base/xtensa.rs b/compiler/rustc_target/src/spec/base/xtensa.rs index 31ad09c52e4fd..280dd16e26453 100644 --- a/compiler/rustc_target/src/spec/base/xtensa.rs +++ b/compiler/rustc_target/src/spec/base/xtensa.rs @@ -1,7 +1,7 @@ use crate::abi::Endian; use crate::spec::{Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, TargetOptions}; -pub fn opts() -> TargetOptions { +pub(crate) fn opts() -> TargetOptions { TargetOptions { os: "none".into(), endian: Endian::Little, diff --git a/compiler/rustc_target/src/spec/targets/aarch64_apple_darwin.rs b/compiler/rustc_target/src/spec/targets/aarch64_apple_darwin.rs index 65f2a1e306987..912392c9fef08 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_apple_darwin.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_apple_darwin.rs @@ -1,7 +1,7 @@ use crate::spec::base::apple::{macos_llvm_target, opts, Arch, TargetAbi}; use crate::spec::{FramePointer, SanitizerSet, Target, TargetOptions}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { let arch = Arch::Arm64; let mut base = opts("macos", arch, TargetAbi::Normal); base.cpu = "apple-m1".into(); diff --git a/compiler/rustc_target/src/spec/targets/aarch64_apple_ios.rs b/compiler/rustc_target/src/spec/targets/aarch64_apple_ios.rs index 11a39c26e9d25..7f3a86f3256ff 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_apple_ios.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_apple_ios.rs @@ -1,7 +1,7 @@ use crate::spec::base::apple::{ios_llvm_target, opts, Arch, TargetAbi}; use crate::spec::{FramePointer, SanitizerSet, Target, TargetOptions}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { let arch = Arch::Arm64; let mut base = opts("ios", arch, TargetAbi::Normal); base.supported_sanitizers = SanitizerSet::ADDRESS | SanitizerSet::THREAD; diff --git a/compiler/rustc_target/src/spec/targets/aarch64_apple_ios_macabi.rs b/compiler/rustc_target/src/spec/targets/aarch64_apple_ios_macabi.rs index 32c2367d5bfdb..e60eeda429565 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_apple_ios_macabi.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_apple_ios_macabi.rs @@ -1,7 +1,7 @@ use crate::spec::base::apple::{mac_catalyst_llvm_target, opts, Arch, TargetAbi}; use crate::spec::{FramePointer, SanitizerSet, Target, TargetOptions}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { let arch = Arch::Arm64; let mut base = opts("ios", arch, TargetAbi::MacCatalyst); base.supported_sanitizers = SanitizerSet::ADDRESS | SanitizerSet::LEAK | SanitizerSet::THREAD; diff --git a/compiler/rustc_target/src/spec/targets/aarch64_apple_ios_sim.rs b/compiler/rustc_target/src/spec/targets/aarch64_apple_ios_sim.rs index 703b886cc19ec..d605e22701af0 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_apple_ios_sim.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_apple_ios_sim.rs @@ -1,7 +1,7 @@ use crate::spec::base::apple::{ios_sim_llvm_target, opts, Arch, TargetAbi}; use crate::spec::{FramePointer, SanitizerSet, Target, TargetOptions}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { let arch = Arch::Arm64; let mut base = opts("ios", arch, TargetAbi::Simulator); base.supported_sanitizers = SanitizerSet::ADDRESS | SanitizerSet::THREAD; diff --git a/compiler/rustc_target/src/spec/targets/aarch64_apple_tvos.rs b/compiler/rustc_target/src/spec/targets/aarch64_apple_tvos.rs index e97ad11cdf6c5..fc774ab94c880 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_apple_tvos.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_apple_tvos.rs @@ -1,7 +1,7 @@ use crate::spec::base::apple::{opts, tvos_llvm_target, Arch, TargetAbi}; use crate::spec::{FramePointer, Target, TargetOptions}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { let arch = Arch::Arm64; Target { llvm_target: tvos_llvm_target(arch).into(), diff --git a/compiler/rustc_target/src/spec/targets/aarch64_apple_tvos_sim.rs b/compiler/rustc_target/src/spec/targets/aarch64_apple_tvos_sim.rs index 8bfa9c8e8b7e1..8e8bb1efc9dfe 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_apple_tvos_sim.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_apple_tvos_sim.rs @@ -1,7 +1,7 @@ use crate::spec::base::apple::{opts, tvos_sim_llvm_target, Arch, TargetAbi}; use crate::spec::{FramePointer, Target, TargetOptions}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { let arch = Arch::Arm64; Target { llvm_target: tvos_sim_llvm_target(arch).into(), diff --git a/compiler/rustc_target/src/spec/targets/aarch64_apple_visionos.rs b/compiler/rustc_target/src/spec/targets/aarch64_apple_visionos.rs index b0798e5e4f580..16c7d72daed85 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_apple_visionos.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_apple_visionos.rs @@ -1,7 +1,7 @@ use crate::spec::base::apple::{opts, visionos_llvm_target, Arch, TargetAbi}; use crate::spec::{FramePointer, SanitizerSet, Target, TargetOptions}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { let arch = Arch::Arm64; let mut base = opts("visionos", arch, TargetAbi::Normal); base.supported_sanitizers = SanitizerSet::ADDRESS | SanitizerSet::THREAD; diff --git a/compiler/rustc_target/src/spec/targets/aarch64_apple_visionos_sim.rs b/compiler/rustc_target/src/spec/targets/aarch64_apple_visionos_sim.rs index 7b2d2b6a8e442..42973e0268e12 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_apple_visionos_sim.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_apple_visionos_sim.rs @@ -1,7 +1,7 @@ use crate::spec::base::apple::{opts, visionos_sim_llvm_target, Arch, TargetAbi}; use crate::spec::{FramePointer, SanitizerSet, Target, TargetOptions}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { let arch = Arch::Arm64; let mut base = opts("visionos", arch, TargetAbi::Simulator); base.supported_sanitizers = SanitizerSet::ADDRESS | SanitizerSet::THREAD; diff --git a/compiler/rustc_target/src/spec/targets/aarch64_apple_watchos.rs b/compiler/rustc_target/src/spec/targets/aarch64_apple_watchos.rs index 6d66299d6d9e0..03fc2518d1d6b 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_apple_watchos.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_apple_watchos.rs @@ -1,7 +1,7 @@ use crate::spec::base::apple::{opts, Arch, TargetAbi}; use crate::spec::{Target, TargetOptions}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { let base = opts("watchos", Arch::Arm64, TargetAbi::Normal); Target { llvm_target: "aarch64-apple-watchos".into(), diff --git a/compiler/rustc_target/src/spec/targets/aarch64_apple_watchos_sim.rs b/compiler/rustc_target/src/spec/targets/aarch64_apple_watchos_sim.rs index 9675a950d5d08..13e2b96179481 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_apple_watchos_sim.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_apple_watchos_sim.rs @@ -1,7 +1,7 @@ use crate::spec::base::apple::{opts, watchos_sim_llvm_target, Arch, TargetAbi}; use crate::spec::{FramePointer, Target, TargetOptions}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { let arch = Arch::Arm64; Target { // Clang automatically chooses a more specific target based on diff --git a/compiler/rustc_target/src/spec/targets/aarch64_be_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/targets/aarch64_be_unknown_linux_gnu.rs index df389fe34bd69..5b8efd6626287 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_be_unknown_linux_gnu.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_be_unknown_linux_gnu.rs @@ -1,7 +1,7 @@ use crate::abi::Endian; use crate::spec::{base, StackProbeType, Target, TargetOptions}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { Target { llvm_target: "aarch64_be-unknown-linux-gnu".into(), metadata: crate::spec::TargetMetadata { diff --git a/compiler/rustc_target/src/spec/targets/aarch64_be_unknown_linux_gnu_ilp32.rs b/compiler/rustc_target/src/spec/targets/aarch64_be_unknown_linux_gnu_ilp32.rs index 10a8e3e4df818..c14fa20b6973d 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_be_unknown_linux_gnu_ilp32.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_be_unknown_linux_gnu_ilp32.rs @@ -1,7 +1,7 @@ use crate::abi::Endian; use crate::spec::{base, StackProbeType, Target, TargetOptions}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { let mut base = base::linux_gnu::opts(); base.max_atomic_width = Some(128); diff --git a/compiler/rustc_target/src/spec/targets/aarch64_be_unknown_netbsd.rs b/compiler/rustc_target/src/spec/targets/aarch64_be_unknown_netbsd.rs index ba646cd6065fc..fe4dadfe8382d 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_be_unknown_netbsd.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_be_unknown_netbsd.rs @@ -1,7 +1,7 @@ use crate::abi::Endian; use crate::spec::{base, StackProbeType, Target, TargetOptions}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { Target { llvm_target: "aarch64_be-unknown-netbsd".into(), metadata: crate::spec::TargetMetadata { diff --git a/compiler/rustc_target/src/spec/targets/aarch64_fuchsia.rs b/compiler/rustc_target/src/spec/targets/aarch64_fuchsia.rs index 3668db912bb81..144ac85622eef 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_fuchsia.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_fuchsia.rs @@ -1 +1 @@ -pub use crate::spec::targets::aarch64_unknown_fuchsia::target; +pub(crate) use crate::spec::targets::aarch64_unknown_fuchsia::target; diff --git a/compiler/rustc_target/src/spec/targets/aarch64_kmc_solid_asp3.rs b/compiler/rustc_target/src/spec/targets/aarch64_kmc_solid_asp3.rs index 1c2273bb3a1f3..1d054dad568a8 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_kmc_solid_asp3.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_kmc_solid_asp3.rs @@ -1,6 +1,6 @@ use crate::spec::{base, RelocModel, StackProbeType, Target, TargetOptions}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { let base = base::solid::opts("asp3"); Target { llvm_target: "aarch64-unknown-none".into(), diff --git a/compiler/rustc_target/src/spec/targets/aarch64_linux_android.rs b/compiler/rustc_target/src/spec/targets/aarch64_linux_android.rs index 3f0072c00c149..ff0a0762e3c80 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_linux_android.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_linux_android.rs @@ -3,7 +3,7 @@ use crate::spec::{base, SanitizerSet, StackProbeType, Target, TargetOptions}; // See https://developer.android.com/ndk/guides/abis.html#arm64-v8a // for target ABI requirements. -pub fn target() -> Target { +pub(crate) fn target() -> Target { Target { llvm_target: "aarch64-linux-android".into(), metadata: crate::spec::TargetMetadata { diff --git a/compiler/rustc_target/src/spec/targets/aarch64_nintendo_switch_freestanding.rs b/compiler/rustc_target/src/spec/targets/aarch64_nintendo_switch_freestanding.rs index 1ba4fbb3d256b..d6d49a4a07044 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_nintendo_switch_freestanding.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_nintendo_switch_freestanding.rs @@ -5,7 +5,7 @@ use crate::spec::{ const LINKER_SCRIPT: &str = include_str!("./aarch64_nintendo_switch_freestanding_linker_script.ld"); /// A base target for Nintendo Switch devices using a pure LLVM toolchain. -pub fn target() -> Target { +pub(crate) fn target() -> Target { Target { llvm_target: "aarch64-unknown-none".into(), metadata: crate::spec::TargetMetadata { diff --git a/compiler/rustc_target/src/spec/targets/aarch64_pc_windows_gnullvm.rs b/compiler/rustc_target/src/spec/targets/aarch64_pc_windows_gnullvm.rs index 070460538c7a3..9d10358a49f80 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_pc_windows_gnullvm.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_pc_windows_gnullvm.rs @@ -1,6 +1,6 @@ use crate::spec::{base, Target}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { let mut base = base::windows_gnullvm::opts(); base.max_atomic_width = Some(128); base.features = "+v8a,+neon,+fp-armv8".into(); diff --git a/compiler/rustc_target/src/spec/targets/aarch64_pc_windows_msvc.rs b/compiler/rustc_target/src/spec/targets/aarch64_pc_windows_msvc.rs index f4e2ee448057a..c3bd2ea6c332b 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_pc_windows_msvc.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_pc_windows_msvc.rs @@ -1,6 +1,6 @@ use crate::spec::{base, Target}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { let mut base = base::windows_msvc::opts(); base.max_atomic_width = Some(128); base.features = "+v8a,+neon,+fp-armv8".into(); diff --git a/compiler/rustc_target/src/spec/targets/aarch64_unknown_freebsd.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_freebsd.rs index b10f1c7592e51..b993275ff8314 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_unknown_freebsd.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_unknown_freebsd.rs @@ -1,6 +1,6 @@ use crate::spec::{base, SanitizerSet, StackProbeType, Target, TargetOptions}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { Target { llvm_target: "aarch64-unknown-freebsd".into(), metadata: crate::spec::TargetMetadata { diff --git a/compiler/rustc_target/src/spec/targets/aarch64_unknown_fuchsia.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_fuchsia.rs index f84853fbb19c4..b462739e5617b 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_unknown_fuchsia.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_unknown_fuchsia.rs @@ -1,6 +1,6 @@ use crate::spec::{base, SanitizerSet, StackProbeType, Target, TargetOptions}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { Target { llvm_target: "aarch64-unknown-fuchsia".into(), metadata: crate::spec::TargetMetadata { diff --git a/compiler/rustc_target/src/spec/targets/aarch64_unknown_hermit.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_hermit.rs index 55cb0b8f2ee78..e9da6a8f3ceb8 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_unknown_hermit.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_unknown_hermit.rs @@ -1,6 +1,6 @@ use crate::spec::{base, StackProbeType, Target, TargetOptions}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { Target { llvm_target: "aarch64-unknown-hermit".into(), metadata: crate::spec::TargetMetadata { diff --git a/compiler/rustc_target/src/spec/targets/aarch64_unknown_illumos.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_illumos.rs index 7f05358e01610..bed9c88fd670b 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_unknown_illumos.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_unknown_illumos.rs @@ -1,6 +1,6 @@ use crate::spec::{base, Cc, LinkerFlavor, SanitizerSet, Target}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { let mut base = base::illumos::opts(); base.add_pre_link_args(LinkerFlavor::Unix(Cc::Yes), &["-std=c99"]); base.max_atomic_width = Some(128); diff --git a/compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_gnu.rs index 1a45c2c5c05ef..56709f788d3eb 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_gnu.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_gnu.rs @@ -1,6 +1,6 @@ use crate::spec::{base, SanitizerSet, StackProbeType, Target, TargetOptions}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { Target { llvm_target: "aarch64-unknown-linux-gnu".into(), metadata: crate::spec::TargetMetadata { diff --git a/compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_gnu_ilp32.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_gnu_ilp32.rs index 851366b7647bc..71b331972cc0d 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_gnu_ilp32.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_gnu_ilp32.rs @@ -1,6 +1,6 @@ use crate::spec::{base, StackProbeType, Target, TargetOptions}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { Target { llvm_target: "aarch64-unknown-linux-gnu_ilp32".into(), metadata: crate::spec::TargetMetadata { diff --git a/compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_musl.rs index 6b4a422a474a0..1cf71b650409c 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_musl.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_musl.rs @@ -1,6 +1,6 @@ use crate::spec::{base, SanitizerSet, StackProbeType, Target, TargetOptions}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { let mut base = base::linux_musl::opts(); base.max_atomic_width = Some(128); base.supports_xray = true; diff --git a/compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_ohos.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_ohos.rs index 726a85c81f39f..0dbf4cb7a705c 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_ohos.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_ohos.rs @@ -1,6 +1,6 @@ use crate::spec::{base, SanitizerSet, StackProbeType, Target, TargetOptions}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { let mut base = base::linux_ohos::opts(); base.max_atomic_width = Some(128); diff --git a/compiler/rustc_target/src/spec/targets/aarch64_unknown_netbsd.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_netbsd.rs index 0069d5431f8e5..e25beec0a1376 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_unknown_netbsd.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_unknown_netbsd.rs @@ -1,6 +1,6 @@ use crate::spec::{base, StackProbeType, Target, TargetOptions}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { Target { llvm_target: "aarch64-unknown-netbsd".into(), metadata: crate::spec::TargetMetadata { diff --git a/compiler/rustc_target/src/spec/targets/aarch64_unknown_none.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_none.rs index 169468f2e2482..54a08853c2860 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_unknown_none.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_unknown_none.rs @@ -11,7 +11,7 @@ use crate::spec::{ TargetOptions, }; -pub fn target() -> Target { +pub(crate) fn target() -> Target { let opts = TargetOptions { linker_flavor: LinkerFlavor::Gnu(Cc::No, Lld::Yes), linker: Some("rust-lld".into()), diff --git a/compiler/rustc_target/src/spec/targets/aarch64_unknown_none_softfloat.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_none_softfloat.rs index 222d5651b5211..7933041b584ec 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_unknown_none_softfloat.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_unknown_none_softfloat.rs @@ -10,7 +10,7 @@ use crate::spec::{ Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, StackProbeType, Target, TargetOptions, }; -pub fn target() -> Target { +pub(crate) fn target() -> Target { let opts = TargetOptions { abi: "softfloat".into(), linker_flavor: LinkerFlavor::Gnu(Cc::No, Lld::Yes), diff --git a/compiler/rustc_target/src/spec/targets/aarch64_unknown_nto_qnx700.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_nto_qnx700.rs index ac1bec02ec8ae..47a9b91663f84 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_unknown_nto_qnx700.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_unknown_nto_qnx700.rs @@ -1,6 +1,6 @@ use crate::spec::{base, Cc, LinkerFlavor, Lld, Target, TargetOptions}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { // In QNX, libc does not provide a compatible ABI between versions. // To distinguish between QNX versions, we needed a stable conditional compilation switch, // which is why we needed to implement different targets in the compiler. diff --git a/compiler/rustc_target/src/spec/targets/aarch64_unknown_nto_qnx710.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_nto_qnx710.rs index 65a1863eb391a..5b5a21fca9527 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_unknown_nto_qnx710.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_unknown_nto_qnx710.rs @@ -1,6 +1,6 @@ use crate::spec::Target; -pub fn target() -> Target { +pub(crate) fn target() -> Target { let mut base = super::aarch64_unknown_nto_qnx700::target(); base.metadata.description = Some("ARM64 QNX Neutrino 7.1 RTOS".into()); base.options.env = "nto71".into(); diff --git a/compiler/rustc_target/src/spec/targets/aarch64_unknown_openbsd.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_openbsd.rs index e16991af4e665..8f6215df71a41 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_unknown_openbsd.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_unknown_openbsd.rs @@ -1,6 +1,6 @@ use crate::spec::{base, StackProbeType, Target, TargetOptions}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { Target { llvm_target: "aarch64-unknown-openbsd".into(), metadata: crate::spec::TargetMetadata { diff --git a/compiler/rustc_target/src/spec/targets/aarch64_unknown_redox.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_redox.rs index e59b38a3e4116..26c1a67109558 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_unknown_redox.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_unknown_redox.rs @@ -1,6 +1,6 @@ use crate::spec::{base, StackProbeType, Target}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { let mut base = base::redox::opts(); base.max_atomic_width = Some(128); base.stack_probes = StackProbeType::Inline; diff --git a/compiler/rustc_target/src/spec/targets/aarch64_unknown_teeos.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_teeos.rs index 5ae2d68332c6e..4e3d5ce34bc50 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_unknown_teeos.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_unknown_teeos.rs @@ -1,6 +1,6 @@ use crate::spec::{base, StackProbeType, Target}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { let mut base = base::teeos::opts(); base.features = "+strict-align,+neon,+fp-armv8".into(); base.max_atomic_width = Some(128); diff --git a/compiler/rustc_target/src/spec/targets/aarch64_unknown_trusty.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_trusty.rs index 9fd7c24649896..69ab992e12ca1 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_unknown_trusty.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_unknown_trusty.rs @@ -2,7 +2,7 @@ use crate::spec::{LinkSelfContainedDefault, PanicStrategy, RelroLevel, Target, TargetOptions}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { Target { llvm_target: "aarch64-unknown-unknown-musl".into(), metadata: crate::spec::TargetMetadata { diff --git a/compiler/rustc_target/src/spec/targets/aarch64_unknown_uefi.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_uefi.rs index 429303170b6b8..bb580af7c4756 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_unknown_uefi.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_unknown_uefi.rs @@ -3,7 +3,7 @@ use crate::spec::{base, LinkerFlavor, Lld, Target}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { let mut base = base::uefi_msvc::opts(); base.max_atomic_width = Some(128); diff --git a/compiler/rustc_target/src/spec/targets/aarch64_uwp_windows_msvc.rs b/compiler/rustc_target/src/spec/targets/aarch64_uwp_windows_msvc.rs index df1b75272b1fe..630658efd0675 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_uwp_windows_msvc.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_uwp_windows_msvc.rs @@ -1,6 +1,6 @@ use crate::spec::{base, Target}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { let mut base = base::windows_uwp_msvc::opts(); base.max_atomic_width = Some(128); base.features = "+v8a".into(); diff --git a/compiler/rustc_target/src/spec/targets/aarch64_wrs_vxworks.rs b/compiler/rustc_target/src/spec/targets/aarch64_wrs_vxworks.rs index 41f7532ecdb19..3c0f92fa31fef 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_wrs_vxworks.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_wrs_vxworks.rs @@ -1,6 +1,6 @@ use crate::spec::{base, StackProbeType, Target, TargetOptions}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { Target { llvm_target: "aarch64-unknown-linux-gnu".into(), metadata: crate::spec::TargetMetadata { diff --git a/compiler/rustc_target/src/spec/targets/arm64_32_apple_watchos.rs b/compiler/rustc_target/src/spec/targets/arm64_32_apple_watchos.rs index 2c76f4736de8e..f292ee7f56312 100644 --- a/compiler/rustc_target/src/spec/targets/arm64_32_apple_watchos.rs +++ b/compiler/rustc_target/src/spec/targets/arm64_32_apple_watchos.rs @@ -1,7 +1,7 @@ use crate::spec::base::apple::{opts, watchos_llvm_target, Arch, TargetAbi}; use crate::spec::{Target, TargetOptions}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { let arch = Arch::Arm64_32; let base = opts("watchos", arch, TargetAbi::Normal); Target { diff --git a/compiler/rustc_target/src/spec/targets/arm64e_apple_darwin.rs b/compiler/rustc_target/src/spec/targets/arm64e_apple_darwin.rs index 6f28f5d054360..e86b8358a9c98 100644 --- a/compiler/rustc_target/src/spec/targets/arm64e_apple_darwin.rs +++ b/compiler/rustc_target/src/spec/targets/arm64e_apple_darwin.rs @@ -1,7 +1,7 @@ use crate::spec::base::apple::{macos_llvm_target, opts, Arch, TargetAbi}; use crate::spec::{FramePointer, SanitizerSet, Target, TargetOptions}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { let arch = Arch::Arm64e; let mut base = opts("macos", arch, TargetAbi::Normal); base.cpu = "apple-m1".into(); diff --git a/compiler/rustc_target/src/spec/targets/arm64e_apple_ios.rs b/compiler/rustc_target/src/spec/targets/arm64e_apple_ios.rs index 1590ae9679d88..fcb850f44bc85 100644 --- a/compiler/rustc_target/src/spec/targets/arm64e_apple_ios.rs +++ b/compiler/rustc_target/src/spec/targets/arm64e_apple_ios.rs @@ -1,7 +1,7 @@ use crate::spec::base::apple::{ios_llvm_target, opts, Arch, TargetAbi}; use crate::spec::{FramePointer, SanitizerSet, Target, TargetOptions}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { let arch = Arch::Arm64e; let mut base = opts("ios", arch, TargetAbi::Normal); base.supported_sanitizers = SanitizerSet::ADDRESS | SanitizerSet::THREAD; diff --git a/compiler/rustc_target/src/spec/targets/arm64ec_pc_windows_msvc.rs b/compiler/rustc_target/src/spec/targets/arm64ec_pc_windows_msvc.rs index 21cb38868fb92..50c399bf4a88b 100644 --- a/compiler/rustc_target/src/spec/targets/arm64ec_pc_windows_msvc.rs +++ b/compiler/rustc_target/src/spec/targets/arm64ec_pc_windows_msvc.rs @@ -1,6 +1,6 @@ use crate::spec::{add_link_args, base, LinkerFlavor, Lld, Target}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { let mut base = base::windows_msvc::opts(); base.max_atomic_width = Some(128); base.features = "+v8a,+neon,+fp-armv8".into(); diff --git a/compiler/rustc_target/src/spec/targets/arm_linux_androideabi.rs b/compiler/rustc_target/src/spec/targets/arm_linux_androideabi.rs index a22bcef47575c..350a01b196714 100644 --- a/compiler/rustc_target/src/spec/targets/arm_linux_androideabi.rs +++ b/compiler/rustc_target/src/spec/targets/arm_linux_androideabi.rs @@ -1,6 +1,6 @@ use crate::spec::{base, SanitizerSet, Target, TargetOptions}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { Target { llvm_target: "arm-linux-androideabi".into(), metadata: crate::spec::TargetMetadata { diff --git a/compiler/rustc_target/src/spec/targets/arm_unknown_linux_gnueabi.rs b/compiler/rustc_target/src/spec/targets/arm_unknown_linux_gnueabi.rs index 8ff272e786db0..296f9d0b423d7 100644 --- a/compiler/rustc_target/src/spec/targets/arm_unknown_linux_gnueabi.rs +++ b/compiler/rustc_target/src/spec/targets/arm_unknown_linux_gnueabi.rs @@ -1,6 +1,6 @@ use crate::spec::{base, Target, TargetOptions}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { Target { llvm_target: "arm-unknown-linux-gnueabi".into(), metadata: crate::spec::TargetMetadata { diff --git a/compiler/rustc_target/src/spec/targets/arm_unknown_linux_gnueabihf.rs b/compiler/rustc_target/src/spec/targets/arm_unknown_linux_gnueabihf.rs index e3e2f4cd05c2a..5d58055f1af35 100644 --- a/compiler/rustc_target/src/spec/targets/arm_unknown_linux_gnueabihf.rs +++ b/compiler/rustc_target/src/spec/targets/arm_unknown_linux_gnueabihf.rs @@ -1,6 +1,6 @@ use crate::spec::{base, Target, TargetOptions}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { Target { llvm_target: "arm-unknown-linux-gnueabihf".into(), metadata: crate::spec::TargetMetadata { diff --git a/compiler/rustc_target/src/spec/targets/arm_unknown_linux_musleabi.rs b/compiler/rustc_target/src/spec/targets/arm_unknown_linux_musleabi.rs index f958b89358b18..89a80ae8bedd6 100644 --- a/compiler/rustc_target/src/spec/targets/arm_unknown_linux_musleabi.rs +++ b/compiler/rustc_target/src/spec/targets/arm_unknown_linux_musleabi.rs @@ -1,6 +1,6 @@ use crate::spec::{base, Target, TargetOptions}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { Target { // It's important we use "gnueabi" and not "musleabi" here. LLVM uses it // to determine the calling convention and float ABI, and it doesn't diff --git a/compiler/rustc_target/src/spec/targets/arm_unknown_linux_musleabihf.rs b/compiler/rustc_target/src/spec/targets/arm_unknown_linux_musleabihf.rs index 98093fdc00324..200bb91796484 100644 --- a/compiler/rustc_target/src/spec/targets/arm_unknown_linux_musleabihf.rs +++ b/compiler/rustc_target/src/spec/targets/arm_unknown_linux_musleabihf.rs @@ -1,6 +1,6 @@ use crate::spec::{base, Target, TargetOptions}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { Target { // It's important we use "gnueabihf" and not "musleabihf" here. LLVM // uses it to determine the calling convention and float ABI, and it diff --git a/compiler/rustc_target/src/spec/targets/armeb_unknown_linux_gnueabi.rs b/compiler/rustc_target/src/spec/targets/armeb_unknown_linux_gnueabi.rs index b56f311793adc..a6ea48817c04f 100644 --- a/compiler/rustc_target/src/spec/targets/armeb_unknown_linux_gnueabi.rs +++ b/compiler/rustc_target/src/spec/targets/armeb_unknown_linux_gnueabi.rs @@ -1,7 +1,7 @@ use crate::abi::Endian; use crate::spec::{base, Target, TargetOptions}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { Target { llvm_target: "armeb-unknown-linux-gnueabi".into(), metadata: crate::spec::TargetMetadata { diff --git a/compiler/rustc_target/src/spec/targets/armebv7r_none_eabi.rs b/compiler/rustc_target/src/spec/targets/armebv7r_none_eabi.rs index df32b74f6d9ac..d09624e0e7391 100644 --- a/compiler/rustc_target/src/spec/targets/armebv7r_none_eabi.rs +++ b/compiler/rustc_target/src/spec/targets/armebv7r_none_eabi.rs @@ -3,7 +3,7 @@ use crate::abi::Endian; use crate::spec::{Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, TargetOptions}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { Target { llvm_target: "armebv7r-none-eabi".into(), metadata: crate::spec::TargetMetadata { diff --git a/compiler/rustc_target/src/spec/targets/armebv7r_none_eabihf.rs b/compiler/rustc_target/src/spec/targets/armebv7r_none_eabihf.rs index 063038c801222..10669dcf09d79 100644 --- a/compiler/rustc_target/src/spec/targets/armebv7r_none_eabihf.rs +++ b/compiler/rustc_target/src/spec/targets/armebv7r_none_eabihf.rs @@ -3,7 +3,7 @@ use crate::abi::Endian; use crate::spec::{Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, TargetOptions}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { Target { llvm_target: "armebv7r-none-eabihf".into(), metadata: crate::spec::TargetMetadata { diff --git a/compiler/rustc_target/src/spec/targets/armv4t_none_eabi.rs b/compiler/rustc_target/src/spec/targets/armv4t_none_eabi.rs index f873fb0d34957..2236e02d006fa 100644 --- a/compiler/rustc_target/src/spec/targets/armv4t_none_eabi.rs +++ b/compiler/rustc_target/src/spec/targets/armv4t_none_eabi.rs @@ -11,7 +11,7 @@ use crate::spec::{cvs, Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, TargetOptions}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { Target { llvm_target: "armv4t-none-eabi".into(), metadata: crate::spec::TargetMetadata { diff --git a/compiler/rustc_target/src/spec/targets/armv4t_unknown_linux_gnueabi.rs b/compiler/rustc_target/src/spec/targets/armv4t_unknown_linux_gnueabi.rs index 18f327bc87f7f..d88022ac10a2a 100644 --- a/compiler/rustc_target/src/spec/targets/armv4t_unknown_linux_gnueabi.rs +++ b/compiler/rustc_target/src/spec/targets/armv4t_unknown_linux_gnueabi.rs @@ -1,6 +1,6 @@ use crate::spec::{base, Target, TargetOptions}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { Target { llvm_target: "armv4t-unknown-linux-gnueabi".into(), metadata: crate::spec::TargetMetadata { diff --git a/compiler/rustc_target/src/spec/targets/armv5te_none_eabi.rs b/compiler/rustc_target/src/spec/targets/armv5te_none_eabi.rs index 1fbe4b89ea177..3d8e75d3ee952 100644 --- a/compiler/rustc_target/src/spec/targets/armv5te_none_eabi.rs +++ b/compiler/rustc_target/src/spec/targets/armv5te_none_eabi.rs @@ -2,7 +2,7 @@ use crate::spec::{base, cvs, FramePointer, Target, TargetOptions}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { Target { llvm_target: "armv5te-none-eabi".into(), metadata: crate::spec::TargetMetadata { diff --git a/compiler/rustc_target/src/spec/targets/armv5te_unknown_linux_gnueabi.rs b/compiler/rustc_target/src/spec/targets/armv5te_unknown_linux_gnueabi.rs index 123686448378e..a73d8298ddeed 100644 --- a/compiler/rustc_target/src/spec/targets/armv5te_unknown_linux_gnueabi.rs +++ b/compiler/rustc_target/src/spec/targets/armv5te_unknown_linux_gnueabi.rs @@ -1,6 +1,6 @@ use crate::spec::{base, Target, TargetOptions}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { Target { llvm_target: "armv5te-unknown-linux-gnueabi".into(), metadata: crate::spec::TargetMetadata { diff --git a/compiler/rustc_target/src/spec/targets/armv5te_unknown_linux_musleabi.rs b/compiler/rustc_target/src/spec/targets/armv5te_unknown_linux_musleabi.rs index ccbc1e36ddece..91b0e2039c7f4 100644 --- a/compiler/rustc_target/src/spec/targets/armv5te_unknown_linux_musleabi.rs +++ b/compiler/rustc_target/src/spec/targets/armv5te_unknown_linux_musleabi.rs @@ -1,6 +1,6 @@ use crate::spec::{base, Target, TargetOptions}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { Target { // FIXME: this comment below does not seem applicable? // It's important we use "gnueabihf" and not "musleabihf" here. LLVM diff --git a/compiler/rustc_target/src/spec/targets/armv5te_unknown_linux_uclibceabi.rs b/compiler/rustc_target/src/spec/targets/armv5te_unknown_linux_uclibceabi.rs index d88b88333b56d..65658ab45fc49 100644 --- a/compiler/rustc_target/src/spec/targets/armv5te_unknown_linux_uclibceabi.rs +++ b/compiler/rustc_target/src/spec/targets/armv5te_unknown_linux_uclibceabi.rs @@ -1,6 +1,6 @@ use crate::spec::{base, Target, TargetOptions}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { Target { llvm_target: "armv5te-unknown-linux-uclibcgnueabi".into(), metadata: crate::spec::TargetMetadata { diff --git a/compiler/rustc_target/src/spec/targets/armv6_unknown_freebsd.rs b/compiler/rustc_target/src/spec/targets/armv6_unknown_freebsd.rs index 24e9d1e039494..52617237f207a 100644 --- a/compiler/rustc_target/src/spec/targets/armv6_unknown_freebsd.rs +++ b/compiler/rustc_target/src/spec/targets/armv6_unknown_freebsd.rs @@ -1,6 +1,6 @@ use crate::spec::{base, Target, TargetOptions}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { Target { llvm_target: "armv6-unknown-freebsd-gnueabihf".into(), metadata: crate::spec::TargetMetadata { diff --git a/compiler/rustc_target/src/spec/targets/armv6_unknown_netbsd_eabihf.rs b/compiler/rustc_target/src/spec/targets/armv6_unknown_netbsd_eabihf.rs index 62e328b9cbda2..eda1c028aad3a 100644 --- a/compiler/rustc_target/src/spec/targets/armv6_unknown_netbsd_eabihf.rs +++ b/compiler/rustc_target/src/spec/targets/armv6_unknown_netbsd_eabihf.rs @@ -1,6 +1,6 @@ use crate::spec::{base, Target, TargetOptions}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { Target { llvm_target: "armv6-unknown-netbsdelf-eabihf".into(), metadata: crate::spec::TargetMetadata { diff --git a/compiler/rustc_target/src/spec/targets/armv6k_nintendo_3ds.rs b/compiler/rustc_target/src/spec/targets/armv6k_nintendo_3ds.rs index bcdad0a55b316..b29ee2dd793b1 100644 --- a/compiler/rustc_target/src/spec/targets/armv6k_nintendo_3ds.rs +++ b/compiler/rustc_target/src/spec/targets/armv6k_nintendo_3ds.rs @@ -4,7 +4,7 @@ use crate::spec::{cvs, Cc, LinkerFlavor, Lld, RelocModel, Target, TargetOptions} /// /// Requires the devkitARM toolchain for 3DS targets on the host system. -pub fn target() -> Target { +pub(crate) fn target() -> Target { let pre_link_args = TargetOptions::link_args( LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-specs=3dsx.specs", "-mtune=mpcore", "-mfloat-abi=hard", "-mtp=soft"], diff --git a/compiler/rustc_target/src/spec/targets/armv7_linux_androideabi.rs b/compiler/rustc_target/src/spec/targets/armv7_linux_androideabi.rs index 8f6a58a1b4982..3bba22f8a1fa7 100644 --- a/compiler/rustc_target/src/spec/targets/armv7_linux_androideabi.rs +++ b/compiler/rustc_target/src/spec/targets/armv7_linux_androideabi.rs @@ -8,7 +8,7 @@ use crate::spec::{base, Cc, LinkerFlavor, Lld, SanitizerSet, Target, TargetOptio // See https://developer.android.com/ndk/guides/abis.html#v7a // for target ABI requirements. -pub fn target() -> Target { +pub(crate) fn target() -> Target { let mut base = base::android::opts(); base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-march=armv7-a"]); Target { diff --git a/compiler/rustc_target/src/spec/targets/armv7_sony_vita_newlibeabihf.rs b/compiler/rustc_target/src/spec/targets/armv7_sony_vita_newlibeabihf.rs index a9b5172385ba7..5f71d325efb0a 100644 --- a/compiler/rustc_target/src/spec/targets/armv7_sony_vita_newlibeabihf.rs +++ b/compiler/rustc_target/src/spec/targets/armv7_sony_vita_newlibeabihf.rs @@ -5,7 +5,7 @@ use crate::spec::{cvs, Cc, LinkerFlavor, Lld, RelocModel, Target, TargetOptions} /// /// Requires the VITASDK toolchain on the host system. -pub fn target() -> Target { +pub(crate) fn target() -> Target { let pre_link_args = TargetOptions::link_args( LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-Wl,-q", "-Wl,--pic-veneer"], diff --git a/compiler/rustc_target/src/spec/targets/armv7_unknown_freebsd.rs b/compiler/rustc_target/src/spec/targets/armv7_unknown_freebsd.rs index 3a16bbe95db34..b955acd0dca97 100644 --- a/compiler/rustc_target/src/spec/targets/armv7_unknown_freebsd.rs +++ b/compiler/rustc_target/src/spec/targets/armv7_unknown_freebsd.rs @@ -1,6 +1,6 @@ use crate::spec::{base, Target, TargetOptions}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { Target { llvm_target: "armv7-unknown-freebsd-gnueabihf".into(), metadata: crate::spec::TargetMetadata { diff --git a/compiler/rustc_target/src/spec/targets/armv7_unknown_linux_gnueabi.rs b/compiler/rustc_target/src/spec/targets/armv7_unknown_linux_gnueabi.rs index 8a4ba271456a9..703a9b132b2d9 100644 --- a/compiler/rustc_target/src/spec/targets/armv7_unknown_linux_gnueabi.rs +++ b/compiler/rustc_target/src/spec/targets/armv7_unknown_linux_gnueabi.rs @@ -3,7 +3,7 @@ use crate::spec::{base, Target, TargetOptions}; // This target is for glibc Linux on ARMv7 without thumb-mode, NEON or // hardfloat. -pub fn target() -> Target { +pub(crate) fn target() -> Target { Target { llvm_target: "armv7-unknown-linux-gnueabi".into(), metadata: crate::spec::TargetMetadata { diff --git a/compiler/rustc_target/src/spec/targets/armv7_unknown_linux_gnueabihf.rs b/compiler/rustc_target/src/spec/targets/armv7_unknown_linux_gnueabihf.rs index a217a2daeb39e..db79810b5dd7d 100644 --- a/compiler/rustc_target/src/spec/targets/armv7_unknown_linux_gnueabihf.rs +++ b/compiler/rustc_target/src/spec/targets/armv7_unknown_linux_gnueabihf.rs @@ -3,7 +3,7 @@ use crate::spec::{base, Target, TargetOptions}; // This target is for glibc Linux on ARMv7 without NEON or // thumb-mode. See the thumbv7neon variant for enabling both. -pub fn target() -> Target { +pub(crate) fn target() -> Target { Target { llvm_target: "armv7-unknown-linux-gnueabihf".into(), metadata: crate::spec::TargetMetadata { diff --git a/compiler/rustc_target/src/spec/targets/armv7_unknown_linux_musleabi.rs b/compiler/rustc_target/src/spec/targets/armv7_unknown_linux_musleabi.rs index 96459a5137fd1..e4e99eab853af 100644 --- a/compiler/rustc_target/src/spec/targets/armv7_unknown_linux_musleabi.rs +++ b/compiler/rustc_target/src/spec/targets/armv7_unknown_linux_musleabi.rs @@ -3,7 +3,7 @@ use crate::spec::{base, Target, TargetOptions}; // This target is for musl Linux on ARMv7 without thumb-mode, NEON or // hardfloat. -pub fn target() -> Target { +pub(crate) fn target() -> Target { // Most of these settings are copied from the armv7_unknown_linux_gnueabi // target. Target { diff --git a/compiler/rustc_target/src/spec/targets/armv7_unknown_linux_musleabihf.rs b/compiler/rustc_target/src/spec/targets/armv7_unknown_linux_musleabihf.rs index 6c878141fd495..5fc3f7031753d 100644 --- a/compiler/rustc_target/src/spec/targets/armv7_unknown_linux_musleabihf.rs +++ b/compiler/rustc_target/src/spec/targets/armv7_unknown_linux_musleabihf.rs @@ -2,7 +2,7 @@ use crate::spec::{base, Target, TargetOptions}; // This target is for musl Linux on ARMv7 without thumb-mode or NEON. -pub fn target() -> Target { +pub(crate) fn target() -> Target { Target { // It's important we use "gnueabihf" and not "musleabihf" here. LLVM // uses it to determine the calling convention and float ABI, and LLVM diff --git a/compiler/rustc_target/src/spec/targets/armv7_unknown_linux_ohos.rs b/compiler/rustc_target/src/spec/targets/armv7_unknown_linux_ohos.rs index bffc51d9b7bca..040a953b12e94 100644 --- a/compiler/rustc_target/src/spec/targets/armv7_unknown_linux_ohos.rs +++ b/compiler/rustc_target/src/spec/targets/armv7_unknown_linux_ohos.rs @@ -3,7 +3,7 @@ use crate::spec::{base, Target, TargetOptions}; // This target is for OpenHarmony on ARMv7 Linux with thumb-mode, but no NEON or // hardfloat. -pub fn target() -> Target { +pub(crate) fn target() -> Target { // Most of these settings are copied from the armv7_unknown_linux_musleabi // target. Target { diff --git a/compiler/rustc_target/src/spec/targets/armv7_unknown_linux_uclibceabi.rs b/compiler/rustc_target/src/spec/targets/armv7_unknown_linux_uclibceabi.rs index 9dc1221287dd0..af10d2d90123d 100644 --- a/compiler/rustc_target/src/spec/targets/armv7_unknown_linux_uclibceabi.rs +++ b/compiler/rustc_target/src/spec/targets/armv7_unknown_linux_uclibceabi.rs @@ -3,7 +3,7 @@ use crate::spec::{base, Target, TargetOptions}; // This target is for uclibc Linux on ARMv7 without NEON, // thumb-mode or hardfloat. -pub fn target() -> Target { +pub(crate) fn target() -> Target { let base = base::linux_uclibc::opts(); Target { llvm_target: "armv7-unknown-linux-gnueabi".into(), diff --git a/compiler/rustc_target/src/spec/targets/armv7_unknown_linux_uclibceabihf.rs b/compiler/rustc_target/src/spec/targets/armv7_unknown_linux_uclibceabihf.rs index 01a1468d3a8c9..53673daa8129b 100644 --- a/compiler/rustc_target/src/spec/targets/armv7_unknown_linux_uclibceabihf.rs +++ b/compiler/rustc_target/src/spec/targets/armv7_unknown_linux_uclibceabihf.rs @@ -3,7 +3,7 @@ use crate::spec::{base, Target, TargetOptions}; // This target is for uclibc Linux on ARMv7 without NEON or // thumb-mode. See the thumbv7neon variant for enabling both. -pub fn target() -> Target { +pub(crate) fn target() -> Target { let base = base::linux_uclibc::opts(); Target { llvm_target: "armv7-unknown-linux-gnueabihf".into(), diff --git a/compiler/rustc_target/src/spec/targets/armv7_unknown_netbsd_eabihf.rs b/compiler/rustc_target/src/spec/targets/armv7_unknown_netbsd_eabihf.rs index a2391503ff8ab..164acd17f21ee 100644 --- a/compiler/rustc_target/src/spec/targets/armv7_unknown_netbsd_eabihf.rs +++ b/compiler/rustc_target/src/spec/targets/armv7_unknown_netbsd_eabihf.rs @@ -1,6 +1,6 @@ use crate::spec::{base, Target, TargetOptions}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { Target { llvm_target: "armv7-unknown-netbsdelf-eabihf".into(), metadata: crate::spec::TargetMetadata { diff --git a/compiler/rustc_target/src/spec/targets/armv7_unknown_trusty.rs b/compiler/rustc_target/src/spec/targets/armv7_unknown_trusty.rs index 889cc20156979..1ad91b8f080e7 100644 --- a/compiler/rustc_target/src/spec/targets/armv7_unknown_trusty.rs +++ b/compiler/rustc_target/src/spec/targets/armv7_unknown_trusty.rs @@ -1,6 +1,6 @@ use crate::spec::{LinkSelfContainedDefault, PanicStrategy, RelroLevel, Target, TargetOptions}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { Target { // It's important we use "gnueabi" and not "musleabi" here. LLVM uses it // to determine the calling convention and float ABI, and it doesn't diff --git a/compiler/rustc_target/src/spec/targets/armv7_wrs_vxworks_eabihf.rs b/compiler/rustc_target/src/spec/targets/armv7_wrs_vxworks_eabihf.rs index 7d60ec1b64dda..f8faec918e4d6 100644 --- a/compiler/rustc_target/src/spec/targets/armv7_wrs_vxworks_eabihf.rs +++ b/compiler/rustc_target/src/spec/targets/armv7_wrs_vxworks_eabihf.rs @@ -1,6 +1,6 @@ use crate::spec::{base, Target, TargetOptions}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { Target { llvm_target: "armv7-unknown-linux-gnueabihf".into(), metadata: crate::spec::TargetMetadata { diff --git a/compiler/rustc_target/src/spec/targets/armv7a_kmc_solid_asp3_eabi.rs b/compiler/rustc_target/src/spec/targets/armv7a_kmc_solid_asp3_eabi.rs index 76d4653931b88..aea897f56b885 100644 --- a/compiler/rustc_target/src/spec/targets/armv7a_kmc_solid_asp3_eabi.rs +++ b/compiler/rustc_target/src/spec/targets/armv7a_kmc_solid_asp3_eabi.rs @@ -1,6 +1,6 @@ use crate::spec::{base, RelocModel, Target, TargetOptions}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { let base = base::solid::opts("asp3"); Target { llvm_target: "armv7a-none-eabi".into(), diff --git a/compiler/rustc_target/src/spec/targets/armv7a_kmc_solid_asp3_eabihf.rs b/compiler/rustc_target/src/spec/targets/armv7a_kmc_solid_asp3_eabihf.rs index d2b4d46adac6b..be526d6325004 100644 --- a/compiler/rustc_target/src/spec/targets/armv7a_kmc_solid_asp3_eabihf.rs +++ b/compiler/rustc_target/src/spec/targets/armv7a_kmc_solid_asp3_eabihf.rs @@ -1,6 +1,6 @@ use crate::spec::{base, RelocModel, Target, TargetOptions}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { let base = base::solid::opts("asp3"); Target { llvm_target: "armv7a-none-eabihf".into(), diff --git a/compiler/rustc_target/src/spec/targets/armv7a_none_eabi.rs b/compiler/rustc_target/src/spec/targets/armv7a_none_eabi.rs index b544c404f3f21..1e4798abfffb0 100644 --- a/compiler/rustc_target/src/spec/targets/armv7a_none_eabi.rs +++ b/compiler/rustc_target/src/spec/targets/armv7a_none_eabi.rs @@ -16,7 +16,7 @@ use crate::spec::{Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, TargetOptions}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { let opts = TargetOptions { abi: "eabi".into(), linker_flavor: LinkerFlavor::Gnu(Cc::No, Lld::Yes), diff --git a/compiler/rustc_target/src/spec/targets/armv7a_none_eabihf.rs b/compiler/rustc_target/src/spec/targets/armv7a_none_eabihf.rs index aebb7e667bcd8..ab8b870c62859 100644 --- a/compiler/rustc_target/src/spec/targets/armv7a_none_eabihf.rs +++ b/compiler/rustc_target/src/spec/targets/armv7a_none_eabihf.rs @@ -7,7 +7,7 @@ use crate::spec::{Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, TargetOptions}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { let opts = TargetOptions { abi: "eabihf".into(), linker_flavor: LinkerFlavor::Gnu(Cc::No, Lld::Yes), diff --git a/compiler/rustc_target/src/spec/targets/armv7k_apple_watchos.rs b/compiler/rustc_target/src/spec/targets/armv7k_apple_watchos.rs index e876c567b09a1..35de6b35eaf2e 100644 --- a/compiler/rustc_target/src/spec/targets/armv7k_apple_watchos.rs +++ b/compiler/rustc_target/src/spec/targets/armv7k_apple_watchos.rs @@ -1,7 +1,7 @@ use crate::spec::base::apple::{opts, Arch, TargetAbi}; use crate::spec::{Target, TargetOptions}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { let arch = Arch::Armv7k; Target { llvm_target: "armv7k-apple-watchos".into(), diff --git a/compiler/rustc_target/src/spec/targets/armv7r_none_eabi.rs b/compiler/rustc_target/src/spec/targets/armv7r_none_eabi.rs index b3246dc792811..aba55f533a71d 100644 --- a/compiler/rustc_target/src/spec/targets/armv7r_none_eabi.rs +++ b/compiler/rustc_target/src/spec/targets/armv7r_none_eabi.rs @@ -2,7 +2,7 @@ use crate::spec::{Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, TargetOptions}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { Target { llvm_target: "armv7r-none-eabi".into(), metadata: crate::spec::TargetMetadata { diff --git a/compiler/rustc_target/src/spec/targets/armv7r_none_eabihf.rs b/compiler/rustc_target/src/spec/targets/armv7r_none_eabihf.rs index 9ac500d7ffe7e..5a8519dcc49d0 100644 --- a/compiler/rustc_target/src/spec/targets/armv7r_none_eabihf.rs +++ b/compiler/rustc_target/src/spec/targets/armv7r_none_eabihf.rs @@ -2,7 +2,7 @@ use crate::spec::{Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, TargetOptions}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { Target { llvm_target: "armv7r-none-eabihf".into(), metadata: crate::spec::TargetMetadata { diff --git a/compiler/rustc_target/src/spec/targets/armv7s_apple_ios.rs b/compiler/rustc_target/src/spec/targets/armv7s_apple_ios.rs index 11608794932b3..41eaa79d3eb22 100644 --- a/compiler/rustc_target/src/spec/targets/armv7s_apple_ios.rs +++ b/compiler/rustc_target/src/spec/targets/armv7s_apple_ios.rs @@ -1,7 +1,7 @@ use crate::spec::base::apple::{ios_llvm_target, opts, Arch, TargetAbi}; use crate::spec::{Target, TargetOptions}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { let arch = Arch::Armv7s; Target { llvm_target: ios_llvm_target(arch).into(), diff --git a/compiler/rustc_target/src/spec/targets/armv8r_none_eabihf.rs b/compiler/rustc_target/src/spec/targets/armv8r_none_eabihf.rs index ee940c3a76a24..042a9a140710c 100644 --- a/compiler/rustc_target/src/spec/targets/armv8r_none_eabihf.rs +++ b/compiler/rustc_target/src/spec/targets/armv8r_none_eabihf.rs @@ -2,7 +2,7 @@ use crate::spec::{Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, TargetOptions}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { Target { llvm_target: "armv8r-none-eabihf".into(), metadata: crate::spec::TargetMetadata { diff --git a/compiler/rustc_target/src/spec/targets/avr_unknown_gnu_atmega328.rs b/compiler/rustc_target/src/spec/targets/avr_unknown_gnu_atmega328.rs index bf01413a80adf..020322b27391d 100644 --- a/compiler/rustc_target/src/spec/targets/avr_unknown_gnu_atmega328.rs +++ b/compiler/rustc_target/src/spec/targets/avr_unknown_gnu_atmega328.rs @@ -1,5 +1,5 @@ use crate::spec::{base, Target}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { base::avr_gnu::target("atmega328", "-mmcu=atmega328") } diff --git a/compiler/rustc_target/src/spec/targets/bpfeb_unknown_none.rs b/compiler/rustc_target/src/spec/targets/bpfeb_unknown_none.rs index eb223af8cf44f..f4c3a35ced585 100644 --- a/compiler/rustc_target/src/spec/targets/bpfeb_unknown_none.rs +++ b/compiler/rustc_target/src/spec/targets/bpfeb_unknown_none.rs @@ -1,7 +1,7 @@ use crate::abi::Endian; use crate::spec::{base, Target}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { Target { llvm_target: "bpfeb".into(), metadata: crate::spec::TargetMetadata { diff --git a/compiler/rustc_target/src/spec/targets/bpfel_unknown_none.rs b/compiler/rustc_target/src/spec/targets/bpfel_unknown_none.rs index 12164adc00f25..6ef72c4021050 100644 --- a/compiler/rustc_target/src/spec/targets/bpfel_unknown_none.rs +++ b/compiler/rustc_target/src/spec/targets/bpfel_unknown_none.rs @@ -1,7 +1,7 @@ use crate::abi::Endian; use crate::spec::{base, Target}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { Target { llvm_target: "bpfel".into(), metadata: crate::spec::TargetMetadata { diff --git a/compiler/rustc_target/src/spec/targets/csky_unknown_linux_gnuabiv2.rs b/compiler/rustc_target/src/spec/targets/csky_unknown_linux_gnuabiv2.rs index e8a0b465e1562..61c246fc4cbf8 100644 --- a/compiler/rustc_target/src/spec/targets/csky_unknown_linux_gnuabiv2.rs +++ b/compiler/rustc_target/src/spec/targets/csky_unknown_linux_gnuabiv2.rs @@ -2,7 +2,7 @@ use crate::spec::{base, Cc, LinkerFlavor, Lld, Target, TargetOptions}; // This target is for glibc Linux on Csky -pub fn target() -> Target { +pub(crate) fn target() -> Target { Target { //https://github.com/llvm/llvm-project/blob/8b76aea8d8b1b71f6220bc2845abc749f18a19b7/clang/lib/Basic/Targets/CSKY.h llvm_target: "csky-unknown-linux-gnuabiv2".into(), diff --git a/compiler/rustc_target/src/spec/targets/csky_unknown_linux_gnuabiv2hf.rs b/compiler/rustc_target/src/spec/targets/csky_unknown_linux_gnuabiv2hf.rs index 99330ddc31894..91c33caae3e2a 100644 --- a/compiler/rustc_target/src/spec/targets/csky_unknown_linux_gnuabiv2hf.rs +++ b/compiler/rustc_target/src/spec/targets/csky_unknown_linux_gnuabiv2hf.rs @@ -2,7 +2,7 @@ use crate::spec::{base, Cc, LinkerFlavor, Lld, Target, TargetOptions}; // This target is for glibc Linux on Csky -pub fn target() -> Target { +pub(crate) fn target() -> Target { Target { //https://github.com/llvm/llvm-project/blob/8b76aea8d8b1b71f6220bc2845abc749f18a19b7/clang/lib/Basic/Targets/CSKY.h llvm_target: "csky-unknown-linux-gnuabiv2".into(), diff --git a/compiler/rustc_target/src/spec/targets/hexagon_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/targets/hexagon_unknown_linux_musl.rs index bd53979902969..cddc3a33f9fb3 100644 --- a/compiler/rustc_target/src/spec/targets/hexagon_unknown_linux_musl.rs +++ b/compiler/rustc_target/src/spec/targets/hexagon_unknown_linux_musl.rs @@ -1,6 +1,6 @@ use crate::spec::{base, Cc, LinkerFlavor, Target}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { let mut base = base::linux_musl::opts(); base.cpu = "hexagonv60".into(); base.max_atomic_width = Some(32); diff --git a/compiler/rustc_target/src/spec/targets/hexagon_unknown_none_elf.rs b/compiler/rustc_target/src/spec/targets/hexagon_unknown_none_elf.rs index cefd0bf6d67b7..730b19abd2bd4 100644 --- a/compiler/rustc_target/src/spec/targets/hexagon_unknown_none_elf.rs +++ b/compiler/rustc_target/src/spec/targets/hexagon_unknown_none_elf.rs @@ -1,6 +1,6 @@ use crate::spec::{PanicStrategy, Target, TargetOptions}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { Target { llvm_target: "hexagon-unknown-none-elf".into(), metadata: crate::spec::TargetMetadata { diff --git a/compiler/rustc_target/src/spec/targets/i386_apple_ios.rs b/compiler/rustc_target/src/spec/targets/i386_apple_ios.rs index b1b2b6cdffa8d..263393fd536ce 100644 --- a/compiler/rustc_target/src/spec/targets/i386_apple_ios.rs +++ b/compiler/rustc_target/src/spec/targets/i386_apple_ios.rs @@ -1,7 +1,7 @@ use crate::spec::base::apple::{ios_sim_llvm_target, opts, Arch, TargetAbi}; use crate::spec::{Target, TargetOptions}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { let arch = Arch::I386; // i386-apple-ios is a simulator target, even though it isn't declared // that way in the target name like the other ones... diff --git a/compiler/rustc_target/src/spec/targets/i586_pc_nto_qnx700.rs b/compiler/rustc_target/src/spec/targets/i586_pc_nto_qnx700.rs index 6c80ab6994ddc..cf0577d8cb01a 100644 --- a/compiler/rustc_target/src/spec/targets/i586_pc_nto_qnx700.rs +++ b/compiler/rustc_target/src/spec/targets/i586_pc_nto_qnx700.rs @@ -1,6 +1,6 @@ use crate::spec::{base, Cc, LinkerFlavor, Lld, StackProbeType, Target, TargetOptions}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { Target { llvm_target: "i586-pc-unknown".into(), metadata: crate::spec::TargetMetadata { diff --git a/compiler/rustc_target/src/spec/targets/i586_pc_windows_msvc.rs b/compiler/rustc_target/src/spec/targets/i586_pc_windows_msvc.rs index befb0f89f3b03..dd38f86bced2e 100644 --- a/compiler/rustc_target/src/spec/targets/i586_pc_windows_msvc.rs +++ b/compiler/rustc_target/src/spec/targets/i586_pc_windows_msvc.rs @@ -1,6 +1,6 @@ use crate::spec::Target; -pub fn target() -> Target { +pub(crate) fn target() -> Target { let mut base = super::i686_pc_windows_msvc::target(); base.cpu = "pentium".into(); base.llvm_target = "i586-pc-windows-msvc".into(); diff --git a/compiler/rustc_target/src/spec/targets/i586_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/targets/i586_unknown_linux_gnu.rs index b699a7af17749..e481e967ebfa2 100644 --- a/compiler/rustc_target/src/spec/targets/i586_unknown_linux_gnu.rs +++ b/compiler/rustc_target/src/spec/targets/i586_unknown_linux_gnu.rs @@ -1,6 +1,6 @@ use crate::spec::Target; -pub fn target() -> Target { +pub(crate) fn target() -> Target { let mut base = super::i686_unknown_linux_gnu::target(); base.cpu = "pentium".into(); base.llvm_target = "i586-unknown-linux-gnu".into(); diff --git a/compiler/rustc_target/src/spec/targets/i586_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/targets/i586_unknown_linux_musl.rs index 55a26eb004a7a..623422a89ea62 100644 --- a/compiler/rustc_target/src/spec/targets/i586_unknown_linux_musl.rs +++ b/compiler/rustc_target/src/spec/targets/i586_unknown_linux_musl.rs @@ -1,6 +1,6 @@ use crate::spec::Target; -pub fn target() -> Target { +pub(crate) fn target() -> Target { let mut base = super::i686_unknown_linux_musl::target(); base.cpu = "pentium".into(); base.llvm_target = "i586-unknown-linux-musl".into(); diff --git a/compiler/rustc_target/src/spec/targets/i586_unknown_netbsd.rs b/compiler/rustc_target/src/spec/targets/i586_unknown_netbsd.rs index de42549b7f8df..3c5ba157c1ecc 100644 --- a/compiler/rustc_target/src/spec/targets/i586_unknown_netbsd.rs +++ b/compiler/rustc_target/src/spec/targets/i586_unknown_netbsd.rs @@ -1,6 +1,6 @@ use crate::spec::{base, StackProbeType, Target, TargetOptions}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { let mut base = base::netbsd::opts(); base.cpu = "pentium".into(); base.max_atomic_width = Some(64); diff --git a/compiler/rustc_target/src/spec/targets/i686_apple_darwin.rs b/compiler/rustc_target/src/spec/targets/i686_apple_darwin.rs index 02f6bec4692fc..f173e8b7e4ae8 100644 --- a/compiler/rustc_target/src/spec/targets/i686_apple_darwin.rs +++ b/compiler/rustc_target/src/spec/targets/i686_apple_darwin.rs @@ -1,7 +1,7 @@ use crate::spec::base::apple::{macos_llvm_target, opts, Arch, TargetAbi}; use crate::spec::{Cc, FramePointer, LinkerFlavor, Lld, Target, TargetOptions}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { // ld64 only understands i386 and not i686 let arch = Arch::I386; let mut base = opts("macos", arch, TargetAbi::Normal); diff --git a/compiler/rustc_target/src/spec/targets/i686_linux_android.rs b/compiler/rustc_target/src/spec/targets/i686_linux_android.rs index fc313e575be6e..bce41976a9697 100644 --- a/compiler/rustc_target/src/spec/targets/i686_linux_android.rs +++ b/compiler/rustc_target/src/spec/targets/i686_linux_android.rs @@ -3,7 +3,7 @@ use crate::spec::{base, SanitizerSet, StackProbeType, Target, TargetOptions}; // See https://developer.android.com/ndk/guides/abis.html#x86 // for target ABI requirements. -pub fn target() -> Target { +pub(crate) fn target() -> Target { let mut base = base::android::opts(); base.max_atomic_width = Some(64); diff --git a/compiler/rustc_target/src/spec/targets/i686_pc_windows_gnu.rs b/compiler/rustc_target/src/spec/targets/i686_pc_windows_gnu.rs index 4b0f4bf3ecd25..7288359f564af 100644 --- a/compiler/rustc_target/src/spec/targets/i686_pc_windows_gnu.rs +++ b/compiler/rustc_target/src/spec/targets/i686_pc_windows_gnu.rs @@ -1,6 +1,6 @@ use crate::spec::{base, Cc, FramePointer, LinkerFlavor, Lld, Target}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { let mut base = base::windows_gnu::opts(); base.cpu = "pentium4".into(); base.max_atomic_width = Some(64); diff --git a/compiler/rustc_target/src/spec/targets/i686_pc_windows_gnullvm.rs b/compiler/rustc_target/src/spec/targets/i686_pc_windows_gnullvm.rs index 5bb082014298a..a38e67b96f0db 100644 --- a/compiler/rustc_target/src/spec/targets/i686_pc_windows_gnullvm.rs +++ b/compiler/rustc_target/src/spec/targets/i686_pc_windows_gnullvm.rs @@ -1,6 +1,6 @@ use crate::spec::{base, Cc, FramePointer, LinkerFlavor, Lld, Target}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { let mut base = base::windows_gnullvm::opts(); base.cpu = "pentium4".into(); base.max_atomic_width = Some(64); diff --git a/compiler/rustc_target/src/spec/targets/i686_pc_windows_msvc.rs b/compiler/rustc_target/src/spec/targets/i686_pc_windows_msvc.rs index 970b43ad109ba..a8e1ad45014ac 100644 --- a/compiler/rustc_target/src/spec/targets/i686_pc_windows_msvc.rs +++ b/compiler/rustc_target/src/spec/targets/i686_pc_windows_msvc.rs @@ -1,6 +1,6 @@ use crate::spec::{base, LinkerFlavor, Lld, SanitizerSet, Target}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { let mut base = base::windows_msvc::opts(); base.cpu = "pentium4".into(); base.max_atomic_width = Some(64); diff --git a/compiler/rustc_target/src/spec/targets/i686_unknown_freebsd.rs b/compiler/rustc_target/src/spec/targets/i686_unknown_freebsd.rs index cce21fcacb1c5..8ba58dfd705ba 100644 --- a/compiler/rustc_target/src/spec/targets/i686_unknown_freebsd.rs +++ b/compiler/rustc_target/src/spec/targets/i686_unknown_freebsd.rs @@ -1,6 +1,6 @@ use crate::spec::{base, Cc, LinkerFlavor, Lld, StackProbeType, Target}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { let mut base = base::freebsd::opts(); base.cpu = "pentium4".into(); base.max_atomic_width = Some(64); diff --git a/compiler/rustc_target/src/spec/targets/i686_unknown_haiku.rs b/compiler/rustc_target/src/spec/targets/i686_unknown_haiku.rs index 84ef00f06c810..b2316fd3bf422 100644 --- a/compiler/rustc_target/src/spec/targets/i686_unknown_haiku.rs +++ b/compiler/rustc_target/src/spec/targets/i686_unknown_haiku.rs @@ -1,6 +1,6 @@ use crate::spec::{base, Cc, LinkerFlavor, Lld, StackProbeType, Target}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { let mut base = base::haiku::opts(); base.cpu = "pentium4".into(); base.max_atomic_width = Some(64); diff --git a/compiler/rustc_target/src/spec/targets/i686_unknown_hurd_gnu.rs b/compiler/rustc_target/src/spec/targets/i686_unknown_hurd_gnu.rs index ad8c0f7f582e7..2e303ff402fa6 100644 --- a/compiler/rustc_target/src/spec/targets/i686_unknown_hurd_gnu.rs +++ b/compiler/rustc_target/src/spec/targets/i686_unknown_hurd_gnu.rs @@ -1,6 +1,6 @@ use crate::spec::{base, Cc, LinkerFlavor, Lld, StackProbeType, Target}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { let mut base = base::hurd_gnu::opts(); base.cpu = "pentiumpro".into(); base.max_atomic_width = Some(64); diff --git a/compiler/rustc_target/src/spec/targets/i686_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/targets/i686_unknown_linux_gnu.rs index 5584435a0ad9d..15bc4da1775a0 100644 --- a/compiler/rustc_target/src/spec/targets/i686_unknown_linux_gnu.rs +++ b/compiler/rustc_target/src/spec/targets/i686_unknown_linux_gnu.rs @@ -1,6 +1,6 @@ use crate::spec::{base, Cc, LinkerFlavor, Lld, SanitizerSet, StackProbeType, Target}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { let mut base = base::linux_gnu::opts(); base.cpu = "pentium4".into(); base.max_atomic_width = Some(64); diff --git a/compiler/rustc_target/src/spec/targets/i686_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/targets/i686_unknown_linux_musl.rs index d1ab1f73b511b..8dd08a9567b46 100644 --- a/compiler/rustc_target/src/spec/targets/i686_unknown_linux_musl.rs +++ b/compiler/rustc_target/src/spec/targets/i686_unknown_linux_musl.rs @@ -1,6 +1,6 @@ use crate::spec::{base, Cc, FramePointer, LinkerFlavor, Lld, StackProbeType, Target}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { let mut base = base::linux_musl::opts(); base.cpu = "pentium4".into(); base.max_atomic_width = Some(64); diff --git a/compiler/rustc_target/src/spec/targets/i686_unknown_netbsd.rs b/compiler/rustc_target/src/spec/targets/i686_unknown_netbsd.rs index 255148fca9a31..02a95ee6626f2 100644 --- a/compiler/rustc_target/src/spec/targets/i686_unknown_netbsd.rs +++ b/compiler/rustc_target/src/spec/targets/i686_unknown_netbsd.rs @@ -1,6 +1,6 @@ use crate::spec::{base, Cc, LinkerFlavor, Lld, StackProbeType, Target, TargetOptions}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { let mut base = base::netbsd::opts(); base.cpu = "pentium4".into(); base.max_atomic_width = Some(64); diff --git a/compiler/rustc_target/src/spec/targets/i686_unknown_openbsd.rs b/compiler/rustc_target/src/spec/targets/i686_unknown_openbsd.rs index d6df801234c66..b8c9efc7c471a 100644 --- a/compiler/rustc_target/src/spec/targets/i686_unknown_openbsd.rs +++ b/compiler/rustc_target/src/spec/targets/i686_unknown_openbsd.rs @@ -1,6 +1,6 @@ use crate::spec::{base, Cc, LinkerFlavor, Lld, StackProbeType, Target}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { let mut base = base::openbsd::opts(); base.cpu = "pentium4".into(); base.max_atomic_width = Some(64); diff --git a/compiler/rustc_target/src/spec/targets/i686_unknown_redox.rs b/compiler/rustc_target/src/spec/targets/i686_unknown_redox.rs index 83252fadb78ea..0e00249d66cf7 100644 --- a/compiler/rustc_target/src/spec/targets/i686_unknown_redox.rs +++ b/compiler/rustc_target/src/spec/targets/i686_unknown_redox.rs @@ -1,6 +1,6 @@ use crate::spec::{base, Cc, LinkerFlavor, Lld, StackProbeType, Target}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { let mut base = base::redox::opts(); base.cpu = "pentiumpro".into(); base.plt_by_default = false; diff --git a/compiler/rustc_target/src/spec/targets/i686_unknown_uefi.rs b/compiler/rustc_target/src/spec/targets/i686_unknown_uefi.rs index b92fc2e759a30..3cda78003edbe 100644 --- a/compiler/rustc_target/src/spec/targets/i686_unknown_uefi.rs +++ b/compiler/rustc_target/src/spec/targets/i686_unknown_uefi.rs @@ -7,7 +7,7 @@ use crate::spec::{base, Target}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { let mut base = base::uefi_msvc::opts(); base.cpu = "pentium4".into(); base.max_atomic_width = Some(64); diff --git a/compiler/rustc_target/src/spec/targets/i686_uwp_windows_gnu.rs b/compiler/rustc_target/src/spec/targets/i686_uwp_windows_gnu.rs index 851bea80fb830..901c9fc378d21 100644 --- a/compiler/rustc_target/src/spec/targets/i686_uwp_windows_gnu.rs +++ b/compiler/rustc_target/src/spec/targets/i686_uwp_windows_gnu.rs @@ -1,6 +1,6 @@ use crate::spec::{base, Cc, FramePointer, LinkerFlavor, Lld, Target}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { let mut base = base::windows_uwp_gnu::opts(); base.cpu = "pentium4".into(); base.max_atomic_width = Some(64); diff --git a/compiler/rustc_target/src/spec/targets/i686_uwp_windows_msvc.rs b/compiler/rustc_target/src/spec/targets/i686_uwp_windows_msvc.rs index 28bd2aae8e711..c7703666ae032 100644 --- a/compiler/rustc_target/src/spec/targets/i686_uwp_windows_msvc.rs +++ b/compiler/rustc_target/src/spec/targets/i686_uwp_windows_msvc.rs @@ -1,6 +1,6 @@ use crate::spec::{base, Target}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { let mut base = base::windows_uwp_msvc::opts(); base.cpu = "pentium4".into(); base.max_atomic_width = Some(64); diff --git a/compiler/rustc_target/src/spec/targets/i686_win7_windows_msvc.rs b/compiler/rustc_target/src/spec/targets/i686_win7_windows_msvc.rs index cd488d0532c2f..79302cdc0a1a3 100644 --- a/compiler/rustc_target/src/spec/targets/i686_win7_windows_msvc.rs +++ b/compiler/rustc_target/src/spec/targets/i686_win7_windows_msvc.rs @@ -1,6 +1,6 @@ use crate::spec::{base, LinkerFlavor, Lld, Target}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { let mut base = base::windows_msvc::opts(); base.cpu = "pentium4".into(); base.max_atomic_width = Some(64); diff --git a/compiler/rustc_target/src/spec/targets/i686_wrs_vxworks.rs b/compiler/rustc_target/src/spec/targets/i686_wrs_vxworks.rs index 973c75eeca6e1..ba669334e7f4d 100644 --- a/compiler/rustc_target/src/spec/targets/i686_wrs_vxworks.rs +++ b/compiler/rustc_target/src/spec/targets/i686_wrs_vxworks.rs @@ -1,6 +1,6 @@ use crate::spec::{base, Cc, LinkerFlavor, Lld, StackProbeType, Target}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { let mut base = base::vxworks::opts(); base.cpu = "pentium4".into(); base.max_atomic_width = Some(64); diff --git a/compiler/rustc_target/src/spec/targets/loongarch64_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/targets/loongarch64_unknown_linux_gnu.rs index 6f0bb449c16c0..d33c7af92c656 100644 --- a/compiler/rustc_target/src/spec/targets/loongarch64_unknown_linux_gnu.rs +++ b/compiler/rustc_target/src/spec/targets/loongarch64_unknown_linux_gnu.rs @@ -1,6 +1,6 @@ use crate::spec::{base, Target, TargetOptions}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { Target { llvm_target: "loongarch64-unknown-linux-gnu".into(), metadata: crate::spec::TargetMetadata { diff --git a/compiler/rustc_target/src/spec/targets/loongarch64_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/targets/loongarch64_unknown_linux_musl.rs index f7a6e0bd857f5..5540e71ad4f31 100644 --- a/compiler/rustc_target/src/spec/targets/loongarch64_unknown_linux_musl.rs +++ b/compiler/rustc_target/src/spec/targets/loongarch64_unknown_linux_musl.rs @@ -1,6 +1,6 @@ use crate::spec::{base, Target, TargetOptions}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { Target { llvm_target: "loongarch64-unknown-linux-musl".into(), metadata: crate::spec::TargetMetadata { diff --git a/compiler/rustc_target/src/spec/targets/loongarch64_unknown_none.rs b/compiler/rustc_target/src/spec/targets/loongarch64_unknown_none.rs index c7f47da6972e7..5628519026831 100644 --- a/compiler/rustc_target/src/spec/targets/loongarch64_unknown_none.rs +++ b/compiler/rustc_target/src/spec/targets/loongarch64_unknown_none.rs @@ -2,7 +2,7 @@ use crate::spec::{ Cc, CodeModel, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, TargetOptions, }; -pub fn target() -> Target { +pub(crate) fn target() -> Target { Target { llvm_target: "loongarch64-unknown-none".into(), metadata: crate::spec::TargetMetadata { diff --git a/compiler/rustc_target/src/spec/targets/loongarch64_unknown_none_softfloat.rs b/compiler/rustc_target/src/spec/targets/loongarch64_unknown_none_softfloat.rs index 21e4f4a2b057b..7e57715ce7a73 100644 --- a/compiler/rustc_target/src/spec/targets/loongarch64_unknown_none_softfloat.rs +++ b/compiler/rustc_target/src/spec/targets/loongarch64_unknown_none_softfloat.rs @@ -2,7 +2,7 @@ use crate::spec::{ Cc, CodeModel, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, TargetOptions, }; -pub fn target() -> Target { +pub(crate) fn target() -> Target { Target { llvm_target: "loongarch64-unknown-none".into(), metadata: crate::spec::TargetMetadata { diff --git a/compiler/rustc_target/src/spec/targets/m68k_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/targets/m68k_unknown_linux_gnu.rs index 7cff0efd112c8..9d9f6145e2f5d 100644 --- a/compiler/rustc_target/src/spec/targets/m68k_unknown_linux_gnu.rs +++ b/compiler/rustc_target/src/spec/targets/m68k_unknown_linux_gnu.rs @@ -1,7 +1,7 @@ use crate::abi::Endian; use crate::spec::{base, Target, TargetOptions}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { let mut base = base::linux_gnu::opts(); base.cpu = "M68020".into(); base.max_atomic_width = Some(32); diff --git a/compiler/rustc_target/src/spec/targets/mips64_openwrt_linux_musl.rs b/compiler/rustc_target/src/spec/targets/mips64_openwrt_linux_musl.rs index c3235bf994fa0..72577749ac64f 100644 --- a/compiler/rustc_target/src/spec/targets/mips64_openwrt_linux_musl.rs +++ b/compiler/rustc_target/src/spec/targets/mips64_openwrt_linux_musl.rs @@ -3,7 +3,7 @@ use crate::abi::Endian; use crate::spec::{base, Target, TargetOptions}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { let mut base = base::linux_musl::opts(); base.cpu = "mips64r2".into(); base.features = "+mips64r2,+soft-float".into(); diff --git a/compiler/rustc_target/src/spec/targets/mips64_unknown_linux_gnuabi64.rs b/compiler/rustc_target/src/spec/targets/mips64_unknown_linux_gnuabi64.rs index cdf4ffb7f9eb5..1fad6be2f8df3 100644 --- a/compiler/rustc_target/src/spec/targets/mips64_unknown_linux_gnuabi64.rs +++ b/compiler/rustc_target/src/spec/targets/mips64_unknown_linux_gnuabi64.rs @@ -1,7 +1,7 @@ use crate::abi::Endian; use crate::spec::{base, Target, TargetOptions}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { Target { llvm_target: "mips64-unknown-linux-gnuabi64".into(), metadata: crate::spec::TargetMetadata { diff --git a/compiler/rustc_target/src/spec/targets/mips64_unknown_linux_muslabi64.rs b/compiler/rustc_target/src/spec/targets/mips64_unknown_linux_muslabi64.rs index 463f7dc47f72f..7627131bc2fe6 100644 --- a/compiler/rustc_target/src/spec/targets/mips64_unknown_linux_muslabi64.rs +++ b/compiler/rustc_target/src/spec/targets/mips64_unknown_linux_muslabi64.rs @@ -1,7 +1,7 @@ use crate::abi::Endian; use crate::spec::{base, Target, TargetOptions}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { let mut base = base::linux_musl::opts(); base.cpu = "mips64r2".into(); base.features = "+mips64r2".into(); diff --git a/compiler/rustc_target/src/spec/targets/mips64el_unknown_linux_gnuabi64.rs b/compiler/rustc_target/src/spec/targets/mips64el_unknown_linux_gnuabi64.rs index ad77a02c0630e..f93e5676b051d 100644 --- a/compiler/rustc_target/src/spec/targets/mips64el_unknown_linux_gnuabi64.rs +++ b/compiler/rustc_target/src/spec/targets/mips64el_unknown_linux_gnuabi64.rs @@ -1,6 +1,6 @@ use crate::spec::{base, Target, TargetOptions}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { Target { llvm_target: "mips64el-unknown-linux-gnuabi64".into(), metadata: crate::spec::TargetMetadata { diff --git a/compiler/rustc_target/src/spec/targets/mips64el_unknown_linux_muslabi64.rs b/compiler/rustc_target/src/spec/targets/mips64el_unknown_linux_muslabi64.rs index 83f5c7ea37d63..6fbb4f40024d9 100644 --- a/compiler/rustc_target/src/spec/targets/mips64el_unknown_linux_muslabi64.rs +++ b/compiler/rustc_target/src/spec/targets/mips64el_unknown_linux_muslabi64.rs @@ -1,6 +1,6 @@ use crate::spec::{base, Target, TargetOptions}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { let mut base = base::linux_musl::opts(); base.cpu = "mips64r2".into(); base.features = "+mips64r2".into(); diff --git a/compiler/rustc_target/src/spec/targets/mips_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/targets/mips_unknown_linux_gnu.rs index 0bdfd6ee6b09d..778b0041214db 100644 --- a/compiler/rustc_target/src/spec/targets/mips_unknown_linux_gnu.rs +++ b/compiler/rustc_target/src/spec/targets/mips_unknown_linux_gnu.rs @@ -1,7 +1,7 @@ use crate::abi::Endian; use crate::spec::{base, Target, TargetOptions}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { Target { llvm_target: "mips-unknown-linux-gnu".into(), metadata: crate::spec::TargetMetadata { diff --git a/compiler/rustc_target/src/spec/targets/mips_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/targets/mips_unknown_linux_musl.rs index 8e27c9936c561..2cce3271c57f8 100644 --- a/compiler/rustc_target/src/spec/targets/mips_unknown_linux_musl.rs +++ b/compiler/rustc_target/src/spec/targets/mips_unknown_linux_musl.rs @@ -1,7 +1,7 @@ use crate::abi::Endian; use crate::spec::{base, Target, TargetOptions}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { let mut base = base::linux_musl::opts(); base.cpu = "mips32r2".into(); base.features = "+mips32r2,+soft-float".into(); diff --git a/compiler/rustc_target/src/spec/targets/mips_unknown_linux_uclibc.rs b/compiler/rustc_target/src/spec/targets/mips_unknown_linux_uclibc.rs index 852e1d9376d08..ef7d6bf82e321 100644 --- a/compiler/rustc_target/src/spec/targets/mips_unknown_linux_uclibc.rs +++ b/compiler/rustc_target/src/spec/targets/mips_unknown_linux_uclibc.rs @@ -1,7 +1,7 @@ use crate::abi::Endian; use crate::spec::{base, Target, TargetOptions}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { Target { llvm_target: "mips-unknown-linux-uclibc".into(), metadata: crate::spec::TargetMetadata { diff --git a/compiler/rustc_target/src/spec/targets/mipsel_sony_psp.rs b/compiler/rustc_target/src/spec/targets/mipsel_sony_psp.rs index 9d3f4d9f79501..850808b4c7ba1 100644 --- a/compiler/rustc_target/src/spec/targets/mipsel_sony_psp.rs +++ b/compiler/rustc_target/src/spec/targets/mipsel_sony_psp.rs @@ -3,7 +3,7 @@ use crate::spec::{cvs, Cc, LinkerFlavor, Lld, RelocModel, Target, TargetOptions} // The PSP has custom linker requirements. const LINKER_SCRIPT: &str = include_str!("./mipsel_sony_psp_linker_script.ld"); -pub fn target() -> Target { +pub(crate) fn target() -> Target { let pre_link_args = TargetOptions::link_args( LinkerFlavor::Gnu(Cc::No, Lld::No), &["--emit-relocs", "--nmagic"], diff --git a/compiler/rustc_target/src/spec/targets/mipsel_sony_psx.rs b/compiler/rustc_target/src/spec/targets/mipsel_sony_psx.rs index c0b99a68b0d07..761495b2a29fb 100644 --- a/compiler/rustc_target/src/spec/targets/mipsel_sony_psx.rs +++ b/compiler/rustc_target/src/spec/targets/mipsel_sony_psx.rs @@ -1,6 +1,6 @@ use crate::spec::{cvs, Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, TargetOptions}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { Target { llvm_target: "mipsel-sony-psx".into(), metadata: crate::spec::TargetMetadata { diff --git a/compiler/rustc_target/src/spec/targets/mipsel_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/targets/mipsel_unknown_linux_gnu.rs index 8fe4548a3ad95..2784b3714690c 100644 --- a/compiler/rustc_target/src/spec/targets/mipsel_unknown_linux_gnu.rs +++ b/compiler/rustc_target/src/spec/targets/mipsel_unknown_linux_gnu.rs @@ -1,6 +1,6 @@ use crate::spec::{base, Target, TargetOptions}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { Target { llvm_target: "mipsel-unknown-linux-gnu".into(), metadata: crate::spec::TargetMetadata { diff --git a/compiler/rustc_target/src/spec/targets/mipsel_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/targets/mipsel_unknown_linux_musl.rs index 43914a2330800..1b2d8e9a105f2 100644 --- a/compiler/rustc_target/src/spec/targets/mipsel_unknown_linux_musl.rs +++ b/compiler/rustc_target/src/spec/targets/mipsel_unknown_linux_musl.rs @@ -1,6 +1,6 @@ use crate::spec::{base, Target, TargetOptions}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { let mut base = base::linux_musl::opts(); base.cpu = "mips32r2".into(); base.features = "+mips32r2,+soft-float".into(); diff --git a/compiler/rustc_target/src/spec/targets/mipsel_unknown_linux_uclibc.rs b/compiler/rustc_target/src/spec/targets/mipsel_unknown_linux_uclibc.rs index 6150654c0817e..21f03a40ec2d5 100644 --- a/compiler/rustc_target/src/spec/targets/mipsel_unknown_linux_uclibc.rs +++ b/compiler/rustc_target/src/spec/targets/mipsel_unknown_linux_uclibc.rs @@ -1,6 +1,6 @@ use crate::spec::{base, Target, TargetOptions}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { Target { llvm_target: "mipsel-unknown-linux-uclibc".into(), metadata: crate::spec::TargetMetadata { diff --git a/compiler/rustc_target/src/spec/targets/mipsel_unknown_netbsd.rs b/compiler/rustc_target/src/spec/targets/mipsel_unknown_netbsd.rs index 03501aa76a83f..ea2fb2e7f3aad 100644 --- a/compiler/rustc_target/src/spec/targets/mipsel_unknown_netbsd.rs +++ b/compiler/rustc_target/src/spec/targets/mipsel_unknown_netbsd.rs @@ -1,7 +1,7 @@ use crate::abi::Endian; use crate::spec::{base, Target, TargetOptions}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { let mut base = base::netbsd::opts(); base.max_atomic_width = Some(32); base.cpu = "mips32".into(); diff --git a/compiler/rustc_target/src/spec/targets/mipsel_unknown_none.rs b/compiler/rustc_target/src/spec/targets/mipsel_unknown_none.rs index 81aac3ce0b87f..bb8eb24908c23 100644 --- a/compiler/rustc_target/src/spec/targets/mipsel_unknown_none.rs +++ b/compiler/rustc_target/src/spec/targets/mipsel_unknown_none.rs @@ -4,7 +4,7 @@ use crate::spec::{Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, TargetOptions}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { Target { llvm_target: "mipsel-unknown-none".into(), metadata: crate::spec::TargetMetadata { diff --git a/compiler/rustc_target/src/spec/targets/mipsisa32r6_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/targets/mipsisa32r6_unknown_linux_gnu.rs index 2ed520e9f48ff..5c07e9ea6dddb 100644 --- a/compiler/rustc_target/src/spec/targets/mipsisa32r6_unknown_linux_gnu.rs +++ b/compiler/rustc_target/src/spec/targets/mipsisa32r6_unknown_linux_gnu.rs @@ -1,7 +1,7 @@ use crate::abi::Endian; use crate::spec::{base, Target, TargetOptions}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { Target { llvm_target: "mipsisa32r6-unknown-linux-gnu".into(), metadata: crate::spec::TargetMetadata { diff --git a/compiler/rustc_target/src/spec/targets/mipsisa32r6el_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/targets/mipsisa32r6el_unknown_linux_gnu.rs index de30c5b35b75b..63b3cc47ffc26 100644 --- a/compiler/rustc_target/src/spec/targets/mipsisa32r6el_unknown_linux_gnu.rs +++ b/compiler/rustc_target/src/spec/targets/mipsisa32r6el_unknown_linux_gnu.rs @@ -1,6 +1,6 @@ use crate::spec::{base, Target, TargetOptions}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { Target { llvm_target: "mipsisa32r6el-unknown-linux-gnu".into(), metadata: crate::spec::TargetMetadata { diff --git a/compiler/rustc_target/src/spec/targets/mipsisa64r6_unknown_linux_gnuabi64.rs b/compiler/rustc_target/src/spec/targets/mipsisa64r6_unknown_linux_gnuabi64.rs index 4178a991e14fe..7f5e2edb03613 100644 --- a/compiler/rustc_target/src/spec/targets/mipsisa64r6_unknown_linux_gnuabi64.rs +++ b/compiler/rustc_target/src/spec/targets/mipsisa64r6_unknown_linux_gnuabi64.rs @@ -1,7 +1,7 @@ use crate::abi::Endian; use crate::spec::{base, Target, TargetOptions}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { Target { llvm_target: "mipsisa64r6-unknown-linux-gnuabi64".into(), metadata: crate::spec::TargetMetadata { diff --git a/compiler/rustc_target/src/spec/targets/mipsisa64r6el_unknown_linux_gnuabi64.rs b/compiler/rustc_target/src/spec/targets/mipsisa64r6el_unknown_linux_gnuabi64.rs index 8e50373bd124b..a2d807bcfe1b9 100644 --- a/compiler/rustc_target/src/spec/targets/mipsisa64r6el_unknown_linux_gnuabi64.rs +++ b/compiler/rustc_target/src/spec/targets/mipsisa64r6el_unknown_linux_gnuabi64.rs @@ -1,6 +1,6 @@ use crate::spec::{base, Target, TargetOptions}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { Target { llvm_target: "mipsisa64r6el-unknown-linux-gnuabi64".into(), metadata: crate::spec::TargetMetadata { diff --git a/compiler/rustc_target/src/spec/targets/msp430_none_elf.rs b/compiler/rustc_target/src/spec/targets/msp430_none_elf.rs index de476741defd6..5bc5f79d1b6c6 100644 --- a/compiler/rustc_target/src/spec/targets/msp430_none_elf.rs +++ b/compiler/rustc_target/src/spec/targets/msp430_none_elf.rs @@ -1,6 +1,6 @@ use crate::spec::{cvs, Cc, LinkerFlavor, PanicStrategy, RelocModel, Target, TargetOptions}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { Target { llvm_target: "msp430-none-elf".into(), metadata: crate::spec::TargetMetadata { diff --git a/compiler/rustc_target/src/spec/targets/nvptx64_nvidia_cuda.rs b/compiler/rustc_target/src/spec/targets/nvptx64_nvidia_cuda.rs index ec5edfb6e42c2..289251e906a0c 100644 --- a/compiler/rustc_target/src/spec/targets/nvptx64_nvidia_cuda.rs +++ b/compiler/rustc_target/src/spec/targets/nvptx64_nvidia_cuda.rs @@ -2,7 +2,7 @@ use crate::spec::{ LinkSelfContainedDefault, LinkerFlavor, MergeFunctions, PanicStrategy, Target, TargetOptions, }; -pub fn target() -> Target { +pub(crate) fn target() -> Target { Target { arch: "nvptx64".into(), data_layout: "e-i64:64-i128:128-v16:16-v32:32-n16:32:64".into(), diff --git a/compiler/rustc_target/src/spec/targets/powerpc64_ibm_aix.rs b/compiler/rustc_target/src/spec/targets/powerpc64_ibm_aix.rs index bda43e7a2b0f1..0f90efb4bb3db 100644 --- a/compiler/rustc_target/src/spec/targets/powerpc64_ibm_aix.rs +++ b/compiler/rustc_target/src/spec/targets/powerpc64_ibm_aix.rs @@ -1,6 +1,6 @@ use crate::spec::{base, Cc, LinkerFlavor, Target}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { let mut base = base::aix::opts(); base.max_atomic_width = Some(64); base.add_pre_link_args( diff --git a/compiler/rustc_target/src/spec/targets/powerpc64_unknown_freebsd.rs b/compiler/rustc_target/src/spec/targets/powerpc64_unknown_freebsd.rs index 6eb5bba0fcd99..89afe2343768e 100644 --- a/compiler/rustc_target/src/spec/targets/powerpc64_unknown_freebsd.rs +++ b/compiler/rustc_target/src/spec/targets/powerpc64_unknown_freebsd.rs @@ -1,7 +1,7 @@ use crate::abi::Endian; use crate::spec::{base, Cc, LinkerFlavor, Lld, StackProbeType, Target, TargetOptions}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { let mut base = base::freebsd::opts(); base.cpu = "ppc64".into(); base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m64"]); diff --git a/compiler/rustc_target/src/spec/targets/powerpc64_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/targets/powerpc64_unknown_linux_gnu.rs index 53b84479a4919..e39849c9b1883 100644 --- a/compiler/rustc_target/src/spec/targets/powerpc64_unknown_linux_gnu.rs +++ b/compiler/rustc_target/src/spec/targets/powerpc64_unknown_linux_gnu.rs @@ -1,7 +1,7 @@ use crate::abi::Endian; use crate::spec::{base, Cc, LinkerFlavor, Lld, StackProbeType, Target, TargetOptions}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { let mut base = base::linux_gnu::opts(); base.cpu = "ppc64".into(); base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m64"]); diff --git a/compiler/rustc_target/src/spec/targets/powerpc64_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/targets/powerpc64_unknown_linux_musl.rs index 0d0484dd17480..24a56f917e5d5 100644 --- a/compiler/rustc_target/src/spec/targets/powerpc64_unknown_linux_musl.rs +++ b/compiler/rustc_target/src/spec/targets/powerpc64_unknown_linux_musl.rs @@ -1,7 +1,7 @@ use crate::abi::Endian; use crate::spec::{base, Cc, LinkerFlavor, Lld, StackProbeType, Target, TargetOptions}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { let mut base = base::linux_musl::opts(); base.cpu = "ppc64".into(); base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m64"]); diff --git a/compiler/rustc_target/src/spec/targets/powerpc64_unknown_openbsd.rs b/compiler/rustc_target/src/spec/targets/powerpc64_unknown_openbsd.rs index 2922c921e17d1..1dab74e93762e 100644 --- a/compiler/rustc_target/src/spec/targets/powerpc64_unknown_openbsd.rs +++ b/compiler/rustc_target/src/spec/targets/powerpc64_unknown_openbsd.rs @@ -1,7 +1,7 @@ use crate::abi::Endian; use crate::spec::{base, Cc, LinkerFlavor, Lld, StackProbeType, Target, TargetOptions}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { let mut base = base::openbsd::opts(); base.cpu = "ppc64".into(); base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m64"]); diff --git a/compiler/rustc_target/src/spec/targets/powerpc64_wrs_vxworks.rs b/compiler/rustc_target/src/spec/targets/powerpc64_wrs_vxworks.rs index dd2ec27420762..1029a135e4aa7 100644 --- a/compiler/rustc_target/src/spec/targets/powerpc64_wrs_vxworks.rs +++ b/compiler/rustc_target/src/spec/targets/powerpc64_wrs_vxworks.rs @@ -1,7 +1,7 @@ use crate::abi::Endian; use crate::spec::{base, Cc, LinkerFlavor, Lld, StackProbeType, Target, TargetOptions}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { let mut base = base::vxworks::opts(); base.cpu = "ppc64".into(); base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m64"]); diff --git a/compiler/rustc_target/src/spec/targets/powerpc64le_unknown_freebsd.rs b/compiler/rustc_target/src/spec/targets/powerpc64le_unknown_freebsd.rs index ea295cf169e0e..3c9d01e2d18d0 100644 --- a/compiler/rustc_target/src/spec/targets/powerpc64le_unknown_freebsd.rs +++ b/compiler/rustc_target/src/spec/targets/powerpc64le_unknown_freebsd.rs @@ -1,6 +1,6 @@ use crate::spec::{base, Cc, LinkerFlavor, Lld, StackProbeType, Target, TargetOptions}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { let mut base = base::freebsd::opts(); base.cpu = "ppc64le".into(); base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m64"]); diff --git a/compiler/rustc_target/src/spec/targets/powerpc64le_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/targets/powerpc64le_unknown_linux_gnu.rs index dc70bd238a749..df8f9f07c2f3e 100644 --- a/compiler/rustc_target/src/spec/targets/powerpc64le_unknown_linux_gnu.rs +++ b/compiler/rustc_target/src/spec/targets/powerpc64le_unknown_linux_gnu.rs @@ -1,6 +1,6 @@ use crate::spec::{base, Cc, LinkerFlavor, Lld, StackProbeType, Target, TargetOptions}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { let mut base = base::linux_gnu::opts(); base.cpu = "ppc64le".into(); base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m64"]); diff --git a/compiler/rustc_target/src/spec/targets/powerpc64le_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/targets/powerpc64le_unknown_linux_musl.rs index dbfbd69b95b17..909a25304f46f 100644 --- a/compiler/rustc_target/src/spec/targets/powerpc64le_unknown_linux_musl.rs +++ b/compiler/rustc_target/src/spec/targets/powerpc64le_unknown_linux_musl.rs @@ -1,6 +1,6 @@ use crate::spec::{base, Cc, LinkerFlavor, Lld, StackProbeType, Target, TargetOptions}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { let mut base = base::linux_musl::opts(); base.cpu = "ppc64le".into(); base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m64"]); diff --git a/compiler/rustc_target/src/spec/targets/powerpc_unknown_freebsd.rs b/compiler/rustc_target/src/spec/targets/powerpc_unknown_freebsd.rs index 2f7acccfae83b..e8f09d70cc844 100644 --- a/compiler/rustc_target/src/spec/targets/powerpc_unknown_freebsd.rs +++ b/compiler/rustc_target/src/spec/targets/powerpc_unknown_freebsd.rs @@ -1,7 +1,7 @@ use crate::abi::Endian; use crate::spec::{base, Cc, LinkerFlavor, Lld, StackProbeType, Target, TargetOptions}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { let mut base = base::freebsd::opts(); // Extra hint to linker that we are generating secure-PLT code. base.add_pre_link_args( diff --git a/compiler/rustc_target/src/spec/targets/powerpc_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/targets/powerpc_unknown_linux_gnu.rs index 2ecafbb08bc33..9e5cea6eff586 100644 --- a/compiler/rustc_target/src/spec/targets/powerpc_unknown_linux_gnu.rs +++ b/compiler/rustc_target/src/spec/targets/powerpc_unknown_linux_gnu.rs @@ -1,7 +1,7 @@ use crate::abi::Endian; use crate::spec::{base, Cc, LinkerFlavor, Lld, StackProbeType, Target, TargetOptions}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { let mut base = base::linux_gnu::opts(); base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m32"]); base.max_atomic_width = Some(32); diff --git a/compiler/rustc_target/src/spec/targets/powerpc_unknown_linux_gnuspe.rs b/compiler/rustc_target/src/spec/targets/powerpc_unknown_linux_gnuspe.rs index 04b2309fdc887..dbea70168a52a 100644 --- a/compiler/rustc_target/src/spec/targets/powerpc_unknown_linux_gnuspe.rs +++ b/compiler/rustc_target/src/spec/targets/powerpc_unknown_linux_gnuspe.rs @@ -1,7 +1,7 @@ use crate::abi::Endian; use crate::spec::{base, Cc, LinkerFlavor, Lld, StackProbeType, Target, TargetOptions}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { let mut base = base::linux_gnu::opts(); base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-mspe"]); base.max_atomic_width = Some(32); diff --git a/compiler/rustc_target/src/spec/targets/powerpc_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/targets/powerpc_unknown_linux_musl.rs index 108e468eb66ba..86840f16d902c 100644 --- a/compiler/rustc_target/src/spec/targets/powerpc_unknown_linux_musl.rs +++ b/compiler/rustc_target/src/spec/targets/powerpc_unknown_linux_musl.rs @@ -1,7 +1,7 @@ use crate::abi::Endian; use crate::spec::{base, Cc, LinkerFlavor, Lld, StackProbeType, Target, TargetOptions}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { let mut base = base::linux_musl::opts(); base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m32"]); base.max_atomic_width = Some(32); diff --git a/compiler/rustc_target/src/spec/targets/powerpc_unknown_linux_muslspe.rs b/compiler/rustc_target/src/spec/targets/powerpc_unknown_linux_muslspe.rs index d19015729ec19..51cd3c186fa9a 100644 --- a/compiler/rustc_target/src/spec/targets/powerpc_unknown_linux_muslspe.rs +++ b/compiler/rustc_target/src/spec/targets/powerpc_unknown_linux_muslspe.rs @@ -1,7 +1,7 @@ use crate::abi::Endian; use crate::spec::{base, Cc, LinkerFlavor, Lld, StackProbeType, Target, TargetOptions}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { let mut base = base::linux_musl::opts(); base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-mspe"]); base.max_atomic_width = Some(32); diff --git a/compiler/rustc_target/src/spec/targets/powerpc_unknown_netbsd.rs b/compiler/rustc_target/src/spec/targets/powerpc_unknown_netbsd.rs index 3ee6cd46c8535..7129fe42876d3 100644 --- a/compiler/rustc_target/src/spec/targets/powerpc_unknown_netbsd.rs +++ b/compiler/rustc_target/src/spec/targets/powerpc_unknown_netbsd.rs @@ -1,7 +1,7 @@ use crate::abi::Endian; use crate::spec::{base, Cc, LinkerFlavor, Lld, StackProbeType, Target, TargetOptions}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { let mut base = base::netbsd::opts(); base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m32"]); base.max_atomic_width = Some(32); diff --git a/compiler/rustc_target/src/spec/targets/powerpc_unknown_openbsd.rs b/compiler/rustc_target/src/spec/targets/powerpc_unknown_openbsd.rs index f00ee9604137f..6e98ecce45b74 100644 --- a/compiler/rustc_target/src/spec/targets/powerpc_unknown_openbsd.rs +++ b/compiler/rustc_target/src/spec/targets/powerpc_unknown_openbsd.rs @@ -1,7 +1,7 @@ use crate::abi::Endian; use crate::spec::{base, StackProbeType, Target}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { let mut base = base::openbsd::opts(); base.endian = Endian::Big; base.max_atomic_width = Some(32); diff --git a/compiler/rustc_target/src/spec/targets/powerpc_wrs_vxworks.rs b/compiler/rustc_target/src/spec/targets/powerpc_wrs_vxworks.rs index 5d107d6e60ecd..b19513bf1d7c9 100644 --- a/compiler/rustc_target/src/spec/targets/powerpc_wrs_vxworks.rs +++ b/compiler/rustc_target/src/spec/targets/powerpc_wrs_vxworks.rs @@ -1,7 +1,7 @@ use crate::abi::Endian; use crate::spec::{base, Cc, LinkerFlavor, Lld, StackProbeType, Target, TargetOptions}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { let mut base = base::vxworks::opts(); base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m32", "--secure-plt"]); base.max_atomic_width = Some(32); diff --git a/compiler/rustc_target/src/spec/targets/powerpc_wrs_vxworks_spe.rs b/compiler/rustc_target/src/spec/targets/powerpc_wrs_vxworks_spe.rs index aea525a69123f..8484c160a99c2 100644 --- a/compiler/rustc_target/src/spec/targets/powerpc_wrs_vxworks_spe.rs +++ b/compiler/rustc_target/src/spec/targets/powerpc_wrs_vxworks_spe.rs @@ -1,7 +1,7 @@ use crate::abi::Endian; use crate::spec::{base, Cc, LinkerFlavor, Lld, StackProbeType, Target, TargetOptions}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { let mut base = base::vxworks::opts(); base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-mspe", "--secure-plt"]); base.max_atomic_width = Some(32); diff --git a/compiler/rustc_target/src/spec/targets/riscv32gc_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/targets/riscv32gc_unknown_linux_gnu.rs index e425d6a3f3fcb..8913df3b95465 100644 --- a/compiler/rustc_target/src/spec/targets/riscv32gc_unknown_linux_gnu.rs +++ b/compiler/rustc_target/src/spec/targets/riscv32gc_unknown_linux_gnu.rs @@ -2,7 +2,7 @@ use std::borrow::Cow; use crate::spec::{base, CodeModel, SplitDebuginfo, Target, TargetOptions}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { Target { llvm_target: "riscv32-unknown-linux-gnu".into(), metadata: crate::spec::TargetMetadata { diff --git a/compiler/rustc_target/src/spec/targets/riscv32gc_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/targets/riscv32gc_unknown_linux_musl.rs index 409b6b22f1cf9..5717e7a390754 100644 --- a/compiler/rustc_target/src/spec/targets/riscv32gc_unknown_linux_musl.rs +++ b/compiler/rustc_target/src/spec/targets/riscv32gc_unknown_linux_musl.rs @@ -2,7 +2,7 @@ use std::borrow::Cow; use crate::spec::{base, CodeModel, SplitDebuginfo, Target, TargetOptions}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { Target { llvm_target: "riscv32-unknown-linux-musl".into(), metadata: crate::spec::TargetMetadata { diff --git a/compiler/rustc_target/src/spec/targets/riscv32i_unknown_none_elf.rs b/compiler/rustc_target/src/spec/targets/riscv32i_unknown_none_elf.rs index 631a31edeb5ec..1995de9dd2d7e 100644 --- a/compiler/rustc_target/src/spec/targets/riscv32i_unknown_none_elf.rs +++ b/compiler/rustc_target/src/spec/targets/riscv32i_unknown_none_elf.rs @@ -1,6 +1,6 @@ use crate::spec::{Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, TargetOptions}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { Target { data_layout: "e-m:e-p:32:32-i64:64-n32-S128".into(), llvm_target: "riscv32".into(), diff --git a/compiler/rustc_target/src/spec/targets/riscv32im_risc0_zkvm_elf.rs b/compiler/rustc_target/src/spec/targets/riscv32im_risc0_zkvm_elf.rs index 8aa5e0988902e..bd37cf80b4833 100644 --- a/compiler/rustc_target/src/spec/targets/riscv32im_risc0_zkvm_elf.rs +++ b/compiler/rustc_target/src/spec/targets/riscv32im_risc0_zkvm_elf.rs @@ -1,6 +1,6 @@ use crate::spec::{Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, TargetOptions}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { Target { data_layout: "e-m:e-p:32:32-i64:64-n32-S128".into(), llvm_target: "riscv32".into(), diff --git a/compiler/rustc_target/src/spec/targets/riscv32im_unknown_none_elf.rs b/compiler/rustc_target/src/spec/targets/riscv32im_unknown_none_elf.rs index 5fa3858e85744..32df30ddb5e3d 100644 --- a/compiler/rustc_target/src/spec/targets/riscv32im_unknown_none_elf.rs +++ b/compiler/rustc_target/src/spec/targets/riscv32im_unknown_none_elf.rs @@ -1,6 +1,6 @@ use crate::spec::{Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, TargetOptions}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { Target { data_layout: "e-m:e-p:32:32-i64:64-n32-S128".into(), llvm_target: "riscv32".into(), diff --git a/compiler/rustc_target/src/spec/targets/riscv32ima_unknown_none_elf.rs b/compiler/rustc_target/src/spec/targets/riscv32ima_unknown_none_elf.rs index 2022873d05cb5..61c887031bcf2 100644 --- a/compiler/rustc_target/src/spec/targets/riscv32ima_unknown_none_elf.rs +++ b/compiler/rustc_target/src/spec/targets/riscv32ima_unknown_none_elf.rs @@ -1,6 +1,6 @@ use crate::spec::{Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, TargetOptions}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { Target { data_layout: "e-m:e-p:32:32-i64:64-n32-S128".into(), llvm_target: "riscv32".into(), diff --git a/compiler/rustc_target/src/spec/targets/riscv32imac_esp_espidf.rs b/compiler/rustc_target/src/spec/targets/riscv32imac_esp_espidf.rs index 386e3a38f9757..0d453901efa73 100644 --- a/compiler/rustc_target/src/spec/targets/riscv32imac_esp_espidf.rs +++ b/compiler/rustc_target/src/spec/targets/riscv32imac_esp_espidf.rs @@ -1,6 +1,6 @@ use crate::spec::{cvs, PanicStrategy, RelocModel, Target, TargetOptions}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { Target { data_layout: "e-m:e-p:32:32-i64:64-n32-S128".into(), llvm_target: "riscv32".into(), diff --git a/compiler/rustc_target/src/spec/targets/riscv32imac_unknown_none_elf.rs b/compiler/rustc_target/src/spec/targets/riscv32imac_unknown_none_elf.rs index 7ced37e153577..cc28198e3ff0a 100644 --- a/compiler/rustc_target/src/spec/targets/riscv32imac_unknown_none_elf.rs +++ b/compiler/rustc_target/src/spec/targets/riscv32imac_unknown_none_elf.rs @@ -1,6 +1,6 @@ use crate::spec::{Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, TargetOptions}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { Target { data_layout: "e-m:e-p:32:32-i64:64-n32-S128".into(), llvm_target: "riscv32".into(), diff --git a/compiler/rustc_target/src/spec/targets/riscv32imac_unknown_nuttx_elf.rs b/compiler/rustc_target/src/spec/targets/riscv32imac_unknown_nuttx_elf.rs index aa51b8957fcd5..5ee6b3cbfa6ee 100644 --- a/compiler/rustc_target/src/spec/targets/riscv32imac_unknown_nuttx_elf.rs +++ b/compiler/rustc_target/src/spec/targets/riscv32imac_unknown_nuttx_elf.rs @@ -1,6 +1,6 @@ use crate::spec::{cvs, Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, TargetOptions}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { Target { data_layout: "e-m:e-p:32:32-i64:64-n32-S128".into(), llvm_target: "riscv32".into(), diff --git a/compiler/rustc_target/src/spec/targets/riscv32imac_unknown_xous_elf.rs b/compiler/rustc_target/src/spec/targets/riscv32imac_unknown_xous_elf.rs index cd50a9e60c32d..0eaabc60cbcd0 100644 --- a/compiler/rustc_target/src/spec/targets/riscv32imac_unknown_xous_elf.rs +++ b/compiler/rustc_target/src/spec/targets/riscv32imac_unknown_xous_elf.rs @@ -1,6 +1,6 @@ use crate::spec::{Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, TargetOptions}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { Target { data_layout: "e-m:e-p:32:32-i64:64-n32-S128".into(), llvm_target: "riscv32".into(), diff --git a/compiler/rustc_target/src/spec/targets/riscv32imafc_esp_espidf.rs b/compiler/rustc_target/src/spec/targets/riscv32imafc_esp_espidf.rs index 3661e38e7b1b3..c2882151d3d18 100644 --- a/compiler/rustc_target/src/spec/targets/riscv32imafc_esp_espidf.rs +++ b/compiler/rustc_target/src/spec/targets/riscv32imafc_esp_espidf.rs @@ -1,6 +1,6 @@ use crate::spec::{cvs, PanicStrategy, RelocModel, Target, TargetOptions}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { Target { data_layout: "e-m:e-p:32:32-i64:64-n32-S128".into(), llvm_target: "riscv32".into(), diff --git a/compiler/rustc_target/src/spec/targets/riscv32imafc_unknown_none_elf.rs b/compiler/rustc_target/src/spec/targets/riscv32imafc_unknown_none_elf.rs index 954660908912f..7395e1a6aad23 100644 --- a/compiler/rustc_target/src/spec/targets/riscv32imafc_unknown_none_elf.rs +++ b/compiler/rustc_target/src/spec/targets/riscv32imafc_unknown_none_elf.rs @@ -1,6 +1,6 @@ use crate::spec::{Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, TargetOptions}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { Target { data_layout: "e-m:e-p:32:32-i64:64-n32-S128".into(), llvm_target: "riscv32".into(), diff --git a/compiler/rustc_target/src/spec/targets/riscv32imafc_unknown_nuttx_elf.rs b/compiler/rustc_target/src/spec/targets/riscv32imafc_unknown_nuttx_elf.rs index fe49951ebfd6e..dcd4fcd9b4836 100644 --- a/compiler/rustc_target/src/spec/targets/riscv32imafc_unknown_nuttx_elf.rs +++ b/compiler/rustc_target/src/spec/targets/riscv32imafc_unknown_nuttx_elf.rs @@ -1,6 +1,6 @@ use crate::spec::{cvs, Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, TargetOptions}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { Target { data_layout: "e-m:e-p:32:32-i64:64-n32-S128".into(), llvm_target: "riscv32".into(), diff --git a/compiler/rustc_target/src/spec/targets/riscv32imc_esp_espidf.rs b/compiler/rustc_target/src/spec/targets/riscv32imc_esp_espidf.rs index d52dc8f96ca27..50d36e724a2c3 100644 --- a/compiler/rustc_target/src/spec/targets/riscv32imc_esp_espidf.rs +++ b/compiler/rustc_target/src/spec/targets/riscv32imc_esp_espidf.rs @@ -1,6 +1,6 @@ use crate::spec::{cvs, PanicStrategy, RelocModel, Target, TargetOptions}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { Target { data_layout: "e-m:e-p:32:32-i64:64-n32-S128".into(), llvm_target: "riscv32".into(), diff --git a/compiler/rustc_target/src/spec/targets/riscv32imc_unknown_none_elf.rs b/compiler/rustc_target/src/spec/targets/riscv32imc_unknown_none_elf.rs index ff9931978466e..0ae49debc3a38 100644 --- a/compiler/rustc_target/src/spec/targets/riscv32imc_unknown_none_elf.rs +++ b/compiler/rustc_target/src/spec/targets/riscv32imc_unknown_none_elf.rs @@ -1,6 +1,6 @@ use crate::spec::{Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, TargetOptions}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { Target { data_layout: "e-m:e-p:32:32-i64:64-n32-S128".into(), llvm_target: "riscv32".into(), diff --git a/compiler/rustc_target/src/spec/targets/riscv32imc_unknown_nuttx_elf.rs b/compiler/rustc_target/src/spec/targets/riscv32imc_unknown_nuttx_elf.rs index baee03e68333c..eab18064334a5 100644 --- a/compiler/rustc_target/src/spec/targets/riscv32imc_unknown_nuttx_elf.rs +++ b/compiler/rustc_target/src/spec/targets/riscv32imc_unknown_nuttx_elf.rs @@ -1,6 +1,6 @@ use crate::spec::{cvs, Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, TargetOptions}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { Target { data_layout: "e-m:e-p:32:32-i64:64-n32-S128".into(), llvm_target: "riscv32".into(), diff --git a/compiler/rustc_target/src/spec/targets/riscv64_linux_android.rs b/compiler/rustc_target/src/spec/targets/riscv64_linux_android.rs index 2dfaf8a2033c6..00059a2691dc2 100644 --- a/compiler/rustc_target/src/spec/targets/riscv64_linux_android.rs +++ b/compiler/rustc_target/src/spec/targets/riscv64_linux_android.rs @@ -2,7 +2,7 @@ use std::borrow::Cow; use crate::spec::{base, CodeModel, SanitizerSet, SplitDebuginfo, Target, TargetOptions}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { Target { llvm_target: "riscv64-linux-android".into(), metadata: crate::spec::TargetMetadata { diff --git a/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_freebsd.rs b/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_freebsd.rs index 1fd6a4b38dcf1..8d2b16c45016e 100644 --- a/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_freebsd.rs +++ b/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_freebsd.rs @@ -1,6 +1,6 @@ use crate::spec::{base, CodeModel, Target, TargetOptions}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { Target { llvm_target: "riscv64-unknown-freebsd".into(), metadata: crate::spec::TargetMetadata { diff --git a/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_fuchsia.rs b/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_fuchsia.rs index 5c3f525966ed8..f5e6b1cbd78f4 100644 --- a/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_fuchsia.rs +++ b/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_fuchsia.rs @@ -1,6 +1,6 @@ use crate::spec::{base, CodeModel, SanitizerSet, Target, TargetOptions}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { Target { llvm_target: "riscv64-unknown-fuchsia".into(), metadata: crate::spec::TargetMetadata { diff --git a/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_hermit.rs b/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_hermit.rs index f11128cfcb676..3033479358ecd 100644 --- a/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_hermit.rs +++ b/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_hermit.rs @@ -1,6 +1,6 @@ use crate::spec::{base, CodeModel, RelocModel, Target, TargetOptions, TlsModel}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { Target { llvm_target: "riscv64-unknown-hermit".into(), metadata: crate::spec::TargetMetadata { diff --git a/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_linux_gnu.rs index 308c995297bba..07253803f5c2e 100644 --- a/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_linux_gnu.rs +++ b/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_linux_gnu.rs @@ -2,7 +2,7 @@ use std::borrow::Cow; use crate::spec::{base, CodeModel, SplitDebuginfo, Target, TargetOptions}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { Target { llvm_target: "riscv64-unknown-linux-gnu".into(), metadata: crate::spec::TargetMetadata { diff --git a/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_linux_musl.rs index 8b40132986867..9b0b14cb1088d 100644 --- a/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_linux_musl.rs +++ b/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_linux_musl.rs @@ -2,7 +2,7 @@ use std::borrow::Cow; use crate::spec::{base, CodeModel, SplitDebuginfo, Target, TargetOptions}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { Target { llvm_target: "riscv64-unknown-linux-musl".into(), metadata: crate::spec::TargetMetadata { diff --git a/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_netbsd.rs b/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_netbsd.rs index 65781f5af5c74..3eb9366c850b6 100644 --- a/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_netbsd.rs +++ b/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_netbsd.rs @@ -1,6 +1,6 @@ use crate::spec::{base, CodeModel, Target, TargetOptions}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { Target { llvm_target: "riscv64-unknown-netbsd".into(), metadata: crate::spec::TargetMetadata { diff --git a/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_none_elf.rs b/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_none_elf.rs index 61226809e52a2..c32c57d92f75b 100644 --- a/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_none_elf.rs +++ b/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_none_elf.rs @@ -3,7 +3,7 @@ use crate::spec::{ TargetOptions, }; -pub fn target() -> Target { +pub(crate) fn target() -> Target { Target { data_layout: "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128".into(), metadata: crate::spec::TargetMetadata { diff --git a/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_nuttx_elf.rs b/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_nuttx_elf.rs index 5bea708e0dd23..27b8ae99753bc 100644 --- a/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_nuttx_elf.rs +++ b/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_nuttx_elf.rs @@ -3,7 +3,7 @@ use crate::spec::{ TargetOptions, }; -pub fn target() -> Target { +pub(crate) fn target() -> Target { Target { data_layout: "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128".into(), metadata: crate::spec::TargetMetadata { diff --git a/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_openbsd.rs b/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_openbsd.rs index 5bdbda773b1bf..dca8a524b103f 100644 --- a/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_openbsd.rs +++ b/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_openbsd.rs @@ -1,6 +1,6 @@ use crate::spec::{base, CodeModel, Target, TargetOptions}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { Target { llvm_target: "riscv64-unknown-openbsd".into(), metadata: crate::spec::TargetMetadata { diff --git a/compiler/rustc_target/src/spec/targets/riscv64imac_unknown_none_elf.rs b/compiler/rustc_target/src/spec/targets/riscv64imac_unknown_none_elf.rs index b7444df04cd1f..d514f8efcd08c 100644 --- a/compiler/rustc_target/src/spec/targets/riscv64imac_unknown_none_elf.rs +++ b/compiler/rustc_target/src/spec/targets/riscv64imac_unknown_none_elf.rs @@ -3,7 +3,7 @@ use crate::spec::{ TargetOptions, }; -pub fn target() -> Target { +pub(crate) fn target() -> Target { Target { data_layout: "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128".into(), llvm_target: "riscv64".into(), diff --git a/compiler/rustc_target/src/spec/targets/riscv64imac_unknown_nuttx_elf.rs b/compiler/rustc_target/src/spec/targets/riscv64imac_unknown_nuttx_elf.rs index 80d58e5baceac..5fbc2a86fa942 100644 --- a/compiler/rustc_target/src/spec/targets/riscv64imac_unknown_nuttx_elf.rs +++ b/compiler/rustc_target/src/spec/targets/riscv64imac_unknown_nuttx_elf.rs @@ -3,7 +3,7 @@ use crate::spec::{ TargetOptions, }; -pub fn target() -> Target { +pub(crate) fn target() -> Target { Target { data_layout: "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128".into(), metadata: crate::spec::TargetMetadata { diff --git a/compiler/rustc_target/src/spec/targets/s390x_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/targets/s390x_unknown_linux_gnu.rs index b0dd0eb612e16..e0a6c230fd6ae 100644 --- a/compiler/rustc_target/src/spec/targets/s390x_unknown_linux_gnu.rs +++ b/compiler/rustc_target/src/spec/targets/s390x_unknown_linux_gnu.rs @@ -1,7 +1,7 @@ use crate::abi::Endian; use crate::spec::{base, SanitizerSet, StackProbeType, Target}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { let mut base = base::linux_gnu::opts(); base.endian = Endian::Big; // z10 is the oldest CPU supported by LLVM diff --git a/compiler/rustc_target/src/spec/targets/s390x_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/targets/s390x_unknown_linux_musl.rs index 3976233819cec..6aabe9ca51923 100644 --- a/compiler/rustc_target/src/spec/targets/s390x_unknown_linux_musl.rs +++ b/compiler/rustc_target/src/spec/targets/s390x_unknown_linux_musl.rs @@ -1,7 +1,7 @@ use crate::abi::Endian; use crate::spec::{base, SanitizerSet, StackProbeType, Target}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { let mut base = base::linux_musl::opts(); base.endian = Endian::Big; // z10 is the oldest CPU supported by LLVM diff --git a/compiler/rustc_target/src/spec/targets/sparc64_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/targets/sparc64_unknown_linux_gnu.rs index eeb7eebfe5035..7c37fa0d63259 100644 --- a/compiler/rustc_target/src/spec/targets/sparc64_unknown_linux_gnu.rs +++ b/compiler/rustc_target/src/spec/targets/sparc64_unknown_linux_gnu.rs @@ -1,7 +1,7 @@ use crate::abi::Endian; use crate::spec::{base, Target}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { let mut base = base::linux_gnu::opts(); base.endian = Endian::Big; base.cpu = "v9".into(); diff --git a/compiler/rustc_target/src/spec/targets/sparc64_unknown_netbsd.rs b/compiler/rustc_target/src/spec/targets/sparc64_unknown_netbsd.rs index 69bb6e1fb60e4..842e35392dcea 100644 --- a/compiler/rustc_target/src/spec/targets/sparc64_unknown_netbsd.rs +++ b/compiler/rustc_target/src/spec/targets/sparc64_unknown_netbsd.rs @@ -1,7 +1,7 @@ use crate::abi::Endian; use crate::spec::{base, Cc, LinkerFlavor, Lld, Target, TargetOptions}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { let mut base = base::netbsd::opts(); base.cpu = "v9".into(); base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m64"]); diff --git a/compiler/rustc_target/src/spec/targets/sparc64_unknown_openbsd.rs b/compiler/rustc_target/src/spec/targets/sparc64_unknown_openbsd.rs index 08f6eaf836176..a8767fa9d3c06 100644 --- a/compiler/rustc_target/src/spec/targets/sparc64_unknown_openbsd.rs +++ b/compiler/rustc_target/src/spec/targets/sparc64_unknown_openbsd.rs @@ -1,7 +1,7 @@ use crate::abi::Endian; use crate::spec::{base, Cc, LinkerFlavor, Lld, Target}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { let mut base = base::openbsd::opts(); base.endian = Endian::Big; base.cpu = "v9".into(); diff --git a/compiler/rustc_target/src/spec/targets/sparc_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/targets/sparc_unknown_linux_gnu.rs index 8b7ff5d8011cf..7089fc511242a 100644 --- a/compiler/rustc_target/src/spec/targets/sparc_unknown_linux_gnu.rs +++ b/compiler/rustc_target/src/spec/targets/sparc_unknown_linux_gnu.rs @@ -1,7 +1,7 @@ use crate::abi::Endian; use crate::spec::{base, Cc, LinkerFlavor, Lld, Target, TargetOptions}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { Target { llvm_target: "sparc-unknown-linux-gnu".into(), metadata: crate::spec::TargetMetadata { diff --git a/compiler/rustc_target/src/spec/targets/sparc_unknown_none_elf.rs b/compiler/rustc_target/src/spec/targets/sparc_unknown_none_elf.rs index c977fe608a78e..0cd4faefd6bb1 100644 --- a/compiler/rustc_target/src/spec/targets/sparc_unknown_none_elf.rs +++ b/compiler/rustc_target/src/spec/targets/sparc_unknown_none_elf.rs @@ -1,7 +1,7 @@ use crate::abi::Endian; use crate::spec::{Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, TargetOptions}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { let options = TargetOptions { linker_flavor: LinkerFlavor::Gnu(Cc::Yes, Lld::No), linker: Some("sparc-elf-gcc".into()), diff --git a/compiler/rustc_target/src/spec/targets/sparcv9_sun_solaris.rs b/compiler/rustc_target/src/spec/targets/sparcv9_sun_solaris.rs index 1c0adadece0be..a932632b85740 100644 --- a/compiler/rustc_target/src/spec/targets/sparcv9_sun_solaris.rs +++ b/compiler/rustc_target/src/spec/targets/sparcv9_sun_solaris.rs @@ -1,7 +1,7 @@ use crate::abi::Endian; use crate::spec::{base, Cc, LinkerFlavor, Target}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { let mut base = base::solaris::opts(); base.endian = Endian::Big; base.add_pre_link_args(LinkerFlavor::Unix(Cc::Yes), &["-m64"]); diff --git a/compiler/rustc_target/src/spec/targets/thumbv4t_none_eabi.rs b/compiler/rustc_target/src/spec/targets/thumbv4t_none_eabi.rs index 8806f3e87fa2a..0f5e16408932f 100644 --- a/compiler/rustc_target/src/spec/targets/thumbv4t_none_eabi.rs +++ b/compiler/rustc_target/src/spec/targets/thumbv4t_none_eabi.rs @@ -11,7 +11,7 @@ use crate::spec::{base, cvs, FramePointer, PanicStrategy, RelocModel, Target, TargetOptions}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { Target { llvm_target: "thumbv4t-none-eabi".into(), metadata: crate::spec::TargetMetadata { diff --git a/compiler/rustc_target/src/spec/targets/thumbv5te_none_eabi.rs b/compiler/rustc_target/src/spec/targets/thumbv5te_none_eabi.rs index d92e68cebaa65..6ae41ce439939 100644 --- a/compiler/rustc_target/src/spec/targets/thumbv5te_none_eabi.rs +++ b/compiler/rustc_target/src/spec/targets/thumbv5te_none_eabi.rs @@ -2,7 +2,7 @@ use crate::spec::{base, cvs, FramePointer, Target, TargetOptions}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { Target { llvm_target: "thumbv5te-none-eabi".into(), metadata: crate::spec::TargetMetadata { diff --git a/compiler/rustc_target/src/spec/targets/thumbv6m_none_eabi.rs b/compiler/rustc_target/src/spec/targets/thumbv6m_none_eabi.rs index a0fa58d8175cf..9d4cc66c7f075 100644 --- a/compiler/rustc_target/src/spec/targets/thumbv6m_none_eabi.rs +++ b/compiler/rustc_target/src/spec/targets/thumbv6m_none_eabi.rs @@ -2,7 +2,7 @@ use crate::spec::{base, Target, TargetOptions}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { Target { llvm_target: "thumbv6m-none-eabi".into(), metadata: crate::spec::TargetMetadata { diff --git a/compiler/rustc_target/src/spec/targets/thumbv6m_nuttx_eabi.rs b/compiler/rustc_target/src/spec/targets/thumbv6m_nuttx_eabi.rs index ac37f40386012..bc9d9856e036e 100644 --- a/compiler/rustc_target/src/spec/targets/thumbv6m_nuttx_eabi.rs +++ b/compiler/rustc_target/src/spec/targets/thumbv6m_nuttx_eabi.rs @@ -2,7 +2,7 @@ use crate::spec::{base, cvs, Target, TargetOptions}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { Target { llvm_target: "thumbv6m-none-eabi".into(), metadata: crate::spec::TargetMetadata { diff --git a/compiler/rustc_target/src/spec/targets/thumbv7a_pc_windows_msvc.rs b/compiler/rustc_target/src/spec/targets/thumbv7a_pc_windows_msvc.rs index e36aa5ab395da..a927cf6902e92 100644 --- a/compiler/rustc_target/src/spec/targets/thumbv7a_pc_windows_msvc.rs +++ b/compiler/rustc_target/src/spec/targets/thumbv7a_pc_windows_msvc.rs @@ -1,6 +1,6 @@ use crate::spec::{base, LinkerFlavor, Lld, PanicStrategy, Target, TargetOptions}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { let mut base = base::windows_msvc::opts(); // Prevent error LNK2013: BRANCH24(T) fixup overflow // The LBR optimization tries to eliminate branch islands, diff --git a/compiler/rustc_target/src/spec/targets/thumbv7a_uwp_windows_msvc.rs b/compiler/rustc_target/src/spec/targets/thumbv7a_uwp_windows_msvc.rs index 2e68dd0ec4e8a..473113854a81b 100644 --- a/compiler/rustc_target/src/spec/targets/thumbv7a_uwp_windows_msvc.rs +++ b/compiler/rustc_target/src/spec/targets/thumbv7a_uwp_windows_msvc.rs @@ -1,6 +1,6 @@ use crate::spec::{base, PanicStrategy, Target, TargetOptions}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { Target { llvm_target: "thumbv7a-pc-windows-msvc".into(), metadata: crate::spec::TargetMetadata { diff --git a/compiler/rustc_target/src/spec/targets/thumbv7em_none_eabi.rs b/compiler/rustc_target/src/spec/targets/thumbv7em_none_eabi.rs index bd2df9236f67b..dca3e73dda570 100644 --- a/compiler/rustc_target/src/spec/targets/thumbv7em_none_eabi.rs +++ b/compiler/rustc_target/src/spec/targets/thumbv7em_none_eabi.rs @@ -11,7 +11,7 @@ use crate::spec::{base, Target, TargetOptions}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { Target { llvm_target: "thumbv7em-none-eabi".into(), metadata: crate::spec::TargetMetadata { diff --git a/compiler/rustc_target/src/spec/targets/thumbv7em_none_eabihf.rs b/compiler/rustc_target/src/spec/targets/thumbv7em_none_eabihf.rs index e2499ef54112b..acc5acfbfb684 100644 --- a/compiler/rustc_target/src/spec/targets/thumbv7em_none_eabihf.rs +++ b/compiler/rustc_target/src/spec/targets/thumbv7em_none_eabihf.rs @@ -10,7 +10,7 @@ use crate::spec::{base, Target, TargetOptions}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { Target { llvm_target: "thumbv7em-none-eabihf".into(), metadata: crate::spec::TargetMetadata { diff --git a/compiler/rustc_target/src/spec/targets/thumbv7em_nuttx_eabi.rs b/compiler/rustc_target/src/spec/targets/thumbv7em_nuttx_eabi.rs index e21facb78f961..b4cd9686f5cc9 100644 --- a/compiler/rustc_target/src/spec/targets/thumbv7em_nuttx_eabi.rs +++ b/compiler/rustc_target/src/spec/targets/thumbv7em_nuttx_eabi.rs @@ -11,7 +11,7 @@ use crate::spec::{base, cvs, Target, TargetOptions}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { Target { llvm_target: "thumbv7em-none-eabi".into(), metadata: crate::spec::TargetMetadata { diff --git a/compiler/rustc_target/src/spec/targets/thumbv7em_nuttx_eabihf.rs b/compiler/rustc_target/src/spec/targets/thumbv7em_nuttx_eabihf.rs index 45092711d2e18..bdb3a38be9391 100644 --- a/compiler/rustc_target/src/spec/targets/thumbv7em_nuttx_eabihf.rs +++ b/compiler/rustc_target/src/spec/targets/thumbv7em_nuttx_eabihf.rs @@ -10,7 +10,7 @@ use crate::spec::{base, cvs, Target, TargetOptions}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { Target { llvm_target: "thumbv7em-none-eabihf".into(), metadata: crate::spec::TargetMetadata { diff --git a/compiler/rustc_target/src/spec/targets/thumbv7m_none_eabi.rs b/compiler/rustc_target/src/spec/targets/thumbv7m_none_eabi.rs index 17e37f800f0b5..f5615de231544 100644 --- a/compiler/rustc_target/src/spec/targets/thumbv7m_none_eabi.rs +++ b/compiler/rustc_target/src/spec/targets/thumbv7m_none_eabi.rs @@ -2,7 +2,7 @@ use crate::spec::{base, Target, TargetOptions}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { Target { llvm_target: "thumbv7m-none-eabi".into(), metadata: crate::spec::TargetMetadata { diff --git a/compiler/rustc_target/src/spec/targets/thumbv7m_nuttx_eabi.rs b/compiler/rustc_target/src/spec/targets/thumbv7m_nuttx_eabi.rs index 4424b9eaadea6..0e3663e1603b9 100644 --- a/compiler/rustc_target/src/spec/targets/thumbv7m_nuttx_eabi.rs +++ b/compiler/rustc_target/src/spec/targets/thumbv7m_nuttx_eabi.rs @@ -2,7 +2,7 @@ use crate::spec::{base, cvs, Target, TargetOptions}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { Target { llvm_target: "thumbv7m-none-eabi".into(), metadata: crate::spec::TargetMetadata { diff --git a/compiler/rustc_target/src/spec/targets/thumbv7neon_linux_androideabi.rs b/compiler/rustc_target/src/spec/targets/thumbv7neon_linux_androideabi.rs index c562f57252e59..9b4d13a96c8ff 100644 --- a/compiler/rustc_target/src/spec/targets/thumbv7neon_linux_androideabi.rs +++ b/compiler/rustc_target/src/spec/targets/thumbv7neon_linux_androideabi.rs @@ -8,7 +8,7 @@ use crate::spec::{base, Cc, LinkerFlavor, Lld, Target, TargetOptions}; // See https://developer.android.com/ndk/guides/abis.html#v7a // for target ABI requirements. -pub fn target() -> Target { +pub(crate) fn target() -> Target { let mut base = base::android::opts(); base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-march=armv7-a"]); Target { diff --git a/compiler/rustc_target/src/spec/targets/thumbv7neon_unknown_linux_gnueabihf.rs b/compiler/rustc_target/src/spec/targets/thumbv7neon_unknown_linux_gnueabihf.rs index b5e91d61308be..b85b9b60b4209 100644 --- a/compiler/rustc_target/src/spec/targets/thumbv7neon_unknown_linux_gnueabihf.rs +++ b/compiler/rustc_target/src/spec/targets/thumbv7neon_unknown_linux_gnueabihf.rs @@ -6,7 +6,7 @@ use crate::spec::{base, Target, TargetOptions}; // registers enabled as well. See section A2.6.2 on page A2-56 in // https://web.archive.org/web/20210307234416/https://static.docs.arm.com/ddi0406/cd/DDI0406C_d_armv7ar_arm.pdf -pub fn target() -> Target { +pub(crate) fn target() -> Target { Target { llvm_target: "armv7-unknown-linux-gnueabihf".into(), metadata: crate::spec::TargetMetadata { diff --git a/compiler/rustc_target/src/spec/targets/thumbv7neon_unknown_linux_musleabihf.rs b/compiler/rustc_target/src/spec/targets/thumbv7neon_unknown_linux_musleabihf.rs index 71d5eb43c1040..f53f21d721772 100644 --- a/compiler/rustc_target/src/spec/targets/thumbv7neon_unknown_linux_musleabihf.rs +++ b/compiler/rustc_target/src/spec/targets/thumbv7neon_unknown_linux_musleabihf.rs @@ -6,7 +6,7 @@ use crate::spec::{base, Target, TargetOptions}; // registers enabled as well. See section A2.6.2 on page A2-56 in // https://web.archive.org/web/20210307234416/https://static.docs.arm.com/ddi0406/cd/DDI0406C_d_armv7ar_arm.pdf -pub fn target() -> Target { +pub(crate) fn target() -> Target { Target { // It's important we use "gnueabihf" and not "musleabihf" here. LLVM // uses it to determine the calling convention and float ABI, and LLVM diff --git a/compiler/rustc_target/src/spec/targets/thumbv8m_base_none_eabi.rs b/compiler/rustc_target/src/spec/targets/thumbv8m_base_none_eabi.rs index e18bf113fe7c9..e392240a3335b 100644 --- a/compiler/rustc_target/src/spec/targets/thumbv8m_base_none_eabi.rs +++ b/compiler/rustc_target/src/spec/targets/thumbv8m_base_none_eabi.rs @@ -2,7 +2,7 @@ use crate::spec::{base, Target, TargetOptions}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { Target { llvm_target: "thumbv8m.base-none-eabi".into(), metadata: crate::spec::TargetMetadata { diff --git a/compiler/rustc_target/src/spec/targets/thumbv8m_base_nuttx_eabi.rs b/compiler/rustc_target/src/spec/targets/thumbv8m_base_nuttx_eabi.rs index 44c6fb0dd1bfa..903b8f029114b 100644 --- a/compiler/rustc_target/src/spec/targets/thumbv8m_base_nuttx_eabi.rs +++ b/compiler/rustc_target/src/spec/targets/thumbv8m_base_nuttx_eabi.rs @@ -2,7 +2,7 @@ use crate::spec::{base, cvs, Target, TargetOptions}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { Target { llvm_target: "thumbv8m.base-none-eabi".into(), metadata: crate::spec::TargetMetadata { diff --git a/compiler/rustc_target/src/spec/targets/thumbv8m_main_none_eabi.rs b/compiler/rustc_target/src/spec/targets/thumbv8m_main_none_eabi.rs index 5c2f1e093819c..d287321c9f293 100644 --- a/compiler/rustc_target/src/spec/targets/thumbv8m_main_none_eabi.rs +++ b/compiler/rustc_target/src/spec/targets/thumbv8m_main_none_eabi.rs @@ -3,7 +3,7 @@ use crate::spec::{base, Target, TargetOptions}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { Target { llvm_target: "thumbv8m.main-none-eabi".into(), metadata: crate::spec::TargetMetadata { diff --git a/compiler/rustc_target/src/spec/targets/thumbv8m_main_none_eabihf.rs b/compiler/rustc_target/src/spec/targets/thumbv8m_main_none_eabihf.rs index 799ac45b479c4..74b143f69956e 100644 --- a/compiler/rustc_target/src/spec/targets/thumbv8m_main_none_eabihf.rs +++ b/compiler/rustc_target/src/spec/targets/thumbv8m_main_none_eabihf.rs @@ -3,7 +3,7 @@ use crate::spec::{base, Target, TargetOptions}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { Target { llvm_target: "thumbv8m.main-none-eabihf".into(), metadata: crate::spec::TargetMetadata { diff --git a/compiler/rustc_target/src/spec/targets/thumbv8m_main_nuttx_eabi.rs b/compiler/rustc_target/src/spec/targets/thumbv8m_main_nuttx_eabi.rs index 2f0df7ae857bd..c5de209246c7a 100644 --- a/compiler/rustc_target/src/spec/targets/thumbv8m_main_nuttx_eabi.rs +++ b/compiler/rustc_target/src/spec/targets/thumbv8m_main_nuttx_eabi.rs @@ -3,7 +3,7 @@ use crate::spec::{base, cvs, Target, TargetOptions}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { Target { llvm_target: "thumbv8m.main-none-eabi".into(), metadata: crate::spec::TargetMetadata { diff --git a/compiler/rustc_target/src/spec/targets/thumbv8m_main_nuttx_eabihf.rs b/compiler/rustc_target/src/spec/targets/thumbv8m_main_nuttx_eabihf.rs index ee31f17bc4511..44ad78b4684a7 100644 --- a/compiler/rustc_target/src/spec/targets/thumbv8m_main_nuttx_eabihf.rs +++ b/compiler/rustc_target/src/spec/targets/thumbv8m_main_nuttx_eabihf.rs @@ -3,7 +3,7 @@ use crate::spec::{base, cvs, Target, TargetOptions}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { Target { llvm_target: "thumbv8m.main-none-eabihf".into(), metadata: crate::spec::TargetMetadata { diff --git a/compiler/rustc_target/src/spec/targets/wasm32_unknown_emscripten.rs b/compiler/rustc_target/src/spec/targets/wasm32_unknown_emscripten.rs index 46257a272d1e1..c22f1589ca137 100644 --- a/compiler/rustc_target/src/spec/targets/wasm32_unknown_emscripten.rs +++ b/compiler/rustc_target/src/spec/targets/wasm32_unknown_emscripten.rs @@ -2,7 +2,7 @@ use crate::spec::{ base, cvs, LinkArgs, LinkerFlavor, PanicStrategy, RelocModel, Target, TargetOptions, }; -pub fn target() -> Target { +pub(crate) fn target() -> Target { // Reset flags for non-Em flavors back to empty to satisfy sanity checking tests. let pre_link_args = LinkArgs::new(); let post_link_args = TargetOptions::link_args(LinkerFlavor::EmCc, &["-sABORTING_MALLOC=0"]); diff --git a/compiler/rustc_target/src/spec/targets/wasm32_unknown_unknown.rs b/compiler/rustc_target/src/spec/targets/wasm32_unknown_unknown.rs index bf92f30e8b372..300108530a5b2 100644 --- a/compiler/rustc_target/src/spec/targets/wasm32_unknown_unknown.rs +++ b/compiler/rustc_target/src/spec/targets/wasm32_unknown_unknown.rs @@ -12,7 +12,7 @@ use crate::spec::{base, Cc, LinkerFlavor, Target}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { let mut options = base::wasm::options(); options.os = "unknown".into(); diff --git a/compiler/rustc_target/src/spec/targets/wasm32_wasi.rs b/compiler/rustc_target/src/spec/targets/wasm32_wasi.rs index 2752125c00991..c317ebd95923d 100644 --- a/compiler/rustc_target/src/spec/targets/wasm32_wasi.rs +++ b/compiler/rustc_target/src/spec/targets/wasm32_wasi.rs @@ -6,6 +6,6 @@ use crate::spec::Target; -pub fn target() -> Target { +pub(crate) fn target() -> Target { super::wasm32_wasip1::target() } diff --git a/compiler/rustc_target/src/spec/targets/wasm32_wasip1.rs b/compiler/rustc_target/src/spec/targets/wasm32_wasip1.rs index 29e6dff2068fc..7728d83c2b680 100644 --- a/compiler/rustc_target/src/spec/targets/wasm32_wasip1.rs +++ b/compiler/rustc_target/src/spec/targets/wasm32_wasip1.rs @@ -12,7 +12,7 @@ use crate::spec::{base, crt_objects, Cc, LinkSelfContainedDefault, LinkerFlavor, Target}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { let mut options = base::wasm::options(); options.os = "wasi".into(); diff --git a/compiler/rustc_target/src/spec/targets/wasm32_wasip1_threads.rs b/compiler/rustc_target/src/spec/targets/wasm32_wasip1_threads.rs index 4e60806f3a736..0ae844c8da8ff 100644 --- a/compiler/rustc_target/src/spec/targets/wasm32_wasip1_threads.rs +++ b/compiler/rustc_target/src/spec/targets/wasm32_wasip1_threads.rs @@ -9,7 +9,7 @@ use crate::spec::{base, crt_objects, Cc, LinkSelfContainedDefault, LinkerFlavor, Target}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { let mut options = base::wasm::options(); options.os = "wasi".into(); diff --git a/compiler/rustc_target/src/spec/targets/wasm32_wasip2.rs b/compiler/rustc_target/src/spec/targets/wasm32_wasip2.rs index 489bae4fedf17..1d096c6f58900 100644 --- a/compiler/rustc_target/src/spec/targets/wasm32_wasip2.rs +++ b/compiler/rustc_target/src/spec/targets/wasm32_wasip2.rs @@ -18,7 +18,7 @@ use crate::spec::{base, crt_objects, LinkSelfContainedDefault, RelocModel, Target}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { let mut options = base::wasm::options(); options.os = "wasi".into(); diff --git a/compiler/rustc_target/src/spec/targets/wasm64_unknown_unknown.rs b/compiler/rustc_target/src/spec/targets/wasm64_unknown_unknown.rs index bc49a3c9f70d0..35c553744763f 100644 --- a/compiler/rustc_target/src/spec/targets/wasm64_unknown_unknown.rs +++ b/compiler/rustc_target/src/spec/targets/wasm64_unknown_unknown.rs @@ -9,7 +9,7 @@ use crate::spec::{base, Cc, LinkerFlavor, Target}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { let mut options = base::wasm::options(); options.os = "unknown".into(); diff --git a/compiler/rustc_target/src/spec/targets/x86_64_apple_darwin.rs b/compiler/rustc_target/src/spec/targets/x86_64_apple_darwin.rs index c3a52a506bc9d..7bf18026735dd 100644 --- a/compiler/rustc_target/src/spec/targets/x86_64_apple_darwin.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_apple_darwin.rs @@ -1,7 +1,7 @@ use crate::spec::base::apple::{macos_llvm_target, opts, Arch, TargetAbi}; use crate::spec::{Cc, FramePointer, LinkerFlavor, Lld, SanitizerSet, Target, TargetOptions}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { let arch = Arch::X86_64; let mut base = opts("macos", arch, TargetAbi::Normal); base.max_atomic_width = Some(128); // penryn+ supports cmpxchg16b diff --git a/compiler/rustc_target/src/spec/targets/x86_64_apple_ios.rs b/compiler/rustc_target/src/spec/targets/x86_64_apple_ios.rs index 3cabca0336098..76a0bb1d91eef 100644 --- a/compiler/rustc_target/src/spec/targets/x86_64_apple_ios.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_apple_ios.rs @@ -1,7 +1,7 @@ use crate::spec::base::apple::{ios_sim_llvm_target, opts, Arch, TargetAbi}; use crate::spec::{SanitizerSet, Target, TargetOptions}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { let arch = Arch::X86_64; // x86_64-apple-ios is a simulator target, even though it isn't declared // that way in the target name like the other ones... diff --git a/compiler/rustc_target/src/spec/targets/x86_64_apple_ios_macabi.rs b/compiler/rustc_target/src/spec/targets/x86_64_apple_ios_macabi.rs index c23a20ff0848e..f66efbbf709d1 100644 --- a/compiler/rustc_target/src/spec/targets/x86_64_apple_ios_macabi.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_apple_ios_macabi.rs @@ -1,7 +1,7 @@ use crate::spec::base::apple::{mac_catalyst_llvm_target, opts, Arch, TargetAbi}; use crate::spec::{SanitizerSet, Target, TargetOptions}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { let arch = Arch::X86_64; let mut base = opts("ios", arch, TargetAbi::MacCatalyst); base.supported_sanitizers = SanitizerSet::ADDRESS | SanitizerSet::LEAK | SanitizerSet::THREAD; diff --git a/compiler/rustc_target/src/spec/targets/x86_64_apple_tvos.rs b/compiler/rustc_target/src/spec/targets/x86_64_apple_tvos.rs index 2a3125157dd9d..f9d5f6e77d9fc 100644 --- a/compiler/rustc_target/src/spec/targets/x86_64_apple_tvos.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_apple_tvos.rs @@ -1,7 +1,7 @@ use crate::spec::base::apple::{opts, tvos_sim_llvm_target, Arch, TargetAbi}; use crate::spec::{Target, TargetOptions}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { let arch = Arch::X86_64; // x86_64-apple-tvos is a simulator target, even though it isn't declared // that way in the target name like the other ones... diff --git a/compiler/rustc_target/src/spec/targets/x86_64_apple_watchos_sim.rs b/compiler/rustc_target/src/spec/targets/x86_64_apple_watchos_sim.rs index 62e60b5e32d04..1fced10c895ea 100644 --- a/compiler/rustc_target/src/spec/targets/x86_64_apple_watchos_sim.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_apple_watchos_sim.rs @@ -1,7 +1,7 @@ use crate::spec::base::apple::{opts, watchos_sim_llvm_target, Arch, TargetAbi}; use crate::spec::{Target, TargetOptions}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { let arch = Arch::X86_64; Target { llvm_target: watchos_sim_llvm_target(arch).into(), diff --git a/compiler/rustc_target/src/spec/targets/x86_64_fortanix_unknown_sgx.rs b/compiler/rustc_target/src/spec/targets/x86_64_fortanix_unknown_sgx.rs index 5a72fad826323..a3d18e5ecdaf0 100644 --- a/compiler/rustc_target/src/spec/targets/x86_64_fortanix_unknown_sgx.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_fortanix_unknown_sgx.rs @@ -2,7 +2,7 @@ use std::borrow::Cow; use crate::spec::{cvs, Cc, LinkerFlavor, Lld, Target, TargetOptions}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { let pre_link_args = TargetOptions::link_args( LinkerFlavor::Gnu(Cc::No, Lld::No), &[ diff --git a/compiler/rustc_target/src/spec/targets/x86_64_fuchsia.rs b/compiler/rustc_target/src/spec/targets/x86_64_fuchsia.rs index 46df00e9c02b7..ce3e1e159b7d7 100644 --- a/compiler/rustc_target/src/spec/targets/x86_64_fuchsia.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_fuchsia.rs @@ -1 +1 @@ -pub use crate::spec::targets::x86_64_unknown_fuchsia::target; +pub(crate) use crate::spec::targets::x86_64_unknown_fuchsia::target; diff --git a/compiler/rustc_target/src/spec/targets/x86_64_linux_android.rs b/compiler/rustc_target/src/spec/targets/x86_64_linux_android.rs index 257093b75545d..84a747e1feb29 100644 --- a/compiler/rustc_target/src/spec/targets/x86_64_linux_android.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_linux_android.rs @@ -2,7 +2,7 @@ use crate::spec::{ base, Cc, LinkerFlavor, Lld, SanitizerSet, StackProbeType, Target, TargetOptions, }; -pub fn target() -> Target { +pub(crate) fn target() -> Target { let mut base = base::android::opts(); base.cpu = "x86-64".into(); base.plt_by_default = false; diff --git a/compiler/rustc_target/src/spec/targets/x86_64_pc_nto_qnx710.rs b/compiler/rustc_target/src/spec/targets/x86_64_pc_nto_qnx710.rs index f6d22ff320494..45963565b06d2 100644 --- a/compiler/rustc_target/src/spec/targets/x86_64_pc_nto_qnx710.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_pc_nto_qnx710.rs @@ -1,6 +1,6 @@ use crate::spec::{base, Cc, LinkerFlavor, Lld, Target, TargetOptions}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { Target { llvm_target: "x86_64-pc-unknown".into(), metadata: crate::spec::TargetMetadata { diff --git a/compiler/rustc_target/src/spec/targets/x86_64_pc_solaris.rs b/compiler/rustc_target/src/spec/targets/x86_64_pc_solaris.rs index 697daf590ad01..37cc7708d6310 100644 --- a/compiler/rustc_target/src/spec/targets/x86_64_pc_solaris.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_pc_solaris.rs @@ -1,6 +1,6 @@ use crate::spec::{base, Cc, LinkerFlavor, SanitizerSet, StackProbeType, Target}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { let mut base = base::solaris::opts(); base.add_pre_link_args(LinkerFlavor::Unix(Cc::Yes), &["-m64"]); base.cpu = "x86-64".into(); diff --git a/compiler/rustc_target/src/spec/targets/x86_64_pc_windows_gnu.rs b/compiler/rustc_target/src/spec/targets/x86_64_pc_windows_gnu.rs index 89a9bb1e1cc53..8efebfd42bba7 100644 --- a/compiler/rustc_target/src/spec/targets/x86_64_pc_windows_gnu.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_pc_windows_gnu.rs @@ -1,6 +1,6 @@ use crate::spec::{base, Cc, LinkerFlavor, Lld, Target}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { let mut base = base::windows_gnu::opts(); base.cpu = "x86-64".into(); base.features = "+cx16,+sse3,+sahf".into(); diff --git a/compiler/rustc_target/src/spec/targets/x86_64_pc_windows_gnullvm.rs b/compiler/rustc_target/src/spec/targets/x86_64_pc_windows_gnullvm.rs index acf0fd421bac9..056b0451bbebd 100644 --- a/compiler/rustc_target/src/spec/targets/x86_64_pc_windows_gnullvm.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_pc_windows_gnullvm.rs @@ -1,6 +1,6 @@ use crate::spec::{base, Cc, LinkerFlavor, Lld, Target}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { let mut base = base::windows_gnullvm::opts(); base.cpu = "x86-64".into(); base.features = "+cx16,+sse3,+sahf".into(); diff --git a/compiler/rustc_target/src/spec/targets/x86_64_pc_windows_msvc.rs b/compiler/rustc_target/src/spec/targets/x86_64_pc_windows_msvc.rs index 3ef3e5114e682..d1881caa27321 100644 --- a/compiler/rustc_target/src/spec/targets/x86_64_pc_windows_msvc.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_pc_windows_msvc.rs @@ -1,6 +1,6 @@ use crate::spec::{base, SanitizerSet, Target}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { let mut base = base::windows_msvc::opts(); base.cpu = "x86-64".into(); base.features = "+cx16,+sse3,+sahf".into(); diff --git a/compiler/rustc_target/src/spec/targets/x86_64_unikraft_linux_musl.rs b/compiler/rustc_target/src/spec/targets/x86_64_unikraft_linux_musl.rs index 883da26d786e1..43fac44e48b1f 100644 --- a/compiler/rustc_target/src/spec/targets/x86_64_unikraft_linux_musl.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_unikraft_linux_musl.rs @@ -1,6 +1,6 @@ use crate::spec::{base, Cc, LinkerFlavor, Lld, StackProbeType, Target, TargetOptions}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { Target { llvm_target: "x86_64-unknown-linux-musl".into(), metadata: crate::spec::TargetMetadata { diff --git a/compiler/rustc_target/src/spec/targets/x86_64_unknown_dragonfly.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_dragonfly.rs index 171a6f2a51e7c..7ad0dc69e7bd1 100644 --- a/compiler/rustc_target/src/spec/targets/x86_64_unknown_dragonfly.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_unknown_dragonfly.rs @@ -1,6 +1,6 @@ use crate::spec::{base, Cc, LinkerFlavor, Lld, StackProbeType, Target}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { let mut base = base::dragonfly::opts(); base.cpu = "x86-64".into(); base.plt_by_default = false; diff --git a/compiler/rustc_target/src/spec/targets/x86_64_unknown_freebsd.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_freebsd.rs index 4692b5a3c74ef..91cc6669f72c5 100644 --- a/compiler/rustc_target/src/spec/targets/x86_64_unknown_freebsd.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_unknown_freebsd.rs @@ -1,6 +1,6 @@ use crate::spec::{base, Cc, LinkerFlavor, Lld, SanitizerSet, StackProbeType, Target}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { let mut base = base::freebsd::opts(); base.cpu = "x86-64".into(); base.plt_by_default = false; diff --git a/compiler/rustc_target/src/spec/targets/x86_64_unknown_fuchsia.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_fuchsia.rs index 5ebf1804302b7..836d41a096350 100644 --- a/compiler/rustc_target/src/spec/targets/x86_64_unknown_fuchsia.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_unknown_fuchsia.rs @@ -1,6 +1,6 @@ use crate::spec::{base, SanitizerSet, StackProbeType, Target}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { let mut base = base::fuchsia::opts(); base.cpu = "x86-64".into(); base.plt_by_default = false; diff --git a/compiler/rustc_target/src/spec/targets/x86_64_unknown_haiku.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_haiku.rs index b593b79e7bbd4..7aab43b520aba 100644 --- a/compiler/rustc_target/src/spec/targets/x86_64_unknown_haiku.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_unknown_haiku.rs @@ -1,6 +1,6 @@ use crate::spec::{base, Cc, LinkerFlavor, Lld, StackProbeType, Target}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { let mut base = base::haiku::opts(); base.cpu = "x86-64".into(); base.plt_by_default = false; diff --git a/compiler/rustc_target/src/spec/targets/x86_64_unknown_hermit.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_hermit.rs index 3e81ff9a4ec4e..6bc3ec5428648 100644 --- a/compiler/rustc_target/src/spec/targets/x86_64_unknown_hermit.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_unknown_hermit.rs @@ -1,6 +1,6 @@ use crate::spec::{base, StackProbeType, Target, TargetOptions}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { Target { llvm_target: "x86_64-unknown-hermit".into(), metadata: crate::spec::TargetMetadata { diff --git a/compiler/rustc_target/src/spec/targets/x86_64_unknown_illumos.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_illumos.rs index d683a44202740..780fd6eb619e3 100644 --- a/compiler/rustc_target/src/spec/targets/x86_64_unknown_illumos.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_unknown_illumos.rs @@ -1,6 +1,6 @@ use crate::spec::{base, Cc, LinkerFlavor, SanitizerSet, Target}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { let mut base = base::illumos::opts(); base.add_pre_link_args(LinkerFlavor::Unix(Cc::Yes), &["-m64", "-std=c99"]); base.cpu = "x86-64".into(); diff --git a/compiler/rustc_target/src/spec/targets/x86_64_unknown_l4re_uclibc.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_l4re_uclibc.rs index adf489ad7b1dd..f67e9f3b3f11c 100644 --- a/compiler/rustc_target/src/spec/targets/x86_64_unknown_l4re_uclibc.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_unknown_l4re_uclibc.rs @@ -1,6 +1,6 @@ use crate::spec::{base, PanicStrategy, Target}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { let mut base = base::l4re::opts(); base.cpu = "x86-64".into(); base.plt_by_default = false; diff --git a/compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_gnu.rs index 4a92d4ef9d5ca..80f49d3a64529 100644 --- a/compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_gnu.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_gnu.rs @@ -1,6 +1,6 @@ use crate::spec::{base, Cc, LinkerFlavor, Lld, SanitizerSet, StackProbeType, Target}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { let mut base = base::linux_gnu::opts(); base.cpu = "x86-64".into(); base.plt_by_default = false; diff --git a/compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_gnux32.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_gnux32.rs index 3c7db0095a148..dce23e2ebee0d 100644 --- a/compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_gnux32.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_gnux32.rs @@ -1,6 +1,6 @@ use crate::spec::{base, Cc, LinkerFlavor, Lld, StackProbeType, Target}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { let mut base = base::linux_gnu::opts(); base.cpu = "x86-64".into(); base.abi = "x32".into(); diff --git a/compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_musl.rs index 109fc3c0728d8..0262c8fd34fdd 100644 --- a/compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_musl.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_musl.rs @@ -1,6 +1,6 @@ use crate::spec::{base, Cc, LinkerFlavor, Lld, SanitizerSet, StackProbeType, Target}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { let mut base = base::linux_musl::opts(); base.cpu = "x86-64".into(); base.plt_by_default = false; diff --git a/compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_none.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_none.rs index b6e331bd85453..47ff0460d7bde 100644 --- a/compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_none.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_none.rs @@ -1,6 +1,6 @@ use crate::spec::{base, Cc, LinkerFlavor, Lld, StackProbeType, Target}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { let mut base = base::linux::opts(); base.cpu = "x86-64".into(); base.max_atomic_width = Some(64); diff --git a/compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_ohos.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_ohos.rs index c1d888899fc21..28982bc13577d 100644 --- a/compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_ohos.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_ohos.rs @@ -1,6 +1,6 @@ use crate::spec::{base, Cc, LinkerFlavor, Lld, SanitizerSet, StackProbeType, Target}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { let mut base = base::linux_ohos::opts(); base.cpu = "x86-64".into(); base.max_atomic_width = Some(64); diff --git a/compiler/rustc_target/src/spec/targets/x86_64_unknown_netbsd.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_netbsd.rs index d413caf4aaf77..1ec07fe5a825e 100644 --- a/compiler/rustc_target/src/spec/targets/x86_64_unknown_netbsd.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_unknown_netbsd.rs @@ -2,7 +2,7 @@ use crate::spec::{ base, Cc, LinkerFlavor, Lld, SanitizerSet, StackProbeType, Target, TargetOptions, }; -pub fn target() -> Target { +pub(crate) fn target() -> Target { let mut base = base::netbsd::opts(); base.cpu = "x86-64".into(); base.plt_by_default = false; diff --git a/compiler/rustc_target/src/spec/targets/x86_64_unknown_none.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_none.rs index 175a53f237da1..cfefb1de99387 100644 --- a/compiler/rustc_target/src/spec/targets/x86_64_unknown_none.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_unknown_none.rs @@ -9,7 +9,7 @@ use crate::spec::{ Target, TargetOptions, }; -pub fn target() -> Target { +pub(crate) fn target() -> Target { let opts = TargetOptions { cpu: "x86-64".into(), plt_by_default: false, diff --git a/compiler/rustc_target/src/spec/targets/x86_64_unknown_openbsd.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_openbsd.rs index 8f1c3ef9bc7bb..580d0ef85309c 100644 --- a/compiler/rustc_target/src/spec/targets/x86_64_unknown_openbsd.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_unknown_openbsd.rs @@ -1,6 +1,6 @@ use crate::spec::{base, Cc, LinkerFlavor, Lld, StackProbeType, Target}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { let mut base = base::openbsd::opts(); base.cpu = "x86-64".into(); base.plt_by_default = false; diff --git a/compiler/rustc_target/src/spec/targets/x86_64_unknown_redox.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_redox.rs index ae38f63f034f7..5694395151899 100644 --- a/compiler/rustc_target/src/spec/targets/x86_64_unknown_redox.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_unknown_redox.rs @@ -1,6 +1,6 @@ use crate::spec::{base, Cc, LinkerFlavor, Lld, StackProbeType, Target}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { let mut base = base::redox::opts(); base.cpu = "x86-64".into(); base.plt_by_default = false; diff --git a/compiler/rustc_target/src/spec/targets/x86_64_unknown_uefi.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_uefi.rs index 2933da92fcc31..f5ab3afffc32c 100644 --- a/compiler/rustc_target/src/spec/targets/x86_64_unknown_uefi.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_unknown_uefi.rs @@ -8,7 +8,7 @@ use crate::abi::call::Conv; use crate::spec::{base, Target}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { let mut base = base::uefi_msvc::opts(); base.cpu = "x86-64".into(); base.plt_by_default = false; diff --git a/compiler/rustc_target/src/spec/targets/x86_64_uwp_windows_gnu.rs b/compiler/rustc_target/src/spec/targets/x86_64_uwp_windows_gnu.rs index c71bc9ed92317..69c70c96d2b54 100644 --- a/compiler/rustc_target/src/spec/targets/x86_64_uwp_windows_gnu.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_uwp_windows_gnu.rs @@ -1,6 +1,6 @@ use crate::spec::{base, Cc, LinkerFlavor, Lld, Target}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { let mut base = base::windows_uwp_gnu::opts(); base.cpu = "x86-64".into(); base.features = "+cx16,+sse3,+sahf".into(); diff --git a/compiler/rustc_target/src/spec/targets/x86_64_uwp_windows_msvc.rs b/compiler/rustc_target/src/spec/targets/x86_64_uwp_windows_msvc.rs index 178baeca68574..74493f0941f20 100644 --- a/compiler/rustc_target/src/spec/targets/x86_64_uwp_windows_msvc.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_uwp_windows_msvc.rs @@ -1,6 +1,6 @@ use crate::spec::{base, Target}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { let mut base = base::windows_uwp_msvc::opts(); base.cpu = "x86-64".into(); base.features = "+cx16,+sse3,+sahf".into(); diff --git a/compiler/rustc_target/src/spec/targets/x86_64_win7_windows_msvc.rs b/compiler/rustc_target/src/spec/targets/x86_64_win7_windows_msvc.rs index d44ae9fc4e0a1..815016e0adea5 100644 --- a/compiler/rustc_target/src/spec/targets/x86_64_win7_windows_msvc.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_win7_windows_msvc.rs @@ -1,6 +1,6 @@ use crate::spec::{base, Target}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { let mut base = base::windows_msvc::opts(); base.cpu = "x86-64".into(); base.plt_by_default = false; diff --git a/compiler/rustc_target/src/spec/targets/x86_64_wrs_vxworks.rs b/compiler/rustc_target/src/spec/targets/x86_64_wrs_vxworks.rs index 7b40f7366d0f3..604f71ffaa616 100644 --- a/compiler/rustc_target/src/spec/targets/x86_64_wrs_vxworks.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_wrs_vxworks.rs @@ -1,6 +1,6 @@ use crate::spec::{base, Cc, LinkerFlavor, Lld, StackProbeType, Target}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { let mut base = base::vxworks::opts(); base.cpu = "x86-64".into(); base.plt_by_default = false; diff --git a/compiler/rustc_target/src/spec/targets/x86_64h_apple_darwin.rs b/compiler/rustc_target/src/spec/targets/x86_64h_apple_darwin.rs index a932d4a3cb466..9b9ffe4e5360e 100644 --- a/compiler/rustc_target/src/spec/targets/x86_64h_apple_darwin.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64h_apple_darwin.rs @@ -1,7 +1,7 @@ use crate::spec::base::apple::{macos_llvm_target, opts, Arch, TargetAbi}; use crate::spec::{Cc, FramePointer, LinkerFlavor, Lld, SanitizerSet, Target, TargetOptions}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { let arch = Arch::X86_64h; let mut base = opts("macos", arch, TargetAbi::Normal); base.max_atomic_width = Some(128); diff --git a/compiler/rustc_target/src/spec/targets/xtensa_esp32_espidf.rs b/compiler/rustc_target/src/spec/targets/xtensa_esp32_espidf.rs index f041e791a9b0f..804659d3c5281 100644 --- a/compiler/rustc_target/src/spec/targets/xtensa_esp32_espidf.rs +++ b/compiler/rustc_target/src/spec/targets/xtensa_esp32_espidf.rs @@ -2,7 +2,7 @@ use crate::abi::Endian; use crate::spec::base::xtensa; use crate::spec::{cvs, Target, TargetOptions}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { Target { llvm_target: "xtensa-none-elf".into(), pointer_width: 32, diff --git a/compiler/rustc_target/src/spec/targets/xtensa_esp32_none_elf.rs b/compiler/rustc_target/src/spec/targets/xtensa_esp32_none_elf.rs index 05666bd81aa13..51960dbec4af4 100644 --- a/compiler/rustc_target/src/spec/targets/xtensa_esp32_none_elf.rs +++ b/compiler/rustc_target/src/spec/targets/xtensa_esp32_none_elf.rs @@ -1,7 +1,7 @@ use crate::spec::base::xtensa; use crate::spec::{Target, TargetOptions}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { Target { llvm_target: "xtensa-none-elf".into(), pointer_width: 32, diff --git a/compiler/rustc_target/src/spec/targets/xtensa_esp32s2_espidf.rs b/compiler/rustc_target/src/spec/targets/xtensa_esp32s2_espidf.rs index 83ef520551f55..6c15a82e95cd7 100644 --- a/compiler/rustc_target/src/spec/targets/xtensa_esp32s2_espidf.rs +++ b/compiler/rustc_target/src/spec/targets/xtensa_esp32s2_espidf.rs @@ -2,7 +2,7 @@ use crate::abi::Endian; use crate::spec::base::xtensa; use crate::spec::{cvs, Target, TargetOptions}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { Target { llvm_target: "xtensa-none-elf".into(), pointer_width: 32, diff --git a/compiler/rustc_target/src/spec/targets/xtensa_esp32s2_none_elf.rs b/compiler/rustc_target/src/spec/targets/xtensa_esp32s2_none_elf.rs index aa125eb1ba689..21330615a874d 100644 --- a/compiler/rustc_target/src/spec/targets/xtensa_esp32s2_none_elf.rs +++ b/compiler/rustc_target/src/spec/targets/xtensa_esp32s2_none_elf.rs @@ -1,7 +1,7 @@ use crate::spec::base::xtensa; use crate::spec::{Target, TargetOptions}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { Target { llvm_target: "xtensa-none-elf".into(), pointer_width: 32, diff --git a/compiler/rustc_target/src/spec/targets/xtensa_esp32s3_espidf.rs b/compiler/rustc_target/src/spec/targets/xtensa_esp32s3_espidf.rs index e18acfccf5ff2..536bd6dc1b2d9 100644 --- a/compiler/rustc_target/src/spec/targets/xtensa_esp32s3_espidf.rs +++ b/compiler/rustc_target/src/spec/targets/xtensa_esp32s3_espidf.rs @@ -2,7 +2,7 @@ use crate::abi::Endian; use crate::spec::base::xtensa; use crate::spec::{cvs, Target, TargetOptions}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { Target { llvm_target: "xtensa-none-elf".into(), pointer_width: 32, diff --git a/compiler/rustc_target/src/spec/targets/xtensa_esp32s3_none_elf.rs b/compiler/rustc_target/src/spec/targets/xtensa_esp32s3_none_elf.rs index ecbb51dfb665d..fca47b4bdb121 100644 --- a/compiler/rustc_target/src/spec/targets/xtensa_esp32s3_none_elf.rs +++ b/compiler/rustc_target/src/spec/targets/xtensa_esp32s3_none_elf.rs @@ -1,7 +1,7 @@ use crate::spec::base::xtensa; use crate::spec::{Target, TargetOptions}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { Target { llvm_target: "xtensa-none-elf".into(), pointer_width: 32, From c4f6f52139f6a708ad183ec2cb619429d2c5eaaa Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 30 Aug 2024 15:23:49 +1000 Subject: [PATCH 0407/2194] Add `warn(unreachable_pub)` to `rustc_traits`. --- compiler/rustc_traits/src/codegen.rs | 2 +- compiler/rustc_traits/src/lib.rs | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_traits/src/codegen.rs b/compiler/rustc_traits/src/codegen.rs index ada2c8e81de5b..1118219824652 100644 --- a/compiler/rustc_traits/src/codegen.rs +++ b/compiler/rustc_traits/src/codegen.rs @@ -21,7 +21,7 @@ use tracing::debug; /// obligations *could be* resolved if we wanted to. /// /// This also expects that `trait_ref` is fully normalized. -pub fn codegen_select_candidate<'tcx>( +pub(crate) fn codegen_select_candidate<'tcx>( tcx: TyCtxt<'tcx>, (param_env, trait_ref): (ty::ParamEnv<'tcx>, ty::TraitRef<'tcx>), ) -> Result<&'tcx ImplSource<'tcx, ()>, CodegenObligationError> { diff --git a/compiler/rustc_traits/src/lib.rs b/compiler/rustc_traits/src/lib.rs index 697c839180312..d2f979bd6d9dc 100644 --- a/compiler/rustc_traits/src/lib.rs +++ b/compiler/rustc_traits/src/lib.rs @@ -2,6 +2,7 @@ // tidy-alphabetical-start #![recursion_limit = "256"] +#![warn(unreachable_pub)] // tidy-alphabetical-end mod codegen; From 2e358e633d3af1dd6a4138c6c53b9d5d97f3a202 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 30 Aug 2024 15:53:47 +1000 Subject: [PATCH 0408/2194] Add `warn(unreachable_pub)` to `rustc_trait_selection`. --- compiler/rustc_trait_selection/src/lib.rs | 1 + .../rustc_trait_selection/src/traits/coherence.rs | 2 +- .../src/traits/object_safety.rs | 10 +++++----- .../src/traits/select/_match.rs | 4 ++-- .../rustc_trait_selection/src/traits/select/mod.rs | 2 +- compiler/rustc_trait_selection/src/traits/util.rs | 14 +++++++------- 6 files changed, 17 insertions(+), 16 deletions(-) diff --git a/compiler/rustc_trait_selection/src/lib.rs b/compiler/rustc_trait_selection/src/lib.rs index aea47c9e987ae..a17c007debd8b 100644 --- a/compiler/rustc_trait_selection/src/lib.rs +++ b/compiler/rustc_trait_selection/src/lib.rs @@ -32,6 +32,7 @@ #![feature(unwrap_infallible)] #![feature(yeet_expr)] #![recursion_limit = "512"] // For rustdoc +#![warn(unreachable_pub)] // For rustdoc // tidy-alphabetical-end pub mod error_reporting; diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs index bf4b0482081d9..8ff803657f046 100644 --- a/compiler/rustc_trait_selection/src/traits/coherence.rs +++ b/compiler/rustc_trait_selection/src/traits/coherence.rs @@ -54,7 +54,7 @@ pub fn add_placeholder_note(err: &mut Diag<'_, G>) { ); } -pub fn suggest_increasing_recursion_limit<'tcx, G: EmissionGuarantee>( +pub(crate) fn suggest_increasing_recursion_limit<'tcx, G: EmissionGuarantee>( tcx: TyCtxt<'tcx>, err: &mut Diag<'_, G>, overflowing_predicates: &[ty::Predicate<'tcx>], diff --git a/compiler/rustc_trait_selection/src/traits/object_safety.rs b/compiler/rustc_trait_selection/src/traits/object_safety.rs index fa696dcd2f59a..a3d5c5307974d 100644 --- a/compiler/rustc_trait_selection/src/traits/object_safety.rs +++ b/compiler/rustc_trait_selection/src/traits/object_safety.rs @@ -29,8 +29,8 @@ use tracing::{debug, instrument}; use super::elaborate; use crate::infer::TyCtxtInferExt; use crate::traits::query::evaluate_obligation::InferCtxtExt; -use crate::traits::{util, Obligation, ObligationCause}; -pub use crate::traits::{MethodViolationCode, ObjectSafetyViolation}; +pub use crate::traits::ObjectSafetyViolation; +use crate::traits::{util, MethodViolationCode, Obligation, ObligationCause}; /// Returns the object safety violations that affect HIR ty lowering. /// @@ -512,7 +512,7 @@ fn virtual_call_violations_for_method<'tcx>( /// /// This check is outlined from the object safety check to avoid cycles with /// layout computation, which relies on knowing whether methods are object safe. -pub fn check_receiver_correct<'tcx>(tcx: TyCtxt<'tcx>, trait_def_id: DefId, method: ty::AssocItem) { +fn check_receiver_correct<'tcx>(tcx: TyCtxt<'tcx>, trait_def_id: DefId, method: ty::AssocItem) { if !is_vtable_safe_method(tcx, trait_def_id, method) { return; } @@ -906,7 +906,7 @@ impl<'tcx> TypeFolder> for EraseEscapingBoundRegions<'tcx> { } } -pub fn contains_illegal_impl_trait_in_trait<'tcx>( +fn contains_illegal_impl_trait_in_trait<'tcx>( tcx: TyCtxt<'tcx>, fn_def_id: DefId, ty: ty::Binder<'tcx, Ty<'tcx>>, @@ -930,7 +930,7 @@ pub fn contains_illegal_impl_trait_in_trait<'tcx>( }) } -pub fn provide(providers: &mut Providers) { +pub(crate) fn provide(providers: &mut Providers) { *providers = Providers { object_safety_violations, is_object_safe, diff --git a/compiler/rustc_trait_selection/src/traits/select/_match.rs b/compiler/rustc_trait_selection/src/traits/select/_match.rs index 7ead65721f9bb..f77f83ed4471c 100644 --- a/compiler/rustc_trait_selection/src/traits/select/_match.rs +++ b/compiler/rustc_trait_selection/src/traits/select/_match.rs @@ -21,12 +21,12 @@ use tracing::instrument; /// Like subtyping, matching is really a binary relation, so the only /// important thing about the result is Ok/Err. Also, matching never /// affects any type variables or unification state. -pub struct MatchAgainstFreshVars<'tcx> { +pub(crate) struct MatchAgainstFreshVars<'tcx> { tcx: TyCtxt<'tcx>, } impl<'tcx> MatchAgainstFreshVars<'tcx> { - pub fn new(tcx: TyCtxt<'tcx>) -> MatchAgainstFreshVars<'tcx> { + pub(crate) fn new(tcx: TyCtxt<'tcx>) -> MatchAgainstFreshVars<'tcx> { MatchAgainstFreshVars { tcx } } } diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 91fe19c20f77b..bc4a3398f9b35 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -3127,7 +3127,7 @@ impl<'o, 'tcx> fmt::Debug for TraitObligationStack<'o, 'tcx> { } } -pub enum ProjectionMatchesProjection { +pub(crate) enum ProjectionMatchesProjection { Yes, Ambiguous, No, diff --git a/compiler/rustc_trait_selection/src/traits/util.rs b/compiler/rustc_trait_selection/src/traits/util.rs index 0689b880f3305..0fb13799e67d5 100644 --- a/compiler/rustc_trait_selection/src/traits/util.rs +++ b/compiler/rustc_trait_selection/src/traits/util.rs @@ -169,7 +169,7 @@ impl<'tcx> Iterator for TraitAliasExpander<'tcx> { /// Instantiate all bound parameters of the impl subject with the given args, /// returning the resulting subject and all obligations that arise. /// The obligations are closed under normalization. -pub fn impl_subject_and_oblig<'a, 'tcx>( +pub(crate) fn impl_subject_and_oblig<'a, 'tcx>( selcx: &SelectionContext<'a, 'tcx>, param_env: ty::ParamEnv<'tcx>, impl_def_id: DefId, @@ -209,7 +209,7 @@ pub fn upcast_choices<'tcx>( supertraits(tcx, source_trait_ref).filter(|r| r.def_id() == target_trait_def_id).collect() } -pub fn closure_trait_ref_and_return_type<'tcx>( +pub(crate) fn closure_trait_ref_and_return_type<'tcx>( tcx: TyCtxt<'tcx>, fn_trait_def_id: DefId, self_ty: Ty<'tcx>, @@ -238,7 +238,7 @@ pub fn closure_trait_ref_and_return_type<'tcx>( sig.map_bound(|sig| (trait_ref, sig.output())) } -pub fn coroutine_trait_ref_and_outputs<'tcx>( +pub(crate) fn coroutine_trait_ref_and_outputs<'tcx>( tcx: TyCtxt<'tcx>, fn_trait_def_id: DefId, self_ty: Ty<'tcx>, @@ -249,7 +249,7 @@ pub fn coroutine_trait_ref_and_outputs<'tcx>( (trait_ref, sig.yield_ty, sig.return_ty) } -pub fn future_trait_ref_and_outputs<'tcx>( +pub(crate) fn future_trait_ref_and_outputs<'tcx>( tcx: TyCtxt<'tcx>, fn_trait_def_id: DefId, self_ty: Ty<'tcx>, @@ -260,7 +260,7 @@ pub fn future_trait_ref_and_outputs<'tcx>( (trait_ref, sig.return_ty) } -pub fn iterator_trait_ref_and_outputs<'tcx>( +pub(crate) fn iterator_trait_ref_and_outputs<'tcx>( tcx: TyCtxt<'tcx>, iterator_def_id: DefId, self_ty: Ty<'tcx>, @@ -271,7 +271,7 @@ pub fn iterator_trait_ref_and_outputs<'tcx>( (trait_ref, sig.yield_ty) } -pub fn async_iterator_trait_ref_and_outputs<'tcx>( +pub(crate) fn async_iterator_trait_ref_and_outputs<'tcx>( tcx: TyCtxt<'tcx>, async_iterator_def_id: DefId, self_ty: Ty<'tcx>, @@ -287,7 +287,7 @@ pub fn impl_item_is_final(tcx: TyCtxt<'_>, assoc_item: &ty::AssocItem) -> bool { && tcx.defaultness(assoc_item.container_id(tcx)).is_final() } -pub enum TupleArgumentsFlag { +pub(crate) enum TupleArgumentsFlag { Yes, No, } From e4b1e2803378e1f4eb6eff0d5042e15239fae6e2 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 30 Aug 2024 16:15:56 +1000 Subject: [PATCH 0409/2194] Add `warn(unreachable_pub)` to `rustc_transmute`. --- compiler/rustc_transmute/src/layout/tree.rs | 2 +- compiler/rustc_transmute/src/layout/tree/tests.rs | 2 +- compiler/rustc_transmute/src/lib.rs | 1 + compiler/rustc_transmute/src/maybe_transmutable/mod.rs | 4 ++-- 4 files changed, 5 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_transmute/src/layout/tree.rs b/compiler/rustc_transmute/src/layout/tree.rs index 2c67e7d4847ac..c3fd771b79734 100644 --- a/compiler/rustc_transmute/src/layout/tree.rs +++ b/compiler/rustc_transmute/src/layout/tree.rs @@ -204,7 +204,7 @@ pub(crate) mod rustc { } impl<'tcx> Tree, Ref<'tcx>> { - pub fn from_ty(ty: Ty<'tcx>, cx: LayoutCx<'tcx, TyCtxt<'tcx>>) -> Result { + pub(crate) fn from_ty(ty: Ty<'tcx>, cx: LayoutCx<'tcx, TyCtxt<'tcx>>) -> Result { use rustc_target::abi::HasDataLayout; let layout = layout_of(cx, ty)?; diff --git a/compiler/rustc_transmute/src/layout/tree/tests.rs b/compiler/rustc_transmute/src/layout/tree/tests.rs index 3cb47517c2195..44f50a25c939a 100644 --- a/compiler/rustc_transmute/src/layout/tree/tests.rs +++ b/compiler/rustc_transmute/src/layout/tree/tests.rs @@ -1,7 +1,7 @@ use super::Tree; #[derive(Debug, Hash, Eq, PartialEq, Clone, Copy)] -pub enum Def { +enum Def { NoSafetyInvariants, HasSafetyInvariants, } diff --git a/compiler/rustc_transmute/src/lib.rs b/compiler/rustc_transmute/src/lib.rs index bdc98bcea5eb0..c1d0b704ab287 100644 --- a/compiler/rustc_transmute/src/lib.rs +++ b/compiler/rustc_transmute/src/lib.rs @@ -2,6 +2,7 @@ #![allow(unused_variables)] #![feature(alloc_layout_extra)] #![feature(never_type)] +#![warn(unreachable_pub)] // tidy-alphabetical-end pub(crate) use rustc_data_structures::fx::{FxIndexMap as Map, FxIndexSet as Set}; diff --git a/compiler/rustc_transmute/src/maybe_transmutable/mod.rs b/compiler/rustc_transmute/src/maybe_transmutable/mod.rs index 2762b4e638405..b3e1bb31e58e0 100644 --- a/compiler/rustc_transmute/src/maybe_transmutable/mod.rs +++ b/compiler/rustc_transmute/src/maybe_transmutable/mod.rs @@ -366,13 +366,13 @@ where } } -pub enum Quantifier { +enum Quantifier { ThereExists, ForAll, } impl Quantifier { - pub fn apply(&self, iter: I) -> Answer + fn apply(&self, iter: I) -> Answer where R: layout::Ref, I: IntoIterator>, From 3e09c450b418c7cf6d2ad54d989aa36bb20d9e80 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 30 Aug 2024 16:30:18 +1000 Subject: [PATCH 0410/2194] Add `warn(unreachable_pub)` to `rustc_type_ir`. --- compiler/rustc_type_ir/src/fold.rs | 2 +- compiler/rustc_type_ir/src/lib.rs | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_type_ir/src/fold.rs b/compiler/rustc_type_ir/src/fold.rs index 8e3534b0e9eb4..f49aa3431b5c0 100644 --- a/compiler/rustc_type_ir/src/fold.rs +++ b/compiler/rustc_type_ir/src/fold.rs @@ -354,7 +354,7 @@ struct Shifter { } impl Shifter { - pub fn new(cx: I, amount: u32) -> Self { + fn new(cx: I, amount: u32) -> Self { Shifter { cx, current_index: ty::INNERMOST, amount } } } diff --git a/compiler/rustc_type_ir/src/lib.rs b/compiler/rustc_type_ir/src/lib.rs index f763153a5fc88..be261b348de52 100644 --- a/compiler/rustc_type_ir/src/lib.rs +++ b/compiler/rustc_type_ir/src/lib.rs @@ -6,6 +6,7 @@ )] #![cfg_attr(feature = "nightly", allow(internal_features))] #![cfg_attr(not(bootstrap), allow(rustc::usage_of_type_ir_inherent))] +#![warn(unreachable_pub)] // tidy-alphabetical-end extern crate self as rustc_type_ir; From d7caea129d3703d3021d29d873fc87ef9a97602f Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 30 Aug 2024 16:32:12 +1000 Subject: [PATCH 0411/2194] Add `warn(unreachable_pub)` to `rustc_ty_utils`. --- compiler/rustc_ty_utils/src/errors.rs | 20 ++++++++++---------- compiler/rustc_ty_utils/src/lib.rs | 1 + 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/compiler/rustc_ty_utils/src/errors.rs b/compiler/rustc_ty_utils/src/errors.rs index 42ecaaeafa905..5497d7d0bd2a0 100644 --- a/compiler/rustc_ty_utils/src/errors.rs +++ b/compiler/rustc_ty_utils/src/errors.rs @@ -7,14 +7,14 @@ use rustc_span::Span; #[derive(Diagnostic)] #[diag(ty_utils_needs_drop_overflow)] -pub struct NeedsDropOverflow<'tcx> { +pub(crate) struct NeedsDropOverflow<'tcx> { pub query_ty: Ty<'tcx>, } #[derive(Diagnostic)] #[diag(ty_utils_generic_constant_too_complex)] #[help] -pub struct GenericConstantTooComplex { +pub(crate) struct GenericConstantTooComplex { #[primary_span] pub span: Span, #[note(ty_utils_maybe_supported)] @@ -24,7 +24,7 @@ pub struct GenericConstantTooComplex { } #[derive(Subdiagnostic)] -pub enum GenericConstantTooComplexSub { +pub(crate) enum GenericConstantTooComplexSub { #[label(ty_utils_borrow_not_supported)] BorrowNotSupported(#[primary_span] Span), #[label(ty_utils_address_and_deref_not_supported)] @@ -71,40 +71,40 @@ pub enum GenericConstantTooComplexSub { #[derive(Diagnostic)] #[diag(ty_utils_unexpected_fnptr_associated_item)] -pub struct UnexpectedFnPtrAssociatedItem { +pub(crate) struct UnexpectedFnPtrAssociatedItem { #[primary_span] pub span: Span, } #[derive(Diagnostic)] #[diag(ty_utils_zero_length_simd_type)] -pub struct ZeroLengthSimdType<'tcx> { +pub(crate) struct ZeroLengthSimdType<'tcx> { pub ty: Ty<'tcx>, } #[derive(Diagnostic)] #[diag(ty_utils_multiple_array_fields_simd_type)] -pub struct MultipleArrayFieldsSimdType<'tcx> { +pub(crate) struct MultipleArrayFieldsSimdType<'tcx> { pub ty: Ty<'tcx>, } #[derive(Diagnostic)] #[diag(ty_utils_oversized_simd_type)] -pub struct OversizedSimdType<'tcx> { +pub(crate) struct OversizedSimdType<'tcx> { pub ty: Ty<'tcx>, pub max_lanes: u64, } #[derive(Diagnostic)] #[diag(ty_utils_non_primitive_simd_type)] -pub struct NonPrimitiveSimdType<'tcx> { +pub(crate) struct NonPrimitiveSimdType<'tcx> { pub ty: Ty<'tcx>, pub e_ty: Ty<'tcx>, } #[derive(Diagnostic)] #[diag(ty_utils_impl_trait_duplicate_arg)] -pub struct DuplicateArg<'tcx> { +pub(crate) struct DuplicateArg<'tcx> { pub arg: GenericArg<'tcx>, #[primary_span] #[label] @@ -115,7 +115,7 @@ pub struct DuplicateArg<'tcx> { #[derive(Diagnostic)] #[diag(ty_utils_impl_trait_not_param, code = E0792)] -pub struct NotParam<'tcx> { +pub(crate) struct NotParam<'tcx> { pub arg: GenericArg<'tcx>, #[primary_span] #[label] diff --git a/compiler/rustc_ty_utils/src/lib.rs b/compiler/rustc_ty_utils/src/lib.rs index ad0bcbfbbc2ac..dc5303317a8a0 100644 --- a/compiler/rustc_ty_utils/src/lib.rs +++ b/compiler/rustc_ty_utils/src/lib.rs @@ -16,6 +16,7 @@ #![feature(let_chains)] #![feature(never_type)] #![feature(rustdoc_internals)] +#![warn(unreachable_pub)] // tidy-alphabetical-end use rustc_middle::query::Providers; From 88b6a78d0b8b7661db8bea0d0743652bcb9a4600 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 30 Aug 2024 16:36:04 +1000 Subject: [PATCH 0412/2194] Add `warn(unreachable_pub)` to `rustc_const_eval`. --- .../src/check_consts/check.rs | 6 +-- .../rustc_const_eval/src/check_consts/ops.rs | 40 +++++++++---------- .../rustc_const_eval/src/interpret/place.rs | 4 +- compiler/rustc_const_eval/src/lib.rs | 1 + 4 files changed, 26 insertions(+), 25 deletions(-) diff --git a/compiler/rustc_const_eval/src/check_consts/check.rs b/compiler/rustc_const_eval/src/check_consts/check.rs index 7cfb101399daa..8be327a8b5647 100644 --- a/compiler/rustc_const_eval/src/check_consts/check.rs +++ b/compiler/rustc_const_eval/src/check_consts/check.rs @@ -46,7 +46,7 @@ impl<'mir, 'tcx> Qualifs<'mir, 'tcx> { /// Returns `true` if `local` is `NeedsDrop` at the given `Location`. /// /// Only updates the cursor if absolutely necessary - pub fn needs_drop( + fn needs_drop( &mut self, ccx: &'mir ConstCx<'mir, 'tcx>, local: Local, @@ -76,7 +76,7 @@ impl<'mir, 'tcx> Qualifs<'mir, 'tcx> { /// Returns `true` if `local` is `NeedsNonConstDrop` at the given `Location`. /// /// Only updates the cursor if absolutely necessary - pub fn needs_non_const_drop( + pub(crate) fn needs_non_const_drop( &mut self, ccx: &'mir ConstCx<'mir, 'tcx>, local: Local, @@ -106,7 +106,7 @@ impl<'mir, 'tcx> Qualifs<'mir, 'tcx> { /// Returns `true` if `local` is `HasMutInterior` at the given `Location`. /// /// Only updates the cursor if absolutely necessary. - pub fn has_mut_interior( + fn has_mut_interior( &mut self, ccx: &'mir ConstCx<'mir, 'tcx>, local: Local, diff --git a/compiler/rustc_const_eval/src/check_consts/ops.rs b/compiler/rustc_const_eval/src/check_consts/ops.rs index 93fafa6055773..e8f10c88408ba 100644 --- a/compiler/rustc_const_eval/src/check_consts/ops.rs +++ b/compiler/rustc_const_eval/src/check_consts/ops.rs @@ -57,7 +57,7 @@ pub trait NonConstOp<'tcx>: std::fmt::Debug { /// A function call where the callee is a pointer. #[derive(Debug)] -pub struct FnCallIndirect; +pub(crate) struct FnCallIndirect; impl<'tcx> NonConstOp<'tcx> for FnCallIndirect { fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> Diag<'tcx> { ccx.dcx().create_err(errors::UnallowedFnPointerCall { span, kind: ccx.const_kind() }) @@ -66,7 +66,7 @@ impl<'tcx> NonConstOp<'tcx> for FnCallIndirect { /// A function call where the callee is not marked as `const`. #[derive(Debug, Clone, Copy)] -pub struct FnCallNonConst<'tcx> { +pub(crate) struct FnCallNonConst<'tcx> { pub caller: LocalDefId, pub callee: DefId, pub args: GenericArgsRef<'tcx>, @@ -299,7 +299,7 @@ impl<'tcx> NonConstOp<'tcx> for FnCallNonConst<'tcx> { /// /// Contains the name of the feature that would allow the use of this function. #[derive(Debug)] -pub struct FnCallUnstable(pub DefId, pub Option); +pub(crate) struct FnCallUnstable(pub DefId, pub Option); impl<'tcx> NonConstOp<'tcx> for FnCallUnstable { fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> Diag<'tcx> { @@ -324,7 +324,7 @@ impl<'tcx> NonConstOp<'tcx> for FnCallUnstable { } #[derive(Debug)] -pub struct Coroutine(pub hir::CoroutineKind); +pub(crate) struct Coroutine(pub hir::CoroutineKind); impl<'tcx> NonConstOp<'tcx> for Coroutine { fn status_in_item(&self, _: &ConstCx<'_, 'tcx>) -> Status { if let hir::CoroutineKind::Desugared( @@ -356,7 +356,7 @@ impl<'tcx> NonConstOp<'tcx> for Coroutine { } #[derive(Debug)] -pub struct HeapAllocation; +pub(crate) struct HeapAllocation; impl<'tcx> NonConstOp<'tcx> for HeapAllocation { fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> Diag<'tcx> { ccx.dcx().create_err(errors::UnallowedHeapAllocations { @@ -368,7 +368,7 @@ impl<'tcx> NonConstOp<'tcx> for HeapAllocation { } #[derive(Debug)] -pub struct InlineAsm; +pub(crate) struct InlineAsm; impl<'tcx> NonConstOp<'tcx> for InlineAsm { fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> Diag<'tcx> { ccx.dcx().create_err(errors::UnallowedInlineAsm { span, kind: ccx.const_kind() }) @@ -376,7 +376,7 @@ impl<'tcx> NonConstOp<'tcx> for InlineAsm { } #[derive(Debug)] -pub struct LiveDrop<'tcx> { +pub(crate) struct LiveDrop<'tcx> { pub dropped_at: Option, pub dropped_ty: Ty<'tcx>, } @@ -394,7 +394,7 @@ impl<'tcx> NonConstOp<'tcx> for LiveDrop<'tcx> { #[derive(Debug)] /// A borrow of a type that contains an `UnsafeCell` somewhere. The borrow never escapes to /// the final value of the constant. -pub struct TransientCellBorrow; +pub(crate) struct TransientCellBorrow; impl<'tcx> NonConstOp<'tcx> for TransientCellBorrow { fn status_in_item(&self, _: &ConstCx<'_, 'tcx>) -> Status { Status::Unstable(sym::const_refs_to_cell) @@ -410,7 +410,7 @@ impl<'tcx> NonConstOp<'tcx> for TransientCellBorrow { /// A borrow of a type that contains an `UnsafeCell` somewhere. The borrow might escape to /// the final value of the constant, and thus we cannot allow this (for now). We may allow /// it in the future for static items. -pub struct CellBorrow; +pub(crate) struct CellBorrow; impl<'tcx> NonConstOp<'tcx> for CellBorrow { fn importance(&self) -> DiagImportance { // Most likely the code will try to do mutation with these borrows, which @@ -431,7 +431,7 @@ impl<'tcx> NonConstOp<'tcx> for CellBorrow { /// This op is for `&mut` borrows in the trailing expression of a constant /// which uses the "enclosing scopes rule" to leak its locals into anonymous /// static or const items. -pub struct MutBorrow(pub hir::BorrowKind); +pub(crate) struct MutBorrow(pub hir::BorrowKind); impl<'tcx> NonConstOp<'tcx> for MutBorrow { fn status_in_item(&self, _ccx: &ConstCx<'_, 'tcx>) -> Status { @@ -461,7 +461,7 @@ impl<'tcx> NonConstOp<'tcx> for MutBorrow { } #[derive(Debug)] -pub struct TransientMutBorrow(pub hir::BorrowKind); +pub(crate) struct TransientMutBorrow(pub hir::BorrowKind); impl<'tcx> NonConstOp<'tcx> for TransientMutBorrow { fn status_in_item(&self, _: &ConstCx<'_, 'tcx>) -> Status { @@ -484,7 +484,7 @@ impl<'tcx> NonConstOp<'tcx> for TransientMutBorrow { } #[derive(Debug)] -pub struct MutDeref; +pub(crate) struct MutDeref; impl<'tcx> NonConstOp<'tcx> for MutDeref { fn status_in_item(&self, _: &ConstCx<'_, 'tcx>) -> Status { Status::Unstable(sym::const_mut_refs) @@ -505,7 +505,7 @@ impl<'tcx> NonConstOp<'tcx> for MutDeref { /// A call to a `panic()` lang item where the first argument is _not_ a `&str`. #[derive(Debug)] -pub struct PanicNonStr; +pub(crate) struct PanicNonStr; impl<'tcx> NonConstOp<'tcx> for PanicNonStr { fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> Diag<'tcx> { ccx.dcx().create_err(errors::PanicNonStrErr { span }) @@ -516,7 +516,7 @@ impl<'tcx> NonConstOp<'tcx> for PanicNonStr { /// Not currently intended to ever be allowed, even behind a feature gate: operation depends on /// allocation base addresses that are not known at compile-time. #[derive(Debug)] -pub struct RawPtrComparison; +pub(crate) struct RawPtrComparison; impl<'tcx> NonConstOp<'tcx> for RawPtrComparison { fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> Diag<'tcx> { // FIXME(const_trait_impl): revert to span_bug? @@ -525,7 +525,7 @@ impl<'tcx> NonConstOp<'tcx> for RawPtrComparison { } #[derive(Debug)] -pub struct RawMutPtrDeref; +pub(crate) struct RawMutPtrDeref; impl<'tcx> NonConstOp<'tcx> for RawMutPtrDeref { fn status_in_item(&self, _: &ConstCx<'_, '_>) -> Status { Status::Unstable(sym::const_mut_refs) @@ -546,7 +546,7 @@ impl<'tcx> NonConstOp<'tcx> for RawMutPtrDeref { /// Not currently intended to ever be allowed, even behind a feature gate: operation depends on /// allocation base addresses that are not known at compile-time. #[derive(Debug)] -pub struct RawPtrToIntCast; +pub(crate) struct RawPtrToIntCast; impl<'tcx> NonConstOp<'tcx> for RawPtrToIntCast { fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> Diag<'tcx> { ccx.dcx().create_err(errors::RawPtrToIntErr { span }) @@ -555,7 +555,7 @@ impl<'tcx> NonConstOp<'tcx> for RawPtrToIntCast { /// An access to a (non-thread-local) `static`. #[derive(Debug)] -pub struct StaticAccess; +pub(crate) struct StaticAccess; impl<'tcx> NonConstOp<'tcx> for StaticAccess { fn status_in_item(&self, ccx: &ConstCx<'_, 'tcx>) -> Status { if let hir::ConstContext::Static(_) = ccx.const_kind() { @@ -582,7 +582,7 @@ impl<'tcx> NonConstOp<'tcx> for StaticAccess { /// An access to a thread-local `static`. #[derive(Debug)] -pub struct ThreadLocalAccess; +pub(crate) struct ThreadLocalAccess; impl<'tcx> NonConstOp<'tcx> for ThreadLocalAccess { fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> Diag<'tcx> { ccx.dcx().create_err(errors::ThreadLocalAccessErr { span }) @@ -590,11 +590,11 @@ impl<'tcx> NonConstOp<'tcx> for ThreadLocalAccess { } /// Types that cannot appear in the signature or locals of a `const fn`. -pub mod mut_ref { +pub(crate) mod mut_ref { use super::*; #[derive(Debug)] - pub struct MutRef(pub mir::LocalKind); + pub(crate) struct MutRef(pub mir::LocalKind); impl<'tcx> NonConstOp<'tcx> for MutRef { fn status_in_item(&self, _ccx: &ConstCx<'_, 'tcx>) -> Status { Status::Unstable(sym::const_mut_refs) diff --git a/compiler/rustc_const_eval/src/interpret/place.rs b/compiler/rustc_const_eval/src/interpret/place.rs index ede6a51c712b9..220ba97f90eed 100644 --- a/compiler/rustc_const_eval/src/interpret/place.rs +++ b/compiler/rustc_const_eval/src/interpret/place.rs @@ -61,13 +61,13 @@ pub(super) struct MemPlace { impl MemPlace { /// Adjust the provenance of the main pointer (metadata is unaffected). - pub fn map_provenance(self, f: impl FnOnce(Prov) -> Prov) -> Self { + fn map_provenance(self, f: impl FnOnce(Prov) -> Prov) -> Self { MemPlace { ptr: self.ptr.map_provenance(|p| p.map(f)), ..self } } /// Turn a mplace into a (thin or wide) pointer, as a reference, pointing to the same space. #[inline] - pub fn to_ref(self, cx: &impl HasDataLayout) -> Immediate { + fn to_ref(self, cx: &impl HasDataLayout) -> Immediate { Immediate::new_pointer_with_meta(self.ptr, self.meta, cx) } diff --git a/compiler/rustc_const_eval/src/lib.rs b/compiler/rustc_const_eval/src/lib.rs index d825a47bfdf5d..73dda81bd298b 100644 --- a/compiler/rustc_const_eval/src/lib.rs +++ b/compiler/rustc_const_eval/src/lib.rs @@ -14,6 +14,7 @@ #![feature(trait_alias)] #![feature(try_blocks)] #![feature(yeet_expr)] +#![warn(unreachable_pub)] // tidy-alphabetical-end pub mod check_consts; From 55bc638a1d3e5c19fcec3462bb8357dea6f7f56c Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 3 Sep 2024 00:42:13 +0200 Subject: [PATCH 0413/2194] Fix wrong padding for expanded scraped example --- src/librustdoc/html/static/css/rustdoc.css | 7 +++++++ .../scrape-examples-button-focus.goml | 4 ++-- tests/rustdoc-gui/scrape-examples-layout.goml | 19 +++++++++++++++++++ 3 files changed, 28 insertions(+), 2 deletions(-) diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css index fa5a936d3f452..b69689cfb6875 100644 --- a/src/librustdoc/html/static/css/rustdoc.css +++ b/src/librustdoc/html/static/css/rustdoc.css @@ -789,11 +789,18 @@ both the code example and the line numbers, so we need to remove the radius in t } .rustdoc:not(.src) .scraped-example:not(.expanded) .src-line-numbers, +.rustdoc:not(.src) .scraped-example:not(.expanded) .src-line-numbers > pre, .rustdoc:not(.src) .scraped-example:not(.expanded) pre.rust { padding-bottom: 0; /* See above comment, should be the same max-height. */ overflow: auto hidden; } +.rustdoc:not(.src) .scraped-example .src-line-numbers { + padding-top: 0; +} +.rustdoc:not(.src) .scraped-example.expanded .src-line-numbers { + padding-bottom: 0; +} .rustdoc:not(.src) .example-wrap pre { overflow: auto; diff --git a/tests/rustdoc-gui/scrape-examples-button-focus.goml b/tests/rustdoc-gui/scrape-examples-button-focus.goml index 442a3a4dcad10..83ed6a219b25a 100644 --- a/tests/rustdoc-gui/scrape-examples-button-focus.goml +++ b/tests/rustdoc-gui/scrape-examples-button-focus.goml @@ -29,10 +29,10 @@ assert-property: (".scraped-example-list > .scraped-example .rust", { // The expand button increases the scrollHeight of the minimized code viewport store-property: (".scraped-example-list > .scraped-example pre", {"offsetHeight": smallOffsetHeight}) -assert-property-false: (".scraped-example-list > .scraped-example .src-line-numbers", { +assert-property: (".scraped-example-list > .scraped-example .src-line-numbers", { "scrollHeight": |smallOffsetHeight| }, NEAR) -assert-property-false: (".scraped-example-list > .scraped-example .rust", { +assert-property: (".scraped-example-list > .scraped-example .rust", { "scrollHeight": |smallOffsetHeight| }, NEAR) focus: ".scraped-example-list > .scraped-example .expand" diff --git a/tests/rustdoc-gui/scrape-examples-layout.goml b/tests/rustdoc-gui/scrape-examples-layout.goml index f0023f7022a69..6bea352bce4bb 100644 --- a/tests/rustdoc-gui/scrape-examples-layout.goml +++ b/tests/rustdoc-gui/scrape-examples-layout.goml @@ -47,6 +47,25 @@ assert-position: (".scraped-example .scraped-example-title", { "y": |y| + |height| - |title_height| - 8, }) +// Check that the expand button works and also that line number aligns with code. +move-cursor-to: ".scraped-example .rust" +click: ".scraped-example .button-holder .expand" +wait-for: ".scraped-example.expanded" +// They should have the same y position. +compare-elements-position: ( + ".scraped-example.expanded .src-line-numbers pre span", + ".scraped-example.expanded .rust code", + ["y"], +) +// And they should have the same height. +compare-elements-size: ( + ".scraped-example.expanded .src-line-numbers", + ".scraped-example.expanded .rust", + ["height"], +) +// Collapse code again. +click: ".scraped-example .button-holder .expand" + // Check that for both mobile and desktop sizes, the buttons in scraped examples are displayed // correctly. From 8104457a1197353f1ed276117a4603076f26e42f Mon Sep 17 00:00:00 2001 From: DropDemBits Date: Mon, 2 Sep 2024 19:11:39 -0400 Subject: [PATCH 0414/2194] support insert{_all} --- .../crates/syntax/src/syntax_editor.rs | 32 +++++++++ .../syntax/src/syntax_editor/edit_algo.rs | 67 ++++++++++++++++--- 2 files changed, 88 insertions(+), 11 deletions(-) diff --git a/src/tools/rust-analyzer/crates/syntax/src/syntax_editor.rs b/src/tools/rust-analyzer/crates/syntax/src/syntax_editor.rs index 75347aeeed909..4b5134249c8d6 100644 --- a/src/tools/rust-analyzer/crates/syntax/src/syntax_editor.rs +++ b/src/tools/rust-analyzer/crates/syntax/src/syntax_editor.rs @@ -50,6 +50,14 @@ impl SyntaxEditor { self.annotations.append(&mut other.annotations); } + pub fn insert(&mut self, position: Position, element: impl Element) { + self.changes.push(Change::Insert(position, element.syntax_element())) + } + + pub fn insert_all(&mut self, position: Position, elements: Vec) { + self.changes.push(Change::InsertAll(position, elements)) + } + pub fn delete(&mut self, element: impl Element) { self.changes.push(Change::Replace(element.syntax_element(), None)); } @@ -117,6 +125,19 @@ pub struct Position { repr: PositionRepr, } +impl Position { + pub(crate) fn parent(&self) -> SyntaxNode { + self.place().0 + } + + pub(crate) fn place(&self) -> (SyntaxNode, usize) { + match &self.repr { + PositionRepr::FirstChild(parent) => (parent.clone(), 0), + PositionRepr::After(child) => (child.parent().unwrap(), child.index() + 1), + } + } +} + #[derive(Debug)] enum PositionRepr { FirstChild(SyntaxNode), @@ -155,6 +176,8 @@ impl Position { #[derive(Debug)] enum Change { + Insert(Position, SyntaxElement), + InsertAll(Position, Vec), /// Represents both a replace single element and a delete element operation. Replace(SyntaxElement, Option), } @@ -162,18 +185,27 @@ enum Change { impl Change { fn target_range(&self) -> TextRange { match self { + Change::Insert(target, _) | Change::InsertAll(target, _) => match &target.repr { + PositionRepr::FirstChild(parent) => TextRange::at( + parent.first_child_or_token().unwrap().text_range().start(), + 0.into(), + ), + PositionRepr::After(child) => TextRange::at(child.text_range().end(), 0.into()), + }, Change::Replace(target, _) => target.text_range(), } } fn target_parent(&self) -> SyntaxNode { match self { + Change::Insert(target, _) | Change::InsertAll(target, _) => target.parent(), Change::Replace(target, _) => target.parent().unwrap(), } } fn change_kind(&self) -> ChangeKind { match self { + Change::Insert(_, _) | Change::InsertAll(_, _) => ChangeKind::Insert, Change::Replace(_, _) => ChangeKind::Replace, } } diff --git a/src/tools/rust-analyzer/crates/syntax/src/syntax_editor/edit_algo.rs b/src/tools/rust-analyzer/crates/syntax/src/syntax_editor/edit_algo.rs index 734a26b60033d..4f0b30ed6ad14 100644 --- a/src/tools/rust-analyzer/crates/syntax/src/syntax_editor/edit_algo.rs +++ b/src/tools/rust-analyzer/crates/syntax/src/syntax_editor/edit_algo.rs @@ -4,8 +4,8 @@ use rowan::TextRange; use rustc_hash::{FxHashMap, FxHashSet}; use crate::{ - syntax_editor::{mapping::MissingMapping, Change, ChangeKind}, - ted, SyntaxElement, SyntaxNode, SyntaxNodePtr, + syntax_editor::{mapping::MissingMapping, Change, ChangeKind, Position, PositionRepr}, + SyntaxElement, SyntaxNode, SyntaxNodePtr, }; use super::{SyntaxEdit, SyntaxEditor}; @@ -94,6 +94,7 @@ pub(super) fn apply_edits(editor: SyntaxEditor) -> SyntaxEdit { // Add to changed ancestors, if applicable match change { + Change::Insert(_, _) | Change::InsertAll(_, _) => {} Change::Replace(target, _) => { changed_ancestors.push_back(ChangedAncestor::single(target, change_index)) } @@ -106,23 +107,46 @@ pub(super) fn apply_edits(editor: SyntaxEditor) -> SyntaxEdit { for index in independent_changes { match &mut changes[index as usize] { - Change::Replace(target, new_node) => { + Change::Insert(target, _) | Change::InsertAll(target, _) => { + match &mut target.repr { + PositionRepr::FirstChild(parent) => { + *parent = tree_mutator.make_syntax_mut(parent); + } + PositionRepr::After(child) => { + *child = tree_mutator.make_element_mut(child); + } + }; + } + Change::Replace(target, _) => { *target = tree_mutator.make_element_mut(target); - - if let Some(new_node) = new_node { - changed_elements.push(new_node.clone()); - } } } + + // Collect changed elements + match &changes[index as usize] { + Change::Insert(_, element) => changed_elements.push(element.clone()), + Change::InsertAll(_, elements) => changed_elements.extend(elements.iter().cloned()), + Change::Replace(_, Some(element)) => changed_elements.push(element.clone()), + Change::Replace(_, None) => {} + } } for DependentChange { parent, child } in dependent_changes.into_iter() { let (input_ancestor, output_ancestor) = match &changes[parent as usize] { - // insert? unreachable + // No change will depend on an insert since changes can only depend on nodes in the root tree + Change::Insert(_, _) | Change::InsertAll(_, _) => unreachable!(), Change::Replace(target, Some(new_target)) => { (to_owning_node(target), to_owning_node(new_target)) } - Change::Replace(_, None) => continue, // silently drop outdated change + // Silently drop outdated change + Change::Replace(_, None) => continue, + }; + + let upmap_target_node = |target: &SyntaxNode| { + match mappings.upmap_child(target, &input_ancestor, &output_ancestor) { + Ok(it) => it, + Err(MissingMapping(current)) => unreachable!("no mappings exist between {current:?} (ancestor of {input_ancestor:?}) and {output_ancestor:?}"), + } }; let upmap_target = |target: &SyntaxElement| { @@ -133,6 +157,14 @@ pub(super) fn apply_edits(editor: SyntaxEditor) -> SyntaxEdit { }; match &mut changes[child as usize] { + Change::Insert(target, _) | Change::InsertAll(target, _) => match &mut target.repr { + PositionRepr::FirstChild(parent) => { + *parent = upmap_target_node(parent); + } + PositionRepr::After(child) => { + *child = upmap_target(child); + } + }, Change::Replace(target, _) => { *target = upmap_target(&target); } @@ -142,8 +174,21 @@ pub(super) fn apply_edits(editor: SyntaxEditor) -> SyntaxEdit { // Apply changes for change in changes { match change { - Change::Replace(target, None) => ted::remove(target), - Change::Replace(target, Some(new_target)) => ted::replace(target, new_target), + Change::Insert(position, element) => { + let (parent, index) = position.place(); + parent.splice_children(index..index, vec![element]); + } + Change::InsertAll(position, elements) => { + let (parent, index) = position.place(); + parent.splice_children(index..index, elements); + } + Change::Replace(target, None) => { + target.detach(); + } + Change::Replace(target, Some(new_target)) => { + let parent = target.parent().unwrap(); + parent.splice_children(target.index()..target.index() + 1, vec![new_target]); + } } } From f08299f9f8014ed9fb0f13f76afaebdb7cb9d2ab Mon Sep 17 00:00:00 2001 From: DropDemBits Date: Mon, 2 Sep 2024 20:45:57 -0400 Subject: [PATCH 0415/2194] fix insert ranges not being excluded from disjointness --- .../syntax/src/syntax_editor/edit_algo.rs | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/src/tools/rust-analyzer/crates/syntax/src/syntax_editor/edit_algo.rs b/src/tools/rust-analyzer/crates/syntax/src/syntax_editor/edit_algo.rs index 4f0b30ed6ad14..4d6cb01c01c01 100644 --- a/src/tools/rust-analyzer/crates/syntax/src/syntax_editor/edit_algo.rs +++ b/src/tools/rust-analyzer/crates/syntax/src/syntax_editor/edit_algo.rs @@ -1,10 +1,10 @@ use std::{collections::VecDeque, ops::RangeInclusive}; use rowan::TextRange; -use rustc_hash::{FxHashMap, FxHashSet}; +use rustc_hash::FxHashMap; use crate::{ - syntax_editor::{mapping::MissingMapping, Change, ChangeKind, Position, PositionRepr}, + syntax_editor::{mapping::MissingMapping, Change, ChangeKind, PositionRepr}, SyntaxElement, SyntaxNode, SyntaxNodePtr, }; @@ -41,12 +41,17 @@ pub(super) fn apply_edits(editor: SyntaxEditor) -> SyntaxEdit { .then(a.change_kind().cmp(&b.change_kind())) }); - let disjoint_replaces_ranges = changes.iter().zip(changes.iter().skip(1)).all(|(l, r)| { - l.change_kind() == ChangeKind::Replace - && r.change_kind() == ChangeKind::Replace - && (l.target_parent() != r.target_parent() + let disjoint_replaces_ranges = changes + .iter() + .zip(changes.iter().skip(1)) + .filter(|(l, r)| { + // We only care about checking for disjoint replace ranges + l.change_kind() == ChangeKind::Replace && r.change_kind() == ChangeKind::Replace + }) + .all(|(l, r)| { + (l.target_parent() != r.target_parent() || l.target_range().intersect(r.target_range()).is_none()) - }); + }); if stdx::never!( !disjoint_replaces_ranges, From 8d3e5fa0ae31a4b00ef7dc8d895e12865af08747 Mon Sep 17 00:00:00 2001 From: Kevin Mehall Date: Mon, 2 Sep 2024 17:38:51 -0600 Subject: [PATCH 0416/2194] Move the `data` and `vtable` methods from `RawWaker` to `Waker` Per the `waker_getters` FCP: https://github.com/rust-lang/rust/issues/96992#issuecomment-1941998046 --- library/core/src/task/wake.rs | 44 +++++++++++++++++------------------ library/core/tests/waker.rs | 11 ++++----- 2 files changed, 27 insertions(+), 28 deletions(-) diff --git a/library/core/src/task/wake.rs b/library/core/src/task/wake.rs index 7e5c1574f5367..9baaa274bb071 100644 --- a/library/core/src/task/wake.rs +++ b/library/core/src/task/wake.rs @@ -60,22 +60,6 @@ impl RawWaker { RawWaker { data, vtable } } - /// Gets the `data` pointer used to create this `RawWaker`. - #[inline] - #[must_use] - #[unstable(feature = "waker_getters", issue = "96992")] - pub fn data(&self) -> *const () { - self.data - } - - /// Gets the `vtable` pointer used to create this `RawWaker`. - #[inline] - #[must_use] - #[unstable(feature = "waker_getters", issue = "96992")] - pub fn vtable(&self) -> &'static RawWakerVTable { - self.vtable - } - #[unstable(feature = "noop_waker", issue = "98286")] const NOOP: RawWaker = { const VTABLE: RawWakerVTable = RawWakerVTable::new( @@ -565,12 +549,20 @@ impl Waker { WAKER } - /// Gets a reference to the underlying [`RawWaker`]. + /// Gets the `data` pointer used to create this `Waker`. #[inline] #[must_use] #[unstable(feature = "waker_getters", issue = "96992")] - pub fn as_raw(&self) -> &RawWaker { - &self.waker + pub fn data(&self) -> *const () { + self.waker.data + } + + /// Gets the `vtable` pointer used to create this `Waker`. + #[inline] + #[must_use] + #[unstable(feature = "waker_getters", issue = "96992")] + pub fn vtable(&self) -> &'static RawWakerVTable { + self.waker.vtable } } @@ -831,12 +823,20 @@ impl LocalWaker { WAKER } - /// Gets a reference to the underlying [`RawWaker`]. + /// Gets the `data` pointer used to create this `LocalWaker`. #[inline] #[must_use] #[unstable(feature = "waker_getters", issue = "96992")] - pub fn as_raw(&self) -> &RawWaker { - &self.waker + pub fn data(&self) -> *const () { + self.waker.data + } + + /// Gets the `vtable` pointer used to create this `LocalWaker`. + #[inline] + #[must_use] + #[unstable(feature = "waker_getters", issue = "96992")] + pub fn vtable(&self) -> &'static RawWakerVTable { + self.waker.vtable } } #[unstable(feature = "local_waker", issue = "118959")] diff --git a/library/core/tests/waker.rs b/library/core/tests/waker.rs index 361e900e69562..8f6bf0565fc35 100644 --- a/library/core/tests/waker.rs +++ b/library/core/tests/waker.rs @@ -4,14 +4,13 @@ use std::task::{RawWaker, RawWakerVTable, Waker}; #[test] fn test_waker_getters() { let raw_waker = RawWaker::new(ptr::without_provenance_mut(42usize), &WAKER_VTABLE); - assert_eq!(raw_waker.data() as usize, 42); - assert!(ptr::eq(raw_waker.vtable(), &WAKER_VTABLE)); - let waker = unsafe { Waker::from_raw(raw_waker) }; + assert_eq!(waker.data() as usize, 42); + assert!(ptr::eq(waker.vtable(), &WAKER_VTABLE)); + let waker2 = waker.clone(); - let raw_waker2 = waker2.as_raw(); - assert_eq!(raw_waker2.data() as usize, 43); - assert!(ptr::eq(raw_waker2.vtable(), &WAKER_VTABLE)); + assert_eq!(waker2.data() as usize, 43); + assert!(ptr::eq(waker2.vtable(), &WAKER_VTABLE)); } static WAKER_VTABLE: RawWakerVTable = RawWakerVTable::new( From 2dc75148ee4ac7e6edfc25911b28b877e1bed0f6 Mon Sep 17 00:00:00 2001 From: Kevin Mehall Date: Mon, 2 Sep 2024 17:42:50 -0600 Subject: [PATCH 0417/2194] Stabilize waker_getters --- library/core/src/task/wake.rs | 8 ++++---- library/core/tests/lib.rs | 1 - 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/library/core/src/task/wake.rs b/library/core/src/task/wake.rs index 9baaa274bb071..8dc7e33aed363 100644 --- a/library/core/src/task/wake.rs +++ b/library/core/src/task/wake.rs @@ -552,7 +552,7 @@ impl Waker { /// Gets the `data` pointer used to create this `Waker`. #[inline] #[must_use] - #[unstable(feature = "waker_getters", issue = "96992")] + #[stable(feature = "waker_getters", since = "CURRENT_RUSTC_VERSION")] pub fn data(&self) -> *const () { self.waker.data } @@ -560,7 +560,7 @@ impl Waker { /// Gets the `vtable` pointer used to create this `Waker`. #[inline] #[must_use] - #[unstable(feature = "waker_getters", issue = "96992")] + #[stable(feature = "waker_getters", since = "CURRENT_RUSTC_VERSION")] pub fn vtable(&self) -> &'static RawWakerVTable { self.waker.vtable } @@ -826,7 +826,7 @@ impl LocalWaker { /// Gets the `data` pointer used to create this `LocalWaker`. #[inline] #[must_use] - #[unstable(feature = "waker_getters", issue = "96992")] + #[unstable(feature = "local_waker", issue = "118959")] pub fn data(&self) -> *const () { self.waker.data } @@ -834,7 +834,7 @@ impl LocalWaker { /// Gets the `vtable` pointer used to create this `LocalWaker`. #[inline] #[must_use] - #[unstable(feature = "waker_getters", issue = "96992")] + #[unstable(feature = "local_waker", issue = "118959")] pub fn vtable(&self) -> &'static RawWakerVTable { self.waker.vtable } diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs index c205f028dd3a7..96fc621494f2a 100644 --- a/library/core/tests/lib.rs +++ b/library/core/tests/lib.rs @@ -112,7 +112,6 @@ #![feature(unsize)] #![feature(unsized_tuple_coercion)] #![feature(unwrap_infallible)] -#![feature(waker_getters)] // tidy-alphabetical-end #![allow(internal_features)] #![deny(fuzzy_provenance_casts)] From 22bd31977294f0c948409ec24034895f14b59ade Mon Sep 17 00:00:00 2001 From: Kevin Mehall Date: Mon, 2 Sep 2024 18:25:09 -0600 Subject: [PATCH 0418/2194] Add `Waker::new` and `LocalWaker::new` Per the `waker_getters` FCP: https://github.com/rust-lang/rust/issues/96992#issuecomment-1941998046 Docs largely copied from `RawWaker::new`. --- library/core/src/task/wake.rs | 55 +++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) diff --git a/library/core/src/task/wake.rs b/library/core/src/task/wake.rs index 8dc7e33aed363..6924b3c13ece3 100644 --- a/library/core/src/task/wake.rs +++ b/library/core/src/task/wake.rs @@ -493,6 +493,37 @@ impl Waker { a_data == b_data && ptr::eq(a_vtable, b_vtable) } + /// Creates a new `Waker` from the provided `data` pointer and `vtable`. + /// + /// The `data` pointer can be used to store arbitrary data as required + /// by the executor. This could be e.g. a type-erased pointer to an `Arc` + /// that is associated with the task. + /// The value of this pointer will get passed to all functions that are part + /// of the `vtable` as the first parameter. + /// + /// It is important to consider that the `data` pointer must point to a + /// thread safe type such as an `Arc`. + /// + /// The `vtable` customizes the behavior of a `Waker`. For each operation + /// on the `Waker`, the associated function in the `vtable` will be called. + /// + /// # Safety + /// + /// The behavior of the returned `Waker` is undefined if the contract defined + /// in [`RawWakerVTable`]'s documentation is not upheld. + /// + /// (Authors wishing to avoid unsafe code may implement the [`Wake`] trait instead, at the + /// cost of a required heap allocation.) + /// + /// [`Wake`]: ../../alloc/task/trait.Wake.html + #[inline] + #[must_use] + #[stable(feature = "waker_getters", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "waker_getters", since = "CURRENT_RUSTC_VERSION")] + pub const unsafe fn new(data: *const (), vtable: &'static RawWakerVTable) -> Self { + Waker { waker: RawWaker { data, vtable } } + } + /// Creates a new `Waker` from [`RawWaker`]. /// /// # Safety @@ -770,6 +801,30 @@ impl LocalWaker { a_data == b_data && ptr::eq(a_vtable, b_vtable) } + /// Creates a new `LocalWaker` from the provided `data` pointer and `vtable`. + /// + /// The `data` pointer can be used to store arbitrary data as required + /// by the executor. This could be e.g. a type-erased pointer to an `Arc` + /// that is associated with the task. + /// The value of this pointer will get passed to all functions that are part + /// of the `vtable` as the first parameter. + /// + /// The `vtable` customizes the behavior of a `LocalWaker`. For each + /// operation on the `LocalWaker`, the associated function in the `vtable` + /// will be called. + /// + /// # Safety + /// + /// The behavior of the returned `Waker` is undefined if the contract defined + /// in [`RawWakerVTable`]'s documentation is not upheld. + /// + #[inline] + #[must_use] + #[unstable(feature = "local_waker", issue = "118959")] + pub const unsafe fn new(data: *const (), vtable: &'static RawWakerVTable) -> Self { + LocalWaker { waker: RawWaker { data, vtable } } + } + /// Creates a new `LocalWaker` from [`RawWaker`]. /// /// The behavior of the returned `LocalWaker` is undefined if the contract defined From f74ef3aa526f1b293f37b6574d5d24f5532d810f Mon Sep 17 00:00:00 2001 From: DropDemBits Date: Mon, 2 Sep 2024 21:34:00 -0400 Subject: [PATCH 0419/2194] properly sort changes by depth to sort between nodes that have the same start range --- .../syntax/src/syntax_editor/edit_algo.rs | 23 +++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/src/tools/rust-analyzer/crates/syntax/src/syntax_editor/edit_algo.rs b/src/tools/rust-analyzer/crates/syntax/src/syntax_editor/edit_algo.rs index 4d6cb01c01c01..2adc1f67d144c 100644 --- a/src/tools/rust-analyzer/crates/syntax/src/syntax_editor/edit_algo.rs +++ b/src/tools/rust-analyzer/crates/syntax/src/syntax_editor/edit_algo.rs @@ -1,4 +1,4 @@ -use std::{collections::VecDeque, ops::RangeInclusive}; +use std::{cmp::Ordering, collections::VecDeque, ops::RangeInclusive}; use rowan::TextRange; use rustc_hash::FxHashMap; @@ -30,7 +30,12 @@ pub(super) fn apply_edits(editor: SyntaxEditor) -> SyntaxEdit { let SyntaxEditor { root, mut changes, mappings, annotations } = editor; - // Sort changes by range then change kind, so that we can: + let mut node_depths = FxHashMap::::default(); + let mut get_node_depth = |node: SyntaxNode| { + *node_depths.entry(node).or_insert_with_key(|node| node.ancestors().count()) + }; + + // Sort changes by range, then depth, then change kind, so that we can: // - ensure that parent edits are ordered before child edits // - ensure that inserts will be guaranteed to be inserted at the right range // - easily check for disjoint replace ranges @@ -38,6 +43,16 @@ pub(super) fn apply_edits(editor: SyntaxEditor) -> SyntaxEdit { a.target_range() .start() .cmp(&b.target_range().start()) + .then_with(|| { + let a_target = a.target_parent(); + let b_target = b.target_parent(); + + if a_target == b_target { + return Ordering::Equal; + } + + get_node_depth(a_target).cmp(&get_node_depth(b_target)) + }) .then(a.change_kind().cmp(&b.change_kind())) }); @@ -49,8 +64,8 @@ pub(super) fn apply_edits(editor: SyntaxEditor) -> SyntaxEdit { l.change_kind() == ChangeKind::Replace && r.change_kind() == ChangeKind::Replace }) .all(|(l, r)| { - (l.target_parent() != r.target_parent() - || l.target_range().intersect(r.target_range()).is_none()) + get_node_depth(l.target_parent()) != get_node_depth(r.target_parent()) + || l.target_range().intersect(r.target_range()).is_none() }); if stdx::never!( From f03f95f36918c5d64ead3fdafc920915ac204e04 Mon Sep 17 00:00:00 2001 From: DropDemBits Date: Mon, 2 Sep 2024 21:42:08 -0400 Subject: [PATCH 0420/2194] support replacing root node --- .../crates/syntax/src/syntax_editor.rs | 197 +++++++++++++++++- .../syntax/src/syntax_editor/edit_algo.rs | 16 +- .../syntax/src/syntax_editor/mapping.rs | 1 - 3 files changed, 200 insertions(+), 14 deletions(-) diff --git a/src/tools/rust-analyzer/crates/syntax/src/syntax_editor.rs b/src/tools/rust-analyzer/crates/syntax/src/syntax_editor.rs index 4b5134249c8d6..77a560bfe5c45 100644 --- a/src/tools/rust-analyzer/crates/syntax/src/syntax_editor.rs +++ b/src/tools/rust-analyzer/crates/syntax/src/syntax_editor.rs @@ -51,18 +51,28 @@ impl SyntaxEditor { } pub fn insert(&mut self, position: Position, element: impl Element) { + debug_assert!(is_ancestor_or_self(&position.parent(), &self.root)); self.changes.push(Change::Insert(position, element.syntax_element())) } pub fn insert_all(&mut self, position: Position, elements: Vec) { + debug_assert!(is_ancestor_or_self(&position.parent(), &self.root)); self.changes.push(Change::InsertAll(position, elements)) } pub fn delete(&mut self, element: impl Element) { + let element = element.syntax_element(); + debug_assert!(is_ancestor_or_self_of_element(&element, &self.root)); + debug_assert!( + !matches!(&element, SyntaxElement::Node(node) if node == &self.root), + "should not delete root node" + ); self.changes.push(Change::Replace(element.syntax_element(), None)); } pub fn replace(&mut self, old: impl Element, new: impl Element) { + let old = old.syntax_element(); + debug_assert!(is_ancestor_or_self_of_element(&old, &self.root)); self.changes.push(Change::Replace(old.syntax_element(), Some(new.syntax_element()))); } @@ -199,7 +209,10 @@ impl Change { fn target_parent(&self) -> SyntaxNode { match self { Change::Insert(target, _) | Change::InsertAll(target, _) => target.parent(), - Change::Replace(target, _) => target.parent().unwrap(), + Change::Replace(SyntaxElement::Node(target), _) => { + target.parent().unwrap_or_else(|| target.clone()) + } + Change::Replace(SyntaxElement::Token(target), _) => target.parent().unwrap(), } } @@ -248,6 +261,15 @@ impl Element for SyntaxToken { } } +fn is_ancestor_or_self(node: &SyntaxNode, ancestor: &SyntaxNode) -> bool { + node == ancestor || node.ancestors().any(|it| &it == ancestor) +} + +fn is_ancestor_or_self_of_element(node: &SyntaxElement, ancestor: &SyntaxNode) -> bool { + matches!(node, SyntaxElement::Node(node) if node == ancestor) + || node.ancestors().any(|it| &it == ancestor) +} + #[cfg(test)] mod tests { use expect_test::expect; @@ -370,15 +392,11 @@ mod tests { Some(to_wrap.clone().into()), ); - // should die: editor.replace(to_replace.syntax(), name_ref.syntax()); editor.replace(to_wrap.syntax(), new_block.syntax()); - // editor.replace(to_replace.syntax(), name_ref.syntax()); let edit = editor.finish(); - dbg!(&edit.annotations); - let expect = expect![[r#" _ => { let var_name = 2 + 2; @@ -393,4 +411,173 @@ mod tests { .flat_map(|(_, elements)| elements) .all(|element| element.ancestors().any(|it| &it == edit.root()))) } + + #[test] + #[should_panic = "some replace change ranges intersect: [Replace(Node(TUPLE_EXPR@5..7), Some(Node(NAME_REF@0..8))), Replace(Node(TUPLE_EXPR@5..7), Some(Node(NAME_REF@0..8)))]"] + fn fail_on_non_disjoint_single_replace() { + let root = make::match_arm([make::wildcard_pat().into()], None, make::expr_tuple([])); + + let to_wrap = root.syntax().descendants().find_map(ast::TupleExpr::cast).unwrap(); + + let mut editor = SyntaxEditor::new(root.syntax().clone()); + + let name_ref = make::name_ref("var_name").clone_for_update(); + + // should die, ranges are not disjoint + editor.replace(to_wrap.syntax(), name_ref.syntax()); + editor.replace(to_wrap.syntax(), name_ref.syntax()); + + let _ = editor.finish(); + } + + #[test] + fn test_insert_independent() { + let root = make::block_expr( + [make::let_stmt( + make::ext::simple_ident_pat(make::name("second")).into(), + None, + Some(make::expr_literal("2").into()), + ) + .into()], + None, + ); + + let second_let = root.syntax().descendants().find_map(ast::LetStmt::cast).unwrap(); + + let mut editor = SyntaxEditor::new(root.syntax().clone()); + + editor.insert( + Position::first_child_of(root.stmt_list().unwrap().syntax()), + make_let_stmt( + None, + make::ext::simple_ident_pat(make::name("first")).into(), + None, + Some(make::expr_literal("1").into()), + ) + .syntax(), + ); + + editor.insert( + Position::after(second_let.syntax()), + make_let_stmt( + None, + make::ext::simple_ident_pat(make::name("third")).into(), + None, + Some(make::expr_literal("3").into()), + ) + .syntax(), + ); + + let edit = editor.finish(); + + let expect = expect![[r#" + let first = 1;{ + let second = 2;let third = 3; + }"#]]; + expect.assert_eq(&edit.root.to_string()); + } + + #[test] + fn test_insert_dependent() { + let root = make::block_expr( + [], + Some( + make::block_expr( + [make::let_stmt( + make::ext::simple_ident_pat(make::name("second")).into(), + None, + Some(make::expr_literal("2").into()), + ) + .into()], + None, + ) + .into(), + ), + ); + + let inner_block = + root.syntax().descendants().flat_map(ast::BlockExpr::cast).nth(1).unwrap(); + let second_let = root.syntax().descendants().find_map(ast::LetStmt::cast).unwrap(); + + let mut editor = SyntaxEditor::new(root.syntax().clone()); + + let new_block_expr = + make_block_expr(Some(&mut editor), [], Some(ast::Expr::BlockExpr(inner_block.clone()))); + + let first_let = make_let_stmt( + Some(&mut editor), + make::ext::simple_ident_pat(make::name("first")).into(), + None, + Some(make::expr_literal("1").into()), + ); + + let third_let = make_let_stmt( + Some(&mut editor), + make::ext::simple_ident_pat(make::name("third")).into(), + None, + Some(make::expr_literal("3").into()), + ); + + editor.insert( + Position::first_child_of(inner_block.stmt_list().unwrap().syntax()), + first_let.syntax(), + ); + editor.insert(Position::after(second_let.syntax()), third_let.syntax()); + editor.replace(inner_block.syntax(), new_block_expr.syntax()); + + let edit = editor.finish(); + + let expect = expect![[r#" + { + { + let first = 1;{ + let second = 2;let third = 3; + } + } + }"#]]; + expect.assert_eq(&edit.root.to_string()); + } + + #[test] + fn test_replace_root_with_dependent() { + let root = make::block_expr( + [make::let_stmt( + make::ext::simple_ident_pat(make::name("second")).into(), + None, + Some(make::expr_literal("2").into()), + ) + .into()], + None, + ); + + let inner_block = root.clone(); + + let mut editor = SyntaxEditor::new(root.syntax().clone()); + + let new_block_expr = + make_block_expr(Some(&mut editor), [], Some(ast::Expr::BlockExpr(inner_block.clone()))); + + let first_let = make_let_stmt( + Some(&mut editor), + make::ext::simple_ident_pat(make::name("first")).into(), + None, + Some(make::expr_literal("1").into()), + ); + + editor.insert( + Position::first_child_of(inner_block.stmt_list().unwrap().syntax()), + first_let.syntax(), + ); + editor.replace(inner_block.syntax(), new_block_expr.syntax()); + + let edit = editor.finish(); + + let expect = expect![[r#" + { + let first = 1;{ + let second = 2; + } + }"#]]; + expect.assert_eq(&edit.root.to_string()); + } } diff --git a/src/tools/rust-analyzer/crates/syntax/src/syntax_editor/edit_algo.rs b/src/tools/rust-analyzer/crates/syntax/src/syntax_editor/edit_algo.rs index 2adc1f67d144c..2c331fc1f69e3 100644 --- a/src/tools/rust-analyzer/crates/syntax/src/syntax_editor/edit_algo.rs +++ b/src/tools/rust-analyzer/crates/syntax/src/syntax_editor/edit_algo.rs @@ -192,6 +192,8 @@ pub(super) fn apply_edits(editor: SyntaxEditor) -> SyntaxEdit { } // Apply changes + let mut root = tree_mutator.mutable_clone; + for change in changes { match change { Change::Insert(position, element) => { @@ -205,6 +207,9 @@ pub(super) fn apply_edits(editor: SyntaxEditor) -> SyntaxEdit { Change::Replace(target, None) => { target.detach(); } + Change::Replace(SyntaxElement::Node(target), Some(new_target)) if &target == &root => { + root = new_target.into_node().expect("root node replacement should be a node"); + } Change::Replace(target, Some(new_target)) => { let parent = target.parent().unwrap(); parent.splice_children(target.index()..target.index() + 1, vec![new_target]); @@ -214,7 +219,7 @@ pub(super) fn apply_edits(editor: SyntaxEditor) -> SyntaxEdit { // Propagate annotations let annotations = annotations.into_iter().filter_map(|(element, annotation)| { - match mappings.upmap_element(&element, &tree_mutator.mutable_clone) { + match mappings.upmap_element(&element, &root) { // Needed to follow the new tree to find the resulting element Some(Ok(mapped)) => Some((mapped, annotation)), // Element did not need to be mapped @@ -230,11 +235,7 @@ pub(super) fn apply_edits(editor: SyntaxEditor) -> SyntaxEdit { annotation_groups.entry(annotation).or_insert(vec![]).push(element); } - SyntaxEdit { - root: tree_mutator.mutable_clone, - changed_elements, - annotations: annotation_groups, - } + SyntaxEdit { root, changed_elements, annotations: annotation_groups } } fn to_owning_node(element: &SyntaxElement) -> SyntaxNode { @@ -278,7 +279,6 @@ impl ChangedAncestor { } struct TreeMutator { - immutable: SyntaxNode, mutable_clone: SyntaxNode, } @@ -286,7 +286,7 @@ impl TreeMutator { fn new(immutable: &SyntaxNode) -> TreeMutator { let immutable = immutable.clone(); let mutable_clone = immutable.clone_for_update(); - TreeMutator { immutable, mutable_clone } + TreeMutator { mutable_clone } } fn make_element_mut(&self, element: &SyntaxElement) -> SyntaxElement { diff --git a/src/tools/rust-analyzer/crates/syntax/src/syntax_editor/mapping.rs b/src/tools/rust-analyzer/crates/syntax/src/syntax_editor/mapping.rs index f14d0b347d780..b2c677c869669 100644 --- a/src/tools/rust-analyzer/crates/syntax/src/syntax_editor/mapping.rs +++ b/src/tools/rust-analyzer/crates/syntax/src/syntax_editor/mapping.rs @@ -108,7 +108,6 @@ impl SyntaxMapping { input_ancestor: &SyntaxNode, output_ancestor: &SyntaxNode, ) -> Result, MissingMapping> { - eprintln!("mapping ancestor {input_ancestor:#?} to {output_ancestor:#?}"); let mut current = self.upmap_node_single(input_ancestor).unwrap_or_else(|| input_ancestor.clone()); let mut upmap_chain = vec![current.index()]; From f6e05a744dcf47aaa229cac246228268394263d8 Mon Sep 17 00:00:00 2001 From: DropDemBits Date: Mon, 2 Sep 2024 22:27:14 -0400 Subject: [PATCH 0421/2194] handle replace_with_many and replace_all --- .../crates/syntax/src/syntax_editor.rs | 47 +++++++++++-- .../syntax/src/syntax_editor/edit_algo.rs | 66 ++++++++++++++++--- 2 files changed, 97 insertions(+), 16 deletions(-) diff --git a/src/tools/rust-analyzer/crates/syntax/src/syntax_editor.rs b/src/tools/rust-analyzer/crates/syntax/src/syntax_editor.rs index 77a560bfe5c45..3a05cc480b210 100644 --- a/src/tools/rust-analyzer/crates/syntax/src/syntax_editor.rs +++ b/src/tools/rust-analyzer/crates/syntax/src/syntax_editor.rs @@ -6,6 +6,7 @@ use std::{ num::NonZeroU32, + ops::RangeInclusive, sync::atomic::{AtomicU32, Ordering}, }; @@ -76,6 +77,26 @@ impl SyntaxEditor { self.changes.push(Change::Replace(old.syntax_element(), Some(new.syntax_element()))); } + pub fn replace_with_many(&mut self, old: impl Element, new: Vec) { + let old = old.syntax_element(); + debug_assert!(is_ancestor_or_self_of_element(&old, &self.root)); + debug_assert!( + !(matches!(&old, SyntaxElement::Node(node) if node == &self.root) && new.len() > 1), + "cannot replace root node with many elements" + ); + self.changes.push(Change::ReplaceWithMany(old.syntax_element(), new)); + } + + pub fn replace_all(&mut self, range: RangeInclusive, new: Vec) { + if range.start() == range.end() { + self.replace_with_many(range.start(), new); + return; + } + + debug_assert!(is_ancestor_or_self_of_element(range.start(), &self.root)); + self.changes.push(Change::ReplaceAll(range, new)) + } + pub fn finish(self) -> SyntaxEdit { edit_algo::apply_edits(self) } @@ -186,10 +207,17 @@ impl Position { #[derive(Debug)] enum Change { + /// Inserts a single element at the specified position. Insert(Position, SyntaxElement), + /// Inserts many elements in-order at the specified position. InsertAll(Position, Vec), /// Represents both a replace single element and a delete element operation. Replace(SyntaxElement, Option), + /// Replaces a single element with many elements. + ReplaceWithMany(SyntaxElement, Vec), + /// Replaces a range of elements with another list of elements. + /// Range will always have start != end. + ReplaceAll(RangeInclusive, Vec), } impl Change { @@ -202,24 +230,29 @@ impl Change { ), PositionRepr::After(child) => TextRange::at(child.text_range().end(), 0.into()), }, - Change::Replace(target, _) => target.text_range(), + Change::Replace(target, _) | Change::ReplaceWithMany(target, _) => target.text_range(), + Change::ReplaceAll(range, _) => { + range.start().text_range().cover(range.end().text_range()) + } } } fn target_parent(&self) -> SyntaxNode { match self { Change::Insert(target, _) | Change::InsertAll(target, _) => target.parent(), - Change::Replace(SyntaxElement::Node(target), _) => { - target.parent().unwrap_or_else(|| target.clone()) - } - Change::Replace(SyntaxElement::Token(target), _) => target.parent().unwrap(), + Change::Replace(target, _) | Change::ReplaceWithMany(target, _) => match target { + SyntaxElement::Node(target) => target.parent().unwrap_or_else(|| target.clone()), + SyntaxElement::Token(target) => target.parent().unwrap(), + }, + Change::ReplaceAll(target, _) => target.start().parent().unwrap(), } } fn change_kind(&self) -> ChangeKind { match self { Change::Insert(_, _) | Change::InsertAll(_, _) => ChangeKind::Insert, - Change::Replace(_, _) => ChangeKind::Replace, + Change::Replace(_, _) | Change::ReplaceWithMany(_, _) => ChangeKind::Replace, + Change::ReplaceAll(_, _) => ChangeKind::ReplaceRange, } } } @@ -227,7 +260,7 @@ impl Change { #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] enum ChangeKind { Insert, - // TODO: deal with replace spans + ReplaceRange, Replace, } diff --git a/src/tools/rust-analyzer/crates/syntax/src/syntax_editor/edit_algo.rs b/src/tools/rust-analyzer/crates/syntax/src/syntax_editor/edit_algo.rs index 2c331fc1f69e3..3b92ac1cbd8a0 100644 --- a/src/tools/rust-analyzer/crates/syntax/src/syntax_editor/edit_algo.rs +++ b/src/tools/rust-analyzer/crates/syntax/src/syntax_editor/edit_algo.rs @@ -61,7 +61,13 @@ pub(super) fn apply_edits(editor: SyntaxEditor) -> SyntaxEdit { .zip(changes.iter().skip(1)) .filter(|(l, r)| { // We only care about checking for disjoint replace ranges - l.change_kind() == ChangeKind::Replace && r.change_kind() == ChangeKind::Replace + matches!( + (l.change_kind(), r.change_kind()), + ( + ChangeKind::Replace | ChangeKind::ReplaceRange, + ChangeKind::Replace | ChangeKind::ReplaceRange + ) + ) }) .all(|(l, r)| { get_node_depth(l.target_parent()) != get_node_depth(r.target_parent()) @@ -97,6 +103,7 @@ pub(super) fn apply_edits(editor: SyntaxEditor) -> SyntaxEdit { // Pop off any ancestors that aren't applicable changed_ancestors.drain((index + 1)..); + // FIXME: Resolve changes that depend on a range of elements let ancestor = &changed_ancestors[index]; dependent_changes.push(DependentChange { @@ -115,9 +122,12 @@ pub(super) fn apply_edits(editor: SyntaxEditor) -> SyntaxEdit { // Add to changed ancestors, if applicable match change { Change::Insert(_, _) | Change::InsertAll(_, _) => {} - Change::Replace(target, _) => { + Change::Replace(target, _) | Change::ReplaceWithMany(target, _) => { changed_ancestors.push_back(ChangedAncestor::single(target, change_index)) } + Change::ReplaceAll(range, _) => { + changed_ancestors.push_back(ChangedAncestor::multiple(range, change_index)) + } } } @@ -137,9 +147,15 @@ pub(super) fn apply_edits(editor: SyntaxEditor) -> SyntaxEdit { } }; } - Change::Replace(target, _) => { + Change::Replace(target, _) | Change::ReplaceWithMany(target, _) => { *target = tree_mutator.make_element_mut(target); } + Change::ReplaceAll(range, _) => { + let start = tree_mutator.make_element_mut(range.start()); + let end = tree_mutator.make_element_mut(range.end()); + + *range = start..=end; + } } // Collect changed elements @@ -148,6 +164,10 @@ pub(super) fn apply_edits(editor: SyntaxEditor) -> SyntaxEdit { Change::InsertAll(_, elements) => changed_elements.extend(elements.iter().cloned()), Change::Replace(_, Some(element)) => changed_elements.push(element.clone()), Change::Replace(_, None) => {} + Change::ReplaceWithMany(_, elements) => { + changed_elements.extend(elements.iter().cloned()) + } + Change::ReplaceAll(_, elements) => changed_elements.extend(elements.iter().cloned()), } } @@ -160,6 +180,9 @@ pub(super) fn apply_edits(editor: SyntaxEditor) -> SyntaxEdit { } // Silently drop outdated change Change::Replace(_, None) => continue, + Change::ReplaceAll(_, _) | Change::ReplaceWithMany(_, _) => { + unimplemented!("cannot resolve changes that depend on replacing many elements") + } }; let upmap_target_node = |target: &SyntaxNode| { @@ -185,9 +208,12 @@ pub(super) fn apply_edits(editor: SyntaxEditor) -> SyntaxEdit { *child = upmap_target(child); } }, - Change::Replace(target, _) => { + Change::Replace(target, _) | Change::ReplaceWithMany(target, _) => { *target = upmap_target(&target); } + Change::ReplaceAll(range, _) => { + *range = upmap_target(range.start())..=upmap_target(range.end()); + } } } @@ -214,6 +240,16 @@ pub(super) fn apply_edits(editor: SyntaxEditor) -> SyntaxEdit { let parent = target.parent().unwrap(); parent.splice_children(target.index()..target.index() + 1, vec![new_target]); } + Change::ReplaceWithMany(target, elements) => { + let parent = target.parent().unwrap(); + parent.splice_children(target.index()..target.index() + 1, elements); + } + Change::ReplaceAll(range, elements) => { + let start = range.start().index(); + let end = range.end().index(); + let parent = range.start().parent().unwrap(); + parent.splice_children(start..end + 1, elements); + } } } @@ -252,7 +288,7 @@ struct ChangedAncestor { enum ChangedAncestorKind { Single { node: SyntaxNode }, - Range { changed_nodes: RangeInclusive, in_parent: SyntaxNode }, + Range { _changed_elements: RangeInclusive, in_parent: SyntaxNode }, } impl ChangedAncestor { @@ -267,13 +303,25 @@ impl ChangedAncestor { Self { kind, change_index } } + fn multiple(range: &RangeInclusive, change_index: usize) -> Self { + Self { + kind: ChangedAncestorKind::Range { + _changed_elements: range.clone(), + in_parent: range.start().parent().unwrap(), + }, + change_index, + } + } + fn affected_range(&self) -> TextRange { match &self.kind { ChangedAncestorKind::Single { node } => node.text_range(), - ChangedAncestorKind::Range { changed_nodes, in_parent: _ } => TextRange::new( - changed_nodes.start().text_range().start(), - changed_nodes.end().text_range().end(), - ), + ChangedAncestorKind::Range { _changed_elements: changed_nodes, in_parent: _ } => { + TextRange::new( + changed_nodes.start().text_range().start(), + changed_nodes.end().text_range().end(), + ) + } } } } From 9d407bfd1b69801d53c9c01dc8988f62d6235fed Mon Sep 17 00:00:00 2001 From: Mattias Wallin Date: Sun, 1 Sep 2024 08:36:44 +0200 Subject: [PATCH 0422/2194] Avoid allocating intermediate strings in `ItemizedBlock::trimmed_block_as_string` --- src/comment.rs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/comment.rs b/src/comment.rs index c8cadf364daf8..1e35395cfb31f 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -533,10 +533,11 @@ impl ItemizedBlock { /// Returns the block as a string, with each line trimmed at the start. fn trimmed_block_as_string(&self) -> String { - self.lines - .iter() - .map(|line| format!("{} ", line.trim_start())) - .collect::() + self.lines.iter().fold(String::new(), |mut acc, line| { + acc.push_str(line.trim_start()); + acc.push(' '); + acc + }) } /// Returns the block as a string under its original form. From 5d30ce68441fabbf4e2b1c789b1af2327d9dc869 Mon Sep 17 00:00:00 2001 From: Mattias Wallin Date: Sun, 1 Sep 2024 09:25:05 +0200 Subject: [PATCH 0423/2194] Avoid allocating intermediate strings in `determine_operation` --- src/bin/main.rs | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/src/bin/main.rs b/src/bin/main.rs index 14299434bc747..3a0427d83720d 100644 --- a/src/bin/main.rs +++ b/src/bin/main.rs @@ -462,16 +462,15 @@ fn print_version() { fn determine_operation(matches: &Matches) -> Result { if matches.opt_present("h") { - let topic = matches.opt_str("h"); - if topic.is_none() { + let Some(topic) = matches.opt_str("h") else { return Ok(Operation::Help(HelpOp::None)); - } else if topic == Some("config".to_owned()) { - return Ok(Operation::Help(HelpOp::Config)); - } else if topic == Some("file-lines".to_owned()) && is_nightly() { - return Ok(Operation::Help(HelpOp::FileLines)); - } else { - return Err(OperationError::UnknownHelpTopic(topic.unwrap())); - } + }; + + return match topic.as_str() { + "config" => Ok(Operation::Help(HelpOp::Config)), + "file-lines" if is_nightly() => Ok(Operation::Help(HelpOp::FileLines)), + _ => Err(OperationError::UnknownHelpTopic(topic)), + }; } let mut free_matches = matches.free.iter(); From 4e81ca344b6ce53b11309d14bc4ea72e39db5b83 Mon Sep 17 00:00:00 2001 From: DropDemBits Date: Mon, 2 Sep 2024 22:53:54 -0400 Subject: [PATCH 0424/2194] misc fixes --- .../crates/syntax/src/syntax_editor.rs | 24 +++++-------------- .../syntax/src/syntax_editor/edit_algo.rs | 14 ++++++----- .../syntax/src/syntax_editor/mapping.rs | 8 +++++-- 3 files changed, 20 insertions(+), 26 deletions(-) diff --git a/src/tools/rust-analyzer/crates/syntax/src/syntax_editor.rs b/src/tools/rust-analyzer/crates/syntax/src/syntax_editor.rs index 3a05cc480b210..139c6518bf7cb 100644 --- a/src/tools/rust-analyzer/crates/syntax/src/syntax_editor.rs +++ b/src/tools/rust-analyzer/crates/syntax/src/syntax_editor.rs @@ -150,6 +150,12 @@ impl SyntaxAnnotation { } } +impl Default for SyntaxAnnotation { + fn default() -> Self { + Self::new() + } +} + /// Position describing where to insert elements #[derive(Debug)] pub struct Position { @@ -445,24 +451,6 @@ mod tests { .all(|element| element.ancestors().any(|it| &it == edit.root()))) } - #[test] - #[should_panic = "some replace change ranges intersect: [Replace(Node(TUPLE_EXPR@5..7), Some(Node(NAME_REF@0..8))), Replace(Node(TUPLE_EXPR@5..7), Some(Node(NAME_REF@0..8)))]"] - fn fail_on_non_disjoint_single_replace() { - let root = make::match_arm([make::wildcard_pat().into()], None, make::expr_tuple([])); - - let to_wrap = root.syntax().descendants().find_map(ast::TupleExpr::cast).unwrap(); - - let mut editor = SyntaxEditor::new(root.syntax().clone()); - - let name_ref = make::name_ref("var_name").clone_for_update(); - - // should die, ranges are not disjoint - editor.replace(to_wrap.syntax(), name_ref.syntax()); - editor.replace(to_wrap.syntax(), name_ref.syntax()); - - let _ = editor.finish(); - } - #[test] fn test_insert_independent() { let root = make::block_expr( diff --git a/src/tools/rust-analyzer/crates/syntax/src/syntax_editor/edit_algo.rs b/src/tools/rust-analyzer/crates/syntax/src/syntax_editor/edit_algo.rs index 3b92ac1cbd8a0..55e8867a46cb4 100644 --- a/src/tools/rust-analyzer/crates/syntax/src/syntax_editor/edit_algo.rs +++ b/src/tools/rust-analyzer/crates/syntax/src/syntax_editor/edit_algo.rs @@ -1,3 +1,5 @@ +//! Implementation of applying changes to a syntax tree. + use std::{cmp::Ordering, collections::VecDeque, ops::RangeInclusive}; use rowan::TextRange; @@ -209,7 +211,7 @@ pub(super) fn apply_edits(editor: SyntaxEditor) -> SyntaxEdit { } }, Change::Replace(target, _) | Change::ReplaceWithMany(target, _) => { - *target = upmap_target(&target); + *target = upmap_target(target); } Change::ReplaceAll(range, _) => { *range = upmap_target(range.start())..=upmap_target(range.end()); @@ -233,7 +235,7 @@ pub(super) fn apply_edits(editor: SyntaxEditor) -> SyntaxEdit { Change::Replace(target, None) => { target.detach(); } - Change::Replace(SyntaxElement::Node(target), Some(new_target)) if &target == &root => { + Change::Replace(SyntaxElement::Node(target), Some(new_target)) if target == root => { root = new_target.into_node().expect("root node replacement should be a node"); } Change::Replace(target, Some(new_target)) => { @@ -288,7 +290,7 @@ struct ChangedAncestor { enum ChangedAncestorKind { Single { node: SyntaxNode }, - Range { _changed_elements: RangeInclusive, in_parent: SyntaxNode }, + Range { _changed_elements: RangeInclusive, _in_parent: SyntaxNode }, } impl ChangedAncestor { @@ -307,7 +309,7 @@ impl ChangedAncestor { Self { kind: ChangedAncestorKind::Range { _changed_elements: range.clone(), - in_parent: range.start().parent().unwrap(), + _in_parent: range.start().parent().unwrap(), }, change_index, } @@ -316,7 +318,7 @@ impl ChangedAncestor { fn affected_range(&self) -> TextRange { match &self.kind { ChangedAncestorKind::Single { node } => node.text_range(), - ChangedAncestorKind::Range { _changed_elements: changed_nodes, in_parent: _ } => { + ChangedAncestorKind::Range { _changed_elements: changed_nodes, _in_parent: _ } => { TextRange::new( changed_nodes.start().text_range().start(), changed_nodes.end().text_range().end(), @@ -339,7 +341,7 @@ impl TreeMutator { fn make_element_mut(&self, element: &SyntaxElement) -> SyntaxElement { match element { - SyntaxElement::Node(node) => SyntaxElement::Node(self.make_syntax_mut(&node)), + SyntaxElement::Node(node) => SyntaxElement::Node(self.make_syntax_mut(node)), SyntaxElement::Token(token) => { let parent = self.make_syntax_mut(&token.parent().unwrap()); parent.children_with_tokens().nth(token.index()).unwrap() diff --git a/src/tools/rust-analyzer/crates/syntax/src/syntax_editor/mapping.rs b/src/tools/rust-analyzer/crates/syntax/src/syntax_editor/mapping.rs index b2c677c869669..9bb5e6d933822 100644 --- a/src/tools/rust-analyzer/crates/syntax/src/syntax_editor/mapping.rs +++ b/src/tools/rust-analyzer/crates/syntax/src/syntax_editor/mapping.rs @@ -1,3 +1,7 @@ +//! Maps syntax elements through disjoint syntax nodes. +//! +//! [`SyntaxMappingBuilder`] should be used to create mappings to add to a [`SyntaxEditor`] + use itertools::Itertools; use rustc_hash::FxHashMap; @@ -168,11 +172,11 @@ impl SyntaxMapping { match (input_mapping, input_ancestor) { (Some(input_mapping), _) => { // A mapping exists at the input, follow along the tree - Some(self.upmap_child(&input_mapping, &input_mapping, &output_root)) + Some(self.upmap_child(&input_mapping, &input_mapping, output_root)) } (None, Some(input_ancestor)) => { // A mapping exists at an ancestor, follow along the tree - Some(self.upmap_child(input, &input_ancestor, &output_root)) + Some(self.upmap_child(input, &input_ancestor, output_root)) } (None, None) => { // No mapping exists at all, is the same position in the final tree From 5410900aaa54a20276a71b39b126d2a4c0ce8493 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 3 Sep 2024 15:01:46 +1000 Subject: [PATCH 0425/2194] Adjust `SanityCheck`. The actual implementation remains in `rustc_mir_dataflow`, but this commit moves the `MirPass` impl to `rustc_mir_transform` and changes it to a `MirLint` (fixing a `FIXME` comment). (I originally tried moving the full implementation from `rustc_mir_dataflow` but I had some trait problems with `HasMoveData` and `RustcPeekAt` and `MaybeLiveLocals`. This commit was much smaller and simpler, but still will allow some follow-up cleanups.) --- compiler/rustc_mir_dataflow/src/rustc_peek.rs | 75 +++++++++---------- compiler/rustc_mir_transform/src/lib.rs | 4 +- .../rustc_mir_transform/src/sanity_check.rs | 13 ++++ 3 files changed, 50 insertions(+), 42 deletions(-) create mode 100644 compiler/rustc_mir_transform/src/sanity_check.rs diff --git a/compiler/rustc_mir_dataflow/src/rustc_peek.rs b/compiler/rustc_mir_dataflow/src/rustc_peek.rs index 0171cc8591809..8c3e6f49b1618 100644 --- a/compiler/rustc_mir_dataflow/src/rustc_peek.rs +++ b/compiler/rustc_mir_dataflow/src/rustc_peek.rs @@ -1,7 +1,7 @@ use rustc_ast::MetaItem; use rustc_hir::def_id::DefId; use rustc_index::bit_set::BitSet; -use rustc_middle::mir::{self, Body, Local, Location, MirPass}; +use rustc_middle::mir::{self, Body, Local, Location}; use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_span::symbol::{sym, Symbol}; use rustc_span::Span; @@ -18,8 +18,6 @@ use crate::impls::{ use crate::move_paths::{HasMoveData, LookupResult, MoveData, MovePathIndex}; use crate::{Analysis, JoinSemiLattice, ResultsCursor}; -pub struct SanityCheck; - fn has_rustc_mir_with(tcx: TyCtxt<'_>, def_id: DefId, name: Symbol) -> Option { for attr in tcx.get_attrs(def_id, sym::rustc_mir) { let items = attr.meta_item_list(); @@ -33,53 +31,50 @@ fn has_rustc_mir_with(tcx: TyCtxt<'_>, def_id: DefId, name: Symbol) -> Option MirPass<'tcx> for SanityCheck { - fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { - let def_id = body.source.def_id(); - if !tcx.has_attr(def_id, sym::rustc_mir) { - debug!("skipping rustc_peek::SanityCheck on {}", tcx.def_path_str(def_id)); - return; - } else { - debug!("running rustc_peek::SanityCheck on {}", tcx.def_path_str(def_id)); - } +pub fn sanity_check<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>) { + let def_id = body.source.def_id(); + if !tcx.has_attr(def_id, sym::rustc_mir) { + debug!("skipping rustc_peek::SanityCheck on {}", tcx.def_path_str(def_id)); + return; + } else { + debug!("running rustc_peek::SanityCheck on {}", tcx.def_path_str(def_id)); + } - let param_env = tcx.param_env(def_id); - let move_data = MoveData::gather_moves(body, tcx, param_env, |_| true); + let param_env = tcx.param_env(def_id); + let move_data = MoveData::gather_moves(body, tcx, param_env, |_| true); - if has_rustc_mir_with(tcx, def_id, sym::rustc_peek_maybe_init).is_some() { - let flow_inits = MaybeInitializedPlaces::new(tcx, body, &move_data) - .into_engine(tcx, body) - .iterate_to_fixpoint(); + if has_rustc_mir_with(tcx, def_id, sym::rustc_peek_maybe_init).is_some() { + let flow_inits = MaybeInitializedPlaces::new(tcx, body, &move_data) + .into_engine(tcx, body) + .iterate_to_fixpoint(); - sanity_check_via_rustc_peek(tcx, flow_inits.into_results_cursor(body)); - } + sanity_check_via_rustc_peek(tcx, flow_inits.into_results_cursor(body)); + } - if has_rustc_mir_with(tcx, def_id, sym::rustc_peek_maybe_uninit).is_some() { - let flow_uninits = MaybeUninitializedPlaces::new(tcx, body, &move_data) - .into_engine(tcx, body) - .iterate_to_fixpoint(); + if has_rustc_mir_with(tcx, def_id, sym::rustc_peek_maybe_uninit).is_some() { + let flow_uninits = MaybeUninitializedPlaces::new(tcx, body, &move_data) + .into_engine(tcx, body) + .iterate_to_fixpoint(); - sanity_check_via_rustc_peek(tcx, flow_uninits.into_results_cursor(body)); - } + sanity_check_via_rustc_peek(tcx, flow_uninits.into_results_cursor(body)); + } - if has_rustc_mir_with(tcx, def_id, sym::rustc_peek_definite_init).is_some() { - let flow_def_inits = DefinitelyInitializedPlaces::new(body, &move_data) - .into_engine(tcx, body) - .iterate_to_fixpoint(); + if has_rustc_mir_with(tcx, def_id, sym::rustc_peek_definite_init).is_some() { + let flow_def_inits = DefinitelyInitializedPlaces::new(body, &move_data) + .into_engine(tcx, body) + .iterate_to_fixpoint(); - sanity_check_via_rustc_peek(tcx, flow_def_inits.into_results_cursor(body)); - } + sanity_check_via_rustc_peek(tcx, flow_def_inits.into_results_cursor(body)); + } - if has_rustc_mir_with(tcx, def_id, sym::rustc_peek_liveness).is_some() { - let flow_liveness = MaybeLiveLocals.into_engine(tcx, body).iterate_to_fixpoint(); + if has_rustc_mir_with(tcx, def_id, sym::rustc_peek_liveness).is_some() { + let flow_liveness = MaybeLiveLocals.into_engine(tcx, body).iterate_to_fixpoint(); - sanity_check_via_rustc_peek(tcx, flow_liveness.into_results_cursor(body)); - } + sanity_check_via_rustc_peek(tcx, flow_liveness.into_results_cursor(body)); + } - if has_rustc_mir_with(tcx, def_id, sym::stop_after_dataflow).is_some() { - tcx.dcx().emit_fatal(StopAfterDataFlowEndedCompilation); - } + if has_rustc_mir_with(tcx, def_id, sym::stop_after_dataflow).is_some() { + tcx.dcx().emit_fatal(StopAfterDataFlowEndedCompilation); } } diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs index 9e460a725eeb2..63793c4f772ef 100644 --- a/compiler/rustc_mir_transform/src/lib.rs +++ b/compiler/rustc_mir_transform/src/lib.rs @@ -32,7 +32,6 @@ use rustc_middle::mir::{ use rustc_middle::ty::{self, TyCtxt, TypeVisitableExt}; use rustc_middle::util::Providers; use rustc_middle::{bug, query, span_bug}; -use rustc_mir_dataflow::rustc_peek; use rustc_span::source_map::Spanned; use rustc_span::{sym, DUMMY_SP}; use rustc_trait_selection::traits; @@ -96,6 +95,7 @@ mod remove_unneeded_drops; mod remove_zsts; mod required_consts; mod reveal_all; +mod sanity_check; mod shim; mod ssa; // This pass is public to allow external drivers to perform MIR cleanup @@ -288,7 +288,7 @@ fn mir_built(tcx: TyCtxt<'_>, def: LocalDefId) -> &Steal> { &Lint(function_item_references::FunctionItemReferences), // What we need to do constant evaluation. &simplify::SimplifyCfg::Initial, - &rustc_peek::SanityCheck, // Just a lint + &Lint(sanity_check::SanityCheck), ], None, ); diff --git a/compiler/rustc_mir_transform/src/sanity_check.rs b/compiler/rustc_mir_transform/src/sanity_check.rs new file mode 100644 index 0000000000000..8c8b3915c0f64 --- /dev/null +++ b/compiler/rustc_mir_transform/src/sanity_check.rs @@ -0,0 +1,13 @@ +use rustc_middle::mir::Body; +use rustc_middle::ty::TyCtxt; +use rustc_mir_dataflow::rustc_peek::sanity_check; + +use crate::MirLint; + +pub(super) struct SanityCheck; + +impl<'tcx> MirLint<'tcx> for SanityCheck { + fn run_lint(&self, tcx: TyCtxt<'tcx>, body: &Body<'tcx>) { + sanity_check(tcx, body); + } +} From 2aae619edbf3f761894cac42a0074718219434df Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 3 Sep 2024 15:45:27 +1000 Subject: [PATCH 0426/2194] Move `MirPass` to `rustc_mir_transform`. Because that's now the only crate that uses it. Moving stuff out of `rustc_middle` is always welcome. I chose to use `impl crate::MirPass`/`impl crate::MirLint` (with explicit `crate::`) everywhere because that's the only mention of `MirPass`/`MirLint` used in all of these files. (Prior to this change, `MirPass` was mostly imported via `use rustc_middle::mir::*` items.) --- compiler/rustc_middle/src/mir/mod.rs | 62 -------------- compiler/rustc_middle/src/util/common.rs | 16 ---- .../src/abort_unwinding_calls.rs | 2 +- .../src/add_call_guards.rs | 2 +- .../src/add_moves_for_packed_drops.rs | 2 +- compiler/rustc_mir_transform/src/add_retag.rs | 2 +- .../src/add_subtyping_projections.rs | 2 +- .../src/check_alignment.rs | 2 +- .../src/check_const_item_mutation.rs | 4 +- .../src/check_packed_ref.rs | 4 +- .../src/cleanup_post_borrowck.rs | 4 +- compiler/rustc_mir_transform/src/copy_prop.rs | 2 +- compiler/rustc_mir_transform/src/coroutine.rs | 2 +- .../rustc_mir_transform/src/coverage/mod.rs | 3 +- .../rustc_mir_transform/src/ctfe_limit.rs | 4 +- .../src/dataflow_const_prop.rs | 2 +- .../src/dead_store_elimination.rs | 2 +- .../src/deduplicate_blocks.rs | 2 +- .../src/deref_separator.rs | 2 +- compiler/rustc_mir_transform/src/dest_prop.rs | 4 +- compiler/rustc_mir_transform/src/dump_mir.rs | 4 +- .../src/early_otherwise_branch.rs | 2 +- .../src/elaborate_box_derefs.rs | 2 +- .../src/elaborate_drops.rs | 2 +- .../src/function_item_references.rs | 4 +- compiler/rustc_mir_transform/src/gvn.rs | 2 +- compiler/rustc_mir_transform/src/inline.rs | 2 +- .../rustc_mir_transform/src/instsimplify.rs | 2 +- .../rustc_mir_transform/src/jump_threading.rs | 2 +- .../src/known_panics_lint.rs | 3 +- .../rustc_mir_transform/src/large_enums.rs | 2 +- compiler/rustc_mir_transform/src/lib.rs | 4 +- .../src/lower_intrinsics.rs | 2 +- .../src/lower_slice_len.rs | 2 +- .../rustc_mir_transform/src/match_branches.rs | 2 +- .../src/mentioned_items.rs | 4 +- .../src/multiple_return_terminators.rs | 2 +- compiler/rustc_mir_transform/src/nrvo.rs | 4 +- .../rustc_mir_transform/src/pass_manager.rs | 83 ++++++++++++++++++- compiler/rustc_mir_transform/src/prettify.rs | 4 +- .../rustc_mir_transform/src/promote_consts.rs | 2 +- compiler/rustc_mir_transform/src/ref_prop.rs | 2 +- .../src/remove_noop_landing_pads.rs | 2 +- .../src/remove_place_mention.rs | 2 +- .../src/remove_storage_markers.rs | 2 +- .../src/remove_uninit_drops.rs | 4 +- .../src/remove_unneeded_drops.rs | 2 +- .../rustc_mir_transform/src/remove_zsts.rs | 2 +- .../rustc_mir_transform/src/reveal_all.rs | 2 +- .../rustc_mir_transform/src/sanity_check.rs | 4 +- compiler/rustc_mir_transform/src/simplify.rs | 4 +- .../src/simplify_branches.rs | 2 +- .../src/simplify_comparison_integral.rs | 4 +- .../src/single_use_consts.rs | 2 +- compiler/rustc_mir_transform/src/sroa.rs | 2 +- .../src/unreachable_enum_branching.rs | 4 +- .../src/unreachable_prop.rs | 2 +- compiler/rustc_mir_transform/src/validate.rs | 2 +- 58 files changed, 143 insertions(+), 162 deletions(-) diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index 7b90191503702..081a23b6ff317 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -3,8 +3,6 @@ //! [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/mir/index.html use std::borrow::Cow; -use std::cell::RefCell; -use std::collections::hash_map::Entry; use std::fmt::{self, Debug, Formatter}; use std::ops::{Index, IndexMut}; use std::{iter, mem}; @@ -26,7 +24,6 @@ use rustc_index::bit_set::BitSet; use rustc_index::{Idx, IndexSlice, IndexVec}; use rustc_macros::{HashStable, TyDecodable, TyEncodable, TypeFoldable, TypeVisitable}; use rustc_serialize::{Decodable, Encodable}; -use rustc_session::Session; use rustc_span::source_map::Spanned; use rustc_span::symbol::Symbol; use rustc_span::{Span, DUMMY_SP}; @@ -106,65 +103,6 @@ impl<'tcx> HasLocalDecls<'tcx> for Body<'tcx> { } } -thread_local! { - static PASS_NAMES: RefCell> = { - RefCell::new(FxHashMap::default()) - }; -} - -/// Converts a MIR pass name into a snake case form to match the profiling naming style. -fn to_profiler_name(type_name: &'static str) -> &'static str { - PASS_NAMES.with(|names| match names.borrow_mut().entry(type_name) { - Entry::Occupied(e) => *e.get(), - Entry::Vacant(e) => { - let snake_case: String = type_name - .chars() - .flat_map(|c| { - if c.is_ascii_uppercase() { - vec!['_', c.to_ascii_lowercase()] - } else if c == '-' { - vec!['_'] - } else { - vec![c] - } - }) - .collect(); - let result = &*String::leak(format!("mir_pass{}", snake_case)); - e.insert(result); - result - } - }) -} - -/// A streamlined trait that you can implement to create a pass; the -/// pass will be named after the type, and it will consist of a main -/// loop that goes over each available MIR and applies `run_pass`. -pub trait MirPass<'tcx> { - fn name(&self) -> &'static str { - // FIXME Simplify the implementation once more `str` methods get const-stable. - // See copypaste in `MirLint` - const { - let name = std::any::type_name::(); - crate::util::common::c_name(name) - } - } - - fn profiler_name(&self) -> &'static str { - to_profiler_name(self.name()) - } - - /// Returns `true` if this pass is enabled with the current combination of compiler flags. - fn is_enabled(&self, _sess: &Session) -> bool { - true - } - - fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>); - - fn is_mir_dump_enabled(&self) -> bool { - true - } -} - impl MirPhase { /// Gets the index of the current MirPhase within the set of all `MirPhase`s. /// diff --git a/compiler/rustc_middle/src/util/common.rs b/compiler/rustc_middle/src/util/common.rs index 2038d3f84484e..223b2b3bfe4de 100644 --- a/compiler/rustc_middle/src/util/common.rs +++ b/compiler/rustc_middle/src/util/common.rs @@ -20,19 +20,3 @@ pub fn to_readable_str(mut val: usize) -> String { groups.join("_") } - -// const wrapper for `if let Some((_, tail)) = name.rsplit_once(':') { tail } else { name }` -pub const fn c_name(name: &'static str) -> &'static str { - // FIXME Simplify the implementation once more `str` methods get const-stable. - // and inline into call site - let bytes = name.as_bytes(); - let mut i = bytes.len(); - while i > 0 && bytes[i - 1] != b':' { - i = i - 1; - } - let (_, bytes) = bytes.split_at(i); - match std::str::from_utf8(bytes) { - Ok(name) => name, - Err(_) => name, - } -} diff --git a/compiler/rustc_mir_transform/src/abort_unwinding_calls.rs b/compiler/rustc_mir_transform/src/abort_unwinding_calls.rs index edb6bc4fbea2f..e4bc6b3efe422 100644 --- a/compiler/rustc_mir_transform/src/abort_unwinding_calls.rs +++ b/compiler/rustc_mir_transform/src/abort_unwinding_calls.rs @@ -22,7 +22,7 @@ use rustc_target::spec::PanicStrategy; #[derive(PartialEq)] pub struct AbortUnwindingCalls; -impl<'tcx> MirPass<'tcx> for AbortUnwindingCalls { +impl<'tcx> crate::MirPass<'tcx> for AbortUnwindingCalls { fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { let def_id = body.source.def_id(); let kind = tcx.def_kind(def_id); diff --git a/compiler/rustc_mir_transform/src/add_call_guards.rs b/compiler/rustc_mir_transform/src/add_call_guards.rs index df5312d155c13..78e850de3c772 100644 --- a/compiler/rustc_mir_transform/src/add_call_guards.rs +++ b/compiler/rustc_mir_transform/src/add_call_guards.rs @@ -30,7 +30,7 @@ pub use self::AddCallGuards::*; * */ -impl<'tcx> MirPass<'tcx> for AddCallGuards { +impl<'tcx> crate::MirPass<'tcx> for AddCallGuards { fn run_pass(&self, _tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { self.add_call_guards(body); } diff --git a/compiler/rustc_mir_transform/src/add_moves_for_packed_drops.rs b/compiler/rustc_mir_transform/src/add_moves_for_packed_drops.rs index e503119a3495b..4a8196aeff5b0 100644 --- a/compiler/rustc_mir_transform/src/add_moves_for_packed_drops.rs +++ b/compiler/rustc_mir_transform/src/add_moves_for_packed_drops.rs @@ -37,7 +37,7 @@ use crate::util; /// blowup. pub struct AddMovesForPackedDrops; -impl<'tcx> MirPass<'tcx> for AddMovesForPackedDrops { +impl<'tcx> crate::MirPass<'tcx> for AddMovesForPackedDrops { fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { debug!("add_moves_for_packed_drops({:?} @ {:?})", body.source, body.span); add_moves_for_packed_drops(tcx, body); diff --git a/compiler/rustc_mir_transform/src/add_retag.rs b/compiler/rustc_mir_transform/src/add_retag.rs index 79bc21cab147e..2e12064fe7351 100644 --- a/compiler/rustc_mir_transform/src/add_retag.rs +++ b/compiler/rustc_mir_transform/src/add_retag.rs @@ -48,7 +48,7 @@ fn may_contain_reference<'tcx>(ty: Ty<'tcx>, depth: u32, tcx: TyCtxt<'tcx>) -> b } } -impl<'tcx> MirPass<'tcx> for AddRetag { +impl<'tcx> crate::MirPass<'tcx> for AddRetag { fn is_enabled(&self, sess: &rustc_session::Session) -> bool { sess.opts.unstable_opts.mir_emit_retag } diff --git a/compiler/rustc_mir_transform/src/add_subtyping_projections.rs b/compiler/rustc_mir_transform/src/add_subtyping_projections.rs index 04204c68f7b76..369f6c6008440 100644 --- a/compiler/rustc_mir_transform/src/add_subtyping_projections.rs +++ b/compiler/rustc_mir_transform/src/add_subtyping_projections.rs @@ -62,7 +62,7 @@ pub fn subtype_finder<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { checker.patcher.apply(body); } -impl<'tcx> MirPass<'tcx> for Subtyper { +impl<'tcx> crate::MirPass<'tcx> for Subtyper { fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { subtype_finder(tcx, body); } diff --git a/compiler/rustc_mir_transform/src/check_alignment.rs b/compiler/rustc_mir_transform/src/check_alignment.rs index ad362f22ce197..2e072aa262aac 100644 --- a/compiler/rustc_mir_transform/src/check_alignment.rs +++ b/compiler/rustc_mir_transform/src/check_alignment.rs @@ -9,7 +9,7 @@ use tracing::{debug, trace}; pub struct CheckAlignment; -impl<'tcx> MirPass<'tcx> for CheckAlignment { +impl<'tcx> crate::MirPass<'tcx> for CheckAlignment { fn is_enabled(&self, sess: &Session) -> bool { // FIXME(#112480) MSVC and rustc disagree on minimum stack alignment on x86 Windows if sess.target.llvm_target == "i686-pc-windows-msvc" { diff --git a/compiler/rustc_mir_transform/src/check_const_item_mutation.rs b/compiler/rustc_mir_transform/src/check_const_item_mutation.rs index 1f615c9d8d1a2..fb03323e37e6e 100644 --- a/compiler/rustc_mir_transform/src/check_const_item_mutation.rs +++ b/compiler/rustc_mir_transform/src/check_const_item_mutation.rs @@ -6,11 +6,11 @@ use rustc_session::lint::builtin::CONST_ITEM_MUTATION; use rustc_span::def_id::DefId; use rustc_span::Span; -use crate::{errors, MirLint}; +use crate::errors; pub struct CheckConstItemMutation; -impl<'tcx> MirLint<'tcx> for CheckConstItemMutation { +impl<'tcx> crate::MirLint<'tcx> for CheckConstItemMutation { fn run_lint(&self, tcx: TyCtxt<'tcx>, body: &Body<'tcx>) { let mut checker = ConstMutationChecker { body, tcx, target_local: None }; checker.visit_body(body); diff --git a/compiler/rustc_mir_transform/src/check_packed_ref.rs b/compiler/rustc_mir_transform/src/check_packed_ref.rs index eb76a39be57ff..2f957de7e78d8 100644 --- a/compiler/rustc_mir_transform/src/check_packed_ref.rs +++ b/compiler/rustc_mir_transform/src/check_packed_ref.rs @@ -3,11 +3,11 @@ use rustc_middle::mir::*; use rustc_middle::span_bug; use rustc_middle::ty::{self, TyCtxt}; -use crate::{errors, util, MirLint}; +use crate::{errors, util}; pub struct CheckPackedRef; -impl<'tcx> MirLint<'tcx> for CheckPackedRef { +impl<'tcx> crate::MirLint<'tcx> for CheckPackedRef { fn run_lint(&self, tcx: TyCtxt<'tcx>, body: &Body<'tcx>) { let param_env = tcx.param_env(body.source.def_id()); let source_info = SourceInfo::outermost(body.span); diff --git a/compiler/rustc_mir_transform/src/cleanup_post_borrowck.rs b/compiler/rustc_mir_transform/src/cleanup_post_borrowck.rs index 08c9f9f08e6b2..2f3be1e425d8d 100644 --- a/compiler/rustc_mir_transform/src/cleanup_post_borrowck.rs +++ b/compiler/rustc_mir_transform/src/cleanup_post_borrowck.rs @@ -21,11 +21,9 @@ use rustc_middle::mir::{Body, BorrowKind, CastKind, Rvalue, StatementKind, Termi use rustc_middle::ty::adjustment::PointerCoercion; use rustc_middle::ty::TyCtxt; -use crate::MirPass; - pub struct CleanupPostBorrowck; -impl<'tcx> MirPass<'tcx> for CleanupPostBorrowck { +impl<'tcx> crate::MirPass<'tcx> for CleanupPostBorrowck { fn run_pass(&self, _tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { for basic_block in body.basic_blocks.as_mut() { for statement in basic_block.statements.iter_mut() { diff --git a/compiler/rustc_mir_transform/src/copy_prop.rs b/compiler/rustc_mir_transform/src/copy_prop.rs index 5c267f853783f..85d25ca22318d 100644 --- a/compiler/rustc_mir_transform/src/copy_prop.rs +++ b/compiler/rustc_mir_transform/src/copy_prop.rs @@ -19,7 +19,7 @@ use crate::ssa::SsaLocals; /// We want to replace all those locals by `_a`, either copied or moved. pub struct CopyProp; -impl<'tcx> MirPass<'tcx> for CopyProp { +impl<'tcx> crate::MirPass<'tcx> for CopyProp { fn is_enabled(&self, sess: &rustc_session::Session) -> bool { sess.mir_opt_level() >= 1 } diff --git a/compiler/rustc_mir_transform/src/coroutine.rs b/compiler/rustc_mir_transform/src/coroutine.rs index 80ba1c4266811..eefb748e49d51 100644 --- a/compiler/rustc_mir_transform/src/coroutine.rs +++ b/compiler/rustc_mir_transform/src/coroutine.rs @@ -1535,7 +1535,7 @@ fn check_field_tys_sized<'tcx>( } } -impl<'tcx> MirPass<'tcx> for StateTransform { +impl<'tcx> crate::MirPass<'tcx> for StateTransform { fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { let Some(old_yield_ty) = body.yield_ty() else { // This only applies to coroutines diff --git a/compiler/rustc_mir_transform/src/coverage/mod.rs b/compiler/rustc_mir_transform/src/coverage/mod.rs index bba354d29363d..4edba61fdec9e 100644 --- a/compiler/rustc_mir_transform/src/coverage/mod.rs +++ b/compiler/rustc_mir_transform/src/coverage/mod.rs @@ -28,14 +28,13 @@ use tracing::{debug, debug_span, instrument, trace}; use crate::coverage::counters::{CounterIncrementSite, CoverageCounters}; use crate::coverage::graph::CoverageGraph; use crate::coverage::mappings::ExtractedMappings; -use crate::MirPass; /// Inserts `StatementKind::Coverage` statements that either instrument the binary with injected /// counters, via intrinsic `llvm.instrprof.increment`, and/or inject metadata used during codegen /// to construct the coverage map. pub struct InstrumentCoverage; -impl<'tcx> MirPass<'tcx> for InstrumentCoverage { +impl<'tcx> crate::MirPass<'tcx> for InstrumentCoverage { fn is_enabled(&self, sess: &rustc_session::Session) -> bool { sess.instrument_coverage() } diff --git a/compiler/rustc_mir_transform/src/ctfe_limit.rs b/compiler/rustc_mir_transform/src/ctfe_limit.rs index bf522fd5ef4ec..ea473b64ce540 100644 --- a/compiler/rustc_mir_transform/src/ctfe_limit.rs +++ b/compiler/rustc_mir_transform/src/ctfe_limit.rs @@ -8,11 +8,9 @@ use rustc_middle::mir::{ use rustc_middle::ty::TyCtxt; use tracing::instrument; -use crate::MirPass; - pub struct CtfeLimit; -impl<'tcx> MirPass<'tcx> for CtfeLimit { +impl<'tcx> crate::MirPass<'tcx> for CtfeLimit { #[instrument(skip(self, _tcx, body))] fn run_pass(&self, _tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { let doms = body.basic_blocks.dominators(); diff --git a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs index b16d25c93bb96..46f7408ef8064 100644 --- a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs +++ b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs @@ -28,7 +28,7 @@ const PLACE_LIMIT: usize = 100; pub struct DataflowConstProp; -impl<'tcx> MirPass<'tcx> for DataflowConstProp { +impl<'tcx> crate::MirPass<'tcx> for DataflowConstProp { fn is_enabled(&self, sess: &rustc_session::Session) -> bool { sess.mir_opt_level() >= 3 } diff --git a/compiler/rustc_mir_transform/src/dead_store_elimination.rs b/compiler/rustc_mir_transform/src/dead_store_elimination.rs index f473073083af4..a5228d80f0449 100644 --- a/compiler/rustc_mir_transform/src/dead_store_elimination.rs +++ b/compiler/rustc_mir_transform/src/dead_store_elimination.rs @@ -132,7 +132,7 @@ pub enum DeadStoreElimination { Final, } -impl<'tcx> MirPass<'tcx> for DeadStoreElimination { +impl<'tcx> crate::MirPass<'tcx> for DeadStoreElimination { fn name(&self) -> &'static str { match self { DeadStoreElimination::Initial => "DeadStoreElimination-initial", diff --git a/compiler/rustc_mir_transform/src/deduplicate_blocks.rs b/compiler/rustc_mir_transform/src/deduplicate_blocks.rs index b38f4a4a823b1..be50c1da8a438 100644 --- a/compiler/rustc_mir_transform/src/deduplicate_blocks.rs +++ b/compiler/rustc_mir_transform/src/deduplicate_blocks.rs @@ -15,7 +15,7 @@ use super::simplify::simplify_cfg; pub struct DeduplicateBlocks; -impl<'tcx> MirPass<'tcx> for DeduplicateBlocks { +impl<'tcx> crate::MirPass<'tcx> for DeduplicateBlocks { fn is_enabled(&self, sess: &rustc_session::Session) -> bool { sess.mir_opt_level() >= 4 } diff --git a/compiler/rustc_mir_transform/src/deref_separator.rs b/compiler/rustc_mir_transform/src/deref_separator.rs index 0e2fccc85dacd..a878f777448f5 100644 --- a/compiler/rustc_mir_transform/src/deref_separator.rs +++ b/compiler/rustc_mir_transform/src/deref_separator.rs @@ -78,7 +78,7 @@ pub fn deref_finder<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { checker.patcher.apply(body); } -impl<'tcx> MirPass<'tcx> for Derefer { +impl<'tcx> crate::MirPass<'tcx> for Derefer { fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { deref_finder(tcx, body); } diff --git a/compiler/rustc_mir_transform/src/dest_prop.rs b/compiler/rustc_mir_transform/src/dest_prop.rs index a530dccf96b27..a7cd5bc534799 100644 --- a/compiler/rustc_mir_transform/src/dest_prop.rs +++ b/compiler/rustc_mir_transform/src/dest_prop.rs @@ -146,11 +146,9 @@ use rustc_mir_dataflow::points::{save_as_intervals, DenseLocationMap, PointIndex use rustc_mir_dataflow::Analysis; use tracing::{debug, trace}; -use crate::MirPass; - pub struct DestinationPropagation; -impl<'tcx> MirPass<'tcx> for DestinationPropagation { +impl<'tcx> crate::MirPass<'tcx> for DestinationPropagation { fn is_enabled(&self, sess: &rustc_session::Session) -> bool { // For now, only run at MIR opt level 3. Two things need to be changed before this can be // turned on by default: diff --git a/compiler/rustc_mir_transform/src/dump_mir.rs b/compiler/rustc_mir_transform/src/dump_mir.rs index 29db45f94506f..06ae1b490d75c 100644 --- a/compiler/rustc_mir_transform/src/dump_mir.rs +++ b/compiler/rustc_mir_transform/src/dump_mir.rs @@ -7,11 +7,9 @@ use rustc_middle::mir::{write_mir_pretty, Body}; use rustc_middle::ty::TyCtxt; use rustc_session::config::{OutFileName, OutputType}; -use crate::MirPass; - pub struct Marker(pub &'static str); -impl<'tcx> MirPass<'tcx> for Marker { +impl<'tcx> crate::MirPass<'tcx> for Marker { fn name(&self) -> &'static str { self.0 } diff --git a/compiler/rustc_mir_transform/src/early_otherwise_branch.rs b/compiler/rustc_mir_transform/src/early_otherwise_branch.rs index 67b81efd61475..1c54cd70023d6 100644 --- a/compiler/rustc_mir_transform/src/early_otherwise_branch.rs +++ b/compiler/rustc_mir_transform/src/early_otherwise_branch.rs @@ -92,7 +92,7 @@ use super::simplify::simplify_cfg; /// ``` pub struct EarlyOtherwiseBranch; -impl<'tcx> MirPass<'tcx> for EarlyOtherwiseBranch { +impl<'tcx> crate::MirPass<'tcx> for EarlyOtherwiseBranch { fn is_enabled(&self, sess: &rustc_session::Session) -> bool { sess.mir_opt_level() >= 2 } diff --git a/compiler/rustc_mir_transform/src/elaborate_box_derefs.rs b/compiler/rustc_mir_transform/src/elaborate_box_derefs.rs index e5778f8a05d2e..5dd82f40163da 100644 --- a/compiler/rustc_mir_transform/src/elaborate_box_derefs.rs +++ b/compiler/rustc_mir_transform/src/elaborate_box_derefs.rs @@ -88,7 +88,7 @@ impl<'tcx, 'a> MutVisitor<'tcx> for ElaborateBoxDerefVisitor<'tcx, 'a> { pub struct ElaborateBoxDerefs; -impl<'tcx> MirPass<'tcx> for ElaborateBoxDerefs { +impl<'tcx> crate::MirPass<'tcx> for ElaborateBoxDerefs { fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { if let Some(def_id) = tcx.lang_items().owned_box() { let unique_did = tcx.adt_def(def_id).non_enum_variant().fields[FieldIdx::ZERO].did; diff --git a/compiler/rustc_mir_transform/src/elaborate_drops.rs b/compiler/rustc_mir_transform/src/elaborate_drops.rs index d0809d9388def..f4a951ebde600 100644 --- a/compiler/rustc_mir_transform/src/elaborate_drops.rs +++ b/compiler/rustc_mir_transform/src/elaborate_drops.rs @@ -49,7 +49,7 @@ use crate::deref_separator::deref_finder; /// ``` pub struct ElaborateDrops; -impl<'tcx> MirPass<'tcx> for ElaborateDrops { +impl<'tcx> crate::MirPass<'tcx> for ElaborateDrops { #[instrument(level = "trace", skip(self, tcx, body))] fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { debug!("elaborate_drops({:?} @ {:?})", body.source, body.span); diff --git a/compiler/rustc_mir_transform/src/function_item_references.rs b/compiler/rustc_mir_transform/src/function_item_references.rs index b7873e73c18c7..199fd0f10ee2c 100644 --- a/compiler/rustc_mir_transform/src/function_item_references.rs +++ b/compiler/rustc_mir_transform/src/function_item_references.rs @@ -9,11 +9,11 @@ use rustc_span::symbol::sym; use rustc_span::Span; use rustc_target::spec::abi::Abi; -use crate::{errors, MirLint}; +use crate::errors; pub struct FunctionItemReferences; -impl<'tcx> MirLint<'tcx> for FunctionItemReferences { +impl<'tcx> crate::MirLint<'tcx> for FunctionItemReferences { fn run_lint(&self, tcx: TyCtxt<'tcx>, body: &Body<'tcx>) { let mut checker = FunctionItemRefChecker { tcx, body }; checker.visit_body(body); diff --git a/compiler/rustc_mir_transform/src/gvn.rs b/compiler/rustc_mir_transform/src/gvn.rs index fb9baeeb3ed88..df0fcc42e5926 100644 --- a/compiler/rustc_mir_transform/src/gvn.rs +++ b/compiler/rustc_mir_transform/src/gvn.rs @@ -111,7 +111,7 @@ use crate::ssa::{AssignedValue, SsaLocals}; pub struct GVN; -impl<'tcx> MirPass<'tcx> for GVN { +impl<'tcx> crate::MirPass<'tcx> for GVN { fn is_enabled(&self, sess: &rustc_session::Session) -> bool { sess.mir_opt_level() >= 2 } diff --git a/compiler/rustc_mir_transform/src/inline.rs b/compiler/rustc_mir_transform/src/inline.rs index 4482801826ab0..6cc7e0ee1e4bc 100644 --- a/compiler/rustc_mir_transform/src/inline.rs +++ b/compiler/rustc_mir_transform/src/inline.rs @@ -42,7 +42,7 @@ struct CallSite<'tcx> { source_info: SourceInfo, } -impl<'tcx> MirPass<'tcx> for Inline { +impl<'tcx> crate::MirPass<'tcx> for Inline { fn is_enabled(&self, sess: &rustc_session::Session) -> bool { // FIXME(#127234): Coverage instrumentation currently doesn't handle inlined // MIR correctly when Modified Condition/Decision Coverage is enabled. diff --git a/compiler/rustc_mir_transform/src/instsimplify.rs b/compiler/rustc_mir_transform/src/instsimplify.rs index 3ec553d0ba0c5..4fbfa744e6733 100644 --- a/compiler/rustc_mir_transform/src/instsimplify.rs +++ b/compiler/rustc_mir_transform/src/instsimplify.rs @@ -27,7 +27,7 @@ impl InstSimplify { } } -impl<'tcx> MirPass<'tcx> for InstSimplify { +impl<'tcx> crate::MirPass<'tcx> for InstSimplify { fn name(&self) -> &'static str { self.name() } diff --git a/compiler/rustc_mir_transform/src/jump_threading.rs b/compiler/rustc_mir_transform/src/jump_threading.rs index 435b6a0116348..02dd56e1b4fdb 100644 --- a/compiler/rustc_mir_transform/src/jump_threading.rs +++ b/compiler/rustc_mir_transform/src/jump_threading.rs @@ -61,7 +61,7 @@ const MAX_BACKTRACK: usize = 5; const MAX_COST: usize = 100; const MAX_PLACES: usize = 100; -impl<'tcx> MirPass<'tcx> for JumpThreading { +impl<'tcx> crate::MirPass<'tcx> for JumpThreading { fn is_enabled(&self, sess: &rustc_session::Session) -> bool { sess.mir_opt_level() >= 2 } diff --git a/compiler/rustc_mir_transform/src/known_panics_lint.rs b/compiler/rustc_mir_transform/src/known_panics_lint.rs index 443d97d004e16..b402e55c5811d 100644 --- a/compiler/rustc_mir_transform/src/known_panics_lint.rs +++ b/compiler/rustc_mir_transform/src/known_panics_lint.rs @@ -25,11 +25,10 @@ use rustc_target::abi::{Abi, FieldIdx, HasDataLayout, Size, TargetDataLayout, Va use tracing::{debug, instrument, trace}; use crate::errors::{AssertLint, AssertLintKind}; -use crate::MirLint; pub struct KnownPanicsLint; -impl<'tcx> MirLint<'tcx> for KnownPanicsLint { +impl<'tcx> crate::MirLint<'tcx> for KnownPanicsLint { fn run_lint(&self, tcx: TyCtxt<'tcx>, body: &Body<'tcx>) { if body.tainted_by_errors.is_some() { return; diff --git a/compiler/rustc_mir_transform/src/large_enums.rs b/compiler/rustc_mir_transform/src/large_enums.rs index cbc3169f2f10a..f02ba71ddc64c 100644 --- a/compiler/rustc_mir_transform/src/large_enums.rs +++ b/compiler/rustc_mir_transform/src/large_enums.rs @@ -27,7 +27,7 @@ pub struct EnumSizeOpt { pub(crate) discrepancy: u64, } -impl<'tcx> MirPass<'tcx> for EnumSizeOpt { +impl<'tcx> crate::MirPass<'tcx> for EnumSizeOpt { fn is_enabled(&self, sess: &Session) -> bool { // There are some differences in behavior on wasm and ARM that are not properly // understood, so we conservatively treat this optimization as unsound: diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs index 63793c4f772ef..62e73ba2c8e24 100644 --- a/compiler/rustc_mir_transform/src/lib.rs +++ b/compiler/rustc_mir_transform/src/lib.rs @@ -26,7 +26,7 @@ use rustc_hir::intravisit::{self, Visitor}; use rustc_index::IndexVec; use rustc_middle::mir::{ AnalysisPhase, Body, CallSource, ClearCrossCrate, ConstOperand, ConstQualifs, LocalDecl, - MirPass, MirPhase, Operand, Place, ProjectionElem, Promoted, RuntimePhase, Rvalue, SourceInfo, + MirPhase, Operand, Place, ProjectionElem, Promoted, RuntimePhase, Rvalue, SourceInfo, Statement, StatementKind, TerminatorKind, START_BLOCK, }; use rustc_middle::ty::{self, TyCtxt, TypeVisitableExt}; @@ -40,7 +40,7 @@ use tracing::{debug, trace}; #[macro_use] mod pass_manager; -use pass_manager::{self as pm, Lint, MirLint, WithMinOptLevel}; +use pass_manager::{self as pm, Lint, MirLint, MirPass, WithMinOptLevel}; mod abort_unwinding_calls; mod add_call_guards; diff --git a/compiler/rustc_mir_transform/src/lower_intrinsics.rs b/compiler/rustc_mir_transform/src/lower_intrinsics.rs index a9bdff95fe5ac..55eec33230615 100644 --- a/compiler/rustc_mir_transform/src/lower_intrinsics.rs +++ b/compiler/rustc_mir_transform/src/lower_intrinsics.rs @@ -9,7 +9,7 @@ use crate::take_array; pub struct LowerIntrinsics; -impl<'tcx> MirPass<'tcx> for LowerIntrinsics { +impl<'tcx> crate::MirPass<'tcx> for LowerIntrinsics { fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { let local_decls = &body.local_decls; for block in body.basic_blocks.as_mut() { diff --git a/compiler/rustc_mir_transform/src/lower_slice_len.rs b/compiler/rustc_mir_transform/src/lower_slice_len.rs index 77a7f4f47dd4e..555309a775001 100644 --- a/compiler/rustc_mir_transform/src/lower_slice_len.rs +++ b/compiler/rustc_mir_transform/src/lower_slice_len.rs @@ -7,7 +7,7 @@ use rustc_middle::ty::TyCtxt; pub struct LowerSliceLenCalls; -impl<'tcx> MirPass<'tcx> for LowerSliceLenCalls { +impl<'tcx> crate::MirPass<'tcx> for LowerSliceLenCalls { fn is_enabled(&self, sess: &rustc_session::Session) -> bool { sess.mir_opt_level() > 0 } diff --git a/compiler/rustc_mir_transform/src/match_branches.rs b/compiler/rustc_mir_transform/src/match_branches.rs index 47758b56f8c90..32b20f93534a7 100644 --- a/compiler/rustc_mir_transform/src/match_branches.rs +++ b/compiler/rustc_mir_transform/src/match_branches.rs @@ -12,7 +12,7 @@ use super::simplify::simplify_cfg; pub struct MatchBranchSimplification; -impl<'tcx> MirPass<'tcx> for MatchBranchSimplification { +impl<'tcx> crate::MirPass<'tcx> for MatchBranchSimplification { fn is_enabled(&self, sess: &rustc_session::Session) -> bool { sess.mir_opt_level() >= 1 } diff --git a/compiler/rustc_mir_transform/src/mentioned_items.rs b/compiler/rustc_mir_transform/src/mentioned_items.rs index 32c8064ebca50..41ce03caf0873 100644 --- a/compiler/rustc_mir_transform/src/mentioned_items.rs +++ b/compiler/rustc_mir_transform/src/mentioned_items.rs @@ -1,5 +1,5 @@ use rustc_middle::mir::visit::Visitor; -use rustc_middle::mir::{self, Location, MentionedItem, MirPass}; +use rustc_middle::mir::{self, Location, MentionedItem}; use rustc_middle::ty::adjustment::PointerCoercion; use rustc_middle::ty::{self, TyCtxt}; use rustc_session::Session; @@ -13,7 +13,7 @@ struct MentionedItemsVisitor<'a, 'tcx> { mentioned_items: &'a mut Vec>>, } -impl<'tcx> MirPass<'tcx> for MentionedItems { +impl<'tcx> crate::MirPass<'tcx> for MentionedItems { fn is_enabled(&self, _sess: &Session) -> bool { // If this pass is skipped the collector assume that nothing got mentioned! We could // potentially skip it in opt-level 0 if we are sure that opt-level will never *remove* uses diff --git a/compiler/rustc_mir_transform/src/multiple_return_terminators.rs b/compiler/rustc_mir_transform/src/multiple_return_terminators.rs index 1e87a0e01d9be..1b4972d487eea 100644 --- a/compiler/rustc_mir_transform/src/multiple_return_terminators.rs +++ b/compiler/rustc_mir_transform/src/multiple_return_terminators.rs @@ -9,7 +9,7 @@ use crate::simplify; pub struct MultipleReturnTerminators; -impl<'tcx> MirPass<'tcx> for MultipleReturnTerminators { +impl<'tcx> crate::MirPass<'tcx> for MultipleReturnTerminators { fn is_enabled(&self, sess: &rustc_session::Session) -> bool { sess.mir_opt_level() >= 4 } diff --git a/compiler/rustc_mir_transform/src/nrvo.rs b/compiler/rustc_mir_transform/src/nrvo.rs index dd1875f2a78ac..94573a9d89bfd 100644 --- a/compiler/rustc_mir_transform/src/nrvo.rs +++ b/compiler/rustc_mir_transform/src/nrvo.rs @@ -8,8 +8,6 @@ use rustc_middle::mir::{self, BasicBlock, Local, Location}; use rustc_middle::ty::TyCtxt; use tracing::{debug, trace}; -use crate::MirPass; - /// This pass looks for MIR that always copies the same local into the return place and eliminates /// the copy by renaming all uses of that local to `_0`. /// @@ -34,7 +32,7 @@ use crate::MirPass; /// [#71003]: https://github.com/rust-lang/rust/pull/71003 pub struct RenameReturnPlace; -impl<'tcx> MirPass<'tcx> for RenameReturnPlace { +impl<'tcx> crate::MirPass<'tcx> for RenameReturnPlace { fn is_enabled(&self, sess: &rustc_session::Session) -> bool { // unsound: #111005 sess.mir_opt_level() > 0 && sess.opts.unstable_opts.unsound_mir_opts diff --git a/compiler/rustc_mir_transform/src/pass_manager.rs b/compiler/rustc_mir_transform/src/pass_manager.rs index 51e2760040478..8b691c9e929ef 100644 --- a/compiler/rustc_mir_transform/src/pass_manager.rs +++ b/compiler/rustc_mir_transform/src/pass_manager.rs @@ -1,10 +1,89 @@ +use std::cell::RefCell; +use std::collections::hash_map::Entry; + +use rustc_data_structures::fx::FxHashMap; use rustc_middle::mir::{self, Body, MirPhase, RuntimePhase}; use rustc_middle::ty::TyCtxt; use rustc_session::Session; use tracing::trace; use crate::lint::lint_body; -use crate::{validate, MirPass}; +use crate::validate; + +thread_local! { + static PASS_NAMES: RefCell> = { + RefCell::new(FxHashMap::default()) + }; +} + +/// Converts a MIR pass name into a snake case form to match the profiling naming style. +fn to_profiler_name(type_name: &'static str) -> &'static str { + PASS_NAMES.with(|names| match names.borrow_mut().entry(type_name) { + Entry::Occupied(e) => *e.get(), + Entry::Vacant(e) => { + let snake_case: String = type_name + .chars() + .flat_map(|c| { + if c.is_ascii_uppercase() { + vec!['_', c.to_ascii_lowercase()] + } else if c == '-' { + vec!['_'] + } else { + vec![c] + } + }) + .collect(); + let result = &*String::leak(format!("mir_pass{}", snake_case)); + e.insert(result); + result + } + }) +} + +// const wrapper for `if let Some((_, tail)) = name.rsplit_once(':') { tail } else { name }` +const fn c_name(name: &'static str) -> &'static str { + // FIXME Simplify the implementation once more `str` methods get const-stable. + // and inline into call site + let bytes = name.as_bytes(); + let mut i = bytes.len(); + while i > 0 && bytes[i - 1] != b':' { + i = i - 1; + } + let (_, bytes) = bytes.split_at(i); + match std::str::from_utf8(bytes) { + Ok(name) => name, + Err(_) => name, + } +} + +/// A streamlined trait that you can implement to create a pass; the +/// pass will be named after the type, and it will consist of a main +/// loop that goes over each available MIR and applies `run_pass`. +pub trait MirPass<'tcx> { + fn name(&self) -> &'static str { + // FIXME Simplify the implementation once more `str` methods get const-stable. + // See copypaste in `MirLint` + const { + let name = std::any::type_name::(); + c_name(name) + } + } + + fn profiler_name(&self) -> &'static str { + to_profiler_name(self.name()) + } + + /// Returns `true` if this pass is enabled with the current combination of compiler flags. + fn is_enabled(&self, _sess: &Session) -> bool { + true + } + + fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>); + + fn is_mir_dump_enabled(&self) -> bool { + true + } +} /// Just like `MirPass`, except it cannot mutate `Body`. pub trait MirLint<'tcx> { @@ -13,7 +92,7 @@ pub trait MirLint<'tcx> { // See copypaste in `MirPass` const { let name = std::any::type_name::(); - rustc_middle::util::common::c_name(name) + c_name(name) } } diff --git a/compiler/rustc_mir_transform/src/prettify.rs b/compiler/rustc_mir_transform/src/prettify.rs index 14dd0c6f61e76..ad71c6226601c 100644 --- a/compiler/rustc_mir_transform/src/prettify.rs +++ b/compiler/rustc_mir_transform/src/prettify.rs @@ -17,7 +17,7 @@ use rustc_session::Session; /// `IndexVec`, unless that successor is a back-edge (such as from a loop). pub struct ReorderBasicBlocks; -impl<'tcx> MirPass<'tcx> for ReorderBasicBlocks { +impl<'tcx> crate::MirPass<'tcx> for ReorderBasicBlocks { fn is_enabled(&self, _session: &Session) -> bool { false } @@ -45,7 +45,7 @@ impl<'tcx> MirPass<'tcx> for ReorderBasicBlocks { /// (Does not reorder arguments nor the [`RETURN_PLACE`].) pub struct ReorderLocals; -impl<'tcx> MirPass<'tcx> for ReorderLocals { +impl<'tcx> crate::MirPass<'tcx> for ReorderLocals { fn is_enabled(&self, _session: &Session) -> bool { false } diff --git a/compiler/rustc_mir_transform/src/promote_consts.rs b/compiler/rustc_mir_transform/src/promote_consts.rs index f2610fd52bc12..68ae2651959a8 100644 --- a/compiler/rustc_mir_transform/src/promote_consts.rs +++ b/compiler/rustc_mir_transform/src/promote_consts.rs @@ -41,7 +41,7 @@ pub struct PromoteTemps<'tcx> { pub promoted_fragments: Cell>>, } -impl<'tcx> MirPass<'tcx> for PromoteTemps<'tcx> { +impl<'tcx> crate::MirPass<'tcx> for PromoteTemps<'tcx> { fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { // There's not really any point in promoting errorful MIR. // diff --git a/compiler/rustc_mir_transform/src/ref_prop.rs b/compiler/rustc_mir_transform/src/ref_prop.rs index 2b07c04a12130..e9c2370b8118f 100644 --- a/compiler/rustc_mir_transform/src/ref_prop.rs +++ b/compiler/rustc_mir_transform/src/ref_prop.rs @@ -72,7 +72,7 @@ use crate::ssa::{SsaLocals, StorageLiveLocals}; /// so we perform all the possible instantiations without removing the `_1 = &_2` statement. pub struct ReferencePropagation; -impl<'tcx> MirPass<'tcx> for ReferencePropagation { +impl<'tcx> crate::MirPass<'tcx> for ReferencePropagation { fn is_enabled(&self, sess: &rustc_session::Session) -> bool { sess.mir_opt_level() >= 2 } diff --git a/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs b/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs index 33c7d1695c02d..ccba8d015e3a6 100644 --- a/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs +++ b/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs @@ -10,7 +10,7 @@ use tracing::debug; /// terrible code for these. pub struct RemoveNoopLandingPads; -impl<'tcx> MirPass<'tcx> for RemoveNoopLandingPads { +impl<'tcx> crate::MirPass<'tcx> for RemoveNoopLandingPads { fn is_enabled(&self, sess: &rustc_session::Session) -> bool { sess.panic_strategy() != PanicStrategy::Abort } diff --git a/compiler/rustc_mir_transform/src/remove_place_mention.rs b/compiler/rustc_mir_transform/src/remove_place_mention.rs index 6c0b50fafdb40..5801fdedcebb2 100644 --- a/compiler/rustc_mir_transform/src/remove_place_mention.rs +++ b/compiler/rustc_mir_transform/src/remove_place_mention.rs @@ -6,7 +6,7 @@ use tracing::trace; pub struct RemovePlaceMention; -impl<'tcx> MirPass<'tcx> for RemovePlaceMention { +impl<'tcx> crate::MirPass<'tcx> for RemovePlaceMention { fn is_enabled(&self, sess: &rustc_session::Session) -> bool { !sess.opts.unstable_opts.mir_keep_place_mention } diff --git a/compiler/rustc_mir_transform/src/remove_storage_markers.rs b/compiler/rustc_mir_transform/src/remove_storage_markers.rs index af89395dddd2d..329b30d3890a3 100644 --- a/compiler/rustc_mir_transform/src/remove_storage_markers.rs +++ b/compiler/rustc_mir_transform/src/remove_storage_markers.rs @@ -6,7 +6,7 @@ use tracing::trace; pub struct RemoveStorageMarkers; -impl<'tcx> MirPass<'tcx> for RemoveStorageMarkers { +impl<'tcx> crate::MirPass<'tcx> for RemoveStorageMarkers { fn is_enabled(&self, sess: &rustc_session::Session) -> bool { sess.mir_opt_level() > 0 && !sess.emit_lifetime_markers() } diff --git a/compiler/rustc_mir_transform/src/remove_uninit_drops.rs b/compiler/rustc_mir_transform/src/remove_uninit_drops.rs index fae1cb5f7d8a5..aafe971311d31 100644 --- a/compiler/rustc_mir_transform/src/remove_uninit_drops.rs +++ b/compiler/rustc_mir_transform/src/remove_uninit_drops.rs @@ -6,8 +6,6 @@ use rustc_mir_dataflow::move_paths::{LookupResult, MoveData, MovePathIndex}; use rustc_mir_dataflow::{move_path_children_matching, Analysis, MaybeReachable}; use rustc_target::abi::FieldIdx; -use crate::MirPass; - /// Removes `Drop` terminators whose target is known to be uninitialized at /// that point. /// @@ -18,7 +16,7 @@ use crate::MirPass; /// [#90770]: https://github.com/rust-lang/rust/issues/90770 pub struct RemoveUninitDrops; -impl<'tcx> MirPass<'tcx> for RemoveUninitDrops { +impl<'tcx> crate::MirPass<'tcx> for RemoveUninitDrops { fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { let param_env = tcx.param_env(body.source.def_id()); let move_data = diff --git a/compiler/rustc_mir_transform/src/remove_unneeded_drops.rs b/compiler/rustc_mir_transform/src/remove_unneeded_drops.rs index 9adcb5a38fd8b..43109aae0fb6c 100644 --- a/compiler/rustc_mir_transform/src/remove_unneeded_drops.rs +++ b/compiler/rustc_mir_transform/src/remove_unneeded_drops.rs @@ -12,7 +12,7 @@ use super::simplify::simplify_cfg; pub struct RemoveUnneededDrops; -impl<'tcx> MirPass<'tcx> for RemoveUnneededDrops { +impl<'tcx> crate::MirPass<'tcx> for RemoveUnneededDrops { fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { trace!("Running RemoveUnneededDrops on {:?}", body.source); diff --git a/compiler/rustc_mir_transform/src/remove_zsts.rs b/compiler/rustc_mir_transform/src/remove_zsts.rs index 9a94cae338288..9aa46bd4fbae6 100644 --- a/compiler/rustc_mir_transform/src/remove_zsts.rs +++ b/compiler/rustc_mir_transform/src/remove_zsts.rs @@ -6,7 +6,7 @@ use rustc_middle::ty::{self, Ty, TyCtxt}; pub struct RemoveZsts; -impl<'tcx> MirPass<'tcx> for RemoveZsts { +impl<'tcx> crate::MirPass<'tcx> for RemoveZsts { fn is_enabled(&self, sess: &rustc_session::Session) -> bool { sess.mir_opt_level() > 0 } diff --git a/compiler/rustc_mir_transform/src/reveal_all.rs b/compiler/rustc_mir_transform/src/reveal_all.rs index 5eaa024f84689..29312a99cbc01 100644 --- a/compiler/rustc_mir_transform/src/reveal_all.rs +++ b/compiler/rustc_mir_transform/src/reveal_all.rs @@ -6,7 +6,7 @@ use rustc_middle::ty::{self, Ty, TyCtxt}; pub struct RevealAll; -impl<'tcx> MirPass<'tcx> for RevealAll { +impl<'tcx> crate::MirPass<'tcx> for RevealAll { fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { let param_env = tcx.param_env_reveal_all_normalized(body.source.def_id()); RevealAllVisitor { tcx, param_env }.visit_body_preserves_cfg(body); diff --git a/compiler/rustc_mir_transform/src/sanity_check.rs b/compiler/rustc_mir_transform/src/sanity_check.rs index 8c8b3915c0f64..c9445d1816295 100644 --- a/compiler/rustc_mir_transform/src/sanity_check.rs +++ b/compiler/rustc_mir_transform/src/sanity_check.rs @@ -2,11 +2,9 @@ use rustc_middle::mir::Body; use rustc_middle::ty::TyCtxt; use rustc_mir_dataflow::rustc_peek::sanity_check; -use crate::MirLint; - pub(super) struct SanityCheck; -impl<'tcx> MirLint<'tcx> for SanityCheck { +impl<'tcx> crate::MirLint<'tcx> for SanityCheck { fn run_lint(&self, tcx: TyCtxt<'tcx>, body: &Body<'tcx>) { sanity_check(tcx, body); } diff --git a/compiler/rustc_mir_transform/src/simplify.rs b/compiler/rustc_mir_transform/src/simplify.rs index d1c2c91e00fd7..1478b86d3c765 100644 --- a/compiler/rustc_mir_transform/src/simplify.rs +++ b/compiler/rustc_mir_transform/src/simplify.rs @@ -74,7 +74,7 @@ pub(crate) fn simplify_cfg(body: &mut Body<'_>) { body.basic_blocks_mut().raw.shrink_to_fit(); } -impl<'tcx> MirPass<'tcx> for SimplifyCfg { +impl<'tcx> crate::MirPass<'tcx> for SimplifyCfg { fn name(&self) -> &'static str { self.name() } @@ -366,7 +366,7 @@ pub enum SimplifyLocals { Final, } -impl<'tcx> MirPass<'tcx> for SimplifyLocals { +impl<'tcx> crate::MirPass<'tcx> for SimplifyLocals { fn name(&self) -> &'static str { match &self { SimplifyLocals::BeforeConstProp => "SimplifyLocals-before-const-prop", diff --git a/compiler/rustc_mir_transform/src/simplify_branches.rs b/compiler/rustc_mir_transform/src/simplify_branches.rs index 7c8a686d0077e..5a014bb734683 100644 --- a/compiler/rustc_mir_transform/src/simplify_branches.rs +++ b/compiler/rustc_mir_transform/src/simplify_branches.rs @@ -7,7 +7,7 @@ pub enum SimplifyConstCondition { Final, } /// A pass that replaces a branch with a goto when its condition is known. -impl<'tcx> MirPass<'tcx> for SimplifyConstCondition { +impl<'tcx> crate::MirPass<'tcx> for SimplifyConstCondition { fn name(&self) -> &'static str { match self { SimplifyConstCondition::AfterConstProp => "SimplifyConstCondition-after-const-prop", diff --git a/compiler/rustc_mir_transform/src/simplify_comparison_integral.rs b/compiler/rustc_mir_transform/src/simplify_comparison_integral.rs index ac892adebec1b..bd30ecc59b3d7 100644 --- a/compiler/rustc_mir_transform/src/simplify_comparison_integral.rs +++ b/compiler/rustc_mir_transform/src/simplify_comparison_integral.rs @@ -9,8 +9,6 @@ use rustc_middle::mir::{ use rustc_middle::ty::{Ty, TyCtxt}; use tracing::trace; -use super::MirPass; - /// Pass to convert `if` conditions on integrals into switches on the integral. /// For an example, it turns something like /// @@ -27,7 +25,7 @@ use super::MirPass; /// ``` pub struct SimplifyComparisonIntegral; -impl<'tcx> MirPass<'tcx> for SimplifyComparisonIntegral { +impl<'tcx> crate::MirPass<'tcx> for SimplifyComparisonIntegral { fn is_enabled(&self, sess: &rustc_session::Session) -> bool { sess.mir_opt_level() > 0 } diff --git a/compiler/rustc_mir_transform/src/single_use_consts.rs b/compiler/rustc_mir_transform/src/single_use_consts.rs index 35cb6872fe9a2..64a928728307b 100644 --- a/compiler/rustc_mir_transform/src/single_use_consts.rs +++ b/compiler/rustc_mir_transform/src/single_use_consts.rs @@ -21,7 +21,7 @@ use rustc_middle::ty::TyCtxt; /// needed to do that too, including updating the debug info. pub struct SingleUseConsts; -impl<'tcx> MirPass<'tcx> for SingleUseConsts { +impl<'tcx> crate::MirPass<'tcx> for SingleUseConsts { fn is_enabled(&self, sess: &rustc_session::Session) -> bool { sess.mir_opt_level() > 0 } diff --git a/compiler/rustc_mir_transform/src/sroa.rs b/compiler/rustc_mir_transform/src/sroa.rs index 906e2c23f3b8c..3c5ccc0c99a8a 100644 --- a/compiler/rustc_mir_transform/src/sroa.rs +++ b/compiler/rustc_mir_transform/src/sroa.rs @@ -13,7 +13,7 @@ use tracing::{debug, instrument}; pub struct ScalarReplacementOfAggregates; -impl<'tcx> MirPass<'tcx> for ScalarReplacementOfAggregates { +impl<'tcx> crate::MirPass<'tcx> for ScalarReplacementOfAggregates { fn is_enabled(&self, sess: &rustc_session::Session) -> bool { sess.mir_opt_level() >= 2 } diff --git a/compiler/rustc_mir_transform/src/unreachable_enum_branching.rs b/compiler/rustc_mir_transform/src/unreachable_enum_branching.rs index 2427fbac5eefa..51a322628ee69 100644 --- a/compiler/rustc_mir_transform/src/unreachable_enum_branching.rs +++ b/compiler/rustc_mir_transform/src/unreachable_enum_branching.rs @@ -12,8 +12,6 @@ use rustc_middle::ty::{Ty, TyCtxt}; use rustc_target::abi::{Abi, Variants}; use tracing::trace; -use crate::MirPass; - pub struct UnreachableEnumBranching; fn get_discriminant_local(terminator: &TerminatorKind<'_>) -> Option { @@ -74,7 +72,7 @@ fn variant_discriminants<'tcx>( } } -impl<'tcx> MirPass<'tcx> for UnreachableEnumBranching { +impl<'tcx> crate::MirPass<'tcx> for UnreachableEnumBranching { fn is_enabled(&self, sess: &rustc_session::Session) -> bool { sess.mir_opt_level() > 0 } diff --git a/compiler/rustc_mir_transform/src/unreachable_prop.rs b/compiler/rustc_mir_transform/src/unreachable_prop.rs index a6c3c3b189ed0..b8da86f1a8dde 100644 --- a/compiler/rustc_mir_transform/src/unreachable_prop.rs +++ b/compiler/rustc_mir_transform/src/unreachable_prop.rs @@ -12,7 +12,7 @@ use rustc_target::abi::Size; pub struct UnreachablePropagation; -impl MirPass<'_> for UnreachablePropagation { +impl crate::MirPass<'_> for UnreachablePropagation { fn is_enabled(&self, sess: &rustc_session::Session) -> bool { // Enable only under -Zmir-opt-level=2 as this can make programs less debuggable. sess.mir_opt_level() >= 2 diff --git a/compiler/rustc_mir_transform/src/validate.rs b/compiler/rustc_mir_transform/src/validate.rs index 99e06f59dd04d..69e2592e82c77 100644 --- a/compiler/rustc_mir_transform/src/validate.rs +++ b/compiler/rustc_mir_transform/src/validate.rs @@ -36,7 +36,7 @@ pub struct Validator { pub mir_phase: MirPhase, } -impl<'tcx> MirPass<'tcx> for Validator { +impl<'tcx> crate::MirPass<'tcx> for Validator { fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { // FIXME(JakobDegen): These bodies never instantiated in codegend anyway, so it's not // terribly important that they pass the validator. However, I think other passes might From 827fa43392ded31eb8d2ec397e542581741f7295 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 3 Sep 2024 15:56:54 +1000 Subject: [PATCH 0427/2194] Reduce visibility of `MirPass` and related things. They're now all just used within this crate. --- .../rustc_mir_transform/src/pass_manager.rs | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/compiler/rustc_mir_transform/src/pass_manager.rs b/compiler/rustc_mir_transform/src/pass_manager.rs index 8b691c9e929ef..4f24139ba748d 100644 --- a/compiler/rustc_mir_transform/src/pass_manager.rs +++ b/compiler/rustc_mir_transform/src/pass_manager.rs @@ -59,7 +59,7 @@ const fn c_name(name: &'static str) -> &'static str { /// A streamlined trait that you can implement to create a pass; the /// pass will be named after the type, and it will consist of a main /// loop that goes over each available MIR and applies `run_pass`. -pub trait MirPass<'tcx> { +pub(super) trait MirPass<'tcx> { fn name(&self) -> &'static str { // FIXME Simplify the implementation once more `str` methods get const-stable. // See copypaste in `MirLint` @@ -86,7 +86,7 @@ pub trait MirPass<'tcx> { } /// Just like `MirPass`, except it cannot mutate `Body`. -pub trait MirLint<'tcx> { +pub(super) trait MirLint<'tcx> { fn name(&self) -> &'static str { // FIXME Simplify the implementation once more `str` methods get const-stable. // See copypaste in `MirPass` @@ -105,7 +105,7 @@ pub trait MirLint<'tcx> { /// An adapter for `MirLint`s that implements `MirPass`. #[derive(Debug, Clone)] -pub struct Lint(pub T); +pub(super) struct Lint(pub T); impl<'tcx, T> MirPass<'tcx> for Lint where @@ -128,7 +128,7 @@ where } } -pub struct WithMinOptLevel(pub u32, pub T); +pub(super) struct WithMinOptLevel(pub u32, pub T); impl<'tcx, T> MirPass<'tcx> for WithMinOptLevel where @@ -149,7 +149,7 @@ where /// Run the sequence of passes without validating the MIR after each pass. The MIR is still /// validated at the end. -pub fn run_passes_no_validate<'tcx>( +pub(super) fn run_passes_no_validate<'tcx>( tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>, passes: &[&dyn MirPass<'tcx>], @@ -159,7 +159,7 @@ pub fn run_passes_no_validate<'tcx>( } /// The optional `phase_change` is applied after executing all the passes, if present -pub fn run_passes<'tcx>( +pub(super) fn run_passes<'tcx>( tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>, passes: &[&dyn MirPass<'tcx>], @@ -168,7 +168,7 @@ pub fn run_passes<'tcx>( run_passes_inner(tcx, body, passes, phase_change, true); } -pub fn should_run_pass<'tcx, P>(tcx: TyCtxt<'tcx>, pass: &P) -> bool +pub(super) fn should_run_pass<'tcx, P>(tcx: TyCtxt<'tcx>, pass: &P) -> bool where P: MirPass<'tcx> + ?Sized, { @@ -264,11 +264,11 @@ fn run_passes_inner<'tcx>( } } -pub fn validate_body<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>, when: String) { +pub(super) fn validate_body<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>, when: String) { validate::Validator { when, mir_phase: body.phase }.run_pass(tcx, body); } -pub fn dump_mir_for_pass<'tcx>( +pub(super) fn dump_mir_for_pass<'tcx>( tcx: TyCtxt<'tcx>, body: &Body<'tcx>, pass_name: &str, @@ -284,7 +284,7 @@ pub fn dump_mir_for_pass<'tcx>( ); } -pub fn dump_mir_for_phase_change<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>) { +pub(super) fn dump_mir_for_phase_change<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>) { assert_eq!(body.pass_count, 0); mir::dump_mir(tcx, true, body.phase.name(), &"after", body, |_, _| Ok(())) } From 0b2b03cf70d76ebe2abe28f68e7ed46ee2c80e08 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 3 Sep 2024 15:58:13 +1000 Subject: [PATCH 0428/2194] Clarify a comment. --- compiler/rustc_mir_transform/src/pass_manager.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_mir_transform/src/pass_manager.rs b/compiler/rustc_mir_transform/src/pass_manager.rs index 4f24139ba748d..28d4e1a1c9184 100644 --- a/compiler/rustc_mir_transform/src/pass_manager.rs +++ b/compiler/rustc_mir_transform/src/pass_manager.rs @@ -85,7 +85,8 @@ pub(super) trait MirPass<'tcx> { } } -/// Just like `MirPass`, except it cannot mutate `Body`. +/// Just like `MirPass`, except it cannot mutate `Body`, and MIR dumping is +/// disabled (via the `Lint` adapter). pub(super) trait MirLint<'tcx> { fn name(&self) -> &'static str { // FIXME Simplify the implementation once more `str` methods get const-stable. From 6188aae369961d6328f7275c78bdf256133b7d5d Mon Sep 17 00:00:00 2001 From: lcnr Date: Mon, 2 Sep 2024 14:50:50 +0000 Subject: [PATCH 0429/2194] do not attempt to prove unknowable goals --- .../src/solve/assembly/mod.rs | 66 ++++----- .../src/traits/coherence.rs | 138 +++++++++--------- compiler/rustc_type_ir/src/solve/mod.rs | 2 +- .../normalize-for-errors.next.stderr | 2 +- tests/ui/coherence/normalize-for-errors.rs | 2 +- 5 files changed, 101 insertions(+), 109 deletions(-) diff --git a/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs b/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs index bb05eb4c25697..6c9a6011144cd 100644 --- a/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs @@ -304,6 +304,11 @@ where let mut candidates = vec![]; + if self.solver_mode() == SolverMode::Coherence { + if let Ok(candidate) = self.consider_coherence_unknowable_candidate(goal) { + return vec![candidate]; + } + } self.assemble_impl_candidates(goal, &mut candidates); self.assemble_builtin_impl_candidates(goal, &mut candidates); @@ -314,11 +319,8 @@ where self.assemble_param_env_candidates(goal, &mut candidates); - match self.solver_mode() { - SolverMode::Normal => self.discard_impls_shadowed_by_env(goal, &mut candidates), - SolverMode::Coherence => { - self.assemble_coherence_unknowable_candidates(goal, &mut candidates) - } + if self.solver_mode() == SolverMode::Normal { + self.discard_impls_shadowed_by_env(goal, &mut candidates); } candidates @@ -682,38 +684,34 @@ where /// also consider impls which may get added in a downstream or sibling crate /// or which an upstream impl may add in a minor release. /// - /// To do so we add an ambiguous candidate in case such an unknown impl could - /// apply to the current goal. + /// To do so we return a single ambiguous candidate in case such an unknown + /// impl could apply to the current goal. #[instrument(level = "trace", skip_all)] - fn assemble_coherence_unknowable_candidates>( + fn consider_coherence_unknowable_candidate>( &mut self, goal: Goal, - candidates: &mut Vec>, - ) { - let cx = self.cx(); - - candidates.extend(self.probe_trait_candidate(CandidateSource::CoherenceUnknowable).enter( - |ecx| { - let trait_ref = goal.predicate.trait_ref(cx); - if ecx.trait_ref_is_knowable(goal.param_env, trait_ref)? { - Err(NoSolution) - } else { - // While the trait bound itself may be unknowable, we may be able to - // prove that a super trait is not implemented. For this, we recursively - // prove the super trait bounds of the current goal. - // - // We skip the goal itself as that one would cycle. - let predicate: I::Predicate = trait_ref.upcast(cx); - ecx.add_goals( - GoalSource::Misc, - elaborate::elaborate(cx, [predicate]) - .skip(1) - .map(|predicate| goal.with(cx, predicate)), - ); - ecx.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS) - } - }, - )) + ) -> Result, NoSolution> { + self.probe_trait_candidate(CandidateSource::CoherenceUnknowable).enter(|ecx| { + let cx = ecx.cx(); + let trait_ref = goal.predicate.trait_ref(cx); + if ecx.trait_ref_is_knowable(goal.param_env, trait_ref)? { + Err(NoSolution) + } else { + // While the trait bound itself may be unknowable, we may be able to + // prove that a super trait is not implemented. For this, we recursively + // prove the super trait bounds of the current goal. + // + // We skip the goal itself as that one would cycle. + let predicate: I::Predicate = trait_ref.upcast(cx); + ecx.add_goals( + GoalSource::Misc, + elaborate::elaborate(cx, [predicate]) + .skip(1) + .map(|predicate| goal.with(cx, predicate)), + ); + ecx.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS) + } + }) } /// If there's a where-bound for the current goal, do not use any impl candidates diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs index 8558520897b5c..8b55f84bccc1d 100644 --- a/compiler/rustc_trait_selection/src/traits/coherence.rs +++ b/compiler/rustc_trait_selection/src/traits/coherence.rs @@ -29,6 +29,7 @@ use crate::infer::outlives::env::OutlivesEnvironment; use crate::infer::InferOk; use crate::solve::inspect::{InspectGoal, ProofTreeInferCtxtExt, ProofTreeVisitor}; use crate::solve::{deeply_normalize_for_diagnostics, inspect}; +use crate::traits::query::evaluate_obligation::InferCtxtExt; use crate::traits::select::IntercrateAmbiguityCause; use crate::traits::{ util, FulfillmentErrorCode, NormalizeExt, Obligation, ObligationCause, PredicateObligation, @@ -624,14 +625,13 @@ impl<'a, 'tcx> ProofTreeVisitor<'tcx> for AmbiguityCausesVisitor<'a, 'tcx> { // at ambiguous goals, as for others the coherence unknowable candidate // was irrelevant. match goal.result() { - Ok(Certainty::Maybe(_)) => {} Ok(Certainty::Yes) | Err(NoSolution) => return, + Ok(Certainty::Maybe(_)) => {} } - let Goal { param_env, predicate } = goal.goal(); - // For bound predicates we simply call `infcx.enter_forall` // and then prove the resulting predicate as a nested goal. + let Goal { param_env, predicate } = goal.goal(); let trait_ref = match predicate.kind().no_bound_vars() { Some(ty::PredicateKind::Clause(ty::ClauseKind::Trait(tr))) => tr.trait_ref, Some(ty::PredicateKind::Clause(ty::ClauseKind::Projection(proj))) @@ -645,7 +645,11 @@ impl<'a, 'tcx> ProofTreeVisitor<'tcx> for AmbiguityCausesVisitor<'a, 'tcx> { _ => return, }; - // Add ambiguity causes for reservation impls. + if trait_ref.references_error() { + return; + } + + let mut candidates = goal.candidates(); for cand in goal.candidates() { if let inspect::ProbeKind::TraitCandidate { source: CandidateSource::Impl(def_id), @@ -664,78 +668,68 @@ impl<'a, 'tcx> ProofTreeVisitor<'tcx> for AmbiguityCausesVisitor<'a, 'tcx> { } } - // Add ambiguity causes for unknowable goals. - let mut ambiguity_cause = None; - for cand in goal.candidates() { - if let inspect::ProbeKind::TraitCandidate { - source: CandidateSource::CoherenceUnknowable, - result: Ok(_), - } = cand.kind() - { - let lazily_normalize_ty = |mut ty: Ty<'tcx>| { - if matches!(ty.kind(), ty::Alias(..)) { - let ocx = ObligationCtxt::new(infcx); - ty = ocx - .structurally_normalize(&ObligationCause::dummy(), param_env, ty) - .map_err(|_| ())?; - if !ocx.select_where_possible().is_empty() { - return Err(()); - } - } - Ok(ty) - }; + // We also look for unknowable candidates. In case a goal is unknowable, there's + // always exactly 1 candidate. + let Some(cand) = candidates.pop() else { + return; + }; - infcx.probe(|_| { - match trait_ref_is_knowable(infcx, trait_ref, lazily_normalize_ty) { - Err(()) => {} - Ok(Ok(())) => warn!("expected an unknowable trait ref: {trait_ref:?}"), - Ok(Err(conflict)) => { - if !trait_ref.references_error() { - // Normalize the trait ref for diagnostics, ignoring any errors if this fails. - let trait_ref = - deeply_normalize_for_diagnostics(infcx, param_env, trait_ref); - - let self_ty = trait_ref.self_ty(); - let self_ty = self_ty.has_concrete_skeleton().then(|| self_ty); - ambiguity_cause = Some(match conflict { - Conflict::Upstream => { - IntercrateAmbiguityCause::UpstreamCrateUpdate { - trait_ref, - self_ty, - } - } - Conflict::Downstream => { - IntercrateAmbiguityCause::DownstreamCrate { - trait_ref, - self_ty, - } - } - }); - } - } - } - }) - } else { - match cand.result() { - // We only add an ambiguity cause if the goal would otherwise - // result in an error. - // - // FIXME: While this matches the behavior of the - // old solver, it is not the only way in which the unknowable - // candidates *weaken* coherence, they can also force otherwise - // successful normalization to be ambiguous. - Ok(Certainty::Maybe(_) | Certainty::Yes) => { - ambiguity_cause = None; - break; - } - Err(NoSolution) => continue, + let inspect::ProbeKind::TraitCandidate { + source: CandidateSource::CoherenceUnknowable, + result: Ok(_), + } = cand.kind() + else { + return; + }; + + let lazily_normalize_ty = |mut ty: Ty<'tcx>| { + if matches!(ty.kind(), ty::Alias(..)) { + let ocx = ObligationCtxt::new(infcx); + ty = ocx + .structurally_normalize(&ObligationCause::dummy(), param_env, ty) + .map_err(|_| ())?; + if !ocx.select_where_possible().is_empty() { + return Err(()); } } - } + Ok(ty) + }; - if let Some(ambiguity_cause) = ambiguity_cause { - self.causes.insert(ambiguity_cause); - } + infcx.probe(|_| { + let conflict = match trait_ref_is_knowable(infcx, trait_ref, lazily_normalize_ty) { + Err(()) => return, + Ok(Ok(())) => { + warn!("expected an unknowable trait ref: {trait_ref:?}"); + return; + } + Ok(Err(conflict)) => conflict, + }; + + // It is only relevant that a goal is unknowable if it would have otherwise + // failed. + let non_intercrate_infcx = infcx.fork_with_intercrate(false); + if non_intercrate_infcx.predicate_may_hold(&Obligation::new( + infcx.tcx, + ObligationCause::dummy(), + param_env, + predicate, + )) { + return; + } + + // Normalize the trait ref for diagnostics, ignoring any errors if this fails. + let trait_ref = deeply_normalize_for_diagnostics(infcx, param_env, trait_ref); + let self_ty = trait_ref.self_ty(); + let self_ty = self_ty.has_concrete_skeleton().then(|| self_ty); + self.causes.insert(match conflict { + Conflict::Upstream => { + IntercrateAmbiguityCause::UpstreamCrateUpdate { trait_ref, self_ty } + } + Conflict::Downstream => { + IntercrateAmbiguityCause::DownstreamCrate { trait_ref, self_ty } + } + }); + }); } } diff --git a/compiler/rustc_type_ir/src/solve/mod.rs b/compiler/rustc_type_ir/src/solve/mod.rs index 96c939a898bd9..96998d2ec9f2c 100644 --- a/compiler/rustc_type_ir/src/solve/mod.rs +++ b/compiler/rustc_type_ir/src/solve/mod.rs @@ -58,7 +58,7 @@ pub enum Reveal { All, } -#[derive(Debug, Clone, Copy)] +#[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum SolverMode { /// Ordinary trait solving, using everywhere except for coherence. Normal, diff --git a/tests/ui/coherence/normalize-for-errors.next.stderr b/tests/ui/coherence/normalize-for-errors.next.stderr index 634a10b7a14c3..44952dc194456 100644 --- a/tests/ui/coherence/normalize-for-errors.next.stderr +++ b/tests/ui/coherence/normalize-for-errors.next.stderr @@ -7,7 +7,7 @@ LL | LL | impl MyTrait for (Box<<(MyType,) as Mirror>::Assoc>, S::Item) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(Box<(MyType,)>, <_ as Iterator>::Item)` | - = note: upstream crates may add a new impl of trait `std::clone::Clone` for type `(MyType,)` in future versions + = note: upstream crates may add a new impl of trait `std::clone::Clone` for type `std::boxed::Box<(MyType,)>` in future versions = note: upstream crates may add a new impl of trait `std::marker::Copy` for type `std::boxed::Box<(MyType,)>` in future versions error: aborting due to 1 previous error diff --git a/tests/ui/coherence/normalize-for-errors.rs b/tests/ui/coherence/normalize-for-errors.rs index 4188389a3ad5b..c17bb766b5bcd 100644 --- a/tests/ui/coherence/normalize-for-errors.rs +++ b/tests/ui/coherence/normalize-for-errors.rs @@ -18,6 +18,6 @@ impl MyTrait for (Box<<(MyType,) as Mirror>::Assoc>, S::Item) {} //~^ ERROR conflicting implementations of trait `MyTrait<_>` for type `(Box<(MyType,)>, //~| NOTE conflicting implementation for `(Box<(MyType,)>, //~| NOTE upstream crates may add a new impl of trait `std::marker::Copy` for type `std::boxed::Box<(MyType,)>` in future versions -//[next]~| NOTE upstream crates may add a new impl of trait `std::clone::Clone` for type `(MyType,)` in future versions +//[next]~| NOTE upstream crates may add a new impl of trait `std::clone::Clone` for type `std::boxed::Box<(MyType,)>` in future versions fn main() {} From 6f435cb07f647f41136af6c175dd6964dd7142b4 Mon Sep 17 00:00:00 2001 From: Jan Sommer Date: Mon, 21 Aug 2023 19:03:17 +0200 Subject: [PATCH 0430/2194] Port std library to RTEMS --- library/core/Cargo.toml | 2 + library/core/src/ffi/mod.rs | 2 +- library/panic_unwind/Cargo.toml | 7 + library/panic_unwind/src/lib.rs | 2 +- library/std/Cargo.toml | 2 + library/std/build.rs | 1 + library/std/src/os/mod.rs | 2 + library/std/src/os/rtems/fs.rs | 374 ++++++++++++++++++ library/std/src/os/rtems/mod.rs | 4 + library/std/src/os/rtems/raw.rs | 33 ++ library/std/src/os/unix/mod.rs | 2 + library/std/src/sys/pal/unix/args.rs | 1 + library/std/src/sys/pal/unix/env.rs | 11 + library/std/src/sys/pal/unix/fs.rs | 18 +- library/std/src/sys/pal/unix/mod.rs | 1 + library/std/src/sys/pal/unix/os.rs | 19 +- .../src/sys/pal/unix/process/process_unix.rs | 6 +- library/std/src/sys/personality/mod.rs | 2 +- library/unwind/Cargo.toml | 7 + library/unwind/src/lib.rs | 1 + src/bootstrap/src/core/sanity.rs | 1 + tests/ui/check-cfg/well-known-values.stderr | 4 +- 22 files changed, 488 insertions(+), 14 deletions(-) create mode 100644 library/std/src/os/rtems/fs.rs create mode 100644 library/std/src/os/rtems/mod.rs create mode 100644 library/std/src/os/rtems/raw.rs diff --git a/library/core/Cargo.toml b/library/core/Cargo.toml index cace4582b489a..94f343d06705e 100644 --- a/library/core/Cargo.toml +++ b/library/core/Cargo.toml @@ -43,6 +43,8 @@ check-cfg = [ 'cfg(bootstrap)', 'cfg(no_fp_fmt_parse)', 'cfg(stdarch_intel_sde)', + # #[cfg(bootstrap)] rtems + 'cfg(target_os, values("rtems"))', # core use #[path] imports to portable-simd `core_simd` crate # and to stdarch `core_arch` crate which messes-up with Cargo list # of declared features, we therefor expect any feature cfg diff --git a/library/core/src/ffi/mod.rs b/library/core/src/ffi/mod.rs index ec1f9052a1564..dc107c5d22cdd 100644 --- a/library/core/src/ffi/mod.rs +++ b/library/core/src/ffi/mod.rs @@ -110,7 +110,7 @@ mod c_char_definition { all(target_os = "android", any(target_arch = "aarch64", target_arch = "arm")), all(target_os = "l4re", target_arch = "x86_64"), all( - any(target_os = "freebsd", target_os = "openbsd"), + any(target_os = "freebsd", target_os = "openbsd", target_os = "rtems"), any( target_arch = "aarch64", target_arch = "arm", diff --git a/library/panic_unwind/Cargo.toml b/library/panic_unwind/Cargo.toml index f830808d19648..6d1f9764efbfd 100644 --- a/library/panic_unwind/Cargo.toml +++ b/library/panic_unwind/Cargo.toml @@ -20,3 +20,10 @@ cfg-if = { version = "1.0", features = ['rustc-dep-of-std'] } [target.'cfg(not(all(windows, target_env = "msvc")))'.dependencies] libc = { version = "0.2", default-features = false } + +[lints.rust.unexpected_cfgs] +level = "warn" +check-cfg = [ + # #[cfg(bootstrap)] rtems + 'cfg(target_os, values("rtems"))', +] diff --git a/library/panic_unwind/src/lib.rs b/library/panic_unwind/src/lib.rs index 2d174f4b1a4a2..4552fb68d26d5 100644 --- a/library/panic_unwind/src/lib.rs +++ b/library/panic_unwind/src/lib.rs @@ -48,7 +48,7 @@ cfg_if::cfg_if! { target_os = "psp", target_os = "xous", target_os = "solid_asp3", - all(target_family = "unix", not(target_os = "espidf")), + all(target_family = "unix", not(any(target_os = "espidf", target_os = "rtems"))), all(target_vendor = "fortanix", target_env = "sgx"), target_family = "wasm", ))] { diff --git a/library/std/Cargo.toml b/library/std/Cargo.toml index 82cfd603a21e3..e20fe9feff114 100644 --- a/library/std/Cargo.toml +++ b/library/std/Cargo.toml @@ -146,4 +146,6 @@ check-cfg = [ # and to the `backtrace` crate which messes-up with Cargo list # of declared features, we therefor expect any feature cfg 'cfg(feature, values(any()))', + # #[cfg(bootstrap)] rtems + 'cfg(target_os, values("rtems"))', ] diff --git a/library/std/build.rs b/library/std/build.rs index 72254cafc850d..ba1eece46f3ce 100644 --- a/library/std/build.rs +++ b/library/std/build.rs @@ -53,6 +53,7 @@ fn main() { || target_os == "uefi" || target_os == "teeos" || target_os == "zkvm" + || target_os == "rtems" // See src/bootstrap/src/core/build_steps/synthetic_targets.rs || env::var("RUSTC_BOOTSTRAP_SYNTHETIC_TARGET").is_ok() diff --git a/library/std/src/os/mod.rs b/library/std/src/os/mod.rs index 020a8b324f410..a2496baa63fb1 100644 --- a/library/std/src/os/mod.rs +++ b/library/std/src/os/mod.rs @@ -143,6 +143,8 @@ pub mod nto; pub mod openbsd; #[cfg(target_os = "redox")] pub mod redox; +#[cfg(target_os = "rtems")] +pub mod rtems; #[cfg(target_os = "solaris")] pub mod solaris; #[cfg(target_os = "solid_asp3")] diff --git a/library/std/src/os/rtems/fs.rs b/library/std/src/os/rtems/fs.rs new file mode 100644 index 0000000000000..bec0d41e42d81 --- /dev/null +++ b/library/std/src/os/rtems/fs.rs @@ -0,0 +1,374 @@ +#![stable(feature = "metadata_ext", since = "1.1.0")] + +use crate::fs::Metadata; +use crate::sys_common::AsInner; + +/// OS-specific extensions to [`fs::Metadata`]. +/// +/// [`fs::Metadata`]: crate::fs::Metadata +#[stable(feature = "metadata_ext", since = "1.1.0")] +pub trait MetadataExt { + /// Returns the device ID on which this file resides. + /// + /// # Examples + /// + /// ```no_run + /// use std::fs; + /// use std::io; + /// use std::os::rtems::fs::MetadataExt; + /// + /// fn main() -> io::Result<()> { + /// let meta = fs::metadata("some_file")?; + /// println!("{}", meta.st_dev()); + /// Ok(()) + /// } + /// ``` + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_dev(&self) -> u64; + + /// Returns the inode number. + /// + /// # Examples + /// + /// ```no_run + /// use std::fs; + /// use std::io; + /// use std::os::rtems::fs::MetadataExt; + /// + /// fn main() -> io::Result<()> { + /// let meta = fs::metadata("some_file")?; + /// println!("{}", meta.st_ino()); + /// Ok(()) + /// } + /// ``` + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_ino(&self) -> u64; + + /// Returns the file type and mode. + /// + /// # Examples + /// + /// ```no_run + /// use std::fs; + /// use std::io; + /// use std::os::rtems::fs::MetadataExt; + /// + /// fn main() -> io::Result<()> { + /// let meta = fs::metadata("some_file")?; + /// println!("{}", meta.st_mode()); + /// Ok(()) + /// } + /// ``` + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_mode(&self) -> u32; + + /// Returns the number of hard links to file. + /// + /// # Examples + /// + /// ```no_run + /// use std::fs; + /// use std::io; + /// use std::os::rtems::fs::MetadataExt; + /// + /// fn main() -> io::Result<()> { + /// let meta = fs::metadata("some_file")?; + /// println!("{}", meta.st_nlink()); + /// Ok(()) + /// } + /// ``` + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_nlink(&self) -> u64; + + /// Returns the user ID of the file owner. + /// + /// # Examples + /// + /// ```no_run + /// use std::fs; + /// use std::io; + /// use std::os::rtems::fs::MetadataExt; + /// + /// fn main() -> io::Result<()> { + /// let meta = fs::metadata("some_file")?; + /// println!("{}", meta.st_uid()); + /// Ok(()) + /// } + /// ``` + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_uid(&self) -> u32; + + /// Returns the group ID of the file owner. + /// + /// # Examples + /// + /// ```no_run + /// use std::fs; + /// use std::io; + /// use std::os::rtems::fs::MetadataExt; + /// + /// fn main() -> io::Result<()> { + /// let meta = fs::metadata("some_file")?; + /// println!("{}", meta.st_gid()); + /// Ok(()) + /// } + /// ``` + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_gid(&self) -> u32; + + /// Returns the device ID that this file represents. Only relevant for special file. + /// + /// # Examples + /// + /// ```no_run + /// use std::fs; + /// use std::io; + /// use std::os::rtems::fs::MetadataExt; + /// + /// fn main() -> io::Result<()> { + /// let meta = fs::metadata("some_file")?; + /// println!("{}", meta.st_rdev()); + /// Ok(()) + /// } + /// ``` + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_rdev(&self) -> u64; + + /// Returns the size of the file (if it is a regular file or a symbolic link) in bytes. + /// + /// The size of a symbolic link is the length of the pathname it contains, + /// without a terminating null byte. + /// + /// # Examples + /// + /// ```no_run + /// use std::fs; + /// use std::io; + /// use std::os::rtems::fs::MetadataExt; + /// + /// fn main() -> io::Result<()> { + /// let meta = fs::metadata("some_file")?; + /// println!("{}", meta.st_size()); + /// Ok(()) + /// } + /// ``` + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_size(&self) -> u64; + + /// Returns the last access time of the file, in seconds since Unix Epoch. + /// + /// # Examples + /// + /// ```no_run + /// use std::fs; + /// use std::io; + /// use std::os::rtems::fs::MetadataExt; + /// + /// fn main() -> io::Result<()> { + /// let meta = fs::metadata("some_file")?; + /// println!("{}", meta.st_atime()); + /// Ok(()) + /// } + /// ``` + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_atime(&self) -> i64; + + /// Returns the last access time of the file, in nanoseconds since [`st_atime`]. + /// + /// [`st_atime`]: Self::st_atime + /// + /// # Examples + /// + /// ```no_run + /// use std::fs; + /// use std::io; + /// use std::os::rtems::fs::MetadataExt; + /// + /// fn main() -> io::Result<()> { + /// let meta = fs::metadata("some_file")?; + /// println!("{}", meta.st_atime_nsec()); + /// Ok(()) + /// } + /// ``` + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_atime_nsec(&self) -> i64; + + /// Returns the last modification time of the file, in seconds since Unix Epoch. + /// + /// # Examples + /// + /// ```no_run + /// use std::fs; + /// use std::io; + /// use std::os::rtems::fs::MetadataExt; + /// + /// fn main() -> io::Result<()> { + /// let meta = fs::metadata("some_file")?; + /// println!("{}", meta.st_mtime()); + /// Ok(()) + /// } + /// ``` + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_mtime(&self) -> i64; + + /// Returns the last modification time of the file, in nanoseconds since [`st_mtime`]. + /// + /// [`st_mtime`]: Self::st_mtime + /// + /// # Examples + /// + /// ```no_run + /// use std::fs; + /// use std::io; + /// use std::os::rtems::fs::MetadataExt; + /// + /// fn main() -> io::Result<()> { + /// let meta = fs::metadata("some_file")?; + /// println!("{}", meta.st_mtime_nsec()); + /// Ok(()) + /// } + /// ``` + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_mtime_nsec(&self) -> i64; + + /// Returns the last status change time of the file, in seconds since Unix Epoch. + /// + /// # Examples + /// + /// ```no_run + /// use std::fs; + /// use std::io; + /// use std::os::rtems::fs::MetadataExt; + /// + /// fn main() -> io::Result<()> { + /// let meta = fs::metadata("some_file")?; + /// println!("{}", meta.st_ctime()); + /// Ok(()) + /// } + /// ``` + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_ctime(&self) -> i64; + + /// Returns the last status change time of the file, in nanoseconds since [`st_ctime`]. + /// + /// [`st_ctime`]: Self::st_ctime + /// + /// # Examples + /// + /// ```no_run + /// use std::fs; + /// use std::io; + /// use std::os::rtems::fs::MetadataExt; + /// + /// fn main() -> io::Result<()> { + /// let meta = fs::metadata("some_file")?; + /// println!("{}", meta.st_ctime_nsec()); + /// Ok(()) + /// } + /// ``` + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_ctime_nsec(&self) -> i64; + + /// Returns the "preferred" block size for efficient filesystem I/O. + /// + /// # Examples + /// + /// ```no_run + /// use std::fs; + /// use std::io; + /// use std::os::rtems::fs::MetadataExt; + /// + /// fn main() -> io::Result<()> { + /// let meta = fs::metadata("some_file")?; + /// println!("{}", meta.st_blksize()); + /// Ok(()) + /// } + /// ``` + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_blksize(&self) -> u64; + + /// Returns the number of blocks allocated to the file, 512-byte units. + /// + /// # Examples + /// + /// ```no_run + /// use std::fs; + /// use std::io; + /// use std::os::rtems::fs::MetadataExt; + /// + /// fn main() -> io::Result<()> { + /// let meta = fs::metadata("some_file")?; + /// println!("{}", meta.st_blocks()); + /// Ok(()) + /// } + /// ``` + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_blocks(&self) -> u64; +} + +#[stable(feature = "metadata_ext", since = "1.1.0")] +impl MetadataExt for Metadata { + fn st_dev(&self) -> u64 { + self.as_inner().as_inner().st_dev as u64 + } + + fn st_ino(&self) -> u64 { + self.as_inner().as_inner().st_ino as u64 + } + + fn st_mode(&self) -> u32 { + self.as_inner().as_inner().st_mode as u32 + } + + fn st_nlink(&self) -> u64 { + self.as_inner().as_inner().st_nlink as u64 + } + + fn st_uid(&self) -> u32 { + self.as_inner().as_inner().st_uid as u32 + } + + fn st_gid(&self) -> u32 { + self.as_inner().as_inner().st_gid as u32 + } + + fn st_rdev(&self) -> u64 { + self.as_inner().as_inner().st_rdev as u64 + } + + fn st_size(&self) -> u64 { + self.as_inner().as_inner().st_size as u64 + } + + fn st_atime(&self) -> i64 { + self.as_inner().as_inner().st_atime as i64 + } + + fn st_atime_nsec(&self) -> i64 { + 0 + } + + fn st_mtime(&self) -> i64 { + self.as_inner().as_inner().st_mtime as i64 + } + + fn st_mtime_nsec(&self) -> i64 { + 0 + } + + fn st_ctime(&self) -> i64 { + self.as_inner().as_inner().st_ctime as i64 + } + + fn st_ctime_nsec(&self) -> i64 { + 0 + } + + fn st_blksize(&self) -> u64 { + self.as_inner().as_inner().st_blksize as u64 + } + + fn st_blocks(&self) -> u64 { + self.as_inner().as_inner().st_blocks as u64 + } +} diff --git a/library/std/src/os/rtems/mod.rs b/library/std/src/os/rtems/mod.rs new file mode 100644 index 0000000000000..7275bfd1765d5 --- /dev/null +++ b/library/std/src/os/rtems/mod.rs @@ -0,0 +1,4 @@ +#![stable(feature = "raw_ext", since = "1.1.0")] +#![forbid(unsafe_op_in_unsafe_fn)] +pub mod fs; +pub(crate) mod raw; diff --git a/library/std/src/os/rtems/raw.rs b/library/std/src/os/rtems/raw.rs new file mode 100644 index 0000000000000..113079cf4abdc --- /dev/null +++ b/library/std/src/os/rtems/raw.rs @@ -0,0 +1,33 @@ +//! rtems raw type definitions + +#![stable(feature = "raw_ext", since = "1.1.0")] +#![deprecated( + since = "1.8.0", + note = "these type aliases are no longer supported by \ + the standard library, the `libc` crate on \ + crates.io should be used instead for the correct \ + definitions" +)] +#![allow(deprecated)] + +#[stable(feature = "pthread_t", since = "1.8.0")] +pub type pthread_t = libc::pthread_t; + +#[stable(feature = "raw_ext", since = "1.1.0")] +pub type blkcnt_t = libc::blkcnt_t; + +#[stable(feature = "raw_ext", since = "1.1.0")] +pub type blksize_t = libc::blksize_t; +#[stable(feature = "raw_ext", since = "1.1.0")] +pub type dev_t = libc::dev_t; +#[stable(feature = "raw_ext", since = "1.1.0")] +pub type ino_t = libc::ino_t; +#[stable(feature = "raw_ext", since = "1.1.0")] +pub type mode_t = libc::mode_t; +#[stable(feature = "raw_ext", since = "1.1.0")] +pub type nlink_t = libc::nlink_t; +#[stable(feature = "raw_ext", since = "1.1.0")] +pub type off_t = libc::off_t; + +#[stable(feature = "raw_ext", since = "1.1.0")] +pub type time_t = libc::time_t; diff --git a/library/std/src/os/unix/mod.rs b/library/std/src/os/unix/mod.rs index c6581b9c4c8c8..7d2f0bd4efea7 100644 --- a/library/std/src/os/unix/mod.rs +++ b/library/std/src/os/unix/mod.rs @@ -73,6 +73,8 @@ mod platform { pub use crate::os::openbsd::*; #[cfg(target_os = "redox")] pub use crate::os::redox::*; + #[cfg(target_os = "rtems")] + pub use crate::os::rtems::*; #[cfg(target_os = "solaris")] pub use crate::os::solaris::*; #[cfg(target_os = "vita")] diff --git a/library/std/src/sys/pal/unix/args.rs b/library/std/src/sys/pal/unix/args.rs index 9a37e1a0346d7..a943e3a581a83 100644 --- a/library/std/src/sys/pal/unix/args.rs +++ b/library/std/src/sys/pal/unix/args.rs @@ -112,6 +112,7 @@ impl DoubleEndedIterator for Args { target_os = "aix", target_os = "nto", target_os = "hurd", + target_os = "rtems", ))] mod imp { use crate::ffi::c_char; diff --git a/library/std/src/sys/pal/unix/env.rs b/library/std/src/sys/pal/unix/env.rs index fb1f868644d48..b2d399b8791b5 100644 --- a/library/std/src/sys/pal/unix/env.rs +++ b/library/std/src/sys/pal/unix/env.rs @@ -240,6 +240,17 @@ pub mod os { pub const EXE_EXTENSION: &str = ""; } +#[cfg(target_os = "rtems")] +pub mod os { + pub const FAMILY: &str = "unix"; + pub const OS: &str = "rtems"; + pub const DLL_PREFIX: &str = "lib"; + pub const DLL_SUFFIX: &str = ".so"; + pub const DLL_EXTENSION: &str = "so"; + pub const EXE_SUFFIX: &str = ""; + pub const EXE_EXTENSION: &str = ""; +} + #[cfg(target_os = "vxworks")] pub mod os { pub const FAMILY: &str = "unix"; diff --git a/library/std/src/sys/pal/unix/fs.rs b/library/std/src/sys/pal/unix/fs.rs index 7fa147c9754b9..4ec577a0a01d0 100644 --- a/library/std/src/sys/pal/unix/fs.rs +++ b/library/std/src/sys/pal/unix/fs.rs @@ -478,6 +478,7 @@ impl FileAttr { target_os = "horizon", target_os = "vita", target_os = "hurd", + target_os = "rtems", )))] pub fn modified(&self) -> io::Result { #[cfg(target_pointer_width = "32")] @@ -490,7 +491,12 @@ impl FileAttr { SystemTime::new(self.stat.st_mtime as i64, self.stat.st_mtime_nsec as i64) } - #[cfg(any(target_os = "vxworks", target_os = "espidf", target_os = "vita"))] + #[cfg(any( + target_os = "vxworks", + target_os = "espidf", + target_os = "vita", + target_os = "rtems", + ))] pub fn modified(&self) -> io::Result { SystemTime::new(self.stat.st_mtime as i64, 0) } @@ -506,6 +512,7 @@ impl FileAttr { target_os = "horizon", target_os = "vita", target_os = "hurd", + target_os = "rtems", )))] pub fn accessed(&self) -> io::Result { #[cfg(target_pointer_width = "32")] @@ -518,7 +525,12 @@ impl FileAttr { SystemTime::new(self.stat.st_atime as i64, self.stat.st_atime_nsec as i64) } - #[cfg(any(target_os = "vxworks", target_os = "espidf", target_os = "vita"))] + #[cfg(any( + target_os = "vxworks", + target_os = "espidf", + target_os = "vita", + target_os = "rtems" + ))] pub fn accessed(&self) -> io::Result { SystemTime::new(self.stat.st_atime as i64, 0) } @@ -853,6 +865,7 @@ impl Drop for Dir { target_os = "fuchsia", target_os = "horizon", target_os = "vxworks", + target_os = "rtems", )))] { let fd = unsafe { libc::dirfd(self.0) }; @@ -970,6 +983,7 @@ impl DirEntry { target_os = "aix", target_os = "nto", target_os = "hurd", + target_os = "rtems", target_vendor = "apple", ))] pub fn ino(&self) -> u64 { diff --git a/library/std/src/sys/pal/unix/mod.rs b/library/std/src/sys/pal/unix/mod.rs index ba2f58f9c10bd..e8428eccb1691 100644 --- a/library/std/src/sys/pal/unix/mod.rs +++ b/library/std/src/sys/pal/unix/mod.rs @@ -79,6 +79,7 @@ pub unsafe fn init(argc: isize, argv: *const *const u8, sigpipe: u8) { target_os = "l4re", target_os = "horizon", target_os = "vita", + target_os = "rtems", // The poll on Darwin doesn't set POLLNVAL for closed fds. target_vendor = "apple", )))] diff --git a/library/std/src/sys/pal/unix/os.rs b/library/std/src/sys/pal/unix/os.rs index a785b97ac8dc5..503f8915256ee 100644 --- a/library/std/src/sys/pal/unix/os.rs +++ b/library/std/src/sys/pal/unix/os.rs @@ -31,7 +31,7 @@ cfg_if::cfg_if! { } extern "C" { - #[cfg(not(any(target_os = "dragonfly", target_os = "vxworks")))] + #[cfg(not(any(target_os = "dragonfly", target_os = "vxworks", target_os = "rtems")))] #[cfg_attr( any( target_os = "linux", @@ -61,13 +61,14 @@ extern "C" { } /// Returns the platform-specific value of errno -#[cfg(not(any(target_os = "dragonfly", target_os = "vxworks")))] +#[cfg(not(any(target_os = "dragonfly", target_os = "vxworks", target_os = "rtems")))] pub fn errno() -> i32 { unsafe { (*errno_location()) as i32 } } /// Sets the platform-specific value of errno -#[cfg(all(not(target_os = "dragonfly"), not(target_os = "vxworks")))] // needed for readdir and syscall! +// needed for readdir and syscall! +#[cfg(all(not(target_os = "dragonfly"), not(target_os = "vxworks"), not(target_os = "rtems")))] #[allow(dead_code)] // but not all target cfgs actually end up using it pub fn set_errno(e: i32) { unsafe { *errno_location() = e as c_int } @@ -78,6 +79,16 @@ pub fn errno() -> i32 { unsafe { libc::errnoGet() } } +#[cfg(target_os = "rtems")] +pub fn errno() -> i32 { + extern "C" { + #[thread_local] + static _tls_errno: c_int; + } + + unsafe { _tls_errno as i32 } +} + #[cfg(target_os = "dragonfly")] pub fn errno() -> i32 { extern "C" { @@ -472,7 +483,7 @@ pub fn current_exe() -> io::Result { } } -#[cfg(target_os = "redox")] +#[cfg(any(target_os = "redox", target_os = "rtems"))] pub fn current_exe() -> io::Result { crate::fs::read_to_string("sys:exe").map(PathBuf::from) } diff --git a/library/std/src/sys/pal/unix/process/process_unix.rs b/library/std/src/sys/pal/unix/process/process_unix.rs index 9d091f033e07f..4bb22f3670978 100644 --- a/library/std/src/sys/pal/unix/process/process_unix.rs +++ b/library/std/src/sys/pal/unix/process/process_unix.rs @@ -1089,13 +1089,13 @@ fn signal_string(signal: i32) -> &'static str { libc::SIGURG => " (SIGURG)", #[cfg(not(target_os = "l4re"))] libc::SIGXCPU => " (SIGXCPU)", - #[cfg(not(target_os = "l4re"))] + #[cfg(not(any(target_os = "l4re", target_os = "rtems")))] libc::SIGXFSZ => " (SIGXFSZ)", - #[cfg(not(target_os = "l4re"))] + #[cfg(not(any(target_os = "l4re", target_os = "rtems")))] libc::SIGVTALRM => " (SIGVTALRM)", #[cfg(not(target_os = "l4re"))] libc::SIGPROF => " (SIGPROF)", - #[cfg(not(target_os = "l4re"))] + #[cfg(not(any(target_os = "l4re", target_os = "rtems")))] libc::SIGWINCH => " (SIGWINCH)", #[cfg(not(any(target_os = "haiku", target_os = "l4re")))] libc::SIGIO => " (SIGIO)", diff --git a/library/std/src/sys/personality/mod.rs b/library/std/src/sys/personality/mod.rs index 1a6ea1dafcb53..68085d026c40a 100644 --- a/library/std/src/sys/personality/mod.rs +++ b/library/std/src/sys/personality/mod.rs @@ -31,7 +31,7 @@ cfg_if::cfg_if! { target_os = "psp", target_os = "xous", target_os = "solid_asp3", - all(target_family = "unix", not(target_os = "espidf"), not(target_os = "l4re")), + all(target_family = "unix", not(target_os = "espidf"), not(target_os = "l4re"), not(target_os = "rtems")), all(target_vendor = "fortanix", target_env = "sgx"), ))] { mod gcc; diff --git a/library/unwind/Cargo.toml b/library/unwind/Cargo.toml index bbd1db8dfa57f..590de31a678ca 100644 --- a/library/unwind/Cargo.toml +++ b/library/unwind/Cargo.toml @@ -34,3 +34,10 @@ llvm-libunwind = [] # If crt-static is enabled, static link to `libunwind.a` provided by system # If crt-static is disabled, dynamic link to `libunwind.so` provided by system system-llvm-libunwind = [] + +[lints.rust.unexpected_cfgs] +level = "warn" +check-cfg = [ + # #[cfg(bootstrap)] rtems + 'cfg(target_os, values("rtems"))', +] diff --git a/library/unwind/src/lib.rs b/library/unwind/src/lib.rs index 250af912e072d..26ed00bfbd53e 100644 --- a/library/unwind/src/lib.rs +++ b/library/unwind/src/lib.rs @@ -22,6 +22,7 @@ cfg_if::cfg_if! { target_os = "l4re", target_os = "none", target_os = "espidf", + target_os = "rtems", ))] { // These "unix" family members do not have unwinder. } else if #[cfg(any( diff --git a/src/bootstrap/src/core/sanity.rs b/src/bootstrap/src/core/sanity.rs index 60ec57d0d443a..50502389b8624 100644 --- a/src/bootstrap/src/core/sanity.rs +++ b/src/bootstrap/src/core/sanity.rs @@ -34,6 +34,7 @@ pub struct Finder { // Targets can be removed from this list once they are present in the stage0 compiler (usually by updating the beta compiler of the bootstrap). const STAGE0_MISSING_TARGETS: &[&str] = &[ // just a dummy comment so the list doesn't get onelined + "armv7-rtems-eabihf", ]; /// Minimum version threshold for libstdc++ required when using prebuilt LLVM diff --git a/tests/ui/check-cfg/well-known-values.stderr b/tests/ui/check-cfg/well-known-values.stderr index 0530e1c34c9af..144a67025b308 100644 --- a/tests/ui/check-cfg/well-known-values.stderr +++ b/tests/ui/check-cfg/well-known-values.stderr @@ -210,7 +210,7 @@ warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` LL | target_os = "_UNEXPECTED_VALUE", | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: expected values for `target_os` are: `aix`, `android`, `cuda`, `dragonfly`, `emscripten`, `espidf`, `freebsd`, `fuchsia`, `haiku`, `hermit`, `horizon`, `hurd`, `illumos`, `ios`, `l4re`, `linux`, `macos`, `netbsd`, `none`, `nto`, `nuttx`, `openbsd`, `psp`, `redox`, `solaris`, `solid_asp3`, `teeos`, `trusty`, `tvos`, `uefi`, `unknown`, `visionos`, `vita`, `vxworks`, `wasi`, `watchos`, `windows`, `xous`, and `zkvm` + = note: expected values for `target_os` are: `aix`, `android`, `cuda`, `dragonfly`, `emscripten`, `espidf`, `freebsd`, `fuchsia`, `haiku`, `hermit`, `horizon`, `hurd`, `illumos`, `ios`, `l4re`, `linux`, `macos`, `netbsd`, `none`, `nto`, `nuttx`, `openbsd`, `psp`, `redox`, `rtems`, `solaris`, `solid_asp3`, `teeos`, `trusty`, `tvos`, `uefi`, `unknown`, `visionos`, `vita`, `vxworks`, `wasi`, `watchos`, `windows`, `xous`, and `zkvm` = note: see for more information about checking conditional configuration warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` @@ -294,7 +294,7 @@ LL | #[cfg(target_os = "linuz")] // testing that we suggest `linux` | | | help: there is a expected value with a similar name: `"linux"` | - = note: expected values for `target_os` are: `aix`, `android`, `cuda`, `dragonfly`, `emscripten`, `espidf`, `freebsd`, `fuchsia`, `haiku`, `hermit`, `horizon`, `hurd`, `illumos`, `ios`, `l4re`, `linux`, `macos`, `netbsd`, `none`, `nto`, `nuttx`, `openbsd`, `psp`, `redox`, `solaris`, `solid_asp3`, `teeos`, `trusty`, `tvos`, `uefi`, `unknown`, `visionos`, `vita`, `vxworks`, `wasi`, `watchos`, `windows`, `xous`, and `zkvm` + = note: expected values for `target_os` are: `aix`, `android`, `cuda`, `dragonfly`, `emscripten`, `espidf`, `freebsd`, `fuchsia`, `haiku`, `hermit`, `horizon`, `hurd`, `illumos`, `ios`, `l4re`, `linux`, `macos`, `netbsd`, `none`, `nto`, `nuttx`, `openbsd`, `psp`, `redox`, `rtems`, `solaris`, `solid_asp3`, `teeos`, `trusty`, `tvos`, `uefi`, `unknown`, `visionos`, `vita`, `vxworks`, `wasi`, `watchos`, `windows`, `xous`, and `zkvm` = note: see for more information about checking conditional configuration warning: 30 warnings emitted From 124454cda84b291c105712c44365a374a16f1119 Mon Sep 17 00:00:00 2001 From: Jan Sommer Date: Tue, 23 Jan 2024 17:57:12 +0100 Subject: [PATCH 0431/2194] rtems: Add spec file for arm_rtems6_eabihf --- compiler/rustc_target/src/spec/mod.rs | 2 ++ .../src/spec/targets/armv7_rtems_eabihf.rs | 35 +++++++++++++++++++ tests/assembly/targets/targets-elf.rs | 3 ++ 3 files changed, 40 insertions(+) create mode 100644 compiler/rustc_target/src/spec/targets/armv7_rtems_eabihf.rs diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index f992ddf841704..1c693a830d509 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -1695,6 +1695,8 @@ supported_targets! { ("armv7r-none-eabihf", armv7r_none_eabihf), ("armv8r-none-eabihf", armv8r_none_eabihf), + ("armv7-rtems-eabihf", armv7_rtems_eabihf), + ("x86_64-pc-solaris", x86_64_pc_solaris), ("sparcv9-sun-solaris", sparcv9_sun_solaris), diff --git a/compiler/rustc_target/src/spec/targets/armv7_rtems_eabihf.rs b/compiler/rustc_target/src/spec/targets/armv7_rtems_eabihf.rs new file mode 100644 index 0000000000000..1edecac095f6f --- /dev/null +++ b/compiler/rustc_target/src/spec/targets/armv7_rtems_eabihf.rs @@ -0,0 +1,35 @@ +use crate::spec::{cvs, Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, TargetOptions}; + +pub(crate) fn target() -> Target { + Target { + llvm_target: "armv7-unknown-none-eabihf".into(), + metadata: crate::spec::TargetMetadata { + description: Some("Armv7 RTEMS (Requires RTEMS toolchain and kernel".into()), + tier: Some(3), + host_tools: Some(false), + std: Some(true), + }, + pointer_width: 32, + data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(), + arch: "arm".into(), + + options: TargetOptions { + os: "rtems".into(), + families: cvs!["unix"], + abi: "eabihf".into(), + linker_flavor: LinkerFlavor::Gnu(Cc::Yes, Lld::No), + linker: None, + relocation_model: RelocModel::Static, + panic_strategy: PanicStrategy::Abort, + features: "+thumb2,+neon,+vfp3".into(), + max_atomic_width: Some(64), + emit_debug_gdb_scripts: false, + // GCC defaults to 8 for arm-none here. + c_enum_min_bits: Some(8), + eh_frame_header: false, + no_default_libraries: false, + env: "newlib".into(), + ..Default::default() + }, + } +} diff --git a/tests/assembly/targets/targets-elf.rs b/tests/assembly/targets/targets-elf.rs index b0c5eec1fe490..c8610e03939da 100644 --- a/tests/assembly/targets/targets-elf.rs +++ b/tests/assembly/targets/targets-elf.rs @@ -129,6 +129,9 @@ //@ revisions: armv7_linux_androideabi //@ [armv7_linux_androideabi] compile-flags: --target armv7-linux-androideabi //@ [armv7_linux_androideabi] needs-llvm-components: arm +//@ revisions: armv7_rtems_eabihf +//@ [armv7_rtems_eabihf] compile-flags: --target armv7-rtems-eabihf +//@ [armv7_rtems_eabihf] needs-llvm-components: arm //@ revisions: armv7_sony_vita_newlibeabihf //@ [armv7_sony_vita_newlibeabihf] compile-flags: --target armv7-sony-vita-newlibeabihf //@ [armv7_sony_vita_newlibeabihf] needs-llvm-components: arm From 6fd358e99d5cae717a19ce4e397f26a82d0cd9ce Mon Sep 17 00:00:00 2001 From: Jan Sommer Date: Wed, 26 Jun 2024 16:23:24 +0200 Subject: [PATCH 0432/2194] Add documentation for target armv7-rtems-eabihf --- src/doc/rustc/src/SUMMARY.md | 1 + src/doc/rustc/src/platform-support.md | 1 + .../platform-support/armv7-rtems-eabihf.md | 52 +++++++++++++++++++ 3 files changed, 54 insertions(+) create mode 100644 src/doc/rustc/src/platform-support/armv7-rtems-eabihf.md diff --git a/src/doc/rustc/src/SUMMARY.md b/src/doc/rustc/src/SUMMARY.md index b3a74a7716bb3..3e199539694ed 100644 --- a/src/doc/rustc/src/SUMMARY.md +++ b/src/doc/rustc/src/SUMMARY.md @@ -40,6 +40,7 @@ - [thumbv8m.base-none-eabi](./platform-support/thumbv8m.base-none-eabi.md) - [thumbv8m.main-none-eabi\*](./platform-support/thumbv8m.main-none-eabi.md) - [armv6k-nintendo-3ds](platform-support/armv6k-nintendo-3ds.md) + - [armv7-rtems-eabihf](platform-support/armv7-rtems-eabihf.md) - [armv7-sony-vita-newlibeabihf](platform-support/armv7-sony-vita-newlibeabihf.md) - [armv7-unknown-linux-uclibceabi](platform-support/armv7-unknown-linux-uclibceabi.md) - [armv7-unknown-linux-uclibceabihf](platform-support/armv7-unknown-linux-uclibceabihf.md) diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md index a2641b227531a..319dc9a7c08cb 100644 --- a/src/doc/rustc/src/platform-support.md +++ b/src/doc/rustc/src/platform-support.md @@ -280,6 +280,7 @@ target | std | host | notes `armv6-unknown-freebsd` | ✓ | ✓ | Armv6 FreeBSD [`armv6-unknown-netbsd-eabihf`](platform-support/netbsd.md) | ✓ | ✓ | Armv6 NetBSD w/hard-float [`armv6k-nintendo-3ds`](platform-support/armv6k-nintendo-3ds.md) | ? | | Armv6k Nintendo 3DS, Horizon (Requires devkitARM toolchain) +[`armv7-rtems-eabihf`](platform-support/armv7-rtems-eabihf.md) | ? | | RTEMS OS for ARM BSPs [`armv7-sony-vita-newlibeabihf`](platform-support/armv7-sony-vita-newlibeabihf.md) | ✓ | | Armv7-A Cortex-A9 Sony PlayStation Vita (requires VITASDK toolchain) [`armv7-unknown-linux-uclibceabi`](platform-support/armv7-unknown-linux-uclibceabi.md) | ✓ | ✓ | Armv7-A Linux with uClibc, softfloat [`armv7-unknown-linux-uclibceabihf`](platform-support/armv7-unknown-linux-uclibceabihf.md) | ✓ | ? | Armv7-A Linux with uClibc, hardfloat diff --git a/src/doc/rustc/src/platform-support/armv7-rtems-eabihf.md b/src/doc/rustc/src/platform-support/armv7-rtems-eabihf.md new file mode 100644 index 0000000000000..2791c21ee453b --- /dev/null +++ b/src/doc/rustc/src/platform-support/armv7-rtems-eabihf.md @@ -0,0 +1,52 @@ +# `armv7-rtems-eabihf` + +**Tier: 3** + +ARM targets for the [RTEMS realtime operating system](https://www.rtems.org) using the RTEMS gcc cross-compiler for linking against the libraries of a specified Board Support Package (BSP). + +## Target maintainers + +- [@thesummer](https://github.com/thesummer) + +## Requirements + +The target does not support host tools. Only cross-compilation is possible. +The cross-compiler toolchain can be obtained by following the installation instructions +of the [RTEMS Documentation](https://docs.rtems.org/branches/master/user/index.html). Additionally to the cross-compiler also a compiled BSP +for a board fitting the architecture needs to be available on the host. +Currently tested has been the BSP `xilinx_zynq_a9_qemu` of RTEMS 6. + +`std` support is available, but not yet fully tested. Do NOT use in flight software! + +The target follows the EABI calling convention for `extern "C"`. + +The resulting binaries are in ELF format. + +## Building the target + +The target can be built by the standard compiler of Rust. + +## Building Rust programs + +Rust does not yet ship pre-compiled artifacts for this target. To compile for +this target, you will either need to build Rust with the target enabled (see +"Building the target" above), or build your own copy of `core` by using +`build-std` or similar. + +In order to build an RTEMS executable it is also necessary to have a basic RTEMS configuration (in C) compiled to link against as this configures the operating system. +An example can be found at this [`rtems-sys`](https://github.com/thesummer/rtems-sys) crate which could be added as an dependency to your application. + +## Testing + +The resulting binaries run fine on an emulated target (possibly also on a real Zedboard or similar). +For example, on qemu the following command can execute the binary: +```sh +qemu-system-arm -no-reboot -serial null -serial mon:stdio -net none -nographic -M xilinx-zynq-a9 -m 512M -kernel +``` + +While basic execution of the unit test harness seems to work. However, running the Rust testsuite on the (emulated) hardware has not yet been tested. + +## Cross-compilation toolchains and C code + +Compatible C-code can be built with the RTEMS cross-compiler toolchain `arm-rtems6-gcc`. +For more information how to build the toolchain, RTEMS itself and RTEMS applications please have a look at the [RTEMS Documentation](https://docs.rtems.org/branches/master/user/index.html). From 5c0dfc61822c5844aaa153c9c772633a583ca2a7 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 1 Sep 2024 18:51:23 +0200 Subject: [PATCH 0433/2194] update comment regarding TargetOptions.features --- compiler/rustc_target/src/spec/mod.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index 3766501821957..1cbe5869118e8 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -2097,9 +2097,10 @@ pub struct TargetOptions { /// Default CPU to pass to LLVM. Corresponds to `llc -mcpu=$cpu`. Defaults /// to "generic". pub cpu: StaticCow, - /// Default target features to pass to LLVM. These features will *always* be - /// passed, and cannot be disabled even via `-C`. Corresponds to `llc - /// -mattr=$features`. + /// Default target features to pass to LLVM. These features overwrite + /// `-Ctarget-cpu` but can be overwritten with `-Ctarget-features`. + /// Corresponds to `llc -mattr=$features`. + /// Note that these are LLVM feature names, not Rust feature names! pub features: StaticCow, /// Direct or use GOT indirect to reference external data symbols pub direct_access_external_data: Option, From aa1f60ecff4060c3c1a76102310af5369460c03d Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 3 Sep 2024 09:41:41 +0200 Subject: [PATCH 0434/2194] rustc_driver_impl: remove some old dead logic --- compiler/rustc_driver_impl/src/lib.rs | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index e49ae60e890ba..cb2fa6e9d746b 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -61,7 +61,6 @@ use rustc_session::lint::{Lint, LintId}; use rustc_session::output::collect_crate_types; use rustc_session::{config, filesearch, EarlyDiagCtxt, Session}; use rustc_span::source_map::FileLoader; -use rustc_span::symbol::sym; use rustc_span::FileName; use rustc_target::json::ToJson; use rustc_target::spec::{Target, TargetTriple}; @@ -777,16 +776,8 @@ fn print_crate_info( .config .iter() .filter_map(|&(name, value)| { - // Note that crt-static is a specially recognized cfg - // directive that's printed out here as part of - // rust-lang/rust#37406, but in general the - // `target_feature` cfg is gated under - // rust-lang/rust#29717. For now this is just - // specifically allowing the crt-static cfg and that's - // it, this is intended to get into Cargo and then go - // through to build scripts. - if (name != sym::target_feature || value != Some(sym::crt_dash_static)) - && !sess.is_nightly_build() + // On stable, exclude unstable flags. + if !sess.is_nightly_build() && find_gated_cfg(|cfg_sym| cfg_sym == name).is_some() { return None; From 17e5f01d2b871440f5f35b3faec1fcdc8cca6fa0 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Tue, 3 Sep 2024 11:54:33 +0200 Subject: [PATCH 0435/2194] Bump smol_str --- src/tools/rust-analyzer/Cargo.lock | 22 +++++++++++++++++++--- src/tools/rust-analyzer/Cargo.toml | 2 +- 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/src/tools/rust-analyzer/Cargo.lock b/src/tools/rust-analyzer/Cargo.lock index 8733508be746b..6eaded6da14ab 100644 --- a/src/tools/rust-analyzer/Cargo.lock +++ b/src/tools/rust-analyzer/Cargo.lock @@ -96,6 +96,15 @@ version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" +[[package]] +name = "borsh" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6362ed55def622cddc70a4746a68554d7b687713770de539e59a739b249f8ed" +dependencies = [ + "cfg_aliases 0.2.1", +] + [[package]] name = "byteorder" version = "1.5.0" @@ -167,6 +176,12 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e" +[[package]] +name = "cfg_aliases" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" + [[package]] name = "chalk-derive" version = "0.98.0" @@ -1114,7 +1129,7 @@ checksum = "ab2156c4fce2f8df6c499cc1c763e4394b7482525bf2a9701c9d79d215f519e4" dependencies = [ "bitflags 2.6.0", "cfg-if", - "cfg_aliases", + "cfg_aliases 0.1.1", "libc", ] @@ -1844,10 +1859,11 @@ checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" [[package]] name = "smol_str" -version = "0.2.2" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd538fb6910ac1099850255cf94a94df6551fbdd602454387d0adb2d1ca6dead" +checksum = "66eaf762c5af19db3108300515c8aa7a50efc90ff745f4c62288052ebf9fdd25" dependencies = [ + "borsh", "serde", ] diff --git a/src/tools/rust-analyzer/Cargo.toml b/src/tools/rust-analyzer/Cargo.toml index aa7bd2dc5fe8b..e55628c8dcf4c 100644 --- a/src/tools/rust-analyzer/Cargo.toml +++ b/src/tools/rust-analyzer/Cargo.toml @@ -145,7 +145,7 @@ smallvec = { version = "1.10.0", features = [ "union", "const_generics", ] } -smol_str = "0.2.1" +smol_str = "0.3.1" snap = "1.1.0" text-size = "1.1.1" tracing = "0.1.40" From df38e644ce24510f948fff3a0977087155ac4b08 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 3 Sep 2024 10:49:16 +0200 Subject: [PATCH 0436/2194] deprecate -Csoft-float because it is unsound (and not fixable) --- compiler/rustc_codegen_llvm/src/back/write.rs | 8 +++++++- compiler/rustc_session/messages.ftl | 10 ++++++++++ compiler/rustc_session/src/errors.rs | 11 +++++++++++ compiler/rustc_session/src/options.rs | 2 +- compiler/rustc_session/src/session.rs | 10 ++++++++++ 5 files changed, 39 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/back/write.rs b/compiler/rustc_codegen_llvm/src/back/write.rs index a5c27d2282eaf..b1b692cc027b0 100644 --- a/compiler/rustc_codegen_llvm/src/back/write.rs +++ b/compiler/rustc_codegen_llvm/src/back/write.rs @@ -185,7 +185,13 @@ pub(crate) fn target_machine_factory( let reloc_model = to_llvm_relocation_model(sess.relocation_model()); let (opt_level, _) = to_llvm_opt_settings(optlvl); - let use_softfp = sess.opts.cg.soft_float; + let use_softfp = if sess.target.arch == "arm" && sess.target.abi == "eabihf" { + sess.opts.cg.soft_float + } else { + // `validate_commandline_args_with_session_available` has already warned about this being ignored. + // Let's make sure LLVM doesn't suddenly start using this flag on more targets. + false + }; let ffunction_sections = sess.opts.unstable_opts.function_sections.unwrap_or(sess.target.function_sections); diff --git a/compiler/rustc_session/messages.ftl b/compiler/rustc_session/messages.ftl index 01c371ee49884..4477d89299a1d 100644 --- a/compiler/rustc_session/messages.ftl +++ b/compiler/rustc_session/messages.ftl @@ -107,6 +107,16 @@ session_sanitizer_not_supported = {$us} sanitizer is not supported for this targ session_sanitizers_not_supported = {$us} sanitizers are not supported for this target session_skipping_const_checks = skipping const checks + +session_soft_float_deprecated = + `-Csoft-float` is unsound and deprecated; use a corresponding *eabi target instead + .note = it will be removed or ignored in a future version of Rust +session_soft_float_deprecated_issue = see issue #129893 for more information + +session_soft_float_ignored = + `-Csoft-float` is ignored on this target; it only has an effect on *eabihf targets + .note = this may become a hard error in a future version of Rust + session_split_debuginfo_unstable_platform = `-Csplit-debuginfo={$debuginfo}` is unstable on this platform session_split_lto_unit_requires_lto = `-Zsplit-lto-unit` requires `-Clto`, `-Clto=thin`, or `-Clinker-plugin-lto` diff --git a/compiler/rustc_session/src/errors.rs b/compiler/rustc_session/src/errors.rs index 15bbd4ff7bf4b..8f671183fac7a 100644 --- a/compiler/rustc_session/src/errors.rs +++ b/compiler/rustc_session/src/errors.rs @@ -484,3 +484,14 @@ pub(crate) struct FunctionReturnThunkExternRequiresNonLargeCodeModel; pub(crate) struct FailedToCreateProfiler { pub(crate) err: String, } + +#[derive(Diagnostic)] +#[diag(session_soft_float_ignored)] +#[note] +pub(crate) struct SoftFloatIgnored; + +#[derive(Diagnostic)] +#[diag(session_soft_float_deprecated)] +#[note] +#[note(session_soft_float_deprecated_issue)] +pub(crate) struct SoftFloatDeprecated; diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index 37077901e0c34..4427cf346bb47 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -1615,7 +1615,7 @@ options! { save_temps: bool = (false, parse_bool, [UNTRACKED], "save all temporary output files during compilation (default: no)"), soft_float: bool = (false, parse_bool, [TRACKED], - "use soft float ABI (*eabihf targets only) (default: no)"), + "deprecated option: use soft float ABI (*eabihf targets only) (default: no)"), #[rustc_lint_opt_deny_field_access("use `Session::split_debuginfo` instead of this field")] split_debuginfo: Option = (None, parse_split_debuginfo, [TRACKED], "how to handle split-debuginfo, a platform-specific option"), diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index 70430d82ab55b..9b3348c3969c4 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -1340,6 +1340,16 @@ fn validate_commandline_args_with_session_available(sess: &Session) { } } } + + if sess.opts.cg.soft_float { + if sess.target.arch == "arm" && sess.target.abi == "eabihf" { + sess.dcx().emit_warn(errors::SoftFloatDeprecated); + } else { + // All `use_softfp` does is the equivalent of `-mfloat-abi` in GCC/clang, which only exists on ARM targets. + // We document this flag to only affect `*eabihf` targets, so let's show a warning for all other targets. + sess.dcx().emit_warn(errors::SoftFloatIgnored); + } + } } /// Holds data on the current incremental compilation session, if there is one. From 914d8f4bca7990768ca9b5c8d6227d7177b55b4a Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 3 Sep 2024 12:21:38 +0200 Subject: [PATCH 0437/2194] add rustc_lint_opt_deny_field_access to options that are documented to do nothing --- compiler/rustc_session/src/options.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index 4427cf346bb47..eacdc035957b3 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -1511,6 +1511,7 @@ options! { // - src/doc/rustc/src/codegen-options/index.md // tidy-alphabetical-start + #[rustc_lint_opt_deny_field_access("documented to do nothing")] ar: String = (String::new(), parse_string, [UNTRACKED], "this option is deprecated and does nothing"), #[rustc_lint_opt_deny_field_access("use `Session::code_model` instead of this field")] @@ -1543,6 +1544,7 @@ options! { "force use of unwind tables"), incremental: Option = (None, parse_opt_string, [UNTRACKED], "enable incremental compilation"), + #[rustc_lint_opt_deny_field_access("documented to do nothing")] inline_threshold: Option = (None, parse_opt_number, [TRACKED], "this option is deprecated and does nothing \ (consider using `-Cllvm-args=--inline-threshold=...`)"), @@ -1579,6 +1581,7 @@ options! { "give an empty list of passes to the pass manager"), no_redzone: Option = (None, parse_opt_bool, [TRACKED], "disable the use of the redzone"), + #[rustc_lint_opt_deny_field_access("documented to do nothing")] no_stack_check: bool = (false, parse_no_flag, [UNTRACKED], "this option is deprecated and does nothing"), no_vectorize_loops: bool = (false, parse_no_flag, [TRACKED], From 17f3f92e8b6619f73a92fac95a324bb59b0390bf Mon Sep 17 00:00:00 2001 From: Pietro Albini Date: Tue, 3 Sep 2024 12:42:48 +0200 Subject: [PATCH 0438/2194] include 1.80.1 release notes on master Forgot this during the release process --- RELEASES.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/RELEASES.md b/RELEASES.md index 6aba476103e7f..29c872eb44896 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -112,6 +112,14 @@ tools. - [Add a Rust-for Linux `auto` CI job to check kernel builds.](https://github.com/rust-lang/rust/pull/125209/) +Version 1.80.1 (2024-08-08) +=========================== + + + +- [Fix miscompilation in the jump threading MIR optimization when comparing floats](https://github.com/rust-lang/rust/pull/128271) +- [Revert changes to the `dead_code` lint from 1.80.0](https://github.com/rust-lang/rust/pull/128618) + Version 1.80.0 (2024-07-25) ========================== From 39defb1c9caaa30aa4d3b55dfc35fa648258f3c4 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Tue, 3 Sep 2024 11:01:25 +0000 Subject: [PATCH 0439/2194] Rustup to rustc 1.83.0-nightly (bd53aa3bf 2024-09-02) --- rust-toolchain | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust-toolchain b/rust-toolchain index 2c76d34b65d3c..0ac239c441f02 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1,4 +1,4 @@ [toolchain] -channel = "nightly-2024-08-28" +channel = "nightly-2024-09-03" components = ["rust-src", "rustc-dev", "llvm-tools"] profile = "minimal" From b7ed9ad22674de27c01f3a87120c66a835503af7 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Tue, 3 Sep 2024 11:08:17 +0000 Subject: [PATCH 0440/2194] Remove test exclusion for fixed rustc test --- scripts/test_rustc_tests.sh | 1 - 1 file changed, 1 deletion(-) diff --git a/scripts/test_rustc_tests.sh b/scripts/test_rustc_tests.sh index fcfbaf053deec..046390d458d32 100755 --- a/scripts/test_rustc_tests.sh +++ b/scripts/test_rustc_tests.sh @@ -141,7 +141,6 @@ rm tests/ui/deprecation/deprecated_inline_threshold.rs # missing deprecation war rm tests/ui/process/nofile-limit.rs # TODO some AArch64 linking issue rm tests/ui/backtrace/synchronized-panic-handler.rs # missing needs-unwind annotation rm -r tests/ui/codegen/equal-pointers-unequal # make incorrect assumptions about the location of stack variables -rm -r tests/run-make/libtest-thread-limit # doesn't work with -Zpanic-abort-tests, missing needs-unwind annotation rm tests/ui/stdio-is-blocking.rs # really slow with unoptimized libstd From de96082152a4ecae3273381db9b571ceefa51e83 Mon Sep 17 00:00:00 2001 From: Jesse Rusak Date: Sun, 1 Sep 2024 16:13:58 -0400 Subject: [PATCH 0441/2194] Enable native libraries on macOS Fixes #3595 by using -fvisibility=hidden and the visibility attribute supported by both gcc and clang rather than the previous gcc-only mechanism for symbol hiding. Also brings over cfg changes from #3594 which enable native-lib functionality on all unixes. --- src/tools/miri/Cargo.toml | 2 -- src/tools/miri/README.md | 2 +- src/tools/miri/src/machine.rs | 10 +++++----- src/tools/miri/src/shims/foreign_items.rs | 2 +- src/tools/miri/src/shims/mod.rs | 2 +- .../native-lib/fail/function_not_in_so.rs | 4 +++- .../tests/native-lib/fail/private_function.rs | 15 ++++++++++++++ .../native-lib/fail/private_function.stderr | 15 ++++++++++++++ .../miri/tests/native-lib/native-lib.map | 20 ------------------- .../tests/native-lib/pass/ptr_read_access.rs | 4 +++- .../tests/native-lib/pass/scalar_arguments.rs | 4 +++- .../miri/tests/native-lib/ptr_read_access.c | 11 ++++++---- .../miri/tests/native-lib/scalar_arguments.c | 20 +++++++++++++------ src/tools/miri/tests/ui.rs | 19 +++++++++--------- 14 files changed, 78 insertions(+), 52 deletions(-) create mode 100644 src/tools/miri/tests/native-lib/fail/private_function.rs create mode 100644 src/tools/miri/tests/native-lib/fail/private_function.stderr delete mode 100644 src/tools/miri/tests/native-lib/native-lib.map diff --git a/src/tools/miri/Cargo.toml b/src/tools/miri/Cargo.toml index 4b7f3483ff7db..d8cfa5b886dad 100644 --- a/src/tools/miri/Cargo.toml +++ b/src/tools/miri/Cargo.toml @@ -37,8 +37,6 @@ features = ['unprefixed_malloc_on_supported_platforms'] [target.'cfg(unix)'.dependencies] libc = "0.2" - -[target.'cfg(target_os = "linux")'.dependencies] libffi = "3.2.0" libloading = "0.8" diff --git a/src/tools/miri/README.md b/src/tools/miri/README.md index 5821adb96ce29..dbb0e8a2925b3 100644 --- a/src/tools/miri/README.md +++ b/src/tools/miri/README.md @@ -383,7 +383,7 @@ to Miri failing to detect cases of undefined behavior in a program. file descriptors will be mixed up. This is **work in progress**; currently, only integer arguments and return values are supported (and no, pointer/integer casts to work around this limitation will not work; - they will fail horribly). It also only works on Linux hosts for now. + they will fail horribly). It also only works on Unix hosts for now. * `-Zmiri-measureme=` enables `measureme` profiling for the interpreted program. This can be used to find which parts of your program are executing slowly under Miri. The profile is written out to a file inside a directory called ``, and can be processed diff --git a/src/tools/miri/src/machine.rs b/src/tools/miri/src/machine.rs index 331edf9c7ea31..2cd57e72871ba 100644 --- a/src/tools/miri/src/machine.rs +++ b/src/tools/miri/src/machine.rs @@ -535,9 +535,9 @@ pub struct MiriMachine<'tcx> { pub(crate) basic_block_count: u64, /// Handle of the optional shared object file for native functions. - #[cfg(target_os = "linux")] + #[cfg(unix)] pub native_lib: Option<(libloading::Library, std::path::PathBuf)>, - #[cfg(not(target_os = "linux"))] + #[cfg(not(unix))] pub native_lib: Option, /// Run a garbage collector for BorTags every N basic blocks. @@ -678,7 +678,7 @@ impl<'tcx> MiriMachine<'tcx> { report_progress: config.report_progress, basic_block_count: 0, clock: Clock::new(config.isolated_op == IsolatedOp::Allow), - #[cfg(target_os = "linux")] + #[cfg(unix)] native_lib: config.native_lib.as_ref().map(|lib_file_path| { let target_triple = layout_cx.tcx.sess.opts.target_triple.triple(); // Check if host target == the session target. @@ -700,9 +700,9 @@ impl<'tcx> MiriMachine<'tcx> { lib_file_path.clone(), ) }), - #[cfg(not(target_os = "linux"))] + #[cfg(not(unix))] native_lib: config.native_lib.as_ref().map(|_| { - panic!("loading external .so files is only supported on Linux") + panic!("calling functions from native libraries via FFI is only supported on Unix") }), gc_interval: config.gc_interval, since_gc: 0, diff --git a/src/tools/miri/src/shims/foreign_items.rs b/src/tools/miri/src/shims/foreign_items.rs index d40dbdba80f1e..1b45bc22038b1 100644 --- a/src/tools/miri/src/shims/foreign_items.rs +++ b/src/tools/miri/src/shims/foreign_items.rs @@ -226,7 +226,7 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { let this = self.eval_context_mut(); // First deal with any external C functions in linked .so file. - #[cfg(target_os = "linux")] + #[cfg(unix)] if this.machine.native_lib.as_ref().is_some() { use crate::shims::native_lib::EvalContextExt as _; // An Ok(false) here means that the function being called was not exported diff --git a/src/tools/miri/src/shims/mod.rs b/src/tools/miri/src/shims/mod.rs index 7d5349f26b127..618cf8cf200c1 100644 --- a/src/tools/miri/src/shims/mod.rs +++ b/src/tools/miri/src/shims/mod.rs @@ -2,7 +2,7 @@ mod alloc; mod backtrace; -#[cfg(target_os = "linux")] +#[cfg(unix)] mod native_lib; mod unix; mod wasi; diff --git a/src/tools/miri/tests/native-lib/fail/function_not_in_so.rs b/src/tools/miri/tests/native-lib/fail/function_not_in_so.rs index 3540c75b73a12..c532d05224537 100644 --- a/src/tools/miri/tests/native-lib/fail/function_not_in_so.rs +++ b/src/tools/miri/tests/native-lib/fail/function_not_in_so.rs @@ -1,4 +1,6 @@ -//@only-target-linux +// Only works on Unix targets +//@ignore-target-windows +//@ignore-target-wasm //@only-on-host //@normalize-stderr-test: "OS `.*`" -> "$$OS" diff --git a/src/tools/miri/tests/native-lib/fail/private_function.rs b/src/tools/miri/tests/native-lib/fail/private_function.rs new file mode 100644 index 0000000000000..3c6fda741dd70 --- /dev/null +++ b/src/tools/miri/tests/native-lib/fail/private_function.rs @@ -0,0 +1,15 @@ +// Only works on Unix targets +//@ignore-target-windows +//@ignore-target-wasm +//@only-on-host +//@normalize-stderr-test: "OS `.*`" -> "$$OS" + +extern "C" { + fn not_exported(); +} + +fn main() { + unsafe { + not_exported(); //~ ERROR: unsupported operation: can't call foreign function `not_exported` + } +} diff --git a/src/tools/miri/tests/native-lib/fail/private_function.stderr b/src/tools/miri/tests/native-lib/fail/private_function.stderr new file mode 100644 index 0000000000000..e27a501ebb9d8 --- /dev/null +++ b/src/tools/miri/tests/native-lib/fail/private_function.stderr @@ -0,0 +1,15 @@ +error: unsupported operation: can't call foreign function `not_exported` on $OS + --> $DIR/private_function.rs:LL:CC + | +LL | not_exported(); + | ^^^^^^^^^^^^^^ can't call foreign function `not_exported` on $OS + | + = help: if this is a basic API commonly used on this target, please report an issue with Miri + = help: however, note that Miri does not aim to support every FFI function out there; for instance, we will not support APIs for things such as GUIs, scripting languages, or databases + = note: BACKTRACE: + = note: inside `main` at $DIR/private_function.rs:LL:CC + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to 1 previous error + diff --git a/src/tools/miri/tests/native-lib/native-lib.map b/src/tools/miri/tests/native-lib/native-lib.map deleted file mode 100644 index 7e3bd19622af3..0000000000000 --- a/src/tools/miri/tests/native-lib/native-lib.map +++ /dev/null @@ -1,20 +0,0 @@ -CODEABI_1.0 { - # Define which symbols to export. - global: - # scalar_arguments.c - add_one_int; - printer; - test_stack_spill; - get_unsigned_int; - add_int16; - add_short_to_long; - - # ptr_read_access.c - print_pointer; - access_simple; - access_nested; - access_static; - - # The rest remains private. - local: *; -}; diff --git a/src/tools/miri/tests/native-lib/pass/ptr_read_access.rs b/src/tools/miri/tests/native-lib/pass/ptr_read_access.rs index 77a73deddedb8..2990dfa89756c 100644 --- a/src/tools/miri/tests/native-lib/pass/ptr_read_access.rs +++ b/src/tools/miri/tests/native-lib/pass/ptr_read_access.rs @@ -1,4 +1,6 @@ -//@only-target-linux +// Only works on Unix targets +//@ignore-target-windows +//@ignore-target-wasm //@only-on-host fn main() { diff --git a/src/tools/miri/tests/native-lib/pass/scalar_arguments.rs b/src/tools/miri/tests/native-lib/pass/scalar_arguments.rs index 1e1d0b11e99ff..378baa7ce98de 100644 --- a/src/tools/miri/tests/native-lib/pass/scalar_arguments.rs +++ b/src/tools/miri/tests/native-lib/pass/scalar_arguments.rs @@ -1,4 +1,6 @@ -//@only-target-linux +// Only works on Unix targets +//@ignore-target-windows +//@ignore-target-wasm //@only-on-host extern "C" { diff --git a/src/tools/miri/tests/native-lib/ptr_read_access.c b/src/tools/miri/tests/native-lib/ptr_read_access.c index 03b9189e2e86d..540845d53a744 100644 --- a/src/tools/miri/tests/native-lib/ptr_read_access.c +++ b/src/tools/miri/tests/native-lib/ptr_read_access.c @@ -1,8 +1,11 @@ #include +// See comments in build_native_lib() +#define EXPORT __attribute__((visibility("default"))) + /* Test: test_pointer */ -void print_pointer(const int *ptr) { +EXPORT void print_pointer(const int *ptr) { printf("printing pointer dereference from C: %d\n", *ptr); } @@ -12,7 +15,7 @@ typedef struct Simple { int field; } Simple; -int access_simple(const Simple *s_ptr) { +EXPORT int access_simple(const Simple *s_ptr) { return s_ptr->field; } @@ -24,7 +27,7 @@ typedef struct Nested { } Nested; // Returns the innermost/last value of a Nested pointer chain. -int access_nested(const Nested *n_ptr) { +EXPORT int access_nested(const Nested *n_ptr) { // Edge case: `n_ptr == NULL` (i.e. first Nested is None). if (!n_ptr) { return 0; } @@ -42,6 +45,6 @@ typedef struct Static { struct Static *recurse; } Static; -int access_static(const Static *s_ptr) { +EXPORT int access_static(const Static *s_ptr) { return s_ptr->recurse->recurse->value; } diff --git a/src/tools/miri/tests/native-lib/scalar_arguments.c b/src/tools/miri/tests/native-lib/scalar_arguments.c index 68714f1743b6e..6da730a498724 100644 --- a/src/tools/miri/tests/native-lib/scalar_arguments.c +++ b/src/tools/miri/tests/native-lib/scalar_arguments.c @@ -1,27 +1,35 @@ #include -int add_one_int(int x) { +// See comments in build_native_lib() +#define EXPORT __attribute__((visibility("default"))) + +EXPORT int add_one_int(int x) { return 2 + x; } -void printer() { +EXPORT void printer(void) { printf("printing from C\n"); } // function with many arguments, to test functionality when some args are stored // on the stack -int test_stack_spill(int a, int b, int c, int d, int e, int f, int g, int h, int i, int j, int k, int l) { +EXPORT int test_stack_spill(int a, int b, int c, int d, int e, int f, int g, int h, int i, int j, int k, int l) { return a+b+c+d+e+f+g+h+i+j+k+l; } -unsigned int get_unsigned_int() { +EXPORT unsigned int get_unsigned_int(void) { return -10; } -short add_int16(short x) { +EXPORT short add_int16(short x) { return x + 3; } -long add_short_to_long(short x, long y) { +EXPORT long add_short_to_long(short x, long y) { return x + y; } + +// To test that functions not marked with EXPORT cannot be called by Miri. +int not_exported(void) { + return 0; +} diff --git a/src/tools/miri/tests/ui.rs b/src/tools/miri/tests/ui.rs index c510ef95c30e8..e62394bc499f1 100644 --- a/src/tools/miri/tests/ui.rs +++ b/src/tools/miri/tests/ui.rs @@ -36,20 +36,21 @@ fn build_native_lib() -> PathBuf { // Create the directory if it does not already exist. std::fs::create_dir_all(&so_target_dir) .expect("Failed to create directory for shared object file"); - let so_file_path = so_target_dir.join("native-lib.so"); + // We use a platform-neutral file extension to avoid having to hard-code alternatives. + let native_lib_path = so_target_dir.join("native-lib.module"); let cc_output = Command::new(cc) .args([ "-shared", + "-fPIC", + // We hide all symbols by default and export just the ones we need + // This is to future-proof against a more complex shared object which eg defines its own malloc + // (but we wouldn't want miri to call that, as it would if it was exported). + "-fvisibility=hidden", "-o", - so_file_path.to_str().unwrap(), + native_lib_path.to_str().unwrap(), // FIXME: Automate gathering of all relevant C source files in the directory. "tests/native-lib/scalar_arguments.c", "tests/native-lib/ptr_read_access.c", - // Only add the functions specified in libcode.version to the shared object file. - // This is to avoid automatically adding `malloc`, etc. - // Source: https://anadoxin.org/blog/control-over-symbol-exports-in-gcc.html/ - "-fPIC", - "-Wl,--version-script=tests/native-lib/native-lib.map", // Ensure we notice serious problems in the C code. "-Wall", "-Wextra", @@ -64,7 +65,7 @@ fn build_native_lib() -> PathBuf { String::from_utf8_lossy(&cc_output.stderr), ); } - so_file_path + native_lib_path } /// Does *not* set any args or env vars, since it is shared between the test runner and @@ -300,7 +301,7 @@ fn main() -> Result<()> { WithDependencies, tmpdir.path(), )?; - if cfg!(target_os = "linux") { + if cfg!(unix) { ui(Mode::Pass, "tests/native-lib/pass", &target, WithoutDependencies, tmpdir.path())?; ui( Mode::Fail { require_patterns: true, rustfix: RustfixMode::Disabled }, From c811d3126f87930b3de3c9e5e7b8d37e9d9d0cae Mon Sep 17 00:00:00 2001 From: Chris Denton Date: Thu, 18 Jul 2024 14:35:01 +0000 Subject: [PATCH 0442/2194] More robust extension checking --- library/std/src/sys/pal/windows/mod.rs | 2 +- library/std/src/sys/pal/windows/process.rs | 23 +++++++++++++++++----- library/std/src/sys/path/windows.rs | 5 +++++ tests/ui/std/windows-bat-args.rs | 4 +++- 4 files changed, 27 insertions(+), 7 deletions(-) diff --git a/library/std/src/sys/pal/windows/mod.rs b/library/std/src/sys/pal/windows/mod.rs index 272fadd915005..1cc9a2b7ffa98 100644 --- a/library/std/src/sys/pal/windows/mod.rs +++ b/library/std/src/sys/pal/windows/mod.rs @@ -13,7 +13,7 @@ use crate::time::Duration; #[macro_use] pub mod compat; -mod api; +pub mod api; pub mod args; pub mod c; diff --git a/library/std/src/sys/pal/windows/process.rs b/library/std/src/sys/pal/windows/process.rs index 06eae5a07b068..d40a537e3594a 100644 --- a/library/std/src/sys/pal/windows/process.rs +++ b/library/std/src/sys/pal/windows/process.rs @@ -272,11 +272,24 @@ impl Command { None }; let program = resolve_exe(&self.program, || env::var_os("PATH"), child_paths)?; - // Case insensitive "ends_with" of UTF-16 encoded ".bat" or ".cmd" - let is_batch_file = matches!( - program.len().checked_sub(5).and_then(|i| program.get(i..)), - Some([46, 98 | 66, 97 | 65, 116 | 84, 0] | [46, 99 | 67, 109 | 77, 100 | 68, 0]) - ); + let has_bat_extension = |program: &[u16]| { + matches!( + // Case insensitive "ends_with" of UTF-16 encoded ".bat" or ".cmd" + program.len().checked_sub(4).and_then(|i| program.get(i..)), + Some([46, 98 | 66, 97 | 65, 116 | 84] | [46, 99 | 67, 109 | 77, 100 | 68]) + ) + }; + let is_batch_file = if path::is_verbatim(&program) { + has_bat_extension(&program[..program.len() - 1]) + } else { + super::fill_utf16_buf( + |buffer, size| unsafe { + // resolve the path so we can test the final file name. + c::GetFullPathNameW(program.as_ptr(), size, buffer, ptr::null_mut()) + }, + |program| has_bat_extension(program), + )? + }; let (program, mut cmd_str) = if is_batch_file { ( command_prompt()?, diff --git a/library/std/src/sys/path/windows.rs b/library/std/src/sys/path/windows.rs index 21841eb18cc0e..2ae9a0a91996f 100644 --- a/library/std/src/sys/path/windows.rs +++ b/library/std/src/sys/path/windows.rs @@ -1,5 +1,6 @@ use crate::ffi::{OsStr, OsString}; use crate::path::{Path, PathBuf, Prefix}; +use crate::sys::api::utf16; use crate::sys::pal::{c, fill_utf16_buf, os2path, to_u16s}; use crate::{io, ptr}; @@ -19,6 +20,10 @@ pub fn is_verbatim_sep(b: u8) -> bool { b == b'\\' } +pub fn is_verbatim(path: &[u16]) -> bool { + path.starts_with(utf16!(r"\\?\")) || path.starts_with(utf16!(r"\??\")) +} + /// Returns true if `path` looks like a lone filename. pub(crate) fn is_file_name(path: &OsStr) -> bool { !path.as_encoded_bytes().iter().copied().any(is_sep_byte) diff --git a/tests/ui/std/windows-bat-args.rs b/tests/ui/std/windows-bat-args.rs index a9b6252b78c85..cc4a43692abd8 100644 --- a/tests/ui/std/windows-bat-args.rs +++ b/tests/ui/std/windows-bat-args.rs @@ -32,7 +32,9 @@ fn parent() { let bat2 = String::from(bat.to_str().unwrap()); bat.set_file_name("windows-bat-args3.bat"); let bat3 = String::from(bat.to_str().unwrap()); - let bat = [bat1.as_str(), bat2.as_str(), bat3.as_str()]; + bat.set_file_name("windows-bat-args1.bat .. "); + let bat4 = String::from(bat.to_str().unwrap()); + let bat = [bat1.as_str(), bat2.as_str(), bat3.as_str(), bat4.as_str()]; check_args(&bat, &["a", "b"]).unwrap(); check_args(&bat, &["c is for cat", "d is for dog"]).unwrap(); From 59885f5065c95d52497220668debf76b4ad1cd0a Mon Sep 17 00:00:00 2001 From: Bryanskiy Date: Mon, 26 Aug 2024 16:18:05 +0300 Subject: [PATCH 0443/2194] Delegation refactoring: add builders for generics inheritance --- compiler/rustc_hir_analysis/src/delegation.rs | 264 ++++++++++++------ .../{not-supported.rs => unsupported.rs} | 0 ...ot-supported.stderr => unsupported.stderr} | 60 ++-- 3 files changed, 214 insertions(+), 110 deletions(-) rename tests/ui/delegation/{not-supported.rs => unsupported.rs} (100%) rename tests/ui/delegation/{not-supported.stderr => unsupported.stderr} (83%) diff --git a/compiler/rustc_hir_analysis/src/delegation.rs b/compiler/rustc_hir_analysis/src/delegation.rs index 20aaa43219f34..d7a0698b6b3fb 100644 --- a/compiler/rustc_hir_analysis/src/delegation.rs +++ b/compiler/rustc_hir_analysis/src/delegation.rs @@ -76,41 +76,153 @@ fn fn_kind<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> FnKind { } } +struct GenericsBuilder<'tcx> { + tcx: TyCtxt<'tcx>, + sig_id: DefId, + parent: Option, +} + +impl<'tcx> GenericsBuilder<'tcx> { + fn new(tcx: TyCtxt<'tcx>, sig_id: DefId) -> GenericsBuilder<'tcx> { + GenericsBuilder { tcx, sig_id, parent: None } + } + + fn build(self) -> ty::Generics { + let mut own_params = vec![]; + + let sig_generics = self.tcx.generics_of(self.sig_id); + if let Some(parent_def_id) = sig_generics.parent { + let sig_parent_generics = self.tcx.generics_of(parent_def_id); + own_params.append(&mut sig_parent_generics.own_params.clone()); + } + own_params.append(&mut sig_generics.own_params.clone()); + + // Lifetime parameters must be declared before type and const parameters. + // Therefore, When delegating from a free function to a associated function, + // generic parameters need to be reordered: + // + // trait Trait<'a, A> { + // fn foo<'b, B>(...) {...} + // } + // + // reuse Trait::foo; + // desugaring: + // fn foo<'a, 'b, This: Trait<'a, A>, A, B>(...) { + // Trait::foo(...) + // } + own_params.sort_by_key(|key| key.kind.is_ty_or_const()); + + let param_def_id_to_index = + own_params.iter().map(|param| (param.def_id, param.index)).collect(); + + for (idx, param) in own_params.iter_mut().enumerate() { + param.index = idx as u32; + // FIXME(fn_delegation): Default parameters are not inherited, because they are + // not permitted in functions. Therefore, there are 2 options here: + // + // - We can create non-default generic parameters. + // - We can substitute default parameters into the signature. + // + // At the moment, first option has been selected as the most general. + if let ty::GenericParamDefKind::Type { has_default, .. } + | ty::GenericParamDefKind::Const { has_default, .. } = &mut param.kind + { + *has_default = false; + } + } + + ty::Generics { + parent: self.parent, + parent_count: 0, + own_params, + param_def_id_to_index, + has_self: false, + has_late_bound_regions: sig_generics.has_late_bound_regions, + host_effect_index: sig_generics.host_effect_index, + } + } +} + +struct PredicatesBuilder<'tcx> { + tcx: TyCtxt<'tcx>, + args: ty::GenericArgsRef<'tcx>, + parent: Option, + sig_id: DefId, +} + +impl<'tcx> PredicatesBuilder<'tcx> { + fn new( + tcx: TyCtxt<'tcx>, + args: ty::GenericArgsRef<'tcx>, + sig_id: DefId, + ) -> PredicatesBuilder<'tcx> { + PredicatesBuilder { tcx, args, parent: None, sig_id } + } + + fn build(self) -> ty::GenericPredicates<'tcx> { + let mut preds = vec![]; + + let sig_predicates = self.tcx.predicates_of(self.sig_id); + if let Some(parent) = sig_predicates.parent { + let sig_parent_preds = self.tcx.predicates_of(parent); + preds.extend(sig_parent_preds.instantiate_own(self.tcx, self.args)); + } + preds.extend(sig_predicates.instantiate_own(self.tcx, self.args)); + + ty::GenericPredicates { + parent: self.parent, + predicates: self.tcx.arena.alloc_from_iter(preds), + // FIXME(fn_delegation): Support effects. + effects_min_tys: ty::List::empty(), + } + } +} + +struct GenericArgsBuilder<'tcx> { + tcx: TyCtxt<'tcx>, + remap_table: RemapTable, + sig_id: DefId, + def_id: LocalDefId, +} + +impl<'tcx> GenericArgsBuilder<'tcx> { + fn new(tcx: TyCtxt<'tcx>, sig_id: DefId, def_id: LocalDefId) -> GenericArgsBuilder<'tcx> { + GenericArgsBuilder { tcx, remap_table: FxHashMap::default(), sig_id, def_id } + } + + fn build_from_args(mut self, args: ty::GenericArgsRef<'tcx>) -> ty::GenericArgsRef<'tcx> { + let caller_generics = self.tcx.generics_of(self.def_id); + let callee_generics = self.tcx.generics_of(self.sig_id); + + for caller_param in &caller_generics.own_params { + let callee_index = + callee_generics.param_def_id_to_index(self.tcx, caller_param.def_id).unwrap(); + self.remap_table.insert(callee_index, caller_param.index); + } + + let mut folder = ParamIndexRemapper { tcx: self.tcx, remap_table: self.remap_table }; + args.fold_with(&mut folder) + } +} + fn create_generic_args<'tcx>( tcx: TyCtxt<'tcx>, def_id: LocalDefId, sig_id: DefId, ) -> ty::GenericArgsRef<'tcx> { - let caller_generics = tcx.generics_of(def_id); - let callee_generics = tcx.generics_of(sig_id); + let builder = GenericArgsBuilder::new(tcx, sig_id, def_id); let caller_kind = fn_kind(tcx, def_id.into()); let callee_kind = fn_kind(tcx, sig_id); - // FIXME(fn_delegation): Support generics on associated delegation items. - // Error will be reported in `check_constraints`. + match (caller_kind, callee_kind) { - (FnKind::Free, _) => { - // Lifetime parameters must be declared before type and const parameters. - // Therefore, When delegating from a free function to a associated function, - // generic parameters need to be reordered: - // - // trait Trait<'a, A> { - // fn foo<'b, B>(...) {...} - // } - // - // reuse Trait::foo; - // desugaring: - // fn foo<'a, 'b, This: Trait<'a, A>, A, B>(...) { - // Trait::foo(...) - // } - let mut remap_table = RemapTable::default(); - for caller_param in &caller_generics.own_params { - let callee_index = - callee_generics.param_def_id_to_index(tcx, caller_param.def_id).unwrap(); - remap_table.insert(callee_index, caller_param.index); - } - let mut folder = ParamIndexRemapper { tcx, remap_table }; - ty::GenericArgs::identity_for_item(tcx, sig_id).fold_with(&mut folder) + (FnKind::Free, FnKind::Free) + | (FnKind::Free, FnKind::AssocTrait) + | (FnKind::AssocInherentImpl, FnKind::Free) + | (FnKind::AssocTrait, FnKind::Free) + | (FnKind::AssocTrait, FnKind::AssocTrait) => { + let args = ty::GenericArgs::identity_for_item(tcx, sig_id); + builder.build_from_args(args) } // FIXME(fn_delegation): Only `Self` param supported here. (FnKind::AssocTraitImpl, FnKind::AssocTrait) @@ -120,7 +232,11 @@ fn create_generic_args<'tcx>( let generic_self_ty = ty::GenericArg::from(self_ty); tcx.mk_args_from_iter(std::iter::once(generic_self_ty)) } - _ => ty::GenericArgs::identity_for_item(tcx, sig_id), + // For trait impl's `sig_id` is always equal to the corresponding trait method. + (FnKind::AssocTraitImpl, _) + | (_, FnKind::AssocTraitImpl) + // Delegation to inherent methods is not yet supported. + | (_, FnKind::AssocInherentImpl) => unreachable!(), } } @@ -129,47 +245,29 @@ pub(crate) fn inherit_generics_for_delegation_item<'tcx>( def_id: LocalDefId, sig_id: DefId, ) -> Option { - // FIXME(fn_delegation): Support generics on associated delegation items. - // Error will be reported in `check_constraints`. - if fn_kind(tcx, def_id.into()) != FnKind::Free { - return None; - } + let builder = GenericsBuilder::new(tcx, sig_id); - let mut own_params = vec![]; - - let callee_generics = tcx.generics_of(sig_id); - if let Some(parent_sig_id) = callee_generics.parent { - let parent_sig_generics = tcx.generics_of(parent_sig_id); - own_params.append(&mut parent_sig_generics.own_params.clone()); - } - own_params.append(&mut callee_generics.own_params.clone()); + let caller_kind = fn_kind(tcx, def_id.into()); + let callee_kind = fn_kind(tcx, sig_id); - // Lifetimes go first. - own_params.sort_by_key(|key| key.kind.is_ty_or_const()); + // FIXME(fn_delegation): Support generics on associated delegation items. + // Error will be reported in `check_constraints`. + match (caller_kind, callee_kind) { + (FnKind::Free, FnKind::Free) + | (FnKind::Free, FnKind::AssocTrait) => Some(builder.build()), - for (idx, param) in own_params.iter_mut().enumerate() { - param.index = idx as u32; - // Default parameters are not inherited: they are not allowed - // in fn's. - if let ty::GenericParamDefKind::Type { has_default, .. } - | ty::GenericParamDefKind::Const { has_default, .. } = &mut param.kind - { - *has_default = false; - } + (FnKind::AssocTraitImpl, FnKind::AssocTrait) + | (FnKind::AssocInherentImpl, FnKind::AssocTrait) + | (FnKind::AssocTrait, FnKind::AssocTrait) + | (FnKind::AssocInherentImpl, FnKind::Free) + | (FnKind::AssocTrait, FnKind::Free) => None, + + // For trait impl's `sig_id` is always equal to the corresponding trait method. + (FnKind::AssocTraitImpl, _) + | (_, FnKind::AssocTraitImpl) + // Delegation to inherent methods is not yet supported. + | (_, FnKind::AssocInherentImpl) => unreachable!(), } - - let param_def_id_to_index = - own_params.iter().map(|param| (param.def_id, param.index)).collect(); - - Some(ty::Generics { - parent: None, - parent_count: 0, - own_params, - param_def_id_to_index, - has_self: false, - has_late_bound_regions: callee_generics.has_late_bound_regions, - host_effect_index: callee_generics.host_effect_index, - }) } pub(crate) fn inherit_predicates_for_delegation_item<'tcx>( @@ -177,26 +275,32 @@ pub(crate) fn inherit_predicates_for_delegation_item<'tcx>( def_id: LocalDefId, sig_id: DefId, ) -> Option> { + let args = create_generic_args(tcx, def_id, sig_id); + let builder = PredicatesBuilder::new(tcx, args, sig_id); + + let caller_kind = fn_kind(tcx, def_id.into()); + let callee_kind = fn_kind(tcx, sig_id); + // FIXME(fn_delegation): Support generics on associated delegation items. // Error will be reported in `check_constraints`. - if fn_kind(tcx, def_id.into()) != FnKind::Free { - return None; - } - - let callee_predicates = tcx.predicates_of(sig_id); - let args = create_generic_args(tcx, def_id, sig_id); + match (caller_kind, callee_kind) { + (FnKind::Free, FnKind::Free) + | (FnKind::Free, FnKind::AssocTrait) => { + Some(builder.build()) + } - let mut preds = vec![]; - if let Some(parent_id) = callee_predicates.parent { - preds.extend(tcx.predicates_of(parent_id).instantiate_own(tcx, args)); + (FnKind::AssocTraitImpl, FnKind::AssocTrait) + | (FnKind::AssocInherentImpl, FnKind::AssocTrait) + | (FnKind::AssocTrait, FnKind::AssocTrait) + | (FnKind::AssocInherentImpl, FnKind::Free) + | (FnKind::AssocTrait, FnKind::Free) => None, + + // For trait impl's `sig_id` is always equal to the corresponding trait method. + (FnKind::AssocTraitImpl, _) + | (_, FnKind::AssocTraitImpl) + // Delegation to inherent methods is not yet supported. + | (_, FnKind::AssocInherentImpl) => unreachable!(), } - preds.extend(callee_predicates.instantiate_own(tcx, args)); - - Some(ty::GenericPredicates { - parent: None, - predicates: tcx.arena.alloc_from_iter(preds), - effects_min_tys: ty::List::empty(), - }) } fn check_constraints<'tcx>( diff --git a/tests/ui/delegation/not-supported.rs b/tests/ui/delegation/unsupported.rs similarity index 100% rename from tests/ui/delegation/not-supported.rs rename to tests/ui/delegation/unsupported.rs diff --git a/tests/ui/delegation/not-supported.stderr b/tests/ui/delegation/unsupported.stderr similarity index 83% rename from tests/ui/delegation/not-supported.stderr rename to tests/ui/delegation/unsupported.stderr index 14d6b374bd2c4..bb150254f48b9 100644 --- a/tests/ui/delegation/not-supported.stderr +++ b/tests/ui/delegation/unsupported.stderr @@ -4,7 +4,7 @@ error: using `#![feature(effects)]` without enabling next trait solver globally = help: use `-Znext-solver` to enable error: early bound generics are not supported for associated delegation items - --> $DIR/not-supported.rs:18:29 + --> $DIR/unsupported.rs:18:29 | LL | fn bar(&self, x: T) -> T { x } | ------------------------ callee defined here @@ -13,7 +13,7 @@ LL | reuse GenericTrait::bar; | ^^^ error: early bound generics are not supported for associated delegation items - --> $DIR/not-supported.rs:20:29 + --> $DIR/unsupported.rs:20:29 | LL | fn bar1() {} | --------- callee defined here @@ -22,7 +22,7 @@ LL | reuse GenericTrait::bar1; | ^^^^ error: early bound generics are not supported for associated delegation items - --> $DIR/not-supported.rs:31:39 + --> $DIR/unsupported.rs:31:39 | LL | fn bar(&self, x: T) -> T { x } | ------------------------ callee defined here @@ -31,7 +31,7 @@ LL | reuse >::bar { &self.0 } | ^^^ error: early bound generics are not supported for associated delegation items - --> $DIR/not-supported.rs:33:34 + --> $DIR/unsupported.rs:33:34 | LL | fn bar1() {} | --------- callee defined here @@ -40,7 +40,7 @@ LL | reuse GenericTrait::::bar1; | ^^^^ error: early bound generics are not supported for associated delegation items - --> $DIR/not-supported.rs:38:29 + --> $DIR/unsupported.rs:38:29 | LL | fn bar(&self, x: T) -> T { x } | ------------------------ callee defined here @@ -49,7 +49,7 @@ LL | reuse GenericTrait::bar { &F } | ^^^ error: early bound generics are not supported for associated delegation items - --> $DIR/not-supported.rs:40:29 + --> $DIR/unsupported.rs:40:29 | LL | fn bar1() {} | --------- callee defined here @@ -58,7 +58,7 @@ LL | reuse GenericTrait::bar1; | ^^^^ error: early bound generics are not supported for associated delegation items - --> $DIR/not-supported.rs:45:22 + --> $DIR/unsupported.rs:45:22 | LL | fn foo(&self, x: i32) -> i32 { x } | ---------------------------- callee defined here @@ -67,7 +67,7 @@ LL | reuse Trait::foo; | ^^^ error[E0049]: method `foo2` has 0 type parameters but its trait declaration has 1 type parameter - --> $DIR/not-supported.rs:51:22 + --> $DIR/unsupported.rs:51:22 | LL | fn foo2(&self, x: T) -> T { x } | - expected 1 type parameter @@ -76,7 +76,7 @@ LL | reuse Trait::foo2 { &self.0 } | ^^^^ found 0 type parameters error: early bound generics are not supported for associated delegation items - --> $DIR/not-supported.rs:54:29 + --> $DIR/unsupported.rs:54:29 | LL | fn foo3<'a: 'a>(_: &'a u32) {} | --------------------------- callee defined here @@ -85,7 +85,7 @@ LL | reuse ::foo3; | ^^^^ error[E0195]: lifetime parameters or bounds on associated function `foo3` do not match the trait declaration - --> $DIR/not-supported.rs:54:29 + --> $DIR/unsupported.rs:54:29 | LL | fn foo3<'a: 'a>(_: &'a u32) {} | -------- lifetimes in impl do not match this associated function in trait @@ -94,7 +94,7 @@ LL | reuse ::foo3; | ^^^^ lifetimes do not match associated function in trait error: delegation to a function with effect parameter is not supported yet - --> $DIR/not-supported.rs:112:18 + --> $DIR/unsupported.rs:112:18 | LL | fn foo(); | --------- callee defined here @@ -103,7 +103,7 @@ LL | reuse Trait::foo; | ^^^ error: early bound generics are not supported for associated delegation items - --> $DIR/not-supported.rs:61:22 + --> $DIR/unsupported.rs:61:22 | LL | fn foo(&self, x: i32) -> i32 { x } | ---------------------------- callee defined here @@ -112,7 +112,7 @@ LL | reuse Trait::foo { &self.0 } | ^^^ error: early bound generics are not supported for associated delegation items - --> $DIR/not-supported.rs:51:22 + --> $DIR/unsupported.rs:51:22 | LL | fn foo2(&self, x: T) -> T { x } | ---------------------------- callee defined here @@ -121,7 +121,7 @@ LL | reuse Trait::foo2 { &self.0 } | ^^^^ warning: this function depends on never type fallback being `()` - --> $DIR/not-supported.rs:79:9 + --> $DIR/unsupported.rs:79:9 | LL | fn opaque_ret() -> impl Trait { unimplemented!() } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -130,33 +130,33 @@ LL | fn opaque_ret() -> impl Trait { unimplemented!() } = note: for more information, see issue #123748 = help: specify the types explicitly note: in edition 2024, the requirement `!: opaque::Trait` will fail - --> $DIR/not-supported.rs:79:28 + --> $DIR/unsupported.rs:79:28 | LL | fn opaque_ret() -> impl Trait { unimplemented!() } | ^^^^^^^^^^ = note: `#[warn(dependency_on_unit_never_type_fallback)]` on by default -error[E0391]: cycle detected when computing type of `opaque::::{synthetic#0}` - --> $DIR/not-supported.rs:86:25 +error[E0391]: cycle detected when computing type of `opaque::::{synthetic#0}` + --> $DIR/unsupported.rs:86:25 | LL | reuse to_reuse::opaque_ret; | ^^^^^^^^^^ | note: ...which requires comparing an impl and trait method signature, inferring any hidden `impl Trait` types in the process... - --> $DIR/not-supported.rs:86:25 + --> $DIR/unsupported.rs:86:25 | LL | reuse to_reuse::opaque_ret; | ^^^^^^^^^^ - = note: ...which again requires computing type of `opaque::::{synthetic#0}`, completing the cycle -note: cycle used when checking that `opaque::` is well-formed - --> $DIR/not-supported.rs:85:5 + = note: ...which again requires computing type of `opaque::::{synthetic#0}`, completing the cycle +note: cycle used when checking that `opaque::` is well-formed + --> $DIR/unsupported.rs:85:5 | LL | impl ToReuse for u8 { | ^^^^^^^^^^^^^^^^^^^ = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information warning: this function depends on never type fallback being `()` - --> $DIR/not-supported.rs:73:9 + --> $DIR/unsupported.rs:73:9 | LL | pub fn opaque_ret() -> impl Trait { unimplemented!() } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -165,32 +165,32 @@ LL | pub fn opaque_ret() -> impl Trait { unimplemented!() } = note: for more information, see issue #123748 = help: specify the types explicitly note: in edition 2024, the requirement `!: opaque::Trait` will fail - --> $DIR/not-supported.rs:73:32 + --> $DIR/unsupported.rs:73:32 | LL | pub fn opaque_ret() -> impl Trait { unimplemented!() } | ^^^^^^^^^^ -error[E0391]: cycle detected when computing type of `opaque::::{synthetic#0}` - --> $DIR/not-supported.rs:89:24 +error[E0391]: cycle detected when computing type of `opaque::::{synthetic#0}` + --> $DIR/unsupported.rs:89:24 | LL | reuse ToReuse::opaque_ret; | ^^^^^^^^^^ | note: ...which requires comparing an impl and trait method signature, inferring any hidden `impl Trait` types in the process... - --> $DIR/not-supported.rs:89:24 + --> $DIR/unsupported.rs:89:24 | LL | reuse ToReuse::opaque_ret; | ^^^^^^^^^^ - = note: ...which again requires computing type of `opaque::::{synthetic#0}`, completing the cycle -note: cycle used when checking that `opaque::` is well-formed - --> $DIR/not-supported.rs:88:5 + = note: ...which again requires computing type of `opaque::::{synthetic#0}`, completing the cycle +note: cycle used when checking that `opaque::` is well-formed + --> $DIR/unsupported.rs:88:5 | LL | impl ToReuse for u16 { | ^^^^^^^^^^^^^^^^^^^^ = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information error: recursive delegation is not supported yet - --> $DIR/not-supported.rs:102:22 + --> $DIR/unsupported.rs:102:22 | LL | pub reuse to_reuse2::foo; | --- callee defined here From 2d6d6a84df371390046269fe4955d2e4300f118f Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 27 Aug 2024 07:33:49 -0700 Subject: [PATCH 0444/2194] Updates/clarifications --- .../platform-support/wasm32-unknown-unknown.md | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/src/doc/rustc/src/platform-support/wasm32-unknown-unknown.md b/src/doc/rustc/src/platform-support/wasm32-unknown-unknown.md index 6ce022e5ebba2..0e06a820a22c3 100644 --- a/src/doc/rustc/src/platform-support/wasm32-unknown-unknown.md +++ b/src/doc/rustc/src/platform-support/wasm32-unknown-unknown.md @@ -205,7 +205,7 @@ be fixed in a future version of Rust. For example this Rust code: -```rust +```rust,ignore (does-not-link) #[repr(C)] struct MyPair { a: u32, @@ -280,20 +280,22 @@ unfortunate accident which got relied on. The `wasm-bindgen` project prior to seen as not worth the tradeoff of breaking `wasm-bindgen` historically to fix this issue in the compiler. -Thanks to the heroic efforts of many involved in this, however, the nightly -compiler currently supports a `-Zwasm-c-abi` implemented in +Thanks to the heroic efforts of many involved in this, however, `wasm-bindgen` +0.2.89 and later are compatible with the correct definition of `extern "C"` and +the nightly compiler currently supports a `-Zwasm-c-abi` implemented in [#117919](https://github.com/rust-lang/rust/pull/117919). This nightly-only flag can be used to indicate whether the spec-defined version of `extern "C"` should be used instead of the "legacy" version of whatever-the-Rust-target-originally-implemented. For example using the above code you can see (lightly edited for clarity): -``` +```shell $ rustc +nightly -Zwasm-c-abi=spec foo.rs --target wasm32-unknown-unknown --crate-type lib --emit obj -O $ wasm-tools print foo.o (module (import "env" "take_my_pair" (func $take_my_pair (param i32) (result i32))) (func $call_c (result i32) + ;; ... ) ;; ... ) @@ -305,6 +307,8 @@ they should. The `-Zwasm-c-abi` compiler flag is tracked in [#122532](https://github.com/rust-lang/rust/issues/122532) and a lint was implemented in [#117918](https://github.com/rust-lang/rust/issues/117918) to -help warn users about the transition. The current plan is to, in the future, -switch `-Zwasm-c-api=spec` to being the default. Some time after that the -`-Zwasm-c-abi` flag and the "legacy" implementation will all be removed. +help warn users about the transition if they're using `wasm-bindgen` 0.2.88 or +prior. The current plan is to, in the future, switch `-Zwasm-c-api=spec` to +being the default. Some time after that the `-Zwasm-c-abi` flag and the +"legacy" implementation will all be removed. During this process users on a +sufficiently updated version of `wasm-bindgen` should not experience breakage. From a07e54c6ea28ced847f954b5e05e948839f991f2 Mon Sep 17 00:00:00 2001 From: DropDemBits Date: Tue, 3 Sep 2024 11:20:23 -0400 Subject: [PATCH 0445/2194] bundle old root into `SyntaxEdit` result useful for `SourceChangeBuilder` so it can still perform a tree diff without having to store the old root separately --- .../crates/syntax/src/syntax_editor.rs | 25 ++++++++++++------- .../syntax/src/syntax_editor/edit_algo.rs | 17 ++++++++++--- 2 files changed, 30 insertions(+), 12 deletions(-) diff --git a/src/tools/rust-analyzer/crates/syntax/src/syntax_editor.rs b/src/tools/rust-analyzer/crates/syntax/src/syntax_editor.rs index 139c6518bf7cb..eb114f5e5f1f7 100644 --- a/src/tools/rust-analyzer/crates/syntax/src/syntax_editor.rs +++ b/src/tools/rust-analyzer/crates/syntax/src/syntax_editor.rs @@ -102,16 +102,23 @@ impl SyntaxEditor { } } +/// Represents a completed [`SyntaxEditor`] operation. pub struct SyntaxEdit { - root: SyntaxNode, + old_root: SyntaxNode, + new_root: SyntaxNode, changed_elements: Vec, annotations: FxHashMap>, } impl SyntaxEdit { - /// Root of the modified syntax tree - pub fn root(&self) -> &SyntaxNode { - &self.root + /// Root of the initial unmodified syntax tree. + pub fn old_root(&self) -> &SyntaxNode { + &self.old_root + } + + /// Root of the modified syntax tree. + pub fn new_root(&self) -> &SyntaxNode { + &self.new_root } /// Which syntax elements in the modified syntax tree were inserted or @@ -441,14 +448,14 @@ mod tests { let var_name = 2 + 2; (var_name, true) }"#]]; - expect.assert_eq(&edit.root.to_string()); + expect.assert_eq(&edit.new_root.to_string()); assert_eq!(edit.find_annotation(placeholder_snippet).len(), 2); assert!(edit .annotations .iter() .flat_map(|(_, elements)| elements) - .all(|element| element.ancestors().any(|it| &it == edit.root()))) + .all(|element| element.ancestors().any(|it| &it == edit.new_root()))) } #[test] @@ -495,7 +502,7 @@ mod tests { let first = 1;{ let second = 2;let third = 3; }"#]]; - expect.assert_eq(&edit.root.to_string()); + expect.assert_eq(&edit.new_root.to_string()); } #[test] @@ -556,7 +563,7 @@ mod tests { } } }"#]]; - expect.assert_eq(&edit.root.to_string()); + expect.assert_eq(&edit.new_root.to_string()); } #[test] @@ -599,6 +606,6 @@ mod tests { let second = 2; } }"#]]; - expect.assert_eq(&edit.root.to_string()); + expect.assert_eq(&edit.new_root.to_string()); } } diff --git a/src/tools/rust-analyzer/crates/syntax/src/syntax_editor/edit_algo.rs b/src/tools/rust-analyzer/crates/syntax/src/syntax_editor/edit_algo.rs index 55e8867a46cb4..b769c941105b7 100644 --- a/src/tools/rust-analyzer/crates/syntax/src/syntax_editor/edit_algo.rs +++ b/src/tools/rust-analyzer/crates/syntax/src/syntax_editor/edit_algo.rs @@ -81,7 +81,12 @@ pub(super) fn apply_edits(editor: SyntaxEditor) -> SyntaxEdit { "some replace change ranges intersect: {:?}", changes ) { - return SyntaxEdit { root, annotations: Default::default(), changed_elements: vec![] }; + return SyntaxEdit { + old_root: root.clone(), + new_root: root, + annotations: Default::default(), + changed_elements: vec![], + }; } #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] @@ -273,7 +278,12 @@ pub(super) fn apply_edits(editor: SyntaxEditor) -> SyntaxEdit { annotation_groups.entry(annotation).or_insert(vec![]).push(element); } - SyntaxEdit { root, changed_elements, annotations: annotation_groups } + SyntaxEdit { + old_root: tree_mutator.immutable, + new_root: root, + changed_elements, + annotations: annotation_groups, + } } fn to_owning_node(element: &SyntaxElement) -> SyntaxNode { @@ -329,6 +339,7 @@ impl ChangedAncestor { } struct TreeMutator { + immutable: SyntaxNode, mutable_clone: SyntaxNode, } @@ -336,7 +347,7 @@ impl TreeMutator { fn new(immutable: &SyntaxNode) -> TreeMutator { let immutable = immutable.clone(); let mutable_clone = immutable.clone_for_update(); - TreeMutator { mutable_clone } + TreeMutator { immutable, mutable_clone } } fn make_element_mut(&self, element: &SyntaxElement) -> SyntaxElement { From d3c9cc57d291efa09963add37b11cc52edcae19e Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Tue, 3 Sep 2024 12:03:53 -0400 Subject: [PATCH 0446/2194] Add support for missing SIMD intrinsics --- src/intrinsic/llvm.rs | 45 ++++++++++++++++++++++++++++++++++++++++++- src/intrinsic/simd.rs | 18 ++++++++++++++++- 2 files changed, 61 insertions(+), 2 deletions(-) diff --git a/src/intrinsic/llvm.rs b/src/intrinsic/llvm.rs index 2287c96b41b8f..614bdbe26b808 100644 --- a/src/intrinsic/llvm.rs +++ b/src/intrinsic/llvm.rs @@ -182,7 +182,10 @@ pub fn adjust_intrinsic_arguments<'a, 'b, 'gcc, 'tcx>( | "__builtin_ia32_vplzcntd_128_mask" | "__builtin_ia32_vplzcntq_512_mask" | "__builtin_ia32_vplzcntq_256_mask" - | "__builtin_ia32_vplzcntq_128_mask" => { + | "__builtin_ia32_vplzcntq_128_mask" + | "__builtin_ia32_cvtqq2pd128_mask" + | "__builtin_ia32_cvtqq2pd256_mask" + | "__builtin_ia32_cvtqq2ps256_mask" => { let mut new_args = args.to_vec(); // Remove last arg as it doesn't seem to be used in GCC and is always false. new_args.pop(); @@ -378,6 +381,23 @@ pub fn adjust_intrinsic_arguments<'a, 'b, 'gcc, 'tcx>( ); args = vec![arg.get_address(None)].into(); } + "__builtin_ia32_cvtqq2pd512_mask" | "__builtin_ia32_cvtqq2ps512_mask" => { + let mut old_args = args.to_vec(); + let mut new_args = vec![]; + new_args.push(old_args.swap_remove(0)); + let arg2_type = gcc_func.get_param_type(1); + let vector_type = arg2_type.dyncast_vector().expect("vector type"); + let zero = builder.context.new_rvalue_zero(vector_type.get_element_type()); + let num_units = vector_type.get_num_units(); + let first_arg = + builder.context.new_rvalue_from_vector(None, arg2_type, &vec![zero; num_units]); + new_args.push(first_arg); + let arg3_type = gcc_func.get_param_type(2); + let minus_one = builder.context.new_rvalue_from_int(arg3_type, -1); + new_args.push(minus_one); + new_args.push(old_args.swap_remove(0)); + args = new_args.into(); + } _ => (), } } else { @@ -987,6 +1007,29 @@ pub fn intrinsic<'gcc, 'tcx>(name: &str, cx: &CodegenCx<'gcc, 'tcx>) -> Function "llvm.x86.avx512.vpdpbusds.128" => "__builtin_ia32_vpdpbusds_v4si", "llvm.x86.xsave" => "__builtin_ia32_xsave", "llvm.x86.xsaveopt" => "__builtin_ia32_xsaveopt", + "llvm.x86.avx512.mask.loadu.w.512" => "__builtin_ia32_loaddquhi512_mask", + "llvm.x86.avx512.mask.loadu.b.512" => "__builtin_ia32_loaddquqi512_mask", + "llvm.x86.avx512.mask.loadu.w.256" => "__builtin_ia32_loaddquhi256_mask", + "llvm.x86.avx512.mask.loadu.b.256" => "__builtin_ia32_loaddquqi256_mask", + "llvm.x86.avx512.mask.loadu.w.128" => "__builtin_ia32_loaddquhi128_mask", + "llvm.x86.avx512.mask.loadu.b.128" => "__builtin_ia32_loaddquqi128_mask", + "llvm.x86.avx512.mask.storeu.w.512" => "__builtin_ia32_storedquhi512_mask", + "llvm.x86.avx512.mask.storeu.b.512" => "__builtin_ia32_storedquqi512_mask", + "llvm.x86.avx512.mask.storeu.w.256" => "__builtin_ia32_storedquhi256_mask", + "llvm.x86.avx512.mask.storeu.b.256" => "__builtin_ia32_storedquqi256_mask", + "llvm.x86.avx512.mask.storeu.w.128" => "__builtin_ia32_storedquhi128_mask", + "llvm.x86.avx512.mask.storeu.b.128" => "__builtin_ia32_storedquqi128_mask", + "llvm.x86.avx512.mask.expand.load.w.512" => "__builtin_ia32_expandloadhi512_mask", + "llvm.x86.avx512.mask.expand.load.w.256" => "__builtin_ia32_expandloadhi256_mask", + "llvm.x86.avx512.mask.expand.load.w.128" => "__builtin_ia32_expandloadhi128_mask", + "llvm.x86.avx512.mask.expand.load.b.512" => "__builtin_ia32_expandloadqi512_mask", + "llvm.x86.avx512.mask.expand.load.b.256" => "__builtin_ia32_expandloadqi256_mask", + "llvm.x86.avx512.mask.expand.load.b.128" => "__builtin_ia32_expandloadqi128_mask", + "llvm.x86.avx512.sitofp.round.v8f64.v8i64" => "__builtin_ia32_cvtqq2pd512_mask", + "llvm.x86.avx512.sitofp.round.v2f64.v2i64" => "__builtin_ia32_cvtqq2pd128_mask", + "llvm.x86.avx512.sitofp.round.v4f64.v4i64" => "__builtin_ia32_cvtqq2pd256_mask", + "llvm.x86.avx512.sitofp.round.v8f32.v8i64" => "__builtin_ia32_cvtqq2ps512_mask", + "llvm.x86.avx512.sitofp.round.v4f32.v4i64" => "__builtin_ia32_cvtqq2ps256_mask", // NOTE: this file is generated by https://github.com/GuillaumeGomez/llvmint/blob/master/generate_list.py _ => include!("archs.rs"), diff --git a/src/intrinsic/simd.rs b/src/intrinsic/simd.rs index d1b4a9689a93a..a0d8ff6346f3e 100644 --- a/src/intrinsic/simd.rs +++ b/src/intrinsic/simd.rs @@ -201,7 +201,7 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( bx.context.new_bitcast(None, shuffled, v_type) }; - if name == sym::simd_bswap || name == sym::simd_bitreverse { + if matches!(name, sym::simd_bswap | sym::simd_bitreverse | sym::simd_ctpop) { require!( bx.type_kind(bx.element_type(llret_ty)) == TypeKind::Integer, InvalidMonomorphization::UnsupportedOperation { span, name, in_ty, in_elem } @@ -212,6 +212,22 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( return Ok(simd_bswap(bx, args[0].immediate())); } + let simd_ctpop = |bx: &mut Builder<'a, 'gcc, 'tcx>, vector: RValue<'gcc>| -> RValue<'gcc> { + let mut vector_elements = vec![]; + let elem_ty = bx.element_type(llret_ty); + for i in 0..in_len { + let index = bx.context.new_rvalue_from_long(bx.ulong_type, i as i64); + let element = bx.extract_element(vector, index).to_rvalue(); + let result = bx.context.new_cast(None, bx.pop_count(element), elem_ty); + vector_elements.push(result); + } + bx.context.new_rvalue_from_vector(None, llret_ty, &vector_elements) + }; + + if name == sym::simd_ctpop { + return Ok(simd_ctpop(bx, args[0].immediate())); + } + // We use a different algorithm from non-vector bitreverse to take advantage of most // processors' vector shuffle units. It works like this: // 1. Generate pre-reversed low and high nibbles as a vector. From 6b0fc97c7ab25b50c5b061cbe8ec4aaa5575e9f9 Mon Sep 17 00:00:00 2001 From: Chris Denton Date: Tue, 3 Sep 2024 16:27:46 +0000 Subject: [PATCH 0447/2194] Win: Open dir for sync access in remove_dir_all --- .../std/src/sys/pal/windows/fs/remove_dir_all.rs | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/library/std/src/sys/pal/windows/fs/remove_dir_all.rs b/library/std/src/sys/pal/windows/fs/remove_dir_all.rs index e7234ed8e5f56..9416049da78f8 100644 --- a/library/std/src/sys/pal/windows/fs/remove_dir_all.rs +++ b/library/std/src/sys/pal/windows/fs/remove_dir_all.rs @@ -71,10 +71,12 @@ unsafe fn nt_open_file( } /// Open the file `path` in the directory `parent`, requesting the given `access` rights. +/// `options` will be OR'd with `FILE_OPEN_REPARSE_POINT`. fn open_link_no_reparse( parent: &File, path: &[u16], access: u32, + options: u32, ) -> Result, WinError> { // This is implemented using the lower level `NtOpenFile` function as // unfortunately opening a file relative to a parent is not supported by @@ -96,7 +98,7 @@ fn open_link_no_reparse( ..c::OBJECT_ATTRIBUTES::default() }; let share = c::FILE_SHARE_DELETE | c::FILE_SHARE_READ | c::FILE_SHARE_WRITE; - let options = c::FILE_OPEN_REPARSE_POINT; + let options = c::FILE_OPEN_REPARSE_POINT | options; let result = nt_open_file(access, &object, share, options); // Retry without OBJ_DONT_REPARSE if it's not supported. @@ -128,13 +130,20 @@ fn open_link_no_reparse( } fn open_dir(parent: &File, name: &[u16]) -> Result, WinError> { - open_link_no_reparse(parent, name, c::SYNCHRONIZE | c::FILE_LIST_DIRECTORY) + // Open the directory for synchronous directory listing. + open_link_no_reparse( + parent, + name, + c::SYNCHRONIZE | c::FILE_LIST_DIRECTORY, + // "_IO_NONALERT" means that a synchronous call won't be interrupted. + c::FILE_SYNCHRONOUS_IO_NONALERT, + ) } fn delete(parent: &File, name: &[u16]) -> Result<(), WinError> { // Note that the `delete` function consumes the opened file to ensure it's // dropped immediately. See module comments for why this is important. - match open_link_no_reparse(parent, name, c::SYNCHRONIZE | c::DELETE) { + match open_link_no_reparse(parent, name, c::DELETE, 0) { Ok(Some(f)) => f.delete(), Ok(None) => Ok(()), Err(e) => Err(e), From 273b561609de64131af3d59a38e38eceb76e4a29 Mon Sep 17 00:00:00 2001 From: Soveu Date: Fri, 12 Jul 2024 12:12:58 +0200 Subject: [PATCH 0448/2194] add pointers_in_nomem_asm_block lint --- CHANGELOG.md | 1 + clippy_lints/src/declared_lints.rs | 1 + clippy_lints/src/lib.rs | 2 + .../src/pointers_in_nomem_asm_block.rs | 88 +++++++++++++++++++ tests/ui/pointers_in_nomem_asm_block.rs | 33 +++++++ tests/ui/pointers_in_nomem_asm_block.stderr | 34 +++++++ 6 files changed, 159 insertions(+) create mode 100644 clippy_lints/src/pointers_in_nomem_asm_block.rs create mode 100644 tests/ui/pointers_in_nomem_asm_block.rs create mode 100644 tests/ui/pointers_in_nomem_asm_block.stderr diff --git a/CHANGELOG.md b/CHANGELOG.md index 682c3cfe0151c..fc51694ff57f4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5758,6 +5758,7 @@ Released 2018-09-13 [`pathbuf_init_then_push`]: https://rust-lang.github.io/rust-clippy/master/index.html#pathbuf_init_then_push [`pattern_type_mismatch`]: https://rust-lang.github.io/rust-clippy/master/index.html#pattern_type_mismatch [`permissions_set_readonly_false`]: https://rust-lang.github.io/rust-clippy/master/index.html#permissions_set_readonly_false +[`pointers_in_nomem_asm_block`]: https://rust-lang.github.io/rust-clippy/master/index.html#pointers_in_nomem_asm_block [`positional_named_format_parameters`]: https://rust-lang.github.io/rust-clippy/master/index.html#positional_named_format_parameters [`possible_missing_comma`]: https://rust-lang.github.io/rust-clippy/master/index.html#possible_missing_comma [`precedence`]: https://rust-lang.github.io/rust-clippy/master/index.html#precedence diff --git a/clippy_lints/src/declared_lints.rs b/clippy_lints/src/declared_lints.rs index aded9e276c4a8..e478ab330e8bc 100644 --- a/clippy_lints/src/declared_lints.rs +++ b/clippy_lints/src/declared_lints.rs @@ -600,6 +600,7 @@ pub static LINTS: &[&crate::LintInfo] = &[ crate::pathbuf_init_then_push::PATHBUF_INIT_THEN_PUSH_INFO, crate::pattern_type_mismatch::PATTERN_TYPE_MISMATCH_INFO, crate::permissions_set_readonly_false::PERMISSIONS_SET_READONLY_FALSE_INFO, + crate::pointers_in_nomem_asm_block::POINTERS_IN_NOMEM_ASM_BLOCK_INFO, crate::precedence::PRECEDENCE_INFO, crate::ptr::CMP_NULL_INFO, crate::ptr::INVALID_NULL_PTR_USAGE_INFO, diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 078f38656ece8..58ad9f645d6a5 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -287,6 +287,7 @@ mod pass_by_ref_or_value; mod pathbuf_init_then_push; mod pattern_type_mismatch; mod permissions_set_readonly_false; +mod pointers_in_nomem_asm_block; mod precedence; mod ptr; mod ptr_offset_with_cast; @@ -935,5 +936,6 @@ pub fn register_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) { store.register_early_pass(|| Box::new(byte_char_slices::ByteCharSlice)); store.register_early_pass(|| Box::new(cfg_not_test::CfgNotTest)); store.register_late_pass(|_| Box::new(zombie_processes::ZombieProcesses)); + store.register_late_pass(|_| Box::new(pointers_in_nomem_asm_block::PointersInNomemAsmBlock)); // add lints here, do not remove this comment, it's used in `new_lint` } diff --git a/clippy_lints/src/pointers_in_nomem_asm_block.rs b/clippy_lints/src/pointers_in_nomem_asm_block.rs new file mode 100644 index 0000000000000..385f634a15050 --- /dev/null +++ b/clippy_lints/src/pointers_in_nomem_asm_block.rs @@ -0,0 +1,88 @@ +use clippy_utils::diagnostics::span_lint_and_then; +use rustc_ast::InlineAsmOptions; +use rustc_hir::{Expr, ExprKind, InlineAsm, InlineAsmOperand}; +use rustc_lint::{LateContext, LateLintPass}; +use rustc_session::declare_lint_pass; +use rustc_span::Span; + +declare_clippy_lint! { + /// ### What it does + /// Checks if any pointer is being passed to an asm! block with `nomem` option. + /// + /// ### Why is this bad? + /// `nomem` forbids any reads or writes to memory and passing a pointer suggests + /// that either of those will happen. + /// + /// ### Example + /// ```no_run + /// fn f(p: *mut u32) { + /// unsafe { core::arch::asm!("mov [{p}], 42", p = in(reg) p, options(nomem, nostack)); } + /// } + /// ``` + /// Use instead: + /// ```no_run + /// fn f(p: *mut u32) { + /// unsafe { core::arch::asm!("mov [{p}], 42", p = in(reg) p, options(nostack)); } + /// } + /// ``` + #[clippy::version = "1.81.0"] + pub POINTERS_IN_NOMEM_ASM_BLOCK, + suspicious, + "pointers in nomem asm block" +} + +declare_lint_pass!(PointersInNomemAsmBlock => [POINTERS_IN_NOMEM_ASM_BLOCK]); + +impl<'tcx> LateLintPass<'tcx> for PointersInNomemAsmBlock { + fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &Expr<'tcx>) { + if let ExprKind::InlineAsm(asm) = &expr.kind { + check_asm(cx, asm); + } + } +} + +fn check_asm(cx: &LateContext<'_>, asm: &InlineAsm<'_>) { + if !asm.options.contains(InlineAsmOptions::NOMEM) { + return; + } + + let spans = asm + .operands + .iter() + .filter(|(op, _span)| has_in_operand_pointer(cx, op)) + .map(|(_op, span)| *span) + .collect::>(); + + if spans.is_empty() { + return; + } + + span_lint_and_then( + cx, + POINTERS_IN_NOMEM_ASM_BLOCK, + spans, + "passing pointers to nomem asm block", + additional_notes, + ); +} + +fn has_in_operand_pointer(cx: &LateContext<'_>, asm_op: &InlineAsmOperand<'_>) -> bool { + let asm_in_expr = match asm_op { + InlineAsmOperand::SymStatic { .. } + | InlineAsmOperand::Out { .. } + | InlineAsmOperand::Const { .. } + | InlineAsmOperand::SymFn { .. } + | InlineAsmOperand::Label { .. } => return false, + InlineAsmOperand::SplitInOut { in_expr, .. } => in_expr, + InlineAsmOperand::In { expr, .. } | InlineAsmOperand::InOut { expr, .. } => expr, + }; + + // This checks for raw ptrs, refs and function pointers - the last one + // also technically counts as reading memory. + cx.typeck_results().expr_ty(asm_in_expr).is_any_ptr() +} + +fn additional_notes(diag: &mut rustc_errors::Diag<'_, ()>) { + diag.note("`nomem` means that no memory write or read happens inside the asm! block"); + diag.note("if this is intentional and no pointers are read or written to, consider allowing the lint"); +} diff --git a/tests/ui/pointers_in_nomem_asm_block.rs b/tests/ui/pointers_in_nomem_asm_block.rs new file mode 100644 index 0000000000000..b5abcbb3474c2 --- /dev/null +++ b/tests/ui/pointers_in_nomem_asm_block.rs @@ -0,0 +1,33 @@ +//@ needs-asm-support +#![warn(clippy::pointers_in_nomem_asm_block)] +#![crate_type = "lib"] +#![no_std] + +use core::arch::asm; + +unsafe fn nomem_bad(p: &i32) { + asm!( + "asdf {p1}, {p2}, {p3}", + p1 = in(reg) p, + //~^ ERROR: passing pointers to nomem asm block + p2 = in(reg) p as *const _ as usize, + p3 = in(reg) p, + options(nomem, nostack, preserves_flags) + ); +} + +unsafe fn nomem_good(p: &i32) { + asm!("asdf {p}", p = in(reg) p, options(readonly, nostack, preserves_flags)); + let p = p as *const i32 as usize; + asm!("asdf {p}", p = in(reg) p, options(nomem, nostack, preserves_flags)); +} + +unsafe fn nomem_bad2(p: &mut i32) { + asm!("asdf {p}", p = in(reg) p, options(nomem, nostack, preserves_flags)); + //~^ ERROR: passing pointers to nomem asm block +} + +unsafe fn nomem_fn(p: extern "C" fn()) { + asm!("call {p}", p = in(reg) p, options(nomem)); + //~^ ERROR: passing pointers to nomem asm block +} diff --git a/tests/ui/pointers_in_nomem_asm_block.stderr b/tests/ui/pointers_in_nomem_asm_block.stderr new file mode 100644 index 0000000000000..cabeb37344f2b --- /dev/null +++ b/tests/ui/pointers_in_nomem_asm_block.stderr @@ -0,0 +1,34 @@ +error: passing pointers to nomem asm block + --> tests/ui/pointers_in_nomem_asm_block.rs:11:9 + | +LL | p1 = in(reg) p, + | ^^^^^^^^^^^^^^ +... +LL | p3 = in(reg) p, + | ^^^^^^^^^^^^^^ + | + = note: `nomem` means that no memory write or read happens inside the asm! block + = note: if this is intentional and no pointers are read or written to, consider allowing the lint + = note: `-D clippy::pointers-in-nomem-asm-block` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::pointers_in_nomem_asm_block)]` + +error: passing pointers to nomem asm block + --> tests/ui/pointers_in_nomem_asm_block.rs:26:22 + | +LL | asm!("asdf {p}", p = in(reg) p, options(nomem, nostack, preserves_flags)); + | ^^^^^^^^^^^^^ + | + = note: `nomem` means that no memory write or read happens inside the asm! block + = note: if this is intentional and no pointers are read or written to, consider allowing the lint + +error: passing pointers to nomem asm block + --> tests/ui/pointers_in_nomem_asm_block.rs:31:22 + | +LL | asm!("call {p}", p = in(reg) p, options(nomem)); + | ^^^^^^^^^^^^^ + | + = note: `nomem` means that no memory write or read happens inside the asm! block + = note: if this is intentional and no pointers are read or written to, consider allowing the lint + +error: aborting due to 3 previous errors + From 040239465aefc09f8c837ff9d4d66ca6297e5c5c Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Fri, 9 Aug 2024 09:52:12 +0200 Subject: [PATCH 0449/2194] Add an internal lint that warns when accessing untracked data --- compiler/rustc_data_structures/src/steal.rs | 1 + compiler/rustc_feature/src/builtin_attrs.rs | 6 +++ compiler/rustc_lint/messages.ftl | 3 ++ compiler/rustc_lint/src/internal.rs | 24 +++++++++-- compiler/rustc_lint/src/lib.rs | 1 + compiler/rustc_lint/src/lints.rs | 7 ++++ compiler/rustc_passes/src/check_attr.rs | 40 ++++--------------- compiler/rustc_span/src/symbol.rs | 1 + .../crates/hir-expand/src/inert_attr_macro.rs | 3 ++ .../internal-lints/query_completeness.rs | 16 ++++++++ .../internal-lints/query_completeness.stderr | 15 +++++++ 11 files changed, 82 insertions(+), 35 deletions(-) create mode 100644 tests/ui-fulldeps/internal-lints/query_completeness.rs create mode 100644 tests/ui-fulldeps/internal-lints/query_completeness.stderr diff --git a/compiler/rustc_data_structures/src/steal.rs b/compiler/rustc_data_structures/src/steal.rs index 0f2c0eee27d2f..aaa95f6b7f19e 100644 --- a/compiler/rustc_data_structures/src/steal.rs +++ b/compiler/rustc_data_structures/src/steal.rs @@ -57,6 +57,7 @@ impl Steal { /// /// This should not be used within rustc as it leaks information not tracked /// by the query system, breaking incremental compilation. + #[cfg_attr(not(bootstrap), rustc_lint_untracked_query_information)] pub fn is_stolen(&self) -> bool { self.value.borrow().is_none() } diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs index e2491922b8df6..e86421f2150db 100644 --- a/compiler/rustc_feature/src/builtin_attrs.rs +++ b/compiler/rustc_feature/src/builtin_attrs.rs @@ -793,6 +793,12 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ rustc_lint_query_instability, Normal, template!(Word), WarnFollowing, EncodeCrossCrate::Yes, INTERNAL_UNSTABLE ), + // Used by the `rustc::untracked_query_information` lint to warn methods which + // might not be stable during incremental compilation. + rustc_attr!( + rustc_lint_untracked_query_information, Normal, template!(Word), + WarnFollowing, EncodeCrossCrate::Yes, INTERNAL_UNSTABLE + ), // Used by the `rustc::diagnostic_outside_of_impl` lints to assist in changes to diagnostic // APIs. Any function with this attribute will be checked by that lint. rustc_attr!( diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl index 353345958337c..759320b9eb65f 100644 --- a/compiler/rustc_lint/messages.ftl +++ b/compiler/rustc_lint/messages.ftl @@ -699,6 +699,9 @@ lint_ptr_null_checks_ref = references are not nullable, so checking them for nul lint_query_instability = using `{$query}` can result in unstable query results .note = if you believe this case to be fine, allow this lint and add a comment explaining your rationale +lint_query_untracked = `{$method}` accesses information that is not tracked by the query system + .note = if you believe this case to be fine, allow this lint and add a comment explaining your rationale + lint_range_endpoint_out_of_range = range endpoint is out of range for `{$ty}` lint_range_use_inclusive_range = use an inclusive range instead diff --git a/compiler/rustc_lint/src/internal.rs b/compiler/rustc_lint/src/internal.rs index 2e8116b8ba892..9d637c1eb7f84 100644 --- a/compiler/rustc_lint/src/internal.rs +++ b/compiler/rustc_lint/src/internal.rs @@ -17,8 +17,8 @@ use tracing::debug; use crate::lints::{ BadOptAccessDiag, DefaultHashTypesDiag, DiagOutOfImpl, LintPassByHand, NonExistentDocKeyword, - NonGlobImportTypeIrInherent, QueryInstability, SpanUseEqCtxtDiag, TyQualified, TykindDiag, - TykindKind, TypeIrInherentUsage, UntranslatableDiag, + NonGlobImportTypeIrInherent, QueryInstability, QueryUntracked, SpanUseEqCtxtDiag, TyQualified, + TykindDiag, TykindKind, TypeIrInherentUsage, UntranslatableDiag, }; use crate::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext}; @@ -88,7 +88,18 @@ declare_tool_lint! { report_in_external_macro: true } -declare_lint_pass!(QueryStability => [POTENTIAL_QUERY_INSTABILITY]); +declare_tool_lint! { + /// The `untracked_query_information` lint detects use of methods which leak information not + /// tracked by the query system, such as whether a `Steal` value has already been stolen. In + /// order not to break incremental compilation, such methods must be used very carefully or not + /// at all. + pub rustc::UNTRACKED_QUERY_INFORMATION, + Allow, + "require explicit opt-in when accessing information not tracked by the query system", + report_in_external_macro: true +} + +declare_lint_pass!(QueryStability => [POTENTIAL_QUERY_INSTABILITY, UNTRACKED_QUERY_INFORMATION]); impl LateLintPass<'_> for QueryStability { fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) { @@ -102,6 +113,13 @@ impl LateLintPass<'_> for QueryStability { QueryInstability { query: cx.tcx.item_name(def_id) }, ); } + if cx.tcx.has_attr(def_id, sym::rustc_lint_untracked_query_information) { + cx.emit_span_lint( + UNTRACKED_QUERY_INFORMATION, + span, + QueryUntracked { method: cx.tcx.item_name(def_id) }, + ); + } } } } diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs index c5a5c5b30afef..105a90de03407 100644 --- a/compiler/rustc_lint/src/lib.rs +++ b/compiler/rustc_lint/src/lib.rs @@ -609,6 +609,7 @@ fn register_internals(store: &mut LintStore) { vec![ LintId::of(DEFAULT_HASH_TYPES), LintId::of(POTENTIAL_QUERY_INSTABILITY), + LintId::of(UNTRACKED_QUERY_INFORMATION), LintId::of(USAGE_OF_TY_TYKIND), LintId::of(PASS_BY_VALUE), LintId::of(LINT_PASS_IMPL_WITHOUT_MACRO), diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index 7ca282b7c8541..9050f36acba7b 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -894,6 +894,13 @@ pub(crate) struct QueryInstability { pub query: Symbol, } +#[derive(LintDiagnostic)] +#[diag(lint_query_untracked)] +#[note] +pub(crate) struct QueryUntracked { + pub method: Symbol, +} + #[derive(LintDiagnostic)] #[diag(lint_span_use_eq_ctxt)] pub(crate) struct SpanUseEqCtxtDiag; diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 21478a44b0e14..e41f89a3c9da9 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -125,7 +125,9 @@ impl<'tcx> CheckAttrVisitor<'tcx> { [sym::inline, ..] => self.check_inline(hir_id, attr, span, target), [sym::coverage, ..] => self.check_coverage(attr, span, target), [sym::optimize, ..] => self.check_optimize(hir_id, attr, target), - [sym::no_sanitize, ..] => self.check_no_sanitize(hir_id, attr, span, target), + [sym::no_sanitize, ..] => { + self.check_applied_to_fn_or_method(hir_id, attr, span, target) + } [sym::non_exhaustive, ..] => self.check_non_exhaustive(hir_id, attr, span, target), [sym::marker, ..] => self.check_marker(hir_id, attr, span, target), [sym::target_feature, ..] => { @@ -166,10 +168,13 @@ impl<'tcx> CheckAttrVisitor<'tcx> { self.check_rustc_legacy_const_generics(hir_id, attr, span, target, item) } [sym::rustc_lint_query_instability, ..] => { - self.check_rustc_lint_query_instability(hir_id, attr, span, target) + self.check_applied_to_fn_or_method(hir_id, attr, span, target) + } + [sym::rustc_lint_untracked_query_information, ..] => { + self.check_applied_to_fn_or_method(hir_id, attr, span, target) } [sym::rustc_lint_diagnostics, ..] => { - self.check_rustc_lint_diagnostics(hir_id, attr, span, target) + self.check_applied_to_fn_or_method(hir_id, attr, span, target) } [sym::rustc_lint_opt_ty, ..] => self.check_rustc_lint_opt_ty(attr, span, target), [sym::rustc_lint_opt_deny_field_access, ..] => { @@ -452,11 +457,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> { } } - /// Checks that `#[no_sanitize(..)]` is applied to a function or method. - fn check_no_sanitize(&self, hir_id: HirId, attr: &Attribute, span: Span, target: Target) { - self.check_applied_to_fn_or_method(hir_id, attr, span, target) - } - fn check_generic_attr( &self, hir_id: HirId, @@ -1635,30 +1635,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> { } } - /// Checks that the `#[rustc_lint_query_instability]` attribute is only applied to a function - /// or method. - fn check_rustc_lint_query_instability( - &self, - hir_id: HirId, - attr: &Attribute, - span: Span, - target: Target, - ) { - self.check_applied_to_fn_or_method(hir_id, attr, span, target) - } - - /// Checks that the `#[rustc_lint_diagnostics]` attribute is only applied to a function or - /// method. - fn check_rustc_lint_diagnostics( - &self, - hir_id: HirId, - attr: &Attribute, - span: Span, - target: Target, - ) { - self.check_applied_to_fn_or_method(hir_id, attr, span, target) - } - /// Checks that the `#[rustc_lint_opt_ty]` attribute is only applied to a struct. fn check_rustc_lint_opt_ty(&self, attr: &Attribute, span: Span, target: Target) { match target { diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 3476520960585..cc63769d51df6 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1653,6 +1653,7 @@ symbols! { rustc_lint_opt_deny_field_access, rustc_lint_opt_ty, rustc_lint_query_instability, + rustc_lint_untracked_query_information, rustc_macro_transparency, rustc_main, rustc_mir, diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/inert_attr_macro.rs b/src/tools/rust-analyzer/crates/hir-expand/src/inert_attr_macro.rs index ee15b1b5ce9d5..5c25a55362e64 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/inert_attr_macro.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/inert_attr_macro.rs @@ -464,6 +464,9 @@ pub const INERT_ATTRIBUTES: &[BuiltinAttribute] = &[ // Used by the `rustc::potential_query_instability` lint to warn methods which // might not be stable during incremental compilation. rustc_attr!(rustc_lint_query_instability, Normal, template!(Word), WarnFollowing, INTERNAL_UNSTABLE), + // Used by the `rustc::untracked_query_information` lint to warn methods which + // might break incremental compilation. + rustc_attr!(rustc_lint_untracked_query_information, Normal, template!(Word), WarnFollowing, INTERNAL_UNSTABLE), // Used by the `rustc::untranslatable_diagnostic` and `rustc::diagnostic_outside_of_impl` lints // to assist in changes to diagnostic APIs. rustc_attr!(rustc_lint_diagnostics, Normal, template!(Word), WarnFollowing, INTERNAL_UNSTABLE), diff --git a/tests/ui-fulldeps/internal-lints/query_completeness.rs b/tests/ui-fulldeps/internal-lints/query_completeness.rs new file mode 100644 index 0000000000000..50b0fb4c3fc02 --- /dev/null +++ b/tests/ui-fulldeps/internal-lints/query_completeness.rs @@ -0,0 +1,16 @@ +//@ compile-flags: -Z unstable-options +// #[cfg(bootstrap)]: We can stop ignoring next beta bump; afterward this ALWAYS should run. +//@ ignore-stage1 (requires matching sysroot built with in-tree compiler) +#![feature(rustc_private)] +#![deny(rustc::untracked_query_information)] + +extern crate rustc_data_structures; + +use rustc_data_structures::steal::Steal; + +fn use_steal(x: Steal<()>) { + let _ = x.is_stolen(); + //~^ ERROR `is_stolen` accesses information that is not tracked by the query system +} + +fn main() {} diff --git a/tests/ui-fulldeps/internal-lints/query_completeness.stderr b/tests/ui-fulldeps/internal-lints/query_completeness.stderr new file mode 100644 index 0000000000000..35bb867f40e8f --- /dev/null +++ b/tests/ui-fulldeps/internal-lints/query_completeness.stderr @@ -0,0 +1,15 @@ +error: `is_stolen` accesses information that is not tracked by the query system + --> $DIR/query_completeness.rs:12:15 + | +LL | let _ = x.is_stolen(); + | ^^^^^^^^^ + | + = note: if you believe this case to be fine, allow this lint and add a comment explaining your rationale +note: the lint level is defined here + --> $DIR/query_completeness.rs:5:9 + | +LL | #![deny(rustc::untracked_query_information)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + From b5d07fd3567f5ca42b677ffd9cf4756c5dbf12ba Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Tue, 3 Sep 2024 21:03:46 +0300 Subject: [PATCH 0450/2194] copy rustc rustlib artifacts from ci-rustc We recently had an issue because some rustlib files were missing (like: "error[E0463]: can't find crate for rustc_ast") when building tools that rely on rustc. This patch fixes that by copying those files as required. Signed-off-by: onur-ozkan --- src/bootstrap/src/core/build_steps/compile.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/bootstrap/src/core/build_steps/compile.rs b/src/bootstrap/src/core/build_steps/compile.rs index eef548033f1c6..71e217bbbfc42 100644 --- a/src/bootstrap/src/core/build_steps/compile.rs +++ b/src/bootstrap/src/core/build_steps/compile.rs @@ -931,7 +931,12 @@ impl Step for Rustc { // NOTE: the ABI of the beta compiler is different from the ABI of the downloaded compiler, // so its artifacts can't be reused. if builder.download_rustc() && compiler.stage != 0 { - builder.ensure(Sysroot { compiler, force_recompile: false }); + let sysroot = builder.ensure(Sysroot { compiler, force_recompile: false }); + cp_rustc_component_to_ci_sysroot( + builder, + &sysroot, + builder.config.ci_rustc_dev_contents(), + ); return compiler.stage; } From 65e78db8d7b41ec40fd9b789a96df12fd3d18180 Mon Sep 17 00:00:00 2001 From: Godfrey Chan Date: Tue, 3 Sep 2024 11:27:34 -0700 Subject: [PATCH 0451/2194] Elaborate on deriving vs implementing `Copy` --- library/core/src/marker.rs | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/library/core/src/marker.rs b/library/core/src/marker.rs index 5654f5aa4b8d2..91ec046eeabdd 100644 --- a/library/core/src/marker.rs +++ b/library/core/src/marker.rs @@ -288,8 +288,18 @@ marker_impls! { /// } /// ``` /// -/// There is a small difference between the two: the `derive` strategy will also place a `Copy` -/// bound on type parameters, which isn't always desired. +/// There is a small difference between the two. The `derive` strategy will also place a `Copy` +/// bound on type parameters: +/// +/// ``` +/// struct MyStruct; +/// +/// impl Copy for MyStruct { } +/// ``` +/// +/// This isn't always desired. For example, shared references (`&T`) can be copied regardless of +/// whether `T` is `Copy`. Likewise, a generic struct containing markers such as [`PhantomData`] +/// could potentially be duplicated with a bit-wise copy. /// /// ## What's the difference between `Copy` and `Clone`? /// From e98e88bfdf810d74540fcc0a464608683a7eacc7 Mon Sep 17 00:00:00 2001 From: liushuyu Date: Tue, 3 Sep 2024 12:42:57 -0600 Subject: [PATCH 0452/2194] rustc_codegen_llvm: fix a regression where backchain feature ... ... can not be correctly gated using #[cfg] macro --- compiler/rustc_codegen_llvm/src/llvm_util.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/llvm_util.rs b/compiler/rustc_codegen_llvm/src/llvm_util.rs index 618602ed70f44..d55220ba5c3a4 100644 --- a/compiler/rustc_codegen_llvm/src/llvm_util.rs +++ b/compiler/rustc_codegen_llvm/src/llvm_util.rs @@ -353,9 +353,7 @@ pub fn target_features(sess: &Session, allow_unstable: bool) -> Vec { None } }) - .filter(|feature| { - RUSTC_SPECIAL_FEATURES.contains(feature) || features.contains(&Symbol::intern(feature)) - }) + .filter(|feature| features.contains(&Symbol::intern(feature))) .map(|feature| Symbol::intern(feature)) .collect() } From 3626b66af05e00b7b836a620e0d5236a64f3a89b Mon Sep 17 00:00:00 2001 From: Godfrey Chan Date: Tue, 3 Sep 2024 11:43:03 -0700 Subject: [PATCH 0453/2194] Update marker.rs --- library/core/src/marker.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/core/src/marker.rs b/library/core/src/marker.rs index 91ec046eeabdd..dfc988c885e25 100644 --- a/library/core/src/marker.rs +++ b/library/core/src/marker.rs @@ -299,7 +299,7 @@ marker_impls! { /// /// This isn't always desired. For example, shared references (`&T`) can be copied regardless of /// whether `T` is `Copy`. Likewise, a generic struct containing markers such as [`PhantomData`] -/// could potentially be duplicated with a bit-wise copy. +/// could potentially be duplicated with a bit-wise copy. /// /// ## What's the difference between `Copy` and `Clone`? /// From efc20deb57b142af1a0ce59af9d60479bef5b902 Mon Sep 17 00:00:00 2001 From: Godfrey Chan Date: Tue, 3 Sep 2024 12:18:46 -0700 Subject: [PATCH 0454/2194] Update marker.rs --- library/core/src/marker.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/library/core/src/marker.rs b/library/core/src/marker.rs index dfc988c885e25..62f35c1bfa2a6 100644 --- a/library/core/src/marker.rs +++ b/library/core/src/marker.rs @@ -292,9 +292,10 @@ marker_impls! { /// bound on type parameters: /// /// ``` +/// #[derive(Clone)] /// struct MyStruct; /// -/// impl Copy for MyStruct { } +/// impl Copy for MyStruct { } /// ``` /// /// This isn't always desired. For example, shared references (`&T`) can be copied regardless of From 277a08c7d800880863a1386e19379efb98ca3f07 Mon Sep 17 00:00:00 2001 From: Godfrey Chan Date: Tue, 3 Sep 2024 12:20:36 -0700 Subject: [PATCH 0455/2194] Update marker.rs --- library/core/src/marker.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/core/src/marker.rs b/library/core/src/marker.rs index 62f35c1bfa2a6..a13cef26dee07 100644 --- a/library/core/src/marker.rs +++ b/library/core/src/marker.rs @@ -293,7 +293,7 @@ marker_impls! { /// /// ``` /// #[derive(Clone)] -/// struct MyStruct; +/// struct MyStruct(T); /// /// impl Copy for MyStruct { } /// ``` From 1681c91a356af14a2425a2017fea2fc675c8200a Mon Sep 17 00:00:00 2001 From: Yacin Tmimi Date: Tue, 9 Jul 2024 02:20:31 -0400 Subject: [PATCH 0456/2194] implement version-sorting algorithm for rust identifiers The algorithm is described in the [style guide] and was introduced in `r-l/rust 115046`. [style guide]: https://doc.rust-lang.org/nightly/style-guide/#sorting --- src/lib.rs | 1 + src/sort.rs | 368 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 369 insertions(+) create mode 100644 src/sort.rs diff --git a/src/lib.rs b/src/lib.rs index 7dc698dd92c42..1f186b87767f1 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -93,6 +93,7 @@ mod rewrite; pub(crate) mod rustfmt_diff; mod shape; mod skip; +mod sort; pub(crate) mod source_file; pub(crate) mod source_map; mod spanned; diff --git a/src/sort.rs b/src/sort.rs new file mode 100644 index 0000000000000..670f664a11949 --- /dev/null +++ b/src/sort.rs @@ -0,0 +1,368 @@ +use itertools::EitherOrBoth; +use itertools::Itertools; + +/// Iterator which breaks an identifier into various [VersionChunk]s. +struct VersionChunkIter<'a> { + ident: &'a str, + start: usize, +} + +impl<'a> VersionChunkIter<'a> { + pub(crate) fn new(ident: &'a str) -> Self { + Self { ident, start: 0 } + } + + fn parse_numeric_chunk( + &mut self, + mut chars: std::str::CharIndices<'a>, + ) -> Option> { + let mut end = self.start; + let mut is_end_of_chunk = false; + + while let Some((idx, c)) = chars.next() { + end = self.start + idx; + + if c.is_ascii_digit() { + continue; + } + + is_end_of_chunk = true; + break; + } + + let source = if is_end_of_chunk { + let value = &self.ident[self.start..end]; + self.start = end; + value + } else { + let value = &self.ident[self.start..]; + self.start = self.ident.len(); + value + }; + + let zeros = source.chars().take_while(|c| *c == '0').count(); + let value = source.parse::().ok()?; + + Some(VersionChunk::Number { + value, + zeros, + source, + }) + } + + fn parse_str_chunk( + &mut self, + mut chars: std::str::CharIndices<'a>, + ) -> Option> { + let mut end = self.start; + let mut is_end_of_chunk = false; + + while let Some((idx, c)) = chars.next() { + end = self.start + idx; + + if c == '_' { + is_end_of_chunk = true; + break; + } + + if !c.is_numeric() { + continue; + } + + is_end_of_chunk = true; + break; + } + + let source = if is_end_of_chunk { + let value = &self.ident[self.start..end]; + self.start = end; + value + } else { + let value = &self.ident[self.start..]; + self.start = self.ident.len(); + value + }; + + Some(VersionChunk::Str(source)) + } +} + +impl<'a> Iterator for VersionChunkIter<'a> { + type Item = VersionChunk<'a>; + + fn next(&mut self) -> Option { + let mut chars = self.ident[self.start..].char_indices(); + let (_, next) = chars.next()?; + + if next == '_' { + self.start = self.start + next.len_utf8(); + return Some(VersionChunk::Underscore); + } + + if next.is_ascii_digit() { + return self.parse_numeric_chunk(chars); + } + + self.parse_str_chunk(chars) + } +} + +/// Represents a chunk in the version-sort algorithm +#[derive(Debug, PartialEq, Eq)] +enum VersionChunk<'a> { + /// A single `_` in an identifier. Underscores are sorted before all other characters. + Underscore, + /// A &str chunk in the version sort. + Str(&'a str), + /// A numeric chunk in the version sort. Keeps track of the numeric value and leading zeros. + Number { + value: usize, + zeros: usize, + source: &'a str, + }, +} + +/// Determine which side of the version-sort comparison had more leading zeros. +#[derive(Debug, PartialEq, Eq)] +enum MoreLeadingZeros { + Left, + Right, + Equal, +} + +/// Compare two identifiers based on the version sorting algorithm described in [the style guide] +/// +/// [the style guide]: https://doc.rust-lang.org/nightly/style-guide/#sorting +pub(crate) fn version_sort(a: &str, b: &str) -> std::cmp::Ordering { + let iter_a = VersionChunkIter::new(a); + let iter_b = VersionChunkIter::new(b); + let mut more_leading_zeros = MoreLeadingZeros::Equal; + + for either_or_both in iter_a.zip_longest(iter_b) { + match either_or_both { + EitherOrBoth::Left(_) => return std::cmp::Ordering::Greater, + EitherOrBoth::Right(_) => return std::cmp::Ordering::Less, + EitherOrBoth::Both(a, b) => match (a, b) { + (VersionChunk::Underscore, VersionChunk::Underscore) => { + continue; + } + (VersionChunk::Underscore, _) => return std::cmp::Ordering::Less, + (_, VersionChunk::Underscore) => return std::cmp::Ordering::Greater, + (VersionChunk::Str(ca), VersionChunk::Str(cb)) + | (VersionChunk::Str(ca), VersionChunk::Number { source: cb, .. }) + | (VersionChunk::Number { source: ca, .. }, VersionChunk::Str(cb)) => { + match ca.cmp(&cb) { + std::cmp::Ordering::Equal => { + continue; + } + order @ _ => return order, + } + } + ( + VersionChunk::Number { + value: va, + zeros: lza, + .. + }, + VersionChunk::Number { + value: vb, + zeros: lzb, + .. + }, + ) => match va.cmp(&vb) { + std::cmp::Ordering::Equal => { + if lza == lzb { + continue; + } + + if more_leading_zeros == MoreLeadingZeros::Equal && lza > lzb { + more_leading_zeros = MoreLeadingZeros::Left; + } else if more_leading_zeros == MoreLeadingZeros::Equal && lza < lzb { + more_leading_zeros = MoreLeadingZeros::Right; + } + continue; + } + order @ _ => return order, + }, + }, + } + } + + match more_leading_zeros { + MoreLeadingZeros::Equal => std::cmp::Ordering::Equal, + MoreLeadingZeros::Left => std::cmp::Ordering::Less, + MoreLeadingZeros::Right => std::cmp::Ordering::Greater, + } +} + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn test_chunks() { + let mut iter = VersionChunkIter::new("x86_128"); + assert_eq!(iter.next(), Some(VersionChunk::Str("x"))); + assert_eq!( + iter.next(), + Some(VersionChunk::Number { + value: 86, + zeros: 0, + source: "86" + }) + ); + assert_eq!(iter.next(), Some(VersionChunk::Underscore)); + assert_eq!( + iter.next(), + Some(VersionChunk::Number { + value: 128, + zeros: 0, + source: "128" + }) + ); + assert_eq!(iter.next(), None); + + let mut iter = VersionChunkIter::new("w005s09t"); + assert_eq!(iter.next(), Some(VersionChunk::Str("w"))); + assert_eq!( + iter.next(), + Some(VersionChunk::Number { + value: 5, + zeros: 2, + source: "005" + }) + ); + assert_eq!(iter.next(), Some(VersionChunk::Str("s"))); + assert_eq!( + iter.next(), + Some(VersionChunk::Number { + value: 9, + zeros: 1, + source: "09" + }) + ); + assert_eq!(iter.next(), Some(VersionChunk::Str("t"))); + assert_eq!(iter.next(), None); + + let mut iter = VersionChunkIter::new("ZY_WX"); + assert_eq!(iter.next(), Some(VersionChunk::Str("ZY"))); + assert_eq!(iter.next(), Some(VersionChunk::Underscore)); + assert_eq!(iter.next(), Some(VersionChunk::Str("WX"))); + + let mut iter = VersionChunkIter::new("_v1"); + assert_eq!(iter.next(), Some(VersionChunk::Underscore)); + assert_eq!(iter.next(), Some(VersionChunk::Str("v"))); + assert_eq!( + iter.next(), + Some(VersionChunk::Number { + value: 1, + zeros: 0, + source: "1" + }) + ); + + let mut iter = VersionChunkIter::new("_1v"); + assert_eq!(iter.next(), Some(VersionChunk::Underscore)); + assert_eq!( + iter.next(), + Some(VersionChunk::Number { + value: 1, + zeros: 0, + source: "1" + }) + ); + assert_eq!(iter.next(), Some(VersionChunk::Str("v"))); + + let mut iter = VersionChunkIter::new("v009"); + assert_eq!(iter.next(), Some(VersionChunk::Str("v"))); + assert_eq!( + iter.next(), + Some(VersionChunk::Number { + value: 9, + zeros: 2, + source: "009" + }) + ); + } + + #[test] + fn test_version_sort() { + let mut input = vec!["", "b", "a"]; + let expected = vec!["", "a", "b"]; + input.sort_by(|a, b| version_sort(a, b)); + assert_eq!(input, expected); + + let mut input = vec!["x7x", "xxx"]; + let expected = vec!["x7x", "xxx"]; + input.sort_by(|a, b| version_sort(a, b)); + assert_eq!(input, expected); + + let mut input = vec!["applesauce", "apple"]; + let expected = vec!["apple", "applesauce"]; + input.sort_by(|a, b| version_sort(a, b)); + assert_eq!(input, expected); + + let mut input = vec!["aaaaa", "aaa_a"]; + let expected = vec!["aaa_a", "aaaaa"]; + input.sort_by(|a, b| version_sort(a, b)); + assert_eq!(input, expected); + + let mut input = vec!["AAAAA", "AAA1A", "BBBBB", "BB_BB", "C3CCC"]; + let expected = vec!["AAA1A", "AAAAA", "BB_BB", "BBBBB", "C3CCC"]; + input.sort_by(|a, b| version_sort(a, b)); + assert_eq!(input, expected); + + let mut input = vec!["1_000_000", "1_010_001"]; + let expected = vec!["1_000_000", "1_010_001"]; + input.sort_by(|a, b| version_sort(a, b)); + assert_eq!(input, expected); + + let mut input = vec![ + "5", "50", "500", "5_000", "5_005", "5_050", "5_500", "50_000", "50_005", "50_050", + "50_500", + ]; + let expected = vec![ + "5", "5_000", "5_005", "5_050", "5_500", "50", "50_000", "50_005", "50_050", "50_500", + "500", + ]; + input.sort_by(|a, b| version_sort(a, b)); + assert_eq!(input, expected); + + let mut input = vec!["X86_64", "x86_64", "X86_128", "x86_128"]; + let expected = vec!["X86_64", "X86_128", "x86_64", "x86_128"]; + input.sort_by(|a, b| version_sort(a, b)); + assert_eq!(input, expected); + + let mut input = vec!["__", "_"]; + let expected = vec!["_", "__"]; + input.sort_by(|a, b| version_sort(a, b)); + assert_eq!(input, expected); + + let mut input = vec!["foo_", "foo"]; + let expected = vec!["foo", "foo_"]; + input.sort_by(|a, b| version_sort(a, b)); + assert_eq!(input, expected); + + let mut input = vec!["A", "AA", "B", "a", "aA", "aa", "b"]; + let expected = vec!["A", "AA", "B", "a", "aA", "aa", "b"]; + input.sort_by(|a, b| version_sort(a, b)); + assert_eq!(input, expected); + + let mut input = vec![ + "x86_128", "usize", "uz", "v000", "v00", "v0", "v0s", "v00t", "v0u", "v001", "v01", + "v1", "v009", "x87", "zyxw", "_ZYXW", "_abcd", "A2", "ABCD", "Z_YXW", "ZY_XW", "ZY_XW", + "ZYXW", "v09", "v9", "v010", "v10", "w005s09t", "w5s009t", "x64", "x86", "x86_32", + "ua", "x86_64", "ZYXW_", "a1", "abcd", "u_zzz", "u8", "u16", "u32", "u64", "u128", + "u256", + ]; + let expected = vec![ + "_ZYXW", "_abcd", "A2", "ABCD", "Z_YXW", "ZY_XW", "ZY_XW", "ZYXW", "ZYXW_", "a1", + "abcd", "u_zzz", "u8", "u16", "u32", "u64", "u128", "u256", "ua", "usize", "uz", + "v000", "v00", "v0", "v0s", "v00t", "v0u", "v001", "v01", "v1", "v009", "v09", "v9", + "v010", "v10", "w005s09t", "w5s009t", "x64", "x86", "x86_32", "x86_64", "x86_128", + "x87", "zyxw", + ]; + input.sort_by(|a, b| version_sort(a, b)); + assert_eq!(input, expected) + } +} From 296417260c6a53fca85a0adf1dfd6a9b3760768f Mon Sep 17 00:00:00 2001 From: Yacin Tmimi Date: Tue, 9 Jul 2024 02:28:11 -0400 Subject: [PATCH 0457/2194] use version-sort when reordering imports using `style_edition=2024` --- src/imports.rs | 40 +++++++++++++++++++++++----------------- 1 file changed, 23 insertions(+), 17 deletions(-) diff --git a/src/imports.rs b/src/imports.rs index 94b62ef7aa030..868314354b048 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -21,6 +21,7 @@ use crate::lists::{ }; use crate::rewrite::{Rewrite, RewriteContext, RewriteErrorExt, RewriteResult}; use crate::shape::Shape; +use crate::sort::version_sort; use crate::source_map::SpanUtils; use crate::spanned::Spanned; use crate::utils::{is_same_visibility, mk_sp, rewrite_ident}; @@ -923,7 +924,7 @@ impl Ord for UseSegment { | (Crate(ref a), Crate(ref b)) => match (a, b) { (Some(sa), Some(sb)) => { if self.style_edition >= StyleEdition::Edition2024 { - sa.trim_start_matches("r#").cmp(sb.trim_start_matches("r#")) + version_sort(sa.trim_start_matches("r#"), sb.trim_start_matches("r#")) } else { a.cmp(b) } @@ -937,20 +938,26 @@ impl Ord for UseSegment { } else { (pia.as_str(), pib.as_str()) }; - // snake_case < CamelCase < UPPER_SNAKE_CASE - if ia.starts_with(char::is_uppercase) && ib.starts_with(char::is_lowercase) { - return Ordering::Greater; - } - if ia.starts_with(char::is_lowercase) && ib.starts_with(char::is_uppercase) { - return Ordering::Less; - } - if is_upper_snake_case(ia) && !is_upper_snake_case(ib) { - return Ordering::Greater; - } - if !is_upper_snake_case(ia) && is_upper_snake_case(ib) { - return Ordering::Less; - } - let ident_ord = ia.cmp(ib); + + let ident_ord = if self.style_edition >= StyleEdition::Edition2024 { + version_sort(ia, ib) + } else { + // snake_case < CamelCase < UPPER_SNAKE_CASE + if ia.starts_with(char::is_uppercase) && ib.starts_with(char::is_lowercase) { + return Ordering::Greater; + } + if ia.starts_with(char::is_lowercase) && ib.starts_with(char::is_uppercase) { + return Ordering::Less; + } + if is_upper_snake_case(ia) && !is_upper_snake_case(ib) { + return Ordering::Greater; + } + if !is_upper_snake_case(ia) && is_upper_snake_case(ib) { + return Ordering::Less; + } + ia.cmp(ib) + }; + if ident_ord != Ordering::Equal { return ident_ord; } @@ -959,8 +966,7 @@ impl Ord for UseSegment { (Some(_), None) => Ordering::Greater, (Some(aas), Some(abs)) => { if self.style_edition >= StyleEdition::Edition2024 { - aas.trim_start_matches("r#") - .cmp(abs.trim_start_matches("r#")) + version_sort(aas.trim_start_matches("r#"), abs.trim_start_matches("r#")) } else { aas.cmp(abs) } From ae59ee755afdbc086c10ce8d693f363a40e3216e Mon Sep 17 00:00:00 2001 From: Yacin Tmimi Date: Fri, 16 Aug 2024 14:34:06 -0400 Subject: [PATCH 0458/2194] sort rustfmt imports The version-sort algorithm makes changes to the sort order of imports, and we're updating them here for the self tests. --- config_proc_macro/src/utils.rs | 2 +- src/attr.rs | 12 ++++++------ src/bin/main.rs | 8 ++++---- src/chains.rs | 4 ++-- src/closures.rs | 6 +++--- src/comment.rs | 4 ++-- src/config/file_lines.rs | 2 +- src/config/options.rs | 4 ++-- src/emitter/checkstyle.rs | 2 +- src/emitter/json.rs | 2 +- src/emitter/modified_lines.rs | 2 +- src/expr.rs | 18 +++++++++--------- src/formatting.rs | 2 +- src/git-rustfmt/main.rs | 2 +- src/imports.rs | 6 +++--- src/items.rs | 17 ++++++++--------- src/lib.rs | 4 ++-- src/lists.rs | 2 +- src/macros.rs | 18 +++++++++--------- src/matches.rs | 10 +++++----- src/missed_spans.rs | 4 ++-- src/modules.rs | 2 +- src/overflow.rs | 8 ++++---- src/pairs.rs | 2 +- src/parse/macros/asm.rs | 2 +- src/parse/macros/cfg_if.rs | 2 +- src/parse/macros/mod.rs | 4 ++-- src/parse/parser.rs | 6 +++--- src/parse/session.rs | 5 +++-- src/patterns.rs | 14 +++++++------- src/reorder.rs | 6 +++--- src/rewrite.rs | 2 +- src/rustfmt_diff.rs | 2 +- src/source_file.rs | 2 +- src/spanned.rs | 2 +- src/stmt.rs | 2 +- src/string.rs | 2 +- src/test/configuration_snippet.rs | 4 ++-- src/test/mod.rs | 6 +++--- src/types.rs | 12 ++++++------ src/utils.rs | 4 ++-- src/vertical.rs | 2 +- src/visitor.rs | 12 ++++++------ 43 files changed, 117 insertions(+), 117 deletions(-) diff --git a/config_proc_macro/src/utils.rs b/config_proc_macro/src/utils.rs index f5cba87b07b67..1f5b5cdb604f0 100644 --- a/config_proc_macro/src/utils.rs +++ b/config_proc_macro/src/utils.rs @@ -1,5 +1,5 @@ use proc_macro2::TokenStream; -use quote::{quote, ToTokens}; +use quote::{ToTokens, quote}; pub fn fold_quote(input: impl Iterator, f: F) -> TokenStream where diff --git a/src/attr.rs b/src/attr.rs index 802dfc0485c26..ac57858ef7e95 100644 --- a/src/attr.rs +++ b/src/attr.rs @@ -1,20 +1,20 @@ //! Format attributes and meta items. -use rustc_ast::ast; use rustc_ast::HasAttrs; -use rustc_span::{symbol::sym, Span}; +use rustc_ast::ast; +use rustc_span::{Span, symbol::sym}; use self::doc_comment::DocCommentFormatter; -use crate::comment::{contains_comment, rewrite_doc_comment, CommentStyle}; -use crate::config::lists::*; +use crate::comment::{CommentStyle, contains_comment, rewrite_doc_comment}; use crate::config::IndentStyle; +use crate::config::lists::*; use crate::expr::rewrite_literal; -use crate::lists::{definitive_tactic, itemize_list, write_list, ListFormatting, Separator}; +use crate::lists::{ListFormatting, Separator, definitive_tactic, itemize_list, write_list}; use crate::overflow; use crate::rewrite::{Rewrite, RewriteContext, RewriteError, RewriteErrorExt, RewriteResult}; use crate::shape::Shape; use crate::source_map::SpanUtils; -use crate::types::{rewrite_path, PathContext}; +use crate::types::{PathContext, rewrite_path}; use crate::utils::{count_newlines, mk_sp}; mod doc_comment; diff --git a/src/bin/main.rs b/src/bin/main.rs index 3a0427d83720d..0d593c6c4168b 100644 --- a/src/bin/main.rs +++ b/src/bin/main.rs @@ -1,6 +1,6 @@ #![feature(rustc_private)] -use anyhow::{format_err, Result}; +use anyhow::{Result, format_err}; use io::Error as IoError; use thiserror::Error; @@ -11,15 +11,15 @@ use tracing_subscriber::EnvFilter; use std::collections::HashMap; use std::env; use std::fs::File; -use std::io::{self, stdout, Read, Write}; +use std::io::{self, Read, Write, stdout}; use std::path::{Path, PathBuf}; use std::str::FromStr; use getopts::{Matches, Options}; use crate::rustfmt::{ - load_config, CliOptions, Color, Config, Edition, EmitMode, FileLines, FileName, - FormatReportFormatterBuilder, Input, Session, StyleEdition, Verbosity, Version, + CliOptions, Color, Config, Edition, EmitMode, FileLines, FileName, + FormatReportFormatterBuilder, Input, Session, StyleEdition, Verbosity, Version, load_config, }; const BUG_REPORT_URL: &str = "https://github.com/rust-lang/rustfmt/issues/new?labels=bug"; diff --git a/src/chains.rs b/src/chains.rs index a3f7005542575..297eb268d30cd 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -59,9 +59,9 @@ use std::borrow::Cow; use std::cmp::min; use rustc_ast::{ast, ptr}; -use rustc_span::{symbol, BytePos, Span}; +use rustc_span::{BytePos, Span, symbol}; -use crate::comment::{rewrite_comment, CharClasses, FullCodeCharKind, RichChar}; +use crate::comment::{CharClasses, FullCodeCharKind, RichChar, rewrite_comment}; use crate::config::{IndentStyle, StyleEdition}; use crate::expr::rewrite_call; use crate::lists::extract_pre_comment; diff --git a/src/closures.rs b/src/closures.rs index a628e3da97996..95d2bc5a00b9a 100644 --- a/src/closures.rs +++ b/src/closures.rs @@ -3,17 +3,17 @@ use rustc_span::Span; use thin_vec::thin_vec; use crate::attr::get_attrs_from_stmt; -use crate::config::lists::*; use crate::config::StyleEdition; +use crate::config::lists::*; use crate::expr::{block_contains_comment, is_simple_block, is_unsafe_block, rewrite_cond}; use crate::items::{span_hi_for_param, span_lo_for_param}; -use crate::lists::{definitive_tactic, itemize_list, write_list, ListFormatting, Separator}; +use crate::lists::{ListFormatting, Separator, definitive_tactic, itemize_list, write_list}; use crate::overflow::OverflowableItem; use crate::rewrite::{Rewrite, RewriteContext, RewriteError, RewriteErrorExt, RewriteResult}; use crate::shape::Shape; use crate::source_map::SpanUtils; use crate::types::rewrite_bound_params; -use crate::utils::{last_line_width, left_most_sub_expr, stmt_expr, NodeIdExt}; +use crate::utils::{NodeIdExt, last_line_width, left_most_sub_expr, stmt_expr}; // This module is pretty messy because of the rules around closures and blocks: // FIXME - the below is probably no longer true in full. diff --git a/src/comment.rs b/src/comment.rs index 1e35395cfb31f..b565712b326e6 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -2,13 +2,13 @@ use std::{borrow::Cow, iter}; -use itertools::{multipeek, MultiPeek}; +use itertools::{MultiPeek, multipeek}; use rustc_span::Span; use crate::config::Config; use crate::rewrite::{RewriteContext, RewriteErrorExt, RewriteResult}; use crate::shape::{Indent, Shape}; -use crate::string::{rewrite_string, StringFormat}; +use crate::string::{StringFormat, rewrite_string}; use crate::utils::{ count_newlines, first_line_width, last_line_width, trim_left_preserve_layout, trimmed_last_line_width, unicode_str_width, diff --git a/src/config/file_lines.rs b/src/config/file_lines.rs index bc5a28b74237f..7f32765195da9 100644 --- a/src/config/file_lines.rs +++ b/src/config/file_lines.rs @@ -7,7 +7,7 @@ use std::{cmp, fmt, iter, str}; use rustc_data_structures::sync::Lrc; use rustc_span::SourceFile; -use serde::{ser, Deserialize, Deserializer, Serialize, Serializer}; +use serde::{Deserialize, Deserializer, Serialize, Serializer, ser}; use serde_json as json; use thiserror::Error; diff --git a/src/config/options.rs b/src/config/options.rs index b9e79b9a7de59..45496fd4e48a7 100644 --- a/src/config/options.rs +++ b/src/config/options.rs @@ -1,6 +1,6 @@ #![allow(unused_imports)] -use std::collections::{hash_set, HashSet}; +use std::collections::{HashSet, hash_set}; use std::fmt; use std::path::{Path, PathBuf}; use std::str::FromStr; @@ -11,10 +11,10 @@ use serde::de::{SeqAccess, Visitor}; use serde::ser::SerializeSeq; use serde::{Deserialize, Deserializer, Serialize, Serializer}; +use crate::config::Config; use crate::config::file_lines::FileLines; use crate::config::lists::*; use crate::config::macro_names::MacroSelectors; -use crate::config::Config; #[config_type] pub enum NewlineStyle { diff --git a/src/emitter/checkstyle.rs b/src/emitter/checkstyle.rs index 9385ae59a06b0..c320c16bd1d33 100644 --- a/src/emitter/checkstyle.rs +++ b/src/emitter/checkstyle.rs @@ -1,6 +1,6 @@ use self::xml::XmlEscaped; use super::*; -use crate::rustfmt_diff::{make_diff, DiffLine, Mismatch}; +use crate::rustfmt_diff::{DiffLine, Mismatch, make_diff}; mod xml; diff --git a/src/emitter/json.rs b/src/emitter/json.rs index 084f565804c97..a99626f783d4d 100644 --- a/src/emitter/json.rs +++ b/src/emitter/json.rs @@ -1,5 +1,5 @@ use super::*; -use crate::rustfmt_diff::{make_diff, DiffLine, Mismatch}; +use crate::rustfmt_diff::{DiffLine, Mismatch, make_diff}; use serde::Serialize; use serde_json::to_string as to_json_string; diff --git a/src/emitter/modified_lines.rs b/src/emitter/modified_lines.rs index 81f0a31b97483..0d5124bc33ee8 100644 --- a/src/emitter/modified_lines.rs +++ b/src/emitter/modified_lines.rs @@ -1,5 +1,5 @@ use super::*; -use crate::rustfmt_diff::{make_diff, ModifiedLines}; +use crate::rustfmt_diff::{ModifiedLines, make_diff}; #[derive(Debug, Default)] pub(crate) struct ModifiedLinesEmitter; diff --git a/src/expr.rs b/src/expr.rs index 8381e3ab0835e..5bd87d00b1d57 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -3,32 +3,32 @@ use std::cmp::min; use itertools::Itertools; use rustc_ast::token::{Delimiter, Lit, LitKind}; -use rustc_ast::{ast, ptr, token, ForLoopKind, MatchKind}; +use rustc_ast::{ForLoopKind, MatchKind, ast, ptr, token}; use rustc_span::{BytePos, Span}; use crate::chains::rewrite_chain; use crate::closures; use crate::comment::{ - combine_strs_with_missing_comments, contains_comment, recover_comment_removed, rewrite_comment, - rewrite_missing_comment, CharClasses, FindUncommented, + CharClasses, FindUncommented, combine_strs_with_missing_comments, contains_comment, + recover_comment_removed, rewrite_comment, rewrite_missing_comment, }; use crate::config::lists::*; use crate::config::{Config, ControlBraceStyle, HexLiteralCase, IndentStyle, StyleEdition}; use crate::lists::{ - definitive_tactic, itemize_list, shape_for_tactic, struct_lit_formatting, struct_lit_shape, - struct_lit_tactic, write_list, ListFormatting, Separator, + ListFormatting, Separator, definitive_tactic, itemize_list, shape_for_tactic, + struct_lit_formatting, struct_lit_shape, struct_lit_tactic, write_list, }; -use crate::macros::{rewrite_macro, MacroPosition}; +use crate::macros::{MacroPosition, rewrite_macro}; use crate::matches::rewrite_match; use crate::overflow::{self, IntoOverflowableItem, OverflowableItem}; -use crate::pairs::{rewrite_all_pairs, rewrite_pair, PairParts}; +use crate::pairs::{PairParts, rewrite_all_pairs, rewrite_pair}; use crate::rewrite::{Rewrite, RewriteContext, RewriteError, RewriteErrorExt, RewriteResult}; use crate::shape::{Indent, Shape}; use crate::source_map::{LineRangeUtils, SpanUtils}; use crate::spanned::Spanned; use crate::stmt; -use crate::string::{rewrite_string, StringFormat}; -use crate::types::{rewrite_path, PathContext}; +use crate::string::{StringFormat, rewrite_string}; +use crate::types::{PathContext, rewrite_path}; use crate::utils::{ colon_spaces, contains_skip, count_newlines, filtered_str_fits, first_line_ends_with, inner_attributes, last_line_extendable, last_line_width, mk_sp, outer_attributes, diff --git a/src/formatting.rs b/src/formatting.rs index 7f442230b12be..1315c9c43a1e6 100644 --- a/src/formatting.rs +++ b/src/formatting.rs @@ -16,7 +16,7 @@ use crate::parse::parser::{DirectoryOwnership, Parser, ParserError}; use crate::parse::session::ParseSess; use crate::utils::{contains_skip, count_newlines}; use crate::visitor::FmtVisitor; -use crate::{modules, source_file, ErrorKind, FormatReport, Input, Session}; +use crate::{ErrorKind, FormatReport, Input, Session, modules, source_file}; mod generated; mod newline_style; diff --git a/src/git-rustfmt/main.rs b/src/git-rustfmt/main.rs index b5a71588e9e4e..a487ede92844b 100644 --- a/src/git-rustfmt/main.rs +++ b/src/git-rustfmt/main.rs @@ -16,7 +16,7 @@ use rustfmt_nightly as rustfmt; use tracing_subscriber::EnvFilter; use crate::rustfmt::{ - load_config, CliOptions, FormatReportFormatterBuilder, Input, Session, Version, + CliOptions, FormatReportFormatterBuilder, Input, Session, Version, load_config, }; fn prune_files(files: Vec<&str>) -> Vec<&str> { diff --git a/src/imports.rs b/src/imports.rs index 868314354b048..b741dd9b5da54 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -8,16 +8,16 @@ use itertools::Itertools; use rustc_ast::ast::{self, UseTreeKind}; use rustc_span::{ + BytePos, DUMMY_SP, Span, symbol::{self, sym}, - BytePos, Span, DUMMY_SP, }; use crate::comment::combine_strs_with_missing_comments; -use crate::config::lists::*; use crate::config::ImportGranularity; +use crate::config::lists::*; use crate::config::{Edition, IndentStyle, StyleEdition}; use crate::lists::{ - definitive_tactic, itemize_list, write_list, ListFormatting, ListItem, Separator, + ListFormatting, ListItem, Separator, definitive_tactic, itemize_list, write_list, }; use crate::rewrite::{Rewrite, RewriteContext, RewriteErrorExt, RewriteResult}; use crate::shape::Shape; diff --git a/src/items.rs b/src/items.rs index 89fb9bda9dfca..ddcbfac129956 100644 --- a/src/items.rs +++ b/src/items.rs @@ -1,28 +1,27 @@ // Formatting top-level items - functions, structs, enums, traits, impls. use std::borrow::Cow; -use std::cmp::{max, min, Ordering}; +use std::cmp::{Ordering, max, min}; use regex::Regex; use rustc_ast::visit; use rustc_ast::{ast, ptr}; -use rustc_span::{symbol, BytePos, Span, DUMMY_SP}; +use rustc_span::{BytePos, DUMMY_SP, Span, symbol}; use crate::attr::filter_inline_attrs; use crate::comment::{ - combine_strs_with_missing_comments, contains_comment, is_last_comment_block, + FindUncommented, combine_strs_with_missing_comments, contains_comment, is_last_comment_block, recover_comment_removed, recover_missing_comment_in_span, rewrite_missing_comment, - FindUncommented, }; use crate::config::lists::*; use crate::config::{BraceStyle, Config, IndentStyle, StyleEdition}; use crate::expr::{ - is_empty_block, is_simple_block_stmt, rewrite_assign_rhs, rewrite_assign_rhs_with, - rewrite_assign_rhs_with_comments, rewrite_else_kw_with_comments, rewrite_let_else_block, - RhsAssignKind, RhsTactics, + RhsAssignKind, RhsTactics, is_empty_block, is_simple_block_stmt, rewrite_assign_rhs, + rewrite_assign_rhs_with, rewrite_assign_rhs_with_comments, rewrite_else_kw_with_comments, + rewrite_let_else_block, }; -use crate::lists::{definitive_tactic, itemize_list, write_list, ListFormatting, Separator}; -use crate::macros::{rewrite_macro, MacroPosition}; +use crate::lists::{ListFormatting, Separator, definitive_tactic, itemize_list, write_list}; +use crate::macros::{MacroPosition, rewrite_macro}; use crate::overflow; use crate::rewrite::{Rewrite, RewriteContext, RewriteError, RewriteErrorExt, RewriteResult}; use crate::shape::{Indent, Shape}; diff --git a/src/lib.rs b/src/lib.rs index 1f186b87767f1..7d707c341cb53 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -47,8 +47,8 @@ use crate::shape::Indent; use crate::utils::indent_next_line; pub use crate::config::{ - load_config, CliOptions, Color, Config, Edition, EmitMode, FileLines, FileName, NewlineStyle, - Range, StyleEdition, Verbosity, Version, + CliOptions, Color, Config, Edition, EmitMode, FileLines, FileName, NewlineStyle, Range, + StyleEdition, Verbosity, Version, load_config, }; pub use crate::format_report_formatter::{FormatReportFormatter, FormatReportFormatterBuilder}; diff --git a/src/lists.rs b/src/lists.rs index f9e722130cd12..415144a8abc05 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -5,7 +5,7 @@ use std::iter::Peekable; use rustc_span::BytePos; -use crate::comment::{find_comment_end, rewrite_comment, FindUncommented}; +use crate::comment::{FindUncommented, find_comment_end, rewrite_comment}; use crate::config::lists::*; use crate::config::{Config, IndentStyle}; use crate::rewrite::{RewriteContext, RewriteError, RewriteResult}; diff --git a/src/macros.rs b/src/macros.rs index 5e537002324f8..2085ed35324ae 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -10,27 +10,27 @@ // and those with brackets will be formatted as array literals. use std::collections::HashMap; -use std::panic::{catch_unwind, AssertUnwindSafe}; +use std::panic::{AssertUnwindSafe, catch_unwind}; use rustc_ast::token::{BinOpToken, Delimiter, Token, TokenKind}; use rustc_ast::tokenstream::{RefTokenTreeCursor, TokenStream, TokenTree}; use rustc_ast::{ast, ptr}; use rustc_ast_pretty::pprust; use rustc_span::{ + BytePos, DUMMY_SP, Span, Symbol, symbol::{self, kw}, - BytePos, Span, Symbol, DUMMY_SP, }; use crate::comment::{ - contains_comment, CharClasses, FindUncommented, FullCodeCharKind, LineClasses, + CharClasses, FindUncommented, FullCodeCharKind, LineClasses, contains_comment, }; -use crate::config::lists::*; use crate::config::StyleEdition; -use crate::expr::{rewrite_array, rewrite_assign_rhs, RhsAssignKind}; -use crate::lists::{itemize_list, write_list, ListFormatting}; +use crate::config::lists::*; +use crate::expr::{RhsAssignKind, rewrite_array, rewrite_assign_rhs}; +use crate::lists::{ListFormatting, itemize_list, write_list}; use crate::overflow; use crate::parse::macros::lazy_static::parse_lazy_static; -use crate::parse::macros::{parse_expr, parse_macro_args, ParsedMacroArgs}; +use crate::parse::macros::{ParsedMacroArgs, parse_expr, parse_macro_args}; use crate::rewrite::{ MacroErrorKind, Rewrite, RewriteContext, RewriteError, RewriteErrorExt, RewriteResult, }; @@ -38,8 +38,8 @@ use crate::shape::{Indent, Shape}; use crate::source_map::SpanUtils; use crate::spanned::Spanned; use crate::utils::{ - filtered_str_fits, format_visibility, indent_next_line, is_empty_line, mk_sp, - remove_trailing_white_spaces, rewrite_ident, trim_left_preserve_layout, NodeIdExt, + NodeIdExt, filtered_str_fits, format_visibility, indent_next_line, is_empty_line, mk_sp, + remove_trailing_white_spaces, rewrite_ident, trim_left_preserve_layout, }; use crate::visitor::FmtVisitor; diff --git a/src/matches.rs b/src/matches.rs index 0a6fada5cb300..8de92eb55383e 100644 --- a/src/matches.rs +++ b/src/matches.rs @@ -2,17 +2,17 @@ use std::iter::repeat; -use rustc_ast::{ast, ptr, MatchKind}; +use rustc_ast::{MatchKind, ast, ptr}; use rustc_span::{BytePos, Span}; -use crate::comment::{combine_strs_with_missing_comments, rewrite_comment, FindUncommented}; +use crate::comment::{FindUncommented, combine_strs_with_missing_comments, rewrite_comment}; use crate::config::lists::*; use crate::config::{Config, ControlBraceStyle, IndentStyle, MatchArmLeadingPipe, StyleEdition}; use crate::expr::{ - format_expr, is_empty_block, is_simple_block, is_unsafe_block, prefer_next_line, rewrite_cond, - ExprType, RhsTactics, + ExprType, RhsTactics, format_expr, is_empty_block, is_simple_block, is_unsafe_block, + prefer_next_line, rewrite_cond, }; -use crate::lists::{itemize_list, write_list, ListFormatting}; +use crate::lists::{ListFormatting, itemize_list, write_list}; use crate::rewrite::{Rewrite, RewriteContext, RewriteError, RewriteErrorExt, RewriteResult}; use crate::shape::Shape; use crate::source_map::SpanUtils; diff --git a/src/missed_spans.rs b/src/missed_spans.rs index 4d947328bf763..4ef54c90d4664 100644 --- a/src/missed_spans.rs +++ b/src/missed_spans.rs @@ -1,9 +1,9 @@ use rustc_span::{BytePos, Pos, Span}; -use crate::comment::{is_last_comment_block, rewrite_comment, CodeCharKind, CommentCodeSlices}; -use crate::config::file_lines::FileLines; +use crate::comment::{CodeCharKind, CommentCodeSlices, is_last_comment_block, rewrite_comment}; use crate::config::FileName; use crate::config::StyleEdition; +use crate::config::file_lines::FileLines; use crate::coverage::transform_missing_snippet; use crate::shape::{Indent, Shape}; use crate::source_map::LineRangeUtils; diff --git a/src/modules.rs b/src/modules.rs index 0590f28ee0521..493b04f16c6f4 100644 --- a/src/modules.rs +++ b/src/modules.rs @@ -4,8 +4,8 @@ use std::path::{Path, PathBuf}; use rustc_ast::ast; use rustc_ast::visit::Visitor; -use rustc_span::symbol::{self, sym, Symbol}; use rustc_span::Span; +use rustc_span::symbol::{self, Symbol, sym}; use thin_vec::ThinVec; use thiserror::Error; diff --git a/src/overflow.rs b/src/overflow.rs index dc4716a81af9b..8ce11897d265a 100644 --- a/src/overflow.rs +++ b/src/overflow.rs @@ -9,21 +9,21 @@ use rustc_span::Span; use crate::closures; use crate::config::StyleEdition; -use crate::config::{lists::*, Config}; +use crate::config::{Config, lists::*}; use crate::expr::{ can_be_overflowed_expr, is_every_expr_simple, is_method_call, is_nested_call, is_simple_expr, rewrite_cond, }; use crate::lists::{ - definitive_tactic, itemize_list, write_list, ListFormatting, ListItem, Separator, + ListFormatting, ListItem, Separator, definitive_tactic, itemize_list, write_list, }; use crate::macros::MacroArg; -use crate::patterns::{can_be_overflowed_pat, TuplePatField}; +use crate::patterns::{TuplePatField, can_be_overflowed_pat}; use crate::rewrite::{Rewrite, RewriteContext, RewriteError, RewriteErrorExt, RewriteResult}; use crate::shape::Shape; use crate::source_map::SpanUtils; use crate::spanned::Spanned; -use crate::types::{can_be_overflowed_type, SegmentParam}; +use crate::types::{SegmentParam, can_be_overflowed_type}; use crate::utils::{count_newlines, extra_offset, first_line_width, last_line_width, mk_sp}; /// A list of `format!`-like macros, that take a long format string and a list of arguments to diff --git a/src/pairs.rs b/src/pairs.rs index 5a7d9c8aaa45f..9c51298416b0d 100644 --- a/src/pairs.rs +++ b/src/pairs.rs @@ -1,8 +1,8 @@ use rustc_ast::ast; use rustc_span::Span; -use crate::config::lists::*; use crate::config::IndentStyle; +use crate::config::lists::*; use crate::rewrite::{Rewrite, RewriteContext, RewriteErrorExt, RewriteResult}; use crate::shape::Shape; use crate::spanned::Spanned; diff --git a/src/parse/macros/asm.rs b/src/parse/macros/asm.rs index 6373d0251f896..5ee083da5399d 100644 --- a/src/parse/macros/asm.rs +++ b/src/parse/macros/asm.rs @@ -1,5 +1,5 @@ use rustc_ast::ast; -use rustc_builtin_macros::asm::{parse_asm_args, AsmArgs}; +use rustc_builtin_macros::asm::{AsmArgs, parse_asm_args}; use crate::rewrite::RewriteContext; diff --git a/src/parse/macros/cfg_if.rs b/src/parse/macros/cfg_if.rs index b91d203d53118..ec771f96a3f1a 100644 --- a/src/parse/macros/cfg_if.rs +++ b/src/parse/macros/cfg_if.rs @@ -1,4 +1,4 @@ -use std::panic::{catch_unwind, AssertUnwindSafe}; +use std::panic::{AssertUnwindSafe, catch_unwind}; use rustc_ast::ast; use rustc_ast::token::{Delimiter, TokenKind}; diff --git a/src/parse/macros/mod.rs b/src/parse/macros/mod.rs index 8d5f7f90958f1..7271e73db8dd4 100644 --- a/src/parse/macros/mod.rs +++ b/src/parse/macros/mod.rs @@ -1,11 +1,11 @@ use rustc_ast::token::{Delimiter, NonterminalKind, NtExprKind::*, NtPatKind::*, TokenKind}; use rustc_ast::tokenstream::TokenStream; use rustc_ast::{ast, ptr}; -use rustc_parse::parser::{ForceCollect, Parser, Recovery}; use rustc_parse::MACRO_ARGUMENTS; +use rustc_parse::parser::{ForceCollect, Parser, Recovery}; use rustc_session::parse::ParseSess; -use rustc_span::symbol::{self, kw}; use rustc_span::Symbol; +use rustc_span::symbol::{self, kw}; use crate::macros::MacroArg; use crate::rewrite::RewriteContext; diff --git a/src/parse/parser.rs b/src/parse/parser.rs index 6051241309d19..28b4c2b612f1d 100644 --- a/src/parse/parser.rs +++ b/src/parse/parser.rs @@ -1,4 +1,4 @@ -use std::panic::{catch_unwind, AssertUnwindSafe}; +use std::panic::{AssertUnwindSafe, catch_unwind}; use std::path::{Path, PathBuf}; use rustc_ast::token::TokenKind; @@ -6,11 +6,11 @@ use rustc_ast::{ast, attr, ptr}; use rustc_errors::Diag; use rustc_parse::parser::Parser as RawParser; use rustc_parse::{new_parser_from_file, new_parser_from_source_str, unwrap_or_emit_fatal}; -use rustc_span::{sym, Span}; +use rustc_span::{Span, sym}; use thin_vec::ThinVec; -use crate::parse::session::ParseSess; use crate::Input; +use crate::parse::session::ParseSess; pub(crate) type DirectoryOwnership = rustc_expand::module::DirOwnership; pub(crate) type ModulePathSuccess = rustc_expand::module::ModulePathSuccess; diff --git a/src/parse/session.rs b/src/parse/session.rs index 05cf467167c8d..4160e02b8f8b3 100644 --- a/src/parse/session.rs +++ b/src/parse/session.rs @@ -2,13 +2,14 @@ use std::path::Path; use std::sync::atomic::{AtomicBool, Ordering}; use rustc_data_structures::sync::{IntoDynSyncSend, Lrc}; -use rustc_errors::emitter::{stderr_destination, DynEmitter, Emitter, HumanEmitter, SilentEmitter}; +use rustc_errors::emitter::{DynEmitter, Emitter, HumanEmitter, SilentEmitter, stderr_destination}; use rustc_errors::translation::Translate; use rustc_errors::{ColorConfig, Diag, DiagCtxt, DiagInner, Level as DiagnosticLevel}; use rustc_session::parse::ParseSess as RawParseSess; use rustc_span::{ + BytePos, Span, source_map::{FilePathMapping, SourceMap}, - symbol, BytePos, Span, + symbol, }; use crate::config::file_lines::LineRange; diff --git a/src/patterns.rs b/src/patterns.rs index 9a4f6528ce8e9..6fe2d4a8520e3 100644 --- a/src/patterns.rs +++ b/src/patterns.rs @@ -2,22 +2,22 @@ use rustc_ast::ast::{self, BindingMode, ByRef, Pat, PatField, PatKind, RangeEnd, use rustc_ast::ptr; use rustc_span::{BytePos, Span}; -use crate::comment::{combine_strs_with_missing_comments, FindUncommented}; -use crate::config::lists::*; +use crate::comment::{FindUncommented, combine_strs_with_missing_comments}; use crate::config::StyleEdition; +use crate::config::lists::*; use crate::expr::{can_be_overflowed_expr, rewrite_unary_prefix, wrap_struct_field}; use crate::lists::{ - definitive_tactic, itemize_list, shape_for_tactic, struct_lit_formatting, struct_lit_shape, - struct_lit_tactic, write_list, ListFormatting, ListItem, Separator, + ListFormatting, ListItem, Separator, definitive_tactic, itemize_list, shape_for_tactic, + struct_lit_formatting, struct_lit_shape, struct_lit_tactic, write_list, }; -use crate::macros::{rewrite_macro, MacroPosition}; +use crate::macros::{MacroPosition, rewrite_macro}; use crate::overflow; -use crate::pairs::{rewrite_pair, PairParts}; +use crate::pairs::{PairParts, rewrite_pair}; use crate::rewrite::{Rewrite, RewriteContext, RewriteError, RewriteErrorExt, RewriteResult}; use crate::shape::Shape; use crate::source_map::SpanUtils; use crate::spanned::Spanned; -use crate::types::{rewrite_path, PathContext}; +use crate::types::{PathContext, rewrite_path}; use crate::utils::{format_mutability, mk_sp, mk_sp_lo_plus_one, rewrite_ident}; /// Returns `true` if the given pattern is "short". diff --git a/src/reorder.rs b/src/reorder.rs index 80d1c73899497..8a31e0ac816e3 100644 --- a/src/reorder.rs +++ b/src/reorder.rs @@ -9,12 +9,12 @@ use std::cmp::Ordering; use rustc_ast::{ast, attr}; -use rustc_span::{symbol::sym, Span}; +use rustc_span::{Span, symbol::sym}; use crate::config::{Config, GroupImportsTactic}; -use crate::imports::{normalize_use_trees_with_granularity, UseSegmentKind, UseTree}; +use crate::imports::{UseSegmentKind, UseTree, normalize_use_trees_with_granularity}; use crate::items::{is_mod_decl, rewrite_extern_crate, rewrite_mod}; -use crate::lists::{itemize_list, write_list, ListFormatting, ListItem}; +use crate::lists::{ListFormatting, ListItem, itemize_list, write_list}; use crate::rewrite::{RewriteContext, RewriteErrorExt}; use crate::shape::Shape; use crate::source_map::LineRangeUtils; diff --git a/src/rewrite.rs b/src/rewrite.rs index 8cefda1657f9d..830207097970d 100644 --- a/src/rewrite.rs +++ b/src/rewrite.rs @@ -7,12 +7,12 @@ use rustc_ast::ptr; use rustc_span::Span; use thiserror::Error; +use crate::FormatReport; use crate::config::{Config, IndentStyle}; use crate::parse::session::ParseSess; use crate::shape::Shape; use crate::skip::SkipContext; use crate::visitor::SnippetProvider; -use crate::FormatReport; pub(crate) type RewriteResult = Result; pub(crate) trait Rewrite { diff --git a/src/rustfmt_diff.rs b/src/rustfmt_diff.rs index c98834521852c..4624683fa05b1 100644 --- a/src/rustfmt_diff.rs +++ b/src/rustfmt_diff.rs @@ -282,7 +282,7 @@ where #[cfg(test)] mod test { use super::DiffLine::*; - use super::{make_diff, Mismatch}; + use super::{Mismatch, make_diff}; use super::{ModifiedChunk, ModifiedLines}; #[test] diff --git a/src/source_file.rs b/src/source_file.rs index 5eea8021b329a..73f8ecb552977 100644 --- a/src/source_file.rs +++ b/src/source_file.rs @@ -2,10 +2,10 @@ use std::fs; use std::io::{self, Write}; use std::path::Path; +use crate::NewlineStyle; use crate::config::FileName; use crate::emitter::{self, Emitter}; use crate::parse::session::ParseSess; -use crate::NewlineStyle; #[cfg(test)] use crate::config::Config; diff --git a/src/spanned.rs b/src/spanned.rs index 030495e3ff8f3..b4424e476ee6b 100644 --- a/src/spanned.rs +++ b/src/spanned.rs @@ -1,7 +1,7 @@ use std::cmp::max; use rustc_ast::{ast, ptr}; -use rustc_span::{source_map, Span}; +use rustc_span::{Span, source_map}; use crate::macros::MacroArg; use crate::patterns::RangeOperand; diff --git a/src/stmt.rs b/src/stmt.rs index 4f31705295eb1..426bf89fc1622 100644 --- a/src/stmt.rs +++ b/src/stmt.rs @@ -3,7 +3,7 @@ use rustc_span::Span; use crate::comment::recover_comment_removed; use crate::config::StyleEdition; -use crate::expr::{format_expr, is_simple_block, ExprType}; +use crate::expr::{ExprType, format_expr, is_simple_block}; use crate::rewrite::{Rewrite, RewriteContext, RewriteError, RewriteErrorExt, RewriteResult}; use crate::shape::Shape; use crate::source_map::LineRangeUtils; diff --git a/src/string.rs b/src/string.rs index cb666fff69514..41fddeb517ec6 100644 --- a/src/string.rs +++ b/src/string.rs @@ -375,7 +375,7 @@ fn graphemes_width(graphemes: &[&str]) -> usize { #[cfg(test)] mod test { - use super::{break_string, detect_url, rewrite_string, SnippetState, StringFormat}; + use super::{SnippetState, StringFormat, break_string, detect_url, rewrite_string}; use crate::config::Config; use crate::shape::{Indent, Shape}; use unicode_segmentation::UnicodeSegmentation; diff --git a/src/test/configuration_snippet.rs b/src/test/configuration_snippet.rs index e4a390ada6631..5b93703de0b80 100644 --- a/src/test/configuration_snippet.rs +++ b/src/test/configuration_snippet.rs @@ -4,9 +4,9 @@ use std::io::{BufRead, BufReader, Write}; use std::iter::Enumerate; use std::path::{Path, PathBuf}; -use super::{print_mismatches, write_message, DIFF_CONTEXT_SIZE}; +use super::{DIFF_CONTEXT_SIZE, print_mismatches, write_message}; use crate::config::{Config, EmitMode, Verbosity}; -use crate::rustfmt_diff::{make_diff, Mismatch}; +use crate::rustfmt_diff::{Mismatch, make_diff}; use crate::{Input, Session}; const CONFIGURATIONS_FILE_NAME: &str = "Configurations.md"; diff --git a/src/test/mod.rs b/src/test/mod.rs index 4d22f64f3526c..9dc05c846dedb 100644 --- a/src/test/mod.rs +++ b/src/test/mod.rs @@ -11,11 +11,11 @@ use std::thread; use crate::config::{Color, Config, EmitMode, FileName, NewlineStyle}; use crate::formatting::{ReportedErrors, SourceFile}; -use crate::rustfmt_diff::{make_diff, print_diff, DiffLine, Mismatch, ModifiedChunk, OutputWriter}; +use crate::rustfmt_diff::{DiffLine, Mismatch, ModifiedChunk, OutputWriter, make_diff, print_diff}; use crate::source_file; use crate::{ - is_nightly_channel, Edition, FormatReport, FormatReportFormatterBuilder, Input, Session, - StyleEdition, Version, + Edition, FormatReport, FormatReportFormatterBuilder, Input, Session, StyleEdition, Version, + is_nightly_channel, }; use rustfmt_config_proc_macro::nightly_only_test; diff --git a/src/types.rs b/src/types.rs index af57a5843dbe6..384a69e23b222 100644 --- a/src/types.rs +++ b/src/types.rs @@ -2,21 +2,21 @@ use std::ops::Deref; use rustc_ast::ast::{self, FnRetTy, Mutability, Term}; use rustc_ast::ptr; -use rustc_span::{symbol::kw, BytePos, Pos, Span}; +use rustc_span::{BytePos, Pos, Span, symbol::kw}; use crate::comment::{combine_strs_with_missing_comments, contains_comment}; use crate::config::lists::*; use crate::config::{IndentStyle, StyleEdition, TypeDensity}; use crate::expr::{ - format_expr, rewrite_assign_rhs, rewrite_call, rewrite_tuple, rewrite_unary_prefix, ExprType, - RhsAssignKind, + ExprType, RhsAssignKind, format_expr, rewrite_assign_rhs, rewrite_call, rewrite_tuple, + rewrite_unary_prefix, }; use crate::lists::{ - definitive_tactic, itemize_list, write_list, ListFormatting, ListItem, Separator, + ListFormatting, ListItem, Separator, definitive_tactic, itemize_list, write_list, }; -use crate::macros::{rewrite_macro, MacroPosition}; +use crate::macros::{MacroPosition, rewrite_macro}; use crate::overflow; -use crate::pairs::{rewrite_pair, PairParts}; +use crate::pairs::{PairParts, rewrite_pair}; use crate::rewrite::{Rewrite, RewriteContext, RewriteError, RewriteErrorExt, RewriteResult}; use crate::shape::Shape; use crate::source_map::SpanUtils; diff --git a/src/utils.rs b/src/utils.rs index 57f2f1779603d..be21e89f760e9 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -6,10 +6,10 @@ use rustc_ast::ast::{ }; use rustc_ast::ptr; use rustc_ast_pretty::pprust; -use rustc_span::{sym, symbol, BytePos, LocalExpnId, Span, Symbol, SyntaxContext}; +use rustc_span::{BytePos, LocalExpnId, Span, Symbol, SyntaxContext, sym, symbol}; use unicode_width::UnicodeWidthStr; -use crate::comment::{filter_normal_code, CharClasses, FullCodeCharKind, LineClasses}; +use crate::comment::{CharClasses, FullCodeCharKind, LineClasses, filter_normal_code}; use crate::config::{Config, StyleEdition}; use crate::rewrite::RewriteContext; use crate::shape::{Indent, Shape}; diff --git a/src/vertical.rs b/src/vertical.rs index 80c46da4620c7..1ec239c382100 100644 --- a/src/vertical.rs +++ b/src/vertical.rs @@ -11,7 +11,7 @@ use crate::config::lists::*; use crate::expr::rewrite_field; use crate::items::{rewrite_struct_field, rewrite_struct_field_prefix}; use crate::lists::{ - definitive_tactic, itemize_list, write_list, ListFormatting, ListItem, Separator, + ListFormatting, ListItem, Separator, definitive_tactic, itemize_list, write_list, }; use crate::rewrite::{Rewrite, RewriteContext, RewriteResult}; use crate::shape::{Indent, Shape}; diff --git a/src/visitor.rs b/src/visitor.rs index 9859100a038ca..afb54c8e2bcd7 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -3,22 +3,22 @@ use std::rc::Rc; use rustc_ast::{ast, token::Delimiter, visit}; use rustc_data_structures::sync::Lrc; -use rustc_span::{symbol, BytePos, Pos, Span}; +use rustc_span::{BytePos, Pos, Span, symbol}; use crate::attr::*; -use crate::comment::{contains_comment, rewrite_comment, CodeCharKind, CommentCodeSlices}; +use crate::comment::{CodeCharKind, CommentCodeSlices, contains_comment, rewrite_comment}; use crate::config::{BraceStyle, Config, MacroSelector, StyleEdition}; use crate::coverage::transform_missing_snippet; use crate::items::{ - format_impl, format_trait, format_trait_alias, is_mod_decl, is_use_item, rewrite_extern_crate, - rewrite_type_alias, FnBraceStyle, FnSig, ItemVisitorKind, StaticParts, StructParts, + FnBraceStyle, FnSig, ItemVisitorKind, StaticParts, StructParts, format_impl, format_trait, + format_trait_alias, is_mod_decl, is_use_item, rewrite_extern_crate, rewrite_type_alias, }; -use crate::macros::{macro_style, rewrite_macro, rewrite_macro_def, MacroPosition}; +use crate::macros::{MacroPosition, macro_style, rewrite_macro, rewrite_macro_def}; use crate::modules::Module; use crate::parse::session::ParseSess; use crate::rewrite::{Rewrite, RewriteContext}; use crate::shape::{Indent, Shape}; -use crate::skip::{is_skip_attr, SkipContext}; +use crate::skip::{SkipContext, is_skip_attr}; use crate::source_map::{LineRangeUtils, SpanUtils}; use crate::spanned::Spanned; use crate::stmt::Stmt; From 06e16449d28bf4ff2c56e49b158b4f1cead2b993 Mon Sep 17 00:00:00 2001 From: Yacin Tmimi Date: Fri, 16 Aug 2024 15:27:57 -0400 Subject: [PATCH 0459/2194] Add test cases for issue 4381 This was one of the original issues filed against rustfmt that discussed using a natural sort order instead of a lexicographical order. At the time it was closed, but now that we're supporting version-sorting in `style_edition=2024` I thought it would be good to add a test case. --- tests/source/issue-4381/style_edition_2015.rs | 3 +++ tests/target/issue-4381/style_edition_2015.rs | 3 +++ tests/target/issue-4381/style_edition_2024.rs | 3 +++ 3 files changed, 9 insertions(+) create mode 100644 tests/source/issue-4381/style_edition_2015.rs create mode 100644 tests/target/issue-4381/style_edition_2015.rs create mode 100644 tests/target/issue-4381/style_edition_2024.rs diff --git a/tests/source/issue-4381/style_edition_2015.rs b/tests/source/issue-4381/style_edition_2015.rs new file mode 100644 index 0000000000000..bb4c9feae1d56 --- /dev/null +++ b/tests/source/issue-4381/style_edition_2015.rs @@ -0,0 +1,3 @@ +// rustfmt-style_edition: 2015 + +use std::num::{NonZeroU8, NonZeroU16, NonZeroU32, NonZeroU64}; diff --git a/tests/target/issue-4381/style_edition_2015.rs b/tests/target/issue-4381/style_edition_2015.rs new file mode 100644 index 0000000000000..1fc1613083eb1 --- /dev/null +++ b/tests/target/issue-4381/style_edition_2015.rs @@ -0,0 +1,3 @@ +// rustfmt-style_edition: 2015 + +use std::num::{NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU8}; diff --git a/tests/target/issue-4381/style_edition_2024.rs b/tests/target/issue-4381/style_edition_2024.rs new file mode 100644 index 0000000000000..df85636ad573d --- /dev/null +++ b/tests/target/issue-4381/style_edition_2024.rs @@ -0,0 +1,3 @@ +// rustfmt-style_edition: 2024 + +use std::num::{NonZeroU8, NonZeroU16, NonZeroU32, NonZeroU64}; From e45b53efc0ef0f86df82918720cfae78e295e3ac Mon Sep 17 00:00:00 2001 From: Godfrey Chan Date: Tue, 3 Sep 2024 12:29:23 -0700 Subject: [PATCH 0460/2194] Update marker.rs --- library/core/src/marker.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/core/src/marker.rs b/library/core/src/marker.rs index a13cef26dee07..d9f197d9510ef 100644 --- a/library/core/src/marker.rs +++ b/library/core/src/marker.rs @@ -295,7 +295,7 @@ marker_impls! { /// #[derive(Clone)] /// struct MyStruct(T); /// -/// impl Copy for MyStruct { } +/// impl Copy for MyStruct { } /// ``` /// /// This isn't always desired. For example, shared references (`&T`) can be copied regardless of From 98f74b4d047006aaa475b0252b61f0ca772372fb Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 3 Sep 2024 21:50:08 +0200 Subject: [PATCH 0461/2194] explain why Rvalue::Len still exists --- compiler/rustc_middle/src/mir/syntax.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs index 748ca047754a9..22a4b688c517c 100644 --- a/compiler/rustc_middle/src/mir/syntax.rs +++ b/compiler/rustc_middle/src/mir/syntax.rs @@ -1307,6 +1307,9 @@ pub enum Rvalue<'tcx> { /// If the type of the place is an array, this is the array length. For slices (`[T]`, not /// `&[T]`) this accesses the place's metadata to determine the length. This rvalue is /// ill-formed for places of other types. + /// + /// This cannot be a `UnOp(PtrMetadata, _)` because that expects a value, and we only + /// have a place, and `UnOp(PtrMetadata, RawPtr(place))` is not a thing. Len(Place<'tcx>), /// Performs essentially all of the casts that can be performed via `as`. From e064b729b9cff869e3c03b28cc2fd28f25b928dd Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 3 Sep 2024 21:53:06 +0200 Subject: [PATCH 0462/2194] Add missing intrinsic translation for `llvm.x86.xsave64` --- src/intrinsic/llvm.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/intrinsic/llvm.rs b/src/intrinsic/llvm.rs index 614bdbe26b808..3b9855ddc1894 100644 --- a/src/intrinsic/llvm.rs +++ b/src/intrinsic/llvm.rs @@ -802,6 +802,7 @@ pub fn intrinsic<'gcc, 'tcx>(name: &str, cx: &CodegenCx<'gcc, 'tcx>) -> Function "llvm.x86.avx512.mask.cmp.b.128" => "__builtin_ia32_cmpb128_mask", "llvm.x86.xrstor" => "__builtin_ia32_xrstor", "llvm.x86.xsavec" => "__builtin_ia32_xsavec", + "llvm.x86.xsave64" => "__builtin_ia32_xsave64", "llvm.x86.addcarry.32" => "__builtin_ia32_addcarryx_u32", "llvm.x86.subborrow.32" => "__builtin_ia32_sbb_u32", "llvm.x86.avx512.mask.compress.store.w.512" => "__builtin_ia32_compressstoreuhi512_mask", From 3dca90946f612f73b64f6c17ecb82a520a1d8da1 Mon Sep 17 00:00:00 2001 From: Boxy Date: Mon, 2 Sep 2024 17:48:42 +0100 Subject: [PATCH 0463/2194] replace placeholder version --- compiler/rustc_feature/src/accepted.rs | 16 ++++++++-------- compiler/rustc_feature/src/removed.rs | 2 +- compiler/rustc_feature/src/unstable.rs | 14 +++++++------- library/alloc/src/boxed.rs | 8 ++++---- library/alloc/src/collections/binary_heap/mod.rs | 2 +- library/alloc/src/collections/btree/map.rs | 4 ++-- library/alloc/src/collections/vec_deque/iter.rs | 2 +- .../alloc/src/collections/vec_deque/iter_mut.rs | 2 +- library/alloc/src/rc.rs | 8 ++++---- library/alloc/src/sync.rs | 8 ++++---- library/core/src/future/ready.rs | 2 +- library/core/src/iter/adapters/take.rs | 6 +++--- library/core/src/iter/mod.rs | 2 +- library/core/src/iter/sources.rs | 2 +- library/core/src/iter/sources/repeat_n.rs | 16 ++++++++-------- library/core/src/iter/traits/iterator.rs | 6 +++--- library/core/src/num/error.rs | 2 +- library/core/src/num/mod.rs | 6 +++--- library/core/src/option.rs | 2 +- library/core/src/slice/mod.rs | 6 +++--- library/core/src/str/iter.rs | 2 +- library/core/src/task/wake.rs | 10 +++++----- library/std/src/thread/mod.rs | 2 +- 23 files changed, 65 insertions(+), 65 deletions(-) diff --git a/compiler/rustc_feature/src/accepted.rs b/compiler/rustc_feature/src/accepted.rs index 9223c3c322a56..8949fdffdaec1 100644 --- a/compiler/rustc_feature/src/accepted.rs +++ b/compiler/rustc_feature/src/accepted.rs @@ -61,7 +61,7 @@ declare_features! ( /// Allows explicit discriminants on non-unit enum variants. (accepted, arbitrary_enum_discriminant, "1.66.0", Some(60553)), /// Allows using `const` operands in inline assembly. - (accepted, asm_const, "CURRENT_RUSTC_VERSION", Some(93332)), + (accepted, asm_const, "1.82.0", Some(93332)), /// Allows using `sym` operands in inline assembly. (accepted, asm_sym, "1.66.0", Some(93333)), /// Allows the definition of associated constants in `trait` or `impl` blocks. @@ -116,7 +116,7 @@ declare_features! ( /// Allows calling constructor functions in `const fn`. (accepted, const_constructor, "1.40.0", Some(61456)), /// Allows basic arithmetic on floating point types in a `const fn`. - (accepted, const_fn_floating_point_arithmetic, "CURRENT_RUSTC_VERSION", Some(57241)), + (accepted, const_fn_floating_point_arithmetic, "1.82.0", Some(57241)), /// Allows using and casting function pointers in a `const fn`. (accepted, const_fn_fn_ptr_basics, "1.61.0", Some(57563)), /// Allows trait bounds in `const fn`. @@ -272,7 +272,7 @@ declare_features! ( /// Allows calling `const unsafe fn` inside `unsafe` blocks in `const fn` functions. (accepted, min_const_unsafe_fn, "1.33.0", Some(55607)), /// Allows exhaustive pattern matching on uninhabited types when matched by value. - (accepted, min_exhaustive_patterns, "CURRENT_RUSTC_VERSION", Some(119612)), + (accepted, min_exhaustive_patterns, "1.82.0", Some(119612)), /// Allows using `Self` and associated types in struct expressions and patterns. (accepted, more_struct_aliases, "1.16.0", Some(37544)), /// Allows using the MOVBE target feature. @@ -299,7 +299,7 @@ declare_features! ( /// Allows `foo.rs` as an alternative to `foo/mod.rs`. (accepted, non_modrs_mods, "1.30.0", Some(44660)), /// Allows using multiple nested field accesses in offset_of! - (accepted, offset_of_nested, "CURRENT_RUSTC_VERSION", Some(120140)), + (accepted, offset_of_nested, "1.82.0", Some(120140)), /// Allows the use of or-patterns (e.g., `0 | 1`). (accepted, or_patterns, "1.53.0", Some(54883)), /// Allows using `+bundle,+whole-archive` link modifiers with native libs. @@ -312,7 +312,7 @@ declare_features! ( /// Allows parentheses in patterns. (accepted, pattern_parentheses, "1.31.0", Some(51087)), /// Allows `use<'a, 'b, A, B>` in `impl Trait + use<...>` for precise capture of generic args. - (accepted, precise_capturing, "CURRENT_RUSTC_VERSION", Some(123432)), + (accepted, precise_capturing, "1.82.0", Some(123432)), /// Allows procedural macros in `proc-macro` crates. (accepted, proc_macro, "1.29.0", Some(38356)), /// Allows multi-segment paths in attributes and derives. @@ -326,7 +326,7 @@ declare_features! ( /// Allows keywords to be escaped for use as identifiers. (accepted, raw_identifiers, "1.30.0", Some(48589)), /// Allows `&raw const $place_expr` and `&raw mut $place_expr` expressions. - (accepted, raw_ref_op, "CURRENT_RUSTC_VERSION", Some(64490)), + (accepted, raw_ref_op, "1.82.0", Some(64490)), /// Allows relaxing the coherence rules such that /// `impl ForeignTrait for ForeignType` is permitted. (accepted, re_rebalance_coherence, "1.41.0", Some(55437)), @@ -399,11 +399,11 @@ declare_features! ( /// Allows arbitrary delimited token streams in non-macro attributes. (accepted, unrestricted_attribute_tokens, "1.34.0", Some(55208)), /// Allows unsafe attributes. - (accepted, unsafe_attributes, "CURRENT_RUSTC_VERSION", Some(123757)), + (accepted, unsafe_attributes, "1.82.0", Some(123757)), /// The `unsafe_op_in_unsafe_fn` lint (allowed by default): no longer treat an unsafe function as an unsafe block. (accepted, unsafe_block_in_unsafe_fn, "1.52.0", Some(71668)), /// Allows unsafe on extern declarations and safety qualifiers over internal items. - (accepted, unsafe_extern_blocks, "CURRENT_RUSTC_VERSION", Some(123743)), + (accepted, unsafe_extern_blocks, "1.82.0", Some(123743)), /// Allows importing and reexporting macros with `use`, /// enables macro modularization in general. (accepted, use_extern_macros, "1.30.0", Some(35896)), diff --git a/compiler/rustc_feature/src/removed.rs b/compiler/rustc_feature/src/removed.rs index b7f0ed5afce93..3d7d877ba17e8 100644 --- a/compiler/rustc_feature/src/removed.rs +++ b/compiler/rustc_feature/src/removed.rs @@ -83,7 +83,7 @@ declare_features! ( (removed, custom_derive, "1.32.0", Some(29644), Some("subsumed by `#[proc_macro_derive]`")), /// Allows default type parameters to influence type inference. - (removed, default_type_parameter_fallback, "CURRENT_RUSTC_VERSION", Some(27336), + (removed, default_type_parameter_fallback, "1.82.0", Some(27336), Some("never properly implemented; requires significant design work")), /// Allows using `#[doc(keyword = "...")]`. (removed, doc_keyword, "1.28.0", Some(51315), diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index cd6adbda039b2..5ca33cede302d 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -208,7 +208,7 @@ declare_features! ( /// Allows `#[link(..., cfg(..))]`; perma-unstable per #37406 (unstable, link_cfg, "1.14.0", None), /// Allows using `?Trait` trait bounds in more contexts. - (internal, more_maybe_bounds, "CURRENT_RUSTC_VERSION", None), + (internal, more_maybe_bounds, "1.82.0", None), /// Allows the `multiple_supertrait_upcastable` lint. (unstable, multiple_supertrait_upcastable, "1.69.0", None), /// Allow negative trait bounds. This is an internal-only feature for testing the trait solver! @@ -302,7 +302,7 @@ declare_features! ( // FIXME: Document these and merge with the list below. // Unstable `#[target_feature]` directives. - (unstable, aarch64_unstable_target_feature, "CURRENT_RUSTC_VERSION", Some(44839)), + (unstable, aarch64_unstable_target_feature, "1.82.0", Some(44839)), (unstable, aarch64_ver_target_feature, "1.27.0", Some(44839)), (unstable, arm_target_feature, "1.27.0", Some(44839)), (unstable, avx512_target_feature, "1.27.0", Some(44839)), @@ -317,7 +317,7 @@ declare_features! ( (unstable, prfchw_target_feature, "1.78.0", Some(44839)), (unstable, riscv_target_feature, "1.45.0", Some(44839)), (unstable, rtm_target_feature, "1.35.0", Some(44839)), - (unstable, s390x_target_feature, "CURRENT_RUSTC_VERSION", Some(44839)), + (unstable, s390x_target_feature, "1.82.0", Some(44839)), (unstable, sse4a_target_feature, "1.27.0", Some(44839)), (unstable, tbm_target_feature, "1.27.0", Some(44839)), (unstable, wasm_target_feature, "1.30.0", Some(44839)), @@ -472,7 +472,7 @@ declare_features! ( /// Allows the use of `#[ffi_pure]` on foreign functions. (unstable, ffi_pure, "1.45.0", Some(58329)), /// Controlling the behavior of fmt::Debug - (unstable, fmt_debug, "CURRENT_RUSTC_VERSION", Some(129709)), + (unstable, fmt_debug, "1.82.0", Some(129709)), /// Allows using `#[repr(align(...))]` on function items (unstable, fn_align, "1.53.0", Some(82232)), /// Support delegating implementation of functions to other already implemented functions. @@ -584,8 +584,8 @@ declare_features! ( /// Allows `extern "rust-cold"`. (unstable, rust_cold_cc, "1.63.0", Some(97544)), /// Allows use of x86 SHA512, SM3 and SM4 target-features and intrinsics - (unstable, sha512_sm_x86, "CURRENT_RUSTC_VERSION", Some(126624)), - /// Shorten the tail expression lifetime + (unstable, sha512_sm_x86, "1.82.0", Some(126624)), + /// Shortern the tail expression lifetime (unstable, shorter_tail_lifetimes, "1.79.0", Some(123739)), /// Allows the use of SIMD types in functions declared in `extern` blocks. (unstable, simd_ffi, "1.0.0", Some(27731)), @@ -623,7 +623,7 @@ declare_features! ( (incomplete, unnamed_fields, "1.74.0", Some(49804)), /// Allows const generic parameters to be defined with types that /// are not `Sized`, e.g. `fn foo() {`. - (incomplete, unsized_const_params, "CURRENT_RUSTC_VERSION", Some(95174)), + (incomplete, unsized_const_params, "1.82.0", Some(95174)), /// Allows unsized fn parameters. (internal, unsized_fn_params, "1.49.0", Some(48055)), /// Allows unsized rvalues at arguments and parameters. diff --git a/library/alloc/src/boxed.rs b/library/alloc/src/boxed.rs index a924feaf15f2a..6dc75478700ce 100644 --- a/library/alloc/src/boxed.rs +++ b/library/alloc/src/boxed.rs @@ -272,7 +272,7 @@ impl Box { /// assert_eq!(*five, 5) /// ``` #[cfg(not(no_global_oom_handling))] - #[stable(feature = "new_uninit", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "new_uninit", since = "1.82.0")] #[must_use] #[inline] pub fn new_uninit() -> Box> { @@ -663,7 +663,7 @@ impl Box<[T]> { /// assert_eq!(*values, [1, 2, 3]) /// ``` #[cfg(not(no_global_oom_handling))] - #[stable(feature = "new_uninit", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "new_uninit", since = "1.82.0")] #[must_use] pub fn new_uninit_slice(len: usize) -> Box<[mem::MaybeUninit]> { unsafe { RawVec::with_capacity(len).into_box(len) } @@ -930,7 +930,7 @@ impl Box, A> { /// /// assert_eq!(*five, 5) /// ``` - #[stable(feature = "new_uninit", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "new_uninit", since = "1.82.0")] #[inline] pub unsafe fn assume_init(self) -> Box { let (raw, alloc) = Box::into_raw_with_allocator(self); @@ -1003,7 +1003,7 @@ impl Box<[mem::MaybeUninit], A> { /// /// assert_eq!(*values, [1, 2, 3]) /// ``` - #[stable(feature = "new_uninit", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "new_uninit", since = "1.82.0")] #[inline] pub unsafe fn assume_init(self) -> Box<[T], A> { let (raw, alloc) = Box::into_raw_with_allocator(self); diff --git a/library/alloc/src/collections/binary_heap/mod.rs b/library/alloc/src/collections/binary_heap/mod.rs index 88701370c1056..fe9f1010d327c 100644 --- a/library/alloc/src/collections/binary_heap/mod.rs +++ b/library/alloc/src/collections/binary_heap/mod.rs @@ -1433,7 +1433,7 @@ pub struct Iter<'a, T: 'a> { iter: slice::Iter<'a, T>, } -#[stable(feature = "default_iters_sequel", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "default_iters_sequel", since = "1.82.0")] impl Default for Iter<'_, T> { /// Creates an empty `binary_heap::Iter`. /// diff --git a/library/alloc/src/collections/btree/map.rs b/library/alloc/src/collections/btree/map.rs index c7908578522a5..60e08b47e3d35 100644 --- a/library/alloc/src/collections/btree/map.rs +++ b/library/alloc/src/collections/btree/map.rs @@ -2016,7 +2016,7 @@ impl Default for Range<'_, K, V> { } } -#[stable(feature = "default_iters_sequel", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "default_iters_sequel", since = "1.82.0")] impl Default for RangeMut<'_, K, V> { /// Creates an empty `btree_map::RangeMut`. /// @@ -2064,7 +2064,7 @@ impl ExactSizeIterator for ValuesMut<'_, K, V> { #[stable(feature = "fused", since = "1.26.0")] impl FusedIterator for ValuesMut<'_, K, V> {} -#[stable(feature = "default_iters_sequel", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "default_iters_sequel", since = "1.82.0")] impl Default for ValuesMut<'_, K, V> { /// Creates an empty `btree_map::ValuesMut`. /// diff --git a/library/alloc/src/collections/vec_deque/iter.rs b/library/alloc/src/collections/vec_deque/iter.rs index 67b5b91c4d4b0..bf4dd66f47638 100644 --- a/library/alloc/src/collections/vec_deque/iter.rs +++ b/library/alloc/src/collections/vec_deque/iter.rs @@ -28,7 +28,7 @@ impl fmt::Debug for Iter<'_, T> { } } -#[stable(feature = "default_iters_sequel", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "default_iters_sequel", since = "1.82.0")] impl Default for Iter<'_, T> { /// Creates an empty `vec_deque::Iter`. /// diff --git a/library/alloc/src/collections/vec_deque/iter_mut.rs b/library/alloc/src/collections/vec_deque/iter_mut.rs index 2726e3e425290..7a349a1b4edd0 100644 --- a/library/alloc/src/collections/vec_deque/iter_mut.rs +++ b/library/alloc/src/collections/vec_deque/iter_mut.rs @@ -28,7 +28,7 @@ impl fmt::Debug for IterMut<'_, T> { } } -#[stable(feature = "default_iters_sequel", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "default_iters_sequel", since = "1.82.0")] impl Default for IterMut<'_, T> { /// Creates an empty `vec_deque::IterMut`. /// diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rc.rs index 1b31a78394eca..88c7a12db23ca 100644 --- a/library/alloc/src/rc.rs +++ b/library/alloc/src/rc.rs @@ -517,7 +517,7 @@ impl Rc { /// assert_eq!(*five, 5) /// ``` #[cfg(not(no_global_oom_handling))] - #[stable(feature = "new_uninit", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "new_uninit", since = "1.82.0")] #[must_use] pub fn new_uninit() -> Rc> { unsafe { @@ -980,7 +980,7 @@ impl Rc<[T]> { /// assert_eq!(*values, [1, 2, 3]) /// ``` #[cfg(not(no_global_oom_handling))] - #[stable(feature = "new_uninit", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "new_uninit", since = "1.82.0")] #[must_use] pub fn new_uninit_slice(len: usize) -> Rc<[mem::MaybeUninit]> { unsafe { Rc::from_ptr(Rc::allocate_for_slice(len)) } @@ -1127,7 +1127,7 @@ impl Rc, A> { /// /// assert_eq!(*five, 5) /// ``` - #[stable(feature = "new_uninit", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "new_uninit", since = "1.82.0")] #[inline] pub unsafe fn assume_init(self) -> Rc { let (ptr, alloc) = Rc::into_inner_with_allocator(self); @@ -1167,7 +1167,7 @@ impl Rc<[mem::MaybeUninit], A> { /// /// assert_eq!(*values, [1, 2, 3]) /// ``` - #[stable(feature = "new_uninit", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "new_uninit", since = "1.82.0")] #[inline] pub unsafe fn assume_init(self) -> Rc<[T], A> { let (ptr, alloc) = Rc::into_inner_with_allocator(self); diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs index 024a794f17b01..43684f31cb723 100644 --- a/library/alloc/src/sync.rs +++ b/library/alloc/src/sync.rs @@ -520,7 +520,7 @@ impl Arc { /// ``` #[cfg(not(no_global_oom_handling))] #[inline] - #[stable(feature = "new_uninit", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "new_uninit", since = "1.82.0")] #[must_use] pub fn new_uninit() -> Arc> { unsafe { @@ -1115,7 +1115,7 @@ impl Arc<[T]> { /// ``` #[cfg(not(no_global_oom_handling))] #[inline] - #[stable(feature = "new_uninit", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "new_uninit", since = "1.82.0")] #[must_use] pub fn new_uninit_slice(len: usize) -> Arc<[mem::MaybeUninit]> { unsafe { Arc::from_ptr(Arc::allocate_for_slice(len)) } @@ -1262,7 +1262,7 @@ impl Arc, A> { /// /// assert_eq!(*five, 5) /// ``` - #[stable(feature = "new_uninit", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "new_uninit", since = "1.82.0")] #[must_use = "`self` will be dropped if the result is not used"] #[inline] pub unsafe fn assume_init(self) -> Arc { @@ -1303,7 +1303,7 @@ impl Arc<[mem::MaybeUninit], A> { /// /// assert_eq!(*values, [1, 2, 3]) /// ``` - #[stable(feature = "new_uninit", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "new_uninit", since = "1.82.0")] #[must_use = "`self` will be dropped if the result is not used"] #[inline] pub unsafe fn assume_init(self) -> Arc<[T], A> { diff --git a/library/core/src/future/ready.rs b/library/core/src/future/ready.rs index 6f6da8ce51ddf..b562ad4d8860d 100644 --- a/library/core/src/future/ready.rs +++ b/library/core/src/future/ready.rs @@ -39,7 +39,7 @@ impl Ready { /// let a = future::ready(1); /// assert_eq!(a.into_inner(), 1); /// ``` - #[stable(feature = "ready_into_inner", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "ready_into_inner", since = "1.82.0")] #[must_use] #[inline] pub fn into_inner(self) -> T { diff --git a/library/core/src/iter/adapters/take.rs b/library/core/src/iter/adapters/take.rs index 4c8f9fe16da0f..b96335f415257 100644 --- a/library/core/src/iter/adapters/take.rs +++ b/library/core/src/iter/adapters/take.rs @@ -318,7 +318,7 @@ impl SpecTake for Take { } } -#[stable(feature = "exact_size_take_repeat", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "exact_size_take_repeat", since = "1.82.0")] impl DoubleEndedIterator for Take> { #[inline] fn next_back(&mut self) -> Option { @@ -361,14 +361,14 @@ impl DoubleEndedIterator for Take> { // because we have no way to return value of nth invocation of repeater followed // by n-1st without remembering all results. -#[stable(feature = "exact_size_take_repeat", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "exact_size_take_repeat", since = "1.82.0")] impl ExactSizeIterator for Take> { fn len(&self) -> usize { self.n } } -#[stable(feature = "exact_size_take_repeat", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "exact_size_take_repeat", since = "1.82.0")] impl A, A> ExactSizeIterator for Take> { fn len(&self) -> usize { self.n diff --git a/library/core/src/iter/mod.rs b/library/core/src/iter/mod.rs index 5dad9e1a75ed6..387963d0afd01 100644 --- a/library/core/src/iter/mod.rs +++ b/library/core/src/iter/mod.rs @@ -436,7 +436,7 @@ pub use self::sources::{once, Once}; pub use self::sources::{once_with, OnceWith}; #[stable(feature = "rust1", since = "1.0.0")] pub use self::sources::{repeat, Repeat}; -#[stable(feature = "iter_repeat_n", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "iter_repeat_n", since = "1.82.0")] pub use self::sources::{repeat_n, RepeatN}; #[stable(feature = "iterator_repeat_with", since = "1.28.0")] pub use self::sources::{repeat_with, RepeatWith}; diff --git a/library/core/src/iter/sources.rs b/library/core/src/iter/sources.rs index 55901e1e50b42..2c726fbca8760 100644 --- a/library/core/src/iter/sources.rs +++ b/library/core/src/iter/sources.rs @@ -24,7 +24,7 @@ pub use self::once::{once, Once}; pub use self::once_with::{once_with, OnceWith}; #[stable(feature = "rust1", since = "1.0.0")] pub use self::repeat::{repeat, Repeat}; -#[stable(feature = "iter_repeat_n", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "iter_repeat_n", since = "1.82.0")] pub use self::repeat_n::{repeat_n, RepeatN}; #[stable(feature = "iterator_repeat_with", since = "1.28.0")] pub use self::repeat_with::{repeat_with, RepeatWith}; diff --git a/library/core/src/iter/sources/repeat_n.rs b/library/core/src/iter/sources/repeat_n.rs index 2e247a34075c4..9c0621933638e 100644 --- a/library/core/src/iter/sources/repeat_n.rs +++ b/library/core/src/iter/sources/repeat_n.rs @@ -56,7 +56,7 @@ use crate::num::NonZero; /// assert_eq!(None, it.next()); /// ``` #[inline] -#[stable(feature = "iter_repeat_n", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "iter_repeat_n", since = "1.82.0")] pub fn repeat_n(element: T, count: usize) -> RepeatN { let mut element = ManuallyDrop::new(element); @@ -75,7 +75,7 @@ pub fn repeat_n(element: T, count: usize) -> RepeatN { /// This `struct` is created by the [`repeat_n()`] function. /// See its documentation for more. #[derive(Clone, Debug)] -#[stable(feature = "iter_repeat_n", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "iter_repeat_n", since = "1.82.0")] pub struct RepeatN { count: usize, // Invariant: has been dropped iff count == 0. @@ -99,14 +99,14 @@ impl RepeatN { } } -#[stable(feature = "iter_repeat_n", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "iter_repeat_n", since = "1.82.0")] impl Drop for RepeatN { fn drop(&mut self) { self.take_element(); } } -#[stable(feature = "iter_repeat_n", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "iter_repeat_n", since = "1.82.0")] impl Iterator for RepeatN { type Item = A; @@ -154,14 +154,14 @@ impl Iterator for RepeatN { } } -#[stable(feature = "iter_repeat_n", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "iter_repeat_n", since = "1.82.0")] impl ExactSizeIterator for RepeatN { fn len(&self) -> usize { self.count } } -#[stable(feature = "iter_repeat_n", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "iter_repeat_n", since = "1.82.0")] impl DoubleEndedIterator for RepeatN { #[inline] fn next_back(&mut self) -> Option { @@ -179,12 +179,12 @@ impl DoubleEndedIterator for RepeatN { } } -#[stable(feature = "iter_repeat_n", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "iter_repeat_n", since = "1.82.0")] impl FusedIterator for RepeatN {} #[unstable(feature = "trusted_len", issue = "37572")] unsafe impl TrustedLen for RepeatN {} -#[stable(feature = "iter_repeat_n", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "iter_repeat_n", since = "1.82.0")] impl UncheckedIterator for RepeatN { #[inline] unsafe fn next_unchecked(&mut self) -> Self::Item { diff --git a/library/core/src/iter/traits/iterator.rs b/library/core/src/iter/traits/iterator.rs index 50a2d952e5b36..8352486ad416e 100644 --- a/library/core/src/iter/traits/iterator.rs +++ b/library/core/src/iter/traits/iterator.rs @@ -3953,7 +3953,7 @@ pub trait Iterator { /// assert!(![0.0, 1.0, f32::NAN].iter().is_sorted()); /// ``` #[inline] - #[stable(feature = "is_sorted", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "is_sorted", since = "1.82.0")] #[rustc_do_not_const_check] fn is_sorted(self) -> bool where @@ -3980,7 +3980,7 @@ pub trait Iterator { /// assert!(std::iter::empty::().is_sorted_by(|a, b| false)); /// assert!(std::iter::empty::().is_sorted_by(|a, b| true)); /// ``` - #[stable(feature = "is_sorted", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "is_sorted", since = "1.82.0")] #[rustc_do_not_const_check] fn is_sorted_by(mut self, compare: F) -> bool where @@ -4025,7 +4025,7 @@ pub trait Iterator { /// assert!(![-2i32, -1, 0, 3].iter().is_sorted_by_key(|n| n.abs())); /// ``` #[inline] - #[stable(feature = "is_sorted", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "is_sorted", since = "1.82.0")] #[rustc_do_not_const_check] fn is_sorted_by_key(self, f: F) -> bool where diff --git a/library/core/src/num/error.rs b/library/core/src/num/error.rs index b8e22a8aef955..6ef2fdd14c149 100644 --- a/library/core/src/num/error.rs +++ b/library/core/src/num/error.rs @@ -113,7 +113,7 @@ pub enum IntErrorKind { impl ParseIntError { /// Outputs the detailed cause of parsing an integer failing. #[must_use] - #[rustc_const_stable(feature = "const_int_from_str", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_int_from_str", since = "1.82.0")] #[stable(feature = "int_error_matching", since = "1.55.0")] pub const fn kind(&self) -> &IntErrorKind { &self.kind diff --git a/library/core/src/num/mod.rs b/library/core/src/num/mod.rs index e9e5324666ada..37c9db7f474b5 100644 --- a/library/core/src/num/mod.rs +++ b/library/core/src/num/mod.rs @@ -1385,7 +1385,7 @@ from_str_radix_int_impl! { isize i8 i16 i32 i64 i128 usize u8 u16 u32 u64 u128 } #[doc(hidden)] #[inline(always)] #[unstable(issue = "none", feature = "std_internals")] -#[rustc_const_stable(feature = "const_int_from_str", since = "CURRENT_RUSTC_VERSION")] +#[rustc_const_stable(feature = "const_int_from_str", since = "1.82.0")] pub const fn can_not_overflow(radix: u32, is_signed_ty: bool, digits: &[u8]) -> bool { radix <= 16 && digits.len() <= mem::size_of::() * 2 - is_signed_ty as usize } @@ -1435,7 +1435,7 @@ macro_rules! from_str_radix { #[doc = concat!("assert_eq!(", stringify!($int_ty), "::from_str_radix(\"A\", 16), Ok(10));")] /// ``` #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_stable(feature = "const_int_from_str", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_int_from_str", since = "1.82.0")] pub const fn from_str_radix(src: &str, radix: u32) -> Result<$int_ty, ParseIntError> { use self::IntErrorKind::*; use self::ParseIntError as PIE; @@ -1565,7 +1565,7 @@ macro_rules! from_str_radix_size_impl { #[doc = concat!("assert_eq!(", stringify!($size), "::from_str_radix(\"A\", 16), Ok(10));")] /// ``` #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_stable(feature = "const_int_from_str", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_int_from_str", since = "1.82.0")] pub const fn from_str_radix(src: &str, radix: u32) -> Result<$size, ParseIntError> { match <$t>::from_str_radix(src, radix) { Ok(x) => Ok(x as $size), diff --git a/library/core/src/option.rs b/library/core/src/option.rs index 50cb22b7eb3f5..212e4f0215463 100644 --- a/library/core/src/option.rs +++ b/library/core/src/option.rs @@ -667,7 +667,7 @@ impl Option { /// ``` #[must_use] #[inline] - #[stable(feature = "is_none_or", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "is_none_or", since = "1.82.0")] pub fn is_none_or(self, f: impl FnOnce(T) -> bool) -> bool { match self { None => true, diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs index c7918499d4ab9..166189f4b6cf3 100644 --- a/library/core/src/slice/mod.rs +++ b/library/core/src/slice/mod.rs @@ -4088,7 +4088,7 @@ impl [T] { /// assert!(![0.0, 1.0, f32::NAN].is_sorted()); /// ``` #[inline] - #[stable(feature = "is_sorted", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "is_sorted", since = "1.82.0")] #[must_use] pub fn is_sorted(&self) -> bool where @@ -4115,7 +4115,7 @@ impl [T] { /// assert!(empty.is_sorted_by(|a, b| false)); /// assert!(empty.is_sorted_by(|a, b| true)); /// ``` - #[stable(feature = "is_sorted", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "is_sorted", since = "1.82.0")] #[must_use] pub fn is_sorted_by<'a, F>(&'a self, mut compare: F) -> bool where @@ -4139,7 +4139,7 @@ impl [T] { /// assert!(![-2i32, -1, 0, 3].is_sorted_by_key(|n| n.abs())); /// ``` #[inline] - #[stable(feature = "is_sorted", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "is_sorted", since = "1.82.0")] #[must_use] pub fn is_sorted_by_key<'a, F, K>(&'a self, f: F) -> bool where diff --git a/library/core/src/str/iter.rs b/library/core/src/str/iter.rs index 681ec79c0b7bf..d9301a8a66ea2 100644 --- a/library/core/src/str/iter.rs +++ b/library/core/src/str/iter.rs @@ -269,7 +269,7 @@ impl<'a> CharIndices<'a> { /// ``` #[inline] #[must_use] - #[stable(feature = "char_indices_offset", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "char_indices_offset", since = "1.82.0")] pub fn offset(&self) -> usize { self.front_offset } diff --git a/library/core/src/task/wake.rs b/library/core/src/task/wake.rs index 7e5c1574f5367..1761584cfc4e3 100644 --- a/library/core/src/task/wake.rs +++ b/library/core/src/task/wake.rs @@ -250,7 +250,7 @@ pub struct Context<'a> { impl<'a> Context<'a> { /// Creates a new `Context` from a [`&Waker`](Waker). #[stable(feature = "futures_api", since = "1.36.0")] - #[rustc_const_stable(feature = "const_waker", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_waker", since = "1.82.0")] #[must_use] #[inline] pub const fn from_waker(waker: &'a Waker) -> Self { @@ -261,7 +261,7 @@ impl<'a> Context<'a> { #[inline] #[must_use] #[stable(feature = "futures_api", since = "1.36.0")] - #[rustc_const_stable(feature = "const_waker", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_waker", since = "1.82.0")] pub const fn waker(&self) -> &'a Waker { &self.waker } @@ -337,7 +337,7 @@ impl<'a> ContextBuilder<'a> { /// Creates a ContextBuilder from a Waker. #[inline] #[unstable(feature = "local_waker", issue = "118959")] - #[rustc_const_stable(feature = "const_waker", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_waker", since = "1.82.0")] pub const fn from_waker(waker: &'a Waker) -> Self { // SAFETY: LocalWaker is just Waker without thread safety let local_waker = unsafe { transmute(waker) }; @@ -395,7 +395,7 @@ impl<'a> ContextBuilder<'a> { /// Builds the `Context`. #[inline] #[unstable(feature = "local_waker", issue = "118959")] - #[rustc_const_stable(feature = "const_waker", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_waker", since = "1.82.0")] pub const fn build(self) -> Context<'a> { let ContextBuilder { waker, local_waker, ext, _marker, _marker2 } = self; Context { waker, local_waker, ext: AssertUnwindSafe(ext), _marker, _marker2 } @@ -523,7 +523,7 @@ impl Waker { #[inline] #[must_use] #[stable(feature = "futures_api", since = "1.36.0")] - #[rustc_const_stable(feature = "const_waker", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_waker", since = "1.82.0")] pub const unsafe fn from_raw(waker: RawWaker) -> Waker { Waker { waker } } diff --git a/library/std/src/thread/mod.rs b/library/std/src/thread/mod.rs index e29c28f3c7ec2..0fc63c5081b03 100644 --- a/library/std/src/thread/mod.rs +++ b/library/std/src/thread/mod.rs @@ -432,7 +432,7 @@ impl Builder { /// ``` /// /// [`io::Result`]: crate::io::Result - #[stable(feature = "thread_spawn_unchecked", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "thread_spawn_unchecked", since = "1.82.0")] pub unsafe fn spawn_unchecked(self, f: F) -> io::Result> where F: FnOnce() -> T, From 197df44af97026e6c04da77a73c3121387f9816f Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 3 Sep 2024 21:58:18 +0200 Subject: [PATCH 0464/2194] Regenerate intrinsics --- src/intrinsic/archs.rs | 364 ++++++++++++++++++++++++++--------------- 1 file changed, 234 insertions(+), 130 deletions(-) diff --git a/src/intrinsic/archs.rs b/src/intrinsic/archs.rs index f750093378989..b8d1cde1d5dda 100644 --- a/src/intrinsic/archs.rs +++ b/src/intrinsic/archs.rs @@ -31,8 +31,11 @@ match name { "llvm.AMDGPU.trig.preop.v2f64" => "__builtin_amdgpu_trig_preop", "llvm.AMDGPU.trig.preop.v4f32" => "__builtin_amdgpu_trig_preop", // aarch64 + "llvm.aarch64.chkfeat" => "__builtin_arm_chkfeat", "llvm.aarch64.dmb" => "__builtin_arm_dmb", "llvm.aarch64.dsb" => "__builtin_arm_dsb", + "llvm.aarch64.gcspopm" => "__builtin_arm_gcspopm", + "llvm.aarch64.gcsss" => "__builtin_arm_gcsss", "llvm.aarch64.isb" => "__builtin_arm_isb", "llvm.aarch64.prefetch" => "__builtin_arm_prefetch", "llvm.aarch64.sve.aesd" => "__builtin_sve_svaesd_u8", @@ -80,7 +83,6 @@ match name { "llvm.amdgcn.dot4.f32.fp8.fp8" => "__builtin_amdgcn_dot4_f32_fp8_fp8", "llvm.amdgcn.ds.add.gs.reg.rtn" => "__builtin_amdgcn_ds_add_gs_reg_rtn", "llvm.amdgcn.ds.bpermute" => "__builtin_amdgcn_ds_bpermute", - "llvm.amdgcn.ds.fadd.v2bf16" => "__builtin_amdgcn_ds_atomic_fadd_v2bf16", "llvm.amdgcn.ds.gws.barrier" => "__builtin_amdgcn_ds_gws_barrier", "llvm.amdgcn.ds.gws.init" => "__builtin_amdgcn_ds_gws_init", "llvm.amdgcn.ds.gws.sema.br" => "__builtin_amdgcn_ds_gws_sema_br", @@ -96,6 +98,7 @@ match name { "llvm.amdgcn.fdot2.f16.f16" => "__builtin_amdgcn_fdot2_f16_f16", "llvm.amdgcn.fdot2.f32.bf16" => "__builtin_amdgcn_fdot2_f32_bf16", "llvm.amdgcn.fmul.legacy" => "__builtin_amdgcn_fmul_legacy", + "llvm.amdgcn.global.load.lds" => "__builtin_amdgcn_global_load_lds", "llvm.amdgcn.groupstaticsize" => "__builtin_amdgcn_groupstaticsize", "llvm.amdgcn.iglp.opt" => "__builtin_amdgcn_iglp_opt", "llvm.amdgcn.implicit.buffer.ptr" => "__builtin_amdgcn_implicit_buffer_ptr", @@ -154,16 +157,11 @@ match name { "llvm.amdgcn.mqsad.u32.u8" => "__builtin_amdgcn_mqsad_u32_u8", "llvm.amdgcn.msad.u8" => "__builtin_amdgcn_msad_u8", "llvm.amdgcn.perm" => "__builtin_amdgcn_perm", - "llvm.amdgcn.permlane16" => "__builtin_amdgcn_permlane16", "llvm.amdgcn.permlane16.var" => "__builtin_amdgcn_permlane16_var", - "llvm.amdgcn.permlane64" => "__builtin_amdgcn_permlane64", - "llvm.amdgcn.permlanex16" => "__builtin_amdgcn_permlanex16", "llvm.amdgcn.permlanex16.var" => "__builtin_amdgcn_permlanex16_var", "llvm.amdgcn.qsad.pk.u16.u8" => "__builtin_amdgcn_qsad_pk_u16_u8", "llvm.amdgcn.queue.ptr" => "__builtin_amdgcn_queue_ptr", "llvm.amdgcn.rcp.legacy" => "__builtin_amdgcn_rcp_legacy", - "llvm.amdgcn.readfirstlane" => "__builtin_amdgcn_readfirstlane", - "llvm.amdgcn.readlane" => "__builtin_amdgcn_readlane", "llvm.amdgcn.rsq.legacy" => "__builtin_amdgcn_rsq_legacy", "llvm.amdgcn.s.barrier" => "__builtin_amdgcn_s_barrier", "llvm.amdgcn.s.barrier.init" => "__builtin_amdgcn_s_barrier_init", @@ -192,6 +190,8 @@ match name { "llvm.amdgcn.s.setreg" => "__builtin_amdgcn_s_setreg", "llvm.amdgcn.s.sleep" => "__builtin_amdgcn_s_sleep", "llvm.amdgcn.s.sleep.var" => "__builtin_amdgcn_s_sleep_var", + "llvm.amdgcn.s.ttracedata" => "__builtin_amdgcn_s_ttracedata", + "llvm.amdgcn.s.ttracedata.imm" => "__builtin_amdgcn_s_ttracedata_imm", "llvm.amdgcn.s.wait.event.export.ready" => "__builtin_amdgcn_s_wait_event_export_ready", "llvm.amdgcn.s.waitcnt" => "__builtin_amdgcn_s_waitcnt", "llvm.amdgcn.s.wakeup.barrier" => "__builtin_amdgcn_s_wakeup_barrier", @@ -227,7 +227,6 @@ match name { "llvm.amdgcn.workgroup.id.x" => "__builtin_amdgcn_workgroup_id_x", "llvm.amdgcn.workgroup.id.y" => "__builtin_amdgcn_workgroup_id_y", "llvm.amdgcn.workgroup.id.z" => "__builtin_amdgcn_workgroup_id_z", - "llvm.amdgcn.writelane" => "__builtin_amdgcn_writelane", // arm "llvm.arm.cdp" => "__builtin_arm_cdp", "llvm.arm.cdp2" => "__builtin_arm_cdp2", @@ -4536,10 +4535,18 @@ match name { "llvm.nvvm.div.rz.d" => "__nvvm_div_rz_d", "llvm.nvvm.div.rz.f" => "__nvvm_div_rz_f", "llvm.nvvm.div.rz.ftz.f" => "__nvvm_div_rz_ftz_f", + "llvm.nvvm.e4m3x2.to.f16x2.rn" => "__nvvm_e4m3x2_to_f16x2_rn", + "llvm.nvvm.e4m3x2.to.f16x2.rn.relu" => "__nvvm_e4m3x2_to_f16x2_rn_relu", + "llvm.nvvm.e5m2x2.to.f16x2.rn" => "__nvvm_e5m2x2_to_f16x2_rn", + "llvm.nvvm.e5m2x2.to.f16x2.rn.relu" => "__nvvm_e5m2x2_to_f16x2_rn_relu", "llvm.nvvm.ex2.approx.d" => "__nvvm_ex2_approx_d", "llvm.nvvm.ex2.approx.f" => "__nvvm_ex2_approx_f", "llvm.nvvm.ex2.approx.ftz.f" => "__nvvm_ex2_approx_ftz_f", "llvm.nvvm.exit" => "__nvvm_exit", + "llvm.nvvm.f16x2.to.e4m3x2.rn" => "__nvvm_f16x2_to_e4m3x2_rn", + "llvm.nvvm.f16x2.to.e4m3x2.rn.relu" => "__nvvm_f16x2_to_e4m3x2_rn_relu", + "llvm.nvvm.f16x2.to.e5m2x2.rn" => "__nvvm_f16x2_to_e5m2x2_rn", + "llvm.nvvm.f16x2.to.e5m2x2.rn.relu" => "__nvvm_f16x2_to_e5m2x2_rn_relu", "llvm.nvvm.f2bf16.rn" => "__nvvm_f2bf16_rn", "llvm.nvvm.f2bf16.rn.relu" => "__nvvm_f2bf16_rn_relu", "llvm.nvvm.f2bf16.rz" => "__nvvm_f2bf16_rz", @@ -4582,6 +4589,10 @@ match name { "llvm.nvvm.fabs.d" => "__nvvm_fabs_d", "llvm.nvvm.fabs.f" => "__nvvm_fabs_f", "llvm.nvvm.fabs.ftz.f" => "__nvvm_fabs_ftz_f", + "llvm.nvvm.ff.to.e4m3x2.rn" => "__nvvm_ff_to_e4m3x2_rn", + "llvm.nvvm.ff.to.e4m3x2.rn.relu" => "__nvvm_ff_to_e4m3x2_rn_relu", + "llvm.nvvm.ff.to.e5m2x2.rn" => "__nvvm_ff_to_e5m2x2_rn", + "llvm.nvvm.ff.to.e5m2x2.rn.relu" => "__nvvm_ff_to_e5m2x2_rn_relu", "llvm.nvvm.ff2bf16x2.rn" => "__nvvm_ff2bf16x2_rn", "llvm.nvvm.ff2bf16x2.rn.relu" => "__nvvm_ff2bf16x2_rn_relu", "llvm.nvvm.ff2bf16x2.rz" => "__nvvm_ff2bf16x2_rz", @@ -4866,6 +4877,7 @@ match name { "llvm.nvvm.round.ftz.f" => "__nvvm_round_ftz_f", "llvm.nvvm.rsqrt.approx.d" => "__nvvm_rsqrt_approx_d", "llvm.nvvm.rsqrt.approx.f" => "__nvvm_rsqrt_approx_f", + "llvm.nvvm.rsqrt.approx.ftz.d" => "__nvvm_rsqrt_approx_ftz_d", "llvm.nvvm.rsqrt.approx.ftz.f" => "__nvvm_rsqrt_approx_ftz_f", "llvm.nvvm.sad.i" => "__nvvm_sad_i", "llvm.nvvm.sad.ll" => "__nvvm_sad_ll", @@ -5164,6 +5176,8 @@ match name { // ppc "llvm.ppc.addex" => "__builtin_ppc_addex", "llvm.ppc.addf128.round.to.odd" => "__builtin_addf128_round_to_odd", + "llvm.ppc.addg6s" => "__builtin_addg6s", + "llvm.ppc.addg6sd" => "__builtin_ppc_addg6s", "llvm.ppc.altivec.crypto.vcipher" => "__builtin_altivec_crypto_vcipher", "llvm.ppc.altivec.crypto.vcipherlast" => "__builtin_altivec_crypto_vcipherlast", "llvm.ppc.altivec.crypto.vncipher" => "__builtin_altivec_crypto_vncipher", @@ -5461,6 +5475,10 @@ match name { "llvm.ppc.bcdsub" => "__builtin_ppc_bcdsub", "llvm.ppc.bcdsub.p" => "__builtin_ppc_bcdsub_p", "llvm.ppc.bpermd" => "__builtin_bpermd", + "llvm.ppc.cbcdtd" => "__builtin_cbcdtd", + "llvm.ppc.cbcdtdd" => "__builtin_ppc_cbcdtd", + "llvm.ppc.cdtbcd" => "__builtin_cdtbcd", + "llvm.ppc.cdtbcdd" => "__builtin_ppc_cdtbcd", "llvm.ppc.cfuged" => "__builtin_cfuged", "llvm.ppc.cmpeqb" => "__builtin_ppc_cmpeqb", "llvm.ppc.cmprb" => "__builtin_ppc_cmprb", @@ -5627,7 +5645,6 @@ match name { "llvm.ppc.qpx.qvstfs" => "__builtin_qpx_qvstfs", "llvm.ppc.qpx.qvstfsa" => "__builtin_qpx_qvstfsa", "llvm.ppc.readflm" => "__builtin_readflm", - "llvm.ppc.rldimi" => "__builtin_ppc_rldimi", "llvm.ppc.rlwimi" => "__builtin_ppc_rlwimi", "llvm.ppc.rlwnm" => "__builtin_ppc_rlwnm", "llvm.ppc.scalar.extract.expq" => "__builtin_vsx_scalar_extract_expq", @@ -7210,29 +7227,6 @@ match name { "llvm.ve.vl.xorm.MMM" => "__builtin_ve_vl_xorm_MMM", "llvm.ve.vl.xorm.mmm" => "__builtin_ve_vl_xorm_mmm", // x86 - "llvm.x86.3dnow.pavgusb" => "__builtin_ia32_pavgusb", - "llvm.x86.3dnow.pf2id" => "__builtin_ia32_pf2id", - "llvm.x86.3dnow.pfacc" => "__builtin_ia32_pfacc", - "llvm.x86.3dnow.pfadd" => "__builtin_ia32_pfadd", - "llvm.x86.3dnow.pfcmpeq" => "__builtin_ia32_pfcmpeq", - "llvm.x86.3dnow.pfcmpge" => "__builtin_ia32_pfcmpge", - "llvm.x86.3dnow.pfcmpgt" => "__builtin_ia32_pfcmpgt", - "llvm.x86.3dnow.pfmax" => "__builtin_ia32_pfmax", - "llvm.x86.3dnow.pfmin" => "__builtin_ia32_pfmin", - "llvm.x86.3dnow.pfmul" => "__builtin_ia32_pfmul", - "llvm.x86.3dnow.pfrcp" => "__builtin_ia32_pfrcp", - "llvm.x86.3dnow.pfrcpit1" => "__builtin_ia32_pfrcpit1", - "llvm.x86.3dnow.pfrcpit2" => "__builtin_ia32_pfrcpit2", - "llvm.x86.3dnow.pfrsqit1" => "__builtin_ia32_pfrsqit1", - "llvm.x86.3dnow.pfrsqrt" => "__builtin_ia32_pfrsqrt", - "llvm.x86.3dnow.pfsub" => "__builtin_ia32_pfsub", - "llvm.x86.3dnow.pfsubr" => "__builtin_ia32_pfsubr", - "llvm.x86.3dnow.pi2fd" => "__builtin_ia32_pi2fd", - "llvm.x86.3dnow.pmulhrw" => "__builtin_ia32_pmulhrw", - "llvm.x86.3dnowa.pf2iw" => "__builtin_ia32_pf2iw", - "llvm.x86.3dnowa.pfnacc" => "__builtin_ia32_pfnacc", - "llvm.x86.3dnowa.pfpnacc" => "__builtin_ia32_pfpnacc", - "llvm.x86.3dnowa.pi2fw" => "__builtin_ia32_pi2fw", "llvm.x86.aadd32" => "__builtin_ia32_aadd32", "llvm.x86.aadd64" => "__builtin_ia32_aadd64", "llvm.x86.aand32" => "__builtin_ia32_aand32", @@ -7334,6 +7328,207 @@ match name { "llvm.x86.avx.vtestz.ps.256" => "__builtin_ia32_vtestzps256", "llvm.x86.avx.vzeroall" => "__builtin_ia32_vzeroall", "llvm.x86.avx.vzeroupper" => "__builtin_ia32_vzeroupper", + "llvm.x86.avx10.mask.vcvt2ps2phx.128" => "__builtin_ia32_vcvt2ps2phx128_mask", + "llvm.x86.avx10.mask.vcvt2ps2phx.256" => "__builtin_ia32_vcvt2ps2phx256_mask", + "llvm.x86.avx10.mask.vcvt2ps2phx.512" => "__builtin_ia32_vcvt2ps2phx512_mask", + "llvm.x86.avx10.mask.vcvtbiasph2bf8128" => "__builtin_ia32_vcvtbiasph2bf8_128_mask", + "llvm.x86.avx10.mask.vcvtbiasph2bf8256" => "__builtin_ia32_vcvtbiasph2bf8_256_mask", + "llvm.x86.avx10.mask.vcvtbiasph2bf8512" => "__builtin_ia32_vcvtbiasph2bf8_512_mask", + "llvm.x86.avx10.mask.vcvtbiasph2bf8s128" => "__builtin_ia32_vcvtbiasph2bf8s_128_mask", + "llvm.x86.avx10.mask.vcvtbiasph2bf8s256" => "__builtin_ia32_vcvtbiasph2bf8s_256_mask", + "llvm.x86.avx10.mask.vcvtbiasph2bf8s512" => "__builtin_ia32_vcvtbiasph2bf8s_512_mask", + "llvm.x86.avx10.mask.vcvtbiasph2hf8128" => "__builtin_ia32_vcvtbiasph2hf8_128_mask", + "llvm.x86.avx10.mask.vcvtbiasph2hf8256" => "__builtin_ia32_vcvtbiasph2hf8_256_mask", + "llvm.x86.avx10.mask.vcvtbiasph2hf8512" => "__builtin_ia32_vcvtbiasph2hf8_512_mask", + "llvm.x86.avx10.mask.vcvtbiasph2hf8s128" => "__builtin_ia32_vcvtbiasph2hf8s_128_mask", + "llvm.x86.avx10.mask.vcvtbiasph2hf8s256" => "__builtin_ia32_vcvtbiasph2hf8s_256_mask", + "llvm.x86.avx10.mask.vcvtbiasph2hf8s512" => "__builtin_ia32_vcvtbiasph2hf8s_512_mask", + "llvm.x86.avx10.mask.vcvthf82ph128" => "__builtin_ia32_vcvthf8_2ph128_mask", + "llvm.x86.avx10.mask.vcvthf82ph256" => "__builtin_ia32_vcvthf8_2ph256_mask", + "llvm.x86.avx10.mask.vcvthf82ph512" => "__builtin_ia32_vcvthf8_2ph512_mask", + "llvm.x86.avx10.mask.vcvtneph2bf8128" => "__builtin_ia32_vcvtneph2bf8_128_mask", + "llvm.x86.avx10.mask.vcvtneph2bf8256" => "__builtin_ia32_vcvtneph2bf8_256_mask", + "llvm.x86.avx10.mask.vcvtneph2bf8512" => "__builtin_ia32_vcvtneph2bf8_512_mask", + "llvm.x86.avx10.mask.vcvtneph2bf8s128" => "__builtin_ia32_vcvtneph2bf8s_128_mask", + "llvm.x86.avx10.mask.vcvtneph2bf8s256" => "__builtin_ia32_vcvtneph2bf8s_256_mask", + "llvm.x86.avx10.mask.vcvtneph2bf8s512" => "__builtin_ia32_vcvtneph2bf8s_512_mask", + "llvm.x86.avx10.mask.vcvtneph2hf8128" => "__builtin_ia32_vcvtneph2hf8_128_mask", + "llvm.x86.avx10.mask.vcvtneph2hf8256" => "__builtin_ia32_vcvtneph2hf8_256_mask", + "llvm.x86.avx10.mask.vcvtneph2hf8512" => "__builtin_ia32_vcvtneph2hf8_512_mask", + "llvm.x86.avx10.mask.vcvtneph2hf8s128" => "__builtin_ia32_vcvtneph2hf8s_128_mask", + "llvm.x86.avx10.mask.vcvtneph2hf8s256" => "__builtin_ia32_vcvtneph2hf8s_256_mask", + "llvm.x86.avx10.mask.vcvtneph2hf8s512" => "__builtin_ia32_vcvtneph2hf8s_512_mask", + // [INVALID CONVERSION]: "llvm.x86.avx10.mask.vcvtpd2dq256" => "__builtin_ia32_vcvtpd2dq256_round_mask", + // [INVALID CONVERSION]: "llvm.x86.avx10.mask.vcvtpd2ph256" => "__builtin_ia32_vcvtpd2ph256_round_mask", + // [INVALID CONVERSION]: "llvm.x86.avx10.mask.vcvtpd2ps256" => "__builtin_ia32_vcvtpd2ps256_round_mask", + // [INVALID CONVERSION]: "llvm.x86.avx10.mask.vcvtpd2qq256" => "__builtin_ia32_vcvtpd2qq256_round_mask", + // [INVALID CONVERSION]: "llvm.x86.avx10.mask.vcvtpd2udq256" => "__builtin_ia32_vcvtpd2udq256_round_mask", + // [INVALID CONVERSION]: "llvm.x86.avx10.mask.vcvtpd2uqq256" => "__builtin_ia32_vcvtpd2uqq256_round_mask", + // [INVALID CONVERSION]: "llvm.x86.avx10.mask.vcvtph2dq256" => "__builtin_ia32_vcvtph2dq256_round_mask", + "llvm.x86.avx10.mask.vcvtph2ibs128" => "__builtin_ia32_vcvtph2ibs128_mask", + "llvm.x86.avx10.mask.vcvtph2ibs256" => "__builtin_ia32_vcvtph2ibs256_mask", + "llvm.x86.avx10.mask.vcvtph2ibs512" => "__builtin_ia32_vcvtph2ibs512_mask", + "llvm.x86.avx10.mask.vcvtph2iubs128" => "__builtin_ia32_vcvtph2iubs128_mask", + "llvm.x86.avx10.mask.vcvtph2iubs256" => "__builtin_ia32_vcvtph2iubs256_mask", + "llvm.x86.avx10.mask.vcvtph2iubs512" => "__builtin_ia32_vcvtph2iubs512_mask", + // [INVALID CONVERSION]: "llvm.x86.avx10.mask.vcvtph2pd256" => "__builtin_ia32_vcvtph2pd256_round_mask", + // [INVALID CONVERSION]: "llvm.x86.avx10.mask.vcvtph2psx256" => "__builtin_ia32_vcvtph2psx256_round_mask", + // [INVALID CONVERSION]: "llvm.x86.avx10.mask.vcvtph2qq256" => "__builtin_ia32_vcvtph2qq256_round_mask", + // [INVALID CONVERSION]: "llvm.x86.avx10.mask.vcvtph2udq256" => "__builtin_ia32_vcvtph2udq256_round_mask", + // [INVALID CONVERSION]: "llvm.x86.avx10.mask.vcvtph2uqq256" => "__builtin_ia32_vcvtph2uqq256_round_mask", + // [INVALID CONVERSION]: "llvm.x86.avx10.mask.vcvtph2uw256" => "__builtin_ia32_vcvtph2uw256_round_mask", + // [INVALID CONVERSION]: "llvm.x86.avx10.mask.vcvtph2w256" => "__builtin_ia32_vcvtph2w256_round_mask", + // [INVALID CONVERSION]: "llvm.x86.avx10.mask.vcvtps2dq256" => "__builtin_ia32_vcvtps2dq256_round_mask", + "llvm.x86.avx10.mask.vcvtps2ibs128" => "__builtin_ia32_vcvtps2ibs128_mask", + "llvm.x86.avx10.mask.vcvtps2ibs256" => "__builtin_ia32_vcvtps2ibs256_mask", + "llvm.x86.avx10.mask.vcvtps2ibs512" => "__builtin_ia32_vcvtps2ibs512_mask", + "llvm.x86.avx10.mask.vcvtps2iubs128" => "__builtin_ia32_vcvtps2iubs128_mask", + "llvm.x86.avx10.mask.vcvtps2iubs256" => "__builtin_ia32_vcvtps2iubs256_mask", + "llvm.x86.avx10.mask.vcvtps2iubs512" => "__builtin_ia32_vcvtps2iubs512_mask", + // [INVALID CONVERSION]: "llvm.x86.avx10.mask.vcvtps2pd256" => "__builtin_ia32_vcvtps2pd256_round_mask", + // [INVALID CONVERSION]: "llvm.x86.avx10.mask.vcvtps2ph256" => "__builtin_ia32_vcvtps2ph256_round_mask", + // [INVALID CONVERSION]: "llvm.x86.avx10.mask.vcvtps2phx256" => "__builtin_ia32_vcvtps2phx256_round_mask", + // [INVALID CONVERSION]: "llvm.x86.avx10.mask.vcvtps2qq256" => "__builtin_ia32_vcvtps2qq256_round_mask", + // [INVALID CONVERSION]: "llvm.x86.avx10.mask.vcvtps2udq256" => "__builtin_ia32_vcvtps2udq256_round_mask", + // [INVALID CONVERSION]: "llvm.x86.avx10.mask.vcvtps2uqq256" => "__builtin_ia32_vcvtps2uqq256_round_mask", + // [INVALID CONVERSION]: "llvm.x86.avx10.mask.vcvttpd2dq256" => "__builtin_ia32_vcvttpd2dq256_round_mask", + // [INVALID CONVERSION]: "llvm.x86.avx10.mask.vcvttpd2qq256" => "__builtin_ia32_vcvttpd2qq256_round_mask", + // [INVALID CONVERSION]: "llvm.x86.avx10.mask.vcvttpd2udq256" => "__builtin_ia32_vcvttpd2udq256_round_mask", + // [INVALID CONVERSION]: "llvm.x86.avx10.mask.vcvttpd2uqq256" => "__builtin_ia32_vcvttpd2uqq256_round_mask", + // [INVALID CONVERSION]: "llvm.x86.avx10.mask.vcvttph2dq256" => "__builtin_ia32_vcvttph2dq256_round_mask", + "llvm.x86.avx10.mask.vcvttph2ibs128" => "__builtin_ia32_vcvttph2ibs128_mask", + "llvm.x86.avx10.mask.vcvttph2ibs256" => "__builtin_ia32_vcvttph2ibs256_mask", + "llvm.x86.avx10.mask.vcvttph2ibs512" => "__builtin_ia32_vcvttph2ibs512_mask", + "llvm.x86.avx10.mask.vcvttph2iubs128" => "__builtin_ia32_vcvttph2iubs128_mask", + "llvm.x86.avx10.mask.vcvttph2iubs256" => "__builtin_ia32_vcvttph2iubs256_mask", + "llvm.x86.avx10.mask.vcvttph2iubs512" => "__builtin_ia32_vcvttph2iubs512_mask", + // [INVALID CONVERSION]: "llvm.x86.avx10.mask.vcvttph2qq256" => "__builtin_ia32_vcvttph2qq256_round_mask", + // [INVALID CONVERSION]: "llvm.x86.avx10.mask.vcvttph2udq256" => "__builtin_ia32_vcvttph2udq256_round_mask", + // [INVALID CONVERSION]: "llvm.x86.avx10.mask.vcvttph2uqq256" => "__builtin_ia32_vcvttph2uqq256_round_mask", + // [INVALID CONVERSION]: "llvm.x86.avx10.mask.vcvttph2uw256" => "__builtin_ia32_vcvttph2uw256_round_mask", + // [INVALID CONVERSION]: "llvm.x86.avx10.mask.vcvttph2w256" => "__builtin_ia32_vcvttph2w256_round_mask", + // [INVALID CONVERSION]: "llvm.x86.avx10.mask.vcvttps2dq256" => "__builtin_ia32_vcvttps2dq256_round_mask", + "llvm.x86.avx10.mask.vcvttps2ibs128" => "__builtin_ia32_vcvttps2ibs128_mask", + "llvm.x86.avx10.mask.vcvttps2ibs256" => "__builtin_ia32_vcvttps2ibs256_mask", + "llvm.x86.avx10.mask.vcvttps2ibs512" => "__builtin_ia32_vcvttps2ibs512_mask", + "llvm.x86.avx10.mask.vcvttps2iubs128" => "__builtin_ia32_vcvttps2iubs128_mask", + "llvm.x86.avx10.mask.vcvttps2iubs256" => "__builtin_ia32_vcvttps2iubs256_mask", + "llvm.x86.avx10.mask.vcvttps2iubs512" => "__builtin_ia32_vcvttps2iubs512_mask", + // [INVALID CONVERSION]: "llvm.x86.avx10.mask.vcvttps2qq256" => "__builtin_ia32_vcvttps2qq256_round_mask", + // [INVALID CONVERSION]: "llvm.x86.avx10.mask.vcvttps2udq256" => "__builtin_ia32_vcvttps2udq256_round_mask", + // [INVALID CONVERSION]: "llvm.x86.avx10.mask.vcvttps2uqq256" => "__builtin_ia32_vcvttps2uqq256_round_mask", + // [INVALID CONVERSION]: "llvm.x86.avx10.mask.vfcmaddcph256" => "__builtin_ia32_vfcmaddcph256_round_mask3", + // [INVALID CONVERSION]: "llvm.x86.avx10.mask.vfcmulcph256" => "__builtin_ia32_vfcmulcph256_round_mask", + // [INVALID CONVERSION]: "llvm.x86.avx10.mask.vfixupimmpd256" => "__builtin_ia32_vfixupimmpd256_round_mask", + // [INVALID CONVERSION]: "llvm.x86.avx10.mask.vfixupimmps256" => "__builtin_ia32_vfixupimmps256_round_mask", + // [INVALID CONVERSION]: "llvm.x86.avx10.mask.vfmaddcph256" => "__builtin_ia32_vfmaddcph256_round_mask3", + // [INVALID CONVERSION]: "llvm.x86.avx10.mask.vfmulcph256" => "__builtin_ia32_vfmulcph256_round_mask", + // [INVALID CONVERSION]: "llvm.x86.avx10.mask.vgetexppd256" => "__builtin_ia32_vgetexppd256_round_mask", + // [INVALID CONVERSION]: "llvm.x86.avx10.mask.vgetexpph256" => "__builtin_ia32_vgetexpph256_round_mask", + // [INVALID CONVERSION]: "llvm.x86.avx10.mask.vgetexpps256" => "__builtin_ia32_vgetexpps256_round_mask", + // [INVALID CONVERSION]: "llvm.x86.avx10.mask.vgetmantpd256" => "__builtin_ia32_vgetmantpd256_round_mask", + // [INVALID CONVERSION]: "llvm.x86.avx10.mask.vgetmantph256" => "__builtin_ia32_vgetmantph256_round_mask", + // [INVALID CONVERSION]: "llvm.x86.avx10.mask.vgetmantps256" => "__builtin_ia32_vgetmantps256_round_mask", + // [INVALID CONVERSION]: "llvm.x86.avx10.mask.vminmaxpd.round" => "__builtin_ia32_vminmaxpd512_round_mask", + "llvm.x86.avx10.mask.vminmaxpd128" => "__builtin_ia32_vminmaxpd128_mask", + // [INVALID CONVERSION]: "llvm.x86.avx10.mask.vminmaxpd256.round" => "__builtin_ia32_vminmaxpd256_round_mask", + // [INVALID CONVERSION]: "llvm.x86.avx10.mask.vminmaxph.round" => "__builtin_ia32_vminmaxph512_round_mask", + "llvm.x86.avx10.mask.vminmaxph128" => "__builtin_ia32_vminmaxph128_mask", + // [INVALID CONVERSION]: "llvm.x86.avx10.mask.vminmaxph256.round" => "__builtin_ia32_vminmaxph256_round_mask", + // [INVALID CONVERSION]: "llvm.x86.avx10.mask.vminmaxps.round" => "__builtin_ia32_vminmaxps512_round_mask", + "llvm.x86.avx10.mask.vminmaxps128" => "__builtin_ia32_vminmaxps128_mask", + // [INVALID CONVERSION]: "llvm.x86.avx10.mask.vminmaxps256.round" => "__builtin_ia32_vminmaxps256_round_mask", + // [INVALID CONVERSION]: "llvm.x86.avx10.mask.vminmaxsd.round" => "__builtin_ia32_vminmaxsd_round_mask", + // [INVALID CONVERSION]: "llvm.x86.avx10.mask.vminmaxsh.round" => "__builtin_ia32_vminmaxsh_round_mask", + // [INVALID CONVERSION]: "llvm.x86.avx10.mask.vminmaxss.round" => "__builtin_ia32_vminmaxss_round_mask", + // [INVALID CONVERSION]: "llvm.x86.avx10.mask.vrangepd256" => "__builtin_ia32_vrangepd256_round_mask", + // [INVALID CONVERSION]: "llvm.x86.avx10.mask.vrangeps256" => "__builtin_ia32_vrangeps256_round_mask", + // [INVALID CONVERSION]: "llvm.x86.avx10.mask.vreducepd256" => "__builtin_ia32_vreducepd256_round_mask", + // [INVALID CONVERSION]: "llvm.x86.avx10.mask.vreduceph256" => "__builtin_ia32_vreduceph256_round_mask", + // [INVALID CONVERSION]: "llvm.x86.avx10.mask.vreduceps256" => "__builtin_ia32_vreduceps256_round_mask", + // [INVALID CONVERSION]: "llvm.x86.avx10.mask.vrndscalepd256" => "__builtin_ia32_vrndscalepd256_round_mask", + // [INVALID CONVERSION]: "llvm.x86.avx10.mask.vrndscaleph256" => "__builtin_ia32_vrndscaleph256_round_mask", + // [INVALID CONVERSION]: "llvm.x86.avx10.mask.vrndscaleps256" => "__builtin_ia32_vrndscaleps256_round_mask", + // [INVALID CONVERSION]: "llvm.x86.avx10.mask.vscalefpd256" => "__builtin_ia32_vscalefpd256_round_mask", + // [INVALID CONVERSION]: "llvm.x86.avx10.mask.vscalefph256" => "__builtin_ia32_vscalefph256_round_mask", + // [INVALID CONVERSION]: "llvm.x86.avx10.mask.vscalefps256" => "__builtin_ia32_vscalefps256_round_mask", + // [INVALID CONVERSION]: "llvm.x86.avx10.maskz.vfcmaddcph256" => "__builtin_ia32_vfcmaddcph256_round_maskz", + // [INVALID CONVERSION]: "llvm.x86.avx10.maskz.vfixupimmpd256" => "__builtin_ia32_vfixupimmpd256_round_maskz", + // [INVALID CONVERSION]: "llvm.x86.avx10.maskz.vfixupimmps256" => "__builtin_ia32_vfixupimmps256_round_maskz", + // [INVALID CONVERSION]: "llvm.x86.avx10.maskz.vfmaddcph256" => "__builtin_ia32_vfmaddcph256_round_maskz", + "llvm.x86.avx10.vaddpd256" => "__builtin_ia32_vaddpd256_round", + "llvm.x86.avx10.vaddph256" => "__builtin_ia32_vaddph256_round", + "llvm.x86.avx10.vaddps256" => "__builtin_ia32_vaddps256_round", + "llvm.x86.avx10.vcvtne2ph2bf8128" => "__builtin_ia32_vcvtne2ph2bf8_128", + "llvm.x86.avx10.vcvtne2ph2bf8256" => "__builtin_ia32_vcvtne2ph2bf8_256", + "llvm.x86.avx10.vcvtne2ph2bf8512" => "__builtin_ia32_vcvtne2ph2bf8_512", + "llvm.x86.avx10.vcvtne2ph2bf8s128" => "__builtin_ia32_vcvtne2ph2bf8s_128", + "llvm.x86.avx10.vcvtne2ph2bf8s256" => "__builtin_ia32_vcvtne2ph2bf8s_256", + "llvm.x86.avx10.vcvtne2ph2bf8s512" => "__builtin_ia32_vcvtne2ph2bf8s_512", + "llvm.x86.avx10.vcvtne2ph2hf8128" => "__builtin_ia32_vcvtne2ph2hf8_128", + "llvm.x86.avx10.vcvtne2ph2hf8256" => "__builtin_ia32_vcvtne2ph2hf8_256", + "llvm.x86.avx10.vcvtne2ph2hf8512" => "__builtin_ia32_vcvtne2ph2hf8_512", + "llvm.x86.avx10.vcvtne2ph2hf8s128" => "__builtin_ia32_vcvtne2ph2hf8s_128", + "llvm.x86.avx10.vcvtne2ph2hf8s256" => "__builtin_ia32_vcvtne2ph2hf8s_256", + "llvm.x86.avx10.vcvtne2ph2hf8s512" => "__builtin_ia32_vcvtne2ph2hf8s_512", + "llvm.x86.avx10.vcvtnebf162ibs128" => "__builtin_ia32_vcvtnebf162ibs128", + "llvm.x86.avx10.vcvtnebf162ibs256" => "__builtin_ia32_vcvtnebf162ibs256", + "llvm.x86.avx10.vcvtnebf162ibs512" => "__builtin_ia32_vcvtnebf162ibs512", + "llvm.x86.avx10.vcvtnebf162iubs128" => "__builtin_ia32_vcvtnebf162iubs128", + "llvm.x86.avx10.vcvtnebf162iubs256" => "__builtin_ia32_vcvtnebf162iubs256", + "llvm.x86.avx10.vcvtnebf162iubs512" => "__builtin_ia32_vcvtnebf162iubs512", + "llvm.x86.avx10.vcvttnebf162ibs128" => "__builtin_ia32_vcvttnebf162ibs128", + "llvm.x86.avx10.vcvttnebf162ibs256" => "__builtin_ia32_vcvttnebf162ibs256", + "llvm.x86.avx10.vcvttnebf162ibs512" => "__builtin_ia32_vcvttnebf162ibs512", + "llvm.x86.avx10.vcvttnebf162iubs128" => "__builtin_ia32_vcvttnebf162iubs128", + "llvm.x86.avx10.vcvttnebf162iubs256" => "__builtin_ia32_vcvttnebf162iubs256", + "llvm.x86.avx10.vcvttnebf162iubs512" => "__builtin_ia32_vcvttnebf162iubs512", + "llvm.x86.avx10.vdivpd256" => "__builtin_ia32_vdivpd256_round", + "llvm.x86.avx10.vdivph256" => "__builtin_ia32_vdivph256_round", + "llvm.x86.avx10.vdivps256" => "__builtin_ia32_vdivps256_round", + "llvm.x86.avx10.vdpphps.128" => "__builtin_ia32_vdpphps128", + "llvm.x86.avx10.vdpphps.256" => "__builtin_ia32_vdpphps256", + "llvm.x86.avx10.vdpphps.512" => "__builtin_ia32_vdpphps512", + "llvm.x86.avx10.vfmaddsubpd256" => "__builtin_ia32_vfmaddsubpd256_round", + "llvm.x86.avx10.vfmaddsubph256" => "__builtin_ia32_vfmaddsubph256_round", + "llvm.x86.avx10.vfmaddsubps256" => "__builtin_ia32_vfmaddsubps256_round", + "llvm.x86.avx10.vmaxpd256" => "__builtin_ia32_vmaxpd256_round", + "llvm.x86.avx10.vmaxph256" => "__builtin_ia32_vmaxph256_round", + "llvm.x86.avx10.vmaxps256" => "__builtin_ia32_vmaxps256_round", + "llvm.x86.avx10.vminmaxnepbf16128" => "__builtin_ia32_vminmaxnepbf16128", + "llvm.x86.avx10.vminmaxnepbf16256" => "__builtin_ia32_vminmaxnepbf16256", + "llvm.x86.avx10.vminmaxnepbf16512" => "__builtin_ia32_vminmaxnepbf16512", + "llvm.x86.avx10.vminmaxpd128" => "__builtin_ia32_vminmaxpd128", + "llvm.x86.avx10.vminmaxpd256" => "__builtin_ia32_vminmaxpd256", + "llvm.x86.avx10.vminmaxph128" => "__builtin_ia32_vminmaxph128", + "llvm.x86.avx10.vminmaxph256" => "__builtin_ia32_vminmaxph256", + "llvm.x86.avx10.vminmaxps128" => "__builtin_ia32_vminmaxps128", + "llvm.x86.avx10.vminmaxps256" => "__builtin_ia32_vminmaxps256", + "llvm.x86.avx10.vminpd256" => "__builtin_ia32_vminpd256_round", + "llvm.x86.avx10.vminph256" => "__builtin_ia32_vminph256_round", + "llvm.x86.avx10.vminps256" => "__builtin_ia32_vminps256_round", + "llvm.x86.avx10.vmpsadbw.512" => "__builtin_ia32_mpsadbw512", + "llvm.x86.avx10.vmulpd256" => "__builtin_ia32_vmulpd256_round", + "llvm.x86.avx10.vmulph256" => "__builtin_ia32_vmulph256_round", + "llvm.x86.avx10.vmulps256" => "__builtin_ia32_vmulps256_round", + "llvm.x86.avx10.vpdpbssd.512" => "__builtin_ia32_vpdpbssd512", + "llvm.x86.avx10.vpdpbssds.512" => "__builtin_ia32_vpdpbssds512", + "llvm.x86.avx10.vpdpbsud.512" => "__builtin_ia32_vpdpbsud512", + "llvm.x86.avx10.vpdpbsuds.512" => "__builtin_ia32_vpdpbsuds512", + "llvm.x86.avx10.vpdpbuud.512" => "__builtin_ia32_vpdpbuud512", + "llvm.x86.avx10.vpdpbuuds.512" => "__builtin_ia32_vpdpbuuds512", + "llvm.x86.avx10.vpdpwsud.512" => "__builtin_ia32_vpdpwsud512", + "llvm.x86.avx10.vpdpwsuds.512" => "__builtin_ia32_vpdpwsuds512", + "llvm.x86.avx10.vpdpwusd.512" => "__builtin_ia32_vpdpwusd512", + "llvm.x86.avx10.vpdpwusds.512" => "__builtin_ia32_vpdpwusds512", + "llvm.x86.avx10.vpdpwuud.512" => "__builtin_ia32_vpdpwuud512", + "llvm.x86.avx10.vpdpwuuds.512" => "__builtin_ia32_vpdpwuuds512", + "llvm.x86.avx10.vsqrtpd256" => "__builtin_ia32_vsqrtpd256_round", + "llvm.x86.avx10.vsqrtph256" => "__builtin_ia32_vsqrtph256_round", + "llvm.x86.avx10.vsqrtps256" => "__builtin_ia32_vsqrtps256_round", + "llvm.x86.avx10.vsubpd256" => "__builtin_ia32_vsubpd256_round", + "llvm.x86.avx10.vsubph256" => "__builtin_ia32_vsubph256_round", + "llvm.x86.avx10.vsubps256" => "__builtin_ia32_vsubps256_round", "llvm.x86.avx2.gather.d.d" => "__builtin_ia32_gatherd_d", "llvm.x86.avx2.gather.d.d.256" => "__builtin_ia32_gatherd_d256", "llvm.x86.avx2.gather.d.pd" => "__builtin_ia32_gatherd_pd", @@ -8738,10 +8933,10 @@ match name { "llvm.x86.avx512.rcp14.ss" => "__builtin_ia32_rcp14ss_mask", "llvm.x86.avx512.rcp28.pd" => "__builtin_ia32_rcp28pd_mask", "llvm.x86.avx512.rcp28.ps" => "__builtin_ia32_rcp28ps_mask", - // [INVALID CONVERSION]: "llvm.x86.avx512.rcp28.sd" => "__builtin_ia32_rcp28sd_round_mask", - // [DUPLICATE]: "llvm.x86.avx512.rcp28.sd" => "__builtin_ia32_rcp28sd_mask", - // [INVALID CONVERSION]: "llvm.x86.avx512.rcp28.ss" => "__builtin_ia32_rcp28ss_round_mask", - // [DUPLICATE]: "llvm.x86.avx512.rcp28.ss" => "__builtin_ia32_rcp28ss_mask", + "llvm.x86.avx512.rcp28.sd" => "__builtin_ia32_rcp28sd_mask", + // [DUPLICATE]: "llvm.x86.avx512.rcp28.sd" => "__builtin_ia32_rcp28sd_round_mask", + "llvm.x86.avx512.rcp28.ss" => "__builtin_ia32_rcp28ss_mask", + // [DUPLICATE]: "llvm.x86.avx512.rcp28.ss" => "__builtin_ia32_rcp28ss_round_mask", "llvm.x86.avx512.rndscale.sd" => "__builtin_ia32_rndscalesd", "llvm.x86.avx512.rndscale.ss" => "__builtin_ia32_rndscaless", "llvm.x86.avx512.rsqrt14.pd.128" => "__builtin_ia32_rsqrt14pd128_mask", @@ -8754,10 +8949,10 @@ match name { "llvm.x86.avx512.rsqrt14.ss" => "__builtin_ia32_rsqrt14ss_mask", "llvm.x86.avx512.rsqrt28.pd" => "__builtin_ia32_rsqrt28pd_mask", "llvm.x86.avx512.rsqrt28.ps" => "__builtin_ia32_rsqrt28ps_mask", - // [INVALID CONVERSION]: "llvm.x86.avx512.rsqrt28.sd" => "__builtin_ia32_rsqrt28sd_round_mask", - // [DUPLICATE]: "llvm.x86.avx512.rsqrt28.sd" => "__builtin_ia32_rsqrt28sd_mask", - // [INVALID CONVERSION]: "llvm.x86.avx512.rsqrt28.ss" => "__builtin_ia32_rsqrt28ss_round_mask", - // [DUPLICATE]: "llvm.x86.avx512.rsqrt28.ss" => "__builtin_ia32_rsqrt28ss_mask", + "llvm.x86.avx512.rsqrt28.sd" => "__builtin_ia32_rsqrt28sd_mask", + // [DUPLICATE]: "llvm.x86.avx512.rsqrt28.sd" => "__builtin_ia32_rsqrt28sd_round_mask", + "llvm.x86.avx512.rsqrt28.ss" => "__builtin_ia32_rsqrt28ss_mask", + // [DUPLICATE]: "llvm.x86.avx512.rsqrt28.ss" => "__builtin_ia32_rsqrt28ss_round_mask", "llvm.x86.avx512.scatter.dpd.512" => "__builtin_ia32_scattersiv8df", "llvm.x86.avx512.scatter.dpi.512" => "__builtin_ia32_scattersiv16si", "llvm.x86.avx512.scatter.dpq.512" => "__builtin_ia32_scattersiv8di", @@ -9082,75 +9277,6 @@ match name { "llvm.x86.lwpval64" => "__builtin_ia32_lwpval64", "llvm.x86.mmx.emms" => "__builtin_ia32_emms", "llvm.x86.mmx.femms" => "__builtin_ia32_femms", - "llvm.x86.mmx.maskmovq" => "__builtin_ia32_maskmovq", - "llvm.x86.mmx.movnt.dq" => "__builtin_ia32_movntq", - "llvm.x86.mmx.packssdw" => "__builtin_ia32_packssdw", - "llvm.x86.mmx.packsswb" => "__builtin_ia32_packsswb", - "llvm.x86.mmx.packuswb" => "__builtin_ia32_packuswb", - "llvm.x86.mmx.padd.b" => "__builtin_ia32_paddb", - "llvm.x86.mmx.padd.d" => "__builtin_ia32_paddd", - "llvm.x86.mmx.padd.q" => "__builtin_ia32_paddq", - "llvm.x86.mmx.padd.w" => "__builtin_ia32_paddw", - "llvm.x86.mmx.padds.b" => "__builtin_ia32_paddsb", - "llvm.x86.mmx.padds.w" => "__builtin_ia32_paddsw", - "llvm.x86.mmx.paddus.b" => "__builtin_ia32_paddusb", - "llvm.x86.mmx.paddus.w" => "__builtin_ia32_paddusw", - "llvm.x86.mmx.palignr.b" => "__builtin_ia32_palignr", - "llvm.x86.mmx.pand" => "__builtin_ia32_pand", - "llvm.x86.mmx.pandn" => "__builtin_ia32_pandn", - "llvm.x86.mmx.pavg.b" => "__builtin_ia32_pavgb", - "llvm.x86.mmx.pavg.w" => "__builtin_ia32_pavgw", - "llvm.x86.mmx.pcmpeq.b" => "__builtin_ia32_pcmpeqb", - "llvm.x86.mmx.pcmpeq.d" => "__builtin_ia32_pcmpeqd", - "llvm.x86.mmx.pcmpeq.w" => "__builtin_ia32_pcmpeqw", - "llvm.x86.mmx.pcmpgt.b" => "__builtin_ia32_pcmpgtb", - "llvm.x86.mmx.pcmpgt.d" => "__builtin_ia32_pcmpgtd", - "llvm.x86.mmx.pcmpgt.w" => "__builtin_ia32_pcmpgtw", - "llvm.x86.mmx.pextr.w" => "__builtin_ia32_vec_ext_v4hi", - "llvm.x86.mmx.pinsr.w" => "__builtin_ia32_vec_set_v4hi", - "llvm.x86.mmx.pmadd.wd" => "__builtin_ia32_pmaddwd", - "llvm.x86.mmx.pmaxs.w" => "__builtin_ia32_pmaxsw", - "llvm.x86.mmx.pmaxu.b" => "__builtin_ia32_pmaxub", - "llvm.x86.mmx.pmins.w" => "__builtin_ia32_pminsw", - "llvm.x86.mmx.pminu.b" => "__builtin_ia32_pminub", - "llvm.x86.mmx.pmovmskb" => "__builtin_ia32_pmovmskb", - "llvm.x86.mmx.pmulh.w" => "__builtin_ia32_pmulhw", - "llvm.x86.mmx.pmulhu.w" => "__builtin_ia32_pmulhuw", - "llvm.x86.mmx.pmull.w" => "__builtin_ia32_pmullw", - "llvm.x86.mmx.pmulu.dq" => "__builtin_ia32_pmuludq", - "llvm.x86.mmx.por" => "__builtin_ia32_por", - "llvm.x86.mmx.psad.bw" => "__builtin_ia32_psadbw", - "llvm.x86.mmx.psll.d" => "__builtin_ia32_pslld", - "llvm.x86.mmx.psll.q" => "__builtin_ia32_psllq", - "llvm.x86.mmx.psll.w" => "__builtin_ia32_psllw", - "llvm.x86.mmx.pslli.d" => "__builtin_ia32_pslldi", - "llvm.x86.mmx.pslli.q" => "__builtin_ia32_psllqi", - "llvm.x86.mmx.pslli.w" => "__builtin_ia32_psllwi", - "llvm.x86.mmx.psra.d" => "__builtin_ia32_psrad", - "llvm.x86.mmx.psra.w" => "__builtin_ia32_psraw", - "llvm.x86.mmx.psrai.d" => "__builtin_ia32_psradi", - "llvm.x86.mmx.psrai.w" => "__builtin_ia32_psrawi", - "llvm.x86.mmx.psrl.d" => "__builtin_ia32_psrld", - "llvm.x86.mmx.psrl.q" => "__builtin_ia32_psrlq", - "llvm.x86.mmx.psrl.w" => "__builtin_ia32_psrlw", - "llvm.x86.mmx.psrli.d" => "__builtin_ia32_psrldi", - "llvm.x86.mmx.psrli.q" => "__builtin_ia32_psrlqi", - "llvm.x86.mmx.psrli.w" => "__builtin_ia32_psrlwi", - "llvm.x86.mmx.psub.b" => "__builtin_ia32_psubb", - "llvm.x86.mmx.psub.d" => "__builtin_ia32_psubd", - "llvm.x86.mmx.psub.q" => "__builtin_ia32_psubq", - "llvm.x86.mmx.psub.w" => "__builtin_ia32_psubw", - "llvm.x86.mmx.psubs.b" => "__builtin_ia32_psubsb", - "llvm.x86.mmx.psubs.w" => "__builtin_ia32_psubsw", - "llvm.x86.mmx.psubus.b" => "__builtin_ia32_psubusb", - "llvm.x86.mmx.psubus.w" => "__builtin_ia32_psubusw", - "llvm.x86.mmx.punpckhbw" => "__builtin_ia32_punpckhbw", - "llvm.x86.mmx.punpckhdq" => "__builtin_ia32_punpckhdq", - "llvm.x86.mmx.punpckhwd" => "__builtin_ia32_punpckhwd", - "llvm.x86.mmx.punpcklbw" => "__builtin_ia32_punpcklbw", - "llvm.x86.mmx.punpckldq" => "__builtin_ia32_punpckldq", - "llvm.x86.mmx.punpcklwd" => "__builtin_ia32_punpcklwd", - "llvm.x86.mmx.pxor" => "__builtin_ia32_pxor", "llvm.x86.monitorx" => "__builtin_ia32_monitorx", "llvm.x86.movdir64b" => "__builtin_ia32_movdir64b", "llvm.x86.mwaitx" => "__builtin_ia32_mwaitx", @@ -9193,16 +9319,10 @@ match name { "llvm.x86.sse.comile.ss" => "__builtin_ia32_comile", "llvm.x86.sse.comilt.ss" => "__builtin_ia32_comilt", "llvm.x86.sse.comineq.ss" => "__builtin_ia32_comineq", - "llvm.x86.sse.cvtpd2pi" => "__builtin_ia32_cvtpd2pi", - "llvm.x86.sse.cvtpi2pd" => "__builtin_ia32_cvtpi2pd", - "llvm.x86.sse.cvtpi2ps" => "__builtin_ia32_cvtpi2ps", - "llvm.x86.sse.cvtps2pi" => "__builtin_ia32_cvtps2pi", "llvm.x86.sse.cvtsi2ss" => "__builtin_ia32_cvtsi2ss", "llvm.x86.sse.cvtsi642ss" => "__builtin_ia32_cvtsi642ss", "llvm.x86.sse.cvtss2si" => "__builtin_ia32_cvtss2si", "llvm.x86.sse.cvtss2si64" => "__builtin_ia32_cvtss2si64", - "llvm.x86.sse.cvttpd2pi" => "__builtin_ia32_cvttpd2pi", - "llvm.x86.sse.cvttps2pi" => "__builtin_ia32_cvttps2pi", "llvm.x86.sse.cvttss2si" => "__builtin_ia32_cvttss2si", "llvm.x86.sse.cvttss2si64" => "__builtin_ia32_cvttss2si64", "llvm.x86.sse.div.ss" => "__builtin_ia32_divss", @@ -9212,7 +9332,6 @@ match name { "llvm.x86.sse.min.ss" => "__builtin_ia32_minss", "llvm.x86.sse.movmsk.ps" => "__builtin_ia32_movmskps", "llvm.x86.sse.mul.ss" => "__builtin_ia32_mulss", - "llvm.x86.sse.pshuf.w" => "__builtin_ia32_pshufw", "llvm.x86.sse.rcp.ps" => "__builtin_ia32_rcpps", "llvm.x86.sse.rcp.ss" => "__builtin_ia32_rcpss", "llvm.x86.sse.rsqrt.ps" => "__builtin_ia32_rsqrtps", @@ -9398,35 +9517,20 @@ match name { "llvm.x86.sse4a.insertqi" => "__builtin_ia32_insertqi", "llvm.x86.sse4a.movnt.sd" => "__builtin_ia32_movntsd", "llvm.x86.sse4a.movnt.ss" => "__builtin_ia32_movntss", - "llvm.x86.ssse3.pabs.b" => "__builtin_ia32_pabsb", "llvm.x86.ssse3.pabs.b.128" => "__builtin_ia32_pabsb128", - "llvm.x86.ssse3.pabs.d" => "__builtin_ia32_pabsd", "llvm.x86.ssse3.pabs.d.128" => "__builtin_ia32_pabsd128", - "llvm.x86.ssse3.pabs.w" => "__builtin_ia32_pabsw", "llvm.x86.ssse3.pabs.w.128" => "__builtin_ia32_pabsw128", - "llvm.x86.ssse3.phadd.d" => "__builtin_ia32_phaddd", "llvm.x86.ssse3.phadd.d.128" => "__builtin_ia32_phaddd128", - "llvm.x86.ssse3.phadd.sw" => "__builtin_ia32_phaddsw", "llvm.x86.ssse3.phadd.sw.128" => "__builtin_ia32_phaddsw128", - "llvm.x86.ssse3.phadd.w" => "__builtin_ia32_phaddw", "llvm.x86.ssse3.phadd.w.128" => "__builtin_ia32_phaddw128", - "llvm.x86.ssse3.phsub.d" => "__builtin_ia32_phsubd", "llvm.x86.ssse3.phsub.d.128" => "__builtin_ia32_phsubd128", - "llvm.x86.ssse3.phsub.sw" => "__builtin_ia32_phsubsw", "llvm.x86.ssse3.phsub.sw.128" => "__builtin_ia32_phsubsw128", - "llvm.x86.ssse3.phsub.w" => "__builtin_ia32_phsubw", "llvm.x86.ssse3.phsub.w.128" => "__builtin_ia32_phsubw128", - "llvm.x86.ssse3.pmadd.ub.sw" => "__builtin_ia32_pmaddubsw", "llvm.x86.ssse3.pmadd.ub.sw.128" => "__builtin_ia32_pmaddubsw128", - "llvm.x86.ssse3.pmul.hr.sw" => "__builtin_ia32_pmulhrsw", "llvm.x86.ssse3.pmul.hr.sw.128" => "__builtin_ia32_pmulhrsw128", - "llvm.x86.ssse3.pshuf.b" => "__builtin_ia32_pshufb", "llvm.x86.ssse3.pshuf.b.128" => "__builtin_ia32_pshufb128", - "llvm.x86.ssse3.psign.b" => "__builtin_ia32_psignb", "llvm.x86.ssse3.psign.b.128" => "__builtin_ia32_psignb128", - "llvm.x86.ssse3.psign.d" => "__builtin_ia32_psignd", "llvm.x86.ssse3.psign.d.128" => "__builtin_ia32_psignd128", - "llvm.x86.ssse3.psign.w" => "__builtin_ia32_psignw", "llvm.x86.ssse3.psign.w.128" => "__builtin_ia32_psignw128", "llvm.x86.sttilecfg" => "__builtin_ia32_tile_storeconfig", "llvm.x86.stui" => "__builtin_ia32_stui", From 7157f98cb481766873306238185fb5d4522a903a Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 3 Sep 2024 22:17:04 +0200 Subject: [PATCH 0465/2194] Fix square corners on line numbers when code is collapsed --- src/librustdoc/html/static/css/rustdoc.css | 6 ++++-- .../rustdoc-gui/docblock-code-block-line-number.goml | 11 +++++++++++ 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css index b69689cfb6875..c2b3d65b2f99d 100644 --- a/src/librustdoc/html/static/css/rustdoc.css +++ b/src/librustdoc/html/static/css/rustdoc.css @@ -746,7 +746,8 @@ ul.block, .block li { } .rustdoc .example-wrap > pre, -.rustdoc .scraped-example .src-line-numbers { +.rustdoc .scraped-example .src-line-numbers, +.rustdoc .scraped-example .src-line-numbers > pre { border-radius: 6px; } @@ -755,7 +756,8 @@ If the code example line numbers are displayed, there will be a weird radius in both the code example and the line numbers, so we need to remove the radius in this case. */ .rustdoc .example-wrap > .example-line-numbers, -.rustdoc .scraped-example .src-line-numbers { +.rustdoc .scraped-example .src-line-numbers, +.rustdoc .scraped-example .src-line-numbers > pre { border-top-right-radius: 0; border-bottom-right-radius: 0; } diff --git a/tests/rustdoc-gui/docblock-code-block-line-number.goml b/tests/rustdoc-gui/docblock-code-block-line-number.goml index 71ef041c684cb..03f8f80b10d4d 100644 --- a/tests/rustdoc-gui/docblock-code-block-line-number.goml +++ b/tests/rustdoc-gui/docblock-code-block-line-number.goml @@ -108,6 +108,17 @@ assert-local-storage: {"rustdoc-line-numbers": "true" } // Same check with scraped examples line numbers. go-to: "file://" + |DOC_PATH| + "/scrape_examples/fn.test_many.html" +assert-css: ( + ".scraped-example .src-line-numbers > pre", + { + // There should not be a radius on the right of the line numbers. + "border-top-left-radius": "6px", + "border-bottom-left-radius": "6px", + "border-top-right-radius": "0px", + "border-bottom-right-radius": "0px", + }, + ALL, +) assert-css: ( ".scraped-example .src-line-numbers", { From a4f2a311db7622f73d6c0fa29ac0397064a75686 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 28 Aug 2024 18:28:46 -0400 Subject: [PATCH 0466/2194] Don't ICE when dumping MIR of a synthetic coroutine body --- compiler/rustc_middle/src/mir/pretty.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs index 9906be60e3e95..a98e6943d68ee 100644 --- a/compiler/rustc_middle/src/mir/pretty.rs +++ b/compiler/rustc_middle/src/mir/pretty.rs @@ -612,7 +612,9 @@ fn write_mir_sig(tcx: TyCtxt<'_>, body: &Body<'_>, w: &mut dyn io::Write) -> io: let def_id = body.source.def_id(); let kind = tcx.def_kind(def_id); let is_function = match kind { - DefKind::Fn | DefKind::AssocFn | DefKind::Ctor(..) => true, + DefKind::Fn | DefKind::AssocFn | DefKind::Ctor(..) | DefKind::SyntheticCoroutineBody => { + true + } _ => tcx.is_closure_like(def_id), }; match (kind, body.source.promoted) { From 5525043ac8b2b84239198778e6bb87f4dba98a7b Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 28 Aug 2024 18:20:49 -0400 Subject: [PATCH 0467/2194] Rename dump of coroutine by-move-body to be more consistent, adjust test --- .../rustc_mir_transform/src/coroutine/by_move_body.rs | 2 +- ...losure#0}-{closure#0}.built.after.panic-unwind.mir} | 4 ++-- ...losure#0}-{closure#0}.built.after.panic-unwind.mir} | 8 ++++---- ...ure#0}.coroutine_closure_by_move.0.panic-unwind.mir | 6 +++--- ...losure#0}-{closure#0}.built.after.panic-unwind.mir} | 4 ++-- ...losure#1}-{closure#0}.built.after.panic-unwind.mir} | 4 ++-- ...ure#1}.coroutine_closure_by_move.0.panic-unwind.mir | 6 +++--- ...sure#1}.coroutine_closure_by_ref.0.panic-unwind.mir | 6 +++--- tests/mir-opt/async_closure_shims.rs | 10 ++++++---- 9 files changed, 26 insertions(+), 24 deletions(-) rename tests/mir-opt/{async_closure_shims.main-{closure#0}-{closure#0}-{closure#0}.coroutine_by_move.0.panic-unwind.mir => async_closure_shims.main-{closure#0}-{closure#0}-{closure#0}-{closure#0}.built.after.panic-unwind.mir} (78%) rename tests/mir-opt/{async_closure_shims.main-{closure#0}-{closure#0}-{closure#0}.coroutine_by_move.0.panic-abort.mir => async_closure_shims.main-{closure#0}-{closure#0}-{closure#0}.built.after.panic-unwind.mir} (81%) rename tests/mir-opt/{async_closure_shims.main-{closure#0}-{closure#1}-{closure#0}.coroutine_by_move.0.panic-unwind.mir => async_closure_shims.main-{closure#0}-{closure#1}-{closure#0}-{closure#0}.built.after.panic-unwind.mir} (79%) rename tests/mir-opt/{async_closure_shims.main-{closure#0}-{closure#1}-{closure#0}.coroutine_by_move.0.panic-abort.mir => async_closure_shims.main-{closure#0}-{closure#1}-{closure#0}.built.after.panic-unwind.mir} (86%) diff --git a/compiler/rustc_mir_transform/src/coroutine/by_move_body.rs b/compiler/rustc_mir_transform/src/coroutine/by_move_body.rs index ebe8d2eff4ff3..79cdca5d937fd 100644 --- a/compiler/rustc_mir_transform/src/coroutine/by_move_body.rs +++ b/compiler/rustc_mir_transform/src/coroutine/by_move_body.rs @@ -207,11 +207,11 @@ pub fn coroutine_by_move_body_def_id<'tcx>( let mut by_move_body = body.clone(); MakeByMoveBody { tcx, field_remapping, by_move_coroutine_ty }.visit_body(&mut by_move_body); - dump_mir(tcx, false, "coroutine_by_move", &0, &by_move_body, |_, _| Ok(())); let body_def = tcx.create_def(coroutine_def_id, kw::Empty, DefKind::SyntheticCoroutineBody); by_move_body.source = mir::MirSource::from_instance(InstanceKind::Item(body_def.def_id().to_def_id())); + dump_mir(tcx, false, "built", &"after", &by_move_body, |_, _| Ok(())); // Inherited from the by-ref coroutine. body_def.codegen_fn_attrs(tcx.codegen_fn_attrs(coroutine_def_id).clone()); diff --git a/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#0}-{closure#0}.coroutine_by_move.0.panic-unwind.mir b/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#0}-{closure#0}-{closure#0}.built.after.panic-unwind.mir similarity index 78% rename from tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#0}-{closure#0}.coroutine_by_move.0.panic-unwind.mir rename to tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#0}-{closure#0}-{closure#0}.built.after.panic-unwind.mir index 1f5bb551b8e01..80def6c89a190 100644 --- a/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#0}-{closure#0}.coroutine_by_move.0.panic-unwind.mir +++ b/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#0}-{closure#0}-{closure#0}.built.after.panic-unwind.mir @@ -1,6 +1,6 @@ -// MIR for `main::{closure#0}::{closure#0}::{closure#0}` 0 coroutine_by_move +// MIR for `main::{closure#0}::{closure#0}::{closure#0}::{closure#0}` after built -fn main::{closure#0}::{closure#0}::{closure#0}(_1: {async closure body@$DIR/async_closure_shims.rs:53:53: 56:10}, _2: ResumeTy) -> () +fn main::{closure#0}::{closure#0}::{closure#0}::{closure#0}(_1: {async closure body@$DIR/async_closure_shims.rs:55:53: 58:10}, _2: ResumeTy) -> () yields () { debug _task_context => _2; diff --git a/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#0}-{closure#0}.coroutine_by_move.0.panic-abort.mir b/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#0}-{closure#0}.built.after.panic-unwind.mir similarity index 81% rename from tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#0}-{closure#0}.coroutine_by_move.0.panic-abort.mir rename to tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#0}-{closure#0}.built.after.panic-unwind.mir index 1f5bb551b8e01..d273512b91fdb 100644 --- a/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#0}-{closure#0}.coroutine_by_move.0.panic-abort.mir +++ b/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#0}-{closure#0}.built.after.panic-unwind.mir @@ -1,11 +1,11 @@ -// MIR for `main::{closure#0}::{closure#0}::{closure#0}` 0 coroutine_by_move +// MIR for `main::{closure#0}::{closure#0}::{closure#0}` after built -fn main::{closure#0}::{closure#0}::{closure#0}(_1: {async closure body@$DIR/async_closure_shims.rs:53:53: 56:10}, _2: ResumeTy) -> () +fn main::{closure#0}::{closure#0}::{closure#0}(_1: {async closure body@$DIR/async_closure_shims.rs:55:53: 58:10}, _2: ResumeTy) -> () yields () { debug _task_context => _2; debug a => (_1.0: i32); - debug b => (_1.1: i32); + debug b => (*(_1.1: &i32)); let mut _0: (); let _3: i32; scope 1 { @@ -28,7 +28,7 @@ yields () _4 = &_3; FakeRead(ForLet(None), _4); StorageLive(_5); - _5 = &(_1.1: i32); + _5 = &(*(_1.1: &i32)); FakeRead(ForLet(None), _5); _0 = const (); StorageDead(_5); diff --git a/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#0}.coroutine_closure_by_move.0.panic-unwind.mir b/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#0}.coroutine_closure_by_move.0.panic-unwind.mir index a984845fd2c11..ce1d06ce1d3e9 100644 --- a/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#0}.coroutine_closure_by_move.0.panic-unwind.mir +++ b/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#0}.coroutine_closure_by_move.0.panic-unwind.mir @@ -1,10 +1,10 @@ // MIR for `main::{closure#0}::{closure#0}` 0 coroutine_closure_by_move -fn main::{closure#0}::{closure#0}(_1: {async closure@$DIR/async_closure_shims.rs:53:33: 53:52}, _2: i32) -> {async closure body@$DIR/async_closure_shims.rs:53:53: 56:10} { - let mut _0: {async closure body@$DIR/async_closure_shims.rs:53:53: 56:10}; +fn main::{closure#0}::{closure#0}(_1: {async closure@$DIR/async_closure_shims.rs:55:33: 55:52}, _2: i32) -> {async closure body@$DIR/async_closure_shims.rs:55:53: 58:10} { + let mut _0: {async closure body@$DIR/async_closure_shims.rs:55:53: 58:10}; bb0: { - _0 = {coroutine@$DIR/async_closure_shims.rs:53:53: 56:10 (#0)} { a: move _2, b: move (_1.0: i32) }; + _0 = {coroutine@$DIR/async_closure_shims.rs:55:53: 58:10 (#0)} { a: move _2, b: move (_1.0: i32) }; return; } } diff --git a/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#1}-{closure#0}.coroutine_by_move.0.panic-unwind.mir b/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#1}-{closure#0}-{closure#0}.built.after.panic-unwind.mir similarity index 79% rename from tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#1}-{closure#0}.coroutine_by_move.0.panic-unwind.mir rename to tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#1}-{closure#0}-{closure#0}.built.after.panic-unwind.mir index 17fa93148064f..cea330cf2f7f4 100644 --- a/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#1}-{closure#0}.coroutine_by_move.0.panic-unwind.mir +++ b/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#1}-{closure#0}-{closure#0}.built.after.panic-unwind.mir @@ -1,6 +1,6 @@ -// MIR for `main::{closure#0}::{closure#1}::{closure#0}` 0 coroutine_by_move +// MIR for `main::{closure#0}::{closure#1}::{closure#0}::{closure#0}` after built -fn main::{closure#0}::{closure#1}::{closure#0}(_1: {async closure body@$DIR/async_closure_shims.rs:62:48: 65:10}, _2: ResumeTy) -> () +fn main::{closure#0}::{closure#1}::{closure#0}::{closure#0}(_1: {async closure body@$DIR/async_closure_shims.rs:64:48: 67:10}, _2: ResumeTy) -> () yields () { debug _task_context => _2; diff --git a/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#1}-{closure#0}.coroutine_by_move.0.panic-abort.mir b/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#1}-{closure#0}.built.after.panic-unwind.mir similarity index 86% rename from tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#1}-{closure#0}.coroutine_by_move.0.panic-abort.mir rename to tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#1}-{closure#0}.built.after.panic-unwind.mir index 17fa93148064f..b4765c0b74ca8 100644 --- a/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#1}-{closure#0}.coroutine_by_move.0.panic-abort.mir +++ b/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#1}-{closure#0}.built.after.panic-unwind.mir @@ -1,6 +1,6 @@ -// MIR for `main::{closure#0}::{closure#1}::{closure#0}` 0 coroutine_by_move +// MIR for `main::{closure#0}::{closure#1}::{closure#0}` after built -fn main::{closure#0}::{closure#1}::{closure#0}(_1: {async closure body@$DIR/async_closure_shims.rs:62:48: 65:10}, _2: ResumeTy) -> () +fn main::{closure#0}::{closure#1}::{closure#0}(_1: {async closure body@$DIR/async_closure_shims.rs:64:48: 67:10}, _2: ResumeTy) -> () yields () { debug _task_context => _2; diff --git a/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#1}.coroutine_closure_by_move.0.panic-unwind.mir b/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#1}.coroutine_closure_by_move.0.panic-unwind.mir index aab9f7b03b9ab..8452c79bf41bb 100644 --- a/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#1}.coroutine_closure_by_move.0.panic-unwind.mir +++ b/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#1}.coroutine_closure_by_move.0.panic-unwind.mir @@ -1,10 +1,10 @@ // MIR for `main::{closure#0}::{closure#1}` 0 coroutine_closure_by_move -fn main::{closure#0}::{closure#1}(_1: {async closure@$DIR/async_closure_shims.rs:62:33: 62:47}, _2: i32) -> {async closure body@$DIR/async_closure_shims.rs:62:48: 65:10} { - let mut _0: {async closure body@$DIR/async_closure_shims.rs:62:48: 65:10}; +fn main::{closure#0}::{closure#1}(_1: {async closure@$DIR/async_closure_shims.rs:64:33: 64:47}, _2: i32) -> {async closure body@$DIR/async_closure_shims.rs:64:48: 67:10} { + let mut _0: {async closure body@$DIR/async_closure_shims.rs:64:48: 67:10}; bb0: { - _0 = {coroutine@$DIR/async_closure_shims.rs:62:48: 65:10 (#0)} { a: move _2, b: move (_1.0: &i32) }; + _0 = {coroutine@$DIR/async_closure_shims.rs:64:48: 67:10 (#0)} { a: move _2, b: move (_1.0: &i32) }; return; } } diff --git a/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#1}.coroutine_closure_by_ref.0.panic-unwind.mir b/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#1}.coroutine_closure_by_ref.0.panic-unwind.mir index 3fdc81791deef..08abe7197224c 100644 --- a/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#1}.coroutine_closure_by_ref.0.panic-unwind.mir +++ b/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#1}.coroutine_closure_by_ref.0.panic-unwind.mir @@ -1,10 +1,10 @@ // MIR for `main::{closure#0}::{closure#1}` 0 coroutine_closure_by_ref -fn main::{closure#0}::{closure#1}(_1: &{async closure@$DIR/async_closure_shims.rs:62:33: 62:47}, _2: i32) -> {async closure body@$DIR/async_closure_shims.rs:62:48: 65:10} { - let mut _0: {async closure body@$DIR/async_closure_shims.rs:62:48: 65:10}; +fn main::{closure#0}::{closure#1}(_1: &{async closure@$DIR/async_closure_shims.rs:64:33: 64:47}, _2: i32) -> {async closure body@$DIR/async_closure_shims.rs:64:48: 67:10} { + let mut _0: {async closure body@$DIR/async_closure_shims.rs:64:48: 67:10}; bb0: { - _0 = {coroutine@$DIR/async_closure_shims.rs:62:48: 65:10 (#0)} { a: move _2, b: copy ((*_1).0: &i32) }; + _0 = {coroutine@$DIR/async_closure_shims.rs:64:48: 67:10 (#0)} { a: move _2, b: copy ((*_1).0: &i32) }; return; } } diff --git a/tests/mir-opt/async_closure_shims.rs b/tests/mir-opt/async_closure_shims.rs index 57c55ef055cd7..6a3e1d777d808 100644 --- a/tests/mir-opt/async_closure_shims.rs +++ b/tests/mir-opt/async_closure_shims.rs @@ -22,7 +22,7 @@ pub fn block_on(fut: impl Future) -> T { } } -async fn call(f: &mut impl AsyncFn(i32)) { +async fn call(f: &impl AsyncFn(i32)) { f(0).await; } @@ -43,10 +43,12 @@ async fn call_normal_mut>(f: &mut impl FnMut(i32) -> F) { } // EMIT_MIR async_closure_shims.main-{closure#0}-{closure#0}.coroutine_closure_by_move.0.mir -// EMIT_MIR async_closure_shims.main-{closure#0}-{closure#0}-{closure#0}.coroutine_by_move.0.mir +// EMIT_MIR async_closure_shims.main-{closure#0}-{closure#0}-{closure#0}.built.after.mir +// EMIT_MIR async_closure_shims.main-{closure#0}-{closure#0}-{closure#0}-{closure#0}.built.after.mir // EMIT_MIR async_closure_shims.main-{closure#0}-{closure#1}.coroutine_closure_by_ref.0.mir // EMIT_MIR async_closure_shims.main-{closure#0}-{closure#1}.coroutine_closure_by_move.0.mir -// EMIT_MIR async_closure_shims.main-{closure#0}-{closure#1}-{closure#0}.coroutine_by_move.0.mir +// EMIT_MIR async_closure_shims.main-{closure#0}-{closure#1}-{closure#0}.built.after.mir +// EMIT_MIR async_closure_shims.main-{closure#0}-{closure#1}-{closure#0}-{closure#0}.built.after.mir pub fn main() { block_on(async { let b = 2i32; @@ -54,7 +56,7 @@ pub fn main() { let a = &a; let b = &b; }; - call(&mut async_closure).await; + call(&async_closure).await; call_mut(&mut async_closure).await; call_once(async_closure).await; From 2e7d2562805b79647d192a1511f2d616607c565a Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Tue, 3 Sep 2024 16:25:28 -0400 Subject: [PATCH 0468/2194] Add more SIMD intrinsics --- src/intrinsic/llvm.rs | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/src/intrinsic/llvm.rs b/src/intrinsic/llvm.rs index 3b9855ddc1894..2d7bb8a2d5481 100644 --- a/src/intrinsic/llvm.rs +++ b/src/intrinsic/llvm.rs @@ -185,7 +185,10 @@ pub fn adjust_intrinsic_arguments<'a, 'b, 'gcc, 'tcx>( | "__builtin_ia32_vplzcntq_128_mask" | "__builtin_ia32_cvtqq2pd128_mask" | "__builtin_ia32_cvtqq2pd256_mask" - | "__builtin_ia32_cvtqq2ps256_mask" => { + | "__builtin_ia32_cvtqq2ps256_mask" + | "__builtin_ia32_cvtuqq2pd128_mask" + | "__builtin_ia32_cvtuqq2pd256_mask" + | "__builtin_ia32_cvtuqq2ps256_mask" => { let mut new_args = args.to_vec(); // Remove last arg as it doesn't seem to be used in GCC and is always false. new_args.pop(); @@ -381,7 +384,8 @@ pub fn adjust_intrinsic_arguments<'a, 'b, 'gcc, 'tcx>( ); args = vec![arg.get_address(None)].into(); } - "__builtin_ia32_cvtqq2pd512_mask" | "__builtin_ia32_cvtqq2ps512_mask" => { + "__builtin_ia32_cvtqq2pd512_mask" | "__builtin_ia32_cvtqq2ps512_mask" | "__builtin_ia32_cvtuqq2pd512_mask" | + "__builtin_ia32_cvtuqq2ps512_mask" => { let mut old_args = args.to_vec(); let mut new_args = vec![]; new_args.push(old_args.swap_remove(0)); @@ -493,6 +497,11 @@ pub fn adjust_intrinsic_arguments<'a, 'b, 'gcc, 'tcx>( let new_args = args.to_vec(); args = vec![new_args[1], new_args[0], new_args[2]].into(); } + "__builtin_ia32_rangesd128_mask_round" | "__builtin_ia32_rangess128_mask_round" + | "__builtin_ia32_reducesd_mask_round" => { + let new_args = args.to_vec(); + args = vec![new_args[0], new_args[1], new_args[4], new_args[2], new_args[3], new_args[5]].into(); + } _ => (), } } @@ -1031,6 +1040,14 @@ pub fn intrinsic<'gcc, 'tcx>(name: &str, cx: &CodegenCx<'gcc, 'tcx>) -> Function "llvm.x86.avx512.sitofp.round.v4f64.v4i64" => "__builtin_ia32_cvtqq2pd256_mask", "llvm.x86.avx512.sitofp.round.v8f32.v8i64" => "__builtin_ia32_cvtqq2ps512_mask", "llvm.x86.avx512.sitofp.round.v4f32.v4i64" => "__builtin_ia32_cvtqq2ps256_mask", + "llvm.x86.avx512.uitofp.round.v8f64.v8u64" => "__builtin_ia32_cvtuqq2pd512_mask", + "llvm.x86.avx512.uitofp.round.v2f64.v2u64" => "__builtin_ia32_cvtuqq2pd128_mask", + "llvm.x86.avx512.uitofp.round.v4f64.v4u64" => "__builtin_ia32_cvtuqq2pd256_mask", + "llvm.x86.avx512.uitofp.round.v8f32.v8u64" => "__builtin_ia32_cvtuqq2ps512_mask", + "llvm.x86.avx512.uitofp.round.v4f32.v4u64" => "__builtin_ia32_cvtuqq2ps256_mask", + "llvm.x86.avx512.mask.reduce.pd.512" => "__builtin_ia32_reducepd512_mask_round", + "llvm.x86.avx512.mask.reduce.ps.512" => "__builtin_ia32_reduceps512_mask_round", + "llvm.x86.avx512.mask.reduce.sd" => "__builtin_ia32_reducesd_mask_round", // NOTE: this file is generated by https://github.com/GuillaumeGomez/llvmint/blob/master/generate_list.py _ => include!("archs.rs"), From f3efe3de1597b530735fd81fd776870cbfc952f0 Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Tue, 3 Sep 2024 17:04:28 -0400 Subject: [PATCH 0469/2194] Add compat note for trait solver change --- RELEASES.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/RELEASES.md b/RELEASES.md index 6aba476103e7f..c1e157e5455b7 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -100,6 +100,9 @@ Compatibility Notes The reason is that these types have different roles: `std::panic::PanicHookInfo` is the argument to the [panic hook](https://doc.rust-lang.org/stable/std/panic/fn.set_hook.html) in std context (where panics can have an arbitrary payload), while `core::panic::PanicInfo` is the argument to the [`#[panic_handler]`](https://doc.rust-lang.org/nomicon/panic-handler.html) in no_std context (where panics always carry a formatted *message*). Separating these types allows us to add more useful methods to these types, such as `std::panic::PanicHookInfo::payload_as_str()` and `core::panic::PanicInfo::message()`. * The new sort implementations may panic if a type's implementation of [`Ord`](https://doc.rust-lang.org/std/cmp/trait.Ord.html) (or the given comparison function) does not implement a [total order](https://en.wikipedia.org/wiki/Total_order) as the trait requires. `Ord`'s supertraits (`PartialOrd`, `Eq`, and `PartialEq`) must also be consistent. The previous implementations would not "notice" any problem, but the new implementations have a good chance of detecting inconsistencies, throwing a panic rather than returning knowingly unsorted data. +* [In very rare cases, a change in the internal evaluation order of the trait + solver may result in new fatal overflow errors.](https://github.com/rust-lang/rust/pull/126128) + From 139eea948d2f4d6f816f1ac548527566814b37de Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 4 Sep 2024 00:34:34 +0200 Subject: [PATCH 0470/2194] fmt --- src/intrinsic/llvm.rs | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/src/intrinsic/llvm.rs b/src/intrinsic/llvm.rs index 2d7bb8a2d5481..981603747c547 100644 --- a/src/intrinsic/llvm.rs +++ b/src/intrinsic/llvm.rs @@ -384,8 +384,10 @@ pub fn adjust_intrinsic_arguments<'a, 'b, 'gcc, 'tcx>( ); args = vec![arg.get_address(None)].into(); } - "__builtin_ia32_cvtqq2pd512_mask" | "__builtin_ia32_cvtqq2ps512_mask" | "__builtin_ia32_cvtuqq2pd512_mask" | - "__builtin_ia32_cvtuqq2ps512_mask" => { + "__builtin_ia32_cvtqq2pd512_mask" + | "__builtin_ia32_cvtqq2ps512_mask" + | "__builtin_ia32_cvtuqq2pd512_mask" + | "__builtin_ia32_cvtuqq2ps512_mask" => { let mut old_args = args.to_vec(); let mut new_args = vec![]; new_args.push(old_args.swap_remove(0)); @@ -497,10 +499,19 @@ pub fn adjust_intrinsic_arguments<'a, 'b, 'gcc, 'tcx>( let new_args = args.to_vec(); args = vec![new_args[1], new_args[0], new_args[2]].into(); } - "__builtin_ia32_rangesd128_mask_round" | "__builtin_ia32_rangess128_mask_round" - | "__builtin_ia32_reducesd_mask_round" => { + "__builtin_ia32_rangesd128_mask_round" + | "__builtin_ia32_rangess128_mask_round" + | "__builtin_ia32_reducesd_mask_round" => { let new_args = args.to_vec(); - args = vec![new_args[0], new_args[1], new_args[4], new_args[2], new_args[3], new_args[5]].into(); + args = vec![ + new_args[0], + new_args[1], + new_args[4], + new_args[2], + new_args[3], + new_args[5], + ] + .into(); } _ => (), } From 244ac087349bd57a626202ce37a82f90a94d4037 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 4 Sep 2024 00:35:04 +0200 Subject: [PATCH 0471/2194] Add missing intrinsic translation for `llvm.x86.xrstor64` --- src/intrinsic/llvm.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/intrinsic/llvm.rs b/src/intrinsic/llvm.rs index 981603747c547..d3e50afe53b2a 100644 --- a/src/intrinsic/llvm.rs +++ b/src/intrinsic/llvm.rs @@ -821,6 +821,7 @@ pub fn intrinsic<'gcc, 'tcx>(name: &str, cx: &CodegenCx<'gcc, 'tcx>) -> Function "llvm.x86.avx512.mask.cmp.b.256" => "__builtin_ia32_cmpb256_mask", "llvm.x86.avx512.mask.cmp.b.128" => "__builtin_ia32_cmpb128_mask", "llvm.x86.xrstor" => "__builtin_ia32_xrstor", + "llvm.x86.xrstor64" => "__builtin_ia32_xrstor64", "llvm.x86.xsavec" => "__builtin_ia32_xsavec", "llvm.x86.xsave64" => "__builtin_ia32_xsave64", "llvm.x86.addcarry.32" => "__builtin_ia32_addcarryx_u32", From 39e191077bb075a1b4f6facc9b75e5270cb507e4 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 4 Sep 2024 00:42:12 +0200 Subject: [PATCH 0472/2194] Add missing intrinsic translation for `llvm.x86.xsaveopt64` --- src/intrinsic/llvm.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/intrinsic/llvm.rs b/src/intrinsic/llvm.rs index d3e50afe53b2a..286aa6dab75c4 100644 --- a/src/intrinsic/llvm.rs +++ b/src/intrinsic/llvm.rs @@ -1029,6 +1029,7 @@ pub fn intrinsic<'gcc, 'tcx>(name: &str, cx: &CodegenCx<'gcc, 'tcx>) -> Function "llvm.x86.avx512.vpdpbusds.128" => "__builtin_ia32_vpdpbusds_v4si", "llvm.x86.xsave" => "__builtin_ia32_xsave", "llvm.x86.xsaveopt" => "__builtin_ia32_xsaveopt", + "llvm.x86.xsaveopt64" => "__builtin_ia32_xsaveopt64", "llvm.x86.avx512.mask.loadu.w.512" => "__builtin_ia32_loaddquhi512_mask", "llvm.x86.avx512.mask.loadu.b.512" => "__builtin_ia32_loaddquqi512_mask", "llvm.x86.avx512.mask.loadu.w.256" => "__builtin_ia32_loaddquhi256_mask", From 1a70f40d7fa8cafa37037652ba6ea8b7d9938b7a Mon Sep 17 00:00:00 2001 From: Mattias Wallin Date: Sun, 1 Sep 2024 13:13:14 +0200 Subject: [PATCH 0473/2194] Avoid allocation in `ChainItemKind::is_tup_field_access` --- src/chains.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/chains.rs b/src/chains.rs index 297eb268d30cd..693aaef997904 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -209,7 +209,7 @@ impl ChainItemKind { fn is_tup_field_access(expr: &ast::Expr) -> bool { match expr.kind { ast::ExprKind::Field(_, ref field) => { - field.name.to_string().chars().all(|c| c.is_digit(10)) + field.name.as_str().chars().all(|c| c.is_digit(10)) } _ => false, } From e2484be0c7047485649f761cf58014bc1df1e227 Mon Sep 17 00:00:00 2001 From: Literally Void Date: Tue, 3 Sep 2024 15:34:46 -0700 Subject: [PATCH 0474/2194] docs: add digit separators in `Duration` examples --- library/core/src/time.rs | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/library/core/src/time.rs b/library/core/src/time.rs index 0390bb59a8984..c19eeedb35426 100644 --- a/library/core/src/time.rs +++ b/library/core/src/time.rs @@ -250,7 +250,7 @@ impl Duration { /// ``` /// use std::time::Duration; /// - /// let duration = Duration::from_millis(2569); + /// let duration = Duration::from_millis(2_569); /// /// assert_eq!(2, duration.as_secs()); /// assert_eq!(569_000_000, duration.subsec_nanos()); @@ -279,7 +279,7 @@ impl Duration { /// let duration = Duration::from_micros(1_000_002); /// /// assert_eq!(1, duration.as_secs()); - /// assert_eq!(2000, duration.subsec_nanos()); + /// assert_eq!(2_000, duration.subsec_nanos()); /// ``` #[stable(feature = "duration_from_micros", since = "1.27.0")] #[must_use] @@ -472,7 +472,7 @@ impl Duration { /// ``` /// use std::time::Duration; /// - /// let duration = Duration::new(5, 730023852); + /// let duration = Duration::new(5, 730_023_852); /// assert_eq!(duration.as_secs(), 5); /// ``` /// @@ -501,7 +501,7 @@ impl Duration { /// ``` /// use std::time::Duration; /// - /// let duration = Duration::from_millis(5432); + /// let duration = Duration::from_millis(5_432); /// assert_eq!(duration.as_secs(), 5); /// assert_eq!(duration.subsec_millis(), 432); /// ``` @@ -547,7 +547,7 @@ impl Duration { /// ``` /// use std::time::Duration; /// - /// let duration = Duration::from_millis(5010); + /// let duration = Duration::from_millis(5_010); /// assert_eq!(duration.as_secs(), 5); /// assert_eq!(duration.subsec_nanos(), 10_000_000); /// ``` @@ -566,8 +566,8 @@ impl Duration { /// ``` /// use std::time::Duration; /// - /// let duration = Duration::new(5, 730023852); - /// assert_eq!(duration.as_millis(), 5730); + /// let duration = Duration::new(5, 730_023_852); + /// assert_eq!(duration.as_millis(), 5_730); /// ``` #[stable(feature = "duration_as_u128", since = "1.33.0")] #[rustc_const_stable(feature = "duration_as_u128", since = "1.33.0")] @@ -584,8 +584,8 @@ impl Duration { /// ``` /// use std::time::Duration; /// - /// let duration = Duration::new(5, 730023852); - /// assert_eq!(duration.as_micros(), 5730023); + /// let duration = Duration::new(5, 730_023_852); + /// assert_eq!(duration.as_micros(), 5_730_023); /// ``` #[stable(feature = "duration_as_u128", since = "1.33.0")] #[rustc_const_stable(feature = "duration_as_u128", since = "1.33.0")] @@ -602,8 +602,8 @@ impl Duration { /// ``` /// use std::time::Duration; /// - /// let duration = Duration::new(5, 730023852); - /// assert_eq!(duration.as_nanos(), 5730023852); + /// let duration = Duration::new(5, 730_023_852); + /// assert_eq!(duration.as_nanos(), 5_730_023_852); /// ``` #[stable(feature = "duration_as_u128", since = "1.33.0")] #[rustc_const_stable(feature = "duration_as_u128", since = "1.33.0")] @@ -879,7 +879,7 @@ impl Duration { /// use std::time::Duration; /// /// let dur = Duration::new(2, 345_678_000); - /// assert_eq!(dur.as_millis_f64(), 2345.678); + /// assert_eq!(dur.as_millis_f64(), 2_345.678); /// ``` #[unstable(feature = "duration_millis_float", issue = "122451")] #[must_use] @@ -900,7 +900,7 @@ impl Duration { /// use std::time::Duration; /// /// let dur = Duration::new(2, 345_678_000); - /// assert_eq!(dur.as_millis_f32(), 2345.678); + /// assert_eq!(dur.as_millis_f32(), 2_345.678); /// ``` #[unstable(feature = "duration_millis_float", issue = "122451")] #[must_use] @@ -1017,7 +1017,7 @@ impl Duration { /// /// let dur = Duration::new(2, 700_000_000); /// assert_eq!(dur.mul_f32(3.14), Duration::new(8, 478_000_641)); - /// assert_eq!(dur.mul_f32(3.14e5), Duration::new(847800, 0)); + /// assert_eq!(dur.mul_f32(3.14e5), Duration::new(847_800, 0)); /// ``` #[stable(feature = "duration_float", since = "1.38.0")] #[must_use = "this returns the result of the operation, \ From 623dc09fa3a1d12f5a83ed763f4defa1c7e84c67 Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Tue, 3 Sep 2024 21:09:49 -0400 Subject: [PATCH 0475/2194] Add support for more SIMD intrinsics --- src/intrinsic/llvm.rs | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/src/intrinsic/llvm.rs b/src/intrinsic/llvm.rs index 286aa6dab75c4..ba57e425b0fca 100644 --- a/src/intrinsic/llvm.rs +++ b/src/intrinsic/llvm.rs @@ -501,7 +501,8 @@ pub fn adjust_intrinsic_arguments<'a, 'b, 'gcc, 'tcx>( } "__builtin_ia32_rangesd128_mask_round" | "__builtin_ia32_rangess128_mask_round" - | "__builtin_ia32_reducesd_mask_round" => { + | "__builtin_ia32_reducesd_mask_round" + | "__builtin_ia32_reducess_mask_round" => { let new_args = args.to_vec(); args = vec![ new_args[0], @@ -1061,6 +1062,21 @@ pub fn intrinsic<'gcc, 'tcx>(name: &str, cx: &CodegenCx<'gcc, 'tcx>) -> Function "llvm.x86.avx512.mask.reduce.pd.512" => "__builtin_ia32_reducepd512_mask_round", "llvm.x86.avx512.mask.reduce.ps.512" => "__builtin_ia32_reduceps512_mask_round", "llvm.x86.avx512.mask.reduce.sd" => "__builtin_ia32_reducesd_mask_round", + "llvm.x86.avx512.mask.reduce.ss" => "__builtin_ia32_reducess_mask_round", + "llvm.x86.avx512.mask.loadu.d.256" => "__builtin_ia32_loaddqusi256_mask", + "llvm.x86.avx512.mask.loadu.q.256" => "__builtin_ia32_loaddqudi256_mask", + "llvm.x86.avx512.mask.loadu.ps.256" => "__builtin_ia32_loadups256_mask", + "llvm.x86.avx512.mask.loadu.pd.256" => "__builtin_ia32_loadupd256_mask", + "llvm.x86.avx512.mask.loadu.d.128" => "__builtin_ia32_loaddqusi128_mask", + "llvm.x86.avx512.mask.loadu.q.128" => "__builtin_ia32_loaddqudi128_mask", + "llvm.x86.avx512.mask.loadu.ps.128" => "__builtin_ia32_loadups128_mask", + "llvm.x86.avx512.mask.loadu.pd.128" => "__builtin_ia32_loadupd128_mask", + "llvm.x86.avx512.mask.load.d.512" => "__builtin_ia32_movdqa32load512_mask", + "llvm.x86.avx512.mask.load.q.512" => "__builtin_ia32_movdqa64load512_mask", + "llvm.x86.avx512.mask.load.ps.512" => "__builtin_ia32_loadaps512_mask", + "llvm.x86.avx512.mask.load.pd.512" => "__builtin_ia32_loadapd512_mask", + "llvm.x86.avx512.mask.load.d.256" => "__builtin_ia32_movdqa32load256_mask", + "llvm.x86.avx512.mask.load.q.256" => "__builtin_ia32_movdqa64load256_mask", // NOTE: this file is generated by https://github.com/GuillaumeGomez/llvmint/blob/master/generate_list.py _ => include!("archs.rs"), From a9998704d378dcb7bf399a5835dab1d22543c01f Mon Sep 17 00:00:00 2001 From: Boxy Date: Tue, 3 Sep 2024 20:56:29 +0100 Subject: [PATCH 0476/2194] bump stage0 --- src/stage0 | 892 +++++++++++++++++++++++++++-------------------------- 1 file changed, 450 insertions(+), 442 deletions(-) diff --git a/src/stage0 b/src/stage0 index dcc22673f13ed..1a603931792c3 100644 --- a/src/stage0 +++ b/src/stage0 @@ -14,448 +14,456 @@ nightly_branch=master # All changes below this comment will be overridden the next time the # tool is executed. -compiler_date=2024-07-26 +compiler_date=2024-09-04 compiler_version=beta -rustfmt_date=2024-07-30 +rustfmt_date=2024-09-04 rustfmt_version=nightly -dist/2024-07-26/rustc-beta-aarch64-apple-darwin.tar.gz=a265d7831284938f090ef34cf2fb374f4d2b946c52829de8e53a06b7373c3d7e -dist/2024-07-26/rustc-beta-aarch64-apple-darwin.tar.xz=f2420846f82f474892776f0bea176fbb2f1850a1fb9f51a1afe40ae6de8bbc17 -dist/2024-07-26/rustc-beta-aarch64-pc-windows-msvc.tar.gz=e3e0e2b8d1f8804cc2b5785765cc6807bbf7120fb010d74453097b5931c82e96 -dist/2024-07-26/rustc-beta-aarch64-pc-windows-msvc.tar.xz=1270aaea2f20a378e68d26518e1d34810ed346a4d4c272138c8aef67e3c386d5 -dist/2024-07-26/rustc-beta-aarch64-unknown-linux-gnu.tar.gz=02bcdc3eed81ba17e485556f1c4d5a00e851afb75a20f860ce7b6d22cb8f9e99 -dist/2024-07-26/rustc-beta-aarch64-unknown-linux-gnu.tar.xz=52b72cc7270fe75e023ca9c40d095a84cb0ce31657357cd7676d6570ca59bc1c -dist/2024-07-26/rustc-beta-aarch64-unknown-linux-musl.tar.gz=b47ba6f2214f238cf8df3c386765e7816bc86e1166f27ddb6c0ce678ec716939 -dist/2024-07-26/rustc-beta-aarch64-unknown-linux-musl.tar.xz=95537778025708922b4bf27f34f0634a61a1d963a8424f8a06c82564c74e849a -dist/2024-07-26/rustc-beta-arm-unknown-linux-gnueabi.tar.gz=d79c8b744d00b174be7630a54f9ee23562f8977d7e09e2ee46a9d72a80eef514 -dist/2024-07-26/rustc-beta-arm-unknown-linux-gnueabi.tar.xz=0f7d3d0773a3c1f94e8252d95b134f7f5e727a884ece54aa0f77e5edec5c6e29 -dist/2024-07-26/rustc-beta-arm-unknown-linux-gnueabihf.tar.gz=5e0d51532c4bb0c29fd01ef5d931c229f711c9326df0bdcb2b88c75aa72dc210 -dist/2024-07-26/rustc-beta-arm-unknown-linux-gnueabihf.tar.xz=5fe623cab0afd5f7bdd664a593ac02791915e30cfc9ca76a02ffd70e1e865ede -dist/2024-07-26/rustc-beta-armv7-unknown-linux-gnueabihf.tar.gz=1df1e1a44170d6c9ab4988e9841ab56ee00248ca5cbf7e38b69677bd5b2de585 -dist/2024-07-26/rustc-beta-armv7-unknown-linux-gnueabihf.tar.xz=70791fcd1aef6686e012740017a0e5bb4441eb4018f875e8e50d5597c183291d -dist/2024-07-26/rustc-beta-i686-pc-windows-gnu.tar.gz=045fe2478c5a5341d7b7a05b9df23ef8f81ddbe0faa78e3f2107341a0e8189f6 -dist/2024-07-26/rustc-beta-i686-pc-windows-gnu.tar.xz=d7f3888692210b6024ed72864015d1c101f28814dec5b60c9e32a772f11f3b47 -dist/2024-07-26/rustc-beta-i686-pc-windows-msvc.tar.gz=5b2988c87d91013cd92ebca43fd6cf5d49250fc0452830ea46622e418984041e -dist/2024-07-26/rustc-beta-i686-pc-windows-msvc.tar.xz=b9d65cca6691baf2841432d6d2d566face171c460cf161f39a21acf7c0b033c1 -dist/2024-07-26/rustc-beta-i686-unknown-linux-gnu.tar.gz=7b037163f1c19a0fbbf4029d12a7b3764e747c9ea7944f1e45a6f91a068df224 -dist/2024-07-26/rustc-beta-i686-unknown-linux-gnu.tar.xz=f5044d8f3784e5bc682b03ccbe7389abf5b254a01074fa67eb824d2dfc9fd3ad -dist/2024-07-26/rustc-beta-loongarch64-unknown-linux-gnu.tar.gz=840131ab570c68c0d46244eac743f7d8a1f470d1926068868d288307a488b3c9 -dist/2024-07-26/rustc-beta-loongarch64-unknown-linux-gnu.tar.xz=6513a144014807bd258d2a90fa4618aabdb4e265268e408d5cb699a610b78c31 -dist/2024-07-26/rustc-beta-loongarch64-unknown-linux-musl.tar.gz=d703a904da3604e553ba0a74775f8005e9f52615be3266197b71362b20414def -dist/2024-07-26/rustc-beta-loongarch64-unknown-linux-musl.tar.xz=8ab79d34b3c182a4349fd01a50aa13ca064ecea64c2ab09f7a9ec38046741c7a -dist/2024-07-26/rustc-beta-powerpc-unknown-linux-gnu.tar.gz=70eb8f65e91068ac20366fca1fc30227f36cb2b2ce1abdaa72504583cc7865c7 -dist/2024-07-26/rustc-beta-powerpc-unknown-linux-gnu.tar.xz=3372e272cf9620191000a95fff23e417586e6b894e211d44e4f658c241c3d014 -dist/2024-07-26/rustc-beta-powerpc64-unknown-linux-gnu.tar.gz=e8f09f56c43ae6e99a42a8c430492157415fa6baee2c3f8f86f94ab4279634cd -dist/2024-07-26/rustc-beta-powerpc64-unknown-linux-gnu.tar.xz=599fcd5c57687e29eec085f7cc2733965a8e8fe5eac6499abd92ffda64f6e500 -dist/2024-07-26/rustc-beta-powerpc64le-unknown-linux-gnu.tar.gz=904029f0c81ec9679851d952f0f0f616cc183028882c6686f5b5bb665ca00cef -dist/2024-07-26/rustc-beta-powerpc64le-unknown-linux-gnu.tar.xz=31f3f895d665acf082a6dbb40e91fd97f823f84c8e62074dfa82e60f22606f5b -dist/2024-07-26/rustc-beta-riscv64gc-unknown-linux-gnu.tar.gz=4d374e60b8ac2f3fddd5ba9b46ab80555bc5b19f080b86604dde994087b00ed9 -dist/2024-07-26/rustc-beta-riscv64gc-unknown-linux-gnu.tar.xz=c905a880b98d1eaabfb306d5b6dda018e5025b42028cbb12bad408f4d469f3ae -dist/2024-07-26/rustc-beta-s390x-unknown-linux-gnu.tar.gz=69f0228799685960f36f31eb4c139cbd7925f5180468e2d4a435ecbad63e9535 -dist/2024-07-26/rustc-beta-s390x-unknown-linux-gnu.tar.xz=1da1caf5b2ad149ef82af58278dea6c381c372366c48cda8ca7f520cc8752b2c -dist/2024-07-26/rustc-beta-x86_64-apple-darwin.tar.gz=81fe4bef33afb3010fdd7af42653fbf5dd9abf0d69268576dfe144c88c7b9944 -dist/2024-07-26/rustc-beta-x86_64-apple-darwin.tar.xz=c4785475e3f7087cbab405937c0ca3ebc08455dd36df156680cea1ed38fcce5b -dist/2024-07-26/rustc-beta-x86_64-pc-windows-gnu.tar.gz=6e58397829f67bf952037c94894409032e52ac8ccdf3858346d131fff6175a50 -dist/2024-07-26/rustc-beta-x86_64-pc-windows-gnu.tar.xz=8e834602e7cd1fcd585f51ab280266b4ffc57e0c974a1a26b901701b5127135d -dist/2024-07-26/rustc-beta-x86_64-pc-windows-msvc.tar.gz=94a8a08495b8093db5d9a32c3258c9f97ea8b0f57947d7ca642664c06cfb438d -dist/2024-07-26/rustc-beta-x86_64-pc-windows-msvc.tar.xz=8d057c7167cffeebeddabf25f08a50de8dbad5ed7cfffce625c81a99d757e998 -dist/2024-07-26/rustc-beta-x86_64-unknown-freebsd.tar.gz=dcc93e7b76ca7a469544597885a7b5f4b5f822e05a89b2d7a093e06dede9f52b -dist/2024-07-26/rustc-beta-x86_64-unknown-freebsd.tar.xz=3efb7d4d97dc9b13a0178464e79bbf96bb71763a588b48c587746acd456ceb8d -dist/2024-07-26/rustc-beta-x86_64-unknown-illumos.tar.gz=ef5a0d34b78848962e83ed468934d7cbedff778a89e50f2128ba25d0943e25ed -dist/2024-07-26/rustc-beta-x86_64-unknown-illumos.tar.xz=5cccc7bbb15b63d422dfd2c8ac25e2103906880e843feccd318ba8b8c614d3b4 -dist/2024-07-26/rustc-beta-x86_64-unknown-linux-gnu.tar.gz=a9b352f61f8124c1fba0c76ecc8c1c972e61e97f5299f3b86bc17f035351ced5 -dist/2024-07-26/rustc-beta-x86_64-unknown-linux-gnu.tar.xz=a8fced9a5de02bb660491b440f6596e4baf6eb9114b8dd8d93ac7ada6266d274 -dist/2024-07-26/rustc-beta-x86_64-unknown-linux-musl.tar.gz=5e6fae2fd75e1780995fa9839593044539fac3f095c8948ba446b7024f632ec9 -dist/2024-07-26/rustc-beta-x86_64-unknown-linux-musl.tar.xz=9eb16965a7f1f7be7751fb61280f272c2497765e552fc0dd653700d551a04539 -dist/2024-07-26/rustc-beta-x86_64-unknown-netbsd.tar.gz=40b7312ce424dcbde5537da50d17854c255c3ed535a124f4f0102cf62bc86b5a -dist/2024-07-26/rustc-beta-x86_64-unknown-netbsd.tar.xz=222a86f97d9bf2db38ebea9f45901790429658154d3448d05e7f0ddd9833ff18 -dist/2024-07-26/rust-std-beta-aarch64-apple-darwin.tar.gz=a9b3cfe03b3053cd533ff02fb54f95db009396802464f32840b3369e9a3e6afc -dist/2024-07-26/rust-std-beta-aarch64-apple-darwin.tar.xz=9ddb6b8291ade9224cc76f4d946c179bdc6e25f5819a4ba1ebe1f207d4c663ac -dist/2024-07-26/rust-std-beta-aarch64-apple-ios.tar.gz=8c129310921ed45d3cdfc30e60d93403adf8158a6661de96ee5d4a63119cf3e5 -dist/2024-07-26/rust-std-beta-aarch64-apple-ios.tar.xz=e1fcee4b062f25b0350e5e74064615c354ee8b399adf792d46319ee782857398 -dist/2024-07-26/rust-std-beta-aarch64-apple-ios-sim.tar.gz=40d6d48dea64407bf31be39f9e0316a1e47648ee75bc0d3361edb961e062aa6b -dist/2024-07-26/rust-std-beta-aarch64-apple-ios-sim.tar.xz=3e01648f45e0c7cb040d3c293024477801930d5078d54c6291ba13aa8eb4e1f6 -dist/2024-07-26/rust-std-beta-aarch64-linux-android.tar.gz=da310568bee0d4868132589399c9229df5ac575a028f2409f51fd1f8c9e81779 -dist/2024-07-26/rust-std-beta-aarch64-linux-android.tar.xz=f3079ebecbe5b9f23495fe0966fc39fee1d38869287695804c3c04d53df07496 -dist/2024-07-26/rust-std-beta-aarch64-pc-windows-gnullvm.tar.gz=9dce2956e4b01d867ef6c229dbff9319a779a80e43a29fe1f8b10a333049264d -dist/2024-07-26/rust-std-beta-aarch64-pc-windows-gnullvm.tar.xz=b64e7b87027dceba21283ba71430a8053a918bfaf6c071cc70d5f5da00155944 -dist/2024-07-26/rust-std-beta-aarch64-pc-windows-msvc.tar.gz=0d103e0c4ec8039dd42be09bb9c74f269a9567fe7dfacfc54106912cd2aeb35b -dist/2024-07-26/rust-std-beta-aarch64-pc-windows-msvc.tar.xz=4b3627e9e363e9b2fd85222c677a7250b12a5d32919f38a31ed7375637a79a81 -dist/2024-07-26/rust-std-beta-aarch64-unknown-fuchsia.tar.gz=061fdac14ee0bd3abba36269f68e9ad25a243ac7062f946155f98680f484a84c -dist/2024-07-26/rust-std-beta-aarch64-unknown-fuchsia.tar.xz=8acc12f14ac643b822595a6a07c7e5ac65855b83938ac122e3278f64769eeb13 -dist/2024-07-26/rust-std-beta-aarch64-unknown-linux-gnu.tar.gz=199498df7d94989d4ff1773fdfe86e97ac99ead487f402d020f78688bc6dfba4 -dist/2024-07-26/rust-std-beta-aarch64-unknown-linux-gnu.tar.xz=1337c2f00e9bec2e0a553234d74daea67a9781459d0abe3c8de954981d9354d2 -dist/2024-07-26/rust-std-beta-aarch64-unknown-linux-musl.tar.gz=a7116c13a413989f2ed874d45780aced3299c4ef8ce8e3bc99efe960a73cadb3 -dist/2024-07-26/rust-std-beta-aarch64-unknown-linux-musl.tar.xz=80ef87143ee2339e90842c4893284217ddfa56926524baf94341277c1210dd07 -dist/2024-07-26/rust-std-beta-aarch64-unknown-linux-ohos.tar.gz=c47cab4bb196e749f07d03f6f6c8f2fe538c84a055a298f0b505ab98dadf4a1c -dist/2024-07-26/rust-std-beta-aarch64-unknown-linux-ohos.tar.xz=b36aa3f0bab63ac21fb69610d379a87fbd1ee87041153eb1e6886a237d22b171 -dist/2024-07-26/rust-std-beta-aarch64-unknown-none.tar.gz=92de36c897dbf90f9986396da1f8a954ad7b4fdab3e466d63974c82611e76d47 -dist/2024-07-26/rust-std-beta-aarch64-unknown-none.tar.xz=fb5d50ce34bd222c1b624e5aa2248776f8926f3ee360b7c4c1e0bd412d01bae2 -dist/2024-07-26/rust-std-beta-aarch64-unknown-none-softfloat.tar.gz=fea794a4c8aec3e5357199db7a9b701ceedded1dbb50167b002d368a6ae09cc7 -dist/2024-07-26/rust-std-beta-aarch64-unknown-none-softfloat.tar.xz=47fc6e497bd4c8013f708ed052701129c308b657d28ee2dce877cb63ccb1b06b -dist/2024-07-26/rust-std-beta-aarch64-unknown-uefi.tar.gz=17eb45b10a0c9cc702e7fb4f0c7926591d3ad0f052f2bded9cf852ea082cd2bb -dist/2024-07-26/rust-std-beta-aarch64-unknown-uefi.tar.xz=1f6b1a3082fc29546e4d8dcb20675f62ead20fe96112998dcb1260e206e93cbc -dist/2024-07-26/rust-std-beta-arm-linux-androideabi.tar.gz=baad78bda532ed77dbf3e4265595b9dac82f6fdc27dc6deaf7386a60b981b927 -dist/2024-07-26/rust-std-beta-arm-linux-androideabi.tar.xz=cf4283b1224d4dac3c55da905608c5bba7639b6511977f3de344a999ae39e571 -dist/2024-07-26/rust-std-beta-arm-unknown-linux-gnueabi.tar.gz=0da01efb79d43140515c48561cbe7a2fdb83895fe4351f2fffaaf108fb163268 -dist/2024-07-26/rust-std-beta-arm-unknown-linux-gnueabi.tar.xz=baa52bf16290d71b1b89f12ddcee5adf18c480071f9fd4daf3fcab72f92fad4a -dist/2024-07-26/rust-std-beta-arm-unknown-linux-gnueabihf.tar.gz=2325e8bc225a24a0a8c16da6dded16d4befb671b913051a7cce12ee3e183eac7 -dist/2024-07-26/rust-std-beta-arm-unknown-linux-gnueabihf.tar.xz=ab9ad0ec7057deda5c29e5d7de317eb32512fb95b62ba628b91b5246dde9c90d -dist/2024-07-26/rust-std-beta-arm-unknown-linux-musleabi.tar.gz=be6d9a01609152eb815cef9462023f0ca2f2950ed03d914629d8e6e3a96af8ab -dist/2024-07-26/rust-std-beta-arm-unknown-linux-musleabi.tar.xz=75ec6023cf9a43ec7ed0f52a1633b56154d9505c5d5d769153b48b9991ce99a8 -dist/2024-07-26/rust-std-beta-arm-unknown-linux-musleabihf.tar.gz=cc1d361b775e966c700d122f925a9f2feacecaf7d2891d9c5c5a4a1060336408 -dist/2024-07-26/rust-std-beta-arm-unknown-linux-musleabihf.tar.xz=934c10c58db5d7644bd0b7df6c3a128cc53b88b412128c33de5932fa0194f4bb -dist/2024-07-26/rust-std-beta-arm64ec-pc-windows-msvc.tar.gz=949a18d9d8b4c7cb3442ec4e387c91feddf0cc26f1fe602ec6c2c484312c9845 -dist/2024-07-26/rust-std-beta-arm64ec-pc-windows-msvc.tar.xz=7adb9a93d35002d0335b3449b8d9af35a80a35524fe98bd86c3896481f020597 -dist/2024-07-26/rust-std-beta-armebv7r-none-eabi.tar.gz=b40dbc6ba0f3f80414bdc11260f291f067acbceb50d84597a9366746cff53348 -dist/2024-07-26/rust-std-beta-armebv7r-none-eabi.tar.xz=1564c3215b173956bae41cda7312ed7912812e0fbb65dd8d75808a1d5084fc8d -dist/2024-07-26/rust-std-beta-armebv7r-none-eabihf.tar.gz=809d7f027aecc4a131921181418e66b956ad0a2a7170a3ec3649e21659c5a524 -dist/2024-07-26/rust-std-beta-armebv7r-none-eabihf.tar.xz=1b9589a72d2902cd4491406d93c599d2e850fa2ba19b1bcc6bdc5cc7196f9643 -dist/2024-07-26/rust-std-beta-armv5te-unknown-linux-gnueabi.tar.gz=f2840d36b089fdbcff5f6f9f7a6e576cf21836824957cdf2d1ef2c75a1f5c11f -dist/2024-07-26/rust-std-beta-armv5te-unknown-linux-gnueabi.tar.xz=5723cf48a1ff47fb764cc5ad921356e490997aa09ecd86404e370ffdacfa4b31 -dist/2024-07-26/rust-std-beta-armv5te-unknown-linux-musleabi.tar.gz=fb33110ad649aac6f55310e6f03d03d4d75ccdca43ada93fb97a717975ef867f -dist/2024-07-26/rust-std-beta-armv5te-unknown-linux-musleabi.tar.xz=cef39c2886fffef2986e9fe8f3be58f0d7f3846466a35443bc0d49464bdef98a -dist/2024-07-26/rust-std-beta-armv7-linux-androideabi.tar.gz=68fe7b30550cf1ccc44a1669f26620ae418b48cd6283b716aff3dee91acfcbec -dist/2024-07-26/rust-std-beta-armv7-linux-androideabi.tar.xz=81f24aedc06a25c8dfce729132a77e90adc5fe2aec86a3a9548aec9458127ce1 -dist/2024-07-26/rust-std-beta-armv7-unknown-linux-gnueabi.tar.gz=a63c5d40bcf8b0702c1a91e992c042130916edfdcf94fb4615ba10c89dad6642 -dist/2024-07-26/rust-std-beta-armv7-unknown-linux-gnueabi.tar.xz=4706424b53063b768223880d87bbec0cf57e524374a6ef053ebef02d096484e4 -dist/2024-07-26/rust-std-beta-armv7-unknown-linux-gnueabihf.tar.gz=85c3684f175642463777aa69889a20391e39afc0d6356baa3ac0445f7aa25119 -dist/2024-07-26/rust-std-beta-armv7-unknown-linux-gnueabihf.tar.xz=a8d67436a8ee232d57e2924f8f9e5cb0050c71740d57a4e677674adb75093f31 -dist/2024-07-26/rust-std-beta-armv7-unknown-linux-musleabi.tar.gz=b3226669f49ee8fc89c1f84855c29f8416df3e32d3276547f521f738179164a6 -dist/2024-07-26/rust-std-beta-armv7-unknown-linux-musleabi.tar.xz=9a5711743a0984ab7baed2a50f87e50d7facff2ef05f5b936b7b25f5a5992734 -dist/2024-07-26/rust-std-beta-armv7-unknown-linux-musleabihf.tar.gz=fd2db70418d432c7b32bed92f5af0f301baa3a71c171d0ee8b0798bbc8e239e2 -dist/2024-07-26/rust-std-beta-armv7-unknown-linux-musleabihf.tar.xz=97922d70b37e1e2ff6dc447625b3482094824910a1d7a483cc707985406560ee -dist/2024-07-26/rust-std-beta-armv7-unknown-linux-ohos.tar.gz=710be82238e9ad617b2d5f52ef37976b415e7b6ba3d5f3677080f2ccf78b9d44 -dist/2024-07-26/rust-std-beta-armv7-unknown-linux-ohos.tar.xz=2cd0956277cf963f95ffa0104bdcd60cb4e6c4bb2a443a683d67f41726408159 -dist/2024-07-26/rust-std-beta-armv7a-none-eabi.tar.gz=dd38446053d1500f3bdc325ae5cd52d0434c618d79a7c0a0473c76691353bac4 -dist/2024-07-26/rust-std-beta-armv7a-none-eabi.tar.xz=5b82a2f970be59563cc4f550e4202be802cbe21dcbf14de413ed8f30b0e22020 -dist/2024-07-26/rust-std-beta-armv7r-none-eabi.tar.gz=9758806233e59d7d40eeda0740559d9838f9a6c608309567af61245ea57dc212 -dist/2024-07-26/rust-std-beta-armv7r-none-eabi.tar.xz=4266b69d61a46c0c6f6d3aeb2b3378ff88201039df50cd8d3a51c9ff910be181 -dist/2024-07-26/rust-std-beta-armv7r-none-eabihf.tar.gz=6142ea4cdff99902181379fdb9a651fd9d1ab6276ebc104e73b2280a6d9f380f -dist/2024-07-26/rust-std-beta-armv7r-none-eabihf.tar.xz=bbf4c74f6b6a32f01d03bf101f69dd19b909717036117064fa2c8cdd0b4146da -dist/2024-07-26/rust-std-beta-i586-pc-windows-msvc.tar.gz=2cc32752932477945f248dee4d277754928b982815e2e2e0d27883522fb9b8d2 -dist/2024-07-26/rust-std-beta-i586-pc-windows-msvc.tar.xz=e40eae93c31c1fa06517a21cfbdd2dd18e2f740aee1251bcc9bdc680a565241c -dist/2024-07-26/rust-std-beta-i586-unknown-linux-gnu.tar.gz=6d7210503568d9fa02231ac2d9a1b400d00a37f38ec8f00bfcfe45c325aeed02 -dist/2024-07-26/rust-std-beta-i586-unknown-linux-gnu.tar.xz=cdd81201e38226750f2b4292b099b5d78fe0115cedb4c28bf20200144297d8b6 -dist/2024-07-26/rust-std-beta-i586-unknown-linux-musl.tar.gz=95244114ed2d6dd2de488f49115b11a25b008134f1fa1c8f2e2a62849b51f213 -dist/2024-07-26/rust-std-beta-i586-unknown-linux-musl.tar.xz=fcb3280dabb4aae920a14c7f4fec52dc3f11bc68f5143961fa88347aa020bb9a -dist/2024-07-26/rust-std-beta-i686-linux-android.tar.gz=d36c3baba2df9d69e197a773f752bc36e107c2411d78037a357039a856e35aa5 -dist/2024-07-26/rust-std-beta-i686-linux-android.tar.xz=14b9bedd1bb95e1bac2bb028670b1d9dbe6998bb6ad0cfab1db0be0cd9e3d4cf -dist/2024-07-26/rust-std-beta-i686-pc-windows-gnu.tar.gz=44463b4a17c87a2de8554e2629eed8172b60b078ccca7e78bb2b0a20324f51ef -dist/2024-07-26/rust-std-beta-i686-pc-windows-gnu.tar.xz=1e4c3a1d8585aac5aa3e66541b4aef03a0b429a6067300c58f6cf588eac19fa6 -dist/2024-07-26/rust-std-beta-i686-pc-windows-gnullvm.tar.gz=b1d9d5967c039721eda402a7227074ba6e6e8f2877be49eed961ecbce00004ed -dist/2024-07-26/rust-std-beta-i686-pc-windows-gnullvm.tar.xz=2436343b99d81abae0e6bba16850dbc1c005ebba5defb991c3a0e99834410746 -dist/2024-07-26/rust-std-beta-i686-pc-windows-msvc.tar.gz=c6147e9c6c39501d133a344972dbb8108bdc45bb2fe8ad624162ad04a9c00c6e -dist/2024-07-26/rust-std-beta-i686-pc-windows-msvc.tar.xz=6207bdfe0796e4bd4e7d25457d67559f15aa2e8bb91b05284ed147f8799de869 -dist/2024-07-26/rust-std-beta-i686-unknown-freebsd.tar.gz=c675df742bd9fbc01f67411a19926e2814412f12e09b53d1492e8c7250f3e685 -dist/2024-07-26/rust-std-beta-i686-unknown-freebsd.tar.xz=d5b9c3783f6d2dbdf25e0495e32a295c4820bbc5b65a44f19f018b1141e85371 -dist/2024-07-26/rust-std-beta-i686-unknown-linux-gnu.tar.gz=748dfafeb6b953017b9129be9697d02a73d5bc8b1371a6a00bbfa20b7b45033c -dist/2024-07-26/rust-std-beta-i686-unknown-linux-gnu.tar.xz=0c9a0717054858fa821e4c418b9e99cb0a0f852ec3c866951c1d1795cc1e8152 -dist/2024-07-26/rust-std-beta-i686-unknown-linux-musl.tar.gz=96afb9b33c86a6007f9c02f1f418d28f13014ec5154b648ceb7f725449dcbddf -dist/2024-07-26/rust-std-beta-i686-unknown-linux-musl.tar.xz=7ed52c039fdd13a7477ed211ad8432cfd2fab98832174c8a534e5ac280f28572 -dist/2024-07-26/rust-std-beta-i686-unknown-uefi.tar.gz=676786bd5e7f0739d18d40d99158045fcba746dc306485c0f15ce49ef2b63b0b -dist/2024-07-26/rust-std-beta-i686-unknown-uefi.tar.xz=d7fdba095ca515454034891c8a862aaa563ee7451289138ce32b10691dbfe38a -dist/2024-07-26/rust-std-beta-loongarch64-unknown-linux-gnu.tar.gz=ff2eb11f284da7883dbf6ae465af86e50a9cd98c9b7d22b1e710626716e07db5 -dist/2024-07-26/rust-std-beta-loongarch64-unknown-linux-gnu.tar.xz=953fedb9dac336cb796290f619919f4ff9b2a6fcce09e23072f93a40b5498bdd -dist/2024-07-26/rust-std-beta-loongarch64-unknown-linux-musl.tar.gz=ba1b4f772faf2e738d2696eb576f74bdbd1fed1a073053eee341ec6423b6e1c6 -dist/2024-07-26/rust-std-beta-loongarch64-unknown-linux-musl.tar.xz=f3f3eaafd9ecb1ee0ba68259d88d65ced56f20323a4f542fc85993e92a044206 -dist/2024-07-26/rust-std-beta-loongarch64-unknown-none.tar.gz=f20ecabfab9d8ecbab44d661018b865e449137993726e76b20c7749db4d0986e -dist/2024-07-26/rust-std-beta-loongarch64-unknown-none.tar.xz=7da2cf413c0665b07b3083862747c9815a78b3775c2bee6cd1f7551e7f2e4c8a -dist/2024-07-26/rust-std-beta-loongarch64-unknown-none-softfloat.tar.gz=3f7529ea5dcb17c18efa949916dd1ebc29b123a265cc8839cee4fe4e637f19be -dist/2024-07-26/rust-std-beta-loongarch64-unknown-none-softfloat.tar.xz=d2a30f8659cc66d48da0e6c1919707943321d7f3ac0e2d58a9078aec16c86ef7 -dist/2024-07-26/rust-std-beta-nvptx64-nvidia-cuda.tar.gz=f971daa3f8c3d0773fb6667cb7a544f96ebd049e9b5d1b5ac4bd3ea0c342467b -dist/2024-07-26/rust-std-beta-nvptx64-nvidia-cuda.tar.xz=3cd2f4ad7d9f41e9f903aa49eb86d142bb5ef69c2c39d9ba16a00a39d74046f1 -dist/2024-07-26/rust-std-beta-powerpc-unknown-linux-gnu.tar.gz=b319ee87ee034a6a2a67dc2efdc72f8285c73d9bd1bd893586170ac54049151a -dist/2024-07-26/rust-std-beta-powerpc-unknown-linux-gnu.tar.xz=c751e65bbdfd72de07abf138162ab64dcbce51ba50375cef5ca8f35945d9ac7b -dist/2024-07-26/rust-std-beta-powerpc64-unknown-linux-gnu.tar.gz=0228f8d7e0913cca5db975e0b9ec4807e817dcbc0cd0bd64b64826c9537f25e5 -dist/2024-07-26/rust-std-beta-powerpc64-unknown-linux-gnu.tar.xz=d37d5ae3605d745a393fc71c5f0e169cee283aa840edb9543682b339cd040310 -dist/2024-07-26/rust-std-beta-powerpc64le-unknown-linux-gnu.tar.gz=6dd97a7215bdc8145cee5856957bf3f20719f65c73033006243ac2a9e347394b -dist/2024-07-26/rust-std-beta-powerpc64le-unknown-linux-gnu.tar.xz=d7541a8e83f7b8a9761988c3ac295a665e21e4d5dc9e2284ef48314f6c784166 -dist/2024-07-26/rust-std-beta-riscv32i-unknown-none-elf.tar.gz=34b21aec2cc1b92b2911211fe3c798918ea6c99d51975f6a979c2da3a09b0a05 -dist/2024-07-26/rust-std-beta-riscv32i-unknown-none-elf.tar.xz=50ba48e76e60ffbfb2bb0ba0b8e12418b7f6a9d7cde31b508bb4656536934e82 -dist/2024-07-26/rust-std-beta-riscv32im-unknown-none-elf.tar.gz=e84526736c1a48dbec3b122b8c01458ff549afdbdd0f73e705c76cca1bd1f767 -dist/2024-07-26/rust-std-beta-riscv32im-unknown-none-elf.tar.xz=df8d9909b0afd0e02b9c027f12e28aa2c40716d7c8a8f5e82b7521d2e145fbf8 -dist/2024-07-26/rust-std-beta-riscv32imac-unknown-none-elf.tar.gz=7b671c5257a7653481fe6bc090c55398607590292590e0fdf5973f5f9b7b18b1 -dist/2024-07-26/rust-std-beta-riscv32imac-unknown-none-elf.tar.xz=7f4d1a8e757fd29f4f58005032608df709003098eb661fe98a0b3116b7237e6a -dist/2024-07-26/rust-std-beta-riscv32imafc-unknown-none-elf.tar.gz=9d957edfba201b541bd589ca4085e26bf6f890b3970817fe9af6ccf5f2eb0854 -dist/2024-07-26/rust-std-beta-riscv32imafc-unknown-none-elf.tar.xz=0f867e1391009d1d0caefb6b9217fc8e9f3e087a7dd9b22a157719bdc44ac074 -dist/2024-07-26/rust-std-beta-riscv32imc-unknown-none-elf.tar.gz=a02ccac46574fad8929b419eff7510b8a773211d3ccce9ca96f0485e2dab8eaa -dist/2024-07-26/rust-std-beta-riscv32imc-unknown-none-elf.tar.xz=b70f37cddd519d0d207e28089b469f702bfe72ba5d32a631c85270db75b83d61 -dist/2024-07-26/rust-std-beta-riscv64gc-unknown-linux-gnu.tar.gz=151863cece818be834261e6c148eeabbb1c796c991065c84b813bac64e73fef7 -dist/2024-07-26/rust-std-beta-riscv64gc-unknown-linux-gnu.tar.xz=94cbae695036a4a1fa1faac12a6dd5ebeea18ec2d6e7b01c311d340ce7ddba39 -dist/2024-07-26/rust-std-beta-riscv64gc-unknown-none-elf.tar.gz=3c8ca657208a4d96eff193363375a33d966dc319cd329dd7a0d379e052ab43bc -dist/2024-07-26/rust-std-beta-riscv64gc-unknown-none-elf.tar.xz=037f7b599421eca888332dadd797509d81af04743eac06120a9882b27aff5ca2 -dist/2024-07-26/rust-std-beta-riscv64imac-unknown-none-elf.tar.gz=d931a3611003cbe61003ca4feeb637449f1d10f7969cd27ca37f11cf5536e465 -dist/2024-07-26/rust-std-beta-riscv64imac-unknown-none-elf.tar.xz=3c7a3a9e1e03c2fe097e2e7353d00d02e864d3964db559f6a08a3d33f1fb7927 -dist/2024-07-26/rust-std-beta-s390x-unknown-linux-gnu.tar.gz=f877200e388345c10d3b0f5b8c484dd42905e769dcc1e21692e1cf7f2d59317e -dist/2024-07-26/rust-std-beta-s390x-unknown-linux-gnu.tar.xz=1052e8e5681c95ed3c004adee2492ff19d109965e9441a3362df876719899486 -dist/2024-07-26/rust-std-beta-sparc64-unknown-linux-gnu.tar.gz=e487752db0ecd837fb1ecb57064ef2464f7f85ed5fdc9d47322e7b5c37c32300 -dist/2024-07-26/rust-std-beta-sparc64-unknown-linux-gnu.tar.xz=e74a462d598c55822b5841bdc35cb2605b4aa7993e305246b3adf079ae79ea1d -dist/2024-07-26/rust-std-beta-sparcv9-sun-solaris.tar.gz=3ea692ffe99c953d0049c0a16b71eb0bc3da492b9f9308463311dc0143af84dd -dist/2024-07-26/rust-std-beta-sparcv9-sun-solaris.tar.xz=97005f0d686a6481c5a532b6e1ea14befc794ed89394a8f1c94ad39257ebdaa8 -dist/2024-07-26/rust-std-beta-thumbv6m-none-eabi.tar.gz=2aa967414bd03764774338e377c4714b8d169b1bbc651624a20158441b8111c3 -dist/2024-07-26/rust-std-beta-thumbv6m-none-eabi.tar.xz=d1a3b6ccbc55d1d9555674d1596a0c9f489304f9cb211e0c4645c17256ada4d1 -dist/2024-07-26/rust-std-beta-thumbv7em-none-eabi.tar.gz=33fe3c61aa2e93c6a925b132fabc11c24e102cc070260d5f89a66e374e9a4d23 -dist/2024-07-26/rust-std-beta-thumbv7em-none-eabi.tar.xz=f50bb682fe484f23ae1ae9b2466c450b8fe9ecc3694fb68e162ce43cc8917af7 -dist/2024-07-26/rust-std-beta-thumbv7em-none-eabihf.tar.gz=53a17d10d498f1b6ebd6852987f304b2e1187544f2c9e91b69d0fdbf88630910 -dist/2024-07-26/rust-std-beta-thumbv7em-none-eabihf.tar.xz=fb97e6f2b047d6251eb6e34891b64f20d0dbc648beb78bb7364fe563670d7de8 -dist/2024-07-26/rust-std-beta-thumbv7m-none-eabi.tar.gz=940eef037faceb2b9bdb1094eac6b175843094d3a3ab3c9850eb28742643e92d -dist/2024-07-26/rust-std-beta-thumbv7m-none-eabi.tar.xz=c892b8a80db788d1f4bf64ec6f740bb1168a8b9dc88d105366892a476ad3c244 -dist/2024-07-26/rust-std-beta-thumbv7neon-linux-androideabi.tar.gz=905d378e6fd4387381fc166718ff31f017c99e725a9c8461bbac39d5571e246f -dist/2024-07-26/rust-std-beta-thumbv7neon-linux-androideabi.tar.xz=6c5fc29004bda36ddfb0280636ac2b2c28c538f33cadb07a55174fadb068daa5 -dist/2024-07-26/rust-std-beta-thumbv7neon-unknown-linux-gnueabihf.tar.gz=38c8b07558734a9fff1807a823af72faaf8ab5ea47042f1b88a38d6c3648c43b -dist/2024-07-26/rust-std-beta-thumbv7neon-unknown-linux-gnueabihf.tar.xz=e30e0000336449a8aabf60839cba4ecca32cf82b02ed0a7a23935793072679f4 -dist/2024-07-26/rust-std-beta-thumbv8m.base-none-eabi.tar.gz=db784556ebf56a79e6330de3204ce6ce5422eca2543b872ed55c238aedbfedae -dist/2024-07-26/rust-std-beta-thumbv8m.base-none-eabi.tar.xz=373efe8c55e85aae60dfac234471b76fefbc2ba722d97e0338ec593b7c70cce3 -dist/2024-07-26/rust-std-beta-thumbv8m.main-none-eabi.tar.gz=1bd5a11163f5fb9325e21c425d5d2fb3e1f845d265cbf7736679c3bb9c8d22a7 -dist/2024-07-26/rust-std-beta-thumbv8m.main-none-eabi.tar.xz=d858d0077df0fa7363258994e76a1bc0ff850734de6a0fbe955c3c9b9cd46cb7 -dist/2024-07-26/rust-std-beta-thumbv8m.main-none-eabihf.tar.gz=07b356cd0ec3f18617e8f5be04d784847acfca43d6fa2101821dcdee18aada36 -dist/2024-07-26/rust-std-beta-thumbv8m.main-none-eabihf.tar.xz=aecacd11945e6e053fe27faab2c0816628b392cb06c41feb8ed693d43043eba4 -dist/2024-07-26/rust-std-beta-wasm32-unknown-emscripten.tar.gz=7bf6bdb443503d48cb711f8b3e2670fe20e02f71ae940c2f1b273ab1d15452b7 -dist/2024-07-26/rust-std-beta-wasm32-unknown-emscripten.tar.xz=9ed34d7467722660d625e9a048fcb843bdb80aac407b0395a693a5698f6c1465 -dist/2024-07-26/rust-std-beta-wasm32-unknown-unknown.tar.gz=5144fe563c42205ba777678291950bd1b8c2b010b9aae28e2fe96e14e93e28cb -dist/2024-07-26/rust-std-beta-wasm32-unknown-unknown.tar.xz=6e55e79f65a02abf37e1533c2590f53dfe56b474b58a3220d88f3d1458b6dcdc -dist/2024-07-26/rust-std-beta-wasm32-wasi.tar.gz=84d03b1c1fc7338895f82f54fdccb18ea6c4ceb43f47c3d46fadb014aa0c9549 -dist/2024-07-26/rust-std-beta-wasm32-wasi.tar.xz=f28cbf9552e3c680342364087e7305a12417a92ed6b6696d71d476e1c1d8d4e7 -dist/2024-07-26/rust-std-beta-wasm32-wasip1.tar.gz=8d56f1aa8661047f854806278b83a514fa79b7a5097635cd095943b3f848ea74 -dist/2024-07-26/rust-std-beta-wasm32-wasip1.tar.xz=78609204d01e0d0bcbc1fb5dd3d9cfcac60db23bfbd2428f1e021d1b05793519 -dist/2024-07-26/rust-std-beta-wasm32-wasip1-threads.tar.gz=ed1b9141bd68b8c13e295904ac66d18ca92c5b92a263fa5109262d15065aeded -dist/2024-07-26/rust-std-beta-wasm32-wasip1-threads.tar.xz=0c036271c4c4e04357b630146cad296dc6a57363f7dc0cd2f3142ead13bf0602 -dist/2024-07-26/rust-std-beta-x86_64-apple-darwin.tar.gz=c12bc5543c262645f7000cc84247518033f15fcbdfed510eb92393d723906eb1 -dist/2024-07-26/rust-std-beta-x86_64-apple-darwin.tar.xz=a5fc26dd6068cdb28ee2a252af545a34dd2be6e075e7d0aac2d03796c07579f4 -dist/2024-07-26/rust-std-beta-x86_64-apple-ios.tar.gz=a62be7f900cec101b1b7444c7466e8fe0b823d708fadd92bce8bd531866b4938 -dist/2024-07-26/rust-std-beta-x86_64-apple-ios.tar.xz=993875efe27c1018bbcb8326665247a33eda6fc0e934f71124b0a08d72685474 -dist/2024-07-26/rust-std-beta-x86_64-fortanix-unknown-sgx.tar.gz=bc6ae4d5e93b47828678f1af55efc1baae2d76975be3259854272a566f5489c9 -dist/2024-07-26/rust-std-beta-x86_64-fortanix-unknown-sgx.tar.xz=51cf1d675e61aaeedf895e52a9a81b188aa066a68d599963e0435bddfd2f6a5b -dist/2024-07-26/rust-std-beta-x86_64-linux-android.tar.gz=6bd4089f30f05d9902d667a2d48028345bd558e7365bd3957bc554a4d0c1f939 -dist/2024-07-26/rust-std-beta-x86_64-linux-android.tar.xz=2a7e9250e3bea7f7e502131012139eadb66c71e95e8cec1698e22b21e7c9fbcd -dist/2024-07-26/rust-std-beta-x86_64-pc-solaris.tar.gz=4169c938b638faff18a5db1bed5e7d2036f45d25ec9799dc2967ad1589d447a9 -dist/2024-07-26/rust-std-beta-x86_64-pc-solaris.tar.xz=8cbda8eeb98be575b78170e9895390e9406c4de41db8363988185dd24e276427 -dist/2024-07-26/rust-std-beta-x86_64-pc-windows-gnu.tar.gz=99a14bf8cffa0c736a25ce117bc5d4ab64963d81c9d9ac377f118a77a6a3c4b6 -dist/2024-07-26/rust-std-beta-x86_64-pc-windows-gnu.tar.xz=9902878b75b3f6cf944909cf6d17efc26dc820708b164b34757d841e89c948bd -dist/2024-07-26/rust-std-beta-x86_64-pc-windows-gnullvm.tar.gz=54b83918128c3d19b09a4e1801783500266794395e6a6f138ad647bd890b79f6 -dist/2024-07-26/rust-std-beta-x86_64-pc-windows-gnullvm.tar.xz=2b0ed80c922e25f3783fbc0ce181b76b7f758d2a1b85b823851b7ac35c6872df -dist/2024-07-26/rust-std-beta-x86_64-pc-windows-msvc.tar.gz=44ce7faad791029b670a9d815766a647d488dbbb56eb09024a09a595427fd19b -dist/2024-07-26/rust-std-beta-x86_64-pc-windows-msvc.tar.xz=cd7011512df191100d31caef920d1a5c6d5ec2a771e0b52078d5d60b45e9a497 -dist/2024-07-26/rust-std-beta-x86_64-unknown-freebsd.tar.gz=dc20c2fc14b2211bf4517464109871f940a227298302d2ec84eaca539a19e9b4 -dist/2024-07-26/rust-std-beta-x86_64-unknown-freebsd.tar.xz=5a7fa24ca3f7b43526c116a5ebce60f29116640ad51c1ed426f9aee705b10897 -dist/2024-07-26/rust-std-beta-x86_64-unknown-fuchsia.tar.gz=975917e862347f7e1472cdaa2258de16cb9981e3a8256f9b7860104740076187 -dist/2024-07-26/rust-std-beta-x86_64-unknown-fuchsia.tar.xz=bb89062b05f025a964e0110fcfc8fdf57300b23314409924cd4a05e9af9614af -dist/2024-07-26/rust-std-beta-x86_64-unknown-illumos.tar.gz=a1c1e3e15bea1c4e6c70b8a56c4fef1c231b6ab5528c32cb69ded38456b3fa21 -dist/2024-07-26/rust-std-beta-x86_64-unknown-illumos.tar.xz=43b31f7dd50621faff96c13a2246c80e84fc4da4076d4aedca4e9a6bf63ca43b -dist/2024-07-26/rust-std-beta-x86_64-unknown-linux-gnu.tar.gz=3f8df0e35e2e8d5e0f8181f20f0639323aa8e8c21da60697599447c0d77f783a -dist/2024-07-26/rust-std-beta-x86_64-unknown-linux-gnu.tar.xz=d0e727d9176abdbef02b1276b3b1acf69068b9c0fc0477fb3248fd06c99292b5 -dist/2024-07-26/rust-std-beta-x86_64-unknown-linux-gnux32.tar.gz=73ba835c5c4c9fcabbcb4e1460d402cf0c0aa9b2e01342521897abd9769dcc02 -dist/2024-07-26/rust-std-beta-x86_64-unknown-linux-gnux32.tar.xz=64e6fc64ccfd0adb2fabc610eba6e877ab83f2de49532363deef4579728baf6f -dist/2024-07-26/rust-std-beta-x86_64-unknown-linux-musl.tar.gz=58dcb73ba02fa38742d255bd346a77340cf634247904624c7af9b11e769a364c -dist/2024-07-26/rust-std-beta-x86_64-unknown-linux-musl.tar.xz=ea4417de121ab7e869659b26efd144baf2fd839a956da4acb30121d1bc9132aa -dist/2024-07-26/rust-std-beta-x86_64-unknown-linux-ohos.tar.gz=d1e861a9176a5cb934270592f7b98528283c363d135736477a844499015ac44a -dist/2024-07-26/rust-std-beta-x86_64-unknown-linux-ohos.tar.xz=c5f548845c6ccbee1980892e630ab06ec1bef498fb7f6fc80b4ced4a84c23f85 -dist/2024-07-26/rust-std-beta-x86_64-unknown-netbsd.tar.gz=3f6677ecdb1a2f016e9941234c221b06fd0a21cd9bae83a59bdcfde055c4878a -dist/2024-07-26/rust-std-beta-x86_64-unknown-netbsd.tar.xz=60eae08756d92a70b740ecd8a1412138a9a14486289d73440bf7ee068586f9c4 -dist/2024-07-26/rust-std-beta-x86_64-unknown-none.tar.gz=1f11ad1a66d01a09c7237da76327b70ae2e2a9f7647a3ee0de58d563576efacf -dist/2024-07-26/rust-std-beta-x86_64-unknown-none.tar.xz=960fb614a927e1b3d1d8e4a9fb7220ae675d0e8219fdde204bc6454fbe69a0a9 -dist/2024-07-26/rust-std-beta-x86_64-unknown-redox.tar.gz=3af955fc52feaee2d89d6d50e0df4d00417897679f0d607a0f146a8d34c20496 -dist/2024-07-26/rust-std-beta-x86_64-unknown-redox.tar.xz=cb607387d0524bc84610cd6cc0a0070e0dadc379a7fb1a736f3f336cf0458b8d -dist/2024-07-26/rust-std-beta-x86_64-unknown-uefi.tar.gz=ae56b334234ba51cf68be42d0fd58cf3487673dbe747bb3efa01e8563b9b8a90 -dist/2024-07-26/rust-std-beta-x86_64-unknown-uefi.tar.xz=1468622e9bb6384a6ab7006863d2b7d55307e74239befc8e72dfd39f83c0af1e -dist/2024-07-26/cargo-beta-aarch64-apple-darwin.tar.gz=62f687da4c02bef3e114b92c75b62fc6f7fdfcd210fb66329f6d4780f7dbcd70 -dist/2024-07-26/cargo-beta-aarch64-apple-darwin.tar.xz=f9346e9ed4e5638f58dc237b22aef9e1b25b23bb588c736dceaa25b7b935f2bb -dist/2024-07-26/cargo-beta-aarch64-pc-windows-msvc.tar.gz=f2442eab2908bb90c551f56da8889e39ce44a31936ce63e13a54432105a67cf9 -dist/2024-07-26/cargo-beta-aarch64-pc-windows-msvc.tar.xz=ffc8c803668d09333fdfee996fa72c8874e91d92567f0b4eff9077d7b9a3070a -dist/2024-07-26/cargo-beta-aarch64-unknown-linux-gnu.tar.gz=97f6b771f7e559df03f00f8665c6580535499d4afa7bf2a252a145b1aa0e2c0b -dist/2024-07-26/cargo-beta-aarch64-unknown-linux-gnu.tar.xz=3ee58d5c57ba00e27428392dab1d69655bf7e997a0d3aa6629bb32f4f863396b -dist/2024-07-26/cargo-beta-aarch64-unknown-linux-musl.tar.gz=b36871d3c88eca54e4c24d50171fd649d10a92f689d4812ebef7b510f0c3d799 -dist/2024-07-26/cargo-beta-aarch64-unknown-linux-musl.tar.xz=ee550d60ae217fe7aec12feada1ba1f84222427677de42382d192ec748f73f18 -dist/2024-07-26/cargo-beta-arm-unknown-linux-gnueabi.tar.gz=6599270c877164e76ef30f00a9b47da1a021fdaf1d4f7fdb194500f861ca8d21 -dist/2024-07-26/cargo-beta-arm-unknown-linux-gnueabi.tar.xz=46429528039b5499c6ac4618c4b73fcdfabf7fdd5ed9f9f3d64ccde0428d78c0 -dist/2024-07-26/cargo-beta-arm-unknown-linux-gnueabihf.tar.gz=01ba37e80e18e673c275538fc0db63b667ef52a72000dcbe76ac68018bd585e8 -dist/2024-07-26/cargo-beta-arm-unknown-linux-gnueabihf.tar.xz=004f5119454fa53c2a7a58f6d176f65903b3c5bfc8eb1f894f6ca4e9bc32b7a1 -dist/2024-07-26/cargo-beta-armv7-unknown-linux-gnueabihf.tar.gz=2bb2e69563684bf64607d3f584b4216b24fe190dd2eabd6c00c2044290beabde -dist/2024-07-26/cargo-beta-armv7-unknown-linux-gnueabihf.tar.xz=454b0dafb3cd62788dc541ddfea5b484ac799253937602f6456e853c2a293707 -dist/2024-07-26/cargo-beta-i686-pc-windows-gnu.tar.gz=779d704f8f64a7290227631d1e396fe00bdada3cfb7f3e6c775a0bb00047cb97 -dist/2024-07-26/cargo-beta-i686-pc-windows-gnu.tar.xz=8cce8e286ff04f4d58235e8716a0ca05aedfeb9db6fb8952c523264ea649e542 -dist/2024-07-26/cargo-beta-i686-pc-windows-msvc.tar.gz=58b31a781da4f5215b0fbb5f355cbc3c5b2212971c68a1e00de19b851698fda3 -dist/2024-07-26/cargo-beta-i686-pc-windows-msvc.tar.xz=008125eca7351844707c9c14637030da45441a68d74f6e2752ee713f6403f03b -dist/2024-07-26/cargo-beta-i686-unknown-linux-gnu.tar.gz=cbfc580db37b135a20f42f9da02517ec8cf0a286b7274252c23c6a4947ba6755 -dist/2024-07-26/cargo-beta-i686-unknown-linux-gnu.tar.xz=dc2198fabb6fe6f68353c268698dece4ca3d6901b424a7cc2c68850f81f75f20 -dist/2024-07-26/cargo-beta-loongarch64-unknown-linux-gnu.tar.gz=46ea726328e1700cf2b7d0ddeb16e25ebb648267c76268ba2f4aecb75ba47661 -dist/2024-07-26/cargo-beta-loongarch64-unknown-linux-gnu.tar.xz=520ee25c1f18d80b4e4ce25e8fd961a19c0dd2ee0274e9d9cd3201f7c57c6f77 -dist/2024-07-26/cargo-beta-loongarch64-unknown-linux-musl.tar.gz=fb710b6ae058619042bdf80ef5c2a56457076692a122b4155e0a53f382e8ad83 -dist/2024-07-26/cargo-beta-loongarch64-unknown-linux-musl.tar.xz=ac15e80c28c7a4570bb4a99fa70522a3ae5ba602ce25e96b8e82d097f8b42904 -dist/2024-07-26/cargo-beta-powerpc-unknown-linux-gnu.tar.gz=6907a40c1e7b18146ff2a60c6d44c9716f31cd4aeaae4fe858032aa26c359d27 -dist/2024-07-26/cargo-beta-powerpc-unknown-linux-gnu.tar.xz=4287d73ae2b3272a1893c2ffa32d007edf0b05ff2dbf1da92aa20f2b857e0eab -dist/2024-07-26/cargo-beta-powerpc64-unknown-linux-gnu.tar.gz=edbdd5fc1e9bc5fdea67e7c2fda3fa9f3eb3f599c307a278bc7bf45ff97d1f48 -dist/2024-07-26/cargo-beta-powerpc64-unknown-linux-gnu.tar.xz=9c7d487f65a6273b76970b2c057b8120abbd89ba67a2f92dd446ecbacf218576 -dist/2024-07-26/cargo-beta-powerpc64le-unknown-linux-gnu.tar.gz=74e57cbc139d548202d94262170ee45e33ae01331358ac2eaa9fa67c968ea1ea -dist/2024-07-26/cargo-beta-powerpc64le-unknown-linux-gnu.tar.xz=6cf99b689e32ff0caa56e9704dd185f6c268b484ccb657eff212e66fe64d1c10 -dist/2024-07-26/cargo-beta-riscv64gc-unknown-linux-gnu.tar.gz=ed13a39d74e9d814d585ce7fb1aafd093f94317d6ead76e4b43c03b01e210086 -dist/2024-07-26/cargo-beta-riscv64gc-unknown-linux-gnu.tar.xz=b5379d677d6596ffcbd7f3ebef2fd6d968096228101104a45565b170fb050042 -dist/2024-07-26/cargo-beta-s390x-unknown-linux-gnu.tar.gz=1a29502881e6512a8bea566a90781870181f5727359668fa3bed2b3210a21b8d -dist/2024-07-26/cargo-beta-s390x-unknown-linux-gnu.tar.xz=95970245a7f304c6b83b8dad58b4c877ad2c9b0ca6bfc0090151561ce53a217b -dist/2024-07-26/cargo-beta-x86_64-apple-darwin.tar.gz=521f03a968c6e0640de6f09ecbc6328ea57b2815f353a14e1d4dd09925e98366 -dist/2024-07-26/cargo-beta-x86_64-apple-darwin.tar.xz=14b733585cc768d26a822de630d990f519b6d6b4ae079f09bacd51b7449c18a4 -dist/2024-07-26/cargo-beta-x86_64-pc-windows-gnu.tar.gz=1bf5d0201ca87a76de8044dd8222517bd130ef3db631dc60a84e2fceced465d7 -dist/2024-07-26/cargo-beta-x86_64-pc-windows-gnu.tar.xz=2eaeb6863c655047e6c938e208ae952df4da2d8b4326aeda60918414764aa7b6 -dist/2024-07-26/cargo-beta-x86_64-pc-windows-msvc.tar.gz=7b7ef80aa6131ddcb8bfec0f9493417e9a1e617a8f599a27de52ee914d022f95 -dist/2024-07-26/cargo-beta-x86_64-pc-windows-msvc.tar.xz=647a6d0ff8f38dd4404c0006e5ed7b3a981dc89bbc334b1bd53225cc4f5511c8 -dist/2024-07-26/cargo-beta-x86_64-unknown-freebsd.tar.gz=bcd0e100d4c66784a2357be74813551c68d4e3b5e6846bfd1bbcb316e5c82c53 -dist/2024-07-26/cargo-beta-x86_64-unknown-freebsd.tar.xz=cc31bb9f5a67359f4af4743afbdf9b694e40cd209211d4ea819c94183de6ab60 -dist/2024-07-26/cargo-beta-x86_64-unknown-illumos.tar.gz=12f6a8d3d17b54ea260f6f5b19be9e208111b0ad37518ae6b6eae558d77a1dc5 -dist/2024-07-26/cargo-beta-x86_64-unknown-illumos.tar.xz=221c9cf9d1fce2b5c50bcf8f435f5335f1c5e9533f51d52b941593d6a964b4c8 -dist/2024-07-26/cargo-beta-x86_64-unknown-linux-gnu.tar.gz=53c64845abe4582a90041b2128b3f931ce636d01fc9a8509b35ded5dd7ae0a35 -dist/2024-07-26/cargo-beta-x86_64-unknown-linux-gnu.tar.xz=61805cfca6e7f602eaab0fde2be48cfed244105b2f4b5bff798752ce06d62713 -dist/2024-07-26/cargo-beta-x86_64-unknown-linux-musl.tar.gz=92ac04de9689176a42e5f0ccf1e44ce78b64bcd15d6e570c171d51c44cf8c6ce -dist/2024-07-26/cargo-beta-x86_64-unknown-linux-musl.tar.xz=59a371de4343d330b79e84f629c98b5cb9dc58bd9706d1a7a9ff474b28394851 -dist/2024-07-26/cargo-beta-x86_64-unknown-netbsd.tar.gz=f48bb7b7d13862edaa8949be046b5bd2b8c63b0aab8e29bffb1940ec149eb123 -dist/2024-07-26/cargo-beta-x86_64-unknown-netbsd.tar.xz=0a6e09604fe291d0a9a0845a8ac7f434c9f4ffbb698c042ba83a070c23f804fb -dist/2024-07-26/clippy-beta-aarch64-apple-darwin.tar.gz=4c8991c692f200c6a5f25957e6648e07b7271681cbd9c61749bc990216dbbe6f -dist/2024-07-26/clippy-beta-aarch64-apple-darwin.tar.xz=51b5b85d46af2a3faeb53b81472c285eccc01f0c83575f62f37739cd48397fe2 -dist/2024-07-26/clippy-beta-aarch64-pc-windows-msvc.tar.gz=3a7755c10b32ee3b4f95875c974f21efad2be7ae27d317bbac056b3e5b9298b7 -dist/2024-07-26/clippy-beta-aarch64-pc-windows-msvc.tar.xz=718692e6a1e00ca042d9767273e487c941c65440e64729844a46e42ec6a8abb2 -dist/2024-07-26/clippy-beta-aarch64-unknown-linux-gnu.tar.gz=18da4a1fac25597186bdc5c825c71bc6fe020e8e6552ac97dd307a0311acab20 -dist/2024-07-26/clippy-beta-aarch64-unknown-linux-gnu.tar.xz=86a7ec123586e0c953efd23b82aea5eab62ab8c065bf3596d3001a23b01243ce -dist/2024-07-26/clippy-beta-aarch64-unknown-linux-musl.tar.gz=267b8dd0b5024152e36bcfb15af0b8ae3c68a71f559b8ecea1a3c9a8982e315b -dist/2024-07-26/clippy-beta-aarch64-unknown-linux-musl.tar.xz=6aaae715599da14ca8cc405e51deed3bc160661ec56e929ae347ef1ead7ccf00 -dist/2024-07-26/clippy-beta-arm-unknown-linux-gnueabi.tar.gz=f794412df97e19240f628037f5d1d7391dd09ee1a6de02f4dbff72e2b03d94b6 -dist/2024-07-26/clippy-beta-arm-unknown-linux-gnueabi.tar.xz=49a78a14b9638cabd19ba4261f5bd04066646e1260146e3be288182b73fa1864 -dist/2024-07-26/clippy-beta-arm-unknown-linux-gnueabihf.tar.gz=3dcd9775b46a100a50fbb00188dffdc6f07fca9843994c8406a2d053e41c1672 -dist/2024-07-26/clippy-beta-arm-unknown-linux-gnueabihf.tar.xz=e069b852ace430b2f75486a291d3d7849439c67c3381f5eedc0d6a9e6cde56db -dist/2024-07-26/clippy-beta-armv7-unknown-linux-gnueabihf.tar.gz=57f7109bef934d0da06f7aea6eaca72b0e66f82d1160fbae05f53c2276da2b82 -dist/2024-07-26/clippy-beta-armv7-unknown-linux-gnueabihf.tar.xz=5ed50d8d088ae0d86ba51a03bf56040da027376f70b5114f593813daa4ce7a40 -dist/2024-07-26/clippy-beta-i686-pc-windows-gnu.tar.gz=d8712ca2ab26256c0fade4ecc8dd8e4ea6770d91e16e460ff2fe3f070febc59f -dist/2024-07-26/clippy-beta-i686-pc-windows-gnu.tar.xz=9d0c88881e0535f9cb4a48f59b389b1c2a0b5fa46ad8bfa37fbc540676a8f557 -dist/2024-07-26/clippy-beta-i686-pc-windows-msvc.tar.gz=ffa017562648e98c7229e43a7422602c265441228485f0e14e52ebaf48a13e91 -dist/2024-07-26/clippy-beta-i686-pc-windows-msvc.tar.xz=292ab3d318a34e67463728752dc175f65cf5530f9368344dccaa79bad4df3b85 -dist/2024-07-26/clippy-beta-i686-unknown-linux-gnu.tar.gz=89bd927bc9370a405561f6534c5cd88e0f6e06b0b512589e5722349b12a17763 -dist/2024-07-26/clippy-beta-i686-unknown-linux-gnu.tar.xz=732120c4fcdde08fadca139216a91af7a6abee15f0a41735dc8860b36039d88d -dist/2024-07-26/clippy-beta-loongarch64-unknown-linux-gnu.tar.gz=101e3118bf23246195b159abab59ee5626e767977d97f00e71fc5e67dfbf7784 -dist/2024-07-26/clippy-beta-loongarch64-unknown-linux-gnu.tar.xz=e40c0c15a7b195ed03c5e1167c2cb5e765ef643b0f6621c36643faf87bf46369 -dist/2024-07-26/clippy-beta-loongarch64-unknown-linux-musl.tar.gz=f6ed6391c8997f942d180cd32e81aca654450fb050cd865a8a1b13f77a892245 -dist/2024-07-26/clippy-beta-loongarch64-unknown-linux-musl.tar.xz=16e736f65b0ff029fe9fbafceec938123dff1b5a133f6c48b25edab379a20685 -dist/2024-07-26/clippy-beta-powerpc-unknown-linux-gnu.tar.gz=711fdb406a23ab5c3b1199e7af06608297bd071d7e48734a03bbc1f7a00b66dd -dist/2024-07-26/clippy-beta-powerpc-unknown-linux-gnu.tar.xz=36d05ba29927b56e0d815dd09b39a3db12b6395e9717e653c20449fa83aa636f -dist/2024-07-26/clippy-beta-powerpc64-unknown-linux-gnu.tar.gz=d53fb59c723a2e76f1716cf1c82aacd2627e1694aebf70511c24529a4fe1ee99 -dist/2024-07-26/clippy-beta-powerpc64-unknown-linux-gnu.tar.xz=ffec66667d95cabc893cc87988218552eba8930f031419612f80144dcf2cc881 -dist/2024-07-26/clippy-beta-powerpc64le-unknown-linux-gnu.tar.gz=a2cd11651304ecf5ce6a1ee5fdd1acbfd36b1dbd2680cd76f2b9d3a86012b837 -dist/2024-07-26/clippy-beta-powerpc64le-unknown-linux-gnu.tar.xz=c8a8d9fe8badb1e06811412a15ce9cdfef07ecc59bf83cd578b33889751bb560 -dist/2024-07-26/clippy-beta-riscv64gc-unknown-linux-gnu.tar.gz=01ba50dae501edf3afa60aab59d8d81ccfd91126ded4cf7d45f7c4b13fb8c4aa -dist/2024-07-26/clippy-beta-riscv64gc-unknown-linux-gnu.tar.xz=a7e749bc581f9c64137a00dd891c4abff0d7f5684d2d501aad20ed1b01d9a312 -dist/2024-07-26/clippy-beta-s390x-unknown-linux-gnu.tar.gz=f19081755c37e3dc43091b06bcdc59c82b28c6fa0a78ff02d800a25d6d9f22f2 -dist/2024-07-26/clippy-beta-s390x-unknown-linux-gnu.tar.xz=d5f222e23f4f0ed4929e11684bc7b861c29fa183fffba0dbbfd5739b921f5234 -dist/2024-07-26/clippy-beta-x86_64-apple-darwin.tar.gz=edd631b7938dae6bb6c2694df0dab3ff6670e1a5ab3b5f0e6ce5bd7e992b6310 -dist/2024-07-26/clippy-beta-x86_64-apple-darwin.tar.xz=e4bc44ff13cfdd70f94c5efe86e93de041599e570c19611141c00700a656b40c -dist/2024-07-26/clippy-beta-x86_64-pc-windows-gnu.tar.gz=1b1aff83773de4dd972734cb03209eccfc3793f442a1a5dea51f451ca34cd1cc -dist/2024-07-26/clippy-beta-x86_64-pc-windows-gnu.tar.xz=71c357ff694cd954314c47e3bd458465453c65e6022799827b8560ecae16fdc8 -dist/2024-07-26/clippy-beta-x86_64-pc-windows-msvc.tar.gz=d4759993b9659ad8354d3fdf858cf99efebdf8202442505e11b55d24a54b31a0 -dist/2024-07-26/clippy-beta-x86_64-pc-windows-msvc.tar.xz=e29eaea7b7f2e54b9285a2216f5b85440313650090c268048ce9e830e007fa92 -dist/2024-07-26/clippy-beta-x86_64-unknown-freebsd.tar.gz=4009c19d557156e63ad7123d27264650d046cd20e723ec6cc8ffdb3fc1d3b8b1 -dist/2024-07-26/clippy-beta-x86_64-unknown-freebsd.tar.xz=9622117651423c53c35f69cb3087a5294cca098ac93aeb7c18bcab035a1e69ef -dist/2024-07-26/clippy-beta-x86_64-unknown-illumos.tar.gz=a88fd4b3e30faaecf270936422e254a25ff5dba93b08ca4003a9978ee80d0838 -dist/2024-07-26/clippy-beta-x86_64-unknown-illumos.tar.xz=f391b26009b7089f3d49d2f3409bb4e02e3de0700284727d2d26e7062bb18011 -dist/2024-07-26/clippy-beta-x86_64-unknown-linux-gnu.tar.gz=e467501c65651d519ae9a489e821e7d5dc82fdbeb2da2d4c75f093e1b898abd6 -dist/2024-07-26/clippy-beta-x86_64-unknown-linux-gnu.tar.xz=9dcbd07899af86db3c101275ab0f2fd3b5b0c43d4a92c5b5be05f0e4500d7535 -dist/2024-07-26/clippy-beta-x86_64-unknown-linux-musl.tar.gz=c2a30c78a6ab64d1655651fdd5c7f970dadcd6dfd1a585d130bd890190fe67f6 -dist/2024-07-26/clippy-beta-x86_64-unknown-linux-musl.tar.xz=05c2a38fa5bca162e365218670a7c195ebd9b3491d14464282a273dfe93b0ad7 -dist/2024-07-26/clippy-beta-x86_64-unknown-netbsd.tar.gz=75ee727a80119a810193519535f962721d547297feb9b5597b397e59277de701 -dist/2024-07-26/clippy-beta-x86_64-unknown-netbsd.tar.xz=002b726868a14df5ea31fe8eb75fae24660fb1cfad73591e86f9179dd1bb2dc4 -dist/2024-07-30/rustfmt-nightly-aarch64-apple-darwin.tar.gz=d3bb2f1fa20555373189caa7e58a8e3071c7ea6e7059bab15d6dd52dfef56c4f -dist/2024-07-30/rustfmt-nightly-aarch64-apple-darwin.tar.xz=ba0019eb0766dd438069988156994270959c875b010afce0f455540a0bb2ee2f -dist/2024-07-30/rustfmt-nightly-aarch64-pc-windows-msvc.tar.gz=24bbbe80a998b78f04c15d82fcef9498315b1b8d0ddabeeb5b6729b14bafbf70 -dist/2024-07-30/rustfmt-nightly-aarch64-pc-windows-msvc.tar.xz=cc396d3639c7213ab6442dc79ab6a1a42bb17910aa6d27046cc89ebeb6973231 -dist/2024-07-30/rustfmt-nightly-aarch64-unknown-linux-gnu.tar.gz=e6dc772727a20920607923ff5a99526054e6244c40cc6c97fe68db58896de6fc -dist/2024-07-30/rustfmt-nightly-aarch64-unknown-linux-gnu.tar.xz=eec95e09ec7bd64ab8a47e7311103f5bc58aa3499edcba052699686315f8441a -dist/2024-07-30/rustfmt-nightly-aarch64-unknown-linux-musl.tar.gz=fef3eb7d5dee7458daacfba9b97d579868864267fcdc85334f02384683ce0c17 -dist/2024-07-30/rustfmt-nightly-aarch64-unknown-linux-musl.tar.xz=44f376f4d9e84645373b4cbfe17678c288a71b92622ab4091ca7b82ed6a21b57 -dist/2024-07-30/rustfmt-nightly-arm-unknown-linux-gnueabi.tar.gz=5c17927f12149fa605e3f671d25ac456d1d2bdac796b5ca466bfa7fb8688d224 -dist/2024-07-30/rustfmt-nightly-arm-unknown-linux-gnueabi.tar.xz=04783b1a2efc10696b0d32fde7c63437e17548d38b2272f928f28915107f4f18 -dist/2024-07-30/rustfmt-nightly-arm-unknown-linux-gnueabihf.tar.gz=1365d93efc4391f189726e69c7a968c8debb50411f29404da42d19bc9e053937 -dist/2024-07-30/rustfmt-nightly-arm-unknown-linux-gnueabihf.tar.xz=db344c9f6d31ac5a2efc839cbb886c312534e9b1fe4b116629eaca74f79c316d -dist/2024-07-30/rustfmt-nightly-armv7-unknown-linux-gnueabihf.tar.gz=049a2b666956a56365661d944a0fc030673bec5578062ddaad104363f4ff1031 -dist/2024-07-30/rustfmt-nightly-armv7-unknown-linux-gnueabihf.tar.xz=32d3bc08316c0cfc3c1ea689ccdc80978f744864c048863b9d51ae59b6e2f0c2 -dist/2024-07-30/rustfmt-nightly-i686-pc-windows-gnu.tar.gz=bc33833cd41bf5ac36730fc9d3ef9c87643d42b8e711de286138962fb5fac4a5 -dist/2024-07-30/rustfmt-nightly-i686-pc-windows-gnu.tar.xz=feffb4527ad627a0239d788272edac9a0fbec704de3a67aabbd8a9cbb95d4fe3 -dist/2024-07-30/rustfmt-nightly-i686-pc-windows-msvc.tar.gz=0ffb98b839f6640ac75e094cbb469a06f2e45f51ced01efbeb51a3fba866a048 -dist/2024-07-30/rustfmt-nightly-i686-pc-windows-msvc.tar.xz=d229ea866bf4d6c2d8d748630146c7bccedb4ba5a17056fbdc4558baf976f067 -dist/2024-07-30/rustfmt-nightly-i686-unknown-linux-gnu.tar.gz=431de55efb797c75d8e440ba3da9ac70a04cccfc56b4e22b80b6488360915f90 -dist/2024-07-30/rustfmt-nightly-i686-unknown-linux-gnu.tar.xz=e9e4eac4205014b6b61c759a8326f7a5e44e8ff05726510a8bbefd656f78e97c -dist/2024-07-30/rustfmt-nightly-loongarch64-unknown-linux-gnu.tar.gz=99381507f8fc42d9bd00c545dd7ef4734e364a4e994d02bae148f78b94f50ab5 -dist/2024-07-30/rustfmt-nightly-loongarch64-unknown-linux-gnu.tar.xz=6e2cd283d9370beb9c208bd823ac2433df500adf7e70d8acfe5a261e62be2b4a -dist/2024-07-30/rustfmt-nightly-loongarch64-unknown-linux-musl.tar.gz=761a9733f53ecba343139bd1c028a66242824ef8f7c54ae63e0aaf0e77cabcf9 -dist/2024-07-30/rustfmt-nightly-loongarch64-unknown-linux-musl.tar.xz=c2973a99220588ea78b7a052861c345f01254073d6bb77e96982b12382907e2b -dist/2024-07-30/rustfmt-nightly-powerpc-unknown-linux-gnu.tar.gz=4288ee8fc5f650b3d5c24be2ea114e133d3bad8ddf7e2211cdb72151410c755a -dist/2024-07-30/rustfmt-nightly-powerpc-unknown-linux-gnu.tar.xz=2a31e1f211a26f6798acd4c779827bfa4e1ac4d77103a48be74617e5af1661a1 -dist/2024-07-30/rustfmt-nightly-powerpc64-unknown-linux-gnu.tar.gz=9598edeb1ff5eff934f1e4783b3ed263babb53d3513564ccccf453dada872ba1 -dist/2024-07-30/rustfmt-nightly-powerpc64-unknown-linux-gnu.tar.xz=eb5392fce8ee4a016406efba546366ff91d4db8cda94dd131dbda70c553b6c06 -dist/2024-07-30/rustfmt-nightly-powerpc64le-unknown-linux-gnu.tar.gz=0e9c55ee790eed653eda7b913e64d344ccbbe1681321377186d1e4882dc93bfc -dist/2024-07-30/rustfmt-nightly-powerpc64le-unknown-linux-gnu.tar.xz=c9a0b3eddac707c4e0c1cdc754d2821845e5f4bdcbd001b71d7287fe851cc44b -dist/2024-07-30/rustfmt-nightly-riscv64gc-unknown-linux-gnu.tar.gz=99c264f806d4a6a1288a9cc7f28e178102520ebe4728fb0da3f8142c1d6720e0 -dist/2024-07-30/rustfmt-nightly-riscv64gc-unknown-linux-gnu.tar.xz=3f1835460dbf17a3dbf47f2772e182ebf6337fd6a946a033f9700fb38140eda6 -dist/2024-07-30/rustfmt-nightly-s390x-unknown-linux-gnu.tar.gz=385224b95c56de8598dd5b4eeb48d7d7a8eb920825c55bb4d7be54142d7e2857 -dist/2024-07-30/rustfmt-nightly-s390x-unknown-linux-gnu.tar.xz=535220608ee858d46746c8de4c1e58f4f675061517b6b06c8af47004d5291f85 -dist/2024-07-30/rustfmt-nightly-x86_64-apple-darwin.tar.gz=aa19f1856befff101bcb433049e923486d7bc1a056638e478651936572e7e3bf -dist/2024-07-30/rustfmt-nightly-x86_64-apple-darwin.tar.xz=2ed04cf9fddeafbb83d82988e00d3b7f5ae9382468ce1093cbb110bf46b04711 -dist/2024-07-30/rustfmt-nightly-x86_64-pc-windows-gnu.tar.gz=962dea60de3ac68a573f088f9c1b003816ce93f9088df15fe8cf7771a3abdc73 -dist/2024-07-30/rustfmt-nightly-x86_64-pc-windows-gnu.tar.xz=72f7b787644bd9008b13018512c0b09a425c15a337821dc9bded9ab7211c61de -dist/2024-07-30/rustfmt-nightly-x86_64-pc-windows-msvc.tar.gz=1096ba25a23461eed84804584eb9ffdff780e2c737cc9dce1e8929419dfd645b -dist/2024-07-30/rustfmt-nightly-x86_64-pc-windows-msvc.tar.xz=854b9e410e65b953ab71f356bd5b618679aa7c1f5a3de7f81ec388720ed04f60 -dist/2024-07-30/rustfmt-nightly-x86_64-unknown-freebsd.tar.gz=03b4ab410c70fee3daa7a577c311b29344158a7d35ea87627233cb6165191338 -dist/2024-07-30/rustfmt-nightly-x86_64-unknown-freebsd.tar.xz=d755700cc17416c4488db2d582250b5ec329fc0c2b94e9db0e6688ca30a7316c -dist/2024-07-30/rustfmt-nightly-x86_64-unknown-illumos.tar.gz=b7448089c61c2f0a427416cd7521130c31a98c52e435bd0d04d6aad72d765ba6 -dist/2024-07-30/rustfmt-nightly-x86_64-unknown-illumos.tar.xz=cb3f479897032ff9ec5e06913e8e4374ce46af7f8a9030299c7b0cab2dab2005 -dist/2024-07-30/rustfmt-nightly-x86_64-unknown-linux-gnu.tar.gz=0c7dbff79d04218a7ba3f5992f67d25043bc5f348038f37ab7385cbc4d0df00d -dist/2024-07-30/rustfmt-nightly-x86_64-unknown-linux-gnu.tar.xz=4f62cbc75a81d57748111a915ebb20f561f403c1b695141780d50c398b186fa6 -dist/2024-07-30/rustfmt-nightly-x86_64-unknown-linux-musl.tar.gz=e5e8b07ae7ba0e1f526828a10f2515a68b0ed6023eed25e3bb10b80e21e8db76 -dist/2024-07-30/rustfmt-nightly-x86_64-unknown-linux-musl.tar.xz=424ec90c59fca7e21b302efd7c6c7f7dbc5dcadd1afbb15e90efea38ea8a19cf -dist/2024-07-30/rustfmt-nightly-x86_64-unknown-netbsd.tar.gz=f22576893113958f6caabcf3ab3e38287fea010c1809a8bb1197220d6660ea4e -dist/2024-07-30/rustfmt-nightly-x86_64-unknown-netbsd.tar.xz=5e85141abe2a3c537cb4171c60cff5bdb11f075aa79212e0a958081d4648aec6 -dist/2024-07-30/rustc-nightly-aarch64-apple-darwin.tar.gz=f793e4645be9461fae09e82710bcfdfc6d749735be202f2e2cd6c2c643bb8925 -dist/2024-07-30/rustc-nightly-aarch64-apple-darwin.tar.xz=e42f52cc5a865ab92321b97aaeff4d39cbaad1a5b60a9a77de9f42e3b3231d21 -dist/2024-07-30/rustc-nightly-aarch64-pc-windows-msvc.tar.gz=0258ba5bf957d190ef3a384c5451ebbe8406c195a29b3a7ee2a4c48e0514f203 -dist/2024-07-30/rustc-nightly-aarch64-pc-windows-msvc.tar.xz=788b7e9239562f43c0d96cfd66f543604eef1c9b40d22898c456fade608e9c31 -dist/2024-07-30/rustc-nightly-aarch64-unknown-linux-gnu.tar.gz=94187df22d7b96a5c39c5c9a078f566b80d392abfd2a5d7059b836cfa0c446e1 -dist/2024-07-30/rustc-nightly-aarch64-unknown-linux-gnu.tar.xz=ca1381c6de1a96f32a30736c28aa196f7e653b4f57f01ffe2db52fe238a9f202 -dist/2024-07-30/rustc-nightly-aarch64-unknown-linux-musl.tar.gz=1c72596862a133003f68590a8ae09bf6ab25a5f9667a6d245eafede1ebd8f450 -dist/2024-07-30/rustc-nightly-aarch64-unknown-linux-musl.tar.xz=de0c216f229301bc88690b10b8f063b8e389915503980973b91bfe17b1fb6eda -dist/2024-07-30/rustc-nightly-arm-unknown-linux-gnueabi.tar.gz=e00283a7ee9a702446456feb0156f1d1fc738fd013983f15c456fcafb8294309 -dist/2024-07-30/rustc-nightly-arm-unknown-linux-gnueabi.tar.xz=03fab128bc3756676c645f637edc5051f8096b00780d8ef4de7a85b3f248933a -dist/2024-07-30/rustc-nightly-arm-unknown-linux-gnueabihf.tar.gz=105e06c0ca69b4a700980f2a588f831c23a9a9253268bd652110328b99918cb1 -dist/2024-07-30/rustc-nightly-arm-unknown-linux-gnueabihf.tar.xz=0da27ffe5504a03923ae5858b69cdd6eb276e6bd2bfb504bcf13ebdda654316b -dist/2024-07-30/rustc-nightly-armv7-unknown-linux-gnueabihf.tar.gz=edb1bec402f3799e05fd3e31f30763e7266d2e062e410af8eab7636440da272c -dist/2024-07-30/rustc-nightly-armv7-unknown-linux-gnueabihf.tar.xz=638a09ecfe0b66391ce6802e3e15bf15462aca1c8cfb2a49b948ec69eda0575c -dist/2024-07-30/rustc-nightly-i686-pc-windows-gnu.tar.gz=456683fa10703ba8249f8b1735293c79edac0c32aec60c1a91315fb41c8e5ecc -dist/2024-07-30/rustc-nightly-i686-pc-windows-gnu.tar.xz=fd5d9a7bf543d3c61ca85340961d5e17b42b37c35fe45c666c2a0e125548f42e -dist/2024-07-30/rustc-nightly-i686-pc-windows-msvc.tar.gz=2b75a4e15d1f98f123ef74aecab3570296aeb7e35f18548a2b3d1735e01b06e0 -dist/2024-07-30/rustc-nightly-i686-pc-windows-msvc.tar.xz=1163178e95180725bd31b7dabf1e9a9788a8e7cc576dd53148cfec32443e64a1 -dist/2024-07-30/rustc-nightly-i686-unknown-linux-gnu.tar.gz=0aad8dd79beca26278e1c1847dde17ee22ae64b78f2b02be65e12bc126de699b -dist/2024-07-30/rustc-nightly-i686-unknown-linux-gnu.tar.xz=a548e90fbce90c26b6700cff7964d72c7e959a6f317e891db4f91ce7cd187c41 -dist/2024-07-30/rustc-nightly-loongarch64-unknown-linux-gnu.tar.gz=654ec9040afb20d660603adcd31824efeacef0ae2d48d342bb9504bd2f723453 -dist/2024-07-30/rustc-nightly-loongarch64-unknown-linux-gnu.tar.xz=998407bc1303eecb1ef4c6b14862ffdf31fb0cf991f5d169a822a23627b29352 -dist/2024-07-30/rustc-nightly-loongarch64-unknown-linux-musl.tar.gz=5b4febf9a1802c2c756ef8a7693a9cfd83bf95284d79d9f9b9dd265234d6aebc -dist/2024-07-30/rustc-nightly-loongarch64-unknown-linux-musl.tar.xz=dbc2a6417fabcfb37f4fa42d50391c1cb29f18d1771321088c08afdf0a0e4809 -dist/2024-07-30/rustc-nightly-powerpc-unknown-linux-gnu.tar.gz=2befcab4aa3e31064b87e4696aa2f1e76bd9c24067eb1921feb7f6497d58338c -dist/2024-07-30/rustc-nightly-powerpc-unknown-linux-gnu.tar.xz=508a3c1241507a53a0d6b27df2171eaf0a4df903773b5592f005ee4d39d91287 -dist/2024-07-30/rustc-nightly-powerpc64-unknown-linux-gnu.tar.gz=c4e8da248306be350f7a89b2522e976a12ab89d5ae2e19157ed3b148e3948c50 -dist/2024-07-30/rustc-nightly-powerpc64-unknown-linux-gnu.tar.xz=5858e1cf6371f25ba3c381e07ba6f4551c2a13516011fc10dbdafc4caf1bff93 -dist/2024-07-30/rustc-nightly-powerpc64le-unknown-linux-gnu.tar.gz=3639bbb7aac353772171dcfaecd589352de3fd8cc7395e7628d7590830034af4 -dist/2024-07-30/rustc-nightly-powerpc64le-unknown-linux-gnu.tar.xz=3cad5f0b74fc3f5be70cf496c93054c50e8a3f92cfc894a2febfbecc382dcb55 -dist/2024-07-30/rustc-nightly-riscv64gc-unknown-linux-gnu.tar.gz=437fc8b815c09a3c5159735d9fec0e5d8dd64416149cb77c13a16863e6636412 -dist/2024-07-30/rustc-nightly-riscv64gc-unknown-linux-gnu.tar.xz=7bc2917e7816f7df1bc7faeda28010d247c923aba412b5ec1cc9c6757eec37d9 -dist/2024-07-30/rustc-nightly-s390x-unknown-linux-gnu.tar.gz=603e391a14c26a51f4f02020b5abbd307d29476fdc0689e5bf9570f2e6ac69a8 -dist/2024-07-30/rustc-nightly-s390x-unknown-linux-gnu.tar.xz=d04ea4e522cf1ecaa6b2f3edcb32155142378bc648aa159a574838ed2d58b794 -dist/2024-07-30/rustc-nightly-x86_64-apple-darwin.tar.gz=0ed639da01e58645eb33a75e020d57c58c92651d817e89574cb67bae5b298d35 -dist/2024-07-30/rustc-nightly-x86_64-apple-darwin.tar.xz=b4010f38396e7b8acd67cf2234c94ede11cf78a226a134c809d504e594037311 -dist/2024-07-30/rustc-nightly-x86_64-pc-windows-gnu.tar.gz=7ec8aba7a7581d59c7ceaffdd374852d08b17bc7e02674c5bfd4f47f4a0aee39 -dist/2024-07-30/rustc-nightly-x86_64-pc-windows-gnu.tar.xz=41c3ba0543220e11bc53282dd7d2a37acd6450a59683e1c83d2150dc798cfba7 -dist/2024-07-30/rustc-nightly-x86_64-pc-windows-msvc.tar.gz=67e5d75dda47c587a4be517db547354d1da0228110b7d5488d8822a7ef7cda20 -dist/2024-07-30/rustc-nightly-x86_64-pc-windows-msvc.tar.xz=4b5f0c4101a783dd313c0cd1435d7eccfeac97452afaeaf42ba975805541dc74 -dist/2024-07-30/rustc-nightly-x86_64-unknown-freebsd.tar.gz=09e12b5003969b768b5c06b3e3b41a64429e28c32790ff28c12b8c5814f350c0 -dist/2024-07-30/rustc-nightly-x86_64-unknown-freebsd.tar.xz=a4b3b402cf4beb3e7c7b9b6620f34d045ef42261514ae7d8483d3790d1dfd88a -dist/2024-07-30/rustc-nightly-x86_64-unknown-illumos.tar.gz=c344d0c95aadac0e5e0100743b80768c9d0cd76b123ab07e6387ad1ea3e3efba -dist/2024-07-30/rustc-nightly-x86_64-unknown-illumos.tar.xz=ac0a79660227fe163c796e6b816596299f6d8b32ba008ce30cde492709efb7c0 -dist/2024-07-30/rustc-nightly-x86_64-unknown-linux-gnu.tar.gz=4090ff8086317662d3def1bc92d51e6f2decd2c64f4b6ede38604fd5029d3d02 -dist/2024-07-30/rustc-nightly-x86_64-unknown-linux-gnu.tar.xz=e665bd4e3763b456576eaa45bcf188648cc6e6443ecdff8ef91a5c7649cbfd25 -dist/2024-07-30/rustc-nightly-x86_64-unknown-linux-musl.tar.gz=4fa994e08274599ae3bceb9310c584be89d11f231aad3e8fc1e2d6a6ddbb77bf -dist/2024-07-30/rustc-nightly-x86_64-unknown-linux-musl.tar.xz=bd8d53403bf6337782bffc3050a46887fbe2568c850809c5b32c8d84492d2ee9 -dist/2024-07-30/rustc-nightly-x86_64-unknown-netbsd.tar.gz=606a430036fdda0b92dd4a4cb99830881389693e6ed02a01ddd51eaecdfdf463 -dist/2024-07-30/rustc-nightly-x86_64-unknown-netbsd.tar.xz=fa34273b20336b8b373f686c88ee297033f635895ad225a2ca5271b6da3d7dea \ No newline at end of file +dist/2024-09-04/rustc-beta-aarch64-apple-darwin.tar.gz=cb6487c102a7c5822be2236d79a2c4737b0ff284931c61607518a0de8d300abf +dist/2024-09-04/rustc-beta-aarch64-apple-darwin.tar.xz=2556c7c07811195e94639f6d6556a0f49f3c267e0e3bfc44b1fdc555aac1ffe5 +dist/2024-09-04/rustc-beta-aarch64-pc-windows-msvc.tar.gz=c207a307bf10a50e2884f4d9408528a22703e1010dd921459541ee11aecc2405 +dist/2024-09-04/rustc-beta-aarch64-pc-windows-msvc.tar.xz=d6f99991029db32be7527dbe1a6ae840600db6d7497123156e6672f7a0e83aa2 +dist/2024-09-04/rustc-beta-aarch64-unknown-linux-gnu.tar.gz=b57cb4d25045e23f897078216776f244a73498ea89240077bda7a84c31c2f4fe +dist/2024-09-04/rustc-beta-aarch64-unknown-linux-gnu.tar.xz=2c2b95c852114d7b18c3db13234ac56f933b70c3cf8b5ac9fce65415434961fe +dist/2024-09-04/rustc-beta-aarch64-unknown-linux-musl.tar.gz=1f216d67bcd5d1e011bd2c6c69b6791c94e29cf7da3ab7dea82ff71a911e149b +dist/2024-09-04/rustc-beta-aarch64-unknown-linux-musl.tar.xz=86abb27afb03e347abff65e4e34f1ec2e943af14f04f8cd9dd8666338147562d +dist/2024-09-04/rustc-beta-arm-unknown-linux-gnueabi.tar.gz=842754febca1a5c6f7ccacf231621ba4578d72718a950ddedbf07a73594fa55f +dist/2024-09-04/rustc-beta-arm-unknown-linux-gnueabi.tar.xz=3094887ecd5e3432e1ada0bba4a425213215c50680dc30d0c1d15ffda5bc62a0 +dist/2024-09-04/rustc-beta-arm-unknown-linux-gnueabihf.tar.gz=27192e3423f2b580d7927ae788cf778ff9c092e2eb7cdd5d16b41aa94d2bf03c +dist/2024-09-04/rustc-beta-arm-unknown-linux-gnueabihf.tar.xz=e57767bd767964d51533e2310f177827842bf49176895280b3de3860caf351ab +dist/2024-09-04/rustc-beta-armv7-unknown-linux-gnueabihf.tar.gz=b639bfce72277714769d36efab294ef3578573b93037160be7dff9f4a6e6b5ef +dist/2024-09-04/rustc-beta-armv7-unknown-linux-gnueabihf.tar.xz=fce2b931641d51e88eb3e34d60bebe75384c1981654937b16f1333438d8b0696 +dist/2024-09-04/rustc-beta-i686-pc-windows-gnu.tar.gz=b58f7013b41044260ab2f9456940d9ce017dcfea06059fae8a672664f8ba00df +dist/2024-09-04/rustc-beta-i686-pc-windows-gnu.tar.xz=c91958645f3c4cd562a5eb800ddb843aabfa2f067f5659313fdedeb270935bf8 +dist/2024-09-04/rustc-beta-i686-pc-windows-msvc.tar.gz=9a5075768fe2d42195c639d8c1066a020b573eae24c0c63e9a8876b78c39d673 +dist/2024-09-04/rustc-beta-i686-pc-windows-msvc.tar.xz=e76c27a8892a5b7a74c4d18d10c745af226711dbf62450378a3034a706624ce1 +dist/2024-09-04/rustc-beta-i686-unknown-linux-gnu.tar.gz=c10ffb2db62b113af1feab8625f1d88d31c1d4a4246d00e19a3588c9f69c0164 +dist/2024-09-04/rustc-beta-i686-unknown-linux-gnu.tar.xz=0496fbfa32d6c22929fe94ae5dcaabc47d31d7482f0fe6748ef7b7eb7443b775 +dist/2024-09-04/rustc-beta-loongarch64-unknown-linux-gnu.tar.gz=64b55368e8044ea44588c98f1529f46d65f7607ebf2fa2d50785abecfb37c188 +dist/2024-09-04/rustc-beta-loongarch64-unknown-linux-gnu.tar.xz=e03528ee7e4e92d666199ebcdde7d10f1d0fbeb2766217fd95f98da93bc361d0 +dist/2024-09-04/rustc-beta-loongarch64-unknown-linux-musl.tar.gz=eeb913008ecfbaaa76b7690b2e68bd1e70efc1afda19f44a1aa551a76e4b536a +dist/2024-09-04/rustc-beta-loongarch64-unknown-linux-musl.tar.xz=c94c3545fa2a491763b1e593419034294c57a3df2ca8064db0b11d2e82e76c85 +dist/2024-09-04/rustc-beta-powerpc-unknown-linux-gnu.tar.gz=54c97827079aa7646cf206517f603487f4634ab1a17f2a7882b0cd3d6ffae8db +dist/2024-09-04/rustc-beta-powerpc-unknown-linux-gnu.tar.xz=ee98a0e07989de836ff8ff4e768c6f0f13aa15150d1b59543297f31b2768a5fc +dist/2024-09-04/rustc-beta-powerpc64-unknown-linux-gnu.tar.gz=a0fcd0f7af5b05a22d9be0abb6f3aa44c028c2606195163d2ad4b0352455ed1f +dist/2024-09-04/rustc-beta-powerpc64-unknown-linux-gnu.tar.xz=cf35d480a6c0b439d29baacc4ee4087c4d7b5c1b4050302f3146f0bdbffcd472 +dist/2024-09-04/rustc-beta-powerpc64le-unknown-linux-gnu.tar.gz=ef19ce4d791b1caad30bc5af9e30494161f343d936a3300eb0d7c5e8f37db441 +dist/2024-09-04/rustc-beta-powerpc64le-unknown-linux-gnu.tar.xz=12adfd58c851d1f7bb23c5698abf6dffa2c26348df55fbb518c27497f7ebdf17 +dist/2024-09-04/rustc-beta-riscv64gc-unknown-linux-gnu.tar.gz=818151529f1e445f9202d0092f09f02818a2c52ad6814a89b2bbfcb0227c5202 +dist/2024-09-04/rustc-beta-riscv64gc-unknown-linux-gnu.tar.xz=e195d07d37699d860ce97422bba7f68166292103cedf4932b3ba8c0d9fa7e186 +dist/2024-09-04/rustc-beta-s390x-unknown-linux-gnu.tar.gz=d4a73ddd7eafdffe7f23720a7202f48676ae0bc49248d3a455c997d718730c5f +dist/2024-09-04/rustc-beta-s390x-unknown-linux-gnu.tar.xz=475bb6e51f37fc769480345982e14afeee099cdf769773d0d0215d01fc77ce41 +dist/2024-09-04/rustc-beta-x86_64-apple-darwin.tar.gz=c061d06da7d4a283136d8e80f307c1ef4157739898776f5579b8d92980be0775 +dist/2024-09-04/rustc-beta-x86_64-apple-darwin.tar.xz=330b580c90ace563c96db64f639668284d8ede835870acf76b106d4c4913f476 +dist/2024-09-04/rustc-beta-x86_64-pc-windows-gnu.tar.gz=27f9e3c2e9380c689ab0c5e8438f1969261a30445e9b2d38efa9417fba1f4ea2 +dist/2024-09-04/rustc-beta-x86_64-pc-windows-gnu.tar.xz=62fc92dac7be442dcf306ae1baef471447b80a6a221502bf7b14b249dd599db7 +dist/2024-09-04/rustc-beta-x86_64-pc-windows-msvc.tar.gz=c52202bf41aafb517959e01cac2e4bbb53144aa0164f9b31e7b9db0af32be6c6 +dist/2024-09-04/rustc-beta-x86_64-pc-windows-msvc.tar.xz=24db84f0de7573812fe36fed5653fc117c80fc35b02a9340f746ded6a11d3bc0 +dist/2024-09-04/rustc-beta-x86_64-unknown-freebsd.tar.gz=406f8a37572376fec7563664043b4fc3b0e7a48c738b6ef862da3fc41f33b1d3 +dist/2024-09-04/rustc-beta-x86_64-unknown-freebsd.tar.xz=93fa021ca3973a52cbccd51771536e2b9a355eae4f4ab95c7168f4af79e96d4e +dist/2024-09-04/rustc-beta-x86_64-unknown-illumos.tar.gz=a2a5942342b2f5dc7a196500210075ac695f106a18fd487a3c694847013454f3 +dist/2024-09-04/rustc-beta-x86_64-unknown-illumos.tar.xz=c8b63f35f30bb1d6adb49834b3a42dfc07c27042e8411f1b4777adced6193298 +dist/2024-09-04/rustc-beta-x86_64-unknown-linux-gnu.tar.gz=145c5d6e0edb688dbe59f9c638959e11718e0bdc625db76bac1d2836efd9f116 +dist/2024-09-04/rustc-beta-x86_64-unknown-linux-gnu.tar.xz=82845313e17067dac361eada63fdf2479fc177e8aa97aba5cb40a50861e276bc +dist/2024-09-04/rustc-beta-x86_64-unknown-linux-musl.tar.gz=8351011105a5a338adbd2433ff5aa24cd038a67c0f0d040e4b92926d4aecd28e +dist/2024-09-04/rustc-beta-x86_64-unknown-linux-musl.tar.xz=b2a972069142d5fdab775fd7709d4bc85b1c2c4167e9c455d2ef1b72cc207fd1 +dist/2024-09-04/rustc-beta-x86_64-unknown-netbsd.tar.gz=327501931ce36eb5613e5e77fb5356ff24f60078516473cd7f664bc970aee994 +dist/2024-09-04/rustc-beta-x86_64-unknown-netbsd.tar.xz=6d940ec725fa4931c914c291977f63828fe71e9763a3b8195dda668541c9122f +dist/2024-09-04/rust-std-beta-aarch64-apple-darwin.tar.gz=9bf325e98fa60fcb7d4f09b796f2fe0e7e7c54e83ffba6d5cf30776a0346972d +dist/2024-09-04/rust-std-beta-aarch64-apple-darwin.tar.xz=45d632045f5e3f8150d82fdc5163aea1d5ad785cd16da2d46293581b09bda895 +dist/2024-09-04/rust-std-beta-aarch64-apple-ios.tar.gz=c42f808164d79e023dc4186e47a6032c0877536a0c9459f3e871c66c129b0f75 +dist/2024-09-04/rust-std-beta-aarch64-apple-ios.tar.xz=9bbe6ae21530fb0555472f9a540b7791d5dce059439608d797507057199e696e +dist/2024-09-04/rust-std-beta-aarch64-apple-ios-macabi.tar.gz=ae8005ea419f9f19be0c2603529d8801dc77e5344c72c1bd42eed81046fe5113 +dist/2024-09-04/rust-std-beta-aarch64-apple-ios-macabi.tar.xz=0053948699aba18b2bee7473f335940573aaf4bad6aabb00f28f2a335d280dab +dist/2024-09-04/rust-std-beta-aarch64-apple-ios-sim.tar.gz=5adc7721f8f7fc0537b11a28ee2df6d90b96222a07590c84fab4dbefe33087d1 +dist/2024-09-04/rust-std-beta-aarch64-apple-ios-sim.tar.xz=4f3a9b61500ef3a38961288784c61a520baabfa597e997195007e0e229d1e4bf +dist/2024-09-04/rust-std-beta-aarch64-linux-android.tar.gz=7192a628d6605b437a7203c18d48ac9a5af4879674117e9aebafb5029a10e069 +dist/2024-09-04/rust-std-beta-aarch64-linux-android.tar.xz=845177bda3220a534b20c66cda3bf27b0681c2977dfbcedeaf41022bc518f832 +dist/2024-09-04/rust-std-beta-aarch64-pc-windows-gnullvm.tar.gz=1a0ced7e1fbcdd38fcb33f1753f3af8b23f075d4ce38c3d1256ba142ddf80a47 +dist/2024-09-04/rust-std-beta-aarch64-pc-windows-gnullvm.tar.xz=75272f629adfaacb58c511163ae9b73714fe3f60d5e39b4cd996a42226626518 +dist/2024-09-04/rust-std-beta-aarch64-pc-windows-msvc.tar.gz=3b19e6dca8515f28a2325d7cf2f098e82e194d4418fce7c3caa94c9c08023646 +dist/2024-09-04/rust-std-beta-aarch64-pc-windows-msvc.tar.xz=138e8e1a85efb4f66ec878db18dfa48681f3045589c7b9a749afd0104dafd278 +dist/2024-09-04/rust-std-beta-aarch64-unknown-fuchsia.tar.gz=6da128ca58f46d2608c4d9630c09de263b853f9fe8b6fa41def0749e99a128e0 +dist/2024-09-04/rust-std-beta-aarch64-unknown-fuchsia.tar.xz=67a2c04a9f4947b4c313220150521f494364c5e589ff23a4584fa60b924ae095 +dist/2024-09-04/rust-std-beta-aarch64-unknown-linux-gnu.tar.gz=85ccd5a6e81caa63d4d4cfe55eead8a3829a5636d41f7640ea393bf7652eec28 +dist/2024-09-04/rust-std-beta-aarch64-unknown-linux-gnu.tar.xz=fb91518e70808c659f6f078c0094ca471e4e4f5d81c29c1bdc8907f6bdffc64f +dist/2024-09-04/rust-std-beta-aarch64-unknown-linux-musl.tar.gz=410b24f1372f84d60804b4bcf20fa2025adaee3c56ab7dabda1e320809acafdb +dist/2024-09-04/rust-std-beta-aarch64-unknown-linux-musl.tar.xz=64d7fa38af8a1c38e42bc9b9ab909f476d3388b7d02a21ba92519145cb3a3df8 +dist/2024-09-04/rust-std-beta-aarch64-unknown-linux-ohos.tar.gz=f4722b2a656d4f87bd13d4c8da6116e993e916114c55a2fd1a588e51dfde4ab0 +dist/2024-09-04/rust-std-beta-aarch64-unknown-linux-ohos.tar.xz=cb9150701f21de444addcdc9a53c83eeed3aaa3bc447e8f6358825a2f889bff2 +dist/2024-09-04/rust-std-beta-aarch64-unknown-none.tar.gz=26cf0407f17db7645fc1a4051d08246f1325b17941dd5139cb69b782498aa043 +dist/2024-09-04/rust-std-beta-aarch64-unknown-none.tar.xz=9dcdfd018e2ca6f21d0689adb152917a8695c2f14c4f6a53a5b52280219c2540 +dist/2024-09-04/rust-std-beta-aarch64-unknown-none-softfloat.tar.gz=1d1e555bb8af601d8df16b80dd263391a4c0805e1203c618fb370de1911a5a17 +dist/2024-09-04/rust-std-beta-aarch64-unknown-none-softfloat.tar.xz=078d88a6d4882696b3764d10dbd10e0d756752255096690e895903cd83265c70 +dist/2024-09-04/rust-std-beta-aarch64-unknown-uefi.tar.gz=5933f618e5c99e06c8556871a85016eba58f6de1056468a1ad47823105908fba +dist/2024-09-04/rust-std-beta-aarch64-unknown-uefi.tar.xz=322f61ff7a6f6b261bbb9c592f50a39fa179c1f870d911a57b2afda7d7b2d196 +dist/2024-09-04/rust-std-beta-arm-linux-androideabi.tar.gz=e66bc47a75e12569032c81f6c950513e3fc78cf75e496e9873792b4c83f3dca1 +dist/2024-09-04/rust-std-beta-arm-linux-androideabi.tar.xz=9a84da40c9e5fb55e1ebad0dc9b724fe9d71d86bea0d2227315590f290fdce13 +dist/2024-09-04/rust-std-beta-arm-unknown-linux-gnueabi.tar.gz=3e8b535ec051eaaf63490649b1258ae64f1786abca6967bdc3eb6c6da96a4d81 +dist/2024-09-04/rust-std-beta-arm-unknown-linux-gnueabi.tar.xz=4936561a884b3b725a9b78651ea05a36da5e643be4e574416e12ba1c1e5f37d9 +dist/2024-09-04/rust-std-beta-arm-unknown-linux-gnueabihf.tar.gz=00eb51ffccdac33a39da37878104dded2c5efa01da5adf8bd932a0d9fb49d17b +dist/2024-09-04/rust-std-beta-arm-unknown-linux-gnueabihf.tar.xz=3eb187c4a6f416672a8a36997aca5f04bab9ec6aee3a0d1f4ad5a0ed950605c3 +dist/2024-09-04/rust-std-beta-arm-unknown-linux-musleabi.tar.gz=66752ad65876dad43c19973f8967a098236f2605d2aa82df5b0f040247e049c3 +dist/2024-09-04/rust-std-beta-arm-unknown-linux-musleabi.tar.xz=f508b8c7956209c87259b38bebe5576ca8a5662a4d4747941082dd39d991610e +dist/2024-09-04/rust-std-beta-arm-unknown-linux-musleabihf.tar.gz=926f2839c6627c822aa9f494e99030873987b6fca66364cc12ba468928a93b9c +dist/2024-09-04/rust-std-beta-arm-unknown-linux-musleabihf.tar.xz=e2be0999ea8df01c1029b0976861162c9c60e41a87b4097345f2c5822777ee2b +dist/2024-09-04/rust-std-beta-arm64ec-pc-windows-msvc.tar.gz=ec912c9e372cd0ae1a754305f0645580cf40f9742c4cbcc54952e613d47f595e +dist/2024-09-04/rust-std-beta-arm64ec-pc-windows-msvc.tar.xz=f86091e5d806a9b4efa388e036ee69fa63fca68feca174c6670cd04966e2725f +dist/2024-09-04/rust-std-beta-armebv7r-none-eabi.tar.gz=d51aa780c5df5b8b2e1fbbe97f79914ed083ea13528c43cca797ab8931a418d2 +dist/2024-09-04/rust-std-beta-armebv7r-none-eabi.tar.xz=19cbb2d1d8a6a3a33669da9fab7eb48f78f0682d777d2c2f188daf6d91895bc7 +dist/2024-09-04/rust-std-beta-armebv7r-none-eabihf.tar.gz=a1ae798b4eaf206510c33d5af1d4c99ed553fce89413449a5f82d5b80a2558aa +dist/2024-09-04/rust-std-beta-armebv7r-none-eabihf.tar.xz=a0cb421635b927e5b255238658c9f9f5a0b2da60e05c993ecbda35af9318d6bc +dist/2024-09-04/rust-std-beta-armv5te-unknown-linux-gnueabi.tar.gz=5f9995804004211baefab1d230089a5719bce40b632bd3380044142a89ae5f2d +dist/2024-09-04/rust-std-beta-armv5te-unknown-linux-gnueabi.tar.xz=66f410541f2f53d44b2a2931b10a229c8143d6e9caabadea2df40704aad71854 +dist/2024-09-04/rust-std-beta-armv5te-unknown-linux-musleabi.tar.gz=64b62816adc9574f6961832a4c469e1103057ed553a4c42796e3af4962dc694a +dist/2024-09-04/rust-std-beta-armv5te-unknown-linux-musleabi.tar.xz=3c0b3741af7f9b50d041dd52fe86fb4144c295632a6eba0197e77ac4ca94ab27 +dist/2024-09-04/rust-std-beta-armv7-linux-androideabi.tar.gz=aa3d37e6fc483c798a9debecf2ae7609609d0560baebb90733582b9bee15c493 +dist/2024-09-04/rust-std-beta-armv7-linux-androideabi.tar.xz=ed88cf7c141efd01eceb81b3b85e4eef38f559d8652d2fc4bf3395f4e3d2ef48 +dist/2024-09-04/rust-std-beta-armv7-unknown-linux-gnueabi.tar.gz=f8b34e2dd9bb5b2ea008bf6a69944da389d8d086a1ece57c1572c749717f4df8 +dist/2024-09-04/rust-std-beta-armv7-unknown-linux-gnueabi.tar.xz=7ae6076c42fecf7b92305af4220abd3d724d49d96def617a67db1ef298b74bb5 +dist/2024-09-04/rust-std-beta-armv7-unknown-linux-gnueabihf.tar.gz=4e13553b0288f4cd046372c080f4968a2b69bcb489f6929e98e72682b601d4cc +dist/2024-09-04/rust-std-beta-armv7-unknown-linux-gnueabihf.tar.xz=dbaeb0445cfc110d7879a23ea7c4034cebb4158cd9781d8719f51864356a15d4 +dist/2024-09-04/rust-std-beta-armv7-unknown-linux-musleabi.tar.gz=164fa06abffc38aaf81c86aeb50fde51c96d713bb78d759a6f7e668c7967bdfb +dist/2024-09-04/rust-std-beta-armv7-unknown-linux-musleabi.tar.xz=2ec4d5e339593555d02ea738ae1815e27d108fce5faeffd503308780c80a1a8d +dist/2024-09-04/rust-std-beta-armv7-unknown-linux-musleabihf.tar.gz=36a09d9287c9d89b3946dc6aea2ce846e754ca2b07b667035f62e8d00c81587c +dist/2024-09-04/rust-std-beta-armv7-unknown-linux-musleabihf.tar.xz=573316d483a27930bd1423ae8c1f2624dba141865150a41a5be317cc53fd850a +dist/2024-09-04/rust-std-beta-armv7-unknown-linux-ohos.tar.gz=487feddaa3b11ad15b544e3338f4dfeb1f5297ce5d851dec1df36eee7bc016a2 +dist/2024-09-04/rust-std-beta-armv7-unknown-linux-ohos.tar.xz=866f612bc4fce03e851eb0b370282b35b066018c2b2467d265cbdde4bcc8afbd +dist/2024-09-04/rust-std-beta-armv7a-none-eabi.tar.gz=3b2f1fefd2d97006264e5ce50839c8c22e9f6553f639e95c8bcc5bd01c54bead +dist/2024-09-04/rust-std-beta-armv7a-none-eabi.tar.xz=55294ba0b8da663399c427b57157f4a3e43b117c77e011801410a9bfb62584a0 +dist/2024-09-04/rust-std-beta-armv7r-none-eabi.tar.gz=60ef291da36a614ddfd38c8bac0519113dc1203603181ba3a581df074fb62f07 +dist/2024-09-04/rust-std-beta-armv7r-none-eabi.tar.xz=6dde05a2b3a57ae340f699f959e7032bb6e53cf7e1ea24bf1dd88766dba2dcdf +dist/2024-09-04/rust-std-beta-armv7r-none-eabihf.tar.gz=cc2ae41c8c8ee69f26eb55a033e5c6c23ec1e968aaa4c2e03357b62056176725 +dist/2024-09-04/rust-std-beta-armv7r-none-eabihf.tar.xz=dc7d1e0637369b0a32f8730a771e4b059ce45131b51beb276de8c03e153834b5 +dist/2024-09-04/rust-std-beta-i586-pc-windows-msvc.tar.gz=d6ce6f7d1412c1e0ec60a09c9db3d9bcbd0075617dd1756fa82e93d3df0ef8e4 +dist/2024-09-04/rust-std-beta-i586-pc-windows-msvc.tar.xz=60ff61cf60ac63a6c1ce3c6558351e873968ea1f812afdc7516ae5d19d85e54e +dist/2024-09-04/rust-std-beta-i586-unknown-linux-gnu.tar.gz=4f5204d8d51ecbf0768419076c94dde6e0c776a9403e3e108866eec3faa68d06 +dist/2024-09-04/rust-std-beta-i586-unknown-linux-gnu.tar.xz=3ba0815668b11d682a54bfc4731aca5f7a821d77ab8ac32f9922bf9d684d72b4 +dist/2024-09-04/rust-std-beta-i586-unknown-linux-musl.tar.gz=ac1094f3e22829c4e3e27a91dae48f84ab2bca4373a6e851bdee807887e145ab +dist/2024-09-04/rust-std-beta-i586-unknown-linux-musl.tar.xz=6547347750eefb619ac15256a3e1ef09c3ee633d73b23aae239cfcf4261f0d16 +dist/2024-09-04/rust-std-beta-i686-linux-android.tar.gz=af1e7557a1008392a0c2eee4f9e6b26ca56b21be2838ff4a4e3784363b1c3423 +dist/2024-09-04/rust-std-beta-i686-linux-android.tar.xz=b5d395b1c6994447b3358058aaf2219f952cb9fe6d5df0d8a533b9c2ed84134c +dist/2024-09-04/rust-std-beta-i686-pc-windows-gnu.tar.gz=a0c0535feb405bf313035cdbc690fd80c18e1975ef0da2fcaeaeab66eb8ee461 +dist/2024-09-04/rust-std-beta-i686-pc-windows-gnu.tar.xz=85b08876c40d2bc1b44bf7d64319d1dae3af2dbd75cf3e3f37b3ea20bd21209c +dist/2024-09-04/rust-std-beta-i686-pc-windows-gnullvm.tar.gz=60c37fb7de68381a3665728eb6a74ea017d81e2dcae11acf683cebcef7267487 +dist/2024-09-04/rust-std-beta-i686-pc-windows-gnullvm.tar.xz=a97edc7de6792da17dbcb6b5a67da4aa79784921c2b160185b2c8a806bd4945b +dist/2024-09-04/rust-std-beta-i686-pc-windows-msvc.tar.gz=ea25bfabaad2bc02b0d37672bdf9357f317fd27031ef6039460e25c066917b11 +dist/2024-09-04/rust-std-beta-i686-pc-windows-msvc.tar.xz=ef65a47d79945d6375347c9889c3ec3250d4635e1918689cc1f992b7daf4f547 +dist/2024-09-04/rust-std-beta-i686-unknown-freebsd.tar.gz=5c4ca0b3bca99fc468bc7ada8ef1d202e9be8ba9808298485654ceab545538e8 +dist/2024-09-04/rust-std-beta-i686-unknown-freebsd.tar.xz=59ffa74e46e807cacd4ea0a1b16ce0ec7152c4458ad9f86feea82162b1c53da6 +dist/2024-09-04/rust-std-beta-i686-unknown-linux-gnu.tar.gz=dc535c0b1fe81cc6d1bbd8fecbc0625cb85c44a6f10dd8641fb8ae88083febc5 +dist/2024-09-04/rust-std-beta-i686-unknown-linux-gnu.tar.xz=624ce72e0b60a7b0d9a06b6925fd0e9a3bd50d9d7ed59db4a16145ff5381c232 +dist/2024-09-04/rust-std-beta-i686-unknown-linux-musl.tar.gz=6d43cf9f2dc34205616b17eafa8bf28f951de538e6d80ab4993d9b840b72ba49 +dist/2024-09-04/rust-std-beta-i686-unknown-linux-musl.tar.xz=b397f611d609167ddf2b5699d7cfef9da9c6c78988c7ca2c32b2f81f6640eba6 +dist/2024-09-04/rust-std-beta-i686-unknown-uefi.tar.gz=878584e638e92902521231a4b578ae1828d1e06093104b6ceca9a22a6c05939d +dist/2024-09-04/rust-std-beta-i686-unknown-uefi.tar.xz=2806b9124d6145b65bfefc2e72a8ec3f745d3972904b7a2546bcaf649028a332 +dist/2024-09-04/rust-std-beta-loongarch64-unknown-linux-gnu.tar.gz=eb2792e0b57b36ed03762eff460bfbb7d8b28aaa309702e7e6414eba0a7d0e63 +dist/2024-09-04/rust-std-beta-loongarch64-unknown-linux-gnu.tar.xz=c36d7526ad190b15a41a1695be4b813d09d649395b1e91bf6dadc336333c690d +dist/2024-09-04/rust-std-beta-loongarch64-unknown-linux-musl.tar.gz=d891dc7b3c1d05a1c245076a6656f2ad33cba79073e36e8e1eb11ab0c0045cdd +dist/2024-09-04/rust-std-beta-loongarch64-unknown-linux-musl.tar.xz=6dbbd097bba35b9f0465a6d6b4d19d8b4700dbeecc1b0919aa99c72cad564a0a +dist/2024-09-04/rust-std-beta-loongarch64-unknown-none.tar.gz=54da489ea59169e39b50d0be0221e20cf03bdad413854e0f35f66c323bf4e88e +dist/2024-09-04/rust-std-beta-loongarch64-unknown-none.tar.xz=4c360c531107de92b695dd389514dc0af053a04d28c566a06a25e467d5ab548f +dist/2024-09-04/rust-std-beta-loongarch64-unknown-none-softfloat.tar.gz=7ce834710452cb0569cdd234698f647db87e774d3e964493e17017a81a417aba +dist/2024-09-04/rust-std-beta-loongarch64-unknown-none-softfloat.tar.xz=3e554450f5107e02335fa14fc7c7a2a3d4718741001f0f4e43984a3c0841ddf4 +dist/2024-09-04/rust-std-beta-nvptx64-nvidia-cuda.tar.gz=e8c8607e58379162fe0ec072bd544c97d73619df88eb56aeccdf2ebd5357f1b3 +dist/2024-09-04/rust-std-beta-nvptx64-nvidia-cuda.tar.xz=1dd759c92e6c1f67d5b697e1034b4962434a17211383741d0cc71acda9fcf209 +dist/2024-09-04/rust-std-beta-powerpc-unknown-linux-gnu.tar.gz=83907d49dd4cf4f73c1295571400c9761bae7a3b2447c140a358a07710e28f93 +dist/2024-09-04/rust-std-beta-powerpc-unknown-linux-gnu.tar.xz=f1ec605497fb3d7d364f2dfb7bc5c4898940518c1712b0271372ee608d61fd34 +dist/2024-09-04/rust-std-beta-powerpc64-unknown-linux-gnu.tar.gz=ac2b94c0f76c1f23be43880c01aab0a45d47e48a6c53b5dcfcf4e9507aa481e9 +dist/2024-09-04/rust-std-beta-powerpc64-unknown-linux-gnu.tar.xz=129ff2031d8ae69c34e944516bb47e093a2f2b47972bd401337fc1dc8b0f2b93 +dist/2024-09-04/rust-std-beta-powerpc64le-unknown-linux-gnu.tar.gz=2dd17129ca857bfa97d8ae3429984f80a116cc9f967809b7e5bdcc5845398a30 +dist/2024-09-04/rust-std-beta-powerpc64le-unknown-linux-gnu.tar.xz=06426a601db3dfc60f01b03bc201d21cc6bdc9b633a564e7025518decb91fea1 +dist/2024-09-04/rust-std-beta-riscv32i-unknown-none-elf.tar.gz=80bcbeed550e6ac30e9826cb801be5206d7937d2d940fca2d40ddabec62e2111 +dist/2024-09-04/rust-std-beta-riscv32i-unknown-none-elf.tar.xz=2994ee26443be51f11e8cc6e66aa2ee38e7f9440efbe0aa6aa2c513b3fe07f33 +dist/2024-09-04/rust-std-beta-riscv32im-unknown-none-elf.tar.gz=09f2b6dd18ebff39077a252e0d4b63b3557a49fb3a4f218f50f127aa44f653ec +dist/2024-09-04/rust-std-beta-riscv32im-unknown-none-elf.tar.xz=156c0ef4be19442b8f59269815e570faa464332ccd2a8db91828eff9ab702ea7 +dist/2024-09-04/rust-std-beta-riscv32imac-unknown-none-elf.tar.gz=037ceaaf4b1356f72d16f2a6c0dfe50b1df8a82743da79262b020712ffcfb7ff +dist/2024-09-04/rust-std-beta-riscv32imac-unknown-none-elf.tar.xz=a6e6f00d5df339ac19ebe2c661a5a4ec9b648328767db864b3db1bde0b330bfe +dist/2024-09-04/rust-std-beta-riscv32imafc-unknown-none-elf.tar.gz=6da55a90ba454e77dd2c90d5d5c5ed833befab415ba65adf27d8e36645b189c0 +dist/2024-09-04/rust-std-beta-riscv32imafc-unknown-none-elf.tar.xz=9213accb8bc2b3a678c3b3cb4300015b1cc52798157e3898d99699b96bac486d +dist/2024-09-04/rust-std-beta-riscv32imc-unknown-none-elf.tar.gz=5504f5fe7b45570922f7901476b8ac1eb28e9a7643bf5ace75bb368a644a05f8 +dist/2024-09-04/rust-std-beta-riscv32imc-unknown-none-elf.tar.xz=50109eb03c075ced8ebcff0909450f173e00491efece5874b8b59ad750bfc9ad +dist/2024-09-04/rust-std-beta-riscv64gc-unknown-linux-gnu.tar.gz=1ed3d0c1066b52dd2174ed45635386ff22798de8cee92765503fbcf71463094a +dist/2024-09-04/rust-std-beta-riscv64gc-unknown-linux-gnu.tar.xz=e2b22ed31374775441c6d80da80a52bc7558a1363776363ae341e78d0abf34fb +dist/2024-09-04/rust-std-beta-riscv64gc-unknown-linux-musl.tar.gz=eff055a0e773741c4c2101791feea744c57ae95c50ad32ebec616daab1d098c8 +dist/2024-09-04/rust-std-beta-riscv64gc-unknown-linux-musl.tar.xz=680c9c2de4c7abf391d073709988593eb1daffe19876bd789a0f810f9d8d8458 +dist/2024-09-04/rust-std-beta-riscv64gc-unknown-none-elf.tar.gz=ae71d4f0789955cc883948c75aad9e492e37c206a64561705c8b7a9fec243f3e +dist/2024-09-04/rust-std-beta-riscv64gc-unknown-none-elf.tar.xz=f41ecbae85295dda2dde95653a059be1852eacc28c175d36cb82cdacbf97a5e9 +dist/2024-09-04/rust-std-beta-riscv64imac-unknown-none-elf.tar.gz=1db39d0674e227b0fcacbc9de7aea52a349f515aaa8ea595cfbd91c6138e0b4c +dist/2024-09-04/rust-std-beta-riscv64imac-unknown-none-elf.tar.xz=971c6dd1c7e3c6ab14d6d5f563edf974c87cbfd2a2028bced6e01175c8abafe6 +dist/2024-09-04/rust-std-beta-s390x-unknown-linux-gnu.tar.gz=029150a3c19afdafaff023ffd80f7aa1c2cfce7d7464339b0873a6e3da10a923 +dist/2024-09-04/rust-std-beta-s390x-unknown-linux-gnu.tar.xz=22a4612a5a7b38adb3e63ec8526444e51fe222c125c2ba51499987a3906b1cf5 +dist/2024-09-04/rust-std-beta-sparc64-unknown-linux-gnu.tar.gz=069c8fc749bc2ed94179af8e38849b83912c84cd551c4bf27f95e99def8ed0fc +dist/2024-09-04/rust-std-beta-sparc64-unknown-linux-gnu.tar.xz=5b436df8a26688cc9853f5e12735187e9924a44101e21c4e59fc3dd38778e39a +dist/2024-09-04/rust-std-beta-sparcv9-sun-solaris.tar.gz=77f6b8e4760ea43aac97ebb177223ad943fbbcc55dc3656afa400d7d1ea35787 +dist/2024-09-04/rust-std-beta-sparcv9-sun-solaris.tar.xz=d2b3e49982ccdb966f420eaba9d582108b227f1acb485f0b176762871d41ef3c +dist/2024-09-04/rust-std-beta-thumbv6m-none-eabi.tar.gz=5e511b55cc961482998cca16def2424e749cf83a46a52b235e902baf8a653cca +dist/2024-09-04/rust-std-beta-thumbv6m-none-eabi.tar.xz=8491ec0a3233b04909ad307bf679d6a012fe153eb9ae544956c8fa87a57dd55c +dist/2024-09-04/rust-std-beta-thumbv7em-none-eabi.tar.gz=9b4d4913146843b01b4b6b7d8e1230c01f764a2ae2433dbb3264bfad14d0b3c6 +dist/2024-09-04/rust-std-beta-thumbv7em-none-eabi.tar.xz=ee700f3dca7d811a230222627ecc6c22d9850151adf47c2a48fb840a079508aa +dist/2024-09-04/rust-std-beta-thumbv7em-none-eabihf.tar.gz=d54ea14641f79deb2b661e1fe9e9ff56d85189da5ced0f96c16503892c4b367a +dist/2024-09-04/rust-std-beta-thumbv7em-none-eabihf.tar.xz=cd1529c6f77a079fbf15bcf81d41b4f18a8572729975b2a3ac91e18841e93495 +dist/2024-09-04/rust-std-beta-thumbv7m-none-eabi.tar.gz=fe214540eafddf6dc65ca94f1dad3a12df9e92a157060a9c27a730d99a706b28 +dist/2024-09-04/rust-std-beta-thumbv7m-none-eabi.tar.xz=2b9b1289855f7d9520eab69bc8c4e8505857e44b1e498968e47e3e847ae5a7da +dist/2024-09-04/rust-std-beta-thumbv7neon-linux-androideabi.tar.gz=dc28759dc83a72d5c8505e90abb98ee55fb0ac53736422c95b631e063f566e5f +dist/2024-09-04/rust-std-beta-thumbv7neon-linux-androideabi.tar.xz=b25c463af699783e8df43d7ccc5d1692d97e8a1ade8322dcf0cd74246d1d94b8 +dist/2024-09-04/rust-std-beta-thumbv7neon-unknown-linux-gnueabihf.tar.gz=bb8ebf0008749bafb9cee686c7b09db4e4585178b506bc9bec6508577bc98713 +dist/2024-09-04/rust-std-beta-thumbv7neon-unknown-linux-gnueabihf.tar.xz=afb9a8ed9a5dccb0c43eb6a920c647735648a1378413ff1fae754a7e5f972b06 +dist/2024-09-04/rust-std-beta-thumbv8m.base-none-eabi.tar.gz=b090d076b04e7894a94c1ed892825a3f6d27aa3908d40d1a66f098b9d53f4309 +dist/2024-09-04/rust-std-beta-thumbv8m.base-none-eabi.tar.xz=3213f7cb7365420b767779edc091a35f9e3a39e9439d0bf542dcc099eff25ce7 +dist/2024-09-04/rust-std-beta-thumbv8m.main-none-eabi.tar.gz=5d977dc47e7c04d1f729a2a153e2c37ceab7d9a049b111505146e82b7b3bc30b +dist/2024-09-04/rust-std-beta-thumbv8m.main-none-eabi.tar.xz=8e9cef53163ff70ec8868d11d7c237cf40ced06852fcb193b3ef45232c3cd90a +dist/2024-09-04/rust-std-beta-thumbv8m.main-none-eabihf.tar.gz=01f1916e4de4401ef0b7c43bfb0df72169f36ab09eda9ee923ef0d6608b8fafb +dist/2024-09-04/rust-std-beta-thumbv8m.main-none-eabihf.tar.xz=1a9a9fe79884bd8e8e35cc8bcf3d1fb7a82ee4a40c630b78a302aabb047959f1 +dist/2024-09-04/rust-std-beta-wasm32-unknown-emscripten.tar.gz=66da8c5a7e579df020ef012747f9c8ce6a3094bdf43a99dc3763a9234eda3fff +dist/2024-09-04/rust-std-beta-wasm32-unknown-emscripten.tar.xz=34ba780c992a10428fac49c9149d1f613fac221dd92866a93795543a991c29af +dist/2024-09-04/rust-std-beta-wasm32-unknown-unknown.tar.gz=485304f0705ea8ef1a3516cd01e9b63e010af514edc03774cd87284367ed5e04 +dist/2024-09-04/rust-std-beta-wasm32-unknown-unknown.tar.xz=414608d21dd7cd268ad57a6be916b0be2c95433e2bc14083ff8c4a7a7cc8952b +dist/2024-09-04/rust-std-beta-wasm32-wasi.tar.gz=c745c8682a54abe37c2734bf0c7931b6d10269eb56c07765e39dd289dab67e01 +dist/2024-09-04/rust-std-beta-wasm32-wasi.tar.xz=732c12837772531eabc44a7d4a545e130e2ae220d3670748fa2050cd4c65a18b +dist/2024-09-04/rust-std-beta-wasm32-wasip1.tar.gz=2b54c587ddd908481f5561d6de60c7fdbef234ca2ecec4eb4d4791416038f7db +dist/2024-09-04/rust-std-beta-wasm32-wasip1.tar.xz=799ee151f0aa3c5ec132f03c42152393d966c9249972967133edef56b30d66ae +dist/2024-09-04/rust-std-beta-wasm32-wasip1-threads.tar.gz=120b8cad5a2a153bee58ccf81824e6a1c7c16befdd2785f963a9b2dfc350b9f2 +dist/2024-09-04/rust-std-beta-wasm32-wasip1-threads.tar.xz=5d74a8dc4731ab433cf796e7568122c7ca1463c648d2b49876ae1deaeaefa314 +dist/2024-09-04/rust-std-beta-wasm32-wasip2.tar.gz=911e60f2976d3b98dc9f6e82f72c459c5e07713e2dde2c7337569a71db2d1218 +dist/2024-09-04/rust-std-beta-wasm32-wasip2.tar.xz=947d312ec07c6190dcd4abeb493a2b67ac64a9a549ef30372c8eee7164c74883 +dist/2024-09-04/rust-std-beta-x86_64-apple-darwin.tar.gz=7b6e65885f14982f1112a2c0e8dd3266b1c4313276342ed98f2681432720b8c6 +dist/2024-09-04/rust-std-beta-x86_64-apple-darwin.tar.xz=cdbe462e3935c5a34415275afe830a6b5edae2fda84ed35e836ae868c884d19f +dist/2024-09-04/rust-std-beta-x86_64-apple-ios.tar.gz=f75e7896ed5c9b64f817e9b2d6ed4d637e19ff26a14f72a570b4eff532f5b32b +dist/2024-09-04/rust-std-beta-x86_64-apple-ios.tar.xz=60db5599bdad826b32637dfd2989daa90597b278ac14b42ede3a7c15aed119e0 +dist/2024-09-04/rust-std-beta-x86_64-apple-ios-macabi.tar.gz=3f57688112d2d80010636724acec5083bce0bc0a901f9ccbd76a09bb21de2b17 +dist/2024-09-04/rust-std-beta-x86_64-apple-ios-macabi.tar.xz=841dcf3eba0ad5b7bc8a4d55fabca80a1a27a3d697431c251b48912131148b6e +dist/2024-09-04/rust-std-beta-x86_64-fortanix-unknown-sgx.tar.gz=96af596e4bc63519decc0e17005006aee8a2f22258d86b6efa25a94fbbe62f23 +dist/2024-09-04/rust-std-beta-x86_64-fortanix-unknown-sgx.tar.xz=4215a327f11bc7fa02546e69cb52c6c7bfe6a1ca602a6bf7a266e11937204bef +dist/2024-09-04/rust-std-beta-x86_64-linux-android.tar.gz=80849fc95791de8cf98da9ebd405a4e268445b22b9413c8545870fe83f5891c7 +dist/2024-09-04/rust-std-beta-x86_64-linux-android.tar.xz=f849ad9d7ccc7eda06404e3bd67f150c3d8dfa66609405435fb2ba09c00ca136 +dist/2024-09-04/rust-std-beta-x86_64-pc-solaris.tar.gz=f871244a44131b1e2f56ad7c77ccb4e7433f39d6b248951f449914a65178bea3 +dist/2024-09-04/rust-std-beta-x86_64-pc-solaris.tar.xz=933b3b634b5caf57213be093977b0f56ba3609dc9407ac026079f75f4783642d +dist/2024-09-04/rust-std-beta-x86_64-pc-windows-gnu.tar.gz=28ef28c4b17b5e8a20ae5f19feeb4643864f64ac8e9c68b84f8cec067317c339 +dist/2024-09-04/rust-std-beta-x86_64-pc-windows-gnu.tar.xz=1e40daa830d390d57c0dd23331849edf45adc0a35d120725bfd9fae43edf13e1 +dist/2024-09-04/rust-std-beta-x86_64-pc-windows-gnullvm.tar.gz=b9a6e290d7b9c71b4a33164116cc523654c3147168a04fc7608a27397c100944 +dist/2024-09-04/rust-std-beta-x86_64-pc-windows-gnullvm.tar.xz=a6e1db0945d1a5243caf2d1ad7d24b4dd16f8882d3e88118f203c91ff5e2cd52 +dist/2024-09-04/rust-std-beta-x86_64-pc-windows-msvc.tar.gz=8d70d70a645b36e6de01b08a34a28a995c73f91e8a285607a5516180d3a93350 +dist/2024-09-04/rust-std-beta-x86_64-pc-windows-msvc.tar.xz=d5a6fc72bf9dc0b7083d364358232a5df68b2b9f03a1a553bbeecf2a84936cb8 +dist/2024-09-04/rust-std-beta-x86_64-unknown-freebsd.tar.gz=01e159405178d883deb8eb09e9101826e7591c8d8fd6840133c0e8f77e00e395 +dist/2024-09-04/rust-std-beta-x86_64-unknown-freebsd.tar.xz=7fddda753b5f3e244de9427de6399052c81df87bd2b76d2c1f9a0fa4d1d1cddf +dist/2024-09-04/rust-std-beta-x86_64-unknown-fuchsia.tar.gz=2c37eaef53b50d812205ed24de580165bfa800658ab9a9ea503667105119a544 +dist/2024-09-04/rust-std-beta-x86_64-unknown-fuchsia.tar.xz=8d1e3d290c5736c4e7a48a6b1a88ba18b9e68876638896b31b61917c6fcd2af4 +dist/2024-09-04/rust-std-beta-x86_64-unknown-illumos.tar.gz=83a57ec9e9696a63dadf9307e0cce117b92be8e9b7d17edfe410d38f75629202 +dist/2024-09-04/rust-std-beta-x86_64-unknown-illumos.tar.xz=3db6747b556581f02e0cf058b93538785d1eca9aaefe36dc8b7667428fa05ef7 +dist/2024-09-04/rust-std-beta-x86_64-unknown-linux-gnu.tar.gz=fe737fb11bd2a16b7636013f37041a35126f0bf8b2c562ac38384d45e49088c4 +dist/2024-09-04/rust-std-beta-x86_64-unknown-linux-gnu.tar.xz=a7a3f5245067b2967bbc4bd010ac3a6e9613cc9b6462c53cdcf0b91eab6cddbb +dist/2024-09-04/rust-std-beta-x86_64-unknown-linux-gnux32.tar.gz=8b3fa007713d4e37de79d5662a3de446d378e00fc631478e465fb170447c49ea +dist/2024-09-04/rust-std-beta-x86_64-unknown-linux-gnux32.tar.xz=c2dd95e94f9a9bc2d31e807a3b7cc5cb43a994cd4400ac1636ade3005344146b +dist/2024-09-04/rust-std-beta-x86_64-unknown-linux-musl.tar.gz=a294420b029900027530932ebd29cbd3f17672fffc60128122473088329f8cb8 +dist/2024-09-04/rust-std-beta-x86_64-unknown-linux-musl.tar.xz=72a1c8052534e1b986ebd1bb5364de9e9e67353cfc6de7341f759d8da370bf2d +dist/2024-09-04/rust-std-beta-x86_64-unknown-linux-ohos.tar.gz=7227b14f3148302d954756bd4df570289aa8dedd8d889b5399821356ac097f8a +dist/2024-09-04/rust-std-beta-x86_64-unknown-linux-ohos.tar.xz=61cf15b98ba67fb648ee87901bc33644efc342c2b6401ab8b6a14cae755cbd8d +dist/2024-09-04/rust-std-beta-x86_64-unknown-netbsd.tar.gz=61b604f112031aadd7ad87e535cbb4966c53099e276fc76d99fecd0e912b2e28 +dist/2024-09-04/rust-std-beta-x86_64-unknown-netbsd.tar.xz=428a0a6955266ac0e74b11bb4c58a461c041f13f241d5a2d698139b4b5839ad5 +dist/2024-09-04/rust-std-beta-x86_64-unknown-none.tar.gz=c8b29984bf2b6d77893cda301e55dd128da76bad7dd87c751aa5585add2262fd +dist/2024-09-04/rust-std-beta-x86_64-unknown-none.tar.xz=1460566b927586f6afa531aa1cefa9aec0d4e829a08a151638a42c255b6a7ef3 +dist/2024-09-04/rust-std-beta-x86_64-unknown-redox.tar.gz=17503716bb940d50db15bd1b467fe03ff15474f1b0b162eb3f2891699d898768 +dist/2024-09-04/rust-std-beta-x86_64-unknown-redox.tar.xz=66007a1f995597a697747886eacbe38c9d6a588b1ed365e6b4b522c72bc7b8af +dist/2024-09-04/rust-std-beta-x86_64-unknown-uefi.tar.gz=b612bac841c9f93bc6189971bf82df47e8730cf1696d2d6f3344be67a6c28f0c +dist/2024-09-04/rust-std-beta-x86_64-unknown-uefi.tar.xz=3dd0f70f8f226160700a52c19aebc2f27801360a8d2882702c5a0be94560da3b +dist/2024-09-04/cargo-beta-aarch64-apple-darwin.tar.gz=3efe0d5356824c1620e223686c81cf10b629db0a0c385c3177b5fe1866776b5c +dist/2024-09-04/cargo-beta-aarch64-apple-darwin.tar.xz=07deeec79d74a39b0cf971bd980936eb476005bf0e832adef9e4521bba3c010b +dist/2024-09-04/cargo-beta-aarch64-pc-windows-msvc.tar.gz=c9da3632a36a2db512015580bd20e0b5207f8a0d98ae093a99755e4c512215f8 +dist/2024-09-04/cargo-beta-aarch64-pc-windows-msvc.tar.xz=b0b9aabd90863c1671ad80955277c2f006654779837cb1358774b8189fba357b +dist/2024-09-04/cargo-beta-aarch64-unknown-linux-gnu.tar.gz=cb862535909b1f0fea6ee40a6a888f2f860f95b8700b1d5167bd7a41b9e33958 +dist/2024-09-04/cargo-beta-aarch64-unknown-linux-gnu.tar.xz=b1ff8f714cda2c98a7129e861adcf33245bd84bdfbdcec9fb1a89545dcd033f7 +dist/2024-09-04/cargo-beta-aarch64-unknown-linux-musl.tar.gz=5c3659e979393c8c1dbe1a6ccb09eea412671363e228f0c7ab4bd4896cd48470 +dist/2024-09-04/cargo-beta-aarch64-unknown-linux-musl.tar.xz=0435e1332b1bc40a280fc867eab54e925135eba774c3bc0553a8bb100d644f59 +dist/2024-09-04/cargo-beta-arm-unknown-linux-gnueabi.tar.gz=6f7f079ef04c4b1d14864cba67ec650a3e43f3baa81fea1797d00067f22a72a8 +dist/2024-09-04/cargo-beta-arm-unknown-linux-gnueabi.tar.xz=549607bdeacd26fa770ecb00ce54cb3ea72c5568e65966c1fddc3a540b9f6e6a +dist/2024-09-04/cargo-beta-arm-unknown-linux-gnueabihf.tar.gz=e23b18a2a86bca5320b66c54d43a54d90db1b787443cb0e04d66e9d7428fece7 +dist/2024-09-04/cargo-beta-arm-unknown-linux-gnueabihf.tar.xz=5968c534ce88a2574a4f59a0ced82df36aef9c7338ed9c718e85aad514a792f4 +dist/2024-09-04/cargo-beta-armv7-unknown-linux-gnueabihf.tar.gz=3170e39d306e797e5631884c629ecb33a54635056b5a71fbebe5372c1c34da37 +dist/2024-09-04/cargo-beta-armv7-unknown-linux-gnueabihf.tar.xz=76b729642fdba25c015e49e444e158170d3ed2ac0a533ba7c6095ecdc0862ba5 +dist/2024-09-04/cargo-beta-i686-pc-windows-gnu.tar.gz=c58826189772af945c9d40868e80d64359f4108afa06d150a3d350323b0eb8df +dist/2024-09-04/cargo-beta-i686-pc-windows-gnu.tar.xz=1b644d661778bfcbec892eab17bee06861940037992821c4ded8321a69c0f6a8 +dist/2024-09-04/cargo-beta-i686-pc-windows-msvc.tar.gz=e026eac2c2e891976e085d26591d85000dccf3c3654f3edd65e99c6c0ba43574 +dist/2024-09-04/cargo-beta-i686-pc-windows-msvc.tar.xz=e7307b2e55302228c5036991ca6141a5202a16f43b0148607f3802fdc90aa0cc +dist/2024-09-04/cargo-beta-i686-unknown-linux-gnu.tar.gz=0a00604bad2096cd0b0db59a1b41b5737696015a4ddc60f9b1132829a4cd0a5f +dist/2024-09-04/cargo-beta-i686-unknown-linux-gnu.tar.xz=a623eecb18a21b2dc6a4b62876b8fa4fc467c53fdd0cfdac493f89d619be5aa7 +dist/2024-09-04/cargo-beta-loongarch64-unknown-linux-gnu.tar.gz=64955892d99d0e7f0042016d7a5e3ac87f89b6f514b1934611050f89aa5f6a28 +dist/2024-09-04/cargo-beta-loongarch64-unknown-linux-gnu.tar.xz=3c7c3061c466fc4a1eb836c97cab95d511778d77d220189a6a77f8e5b46e4888 +dist/2024-09-04/cargo-beta-loongarch64-unknown-linux-musl.tar.gz=be1c255840307bd24c2c8b5c92e2fa0eed6037daf3ed9597e17bc56f313ef506 +dist/2024-09-04/cargo-beta-loongarch64-unknown-linux-musl.tar.xz=d0e456bc8b64a0ee778e69eac75b6a258c37f7b2d06496a8dfcc47d91e1c2dd1 +dist/2024-09-04/cargo-beta-powerpc-unknown-linux-gnu.tar.gz=b9cd94c4ac9a11eece8712b325d08007b641d5da7487fd38b30dbaf0f3d1b5a4 +dist/2024-09-04/cargo-beta-powerpc-unknown-linux-gnu.tar.xz=68dd4a74494fe8f02781a2b338eff5f5cc78d66048eddd3ed7cc3e31dcecd2c8 +dist/2024-09-04/cargo-beta-powerpc64-unknown-linux-gnu.tar.gz=b464ad7a1233e3ad5129340e623a60d2ad0882843acbef60a9aed45a453ccac1 +dist/2024-09-04/cargo-beta-powerpc64-unknown-linux-gnu.tar.xz=1167f3d38628c01b11dfb9f66eacdf4cd519b46ea1b8c9d182a390e7d552a933 +dist/2024-09-04/cargo-beta-powerpc64le-unknown-linux-gnu.tar.gz=eb16d3791a79aa384326e2e79aeafd8d3e27adf4733a5bcca441e278e578b60e +dist/2024-09-04/cargo-beta-powerpc64le-unknown-linux-gnu.tar.xz=d100dcb6437e87b3b687a7059dd932567855f68d962a109268fcce5a5aa688c6 +dist/2024-09-04/cargo-beta-riscv64gc-unknown-linux-gnu.tar.gz=ee771d98286302d4a8a93ba5165c342a2fbe770bf7758f8bbc490ad188d2e5cc +dist/2024-09-04/cargo-beta-riscv64gc-unknown-linux-gnu.tar.xz=d2e9eb5a1800545eec4186b5252737f3b3a02d232473e6864e4c6fd752a69623 +dist/2024-09-04/cargo-beta-s390x-unknown-linux-gnu.tar.gz=b35ef65a54c9dd068a699f4210c0c88bd2777308fd7ddad3c7d0b9a1c994657e +dist/2024-09-04/cargo-beta-s390x-unknown-linux-gnu.tar.xz=eaee5c891aab499438427c2c965c2c8f4471a3b051effee139f251f544ac4ac4 +dist/2024-09-04/cargo-beta-x86_64-apple-darwin.tar.gz=917ba277cb3f050fb3e65126b587245bf89891256faec33a57e2b1a064075534 +dist/2024-09-04/cargo-beta-x86_64-apple-darwin.tar.xz=179d6fe24981d477eb806ba714bd639750577cb9de2d152116e994d3955ade38 +dist/2024-09-04/cargo-beta-x86_64-pc-windows-gnu.tar.gz=6aa52989d1ccb25b03433dec436507455256cb1e2ed305ba747c342551d0778f +dist/2024-09-04/cargo-beta-x86_64-pc-windows-gnu.tar.xz=bc0403c00fa2093f09d95b1ad091850b2450f4e1d7fac225a730d7363074806b +dist/2024-09-04/cargo-beta-x86_64-pc-windows-msvc.tar.gz=5c1e018191c296ddc443699e48c4f1a3e700983fc45ea230172f35881d09e103 +dist/2024-09-04/cargo-beta-x86_64-pc-windows-msvc.tar.xz=f1b44ff315f5332815263d5b0a1cd06f852431acbf5cc902bb6723c3398e11d6 +dist/2024-09-04/cargo-beta-x86_64-unknown-freebsd.tar.gz=7da980ccdb2d6bc0946749fcceaed7124f311b38bf28cef0797ca85909f5d5fb +dist/2024-09-04/cargo-beta-x86_64-unknown-freebsd.tar.xz=a935462749686fb68eac699ea67ef1afaa22ed0b147d2e4d0a6712f225341fa2 +dist/2024-09-04/cargo-beta-x86_64-unknown-illumos.tar.gz=ccc3d29e88482885090f6fb954518bcb0b6bd3f54283702df9e0e80b78454c01 +dist/2024-09-04/cargo-beta-x86_64-unknown-illumos.tar.xz=c0cb33e5088f2b9f5fe8bedb3915fec10e7f65563013b914e0738486b5e8ebab +dist/2024-09-04/cargo-beta-x86_64-unknown-linux-gnu.tar.gz=84fdbbc0912c4020dd1baec1d603c5d5c1986c7b321d3d9c0c42184aa6347f15 +dist/2024-09-04/cargo-beta-x86_64-unknown-linux-gnu.tar.xz=8f8948750141c3ee8a50e575f196bd972876e784cf1793b256a5a9462c9e3d44 +dist/2024-09-04/cargo-beta-x86_64-unknown-linux-musl.tar.gz=9ef6b7450b94ce202f1b603151075bf8f595022f2c52f6bcd1c4a72423db2b80 +dist/2024-09-04/cargo-beta-x86_64-unknown-linux-musl.tar.xz=5b63b98d67e211057fbaeb1db3721b90252a331143ca267bb30eebca4ac01cdd +dist/2024-09-04/cargo-beta-x86_64-unknown-netbsd.tar.gz=69d500e2fca1c44fea31310b0636a9af009d4ec96b5ed2335864c47350fa7b59 +dist/2024-09-04/cargo-beta-x86_64-unknown-netbsd.tar.xz=7da3c2641f0ecdbd8b770402356416750a52265a6848d3734fce2195c889768a +dist/2024-09-04/clippy-beta-aarch64-apple-darwin.tar.gz=15395c04235f2475d5e41371e2797f181af71275f82f04fbb885b1cd7a197f45 +dist/2024-09-04/clippy-beta-aarch64-apple-darwin.tar.xz=8be6fb9e0cafcd262594cfc4a36807bede9e158cbf7eb38c0f25144bf3bfdd1e +dist/2024-09-04/clippy-beta-aarch64-pc-windows-msvc.tar.gz=b043e41facce81a5fc607f2268330b279d7e26975e409158ac2cbbc841d10f85 +dist/2024-09-04/clippy-beta-aarch64-pc-windows-msvc.tar.xz=ba41705b213f863416120c28fa4a7959cf41e261cce8233b12fd91aa0157d601 +dist/2024-09-04/clippy-beta-aarch64-unknown-linux-gnu.tar.gz=b093269be813ea76964de2c03c7380bcefab1e7d6e31c93fd3f374619a99a5f0 +dist/2024-09-04/clippy-beta-aarch64-unknown-linux-gnu.tar.xz=06d71273208fcbfa5958987038eacda066d4518b5cd6bd7405a981bf841868ae +dist/2024-09-04/clippy-beta-aarch64-unknown-linux-musl.tar.gz=aa159e61c4986def9d27f55504d822d6023c277a546e95079161577ae2991df4 +dist/2024-09-04/clippy-beta-aarch64-unknown-linux-musl.tar.xz=7a3023b98a1c72c993d176c85f4790b234c41f35184636d29deeba40d51587a2 +dist/2024-09-04/clippy-beta-arm-unknown-linux-gnueabi.tar.gz=8e30a0377b780311bf51bdc48dcf233a344cb2fd9ae9aec174bc87d29f94c34b +dist/2024-09-04/clippy-beta-arm-unknown-linux-gnueabi.tar.xz=488c28d10f45a498b1054fad9feb72a848d0668cd12d29b3a81f5569b1145018 +dist/2024-09-04/clippy-beta-arm-unknown-linux-gnueabihf.tar.gz=db25c9aa95b08acdaeaba407367a823e9e2094b0616c80b0c8a84d7c2f6c4292 +dist/2024-09-04/clippy-beta-arm-unknown-linux-gnueabihf.tar.xz=7c320cc979ebdde8753093a0e4b1da850b1b680c1ecd10c5d3e33242af12e4dd +dist/2024-09-04/clippy-beta-armv7-unknown-linux-gnueabihf.tar.gz=835c0912556cd5b0b180856359db8d75204830984fb1b5f72bf436f137955fa2 +dist/2024-09-04/clippy-beta-armv7-unknown-linux-gnueabihf.tar.xz=836a54126122c2abfc649982708d97b6451eaf3a31ba556ed73ec1f4269be738 +dist/2024-09-04/clippy-beta-i686-pc-windows-gnu.tar.gz=90b52880cbd51bacb9597ee4fed07fa13fc399f03c5ba840c0c9e6c0a096b772 +dist/2024-09-04/clippy-beta-i686-pc-windows-gnu.tar.xz=c41be130f3276c4c905eab580e866682e4f3bbdd11b348f4d1438c67602fb036 +dist/2024-09-04/clippy-beta-i686-pc-windows-msvc.tar.gz=f023406dc34bb09d020a41fdf6ceb3e60c90dd38380fbbcc26e9f4e144eebca0 +dist/2024-09-04/clippy-beta-i686-pc-windows-msvc.tar.xz=b21746ec1a2c9fc76ce82917b65c8e73482aaefe5f99282f0c5e9682a3af486e +dist/2024-09-04/clippy-beta-i686-unknown-linux-gnu.tar.gz=cce9cd9d470250c73437e151622b02f804fff3db045c6de25ee949aed435c383 +dist/2024-09-04/clippy-beta-i686-unknown-linux-gnu.tar.xz=9565f70c8d90540d464fb1f3b8bff52b77bf55189ab938b2c18bdeed751e9e4c +dist/2024-09-04/clippy-beta-loongarch64-unknown-linux-gnu.tar.gz=0d1d63a8eca4d0812446f94bc793fbb7660da11babf5d8607d2798749c938a6b +dist/2024-09-04/clippy-beta-loongarch64-unknown-linux-gnu.tar.xz=db178c0eaddcb318653d4b05fe0d97738440713f0cd120657cc2a3e758d52432 +dist/2024-09-04/clippy-beta-loongarch64-unknown-linux-musl.tar.gz=a604be9f091f88e97f702f619d86b91bff0a20fbd267200ac1e66df2bd823766 +dist/2024-09-04/clippy-beta-loongarch64-unknown-linux-musl.tar.xz=93c395e07a8457b8904c470751490326303e2ceaa93b737f8fc521b49dfbd69b +dist/2024-09-04/clippy-beta-powerpc-unknown-linux-gnu.tar.gz=08aa4a8ccd7569a0513c2443e2b10993cbb92bed531370891452bd3dd8c0eb82 +dist/2024-09-04/clippy-beta-powerpc-unknown-linux-gnu.tar.xz=f6b0222261e1e2b1465549eda331c16d4ea6729d15e6fe208dbc4cce115e75e7 +dist/2024-09-04/clippy-beta-powerpc64-unknown-linux-gnu.tar.gz=96e2dca5adb7f5ffe41e5ff30e9419575f3991adde8bdbba023d11f344044dc1 +dist/2024-09-04/clippy-beta-powerpc64-unknown-linux-gnu.tar.xz=3ced511aca7268960c616d0105da02a92d83b7983b6accbb37eba722eff64cbf +dist/2024-09-04/clippy-beta-powerpc64le-unknown-linux-gnu.tar.gz=421c27b25b79b9c88e4b65ac7cd0a4f06934a63324c56870cd7fff905869a33e +dist/2024-09-04/clippy-beta-powerpc64le-unknown-linux-gnu.tar.xz=63254a01ab1a9a21cdb5a0b3a4da9e8ae7921b9ceec2339df4bbfb19ea7c6454 +dist/2024-09-04/clippy-beta-riscv64gc-unknown-linux-gnu.tar.gz=4ee751b09816886f8edbc431ab8c63df6c664dbedc40a67748fb17a639a070f1 +dist/2024-09-04/clippy-beta-riscv64gc-unknown-linux-gnu.tar.xz=7e9ffb62ab6c8f1cbb5f9e0b0a3c79cf104dfac09be2ef1d5e6b6c0c34b406c7 +dist/2024-09-04/clippy-beta-s390x-unknown-linux-gnu.tar.gz=0a49c1e844859f27b1283087c476a559c4c3a4c33c8ce2748165cc5c0b0ed039 +dist/2024-09-04/clippy-beta-s390x-unknown-linux-gnu.tar.xz=6daec872df52125b3de854ff0962433ba13b7cbe5519edfb29944fbc4cc817ad +dist/2024-09-04/clippy-beta-x86_64-apple-darwin.tar.gz=6611771ce0e7cc19fbbb9383875edaf7de975b6cf154fcd5cd18a09f09793a36 +dist/2024-09-04/clippy-beta-x86_64-apple-darwin.tar.xz=1c90c63f87b43797aa04b88e4c1d0fe0f2ad131060fc8495be190d0ebd89a43e +dist/2024-09-04/clippy-beta-x86_64-pc-windows-gnu.tar.gz=53a04c1426bc151fec4699848e33141df1b04097d4883c07fc07d2bf0bcddf8a +dist/2024-09-04/clippy-beta-x86_64-pc-windows-gnu.tar.xz=be748b65b238e3e948e2421f82a72d1108ec79651381b1dcdaaa97df15c981df +dist/2024-09-04/clippy-beta-x86_64-pc-windows-msvc.tar.gz=24ea01230bbf6b4f43094cfcf6c7c72e6d319c493ff3817456c667b89026c608 +dist/2024-09-04/clippy-beta-x86_64-pc-windows-msvc.tar.xz=37130d66eeaed68f0780b1dc19f2f59a2a0419350920521690d4870d7d71d8f1 +dist/2024-09-04/clippy-beta-x86_64-unknown-freebsd.tar.gz=4e427b7ea0f334bd6ea8c2de7fc1d5bf43d5333bc7a435cf65543c564fab6e41 +dist/2024-09-04/clippy-beta-x86_64-unknown-freebsd.tar.xz=b221491159f5352dd392f6ee6419f9d5d693ac347df9863fdac77f2ca1cf6a67 +dist/2024-09-04/clippy-beta-x86_64-unknown-illumos.tar.gz=9d835b4369fb51ab8c1eafb553b9304548e91dd32784ae81cb783b40985d2eee +dist/2024-09-04/clippy-beta-x86_64-unknown-illumos.tar.xz=a6780c72c71f2e6c6e1bbc8bc4e639389ab9b7aed0ee7e2e0c21819156b5578e +dist/2024-09-04/clippy-beta-x86_64-unknown-linux-gnu.tar.gz=613bf471668edb8209910dd13086cbefed0da6dea46dce2013a000ecc4315e45 +dist/2024-09-04/clippy-beta-x86_64-unknown-linux-gnu.tar.xz=e3328f37cfc89de1aabd89653a42ff54b8dadcc49e651b22fda325c00644309d +dist/2024-09-04/clippy-beta-x86_64-unknown-linux-musl.tar.gz=d6a7a5ee37587c0b92aabfc5b9466d175cb8d05d209412a5beee8a61c241396f +dist/2024-09-04/clippy-beta-x86_64-unknown-linux-musl.tar.xz=dc73b566be162eef2032eccb69b3542ab3c72b760fe7eeaacfcd367ee0b20f12 +dist/2024-09-04/clippy-beta-x86_64-unknown-netbsd.tar.gz=6f1e0be96b59a63a6616b68717c0a393fd99ec1a768affdd5c86249e5eb5d210 +dist/2024-09-04/clippy-beta-x86_64-unknown-netbsd.tar.xz=30fff8aceaedf6d76c6fc0636c2ddecc97fb66f9219b86299550b7312f043e38 +dist/2024-09-04/rustfmt-nightly-aarch64-apple-darwin.tar.gz=37a5383ba608540ed57484e221e87f3cd78fd35f068e98f0da1d3932d86d2eff +dist/2024-09-04/rustfmt-nightly-aarch64-apple-darwin.tar.xz=a3935c24f5ac1d69756f4598f227e43304ede4e35f9808b3db9f04adfecc5445 +dist/2024-09-04/rustfmt-nightly-aarch64-pc-windows-msvc.tar.gz=0b21dd8c54055102a41f7ad622565c1fc36ff97642f2e2998e48d1cb1ebae196 +dist/2024-09-04/rustfmt-nightly-aarch64-pc-windows-msvc.tar.xz=2a543dbf79042924e8c05aaeed97ff37089c8f6994977b932bacb0403f11584c +dist/2024-09-04/rustfmt-nightly-aarch64-unknown-linux-gnu.tar.gz=8d9b19108587e6d8d12270ff025579dc559173245e08b94113bb91a7ada80670 +dist/2024-09-04/rustfmt-nightly-aarch64-unknown-linux-gnu.tar.xz=d288770b8a85e24b35561129cc2a09c848006c547ce5fa35d33c8ed7e85d5322 +dist/2024-09-04/rustfmt-nightly-aarch64-unknown-linux-musl.tar.gz=2e69adc7e75efcd889108d185f200db6280494b05de6a06291dbf26ef32e5d42 +dist/2024-09-04/rustfmt-nightly-aarch64-unknown-linux-musl.tar.xz=fca74af6db1c53a79a4412a020f56ec9c61603d3373eaa936a57dad45f3751d7 +dist/2024-09-04/rustfmt-nightly-arm-unknown-linux-gnueabi.tar.gz=b2be0123cde401aaed259a9387e04f3978fbddce98096b3a8a654b76f92f2e6b +dist/2024-09-04/rustfmt-nightly-arm-unknown-linux-gnueabi.tar.xz=c44c42a59887f1479383694f43688f9f2a8174ac89fdf657b2e8619372e0bcef +dist/2024-09-04/rustfmt-nightly-arm-unknown-linux-gnueabihf.tar.gz=3d99bab3656d0318173c414dcb8930291ab43285883ca80a04d854023a4201a3 +dist/2024-09-04/rustfmt-nightly-arm-unknown-linux-gnueabihf.tar.xz=29e506c1a18449b84a643f0075f1263cd8512662f55e2c5b18305213e4246783 +dist/2024-09-04/rustfmt-nightly-armv7-unknown-linux-gnueabihf.tar.gz=b486ff8e1e136ba15c9bb14db08dcd14b612adf1617cf1f820a23ee403958049 +dist/2024-09-04/rustfmt-nightly-armv7-unknown-linux-gnueabihf.tar.xz=b4d593b5a89bb42e7f9eaa17df12778dd816c75e8997e964371286041691cbbf +dist/2024-09-04/rustfmt-nightly-i686-pc-windows-gnu.tar.gz=dcf94a642166b0664a63c4162a2d303c75fdef6f2a7f9b3e502ba5baae117f69 +dist/2024-09-04/rustfmt-nightly-i686-pc-windows-gnu.tar.xz=4b27ac17748d8cdcd2bc7b9956541333997c6ec56f7a770628dc8e57fc7f442f +dist/2024-09-04/rustfmt-nightly-i686-pc-windows-msvc.tar.gz=8a3caf2dc2b786ca58f6d37c011dc210e883398a3734f9f13678a9e57c5ccf5d +dist/2024-09-04/rustfmt-nightly-i686-pc-windows-msvc.tar.xz=e129b88dd69200e305cc5ae16231952d85f9461dad13fd3bae5e889dac89d9c6 +dist/2024-09-04/rustfmt-nightly-i686-unknown-linux-gnu.tar.gz=1bc390abb8f754d5b8679b33186b97262dadff9c6db7268cfbcfe605c628a681 +dist/2024-09-04/rustfmt-nightly-i686-unknown-linux-gnu.tar.xz=8420198b0a22aaa5951678b954bcce636c78ba6567a06484c830b3eded815228 +dist/2024-09-04/rustfmt-nightly-loongarch64-unknown-linux-gnu.tar.gz=05071fe12ed4030464f996fe36dd2e3f60d3701956275499acaeaf03a16e36eb +dist/2024-09-04/rustfmt-nightly-loongarch64-unknown-linux-gnu.tar.xz=2bfdabab0d03e570c073463a8867bbdb54879f501b0822906fa2aa5705603d7c +dist/2024-09-04/rustfmt-nightly-loongarch64-unknown-linux-musl.tar.gz=0c7e3b10626a9d9a3f8522175085169ea4e34568a7be0093c6682bb9659bf65f +dist/2024-09-04/rustfmt-nightly-loongarch64-unknown-linux-musl.tar.xz=deb2b51a41dae2e72188fa6c06c4a7bdb08c2723b3ce823602087bd9eb36eb07 +dist/2024-09-04/rustfmt-nightly-powerpc-unknown-linux-gnu.tar.gz=e34590ec2cbd481ffd237101c239f27bd2298517bb7fc9c9f9b6d71abfff69e4 +dist/2024-09-04/rustfmt-nightly-powerpc-unknown-linux-gnu.tar.xz=9cd0d3dd57b764ad054d4295f822a7fd74a1b1ee5babf77ed2dc2c39ee60b7a2 +dist/2024-09-04/rustfmt-nightly-powerpc64-unknown-linux-gnu.tar.gz=62566938d97058dd38b1e0c97aa4421d709ce988544956d6a4aaf3e54425dbce +dist/2024-09-04/rustfmt-nightly-powerpc64-unknown-linux-gnu.tar.xz=8f27c6fc5b56092302e49da973ff08f0d3131465bf9a701a9ddc91d373acc435 +dist/2024-09-04/rustfmt-nightly-powerpc64le-unknown-linux-gnu.tar.gz=7637f3b8060635595a3d2fb83fef68e9990ff1adb1bd3288c7c41767b37ee2c4 +dist/2024-09-04/rustfmt-nightly-powerpc64le-unknown-linux-gnu.tar.xz=3275f15e3d7e9ccb991f6f9a7059acefd0bee49bfd4cf0724aed11e51e3772db +dist/2024-09-04/rustfmt-nightly-riscv64gc-unknown-linux-gnu.tar.gz=29379bab930e7b350cec51be33663ad67a0d30922d658006911f895221dcbffd +dist/2024-09-04/rustfmt-nightly-riscv64gc-unknown-linux-gnu.tar.xz=4f71e948ec587836315d7ec98e6f3c6125a298faf1321b4524257d3c9664f9eb +dist/2024-09-04/rustfmt-nightly-s390x-unknown-linux-gnu.tar.gz=5b9361317481269e090b4270bcf754caca8a1797f6b2d83a4c570a4024bb0dc3 +dist/2024-09-04/rustfmt-nightly-s390x-unknown-linux-gnu.tar.xz=db3bf98663017bec6b6beba5848a350d4d34f39e3f98bacb321866112cff7c15 +dist/2024-09-04/rustfmt-nightly-x86_64-apple-darwin.tar.gz=9d5b8c84f82ededb2370c20afdb6b7d06d97161a65348f4ee2b6ab2171236cd0 +dist/2024-09-04/rustfmt-nightly-x86_64-apple-darwin.tar.xz=e880f57ba68bce871fa67230db19aab1f146548254867f09e0d83750bbb50a1c +dist/2024-09-04/rustfmt-nightly-x86_64-pc-windows-gnu.tar.gz=8b2c79814b202661c74584d7c4aeb35cc0c8520c4df1c81f2fb2896a22385191 +dist/2024-09-04/rustfmt-nightly-x86_64-pc-windows-gnu.tar.xz=c193e2f2b859239aa0489c65663fb83c4bd7a87571d5b6ca6572f722c46cef64 +dist/2024-09-04/rustfmt-nightly-x86_64-pc-windows-msvc.tar.gz=8d6583366248882490371ef5d4532f82ba1779cb993b0078ca6903f9b6a0c5be +dist/2024-09-04/rustfmt-nightly-x86_64-pc-windows-msvc.tar.xz=0b69fdd8edb566a75cdff616e09223b10796a91eaf8bd90aa11ddd6af61381b9 +dist/2024-09-04/rustfmt-nightly-x86_64-unknown-freebsd.tar.gz=0a452883a9a494f1613f9b0c796d13745e56eb85597142a677c78daeca95a67c +dist/2024-09-04/rustfmt-nightly-x86_64-unknown-freebsd.tar.xz=01eb4d938f6e9228cae297688340daf298bf6e5322a4e3cdb4e06554fa131deb +dist/2024-09-04/rustfmt-nightly-x86_64-unknown-illumos.tar.gz=4d9220bee07e3576f34c3a3dd327723ed660a774c4391f7a4a7e6a78ea2ca88c +dist/2024-09-04/rustfmt-nightly-x86_64-unknown-illumos.tar.xz=2e2cd60bbb356d7b702c511ba56b480ffe0bbceef8f945be0f7b8e338d7998a0 +dist/2024-09-04/rustfmt-nightly-x86_64-unknown-linux-gnu.tar.gz=4aac5347a6011ff27609b4a6b413454d610a5687253a7e09d1bcc8c0e3aa0e6f +dist/2024-09-04/rustfmt-nightly-x86_64-unknown-linux-gnu.tar.xz=ad3a0127c2cc09893fb19e4c58faa6188afeb575996ee4708eae6c5713ff9646 +dist/2024-09-04/rustfmt-nightly-x86_64-unknown-linux-musl.tar.gz=869fbf24ca816b0bf931da79920ae8edaef8a749271434c6522f7ff55920a507 +dist/2024-09-04/rustfmt-nightly-x86_64-unknown-linux-musl.tar.xz=f4870110759f28ad1cdde912fd3f79bd8eb0073bd42e436a456f0d04e7c2bd26 +dist/2024-09-04/rustfmt-nightly-x86_64-unknown-netbsd.tar.gz=eac75028d080b3d4ab86dbbb4f46c7734c60bd747e0325afbaa3b7a7cf0003be +dist/2024-09-04/rustfmt-nightly-x86_64-unknown-netbsd.tar.xz=fe13bf3e0ec3088b35608d65b76f77014e0b90886ba81decfa21019ff222c79b +dist/2024-09-04/rustc-nightly-aarch64-apple-darwin.tar.gz=ecda4ccde26bf6f8405ddbb838239c4f42e9136001e8954b21357d86343ad06d +dist/2024-09-04/rustc-nightly-aarch64-apple-darwin.tar.xz=cdb1b12e6acf5b2bc5a5328f7cb292760d391b3e269d2b2143c87a344efcc9dd +dist/2024-09-04/rustc-nightly-aarch64-pc-windows-msvc.tar.gz=46af634f433b9c7182637880f7b910ef13d2da9b1d7d4e255f9cd302691b99fc +dist/2024-09-04/rustc-nightly-aarch64-pc-windows-msvc.tar.xz=a14935b0b82835388886c826b703057af093dfe16f0367c058dd6d352e585859 +dist/2024-09-04/rustc-nightly-aarch64-unknown-linux-gnu.tar.gz=68ced431fa8682f83dd79901ccb986accc5a6d948c837c43eb5fa244c19eab88 +dist/2024-09-04/rustc-nightly-aarch64-unknown-linux-gnu.tar.xz=fa078e5edc9f6c7be5a39eac722f142d526b68e30acc8f81bd001035fd657a83 +dist/2024-09-04/rustc-nightly-aarch64-unknown-linux-musl.tar.gz=c88a3c5cbb7a8a55f18d27f2c573192d824e33657a143641d1c8fa1504cbc805 +dist/2024-09-04/rustc-nightly-aarch64-unknown-linux-musl.tar.xz=00170baf596aa6e043598e3c38153f29c1cbfe4a63298d4007979877e9c3e1c2 +dist/2024-09-04/rustc-nightly-arm-unknown-linux-gnueabi.tar.gz=19a55b89192897c77240404ff7ed8c64cdba106db13be4a1ae86a9ac44753c30 +dist/2024-09-04/rustc-nightly-arm-unknown-linux-gnueabi.tar.xz=42937abfd803faed251cecc7ac74abcc3c40332b8466535cc1727138fe03beeb +dist/2024-09-04/rustc-nightly-arm-unknown-linux-gnueabihf.tar.gz=3cc5d6e89cd8b53db0c2900a73e59c188e90d042b2e43502e384f44d229b93e7 +dist/2024-09-04/rustc-nightly-arm-unknown-linux-gnueabihf.tar.xz=4e1ff68b91e0cc730ca6012aa577aaf73dd5108d0b26575eaade0a2380914fe0 +dist/2024-09-04/rustc-nightly-armv7-unknown-linux-gnueabihf.tar.gz=082a2efdf341bdfd9bbe3e2340ae8dbf71bff71908439696d30fa25d00c5fe1b +dist/2024-09-04/rustc-nightly-armv7-unknown-linux-gnueabihf.tar.xz=0b480d334a3709ca23dfd4839b518391031b6afde4cea0c30f08f160e39592a0 +dist/2024-09-04/rustc-nightly-i686-pc-windows-gnu.tar.gz=bf06c7a0faebb7dbfa2c09d02f506410f05abc6aa2ba54c515f2a429e904de2a +dist/2024-09-04/rustc-nightly-i686-pc-windows-gnu.tar.xz=c49f577fa788bb6b40350dd9e9f9088ded647f0a5cf5df69135a83d2e085d9ca +dist/2024-09-04/rustc-nightly-i686-pc-windows-msvc.tar.gz=e42254e299e367c9414c4b61715125410ddc3ecb30f2457e4eb843725c6b6abd +dist/2024-09-04/rustc-nightly-i686-pc-windows-msvc.tar.xz=91a752b8a61b81281203297712b1bc775a227d9626b4c84d9e10130f428f843d +dist/2024-09-04/rustc-nightly-i686-unknown-linux-gnu.tar.gz=6f23df634f3e7028d9a6e9989e1edbc2d00e9b435473807f526fd58c150baf3d +dist/2024-09-04/rustc-nightly-i686-unknown-linux-gnu.tar.xz=de7cef873379e3d5ef80b402b9d98bdf74366de27e8f928125081628937baf76 +dist/2024-09-04/rustc-nightly-loongarch64-unknown-linux-gnu.tar.gz=ef0946845c41e096dced01baf6e843c57fcf695c82d5408a1b7c0a5bbd150b39 +dist/2024-09-04/rustc-nightly-loongarch64-unknown-linux-gnu.tar.xz=d43bb8987a3bb394d7d2cf39d78f54505700525b250cb30741b903bf8712f3bf +dist/2024-09-04/rustc-nightly-loongarch64-unknown-linux-musl.tar.gz=00013767600b1a5153ed4faa9d227fd55a905c375f712a7ca59573a317684c97 +dist/2024-09-04/rustc-nightly-loongarch64-unknown-linux-musl.tar.xz=cf1c4351f70e951290583213dade06fe4a61e6dcbc2d0e69be54ea91210051de +dist/2024-09-04/rustc-nightly-powerpc-unknown-linux-gnu.tar.gz=be1957674fdda24a9cd8935789db35a17d3a0d71219bb6f1256af74c64ffc697 +dist/2024-09-04/rustc-nightly-powerpc-unknown-linux-gnu.tar.xz=20541daa3925834012ab68f186a1f1ab4d060cced96646e2142a0f14c04b6ad6 +dist/2024-09-04/rustc-nightly-powerpc64-unknown-linux-gnu.tar.gz=0eb6741b87d430573c9b0d5b9ba9725c0c03caabc01d5ee258867ea19aedafdc +dist/2024-09-04/rustc-nightly-powerpc64-unknown-linux-gnu.tar.xz=8ad4670b74093e3c7055149649145a4af2b2a3d24a68bf893ed72202cc934946 +dist/2024-09-04/rustc-nightly-powerpc64le-unknown-linux-gnu.tar.gz=2d7b60aa2d4853eba2bb2644cb14768a5a864386da0854aca7c1f6397374dca2 +dist/2024-09-04/rustc-nightly-powerpc64le-unknown-linux-gnu.tar.xz=17792328178392ad96b1a0c05405c61d0b1e7196bdca9e55baebff12a4949725 +dist/2024-09-04/rustc-nightly-riscv64gc-unknown-linux-gnu.tar.gz=2db9fe19d4e1d7f68a0802868d9344e23932190e2d46407523208a67b5ba053a +dist/2024-09-04/rustc-nightly-riscv64gc-unknown-linux-gnu.tar.xz=f0d4df5e4cfeff06eb2cb07c6f9ac0596130923133571fd1702d56a0251ebb99 +dist/2024-09-04/rustc-nightly-s390x-unknown-linux-gnu.tar.gz=4d3fea9ec53336195c0daa2b2937507c2216537647829466a19acee2ce9e201a +dist/2024-09-04/rustc-nightly-s390x-unknown-linux-gnu.tar.xz=84ca3dccf7af68a343fed4d209771bac7439149695f63517bd048287f4539add +dist/2024-09-04/rustc-nightly-x86_64-apple-darwin.tar.gz=f6f43ebb82851edae301033a2cfbd02724849c7fda42294818f3081f74d3a1a3 +dist/2024-09-04/rustc-nightly-x86_64-apple-darwin.tar.xz=55b0db99f02bd4c5595117663f6b6cc739f63723999062ced0096727e627f072 +dist/2024-09-04/rustc-nightly-x86_64-pc-windows-gnu.tar.gz=6cb63e57f9873e40695b735b8cdb9f0de70306f1692161cd8f7767b4016dcf39 +dist/2024-09-04/rustc-nightly-x86_64-pc-windows-gnu.tar.xz=79bf54beceda0a7f6580d3ef336d8deae3991b3b57e4c6aba635f9d848cc860d +dist/2024-09-04/rustc-nightly-x86_64-pc-windows-msvc.tar.gz=7757651c78d5000926bd5e91996ea8abdc32db8e67b31271cb70680f551edd5f +dist/2024-09-04/rustc-nightly-x86_64-pc-windows-msvc.tar.xz=4671e03fc7100bac43cf332e387161c0ccde77d3f893a9dfdd27be63fff39932 +dist/2024-09-04/rustc-nightly-x86_64-unknown-freebsd.tar.gz=675f49fc6a51d5e715789bc9ad92b9db12a94a033254e34efb65358700207bb5 +dist/2024-09-04/rustc-nightly-x86_64-unknown-freebsd.tar.xz=f9efc43f26600caf2ef7c8084fe94ae31ba540ae7e9f104e6a587c6e4272cd6b +dist/2024-09-04/rustc-nightly-x86_64-unknown-illumos.tar.gz=9bd74b7ee78a02306f47640b99d752ea373ffdd88067376d9f03564f07edfb24 +dist/2024-09-04/rustc-nightly-x86_64-unknown-illumos.tar.xz=67c5d546df9fa451d42804de2d439229e9b21eb9329ff16eeadcc52f5b6393d1 +dist/2024-09-04/rustc-nightly-x86_64-unknown-linux-gnu.tar.gz=dfc427db6a14237a12fd077ccc44c07e7bb46a1b2965a3fb1ddd78a2ec334b81 +dist/2024-09-04/rustc-nightly-x86_64-unknown-linux-gnu.tar.xz=8d307dce871ae5f7cc1410e85bb7b38f80aed5c1138030b4f112e727fb8c654b +dist/2024-09-04/rustc-nightly-x86_64-unknown-linux-musl.tar.gz=b7f84d8aab03afcf2bab8ed21fa3ece6ac418d076e0195381110adfac2aa1fbc +dist/2024-09-04/rustc-nightly-x86_64-unknown-linux-musl.tar.xz=296083c6b50b7dffe8a62884bac7e831e29487a31c8e6fb319f04f0e62157175 +dist/2024-09-04/rustc-nightly-x86_64-unknown-netbsd.tar.gz=96986595ce82c735b87fe75f00722514c49e7118d38c4bced554c9017377ec91 +dist/2024-09-04/rustc-nightly-x86_64-unknown-netbsd.tar.xz=bf8c9411ff7279fd56bb7e3c68ac29c8ce79ba031317b76aac6a74d20f1511f0 \ No newline at end of file From 4df28b8bf1c3e9dade6ab29358effc99010f594b Mon Sep 17 00:00:00 2001 From: chenx97 Date: Wed, 4 Sep 2024 14:44:23 +0800 Subject: [PATCH 0477/2194] forward linker option to lint-docs --- src/bootstrap/src/core/build_steps/doc.rs | 3 +++ src/tools/lint-docs/src/lib.rs | 5 +++++ src/tools/lint-docs/src/main.rs | 8 ++++++++ 3 files changed, 16 insertions(+) diff --git a/src/bootstrap/src/core/build_steps/doc.rs b/src/bootstrap/src/core/build_steps/doc.rs index ffb617c642baf..ac68bbf805092 100644 --- a/src/bootstrap/src/core/build_steps/doc.rs +++ b/src/bootstrap/src/core/build_steps/doc.rs @@ -1186,6 +1186,9 @@ impl Step for RustcBook { cmd.arg("--rustc"); cmd.arg(&rustc); cmd.arg("--rustc-target").arg(self.target.rustc_target_arg()); + if let Some(target_linker) = builder.linker(self.target) { + cmd.arg("--rustc-linker").arg(target_linker); + } if builder.is_verbose() { cmd.arg("--verbose"); } diff --git a/src/tools/lint-docs/src/lib.rs b/src/tools/lint-docs/src/lib.rs index 72bb9db7e7414..532a27b22aa6f 100644 --- a/src/tools/lint-docs/src/lib.rs +++ b/src/tools/lint-docs/src/lib.rs @@ -56,6 +56,8 @@ pub struct LintExtractor<'a> { pub rustc_path: &'a Path, /// The target arch to build the docs for. pub rustc_target: &'a str, + /// The target linker overriding `rustc`'s default + pub rustc_linker: Option<&'a str>, /// Verbose output. pub verbose: bool, /// Validate the style and the code example. @@ -459,6 +461,9 @@ impl<'a> LintExtractor<'a> { } cmd.arg("--error-format=json"); cmd.arg("--target").arg(self.rustc_target); + if let Some(target_linker) = self.rustc_linker { + cmd.arg(format!("-Clinker={target_linker}")); + } if options.contains(&"test") { cmd.arg("--test"); } diff --git a/src/tools/lint-docs/src/main.rs b/src/tools/lint-docs/src/main.rs index 2055fed2b480c..e377283b1a453 100644 --- a/src/tools/lint-docs/src/main.rs +++ b/src/tools/lint-docs/src/main.rs @@ -27,6 +27,7 @@ fn doit() -> Result<(), Box> { let mut out_path = None; let mut rustc_path = None; let mut rustc_target = None; + let mut rustc_linker = None; let mut verbose = false; let mut validate = false; while let Some(arg) = args.next() { @@ -55,6 +56,12 @@ fn doit() -> Result<(), Box> { None => return Err("--rustc-target requires a value".into()), }; } + "--rustc-linker" => { + rustc_linker = match args.next() { + Some(s) => Some(s), + None => return Err("--rustc-linker requires a value".into()), + }; + } "-v" | "--verbose" => verbose = true, "--validate" => validate = true, s => return Err(format!("unexpected argument `{}`", s).into()), @@ -77,6 +84,7 @@ fn doit() -> Result<(), Box> { out_path: &out_path.unwrap(), rustc_path: &rustc_path.unwrap(), rustc_target: &rustc_target.unwrap(), + rustc_linker: rustc_linker.as_deref(), verbose, validate, }; From 9cb6d12f00426dd6fe1f32575a58fc6ef071b680 Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Tue, 3 Sep 2024 22:54:32 +0300 Subject: [PATCH 0478/2194] use the bootstrapped compiler for `test-float-parse` test Signed-off-by: onur-ozkan --- src/bootstrap/src/core/build_steps/test.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/bootstrap/src/core/build_steps/test.rs b/src/bootstrap/src/core/build_steps/test.rs index 84a6b26a491ed..0858edc690b71 100644 --- a/src/bootstrap/src/core/build_steps/test.rs +++ b/src/bootstrap/src/core/build_steps/test.rs @@ -3526,11 +3526,13 @@ impl Step for TestFloatParse { fn run(self, builder: &Builder<'_>) { let bootstrap_host = builder.config.build; - let compiler = builder.compiler(0, bootstrap_host); + let compiler = builder.compiler(builder.top_stage, bootstrap_host); let path = self.path.to_str().unwrap(); let crate_name = self.path.components().last().unwrap().as_os_str().to_str().unwrap(); - builder.ensure(compile::Std::new(compiler, self.host)); + if !builder.download_rustc() { + builder.ensure(compile::Std::new(compiler, self.host)); + } // Run any unit tests in the crate let cargo_test = tool::prepare_tool_cargo( From 01b1bfd18aa97c42bdee359260561b27e351e9a6 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Wed, 4 Sep 2024 11:32:59 +0200 Subject: [PATCH 0479/2194] Add edition dependent keyword highlighting tests --- .../test_data/highlight_keywords_2015.html | 74 +++++++++++++++++++ .../test_data/highlight_keywords_2018.html | 74 +++++++++++++++++++ .../test_data/highlight_keywords_2021.html | 74 +++++++++++++++++++ .../test_data/highlight_keywords_2024.html | 74 +++++++++++++++++++ .../ide/src/syntax_highlighting/tests.rs | 31 ++++++-- .../crates/parser/src/edition.rs | 6 ++ 6 files changed, 326 insertions(+), 7 deletions(-) create mode 100644 src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_keywords_2015.html create mode 100644 src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_keywords_2018.html create mode 100644 src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_keywords_2021.html create mode 100644 src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_keywords_2024.html diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_keywords_2015.html b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_keywords_2015.html new file mode 100644 index 0000000000000..a790b385786d8 --- /dev/null +++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_keywords_2015.html @@ -0,0 +1,74 @@ + + +
extern crate self;
+
+use crate;
+use self;
+mod __ {
+    use super::*;
+}
+
+macro_rules! void {
+    ($($tt:tt)*) => {}
+}
+
+struct __ where Self:;
+fn __(_: Self) {}
+void!(Self);
+
+// edition dependent
+void!(try async await gen);
+// edition and context dependent
+void!(dyn);
+// builtin custom syntax
+void!(builtin offset_of format_args asm);
+// contextual
+void!(macro_rules, union, default, raw, auto, yeet);
+// reserved
+void!(abstract become box do final macro override priv typeof unsized virtual yield);
+void!('static 'self 'unsafe)
\ No newline at end of file diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_keywords_2018.html b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_keywords_2018.html new file mode 100644 index 0000000000000..6dac066bfaa19 --- /dev/null +++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_keywords_2018.html @@ -0,0 +1,74 @@ + + +
extern crate self;
+
+use crate;
+use self;
+mod __ {
+    use super::*;
+}
+
+macro_rules! void {
+    ($($tt:tt)*) => {}
+}
+
+struct __ where Self:;
+fn __(_: Self) {}
+void!(Self);
+
+// edition dependent
+void!(try async await gen);
+// edition and context dependent
+void!(dyn);
+// builtin custom syntax
+void!(builtin offset_of format_args asm);
+// contextual
+void!(macro_rules, union, default, raw, auto, yeet);
+// reserved
+void!(abstract become box do final macro override priv typeof unsized virtual yield);
+void!('static 'self 'unsafe)
\ No newline at end of file diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_keywords_2021.html b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_keywords_2021.html new file mode 100644 index 0000000000000..6dac066bfaa19 --- /dev/null +++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_keywords_2021.html @@ -0,0 +1,74 @@ + + +
extern crate self;
+
+use crate;
+use self;
+mod __ {
+    use super::*;
+}
+
+macro_rules! void {
+    ($($tt:tt)*) => {}
+}
+
+struct __ where Self:;
+fn __(_: Self) {}
+void!(Self);
+
+// edition dependent
+void!(try async await gen);
+// edition and context dependent
+void!(dyn);
+// builtin custom syntax
+void!(builtin offset_of format_args asm);
+// contextual
+void!(macro_rules, union, default, raw, auto, yeet);
+// reserved
+void!(abstract become box do final macro override priv typeof unsized virtual yield);
+void!('static 'self 'unsafe)
\ No newline at end of file diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_keywords_2024.html b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_keywords_2024.html new file mode 100644 index 0000000000000..4ccc40799088a --- /dev/null +++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_keywords_2024.html @@ -0,0 +1,74 @@ + + +
extern crate self;
+
+use crate;
+use self;
+mod __ {
+    use super::*;
+}
+
+macro_rules! void {
+    ($($tt:tt)*) => {}
+}
+
+struct __ where Self:;
+fn __(_: Self) {}
+void!(Self);
+
+// edition dependent
+void!(try async await gen);
+// edition and context dependent
+void!(dyn);
+// builtin custom syntax
+void!(builtin offset_of format_args asm);
+// contextual
+void!(macro_rules, union, default, raw, auto, yeet);
+// reserved
+void!(abstract become box do final macro override priv typeof unsized virtual yield);
+void!('static 'self 'unsafe)
\ No newline at end of file diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/tests.rs b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/tests.rs index ad7fbb00e5c66..c06ea155fb86b 100644 --- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/tests.rs +++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/tests.rs @@ -2,6 +2,7 @@ use std::time::Instant; use expect_test::{expect_file, ExpectFile}; use ide_db::SymbolKind; +use span::Edition; use test_utils::{bench, bench_fixture, skip_slow_tests, AssertLinear}; use crate::{fixture, FileRange, HighlightConfig, HlTag, TextRange}; @@ -383,8 +384,10 @@ where #[test] fn test_keyword_highlighting() { - check_highlighting( - r#" + for edition in Edition::iter() { + check_highlighting( + &(format!("//- /main.rs crate:main edition:{edition}") + + r#" extern crate self; use crate; @@ -396,13 +399,27 @@ mod __ { macro_rules! void { ($($tt:tt)*) => {} } -void!(Self); + struct __ where Self:; fn __(_: Self) {} -"#, - expect_file!["./test_data/highlight_keywords.html"], - false, - ); +void!(Self); + +// edition dependent +void!(try async await gen); +// edition and context dependent +void!(dyn); +// builtin custom syntax +void!(builtin offset_of format_args asm); +// contextual +void!(macro_rules, union, default, raw, auto, yeet); +// reserved +void!(abstract become box do final macro override priv typeof unsized virtual yield); +void!('static 'self 'unsafe) +"#), + expect_file![format!("./test_data/highlight_keywords_{edition}.html")], + false, + ); + } } #[test] diff --git a/src/tools/rust-analyzer/crates/parser/src/edition.rs b/src/tools/rust-analyzer/crates/parser/src/edition.rs index be0a2c794e58c..702b16252d4e7 100644 --- a/src/tools/rust-analyzer/crates/parser/src/edition.rs +++ b/src/tools/rust-analyzer/crates/parser/src/edition.rs @@ -30,6 +30,12 @@ impl Edition { pub fn at_least_2018(self) -> bool { self >= Edition::Edition2018 } + + pub fn iter() -> impl Iterator { + [Edition::Edition2015, Edition::Edition2018, Edition::Edition2021, Edition::Edition2024] + .iter() + .copied() + } } #[derive(Debug)] From 93b4b2d51cd55177fedf1a38173c7e9576e98d31 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Le=C3=B3n=20Orell=20Valerian=20Liehr?= Date: Wed, 4 Sep 2024 11:43:38 +0200 Subject: [PATCH 0480/2194] Temporarily remove fmease from the review rotation --- triagebot.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/triagebot.toml b/triagebot.toml index 1afcad7d1315c..f379f8cc7af50 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -914,6 +914,7 @@ cc = ["@kobzol"] warn_non_default_branch = true contributing_url = "https://rustc-dev-guide.rust-lang.org/getting-started.html" users_on_vacation = [ + "fmease", "jhpratt", "joboet", "jyn514", From 1e7d99ff4392e10c5d6195d624ba3de846198c88 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Wed, 4 Sep 2024 11:48:03 +0200 Subject: [PATCH 0481/2194] fix: Fix lowering of for loops dropping the `loop` block --- .../crates/hir-def/src/body/lower.rs | 31 +++++++++++----- .../crates/hir-def/src/body/tests.rs | 35 +++++++++++++++++++ .../crates/hir-ty/src/tests/macros.rs | 2 ++ .../crates/hir-ty/src/tests/never_type.rs | 3 ++ .../crates/hir-ty/src/tests/patterns.rs | 1 + .../crates/hir-ty/src/tests/regression.rs | 2 ++ 6 files changed, 65 insertions(+), 9 deletions(-) diff --git a/src/tools/rust-analyzer/crates/hir-def/src/body/lower.rs b/src/tools/rust-analyzer/crates/hir-def/src/body/lower.rs index abf7895829206..145afc1b610c2 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/body/lower.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/body/lower.rs @@ -737,7 +737,7 @@ impl ExprCollector<'_> { /// `try { ; }` into `': { ; ::std::ops::Try::from_output(()) }` /// and save the `` to use it as a break target for desugaring of the `?` operator. fn desugar_try_block(&mut self, e: BlockExpr) -> ExprId { - let Some(try_from_output) = LangItem::TryTraitFromOutput.path(self.db, self.krate) else { + let Some(try_from_output) = self.lang_path(LangItem::TryTraitFromOutput) else { return self.collect_block(e); }; let label = self @@ -840,10 +840,10 @@ impl ExprCollector<'_> { fn collect_for_loop(&mut self, syntax_ptr: AstPtr, e: ast::ForExpr) -> ExprId { let Some((into_iter_fn, iter_next_fn, option_some, option_none)) = (|| { Some(( - LangItem::IntoIterIntoIter.path(self.db, self.krate)?, - LangItem::IteratorNext.path(self.db, self.krate)?, - LangItem::OptionSome.path(self.db, self.krate)?, - LangItem::OptionNone.path(self.db, self.krate)?, + self.lang_path(LangItem::IntoIterIntoIter)?, + self.lang_path(LangItem::IteratorNext)?, + self.lang_path(LangItem::OptionSome)?, + self.lang_path(LangItem::OptionNone)?, )) })() else { // Some of the needed lang items are missing, so we can't desugar @@ -896,6 +896,15 @@ impl ExprCollector<'_> { Expr::Match { expr: iter_next_expr, arms: Box::new([none_arm, some_arm]) }, syntax_ptr, ); + let loop_inner = self.alloc_expr( + Expr::Block { + id: None, + statements: Box::default(), + tail: Some(loop_inner), + label: None, + }, + syntax_ptr, + ); let loop_outer = self.alloc_expr(Expr::Loop { body: loop_inner, label }, syntax_ptr); let iter_binding = self.alloc_binding(iter_name, BindingAnnotation::Mutable); let iter_pat = self.alloc_pat_desugared(Pat::Bind { id: iter_binding, subpat: None }); @@ -923,10 +932,10 @@ impl ExprCollector<'_> { fn collect_try_operator(&mut self, syntax_ptr: AstPtr, e: ast::TryExpr) -> ExprId { let Some((try_branch, cf_continue, cf_break, try_from_residual)) = (|| { Some(( - LangItem::TryTraitBranch.path(self.db, self.krate)?, - LangItem::ControlFlowContinue.path(self.db, self.krate)?, - LangItem::ControlFlowBreak.path(self.db, self.krate)?, - LangItem::TryTraitFromResidual.path(self.db, self.krate)?, + self.lang_path(LangItem::TryTraitBranch)?, + self.lang_path(LangItem::ControlFlowContinue)?, + self.lang_path(LangItem::ControlFlowBreak)?, + self.lang_path(LangItem::TryTraitFromResidual)?, )) })() else { // Some of the needed lang items are missing, so we can't desugar @@ -2053,6 +2062,10 @@ impl ExprCollector<'_> { }) } // endregion: format + + fn lang_path(&self, lang: LangItem) -> Option { + lang.path(self.db, self.krate) + } } fn pat_literal_to_hir(lit: &ast::LiteralPat) -> Option<(Literal, ast::Literal)> { diff --git a/src/tools/rust-analyzer/crates/hir-def/src/body/tests.rs b/src/tools/rust-analyzer/crates/hir-def/src/body/tests.rs index 38fc01d8fca5f..dd3e79c874d85 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/body/tests.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/body/tests.rs @@ -142,6 +142,41 @@ mod m { ); } +#[test] +fn desugar_for_loop() { + let (db, body, def) = lower( + r#" +//- minicore: iterator +fn main() { + for ident in 0..10 { + foo(); + bar() + } +} +"#, + ); + + expect![[r#" + fn main() -> () { + match builtin#lang(into_iter)( + (0) ..(10) , + ) { + mut 11 => loop { + match builtin#lang(next)( + &mut 11, + ) { + builtin#lang(None) => break, + builtin#lang(Some)(ident) => { + foo(); + bar() + }, + } + }, + } + }"#]] + .assert_eq(&body.pretty_print(&db, def, Edition::CURRENT)) +} + #[test] fn desugar_builtin_format_args() { let (db, body, def) = lower( diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/tests/macros.rs b/src/tools/rust-analyzer/crates/hir-ty/src/tests/macros.rs index 5454a496ba8c1..5a6161f94289f 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/tests/macros.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/tests/macros.rs @@ -206,6 +206,7 @@ fn expr_macro_def_expanded_in_various_places() { 100..119 'for _ ...!() {}': () 100..119 'for _ ...!() {}': () 100..119 'for _ ...!() {}': () + 100..119 'for _ ...!() {}': () 104..105 '_': IntoIterator::Item 117..119 '{}': () 124..134 '|| spam!()': impl Fn() -> isize @@ -299,6 +300,7 @@ fn expr_macro_rules_expanded_in_various_places() { 114..133 'for _ ...!() {}': () 114..133 'for _ ...!() {}': () 114..133 'for _ ...!() {}': () + 114..133 'for _ ...!() {}': () 118..119 '_': IntoIterator::Item 131..133 '{}': () 138..148 '|| spam!()': impl Fn() -> isize diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/tests/never_type.rs b/src/tools/rust-analyzer/crates/hir-ty/src/tests/never_type.rs index 0ccbcf63e2b67..5c63cd00f97d9 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/tests/never_type.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/tests/never_type.rs @@ -371,6 +371,7 @@ fn diverging_expression_3_break() { 151..172 'for a ...eak; }': () 151..172 'for a ...eak; }': () 151..172 'for a ...eak; }': () + 151..172 'for a ...eak; }': () 155..156 'a': {unknown} 160..161 'b': {unknown} 162..172 '{ break; }': () @@ -387,6 +388,7 @@ fn diverging_expression_3_break() { 237..250 'for a in b {}': () 237..250 'for a in b {}': () 237..250 'for a in b {}': () + 237..250 'for a in b {}': () 241..242 'a': {unknown} 246..247 'b': {unknown} 248..250 '{}': () @@ -402,6 +404,7 @@ fn diverging_expression_3_break() { 315..337 'for a ...urn; }': () 315..337 'for a ...urn; }': () 315..337 'for a ...urn; }': () + 315..337 'for a ...urn; }': () 319..320 'a': {unknown} 324..325 'b': {unknown} 326..337 '{ return; }': () diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/tests/patterns.rs b/src/tools/rust-analyzer/crates/hir-ty/src/tests/patterns.rs index 57866acc06374..51c27f8714ac5 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/tests/patterns.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/tests/patterns.rs @@ -57,6 +57,7 @@ fn infer_pattern() { 101..151 'for (e... }': () 101..151 'for (e... }': () 101..151 'for (e... }': () + 101..151 'for (e... }': () 105..111 '(e, f)': ({unknown}, {unknown}) 106..107 'e': {unknown} 109..110 'f': {unknown} diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/tests/regression.rs b/src/tools/rust-analyzer/crates/hir-ty/src/tests/regression.rs index 4df10025f80fb..db289f430eafb 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/tests/regression.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/tests/regression.rs @@ -275,6 +275,7 @@ fn infer_std_crash_5() { 32..320 'for co... }': () 32..320 'for co... }': () 32..320 'for co... }': () + 32..320 'for co... }': () 36..43 'content': {unknown} 47..60 'doesnt_matter': {unknown} 61..320 '{ ... }': () @@ -1244,6 +1245,7 @@ fn test() { 16..66 'for _ ... }': () 16..66 'for _ ... }': () 16..66 'for _ ... }': () + 16..66 'for _ ... }': () 20..21 '_': IntoIterator::Item<()> 25..39 '{ let x = 0; }': () 31..32 'x': i32 From 8860008e7f3bf67c420d2d1ce4bc333c08886eb2 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 28 Aug 2024 18:27:41 -0400 Subject: [PATCH 0482/2194] Re-parent the by-move body --- .../rustc_mir_transform/src/coroutine/by_move_body.rs | 3 ++- ...closure#0}-{closure#0}-{closure#0}.built.after.mir} | 2 +- ...closure#0}-{closure#0}-{closure#1}.built.after.mir} | 4 ++-- ...ure#0}-{closure#0}.coroutine_closure_by_move.0.mir} | 6 +++--- ...ure#0}.coroutine_closure_by_move.0.panic-unwind.mir | 10 ---------- ...closure#0}-{closure#1}-{closure#0}.built.after.mir} | 2 +- ...closure#0}-{closure#1}-{closure#1}.built.after.mir} | 4 ++-- ...ure#0}-{closure#1}.coroutine_closure_by_move.0.mir} | 6 +++--- ...ure#1}.coroutine_closure_by_move.0.panic-unwind.mir | 10 ---------- ...sure#0}-{closure#1}.coroutine_closure_by_ref.0.mir} | 6 +++--- ...sure#1}.coroutine_closure_by_ref.0.panic-unwind.mir | 10 ---------- tests/mir-opt/async_closure_shims.rs | 5 ++--- 12 files changed, 19 insertions(+), 49 deletions(-) rename tests/mir-opt/{async_closure_shims.main-{closure#0}-{closure#0}-{closure#0}.built.after.panic-unwind.mir => async_closure_shims.main-{closure#0}-{closure#0}-{closure#0}.built.after.mir} (93%) rename tests/mir-opt/{async_closure_shims.main-{closure#0}-{closure#0}-{closure#0}-{closure#0}.built.after.panic-unwind.mir => async_closure_shims.main-{closure#0}-{closure#0}-{closure#1}.built.after.mir} (78%) rename tests/mir-opt/{async_closure_shims.main-{closure#0}-{closure#0}.coroutine_closure_by_move.0.panic-abort.mir => async_closure_shims.main-{closure#0}-{closure#0}.coroutine_closure_by_move.0.mir} (60%) delete mode 100644 tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#0}.coroutine_closure_by_move.0.panic-unwind.mir rename tests/mir-opt/{async_closure_shims.main-{closure#0}-{closure#1}-{closure#0}.built.after.panic-unwind.mir => async_closure_shims.main-{closure#0}-{closure#1}-{closure#0}.built.after.mir} (93%) rename tests/mir-opt/{async_closure_shims.main-{closure#0}-{closure#1}-{closure#0}-{closure#0}.built.after.panic-unwind.mir => async_closure_shims.main-{closure#0}-{closure#1}-{closure#1}.built.after.mir} (79%) rename tests/mir-opt/{async_closure_shims.main-{closure#0}-{closure#1}.coroutine_closure_by_move.0.panic-abort.mir => async_closure_shims.main-{closure#0}-{closure#1}.coroutine_closure_by_move.0.mir} (60%) delete mode 100644 tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#1}.coroutine_closure_by_move.0.panic-unwind.mir rename tests/mir-opt/{async_closure_shims.main-{closure#0}-{closure#1}.coroutine_closure_by_ref.0.panic-abort.mir => async_closure_shims.main-{closure#0}-{closure#1}.coroutine_closure_by_ref.0.mir} (60%) delete mode 100644 tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#1}.coroutine_closure_by_ref.0.panic-unwind.mir diff --git a/compiler/rustc_mir_transform/src/coroutine/by_move_body.rs b/compiler/rustc_mir_transform/src/coroutine/by_move_body.rs index 79cdca5d937fd..cf39c136b01a3 100644 --- a/compiler/rustc_mir_transform/src/coroutine/by_move_body.rs +++ b/compiler/rustc_mir_transform/src/coroutine/by_move_body.rs @@ -208,7 +208,8 @@ pub fn coroutine_by_move_body_def_id<'tcx>( let mut by_move_body = body.clone(); MakeByMoveBody { tcx, field_remapping, by_move_coroutine_ty }.visit_body(&mut by_move_body); - let body_def = tcx.create_def(coroutine_def_id, kw::Empty, DefKind::SyntheticCoroutineBody); + // This will always be `{closure#1}`, since the original coroutine is `{closure#0}`. + let body_def = tcx.create_def(parent_def_id, kw::Empty, DefKind::SyntheticCoroutineBody); by_move_body.source = mir::MirSource::from_instance(InstanceKind::Item(body_def.def_id().to_def_id())); dump_mir(tcx, false, "built", &"after", &by_move_body, |_, _| Ok(())); diff --git a/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#0}-{closure#0}.built.after.panic-unwind.mir b/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#0}-{closure#0}.built.after.mir similarity index 93% rename from tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#0}-{closure#0}.built.after.panic-unwind.mir rename to tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#0}-{closure#0}.built.after.mir index d273512b91fdb..7da33b8a094b3 100644 --- a/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#0}-{closure#0}.built.after.panic-unwind.mir +++ b/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#0}-{closure#0}.built.after.mir @@ -1,6 +1,6 @@ // MIR for `main::{closure#0}::{closure#0}::{closure#0}` after built -fn main::{closure#0}::{closure#0}::{closure#0}(_1: {async closure body@$DIR/async_closure_shims.rs:55:53: 58:10}, _2: ResumeTy) -> () +fn main::{closure#0}::{closure#0}::{closure#0}(_1: {async closure body@$DIR/async_closure_shims.rs:54:53: 57:10}, _2: ResumeTy) -> () yields () { debug _task_context => _2; diff --git a/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#0}-{closure#0}-{closure#0}.built.after.panic-unwind.mir b/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#0}-{closure#1}.built.after.mir similarity index 78% rename from tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#0}-{closure#0}-{closure#0}.built.after.panic-unwind.mir rename to tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#0}-{closure#1}.built.after.mir index 80def6c89a190..a21e82ef5b633 100644 --- a/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#0}-{closure#0}-{closure#0}.built.after.panic-unwind.mir +++ b/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#0}-{closure#1}.built.after.mir @@ -1,6 +1,6 @@ -// MIR for `main::{closure#0}::{closure#0}::{closure#0}::{closure#0}` after built +// MIR for `main::{closure#0}::{closure#0}::{closure#1}` after built -fn main::{closure#0}::{closure#0}::{closure#0}::{closure#0}(_1: {async closure body@$DIR/async_closure_shims.rs:55:53: 58:10}, _2: ResumeTy) -> () +fn main::{closure#0}::{closure#0}::{closure#1}(_1: {async closure body@$DIR/async_closure_shims.rs:54:53: 57:10}, _2: ResumeTy) -> () yields () { debug _task_context => _2; diff --git a/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#0}.coroutine_closure_by_move.0.panic-abort.mir b/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#0}.coroutine_closure_by_move.0.mir similarity index 60% rename from tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#0}.coroutine_closure_by_move.0.panic-abort.mir rename to tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#0}.coroutine_closure_by_move.0.mir index a984845fd2c11..c156636099519 100644 --- a/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#0}.coroutine_closure_by_move.0.panic-abort.mir +++ b/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#0}.coroutine_closure_by_move.0.mir @@ -1,10 +1,10 @@ // MIR for `main::{closure#0}::{closure#0}` 0 coroutine_closure_by_move -fn main::{closure#0}::{closure#0}(_1: {async closure@$DIR/async_closure_shims.rs:53:33: 53:52}, _2: i32) -> {async closure body@$DIR/async_closure_shims.rs:53:53: 56:10} { - let mut _0: {async closure body@$DIR/async_closure_shims.rs:53:53: 56:10}; +fn main::{closure#0}::{closure#0}(_1: {async closure@$DIR/async_closure_shims.rs:54:33: 54:52}, _2: i32) -> {async closure body@$DIR/async_closure_shims.rs:54:53: 57:10} { + let mut _0: {async closure body@$DIR/async_closure_shims.rs:54:53: 57:10}; bb0: { - _0 = {coroutine@$DIR/async_closure_shims.rs:53:53: 56:10 (#0)} { a: move _2, b: move (_1.0: i32) }; + _0 = {coroutine@$DIR/async_closure_shims.rs:54:53: 57:10 (#0)} { a: move _2, b: move (_1.0: i32) }; return; } } diff --git a/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#0}.coroutine_closure_by_move.0.panic-unwind.mir b/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#0}.coroutine_closure_by_move.0.panic-unwind.mir deleted file mode 100644 index ce1d06ce1d3e9..0000000000000 --- a/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#0}.coroutine_closure_by_move.0.panic-unwind.mir +++ /dev/null @@ -1,10 +0,0 @@ -// MIR for `main::{closure#0}::{closure#0}` 0 coroutine_closure_by_move - -fn main::{closure#0}::{closure#0}(_1: {async closure@$DIR/async_closure_shims.rs:55:33: 55:52}, _2: i32) -> {async closure body@$DIR/async_closure_shims.rs:55:53: 58:10} { - let mut _0: {async closure body@$DIR/async_closure_shims.rs:55:53: 58:10}; - - bb0: { - _0 = {coroutine@$DIR/async_closure_shims.rs:55:53: 58:10 (#0)} { a: move _2, b: move (_1.0: i32) }; - return; - } -} diff --git a/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#1}-{closure#0}.built.after.panic-unwind.mir b/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#1}-{closure#0}.built.after.mir similarity index 93% rename from tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#1}-{closure#0}.built.after.panic-unwind.mir rename to tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#1}-{closure#0}.built.after.mir index b4765c0b74ca8..a4a6a535a2313 100644 --- a/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#1}-{closure#0}.built.after.panic-unwind.mir +++ b/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#1}-{closure#0}.built.after.mir @@ -1,6 +1,6 @@ // MIR for `main::{closure#0}::{closure#1}::{closure#0}` after built -fn main::{closure#0}::{closure#1}::{closure#0}(_1: {async closure body@$DIR/async_closure_shims.rs:64:48: 67:10}, _2: ResumeTy) -> () +fn main::{closure#0}::{closure#1}::{closure#0}(_1: {async closure body@$DIR/async_closure_shims.rs:63:48: 66:10}, _2: ResumeTy) -> () yields () { debug _task_context => _2; diff --git a/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#1}-{closure#0}-{closure#0}.built.after.panic-unwind.mir b/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#1}-{closure#1}.built.after.mir similarity index 79% rename from tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#1}-{closure#0}-{closure#0}.built.after.panic-unwind.mir rename to tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#1}-{closure#1}.built.after.mir index cea330cf2f7f4..69bba6f519414 100644 --- a/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#1}-{closure#0}-{closure#0}.built.after.panic-unwind.mir +++ b/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#1}-{closure#1}.built.after.mir @@ -1,6 +1,6 @@ -// MIR for `main::{closure#0}::{closure#1}::{closure#0}::{closure#0}` after built +// MIR for `main::{closure#0}::{closure#1}::{closure#1}` after built -fn main::{closure#0}::{closure#1}::{closure#0}::{closure#0}(_1: {async closure body@$DIR/async_closure_shims.rs:64:48: 67:10}, _2: ResumeTy) -> () +fn main::{closure#0}::{closure#1}::{closure#1}(_1: {async closure body@$DIR/async_closure_shims.rs:63:48: 66:10}, _2: ResumeTy) -> () yields () { debug _task_context => _2; diff --git a/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#1}.coroutine_closure_by_move.0.panic-abort.mir b/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#1}.coroutine_closure_by_move.0.mir similarity index 60% rename from tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#1}.coroutine_closure_by_move.0.panic-abort.mir rename to tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#1}.coroutine_closure_by_move.0.mir index aab9f7b03b9ab..134fe145baeee 100644 --- a/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#1}.coroutine_closure_by_move.0.panic-abort.mir +++ b/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#1}.coroutine_closure_by_move.0.mir @@ -1,10 +1,10 @@ // MIR for `main::{closure#0}::{closure#1}` 0 coroutine_closure_by_move -fn main::{closure#0}::{closure#1}(_1: {async closure@$DIR/async_closure_shims.rs:62:33: 62:47}, _2: i32) -> {async closure body@$DIR/async_closure_shims.rs:62:48: 65:10} { - let mut _0: {async closure body@$DIR/async_closure_shims.rs:62:48: 65:10}; +fn main::{closure#0}::{closure#1}(_1: {async closure@$DIR/async_closure_shims.rs:63:33: 63:47}, _2: i32) -> {async closure body@$DIR/async_closure_shims.rs:63:48: 66:10} { + let mut _0: {async closure body@$DIR/async_closure_shims.rs:63:48: 66:10}; bb0: { - _0 = {coroutine@$DIR/async_closure_shims.rs:62:48: 65:10 (#0)} { a: move _2, b: move (_1.0: &i32) }; + _0 = {coroutine@$DIR/async_closure_shims.rs:63:48: 66:10 (#0)} { a: move _2, b: move (_1.0: &i32) }; return; } } diff --git a/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#1}.coroutine_closure_by_move.0.panic-unwind.mir b/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#1}.coroutine_closure_by_move.0.panic-unwind.mir deleted file mode 100644 index 8452c79bf41bb..0000000000000 --- a/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#1}.coroutine_closure_by_move.0.panic-unwind.mir +++ /dev/null @@ -1,10 +0,0 @@ -// MIR for `main::{closure#0}::{closure#1}` 0 coroutine_closure_by_move - -fn main::{closure#0}::{closure#1}(_1: {async closure@$DIR/async_closure_shims.rs:64:33: 64:47}, _2: i32) -> {async closure body@$DIR/async_closure_shims.rs:64:48: 67:10} { - let mut _0: {async closure body@$DIR/async_closure_shims.rs:64:48: 67:10}; - - bb0: { - _0 = {coroutine@$DIR/async_closure_shims.rs:64:48: 67:10 (#0)} { a: move _2, b: move (_1.0: &i32) }; - return; - } -} diff --git a/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#1}.coroutine_closure_by_ref.0.panic-abort.mir b/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#1}.coroutine_closure_by_ref.0.mir similarity index 60% rename from tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#1}.coroutine_closure_by_ref.0.panic-abort.mir rename to tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#1}.coroutine_closure_by_ref.0.mir index 3fdc81791deef..f267d93bd606c 100644 --- a/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#1}.coroutine_closure_by_ref.0.panic-abort.mir +++ b/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#1}.coroutine_closure_by_ref.0.mir @@ -1,10 +1,10 @@ // MIR for `main::{closure#0}::{closure#1}` 0 coroutine_closure_by_ref -fn main::{closure#0}::{closure#1}(_1: &{async closure@$DIR/async_closure_shims.rs:62:33: 62:47}, _2: i32) -> {async closure body@$DIR/async_closure_shims.rs:62:48: 65:10} { - let mut _0: {async closure body@$DIR/async_closure_shims.rs:62:48: 65:10}; +fn main::{closure#0}::{closure#1}(_1: &{async closure@$DIR/async_closure_shims.rs:63:33: 63:47}, _2: i32) -> {async closure body@$DIR/async_closure_shims.rs:63:48: 66:10} { + let mut _0: {async closure body@$DIR/async_closure_shims.rs:63:48: 66:10}; bb0: { - _0 = {coroutine@$DIR/async_closure_shims.rs:62:48: 65:10 (#0)} { a: move _2, b: copy ((*_1).0: &i32) }; + _0 = {coroutine@$DIR/async_closure_shims.rs:63:48: 66:10 (#0)} { a: move _2, b: copy ((*_1).0: &i32) }; return; } } diff --git a/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#1}.coroutine_closure_by_ref.0.panic-unwind.mir b/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#1}.coroutine_closure_by_ref.0.panic-unwind.mir deleted file mode 100644 index 08abe7197224c..0000000000000 --- a/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#1}.coroutine_closure_by_ref.0.panic-unwind.mir +++ /dev/null @@ -1,10 +0,0 @@ -// MIR for `main::{closure#0}::{closure#1}` 0 coroutine_closure_by_ref - -fn main::{closure#0}::{closure#1}(_1: &{async closure@$DIR/async_closure_shims.rs:64:33: 64:47}, _2: i32) -> {async closure body@$DIR/async_closure_shims.rs:64:48: 67:10} { - let mut _0: {async closure body@$DIR/async_closure_shims.rs:64:48: 67:10}; - - bb0: { - _0 = {coroutine@$DIR/async_closure_shims.rs:64:48: 67:10 (#0)} { a: move _2, b: copy ((*_1).0: &i32) }; - return; - } -} diff --git a/tests/mir-opt/async_closure_shims.rs b/tests/mir-opt/async_closure_shims.rs index 6a3e1d777d808..b2168ba0c465b 100644 --- a/tests/mir-opt/async_closure_shims.rs +++ b/tests/mir-opt/async_closure_shims.rs @@ -1,6 +1,5 @@ //@ edition:2021 // skip-filecheck -// EMIT_MIR_FOR_EACH_PANIC_STRATEGY #![feature(async_closure, noop_waker, async_fn_traits)] #![allow(unused)] @@ -44,11 +43,11 @@ async fn call_normal_mut>(f: &mut impl FnMut(i32) -> F) { // EMIT_MIR async_closure_shims.main-{closure#0}-{closure#0}.coroutine_closure_by_move.0.mir // EMIT_MIR async_closure_shims.main-{closure#0}-{closure#0}-{closure#0}.built.after.mir -// EMIT_MIR async_closure_shims.main-{closure#0}-{closure#0}-{closure#0}-{closure#0}.built.after.mir +// EMIT_MIR async_closure_shims.main-{closure#0}-{closure#0}-{closure#1}.built.after.mir // EMIT_MIR async_closure_shims.main-{closure#0}-{closure#1}.coroutine_closure_by_ref.0.mir // EMIT_MIR async_closure_shims.main-{closure#0}-{closure#1}.coroutine_closure_by_move.0.mir // EMIT_MIR async_closure_shims.main-{closure#0}-{closure#1}-{closure#0}.built.after.mir -// EMIT_MIR async_closure_shims.main-{closure#0}-{closure#1}-{closure#0}-{closure#0}.built.after.mir +// EMIT_MIR async_closure_shims.main-{closure#0}-{closure#1}-{closure#1}.built.after.mir pub fn main() { block_on(async { let b = 2i32; From 42d2d7894ced2bb4b629ece4ff861e3f5afa8dbc Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Thu, 29 Aug 2024 12:53:30 -0400 Subject: [PATCH 0483/2194] Make supertrait and implied predicates queries defaulted --- compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs | 4 ++-- compiler/rustc_metadata/src/rmeta/encoder.rs | 8 ++++---- compiler/rustc_metadata/src/rmeta/mod.rs | 6 ++---- 3 files changed, 8 insertions(+), 10 deletions(-) diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs index 1264510a831a9..53da07aeaa695 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs @@ -247,8 +247,8 @@ provide! { tcx, def_id, other, cdata, explicit_predicates_of => { table } generics_of => { table } inferred_outlives_of => { table_defaulted_array } - explicit_super_predicates_of => { table } - explicit_implied_predicates_of => { table } + explicit_super_predicates_of => { table_defaulted_array } + explicit_implied_predicates_of => { table_defaulted_array } type_of => { table } type_alias_is_lazy => { table_direct } variances_of => { table } diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 88256c4db04ec..c55583b39a6c7 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -1443,9 +1443,9 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { } if let DefKind::Trait = def_kind { record!(self.tables.trait_def[def_id] <- self.tcx.trait_def(def_id)); - record_array!(self.tables.explicit_super_predicates_of[def_id] <- + record_defaulted_array!(self.tables.explicit_super_predicates_of[def_id] <- self.tcx.explicit_super_predicates_of(def_id).skip_binder()); - record_array!(self.tables.explicit_implied_predicates_of[def_id] <- + record_defaulted_array!(self.tables.explicit_implied_predicates_of[def_id] <- self.tcx.explicit_implied_predicates_of(def_id).skip_binder()); let module_children = self.tcx.module_children_local(local_id); @@ -1454,9 +1454,9 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { } if let DefKind::TraitAlias = def_kind { record!(self.tables.trait_def[def_id] <- self.tcx.trait_def(def_id)); - record_array!(self.tables.explicit_super_predicates_of[def_id] <- + record_defaulted_array!(self.tables.explicit_super_predicates_of[def_id] <- self.tcx.explicit_super_predicates_of(def_id).skip_binder()); - record_array!(self.tables.explicit_implied_predicates_of[def_id] <- + record_defaulted_array!(self.tables.explicit_implied_predicates_of[def_id] <- self.tcx.explicit_implied_predicates_of(def_id).skip_binder()); } if let DefKind::Trait | DefKind::Impl { .. } = def_kind { diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs index a84923130c3ab..8180a507a514d 100644 --- a/compiler/rustc_metadata/src/rmeta/mod.rs +++ b/compiler/rustc_metadata/src/rmeta/mod.rs @@ -390,6 +390,8 @@ define_tables! { explicit_item_bounds: Table, Span)>>, explicit_item_super_predicates: Table, Span)>>, inferred_outlives_of: Table, Span)>>, + explicit_super_predicates_of: Table, Span)>>, + explicit_implied_predicates_of: Table, Span)>>, inherent_impls: Table>, associated_types_for_impl_traits_in_associated_fn: Table>, associated_type_for_effects: Table>>, @@ -419,10 +421,6 @@ define_tables! { lookup_deprecation_entry: Table>, explicit_predicates_of: Table>>, generics_of: Table>, - explicit_super_predicates_of: Table, Span)>>, - // As an optimization, we only store this for trait aliases, - // since it's identical to explicit_super_predicates_of for traits. - explicit_implied_predicates_of: Table, Span)>>, type_of: Table>>>, variances_of: Table>, fn_sig: Table>>>, From c753d2dbf93a66c521dda0caa6d4c7d70bd4cc35 Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Tue, 3 Sep 2024 08:21:57 +0300 Subject: [PATCH 0484/2194] remove deprecated option `rust.split-debuginfo` Signed-off-by: onur-ozkan --- src/bootstrap/src/core/config/config.rs | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs index fba80b92f459b..466473fa5ec25 100644 --- a/src/bootstrap/src/core/config/config.rs +++ b/src/bootstrap/src/core/config/config.rs @@ -268,7 +268,6 @@ pub struct Config { pub rust_debuginfo_level_std: DebuginfoLevel, pub rust_debuginfo_level_tools: DebuginfoLevel, pub rust_debuginfo_level_tests: DebuginfoLevel, - pub rust_split_debuginfo_for_build_triple: Option, // FIXME: Deprecated field. Remove in Q3'24. pub rust_rpath: bool, pub rust_strip: bool, pub rust_frame_pointers: bool, @@ -1099,7 +1098,6 @@ define_config! { debuginfo_level_std: Option = "debuginfo-level-std", debuginfo_level_tools: Option = "debuginfo-level-tools", debuginfo_level_tests: Option = "debuginfo-level-tests", - split_debuginfo: Option = "split-debuginfo", backtrace: Option = "backtrace", incremental: Option = "incremental", parallel_compiler: Option = "parallel-compiler", @@ -1636,7 +1634,6 @@ impl Config { debuginfo_level_std: debuginfo_level_std_toml, debuginfo_level_tools: debuginfo_level_tools_toml, debuginfo_level_tests: debuginfo_level_tests_toml, - split_debuginfo, backtrace, incremental, parallel_compiler, @@ -1695,18 +1692,6 @@ impl Config { debuginfo_level_tests = debuginfo_level_tests_toml; lld_enabled = lld_enabled_toml; - config.rust_split_debuginfo_for_build_triple = split_debuginfo - .as_deref() - .map(SplitDebuginfo::from_str) - .map(|v| v.expect("invalid value for rust.split-debuginfo")); - - if config.rust_split_debuginfo_for_build_triple.is_some() { - println!( - "WARNING: specifying `rust.split-debuginfo` is deprecated, use `target.{}.split-debuginfo` instead", - config.build - ); - } - optimize = optimize_toml; omit_git_hash = omit_git_hash_toml; config.rust_new_symbol_mangling = new_symbol_mangling; @@ -2504,9 +2489,6 @@ impl Config { self.target_config .get(&target) .and_then(|t| t.split_debuginfo) - .or_else(|| { - if self.build == target { self.rust_split_debuginfo_for_build_triple } else { None } - }) .unwrap_or_else(|| SplitDebuginfo::default_for_platform(target)) } @@ -2927,7 +2909,6 @@ fn check_incompatible_options_for_ci_rustc( debuginfo_level_std: _, debuginfo_level_tools: _, debuginfo_level_tests: _, - split_debuginfo: _, backtrace: _, parallel_compiler: _, musl_root: _, From c06ed92625e1c1b723ea369114b994c4943a271d Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Wed, 4 Sep 2024 13:49:52 +0300 Subject: [PATCH 0485/2194] add change entry for `rust.split-debuginfo` removal Signed-off-by: onur-ozkan --- src/bootstrap/src/utils/change_tracker.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/bootstrap/src/utils/change_tracker.rs b/src/bootstrap/src/utils/change_tracker.rs index 3ab14aade9f81..3fec2d953d968 100644 --- a/src/bootstrap/src/utils/change_tracker.rs +++ b/src/bootstrap/src/utils/change_tracker.rs @@ -240,4 +240,9 @@ pub const CONFIG_CHANGE_HISTORY: &[ChangeInfo] = &[ severity: ChangeSeverity::Info, summary: "New option `build.cargo-clippy` added for supporting the use of custom/external clippy.", }, + ChangeInfo { + change_id: 129925, + severity: ChangeSeverity::Warning, + summary: "Removed `rust.split-debuginfo` as it was deprecated long time ago.", + }, ]; From 5b96ae7106e04606c67588d55927e88653529ec7 Mon Sep 17 00:00:00 2001 From: clubby789 Date: Sun, 25 Feb 2024 22:56:08 +0000 Subject: [PATCH 0486/2194] Don't codegen `expect` in opt-level=0 --- compiler/rustc_codegen_llvm/src/intrinsic.rs | 17 ++++++++++------- compiler/rustc_codegen_ssa/src/mir/rvalue.rs | 2 +- compiler/rustc_codegen_ssa/src/mir/statement.rs | 7 ++----- tests/codegen/intrinsics/likely.rs | 2 +- 4 files changed, 14 insertions(+), 14 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs index a300f5f707a88..05fb77a193af3 100644 --- a/compiler/rustc_codegen_llvm/src/intrinsic.rs +++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs @@ -187,9 +187,7 @@ impl<'ll, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'_, 'll, 'tcx> { Some(instance), ) } - sym::likely => { - self.call_intrinsic("llvm.expect.i1", &[args[0].immediate(), self.const_bool(true)]) - } + sym::likely => self.expect(args[0].immediate(), true), sym::is_val_statically_known => { let intrinsic_type = args[0].layout.immediate_llvm_type(self.cx); let kind = self.type_kind(intrinsic_type); @@ -210,8 +208,7 @@ impl<'ll, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'_, 'll, 'tcx> { self.const_bool(false) } } - sym::unlikely => self - .call_intrinsic("llvm.expect.i1", &[args[0].immediate(), self.const_bool(false)]), + sym::unlikely => self.expect(args[0].immediate(), false), sym::select_unpredictable => { let cond = args[0].immediate(); assert_eq!(args[1].layout, args[2].layout); @@ -604,11 +601,17 @@ impl<'ll, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'_, 'll, 'tcx> { } fn assume(&mut self, val: Self::Value) { - self.call_intrinsic("llvm.assume", &[val]); + if self.cx.sess().opts.optimize != rustc_session::config::OptLevel::No { + self.call_intrinsic("llvm.assume", &[val]); + } } fn expect(&mut self, cond: Self::Value, expected: bool) -> Self::Value { - self.call_intrinsic("llvm.expect.i1", &[cond, self.const_bool(expected)]) + if self.cx.sess().opts.optimize != rustc_session::config::OptLevel::No { + self.call_intrinsic("llvm.expect.i1", &[cond, self.const_bool(expected)]) + } else { + cond + } } fn type_test(&mut self, pointer: Self::Value, typeid: Self::Value) -> Self::Value { diff --git a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs index d94c6f8ddcec3..91fd9905f63cc 100644 --- a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs +++ b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs @@ -382,7 +382,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { scalar: abi::Scalar, backend_ty: Bx::Type, ) { - if matches!(self.cx.sess().opts.optimize, OptLevel::No | OptLevel::Less) + if matches!(self.cx.sess().opts.optimize, OptLevel::No) // For now, the critical niches are all over `Int`eger values. // Should floating-point values or pointers ever get more complex // niches, then this code will probably want to handle them too. diff --git a/compiler/rustc_codegen_ssa/src/mir/statement.rs b/compiler/rustc_codegen_ssa/src/mir/statement.rs index 2ef860fc336d6..73283cafb4947 100644 --- a/compiler/rustc_codegen_ssa/src/mir/statement.rs +++ b/compiler/rustc_codegen_ssa/src/mir/statement.rs @@ -1,6 +1,5 @@ use rustc_middle::mir::{self, NonDivergingIntrinsic}; use rustc_middle::span_bug; -use rustc_session::config::OptLevel; use tracing::instrument; use super::{FunctionCx, LocalRef}; @@ -68,10 +67,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { self.codegen_coverage(bx, kind, statement.source_info.scope); } mir::StatementKind::Intrinsic(box NonDivergingIntrinsic::Assume(ref op)) => { - if !matches!(bx.tcx().sess.opts.optimize, OptLevel::No | OptLevel::Less) { - let op_val = self.codegen_operand(bx, op); - bx.assume(op_val.immediate()); - } + let op_val = self.codegen_operand(bx, op); + bx.assume(op_val.immediate()); } mir::StatementKind::Intrinsic(box NonDivergingIntrinsic::CopyNonOverlapping( mir::CopyNonOverlapping { ref count, ref src, ref dst }, diff --git a/tests/codegen/intrinsics/likely.rs b/tests/codegen/intrinsics/likely.rs index 098fd9936ce17..9dc31d210454b 100644 --- a/tests/codegen/intrinsics/likely.rs +++ b/tests/codegen/intrinsics/likely.rs @@ -1,4 +1,4 @@ -//@ compile-flags: -C no-prepopulate-passes +//@ compile-flags: -C no-prepopulate-passes -Copt-level=1 #![crate_type = "lib"] #![feature(core_intrinsics)] From 7222f2de387c5bf23799b5d9c4e124a75690ed18 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Sun, 1 Sep 2024 13:43:05 +0200 Subject: [PATCH 0487/2194] Parse builtin#asm expressions --- src/tools/rust-analyzer/.typos.toml | 1 + src/tools/rust-analyzer/Cargo.lock | 1 + src/tools/rust-analyzer/Cargo.toml | 1 + .../crates/hir-def/src/body/lower.rs | 7 +- .../rust-analyzer/crates/hir-def/src/hir.rs | 5 +- .../crates/hir-ty/src/infer/closure.rs | 4 +- .../crates/hir-ty/src/infer/expr.rs | 2 +- .../crates/hir-ty/src/infer/mutability.rs | 7 +- .../parser/src/grammar/expressions/atom.rs | 171 ++++++- .../rust-analyzer/crates/parser/src/parser.rs | 8 + .../parser/src/syntax_kind/generated.rs | 77 +++- .../parser/test_data/generated/runner.rs | 2 + .../test_data/parser/inline/ok/asm_expr.rast | 77 ++++ .../test_data/parser/inline/ok/asm_expr.rs | 10 + .../parser/inline/ok/builtin_expr.rast | 2 +- .../parser/inline/ok/builtin_expr.rs | 2 +- .../rust-analyzer/crates/syntax/rust.ungram | 27 +- .../crates/syntax/src/ast/generated/nodes.rs | 425 +++++++++++++++++- src/tools/rust-analyzer/xtask/Cargo.toml | 1 + .../xtask/src/codegen/grammar.rs | 40 +- .../xtask/src/codegen/grammar/ast_src.rs | 26 +- 21 files changed, 865 insertions(+), 31 deletions(-) create mode 100644 src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/asm_expr.rast create mode 100644 src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/asm_expr.rs diff --git a/src/tools/rust-analyzer/.typos.toml b/src/tools/rust-analyzer/.typos.toml index e7e764ce03517..febfb233bd979 100644 --- a/src/tools/rust-analyzer/.typos.toml +++ b/src/tools/rust-analyzer/.typos.toml @@ -15,6 +15,7 @@ extend-ignore-re = [ '"flate2"', "raison d'être", "inout", + "INOUT", "optin" ] diff --git a/src/tools/rust-analyzer/Cargo.lock b/src/tools/rust-analyzer/Cargo.lock index 6eaded6da14ab..85ef3a6ba92ca 100644 --- a/src/tools/rust-analyzer/Cargo.lock +++ b/src/tools/rust-analyzer/Cargo.lock @@ -2624,6 +2624,7 @@ version = "0.1.0" dependencies = [ "anyhow", "directories", + "either", "flate2", "itertools", "proc-macro2", diff --git a/src/tools/rust-analyzer/Cargo.toml b/src/tools/rust-analyzer/Cargo.toml index e55628c8dcf4c..9e972e12118da 100644 --- a/src/tools/rust-analyzer/Cargo.toml +++ b/src/tools/rust-analyzer/Cargo.toml @@ -185,6 +185,7 @@ style = { level = "warn", priority = -1 } suspicious = { level = "warn", priority = -1 } ## allow following lints +too_long_first_doc_paragraph = "allow" # subjective single_match = "allow" # () makes a fine error in most cases diff --git a/src/tools/rust-analyzer/crates/hir-def/src/body/lower.rs b/src/tools/rust-analyzer/crates/hir-def/src/body/lower.rs index 145afc1b610c2..f2eb43beb1f18 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/body/lower.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/body/lower.rs @@ -694,8 +694,11 @@ impl ExprCollector<'_> { } ast::Expr::UnderscoreExpr(_) => self.alloc_expr(Expr::Underscore, syntax_ptr), ast::Expr::AsmExpr(e) => { - let e = self.collect_expr_opt(e.expr()); - self.alloc_expr(Expr::InlineAsm(InlineAsm { e }), syntax_ptr) + let template = e.template().map(|it| self.collect_expr(it)).collect(); + self.alloc_expr( + Expr::InlineAsm(InlineAsm { template, operands: Box::default() }), + syntax_ptr, + ) } ast::Expr::OffsetOfExpr(e) => { let container = Interned::new(TypeRef::from_ast_opt(&self.ctx(), e.ty())); diff --git a/src/tools/rust-analyzer/crates/hir-def/src/hir.rs b/src/tools/rust-analyzer/crates/hir-def/src/hir.rs index 86fd092603ffd..8f537672b58d4 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/hir.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/hir.rs @@ -307,7 +307,8 @@ pub struct OffsetOf { #[derive(Debug, Clone, PartialEq, Eq)] pub struct InlineAsm { - pub e: ExprId, + pub template: Box<[ExprId]>, + pub operands: Box<[()]>, } #[derive(Debug, Clone, Copy, PartialEq, Eq)] @@ -372,7 +373,7 @@ impl Expr { match self { Expr::Missing => {} Expr::Path(_) | Expr::OffsetOf(_) => {} - Expr::InlineAsm(it) => f(it.e), + Expr::InlineAsm(it) => it.template.iter().copied().for_each(f), Expr::If { condition, then_branch, else_branch } => { f(*condition); f(*then_branch); diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer/closure.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer/closure.rs index 36327d1d49c0a..67a3d2434d24e 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/infer/closure.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer/closure.rs @@ -666,7 +666,9 @@ impl InferenceContext<'_> { fn walk_expr_without_adjust(&mut self, tgt_expr: ExprId) { match &self.body[tgt_expr] { Expr::OffsetOf(_) => (), - Expr::InlineAsm(e) => self.walk_expr_without_adjust(e.e), + Expr::InlineAsm(e) => { + e.template.iter().for_each(|it| self.walk_expr_without_adjust(*it)) + } Expr::If { condition, then_branch, else_branch } => { self.consume_expr(*condition); self.consume_expr(*then_branch); diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer/expr.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer/expr.rs index b1c793a1e38f6..6b725d690d1a7 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/infer/expr.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer/expr.rs @@ -925,7 +925,7 @@ impl InferenceContext<'_> { } Expr::OffsetOf(_) => TyKind::Scalar(Scalar::Uint(UintTy::Usize)).intern(Interner), Expr::InlineAsm(it) => { - self.infer_expr_no_expect(it.e); + it.template.iter().for_each(|&expr| _ = self.infer_expr_no_expect(expr)); self.result.standard_types.unit.clone() } }; diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer/mutability.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer/mutability.rs index 7fed5f0203bad..e1b460d072d3f 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/infer/mutability.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer/mutability.rs @@ -39,7 +39,10 @@ impl InferenceContext<'_> { fn infer_mut_expr_without_adjust(&mut self, tgt_expr: ExprId, mutability: Mutability) { match &self.body[tgt_expr] { Expr::Missing => (), - Expr::InlineAsm(e) => self.infer_mut_expr_without_adjust(e.e, Mutability::Not), + Expr::InlineAsm(e) => e + .template + .iter() + .for_each(|&expr| self.infer_mut_expr_without_adjust(expr, Mutability::Not)), Expr::OffsetOf(_) => (), &Expr::If { condition, then_branch, else_branch } => { self.infer_mut_expr(condition, Mutability::Not); @@ -129,7 +132,7 @@ impl InferenceContext<'_> { target, }) = base_adjustments { - // For assignee exprs `IndexMut` obiligations are already applied + // For assignee exprs `IndexMut` obligations are already applied if !is_assignee_expr { if let TyKind::Ref(_, _, ty) = target.kind(Interner) { base_ty = Some(ty.clone()); diff --git a/src/tools/rust-analyzer/crates/parser/src/grammar/expressions/atom.rs b/src/tools/rust-analyzer/crates/parser/src/grammar/expressions/atom.rs index a678c1f3a70e6..57f1e6e9f031f 100644 --- a/src/tools/rust-analyzer/crates/parser/src/grammar/expressions/atom.rs +++ b/src/tools/rust-analyzer/crates/parser/src/grammar/expressions/atom.rs @@ -245,7 +245,7 @@ fn tuple_expr(p: &mut Parser<'_>) -> CompletedMarker { // test builtin_expr // fn foo() { -// builtin#asm(0); +// builtin#asm(""); // builtin#format_args("", 0, 1, a = 2 + 3, a + b); // builtin#offset_of(Foo, bar.baz.0); // } @@ -297,18 +297,175 @@ fn builtin_expr(p: &mut Parser<'_>) -> Option { p.expect(T![')']); Some(m.complete(p, FORMAT_ARGS_EXPR)) } else if p.at_contextual_kw(T![asm]) { - p.bump_remap(T![asm]); - p.expect(T!['(']); - // FIXME: We just put expression here so highlighting kind of keeps working - expr(p); - p.expect(T![')']); - Some(m.complete(p, ASM_EXPR)) + parse_asm_expr(p, m) } else { m.abandon(p); None } } +// test asm_expr +// fn foo() { +// builtin#asm( +// "mov {tmp}, {x}", +// "shl {tmp}, 1", +// "shl {x}, 2", +// "add {x}, {tmp}", +// x = inout(reg) x, +// tmp = out(reg) _, +// ); +// } +fn parse_asm_expr(p: &mut Parser<'_>, m: Marker) -> Option { + p.bump_remap(T![asm]); + p.expect(T!['(']); + if expr(p).is_none() { + p.err_and_bump("expected asm template"); + } + let mut allow_templates = true; + while !p.at(EOF) && !p.at(T![')']) { + p.expect(T![,]); + // accept trailing commas + if p.at(T![')']) { + break; + } + + // Parse clobber_abi + if p.eat_contextual_kw(T![clobber_abi]) { + parse_clobber_abi(p); + allow_templates = false; + continue; + } + + // Parse options + if p.eat_contextual_kw(T![options]) { + parse_options(p); + allow_templates = false; + continue; + } + + // Parse operand names + if p.at(T![ident]) && p.nth_at(1, T![=]) { + name(p); + p.bump(T![=]); + allow_templates = false; + true + } else { + false + }; + + let op = p.start(); + if p.eat(T![in]) { + parse_reg(p); + expr(p); + op.complete(p, ASM_REG_OPERAND); + } else if p.eat_contextual_kw(T![out]) { + parse_reg(p); + expr(p); + op.complete(p, ASM_REG_OPERAND); + } else if p.eat_contextual_kw(T![lateout]) { + parse_reg(p); + expr(p); + op.complete(p, ASM_REG_OPERAND); + } else if p.eat_contextual_kw(T![inout]) { + parse_reg(p); + expr(p); + if p.eat(T![=>]) { + expr(p); + } + op.complete(p, ASM_REG_OPERAND); + } else if p.eat_contextual_kw(T![inlateout]) { + parse_reg(p); + expr(p); + if p.eat(T![=>]) { + expr(p); + } + op.complete(p, ASM_REG_OPERAND); + } else if p.eat_contextual_kw(T![label]) { + block_expr(p); + op.complete(p, ASM_LABEL); + } else if p.eat(T![const]) { + expr(p); + op.complete(p, ASM_CONST); + } else if p.eat_contextual_kw(T![sym]) { + expr(p); + op.complete(p, ASM_SYM); + } else if allow_templates { + op.abandon(p); + if expr(p).is_none() { + p.err_and_bump("expected asm template"); + } + continue; + } else { + op.abandon(p); + p.err_and_bump("expected asm operand"); + if p.at(T!['}']) { + break; + } + continue; + }; + allow_templates = false; + } + p.expect(T![')']); + Some(m.complete(p, ASM_EXPR)) +} + +fn parse_options(p: &mut Parser<'_>) { + p.expect(T!['(']); + + while !p.eat(T![')']) && !p.at(EOF) { + const OPTIONS: &[SyntaxKind] = &[ + T![pure], + T![nomem], + T![readonly], + T![preserves_flags], + T![noreturn], + T![nostack], + T![may_unwind], + T![att_syntax], + T![raw], + ]; + + if !OPTIONS.iter().any(|&syntax| p.eat(syntax)) { + p.err_and_bump("expected asm option"); + continue; + } + + // Allow trailing commas + if p.eat(T![')']) { + break; + } + p.expect(T![,]); + } +} + +fn parse_clobber_abi(p: &mut Parser<'_>) { + p.expect(T!['(']); + + while !p.eat(T![')']) && !p.at(EOF) { + if !p.expect(T![string]) { + break; + } + + // Allow trailing commas + if p.eat(T![')']) { + break; + } + p.expect(T![,]); + } +} + +fn parse_reg(p: &mut Parser<'_>) { + p.expect(T!['(']); + if p.at(T![ident]) { + name_ref(p) + } else if p.at(T![string]) { + p.bump_any() + } else { + p.err_and_bump("expected register name"); + } + p.expect(T![')']); +} + // test array_expr // fn foo() { // []; diff --git a/src/tools/rust-analyzer/crates/parser/src/parser.rs b/src/tools/rust-analyzer/crates/parser/src/parser.rs index 7d3eb5de25f9a..f6b3783d1cace 100644 --- a/src/tools/rust-analyzer/crates/parser/src/parser.rs +++ b/src/tools/rust-analyzer/crates/parser/src/parser.rs @@ -131,6 +131,14 @@ impl<'t> Parser<'t> { true } + pub(crate) fn eat_contextual_kw(&mut self, kind: SyntaxKind) -> bool { + if !self.at_contextual_kw(kind) { + return false; + } + self.bump_remap(kind); + true + } + fn at_composite2(&self, n: usize, k1: SyntaxKind, k2: SyntaxKind) -> bool { self.inp.kind(self.pos + n) == k1 && self.inp.kind(self.pos + n + 1) == k2 diff --git a/src/tools/rust-analyzer/crates/parser/src/syntax_kind/generated.rs b/src/tools/rust-analyzer/crates/parser/src/syntax_kind/generated.rs index 00f212487ae68..ee3adac158f41 100644 --- a/src/tools/rust-analyzer/crates/parser/src/syntax_kind/generated.rs +++ b/src/tools/rust-analyzer/crates/parser/src/syntax_kind/generated.rs @@ -111,16 +111,32 @@ pub enum SyntaxKind { YIELD_KW, ASM_KW, ASYNC_KW, + ATT_SYNTAX_KW, AUTO_KW, AWAIT_KW, BUILTIN_KW, + CLOBBER_ABI_KW, DEFAULT_KW, DYN_KW, FORMAT_ARGS_KW, GEN_KW, + INLATEOUT_KW, + INOUT_KW, + LABEL_KW, + LATEOUT_KW, MACRO_RULES_KW, + MAY_UNWIND_KW, + NOMEM_KW, + NORETURN_KW, + NOSTACK_KW, OFFSET_OF_KW, + OPTIONS_KW, + OUT_KW, + PRESERVES_FLAGS_KW, + PURE_KW, RAW_KW, + READONLY_KW, + SYM_KW, TRY_KW, UNION_KW, YEET_KW, @@ -146,7 +162,18 @@ pub enum SyntaxKind { ARG_LIST, ARRAY_EXPR, ARRAY_TYPE, + ASM_CLOBBER_ABI, + ASM_CONST, + ASM_DIR_SPEC, ASM_EXPR, + ASM_LABEL, + ASM_OPERAND, + ASM_OPERAND_EXPR, + ASM_OPTION, + ASM_OPTIONS, + ASM_REG_OPERAND, + ASM_REG_SPEC, + ASM_SYM, ASSOC_ITEM, ASSOC_ITEM_LIST, ASSOC_TYPE_ARG, @@ -364,14 +391,30 @@ impl SyntaxKind { pub fn is_contextual_keyword(self, edition: Edition) -> bool { match self { ASM_KW => true, + ATT_SYNTAX_KW => true, AUTO_KW => true, BUILTIN_KW => true, + CLOBBER_ABI_KW => true, DEFAULT_KW => true, DYN_KW if edition < Edition::Edition2018 => true, FORMAT_ARGS_KW => true, + INLATEOUT_KW => true, + INOUT_KW => true, + LABEL_KW => true, + LATEOUT_KW => true, MACRO_RULES_KW => true, + MAY_UNWIND_KW => true, + NOMEM_KW => true, + NORETURN_KW => true, + NOSTACK_KW => true, OFFSET_OF_KW => true, + OPTIONS_KW => true, + OUT_KW => true, + PRESERVES_FLAGS_KW => true, + PURE_KW => true, RAW_KW => true, + READONLY_KW => true, + SYM_KW => true, UNION_KW => true, YEET_KW => true, _ => false, @@ -435,14 +478,30 @@ impl SyntaxKind { GEN_KW if Edition::Edition2024 <= edition => true, TRY_KW if Edition::Edition2018 <= edition => true, ASM_KW => true, + ATT_SYNTAX_KW => true, AUTO_KW => true, BUILTIN_KW => true, + CLOBBER_ABI_KW => true, DEFAULT_KW => true, DYN_KW if edition < Edition::Edition2018 => true, FORMAT_ARGS_KW => true, + INLATEOUT_KW => true, + INOUT_KW => true, + LABEL_KW => true, + LATEOUT_KW => true, MACRO_RULES_KW => true, + MAY_UNWIND_KW => true, + NOMEM_KW => true, + NORETURN_KW => true, + NOSTACK_KW => true, OFFSET_OF_KW => true, + OPTIONS_KW => true, + OUT_KW => true, + PRESERVES_FLAGS_KW => true, + PURE_KW => true, RAW_KW => true, + READONLY_KW => true, + SYM_KW => true, UNION_KW => true, YEET_KW => true, _ => false, @@ -580,14 +639,30 @@ impl SyntaxKind { pub fn from_contextual_keyword(ident: &str, edition: Edition) -> Option { let kw = match ident { "asm" => ASM_KW, + "att_syntax" => ATT_SYNTAX_KW, "auto" => AUTO_KW, "builtin" => BUILTIN_KW, + "clobber_abi" => CLOBBER_ABI_KW, "default" => DEFAULT_KW, "dyn" if edition < Edition::Edition2018 => DYN_KW, "format_args" => FORMAT_ARGS_KW, + "inlateout" => INLATEOUT_KW, + "inout" => INOUT_KW, + "label" => LABEL_KW, + "lateout" => LATEOUT_KW, "macro_rules" => MACRO_RULES_KW, + "may_unwind" => MAY_UNWIND_KW, + "nomem" => NOMEM_KW, + "noreturn" => NORETURN_KW, + "nostack" => NOSTACK_KW, "offset_of" => OFFSET_OF_KW, + "options" => OPTIONS_KW, + "out" => OUT_KW, + "preserves_flags" => PRESERVES_FLAGS_KW, + "pure" => PURE_KW, "raw" => RAW_KW, + "readonly" => READONLY_KW, + "sym" => SYM_KW, "union" => UNION_KW, "yeet" => YEET_KW, _ => return None, @@ -630,4 +705,4 @@ impl SyntaxKind { } } #[macro_export] -macro_rules ! T { [$] => { $ crate :: SyntaxKind :: DOLLAR } ; [;] => { $ crate :: SyntaxKind :: SEMICOLON } ; [,] => { $ crate :: SyntaxKind :: COMMA } ; ['('] => { $ crate :: SyntaxKind :: L_PAREN } ; [')'] => { $ crate :: SyntaxKind :: R_PAREN } ; ['{'] => { $ crate :: SyntaxKind :: L_CURLY } ; ['}'] => { $ crate :: SyntaxKind :: R_CURLY } ; ['['] => { $ crate :: SyntaxKind :: L_BRACK } ; [']'] => { $ crate :: SyntaxKind :: R_BRACK } ; [<] => { $ crate :: SyntaxKind :: L_ANGLE } ; [>] => { $ crate :: SyntaxKind :: R_ANGLE } ; [@] => { $ crate :: SyntaxKind :: AT } ; [#] => { $ crate :: SyntaxKind :: POUND } ; [~] => { $ crate :: SyntaxKind :: TILDE } ; [?] => { $ crate :: SyntaxKind :: QUESTION } ; [&] => { $ crate :: SyntaxKind :: AMP } ; [|] => { $ crate :: SyntaxKind :: PIPE } ; [+] => { $ crate :: SyntaxKind :: PLUS } ; [*] => { $ crate :: SyntaxKind :: STAR } ; [/] => { $ crate :: SyntaxKind :: SLASH } ; [^] => { $ crate :: SyntaxKind :: CARET } ; [%] => { $ crate :: SyntaxKind :: PERCENT } ; [_] => { $ crate :: SyntaxKind :: UNDERSCORE } ; [.] => { $ crate :: SyntaxKind :: DOT } ; [..] => { $ crate :: SyntaxKind :: DOT2 } ; [...] => { $ crate :: SyntaxKind :: DOT3 } ; [..=] => { $ crate :: SyntaxKind :: DOT2EQ } ; [:] => { $ crate :: SyntaxKind :: COLON } ; [::] => { $ crate :: SyntaxKind :: COLON2 } ; [=] => { $ crate :: SyntaxKind :: EQ } ; [==] => { $ crate :: SyntaxKind :: EQ2 } ; [=>] => { $ crate :: SyntaxKind :: FAT_ARROW } ; [!] => { $ crate :: SyntaxKind :: BANG } ; [!=] => { $ crate :: SyntaxKind :: NEQ } ; [-] => { $ crate :: SyntaxKind :: MINUS } ; [->] => { $ crate :: SyntaxKind :: THIN_ARROW } ; [<=] => { $ crate :: SyntaxKind :: LTEQ } ; [>=] => { $ crate :: SyntaxKind :: GTEQ } ; [+=] => { $ crate :: SyntaxKind :: PLUSEQ } ; [-=] => { $ crate :: SyntaxKind :: MINUSEQ } ; [|=] => { $ crate :: SyntaxKind :: PIPEEQ } ; [&=] => { $ crate :: SyntaxKind :: AMPEQ } ; [^=] => { $ crate :: SyntaxKind :: CARETEQ } ; [/=] => { $ crate :: SyntaxKind :: SLASHEQ } ; [*=] => { $ crate :: SyntaxKind :: STAREQ } ; [%=] => { $ crate :: SyntaxKind :: PERCENTEQ } ; [&&] => { $ crate :: SyntaxKind :: AMP2 } ; [||] => { $ crate :: SyntaxKind :: PIPE2 } ; [<<] => { $ crate :: SyntaxKind :: SHL } ; [>>] => { $ crate :: SyntaxKind :: SHR } ; [<<=] => { $ crate :: SyntaxKind :: SHLEQ } ; [>>=] => { $ crate :: SyntaxKind :: SHREQ } ; [Self] => { $ crate :: SyntaxKind :: SELF_TYPE_KW } ; [abstract] => { $ crate :: SyntaxKind :: ABSTRACT_KW } ; [as] => { $ crate :: SyntaxKind :: AS_KW } ; [become] => { $ crate :: SyntaxKind :: BECOME_KW } ; [box] => { $ crate :: SyntaxKind :: BOX_KW } ; [break] => { $ crate :: SyntaxKind :: BREAK_KW } ; [const] => { $ crate :: SyntaxKind :: CONST_KW } ; [continue] => { $ crate :: SyntaxKind :: CONTINUE_KW } ; [crate] => { $ crate :: SyntaxKind :: CRATE_KW } ; [do] => { $ crate :: SyntaxKind :: DO_KW } ; [else] => { $ crate :: SyntaxKind :: ELSE_KW } ; [enum] => { $ crate :: SyntaxKind :: ENUM_KW } ; [extern] => { $ crate :: SyntaxKind :: EXTERN_KW } ; [false] => { $ crate :: SyntaxKind :: FALSE_KW } ; [final] => { $ crate :: SyntaxKind :: FINAL_KW } ; [fn] => { $ crate :: SyntaxKind :: FN_KW } ; [for] => { $ crate :: SyntaxKind :: FOR_KW } ; [if] => { $ crate :: SyntaxKind :: IF_KW } ; [impl] => { $ crate :: SyntaxKind :: IMPL_KW } ; [in] => { $ crate :: SyntaxKind :: IN_KW } ; [let] => { $ crate :: SyntaxKind :: LET_KW } ; [loop] => { $ crate :: SyntaxKind :: LOOP_KW } ; [macro] => { $ crate :: SyntaxKind :: MACRO_KW } ; [match] => { $ crate :: SyntaxKind :: MATCH_KW } ; [mod] => { $ crate :: SyntaxKind :: MOD_KW } ; [move] => { $ crate :: SyntaxKind :: MOVE_KW } ; [mut] => { $ crate :: SyntaxKind :: MUT_KW } ; [override] => { $ crate :: SyntaxKind :: OVERRIDE_KW } ; [priv] => { $ crate :: SyntaxKind :: PRIV_KW } ; [pub] => { $ crate :: SyntaxKind :: PUB_KW } ; [ref] => { $ crate :: SyntaxKind :: REF_KW } ; [return] => { $ crate :: SyntaxKind :: RETURN_KW } ; [self] => { $ crate :: SyntaxKind :: SELF_KW } ; [static] => { $ crate :: SyntaxKind :: STATIC_KW } ; [struct] => { $ crate :: SyntaxKind :: STRUCT_KW } ; [super] => { $ crate :: SyntaxKind :: SUPER_KW } ; [trait] => { $ crate :: SyntaxKind :: TRAIT_KW } ; [true] => { $ crate :: SyntaxKind :: TRUE_KW } ; [type] => { $ crate :: SyntaxKind :: TYPE_KW } ; [typeof] => { $ crate :: SyntaxKind :: TYPEOF_KW } ; [unsafe] => { $ crate :: SyntaxKind :: UNSAFE_KW } ; [unsized] => { $ crate :: SyntaxKind :: UNSIZED_KW } ; [use] => { $ crate :: SyntaxKind :: USE_KW } ; [virtual] => { $ crate :: SyntaxKind :: VIRTUAL_KW } ; [where] => { $ crate :: SyntaxKind :: WHERE_KW } ; [while] => { $ crate :: SyntaxKind :: WHILE_KW } ; [yield] => { $ crate :: SyntaxKind :: YIELD_KW } ; [asm] => { $ crate :: SyntaxKind :: ASM_KW } ; [auto] => { $ crate :: SyntaxKind :: AUTO_KW } ; [builtin] => { $ crate :: SyntaxKind :: BUILTIN_KW } ; [default] => { $ crate :: SyntaxKind :: DEFAULT_KW } ; [dyn] => { $ crate :: SyntaxKind :: DYN_KW } ; [format_args] => { $ crate :: SyntaxKind :: FORMAT_ARGS_KW } ; [macro_rules] => { $ crate :: SyntaxKind :: MACRO_RULES_KW } ; [offset_of] => { $ crate :: SyntaxKind :: OFFSET_OF_KW } ; [raw] => { $ crate :: SyntaxKind :: RAW_KW } ; [union] => { $ crate :: SyntaxKind :: UNION_KW } ; [yeet] => { $ crate :: SyntaxKind :: YEET_KW } ; [async] => { $ crate :: SyntaxKind :: ASYNC_KW } ; [await] => { $ crate :: SyntaxKind :: AWAIT_KW } ; [dyn] => { $ crate :: SyntaxKind :: DYN_KW } ; [gen] => { $ crate :: SyntaxKind :: GEN_KW } ; [try] => { $ crate :: SyntaxKind :: TRY_KW } ; [lifetime_ident] => { $ crate :: SyntaxKind :: LIFETIME_IDENT } ; [int_number] => { $ crate :: SyntaxKind :: INT_NUMBER } ; [ident] => { $ crate :: SyntaxKind :: IDENT } ; [string] => { $ crate :: SyntaxKind :: STRING } ; [shebang] => { $ crate :: SyntaxKind :: SHEBANG } ; } +macro_rules ! T { [$] => { $ crate :: SyntaxKind :: DOLLAR } ; [;] => { $ crate :: SyntaxKind :: SEMICOLON } ; [,] => { $ crate :: SyntaxKind :: COMMA } ; ['('] => { $ crate :: SyntaxKind :: L_PAREN } ; [')'] => { $ crate :: SyntaxKind :: R_PAREN } ; ['{'] => { $ crate :: SyntaxKind :: L_CURLY } ; ['}'] => { $ crate :: SyntaxKind :: R_CURLY } ; ['['] => { $ crate :: SyntaxKind :: L_BRACK } ; [']'] => { $ crate :: SyntaxKind :: R_BRACK } ; [<] => { $ crate :: SyntaxKind :: L_ANGLE } ; [>] => { $ crate :: SyntaxKind :: R_ANGLE } ; [@] => { $ crate :: SyntaxKind :: AT } ; [#] => { $ crate :: SyntaxKind :: POUND } ; [~] => { $ crate :: SyntaxKind :: TILDE } ; [?] => { $ crate :: SyntaxKind :: QUESTION } ; [&] => { $ crate :: SyntaxKind :: AMP } ; [|] => { $ crate :: SyntaxKind :: PIPE } ; [+] => { $ crate :: SyntaxKind :: PLUS } ; [*] => { $ crate :: SyntaxKind :: STAR } ; [/] => { $ crate :: SyntaxKind :: SLASH } ; [^] => { $ crate :: SyntaxKind :: CARET } ; [%] => { $ crate :: SyntaxKind :: PERCENT } ; [_] => { $ crate :: SyntaxKind :: UNDERSCORE } ; [.] => { $ crate :: SyntaxKind :: DOT } ; [..] => { $ crate :: SyntaxKind :: DOT2 } ; [...] => { $ crate :: SyntaxKind :: DOT3 } ; [..=] => { $ crate :: SyntaxKind :: DOT2EQ } ; [:] => { $ crate :: SyntaxKind :: COLON } ; [::] => { $ crate :: SyntaxKind :: COLON2 } ; [=] => { $ crate :: SyntaxKind :: EQ } ; [==] => { $ crate :: SyntaxKind :: EQ2 } ; [=>] => { $ crate :: SyntaxKind :: FAT_ARROW } ; [!] => { $ crate :: SyntaxKind :: BANG } ; [!=] => { $ crate :: SyntaxKind :: NEQ } ; [-] => { $ crate :: SyntaxKind :: MINUS } ; [->] => { $ crate :: SyntaxKind :: THIN_ARROW } ; [<=] => { $ crate :: SyntaxKind :: LTEQ } ; [>=] => { $ crate :: SyntaxKind :: GTEQ } ; [+=] => { $ crate :: SyntaxKind :: PLUSEQ } ; [-=] => { $ crate :: SyntaxKind :: MINUSEQ } ; [|=] => { $ crate :: SyntaxKind :: PIPEEQ } ; [&=] => { $ crate :: SyntaxKind :: AMPEQ } ; [^=] => { $ crate :: SyntaxKind :: CARETEQ } ; [/=] => { $ crate :: SyntaxKind :: SLASHEQ } ; [*=] => { $ crate :: SyntaxKind :: STAREQ } ; [%=] => { $ crate :: SyntaxKind :: PERCENTEQ } ; [&&] => { $ crate :: SyntaxKind :: AMP2 } ; [||] => { $ crate :: SyntaxKind :: PIPE2 } ; [<<] => { $ crate :: SyntaxKind :: SHL } ; [>>] => { $ crate :: SyntaxKind :: SHR } ; [<<=] => { $ crate :: SyntaxKind :: SHLEQ } ; [>>=] => { $ crate :: SyntaxKind :: SHREQ } ; [Self] => { $ crate :: SyntaxKind :: SELF_TYPE_KW } ; [abstract] => { $ crate :: SyntaxKind :: ABSTRACT_KW } ; [as] => { $ crate :: SyntaxKind :: AS_KW } ; [become] => { $ crate :: SyntaxKind :: BECOME_KW } ; [box] => { $ crate :: SyntaxKind :: BOX_KW } ; [break] => { $ crate :: SyntaxKind :: BREAK_KW } ; [const] => { $ crate :: SyntaxKind :: CONST_KW } ; [continue] => { $ crate :: SyntaxKind :: CONTINUE_KW } ; [crate] => { $ crate :: SyntaxKind :: CRATE_KW } ; [do] => { $ crate :: SyntaxKind :: DO_KW } ; [else] => { $ crate :: SyntaxKind :: ELSE_KW } ; [enum] => { $ crate :: SyntaxKind :: ENUM_KW } ; [extern] => { $ crate :: SyntaxKind :: EXTERN_KW } ; [false] => { $ crate :: SyntaxKind :: FALSE_KW } ; [final] => { $ crate :: SyntaxKind :: FINAL_KW } ; [fn] => { $ crate :: SyntaxKind :: FN_KW } ; [for] => { $ crate :: SyntaxKind :: FOR_KW } ; [if] => { $ crate :: SyntaxKind :: IF_KW } ; [impl] => { $ crate :: SyntaxKind :: IMPL_KW } ; [in] => { $ crate :: SyntaxKind :: IN_KW } ; [let] => { $ crate :: SyntaxKind :: LET_KW } ; [loop] => { $ crate :: SyntaxKind :: LOOP_KW } ; [macro] => { $ crate :: SyntaxKind :: MACRO_KW } ; [match] => { $ crate :: SyntaxKind :: MATCH_KW } ; [mod] => { $ crate :: SyntaxKind :: MOD_KW } ; [move] => { $ crate :: SyntaxKind :: MOVE_KW } ; [mut] => { $ crate :: SyntaxKind :: MUT_KW } ; [override] => { $ crate :: SyntaxKind :: OVERRIDE_KW } ; [priv] => { $ crate :: SyntaxKind :: PRIV_KW } ; [pub] => { $ crate :: SyntaxKind :: PUB_KW } ; [ref] => { $ crate :: SyntaxKind :: REF_KW } ; [return] => { $ crate :: SyntaxKind :: RETURN_KW } ; [self] => { $ crate :: SyntaxKind :: SELF_KW } ; [static] => { $ crate :: SyntaxKind :: STATIC_KW } ; [struct] => { $ crate :: SyntaxKind :: STRUCT_KW } ; [super] => { $ crate :: SyntaxKind :: SUPER_KW } ; [trait] => { $ crate :: SyntaxKind :: TRAIT_KW } ; [true] => { $ crate :: SyntaxKind :: TRUE_KW } ; [type] => { $ crate :: SyntaxKind :: TYPE_KW } ; [typeof] => { $ crate :: SyntaxKind :: TYPEOF_KW } ; [unsafe] => { $ crate :: SyntaxKind :: UNSAFE_KW } ; [unsized] => { $ crate :: SyntaxKind :: UNSIZED_KW } ; [use] => { $ crate :: SyntaxKind :: USE_KW } ; [virtual] => { $ crate :: SyntaxKind :: VIRTUAL_KW } ; [where] => { $ crate :: SyntaxKind :: WHERE_KW } ; [while] => { $ crate :: SyntaxKind :: WHILE_KW } ; [yield] => { $ crate :: SyntaxKind :: YIELD_KW } ; [asm] => { $ crate :: SyntaxKind :: ASM_KW } ; [att_syntax] => { $ crate :: SyntaxKind :: ATT_SYNTAX_KW } ; [auto] => { $ crate :: SyntaxKind :: AUTO_KW } ; [builtin] => { $ crate :: SyntaxKind :: BUILTIN_KW } ; [clobber_abi] => { $ crate :: SyntaxKind :: CLOBBER_ABI_KW } ; [default] => { $ crate :: SyntaxKind :: DEFAULT_KW } ; [dyn] => { $ crate :: SyntaxKind :: DYN_KW } ; [format_args] => { $ crate :: SyntaxKind :: FORMAT_ARGS_KW } ; [inlateout] => { $ crate :: SyntaxKind :: INLATEOUT_KW } ; [inout] => { $ crate :: SyntaxKind :: INOUT_KW } ; [label] => { $ crate :: SyntaxKind :: LABEL_KW } ; [lateout] => { $ crate :: SyntaxKind :: LATEOUT_KW } ; [macro_rules] => { $ crate :: SyntaxKind :: MACRO_RULES_KW } ; [may_unwind] => { $ crate :: SyntaxKind :: MAY_UNWIND_KW } ; [nomem] => { $ crate :: SyntaxKind :: NOMEM_KW } ; [noreturn] => { $ crate :: SyntaxKind :: NORETURN_KW } ; [nostack] => { $ crate :: SyntaxKind :: NOSTACK_KW } ; [offset_of] => { $ crate :: SyntaxKind :: OFFSET_OF_KW } ; [options] => { $ crate :: SyntaxKind :: OPTIONS_KW } ; [out] => { $ crate :: SyntaxKind :: OUT_KW } ; [preserves_flags] => { $ crate :: SyntaxKind :: PRESERVES_FLAGS_KW } ; [pure] => { $ crate :: SyntaxKind :: PURE_KW } ; [raw] => { $ crate :: SyntaxKind :: RAW_KW } ; [readonly] => { $ crate :: SyntaxKind :: READONLY_KW } ; [sym] => { $ crate :: SyntaxKind :: SYM_KW } ; [union] => { $ crate :: SyntaxKind :: UNION_KW } ; [yeet] => { $ crate :: SyntaxKind :: YEET_KW } ; [async] => { $ crate :: SyntaxKind :: ASYNC_KW } ; [await] => { $ crate :: SyntaxKind :: AWAIT_KW } ; [dyn] => { $ crate :: SyntaxKind :: DYN_KW } ; [gen] => { $ crate :: SyntaxKind :: GEN_KW } ; [try] => { $ crate :: SyntaxKind :: TRY_KW } ; [lifetime_ident] => { $ crate :: SyntaxKind :: LIFETIME_IDENT } ; [int_number] => { $ crate :: SyntaxKind :: INT_NUMBER } ; [ident] => { $ crate :: SyntaxKind :: IDENT } ; [string] => { $ crate :: SyntaxKind :: STRING } ; [shebang] => { $ crate :: SyntaxKind :: SHEBANG } ; } diff --git a/src/tools/rust-analyzer/crates/parser/test_data/generated/runner.rs b/src/tools/rust-analyzer/crates/parser/test_data/generated/runner.rs index 9ce5a2ae748fd..164d0f36f1be2 100644 --- a/src/tools/rust-analyzer/crates/parser/test_data/generated/runner.rs +++ b/src/tools/rust-analyzer/crates/parser/test_data/generated/runner.rs @@ -19,6 +19,8 @@ mod ok { #[test] fn as_precedence() { run_and_expect_no_errors("test_data/parser/inline/ok/as_precedence.rs"); } #[test] + fn asm_expr() { run_and_expect_no_errors("test_data/parser/inline/ok/asm_expr.rs"); } + #[test] fn assoc_const_eq() { run_and_expect_no_errors("test_data/parser/inline/ok/assoc_const_eq.rs"); } diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/asm_expr.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/asm_expr.rast new file mode 100644 index 0000000000000..f4d53fa9ae657 --- /dev/null +++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/asm_expr.rast @@ -0,0 +1,77 @@ +SOURCE_FILE + FN + FN_KW "fn" + WHITESPACE " " + NAME + IDENT "foo" + PARAM_LIST + L_PAREN "(" + R_PAREN ")" + WHITESPACE " " + BLOCK_EXPR + STMT_LIST + L_CURLY "{" + WHITESPACE "\n " + EXPR_STMT + ASM_EXPR + BUILTIN_KW "builtin" + POUND "#" + ASM_KW "asm" + L_PAREN "(" + WHITESPACE "\n " + LITERAL + STRING "\"mov {tmp}, {x}\"" + COMMA "," + WHITESPACE "\n " + LITERAL + STRING "\"shl {tmp}, 1\"" + COMMA "," + WHITESPACE "\n " + LITERAL + STRING "\"shl {x}, 2\"" + COMMA "," + WHITESPACE "\n " + LITERAL + STRING "\"add {x}, {tmp}\"" + COMMA "," + WHITESPACE "\n " + NAME + IDENT "x" + WHITESPACE " " + EQ "=" + WHITESPACE " " + ASM_REG_OPERAND + INOUT_KW "inout" + L_PAREN "(" + NAME_REF + IDENT "reg" + R_PAREN ")" + WHITESPACE " " + PATH_EXPR + PATH + PATH_SEGMENT + NAME_REF + IDENT "x" + COMMA "," + WHITESPACE "\n " + NAME + IDENT "tmp" + WHITESPACE " " + EQ "=" + WHITESPACE " " + ASM_REG_OPERAND + OUT_KW "out" + L_PAREN "(" + NAME_REF + IDENT "reg" + R_PAREN ")" + WHITESPACE " " + UNDERSCORE_EXPR + UNDERSCORE "_" + COMMA "," + WHITESPACE "\n " + R_PAREN ")" + SEMICOLON ";" + WHITESPACE "\n" + R_CURLY "}" + WHITESPACE "\n" diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/asm_expr.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/asm_expr.rs new file mode 100644 index 0000000000000..0906cd3e7197d --- /dev/null +++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/asm_expr.rs @@ -0,0 +1,10 @@ +fn foo() { + builtin#asm( + "mov {tmp}, {x}", + "shl {tmp}, 1", + "shl {x}, 2", + "add {x}, {tmp}", + x = inout(reg) x, + tmp = out(reg) _, + ); +} diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/builtin_expr.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/builtin_expr.rast index 361900b6d3e4b..19a84ac540961 100644 --- a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/builtin_expr.rast +++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/builtin_expr.rast @@ -19,7 +19,7 @@ SOURCE_FILE ASM_KW "asm" L_PAREN "(" LITERAL - INT_NUMBER "0" + STRING "\"\"" R_PAREN ")" SEMICOLON ";" WHITESPACE "\n " diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/builtin_expr.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/builtin_expr.rs index 14431b0210ea8..920d0f794f242 100644 --- a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/builtin_expr.rs +++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/builtin_expr.rs @@ -1,5 +1,5 @@ fn foo() { - builtin#asm(0); + builtin#asm(""); builtin#format_args("", 0, 1, a = 2 + 3, a + b); builtin#offset_of(Foo, bar.baz.0); } diff --git a/src/tools/rust-analyzer/crates/syntax/rust.ungram b/src/tools/rust-analyzer/crates/syntax/rust.ungram index 43375ce6ae051..4d780ba28f310 100644 --- a/src/tools/rust-analyzer/crates/syntax/rust.ungram +++ b/src/tools/rust-analyzer/crates/syntax/rust.ungram @@ -391,8 +391,33 @@ Expr = OffsetOfExpr = Attr* 'builtin' '#' 'offset_of' '(' Type ',' fields:(NameRef ('.' NameRef)* ) ')' +// asm := "asm!(" format_string *("," format_string) *("," operand) [","] ")" +// global_asm := "global_asm!(" format_string *("," format_string) *("," operand) [","] ")" +// format_string := STRING_LITERAL / RAW_STRING_LITERAL AsmExpr = - Attr* 'builtin' '#' 'asm' '(' Expr ')' + Attr* 'builtin' '#' 'asm' '(' template:(Expr (',' Expr)*) (AsmOperand (',' AsmOperand)*)? ','? ')' + +// operand_expr := expr / "_" / expr "=>" expr / expr "=>" "_" +AsmOperandExpr = in_expr:Expr ('=>' out_expr:Expr)? +// dir_spec := "in" / "out" / "lateout" / "inout" / "inlateout" +AsmDirSpec = 'in' | 'out' | 'lateout' | 'inout' | 'inlateout' +// reg_spec := / "\"" "\"" +AsmRegSpec = '@string' | NameRef +// reg_operand := [ident "="] dir_spec "(" reg_spec ")" operand_expr +AsmRegOperand = (Name '=')? AsmDirSpec '(' AsmRegSpec ')' AsmOperandExpr +// clobber_abi := "clobber_abi(" *("," ) [","] ")" +AsmClobberAbi = 'clobber_abi' '(' ('@string' (',' '@string')* ','?) ')' +// option := "pure" / "nomem" / "readonly" / "preserves_flags" / "noreturn" / "nostack" / "att_syntax" / "raw" +AsmOption = 'pure' | 'nomem' | 'readonly' | 'preserves_flags' | 'noreturn' | 'nostack' | 'att_syntax' | 'raw' | 'may_unwind' +// options := "options(" option *("," option) [","] ")" +AsmOptions = 'options' '(' AsmOption *(',' AsmOption) ','? ')' +// operand := reg_operand / clobber_abi / options +AsmOperand = AsmRegOperand | AsmClobberAbi | AsmOptions | AsmLabel +AsmLabel = 'label' BlockExpr +AsmSym = 'sym' Expr +AsmConst = 'const' Expr + + FormatArgsExpr = Attr* 'builtin' '#' 'format_args' '(' diff --git a/src/tools/rust-analyzer/crates/syntax/src/ast/generated/nodes.rs b/src/tools/rust-analyzer/crates/syntax/src/ast/generated/nodes.rs index c9b39e9922c92..e5e1115e05a7b 100644 --- a/src/tools/rust-analyzer/crates/syntax/src/ast/generated/nodes.rs +++ b/src/tools/rust-analyzer/crates/syntax/src/ast/generated/nodes.rs @@ -64,6 +64,53 @@ impl ArrayType { pub fn semicolon_token(&self) -> Option { support::token(&self.syntax, T![;]) } } +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct AsmClobberAbi { + pub(crate) syntax: SyntaxNode, +} +impl AsmClobberAbi { + #[inline] + pub fn l_paren_token(&self) -> Option { support::token(&self.syntax, T!['(']) } + #[inline] + pub fn r_paren_token(&self) -> Option { support::token(&self.syntax, T![')']) } + #[inline] + pub fn clobber_abi_token(&self) -> Option { + support::token(&self.syntax, T![clobber_abi]) + } + #[inline] + pub fn string_token(&self) -> Option { support::token(&self.syntax, T![string]) } +} + +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct AsmConst { + pub(crate) syntax: SyntaxNode, +} +impl AsmConst { + #[inline] + pub fn expr(&self) -> Option { support::child(&self.syntax) } + #[inline] + pub fn const_token(&self) -> Option { support::token(&self.syntax, T![const]) } +} + +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct AsmDirSpec { + pub(crate) syntax: SyntaxNode, +} +impl AsmDirSpec { + #[inline] + pub fn in_token(&self) -> Option { support::token(&self.syntax, T![in]) } + #[inline] + pub fn inlateout_token(&self) -> Option { + support::token(&self.syntax, T![inlateout]) + } + #[inline] + pub fn inout_token(&self) -> Option { support::token(&self.syntax, T![inout]) } + #[inline] + pub fn lateout_token(&self) -> Option { support::token(&self.syntax, T![lateout]) } + #[inline] + pub fn out_token(&self) -> Option { support::token(&self.syntax, T![out]) } +} + #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct AsmExpr { pub(crate) syntax: SyntaxNode, @@ -71,7 +118,9 @@ pub struct AsmExpr { impl ast::HasAttrs for AsmExpr {} impl AsmExpr { #[inline] - pub fn expr(&self) -> Option { support::child(&self.syntax) } + pub fn asm_operands(&self) -> AstChildren { support::children(&self.syntax) } + #[inline] + pub fn template(&self) -> AstChildren { support::children(&self.syntax) } #[inline] pub fn pound_token(&self) -> Option { support::token(&self.syntax, T![#]) } #[inline] @@ -79,11 +128,133 @@ impl AsmExpr { #[inline] pub fn r_paren_token(&self) -> Option { support::token(&self.syntax, T![')']) } #[inline] + pub fn comma_token(&self) -> Option { support::token(&self.syntax, T![,]) } + #[inline] pub fn asm_token(&self) -> Option { support::token(&self.syntax, T![asm]) } #[inline] pub fn builtin_token(&self) -> Option { support::token(&self.syntax, T![builtin]) } } +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct AsmLabel { + pub(crate) syntax: SyntaxNode, +} +impl AsmLabel { + #[inline] + pub fn block_expr(&self) -> Option { support::child(&self.syntax) } + #[inline] + pub fn label_token(&self) -> Option { support::token(&self.syntax, T![label]) } +} + +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct AsmOperandExpr { + pub(crate) syntax: SyntaxNode, +} +impl AsmOperandExpr { + #[inline] + pub fn in_expr(&self) -> Option { support::child(&self.syntax) } + #[inline] + pub fn out_expr(&self) -> Option { support::child(&self.syntax) } + #[inline] + pub fn fat_arrow_token(&self) -> Option { support::token(&self.syntax, T![=>]) } +} + +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct AsmOption { + pub(crate) syntax: SyntaxNode, +} +impl AsmOption { + #[inline] + pub fn att_syntax_token(&self) -> Option { + support::token(&self.syntax, T![att_syntax]) + } + #[inline] + pub fn may_unwind_token(&self) -> Option { + support::token(&self.syntax, T![may_unwind]) + } + #[inline] + pub fn nomem_token(&self) -> Option { support::token(&self.syntax, T![nomem]) } + #[inline] + pub fn noreturn_token(&self) -> Option { + support::token(&self.syntax, T![noreturn]) + } + #[inline] + pub fn nostack_token(&self) -> Option { support::token(&self.syntax, T![nostack]) } + #[inline] + pub fn preserves_flags_token(&self) -> Option { + support::token(&self.syntax, T![preserves_flags]) + } + #[inline] + pub fn pure_token(&self) -> Option { support::token(&self.syntax, T![pure]) } + #[inline] + pub fn raw_token(&self) -> Option { support::token(&self.syntax, T![raw]) } + #[inline] + pub fn readonly_token(&self) -> Option { + support::token(&self.syntax, T![readonly]) + } +} + +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct AsmOptions { + pub(crate) syntax: SyntaxNode, +} +impl AsmOptions { + #[inline] + pub fn asm_option(&self) -> Option { support::child(&self.syntax) } + #[inline] + pub fn asm_options(&self) -> AstChildren { support::children(&self.syntax) } + #[inline] + pub fn l_paren_token(&self) -> Option { support::token(&self.syntax, T!['(']) } + #[inline] + pub fn r_paren_token(&self) -> Option { support::token(&self.syntax, T![')']) } + #[inline] + pub fn comma_token(&self) -> Option { support::token(&self.syntax, T![,]) } + #[inline] + pub fn options_token(&self) -> Option { support::token(&self.syntax, T![options]) } +} + +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct AsmRegOperand { + pub(crate) syntax: SyntaxNode, +} +impl ast::HasName for AsmRegOperand {} +impl AsmRegOperand { + #[inline] + pub fn asm_dir_spec(&self) -> Option { support::child(&self.syntax) } + #[inline] + pub fn asm_operand_expr(&self) -> Option { support::child(&self.syntax) } + #[inline] + pub fn asm_reg_spec(&self) -> Option { support::child(&self.syntax) } + #[inline] + pub fn l_paren_token(&self) -> Option { support::token(&self.syntax, T!['(']) } + #[inline] + pub fn r_paren_token(&self) -> Option { support::token(&self.syntax, T![')']) } + #[inline] + pub fn eq_token(&self) -> Option { support::token(&self.syntax, T![=]) } +} + +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct AsmRegSpec { + pub(crate) syntax: SyntaxNode, +} +impl AsmRegSpec { + #[inline] + pub fn name_ref(&self) -> Option { support::child(&self.syntax) } + #[inline] + pub fn string_token(&self) -> Option { support::token(&self.syntax, T![string]) } +} + +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct AsmSym { + pub(crate) syntax: SyntaxNode, +} +impl AsmSym { + #[inline] + pub fn expr(&self) -> Option { support::child(&self.syntax) } + #[inline] + pub fn sym_token(&self) -> Option { support::token(&self.syntax, T![sym]) } +} + #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct AssocItemList { pub(crate) syntax: SyntaxNode, @@ -2051,6 +2222,14 @@ impl ast::HasGenericParams for Adt {} impl ast::HasName for Adt {} impl ast::HasVisibility for Adt {} +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub enum AsmOperand { + AsmClobberAbi(AsmClobberAbi), + AsmLabel(AsmLabel), + AsmOptions(AsmOptions), + AsmRegOperand(AsmRegOperand), +} + #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub enum AssocItem { Const(Const), @@ -2316,6 +2495,48 @@ impl AstNode for ArrayType { #[inline] fn syntax(&self) -> &SyntaxNode { &self.syntax } } +impl AstNode for AsmClobberAbi { + #[inline] + fn can_cast(kind: SyntaxKind) -> bool { kind == ASM_CLOBBER_ABI } + #[inline] + fn cast(syntax: SyntaxNode) -> Option { + if Self::can_cast(syntax.kind()) { + Some(Self { syntax }) + } else { + None + } + } + #[inline] + fn syntax(&self) -> &SyntaxNode { &self.syntax } +} +impl AstNode for AsmConst { + #[inline] + fn can_cast(kind: SyntaxKind) -> bool { kind == ASM_CONST } + #[inline] + fn cast(syntax: SyntaxNode) -> Option { + if Self::can_cast(syntax.kind()) { + Some(Self { syntax }) + } else { + None + } + } + #[inline] + fn syntax(&self) -> &SyntaxNode { &self.syntax } +} +impl AstNode for AsmDirSpec { + #[inline] + fn can_cast(kind: SyntaxKind) -> bool { kind == ASM_DIR_SPEC } + #[inline] + fn cast(syntax: SyntaxNode) -> Option { + if Self::can_cast(syntax.kind()) { + Some(Self { syntax }) + } else { + None + } + } + #[inline] + fn syntax(&self) -> &SyntaxNode { &self.syntax } +} impl AstNode for AsmExpr { #[inline] fn can_cast(kind: SyntaxKind) -> bool { kind == ASM_EXPR } @@ -2330,6 +2551,104 @@ impl AstNode for AsmExpr { #[inline] fn syntax(&self) -> &SyntaxNode { &self.syntax } } +impl AstNode for AsmLabel { + #[inline] + fn can_cast(kind: SyntaxKind) -> bool { kind == ASM_LABEL } + #[inline] + fn cast(syntax: SyntaxNode) -> Option { + if Self::can_cast(syntax.kind()) { + Some(Self { syntax }) + } else { + None + } + } + #[inline] + fn syntax(&self) -> &SyntaxNode { &self.syntax } +} +impl AstNode for AsmOperandExpr { + #[inline] + fn can_cast(kind: SyntaxKind) -> bool { kind == ASM_OPERAND_EXPR } + #[inline] + fn cast(syntax: SyntaxNode) -> Option { + if Self::can_cast(syntax.kind()) { + Some(Self { syntax }) + } else { + None + } + } + #[inline] + fn syntax(&self) -> &SyntaxNode { &self.syntax } +} +impl AstNode for AsmOption { + #[inline] + fn can_cast(kind: SyntaxKind) -> bool { kind == ASM_OPTION } + #[inline] + fn cast(syntax: SyntaxNode) -> Option { + if Self::can_cast(syntax.kind()) { + Some(Self { syntax }) + } else { + None + } + } + #[inline] + fn syntax(&self) -> &SyntaxNode { &self.syntax } +} +impl AstNode for AsmOptions { + #[inline] + fn can_cast(kind: SyntaxKind) -> bool { kind == ASM_OPTIONS } + #[inline] + fn cast(syntax: SyntaxNode) -> Option { + if Self::can_cast(syntax.kind()) { + Some(Self { syntax }) + } else { + None + } + } + #[inline] + fn syntax(&self) -> &SyntaxNode { &self.syntax } +} +impl AstNode for AsmRegOperand { + #[inline] + fn can_cast(kind: SyntaxKind) -> bool { kind == ASM_REG_OPERAND } + #[inline] + fn cast(syntax: SyntaxNode) -> Option { + if Self::can_cast(syntax.kind()) { + Some(Self { syntax }) + } else { + None + } + } + #[inline] + fn syntax(&self) -> &SyntaxNode { &self.syntax } +} +impl AstNode for AsmRegSpec { + #[inline] + fn can_cast(kind: SyntaxKind) -> bool { kind == ASM_REG_SPEC } + #[inline] + fn cast(syntax: SyntaxNode) -> Option { + if Self::can_cast(syntax.kind()) { + Some(Self { syntax }) + } else { + None + } + } + #[inline] + fn syntax(&self) -> &SyntaxNode { &self.syntax } +} +impl AstNode for AsmSym { + #[inline] + fn can_cast(kind: SyntaxKind) -> bool { kind == ASM_SYM } + #[inline] + fn cast(syntax: SyntaxNode) -> Option { + if Self::can_cast(syntax.kind()) { + Some(Self { syntax }) + } else { + None + } + } + #[inline] + fn syntax(&self) -> &SyntaxNode { &self.syntax } +} impl AstNode for AssocItemList { #[inline] fn can_cast(kind: SyntaxKind) -> bool { kind == ASSOC_ITEM_LIST } @@ -4268,6 +4587,48 @@ impl AstNode for Adt { } } } +impl From for AsmOperand { + #[inline] + fn from(node: AsmClobberAbi) -> AsmOperand { AsmOperand::AsmClobberAbi(node) } +} +impl From for AsmOperand { + #[inline] + fn from(node: AsmLabel) -> AsmOperand { AsmOperand::AsmLabel(node) } +} +impl From for AsmOperand { + #[inline] + fn from(node: AsmOptions) -> AsmOperand { AsmOperand::AsmOptions(node) } +} +impl From for AsmOperand { + #[inline] + fn from(node: AsmRegOperand) -> AsmOperand { AsmOperand::AsmRegOperand(node) } +} +impl AstNode for AsmOperand { + #[inline] + fn can_cast(kind: SyntaxKind) -> bool { + matches!(kind, ASM_CLOBBER_ABI | ASM_LABEL | ASM_OPTIONS | ASM_REG_OPERAND) + } + #[inline] + fn cast(syntax: SyntaxNode) -> Option { + let res = match syntax.kind() { + ASM_CLOBBER_ABI => AsmOperand::AsmClobberAbi(AsmClobberAbi { syntax }), + ASM_LABEL => AsmOperand::AsmLabel(AsmLabel { syntax }), + ASM_OPTIONS => AsmOperand::AsmOptions(AsmOptions { syntax }), + ASM_REG_OPERAND => AsmOperand::AsmRegOperand(AsmRegOperand { syntax }), + _ => return None, + }; + Some(res) + } + #[inline] + fn syntax(&self) -> &SyntaxNode { + match self { + AsmOperand::AsmClobberAbi(it) => &it.syntax, + AsmOperand::AsmLabel(it) => &it.syntax, + AsmOperand::AsmOptions(it) => &it.syntax, + AsmOperand::AsmRegOperand(it) => &it.syntax, + } + } +} impl From for AssocItem { #[inline] fn from(node: Const) -> AssocItem { AssocItem::Const(node) } @@ -5803,7 +6164,8 @@ impl AstNode for AnyHasName { fn can_cast(kind: SyntaxKind) -> bool { matches!( kind, - CONST + ASM_REG_OPERAND + | CONST | CONST_PARAM | ENUM | FN @@ -5832,6 +6194,10 @@ impl AstNode for AnyHasName { #[inline] fn syntax(&self) -> &SyntaxNode { &self.syntax } } +impl From for AnyHasName { + #[inline] + fn from(node: AsmRegOperand) -> AnyHasName { AnyHasName { syntax: node.syntax } } +} impl From for AnyHasName { #[inline] fn from(node: Const) -> AnyHasName { AnyHasName { syntax: node.syntax } } @@ -6072,6 +6438,11 @@ impl std::fmt::Display for Adt { std::fmt::Display::fmt(self.syntax(), f) } } +impl std::fmt::Display for AsmOperand { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} impl std::fmt::Display for AssocItem { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { std::fmt::Display::fmt(self.syntax(), f) @@ -6142,11 +6513,61 @@ impl std::fmt::Display for ArrayType { std::fmt::Display::fmt(self.syntax(), f) } } +impl std::fmt::Display for AsmClobberAbi { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} +impl std::fmt::Display for AsmConst { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} +impl std::fmt::Display for AsmDirSpec { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} impl std::fmt::Display for AsmExpr { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { std::fmt::Display::fmt(self.syntax(), f) } } +impl std::fmt::Display for AsmLabel { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} +impl std::fmt::Display for AsmOperandExpr { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} +impl std::fmt::Display for AsmOption { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} +impl std::fmt::Display for AsmOptions { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} +impl std::fmt::Display for AsmRegOperand { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} +impl std::fmt::Display for AsmRegSpec { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} +impl std::fmt::Display for AsmSym { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} impl std::fmt::Display for AssocItemList { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { std::fmt::Display::fmt(self.syntax(), f) diff --git a/src/tools/rust-analyzer/xtask/Cargo.toml b/src/tools/rust-analyzer/xtask/Cargo.toml index 192de8694721d..4bc1821ee5eab 100644 --- a/src/tools/rust-analyzer/xtask/Cargo.toml +++ b/src/tools/rust-analyzer/xtask/Cargo.toml @@ -19,6 +19,7 @@ stdx.workspace = true proc-macro2 = "1.0.47" quote = "1.0.20" ungrammar = "1.16.1" +either.workspace = true itertools.workspace = true # Avoid adding more dependencies to this crate diff --git a/src/tools/rust-analyzer/xtask/src/codegen/grammar.rs b/src/tools/rust-analyzer/xtask/src/codegen/grammar.rs index 39e06f9642db1..e7534582f2b42 100644 --- a/src/tools/rust-analyzer/xtask/src/codegen/grammar.rs +++ b/src/tools/rust-analyzer/xtask/src/codegen/grammar.rs @@ -11,9 +11,11 @@ use std::{ fs, }; +use either::Either; use itertools::Itertools; use proc_macro2::{Punct, Spacing}; use quote::{format_ident, quote}; +use stdx::panic_context; use ungrammar::{Grammar, Rule}; use crate::{ @@ -462,6 +464,7 @@ fn generate_syntax_kinds(grammar: KindsSrc) -> String { let tokens = grammar.tokens.iter().map(|name| format_ident!("{}", name)).collect::>(); + // FIXME: This generates enum kinds? let nodes = grammar.nodes.iter().map(|name| format_ident!("{}", name)).collect::>(); let ast = quote! { @@ -711,6 +714,7 @@ fn lower(grammar: &Grammar) -> AstSrc { for &node in &nodes { let name = grammar[node].name.clone(); let rule = &grammar[node].rule; + let _g = panic_context::enter(name.clone()); match lower_enum(grammar, rule) { Some(variants) => { let enum_src = AstEnumSrc { doc: Vec::new(), name, traits: Vec::new(), variants }; @@ -838,11 +842,16 @@ fn lower_separated_list( Rule::Seq(it) => it, _ => return false, }; - let (node, repeat, trailing_sep) = match rule.as_slice() { + + let (nt, repeat, trailing_sep) = match rule.as_slice() { [Rule::Node(node), Rule::Rep(repeat), Rule::Opt(trailing_sep)] => { - (node, repeat, Some(trailing_sep)) + (Either::Left(node), repeat, Some(trailing_sep)) + } + [Rule::Node(node), Rule::Rep(repeat)] => (Either::Left(node), repeat, None), + [Rule::Token(token), Rule::Rep(repeat), Rule::Opt(trailing_sep)] => { + (Either::Right(token), repeat, Some(trailing_sep)) } - [Rule::Node(node), Rule::Rep(repeat)] => (node, repeat, None), + [Rule::Token(token), Rule::Rep(repeat)] => (Either::Right(token), repeat, None), _ => return false, }; let repeat = match &**repeat { @@ -851,15 +860,28 @@ fn lower_separated_list( }; if !matches!( repeat.as_slice(), - [comma, Rule::Node(n)] - if trailing_sep.map_or(true, |it| comma == &**it) && n == node + [comma, nt_] + if trailing_sep.map_or(true, |it| comma == &**it) && match (nt, nt_) { + (Either::Left(node), Rule::Node(nt_)) => node == nt_, + (Either::Right(token), Rule::Token(nt_)) => token == nt_, + _ => false, + } ) { return false; } - let ty = grammar[*node].name.clone(); - let name = label.cloned().unwrap_or_else(|| pluralize(&to_lower_snake_case(&ty))); - let field = Field::Node { name, ty, cardinality: Cardinality::Many }; - acc.push(field); + match nt { + Either::Right(token) => { + let name = clean_token_name(&grammar[*token].name); + let field = Field::Token(name); + acc.push(field); + } + Either::Left(node) => { + let ty = grammar[*node].name.clone(); + let name = label.cloned().unwrap_or_else(|| pluralize(&to_lower_snake_case(&ty))); + let field = Field::Node { name, ty, cardinality: Cardinality::Many }; + acc.push(field); + } + } true } diff --git a/src/tools/rust-analyzer/xtask/src/codegen/grammar/ast_src.rs b/src/tools/rust-analyzer/xtask/src/codegen/grammar/ast_src.rs index 34151bd958765..f1a96e0c6a2d4 100644 --- a/src/tools/rust-analyzer/xtask/src/codegen/grammar/ast_src.rs +++ b/src/tools/rust-analyzer/xtask/src/codegen/grammar/ast_src.rs @@ -113,7 +113,31 @@ const RESERVED: &[&str] = &[ const CONTEXTUAL_KEYWORDS: &[&str] = &["macro_rules", "union", "default", "raw", "dyn", "auto", "yeet"]; // keywords we use for special macro expansions -const CONTEXTUAL_BUILTIN_KEYWORDS: &[&str] = &["builtin", "offset_of", "format_args", "asm"]; +const CONTEXTUAL_BUILTIN_KEYWORDS: &[&str] = &[ + "asm", + "att_syntax", + "builtin", + "clobber_abi", + "format_args", + // "in", + "inlateout", + "inout", + "label", + "lateout", + "may_unwind", + "nomem", + "noreturn", + "nostack", + "offset_of", + "options", + "out", + "preserves_flags", + "pure", + // "raw", + "readonly", + "sym", +]; + // keywords that are keywords depending on the edition const EDITION_DEPENDENT_KEYWORDS: &[(&str, Edition)] = &[ ("try", Edition::Edition2018), From 0444056aa3ddd97e02478b7c41d130db74583d16 Mon Sep 17 00:00:00 2001 From: beetrees Date: Thu, 25 Jul 2024 22:15:47 +0100 Subject: [PATCH 0488/2194] Remove macOS 10.10 dynamic linker bug workaround --- compiler/rustc_codegen_llvm/src/consts.rs | 52 ------------------- library/std/src/fs.rs | 13 +++-- .../issues/issue-44056-macos-tls-align.rs | 27 ---------- 3 files changed, 6 insertions(+), 86 deletions(-) delete mode 100644 tests/codegen/issues/issue-44056-macos-tls-align.rs diff --git a/compiler/rustc_codegen_llvm/src/consts.rs b/compiler/rustc_codegen_llvm/src/consts.rs index 80aa2018c81b5..0e50e32913c7b 100644 --- a/compiler/rustc_codegen_llvm/src/consts.rs +++ b/compiler/rustc_codegen_llvm/src/consts.rs @@ -440,58 +440,6 @@ impl<'ll> CodegenCx<'ll, '_> { if attrs.flags.contains(CodegenFnAttrFlags::THREAD_LOCAL) { llvm::set_thread_local_mode(g, self.tls_model); - - // Do not allow LLVM to change the alignment of a TLS on macOS. - // - // By default a global's alignment can be freely increased. - // This allows LLVM to generate more performant instructions - // e.g., using load-aligned into a SIMD register. - // - // However, on macOS 10.10 or below, the dynamic linker does not - // respect any alignment given on the TLS (radar 24221680). - // This will violate the alignment assumption, and causing segfault at runtime. - // - // This bug is very easy to trigger. In `println!` and `panic!`, - // the `LOCAL_STDOUT`/`LOCAL_STDERR` handles are stored in a TLS, - // which the values would be `mem::replace`d on initialization. - // The implementation of `mem::replace` will use SIMD - // whenever the size is 32 bytes or higher. LLVM notices SIMD is used - // and tries to align `LOCAL_STDOUT`/`LOCAL_STDERR` to a 32-byte boundary, - // which macOS's dyld disregarded and causing crashes - // (see issues #51794, #51758, #50867, #48866 and #44056). - // - // To workaround the bug, we trick LLVM into not increasing - // the global's alignment by explicitly assigning a section to it - // (equivalent to automatically generating a `#[link_section]` attribute). - // See the comment in the `GlobalValue::canIncreaseAlignment()` function - // of `lib/IR/Globals.cpp` for why this works. - // - // When the alignment is not increased, the optimized `mem::replace` - // will use load-unaligned instructions instead, and thus avoiding the crash. - // - // We could remove this hack whenever we decide to drop macOS 10.10 support. - if self.tcx.sess.target.is_like_osx { - // The `inspect` method is okay here because we checked for provenance, and - // because we are doing this access to inspect the final interpreter state - // (not as part of the interpreter execution). - // - // FIXME: This check requires that the (arbitrary) value of undefined bytes - // happens to be zero. Instead, we should only check the value of defined bytes - // and set all undefined bytes to zero if this allocation is headed for the - // BSS. - let all_bytes_are_zero = alloc.provenance().ptrs().is_empty() - && alloc - .inspect_with_uninit_and_ptr_outside_interpreter(0..alloc.len()) - .iter() - .all(|&byte| byte == 0); - - let sect_name = if all_bytes_are_zero { - c"__DATA,__thread_bss" - } else { - c"__DATA,__thread_data" - }; - llvm::LLVMSetSection(g, sect_name.as_ptr()); - } } // Wasm statics with custom link sections get special treatment as they diff --git a/library/std/src/fs.rs b/library/std/src/fs.rs index 536d0d1b356a9..25540410cc7eb 100644 --- a/library/std/src/fs.rs +++ b/library/std/src/fs.rs @@ -2471,16 +2471,15 @@ pub fn remove_dir>(path: P) -> io::Result<()> { /// # Platform-specific behavior /// /// This function currently corresponds to `openat`, `fdopendir`, `unlinkat` and `lstat` functions -/// on Unix (except for macOS before version 10.10 and REDOX) and the `CreateFileW`, -/// `GetFileInformationByHandleEx`, `SetFileInformationByHandle`, and `NtCreateFile` functions on -/// Windows. Note that, this [may change in the future][changes]. +/// on Unix (except for REDOX) and the `CreateFileW`, `GetFileInformationByHandleEx`, +/// `SetFileInformationByHandle`, and `NtCreateFile` functions on Windows. Note that, this +/// [may change in the future][changes]. /// /// [changes]: io#platform-specific-behavior /// -/// On macOS before version 10.10 and REDOX, as well as when running in Miri for any target, this -/// function is not protected against time-of-check to time-of-use (TOCTOU) race conditions, and -/// should not be used in security-sensitive code on those platforms. All other platforms are -/// protected. +/// On REDOX, as well as when running in Miri for any target, this function is not protected against +/// time-of-check to time-of-use (TOCTOU) race conditions, and should not be used in +/// security-sensitive code on those platforms. All other platforms are protected. /// /// # Errors /// diff --git a/tests/codegen/issues/issue-44056-macos-tls-align.rs b/tests/codegen/issues/issue-44056-macos-tls-align.rs deleted file mode 100644 index 972b8490d18f9..0000000000000 --- a/tests/codegen/issues/issue-44056-macos-tls-align.rs +++ /dev/null @@ -1,27 +0,0 @@ -// -//@ only-apple -//@ compile-flags: -O - -#![crate_type = "rlib"] -#![feature(thread_local)] - -// local_unnamed_addr does not appear when std is built with debug assertions. -// CHECK: @STATIC_VAR_1 = thread_local {{(local_unnamed_addr )?}}global <{ [32 x i8] }> zeroinitializer, section "__DATA,__thread_bss", align 4 -#[no_mangle] -#[thread_local] -static mut STATIC_VAR_1: [u32; 8] = [0; 8]; - -// CHECK: @STATIC_VAR_2 = thread_local {{(local_unnamed_addr )?}}global <{ [32 x i8] }> <{{[^>]*}}>, section "__DATA,__thread_data", align 4 -#[no_mangle] -#[thread_local] -static mut STATIC_VAR_2: [u32; 8] = [4; 8]; - -#[no_mangle] -pub unsafe fn f(x: &mut [u32; 8]) { - std::mem::swap(x, &mut STATIC_VAR_1) -} - -#[no_mangle] -pub unsafe fn g(x: &mut [u32; 8]) { - std::mem::swap(x, &mut STATIC_VAR_2) -} From 0c45d3bb705e12251eb1914816373792d081ef35 Mon Sep 17 00:00:00 2001 From: Kalle Wachsmuth Date: Mon, 2 Sep 2024 23:51:22 +0200 Subject: [PATCH 0489/2194] update docs of missing_abi lint --- compiler/rustc_lint_defs/src/builtin.rs | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index 7063f488209ea..25d33126754af 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs @@ -3706,7 +3706,7 @@ declare_lint_pass!(UnusedDocComment => [UNUSED_DOC_COMMENTS]); declare_lint! { /// The `missing_abi` lint detects cases where the ABI is omitted from - /// extern declarations. + /// `extern` declarations. /// /// ### Example /// @@ -3720,10 +3720,12 @@ declare_lint! { /// /// ### Explanation /// - /// Historically, Rust implicitly selected C as the ABI for extern - /// declarations. We expect to add new ABIs, like `C-unwind`, in the future, - /// though this has not yet happened, and especially with their addition - /// seeing the ABI easily will make code review easier. + /// For historic reasons, Rust implicitly selects `C` as the default ABI for + /// `extern` declarations. [Other ABIs] like `C-unwind` and `system` have + /// been added since then, and especially with their addition seeing the ABI + /// easily makes code review easier. + /// + /// [Other ABIs]: https://doc.rust-lang.org/reference/items/external-blocks.html#abi pub MISSING_ABI, Allow, "No declared ABI for extern declaration" From c207badc2dd6abb1f416c4e09968184a69ff0484 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 4 Sep 2024 15:19:29 +0200 Subject: [PATCH 0490/2194] Add missing intrinsics translation for `llvm.x86.xsavec64` and fix more intrinsic calls --- src/intrinsic/llvm.rs | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/intrinsic/llvm.rs b/src/intrinsic/llvm.rs index ba57e425b0fca..89d5d582e4c71 100644 --- a/src/intrinsic/llvm.rs +++ b/src/intrinsic/llvm.rs @@ -361,7 +361,14 @@ pub fn adjust_intrinsic_arguments<'a, 'b, 'gcc, 'tcx>( let minus_one = builder.context.new_rvalue_from_int(arg4_type, -1); args = vec![new_args[1], new_args[0], new_args[2], minus_one].into(); } - "__builtin_ia32_xrstor" | "__builtin_ia32_xsavec" => { + "__builtin_ia32_xrstor" + | "__builtin_ia32_xrstor64" + | "__builtin_ia32_xsavec" + | "__builtin_ia32_xsavec64" + | "__builtin_ia32_xsave" + | "__builtin_ia32_xsave64" + | "__builtin_ia32_xsaveopt" + | "__builtin_ia32_xsaveopt64" => { let new_args = args.to_vec(); let thirty_two = builder.context.new_rvalue_from_int(new_args[1].get_type(), 32); let arg2 = new_args[1] << thirty_two | new_args[2]; @@ -824,7 +831,7 @@ pub fn intrinsic<'gcc, 'tcx>(name: &str, cx: &CodegenCx<'gcc, 'tcx>) -> Function "llvm.x86.xrstor" => "__builtin_ia32_xrstor", "llvm.x86.xrstor64" => "__builtin_ia32_xrstor64", "llvm.x86.xsavec" => "__builtin_ia32_xsavec", - "llvm.x86.xsave64" => "__builtin_ia32_xsave64", + "llvm.x86.xsavec64" => "__builtin_ia32_xsavec64", "llvm.x86.addcarry.32" => "__builtin_ia32_addcarryx_u32", "llvm.x86.subborrow.32" => "__builtin_ia32_sbb_u32", "llvm.x86.avx512.mask.compress.store.w.512" => "__builtin_ia32_compressstoreuhi512_mask", @@ -1029,6 +1036,7 @@ pub fn intrinsic<'gcc, 'tcx>(name: &str, cx: &CodegenCx<'gcc, 'tcx>) -> Function "llvm.x86.avx512.vpdpbusds.256" => "__builtin_ia32_vpdpbusds_v8si", "llvm.x86.avx512.vpdpbusds.128" => "__builtin_ia32_vpdpbusds_v4si", "llvm.x86.xsave" => "__builtin_ia32_xsave", + "llvm.x86.xsave64" => "__builtin_ia32_xsave64", "llvm.x86.xsaveopt" => "__builtin_ia32_xsaveopt", "llvm.x86.xsaveopt64" => "__builtin_ia32_xsaveopt64", "llvm.x86.avx512.mask.loadu.w.512" => "__builtin_ia32_loaddquhi512_mask", From 6e4c5c10b9b8740cecd62464c616cc82a01bc962 Mon Sep 17 00:00:00 2001 From: liushuyu Date: Tue, 3 Sep 2024 13:42:10 -0600 Subject: [PATCH 0491/2194] tests: add an assembly scanning test for s390x backchain switch --- tests/assembly/s390x-backchain-toggle.rs | 46 ++++++++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 tests/assembly/s390x-backchain-toggle.rs diff --git a/tests/assembly/s390x-backchain-toggle.rs b/tests/assembly/s390x-backchain-toggle.rs new file mode 100644 index 0000000000000..8b6d0cf212320 --- /dev/null +++ b/tests/assembly/s390x-backchain-toggle.rs @@ -0,0 +1,46 @@ +//@ revisions: enable-backchain disable-backchain +//@ assembly-output: emit-asm +//@ compile-flags: -O --crate-type=lib --target=s390x-unknown-linux-gnu +//@ needs-llvm-components: systemz +//@[enable-backchain] compile-flags: -Ctarget-feature=+backchain +//@[disable-backchain] compile-flags: -Ctarget-feature=-backchain +#![feature(no_core, lang_items)] +#![no_std] +#![no_core] + +#[lang = "sized"] +trait Sized {} + +extern "C" { + fn extern_func(); +} + +// CHECK-LABEL: test_backchain +#[no_mangle] +extern "C" fn test_backchain() -> i32 { + // Here we try to match if backchain register is saved to the parameter area (stored in r15/sp) + // And also if a new parameter area (160 bytes) is allocated for the upcoming function call + // enable-backchain: lgr [[REG1:.*]], %r15 + // enable-backchain-NEXT: aghi %r15, -160 + // enable-backchain: stg [[REG1]], 0(%r15) + // disable-backchain: aghi %r15, -160 + // disable-backchain-NOT: stg %r{{.*}}, 0(%r15) + unsafe { + extern_func(); + } + // enable-backchain-NEXT: brasl %r{{.*}}, extern_func@PLT + // disable-backchain: brasl %r{{.*}}, extern_func@PLT + + // Make sure that the expected return value is written into %r2 (return register): + // enable-backchain-NEXT: lghi %r2, 1 + // disable-backchain: lghi %r2, 0 + #[cfg(target_feature = "backchain")] + { + 1 + } + #[cfg(not(target_feature = "backchain"))] + { + 0 + } + // CHECK: br %r{{.*}} +} From 49a93df77d3c617e14fd466f30d06b4ab54a64df Mon Sep 17 00:00:00 2001 From: Ryosuke Takahashi Date: Thu, 5 Sep 2024 00:48:00 +0900 Subject: [PATCH 0492/2194] fix: correct {Path,OsStr}::to_string_lossy() docs --- library/std/src/ffi/os_str.rs | 2 +- library/std/src/path.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/library/std/src/ffi/os_str.rs b/library/std/src/ffi/os_str.rs index 918eec2d0d8ef..99bea676e1224 100644 --- a/library/std/src/ffi/os_str.rs +++ b/library/std/src/ffi/os_str.rs @@ -852,7 +852,7 @@ impl OsStr { /// Converts an `OsStr` to a [Cow]<[str]>. /// - /// Any non-Unicode sequences are replaced with + /// Any non-UTF-8 sequences are replaced with /// [`U+FFFD REPLACEMENT CHARACTER`][U+FFFD]. /// /// [U+FFFD]: crate::char::REPLACEMENT_CHARACTER diff --git a/library/std/src/path.rs b/library/std/src/path.rs index 9eaa0e01c2c00..506ad445b6bed 100644 --- a/library/std/src/path.rs +++ b/library/std/src/path.rs @@ -2200,7 +2200,7 @@ impl Path { /// Converts a `Path` to a [`Cow`]. /// - /// Any non-Unicode sequences are replaced with + /// Any non-UTF-8 sequences are replaced with /// [`U+FFFD REPLACEMENT CHARACTER`][U+FFFD]. /// /// [U+FFFD]: super::char::REPLACEMENT_CHARACTER From 38514bade22c673cadc244c0f264917104998294 Mon Sep 17 00:00:00 2001 From: David Barsky Date: Wed, 4 Sep 2024 08:52:57 -0400 Subject: [PATCH 0493/2194] assist: ensure replace_qualified_name_with_use applies to the first path segment --- .../replace_qualified_name_with_use.rs | 34 ++++++++++++++----- 1 file changed, 25 insertions(+), 9 deletions(-) diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_qualified_name_with_use.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_qualified_name_with_use.rs index 65330b34c4ad2..1101c20f1b785 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_qualified_name_with_use.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_qualified_name_with_use.rs @@ -29,7 +29,7 @@ pub(crate) fn replace_qualified_name_with_use( acc: &mut Assists, ctx: &AssistContext<'_>, ) -> Option<()> { - let original_path: ast::Path = ctx.find_node_at_offset()?; + let mut original_path: ast::Path = ctx.find_node_at_offset()?; // We don't want to mess with use statements if original_path.syntax().ancestors().find_map(ast::UseTree::cast).is_some() { cov_mark::hit!(not_applicable_in_use); @@ -37,8 +37,7 @@ pub(crate) fn replace_qualified_name_with_use( } if original_path.qualifier().is_none() { - cov_mark::hit!(dont_import_trivial_paths); - return None; + original_path = original_path.parent_path()?; } // only offer replacement for non assoc items @@ -236,12 +235,6 @@ fs::Path ); } - #[test] - fn dont_import_trivial_paths() { - cov_mark::check!(dont_import_trivial_paths); - check_assist_not_applicable(replace_qualified_name_with_use, r"impl foo$0 for () {}"); - } - #[test] fn test_replace_not_applicable_in_use() { cov_mark::check!(not_applicable_in_use); @@ -271,6 +264,29 @@ fn main() { ); } + #[test] + fn assist_runs_on_first_segment() { + check_assist( + replace_qualified_name_with_use, + r" +mod std { pub mod fmt { pub trait Debug {} } } +fn main() { + $0std::fmt::Debug; + let x: std::fmt::Debug = std::fmt::Debug; +} + ", + r" +use std::fmt; + +mod std { pub mod fmt { pub trait Debug {} } } +fn main() { + fmt::Debug; + let x: fmt::Debug = fmt::Debug; +} + ", + ); + } + #[test] fn does_not_replace_in_submodules() { check_assist( From cdb442362b464472f1ede46f5b2763811978c2bf Mon Sep 17 00:00:00 2001 From: Philipp Krones Date: Wed, 4 Sep 2024 18:17:31 +0200 Subject: [PATCH 0494/2194] Bump actions/download-artifact from 3 to 4 --- .github/workflows/clippy_bors.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/clippy_bors.yml b/.github/workflows/clippy_bors.yml index 2aa13313fa518..026771e6fcf42 100644 --- a/.github/workflows/clippy_bors.yml +++ b/.github/workflows/clippy_bors.yml @@ -162,7 +162,7 @@ jobs: find $DIR ! -executable -o -type d ! -path $DIR | xargs rm -rf - name: Upload Binaries - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: binaries path: target/debug @@ -202,7 +202,7 @@ jobs: # Download - name: Download target dir - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: binaries path: target/debug From f2d4198d6ef65134fe5bc277e362df90d237a41d Mon Sep 17 00:00:00 2001 From: Lukas Bergdoll Date: Wed, 4 Sep 2024 18:58:44 +0200 Subject: [PATCH 0495/2194] Drop bubble_sort While using it results in slightly slammer binaries, it's not deemed worth it to add yet another sort algorithm to the standard library. select_nth_unstable has bigger binary-size problems. --- library/core/src/slice/sort/mod.rs | 1 - library/core/src/slice/sort/select.rs | 41 +---------------------- library/core/src/slice/sort/shared/mod.rs | 2 ++ 3 files changed, 3 insertions(+), 41 deletions(-) diff --git a/library/core/src/slice/sort/mod.rs b/library/core/src/slice/sort/mod.rs index 81b99a4364b2e..79852708b81ea 100644 --- a/library/core/src/slice/sort/mod.rs +++ b/library/core/src/slice/sort/mod.rs @@ -5,5 +5,4 @@ pub mod stable; pub mod unstable; pub(crate) mod select; -#[cfg(not(feature = "optimize_for_size"))] pub(crate) mod shared; diff --git a/library/core/src/slice/sort/select.rs b/library/core/src/slice/sort/select.rs index 7bda54e792528..3358c03d30a9b 100644 --- a/library/core/src/slice/sort/select.rs +++ b/library/core/src/slice/sort/select.rs @@ -9,7 +9,6 @@ use crate::mem::{self, SizedTypeProperties}; #[cfg(not(feature = "optimize_for_size"))] use crate::slice::sort::shared::pivot::choose_pivot; -#[cfg(not(feature = "optimize_for_size"))] use crate::slice::sort::shared::smallsort::insertion_sort_shift_left; use crate::slice::sort::unstable::quicksort::partition; @@ -176,13 +175,7 @@ fn median_of_medians bool>(mut v: &mut [T], is_less: &mut loop { if v.len() <= INSERTION_SORT_THRESHOLD { if v.len() >= 2 { - cfg_if! { - if #[cfg(feature = "optimize_for_size")] { - bubble_sort(v, is_less); - } else { - insertion_sort_shift_left(v, 1, is_less); - } - } + insertion_sort_shift_left(v, 1, is_less); } return; @@ -314,35 +307,3 @@ fn median_idx bool>( } b } - -// It's possible to re-use the insertion sort in the smallsort module, but with optimize_for_size it -// would clutter that module with cfg statements and make it generally harder to read and develop. -// So to decouple things and simplify it, we use an even smaller bubble sort. -#[cfg(feature = "optimize_for_size")] -fn bubble_sort bool>(v: &mut [T], is_less: &mut F) { - use crate::ptr; - - let mut n = v.len(); - - let v_base = v.as_mut_ptr(); - - while n > 1 { - let loop_n = n; - n = 0; - for i in 1..loop_n { - // SAFETY: The loop construction implies that `i` and `i - 1` will always be in-bounds. - unsafe { - // Even if `is_less` erroneously always returns true, we are guaranteed that `n` - // reduces by one each out loop iteration, because `1..n` is exclusive. This - // guarantees a bounded run-time should `Ord` be implemented incorrectly. - let v_i = v_base.add(i); - let v_i_minus_one = v_base.add(i - 1); - - if is_less(&*v_i, &*v_i_minus_one) { - ptr::swap_nonoverlapping(v_i, v_i_minus_one, 1); - n = i; - } - } - } - } -} diff --git a/library/core/src/slice/sort/shared/mod.rs b/library/core/src/slice/sort/shared/mod.rs index ad1171bfc6a0a..e0f8d475a2e30 100644 --- a/library/core/src/slice/sort/shared/mod.rs +++ b/library/core/src/slice/sort/shared/mod.rs @@ -1,3 +1,5 @@ +#![cfg_attr(feature = "optimize_for_size", allow(dead_code))] + use crate::marker::Freeze; pub(crate) mod pivot; From adb0e27acd065354b6635c3c5a66dcbbc2e9d9c5 Mon Sep 17 00:00:00 2001 From: Lukas Bergdoll Date: Wed, 4 Sep 2024 19:37:49 +0200 Subject: [PATCH 0496/2194] Shrink heapsort further by combining sift_down loops --- .../core/src/slice/sort/unstable/heapsort.rs | 36 +++++++++---------- library/core/src/slice/sort/unstable/mod.rs | 5 +-- .../core/src/slice/sort/unstable/quicksort.rs | 7 ++-- 3 files changed, 22 insertions(+), 26 deletions(-) diff --git a/library/core/src/slice/sort/unstable/heapsort.rs b/library/core/src/slice/sort/unstable/heapsort.rs index 27e2ad588ea09..35bfe2959cd78 100644 --- a/library/core/src/slice/sort/unstable/heapsort.rs +++ b/library/core/src/slice/sort/unstable/heapsort.rs @@ -1,46 +1,46 @@ //! This module contains a branchless heapsort as fallback for unstable quicksort. -use crate::{intrinsics, ptr}; +use crate::{cmp, intrinsics, ptr}; /// Sorts `v` using heapsort, which guarantees *O*(*n* \* log(*n*)) worst-case. /// /// Never inline this, it sits the main hot-loop in `recurse` and is meant as unlikely algorithmic /// fallback. -/// -/// SAFETY: The caller has to guarantee that `v.len()` >= 2. #[inline(never)] -pub(crate) unsafe fn heapsort(v: &mut [T], is_less: &mut F) +pub(crate) fn heapsort(v: &mut [T], is_less: &mut F) where F: FnMut(&T, &T) -> bool, { - // SAFETY: See function safety. - unsafe { - intrinsics::assume(v.len() >= 2); - - // Build the heap in linear time. - for i in (0..v.len() / 2).rev() { - sift_down(v, i, is_less); - } + let len = v.len(); - // Pop maximal elements from the heap. - for i in (1..v.len()).rev() { + for i in (0..len + len / 2).rev() { + let sift_idx = if i >= len { + i - len + } else { v.swap(0, i); - sift_down(&mut v[..i], 0, is_less); + 0 + }; + + // SAFETY: The above calculation ensures that `sift_idx` is either 0 or + // `(len..(len + (len / 2))) - len`, which simplifies to `0..(len / 2)`. + // This guarantees the required `sift_idx <= len`. + unsafe { + sift_down(&mut v[..cmp::min(i, len)], sift_idx, is_less); } } } // This binary heap respects the invariant `parent >= child`. // -// SAFETY: The caller has to guarantee that node < `v.len()`. -#[inline(never)] +// SAFETY: The caller has to guarantee that `node <= v.len()`. +#[inline(always)] unsafe fn sift_down(v: &mut [T], mut node: usize, is_less: &mut F) where F: FnMut(&T, &T) -> bool, { // SAFETY: See function safety. unsafe { - intrinsics::assume(node < v.len()); + intrinsics::assume(node <= v.len()); } let len = v.len(); diff --git a/library/core/src/slice/sort/unstable/mod.rs b/library/core/src/slice/sort/unstable/mod.rs index 130be21ee3fe8..953c27ab6f417 100644 --- a/library/core/src/slice/sort/unstable/mod.rs +++ b/library/core/src/slice/sort/unstable/mod.rs @@ -32,10 +32,7 @@ pub fn sort bool>(v: &mut [T], is_less: &mut F) { cfg_if! { if #[cfg(feature = "optimize_for_size")] { - // SAFETY: We checked that `len >= 2`. - unsafe { - heapsort::heapsort(v, is_less); - } + heapsort::heapsort(v, is_less); } else { // More advanced sorting methods than insertion sort are faster if called in // a hot loop for small inputs, but for general-purpose code the small diff --git a/library/core/src/slice/sort/unstable/quicksort.rs b/library/core/src/slice/sort/unstable/quicksort.rs index 9c59ccdb70005..4feef5deeb0fb 100644 --- a/library/core/src/slice/sort/unstable/quicksort.rs +++ b/library/core/src/slice/sort/unstable/quicksort.rs @@ -5,6 +5,8 @@ use crate::mem::{self, ManuallyDrop}; use crate::slice::sort::shared::pivot::choose_pivot; #[cfg(not(feature = "optimize_for_size"))] use crate::slice::sort::shared::smallsort::UnstableSmallSortTypeImpl; +#[cfg(not(feature = "optimize_for_size"))] +use crate::slice::sort::unstable::heapsort; use crate::{intrinsics, ptr}; /// Sorts `v` recursively. @@ -31,10 +33,7 @@ pub(crate) fn quicksort<'a, T, F>( // If too many bad pivot choices were made, simply fall back to heapsort in order to // guarantee `O(N x log(N))` worst-case. if limit == 0 { - // SAFETY: We assume the `small_sort` threshold is at least 1. - unsafe { - crate::slice::sort::unstable::heapsort::heapsort(v, is_less); - } + heapsort::heapsort(v, is_less); return; } From 7d2e6ebcbeb2ca161b4b0f8a88bd41bf4c1381f5 Mon Sep 17 00:00:00 2001 From: Lukas Lueg Date: Wed, 4 Sep 2024 19:37:59 +0200 Subject: [PATCH 0497/2194] Expand missing_transmute_annotations docs Fixes #13339 --- clippy_lints/src/transmute/mod.rs | 32 +++++++++++++++++++++++++------ 1 file changed, 26 insertions(+), 6 deletions(-) diff --git a/clippy_lints/src/transmute/mod.rs b/clippy_lints/src/transmute/mod.rs index 373bf61d8ff94..6e62668fd5272 100644 --- a/clippy_lints/src/transmute/mod.rs +++ b/clippy_lints/src/transmute/mod.rs @@ -527,24 +527,44 @@ declare_clippy_lint! { /// Checks if transmute calls have all generics specified. /// /// ### Why is this bad? - /// If not set, some unexpected output type could be retrieved instead of the expected one, - /// potentially leading to invalid code. + /// If not, one or more unexpected types could be used during `transmute()`, potentially leading + /// to Undefined Behavior or other problems. /// - /// This is particularly dangerous in case a seemingly innocent/unrelated change can cause type - /// inference to start inferring a different type. E.g. the transmute is the tail expression of - /// an `if` branch, and a different branches type changes, causing the transmute to silently - /// have a different type, instead of a proper error. + /// This is particularly dangerous in case a seemingly innocent/unrelated change causes type + /// inference to result in a different type. For example, if `transmute()` is the tail + /// expression of an `if`-branch, and the `else`-branch type changes, the compiler may silently + /// infer a different type to be returned by `transmute()`. That is because the compiler is + /// free to change the inference of a type as long as that inference is technically correct, + /// regardless of the programmer's unknown expectation. + /// + /// Both type-parameters, the input- and the output-type, to any `transmute()` should + /// be given explicitly: Setting the input-type explicitly avoids confusion about what the + /// argument's type actually is. Setting the output-type explicitly avoids type-inference + /// to infer a technically correct yet unexpected type. /// /// ### Example /// ```no_run /// # unsafe { + /// // Avoid "naked" calls to `transmute()`! /// let x: i32 = std::mem::transmute([1u16, 2u16]); + /// + /// // `first_answers` is intended to transmute a slice of bool to a slice of u8. + /// // But the programmer forgot to index the first element of the outer slice, + /// // so we are actually transmuting from "pointers to slices" instead of + /// // transmuting from "a slice of bool", causing a nonsensical result. + /// let the_answers: &[&[bool]] = &[&[true, false, true]]; + /// let first_answers: &[u8] = std::mem::transmute(the_answers); /// # } /// ``` /// Use instead: /// ```no_run /// # unsafe { /// let x = std::mem::transmute::<[u16; 2], i32>([1u16, 2u16]); + /// + /// // The explicit type parameters on `transmute()` makes the intention clear, + /// // and cause a type-error if the actual types don't match our expectation. + /// let the_answers: &[&[bool]] = &[&[true, false, true]]; + /// let first_answers: &[u8] = std::mem::transmute::<&[bool], &[u8]>(the_answers[0]); /// # } /// ``` #[clippy::version = "1.79.0"] From a0e4303ba2ed087a85e0218a4049d8cc73d7f404 Mon Sep 17 00:00:00 2001 From: Lukas Bergdoll Date: Wed, 4 Sep 2024 19:53:56 +0200 Subject: [PATCH 0498/2194] Select tiny sorts for 16-bit platforms Also skips stack alloc in stable sort if 16-bit target platform. --- library/core/src/slice/sort/stable/mod.rs | 31 +++++++++++++-------- library/core/src/slice/sort/unstable/mod.rs | 2 +- 2 files changed, 20 insertions(+), 13 deletions(-) diff --git a/library/core/src/slice/sort/stable/mod.rs b/library/core/src/slice/sort/stable/mod.rs index 3472401c4dcf8..00eb3785e0f25 100644 --- a/library/core/src/slice/sort/stable/mod.rs +++ b/library/core/src/slice/sort/stable/mod.rs @@ -40,20 +40,27 @@ pub fn sort bool, BufT: BufGuard>(v: &mut [T], is_less } cfg_if! { - if #[cfg(feature = "optimize_for_size")] { + if #[cfg(any(feature = "optimize_for_size", target_pointer_width = "16"))] { let alloc_len = len / 2; - // For small inputs 4KiB of stack storage suffices, which allows us to avoid - // calling the (de-)allocator. Benchmarks showed this was quite beneficial. - let mut stack_buf = AlignedStorage::::new(); - let stack_scratch = stack_buf.as_uninit_slice_mut(); - let mut heap_buf; - let scratch = if stack_scratch.len() >= alloc_len { - stack_scratch - } else { - heap_buf = BufT::with_capacity(alloc_len); - heap_buf.as_uninit_slice_mut() - }; + cfg_if! { + if #[cfg(target_pointer_width = "16")] { + let heap_buf = BufT::with_capacity(alloc_len); + let scratch = heap_buf.as_uninit_slice_mut(); + } else { + // For small inputs 4KiB of stack storage suffices, which allows us to avoid + // calling the (de-)allocator. Benchmarks showed this was quite beneficial. + let mut stack_buf = AlignedStorage::::new(); + let stack_scratch = stack_buf.as_uninit_slice_mut(); + let mut heap_buf; + let scratch = if stack_scratch.len() >= alloc_len { + stack_scratch + } else { + heap_buf = BufT::with_capacity(alloc_len); + heap_buf.as_uninit_slice_mut() + }; + } + } tiny::mergesort(v, scratch, is_less); } else { diff --git a/library/core/src/slice/sort/unstable/mod.rs b/library/core/src/slice/sort/unstable/mod.rs index 953c27ab6f417..8bbd85443d478 100644 --- a/library/core/src/slice/sort/unstable/mod.rs +++ b/library/core/src/slice/sort/unstable/mod.rs @@ -31,7 +31,7 @@ pub fn sort bool>(v: &mut [T], is_less: &mut F) { } cfg_if! { - if #[cfg(feature = "optimize_for_size")] { + if #[cfg(any(feature = "optimize_for_size", target_pointer_width = "16"))] { heapsort::heapsort(v, is_less); } else { // More advanced sorting methods than insertion sort are faster if called in From 54391983486d5271c378821c8e6a8f018dfdd14d Mon Sep 17 00:00:00 2001 From: Lukas Bergdoll Date: Wed, 4 Sep 2024 19:54:46 +0200 Subject: [PATCH 0499/2194] Use non-overlapping swap for inner heapsort loop This regresses binary-size slightly for normal builds, but the important release_lto_thin_opt_level_s config sees a small improvement in binary-size and a larger types such as string and 1k see 2-3% run-time improvements with this change. --- library/core/src/slice/sort/unstable/heapsort.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/library/core/src/slice/sort/unstable/heapsort.rs b/library/core/src/slice/sort/unstable/heapsort.rs index 35bfe2959cd78..85231779d031f 100644 --- a/library/core/src/slice/sort/unstable/heapsort.rs +++ b/library/core/src/slice/sort/unstable/heapsort.rs @@ -69,9 +69,7 @@ where break; } - // Swap `node` with the greater child, move one step down, and continue sifting. This - // could be ptr::swap_nonoverlapping but that adds a significant amount of binary-size. - ptr::swap(v_base.add(node), v_base.add(child)); + ptr::swap_nonoverlapping(v_base.add(node), v_base.add(child), 1); } node = child; From f7679d050793304eff9ff2a46a824cc5495e6f93 Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Wed, 4 Sep 2024 12:29:44 +0200 Subject: [PATCH 0500/2194] propagate `tainted_by_errors` in `MirBorrowckCtxt::emit_errors` --- compiler/rustc_borrowck/src/lib.rs | 2 +- tests/ui/consts/missing_assoc_const_type.rs | 2 +- tests/ui/consts/missing_assoc_const_type.stderr | 8 +++++++- .../{crashes/124164.rs => ui/static/missing-type.rs} | 3 ++- tests/ui/static/missing-type.stderr | 8 ++++++++ .../126896.rs => ui/type-alias-impl-trait/taint.rs} | 8 ++++---- tests/ui/type-alias-impl-trait/taint.stderr | 12 ++++++++++++ 7 files changed, 35 insertions(+), 8 deletions(-) rename tests/{crashes/124164.rs => ui/static/missing-type.rs} (52%) create mode 100644 tests/ui/static/missing-type.stderr rename tests/{crashes/126896.rs => ui/type-alias-impl-trait/taint.rs} (59%) create mode 100644 tests/ui/type-alias-impl-trait/taint.stderr diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs index ffb350b1d1f0f..d40dcfa58054a 100644 --- a/compiler/rustc_borrowck/src/lib.rs +++ b/compiler/rustc_borrowck/src/lib.rs @@ -2522,7 +2522,7 @@ mod diags { } pub(crate) fn emit_errors(&mut self) -> Option { - let mut res = None; + let mut res = self.infcx.tainted_by_errors(); // Buffer any move errors that we collected and de-duplicated. for (_, (_, diag)) in std::mem::take(&mut self.diags.buffered_move_errors) { diff --git a/tests/ui/consts/missing_assoc_const_type.rs b/tests/ui/consts/missing_assoc_const_type.rs index 8d95e3dca633c..633998e9bc157 100644 --- a/tests/ui/consts/missing_assoc_const_type.rs +++ b/tests/ui/consts/missing_assoc_const_type.rs @@ -16,7 +16,7 @@ impl Range for TwoDigits { const fn digits(x: u8) -> usize { match x { - TwoDigits::FIRST..=TwoDigits::LAST => 0, + TwoDigits::FIRST..=TwoDigits::LAST => 0, //~ ERROR: could not evaluate constant pattern 0..=9 | 100..=255 => panic!(), } } diff --git a/tests/ui/consts/missing_assoc_const_type.stderr b/tests/ui/consts/missing_assoc_const_type.stderr index 28af1f0f321e6..ef7ff962d2d12 100644 --- a/tests/ui/consts/missing_assoc_const_type.stderr +++ b/tests/ui/consts/missing_assoc_const_type.stderr @@ -4,5 +4,11 @@ error: missing type for `const` item LL | const FIRST: = 10; | ^ help: provide a type for the associated constant: `u8` -error: aborting due to 1 previous error +error: could not evaluate constant pattern + --> $DIR/missing_assoc_const_type.rs:19:9 + | +LL | TwoDigits::FIRST..=TwoDigits::LAST => 0, + | ^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors diff --git a/tests/crashes/124164.rs b/tests/ui/static/missing-type.rs similarity index 52% rename from tests/crashes/124164.rs rename to tests/ui/static/missing-type.rs index 8c9b4bddbe80d..2569f47b7c38c 100644 --- a/tests/crashes/124164.rs +++ b/tests/ui/static/missing-type.rs @@ -1,4 +1,5 @@ -//@ known-bug: #124164 +// reported as #124164 static S_COUNT: = std::sync::atomic::AtomicUsize::new(0); +//~^ ERROR: missing type for `static` item fn main() {} diff --git a/tests/ui/static/missing-type.stderr b/tests/ui/static/missing-type.stderr new file mode 100644 index 0000000000000..6489ceb700a2e --- /dev/null +++ b/tests/ui/static/missing-type.stderr @@ -0,0 +1,8 @@ +error: missing type for `static` item + --> $DIR/missing-type.rs:2:16 + | +LL | static S_COUNT: = std::sync::atomic::AtomicUsize::new(0); + | ^ help: provide a type for the static variable: `AtomicUsize` + +error: aborting due to 1 previous error + diff --git a/tests/crashes/126896.rs b/tests/ui/type-alias-impl-trait/taint.rs similarity index 59% rename from tests/crashes/126896.rs rename to tests/ui/type-alias-impl-trait/taint.rs index 49c539d7acc8a..dfb947637c042 100644 --- a/tests/crashes/126896.rs +++ b/tests/ui/type-alias-impl-trait/taint.rs @@ -1,6 +1,7 @@ -//@ known-bug: rust-lang/rust#126896 //@ compile-flags: -Zvalidate-mir -Zinline-mir=yes +// reported as rust-lang/rust#126896 + #![feature(type_alias_impl_trait)] type Two<'a, 'b> = impl std::fmt::Debug; @@ -9,9 +10,8 @@ fn set(x: &mut isize) -> isize { } fn d(x: Two) { - let c1 = || set(x); + let c1 = || set(x); //~ ERROR: expected generic lifetime parameter, found `'_` c1; } -fn main() { -} +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/taint.stderr b/tests/ui/type-alias-impl-trait/taint.stderr new file mode 100644 index 0000000000000..17fcd4b7e9325 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/taint.stderr @@ -0,0 +1,12 @@ +error[E0792]: expected generic lifetime parameter, found `'_` + --> $DIR/taint.rs:13:17 + | +LL | type Two<'a, 'b> = impl std::fmt::Debug; + | -- this generic parameter must be used with a generic lifetime parameter +... +LL | let c1 = || set(x); + | ^^^^^^ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0792`. From 49e3b9a2d2cf9bfbc5ada8e3d5dba8dee507dace Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Fri, 23 Aug 2024 16:38:20 +0200 Subject: [PATCH 0501/2194] fix ICE when `asm_const` and `const_refs_to_static` are combined --- .../rustc_borrowck/src/universal_regions.rs | 14 ++++++++++-- tests/ui/asm/const-refs-to-static.rs | 21 ++++++++++++++++++ tests/ui/asm/const-refs-to-static.stderr | 22 +++++++++++++++++++ 3 files changed, 55 insertions(+), 2 deletions(-) create mode 100644 tests/ui/asm/const-refs-to-static.rs create mode 100644 tests/ui/asm/const-refs-to-static.stderr diff --git a/compiler/rustc_borrowck/src/universal_regions.rs b/compiler/rustc_borrowck/src/universal_regions.rs index 9eabe817359c0..164be73f49296 100644 --- a/compiler/rustc_borrowck/src/universal_regions.rs +++ b/compiler/rustc_borrowck/src/universal_regions.rs @@ -29,7 +29,8 @@ use rustc_macros::extension; use rustc_middle::ty::fold::TypeFoldable; use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_middle::ty::{ - self, GenericArgs, GenericArgsRef, InlineConstArgs, InlineConstArgsParts, RegionVid, Ty, TyCtxt, + self, GenericArgs, GenericArgsRef, InlineConstArgs, InlineConstArgsParts, RegionVid, Ty, + TyCtxt, TypeVisitableExt, }; use rustc_middle::{bug, span_bug}; use rustc_span::symbol::{kw, sym}; @@ -688,7 +689,8 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> { defining_ty: DefiningTy<'tcx>, ) -> ty::Binder<'tcx, &'tcx ty::List>> { let tcx = self.infcx.tcx; - match defining_ty { + + let inputs_and_output = match defining_ty { DefiningTy::Closure(def_id, args) => { assert_eq!(self.mir_def.to_def_id(), def_id); let closure_sig = args.as_closure().sig(); @@ -798,6 +800,7 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> { // "output" (the type of the constant). assert_eq!(self.mir_def.to_def_id(), def_id); let ty = tcx.type_of(self.mir_def).instantiate_identity(); + let ty = indices.fold_to_region_vids(tcx, ty); ty::Binder::dummy(tcx.mk_type_list(&[ty])) } @@ -807,7 +810,14 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> { let ty = args.as_inline_const().ty(); ty::Binder::dummy(tcx.mk_type_list(&[ty])) } + }; + + // FIXME(#129952): We probably want a more principled approach here. + if let Err(terr) = inputs_and_output.skip_binder().error_reported() { + self.infcx.set_tainted_by_errors(terr); } + + inputs_and_output } } diff --git a/tests/ui/asm/const-refs-to-static.rs b/tests/ui/asm/const-refs-to-static.rs new file mode 100644 index 0000000000000..9fc010b576309 --- /dev/null +++ b/tests/ui/asm/const-refs-to-static.rs @@ -0,0 +1,21 @@ +//@ needs-asm-support +//@ ignore-nvptx64 +//@ ignore-spirv + +#![feature(const_refs_to_static)] + +use std::arch::{asm, global_asm}; +use std::ptr::addr_of; + +static FOO: u8 = 42; + +global_asm!("{}", const addr_of!(FOO)); +//~^ ERROR invalid type for `const` operand + +#[no_mangle] +fn inline() { + unsafe { asm!("{}", const addr_of!(FOO)) }; + //~^ ERROR invalid type for `const` operand +} + +fn main() {} diff --git a/tests/ui/asm/const-refs-to-static.stderr b/tests/ui/asm/const-refs-to-static.stderr new file mode 100644 index 0000000000000..8fd69da0d1e92 --- /dev/null +++ b/tests/ui/asm/const-refs-to-static.stderr @@ -0,0 +1,22 @@ +error: invalid type for `const` operand + --> $DIR/const-refs-to-static.rs:12:19 + | +LL | global_asm!("{}", const addr_of!(FOO)); + | ^^^^^^------------- + | | + | is a `*const u8` + | + = help: `const` operands must be of an integer type + +error: invalid type for `const` operand + --> $DIR/const-refs-to-static.rs:17:25 + | +LL | unsafe { asm!("{}", const addr_of!(FOO)) }; + | ^^^^^^------------- + | | + | is a `*const u8` + | + = help: `const` operands must be of an integer type + +error: aborting due to 2 previous errors + From f7f550561e801fa1adb74377fd95a151820d8d0e Mon Sep 17 00:00:00 2001 From: Alex Macleod Date: Wed, 4 Sep 2024 21:22:28 +0000 Subject: [PATCH 0502/2194] Only lint `manual_non_exhaustive` for exported types --- clippy_lints/src/lib.rs | 3 +- clippy_lints/src/manual_non_exhaustive.rs | 182 ++++++++----------- tests/ui/manual_non_exhaustive_enum.rs | 24 ++- tests/ui/manual_non_exhaustive_enum.stderr | 22 ++- tests/ui/manual_non_exhaustive_struct.rs | 50 ++--- tests/ui/manual_non_exhaustive_struct.stderr | 64 ++++--- 6 files changed, 166 insertions(+), 179 deletions(-) diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 078f38656ece8..747119e114795 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -633,8 +633,7 @@ pub fn register_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) { let format_args = format_args_storage.clone(); store.register_late_pass(move |_| Box::new(methods::Methods::new(conf, format_args.clone()))); store.register_late_pass(move |_| Box::new(matches::Matches::new(conf))); - store.register_early_pass(move || Box::new(manual_non_exhaustive::ManualNonExhaustiveStruct::new(conf))); - store.register_late_pass(move |_| Box::new(manual_non_exhaustive::ManualNonExhaustiveEnum::new(conf))); + store.register_late_pass(move |_| Box::new(manual_non_exhaustive::ManualNonExhaustive::new(conf))); store.register_late_pass(move |_| Box::new(manual_strip::ManualStrip::new(conf))); store.register_early_pass(move || Box::new(redundant_static_lifetimes::RedundantStaticLifetimes::new(conf))); store.register_early_pass(move || Box::new(redundant_field_names::RedundantFieldNames::new(conf))); diff --git a/clippy_lints/src/manual_non_exhaustive.rs b/clippy_lints/src/manual_non_exhaustive.rs index 6b1d90483ccd1..01f1d9c3beba2 100644 --- a/clippy_lints/src/manual_non_exhaustive.rs +++ b/clippy_lints/src/manual_non_exhaustive.rs @@ -2,16 +2,16 @@ use clippy_config::msrvs::{self, Msrv}; use clippy_config::Conf; use clippy_utils::diagnostics::{span_lint_and_then, span_lint_hir_and_then}; use clippy_utils::is_doc_hidden; -use clippy_utils::source::SpanRangeExt; -use rustc_ast::ast::{self, VisibilityKind}; +use clippy_utils::source::snippet_indent; +use itertools::Itertools; use rustc_ast::attr; use rustc_data_structures::fx::FxHashSet; use rustc_errors::Applicability; use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res}; -use rustc_hir::{self as hir, Expr, ExprKind, QPath}; -use rustc_lint::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext}; +use rustc_hir::{Expr, ExprKind, Item, ItemKind, QPath, TyKind, VariantData}; +use rustc_lint::{LateContext, LateLintPass}; use rustc_session::impl_lint_pass; -use rustc_span::def_id::{DefId, LocalDefId}; +use rustc_span::def_id::LocalDefId; use rustc_span::{sym, Span}; declare_clippy_lint! { @@ -62,29 +62,13 @@ declare_clippy_lint! { "manual implementations of the non-exhaustive pattern can be simplified using #[non_exhaustive]" } -#[expect(clippy::module_name_repetitions)] -pub struct ManualNonExhaustiveStruct { +pub struct ManualNonExhaustive { msrv: Msrv, -} - -impl ManualNonExhaustiveStruct { - pub fn new(conf: &'static Conf) -> Self { - Self { - msrv: conf.msrv.clone(), - } - } -} - -impl_lint_pass!(ManualNonExhaustiveStruct => [MANUAL_NON_EXHAUSTIVE]); - -#[expect(clippy::module_name_repetitions)] -pub struct ManualNonExhaustiveEnum { - msrv: Msrv, - constructed_enum_variants: FxHashSet<(DefId, DefId)>, + constructed_enum_variants: FxHashSet, potential_enums: Vec<(LocalDefId, LocalDefId, Span, Span)>, } -impl ManualNonExhaustiveEnum { +impl ManualNonExhaustive { pub fn new(conf: &'static Conf) -> Self { Self { msrv: conf.msrv.clone(), @@ -94,96 +78,78 @@ impl ManualNonExhaustiveEnum { } } -impl_lint_pass!(ManualNonExhaustiveEnum => [MANUAL_NON_EXHAUSTIVE]); - -impl EarlyLintPass for ManualNonExhaustiveStruct { - fn check_item(&mut self, cx: &EarlyContext<'_>, item: &ast::Item) { - if let ast::ItemKind::Struct(variant_data, _) = &item.kind - && let (fields, delimiter) = match variant_data { - ast::VariantData::Struct { fields, .. } => (&**fields, '{'), - ast::VariantData::Tuple(fields, _) => (&**fields, '('), - ast::VariantData::Unit(_) => return, - } - && fields.len() > 1 - && self.msrv.meets(msrvs::NON_EXHAUSTIVE) - { - let mut iter = fields.iter().filter_map(|f| match f.vis.kind { - VisibilityKind::Public => None, - VisibilityKind::Inherited => Some(Ok(f)), - VisibilityKind::Restricted { .. } => Some(Err(())), - }); - if let Some(Ok(field)) = iter.next() - && iter.next().is_none() - && field.ty.kind.is_unit() - { - span_lint_and_then( - cx, - MANUAL_NON_EXHAUSTIVE, - item.span, - "this seems like a manual implementation of the non-exhaustive pattern", - |diag| { - if !item.attrs.iter().any(|attr| attr.has_name(sym::non_exhaustive)) - && let header_span = cx.sess().source_map().span_until_char(item.span, delimiter) - && let Some(snippet) = header_span.get_source_text(cx) - { - diag.span_suggestion( - header_span, - "add the attribute", - format!("#[non_exhaustive] {snippet}"), - Applicability::Unspecified, - ); - } - diag.span_help(field.span, "remove this field"); - }, - ); - } - } - } +impl_lint_pass!(ManualNonExhaustive => [MANUAL_NON_EXHAUSTIVE]); - extract_msrv_attr!(EarlyContext); -} - -impl<'tcx> LateLintPass<'tcx> for ManualNonExhaustiveEnum { - fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'_>) { - if !self.msrv.meets(msrvs::NON_EXHAUSTIVE) { +impl<'tcx> LateLintPass<'tcx> for ManualNonExhaustive { + fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) { + if !self.msrv.meets(msrvs::NON_EXHAUSTIVE) || !cx.effective_visibilities.is_exported(item.owner_id.def_id) { return; } - if let hir::ItemKind::Enum(def, _) = &item.kind - && def.variants.len() > 1 - { - let mut iter = def.variants.iter().filter_map(|v| { - (matches!(v.data, hir::VariantData::Unit(_, _)) - && is_doc_hidden(cx.tcx.hir().attrs(v.hir_id)) - && !attr::contains_name(cx.tcx.hir().attrs(item.hir_id()), sym::non_exhaustive)) - .then_some((v.def_id, v.span)) - }); - if let Some((id, span)) = iter.next() - && iter.next().is_none() - { - self.potential_enums.push((item.owner_id.def_id, id, item.span, span)); - } + match item.kind { + ItemKind::Enum(def, _) if def.variants.len() > 1 => { + let iter = def.variants.iter().filter_map(|v| { + (matches!(v.data, VariantData::Unit(_, _)) && is_doc_hidden(cx.tcx.hir().attrs(v.hir_id))) + .then_some((v.def_id, v.span)) + }); + if let Ok((id, span)) = iter.exactly_one() + && !attr::contains_name(cx.tcx.hir().attrs(item.hir_id()), sym::non_exhaustive) + { + self.potential_enums.push((item.owner_id.def_id, id, item.span, span)); + } + }, + ItemKind::Struct(variant_data, _) => { + let fields = variant_data.fields(); + let private_fields = fields + .iter() + .filter(|field| !cx.effective_visibilities.is_exported(field.def_id)); + if fields.len() > 1 + && let Ok(field) = private_fields.exactly_one() + && let TyKind::Tup([]) = field.ty.kind + { + span_lint_and_then( + cx, + MANUAL_NON_EXHAUSTIVE, + item.span, + "this seems like a manual implementation of the non-exhaustive pattern", + |diag| { + if let Some(non_exhaustive) = + attr::find_by_name(cx.tcx.hir().attrs(item.hir_id()), sym::non_exhaustive) + { + diag.span_note(non_exhaustive.span, "the struct is already non-exhaustive"); + } else { + let indent = snippet_indent(cx, item.span).unwrap_or_default(); + diag.span_suggestion_verbose( + item.span.shrink_to_lo(), + "use the `#[non_exhaustive]` attribute instead", + format!("#[non_exhaustive]\n{indent}"), + Applicability::MaybeIncorrect, + ); + } + diag.span_help(field.span, "remove this field"); + }, + ); + } + }, + _ => {}, } } fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) { if let ExprKind::Path(QPath::Resolved(None, p)) = &e.kind - && let Res::Def(DefKind::Ctor(CtorOf::Variant, CtorKind::Const), id) = p.res + && let Res::Def(DefKind::Ctor(CtorOf::Variant, CtorKind::Const), ctor_id) = p.res + && let Some(local_ctor) = ctor_id.as_local() { - let variant_id = cx.tcx.parent(id); - let enum_id = cx.tcx.parent(variant_id); - - self.constructed_enum_variants.insert((enum_id, variant_id)); + let variant_id = cx.tcx.local_parent(local_ctor); + self.constructed_enum_variants.insert(variant_id); } } fn check_crate_post(&mut self, cx: &LateContext<'tcx>) { - for &(enum_id, _, enum_span, variant_span) in - self.potential_enums.iter().filter(|&&(enum_id, variant_id, _, _)| { - !self - .constructed_enum_variants - .contains(&(enum_id.to_def_id(), variant_id.to_def_id())) - }) + for &(enum_id, _, enum_span, variant_span) in self + .potential_enums + .iter() + .filter(|(_, variant_id, _, _)| !self.constructed_enum_variants.contains(variant_id)) { let hir_id = cx.tcx.local_def_id_to_hir_id(enum_id); span_lint_hir_and_then( @@ -193,15 +159,13 @@ impl<'tcx> LateLintPass<'tcx> for ManualNonExhaustiveEnum { enum_span, "this seems like a manual implementation of the non-exhaustive pattern", |diag| { - let header_span = cx.sess().source_map().span_until_char(enum_span, '{'); - if let Some(snippet) = header_span.get_source_text(cx) { - diag.span_suggestion( - header_span, - "add the attribute", - format!("#[non_exhaustive] {snippet}"), - Applicability::Unspecified, - ); - } + let indent = snippet_indent(cx, enum_span).unwrap_or_default(); + diag.span_suggestion_verbose( + enum_span.shrink_to_lo(), + "use the `#[non_exhaustive]` attribute instead", + format!("#[non_exhaustive]\n{indent}"), + Applicability::MaybeIncorrect, + ); diag.span_help(variant_span, "remove this variant"); }, ); diff --git a/tests/ui/manual_non_exhaustive_enum.rs b/tests/ui/manual_non_exhaustive_enum.rs index 31c3cc8013722..ffe2bb9246737 100644 --- a/tests/ui/manual_non_exhaustive_enum.rs +++ b/tests/ui/manual_non_exhaustive_enum.rs @@ -1,8 +1,8 @@ #![warn(clippy::manual_non_exhaustive)] #![allow(unused)] //@no-rustfix -enum E { - //~^ ERROR: this seems like a manual implementation of the non-exhaustive pattern +pub enum E { + //~^ manual_non_exhaustive A, B, #[doc(hidden)] @@ -11,7 +11,7 @@ enum E { // if the user explicitly marks as nonexhaustive we shouldn't warn them #[non_exhaustive] -enum Ep { +pub enum Ep { A, B, #[doc(hidden)] @@ -19,14 +19,14 @@ enum Ep { } // marker variant does not have doc hidden attribute, should be ignored -enum NoDocHidden { +pub enum NoDocHidden { A, B, _C, } // name of variant with doc hidden does not start with underscore -enum NoUnderscore { +pub enum NoUnderscore { A, B, #[doc(hidden)] @@ -34,7 +34,7 @@ enum NoUnderscore { } // variant with doc hidden is not unit, should be ignored -enum NotUnit { +pub enum NotUnit { A, B, #[doc(hidden)] @@ -42,13 +42,13 @@ enum NotUnit { } // variant with doc hidden is the only one, should be ignored -enum OnlyMarker { +pub enum OnlyMarker { #[doc(hidden)] _A, } // variant with multiple markers, should be ignored -enum MultipleMarkers { +pub enum MultipleMarkers { A, #[doc(hidden)] _B, @@ -58,13 +58,13 @@ enum MultipleMarkers { // already non_exhaustive and no markers, should be ignored #[non_exhaustive] -enum NonExhaustive { +pub enum NonExhaustive { A, B, } // marked is used, don't lint -enum UsedHidden { +pub enum UsedHidden { #[doc(hidden)] _A, B, @@ -77,11 +77,9 @@ fn foo(x: &mut UsedHidden) { } #[expect(clippy::manual_non_exhaustive)] -enum ExpectLint { +pub enum ExpectLint { A, B, #[doc(hidden)] _C, } - -fn main() {} diff --git a/tests/ui/manual_non_exhaustive_enum.stderr b/tests/ui/manual_non_exhaustive_enum.stderr index dc669568dd2d4..0a9ac157f8502 100644 --- a/tests/ui/manual_non_exhaustive_enum.stderr +++ b/tests/ui/manual_non_exhaustive_enum.stderr @@ -1,11 +1,7 @@ error: this seems like a manual implementation of the non-exhaustive pattern --> tests/ui/manual_non_exhaustive_enum.rs:4:1 | -LL | enum E { - | ^----- - | | - | _help: add the attribute: `#[non_exhaustive] enum E` - | | +LL | / pub enum E { LL | | LL | | A, LL | | B, @@ -21,15 +17,16 @@ LL | _C, | ^^ = note: `-D clippy::manual-non-exhaustive` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::manual_non_exhaustive)]` +help: use the `#[non_exhaustive]` attribute instead + | +LL + #[non_exhaustive] +LL | pub enum E { + | error: this seems like a manual implementation of the non-exhaustive pattern --> tests/ui/manual_non_exhaustive_enum.rs:29:1 | -LL | enum NoUnderscore { - | ^---------------- - | | - | _help: add the attribute: `#[non_exhaustive] enum NoUnderscore` - | | +LL | / pub enum NoUnderscore { LL | | A, LL | | B, LL | | #[doc(hidden)] @@ -42,6 +39,11 @@ help: remove this variant | LL | C, | ^ +help: use the `#[non_exhaustive]` attribute instead + | +LL + #[non_exhaustive] +LL | pub enum NoUnderscore { + | error: aborting due to 2 previous errors diff --git a/tests/ui/manual_non_exhaustive_struct.rs b/tests/ui/manual_non_exhaustive_struct.rs index 4b2803ccc4a79..31dd50281fa1d 100644 --- a/tests/ui/manual_non_exhaustive_struct.rs +++ b/tests/ui/manual_non_exhaustive_struct.rs @@ -1,9 +1,9 @@ #![warn(clippy::manual_non_exhaustive)] #![allow(unused)] //@no-rustfix -mod structs { - struct S { - //~^ ERROR: this seems like a manual implementation of the non-exhaustive pattern +pub mod structs { + pub struct S { + //~^ manual_non_exhaustive pub a: i32, pub b: i32, _c: (), @@ -11,68 +11,76 @@ mod structs { // user forgot to remove the private field #[non_exhaustive] - struct Sp { - //~^ ERROR: this seems like a manual implementation of the non-exhaustive pattern + pub struct Sp { + //~^ manual_non_exhaustive pub a: i32, pub b: i32, _c: (), } // some other fields are private, should be ignored - struct PrivateFields { + pub struct PrivateFields { a: i32, pub b: i32, _c: (), } - // private field name does not start with underscore, should be ignored - struct NoUnderscore { + pub struct NoUnderscore { + //~^ manual_non_exhaustive pub a: i32, pub b: i32, c: (), } // private field is not unit type, should be ignored - struct NotUnit { + pub struct NotUnit { pub a: i32, pub b: i32, _c: i32, } // private field is the only field, should be ignored - struct OnlyMarker { + pub struct OnlyMarker { _a: (), } // already non exhaustive and no private fields, should be ignored #[non_exhaustive] - struct NonExhaustive { + pub struct NonExhaustive { pub a: i32, pub b: i32, } } -mod tuple_structs { - struct T(pub i32, pub i32, ()); - //~^ ERROR: this seems like a manual implementation of the non-exhaustive pattern +pub mod tuple_structs { + pub struct T(pub i32, pub i32, ()); + //~^ manual_non_exhaustive // user forgot to remove the private field #[non_exhaustive] - struct Tp(pub i32, pub i32, ()); - //~^ ERROR: this seems like a manual implementation of the non-exhaustive pattern + pub struct Tp(pub i32, pub i32, ()); + //~^ manual_non_exhaustive // some other fields are private, should be ignored - struct PrivateFields(pub i32, i32, ()); + pub struct PrivateFields(pub i32, i32, ()); // private field is not unit type, should be ignored - struct NotUnit(pub i32, pub i32, i32); + pub struct NotUnit(pub i32, pub i32, i32); // private field is the only field, should be ignored - struct OnlyMarker(()); + pub struct OnlyMarker(()); // already non exhaustive and no private fields, should be ignored #[non_exhaustive] - struct NonExhaustive(pub i32, pub i32); + pub struct NonExhaustive(pub i32, pub i32); } -fn main() {} +mod private { + // Don't lint structs that are not actually public as `#[non_exhaustive]` only applies to + // external crates. The manual pattern can still be used to get module local non exhaustiveness + pub struct NotPublic { + pub a: i32, + pub b: i32, + _c: (), + } +} diff --git a/tests/ui/manual_non_exhaustive_struct.stderr b/tests/ui/manual_non_exhaustive_struct.stderr index 1cab812988a34..81de1e4f27190 100644 --- a/tests/ui/manual_non_exhaustive_struct.stderr +++ b/tests/ui/manual_non_exhaustive_struct.stderr @@ -1,11 +1,7 @@ error: this seems like a manual implementation of the non-exhaustive pattern --> tests/ui/manual_non_exhaustive_struct.rs:5:5 | -LL | struct S { - | ^------- - | | - | _____help: add the attribute: `#[non_exhaustive] struct S` - | | +LL | / pub struct S { LL | | LL | | pub a: i32, LL | | pub b: i32, @@ -20,11 +16,16 @@ LL | _c: (), | ^^^^^^ = note: `-D clippy::manual-non-exhaustive` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::manual_non_exhaustive)]` +help: use the `#[non_exhaustive]` attribute instead + | +LL ~ #[non_exhaustive] +LL ~ pub struct S { + | error: this seems like a manual implementation of the non-exhaustive pattern --> tests/ui/manual_non_exhaustive_struct.rs:14:5 | -LL | / struct Sp { +LL | / pub struct Sp { LL | | LL | | pub a: i32, LL | | pub b: i32, @@ -32,6 +33,11 @@ LL | | _c: (), LL | | } | |_____^ | +note: the struct is already non-exhaustive + --> tests/ui/manual_non_exhaustive_struct.rs:13:5 + | +LL | #[non_exhaustive] + | ^^^^^^^^^^^^^^^^^ help: remove this field --> tests/ui/manual_non_exhaustive_struct.rs:18:9 | @@ -39,13 +45,10 @@ LL | _c: (), | ^^^^^^ error: this seems like a manual implementation of the non-exhaustive pattern - --> tests/ui/manual_non_exhaustive_struct.rs:29:5 + --> tests/ui/manual_non_exhaustive_struct.rs:28:5 | -LL | struct NoUnderscore { - | ^------------------ - | | - | _____help: add the attribute: `#[non_exhaustive] struct NoUnderscore` - | | +LL | / pub struct NoUnderscore { +LL | | LL | | pub a: i32, LL | | pub b: i32, LL | | c: (), @@ -57,32 +60,45 @@ help: remove this field | LL | c: (), | ^^^^^ +help: use the `#[non_exhaustive]` attribute instead + | +LL ~ #[non_exhaustive] +LL ~ pub struct NoUnderscore { + | error: this seems like a manual implementation of the non-exhaustive pattern --> tests/ui/manual_non_exhaustive_struct.rs:56:5 | -LL | struct T(pub i32, pub i32, ()); - | --------^^^^^^^^^^^^^^^^^^^^^^^ - | | - | help: add the attribute: `#[non_exhaustive] struct T` +LL | pub struct T(pub i32, pub i32, ()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | help: remove this field - --> tests/ui/manual_non_exhaustive_struct.rs:56:32 + --> tests/ui/manual_non_exhaustive_struct.rs:56:36 + | +LL | pub struct T(pub i32, pub i32, ()); + | ^^ +help: use the `#[non_exhaustive]` attribute instead + | +LL ~ #[non_exhaustive] +LL ~ pub struct T(pub i32, pub i32, ()); | -LL | struct T(pub i32, pub i32, ()); - | ^^ error: this seems like a manual implementation of the non-exhaustive pattern --> tests/ui/manual_non_exhaustive_struct.rs:61:5 | -LL | struct Tp(pub i32, pub i32, ()); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | pub struct Tp(pub i32, pub i32, ()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: the struct is already non-exhaustive + --> tests/ui/manual_non_exhaustive_struct.rs:60:5 | +LL | #[non_exhaustive] + | ^^^^^^^^^^^^^^^^^ help: remove this field - --> tests/ui/manual_non_exhaustive_struct.rs:61:33 + --> tests/ui/manual_non_exhaustive_struct.rs:61:37 | -LL | struct Tp(pub i32, pub i32, ()); - | ^^ +LL | pub struct Tp(pub i32, pub i32, ()); + | ^^ error: aborting due to 5 previous errors From 960ec52bcfb697e8db2124c20e5477d3de13c165 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Tue, 20 Aug 2024 16:13:55 -0700 Subject: [PATCH 0503/2194] ci: add a runner for vanilla LLVM 19 --- .../host-x86_64/x86_64-gnu-llvm-19/Dockerfile | 62 +++++++++++++++++++ src/ci/github-actions/jobs.yml | 5 ++ 2 files changed, 67 insertions(+) create mode 100644 src/ci/docker/host-x86_64/x86_64-gnu-llvm-19/Dockerfile diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-llvm-19/Dockerfile b/src/ci/docker/host-x86_64/x86_64-gnu-llvm-19/Dockerfile new file mode 100644 index 0000000000000..44328b078ad41 --- /dev/null +++ b/src/ci/docker/host-x86_64/x86_64-gnu-llvm-19/Dockerfile @@ -0,0 +1,62 @@ +FROM ubuntu:24.10 + +ARG DEBIAN_FRONTEND=noninteractive + +RUN apt-get update && apt-get install -y --no-install-recommends \ + g++ \ + gcc-multilib \ + make \ + ninja-build \ + file \ + curl \ + ca-certificates \ + python3 \ + git \ + cmake \ + sudo \ + gdb \ + llvm-19-tools \ + llvm-19-dev \ + libedit-dev \ + libssl-dev \ + pkg-config \ + zlib1g-dev \ + xz-utils \ + nodejs \ + mingw-w64 \ + # libgccjit dependencies + flex \ + libmpfr-dev \ + libgmp-dev \ + libmpc3 \ + libmpc-dev \ + && rm -rf /var/lib/apt/lists/* + +# Install powershell (universal package) so we can test x.ps1 on Linux +# FIXME: need a "universal" version that supports libicu74, but for now it still works to ignore that dep. +RUN curl -sL "https://github.com/PowerShell/PowerShell/releases/download/v7.3.1/powershell_7.3.1-1.deb_amd64.deb" > powershell.deb && \ + dpkg --ignore-depends=libicu72 -i powershell.deb && \ + rm -f powershell.deb + +COPY scripts/sccache.sh /scripts/ +RUN sh /scripts/sccache.sh + +# We are disabling CI LLVM since this builder is intentionally using a host +# LLVM, rather than the typical src/llvm-project LLVM. +ENV NO_DOWNLOAD_CI_LLVM 1 +ENV EXTERNAL_LLVM 1 + +# Using llvm-link-shared due to libffi issues -- see #34486 +ENV RUST_CONFIGURE_ARGS \ + --build=x86_64-unknown-linux-gnu \ + --llvm-root=/usr/lib/llvm-19 \ + --enable-llvm-link-shared \ + --set rust.thin-lto-import-instr-limit=10 + +COPY host-x86_64/dist-x86_64-linux/shared.sh /scripts/ +COPY host-x86_64/dist-x86_64-linux/build-gccjit.sh /scripts/ + +RUN /scripts/build-gccjit.sh /scripts + +COPY scripts/x86_64-gnu-llvm.sh /tmp/script.sh +ENV SCRIPT /tmp/script.sh diff --git a/src/ci/github-actions/jobs.yml b/src/ci/github-actions/jobs.yml index 4de44c6dd39d7..c5fde010bc669 100644 --- a/src/ci/github-actions/jobs.yml +++ b/src/ci/github-actions/jobs.yml @@ -247,6 +247,11 @@ auto: - image: x86_64-gnu-distcheck <<: *job-linux-8c + - image: x86_64-gnu-llvm-19 + env: + RUST_BACKTRACE: 1 + <<: *job-linux-8c + - image: x86_64-gnu-llvm-18 env: RUST_BACKTRACE: 1 From d4b246bb117d451e34f1692fa34f9574b3d169e4 Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Wed, 4 Sep 2024 16:39:23 -0700 Subject: [PATCH 0504/2194] rustdoc: unify the short-circuit on all lints This is a bit of an experiment to see if it improves perf. --- src/librustdoc/passes/lint.rs | 33 ++- src/librustdoc/passes/lint/bare_urls.rs | 68 +++-- .../passes/lint/check_code_block_syntax.rs | 6 +- src/librustdoc/passes/lint/html_tags.rs | 248 +++++++++--------- .../passes/lint/redundant_explicit_links.rs | 7 +- .../passes/lint/unescaped_backticks.rs | 12 +- .../passes/lint/unportable_markdown.rs | 12 +- 7 files changed, 184 insertions(+), 202 deletions(-) diff --git a/src/librustdoc/passes/lint.rs b/src/librustdoc/passes/lint.rs index bc804a340bf2c..4da5d8f0e0663 100644 --- a/src/librustdoc/passes/lint.rs +++ b/src/librustdoc/passes/lint.rs @@ -27,12 +27,33 @@ pub(crate) fn run_lints(krate: Crate, cx: &mut DocContext<'_>) -> Crate { impl<'a, 'tcx> DocVisitor for Linter<'a, 'tcx> { fn visit_item(&mut self, item: &Item) { - bare_urls::visit_item(self.cx, item); - check_code_block_syntax::visit_item(self.cx, item); - html_tags::visit_item(self.cx, item); - unescaped_backticks::visit_item(self.cx, item); - redundant_explicit_links::visit_item(self.cx, item); - unportable_markdown::visit_item(self.cx, item); + let Some(hir_id) = DocContext::as_local_hir_id(self.cx.tcx, item.item_id) else { + // If non-local, no need to check anything. + return; + }; + let dox = item.doc_value(); + if !dox.is_empty() { + let may_have_link = dox.contains(&[':', '['][..]); + let may_have_block_comment_or_html = dox.contains(&['<', '>']); + // ~~~rust + // // This is a real, supported commonmark syntax for block code + // ~~~ + let may_have_code = dox.contains(&['~', '`', '\t'][..]) || dox.contains(" "); + if may_have_link { + bare_urls::visit_item(self.cx, item, hir_id, &dox); + redundant_explicit_links::visit_item(self.cx, item, hir_id); + } + if may_have_code { + check_code_block_syntax::visit_item(self.cx, item, &dox); + unescaped_backticks::visit_item(self.cx, item, hir_id, &dox); + } + if may_have_block_comment_or_html { + html_tags::visit_item(self.cx, item, hir_id, &dox); + unportable_markdown::visit_item(self.cx, item, hir_id, &dox); + } else if may_have_link { + unportable_markdown::visit_item(self.cx, item, hir_id, &dox); + } + } self.visit_item_recur(item) } diff --git a/src/librustdoc/passes/lint/bare_urls.rs b/src/librustdoc/passes/lint/bare_urls.rs index 22051dd954db3..bac0e07f1c108 100644 --- a/src/librustdoc/passes/lint/bare_urls.rs +++ b/src/librustdoc/passes/lint/bare_urls.rs @@ -8,6 +8,7 @@ use std::sync::LazyLock; use pulldown_cmark::{Event, Parser, Tag}; use regex::Regex; use rustc_errors::Applicability; +use rustc_hir::HirId; use rustc_resolve::rustdoc::source_span_for_markdown_range; use tracing::trace; @@ -15,50 +16,43 @@ use crate::clean::*; use crate::core::DocContext; use crate::html::markdown::main_body_opts; -pub(super) fn visit_item(cx: &DocContext<'_>, item: &Item) { - let Some(hir_id) = DocContext::as_local_hir_id(cx.tcx, item.item_id) else { - // If non-local, no need to check anything. - return; +pub(super) fn visit_item(cx: &DocContext<'_>, item: &Item, hir_id: HirId, dox: &str) { + let report_diag = |cx: &DocContext<'_>, msg: &'static str, range: Range| { + let sp = source_span_for_markdown_range(cx.tcx, &dox, &range, &item.attrs.doc_strings) + .unwrap_or_else(|| item.attr_span(cx.tcx)); + cx.tcx.node_span_lint(crate::lint::BARE_URLS, hir_id, sp, |lint| { + lint.primary_message(msg) + .note("bare URLs are not automatically turned into clickable links") + .multipart_suggestion( + "use an automatic link instead", + vec![ + (sp.shrink_to_lo(), "<".to_string()), + (sp.shrink_to_hi(), ">".to_string()), + ], + Applicability::MachineApplicable, + ); + }); }; - let dox = item.doc_value(); - if !dox.is_empty() { - let report_diag = |cx: &DocContext<'_>, msg: &'static str, range: Range| { - let sp = source_span_for_markdown_range(cx.tcx, &dox, &range, &item.attrs.doc_strings) - .unwrap_or_else(|| item.attr_span(cx.tcx)); - cx.tcx.node_span_lint(crate::lint::BARE_URLS, hir_id, sp, |lint| { - lint.primary_message(msg) - .note("bare URLs are not automatically turned into clickable links") - .multipart_suggestion( - "use an automatic link instead", - vec![ - (sp.shrink_to_lo(), "<".to_string()), - (sp.shrink_to_hi(), ">".to_string()), - ], - Applicability::MachineApplicable, - ); - }); - }; - let mut p = Parser::new_ext(&dox, main_body_opts()).into_offset_iter(); + let mut p = Parser::new_ext(&dox, main_body_opts()).into_offset_iter(); - while let Some((event, range)) = p.next() { - match event { - Event::Text(s) => find_raw_urls(cx, &s, range, &report_diag), - // We don't want to check the text inside code blocks or links. - Event::Start(tag @ (Tag::CodeBlock(_) | Tag::Link { .. })) => { - while let Some((event, _)) = p.next() { - match event { - Event::End(end) - if mem::discriminant(&end) == mem::discriminant(&tag.to_end()) => - { - break; - } - _ => {} + while let Some((event, range)) = p.next() { + match event { + Event::Text(s) => find_raw_urls(cx, &s, range, &report_diag), + // We don't want to check the text inside code blocks or links. + Event::Start(tag @ (Tag::CodeBlock(_) | Tag::Link { .. })) => { + while let Some((event, _)) = p.next() { + match event { + Event::End(end) + if mem::discriminant(&end) == mem::discriminant(&tag.to_end()) => + { + break; } + _ => {} } } - _ => {} } + _ => {} } } } diff --git a/src/librustdoc/passes/lint/check_code_block_syntax.rs b/src/librustdoc/passes/lint/check_code_block_syntax.rs index 977c095333641..1b2431a629b94 100644 --- a/src/librustdoc/passes/lint/check_code_block_syntax.rs +++ b/src/librustdoc/passes/lint/check_code_block_syntax.rs @@ -15,10 +15,8 @@ use crate::clean; use crate::core::DocContext; use crate::html::markdown::{self, RustCodeBlock}; -pub(crate) fn visit_item(cx: &DocContext<'_>, item: &clean::Item) { - if let Some(def_id) = item.item_id.as_local_def_id() - && let Some(dox) = &item.opt_doc_value() - { +pub(crate) fn visit_item(cx: &DocContext<'_>, item: &clean::Item, dox: &str) { + if let Some(def_id) = item.item_id.as_local_def_id() { let sp = item.attr_span(cx.tcx); let extra = crate::html::markdown::ExtraInfo::new(cx.tcx, def_id, sp); for code_block in markdown::rust_code_blocks(dox, &extra) { diff --git a/src/librustdoc/passes/lint/html_tags.rs b/src/librustdoc/passes/lint/html_tags.rs index 6f9e9d36a5c57..223174838ade0 100644 --- a/src/librustdoc/passes/lint/html_tags.rs +++ b/src/librustdoc/passes/lint/html_tags.rs @@ -5,159 +5,149 @@ use std::ops::Range; use std::str::CharIndices; use pulldown_cmark::{BrokenLink, Event, LinkType, Parser, Tag, TagEnd}; +use rustc_hir::HirId; use rustc_resolve::rustdoc::source_span_for_markdown_range; use crate::clean::*; use crate::core::DocContext; use crate::html::markdown::main_body_opts; -pub(crate) fn visit_item(cx: &DocContext<'_>, item: &Item) { +pub(crate) fn visit_item(cx: &DocContext<'_>, item: &Item, hir_id: HirId, dox: &str) { let tcx = cx.tcx; - let Some(hir_id) = DocContext::as_local_hir_id(tcx, item.item_id) - // If non-local, no need to check anything. - else { - return; - }; - let dox = item.doc_value(); - if !dox.is_empty() { - let report_diag = |msg: String, range: &Range, is_open_tag: bool| { - let sp = match source_span_for_markdown_range(tcx, &dox, range, &item.attrs.doc_strings) - { - Some(sp) => sp, - None => item.attr_span(tcx), - }; - tcx.node_span_lint(crate::lint::INVALID_HTML_TAGS, hir_id, sp, |lint| { - use rustc_lint_defs::Applicability; + let report_diag = |msg: String, range: &Range, is_open_tag: bool| { + let sp = match source_span_for_markdown_range(tcx, &dox, range, &item.attrs.doc_strings) { + Some(sp) => sp, + None => item.attr_span(tcx), + }; + tcx.node_span_lint(crate::lint::INVALID_HTML_TAGS, hir_id, sp, |lint| { + use rustc_lint_defs::Applicability; - lint.primary_message(msg); + lint.primary_message(msg); - // If a tag looks like ``, it might actually be a generic. - // We don't try to detect stuff `` because that's not valid HTML, - // and we don't try to detect stuff `` because that's not valid Rust. - let mut generics_end = range.end; - if let Some(Some(mut generics_start)) = (is_open_tag - && dox[..generics_end].ends_with('>')) - .then(|| extract_path_backwards(&dox, range.start)) + // If a tag looks like ``, it might actually be a generic. + // We don't try to detect stuff `` because that's not valid HTML, + // and we don't try to detect stuff `` because that's not valid Rust. + let mut generics_end = range.end; + if let Some(Some(mut generics_start)) = (is_open_tag + && dox[..generics_end].ends_with('>')) + .then(|| extract_path_backwards(&dox, range.start)) + { + while generics_start != 0 + && generics_end < dox.len() + && dox.as_bytes()[generics_start - 1] == b'<' + && dox.as_bytes()[generics_end] == b'>' { - while generics_start != 0 - && generics_end < dox.len() - && dox.as_bytes()[generics_start - 1] == b'<' - && dox.as_bytes()[generics_end] == b'>' - { - generics_end += 1; - generics_start -= 1; - if let Some(new_start) = extract_path_backwards(&dox, generics_start) { - generics_start = new_start; - } - if let Some(new_end) = extract_path_forward(&dox, generics_end) { - generics_end = new_end; - } + generics_end += 1; + generics_start -= 1; + if let Some(new_start) = extract_path_backwards(&dox, generics_start) { + generics_start = new_start; } if let Some(new_end) = extract_path_forward(&dox, generics_end) { generics_end = new_end; } - let generics_sp = match source_span_for_markdown_range( - tcx, - &dox, - &(generics_start..generics_end), - &item.attrs.doc_strings, - ) { - Some(sp) => sp, - None => item.attr_span(tcx), - }; - // Sometimes, we only extract part of a path. For example, consider this: - // - // <[u32] as IntoIter>::Item - // ^^^^^ unclosed HTML tag `u32` - // - // We don't have any code for parsing fully-qualified trait paths. - // In theory, we could add it, but doing it correctly would require - // parsing the entire path grammar, which is problematic because of - // overlap between the path grammar and Markdown. - // - // The example above shows that ambiguity. Is `[u32]` intended to be an - // intra-doc link to the u32 primitive, or is it intended to be a slice? - // - // If the below conditional were removed, we would suggest this, which is - // not what the user probably wants. - // - // <[u32] as `IntoIter`>::Item - // - // We know that the user actually wants to wrap the whole thing in a code - // block, but the only reason we know that is because `u32` does not, in - // fact, implement IntoIter. If the example looks like this: - // - // <[Vec] as IntoIter::Item - // - // The ideal fix would be significantly different. - if (generics_start > 0 && dox.as_bytes()[generics_start - 1] == b'<') - || (generics_end < dox.len() && dox.as_bytes()[generics_end] == b'>') - { - return; - } - // multipart form is chosen here because ``Vec`` would be confusing. - lint.multipart_suggestion( - "try marking as source code", - vec![ - (generics_sp.shrink_to_lo(), String::from("`")), - (generics_sp.shrink_to_hi(), String::from("`")), - ], - Applicability::MaybeIncorrect, - ); } - }); - }; + if let Some(new_end) = extract_path_forward(&dox, generics_end) { + generics_end = new_end; + } + let generics_sp = match source_span_for_markdown_range( + tcx, + &dox, + &(generics_start..generics_end), + &item.attrs.doc_strings, + ) { + Some(sp) => sp, + None => item.attr_span(tcx), + }; + // Sometimes, we only extract part of a path. For example, consider this: + // + // <[u32] as IntoIter>::Item + // ^^^^^ unclosed HTML tag `u32` + // + // We don't have any code for parsing fully-qualified trait paths. + // In theory, we could add it, but doing it correctly would require + // parsing the entire path grammar, which is problematic because of + // overlap between the path grammar and Markdown. + // + // The example above shows that ambiguity. Is `[u32]` intended to be an + // intra-doc link to the u32 primitive, or is it intended to be a slice? + // + // If the below conditional were removed, we would suggest this, which is + // not what the user probably wants. + // + // <[u32] as `IntoIter`>::Item + // + // We know that the user actually wants to wrap the whole thing in a code + // block, but the only reason we know that is because `u32` does not, in + // fact, implement IntoIter. If the example looks like this: + // + // <[Vec] as IntoIter::Item + // + // The ideal fix would be significantly different. + if (generics_start > 0 && dox.as_bytes()[generics_start - 1] == b'<') + || (generics_end < dox.len() && dox.as_bytes()[generics_end] == b'>') + { + return; + } + // multipart form is chosen here because ``Vec`` would be confusing. + lint.multipart_suggestion( + "try marking as source code", + vec![ + (generics_sp.shrink_to_lo(), String::from("`")), + (generics_sp.shrink_to_hi(), String::from("`")), + ], + Applicability::MaybeIncorrect, + ); + } + }); + }; - let mut tags = Vec::new(); - let mut is_in_comment = None; - let mut in_code_block = false; + let mut tags = Vec::new(); + let mut is_in_comment = None; + let mut in_code_block = false; - let link_names = item.link_names(&cx.cache); + let link_names = item.link_names(&cx.cache); - let mut replacer = |broken_link: BrokenLink<'_>| { - if let Some(link) = - link_names.iter().find(|link| *link.original_text == *broken_link.reference) - { - Some((link.href.as_str().into(), link.new_text.to_string().into())) - } else if matches!( - &broken_link.link_type, - LinkType::Reference | LinkType::ReferenceUnknown - ) { - // If the link is shaped [like][this], suppress any broken HTML in the [this] part. - // The `broken_intra_doc_links` will report typos in there anyway. - Some(( - broken_link.reference.to_string().into(), - broken_link.reference.to_string().into(), - )) - } else { - None - } - }; + let mut replacer = |broken_link: BrokenLink<'_>| { + if let Some(link) = + link_names.iter().find(|link| *link.original_text == *broken_link.reference) + { + Some((link.href.as_str().into(), link.new_text.to_string().into())) + } else if matches!(&broken_link.link_type, LinkType::Reference | LinkType::ReferenceUnknown) + { + // If the link is shaped [like][this], suppress any broken HTML in the [this] part. + // The `broken_intra_doc_links` will report typos in there anyway. + Some(( + broken_link.reference.to_string().into(), + broken_link.reference.to_string().into(), + )) + } else { + None + } + }; - let p = Parser::new_with_broken_link_callback(&dox, main_body_opts(), Some(&mut replacer)) - .into_offset_iter(); + let p = Parser::new_with_broken_link_callback(&dox, main_body_opts(), Some(&mut replacer)) + .into_offset_iter(); - for (event, range) in p { - match event { - Event::Start(Tag::CodeBlock(_)) => in_code_block = true, - Event::Html(text) | Event::InlineHtml(text) if !in_code_block => { - extract_tags(&mut tags, &text, range, &mut is_in_comment, &report_diag) - } - Event::End(TagEnd::CodeBlock) => in_code_block = false, - _ => {} + for (event, range) in p { + match event { + Event::Start(Tag::CodeBlock(_)) => in_code_block = true, + Event::Html(text) | Event::InlineHtml(text) if !in_code_block => { + extract_tags(&mut tags, &text, range, &mut is_in_comment, &report_diag) } + Event::End(TagEnd::CodeBlock) => in_code_block = false, + _ => {} } + } - for (tag, range) in tags.iter().filter(|(t, _)| { - let t = t.to_lowercase(); - !ALLOWED_UNCLOSED.contains(&t.as_str()) - }) { - report_diag(format!("unclosed HTML tag `{tag}`"), range, true); - } + for (tag, range) in tags.iter().filter(|(t, _)| { + let t = t.to_lowercase(); + !ALLOWED_UNCLOSED.contains(&t.as_str()) + }) { + report_diag(format!("unclosed HTML tag `{tag}`"), range, true); + } - if let Some(range) = is_in_comment { - report_diag("Unclosed HTML comment".to_string(), &range, false); - } + if let Some(range) = is_in_comment { + report_diag("Unclosed HTML comment".to_string(), &range, false); } } diff --git a/src/librustdoc/passes/lint/redundant_explicit_links.rs b/src/librustdoc/passes/lint/redundant_explicit_links.rs index 0a90c039dfbcb..9c37e11349a32 100644 --- a/src/librustdoc/passes/lint/redundant_explicit_links.rs +++ b/src/librustdoc/passes/lint/redundant_explicit_links.rs @@ -24,12 +24,7 @@ struct LinkData { display_link: String, } -pub(crate) fn visit_item(cx: &DocContext<'_>, item: &Item) { - let Some(hir_id) = DocContext::as_local_hir_id(cx.tcx, item.item_id) else { - // If non-local, no need to check anything. - return; - }; - +pub(crate) fn visit_item(cx: &DocContext<'_>, item: &Item, hir_id: HirId) { let hunks = prepare_to_doc_link_resolution(&item.attrs.doc_strings); for (item_id, doc) in hunks { if let Some(item_id) = item_id.or(item.def_id()) diff --git a/src/librustdoc/passes/lint/unescaped_backticks.rs b/src/librustdoc/passes/lint/unescaped_backticks.rs index a6c8db16f829b..d79f682a580f8 100644 --- a/src/librustdoc/passes/lint/unescaped_backticks.rs +++ b/src/librustdoc/passes/lint/unescaped_backticks.rs @@ -4,6 +4,7 @@ use std::ops::Range; use pulldown_cmark::{BrokenLink, Event, Parser}; use rustc_errors::Diag; +use rustc_hir::HirId; use rustc_lint_defs::Applicability; use rustc_resolve::rustdoc::source_span_for_markdown_range; @@ -11,17 +12,8 @@ use crate::clean::Item; use crate::core::DocContext; use crate::html::markdown::main_body_opts; -pub(crate) fn visit_item(cx: &DocContext<'_>, item: &Item) { +pub(crate) fn visit_item(cx: &DocContext<'_>, item: &Item, hir_id: HirId, dox: &str) { let tcx = cx.tcx; - let Some(hir_id) = DocContext::as_local_hir_id(tcx, item.item_id) else { - // If non-local, no need to check anything. - return; - }; - - let dox = item.doc_value(); - if dox.is_empty() { - return; - } let link_names = item.link_names(&cx.cache); let mut replacer = |broken_link: BrokenLink<'_>| { diff --git a/src/librustdoc/passes/lint/unportable_markdown.rs b/src/librustdoc/passes/lint/unportable_markdown.rs index 87fe0055883c2..f8368a866c882 100644 --- a/src/librustdoc/passes/lint/unportable_markdown.rs +++ b/src/librustdoc/passes/lint/unportable_markdown.rs @@ -12,6 +12,7 @@ use std::collections::{BTreeMap, BTreeSet}; +use rustc_hir::HirId; use rustc_lint_defs::Applicability; use rustc_resolve::rustdoc::source_span_for_markdown_range; use {pulldown_cmark as cmarkn, pulldown_cmark_old as cmarko}; @@ -19,17 +20,8 @@ use {pulldown_cmark as cmarkn, pulldown_cmark_old as cmarko}; use crate::clean::Item; use crate::core::DocContext; -pub(crate) fn visit_item(cx: &DocContext<'_>, item: &Item) { +pub(crate) fn visit_item(cx: &DocContext<'_>, item: &Item, hir_id: HirId, dox: &str) { let tcx = cx.tcx; - let Some(hir_id) = DocContext::as_local_hir_id(tcx, item.item_id) else { - // If non-local, no need to check anything. - return; - }; - - let dox = item.doc_value(); - if dox.is_empty() { - return; - } // P1: unintended strikethrough was fixed by requiring single-tildes to flank // the same way underscores do, so nothing is done here From 23cdb50e4f1c91ad76a3023e8a8c325e98c6348c Mon Sep 17 00:00:00 2001 From: Mads Marquart Date: Thu, 5 Sep 2024 06:47:11 +0200 Subject: [PATCH 0505/2194] Apple: Improve comments for `-arch` linker argument --- .../rustc_target/src/spec/base/apple/mod.rs | 40 ++++++++++++++++--- .../src/spec/targets/i686_apple_darwin.rs | 7 +--- 2 files changed, 36 insertions(+), 11 deletions(-) diff --git a/compiler/rustc_target/src/spec/base/apple/mod.rs b/compiler/rustc_target/src/spec/base/apple/mod.rs index b752a34439537..aef35ff616234 100644 --- a/compiler/rustc_target/src/spec/base/apple/mod.rs +++ b/compiler/rustc_target/src/spec/base/apple/mod.rs @@ -39,6 +39,25 @@ impl Arch { } } + /// The architecture name to forward to the linker. + fn ld_arch(self) -> &'static str { + // Supported architecture names can be found in the source: + // https://github.com/apple-oss-distributions/ld64/blob/ld64-951.9/src/abstraction/MachOFileAbstraction.hpp#L578-L648 + match self { + Armv7k => "armv7k", + Armv7s => "armv7s", + Arm64 => "arm64", + Arm64e => "arm64e", + Arm64_32 => "arm64_32", + // ld64 doesn't understand i686, so fall back to i386 instead + // + // Same story when linking with cc, since that ends up invoking ld64. + I386 | I686 => "i386", + X86_64 => "x86_64", + X86_64h => "x86_64h", + } + } + pub(crate) fn target_arch(self) -> Cow<'static, str> { Cow::Borrowed(match self { Armv7k | Armv7s => "arm", @@ -116,20 +135,29 @@ fn pre_link_args(os: &'static str, arch: Arch, abi: TargetAbi) -> LinkArgs { }; let sdk_version = min_version.clone(); - let mut args = TargetOptions::link_args( - LinkerFlavor::Darwin(Cc::No, Lld::No), - &["-arch", arch.target_name(), "-platform_version"], - ); + // From the man page for ld64 (`man ld`): + // > The linker accepts universal (multiple-architecture) input files, + // > but always creates a "thin" (single-architecture), standard Mach-O + // > output file. The architecture for the output file is specified using + // > the -arch option. + // + // The linker has heuristics to determine the desired architecture, but to + // be safe, and to avoid a warning, we set the architecture explicitly. + let mut args = + TargetOptions::link_args(LinkerFlavor::Darwin(Cc::No, Lld::No), &["-arch", arch.ld_arch()]); + add_link_args_iter( &mut args, LinkerFlavor::Darwin(Cc::No, Lld::No), - [platform_name, min_version, sdk_version].into_iter(), + ["-platform_version".into(), platform_name, min_version, sdk_version].into_iter(), ); if abi != TargetAbi::MacCatalyst { + // CC forwards the `-arch` to the linker, so we use the same value + // here intentionally. add_link_args( &mut args, LinkerFlavor::Darwin(Cc::Yes, Lld::No), - &["-arch", arch.target_name()], + &["-arch", arch.ld_arch()], ); } else { add_link_args_iter( diff --git a/compiler/rustc_target/src/spec/targets/i686_apple_darwin.rs b/compiler/rustc_target/src/spec/targets/i686_apple_darwin.rs index f173e8b7e4ae8..f7045a97bbbf0 100644 --- a/compiler/rustc_target/src/spec/targets/i686_apple_darwin.rs +++ b/compiler/rustc_target/src/spec/targets/i686_apple_darwin.rs @@ -2,8 +2,7 @@ use crate::spec::base::apple::{macos_llvm_target, opts, Arch, TargetAbi}; use crate::spec::{Cc, FramePointer, LinkerFlavor, Lld, Target, TargetOptions}; pub(crate) fn target() -> Target { - // ld64 only understands i386 and not i686 - let arch = Arch::I386; + let arch = Arch::I686; let mut base = opts("macos", arch, TargetAbi::Normal); base.max_atomic_width = Some(64); base.add_pre_link_args(LinkerFlavor::Darwin(Cc::Yes, Lld::No), &["-m32"]); @@ -13,9 +12,7 @@ pub(crate) fn target() -> Target { // Clang automatically chooses a more specific target based on // MACOSX_DEPLOYMENT_TARGET. To enable cross-language LTO to work // correctly, we do too. - // - // While ld64 doesn't understand i686, LLVM does. - llvm_target: macos_llvm_target(Arch::I686).into(), + llvm_target: macos_llvm_target(arch).into(), metadata: crate::spec::TargetMetadata { description: Some("32-bit macOS (10.12+, Sierra+)".into()), tier: Some(3), From 5b51331abe0263a87b5381461543749772071d61 Mon Sep 17 00:00:00 2001 From: Mads Marquart Date: Thu, 5 Sep 2024 06:45:02 +0200 Subject: [PATCH 0506/2194] Apple: Refactor deployment target version parsing - Merge minimum OS version list into one function (makes it easier to see the logic in it). - Parse patch deployment target versions. - Consistently specify deployment target in LLVM target (previously omitted on `aarch64-apple-watchos`). --- .../rustc_codegen_ssa/src/back/metadata.rs | 33 ++- compiler/rustc_driver_impl/src/lib.rs | 6 +- .../rustc_target/src/spec/base/apple/mod.rs | 262 +++++++++--------- .../rustc_target/src/spec/base/apple/tests.rs | 9 + compiler/rustc_target/src/spec/mod.rs | 4 +- .../src/spec/targets/aarch64_apple_darwin.rs | 24 +- .../src/spec/targets/aarch64_apple_ios.rs | 18 +- .../spec/targets/aarch64_apple_ios_macabi.rs | 14 +- .../src/spec/targets/aarch64_apple_ios_sim.rs | 18 +- .../src/spec/targets/aarch64_apple_tvos.rs | 10 +- .../spec/targets/aarch64_apple_tvos_sim.rs | 10 +- .../spec/targets/aarch64_apple_visionos.rs | 14 +- .../targets/aarch64_apple_visionos_sim.rs | 14 +- .../src/spec/targets/aarch64_apple_watchos.rs | 10 +- .../spec/targets/aarch64_apple_watchos_sim.rs | 14 +- .../spec/targets/arm64_32_apple_watchos.rs | 11 +- .../src/spec/targets/arm64e_apple_darwin.rs | 24 +- .../src/spec/targets/arm64e_apple_ios.rs | 18 +- .../src/spec/targets/armv7k_apple_watchos.rs | 10 +- .../src/spec/targets/armv7s_apple_ios.rs | 10 +- .../src/spec/targets/i386_apple_ios.rs | 15 +- .../src/spec/targets/i686_apple_darwin.rs | 23 +- .../src/spec/targets/x86_64_apple_darwin.rs | 30 +- .../src/spec/targets/x86_64_apple_ios.rs | 17 +- .../spec/targets/x86_64_apple_ios_macabi.rs | 17 +- .../src/spec/targets/x86_64_apple_tvos.rs | 11 +- .../spec/targets/x86_64_apple_watchos_sim.rs | 13 +- .../src/spec/targets/x86_64h_apple_darwin.rs | 26 +- 28 files changed, 322 insertions(+), 363 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/back/metadata.rs b/compiler/rustc_codegen_ssa/src/back/metadata.rs index 9b5a797ad5106..0fd9d7fffe8f9 100644 --- a/compiler/rustc_codegen_ssa/src/back/metadata.rs +++ b/compiler/rustc_codegen_ssa/src/back/metadata.rs @@ -372,27 +372,42 @@ pub(crate) fn create_object_file(sess: &Session) -> Option object::write::MachOBuildVersion { /// The `object` crate demands "X.Y.Z encoded in nibbles as xxxx.yy.zz" /// e.g. minOS 14.0 = 0x000E0000, or SDK 16.2 = 0x00100200 - fn pack_version((major, minor): (u32, u32)) -> u32 { - (major << 16) | (minor << 8) + fn pack_version((major, minor, patch): (u16, u8, u8)) -> u32 { + let (major, minor, patch) = (major as u32, minor as u32, patch as u32); + (major << 16) | (minor << 8) | patch } let platform = rustc_target::spec::current_apple_platform(target).expect("unknown Apple target OS"); - let min_os = rustc_target::spec::current_apple_deployment_target(target) - .expect("unknown Apple target OS"); - let sdk = + let min_os = rustc_target::spec::current_apple_deployment_target(target); + let (sdk_major, sdk_minor) = rustc_target::spec::current_apple_sdk_version(platform).expect("unknown Apple target OS"); let mut build_version = object::write::MachOBuildVersion::default(); build_version.platform = platform; build_version.minos = pack_version(min_os); - build_version.sdk = pack_version(sdk); + build_version.sdk = pack_version((sdk_major, sdk_minor, 0)); build_version } diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index e49ae60e890ba..d7d518700844f 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -871,9 +871,9 @@ fn print_crate_info( use rustc_target::spec::current_apple_deployment_target; if sess.target.is_like_osx { - let (major, minor) = current_apple_deployment_target(&sess.target) - .expect("unknown Apple target OS"); - println_info!("deployment_target={}", format!("{major}.{minor}")) + let (major, minor, patch) = current_apple_deployment_target(&sess.target); + let patch = if patch != 0 { format!(".{patch}") } else { String::new() }; + println_info!("deployment_target={major}.{minor}{patch}") } else { #[allow(rustc::diagnostic_outside_of_impl)] sess.dcx().fatal("only Apple targets currently support deployment version info") diff --git a/compiler/rustc_target/src/spec/base/apple/mod.rs b/compiler/rustc_target/src/spec/base/apple/mod.rs index aef35ff616234..2ca6b7d32ca45 100644 --- a/compiler/rustc_target/src/spec/base/apple/mod.rs +++ b/compiler/rustc_target/src/spec/base/apple/mod.rs @@ -1,5 +1,6 @@ use std::borrow::Cow; use std::env; +use std::num::ParseIntError; use crate::spec::{ add_link_args, add_link_args_iter, cvs, Cc, DebuginfoKind, FramePointer, LinkArgs, @@ -123,15 +124,8 @@ fn pre_link_args(os: &'static str, arch: Arch, abi: TargetAbi) -> LinkArgs { }; let min_version: StaticCow = { - let (major, minor) = match os { - "ios" => ios_deployment_target(arch, abi.target_abi()), - "tvos" => tvos_deployment_target(), - "watchos" => watchos_deployment_target(), - "visionos" => visionos_deployment_target(), - "macos" => macos_deployment_target(arch), - _ => unreachable!(), - }; - format!("{major}.{minor}").into() + let (major, minor, patch) = deployment_target(os, arch, abi); + format!("{major}.{minor}.{patch}").into() }; let sdk_version = min_version.clone(); @@ -163,15 +157,22 @@ fn pre_link_args(os: &'static str, arch: Arch, abi: TargetAbi) -> LinkArgs { add_link_args_iter( &mut args, LinkerFlavor::Darwin(Cc::Yes, Lld::No), - ["-target".into(), mac_catalyst_llvm_target(arch).into()].into_iter(), + ["-target".into(), llvm_target(os, arch, abi)].into_iter(), ); } args } -pub(crate) fn opts(os: &'static str, arch: Arch, abi: TargetAbi) -> TargetOptions { - TargetOptions { +/// Get the base target options, LLVM target and `target_arch` from the three +/// things that uniquely identify Rust's Apple targets: The OS, the +/// architecture, and the ABI. +pub(crate) fn base( + os: &'static str, + arch: Arch, + abi: TargetAbi, +) -> (TargetOptions, StaticCow, StaticCow) { + let opts = TargetOptions { abi: abi.target_abi().into(), os: os.into(), cpu: arch.target_cpu(abi).into(), @@ -221,10 +222,11 @@ pub(crate) fn opts(os: &'static str, arch: Arch, abi: TargetAbi) -> TargetOption link_env: Cow::Borrowed(&[(Cow::Borrowed("ZERO_AR_DATE"), Cow::Borrowed("1"))]), ..Default::default() - } + }; + (opts, llvm_target(os, arch, abi), arch.target_arch()) } -pub fn sdk_version(platform: u32) -> Option<(u32, u32)> { +pub fn sdk_version(platform: u32) -> Option<(u16, u8)> { // NOTE: These values are from an arbitrary point in time but shouldn't make it into the final // binary since the final link command will have the current SDK version passed to it. match platform { @@ -258,58 +260,108 @@ pub fn platform(target: &Target) -> Option { }) } -pub fn deployment_target(target: &Target) -> Option<(u32, u32)> { - let (major, minor) = match &*target.os { - "macos" => { - // This does not need to be specific. It just needs to handle x86 vs M1. - let arch = match target.arch.as_ref() { - "x86" | "x86_64" => X86_64, - "arm64e" => Arm64e, - _ => Arm64, - }; - macos_deployment_target(arch) - } - "ios" => { - let arch = match target.arch.as_ref() { - "arm64e" => Arm64e, - _ => Arm64, - }; - ios_deployment_target(arch, &target.abi) - } - "watchos" => watchos_deployment_target(), - "tvos" => tvos_deployment_target(), - "visionos" => visionos_deployment_target(), - _ => return None, +/// Hack for calling `deployment_target` outside of this module. +pub fn deployment_target_for_target(target: &Target) -> (u16, u8, u8) { + let arch = if target.llvm_target.starts_with("arm64e") { + Arch::Arm64e + } else if target.arch == "aarch64" { + Arch::Arm64 + } else { + // Dummy architecture, only used by `deployment_target` anyhow + Arch::X86_64 }; - - Some((major, minor)) + let abi = match &*target.abi { + "macabi" => TargetAbi::MacCatalyst, + "sim" => TargetAbi::Simulator, + "" => TargetAbi::Normal, + abi => unreachable!("invalid abi '{abi}' for Apple target"), + }; + deployment_target(&target.os, arch, abi) } -fn from_set_deployment_target(var_name: &str) -> Option<(u32, u32)> { - let deployment_target = env::var(var_name).ok()?; - let (unparsed_major, unparsed_minor) = deployment_target.split_once('.')?; - let (major, minor) = (unparsed_major.parse().ok()?, unparsed_minor.parse().ok()?); +/// Get the deployment target based on the standard environment variables, or +/// fall back to a sane default. +fn deployment_target(os: &str, arch: Arch, abi: TargetAbi) -> (u16, u8, u8) { + // When bumping a version in here, remember to update the platform-support + // docs too. + // + // NOTE: If you are looking for the default deployment target, prefer + // `rustc --print deployment-target`, as the default here may change in + // future `rustc` versions. + + // Minimum operating system versions currently supported by `rustc`. + let os_min = match os { + "macos" => (10, 12, 0), + "ios" => (10, 0, 0), + "tvos" => (10, 0, 0), + "watchos" => (5, 0, 0), + "visionos" => (1, 0, 0), + _ => unreachable!("tried to get deployment target for non-Apple platform"), + }; - Some((major, minor)) -} + // On certain targets it makes sense to raise the minimum OS version. + let min = match (os, arch, abi) { + // Use 11.0 on Aarch64 as that's the earliest version with M1 support. + ("macos", Arch::Arm64 | Arch::Arm64e, _) => (11, 0, 0), + ("ios", Arch::Arm64e, _) => (14, 0, 0), + // Mac Catalyst defaults to 13.1 in Clang. + ("ios", _, TargetAbi::MacCatalyst) => (13, 1, 0), + _ => os_min, + }; -fn macos_default_deployment_target(arch: Arch) -> (u32, u32) { - match arch { - Arm64 | Arm64e => (11, 0), - _ => (10, 12), - } -} + // The environment variable used to fetch the deployment target. + let env_var = match os { + "macos" => "MACOSX_DEPLOYMENT_TARGET", + "ios" => "IPHONEOS_DEPLOYMENT_TARGET", + "watchos" => "WATCHOS_DEPLOYMENT_TARGET", + "tvos" => "TVOS_DEPLOYMENT_TARGET", + "visionos" => "XROS_DEPLOYMENT_TARGET", + _ => unreachable!("tried to get deployment target env var for non-Apple platform"), + }; -fn macos_deployment_target(arch: Arch) -> (u32, u32) { - // If you are looking for the default deployment target, prefer `rustc --print deployment-target`. - // Note: If bumping this version, remember to update it in the rustc/platform-support docs. - from_set_deployment_target("MACOSX_DEPLOYMENT_TARGET") - .unwrap_or_else(|| macos_default_deployment_target(arch)) + if let Ok(deployment_target) = env::var(env_var) { + match parse_version(&deployment_target) { + // It is common that the deployment target is set too low, e.g. on + // macOS Aarch64 to also target older x86_64, the user may set a + // lower deployment target than supported. + // + // To avoid such issues, we silently raise the deployment target + // here. + // FIXME: We want to show a warning when `version < os_min`. + Ok(version) => version.max(min), + // FIXME: Report erroneous environment variable to user. + Err(_) => min, + } + } else { + min + } } -pub(crate) fn macos_llvm_target(arch: Arch) -> String { - let (major, minor) = macos_deployment_target(arch); - format!("{}-apple-macosx{}.{}.0", arch.target_name(), major, minor) +/// Generate the target triple that we need to pass to LLVM and/or Clang. +fn llvm_target(os: &str, arch: Arch, abi: TargetAbi) -> StaticCow { + // The target triple depends on the deployment target, and is required to + // enable features such as cross-language LTO, and for picking the right + // Mach-O commands. + // + // Certain optimizations also depend on the deployment target. + let (major, minor, patch) = deployment_target(os, arch, abi); + let arch = arch.target_name(); + // Convert to the "canonical" OS name used by LLVM: + // https://github.com/llvm/llvm-project/blob/llvmorg-18.1.8/llvm/lib/TargetParser/Triple.cpp#L236-L282 + let os = match os { + "macos" => "macosx", + "ios" => "ios", + "watchos" => "watchos", + "tvos" => "tvos", + "visionos" => "xros", + _ => unreachable!("tried to get LLVM target OS for non-Apple platform"), + }; + let environment = match abi { + TargetAbi::Normal => "", + TargetAbi::MacCatalyst => "-macabi", + TargetAbi::Simulator => "-simulator", + }; + format!("{arch}-apple-{os}{major}.{minor}.{patch}{environment}").into() } fn link_env_remove(os: &'static str) -> StaticCow<[StaticCow]> { @@ -349,83 +401,19 @@ fn link_env_remove(os: &'static str) -> StaticCow<[StaticCow]> { } } -fn ios_deployment_target(arch: Arch, abi: &str) -> (u32, u32) { - // If you are looking for the default deployment target, prefer `rustc --print deployment-target`. - // Note: If bumping this version, remember to update it in the rustc/platform-support docs. - let (major, minor) = match (arch, abi) { - (Arm64e, _) => (14, 0), - // Mac Catalyst defaults to 13.1 in Clang. - (_, "macabi") => (13, 1), - _ => (10, 0), - }; - from_set_deployment_target("IPHONEOS_DEPLOYMENT_TARGET").unwrap_or((major, minor)) -} - -pub(crate) fn ios_llvm_target(arch: Arch) -> String { - // Modern iOS tooling extracts information about deployment target - // from LC_BUILD_VERSION. This load command will only be emitted when - // we build with a version specific `llvm_target`, with the version - // set high enough. Luckily one LC_BUILD_VERSION is enough, for Xcode - // to pick it up (since std and core are still built with the fallback - // of version 7.0 and hence emit the old LC_IPHONE_MIN_VERSION). - let (major, minor) = ios_deployment_target(arch, ""); - format!("{}-apple-ios{}.{}.0", arch.target_name(), major, minor) -} - -pub(crate) fn mac_catalyst_llvm_target(arch: Arch) -> String { - let (major, minor) = ios_deployment_target(arch, "macabi"); - format!("{}-apple-ios{}.{}.0-macabi", arch.target_name(), major, minor) -} - -pub(crate) fn ios_sim_llvm_target(arch: Arch) -> String { - let (major, minor) = ios_deployment_target(arch, "sim"); - format!("{}-apple-ios{}.{}.0-simulator", arch.target_name(), major, minor) -} - -fn tvos_deployment_target() -> (u32, u32) { - // If you are looking for the default deployment target, prefer `rustc --print deployment-target`. - // Note: If bumping this version, remember to update it in the rustc platform-support docs. - from_set_deployment_target("TVOS_DEPLOYMENT_TARGET").unwrap_or((10, 0)) -} - -pub(crate) fn tvos_llvm_target(arch: Arch) -> String { - let (major, minor) = tvos_deployment_target(); - format!("{}-apple-tvos{}.{}.0", arch.target_name(), major, minor) -} - -pub(crate) fn tvos_sim_llvm_target(arch: Arch) -> String { - let (major, minor) = tvos_deployment_target(); - format!("{}-apple-tvos{}.{}.0-simulator", arch.target_name(), major, minor) -} - -fn watchos_deployment_target() -> (u32, u32) { - // If you are looking for the default deployment target, prefer `rustc --print deployment-target`. - // Note: If bumping this version, remember to update it in the rustc platform-support docs. - from_set_deployment_target("WATCHOS_DEPLOYMENT_TARGET").unwrap_or((5, 0)) -} - -pub(crate) fn watchos_llvm_target(arch: Arch) -> String { - let (major, minor) = watchos_deployment_target(); - format!("{}-apple-watchos{}.{}.0", arch.target_name(), major, minor) -} - -pub(crate) fn watchos_sim_llvm_target(arch: Arch) -> String { - let (major, minor) = watchos_deployment_target(); - format!("{}-apple-watchos{}.{}.0-simulator", arch.target_name(), major, minor) -} - -fn visionos_deployment_target() -> (u32, u32) { - // If you are looking for the default deployment target, prefer `rustc --print deployment-target`. - // Note: If bumping this version, remember to update it in the rustc platform-support docs. - from_set_deployment_target("XROS_DEPLOYMENT_TARGET").unwrap_or((1, 0)) -} - -pub(crate) fn visionos_llvm_target(arch: Arch) -> String { - let (major, minor) = visionos_deployment_target(); - format!("{}-apple-visionos{}.{}.0", arch.target_name(), major, minor) -} - -pub(crate) fn visionos_sim_llvm_target(arch: Arch) -> String { - let (major, minor) = visionos_deployment_target(); - format!("{}-apple-visionos{}.{}.0-simulator", arch.target_name(), major, minor) +/// Parse an OS version triple (SDK version or deployment target). +/// +/// The size of the returned numbers here are limited by Mach-O's +/// `LC_BUILD_VERSION`. +fn parse_version(version: &str) -> Result<(u16, u8, u8), ParseIntError> { + if let Some((major, minor)) = version.split_once('.') { + let major = major.parse()?; + if let Some((minor, patch)) = minor.split_once('.') { + Ok((major, minor.parse()?, patch.parse()?)) + } else { + Ok((major, minor.parse()?, 0)) + } + } else { + Ok((version.parse()?, 0, 0)) + } } diff --git a/compiler/rustc_target/src/spec/base/apple/tests.rs b/compiler/rustc_target/src/spec/base/apple/tests.rs index 7a985ad4dc056..d55b44e3c9e0e 100644 --- a/compiler/rustc_target/src/spec/base/apple/tests.rs +++ b/compiler/rustc_target/src/spec/base/apple/tests.rs @@ -1,3 +1,4 @@ +use super::parse_version; use crate::spec::targets::{ aarch64_apple_darwin, aarch64_apple_ios_sim, aarch64_apple_visionos_sim, aarch64_apple_watchos_sim, i686_apple_darwin, x86_64_apple_darwin, x86_64_apple_ios, @@ -42,3 +43,11 @@ fn macos_link_environment_unmodified() { ); } } + +#[test] +fn test_parse_version() { + assert_eq!(parse_version("10"), Ok((10, 0, 0))); + assert_eq!(parse_version("10.12"), Ok((10, 12, 0))); + assert_eq!(parse_version("10.12.6"), Ok((10, 12, 6))); + assert_eq!(parse_version("9999.99.99"), Ok((9999, 99, 99))); +} diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index f992ddf841704..7ecf1390f8644 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -60,8 +60,8 @@ pub mod crt_objects; mod base; pub use base::apple::{ - deployment_target as current_apple_deployment_target, platform as current_apple_platform, - sdk_version as current_apple_sdk_version, + deployment_target_for_target as current_apple_deployment_target, + platform as current_apple_platform, sdk_version as current_apple_sdk_version, }; pub use base::avr_gnu::ef_avr_arch; diff --git a/compiler/rustc_target/src/spec/targets/aarch64_apple_darwin.rs b/compiler/rustc_target/src/spec/targets/aarch64_apple_darwin.rs index 912392c9fef08..1061633be175f 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_apple_darwin.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_apple_darwin.rs @@ -1,20 +1,10 @@ -use crate::spec::base::apple::{macos_llvm_target, opts, Arch, TargetAbi}; +use crate::spec::base::apple::{base, Arch, TargetAbi}; use crate::spec::{FramePointer, SanitizerSet, Target, TargetOptions}; pub(crate) fn target() -> Target { - let arch = Arch::Arm64; - let mut base = opts("macos", arch, TargetAbi::Normal); - base.cpu = "apple-m1".into(); - base.max_atomic_width = Some(128); - - // FIXME: The leak sanitizer currently fails the tests, see #88132. - base.supported_sanitizers = SanitizerSet::ADDRESS | SanitizerSet::CFI | SanitizerSet::THREAD; - + let (opts, llvm_target, arch) = base("macos", Arch::Arm64, TargetAbi::Normal); Target { - // Clang automatically chooses a more specific target based on - // MACOSX_DEPLOYMENT_TARGET. To enable cross-language LTO to work - // correctly, we do too. - llvm_target: macos_llvm_target(arch).into(), + llvm_target, metadata: crate::spec::TargetMetadata { description: Some("ARM64 macOS (11.0+, Big Sur+)".into()), tier: Some(1), @@ -23,11 +13,15 @@ pub(crate) fn target() -> Target { }, pointer_width: 64, data_layout: "e-m:o-i64:64-i128:128-n32:64-S128-Fn32".into(), - arch: arch.target_arch(), + arch, options: TargetOptions { mcount: "\u{1}mcount".into(), frame_pointer: FramePointer::NonLeaf, - ..base + cpu: "apple-m1".into(), + max_atomic_width: Some(128), + // FIXME: The leak sanitizer currently fails the tests, see #88132. + supported_sanitizers: SanitizerSet::ADDRESS | SanitizerSet::CFI | SanitizerSet::THREAD, + ..opts }, } } diff --git a/compiler/rustc_target/src/spec/targets/aarch64_apple_ios.rs b/compiler/rustc_target/src/spec/targets/aarch64_apple_ios.rs index 7f3a86f3256ff..caeb9a121e48b 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_apple_ios.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_apple_ios.rs @@ -1,17 +1,10 @@ -use crate::spec::base::apple::{ios_llvm_target, opts, Arch, TargetAbi}; +use crate::spec::base::apple::{base, Arch, TargetAbi}; use crate::spec::{FramePointer, SanitizerSet, Target, TargetOptions}; pub(crate) fn target() -> Target { - let arch = Arch::Arm64; - let mut base = opts("ios", arch, TargetAbi::Normal); - base.supported_sanitizers = SanitizerSet::ADDRESS | SanitizerSet::THREAD; - + let (opts, llvm_target, arch) = base("ios", Arch::Arm64, TargetAbi::Normal); Target { - // Clang automatically chooses a more specific target based on - // IPHONEOS_DEPLOYMENT_TARGET. - // This is required for the target to pick the right - // MACH-O commands, so we do too. - llvm_target: ios_llvm_target(arch).into(), + llvm_target, metadata: crate::spec::TargetMetadata { description: Some("ARM64 iOS".into()), tier: Some(2), @@ -20,12 +13,13 @@ pub(crate) fn target() -> Target { }, pointer_width: 64, data_layout: "e-m:o-i64:64-i128:128-n32:64-S128-Fn32".into(), - arch: arch.target_arch(), + arch, options: TargetOptions { features: "+neon,+fp-armv8,+apple-a7".into(), max_atomic_width: Some(128), frame_pointer: FramePointer::NonLeaf, - ..base + supported_sanitizers: SanitizerSet::ADDRESS | SanitizerSet::THREAD, + ..opts }, } } diff --git a/compiler/rustc_target/src/spec/targets/aarch64_apple_ios_macabi.rs b/compiler/rustc_target/src/spec/targets/aarch64_apple_ios_macabi.rs index e60eeda429565..eee9eca3bcbeb 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_apple_ios_macabi.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_apple_ios_macabi.rs @@ -1,13 +1,10 @@ -use crate::spec::base::apple::{mac_catalyst_llvm_target, opts, Arch, TargetAbi}; +use crate::spec::base::apple::{base, Arch, TargetAbi}; use crate::spec::{FramePointer, SanitizerSet, Target, TargetOptions}; pub(crate) fn target() -> Target { - let arch = Arch::Arm64; - let mut base = opts("ios", arch, TargetAbi::MacCatalyst); - base.supported_sanitizers = SanitizerSet::ADDRESS | SanitizerSet::LEAK | SanitizerSet::THREAD; - + let (opts, llvm_target, arch) = base("ios", Arch::Arm64, TargetAbi::MacCatalyst); Target { - llvm_target: mac_catalyst_llvm_target(arch).into(), + llvm_target, metadata: crate::spec::TargetMetadata { description: Some("Apple Catalyst on ARM64".into()), tier: Some(2), @@ -16,12 +13,13 @@ pub(crate) fn target() -> Target { }, pointer_width: 64, data_layout: "e-m:o-i64:64-i128:128-n32:64-S128-Fn32".into(), - arch: arch.target_arch(), + arch, options: TargetOptions { features: "+neon,+fp-armv8,+apple-a12".into(), max_atomic_width: Some(128), frame_pointer: FramePointer::NonLeaf, - ..base + supported_sanitizers: SanitizerSet::ADDRESS | SanitizerSet::LEAK | SanitizerSet::THREAD, + ..opts }, } } diff --git a/compiler/rustc_target/src/spec/targets/aarch64_apple_ios_sim.rs b/compiler/rustc_target/src/spec/targets/aarch64_apple_ios_sim.rs index d605e22701af0..ee58038301d4a 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_apple_ios_sim.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_apple_ios_sim.rs @@ -1,17 +1,10 @@ -use crate::spec::base::apple::{ios_sim_llvm_target, opts, Arch, TargetAbi}; +use crate::spec::base::apple::{base, Arch, TargetAbi}; use crate::spec::{FramePointer, SanitizerSet, Target, TargetOptions}; pub(crate) fn target() -> Target { - let arch = Arch::Arm64; - let mut base = opts("ios", arch, TargetAbi::Simulator); - base.supported_sanitizers = SanitizerSet::ADDRESS | SanitizerSet::THREAD; - + let (opts, llvm_target, arch) = base("ios", Arch::Arm64, TargetAbi::Simulator); Target { - // Clang automatically chooses a more specific target based on - // IPHONEOS_DEPLOYMENT_TARGET. - // This is required for the simulator target to pick the right - // MACH-O commands, so we do too. - llvm_target: ios_sim_llvm_target(arch).into(), + llvm_target, metadata: crate::spec::TargetMetadata { description: Some("Apple iOS Simulator on ARM64".into()), tier: Some(2), @@ -20,12 +13,13 @@ pub(crate) fn target() -> Target { }, pointer_width: 64, data_layout: "e-m:o-i64:64-i128:128-n32:64-S128-Fn32".into(), - arch: arch.target_arch(), + arch, options: TargetOptions { features: "+neon,+fp-armv8,+apple-a7".into(), max_atomic_width: Some(128), frame_pointer: FramePointer::NonLeaf, - ..base + supported_sanitizers: SanitizerSet::ADDRESS | SanitizerSet::THREAD, + ..opts }, } } diff --git a/compiler/rustc_target/src/spec/targets/aarch64_apple_tvos.rs b/compiler/rustc_target/src/spec/targets/aarch64_apple_tvos.rs index fc774ab94c880..baca863d442ba 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_apple_tvos.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_apple_tvos.rs @@ -1,10 +1,10 @@ -use crate::spec::base::apple::{opts, tvos_llvm_target, Arch, TargetAbi}; +use crate::spec::base::apple::{base, Arch, TargetAbi}; use crate::spec::{FramePointer, Target, TargetOptions}; pub(crate) fn target() -> Target { - let arch = Arch::Arm64; + let (opts, llvm_target, arch) = base("tvos", Arch::Arm64, TargetAbi::Normal); Target { - llvm_target: tvos_llvm_target(arch).into(), + llvm_target, metadata: crate::spec::TargetMetadata { description: Some("ARM64 tvOS".into()), tier: Some(3), @@ -13,12 +13,12 @@ pub(crate) fn target() -> Target { }, pointer_width: 64, data_layout: "e-m:o-i64:64-i128:128-n32:64-S128-Fn32".into(), - arch: arch.target_arch(), + arch, options: TargetOptions { features: "+neon,+fp-armv8,+apple-a7".into(), max_atomic_width: Some(128), frame_pointer: FramePointer::NonLeaf, - ..opts("tvos", arch, TargetAbi::Normal) + ..opts }, } } diff --git a/compiler/rustc_target/src/spec/targets/aarch64_apple_tvos_sim.rs b/compiler/rustc_target/src/spec/targets/aarch64_apple_tvos_sim.rs index 8e8bb1efc9dfe..1a48f8c5acffb 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_apple_tvos_sim.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_apple_tvos_sim.rs @@ -1,10 +1,10 @@ -use crate::spec::base::apple::{opts, tvos_sim_llvm_target, Arch, TargetAbi}; +use crate::spec::base::apple::{base, Arch, TargetAbi}; use crate::spec::{FramePointer, Target, TargetOptions}; pub(crate) fn target() -> Target { - let arch = Arch::Arm64; + let (opts, llvm_target, arch) = base("tvos", Arch::Arm64, TargetAbi::Simulator); Target { - llvm_target: tvos_sim_llvm_target(arch).into(), + llvm_target, metadata: crate::spec::TargetMetadata { description: Some("ARM64 tvOS Simulator".into()), tier: Some(3), @@ -13,12 +13,12 @@ pub(crate) fn target() -> Target { }, pointer_width: 64, data_layout: "e-m:o-i64:64-i128:128-n32:64-S128-Fn32".into(), - arch: arch.target_arch(), + arch, options: TargetOptions { features: "+neon,+fp-armv8,+apple-a7".into(), max_atomic_width: Some(128), frame_pointer: FramePointer::NonLeaf, - ..opts("tvos", arch, TargetAbi::Simulator) + ..opts }, } } diff --git a/compiler/rustc_target/src/spec/targets/aarch64_apple_visionos.rs b/compiler/rustc_target/src/spec/targets/aarch64_apple_visionos.rs index 16c7d72daed85..1424126134d64 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_apple_visionos.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_apple_visionos.rs @@ -1,13 +1,10 @@ -use crate::spec::base::apple::{opts, visionos_llvm_target, Arch, TargetAbi}; +use crate::spec::base::apple::{base, Arch, TargetAbi}; use crate::spec::{FramePointer, SanitizerSet, Target, TargetOptions}; pub(crate) fn target() -> Target { - let arch = Arch::Arm64; - let mut base = opts("visionos", arch, TargetAbi::Normal); - base.supported_sanitizers = SanitizerSet::ADDRESS | SanitizerSet::THREAD; - + let (opts, llvm_target, arch) = base("visionos", Arch::Arm64, TargetAbi::Normal); Target { - llvm_target: visionos_llvm_target(arch).into(), + llvm_target, metadata: crate::spec::TargetMetadata { description: Some("ARM64 Apple visionOS".into()), tier: Some(3), @@ -16,12 +13,13 @@ pub(crate) fn target() -> Target { }, pointer_width: 64, data_layout: "e-m:o-i64:64-i128:128-n32:64-S128-Fn32".into(), - arch: arch.target_arch(), + arch, options: TargetOptions { features: "+neon,+fp-armv8,+apple-a16".into(), max_atomic_width: Some(128), frame_pointer: FramePointer::NonLeaf, - ..base + supported_sanitizers: SanitizerSet::ADDRESS | SanitizerSet::THREAD, + ..opts }, } } diff --git a/compiler/rustc_target/src/spec/targets/aarch64_apple_visionos_sim.rs b/compiler/rustc_target/src/spec/targets/aarch64_apple_visionos_sim.rs index 42973e0268e12..d7226e02ecb56 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_apple_visionos_sim.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_apple_visionos_sim.rs @@ -1,13 +1,10 @@ -use crate::spec::base::apple::{opts, visionos_sim_llvm_target, Arch, TargetAbi}; +use crate::spec::base::apple::{base, Arch, TargetAbi}; use crate::spec::{FramePointer, SanitizerSet, Target, TargetOptions}; pub(crate) fn target() -> Target { - let arch = Arch::Arm64; - let mut base = opts("visionos", arch, TargetAbi::Simulator); - base.supported_sanitizers = SanitizerSet::ADDRESS | SanitizerSet::THREAD; - + let (opts, llvm_target, arch) = base("visionos", Arch::Arm64, TargetAbi::Simulator); Target { - llvm_target: visionos_sim_llvm_target(arch).into(), + llvm_target, metadata: crate::spec::TargetMetadata { description: Some("ARM64 Apple visionOS simulator".into()), tier: Some(3), @@ -16,12 +13,13 @@ pub(crate) fn target() -> Target { }, pointer_width: 64, data_layout: "e-m:o-i64:64-i128:128-n32:64-S128-Fn32".into(), - arch: arch.target_arch(), + arch, options: TargetOptions { features: "+neon,+fp-armv8,+apple-a16".into(), max_atomic_width: Some(128), frame_pointer: FramePointer::NonLeaf, - ..base + supported_sanitizers: SanitizerSet::ADDRESS | SanitizerSet::THREAD, + ..opts }, } } diff --git a/compiler/rustc_target/src/spec/targets/aarch64_apple_watchos.rs b/compiler/rustc_target/src/spec/targets/aarch64_apple_watchos.rs index 03fc2518d1d6b..1940a568b3960 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_apple_watchos.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_apple_watchos.rs @@ -1,10 +1,10 @@ -use crate::spec::base::apple::{opts, Arch, TargetAbi}; +use crate::spec::base::apple::{base, Arch, TargetAbi}; use crate::spec::{Target, TargetOptions}; pub(crate) fn target() -> Target { - let base = opts("watchos", Arch::Arm64, TargetAbi::Normal); + let (opts, llvm_target, arch) = base("watchos", Arch::Arm64, TargetAbi::Normal); Target { - llvm_target: "aarch64-apple-watchos".into(), + llvm_target, metadata: crate::spec::TargetMetadata { description: Some("ARM64 Apple WatchOS".into()), tier: Some(3), @@ -13,13 +13,13 @@ pub(crate) fn target() -> Target { }, pointer_width: 64, data_layout: "e-m:o-i64:64-i128:128-n32:64-S128-Fn32".into(), - arch: "aarch64".into(), + arch, options: TargetOptions { features: "+v8a,+neon,+fp-armv8,+apple-a7".into(), max_atomic_width: Some(128), dynamic_linking: false, position_independent_executables: true, - ..base + ..opts }, } } diff --git a/compiler/rustc_target/src/spec/targets/aarch64_apple_watchos_sim.rs b/compiler/rustc_target/src/spec/targets/aarch64_apple_watchos_sim.rs index 13e2b96179481..6beef11c5041f 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_apple_watchos_sim.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_apple_watchos_sim.rs @@ -1,14 +1,10 @@ -use crate::spec::base::apple::{opts, watchos_sim_llvm_target, Arch, TargetAbi}; +use crate::spec::base::apple::{base, Arch, TargetAbi}; use crate::spec::{FramePointer, Target, TargetOptions}; pub(crate) fn target() -> Target { - let arch = Arch::Arm64; + let (opts, llvm_target, arch) = base("watchos", Arch::Arm64, TargetAbi::Simulator); Target { - // Clang automatically chooses a more specific target based on - // WATCHOS_DEPLOYMENT_TARGET. - // This is required for the simulator target to pick the right - // MACH-O commands, so we do too. - llvm_target: watchos_sim_llvm_target(arch).into(), + llvm_target, metadata: crate::spec::TargetMetadata { description: Some("ARM64 Apple WatchOS Simulator".into()), tier: Some(3), @@ -17,12 +13,12 @@ pub(crate) fn target() -> Target { }, pointer_width: 64, data_layout: "e-m:o-i64:64-i128:128-n32:64-S128-Fn32".into(), - arch: arch.target_arch(), + arch, options: TargetOptions { features: "+neon,+fp-armv8,+apple-a7".into(), max_atomic_width: Some(128), frame_pointer: FramePointer::NonLeaf, - ..opts("watchos", arch, TargetAbi::Simulator) + ..opts }, } } diff --git a/compiler/rustc_target/src/spec/targets/arm64_32_apple_watchos.rs b/compiler/rustc_target/src/spec/targets/arm64_32_apple_watchos.rs index f292ee7f56312..e9f4d9330d5f2 100644 --- a/compiler/rustc_target/src/spec/targets/arm64_32_apple_watchos.rs +++ b/compiler/rustc_target/src/spec/targets/arm64_32_apple_watchos.rs @@ -1,11 +1,10 @@ -use crate::spec::base::apple::{opts, watchos_llvm_target, Arch, TargetAbi}; +use crate::spec::base::apple::{base, Arch, TargetAbi}; use crate::spec::{Target, TargetOptions}; pub(crate) fn target() -> Target { - let arch = Arch::Arm64_32; - let base = opts("watchos", arch, TargetAbi::Normal); + let (opts, llvm_target, arch) = base("watchos", Arch::Arm64_32, TargetAbi::Normal); Target { - llvm_target: watchos_llvm_target(arch).into(), + llvm_target, metadata: crate::spec::TargetMetadata { description: Some("Arm Apple WatchOS 64-bit with 32-bit pointers".into()), tier: Some(3), @@ -14,13 +13,13 @@ pub(crate) fn target() -> Target { }, pointer_width: 32, data_layout: "e-m:o-p:32:32-i64:64-i128:128-n32:64-S128-Fn32".into(), - arch: "aarch64".into(), + arch, options: TargetOptions { features: "+v8a,+neon,+fp-armv8,+apple-a7".into(), max_atomic_width: Some(128), dynamic_linking: false, position_independent_executables: true, - ..base + ..opts }, } } diff --git a/compiler/rustc_target/src/spec/targets/arm64e_apple_darwin.rs b/compiler/rustc_target/src/spec/targets/arm64e_apple_darwin.rs index e86b8358a9c98..4f7c945b9fe47 100644 --- a/compiler/rustc_target/src/spec/targets/arm64e_apple_darwin.rs +++ b/compiler/rustc_target/src/spec/targets/arm64e_apple_darwin.rs @@ -1,20 +1,10 @@ -use crate::spec::base::apple::{macos_llvm_target, opts, Arch, TargetAbi}; +use crate::spec::base::apple::{base, Arch, TargetAbi}; use crate::spec::{FramePointer, SanitizerSet, Target, TargetOptions}; pub(crate) fn target() -> Target { - let arch = Arch::Arm64e; - let mut base = opts("macos", arch, TargetAbi::Normal); - base.cpu = "apple-m1".into(); - base.max_atomic_width = Some(128); - - // FIXME: The leak sanitizer currently fails the tests, see #88132. - base.supported_sanitizers = SanitizerSet::ADDRESS | SanitizerSet::CFI | SanitizerSet::THREAD; - + let (opts, llvm_target, arch) = base("macos", Arch::Arm64e, TargetAbi::Normal); Target { - // Clang automatically chooses a more specific target based on - // MACOSX_DEPLOYMENT_TARGET. To enable cross-language LTO to work - // correctly, we do too. - llvm_target: macos_llvm_target(arch).into(), + llvm_target, metadata: crate::spec::TargetMetadata { description: Some("ARM64e Apple Darwin".into()), tier: Some(3), @@ -23,11 +13,15 @@ pub(crate) fn target() -> Target { }, pointer_width: 64, data_layout: "e-m:o-i64:64-i128:128-n32:64-S128-Fn32".into(), - arch: arch.target_arch(), + arch, options: TargetOptions { mcount: "\u{1}mcount".into(), frame_pointer: FramePointer::NonLeaf, - ..base + cpu: "apple-m1".into(), + max_atomic_width: Some(128), + // FIXME: The leak sanitizer currently fails the tests, see #88132. + supported_sanitizers: SanitizerSet::ADDRESS | SanitizerSet::CFI | SanitizerSet::THREAD, + ..opts }, } } diff --git a/compiler/rustc_target/src/spec/targets/arm64e_apple_ios.rs b/compiler/rustc_target/src/spec/targets/arm64e_apple_ios.rs index fcb850f44bc85..8f192fe288603 100644 --- a/compiler/rustc_target/src/spec/targets/arm64e_apple_ios.rs +++ b/compiler/rustc_target/src/spec/targets/arm64e_apple_ios.rs @@ -1,17 +1,10 @@ -use crate::spec::base::apple::{ios_llvm_target, opts, Arch, TargetAbi}; +use crate::spec::base::apple::{base, Arch, TargetAbi}; use crate::spec::{FramePointer, SanitizerSet, Target, TargetOptions}; pub(crate) fn target() -> Target { - let arch = Arch::Arm64e; - let mut base = opts("ios", arch, TargetAbi::Normal); - base.supported_sanitizers = SanitizerSet::ADDRESS | SanitizerSet::THREAD; - + let (opts, llvm_target, arch) = base("ios", Arch::Arm64e, TargetAbi::Normal); Target { - // Clang automatically chooses a more specific target based on - // IPHONEOS_DEPLOYMENT_TARGET. - // This is required for the target to pick the right - // MACH-O commands, so we do too. - llvm_target: ios_llvm_target(arch).into(), + llvm_target, metadata: crate::spec::TargetMetadata { description: Some("ARM64e Apple iOS".into()), tier: Some(3), @@ -20,12 +13,13 @@ pub(crate) fn target() -> Target { }, pointer_width: 64, data_layout: "e-m:o-i64:64-i128:128-n32:64-S128-Fn32".into(), - arch: arch.target_arch(), + arch, options: TargetOptions { features: "+neon,+fp-armv8,+apple-a12,+v8.3a,+pauth".into(), max_atomic_width: Some(128), frame_pointer: FramePointer::NonLeaf, - ..base + supported_sanitizers: SanitizerSet::ADDRESS | SanitizerSet::THREAD, + ..opts }, } } diff --git a/compiler/rustc_target/src/spec/targets/armv7k_apple_watchos.rs b/compiler/rustc_target/src/spec/targets/armv7k_apple_watchos.rs index 35de6b35eaf2e..8fe27f60e0af1 100644 --- a/compiler/rustc_target/src/spec/targets/armv7k_apple_watchos.rs +++ b/compiler/rustc_target/src/spec/targets/armv7k_apple_watchos.rs @@ -1,10 +1,10 @@ -use crate::spec::base::apple::{opts, Arch, TargetAbi}; +use crate::spec::base::apple::{base, Arch, TargetAbi}; use crate::spec::{Target, TargetOptions}; pub(crate) fn target() -> Target { - let arch = Arch::Armv7k; + let (opts, llvm_target, arch) = base("watchos", Arch::Armv7k, TargetAbi::Normal); Target { - llvm_target: "armv7k-apple-watchos".into(), + llvm_target, metadata: crate::spec::TargetMetadata { description: Some("Armv7-A Apple WatchOS".into()), tier: Some(3), @@ -13,13 +13,13 @@ pub(crate) fn target() -> Target { }, pointer_width: 32, data_layout: "e-m:o-p:32:32-Fi8-i64:64-a:0:32-n32-S128".into(), - arch: arch.target_arch(), + arch, options: TargetOptions { features: "+v7,+vfp4,+neon".into(), max_atomic_width: Some(64), dynamic_linking: false, position_independent_executables: true, - ..opts("watchos", arch, TargetAbi::Normal) + ..opts }, } } diff --git a/compiler/rustc_target/src/spec/targets/armv7s_apple_ios.rs b/compiler/rustc_target/src/spec/targets/armv7s_apple_ios.rs index 41eaa79d3eb22..deee6985f1a43 100644 --- a/compiler/rustc_target/src/spec/targets/armv7s_apple_ios.rs +++ b/compiler/rustc_target/src/spec/targets/armv7s_apple_ios.rs @@ -1,10 +1,10 @@ -use crate::spec::base::apple::{ios_llvm_target, opts, Arch, TargetAbi}; +use crate::spec::base::apple::{base, Arch, TargetAbi}; use crate::spec::{Target, TargetOptions}; pub(crate) fn target() -> Target { - let arch = Arch::Armv7s; + let (opts, llvm_target, arch) = base("ios", Arch::Armv7s, TargetAbi::Normal); Target { - llvm_target: ios_llvm_target(arch).into(), + llvm_target, metadata: crate::spec::TargetMetadata { description: Some("Armv7-A Apple-A6 Apple iOS".into()), tier: Some(3), @@ -13,11 +13,11 @@ pub(crate) fn target() -> Target { }, pointer_width: 32, data_layout: "e-m:o-p:32:32-Fi8-f64:32:64-v64:32:64-v128:32:128-a:0:32-n32-S32".into(), - arch: arch.target_arch(), + arch, options: TargetOptions { features: "+v7,+vfp4,+neon".into(), max_atomic_width: Some(64), - ..opts("ios", arch, TargetAbi::Normal) + ..opts }, } } diff --git a/compiler/rustc_target/src/spec/targets/i386_apple_ios.rs b/compiler/rustc_target/src/spec/targets/i386_apple_ios.rs index 263393fd536ce..dc14cb3ec767f 100644 --- a/compiler/rustc_target/src/spec/targets/i386_apple_ios.rs +++ b/compiler/rustc_target/src/spec/targets/i386_apple_ios.rs @@ -1,17 +1,12 @@ -use crate::spec::base::apple::{ios_sim_llvm_target, opts, Arch, TargetAbi}; +use crate::spec::base::apple::{base, Arch, TargetAbi}; use crate::spec::{Target, TargetOptions}; pub(crate) fn target() -> Target { - let arch = Arch::I386; // i386-apple-ios is a simulator target, even though it isn't declared // that way in the target name like the other ones... - let abi = TargetAbi::Simulator; + let (opts, llvm_target, arch) = base("ios", Arch::I386, TargetAbi::Simulator); Target { - // Clang automatically chooses a more specific target based on - // IPHONEOS_DEPLOYMENT_TARGET. - // This is required for the target to pick the right - // MACH-O commands, so we do too. - llvm_target: ios_sim_llvm_target(arch).into(), + llvm_target, metadata: crate::spec::TargetMetadata { description: Some("32-bit x86 iOS".into()), tier: Some(3), @@ -22,7 +17,7 @@ pub(crate) fn target() -> Target { data_layout: "e-m:o-p:32:32-p270:32:32-p271:32:32-p272:64:64-\ i128:128-f64:32:64-f80:128-n8:16:32-S128" .into(), - arch: arch.target_arch(), - options: TargetOptions { max_atomic_width: Some(64), ..opts("ios", arch, abi) }, + arch, + options: TargetOptions { max_atomic_width: Some(64), ..opts }, } } diff --git a/compiler/rustc_target/src/spec/targets/i686_apple_darwin.rs b/compiler/rustc_target/src/spec/targets/i686_apple_darwin.rs index f7045a97bbbf0..67afe35bee402 100644 --- a/compiler/rustc_target/src/spec/targets/i686_apple_darwin.rs +++ b/compiler/rustc_target/src/spec/targets/i686_apple_darwin.rs @@ -1,18 +1,12 @@ -use crate::spec::base::apple::{macos_llvm_target, opts, Arch, TargetAbi}; +use crate::spec::base::apple::{base, Arch, TargetAbi}; use crate::spec::{Cc, FramePointer, LinkerFlavor, Lld, Target, TargetOptions}; pub(crate) fn target() -> Target { - let arch = Arch::I686; - let mut base = opts("macos", arch, TargetAbi::Normal); - base.max_atomic_width = Some(64); - base.add_pre_link_args(LinkerFlavor::Darwin(Cc::Yes, Lld::No), &["-m32"]); - base.frame_pointer = FramePointer::Always; + let (mut opts, llvm_target, arch) = base("macos", Arch::I686, TargetAbi::Normal); + opts.add_pre_link_args(LinkerFlavor::Darwin(Cc::Yes, Lld::No), &["-m32"]); Target { - // Clang automatically chooses a more specific target based on - // MACOSX_DEPLOYMENT_TARGET. To enable cross-language LTO to work - // correctly, we do too. - llvm_target: macos_llvm_target(arch).into(), + llvm_target, metadata: crate::spec::TargetMetadata { description: Some("32-bit macOS (10.12+, Sierra+)".into()), tier: Some(3), @@ -23,7 +17,12 @@ pub(crate) fn target() -> Target { data_layout: "e-m:o-p:32:32-p270:32:32-p271:32:32-p272:64:64-\ i128:128-f64:32:64-f80:128-n8:16:32-S128" .into(), - arch: arch.target_arch(), - options: TargetOptions { mcount: "\u{1}mcount".into(), ..base }, + arch, + options: TargetOptions { + mcount: "\u{1}mcount".into(), + max_atomic_width: Some(64), + frame_pointer: FramePointer::Always, + ..opts + }, } } diff --git a/compiler/rustc_target/src/spec/targets/x86_64_apple_darwin.rs b/compiler/rustc_target/src/spec/targets/x86_64_apple_darwin.rs index 7bf18026735dd..e7f14aa920963 100644 --- a/compiler/rustc_target/src/spec/targets/x86_64_apple_darwin.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_apple_darwin.rs @@ -1,20 +1,11 @@ -use crate::spec::base::apple::{macos_llvm_target, opts, Arch, TargetAbi}; +use crate::spec::base::apple::{base, Arch, TargetAbi}; use crate::spec::{Cc, FramePointer, LinkerFlavor, Lld, SanitizerSet, Target, TargetOptions}; pub(crate) fn target() -> Target { - let arch = Arch::X86_64; - let mut base = opts("macos", arch, TargetAbi::Normal); - base.max_atomic_width = Some(128); // penryn+ supports cmpxchg16b - base.frame_pointer = FramePointer::Always; - base.add_pre_link_args(LinkerFlavor::Darwin(Cc::Yes, Lld::No), &["-m64"]); - base.supported_sanitizers = - SanitizerSet::ADDRESS | SanitizerSet::CFI | SanitizerSet::LEAK | SanitizerSet::THREAD; - + let (mut opts, llvm_target, arch) = base("macos", Arch::X86_64, TargetAbi::Normal); + opts.add_pre_link_args(LinkerFlavor::Darwin(Cc::Yes, Lld::No), &["-m64"]); Target { - // Clang automatically chooses a more specific target based on - // MACOSX_DEPLOYMENT_TARGET. To enable cross-language LTO to work - // correctly, we do too. - llvm_target: macos_llvm_target(arch).into(), + llvm_target, metadata: crate::spec::TargetMetadata { description: Some("64-bit macOS (10.12+, Sierra+)".into()), tier: Some(1), @@ -24,7 +15,16 @@ pub(crate) fn target() -> Target { pointer_width: 64, data_layout: "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128".into(), - arch: arch.target_arch(), - options: TargetOptions { mcount: "\u{1}mcount".into(), ..base }, + arch, + options: TargetOptions { + mcount: "\u{1}mcount".into(), + max_atomic_width: Some(128), // penryn+ supports cmpxchg16b + frame_pointer: FramePointer::Always, + supported_sanitizers: SanitizerSet::ADDRESS + | SanitizerSet::CFI + | SanitizerSet::LEAK + | SanitizerSet::THREAD, + ..opts + }, } } diff --git a/compiler/rustc_target/src/spec/targets/x86_64_apple_ios.rs b/compiler/rustc_target/src/spec/targets/x86_64_apple_ios.rs index 76a0bb1d91eef..847c4f011f9f5 100644 --- a/compiler/rustc_target/src/spec/targets/x86_64_apple_ios.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_apple_ios.rs @@ -1,15 +1,12 @@ -use crate::spec::base::apple::{ios_sim_llvm_target, opts, Arch, TargetAbi}; +use crate::spec::base::apple::{base, Arch, TargetAbi}; use crate::spec::{SanitizerSet, Target, TargetOptions}; pub(crate) fn target() -> Target { - let arch = Arch::X86_64; // x86_64-apple-ios is a simulator target, even though it isn't declared // that way in the target name like the other ones... - let mut base = opts("ios", arch, TargetAbi::Simulator); - base.supported_sanitizers = SanitizerSet::ADDRESS | SanitizerSet::THREAD; - + let (opts, llvm_target, arch) = base("ios", Arch::X86_64, TargetAbi::Simulator); Target { - llvm_target: ios_sim_llvm_target(arch).into(), + llvm_target, metadata: crate::spec::TargetMetadata { description: Some("64-bit x86 iOS".into()), tier: Some(2), @@ -19,7 +16,11 @@ pub(crate) fn target() -> Target { pointer_width: 64, data_layout: "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128".into(), - arch: arch.target_arch(), - options: TargetOptions { max_atomic_width: Some(128), ..base }, + arch, + options: TargetOptions { + max_atomic_width: Some(128), + supported_sanitizers: SanitizerSet::ADDRESS | SanitizerSet::THREAD, + ..opts + }, } } diff --git a/compiler/rustc_target/src/spec/targets/x86_64_apple_ios_macabi.rs b/compiler/rustc_target/src/spec/targets/x86_64_apple_ios_macabi.rs index f66efbbf709d1..042079f800b97 100644 --- a/compiler/rustc_target/src/spec/targets/x86_64_apple_ios_macabi.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_apple_ios_macabi.rs @@ -1,13 +1,10 @@ -use crate::spec::base::apple::{mac_catalyst_llvm_target, opts, Arch, TargetAbi}; +use crate::spec::base::apple::{base, Arch, TargetAbi}; use crate::spec::{SanitizerSet, Target, TargetOptions}; pub(crate) fn target() -> Target { - let arch = Arch::X86_64; - let mut base = opts("ios", arch, TargetAbi::MacCatalyst); - base.supported_sanitizers = SanitizerSet::ADDRESS | SanitizerSet::LEAK | SanitizerSet::THREAD; - + let (opts, llvm_target, arch) = base("ios", Arch::X86_64, TargetAbi::MacCatalyst); Target { - llvm_target: mac_catalyst_llvm_target(arch).into(), + llvm_target, metadata: crate::spec::TargetMetadata { description: Some("Apple Catalyst on x86_64".into()), tier: Some(2), @@ -17,7 +14,11 @@ pub(crate) fn target() -> Target { pointer_width: 64, data_layout: "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128".into(), - arch: arch.target_arch(), - options: TargetOptions { max_atomic_width: Some(128), ..base }, + arch, + options: TargetOptions { + max_atomic_width: Some(128), + supported_sanitizers: SanitizerSet::ADDRESS | SanitizerSet::LEAK | SanitizerSet::THREAD, + ..opts + }, } } diff --git a/compiler/rustc_target/src/spec/targets/x86_64_apple_tvos.rs b/compiler/rustc_target/src/spec/targets/x86_64_apple_tvos.rs index f9d5f6e77d9fc..947086097908c 100644 --- a/compiler/rustc_target/src/spec/targets/x86_64_apple_tvos.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_apple_tvos.rs @@ -1,13 +1,12 @@ -use crate::spec::base::apple::{opts, tvos_sim_llvm_target, Arch, TargetAbi}; +use crate::spec::base::apple::{base, Arch, TargetAbi}; use crate::spec::{Target, TargetOptions}; pub(crate) fn target() -> Target { - let arch = Arch::X86_64; // x86_64-apple-tvos is a simulator target, even though it isn't declared // that way in the target name like the other ones... - let abi = TargetAbi::Simulator; + let (opts, llvm_target, arch) = base("tvos", Arch::X86_64, TargetAbi::Simulator); Target { - llvm_target: tvos_sim_llvm_target(arch).into(), + llvm_target, metadata: crate::spec::TargetMetadata { description: Some("x86 64-bit tvOS".into()), tier: Some(3), @@ -17,7 +16,7 @@ pub(crate) fn target() -> Target { pointer_width: 64, data_layout: "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128".into(), - arch: arch.target_arch(), - options: TargetOptions { max_atomic_width: Some(128), ..opts("tvos", arch, abi) }, + arch, + options: TargetOptions { max_atomic_width: Some(128), ..opts }, } } diff --git a/compiler/rustc_target/src/spec/targets/x86_64_apple_watchos_sim.rs b/compiler/rustc_target/src/spec/targets/x86_64_apple_watchos_sim.rs index 1fced10c895ea..1dab95988601d 100644 --- a/compiler/rustc_target/src/spec/targets/x86_64_apple_watchos_sim.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_apple_watchos_sim.rs @@ -1,10 +1,10 @@ -use crate::spec::base::apple::{opts, watchos_sim_llvm_target, Arch, TargetAbi}; +use crate::spec::base::apple::{base, Arch, TargetAbi}; use crate::spec::{Target, TargetOptions}; pub(crate) fn target() -> Target { - let arch = Arch::X86_64; + let (opts, llvm_target, arch) = base("watchos", Arch::X86_64, TargetAbi::Simulator); Target { - llvm_target: watchos_sim_llvm_target(arch).into(), + llvm_target, metadata: crate::spec::TargetMetadata { description: Some("x86 64-bit Apple WatchOS simulator".into()), tier: Some(3), @@ -14,10 +14,7 @@ pub(crate) fn target() -> Target { pointer_width: 64, data_layout: "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128".into(), - arch: arch.target_arch(), - options: TargetOptions { - max_atomic_width: Some(128), - ..opts("watchos", arch, TargetAbi::Simulator) - }, + arch, + options: TargetOptions { max_atomic_width: Some(128), ..opts }, } } diff --git a/compiler/rustc_target/src/spec/targets/x86_64h_apple_darwin.rs b/compiler/rustc_target/src/spec/targets/x86_64h_apple_darwin.rs index 9b9ffe4e5360e..f44bc660a62f9 100644 --- a/compiler/rustc_target/src/spec/targets/x86_64h_apple_darwin.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64h_apple_darwin.rs @@ -1,13 +1,12 @@ -use crate::spec::base::apple::{macos_llvm_target, opts, Arch, TargetAbi}; +use crate::spec::base::apple::{base, Arch, TargetAbi}; use crate::spec::{Cc, FramePointer, LinkerFlavor, Lld, SanitizerSet, Target, TargetOptions}; pub(crate) fn target() -> Target { - let arch = Arch::X86_64h; - let mut base = opts("macos", arch, TargetAbi::Normal); - base.max_atomic_width = Some(128); - base.frame_pointer = FramePointer::Always; - base.add_pre_link_args(LinkerFlavor::Darwin(Cc::Yes, Lld::No), &["-m64"]); - base.supported_sanitizers = + let (mut opts, llvm_target, arch) = base("macos", Arch::X86_64h, TargetAbi::Normal); + opts.max_atomic_width = Some(128); + opts.frame_pointer = FramePointer::Always; + opts.add_pre_link_args(LinkerFlavor::Darwin(Cc::Yes, Lld::No), &["-m64"]); + opts.supported_sanitizers = SanitizerSet::ADDRESS | SanitizerSet::CFI | SanitizerSet::LEAK | SanitizerSet::THREAD; // x86_64h is core2-avx without a few of the features which would otherwise @@ -20,19 +19,16 @@ pub(crate) fn target() -> Target { // It would be nice if this were not the case, but fixing it seems tricky // (and given that the main use-case for this target is for use in universal // binaries, probably not that important). - base.features = "-rdrnd,-aes,-pclmul,-rtm,-fsgsbase".into(); + opts.features = "-rdrnd,-aes,-pclmul,-rtm,-fsgsbase".into(); // Double-check that the `cpu` is what we expect (if it's not the list above // may need updating). assert_eq!( - base.cpu, "core-avx2", + opts.cpu, "core-avx2", "you need to adjust the feature list in x86_64h-apple-darwin if you change this", ); Target { - // Clang automatically chooses a more specific target based on - // MACOSX_DEPLOYMENT_TARGET. To enable cross-language LTO to work - // correctly, we do too. - llvm_target: macos_llvm_target(arch).into(), + llvm_target, metadata: crate::spec::TargetMetadata { description: Some("macOS with late-gen Intel (at least Haswell)".into()), tier: Some(3), @@ -42,7 +38,7 @@ pub(crate) fn target() -> Target { pointer_width: 64, data_layout: "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128".into(), - arch: arch.target_arch(), - options: TargetOptions { mcount: "\u{1}mcount".into(), ..base }, + arch, + options: TargetOptions { mcount: "\u{1}mcount".into(), ..opts }, } } From bd56857e31e9324d867a4d3184301a1ef510d316 Mon Sep 17 00:00:00 2001 From: Mads Marquart Date: Wed, 21 Aug 2024 15:35:28 +0200 Subject: [PATCH 0507/2194] Apple: Add comments for `-platform_version` linker argument --- .../rustc_target/src/spec/base/apple/mod.rs | 47 ++++++++++++++----- 1 file changed, 35 insertions(+), 12 deletions(-) diff --git a/compiler/rustc_target/src/spec/base/apple/mod.rs b/compiler/rustc_target/src/spec/base/apple/mod.rs index 2ca6b7d32ca45..b1fe49f76caa3 100644 --- a/compiler/rustc_target/src/spec/base/apple/mod.rs +++ b/compiler/rustc_target/src/spec/base/apple/mod.rs @@ -117,18 +117,6 @@ impl TargetAbi { } fn pre_link_args(os: &'static str, arch: Arch, abi: TargetAbi) -> LinkArgs { - let platform_name: StaticCow = match abi { - TargetAbi::Normal => os.into(), - TargetAbi::Simulator => format!("{os}-simulator").into(), - TargetAbi::MacCatalyst => "mac-catalyst".into(), - }; - - let min_version: StaticCow = { - let (major, minor, patch) = deployment_target(os, arch, abi); - format!("{major}.{minor}.{patch}").into() - }; - let sdk_version = min_version.clone(); - // From the man page for ld64 (`man ld`): // > The linker accepts universal (multiple-architecture) input files, // > but always creates a "thin" (single-architecture), standard Mach-O @@ -140,11 +128,46 @@ fn pre_link_args(os: &'static str, arch: Arch, abi: TargetAbi) -> LinkArgs { let mut args = TargetOptions::link_args(LinkerFlavor::Darwin(Cc::No, Lld::No), &["-arch", arch.ld_arch()]); + // From the man page for ld64 (`man ld`): + // > This is set to indicate the platform, oldest supported version of + // > that platform that output is to be used on, and the SDK that the + // > output was built against. platform [...] may be one of the following + // > strings: + // > - macos + // > - ios + // > - tvos + // > - watchos + // > - bridgeos + // > - visionos + // > - xros + // > - mac-catalyst + // > - ios-simulator + // > - tvos-simulator + // > - watchos-simulator + // > - visionos-simulator + // > - xros-simulator + // > - driverkit + // + // Like with `-arch`, the linker can figure out the platform versions + // itself from the binaries being linked, but to be safe, we specify the + // desired versions here explicitly. + let platform_name: StaticCow = match abi { + TargetAbi::Normal => os.into(), + TargetAbi::Simulator => format!("{os}-simulator").into(), + TargetAbi::MacCatalyst => "mac-catalyst".into(), + }; + let min_version: StaticCow = { + let (major, minor, patch) = deployment_target(os, arch, abi); + format!("{major}.{minor}.{patch}").into() + }; + // Lie about the SDK version, we don't know it here + let sdk_version = min_version.clone(); add_link_args_iter( &mut args, LinkerFlavor::Darwin(Cc::No, Lld::No), ["-platform_version".into(), platform_name, min_version, sdk_version].into_iter(), ); + if abi != TargetAbi::MacCatalyst { // CC forwards the `-arch` to the linker, so we use the same value // here intentionally. From 263937090528baf51d703a364a91a2b2a647e848 Mon Sep 17 00:00:00 2001 From: ding-young Date: Thu, 29 Aug 2024 01:25:09 +0900 Subject: [PATCH 0508/2194] impl rewrite_result for TraitAliasBounds, WherePredicate --- src/items.rs | 67 ++++++++++++++++++++++++++++++---------------------- src/types.rs | 19 +++++++++------ 2 files changed, 51 insertions(+), 35 deletions(-) diff --git a/src/items.rs b/src/items.rs index ddcbfac129956..39fb358401eda 100644 --- a/src/items.rs +++ b/src/items.rs @@ -840,7 +840,8 @@ pub(crate) fn format_impl( where_span_end, self_ty.span.hi(), option, - )?; + ) + .ok()?; // If there is no where-clause, we may have missing comments between the trait name and // the opening brace. @@ -1231,7 +1232,8 @@ pub(crate) fn format_trait( None, pos_before_where, option, - )?; + ) + .ok()?; // If the where-clause cannot fit on the same line, // put the where-clause on a new line if !where_clause_str.contains('\n') @@ -1336,7 +1338,11 @@ pub(crate) struct TraitAliasBounds<'a> { impl<'a> Rewrite for TraitAliasBounds<'a> { fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option { - let generic_bounds_str = self.generic_bounds.rewrite(context, shape)?; + self.rewrite_result(context, shape).ok() + } + + fn rewrite_result(&self, context: &RewriteContext<'_>, shape: Shape) -> RewriteResult { + let generic_bounds_str = self.generic_bounds.rewrite_result(context, shape)?; let mut option = WhereClauseOption::new(true, WhereClauseSpace::None); option.allow_single_line(); @@ -1365,7 +1371,7 @@ impl<'a> Rewrite for TraitAliasBounds<'a> { shape.indent.to_string_with_newline(context.config) }; - Some(format!("{generic_bounds_str}{space}{where_str}")) + Ok(format!("{generic_bounds_str}{space}{where_str}")) } } @@ -1623,7 +1629,8 @@ fn format_tuple_struct( None, body_hi, option, - )? + ) + .ok()? } None => "".to_owned(), }; @@ -1792,7 +1799,8 @@ fn rewrite_ty( None, generics.span.hi(), option, - )?; + ) + .ok()?; result.push_str(&where_clause_str); if let Some(ty) = rhs { @@ -2663,7 +2671,8 @@ fn rewrite_fn_base( Some(span.hi()), pos_before_where, option, - )?; + ) + .ok()?; // If there are neither where-clause nor return type, we may be missing comments between // params and `{`. if where_clause_str.is_empty() { @@ -2939,7 +2948,7 @@ fn rewrite_where_clause_rfc_style( span_end: Option, span_end_before_where: BytePos, where_clause_option: WhereClauseOption, -) -> Option { +) -> RewriteResult { let (where_keyword, allow_single_line) = rewrite_where_keyword( context, predicates, @@ -2953,8 +2962,9 @@ fn rewrite_where_clause_rfc_style( let clause_shape = shape .block() .with_max_width(context.config) - .block_left(context.config.tab_spaces())? - .sub_width(1)?; + .block_left(context.config.tab_spaces()) + .and_then(|s| s.sub_width(1)) + .max_width_error(shape.width, where_span)?; let force_single_line = context.config.where_single_line() && predicates.len() == 1 && !where_clause_option.veto_single_line; @@ -2979,7 +2989,7 @@ fn rewrite_where_clause_rfc_style( clause_shape.indent.to_string_with_newline(context.config) }; - Some(format!("{where_keyword}{clause_sep}{preds_str}")) + Ok(format!("{where_keyword}{clause_sep}{preds_str}")) } /// Rewrite `where` and comment around it. @@ -2990,12 +3000,13 @@ fn rewrite_where_keyword( shape: Shape, span_end_before_where: BytePos, where_clause_option: WhereClauseOption, -) -> Option<(String, bool)> { +) -> Result<(String, bool), RewriteError> { let block_shape = shape.block().with_max_width(context.config); // 1 = `,` let clause_shape = block_shape - .block_left(context.config.tab_spaces())? - .sub_width(1)?; + .block_left(context.config.tab_spaces()) + .and_then(|s| s.sub_width(1)) + .max_width_error(block_shape.width, where_span)?; let comment_separator = |comment: &str, shape: Shape| { if comment.is_empty() { @@ -3026,7 +3037,7 @@ fn rewrite_where_keyword( && comment_before.is_empty() && comment_after.is_empty(); - Some((result, allow_single_line)) + Ok((result, allow_single_line)) } /// Rewrite bounds on a where clause. @@ -3038,7 +3049,7 @@ fn rewrite_bounds_on_where_clause( span_end: Option, where_clause_option: WhereClauseOption, force_single_line: bool, -) -> Option { +) -> RewriteResult { let span_start = predicates[0].span().lo(); // If we don't have the start of the next span, then use the end of the // predicates, but that means we miss comments. @@ -3077,7 +3088,7 @@ fn rewrite_bounds_on_where_clause( .tactic(shape_tactic) .trailing_separator(comma_tactic) .preserve_newline(preserve_newline); - write_list(&items.collect::>(), &fmt).ok() + write_list(&items.collect::>(), &fmt) } fn rewrite_where_clause( @@ -3091,9 +3102,9 @@ fn rewrite_where_clause( span_end: Option, span_end_before_where: BytePos, where_clause_option: WhereClauseOption, -) -> Option { +) -> RewriteResult { if predicates.is_empty() { - return Some(String::new()); + return Ok(String::new()); } if context.config.indent_style() == IndentStyle::Block { @@ -3153,7 +3164,7 @@ fn rewrite_where_clause( .trailing_separator(comma_tactic) .ends_with_newline(tactic.ends_with_newline(context.config.indent_style())) .preserve_newline(true); - let preds_str = write_list(&item_vec, &fmt).ok()?; + let preds_str = write_list(&item_vec, &fmt)?; let end_length = if terminator == "{" { // If the brace is on the next line we don't need to count it otherwise it needs two @@ -3171,13 +3182,13 @@ fn rewrite_where_clause( || preds_str.contains('\n') || shape.indent.width() + " where ".len() + preds_str.len() + end_length > shape.width { - Some(format!( + Ok(format!( "\n{}where {}", (shape.indent + extra_indent).to_string(context.config), preds_str )) } else { - Some(format!(" where {preds_str}")) + Ok(format!(" where {preds_str}")) } } @@ -3198,15 +3209,14 @@ fn rewrite_comments_before_after_where( span_before_where: Span, span_after_where: Span, shape: Shape, -) -> Option<(String, String)> { - let before_comment = rewrite_missing_comment(span_before_where, shape, context).ok()?; +) -> Result<(String, String), RewriteError> { + let before_comment = rewrite_missing_comment(span_before_where, shape, context)?; let after_comment = rewrite_missing_comment( span_after_where, shape.block_indent(context.config.tab_spaces()), context, - ) - .ok()?; - Some((before_comment, after_comment)) + )?; + Ok((before_comment, after_comment)) } fn format_header( @@ -3288,7 +3298,8 @@ fn format_generics( Some(span.hi()), span_end_before_where, option, - )?; + ) + .ok()?; result.push_str(&where_clause_str); ( brace_pos == BracePos::ForceSameLine || brace_style == BraceStyle::PreferSameLine, diff --git a/src/types.rs b/src/types.rs index 384a69e23b222..5477942f82e72 100644 --- a/src/types.rs +++ b/src/types.rs @@ -457,6 +457,10 @@ fn get_tactics(item_vec: &[ListItem], output: &str, shape: Shape) -> DefinitiveL impl Rewrite for ast::WherePredicate { fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option { + self.rewrite_result(context, shape).ok() + } + + fn rewrite_result(&self, context: &RewriteContext<'_>, shape: Shape) -> RewriteResult { // FIXME: dead spans? let result = match *self { ast::WherePredicate::BoundPredicate(ast::WhereBoundPredicate { @@ -465,7 +469,7 @@ impl Rewrite for ast::WherePredicate { ref bounds, .. }) => { - let type_str = bounded_ty.rewrite(context, shape)?; + let type_str = bounded_ty.rewrite_result(context, shape)?; let colon = type_bound_colon(context).trim_end(); let lhs = if let Some(binder_str) = rewrite_bound_params(context, shape, bound_generic_params) @@ -475,25 +479,26 @@ impl Rewrite for ast::WherePredicate { format!("{type_str}{colon}") }; - rewrite_assign_rhs(context, lhs, bounds, &RhsAssignKind::Bounds, shape).ok()? + rewrite_assign_rhs(context, lhs, bounds, &RhsAssignKind::Bounds, shape)? } ast::WherePredicate::RegionPredicate(ast::WhereRegionPredicate { ref lifetime, ref bounds, span, - }) => rewrite_bounded_lifetime(lifetime, bounds, span, context, shape).ok()?, + }) => rewrite_bounded_lifetime(lifetime, bounds, span, context, shape)?, ast::WherePredicate::EqPredicate(ast::WhereEqPredicate { ref lhs_ty, ref rhs_ty, .. }) => { - let lhs_ty_str = lhs_ty.rewrite(context, shape).map(|lhs| lhs + " =")?; - rewrite_assign_rhs(context, lhs_ty_str, &**rhs_ty, &RhsAssignKind::Ty, shape) - .ok()? + let lhs_ty_str = lhs_ty + .rewrite_result(context, shape) + .map(|lhs| lhs + " =")?; + rewrite_assign_rhs(context, lhs_ty_str, &**rhs_ty, &RhsAssignKind::Ty, shape)? } }; - Some(result) + Ok(result) } } From b40c3cc3888229080dff8a59e607cffbcfed82b7 Mon Sep 17 00:00:00 2001 From: ding-young Date: Sun, 1 Sep 2024 15:44:17 +0900 Subject: [PATCH 0509/2194] impl rewrite_result for ForeignItem --- src/items.rs | 118 +++++++++++++++++++++++++++---------------------- src/visitor.rs | 16 ++++--- 2 files changed, 76 insertions(+), 58 deletions(-) diff --git a/src/items.rs b/src/items.rs index 39fb358401eda..1f25827e9198c 100644 --- a/src/items.rs +++ b/src/items.rs @@ -433,7 +433,7 @@ impl<'a> FmtVisitor<'a> { let mut fn_brace_style = newline_for_brace(self.config, &fn_sig.generics.where_clause); let (result, _, force_newline_brace) = - rewrite_fn_base(&context, indent, ident, fn_sig, span, fn_brace_style)?; + rewrite_fn_base(&context, indent, ident, fn_sig, span, fn_brace_style).ok()?; // 2 = ` {` if self.config.brace_style() == BraceStyle::AlwaysNextLine @@ -454,7 +454,7 @@ impl<'a> FmtVisitor<'a> { vis: &ast::Visibility, generics: &ast::Generics, span: Span, - ) -> Option { + ) -> RewriteResult { // Drop semicolon or it will be interpreted as comment. let span = mk_sp(span.lo(), span.hi() - BytePos(1)); let context = self.get_context(); @@ -476,7 +476,7 @@ impl<'a> FmtVisitor<'a> { // Re-attach semicolon result.push(';'); - Some(result) + Ok(result) } pub(crate) fn single_line_fn( @@ -977,7 +977,7 @@ fn format_impl_ref_and_type( 0, )? }; - let generics_str = rewrite_generics(context, "impl", generics, shape)?; + let generics_str = rewrite_generics(context, "impl", generics, shape).ok()?; result.push_str(&generics_str); result.push_str(format_constness_right(constness)); @@ -1185,7 +1185,7 @@ pub(crate) fn format_trait( let shape = Shape::indented(offset, context.config).offset_left(result.len())?; let generics_str = - rewrite_generics(context, rewrite_ident(context, item.ident), generics, shape)?; + rewrite_generics(context, rewrite_ident(context, item.ident), generics, shape).ok()?; result.push_str(&generics_str); // FIXME(#2055): rustfmt fails to format when there are comments between trait bounds. @@ -1386,7 +1386,7 @@ pub(crate) fn format_trait_alias( let alias = rewrite_ident(context, ident); // 6 = "trait ", 2 = " =" let g_shape = shape.offset_left(6)?.sub_width(2)?; - let generics_str = rewrite_generics(context, alias, generics, g_shape)?; + let generics_str = rewrite_generics(context, alias, generics, g_shape).ok()?; let vis_str = format_visibility(context, vis); let lhs = format!("{vis_str}trait {generics_str} ="); // 1 = ";" @@ -1613,7 +1613,7 @@ fn format_tuple_struct( Some(generics) => { let budget = context.budget(last_line_width(&header_str)); let shape = Shape::legacy(budget, offset); - let generics_str = rewrite_generics(context, "", generics, shape)?; + let generics_str = rewrite_generics(context, "", generics, shape).ok()?; result.push_str(&generics_str); let where_budget = context.budget(last_line_width(&result)); @@ -1700,7 +1700,7 @@ pub(crate) fn rewrite_type_alias<'a, 'b>( indent: Indent, visitor_kind: &ItemVisitorKind<'b>, span: Span, -) -> Option { +) -> RewriteResult { use ItemVisitorKind::*; let ast::TyAlias { @@ -1738,8 +1738,8 @@ pub(crate) fn rewrite_type_alias<'a, 'b>( rewrite_ty(rw_info, Some(bounds), ty_opt, vis) }?; match defaultness { - ast::Defaultness::Default(..) => Some(format!("default {result}")), - _ => Some(result), + ast::Defaultness::Default(..) => Ok(format!("default {result}")), + _ => Ok(result), } } } @@ -1750,7 +1750,7 @@ fn rewrite_ty( generic_bounds_opt: Option<&ast::GenericBounds>, rhs: Option<&R>, vis: &ast::Visibility, -) -> Option { +) -> RewriteResult { let mut result = String::with_capacity(128); let TyAliasRewriteInfo(context, indent, generics, where_clauses, ident, span) = *rw_info; let (before_where_predicates, after_where_predicates) = generics @@ -1758,7 +1758,7 @@ fn rewrite_ty( .predicates .split_at(where_clauses.split); if !after_where_predicates.is_empty() { - return None; + return Err(RewriteError::Unknown); } result.push_str(&format!("{}type ", format_visibility(context, vis))); let ident_str = rewrite_ident(context, ident); @@ -1767,9 +1767,11 @@ fn rewrite_ty( result.push_str(ident_str) } else { // 2 = `= ` - let g_shape = Shape::indented(indent, context.config) - .offset_left(result.len())? - .sub_width(2)?; + let g_shape = Shape::indented(indent, context.config); + let g_shape = g_shape + .offset_left(result.len()) + .and_then(|s| s.sub_width(2)) + .max_width_error(g_shape.width, span)?; let generics_str = rewrite_generics(context, ident_str, generics, g_shape)?; result.push_str(&generics_str); } @@ -1777,8 +1779,13 @@ fn rewrite_ty( if let Some(bounds) = generic_bounds_opt { if !bounds.is_empty() { // 2 = `: ` - let shape = Shape::indented(indent, context.config).offset_left(result.len() + 2)?; - let type_bounds = bounds.rewrite(context, shape).map(|s| format!(": {}", s))?; + let shape = Shape::indented(indent, context.config); + let shape = shape + .offset_left(result.len() + 2) + .max_width_error(shape.width, span)?; + let type_bounds = bounds + .rewrite_result(context, shape) + .map(|s| format!(": {}", s))?; result.push_str(&type_bounds); } } @@ -1799,8 +1806,7 @@ fn rewrite_ty( None, generics.span.hi(), option, - ) - .ok()?; + )?; result.push_str(&where_clause_str); if let Some(ty) = rhs { @@ -1820,13 +1826,20 @@ fn rewrite_ty( let lhs = match comment_span { Some(comment_span) - if contains_comment(context.snippet_provider.span_to_snippet(comment_span)?) => + if contains_comment( + context + .snippet_provider + .span_to_snippet(comment_span) + .unknown_error()?, + ) => { let comment_shape = if has_where { Shape::indented(indent, context.config) } else { - Shape::indented(indent, context.config) - .block_left(context.config.tab_spaces())? + let shape = Shape::indented(indent, context.config); + shape + .block_left(context.config.tab_spaces()) + .max_width_error(shape.width, span)? }; combine_strs_with_missing_comments( @@ -1836,19 +1849,17 @@ fn rewrite_ty( comment_span, comment_shape, true, - ) - .ok()? + )? } _ => format!("{result}="), }; // 1 = `;` - let shape = Shape::indented(indent, context.config).sub_width(1)?; - rewrite_assign_rhs(context, lhs, &*ty, &RhsAssignKind::Ty, shape) - .map(|s| s + ";") - .ok() + let shape = Shape::indented(indent, context.config); + let shape = shape.sub_width(1).max_width_error(shape.width, span)?; + rewrite_assign_rhs(context, lhs, &*ty, &RhsAssignKind::Ty, shape).map(|s| s + ";") } else { - Some(format!("{result};")) + Ok(format!("{result};")) } } @@ -2392,7 +2403,7 @@ fn rewrite_fn_base( fn_sig: &FnSig<'_>, span: Span, fn_brace_style: FnBraceStyle, -) -> Option<(String, bool, bool)> { +) -> Result<(String, bool, bool), RewriteError> { let mut force_new_line_for_brace = false; let where_clause = &fn_sig.generics.where_clause; @@ -2436,7 +2447,7 @@ fn rewrite_fn_base( // return type later anyway. let ret_str = fd .output - .rewrite(context, Shape::indented(indent, context.config))?; + .rewrite_result(context, Shape::indented(indent, context.config))?; let multi_line_ret_str = ret_str.contains('\n'); let ret_str_len = if multi_line_ret_str { 0 } else { ret_str.len() }; @@ -2449,7 +2460,7 @@ fn rewrite_fn_base( ret_str_len, fn_brace_style, multi_line_ret_str, - )?; + ); debug!( "rewrite_fn_base: one_line_budget: {}, multi_line_budget: {}, param_indent: {:?}", @@ -2611,7 +2622,7 @@ fn rewrite_fn_base( if multi_line_ret_str || ret_should_indent { // Now that we know the proper indent and width, we need to // re-layout the return type. - let ret_str = fd.output.rewrite(context, ret_shape)?; + let ret_str = fd.output.rewrite_result(context, ret_shape)?; result.push_str(&ret_str); } else { result.push_str(&ret_str); @@ -2671,8 +2682,7 @@ fn rewrite_fn_base( Some(span.hi()), pos_before_where, option, - ) - .ok()?; + )?; // If there are neither where-clause nor return type, we may be missing comments between // params and `{`. if where_clause_str.is_empty() { @@ -2699,7 +2709,7 @@ fn rewrite_fn_base( force_new_line_for_brace |= ends_with_comment; force_new_line_for_brace |= is_params_multi_lined && context.config.where_single_line() && !where_clause_str.is_empty(); - Some((result, ends_with_comment, force_new_line_for_brace)) + Ok((result, ends_with_comment, force_new_line_for_brace)) } /// Kind of spaces to put before `where`. @@ -2770,7 +2780,7 @@ fn rewrite_params( param_indent: Indent, span: Span, variadic: bool, -) -> Option { +) -> RewriteResult { if params.is_empty() { let comment = context .snippet(mk_sp( @@ -2779,7 +2789,7 @@ fn rewrite_params( span.hi() - BytePos(1), )) .trim(); - return Some(comment.to_owned()); + return Ok(comment.to_owned()); } let param_items: Vec<_> = itemize_list( context.snippet_provider, @@ -2829,7 +2839,7 @@ fn rewrite_params( .trailing_separator(trailing_separator) .ends_with_newline(tactic.ends_with_newline(context.config.indent_style())) .preserve_newline(true); - write_list(¶m_items, &fmt).ok() + write_list(¶m_items, &fmt) } fn compute_budgets_for_params( @@ -2839,7 +2849,7 @@ fn compute_budgets_for_params( ret_str_len: usize, fn_brace_style: FnBraceStyle, force_vertical_layout: bool, -) -> Option<(usize, usize, Indent)> { +) -> (usize, usize, Indent) { debug!( "compute_budgets_for_params {} {:?}, {}, {:?}", result.len(), @@ -2876,7 +2886,7 @@ fn compute_budgets_for_params( } }; - return Some((one_line_budget, multi_line_budget, indent)); + return (one_line_budget, multi_line_budget, indent); } } @@ -2888,7 +2898,7 @@ fn compute_budgets_for_params( // Account for `)` and possibly ` {`. IndentStyle::Visual => new_indent.width() + if ret_str_len == 0 { 1 } else { 3 }, }; - Some((0, context.budget(used_space), new_indent)) + (0, context.budget(used_space), new_indent) } fn newline_for_brace(config: &Config, where_clause: &ast::WhereClause) -> FnBraceStyle { @@ -2913,16 +2923,16 @@ fn rewrite_generics( ident: &str, generics: &ast::Generics, shape: Shape, -) -> Option { +) -> RewriteResult { // FIXME: convert bounds to where-clauses where they get too big or if // there is a where-clause at all. if generics.params.is_empty() { - return Some(ident.to_owned()); + return Ok(ident.to_owned()); } let params = generics.params.iter(); - overflow::rewrite_with_angle_brackets(context, ident, params, shape, generics.span).ok() + overflow::rewrite_with_angle_brackets(context, ident, params, shape, generics.span) } fn generics_shape_from_config(config: &Config, shape: Shape, offset: usize) -> Option { @@ -3272,7 +3282,7 @@ fn format_generics( used_width: usize, ) -> Option { let shape = Shape::legacy(context.budget(used_width + offset.width()), offset); - let mut result = rewrite_generics(context, "", generics, shape)?; + let mut result = rewrite_generics(context, "", generics, shape).ok()?; // If the generics are not parameterized then generics.span.hi() == 0, // so we use span.lo(), which is the position after `struct Foo`. @@ -3366,7 +3376,11 @@ fn format_generics( impl Rewrite for ast::ForeignItem { fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option { - let attrs_str = self.attrs.rewrite(context, shape)?; + self.rewrite_result(context, shape).ok() + } + + fn rewrite_result(&self, context: &RewriteContext<'_>, shape: Shape) -> RewriteResult { + let attrs_str = self.attrs.rewrite_result(context, shape)?; // Drop semicolon or it will be interpreted as comment. // FIXME: this may be a faulty span from libsyntax. let span = mk_sp(self.span.lo(), self.span.hi() - BytePos(1)); @@ -3399,7 +3413,7 @@ impl Rewrite for ast::ForeignItem { defaultness, Some(&inner_attrs), ); - Some(visitor.buffer.to_owned()) + Ok(visitor.buffer.to_owned()) } else { rewrite_fn_base( context, @@ -3431,17 +3445,18 @@ impl Rewrite for ast::ForeignItem { prefix, &static_foreign_item.ty, &RhsAssignKind::Ty, - shape.sub_width(1)?, + shape + .sub_width(1) + .max_width_error(shape.width, static_foreign_item.ty.span)?, ) .map(|s| s + ";") - .ok() } ast::ForeignItemKind::TyAlias(ref ty_alias) => { let (kind, span) = (&ItemVisitorKind::ForeignItem(self), self.span); rewrite_type_alias(ty_alias, context, shape.indent, kind, span) } ast::ForeignItemKind::MacCall(ref mac) => { - rewrite_macro(mac, None, context, shape, MacroPosition::Item).ok() + rewrite_macro(mac, None, context, shape, MacroPosition::Item) } }?; @@ -3458,7 +3473,6 @@ impl Rewrite for ast::ForeignItem { shape, false, ) - .ok() } } diff --git a/src/visitor.rs b/src/visitor.rs index afb54c8e2bcd7..99416f8550362 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -561,9 +561,11 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { ) } else { let indent = self.block_indent; - let rewrite = self.rewrite_required_fn( - indent, item.ident, sig, &item.vis, generics, item.span, - ); + let rewrite = self + .rewrite_required_fn( + indent, item.ident, sig, &item.vis, generics, item.span, + ) + .ok(); self.push_rewrite(item.span, rewrite); } } @@ -610,7 +612,8 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { self.block_indent, visitor_kind, span, - ); + ) + .ok(); self.push_rewrite(span, rewrite); } @@ -656,8 +659,9 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { ); } else { let indent = self.block_indent; - let rewrite = - self.rewrite_required_fn(indent, ai.ident, sig, &ai.vis, generics, ai.span); + let rewrite = self + .rewrite_required_fn(indent, ai.ident, sig, &ai.vis, generics, ai.span) + .ok(); self.push_rewrite(ai.span, rewrite); } } From d720a7ef77f76670d2275952e81e9ae6b2556638 Mon Sep 17 00:00:00 2001 From: ding-young Date: Sun, 25 Aug 2024 15:42:46 +0900 Subject: [PATCH 0510/2194] impl rewrite_result for ast::Expr --- src/expr.rs | 174 +++++++++++++++++++++++-------------------------- src/matches.rs | 23 ++++--- src/stmt.rs | 4 +- src/types.rs | 4 ++ src/utils.rs | 8 --- 5 files changed, 98 insertions(+), 115 deletions(-) diff --git a/src/expr.rs b/src/expr.rs index 5bd87d00b1d57..32bfc8b4722a4 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -39,6 +39,10 @@ use crate::visitor::FmtVisitor; impl Rewrite for ast::Expr { fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option { + self.rewrite_result(context, shape).ok() + } + + fn rewrite_result(&self, context: &RewriteContext<'_>, shape: Shape) -> RewriteResult { format_expr(self, ExprType::SubExpression, context, shape) } } @@ -58,14 +62,14 @@ pub(crate) fn format_expr( expr_type: ExprType, context: &RewriteContext<'_>, shape: Shape, -) -> Option { - skip_out_of_file_lines_range!(context, expr.span); +) -> RewriteResult { + skip_out_of_file_lines_range_err!(context, expr.span); if contains_skip(&*expr.attrs) { - return Some(context.snippet(expr.span()).to_owned()); + return Ok(context.snippet(expr.span()).to_owned()); } let shape = if expr_type == ExprType::Statement && semicolon_for_expr(context, expr) { - shape.sub_width(1)? + shape.sub_width(1).max_width_error(shape.width, expr.span)? } else { shape }; @@ -79,41 +83,38 @@ pub(crate) fn format_expr( shape, choose_separator_tactic(context, expr.span), None, - ) - .ok(), + ), ast::ExprKind::Lit(token_lit) => { if let Ok(expr_rw) = rewrite_literal(context, token_lit, expr.span, shape) { - Some(expr_rw) + Ok(expr_rw) } else { if let LitKind::StrRaw(_) = token_lit.kind { - Some(context.snippet(expr.span).trim().into()) + Ok(context.snippet(expr.span).trim().into()) } else { - None + Err(RewriteError::Unknown) } } } ast::ExprKind::Call(ref callee, ref args) => { let inner_span = mk_sp(callee.span.hi(), expr.span.hi()); - let callee_str = callee.rewrite(context, shape)?; - rewrite_call(context, &callee_str, args, inner_span, shape).ok() + let callee_str = callee.rewrite_result(context, shape)?; + rewrite_call(context, &callee_str, args, inner_span, shape) } - ast::ExprKind::Paren(ref subexpr) => rewrite_paren(context, subexpr, shape, expr.span).ok(), + ast::ExprKind::Paren(ref subexpr) => rewrite_paren(context, subexpr, shape, expr.span), ast::ExprKind::Binary(op, ref lhs, ref rhs) => { // FIXME: format comments between operands and operator - rewrite_all_pairs(expr, shape, context) - .or_else(|_| { - rewrite_pair( - &**lhs, - &**rhs, - PairParts::infix(&format!(" {} ", context.snippet(op.span))), - context, - shape, - context.config.binop_separator(), - ) - }) - .ok() + rewrite_all_pairs(expr, shape, context).or_else(|_| { + rewrite_pair( + &**lhs, + &**rhs, + PairParts::infix(&format!(" {} ", context.snippet(op.span))), + context, + shape, + context.config.binop_separator(), + ) + }) } - ast::ExprKind::Unary(op, ref subexpr) => rewrite_unary_op(context, op, subexpr, shape).ok(), + ast::ExprKind::Unary(op, ref subexpr) => rewrite_unary_op(context, op, subexpr, shape), ast::ExprKind::Struct(ref struct_expr) => { let ast::StructExpr { qself, @@ -131,19 +132,17 @@ pub(crate) fn format_expr( expr.span, shape, ) - .ok() } ast::ExprKind::Tup(ref items) => { - rewrite_tuple(context, items.iter(), expr.span, shape, items.len() == 1).ok() - } - ast::ExprKind::Let(ref pat, ref expr, _span, _) => { - rewrite_let(context, shape, pat, expr).ok() + rewrite_tuple(context, items.iter(), expr.span, shape, items.len() == 1) } + ast::ExprKind::Let(ref pat, ref expr, _span, _) => rewrite_let(context, shape, pat, expr), ast::ExprKind::If(..) | ast::ExprKind::ForLoop { .. } | ast::ExprKind::Loop(..) | ast::ExprKind::While(..) => to_control_flow(expr, expr_type) - .and_then(|control_flow| control_flow.rewrite(context, shape)), + .unknown_error() + .and_then(|control_flow| control_flow.rewrite_result(context, shape)), ast::ExprKind::ConstBlock(ref anon_const) => { let rewrite = match anon_const.value.kind { ast::ExprKind::Block(ref block, opt_label) => { @@ -151,24 +150,24 @@ pub(crate) fn format_expr( // not the `ast::Block` node we're about to rewrite. To prevent dropping inner // attributes call `rewrite_block` directly. // See https://github.com/rust-lang/rustfmt/issues/6158 - rewrite_block(block, Some(&expr.attrs), opt_label, context, shape).ok()? + rewrite_block(block, Some(&expr.attrs), opt_label, context, shape)? } - _ => anon_const.rewrite(context, shape)?, + _ => anon_const.rewrite_result(context, shape)?, }; - Some(format!("const {}", rewrite)) + Ok(format!("const {}", rewrite)) } ast::ExprKind::Block(ref block, opt_label) => { match expr_type { ExprType::Statement => { if is_unsafe_block(block) { - rewrite_block(block, Some(&expr.attrs), opt_label, context, shape).ok() - } else if let rw @ Some(_) = + rewrite_block(block, Some(&expr.attrs), opt_label, context, shape) + } else if let Some(rw) = rewrite_empty_block(context, block, Some(&expr.attrs), opt_label, "", shape) { // Rewrite block without trying to put it in a single line. - rw + Ok(rw) } else { - let prefix = block_prefix(context, block, shape).ok()?; + let prefix = block_prefix(context, block, shape)?; rewrite_block_with_visitor( context, @@ -179,32 +178,31 @@ pub(crate) fn format_expr( shape, true, ) - .ok() } } ExprType::SubExpression => { - rewrite_block(block, Some(&expr.attrs), opt_label, context, shape).ok() + rewrite_block(block, Some(&expr.attrs), opt_label, context, shape) } } } ast::ExprKind::Match(ref cond, ref arms, kind) => { - rewrite_match(context, cond, arms, shape, expr.span, &expr.attrs, kind).ok() + rewrite_match(context, cond, arms, shape, expr.span, &expr.attrs, kind) } ast::ExprKind::Path(ref qself, ref path) => { - rewrite_path(context, PathContext::Expr, qself, path, shape).ok() + rewrite_path(context, PathContext::Expr, qself, path, shape) } ast::ExprKind::Assign(ref lhs, ref rhs, _) => { - rewrite_assignment(context, lhs, rhs, None, shape).ok() + rewrite_assignment(context, lhs, rhs, None, shape) } ast::ExprKind::AssignOp(ref op, ref lhs, ref rhs) => { - rewrite_assignment(context, lhs, rhs, Some(op), shape).ok() + rewrite_assignment(context, lhs, rhs, Some(op), shape) } ast::ExprKind::Continue(ref opt_label) => { let id_str = match *opt_label { Some(label) => format!(" {}", label.ident), None => String::new(), }; - Some(format!("continue{id_str}")) + Ok(format!("continue{id_str}")) } ast::ExprKind::Break(ref opt_label, ref opt_expr) => { let id_str = match *opt_label { @@ -213,16 +211,16 @@ pub(crate) fn format_expr( }; if let Some(ref expr) = *opt_expr { - rewrite_unary_prefix(context, &format!("break{id_str} "), &**expr, shape).ok() + rewrite_unary_prefix(context, &format!("break{id_str} "), &**expr, shape) } else { - Some(format!("break{id_str}")) + Ok(format!("break{id_str}")) } } ast::ExprKind::Yield(ref opt_expr) => { if let Some(ref expr) = *opt_expr { - rewrite_unary_prefix(context, "yield ", &**expr, shape).ok() + rewrite_unary_prefix(context, "yield ", &**expr, shape) } else { - Some("yield".to_string()) + Ok("yield".to_string()) } } ast::ExprKind::Closure(ref cl) => closures::rewrite_closure( @@ -236,37 +234,32 @@ pub(crate) fn format_expr( expr.span, context, shape, - ) - .ok(), + ), ast::ExprKind::Try(..) | ast::ExprKind::Field(..) | ast::ExprKind::MethodCall(..) - | ast::ExprKind::Await(_, _) => rewrite_chain(expr, context, shape).ok(), + | ast::ExprKind::Await(_, _) => rewrite_chain(expr, context, shape), ast::ExprKind::MacCall(ref mac) => { - rewrite_macro(mac, None, context, shape, MacroPosition::Expression) - .or_else(|_| { - wrap_str( - context.snippet(expr.span).to_owned(), - context.config.max_width(), - shape, - ) - .max_width_error(shape.width, expr.span) - }) - .ok() + rewrite_macro(mac, None, context, shape, MacroPosition::Expression).or_else(|_| { + wrap_str( + context.snippet(expr.span).to_owned(), + context.config.max_width(), + shape, + ) + .max_width_error(shape.width, expr.span) + }) } - ast::ExprKind::Ret(None) => Some("return".to_owned()), + ast::ExprKind::Ret(None) => Ok("return".to_owned()), ast::ExprKind::Ret(Some(ref expr)) => { - rewrite_unary_prefix(context, "return ", &**expr, shape).ok() - } - ast::ExprKind::Become(ref expr) => { - rewrite_unary_prefix(context, "become ", &**expr, shape).ok() + rewrite_unary_prefix(context, "return ", &**expr, shape) } - ast::ExprKind::Yeet(None) => Some("do yeet".to_owned()), + ast::ExprKind::Become(ref expr) => rewrite_unary_prefix(context, "become ", &**expr, shape), + ast::ExprKind::Yeet(None) => Ok("do yeet".to_owned()), ast::ExprKind::Yeet(Some(ref expr)) => { - rewrite_unary_prefix(context, "do yeet ", &**expr, shape).ok() + rewrite_unary_prefix(context, "do yeet ", &**expr, shape) } ast::ExprKind::AddrOf(borrow_kind, mutability, ref expr) => { - rewrite_expr_addrof(context, borrow_kind, mutability, expr, shape).ok() + rewrite_expr_addrof(context, borrow_kind, mutability, expr, shape) } ast::ExprKind::Cast(ref expr, ref ty) => rewrite_pair( &**expr, @@ -275,10 +268,9 @@ pub(crate) fn format_expr( context, shape, SeparatorPlace::Front, - ) - .ok(), + ), ast::ExprKind::Index(ref expr, ref index, _) => { - rewrite_index(&**expr, &**index, context, shape).ok() + rewrite_index(&**expr, &**index, context, shape) } ast::ExprKind::Repeat(ref expr, ref repeats) => rewrite_pair( &**expr, @@ -287,8 +279,7 @@ pub(crate) fn format_expr( context, shape, SeparatorPlace::Back, - ) - .ok(), + ), ast::ExprKind::Range(ref lhs, ref rhs, limits) => { let delim = match limits { ast::RangeLimits::HalfOpen => "..", @@ -341,7 +332,6 @@ pub(crate) fn format_expr( shape, context.config.binop_separator(), ) - .ok() } (None, Some(rhs)) => { let sp_delim = if context.config.spaces_around_ranges() { @@ -349,7 +339,7 @@ pub(crate) fn format_expr( } else { default_sp_delim(None, Some(rhs)) }; - rewrite_unary_prefix(context, &sp_delim, &*rhs, shape).ok() + rewrite_unary_prefix(context, &sp_delim, &*rhs, shape) } (Some(lhs), None) => { let sp_delim = if context.config.spaces_around_ranges() { @@ -357,25 +347,25 @@ pub(crate) fn format_expr( } else { default_sp_delim(Some(lhs), None) }; - rewrite_unary_suffix(context, &sp_delim, &*lhs, shape).ok() + rewrite_unary_suffix(context, &sp_delim, &*lhs, shape) } - (None, None) => Some(delim.to_owned()), + (None, None) => Ok(delim.to_owned()), } } // We do not format these expressions yet, but they should still // satisfy our width restrictions. // Style Guide RFC for InlineAsm variant pending // https://github.com/rust-dev-tools/fmt-rfcs/issues/152 - ast::ExprKind::InlineAsm(..) => Some(context.snippet(expr.span).to_owned()), + ast::ExprKind::InlineAsm(..) => Ok(context.snippet(expr.span).to_owned()), ast::ExprKind::TryBlock(ref block) => { if let rw @ Ok(_) = rewrite_single_line_block(context, "try ", block, Some(&expr.attrs), None, shape) { - rw.ok() + rw } else { // 9 = `try ` let budget = shape.width.saturating_sub(9); - Some(format!( + Ok(format!( "{}{}", "try ", rewrite_block( @@ -384,8 +374,7 @@ pub(crate) fn format_expr( None, context, Shape::legacy(budget, shape.indent) - ) - .ok()? + )? )) } } @@ -403,11 +392,11 @@ pub(crate) fn format_expr( None, shape, ) { - rw.ok() + rw } else { // 6 = `async ` let budget = shape.width.saturating_sub(6); - Some(format!( + Ok(format!( "{kind} {mover}{}", rewrite_block( block, @@ -415,12 +404,11 @@ pub(crate) fn format_expr( None, context, Shape::legacy(budget, shape.indent) - ) - .ok()? + )? )) } } - ast::ExprKind::Underscore => Some("_".to_owned()), + ast::ExprKind::Underscore => Ok("_".to_owned()), ast::ExprKind::FormatArgs(..) | ast::ExprKind::Type(..) | ast::ExprKind::IncludedBytes(..) @@ -429,22 +417,21 @@ pub(crate) fn format_expr( // rustfmt tries to parse macro arguments when formatting macros, so it's not totally // impossible for rustfmt to come across one of these nodes when formatting a file. // Also, rustfmt might get passed the output from `-Zunpretty=expanded`. - None + Err(RewriteError::Unknown) } - ast::ExprKind::Err(_) | ast::ExprKind::Dummy => None, + ast::ExprKind::Err(_) | ast::ExprKind::Dummy => Err(RewriteError::Unknown), }; expr_rw .map(|expr_str| recover_comment_removed(expr_str, expr.span, context)) .and_then(|expr_str| { let attrs = outer_attributes(&expr.attrs); - let attrs_str = attrs.rewrite(context, shape)?; + let attrs_str = attrs.rewrite_result(context, shape)?; let span = mk_sp( attrs.last().map_or(expr.span.lo(), |attr| attr.span.hi()), expr.span.lo(), ); combine_strs_with_missing_comments(context, &attrs_str, &expr_str, span, shape, false) - .ok() }) } @@ -1184,7 +1171,6 @@ impl<'a> Rewrite for ControlFlow<'a> { ..shape }; format_expr(else_block, ExprType::Statement, context, else_shape) - .unknown_error() } }; diff --git a/src/matches.rs b/src/matches.rs index 8de92eb55383e..ee631fa1b4706 100644 --- a/src/matches.rs +++ b/src/matches.rs @@ -516,7 +516,7 @@ fn rewrite_match_body( .offset_left(extra_offset(pats_str, shape) + 4) .and_then(|shape| shape.sub_width(comma.len())); let orig_body = if forbid_same_line || !arrow_comment.is_empty() { - None + Err(RewriteError::Unknown) } else if let Some(body_shape) = orig_body_shape { let rewrite = nop_block_collapse( format_expr(body, ExprType::Statement, context, body_shape), @@ -524,7 +524,7 @@ fn rewrite_match_body( ); match rewrite { - Some(ref body_str) + Ok(ref body_str) if is_block || (!body_str.contains('\n') && unicode_str_width(body_str) <= body_shape.width) => @@ -534,7 +534,7 @@ fn rewrite_match_body( _ => rewrite, } } else { - None + Err(RewriteError::Unknown) }; let orig_budget = orig_body_shape.map_or(0, |shape| shape.width); @@ -545,20 +545,23 @@ fn rewrite_match_body( next_line_body_shape.width, ); match (orig_body, next_line_body) { - (Some(ref orig_str), Some(ref next_line_str)) + (Ok(ref orig_str), Ok(ref next_line_str)) if prefer_next_line(orig_str, next_line_str, RhsTactics::Default) => { combine_next_line_body(next_line_str) } - (Some(ref orig_str), _) if extend && first_line_width(orig_str) <= orig_budget => { + (Ok(ref orig_str), _) if extend && first_line_width(orig_str) <= orig_budget => { combine_orig_body(orig_str) } - (Some(ref orig_str), Some(ref next_line_str)) if orig_str.contains('\n') => { + (Ok(ref orig_str), Ok(ref next_line_str)) if orig_str.contains('\n') => { combine_next_line_body(next_line_str) } - (None, Some(ref next_line_str)) => combine_next_line_body(next_line_str), - (None, None) => Err(RewriteError::Unknown), - (Some(ref orig_str), _) => combine_orig_body(orig_str), + (Err(_), Ok(ref next_line_str)) => combine_next_line_body(next_line_str), + // When both orig_body and next_line_body result in errors, we currently propagate the + // error from the second attempt since it is more generous with width constraints. + // This decision is somewhat arbitrary and is open to change. + (Err(_), Err(next_line_err)) => Err(next_line_err), + (Ok(ref orig_str), _) => combine_orig_body(orig_str), } } @@ -605,7 +608,7 @@ fn rewrite_guard( } } -fn nop_block_collapse(block_str: Option, budget: usize) -> Option { +fn nop_block_collapse(block_str: RewriteResult, budget: usize) -> RewriteResult { debug!("nop_block_collapse {:?} {}", block_str, budget); block_str.map(|block_str| { if block_str.starts_with('{') diff --git a/src/stmt.rs b/src/stmt.rs index 426bf89fc1622..2788159018d0d 100644 --- a/src/stmt.rs +++ b/src/stmt.rs @@ -135,9 +135,7 @@ fn format_stmt( let shape = shape .sub_width(suffix.len()) .max_width_error(shape.width, ex.span())?; - format_expr(ex, expr_type, context, shape) - .map(|s| s + suffix) - .unknown_error() + format_expr(ex, expr_type, context, shape).map(|s| s + suffix) } ast::StmtKind::MacCall(..) | ast::StmtKind::Item(..) | ast::StmtKind::Empty => { Err(RewriteError::Unknown) diff --git a/src/types.rs b/src/types.rs index 5477942f82e72..1aa3f60f86880 100644 --- a/src/types.rs +++ b/src/types.rs @@ -584,6 +584,10 @@ fn rewrite_bounded_lifetime( impl Rewrite for ast::AnonConst { fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option { + self.rewrite_result(context, shape).ok() + } + + fn rewrite_result(&self, context: &RewriteContext<'_>, shape: Shape) -> RewriteResult { format_expr(&self.value, ExprType::SubExpression, context, shape) } } diff --git a/src/utils.rs b/src/utils.rs index be21e89f760e9..d1cfc6acc49bc 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -367,14 +367,6 @@ macro_rules! out_of_file_lines_range { }; } -macro_rules! skip_out_of_file_lines_range { - ($self:ident, $span:expr) => { - if out_of_file_lines_range!($self, $span) { - return None; - } - }; -} - macro_rules! skip_out_of_file_lines_range_err { ($self:ident, $span:expr) => { if out_of_file_lines_range!($self, $span) { From b41f6ab525dbab21a73de3dc844b87a98b36190b Mon Sep 17 00:00:00 2001 From: coekjan Date: Thu, 5 Sep 2024 13:50:44 +0800 Subject: [PATCH 0511/2194] fix: Fix `inline_const_as_literal` error when the number >= 10 --- src/tools/rust-analyzer/crates/hir/src/lib.rs | 11 +++++++++++ .../src/handlers/inline_const_as_literal.rs | 7 +++---- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/src/tools/rust-analyzer/crates/hir/src/lib.rs b/src/tools/rust-analyzer/crates/hir/src/lib.rs index 81d6466c2f31d..410e05fb1d1eb 100644 --- a/src/tools/rust-analyzer/crates/hir/src/lib.rs +++ b/src/tools/rust-analyzer/crates/hir/src/lib.rs @@ -2553,6 +2553,17 @@ impl Const { Type::from_value_def(db, self.id) } + /// Evaluate the constant and return the result as a string. + /// + /// This function is intended for IDE assistance, different from [`Const::render_eval`]. + pub fn eval(self, db: &dyn HirDatabase, edition: Edition) -> Result { + let c = db.const_eval(self.id.into(), Substitution::empty(Interner), None)?; + Ok(format!("{}", c.display(db, edition))) + } + + /// Evaluate the constant and return the result as a string, with more detailed information. + /// + /// This function is intended for user-facing display. pub fn render_eval( self, db: &dyn HirDatabase, diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/inline_const_as_literal.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/inline_const_as_literal.rs index f1c2acdd3ed91..6b504a918b403 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/inline_const_as_literal.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/inline_const_as_literal.rs @@ -53,10 +53,7 @@ pub(crate) fn inline_const_as_literal(acc: &mut Assists, ctx: &AssistContext<'_> | ast::Expr::BinExpr(_) | ast::Expr::CallExpr(_) => { let edition = ctx.sema.scope(variable.syntax())?.krate().edition(ctx.db()); - match konst.render_eval(ctx.sema.db, edition) { - Ok(result) => result, - Err(_) => return None, - } + konst.eval(ctx.sema.db, edition).ok()? } _ => return None, }; @@ -127,12 +124,14 @@ mod tests { ("u64", "0", NUMBER), ("u128", "0", NUMBER), ("usize", "0", NUMBER), + ("usize", "16", NUMBER), ("i8", "0", NUMBER), ("i16", "0", NUMBER), ("i32", "0", NUMBER), ("i64", "0", NUMBER), ("i128", "0", NUMBER), ("isize", "0", NUMBER), + ("isize", "16", NUMBER), ("bool", "false", BOOL), ("&str", "\"str\"", STR), ("char", "'c'", CHAR), From 1a893ac648e03732aaa8b5371b602ab683970b0d Mon Sep 17 00:00:00 2001 From: lcnr Date: Fri, 1 Mar 2024 12:33:42 +0100 Subject: [PATCH 0512/2194] stabilize `-Znext-solver=coherence` --- compiler/rustc_interface/src/tests.rs | 2 +- compiler/rustc_middle/src/ty/context.rs | 4 +- compiler/rustc_session/src/config.rs | 5 ++ compiler/rustc_session/src/options.rs | 31 +++---- .../src/traits/engine.rs | 4 +- .../associated-types-coherence-failure.stderr | 8 +- .../opaque_type_candidate_selection.rs | 30 ------- ...e-negative-outlives-lifetimes.stock.stderr | 2 + ...s-lifetimes.with_negative_coherence.stderr | 2 + ...overlap-negate-not-use-feature-gate.stderr | 2 + ...unnormalizable-projection-0.classic.stderr | 1 - ...unnormalizable-projection-1.classic.stderr | 2 +- ...oherence-check-placeholder-outlives.stderr | 2 + ...oherence-considering-regions.any_lt.stderr | 2 + ...constraints-on-unification.explicit.stderr | 1 + .../normalize-for-errors.current.stderr | 5 +- tests/ui/coherence/normalize-for-errors.rs | 6 +- .../ui/coherence/normalize-for-errors.stderr | 15 ++++ .../occurs-check/associated-type.old.stderr | 8 +- .../occurs-check/opaques.current.stderr | 12 +++ .../occurs-check/opaques.next.stderr | 4 +- tests/ui/coherence/occurs-check/opaques.rs | 7 +- ...reporting-if-references-err.current.stderr | 17 +--- .../skip-reporting-if-references-err.rs | 6 -- .../skip-reporting-if-references-err.stderr | 14 ++++ .../super-trait-knowable-1.current.stderr | 13 --- .../super-traits/super-trait-knowable-1.rs | 6 +- .../super-trait-knowable-3.current.stderr | 13 --- .../super-traits/super-trait-knowable-3.rs | 6 +- .../unevaluated-const-ice-119731.rs | 1 + .../unevaluated-const-ice-119731.stderr | 23 +++-- ...nown-alias-defkind-anonconst-ice-116710.rs | 1 - ...-alias-defkind-anonconst-ice-116710.stderr | 14 +--- tests/ui/error-codes/e0119/issue-23563.stderr | 2 +- ...eature-gate-with_negative_coherence.stderr | 2 + .../structually-relate-aliases.rs | 3 +- .../structually-relate-aliases.stderr | 33 +++----- .../auto-trait-coherence.old.stderr | 4 +- tests/ui/impl-trait/auto-trait-coherence.rs | 6 +- .../ui/impl-trait/auto-trait-coherence.stderr | 12 +++ .../impl-trait/coherence-treats-tait-ambig.rs | 2 +- .../coherence-treats-tait-ambig.stderr | 2 +- tests/ui/impl-trait/negative-reasoning.rs | 2 +- tests/ui/impl-trait/negative-reasoning.stderr | 6 +- tests/ui/impl-unused-tps.rs | 46 +++++----- tests/ui/impl-unused-tps.stderr | 84 ++++++++++++------- tests/ui/issues/issue-48728.rs | 8 +- .../defaultimpl/specialization-no-default.rs | 3 +- ...efault-items-drop-coherence.current.stderr | 12 +++ ...n-default-items-drop-coherence.next.stderr | 2 +- ...ialization-default-items-drop-coherence.rs | 8 +- ...lization-overlap-projection.current.stderr | 22 ++++- ...cialization-overlap-projection.next.stderr | 6 +- .../specialization-overlap-projection.rs | 13 +-- .../specialization-overlap-projection.stderr | 30 +++++++ tests/ui/traits/alias/issue-83613.rs | 2 +- tests/ui/traits/alias/issue-83613.stderr | 4 +- tests/ui/traits/issue-105231.rs | 3 +- tests/ui/traits/issue-105231.stderr | 22 ++--- .../cycle-via-builtin-auto-trait-impl.rs | 2 +- .../cycle-via-builtin-auto-trait-impl.stderr | 26 ++---- .../impl_trait_for_same_tait.stderr | 2 - .../ui/type-alias-impl-trait/issue-104817.rs | 2 +- .../issue-104817.stock.stderr | 4 +- 64 files changed, 326 insertions(+), 318 deletions(-) delete mode 100644 tests/ui/auto-traits/opaque_type_candidate_selection.rs create mode 100644 tests/ui/coherence/normalize-for-errors.stderr create mode 100644 tests/ui/coherence/occurs-check/opaques.current.stderr create mode 100644 tests/ui/coherence/skip-reporting-if-references-err.stderr delete mode 100644 tests/ui/coherence/super-traits/super-trait-knowable-1.current.stderr delete mode 100644 tests/ui/coherence/super-traits/super-trait-knowable-3.current.stderr create mode 100644 tests/ui/impl-trait/auto-trait-coherence.stderr create mode 100644 tests/ui/specialization/specialization-default-items-drop-coherence.current.stderr create mode 100644 tests/ui/specialization/specialization-overlap-projection.stderr diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs index 42fed98df0101..50422df8ee648 100644 --- a/compiler/rustc_interface/src/tests.rs +++ b/compiler/rustc_interface/src/tests.rs @@ -808,7 +808,7 @@ fn test_unstable_options_tracking_hash() { tracked!(mir_opt_level, Some(4)); tracked!(move_size_limit, Some(4096)); tracked!(mutable_noalias, false); - tracked!(next_solver, Some(NextSolverConfig { coherence: true, globally: false })); + tracked!(next_solver, NextSolverConfig { coherence: true, globally: true }); tracked!(no_generate_arange_section, true); tracked!(no_jump_tables, true); tracked!(no_link, true); diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 20828067c469c..599c16f318321 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -3128,11 +3128,11 @@ impl<'tcx> TyCtxt<'tcx> { } pub fn next_trait_solver_globally(self) -> bool { - self.sess.opts.unstable_opts.next_solver.map_or(false, |c| c.globally) + self.sess.opts.unstable_opts.next_solver.globally } pub fn next_trait_solver_in_coherence(self) -> bool { - self.sess.opts.unstable_opts.next_solver.map_or(false, |c| c.coherence) + self.sess.opts.unstable_opts.next_solver.coherence } pub fn is_impl_trait_in_trait(self, def_id: DefId) -> bool { diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index 908d50a041ef1..f3e3b36111c54 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -842,6 +842,11 @@ pub struct NextSolverConfig { /// This is only `true` if `coherence` is also enabled. pub globally: bool, } +impl Default for NextSolverConfig { + fn default() -> Self { + NextSolverConfig { coherence: true, globally: false } + } +} #[derive(Clone)] pub enum Input { diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index 45339c23ea3ef..a57dc80b3168d 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -403,7 +403,7 @@ mod desc { pub(crate) const parse_unpretty: &str = "`string` or `string=string`"; pub(crate) const parse_treat_err_as_bug: &str = "either no value or a non-negative number"; pub(crate) const parse_next_solver_config: &str = - "a comma separated list of solver configurations: `globally` (default), and `coherence`"; + "either `globally` (when used without an argument), `coherence` (default) or `no`"; pub(crate) const parse_lto: &str = "either a boolean (`yes`, `no`, `on`, `off`, etc), `thin`, `fat`, or omitted"; pub(crate) const parse_linker_plugin_lto: &str = @@ -1105,27 +1105,16 @@ mod parse { } } - pub(crate) fn parse_next_solver_config( - slot: &mut Option, - v: Option<&str>, - ) -> bool { + pub(crate) fn parse_next_solver_config(slot: &mut NextSolverConfig, v: Option<&str>) -> bool { if let Some(config) = v { - let mut coherence = false; - let mut globally = true; - for c in config.split(',') { - match c { - "globally" => globally = true, - "coherence" => { - globally = false; - coherence = true; - } - _ => return false, - } - } - - *slot = Some(NextSolverConfig { coherence: coherence || globally, globally }); + *slot = match config { + "no" => NextSolverConfig { coherence: false, globally: false }, + "coherence" => NextSolverConfig { coherence: true, globally: false }, + "globally" => NextSolverConfig { coherence: true, globally: true }, + _ => return false, + }; } else { - *slot = Some(NextSolverConfig { coherence: true, globally: true }); + *slot = NextSolverConfig { coherence: true, globally: true }; } true @@ -1878,7 +1867,7 @@ options! { "the size at which the `large_assignments` lint starts to be emitted"), mutable_noalias: bool = (true, parse_bool, [TRACKED], "emit noalias metadata for mutable references (default: yes)"), - next_solver: Option = (None, parse_next_solver_config, [TRACKED], + next_solver: NextSolverConfig = (NextSolverConfig::default(), parse_next_solver_config, [TRACKED], "enable and configure the next generation trait solver used by rustc"), nll_facts: bool = (false, parse_bool, [UNTRACKED], "dump facts from NLL analysis into side files (default: no)"), diff --git a/compiler/rustc_trait_selection/src/traits/engine.rs b/compiler/rustc_trait_selection/src/traits/engine.rs index de1d4ef15aced..c8811bc37b310 100644 --- a/compiler/rustc_trait_selection/src/traits/engine.rs +++ b/compiler/rustc_trait_selection/src/traits/engine.rs @@ -35,10 +35,8 @@ where if infcx.next_trait_solver() { Box::new(NextFulfillmentCtxt::new(infcx)) } else { - let new_solver_globally = - infcx.tcx.sess.opts.unstable_opts.next_solver.map_or(false, |c| c.globally); assert!( - !new_solver_globally, + !infcx.tcx.next_trait_solver_globally(), "using old solver even though new solver is enabled globally" ); Box::new(FulfillmentContext::new(infcx)) diff --git a/tests/ui/associated-types/associated-types-coherence-failure.stderr b/tests/ui/associated-types/associated-types-coherence-failure.stderr index 211613b371492..25c22e5f82ac2 100644 --- a/tests/ui/associated-types/associated-types-coherence-failure.stderr +++ b/tests/ui/associated-types/associated-types-coherence-failure.stderr @@ -1,20 +1,20 @@ -error[E0119]: conflicting implementations of trait `IntoCow<'_, _>` for type `Cow<'_, _>` +error[E0119]: conflicting implementations of trait `IntoCow<'_, _>` for type `<_ as ToOwned>::Owned` --> $DIR/associated-types-coherence-failure.rs:21:1 | LL | impl<'a, B: ?Sized> IntoCow<'a, B> for ::Owned where B: ToOwned { | ----------------------------------------------------------------------------- first implementation here ... LL | impl<'a, B: ?Sized> IntoCow<'a, B> for Cow<'a, B> where B: ToOwned { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `Cow<'_, _>` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `<_ as ToOwned>::Owned` -error[E0119]: conflicting implementations of trait `IntoCow<'_, _>` for type `&_` +error[E0119]: conflicting implementations of trait `IntoCow<'_, _>` for type `<_ as ToOwned>::Owned` --> $DIR/associated-types-coherence-failure.rs:28:1 | LL | impl<'a, B: ?Sized> IntoCow<'a, B> for ::Owned where B: ToOwned { | ----------------------------------------------------------------------------- first implementation here ... LL | impl<'a, B: ?Sized> IntoCow<'a, B> for &'a B where B: ToOwned { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `&_` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `<_ as ToOwned>::Owned` error: aborting due to 2 previous errors diff --git a/tests/ui/auto-traits/opaque_type_candidate_selection.rs b/tests/ui/auto-traits/opaque_type_candidate_selection.rs deleted file mode 100644 index d6973b76a6e1e..0000000000000 --- a/tests/ui/auto-traits/opaque_type_candidate_selection.rs +++ /dev/null @@ -1,30 +0,0 @@ -//! used to ICE: #119272 - -//@ check-pass - -#![feature(type_alias_impl_trait)] -mod defining_scope { - use super::*; - pub type Alias = impl Sized; - - pub fn cast(x: Container, T>) -> Container { - x - } -} - -struct Container, U> { - x: >::Assoc, -} - -trait Trait { - type Assoc; -} - -impl Trait for T { - type Assoc = Box; -} -impl Trait for defining_scope::Alias { - type Assoc = usize; -} - -fn main() {} diff --git a/tests/ui/coherence/coherence-negative-outlives-lifetimes.stock.stderr b/tests/ui/coherence/coherence-negative-outlives-lifetimes.stock.stderr index dbb22d8937d54..1d28bb46812cf 100644 --- a/tests/ui/coherence/coherence-negative-outlives-lifetimes.stock.stderr +++ b/tests/ui/coherence/coherence-negative-outlives-lifetimes.stock.stderr @@ -5,6 +5,8 @@ LL | impl<'a, T: MyPredicate<'a>> MyTrait<'a> for T {} | ---------------------------------------------- first implementation here LL | impl<'a, T> MyTrait<'a> for &'a T {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `&_` + | + = note: downstream crates may implement trait `MyPredicate<'_>` for type `&_` error: aborting due to 1 previous error diff --git a/tests/ui/coherence/coherence-negative-outlives-lifetimes.with_negative_coherence.stderr b/tests/ui/coherence/coherence-negative-outlives-lifetimes.with_negative_coherence.stderr index dbb22d8937d54..1d28bb46812cf 100644 --- a/tests/ui/coherence/coherence-negative-outlives-lifetimes.with_negative_coherence.stderr +++ b/tests/ui/coherence/coherence-negative-outlives-lifetimes.with_negative_coherence.stderr @@ -5,6 +5,8 @@ LL | impl<'a, T: MyPredicate<'a>> MyTrait<'a> for T {} | ---------------------------------------------- first implementation here LL | impl<'a, T> MyTrait<'a> for &'a T {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `&_` + | + = note: downstream crates may implement trait `MyPredicate<'_>` for type `&_` error: aborting due to 1 previous error diff --git a/tests/ui/coherence/coherence-overlap-negate-not-use-feature-gate.stderr b/tests/ui/coherence/coherence-overlap-negate-not-use-feature-gate.stderr index 21c82eedd5df5..c5bb695eb1882 100644 --- a/tests/ui/coherence/coherence-overlap-negate-not-use-feature-gate.stderr +++ b/tests/ui/coherence/coherence-overlap-negate-not-use-feature-gate.stderr @@ -5,6 +5,8 @@ LL | impl Foo for T {} | --------------------------- first implementation here LL | impl Foo for &U {} | ^^^^^^^^^^^^^^^^^^ conflicting implementation for `&_` + | + = note: downstream crates may implement trait `std::ops::DerefMut` for type `&_` error: aborting due to 1 previous error diff --git a/tests/ui/coherence/coherence-overlap-unnormalizable-projection-0.classic.stderr b/tests/ui/coherence/coherence-overlap-unnormalizable-projection-0.classic.stderr index 2ffb6000ec822..99abdf65abd5f 100644 --- a/tests/ui/coherence/coherence-overlap-unnormalizable-projection-0.classic.stderr +++ b/tests/ui/coherence/coherence-overlap-unnormalizable-projection-0.classic.stderr @@ -12,7 +12,6 @@ LL | impl Trait for Box {} | ^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `Box<_>` | = note: downstream crates may implement trait `WithAssoc<'a>` for type `std::boxed::Box<_>` - = note: downstream crates may implement trait `WhereBound` for type ` as WithAssoc<'a>>::Assoc` error: aborting due to 1 previous error diff --git a/tests/ui/coherence/coherence-overlap-unnormalizable-projection-1.classic.stderr b/tests/ui/coherence/coherence-overlap-unnormalizable-projection-1.classic.stderr index 49b236f9d2aa2..781ab0fcbf766 100644 --- a/tests/ui/coherence/coherence-overlap-unnormalizable-projection-1.classic.stderr +++ b/tests/ui/coherence/coherence-overlap-unnormalizable-projection-1.classic.stderr @@ -12,7 +12,7 @@ LL | impl Trait for Box {} | ^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `Box<_>` | = note: downstream crates may implement trait `WithAssoc<'a>` for type `std::boxed::Box<_>` - = note: downstream crates may implement trait `WhereBound` for type `std::boxed::Box< as WithAssoc<'a>>::Assoc>` + = note: downstream crates may implement trait `WhereBound` for type `std::boxed::Box<_>` error: aborting due to 1 previous error diff --git a/tests/ui/coherence/negative-coherence-check-placeholder-outlives.stderr b/tests/ui/coherence/negative-coherence-check-placeholder-outlives.stderr index f515c39ea8d10..bf1ffcb5f0008 100644 --- a/tests/ui/coherence/negative-coherence-check-placeholder-outlives.stderr +++ b/tests/ui/coherence/negative-coherence-check-placeholder-outlives.stderr @@ -5,6 +5,8 @@ LL | impl Bar for T where T: Foo {} | ------------------------------ first implementation here LL | impl Bar for Box {} | ^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `Box<_>` + | + = note: downstream crates may implement trait `Foo` for type `std::boxed::Box<_>` error: aborting due to 1 previous error diff --git a/tests/ui/coherence/negative-coherence-considering-regions.any_lt.stderr b/tests/ui/coherence/negative-coherence-considering-regions.any_lt.stderr index f24de10f6ac48..97e2e9759c174 100644 --- a/tests/ui/coherence/negative-coherence-considering-regions.any_lt.stderr +++ b/tests/ui/coherence/negative-coherence-considering-regions.any_lt.stderr @@ -6,6 +6,8 @@ LL | impl Bar for T where T: Foo {} ... LL | impl Bar for &T {} | ^^^^^^^^^^^^^^^^^^ conflicting implementation for `&_` + | + = note: downstream crates may implement trait `Foo` for type `&_` error: aborting due to 1 previous error diff --git a/tests/ui/coherence/negative-coherence-placeholder-region-constraints-on-unification.explicit.stderr b/tests/ui/coherence/negative-coherence-placeholder-region-constraints-on-unification.explicit.stderr index 832c56a45549b..8d59cbc3466ba 100644 --- a/tests/ui/coherence/negative-coherence-placeholder-region-constraints-on-unification.explicit.stderr +++ b/tests/ui/coherence/negative-coherence-placeholder-region-constraints-on-unification.explicit.stderr @@ -8,6 +8,7 @@ LL | impl FnMarker for fn(&T) {} | = warning: the behavior may change in a future release = note: for more information, see issue #56105 + = note: downstream crates may implement trait `Marker` for type `&_` = note: this behavior recently changed as a result of a bug fix; see rust-lang/rust#56105 for details note: the lint level is defined here --> $DIR/negative-coherence-placeholder-region-constraints-on-unification.rs:4:11 diff --git a/tests/ui/coherence/normalize-for-errors.current.stderr b/tests/ui/coherence/normalize-for-errors.current.stderr index dcbb73bd1ff10..634a10b7a14c3 100644 --- a/tests/ui/coherence/normalize-for-errors.current.stderr +++ b/tests/ui/coherence/normalize-for-errors.current.stderr @@ -1,12 +1,13 @@ -error[E0119]: conflicting implementations of trait `MyTrait<_>` for type `(Box<(MyType,)>, _)` +error[E0119]: conflicting implementations of trait `MyTrait<_>` for type `(Box<(MyType,)>, <_ as Iterator>::Item)` --> $DIR/normalize-for-errors.rs:17:1 | LL | impl MyTrait for (T, S::Item) {} | ------------------------------------------------------ first implementation here LL | LL | impl MyTrait for (Box<<(MyType,) as Mirror>::Assoc>, S::Item) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(Box<(MyType,)>, _)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(Box<(MyType,)>, <_ as Iterator>::Item)` | + = note: upstream crates may add a new impl of trait `std::clone::Clone` for type `(MyType,)` in future versions = note: upstream crates may add a new impl of trait `std::marker::Copy` for type `std::boxed::Box<(MyType,)>` in future versions error: aborting due to 1 previous error diff --git a/tests/ui/coherence/normalize-for-errors.rs b/tests/ui/coherence/normalize-for-errors.rs index c17bb766b5bcd..3ef91eb0386c0 100644 --- a/tests/ui/coherence/normalize-for-errors.rs +++ b/tests/ui/coherence/normalize-for-errors.rs @@ -1,7 +1,3 @@ -//@ revisions: current next -//@ ignore-compare-mode-next-solver (explicit revisions) -//@[next] compile-flags: -Znext-solver - struct MyType; trait MyTrait {} @@ -18,6 +14,6 @@ impl MyTrait for (Box<<(MyType,) as Mirror>::Assoc>, S::Item) {} //~^ ERROR conflicting implementations of trait `MyTrait<_>` for type `(Box<(MyType,)>, //~| NOTE conflicting implementation for `(Box<(MyType,)>, //~| NOTE upstream crates may add a new impl of trait `std::marker::Copy` for type `std::boxed::Box<(MyType,)>` in future versions -//[next]~| NOTE upstream crates may add a new impl of trait `std::clone::Clone` for type `std::boxed::Box<(MyType,)>` in future versions +//~| NOTE upstream crates may add a new impl of trait `std::clone::Clone` for type `std::boxed::Box<(MyType,)>` in future versions fn main() {} diff --git a/tests/ui/coherence/normalize-for-errors.stderr b/tests/ui/coherence/normalize-for-errors.stderr new file mode 100644 index 0000000000000..6fbcf5b0e1aca --- /dev/null +++ b/tests/ui/coherence/normalize-for-errors.stderr @@ -0,0 +1,15 @@ +error[E0119]: conflicting implementations of trait `MyTrait<_>` for type `(Box<(MyType,)>, <_ as Iterator>::Item)` + --> $DIR/normalize-for-errors.rs:13:1 + | +LL | impl MyTrait for (T, S::Item) {} + | ------------------------------------------------------ first implementation here +LL | +LL | impl MyTrait for (Box<<(MyType,) as Mirror>::Assoc>, S::Item) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(Box<(MyType,)>, <_ as Iterator>::Item)` + | + = note: upstream crates may add a new impl of trait `std::clone::Clone` for type `std::boxed::Box<(MyType,)>` in future versions + = note: upstream crates may add a new impl of trait `std::marker::Copy` for type `std::boxed::Box<(MyType,)>` in future versions + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/coherence/occurs-check/associated-type.old.stderr b/tests/ui/coherence/occurs-check/associated-type.old.stderr index ccc7f30fa6fdb..6a4c6fe54a831 100644 --- a/tests/ui/coherence/occurs-check/associated-type.old.stderr +++ b/tests/ui/coherence/occurs-check/associated-type.old.stderr @@ -1,12 +1,8 @@ WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [*const ?1t, '^0.Named(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), "'a")], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit), .. } - WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [*const ?1t, !2_0.Named(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), "'a")], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit), .. } WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [*const ?1t, '^0.Named(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), "'a")], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit), .. } - WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [*const ?1t, !2_0.Named(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), "'a")], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit), .. } WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [*const ?1t, '^0.Named(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), "'a")], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit), .. } - WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [*const ?1t, !2_0.Named(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), "'a")], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit), .. } WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [*const ?1t, '^0.Named(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), "'a")], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit), .. } - WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [*const ?1t, !2_0.Named(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), "'a")], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit), .. } -error[E0119]: conflicting implementations of trait `Overlap fn(&'a (), _)>` for type `for<'a> fn(&'a (), _)` +error[E0119]: conflicting implementations of trait `Overlap fn(&'a (), ())>` for type `for<'a> fn(&'a (), ())` --> $DIR/associated-type.rs:31:1 | LL | impl Overlap for T { @@ -16,7 +12,7 @@ LL | / impl Overlap fn(&'a (), Assoc<'a, T>)> for T LL | | LL | | where LL | | for<'a> *const T: ToUnit<'a>, - | |_________________________________^ conflicting implementation for `for<'a> fn(&'a (), _)` + | |_________________________________^ conflicting implementation for `for<'a> fn(&'a (), ())` | = note: this behavior recently changed as a result of a bug fix; see rust-lang/rust#56105 for details diff --git a/tests/ui/coherence/occurs-check/opaques.current.stderr b/tests/ui/coherence/occurs-check/opaques.current.stderr new file mode 100644 index 0000000000000..96ef7cd4322b5 --- /dev/null +++ b/tests/ui/coherence/occurs-check/opaques.current.stderr @@ -0,0 +1,12 @@ +error[E0119]: conflicting implementations of trait `Trait<_>` + --> $DIR/opaques.rs:27:1 + | +LL | impl Trait for T { + | ---------------------- first implementation here +... +LL | impl Trait for defining_scope::Alias { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/coherence/occurs-check/opaques.next.stderr b/tests/ui/coherence/occurs-check/opaques.next.stderr index 11d1edcca2f91..5b8eb822d2585 100644 --- a/tests/ui/coherence/occurs-check/opaques.next.stderr +++ b/tests/ui/coherence/occurs-check/opaques.next.stderr @@ -1,5 +1,5 @@ error[E0119]: conflicting implementations of trait `Trait<_>` - --> $DIR/opaques.rs:30:1 + --> $DIR/opaques.rs:27:1 | LL | impl Trait for T { | ---------------------- first implementation here @@ -8,7 +8,7 @@ LL | impl Trait for defining_scope::Alias { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation error[E0282]: type annotations needed - --> $DIR/opaques.rs:13:20 + --> $DIR/opaques.rs:10:20 | LL | pub fn cast(x: Container, T>) -> Container { | ^ cannot infer type diff --git a/tests/ui/coherence/occurs-check/opaques.rs b/tests/ui/coherence/occurs-check/opaques.rs index 241a247c84130..d7032dd53d977 100644 --- a/tests/ui/coherence/occurs-check/opaques.rs +++ b/tests/ui/coherence/occurs-check/opaques.rs @@ -1,10 +1,7 @@ -//@revisions: old next +//@revisions: current next //@[next] compile-flags: -Znext-solver // A regression test for #105787 - -//@[old] known-bug: #105787 -//@[old] check-pass #![feature(type_alias_impl_trait)] mod defining_scope { use super::*; @@ -28,7 +25,7 @@ impl Trait for T { type Assoc = Box; } impl Trait for defining_scope::Alias { - //[next]~^ ERROR conflicting implementations of trait + //~^ ERROR conflicting implementations of trait type Assoc = usize; } diff --git a/tests/ui/coherence/skip-reporting-if-references-err.current.stderr b/tests/ui/coherence/skip-reporting-if-references-err.current.stderr index 5eef3256b2c36..5de4cf626e481 100644 --- a/tests/ui/coherence/skip-reporting-if-references-err.current.stderr +++ b/tests/ui/coherence/skip-reporting-if-references-err.current.stderr @@ -9,19 +9,6 @@ help: indicate the anonymous lifetime LL | impl ToUnit<'_> for T {} | ++++ -error[E0277]: the trait bound `for<'a> (): ToUnit<'a>` is not satisfied - --> $DIR/skip-reporting-if-references-err.rs:15:29 - | -LL | impl Overlap for for<'a> fn(<() as ToUnit<'a>>::Unit) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `for<'a> ToUnit<'a>` is not implemented for `()` - -error[E0277]: the trait bound `for<'a> (): ToUnit<'a>` is not satisfied - --> $DIR/skip-reporting-if-references-err.rs:15:18 - | -LL | impl Overlap for for<'a> fn(<() as ToUnit<'a>>::Unit) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `for<'a> ToUnit<'a>` is not implemented for `()` - -error: aborting due to 3 previous errors +error: aborting due to 1 previous error -Some errors have detailed explanations: E0277, E0726. -For more information about an error, try `rustc --explain E0277`. +For more information about this error, try `rustc --explain E0726`. diff --git a/tests/ui/coherence/skip-reporting-if-references-err.rs b/tests/ui/coherence/skip-reporting-if-references-err.rs index f9eaa498232da..dd8a71c4700f4 100644 --- a/tests/ui/coherence/skip-reporting-if-references-err.rs +++ b/tests/ui/coherence/skip-reporting-if-references-err.rs @@ -1,8 +1,4 @@ // Regression test for #121006. -//@ revisions: current next -//@ ignore-compare-mode-next-solver (explicit revisions) -//@[next] compile-flags: -Znext-solver - trait ToUnit<'a> { type Unit; } @@ -13,7 +9,5 @@ impl ToUnit for T {} trait Overlap {} impl Overlap for fn(U) {} impl Overlap for for<'a> fn(<() as ToUnit<'a>>::Unit) {} -//[current]~^ ERROR the trait bound `for<'a> (): ToUnit<'a>` is not satisfied -//[current]~| ERROR the trait bound `for<'a> (): ToUnit<'a>` is not satisfied fn main() {} diff --git a/tests/ui/coherence/skip-reporting-if-references-err.stderr b/tests/ui/coherence/skip-reporting-if-references-err.stderr new file mode 100644 index 0000000000000..0ff3e88a0af92 --- /dev/null +++ b/tests/ui/coherence/skip-reporting-if-references-err.stderr @@ -0,0 +1,14 @@ +error[E0726]: implicit elided lifetime not allowed here + --> $DIR/skip-reporting-if-references-err.rs:6:9 + | +LL | impl ToUnit for T {} + | ^^^^^^ expected lifetime parameter + | +help: indicate the anonymous lifetime + | +LL | impl ToUnit<'_> for T {} + | ++++ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0726`. diff --git a/tests/ui/coherence/super-traits/super-trait-knowable-1.current.stderr b/tests/ui/coherence/super-traits/super-trait-knowable-1.current.stderr deleted file mode 100644 index fb01cf158d980..0000000000000 --- a/tests/ui/coherence/super-traits/super-trait-knowable-1.current.stderr +++ /dev/null @@ -1,13 +0,0 @@ -error[E0119]: conflicting implementations of trait `Overlap<_>` for type `()` - --> $DIR/super-trait-knowable-1.rs:16:1 - | -LL | impl> Overlap for U {} - | ----------------------------------- first implementation here -LL | impl Overlap for () {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `()` - | - = note: downstream crates may implement trait `Sub<_>` for type `()` - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/coherence/super-traits/super-trait-knowable-1.rs b/tests/ui/coherence/super-traits/super-trait-knowable-1.rs index 80df8c19ee51f..77af4d0f2e3a6 100644 --- a/tests/ui/coherence/super-traits/super-trait-knowable-1.rs +++ b/tests/ui/coherence/super-traits/super-trait-knowable-1.rs @@ -3,10 +3,7 @@ // We therefore elaborate super trait bounds in the implicit negative // overlap check. -//@ revisions: current next -//@ ignore-compare-mode-next-solver (explicit revisions) -//@[next] compile-flags: -Znext-solver -//@[next] check-pass +//@ check-pass trait Super {} trait Sub: Super {} @@ -14,6 +11,5 @@ trait Sub: Super {} trait Overlap {} impl> Overlap for U {} impl Overlap for () {} -//[current]~^ ERROR conflicting implementations fn main() {} diff --git a/tests/ui/coherence/super-traits/super-trait-knowable-3.current.stderr b/tests/ui/coherence/super-traits/super-trait-knowable-3.current.stderr deleted file mode 100644 index 542edb8b7f674..0000000000000 --- a/tests/ui/coherence/super-traits/super-trait-knowable-3.current.stderr +++ /dev/null @@ -1,13 +0,0 @@ -error[E0119]: conflicting implementations of trait `Overlap<_>` for type `()` - --> $DIR/super-trait-knowable-3.rs:19:1 - | -LL | impl>> Overlap for U {} - | ---------------------------------------- first implementation here -LL | impl Overlap for () {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `()` - | - = note: downstream crates may implement trait `Sub<_>` for type `()` - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/coherence/super-traits/super-trait-knowable-3.rs b/tests/ui/coherence/super-traits/super-trait-knowable-3.rs index 295d7ac48d8cc..6198d3d303bd1 100644 --- a/tests/ui/coherence/super-traits/super-trait-knowable-3.rs +++ b/tests/ui/coherence/super-traits/super-trait-knowable-3.rs @@ -2,10 +2,7 @@ // super trait bound is in a nested goal so this would not // compile if we were to only elaborate root goals. -//@ revisions: current next -//@ ignore-compare-mode-next-solver (explicit revisions) -//@[next] compile-flags: -Znext-solver -//@[next] check-pass +//@ check-pass trait Super {} trait Sub: Super {} @@ -17,6 +14,5 @@ impl, U> Bound> for T {} trait Overlap {} impl>> Overlap for U {} impl Overlap for () {} -//[current]~^ ERROR conflicting implementations of trait `Overlap<_>` for type `()` fn main() {} diff --git a/tests/ui/const-generics/generic_const_exprs/unevaluated-const-ice-119731.rs b/tests/ui/const-generics/generic_const_exprs/unevaluated-const-ice-119731.rs index 05a3487ffca51..42c930f952d16 100644 --- a/tests/ui/const-generics/generic_const_exprs/unevaluated-const-ice-119731.rs +++ b/tests/ui/const-generics/generic_const_exprs/unevaluated-const-ice-119731.rs @@ -22,6 +22,7 @@ mod v20 { impl v17<512, v0> { pub const fn v21() -> v18 {} //~^ ERROR cannot find type `v18` in this scope + //~| ERROR duplicate definitions with name `v21` } impl v17 { diff --git a/tests/ui/const-generics/generic_const_exprs/unevaluated-const-ice-119731.stderr b/tests/ui/const-generics/generic_const_exprs/unevaluated-const-ice-119731.stderr index 39f022fbee9db..b336f2b3fca59 100644 --- a/tests/ui/const-generics/generic_const_exprs/unevaluated-const-ice-119731.stderr +++ b/tests/ui/const-generics/generic_const_exprs/unevaluated-const-ice-119731.stderr @@ -1,5 +1,5 @@ error[E0432]: unresolved import `v20::v13` - --> $DIR/unevaluated-const-ice-119731.rs:37:15 + --> $DIR/unevaluated-const-ice-119731.rs:38:15 | LL | pub use v20::{v13, v17}; | ^^^ @@ -23,7 +23,7 @@ LL | pub const fn v21() -> v18 {} | ^^^ help: a type alias with a similar name exists: `v11` error[E0412]: cannot find type `v18` in this scope - --> $DIR/unevaluated-const-ice-119731.rs:30:31 + --> $DIR/unevaluated-const-ice-119731.rs:31:31 | LL | pub type v11 = [[usize; v4]; v4]; | --------------------------------- similarly named type alias `v11` defined here @@ -32,7 +32,7 @@ LL | pub const fn v21() -> v18 { | ^^^ help: a type alias with a similar name exists: `v11` error[E0422]: cannot find struct, variant or union type `v18` in this scope - --> $DIR/unevaluated-const-ice-119731.rs:32:13 + --> $DIR/unevaluated-const-ice-119731.rs:33:13 | LL | pub type v11 = [[usize; v4]; v4]; | --------------------------------- similarly named type alias `v11` defined here @@ -73,20 +73,29 @@ LL + #![feature(adt_const_params)] | error: maximum number of nodes exceeded in constant v20::v17::::{constant#1} - --> $DIR/unevaluated-const-ice-119731.rs:27:37 + --> $DIR/unevaluated-const-ice-119731.rs:28:37 | LL | impl v17 { | ^^ error: maximum number of nodes exceeded in constant v20::v17::::{constant#1} - --> $DIR/unevaluated-const-ice-119731.rs:27:37 + --> $DIR/unevaluated-const-ice-119731.rs:28:37 | LL | impl v17 { | ^^ | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -error: aborting due to 9 previous errors; 2 warnings emitted +error[E0592]: duplicate definitions with name `v21` + --> $DIR/unevaluated-const-ice-119731.rs:23:9 + | +LL | pub const fn v21() -> v18 {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^ duplicate definitions for `v21` +... +LL | pub const fn v21() -> v18 { + | ------------------------- other definition for `v21` + +error: aborting due to 10 previous errors; 2 warnings emitted -Some errors have detailed explanations: E0412, E0422, E0425, E0432. +Some errors have detailed explanations: E0412, E0422, E0425, E0432, E0592. For more information about an error, try `rustc --explain E0412`. diff --git a/tests/ui/const-generics/generic_const_exprs/unknown-alias-defkind-anonconst-ice-116710.rs b/tests/ui/const-generics/generic_const_exprs/unknown-alias-defkind-anonconst-ice-116710.rs index dd0b1e8c9f71d..81ac9979bd8c7 100644 --- a/tests/ui/const-generics/generic_const_exprs/unknown-alias-defkind-anonconst-ice-116710.rs +++ b/tests/ui/const-generics/generic_const_exprs/unknown-alias-defkind-anonconst-ice-116710.rs @@ -10,6 +10,5 @@ trait Trait {} impl Trait for A {} impl Trait for A {} -//~^ ERROR conflicting implementations of trait `Trait` for type `A<_>` pub fn main() {} diff --git a/tests/ui/const-generics/generic_const_exprs/unknown-alias-defkind-anonconst-ice-116710.stderr b/tests/ui/const-generics/generic_const_exprs/unknown-alias-defkind-anonconst-ice-116710.stderr index 80ac96d487000..e29c49ff0422c 100644 --- a/tests/ui/const-generics/generic_const_exprs/unknown-alias-defkind-anonconst-ice-116710.stderr +++ b/tests/ui/const-generics/generic_const_exprs/unknown-alias-defkind-anonconst-ice-116710.stderr @@ -4,16 +4,6 @@ error[E0423]: expected value, found builtin type `u8` LL | struct A; | ^^ not a value -error[E0119]: conflicting implementations of trait `Trait` for type `A<_>` - --> $DIR/unknown-alias-defkind-anonconst-ice-116710.rs:12:1 - | -LL | impl Trait for A {} - | --------------------------------- first implementation here -LL | -LL | impl Trait for A {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `A<_>` - -error: aborting due to 2 previous errors +error: aborting due to 1 previous error -Some errors have detailed explanations: E0119, E0423. -For more information about an error, try `rustc --explain E0119`. +For more information about this error, try `rustc --explain E0423`. diff --git a/tests/ui/error-codes/e0119/issue-23563.stderr b/tests/ui/error-codes/e0119/issue-23563.stderr index 86737742f749b..a308769af131f 100644 --- a/tests/ui/error-codes/e0119/issue-23563.stderr +++ b/tests/ui/error-codes/e0119/issue-23563.stderr @@ -1,4 +1,4 @@ -error[E0119]: conflicting implementations of trait `LolFrom<&[_]>` for type `LocalType<_>` +error[E0119]: conflicting implementations of trait `LolFrom<&[u8]>` for type `LocalType` --> $DIR/issue-23563.rs:13:1 | LL | impl<'a, T> LolFrom<&'a [T]> for LocalType { diff --git a/tests/ui/feature-gates/feature-gate-with_negative_coherence.stderr b/tests/ui/feature-gates/feature-gate-with_negative_coherence.stderr index ba076568088b2..b32f54aaecfa5 100644 --- a/tests/ui/feature-gates/feature-gate-with_negative_coherence.stderr +++ b/tests/ui/feature-gates/feature-gate-with_negative_coherence.stderr @@ -6,6 +6,8 @@ LL | impl Foo for T { } LL | LL | impl Foo for &T { } | ^^^^^^^^^^^^^^^^^^ conflicting implementation for `&_` + | + = note: downstream crates may implement trait `std::ops::DerefMut` for type `&_` error: aborting due to 1 previous error diff --git a/tests/ui/higher-ranked/structually-relate-aliases.rs b/tests/ui/higher-ranked/structually-relate-aliases.rs index 8df24702811dd..6988245096136 100644 --- a/tests/ui/higher-ranked/structually-relate-aliases.rs +++ b/tests/ui/higher-ranked/structually-relate-aliases.rs @@ -11,7 +11,6 @@ type Assoc<'a, T> = >::Unit; impl Overlap for T {} impl Overlap fn(&'a (), Assoc<'a, T>)> for T {} -//~^ ERROR 13:17: 13:49: the trait bound `for<'a> T: ToUnit<'a>` is not satisfied [E0277] -//~| ERROR 13:36: 13:48: the trait bound `for<'a> T: ToUnit<'a>` is not satisfied [E0277] +//~^ ERROR conflicting implementations of trait `Overlap fn(&'a (), _)>` fn main() {} diff --git a/tests/ui/higher-ranked/structually-relate-aliases.stderr b/tests/ui/higher-ranked/structually-relate-aliases.stderr index 7de30efae1cd2..4ecd5829bc352 100644 --- a/tests/ui/higher-ranked/structually-relate-aliases.stderr +++ b/tests/ui/higher-ranked/structually-relate-aliases.stderr @@ -1,27 +1,18 @@ WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [?1t, '^0.Named(DefId(0:15 ~ structually_relate_aliases[de75]::{impl#1}::'a), "'a")], def_id: DefId(0:5 ~ structually_relate_aliases[de75]::ToUnit::Unit), .. } - WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [?1t, !2_0.Named(DefId(0:15 ~ structually_relate_aliases[de75]::{impl#1}::'a), "'a")], def_id: DefId(0:5 ~ structually_relate_aliases[de75]::ToUnit::Unit), .. } -error[E0277]: the trait bound `for<'a> T: ToUnit<'a>` is not satisfied - --> $DIR/structually-relate-aliases.rs:13:36 - | -LL | impl Overlap fn(&'a (), Assoc<'a, T>)> for T {} - | ^^^^^^^^^^^^ the trait `for<'a> ToUnit<'a>` is not implemented for `T` - | -help: consider restricting type parameter `T` - | -LL | impl ToUnit<'a>> Overlap fn(&'a (), Assoc<'a, T>)> for T {} - | ++++++++++++++++++++ - -error[E0277]: the trait bound `for<'a> T: ToUnit<'a>` is not satisfied - --> $DIR/structually-relate-aliases.rs:13:17 + WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [?1t, '^0.Named(DefId(0:15 ~ structually_relate_aliases[de75]::{impl#1}::'a), "'a")], def_id: DefId(0:5 ~ structually_relate_aliases[de75]::ToUnit::Unit), .. } + WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [?1t, '^0.Named(DefId(0:15 ~ structually_relate_aliases[de75]::{impl#1}::'a), "'a")], def_id: DefId(0:5 ~ structually_relate_aliases[de75]::ToUnit::Unit), .. } + WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [?1t, '^0.Named(DefId(0:15 ~ structually_relate_aliases[de75]::{impl#1}::'a), "'a")], def_id: DefId(0:5 ~ structually_relate_aliases[de75]::ToUnit::Unit), .. } +error[E0119]: conflicting implementations of trait `Overlap fn(&'a (), _)>` for type `for<'a> fn(&'a (), _)` + --> $DIR/structually-relate-aliases.rs:13:1 | +LL | impl Overlap for T {} + | ------------------------ first implementation here +LL | LL | impl Overlap fn(&'a (), Assoc<'a, T>)> for T {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `for<'a> ToUnit<'a>` is not implemented for `T` - | -help: consider restricting type parameter `T` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `for<'a> fn(&'a (), _)` | -LL | impl ToUnit<'a>> Overlap fn(&'a (), Assoc<'a, T>)> for T {} - | ++++++++++++++++++++ + = note: this behavior recently changed as a result of a bug fix; see rust-lang/rust#56105 for details -error: aborting due to 2 previous errors +error: aborting due to 1 previous error -For more information about this error, try `rustc --explain E0277`. +For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/impl-trait/auto-trait-coherence.old.stderr b/tests/ui/impl-trait/auto-trait-coherence.old.stderr index 3f979d1a50b33..cd91bfcb48d73 100644 --- a/tests/ui/impl-trait/auto-trait-coherence.old.stderr +++ b/tests/ui/impl-trait/auto-trait-coherence.old.stderr @@ -1,11 +1,11 @@ -error[E0119]: conflicting implementations of trait `AnotherTrait` for type `D` +error[E0119]: conflicting implementations of trait `AnotherTrait` for type `D<_>` --> $DIR/auto-trait-coherence.rs:24:1 | LL | impl AnotherTrait for T {} | -------------------------------- first implementation here ... LL | impl AnotherTrait for D { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `D` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `D<_>` error: aborting due to 1 previous error diff --git a/tests/ui/impl-trait/auto-trait-coherence.rs b/tests/ui/impl-trait/auto-trait-coherence.rs index e3036fd0fe2c5..0d7fef21cc92b 100644 --- a/tests/ui/impl-trait/auto-trait-coherence.rs +++ b/tests/ui/impl-trait/auto-trait-coherence.rs @@ -1,6 +1,3 @@ -//@ revisions: old next -//@[next] compile-flags: -Znext-solver - // Tests that type alias impls traits do not leak auto-traits for // the purposes of coherence checking #![feature(type_alias_impl_trait)] @@ -22,8 +19,7 @@ impl AnotherTrait for T {} // (We treat opaque types as "foreign types" that could grow more impls // in the future.) impl AnotherTrait for D { - //[old]~^ ERROR conflicting implementations of trait `AnotherTrait` for type `D` - //[next]~^^ ERROR conflicting implementations of trait `AnotherTrait` for type `D<_>` + //~^ ERROR conflicting implementations of trait `AnotherTrait` for type `D<_>` } fn main() {} diff --git a/tests/ui/impl-trait/auto-trait-coherence.stderr b/tests/ui/impl-trait/auto-trait-coherence.stderr new file mode 100644 index 0000000000000..e0f4c857717cf --- /dev/null +++ b/tests/ui/impl-trait/auto-trait-coherence.stderr @@ -0,0 +1,12 @@ +error[E0119]: conflicting implementations of trait `AnotherTrait` for type `D<_>` + --> $DIR/auto-trait-coherence.rs:21:1 + | +LL | impl AnotherTrait for T {} + | -------------------------------- first implementation here +... +LL | impl AnotherTrait for D { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `D<_>` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/impl-trait/coherence-treats-tait-ambig.rs b/tests/ui/impl-trait/coherence-treats-tait-ambig.rs index df47208bf3676..e8c1fcdd21334 100644 --- a/tests/ui/impl-trait/coherence-treats-tait-ambig.rs +++ b/tests/ui/impl-trait/coherence-treats-tait-ambig.rs @@ -5,7 +5,7 @@ type T = impl Sized; struct Foo; impl Into for Foo { -//~^ ERROR conflicting implementations of trait `Into` for type `Foo` +//~^ ERROR conflicting implementations of trait `Into<_>` for type `Foo` fn into(self) -> T { Foo } diff --git a/tests/ui/impl-trait/coherence-treats-tait-ambig.stderr b/tests/ui/impl-trait/coherence-treats-tait-ambig.stderr index faaad27692716..618bef1f2714a 100644 --- a/tests/ui/impl-trait/coherence-treats-tait-ambig.stderr +++ b/tests/ui/impl-trait/coherence-treats-tait-ambig.stderr @@ -1,4 +1,4 @@ -error[E0119]: conflicting implementations of trait `Into` for type `Foo` +error[E0119]: conflicting implementations of trait `Into<_>` for type `Foo` --> $DIR/coherence-treats-tait-ambig.rs:7:1 | LL | impl Into for Foo { diff --git a/tests/ui/impl-trait/negative-reasoning.rs b/tests/ui/impl-trait/negative-reasoning.rs index 70e24a3a9d029..0474dc0beda6d 100644 --- a/tests/ui/impl-trait/negative-reasoning.rs +++ b/tests/ui/impl-trait/negative-reasoning.rs @@ -17,7 +17,7 @@ impl AnotherTrait for T {} // This is in error, because we cannot assume that `OpaqueType: !Debug` impl AnotherTrait for D { - //~^ ERROR conflicting implementations of trait `AnotherTrait` for type `D` + //~^ ERROR conflicting implementations of trait `AnotherTrait` for type `D<_>` } fn main() {} diff --git a/tests/ui/impl-trait/negative-reasoning.stderr b/tests/ui/impl-trait/negative-reasoning.stderr index 3cb4be16fc3f1..631784c817b87 100644 --- a/tests/ui/impl-trait/negative-reasoning.stderr +++ b/tests/ui/impl-trait/negative-reasoning.stderr @@ -1,13 +1,11 @@ -error[E0119]: conflicting implementations of trait `AnotherTrait` for type `D` +error[E0119]: conflicting implementations of trait `AnotherTrait` for type `D<_>` --> $DIR/negative-reasoning.rs:19:1 | LL | impl AnotherTrait for T {} | ------------------------------------------- first implementation here ... LL | impl AnotherTrait for D { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `D` - | - = note: upstream crates may add a new impl of trait `std::marker::FnPtr` for type `OpaqueType` in future versions + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `D<_>` error: aborting due to 1 previous error diff --git a/tests/ui/impl-unused-tps.rs b/tests/ui/impl-unused-tps.rs index 3eb9daedf76d7..a5836db3c8e66 100644 --- a/tests/ui/impl-unused-tps.rs +++ b/tests/ui/impl-unused-tps.rs @@ -1,34 +1,35 @@ -//~ ERROR overflow evaluating the requirement `([isize; 0], _): Sized - trait Foo { - fn get(&self, A: &A) { } + fn get(&self, A: &A) {} } trait Bar { type Out; } -impl Foo for [isize;0] { +impl Foo for [isize; 0] { // OK, T is used in `Foo`. } -impl Foo for [isize;1] { +impl Foo for [isize; 1] { //~^ ERROR the type parameter `U` is not constrained } -impl Foo for [isize;2] where T : Bar { +impl Foo for [isize; 2] +where + T: Bar, +{ // OK, `U` is now constrained by the output type parameter. } -impl,U> Foo for [isize;3] { +impl, U> Foo for [isize; 3] { // OK, same as above but written differently. } -impl Foo for U { +impl Foo for U { //~^ ERROR conflicting implementations of trait `Foo<_>` for type `[isize; 0]` } -impl Bar for T { +impl Bar for T { //~^ ERROR the type parameter `U` is not constrained type Out = U; @@ -36,28 +37,33 @@ impl Bar for T { // Using `U` in an associated type within the impl is not good enough! } -impl Bar for T - where T : Bar +impl Bar for T +where + T: Bar, { - //~^^^ ERROR the type parameter `U` is not constrained - + //~^^^^ ERROR the type parameter `U` is not constrained by the impl trait, self type, or predicates + //~| ERROR conflicting implementations of trait `Bar` // This crafty self-referential attempt is still no good. } -impl Foo for T - where (T,U): Bar +impl Foo for T +where + (T, U): Bar, { - //~^^^ ERROR the type parameter `U` is not constrained - //~| ERROR the type parameter `V` is not constrained + //~^^^^ ERROR the type parameter `U` is not constrained + //~| ERROR the type parameter `V` is not constrained + //~| ERROR conflicting implementations of trait `Foo<[isize; 0]>` for type `[isize; 0]` // Here, `V` is bound by an output type parameter, but the inputs // are not themselves constrained. } -impl Foo<(T,U)> for T - where (T,U): Bar +impl Foo<(T, U)> for T +where + (T, U): Bar, { + //~^^^^ ERROR conflicting implementations of trait `Foo<([isize; 0], _)>` for type `[isize; 0]` // As above, but both T and U ARE constrained. } -fn main() { } +fn main() {} diff --git a/tests/ui/impl-unused-tps.stderr b/tests/ui/impl-unused-tps.stderr index af427cb5f3e3c..da4589dee8278 100644 --- a/tests/ui/impl-unused-tps.stderr +++ b/tests/ui/impl-unused-tps.stderr @@ -1,56 +1,76 @@ error[E0119]: conflicting implementations of trait `Foo<_>` for type `[isize; 0]` - --> $DIR/impl-unused-tps.rs:27:1 + --> $DIR/impl-unused-tps.rs:28:1 | -LL | impl Foo for [isize;0] { - | ---------------------------- first implementation here +LL | impl Foo for [isize; 0] { + | ----------------------------- first implementation here ... -LL | impl Foo for U { - | ^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `[isize; 0]` +LL | impl Foo for U { + | ^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `[isize; 0]` -error[E0275]: overflow evaluating the requirement `([isize; 0], _): Sized` +error[E0119]: conflicting implementations of trait `Bar` + --> $DIR/impl-unused-tps.rs:40:1 | - = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`impl_unused_tps`) -note: required for `([isize; 0], _)` to implement `Bar` - --> $DIR/impl-unused-tps.rs:31:11 +LL | impl Bar for T { + | -------------------- first implementation here +... +LL | / impl Bar for T +LL | | where +LL | | T: Bar, + | |____________________^ conflicting implementation + +error[E0119]: conflicting implementations of trait `Foo<[isize; 0]>` for type `[isize; 0]` + --> $DIR/impl-unused-tps.rs:49:1 + | +LL | impl Foo for [isize; 0] { + | ----------------------------- first implementation here +... +LL | / impl Foo for T +LL | | where +LL | | (T, U): Bar, + | |_________________________^ conflicting implementation for `[isize; 0]` + +error[E0119]: conflicting implementations of trait `Foo<([isize; 0], _)>` for type `[isize; 0]` + --> $DIR/impl-unused-tps.rs:61:1 | -LL | impl Bar for T { - | - ^^^ ^ - | | - | unsatisfied trait bound introduced here - = note: 126 redundant requirements hidden - = note: required for `([isize; 0], _)` to implement `Bar` +LL | impl Foo for [isize; 0] { + | ----------------------------- first implementation here +... +LL | / impl Foo<(T, U)> for T +LL | | where +LL | | (T, U): Bar, + | |_________________________^ conflicting implementation for `[isize; 0]` error[E0207]: the type parameter `U` is not constrained by the impl trait, self type, or predicates - --> $DIR/impl-unused-tps.rs:15:8 + --> $DIR/impl-unused-tps.rs:13:9 | -LL | impl Foo for [isize;1] { - | ^ unconstrained type parameter +LL | impl Foo for [isize; 1] { + | ^ unconstrained type parameter error[E0207]: the type parameter `U` is not constrained by the impl trait, self type, or predicates - --> $DIR/impl-unused-tps.rs:31:8 + --> $DIR/impl-unused-tps.rs:32:9 | -LL | impl Bar for T { - | ^ unconstrained type parameter +LL | impl Bar for T { + | ^ unconstrained type parameter error[E0207]: the type parameter `U` is not constrained by the impl trait, self type, or predicates - --> $DIR/impl-unused-tps.rs:39:8 + --> $DIR/impl-unused-tps.rs:40:9 | -LL | impl Bar for T - | ^ unconstrained type parameter +LL | impl Bar for T + | ^ unconstrained type parameter error[E0207]: the type parameter `U` is not constrained by the impl trait, self type, or predicates - --> $DIR/impl-unused-tps.rs:47:8 + --> $DIR/impl-unused-tps.rs:49:9 | -LL | impl Foo for T - | ^ unconstrained type parameter +LL | impl Foo for T + | ^ unconstrained type parameter error[E0207]: the type parameter `V` is not constrained by the impl trait, self type, or predicates - --> $DIR/impl-unused-tps.rs:47:10 + --> $DIR/impl-unused-tps.rs:49:12 | -LL | impl Foo for T - | ^ unconstrained type parameter +LL | impl Foo for T + | ^ unconstrained type parameter -error: aborting due to 7 previous errors +error: aborting due to 9 previous errors -Some errors have detailed explanations: E0119, E0207, E0275. +Some errors have detailed explanations: E0119, E0207. For more information about an error, try `rustc --explain E0119`. diff --git a/tests/ui/issues/issue-48728.rs b/tests/ui/issues/issue-48728.rs index 7ef05f4277b27..8ad9289c65cf2 100644 --- a/tests/ui/issues/issue-48728.rs +++ b/tests/ui/issues/issue-48728.rs @@ -1,12 +1,8 @@ // Regression test for #48728, an ICE that occurred computing // coherence "help" information. -//@ revisions: current next -//@ ignore-compare-mode-next-solver (explicit revisions) -//@[next] compile-flags: -Znext-solver -//@[next] check-pass - -#[derive(Clone)] //[current]~ ERROR conflicting implementations of trait `Clone` +//@ check-pass +#[derive(Clone)] struct Node(Box); impl Clone for Node<[T]> { diff --git a/tests/ui/specialization/defaultimpl/specialization-no-default.rs b/tests/ui/specialization/defaultimpl/specialization-no-default.rs index 661724eef8a43..ddc32337306f3 100644 --- a/tests/ui/specialization/defaultimpl/specialization-no-default.rs +++ b/tests/ui/specialization/defaultimpl/specialization-no-default.rs @@ -71,7 +71,8 @@ impl Redundant for T { } default impl Redundant for i32 { - fn redundant(&self) {} //~ ERROR E0520 + fn redundant(&self) {} + //~^ ERROR `redundant` specializes an item from a parent `impl`, but that item is not marked `default` } fn main() {} diff --git a/tests/ui/specialization/specialization-default-items-drop-coherence.current.stderr b/tests/ui/specialization/specialization-default-items-drop-coherence.current.stderr new file mode 100644 index 0000000000000..36df6bfd9fc15 --- /dev/null +++ b/tests/ui/specialization/specialization-default-items-drop-coherence.current.stderr @@ -0,0 +1,12 @@ +error[E0119]: conflicting implementations of trait `Overlap` for type `u32` + --> $DIR/specialization-default-items-drop-coherence.rs:26:1 + | +LL | impl Overlap for u32 { + | -------------------- first implementation here +... +LL | impl Overlap for ::Id { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `u32` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/specialization/specialization-default-items-drop-coherence.next.stderr b/tests/ui/specialization/specialization-default-items-drop-coherence.next.stderr index e9498a003179b..36df6bfd9fc15 100644 --- a/tests/ui/specialization/specialization-default-items-drop-coherence.next.stderr +++ b/tests/ui/specialization/specialization-default-items-drop-coherence.next.stderr @@ -1,5 +1,5 @@ error[E0119]: conflicting implementations of trait `Overlap` for type `u32` - --> $DIR/specialization-default-items-drop-coherence.rs:29:1 + --> $DIR/specialization-default-items-drop-coherence.rs:26:1 | LL | impl Overlap for u32 { | -------------------- first implementation here diff --git a/tests/ui/specialization/specialization-default-items-drop-coherence.rs b/tests/ui/specialization/specialization-default-items-drop-coherence.rs index 6dc012776391b..b3c1f72777c4c 100644 --- a/tests/ui/specialization/specialization-default-items-drop-coherence.rs +++ b/tests/ui/specialization/specialization-default-items-drop-coherence.rs @@ -1,8 +1,5 @@ -//@ revisions: classic coherence next +//@ revisions: current next //@[next] compile-flags: -Znext-solver -//@[coherence] compile-flags: -Znext-solver=coherence -//@[classic] check-pass -//@[classic] known-bug: #105782 // Should fail. Default items completely drop candidates instead of ambiguity, // which is unsound during coherence, since coherence requires completeness. @@ -27,8 +24,7 @@ impl Overlap for u32 { } impl Overlap for ::Id { - //[coherence]~^ ERROR conflicting implementations of trait `Overlap` for type `u32` - //[next]~^^ ERROR conflicting implementations of trait `Overlap` for type `u32` + //~^ ERROR conflicting implementations of trait `Overlap` for type `u32` type Assoc = Box; } diff --git a/tests/ui/specialization/specialization-overlap-projection.current.stderr b/tests/ui/specialization/specialization-overlap-projection.current.stderr index a69826fa96b08..4e77cb17fbb0a 100644 --- a/tests/ui/specialization/specialization-overlap-projection.current.stderr +++ b/tests/ui/specialization/specialization-overlap-projection.current.stderr @@ -1,5 +1,5 @@ warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/specialization-overlap-projection.rs:10:12 + --> $DIR/specialization-overlap-projection.rs:4:12 | LL | #![feature(specialization)] | ^^^^^^^^^^^^^^ @@ -8,5 +8,23 @@ LL | #![feature(specialization)] = help: consider using `min_specialization` instead, which is more stable and complete = note: `#[warn(incomplete_features)]` on by default -warning: 1 warning emitted +error[E0119]: conflicting implementations of trait `Foo` for type `u32` + --> $DIR/specialization-overlap-projection.rs:19:1 + | +LL | impl Foo for u32 {} + | ---------------- first implementation here +LL | impl Foo for ::Output {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `u32` + +error[E0119]: conflicting implementations of trait `Foo` for type `u32` + --> $DIR/specialization-overlap-projection.rs:21:1 + | +LL | impl Foo for u32 {} + | ---------------- first implementation here +... +LL | impl Foo for ::Output {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `u32` + +error: aborting due to 2 previous errors; 1 warning emitted +For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/specialization/specialization-overlap-projection.next.stderr b/tests/ui/specialization/specialization-overlap-projection.next.stderr index 5b17696162ed5..4e77cb17fbb0a 100644 --- a/tests/ui/specialization/specialization-overlap-projection.next.stderr +++ b/tests/ui/specialization/specialization-overlap-projection.next.stderr @@ -1,5 +1,5 @@ warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/specialization-overlap-projection.rs:10:12 + --> $DIR/specialization-overlap-projection.rs:4:12 | LL | #![feature(specialization)] | ^^^^^^^^^^^^^^ @@ -9,7 +9,7 @@ LL | #![feature(specialization)] = note: `#[warn(incomplete_features)]` on by default error[E0119]: conflicting implementations of trait `Foo` for type `u32` - --> $DIR/specialization-overlap-projection.rs:25:1 + --> $DIR/specialization-overlap-projection.rs:19:1 | LL | impl Foo for u32 {} | ---------------- first implementation here @@ -17,7 +17,7 @@ LL | impl Foo for ::Output {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `u32` error[E0119]: conflicting implementations of trait `Foo` for type `u32` - --> $DIR/specialization-overlap-projection.rs:27:1 + --> $DIR/specialization-overlap-projection.rs:21:1 | LL | impl Foo for u32 {} | ---------------- first implementation here diff --git a/tests/ui/specialization/specialization-overlap-projection.rs b/tests/ui/specialization/specialization-overlap-projection.rs index 16dccf82dcb98..f7a2a79224320 100644 --- a/tests/ui/specialization/specialization-overlap-projection.rs +++ b/tests/ui/specialization/specialization-overlap-projection.rs @@ -1,13 +1,8 @@ -//@ revisions: current next -//@ ignore-compare-mode-next-solver (explicit revisions) -//@[next] compile-flags: -Znext-solver -//@[current] check-pass - // Test that impls on projected self types can resolve overlap, even when the // projections involve specialization, so long as the associated type is // provided by the most specialized impl. - -#![feature(specialization)] //~ WARN the feature `specialization` is incomplete +#![feature(specialization)] +//~^ WARN the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes trait Assoc { type Output; @@ -23,8 +18,8 @@ impl Assoc for u16 { type Output = u16; } trait Foo {} impl Foo for u32 {} impl Foo for ::Output {} -//[next]~^ ERROR conflicting implementations of trait `Foo` for type `u32` +//~^ ERROR conflicting implementations of trait `Foo` for type `u32` impl Foo for ::Output {} -//[next]~^ ERROR conflicting implementations of trait `Foo` for type `u32` +//~^ ERROR conflicting implementations of trait `Foo` for type `u32` fn main() {} diff --git a/tests/ui/specialization/specialization-overlap-projection.stderr b/tests/ui/specialization/specialization-overlap-projection.stderr new file mode 100644 index 0000000000000..5f3cd9c66cfe2 --- /dev/null +++ b/tests/ui/specialization/specialization-overlap-projection.stderr @@ -0,0 +1,30 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/specialization-overlap-projection.rs:4:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: see issue #31844 for more information + = help: consider using `min_specialization` instead, which is more stable and complete + = note: `#[warn(incomplete_features)]` on by default + +error[E0119]: conflicting implementations of trait `Foo` for type `u32` + --> $DIR/specialization-overlap-projection.rs:20:1 + | +LL | impl Foo for u32 {} + | ---------------- first implementation here +LL | impl Foo for ::Output {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `u32` + +error[E0119]: conflicting implementations of trait `Foo` for type `u32` + --> $DIR/specialization-overlap-projection.rs:22:1 + | +LL | impl Foo for u32 {} + | ---------------- first implementation here +... +LL | impl Foo for ::Output {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `u32` + +error: aborting due to 2 previous errors; 1 warning emitted + +For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/traits/alias/issue-83613.rs b/tests/ui/traits/alias/issue-83613.rs index 2462e703a7165..6f0012bf08967 100644 --- a/tests/ui/traits/alias/issue-83613.rs +++ b/tests/ui/traits/alias/issue-83613.rs @@ -8,5 +8,5 @@ fn mk_opaque() -> OpaqueType { trait AnotherTrait {} impl AnotherTrait for T {} impl AnotherTrait for OpaqueType {} -//~^ ERROR conflicting implementations of trait `AnotherTrait` for type `OpaqueType` +//~^ ERROR conflicting implementations of trait `AnotherTrait` fn main() {} diff --git a/tests/ui/traits/alias/issue-83613.stderr b/tests/ui/traits/alias/issue-83613.stderr index 847fda417766a..47181c3f33ed6 100644 --- a/tests/ui/traits/alias/issue-83613.stderr +++ b/tests/ui/traits/alias/issue-83613.stderr @@ -1,10 +1,10 @@ -error[E0119]: conflicting implementations of trait `AnotherTrait` for type `OpaqueType` +error[E0119]: conflicting implementations of trait `AnotherTrait` --> $DIR/issue-83613.rs:10:1 | LL | impl AnotherTrait for T {} | -------------------------------- first implementation here LL | impl AnotherTrait for OpaqueType {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `OpaqueType` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation error: aborting due to 1 previous error diff --git a/tests/ui/traits/issue-105231.rs b/tests/ui/traits/issue-105231.rs index 7338642beefa6..83c3158c106b6 100644 --- a/tests/ui/traits/issue-105231.rs +++ b/tests/ui/traits/issue-105231.rs @@ -1,4 +1,3 @@ -//~ ERROR overflow evaluating the requirement `A>>>>>>: Send` struct A(B); //~^ ERROR recursive types `A` and `B` have infinite size //~| ERROR `T` is only used recursively @@ -7,5 +6,5 @@ struct B(A>); trait Foo {} impl Foo for T where T: Send {} impl Foo for B {} - +//~^ ERROR conflicting implementations of trait `Foo` for type `B` fn main() {} diff --git a/tests/ui/traits/issue-105231.stderr b/tests/ui/traits/issue-105231.stderr index d3014a79ad605..e113f8382b2f4 100644 --- a/tests/ui/traits/issue-105231.stderr +++ b/tests/ui/traits/issue-105231.stderr @@ -1,5 +1,5 @@ error[E0072]: recursive types `A` and `B` have infinite size - --> $DIR/issue-105231.rs:2:1 + --> $DIR/issue-105231.rs:1:1 | LL | struct A(B); | ^^^^^^^^^^^ ---- recursive without indirection @@ -16,7 +16,7 @@ LL ~ struct B(Box>>); | error: type parameter `T` is only used recursively - --> $DIR/issue-105231.rs:2:15 + --> $DIR/issue-105231.rs:1:15 | LL | struct A(B); | - ^ @@ -27,7 +27,7 @@ LL | struct A(B); = note: all type parameters must be used in a non-recursive way in order to constrain their variance error: type parameter `T` is only used recursively - --> $DIR/issue-105231.rs:5:17 + --> $DIR/issue-105231.rs:4:17 | LL | struct B(A>); | - ^ @@ -37,16 +37,18 @@ LL | struct B(A>); = help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData` = note: all type parameters must be used in a non-recursive way in order to constrain their variance -error[E0275]: overflow evaluating the requirement `A>>>>>>: Send` +error[E0119]: conflicting implementations of trait `Foo` for type `B` + --> $DIR/issue-105231.rs:8:1 | - = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`issue_105231`) -note: required because it appears within the type `B>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>` - --> $DIR/issue-105231.rs:5:8 +LL | impl Foo for T where T: Send {} + | ------------------------------- first implementation here +LL | impl Foo for B {} + | ^^^^^^^^^^^^^^^^^^ conflicting implementation for `B` | -LL | struct B(A>); - | ^ + = note: overflow evaluating the requirement `B: Send` + = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`issue_105231`) error: aborting due to 4 previous errors -Some errors have detailed explanations: E0072, E0275. +Some errors have detailed explanations: E0072, E0119. For more information about an error, try `rustc --explain E0072`. diff --git a/tests/ui/traits/solver-cycles/cycle-via-builtin-auto-trait-impl.rs b/tests/ui/traits/solver-cycles/cycle-via-builtin-auto-trait-impl.rs index d37943b929a1f..43443be88df73 100644 --- a/tests/ui/traits/solver-cycles/cycle-via-builtin-auto-trait-impl.rs +++ b/tests/ui/traits/solver-cycles/cycle-via-builtin-auto-trait-impl.rs @@ -1,4 +1,3 @@ -//~ ERROR overflow // A regression test for #111729 checking that we correctly // track recursion depth for obligations returned by confirmation. use std::panic::RefUnwindSafe; @@ -18,6 +17,7 @@ impl Database for T { type Storage = SalsaStorage; } impl Database for RootDatabase { + //~^ ERROR conflicting implementations of trait `Database` for type `RootDatabase` type Storage = SalsaStorage; } diff --git a/tests/ui/traits/solver-cycles/cycle-via-builtin-auto-trait-impl.stderr b/tests/ui/traits/solver-cycles/cycle-via-builtin-auto-trait-impl.stderr index 2ab150fc0f627..1da7671b45190 100644 --- a/tests/ui/traits/solver-cycles/cycle-via-builtin-auto-trait-impl.stderr +++ b/tests/ui/traits/solver-cycles/cycle-via-builtin-auto-trait-impl.stderr @@ -1,24 +1,12 @@ -error[E0275]: overflow evaluating the requirement `Runtime: RefUnwindSafe` - | - = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`cycle_via_builtin_auto_trait_impl`) -note: required because it appears within the type `RootDatabase` - --> $DIR/cycle-via-builtin-auto-trait-impl.rs:13:8 - | -LL | struct RootDatabase { - | ^^^^^^^^^^^^ -note: required for `RootDatabase` to implement `Database` - --> $DIR/cycle-via-builtin-auto-trait-impl.rs:17:24 +error[E0119]: conflicting implementations of trait `Database` for type `RootDatabase` + --> $DIR/cycle-via-builtin-auto-trait-impl.rs:19:1 | LL | impl Database for T { - | ------------- ^^^^^^^^ ^ - | | - | unsatisfied trait bound introduced here -note: required because it appears within the type `Runtime` - --> $DIR/cycle-via-builtin-auto-trait-impl.rs:24:8 - | -LL | struct Runtime { - | ^^^^^^^ + | ------------------------------------- first implementation here +... +LL | impl Database for RootDatabase { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `RootDatabase` error: aborting due to 1 previous error -For more information about this error, try `rustc --explain E0275`. +For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/type-alias-impl-trait/impl_trait_for_same_tait.stderr b/tests/ui/type-alias-impl-trait/impl_trait_for_same_tait.stderr index e35913be899f4..aaf75cc3db97c 100644 --- a/tests/ui/type-alias-impl-trait/impl_trait_for_same_tait.stderr +++ b/tests/ui/type-alias-impl-trait/impl_trait_for_same_tait.stderr @@ -15,8 +15,6 @@ LL | impl Bop for Bar<()> {} ... LL | impl Bop for Barr {} | ^^^^^^^^^^^^^^^^^ conflicting implementation for `Bar<()>` - | - = note: upstream crates may add a new impl of trait `std::marker::FnPtr` for type `Barr` in future versions error[E0119]: conflicting implementations of trait `Bop` for type `Bar<()>` --> $DIR/impl_trait_for_same_tait.rs:30:1 diff --git a/tests/ui/type-alias-impl-trait/issue-104817.rs b/tests/ui/type-alias-impl-trait/issue-104817.rs index 4679d025fce0f..4914632161450 100644 --- a/tests/ui/type-alias-impl-trait/issue-104817.rs +++ b/tests/ui/type-alias-impl-trait/issue-104817.rs @@ -14,6 +14,6 @@ fn mk_opaque() -> OpaqueType { trait AnotherTrait {} impl AnotherTrait for T {} impl AnotherTrait for OpaqueType {} -//[stock]~^ conflicting implementations of trait `AnotherTrait` for type `OpaqueType` +//[stock]~^ conflicting implementations of trait `AnotherTrait` fn main() {} diff --git a/tests/ui/type-alias-impl-trait/issue-104817.stock.stderr b/tests/ui/type-alias-impl-trait/issue-104817.stock.stderr index 41c5206d9e88a..df5a6c320a8a7 100644 --- a/tests/ui/type-alias-impl-trait/issue-104817.stock.stderr +++ b/tests/ui/type-alias-impl-trait/issue-104817.stock.stderr @@ -1,10 +1,10 @@ -error[E0119]: conflicting implementations of trait `AnotherTrait` for type `OpaqueType` +error[E0119]: conflicting implementations of trait `AnotherTrait` --> $DIR/issue-104817.rs:16:1 | LL | impl AnotherTrait for T {} | -------------------------------- first implementation here LL | impl AnotherTrait for OpaqueType {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `OpaqueType` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation error: aborting due to 1 previous error From d93e047c9f1b33892a604273ab3931815f5604a1 Mon Sep 17 00:00:00 2001 From: lcnr Date: Mon, 15 Apr 2024 18:10:46 +0200 Subject: [PATCH 0513/2194] rebase and update fixed `crashes` --- tests/crashes/118987.rs | 17 ------------ .../default-impl-normalization-ambig-2.rs} | 4 ++- .../default-impl-normalization-ambig-2.stderr | 21 +++++++++++++++ .../default-item-normalization-ambig-1.rs} | 5 ++-- .../default-item-normalization-ambig-1.stderr | 21 +++++++++++++++ .../coherence-bikeshed-intrinsic-from.rs} | 4 ++- .../coherence-bikeshed-intrinsic-from.stderr | 27 +++++++++++++++++++ 7 files changed, 78 insertions(+), 21 deletions(-) delete mode 100644 tests/crashes/118987.rs rename tests/{crashes/118987-2.rs => ui/specialization/coherence/default-impl-normalization-ambig-2.rs} (74%) create mode 100644 tests/ui/specialization/coherence/default-impl-normalization-ambig-2.stderr rename tests/{crashes/74299.rs => ui/specialization/coherence/default-item-normalization-ambig-1.rs} (56%) create mode 100644 tests/ui/specialization/coherence/default-item-normalization-ambig-1.stderr rename tests/{crashes/124207.rs => ui/transmutability/malformed-program-gracefulness/coherence-bikeshed-intrinsic-from.rs} (62%) create mode 100644 tests/ui/transmutability/malformed-program-gracefulness/coherence-bikeshed-intrinsic-from.stderr diff --git a/tests/crashes/118987.rs b/tests/crashes/118987.rs deleted file mode 100644 index 4382a7bcb6397..0000000000000 --- a/tests/crashes/118987.rs +++ /dev/null @@ -1,17 +0,0 @@ -//@ known-bug: #118987 -#![feature(specialization)] //~ WARN the feature `specialization` is incomplete - -trait Assoc { - type Output; -} - -default impl Assoc for T { - type Output = bool; -} - -impl Assoc for u8 {} - -trait Foo {} - -impl Foo for ::Output {} -impl Foo for ::Output {} diff --git a/tests/crashes/118987-2.rs b/tests/ui/specialization/coherence/default-impl-normalization-ambig-2.rs similarity index 74% rename from tests/crashes/118987-2.rs rename to tests/ui/specialization/coherence/default-impl-normalization-ambig-2.rs index 4382a7bcb6397..1691530fa0a53 100644 --- a/tests/crashes/118987-2.rs +++ b/tests/ui/specialization/coherence/default-impl-normalization-ambig-2.rs @@ -1,4 +1,4 @@ -//@ known-bug: #118987 +// regression test for #118987 #![feature(specialization)] //~ WARN the feature `specialization` is incomplete trait Assoc { @@ -15,3 +15,5 @@ trait Foo {} impl Foo for ::Output {} impl Foo for ::Output {} +//~^ ERROR the trait bound `u16: Assoc` is not satisfied +fn main() {} diff --git a/tests/ui/specialization/coherence/default-impl-normalization-ambig-2.stderr b/tests/ui/specialization/coherence/default-impl-normalization-ambig-2.stderr new file mode 100644 index 0000000000000..a2fca2ef5b67e --- /dev/null +++ b/tests/ui/specialization/coherence/default-impl-normalization-ambig-2.stderr @@ -0,0 +1,21 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/default-impl-normalization-ambig-2.rs:2:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: see issue #31844 for more information + = help: consider using `min_specialization` instead, which is more stable and complete + = note: `#[warn(incomplete_features)]` on by default + +error[E0277]: the trait bound `u16: Assoc` is not satisfied + --> $DIR/default-impl-normalization-ambig-2.rs:17:14 + | +LL | impl Foo for ::Output {} + | ^^^^^^^^^^^^^^^^^^^^^^ the trait `Assoc` is not implemented for `u16` + | + = help: the trait `Assoc` is implemented for `u8` + +error: aborting due to 1 previous error; 1 warning emitted + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/crashes/74299.rs b/tests/ui/specialization/coherence/default-item-normalization-ambig-1.rs similarity index 56% rename from tests/crashes/74299.rs rename to tests/ui/specialization/coherence/default-item-normalization-ambig-1.rs index 0e2ddce1c5b11..af7cf332d5f4f 100644 --- a/tests/crashes/74299.rs +++ b/tests/ui/specialization/coherence/default-item-normalization-ambig-1.rs @@ -1,5 +1,5 @@ -//@ known-bug: #74299 -#![feature(specialization)] +// regression test for #73299. +#![feature(specialization)] //~ WARN the feature `specialization` is incomplete trait X { type U; @@ -18,6 +18,7 @@ trait Y { impl Y for <() as X>::U {} impl Y for ::U {} +//~^ ERROR conflicting implementations of trait `Y` for type `<() as X>::U` fn main() { ().f().g(); diff --git a/tests/ui/specialization/coherence/default-item-normalization-ambig-1.stderr b/tests/ui/specialization/coherence/default-item-normalization-ambig-1.stderr new file mode 100644 index 0000000000000..a15151cc9c41e --- /dev/null +++ b/tests/ui/specialization/coherence/default-item-normalization-ambig-1.stderr @@ -0,0 +1,21 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/default-item-normalization-ambig-1.rs:2:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: see issue #31844 for more information + = help: consider using `min_specialization` instead, which is more stable and complete + = note: `#[warn(incomplete_features)]` on by default + +error[E0119]: conflicting implementations of trait `Y` for type `<() as X>::U` + --> $DIR/default-item-normalization-ambig-1.rs:20:1 + | +LL | impl Y for <() as X>::U {} + | ----------------------- first implementation here +LL | impl Y for ::U {} + | ^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `<() as X>::U` + +error: aborting due to 1 previous error; 1 warning emitted + +For more information about this error, try `rustc --explain E0119`. diff --git a/tests/crashes/124207.rs b/tests/ui/transmutability/malformed-program-gracefulness/coherence-bikeshed-intrinsic-from.rs similarity index 62% rename from tests/crashes/124207.rs rename to tests/ui/transmutability/malformed-program-gracefulness/coherence-bikeshed-intrinsic-from.rs index a11eedb140a68..0cebc99cd4196 100644 --- a/tests/crashes/124207.rs +++ b/tests/ui/transmutability/malformed-program-gracefulness/coherence-bikeshed-intrinsic-from.rs @@ -1,9 +1,11 @@ -//@ known-bug: #124207 #![feature(transmutability)] #![feature(type_alias_impl_trait)] trait OpaqueTrait {} type OpaqueType = impl OpaqueTrait; +//~^ ERROR unconstrained opaque type trait AnotherTrait {} impl> AnotherTrait for T {} +//~^ ERROR type provided when a constant was expected impl AnotherTrait for OpaqueType {} +//~^ ERROR conflicting implementations of trait `AnotherTrait` pub fn main() {} diff --git a/tests/ui/transmutability/malformed-program-gracefulness/coherence-bikeshed-intrinsic-from.stderr b/tests/ui/transmutability/malformed-program-gracefulness/coherence-bikeshed-intrinsic-from.stderr new file mode 100644 index 0000000000000..2424541af23ec --- /dev/null +++ b/tests/ui/transmutability/malformed-program-gracefulness/coherence-bikeshed-intrinsic-from.stderr @@ -0,0 +1,27 @@ +error: unconstrained opaque type + --> $DIR/coherence-bikeshed-intrinsic-from.rs:4:19 + | +LL | type OpaqueType = impl OpaqueTrait; + | ^^^^^^^^^^^^^^^^ + | + = note: `OpaqueType` must be used in combination with a concrete type within the same module + +error[E0747]: type provided when a constant was expected + --> $DIR/coherence-bikeshed-intrinsic-from.rs:7:37 + | +LL | impl> AnotherTrait for T {} + | ^^ + +error[E0119]: conflicting implementations of trait `AnotherTrait` + --> $DIR/coherence-bikeshed-intrinsic-from.rs:9:1 + | +LL | impl> AnotherTrait for T {} + | ----------------------------------------------------------- first implementation here +LL | +LL | impl AnotherTrait for OpaqueType {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0119, E0747. +For more information about an error, try `rustc --explain E0119`. From 69fdd1457d367ce4de044e9784e58a38acf3d847 Mon Sep 17 00:00:00 2001 From: lcnr Date: Fri, 16 Aug 2024 16:00:46 +0200 Subject: [PATCH 0514/2194] remove unnecessary revisions --- ...nce-overlap-downstream-inherent.old.stderr | 23 ------------------- .../coherence-overlap-downstream-inherent.rs | 3 --- ...erence-overlap-downstream-inherent.stderr} | 4 ++-- .../coherence-overlap-downstream.old.stderr | 21 ----------------- .../coherence/coherence-overlap-downstream.rs | 3 --- ...rr => coherence-overlap-downstream.stderr} | 4 ++-- ...ce-overlap-issue-23516-inherent.old.stderr | 14 ----------- .../coherence-overlap-issue-23516-inherent.rs | 3 --- ...rence-overlap-issue-23516-inherent.stderr} | 2 +- .../coherence-overlap-issue-23516.old.stderr | 13 ----------- .../coherence-overlap-issue-23516.rs | 3 --- ...r => coherence-overlap-issue-23516.stderr} | 2 +- ...ap-unnormalizable-projection-0.next.stderr | 18 --------------- ...nce-overlap-unnormalizable-projection-0.rs | 3 --- ...verlap-unnormalizable-projection-0.stderr} | 2 +- ...ap-unnormalizable-projection-1.next.stderr | 19 --------------- ...nce-overlap-unnormalizable-projection-1.rs | 3 --- ...verlap-unnormalizable-projection-1.stderr} | 2 +- tests/ui/coherence/coherent-due-to-fulfill.rs | 2 -- .../incoherent-even-though-we-fulfill.rs | 2 -- .../incoherent-even-though-we-fulfill.stderr | 2 +- ...er-crate-ambiguity-causes-notes.old.stderr | 17 -------------- .../inter-crate-ambiguity-causes-notes.rs | 3 --- ...inter-crate-ambiguity-causes-notes.stderr} | 2 +- .../normalize-for-errors.current.stderr | 15 ------------ .../normalize-for-errors.next.stderr | 15 ------------ .../occurs-check/associated-type.next.stderr | 4 ++-- .../occurs-check/associated-type.old.stderr | 2 +- .../coherence/occurs-check/associated-type.rs | 1 + .../occurs-check/opaques.current.stderr | 2 +- .../occurs-check/opaques.next.stderr | 4 ++-- tests/ui/coherence/occurs-check/opaques.rs | 3 ++- ...heck-opaque-types-not-covering.next.stderr | 21 ----------------- .../orphan-check-opaque-types-not-covering.rs | 3 --- ...an-check-opaque-types-not-covering.stderr} | 4 ++-- .../orphan-check-projections-covering.rs | 3 --- ...heck-weak-aliases-not-covering.next.stderr | 12 ---------- .../orphan-check-weak-aliases-not-covering.rs | 3 --- ...an-check-weak-aliases-not-covering.stderr} | 2 +- ...reporting-if-references-err.current.stderr | 14 ----------- ...ip-reporting-if-references-err.next.stderr | 14 ----------- .../super-traits/super-trait-knowable-2.rs | 3 --- 42 files changed, 22 insertions(+), 273 deletions(-) delete mode 100644 tests/ui/coherence/coherence-overlap-downstream-inherent.old.stderr rename tests/ui/coherence/{coherence-overlap-downstream-inherent.next.stderr => coherence-overlap-downstream-inherent.stderr} (87%) delete mode 100644 tests/ui/coherence/coherence-overlap-downstream.old.stderr rename tests/ui/coherence/{coherence-overlap-downstream.next.stderr => coherence-overlap-downstream.stderr} (88%) delete mode 100644 tests/ui/coherence/coherence-overlap-issue-23516-inherent.old.stderr rename tests/ui/coherence/{coherence-overlap-issue-23516-inherent.next.stderr => coherence-overlap-issue-23516-inherent.stderr} (90%) delete mode 100644 tests/ui/coherence/coherence-overlap-issue-23516.old.stderr rename tests/ui/coherence/{coherence-overlap-issue-23516.next.stderr => coherence-overlap-issue-23516.stderr} (90%) delete mode 100644 tests/ui/coherence/coherence-overlap-unnormalizable-projection-0.next.stderr rename tests/ui/coherence/{coherence-overlap-unnormalizable-projection-0.classic.stderr => coherence-overlap-unnormalizable-projection-0.stderr} (91%) delete mode 100644 tests/ui/coherence/coherence-overlap-unnormalizable-projection-1.next.stderr rename tests/ui/coherence/{coherence-overlap-unnormalizable-projection-1.classic.stderr => coherence-overlap-unnormalizable-projection-1.stderr} (92%) delete mode 100644 tests/ui/coherence/inter-crate-ambiguity-causes-notes.old.stderr rename tests/ui/coherence/{inter-crate-ambiguity-causes-notes.next.stderr => inter-crate-ambiguity-causes-notes.stderr} (90%) delete mode 100644 tests/ui/coherence/normalize-for-errors.current.stderr delete mode 100644 tests/ui/coherence/normalize-for-errors.next.stderr delete mode 100644 tests/ui/coherence/orphan-check-opaque-types-not-covering.next.stderr rename tests/ui/coherence/{orphan-check-opaque-types-not-covering.classic.stderr => orphan-check-opaque-types-not-covering.stderr} (92%) delete mode 100644 tests/ui/coherence/orphan-check-weak-aliases-not-covering.next.stderr rename tests/ui/coherence/{orphan-check-weak-aliases-not-covering.classic.stderr => orphan-check-weak-aliases-not-covering.stderr} (92%) delete mode 100644 tests/ui/coherence/skip-reporting-if-references-err.current.stderr delete mode 100644 tests/ui/coherence/skip-reporting-if-references-err.next.stderr diff --git a/tests/ui/coherence/coherence-overlap-downstream-inherent.old.stderr b/tests/ui/coherence/coherence-overlap-downstream-inherent.old.stderr deleted file mode 100644 index 2938bc629b2cc..0000000000000 --- a/tests/ui/coherence/coherence-overlap-downstream-inherent.old.stderr +++ /dev/null @@ -1,23 +0,0 @@ -error[E0592]: duplicate definitions with name `dummy` - --> $DIR/coherence-overlap-downstream-inherent.rs:10:26 - | -LL | impl Sweet { fn dummy(&self) { } } - | ^^^^^^^^^^^^^^^ duplicate definitions for `dummy` -LL | -LL | impl Sweet { fn dummy(&self) { } } - | --------------- other definition for `dummy` - -error[E0592]: duplicate definitions with name `f` - --> $DIR/coherence-overlap-downstream-inherent.rs:16:38 - | -LL | impl A where T: Bar { fn f(&self) {} } - | ^^^^^^^^^^^ duplicate definitions for `f` -LL | -LL | impl A { fn f(&self) {} } - | ----------- other definition for `f` - | - = note: downstream crates may implement trait `Bar<_>` for type `i32` - -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0592`. diff --git a/tests/ui/coherence/coherence-overlap-downstream-inherent.rs b/tests/ui/coherence/coherence-overlap-downstream-inherent.rs index 3e90b7c7fdd32..5dea33e330b62 100644 --- a/tests/ui/coherence/coherence-overlap-downstream-inherent.rs +++ b/tests/ui/coherence/coherence-overlap-downstream-inherent.rs @@ -1,6 +1,3 @@ -//@ revisions: old next -//@[next] compile-flags: -Znext-solver - // Tests that we consider `T: Sugar + Fruit` to be ambiguous, even // though no impls are found. diff --git a/tests/ui/coherence/coherence-overlap-downstream-inherent.next.stderr b/tests/ui/coherence/coherence-overlap-downstream-inherent.stderr similarity index 87% rename from tests/ui/coherence/coherence-overlap-downstream-inherent.next.stderr rename to tests/ui/coherence/coherence-overlap-downstream-inherent.stderr index 2938bc629b2cc..bbce4b530b4d6 100644 --- a/tests/ui/coherence/coherence-overlap-downstream-inherent.next.stderr +++ b/tests/ui/coherence/coherence-overlap-downstream-inherent.stderr @@ -1,5 +1,5 @@ error[E0592]: duplicate definitions with name `dummy` - --> $DIR/coherence-overlap-downstream-inherent.rs:10:26 + --> $DIR/coherence-overlap-downstream-inherent.rs:7:26 | LL | impl Sweet { fn dummy(&self) { } } | ^^^^^^^^^^^^^^^ duplicate definitions for `dummy` @@ -8,7 +8,7 @@ LL | impl Sweet { fn dummy(&self) { } } | --------------- other definition for `dummy` error[E0592]: duplicate definitions with name `f` - --> $DIR/coherence-overlap-downstream-inherent.rs:16:38 + --> $DIR/coherence-overlap-downstream-inherent.rs:13:38 | LL | impl A where T: Bar { fn f(&self) {} } | ^^^^^^^^^^^ duplicate definitions for `f` diff --git a/tests/ui/coherence/coherence-overlap-downstream.old.stderr b/tests/ui/coherence/coherence-overlap-downstream.old.stderr deleted file mode 100644 index 6c2e9466b4bde..0000000000000 --- a/tests/ui/coherence/coherence-overlap-downstream.old.stderr +++ /dev/null @@ -1,21 +0,0 @@ -error[E0119]: conflicting implementations of trait `Sweet` - --> $DIR/coherence-overlap-downstream.rs:11:1 - | -LL | impl Sweet for T { } - | ------------------------- first implementation here -LL | impl Sweet for T { } - | ^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation - -error[E0119]: conflicting implementations of trait `Foo<_>` for type `i32` - --> $DIR/coherence-overlap-downstream.rs:17:1 - | -LL | impl Foo for T where T: Bar {} - | --------------------------------------- first implementation here -LL | impl Foo for i32 {} - | ^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `i32` - | - = note: downstream crates may implement trait `Bar<_>` for type `i32` - -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/coherence/coherence-overlap-downstream.rs b/tests/ui/coherence/coherence-overlap-downstream.rs index 8b99296d12a4f..738ec0e3d4550 100644 --- a/tests/ui/coherence/coherence-overlap-downstream.rs +++ b/tests/ui/coherence/coherence-overlap-downstream.rs @@ -1,6 +1,3 @@ -//@ revisions: old next -//@[next] compile-flags: -Znext-solver - // Tests that we consider `T: Sugar + Fruit` to be ambiguous, even // though no impls are found. diff --git a/tests/ui/coherence/coherence-overlap-downstream.next.stderr b/tests/ui/coherence/coherence-overlap-downstream.stderr similarity index 88% rename from tests/ui/coherence/coherence-overlap-downstream.next.stderr rename to tests/ui/coherence/coherence-overlap-downstream.stderr index 6c2e9466b4bde..9ab099489d9e5 100644 --- a/tests/ui/coherence/coherence-overlap-downstream.next.stderr +++ b/tests/ui/coherence/coherence-overlap-downstream.stderr @@ -1,5 +1,5 @@ error[E0119]: conflicting implementations of trait `Sweet` - --> $DIR/coherence-overlap-downstream.rs:11:1 + --> $DIR/coherence-overlap-downstream.rs:8:1 | LL | impl Sweet for T { } | ------------------------- first implementation here @@ -7,7 +7,7 @@ LL | impl Sweet for T { } | ^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation error[E0119]: conflicting implementations of trait `Foo<_>` for type `i32` - --> $DIR/coherence-overlap-downstream.rs:17:1 + --> $DIR/coherence-overlap-downstream.rs:14:1 | LL | impl Foo for T where T: Bar {} | --------------------------------------- first implementation here diff --git a/tests/ui/coherence/coherence-overlap-issue-23516-inherent.old.stderr b/tests/ui/coherence/coherence-overlap-issue-23516-inherent.old.stderr deleted file mode 100644 index 2f3ad6278088f..0000000000000 --- a/tests/ui/coherence/coherence-overlap-issue-23516-inherent.old.stderr +++ /dev/null @@ -1,14 +0,0 @@ -error[E0592]: duplicate definitions with name `dummy` - --> $DIR/coherence-overlap-issue-23516-inherent.rs:12:25 - | -LL | impl Cake { fn dummy(&self) { } } - | ^^^^^^^^^^^^^^^ duplicate definitions for `dummy` -LL | -LL | impl Cake> { fn dummy(&self) { } } - | --------------- other definition for `dummy` - | - = note: downstream crates may implement trait `Sugar` for type `std::boxed::Box<_>` - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0592`. diff --git a/tests/ui/coherence/coherence-overlap-issue-23516-inherent.rs b/tests/ui/coherence/coherence-overlap-issue-23516-inherent.rs index 53b0a40fa6611..a272e620fcab3 100644 --- a/tests/ui/coherence/coherence-overlap-issue-23516-inherent.rs +++ b/tests/ui/coherence/coherence-overlap-issue-23516-inherent.rs @@ -1,6 +1,3 @@ -//@ revisions: old next -//@[next] compile-flags: -Znext-solver - // Tests that we consider `Box: !Sugar` to be ambiguous, even // though we see no impl of `Sugar` for `Box`. Therefore, an overlap // error is reported for the following pair of impls (#23516). diff --git a/tests/ui/coherence/coherence-overlap-issue-23516-inherent.next.stderr b/tests/ui/coherence/coherence-overlap-issue-23516-inherent.stderr similarity index 90% rename from tests/ui/coherence/coherence-overlap-issue-23516-inherent.next.stderr rename to tests/ui/coherence/coherence-overlap-issue-23516-inherent.stderr index 2f3ad6278088f..aacdeb5b0f971 100644 --- a/tests/ui/coherence/coherence-overlap-issue-23516-inherent.next.stderr +++ b/tests/ui/coherence/coherence-overlap-issue-23516-inherent.stderr @@ -1,5 +1,5 @@ error[E0592]: duplicate definitions with name `dummy` - --> $DIR/coherence-overlap-issue-23516-inherent.rs:12:25 + --> $DIR/coherence-overlap-issue-23516-inherent.rs:9:25 | LL | impl Cake { fn dummy(&self) { } } | ^^^^^^^^^^^^^^^ duplicate definitions for `dummy` diff --git a/tests/ui/coherence/coherence-overlap-issue-23516.old.stderr b/tests/ui/coherence/coherence-overlap-issue-23516.old.stderr deleted file mode 100644 index b949477402549..0000000000000 --- a/tests/ui/coherence/coherence-overlap-issue-23516.old.stderr +++ /dev/null @@ -1,13 +0,0 @@ -error[E0119]: conflicting implementations of trait `Sweet` for type `Box<_>` - --> $DIR/coherence-overlap-issue-23516.rs:11:1 - | -LL | impl Sweet for T { } - | ------------------------- first implementation here -LL | impl Sweet for Box { } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `Box<_>` - | - = note: downstream crates may implement trait `Sugar` for type `std::boxed::Box<_>` - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/coherence/coherence-overlap-issue-23516.rs b/tests/ui/coherence/coherence-overlap-issue-23516.rs index 620e00cd0572b..63e42e8f412dd 100644 --- a/tests/ui/coherence/coherence-overlap-issue-23516.rs +++ b/tests/ui/coherence/coherence-overlap-issue-23516.rs @@ -1,6 +1,3 @@ -//@ revisions: old next -//@[next] compile-flags: -Znext-solver - // Tests that we consider `Box: !Sugar` to be ambiguous, even // though we see no impl of `Sugar` for `Box`. Therefore, an overlap // error is reported for the following pair of impls (#23516). diff --git a/tests/ui/coherence/coherence-overlap-issue-23516.next.stderr b/tests/ui/coherence/coherence-overlap-issue-23516.stderr similarity index 90% rename from tests/ui/coherence/coherence-overlap-issue-23516.next.stderr rename to tests/ui/coherence/coherence-overlap-issue-23516.stderr index b949477402549..7b1b240291a87 100644 --- a/tests/ui/coherence/coherence-overlap-issue-23516.next.stderr +++ b/tests/ui/coherence/coherence-overlap-issue-23516.stderr @@ -1,5 +1,5 @@ error[E0119]: conflicting implementations of trait `Sweet` for type `Box<_>` - --> $DIR/coherence-overlap-issue-23516.rs:11:1 + --> $DIR/coherence-overlap-issue-23516.rs:8:1 | LL | impl Sweet for T { } | ------------------------- first implementation here diff --git a/tests/ui/coherence/coherence-overlap-unnormalizable-projection-0.next.stderr b/tests/ui/coherence/coherence-overlap-unnormalizable-projection-0.next.stderr deleted file mode 100644 index 99abdf65abd5f..0000000000000 --- a/tests/ui/coherence/coherence-overlap-unnormalizable-projection-0.next.stderr +++ /dev/null @@ -1,18 +0,0 @@ -error[E0119]: conflicting implementations of trait `Trait` for type `Box<_>` - --> $DIR/coherence-overlap-unnormalizable-projection-0.rs:27:1 - | -LL | / impl Trait for T -LL | | where -LL | | T: 'static, -LL | | for<'a> T: WithAssoc<'a>, -LL | | for<'a> >::Assoc: WhereBound, - | |____________________________________________________- first implementation here -... -LL | impl Trait for Box {} - | ^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `Box<_>` - | - = note: downstream crates may implement trait `WithAssoc<'a>` for type `std::boxed::Box<_>` - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/coherence/coherence-overlap-unnormalizable-projection-0.rs b/tests/ui/coherence/coherence-overlap-unnormalizable-projection-0.rs index b8b6d8846ef78..0695076e221e2 100644 --- a/tests/ui/coherence/coherence-overlap-unnormalizable-projection-0.rs +++ b/tests/ui/coherence/coherence-overlap-unnormalizable-projection-0.rs @@ -2,9 +2,6 @@ // "Coherence incorrectly considers `unnormalizable_projection: Trait` to not hold even if it could" #![crate_type = "lib"] -//@ revisions: classic next -//@[next] compile-flags: -Znext-solver - trait WhereBound {} impl WhereBound for () {} diff --git a/tests/ui/coherence/coherence-overlap-unnormalizable-projection-0.classic.stderr b/tests/ui/coherence/coherence-overlap-unnormalizable-projection-0.stderr similarity index 91% rename from tests/ui/coherence/coherence-overlap-unnormalizable-projection-0.classic.stderr rename to tests/ui/coherence/coherence-overlap-unnormalizable-projection-0.stderr index 99abdf65abd5f..57befbe6e68dd 100644 --- a/tests/ui/coherence/coherence-overlap-unnormalizable-projection-0.classic.stderr +++ b/tests/ui/coherence/coherence-overlap-unnormalizable-projection-0.stderr @@ -1,5 +1,5 @@ error[E0119]: conflicting implementations of trait `Trait` for type `Box<_>` - --> $DIR/coherence-overlap-unnormalizable-projection-0.rs:27:1 + --> $DIR/coherence-overlap-unnormalizable-projection-0.rs:24:1 | LL | / impl Trait for T LL | | where diff --git a/tests/ui/coherence/coherence-overlap-unnormalizable-projection-1.next.stderr b/tests/ui/coherence/coherence-overlap-unnormalizable-projection-1.next.stderr deleted file mode 100644 index 781ab0fcbf766..0000000000000 --- a/tests/ui/coherence/coherence-overlap-unnormalizable-projection-1.next.stderr +++ /dev/null @@ -1,19 +0,0 @@ -error[E0119]: conflicting implementations of trait `Trait` for type `Box<_>` - --> $DIR/coherence-overlap-unnormalizable-projection-1.rs:26:1 - | -LL | / impl Trait for T -LL | | where -LL | | T: 'static, -LL | | for<'a> T: WithAssoc<'a>, -LL | | for<'a> Box<>::Assoc>: WhereBound, - | |_________________________________________________________- first implementation here -... -LL | impl Trait for Box {} - | ^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `Box<_>` - | - = note: downstream crates may implement trait `WithAssoc<'a>` for type `std::boxed::Box<_>` - = note: downstream crates may implement trait `WhereBound` for type `std::boxed::Box<_>` - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/coherence/coherence-overlap-unnormalizable-projection-1.rs b/tests/ui/coherence/coherence-overlap-unnormalizable-projection-1.rs index 8eeadb3dc7542..f5fb5aefb5c39 100644 --- a/tests/ui/coherence/coherence-overlap-unnormalizable-projection-1.rs +++ b/tests/ui/coherence/coherence-overlap-unnormalizable-projection-1.rs @@ -2,9 +2,6 @@ // "Coherence incorrectly considers `unnormalizable_projection: Trait` to not hold even if it could" #![crate_type = "lib"] -//@ revisions: classic next -//@[next] compile-flags: -Znext-solver - pub trait WhereBound {} impl WhereBound for () {} diff --git a/tests/ui/coherence/coherence-overlap-unnormalizable-projection-1.classic.stderr b/tests/ui/coherence/coherence-overlap-unnormalizable-projection-1.stderr similarity index 92% rename from tests/ui/coherence/coherence-overlap-unnormalizable-projection-1.classic.stderr rename to tests/ui/coherence/coherence-overlap-unnormalizable-projection-1.stderr index 781ab0fcbf766..22673cef64079 100644 --- a/tests/ui/coherence/coherence-overlap-unnormalizable-projection-1.classic.stderr +++ b/tests/ui/coherence/coherence-overlap-unnormalizable-projection-1.stderr @@ -1,5 +1,5 @@ error[E0119]: conflicting implementations of trait `Trait` for type `Box<_>` - --> $DIR/coherence-overlap-unnormalizable-projection-1.rs:26:1 + --> $DIR/coherence-overlap-unnormalizable-projection-1.rs:23:1 | LL | / impl Trait for T LL | | where diff --git a/tests/ui/coherence/coherent-due-to-fulfill.rs b/tests/ui/coherence/coherent-due-to-fulfill.rs index 084f9be0a8c3f..f4555ee5171cb 100644 --- a/tests/ui/coherence/coherent-due-to-fulfill.rs +++ b/tests/ui/coherence/coherent-due-to-fulfill.rs @@ -1,6 +1,4 @@ -//@ compile-flags: -Znext-solver=coherence //@ check-pass - trait Mirror { type Assoc; } diff --git a/tests/ui/coherence/incoherent-even-though-we-fulfill.rs b/tests/ui/coherence/incoherent-even-though-we-fulfill.rs index b3c9cf328c21c..28e5b6d3db09b 100644 --- a/tests/ui/coherence/incoherent-even-though-we-fulfill.rs +++ b/tests/ui/coherence/incoherent-even-though-we-fulfill.rs @@ -1,5 +1,3 @@ -//@ compile-flags: -Znext-solver=coherence - trait Mirror { type Assoc; } diff --git a/tests/ui/coherence/incoherent-even-though-we-fulfill.stderr b/tests/ui/coherence/incoherent-even-though-we-fulfill.stderr index b16465d201140..0b15a4e100ed1 100644 --- a/tests/ui/coherence/incoherent-even-though-we-fulfill.stderr +++ b/tests/ui/coherence/incoherent-even-though-we-fulfill.stderr @@ -1,5 +1,5 @@ error[E0119]: conflicting implementations of trait `Foo` for type `()` - --> $DIR/incoherent-even-though-we-fulfill.rs:17:1 + --> $DIR/incoherent-even-though-we-fulfill.rs:15:1 | LL | impl Foo for T where (): Mirror {} | --------------------------------------------- first implementation here diff --git a/tests/ui/coherence/inter-crate-ambiguity-causes-notes.old.stderr b/tests/ui/coherence/inter-crate-ambiguity-causes-notes.old.stderr deleted file mode 100644 index 74be598c44c76..0000000000000 --- a/tests/ui/coherence/inter-crate-ambiguity-causes-notes.old.stderr +++ /dev/null @@ -1,17 +0,0 @@ -error[E0119]: conflicting implementations of trait `From<()>` for type `S` - --> $DIR/inter-crate-ambiguity-causes-notes.rs:12:1 - | -LL | impl From<()> for S { - | ------------------- first implementation here -... -LL | / impl From for S -LL | | -LL | | where -LL | | I: Iterator, - | |___________________________^ conflicting implementation for `S` - | - = note: upstream crates may add a new impl of trait `std::iter::Iterator` for type `()` in future versions - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/coherence/inter-crate-ambiguity-causes-notes.rs b/tests/ui/coherence/inter-crate-ambiguity-causes-notes.rs index 3dead2f0d19ce..5b11c78ab2605 100644 --- a/tests/ui/coherence/inter-crate-ambiguity-causes-notes.rs +++ b/tests/ui/coherence/inter-crate-ambiguity-causes-notes.rs @@ -1,6 +1,3 @@ -//@ revisions: old next -//@[next] compile-flags: -Znext-solver - struct S; impl From<()> for S { diff --git a/tests/ui/coherence/inter-crate-ambiguity-causes-notes.next.stderr b/tests/ui/coherence/inter-crate-ambiguity-causes-notes.stderr similarity index 90% rename from tests/ui/coherence/inter-crate-ambiguity-causes-notes.next.stderr rename to tests/ui/coherence/inter-crate-ambiguity-causes-notes.stderr index 74be598c44c76..b32283274c699 100644 --- a/tests/ui/coherence/inter-crate-ambiguity-causes-notes.next.stderr +++ b/tests/ui/coherence/inter-crate-ambiguity-causes-notes.stderr @@ -1,5 +1,5 @@ error[E0119]: conflicting implementations of trait `From<()>` for type `S` - --> $DIR/inter-crate-ambiguity-causes-notes.rs:12:1 + --> $DIR/inter-crate-ambiguity-causes-notes.rs:9:1 | LL | impl From<()> for S { | ------------------- first implementation here diff --git a/tests/ui/coherence/normalize-for-errors.current.stderr b/tests/ui/coherence/normalize-for-errors.current.stderr deleted file mode 100644 index 634a10b7a14c3..0000000000000 --- a/tests/ui/coherence/normalize-for-errors.current.stderr +++ /dev/null @@ -1,15 +0,0 @@ -error[E0119]: conflicting implementations of trait `MyTrait<_>` for type `(Box<(MyType,)>, <_ as Iterator>::Item)` - --> $DIR/normalize-for-errors.rs:17:1 - | -LL | impl MyTrait for (T, S::Item) {} - | ------------------------------------------------------ first implementation here -LL | -LL | impl MyTrait for (Box<<(MyType,) as Mirror>::Assoc>, S::Item) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(Box<(MyType,)>, <_ as Iterator>::Item)` - | - = note: upstream crates may add a new impl of trait `std::clone::Clone` for type `(MyType,)` in future versions - = note: upstream crates may add a new impl of trait `std::marker::Copy` for type `std::boxed::Box<(MyType,)>` in future versions - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/coherence/normalize-for-errors.next.stderr b/tests/ui/coherence/normalize-for-errors.next.stderr deleted file mode 100644 index 44952dc194456..0000000000000 --- a/tests/ui/coherence/normalize-for-errors.next.stderr +++ /dev/null @@ -1,15 +0,0 @@ -error[E0119]: conflicting implementations of trait `MyTrait<_>` for type `(Box<(MyType,)>, <_ as Iterator>::Item)` - --> $DIR/normalize-for-errors.rs:17:1 - | -LL | impl MyTrait for (T, S::Item) {} - | ------------------------------------------------------ first implementation here -LL | -LL | impl MyTrait for (Box<<(MyType,) as Mirror>::Assoc>, S::Item) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(Box<(MyType,)>, <_ as Iterator>::Item)` - | - = note: upstream crates may add a new impl of trait `std::clone::Clone` for type `std::boxed::Box<(MyType,)>` in future versions - = note: upstream crates may add a new impl of trait `std::marker::Copy` for type `std::boxed::Box<(MyType,)>` in future versions - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/coherence/occurs-check/associated-type.next.stderr b/tests/ui/coherence/occurs-check/associated-type.next.stderr index 9544bdbb468de..466b991471ed9 100644 --- a/tests/ui/coherence/occurs-check/associated-type.next.stderr +++ b/tests/ui/coherence/occurs-check/associated-type.next.stderr @@ -3,7 +3,7 @@ WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [*const ?1t, '^0.Named(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), "'a")], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit), .. } WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [*const ?1t, '^0.Named(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), "'a")], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit), .. } error[E0119]: conflicting implementations of trait `Overlap fn(&'a (), ())>` for type `for<'a> fn(&'a (), ())` - --> $DIR/associated-type.rs:31:1 + --> $DIR/associated-type.rs:32:1 | LL | impl Overlap for T { | ------------------------ first implementation here @@ -17,7 +17,7 @@ LL | | for<'a> *const T: ToUnit<'a>, = note: this behavior recently changed as a result of a bug fix; see rust-lang/rust#56105 for details error[E0284]: type annotations needed: cannot normalize ` fn(&'a (), ()) as Overlap fn(&'a (), ())>>::Assoc` - --> $DIR/associated-type.rs:44:59 + --> $DIR/associated-type.rs:45:59 | LL | foo:: fn(&'a (), ()), for<'a> fn(&'a (), ())>(3usize); | ^^^^^^ cannot normalize ` fn(&'a (), ()) as Overlap fn(&'a (), ())>>::Assoc` diff --git a/tests/ui/coherence/occurs-check/associated-type.old.stderr b/tests/ui/coherence/occurs-check/associated-type.old.stderr index 6a4c6fe54a831..1e0345f4ec05b 100644 --- a/tests/ui/coherence/occurs-check/associated-type.old.stderr +++ b/tests/ui/coherence/occurs-check/associated-type.old.stderr @@ -3,7 +3,7 @@ WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [*const ?1t, '^0.Named(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), "'a")], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit), .. } WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [*const ?1t, '^0.Named(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), "'a")], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit), .. } error[E0119]: conflicting implementations of trait `Overlap fn(&'a (), ())>` for type `for<'a> fn(&'a (), ())` - --> $DIR/associated-type.rs:31:1 + --> $DIR/associated-type.rs:32:1 | LL | impl Overlap for T { | ------------------------ first implementation here diff --git a/tests/ui/coherence/occurs-check/associated-type.rs b/tests/ui/coherence/occurs-check/associated-type.rs index df03d5f60a028..e450c33e80934 100644 --- a/tests/ui/coherence/occurs-check/associated-type.rs +++ b/tests/ui/coherence/occurs-check/associated-type.rs @@ -1,4 +1,5 @@ //@ revisions: old next +//@ ignore-compare-mode-next-solver (explicit revisions) //@[next] compile-flags: -Znext-solver // A regression test for #105787 diff --git a/tests/ui/coherence/occurs-check/opaques.current.stderr b/tests/ui/coherence/occurs-check/opaques.current.stderr index 96ef7cd4322b5..f3fc22027c26a 100644 --- a/tests/ui/coherence/occurs-check/opaques.current.stderr +++ b/tests/ui/coherence/occurs-check/opaques.current.stderr @@ -1,5 +1,5 @@ error[E0119]: conflicting implementations of trait `Trait<_>` - --> $DIR/opaques.rs:27:1 + --> $DIR/opaques.rs:28:1 | LL | impl Trait for T { | ---------------------- first implementation here diff --git a/tests/ui/coherence/occurs-check/opaques.next.stderr b/tests/ui/coherence/occurs-check/opaques.next.stderr index 5b8eb822d2585..3de479963bb44 100644 --- a/tests/ui/coherence/occurs-check/opaques.next.stderr +++ b/tests/ui/coherence/occurs-check/opaques.next.stderr @@ -1,5 +1,5 @@ error[E0119]: conflicting implementations of trait `Trait<_>` - --> $DIR/opaques.rs:27:1 + --> $DIR/opaques.rs:28:1 | LL | impl Trait for T { | ---------------------- first implementation here @@ -8,7 +8,7 @@ LL | impl Trait for defining_scope::Alias { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation error[E0282]: type annotations needed - --> $DIR/opaques.rs:10:20 + --> $DIR/opaques.rs:11:20 | LL | pub fn cast(x: Container, T>) -> Container { | ^ cannot infer type diff --git a/tests/ui/coherence/occurs-check/opaques.rs b/tests/ui/coherence/occurs-check/opaques.rs index d7032dd53d977..e197256c78c77 100644 --- a/tests/ui/coherence/occurs-check/opaques.rs +++ b/tests/ui/coherence/occurs-check/opaques.rs @@ -1,4 +1,5 @@ -//@revisions: current next +//@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) //@[next] compile-flags: -Znext-solver // A regression test for #105787 diff --git a/tests/ui/coherence/orphan-check-opaque-types-not-covering.next.stderr b/tests/ui/coherence/orphan-check-opaque-types-not-covering.next.stderr deleted file mode 100644 index 44f76f321cf10..0000000000000 --- a/tests/ui/coherence/orphan-check-opaque-types-not-covering.next.stderr +++ /dev/null @@ -1,21 +0,0 @@ -error[E0210]: type parameter `T` must be covered by another type when it appears before the first local type (`Local`) - --> $DIR/orphan-check-opaque-types-not-covering.rs:17:6 - | -LL | impl foreign::Trait0 for Identity {} - | ^ type parameter `T` must be covered by another type when it appears before the first local type (`Local`) - | - = note: implementing a foreign trait is only possible if at least one of the types for which it is implemented is local, and no uncovered type parameters appear before that first local type - = note: in this case, 'before' refers to the following order: `impl<..> ForeignTrait for T0`, where `T0` is the first and `Tn` is the last - -error[E0210]: type parameter `T` must be covered by another type when it appears before the first local type (`Local`) - --> $DIR/orphan-check-opaque-types-not-covering.rs:26:6 - | -LL | impl foreign::Trait1 for Opaque {} - | ^ type parameter `T` must be covered by another type when it appears before the first local type (`Local`) - | - = note: implementing a foreign trait is only possible if at least one of the types for which it is implemented is local, and no uncovered type parameters appear before that first local type - = note: in this case, 'before' refers to the following order: `impl<..> ForeignTrait for T0`, where `T0` is the first and `Tn` is the last - -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0210`. diff --git a/tests/ui/coherence/orphan-check-opaque-types-not-covering.rs b/tests/ui/coherence/orphan-check-opaque-types-not-covering.rs index 8dc02b081c51d..02e9eb65570c0 100644 --- a/tests/ui/coherence/orphan-check-opaque-types-not-covering.rs +++ b/tests/ui/coherence/orphan-check-opaque-types-not-covering.rs @@ -1,8 +1,5 @@ // Opaque types never cover type parameters. -//@ revisions: classic next -//@[next] compile-flags: -Znext-solver - //@ aux-crate:foreign=parametrized-trait.rs //@ edition:2021 diff --git a/tests/ui/coherence/orphan-check-opaque-types-not-covering.classic.stderr b/tests/ui/coherence/orphan-check-opaque-types-not-covering.stderr similarity index 92% rename from tests/ui/coherence/orphan-check-opaque-types-not-covering.classic.stderr rename to tests/ui/coherence/orphan-check-opaque-types-not-covering.stderr index 44f76f321cf10..57f5bbd227875 100644 --- a/tests/ui/coherence/orphan-check-opaque-types-not-covering.classic.stderr +++ b/tests/ui/coherence/orphan-check-opaque-types-not-covering.stderr @@ -1,5 +1,5 @@ error[E0210]: type parameter `T` must be covered by another type when it appears before the first local type (`Local`) - --> $DIR/orphan-check-opaque-types-not-covering.rs:17:6 + --> $DIR/orphan-check-opaque-types-not-covering.rs:14:6 | LL | impl foreign::Trait0 for Identity {} | ^ type parameter `T` must be covered by another type when it appears before the first local type (`Local`) @@ -8,7 +8,7 @@ LL | impl foreign::Trait0 for Identity {} = note: in this case, 'before' refers to the following order: `impl<..> ForeignTrait for T0`, where `T0` is the first and `Tn` is the last error[E0210]: type parameter `T` must be covered by another type when it appears before the first local type (`Local`) - --> $DIR/orphan-check-opaque-types-not-covering.rs:26:6 + --> $DIR/orphan-check-opaque-types-not-covering.rs:23:6 | LL | impl foreign::Trait1 for Opaque {} | ^ type parameter `T` must be covered by another type when it appears before the first local type (`Local`) diff --git a/tests/ui/coherence/orphan-check-projections-covering.rs b/tests/ui/coherence/orphan-check-projections-covering.rs index ae1917ec161f1..804784463a1b5 100644 --- a/tests/ui/coherence/orphan-check-projections-covering.rs +++ b/tests/ui/coherence/orphan-check-projections-covering.rs @@ -5,9 +5,6 @@ // first which would've lead to real-word regressions. //@ check-pass -//@ revisions: classic next -//@[next] compile-flags: -Znext-solver - //@ aux-crate:foreign=parametrized-trait.rs //@ edition:2021 diff --git a/tests/ui/coherence/orphan-check-weak-aliases-not-covering.next.stderr b/tests/ui/coherence/orphan-check-weak-aliases-not-covering.next.stderr deleted file mode 100644 index 276833fa17122..0000000000000 --- a/tests/ui/coherence/orphan-check-weak-aliases-not-covering.next.stderr +++ /dev/null @@ -1,12 +0,0 @@ -error[E0210]: type parameter `T` must be covered by another type when it appears before the first local type (`Local`) - --> $DIR/orphan-check-weak-aliases-not-covering.rs:16:6 - | -LL | impl foreign::Trait1 for Identity {} - | ^ type parameter `T` must be covered by another type when it appears before the first local type (`Local`) - | - = note: implementing a foreign trait is only possible if at least one of the types for which it is implemented is local, and no uncovered type parameters appear before that first local type - = note: in this case, 'before' refers to the following order: `impl<..> ForeignTrait for T0`, where `T0` is the first and `Tn` is the last - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0210`. diff --git a/tests/ui/coherence/orphan-check-weak-aliases-not-covering.rs b/tests/ui/coherence/orphan-check-weak-aliases-not-covering.rs index 9ebc45a882937..6d9bccc4c689e 100644 --- a/tests/ui/coherence/orphan-check-weak-aliases-not-covering.rs +++ b/tests/ui/coherence/orphan-check-weak-aliases-not-covering.rs @@ -1,8 +1,5 @@ // Weak aliases might not cover type parameters. -//@ revisions: classic next -//@[next] compile-flags: -Znext-solver - //@ aux-crate:foreign=parametrized-trait.rs //@ edition:2021 diff --git a/tests/ui/coherence/orphan-check-weak-aliases-not-covering.classic.stderr b/tests/ui/coherence/orphan-check-weak-aliases-not-covering.stderr similarity index 92% rename from tests/ui/coherence/orphan-check-weak-aliases-not-covering.classic.stderr rename to tests/ui/coherence/orphan-check-weak-aliases-not-covering.stderr index 276833fa17122..df915141a769f 100644 --- a/tests/ui/coherence/orphan-check-weak-aliases-not-covering.classic.stderr +++ b/tests/ui/coherence/orphan-check-weak-aliases-not-covering.stderr @@ -1,5 +1,5 @@ error[E0210]: type parameter `T` must be covered by another type when it appears before the first local type (`Local`) - --> $DIR/orphan-check-weak-aliases-not-covering.rs:16:6 + --> $DIR/orphan-check-weak-aliases-not-covering.rs:13:6 | LL | impl foreign::Trait1 for Identity {} | ^ type parameter `T` must be covered by another type when it appears before the first local type (`Local`) diff --git a/tests/ui/coherence/skip-reporting-if-references-err.current.stderr b/tests/ui/coherence/skip-reporting-if-references-err.current.stderr deleted file mode 100644 index 5de4cf626e481..0000000000000 --- a/tests/ui/coherence/skip-reporting-if-references-err.current.stderr +++ /dev/null @@ -1,14 +0,0 @@ -error[E0726]: implicit elided lifetime not allowed here - --> $DIR/skip-reporting-if-references-err.rs:10:9 - | -LL | impl ToUnit for T {} - | ^^^^^^ expected lifetime parameter - | -help: indicate the anonymous lifetime - | -LL | impl ToUnit<'_> for T {} - | ++++ - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0726`. diff --git a/tests/ui/coherence/skip-reporting-if-references-err.next.stderr b/tests/ui/coherence/skip-reporting-if-references-err.next.stderr deleted file mode 100644 index 5de4cf626e481..0000000000000 --- a/tests/ui/coherence/skip-reporting-if-references-err.next.stderr +++ /dev/null @@ -1,14 +0,0 @@ -error[E0726]: implicit elided lifetime not allowed here - --> $DIR/skip-reporting-if-references-err.rs:10:9 - | -LL | impl ToUnit for T {} - | ^^^^^^ expected lifetime parameter - | -help: indicate the anonymous lifetime - | -LL | impl ToUnit<'_> for T {} - | ++++ - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0726`. diff --git a/tests/ui/coherence/super-traits/super-trait-knowable-2.rs b/tests/ui/coherence/super-traits/super-trait-knowable-2.rs index d1f2e8d1c1a15..323ee0b10c9f4 100644 --- a/tests/ui/coherence/super-traits/super-trait-knowable-2.rs +++ b/tests/ui/coherence/super-traits/super-trait-knowable-2.rs @@ -9,9 +9,6 @@ // which caused the old solver to emit a `Tensor: TensorValue` goal in // `fn normalize_to_error` which then failed, causing this test to pass. -//@ revisions: current next -//@ ignore-compare-mode-next-solver (explicit revisions) -//@[next] compile-flags: -Znext-solver //@ check-pass pub trait TensorValue { From a138a9261536ac2bdbb7c01a8aa9dc7d43299cae Mon Sep 17 00:00:00 2001 From: lcnr Date: Thu, 5 Sep 2024 07:54:13 +0000 Subject: [PATCH 0515/2194] update test description --- .../leak-check/leak-check-in-selection-5-ambig.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/ui/higher-ranked/leak-check/leak-check-in-selection-5-ambig.rs b/tests/ui/higher-ranked/leak-check/leak-check-in-selection-5-ambig.rs index beda719ac208a..9a44fd2e64a3e 100644 --- a/tests/ui/higher-ranked/leak-check/leak-check-in-selection-5-ambig.rs +++ b/tests/ui/higher-ranked/leak-check/leak-check-in-selection-5-ambig.rs @@ -3,9 +3,9 @@ //@ check-pass // The new trait solver does not return region constraints if the goal -// is still ambiguous. This causes the following test to fail with ambiguity, -// even though `(): LeakCheckFailure<'!a, V>` would return `'!a: 'static` -// which would have caused a leak check failure. +// is still ambiguous. However, the `'!a = 'static` constraint from +// `(): LeakCheckFailure<'!a, V>` is also returned via the canonical +// var values, causing this test to compile. trait Ambig {} impl Ambig for u32 {} From 1328b52e9150c1ef6193528f137e31bd89223cde Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Sun, 1 Sep 2024 15:17:52 +0200 Subject: [PATCH 0516/2194] Lower asm expressions --- .../crates/hir-def/src/body/lower.rs | 15 +- .../crates/hir-def/src/body/lower/asm.rs | 230 ++++++++++++++++++ .../rust-analyzer/crates/hir-def/src/hir.rs | 132 +++++++++- .../macro_expansion_tests/builtin_fn_macro.rs | 6 +- .../crates/hir-expand/src/builtin/fn_macro.rs | 34 +-- .../crates/hir-ty/src/infer/closure.rs | 23 +- .../crates/hir-ty/src/infer/expr.rs | 67 ++++- .../crates/hir-ty/src/infer/mutability.rs | 27 +- .../crates/hir-ty/src/tests/macros.rs | 99 +++++++- .../rust-analyzer/crates/hir/src/semantics.rs | 1 - .../test_data/highlight_strings.html | 8 +- .../parser/src/grammar/expressions/atom.rs | 38 ++- .../rust-analyzer/crates/syntax/rust.ungram | 8 +- .../crates/syntax/src/ast/generated/nodes.rs | 21 +- 14 files changed, 612 insertions(+), 97 deletions(-) create mode 100644 src/tools/rust-analyzer/crates/hir-def/src/body/lower/asm.rs diff --git a/src/tools/rust-analyzer/crates/hir-def/src/body/lower.rs b/src/tools/rust-analyzer/crates/hir-def/src/body/lower.rs index f2eb43beb1f18..dfcb8b81204d2 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/body/lower.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/body/lower.rs @@ -1,6 +1,8 @@ //! Transforms `ast::Expr` into an equivalent `hir_def::expr::Expr` //! representation. +mod asm; + use std::mem; use base_db::CrateId; @@ -35,8 +37,8 @@ use crate::{ FormatPlaceholder, FormatSign, FormatTrait, }, Array, Binding, BindingAnnotation, BindingId, BindingProblems, CaptureBy, ClosureKind, - Expr, ExprId, InlineAsm, Label, LabelId, Literal, LiteralOrConst, MatchArm, Movability, - OffsetOf, Pat, PatId, RecordFieldPat, RecordLitField, Statement, + Expr, ExprId, Label, LabelId, Literal, LiteralOrConst, MatchArm, Movability, OffsetOf, Pat, + PatId, RecordFieldPat, RecordLitField, Statement, }, item_scope::BuiltinShadowMode, lang_item::LangItem, @@ -693,13 +695,7 @@ impl ExprCollector<'_> { } } ast::Expr::UnderscoreExpr(_) => self.alloc_expr(Expr::Underscore, syntax_ptr), - ast::Expr::AsmExpr(e) => { - let template = e.template().map(|it| self.collect_expr(it)).collect(); - self.alloc_expr( - Expr::InlineAsm(InlineAsm { template, operands: Box::default() }), - syntax_ptr, - ) - } + ast::Expr::AsmExpr(e) => self.lower_inline_asm(e, syntax_ptr), ast::Expr::OffsetOfExpr(e) => { let container = Interned::new(TypeRef::from_ast_opt(&self.ctx(), e.ty())); let fields = e.fields().map(|it| it.as_name()).collect(); @@ -2064,6 +2060,7 @@ impl ExprCollector<'_> { is_assignee_expr: false, }) } + // endregion: format fn lang_path(&self, lang: LangItem) -> Option { diff --git a/src/tools/rust-analyzer/crates/hir-def/src/body/lower/asm.rs b/src/tools/rust-analyzer/crates/hir-def/src/body/lower/asm.rs new file mode 100644 index 0000000000000..dafa3a859debd --- /dev/null +++ b/src/tools/rust-analyzer/crates/hir-def/src/body/lower/asm.rs @@ -0,0 +1,230 @@ +use hir_expand::name::Name; +use intern::Symbol; +use rustc_hash::{FxHashMap, FxHashSet}; +use syntax::{ + ast::{self, HasName, IsString}, + AstNode, AstPtr, AstToken, T, +}; +use tt::{TextRange, TextSize}; + +use crate::{ + body::lower::{ExprCollector, FxIndexSet}, + hir::{AsmOperand, AsmOptions, Expr, ExprId, InlineAsm, InlineAsmRegOrRegClass}, +}; + +impl ExprCollector<'_> { + pub(super) fn lower_inline_asm( + &mut self, + asm: ast::AsmExpr, + syntax_ptr: AstPtr, + ) -> ExprId { + let mut clobber_abis = FxIndexSet::default(); + let mut operands = vec![]; + let mut options = AsmOptions::empty(); + + let mut named_pos: FxHashMap = Default::default(); + let mut named_args: FxHashMap = Default::default(); + let mut reg_args: FxHashSet = Default::default(); + for operand in asm.asm_operands() { + let slot = operands.len(); + let mut lower_reg = |reg: Option| { + let reg = reg?; + if let Some(string) = reg.string_token() { + reg_args.insert(slot); + Some(InlineAsmRegOrRegClass::Reg(Symbol::intern(string.text()))) + } else { + reg.name_ref().map(|name_ref| { + InlineAsmRegOrRegClass::RegClass(Symbol::intern(&name_ref.text())) + }) + } + }; + + let op = match operand { + ast::AsmOperand::AsmClobberAbi(clobber_abi) => { + if let Some(abi_name) = clobber_abi.string_token() { + clobber_abis.insert(Symbol::intern(abi_name.text())); + } + continue; + } + ast::AsmOperand::AsmOptions(opt) => { + opt.asm_options().for_each(|opt| { + options |= match opt.syntax().first_token().map_or(T![$], |it| it.kind()) { + T![att_syntax] => AsmOptions::ATT_SYNTAX, + T![may_unwind] => AsmOptions::MAY_UNWIND, + T![nomem] => AsmOptions::NOMEM, + T![noreturn] => AsmOptions::NORETURN, + T![nostack] => AsmOptions::NOSTACK, + T![preserves_flags] => AsmOptions::PRESERVES_FLAGS, + T![pure] => AsmOptions::PURE, + T![raw] => AsmOptions::RAW, + T![readonly] => AsmOptions::READONLY, + _ => return, + } + }); + continue; + } + ast::AsmOperand::AsmRegOperand(op) => { + let Some(dir_spec) = op.asm_dir_spec() else { + continue; + }; + let Some(reg) = lower_reg(op.asm_reg_spec()) else { + continue; + }; + if let Some(name) = op.name() { + let sym = Symbol::intern(&name.text()); + named_args.insert(sym.clone(), slot); + named_pos.insert(slot, sym); + } + if dir_spec.in_token().is_some() { + let expr = self + .collect_expr_opt(op.asm_operand_expr().and_then(|it| it.in_expr())); + AsmOperand::In { reg, expr } + } else if dir_spec.out_token().is_some() { + let expr = self + .collect_expr_opt(op.asm_operand_expr().and_then(|it| it.in_expr())); + AsmOperand::Out { reg, expr: Some(expr), late: false } + } else if dir_spec.lateout_token().is_some() { + let expr = self + .collect_expr_opt(op.asm_operand_expr().and_then(|it| it.in_expr())); + AsmOperand::Out { reg, expr: Some(expr), late: true } + } else if dir_spec.inout_token().is_some() { + let Some(op_expr) = op.asm_operand_expr() else { continue }; + let in_expr = self.collect_expr_opt(op_expr.in_expr()); + let out_expr = op_expr.out_expr().map(|it| self.collect_expr(it)); + match out_expr { + Some(out_expr) => AsmOperand::SplitInOut { + reg, + in_expr, + out_expr: Some(out_expr), + late: false, + }, + None => AsmOperand::InOut { reg, expr: in_expr, late: false }, + } + } else if dir_spec.inlateout_token().is_some() { + let Some(op_expr) = op.asm_operand_expr() else { continue }; + let in_expr = self.collect_expr_opt(op_expr.in_expr()); + let out_expr = op_expr.out_expr().map(|it| self.collect_expr(it)); + match out_expr { + Some(out_expr) => AsmOperand::SplitInOut { + reg, + in_expr, + out_expr: Some(out_expr), + late: false, + }, + None => AsmOperand::InOut { reg, expr: in_expr, late: false }, + } + } else { + continue; + } + } + ast::AsmOperand::AsmLabel(l) => { + AsmOperand::Label(self.collect_block_opt(l.block_expr())) + } + ast::AsmOperand::AsmConst(c) => AsmOperand::Const(self.collect_expr_opt(c.expr())), + ast::AsmOperand::AsmSym(s) => { + let Some(path) = s.path().and_then(|p| self.expander.parse_path(self.db, p)) + else { + continue; + }; + AsmOperand::Sym(path) + } + }; + operands.push(op); + } + + let mut mappings = vec![]; + let mut curarg = 0; + if !options.contains(AsmOptions::RAW) { + // Don't treat raw asm as a format string. + asm.template() + .filter_map(|it| Some((it.clone(), self.expand_macros_to_string(it)?))) + .for_each(|(expr, (s, is_direct_literal))| { + let Ok(text) = s.value() else { + return; + }; + let template_snippet = match expr { + ast::Expr::Literal(literal) => match literal.kind() { + ast::LiteralKind::String(s) => Some(s.text().to_owned()), + _ => None, + }, + _ => None, + }; + let str_style = match s.quote_offsets() { + Some(offsets) => { + let raw = usize::from(offsets.quotes.0.len()) - 1; + // subtract 1 for the `r` prefix + (raw != 0).then(|| raw - 1) + } + None => None, + }; + + let mut parser = rustc_parse_format::Parser::new( + &text, + str_style, + template_snippet, + false, + rustc_parse_format::ParseMode::InlineAsm, + ); + parser.curarg = curarg; + + let mut unverified_pieces = Vec::new(); + while let Some(piece) = parser.next() { + if !parser.errors.is_empty() { + break; + } else { + unverified_pieces.push(piece); + } + } + + curarg = parser.curarg; + + let to_span = |inner_span: rustc_parse_format::InnerSpan| { + is_direct_literal.then(|| { + TextRange::new( + inner_span.start.try_into().unwrap(), + inner_span.end.try_into().unwrap(), + ) - TextSize::from(str_style.map(|it| it + 1).unwrap_or(0) as u32 + 1) + }) + }; + for piece in unverified_pieces { + match piece { + rustc_parse_format::Piece::String(_) => {} + rustc_parse_format::Piece::NextArgument(arg) => { + // let span = arg_spans.next(); + + let _operand_idx = match arg.position { + rustc_parse_format::ArgumentIs(idx) + | rustc_parse_format::ArgumentImplicitlyIs(idx) => { + if idx >= operands.len() + || named_pos.contains_key(&idx) + || reg_args.contains(&idx) + { + None + } else { + Some(idx) + } + } + rustc_parse_format::ArgumentNamed(name) => { + let name = Symbol::intern(name); + if let Some(position_span) = to_span(arg.position_span) { + mappings.push(( + position_span, + Name::new_symbol_root(name.clone()), + )); + } + named_args.get(&name).copied() + } + }; + } + } + } + }) + }; + let idx = self.alloc_expr( + Expr::InlineAsm(InlineAsm { operands: operands.into_boxed_slice(), options }), + syntax_ptr, + ); + self.source_map.format_args_template_map.insert(idx, mappings); + idx + } +} diff --git a/src/tools/rust-analyzer/crates/hir-def/src/hir.rs b/src/tools/rust-analyzer/crates/hir-def/src/hir.rs index 8f537672b58d4..7d2c573ebfed4 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/hir.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/hir.rs @@ -307,8 +307,120 @@ pub struct OffsetOf { #[derive(Debug, Clone, PartialEq, Eq)] pub struct InlineAsm { - pub template: Box<[ExprId]>, - pub operands: Box<[()]>, + pub operands: Box<[AsmOperand]>, + pub options: AsmOptions, +} + +#[derive(Clone, Copy, PartialEq, Eq, Hash)] +pub struct AsmOptions(u16); +bitflags::bitflags! { + impl AsmOptions: u16 { + const PURE = 1 << 0; + const NOMEM = 1 << 1; + const READONLY = 1 << 2; + const PRESERVES_FLAGS = 1 << 3; + const NORETURN = 1 << 4; + const NOSTACK = 1 << 5; + const ATT_SYNTAX = 1 << 6; + const RAW = 1 << 7; + const MAY_UNWIND = 1 << 8; + } +} + +impl AsmOptions { + pub const COUNT: usize = Self::all().bits().count_ones() as usize; + + pub const GLOBAL_OPTIONS: Self = Self::ATT_SYNTAX.union(Self::RAW); + pub const NAKED_OPTIONS: Self = Self::ATT_SYNTAX.union(Self::RAW).union(Self::NORETURN); + + pub fn human_readable_names(&self) -> Vec<&'static str> { + let mut options = vec![]; + + if self.contains(AsmOptions::PURE) { + options.push("pure"); + } + if self.contains(AsmOptions::NOMEM) { + options.push("nomem"); + } + if self.contains(AsmOptions::READONLY) { + options.push("readonly"); + } + if self.contains(AsmOptions::PRESERVES_FLAGS) { + options.push("preserves_flags"); + } + if self.contains(AsmOptions::NORETURN) { + options.push("noreturn"); + } + if self.contains(AsmOptions::NOSTACK) { + options.push("nostack"); + } + if self.contains(AsmOptions::ATT_SYNTAX) { + options.push("att_syntax"); + } + if self.contains(AsmOptions::RAW) { + options.push("raw"); + } + if self.contains(AsmOptions::MAY_UNWIND) { + options.push("may_unwind"); + } + + options + } +} + +impl std::fmt::Debug for AsmOptions { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + bitflags::parser::to_writer(self, f) + } +} + +#[derive(Clone, Debug, Eq, PartialEq, Hash)] +pub enum AsmOperand { + In { + reg: InlineAsmRegOrRegClass, + expr: ExprId, + }, + Out { + reg: InlineAsmRegOrRegClass, + expr: Option, + late: bool, + }, + InOut { + reg: InlineAsmRegOrRegClass, + expr: ExprId, + late: bool, + }, + SplitInOut { + reg: InlineAsmRegOrRegClass, + in_expr: ExprId, + out_expr: Option, + late: bool, + }, + Label(ExprId), + Const(ExprId), + Sym(Path), +} + +impl AsmOperand { + pub fn reg(&self) -> Option<&InlineAsmRegOrRegClass> { + match self { + Self::In { reg, .. } + | Self::Out { reg, .. } + | Self::InOut { reg, .. } + | Self::SplitInOut { reg, .. } => Some(reg), + Self::Const { .. } | Self::Sym { .. } | Self::Label { .. } => None, + } + } + + pub fn is_clobber(&self) -> bool { + matches!(self, AsmOperand::Out { reg: InlineAsmRegOrRegClass::Reg(_), late: _, expr: None }) + } +} + +#[derive(Clone, Debug, Eq, PartialEq, Hash)] +pub enum InlineAsmRegOrRegClass { + Reg(Symbol), + RegClass(Symbol), } #[derive(Debug, Clone, Copy, PartialEq, Eq)] @@ -373,7 +485,21 @@ impl Expr { match self { Expr::Missing => {} Expr::Path(_) | Expr::OffsetOf(_) => {} - Expr::InlineAsm(it) => it.template.iter().copied().for_each(f), + Expr::InlineAsm(it) => it.operands.iter().for_each(|op| match op { + AsmOperand::In { expr, .. } + | AsmOperand::Out { expr: Some(expr), .. } + | AsmOperand::InOut { expr, .. } => f(*expr), + AsmOperand::SplitInOut { in_expr, out_expr, .. } => { + f(*in_expr); + if let Some(out_expr) = out_expr { + f(*out_expr); + } + } + AsmOperand::Out { expr: None, .. } + | AsmOperand::Const(_) + | AsmOperand::Label(_) + | AsmOperand::Sym(_) => (), + }), Expr::If { condition, then_branch, else_branch } => { f(*condition); f(*then_branch); diff --git a/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/builtin_fn_macro.rs b/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/builtin_fn_macro.rs index b6dbba12cd6d6..37ae1ab39b494 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/builtin_fn_macro.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/builtin_fn_macro.rs @@ -50,11 +50,7 @@ fn main() { let i: u64 = 3; let o: u64; unsafe { - builtin #asm ( { - $crate::format_args!("mov {0}, {1}"); - $crate::format_args!("add {0}, 5"); - } - ); + builtin #asm ("mov {0}, {1}", "add {0}, 5", out (reg)o, in (reg)i, ); } } "##]], diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/builtin/fn_macro.rs b/src/tools/rust-analyzer/crates/hir-expand/src/builtin/fn_macro.rs index 795d9b14df961..15fed45caf02f 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/builtin/fn_macro.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/builtin/fn_macro.rs @@ -119,9 +119,8 @@ register_builtin! { (module_path, ModulePath) => module_path_expand, (assert, Assert) => assert_expand, (stringify, Stringify) => stringify_expand, - (llvm_asm, LlvmAsm) => asm_expand, (asm, Asm) => asm_expand, - (global_asm, GlobalAsm) => global_asm_expand, + (global_asm, GlobalAsm) => asm_expand, (cfg, Cfg) => cfg_expand, (core_panic, CorePanic) => panic_expand, (std_panic, StdPanic) => panic_expand, @@ -324,40 +323,15 @@ fn asm_expand( tt: &tt::Subtree, span: Span, ) -> ExpandResult { - // We expand all assembly snippets to `format_args!` invocations to get format syntax - // highlighting for them. - let mut literals = Vec::new(); - for tt in tt.token_trees.chunks(2) { - match tt { - [tt::TokenTree::Leaf(tt::Leaf::Literal(lit))] - | [tt::TokenTree::Leaf(tt::Leaf::Literal(lit)), tt::TokenTree::Leaf(tt::Leaf::Punct(tt::Punct { char: ',', span: _, spacing: _ }))] => - { - let dollar_krate = dollar_crate(span); - literals.push(quote!(span=>#dollar_krate::format_args!(#lit);)); - } - _ => break, - } - } - + let mut tt = tt.clone(); + tt.delimiter.kind = tt::DelimiterKind::Parenthesis; let pound = mk_pound(span); let expanded = quote! {span => - builtin #pound asm ( - {##literals} - ) + builtin #pound asm #tt }; ExpandResult::ok(expanded) } -fn global_asm_expand( - _db: &dyn ExpandDatabase, - _id: MacroCallId, - _tt: &tt::Subtree, - span: Span, -) -> ExpandResult { - // Expand to nothing (at item-level) - ExpandResult::ok(quote! {span =>}) -} - fn cfg_expand( db: &dyn ExpandDatabase, id: MacroCallId, diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer/closure.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer/closure.rs index 67a3d2434d24e..3ad330c1a0b5d 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/infer/closure.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer/closure.rs @@ -10,7 +10,10 @@ use chalk_ir::{ use either::Either; use hir_def::{ data::adt::VariantData, - hir::{Array, BinaryOp, BindingId, CaptureBy, Expr, ExprId, Pat, PatId, Statement, UnaryOp}, + hir::{ + Array, AsmOperand, BinaryOp, BindingId, CaptureBy, Expr, ExprId, Pat, PatId, Statement, + UnaryOp, + }, lang_item::LangItem, resolver::{resolver_for_expr, ResolveValueResult, ValueNs}, DefWithBodyId, FieldId, HasModule, TupleFieldId, TupleId, VariantId, @@ -666,9 +669,21 @@ impl InferenceContext<'_> { fn walk_expr_without_adjust(&mut self, tgt_expr: ExprId) { match &self.body[tgt_expr] { Expr::OffsetOf(_) => (), - Expr::InlineAsm(e) => { - e.template.iter().for_each(|it| self.walk_expr_without_adjust(*it)) - } + Expr::InlineAsm(e) => e.operands.iter().for_each(|op| match op { + AsmOperand::In { expr, .. } + | AsmOperand::Out { expr: Some(expr), .. } + | AsmOperand::InOut { expr, .. } => self.walk_expr_without_adjust(*expr), + AsmOperand::SplitInOut { in_expr, out_expr, .. } => { + self.walk_expr_without_adjust(*in_expr); + if let Some(out_expr) = out_expr { + self.walk_expr_without_adjust(*out_expr); + } + } + AsmOperand::Out { expr: None, .. } + | AsmOperand::Const(_) + | AsmOperand::Label(_) + | AsmOperand::Sym(_) => (), + }), Expr::If { condition, then_branch, else_branch } => { self.consume_expr(*condition); self.consume_expr(*then_branch); diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer/expr.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer/expr.rs index 6b725d690d1a7..e6eaf2f446d43 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/infer/expr.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer/expr.rs @@ -9,7 +9,8 @@ use chalk_ir::{cast::Cast, fold::Shift, DebruijnIndex, Mutability, TyVariableKin use either::Either; use hir_def::{ hir::{ - ArithOp, Array, BinaryOp, ClosureKind, Expr, ExprId, LabelId, Literal, Statement, UnaryOp, + ArithOp, Array, AsmOperand, AsmOptions, BinaryOp, ClosureKind, Expr, ExprId, LabelId, + Literal, Statement, UnaryOp, }, lang_item::{LangItem, LangItemTarget}, path::{GenericArg, GenericArgs, Path}, @@ -41,9 +42,9 @@ use crate::{ primitive::{self, UintTy}, static_lifetime, to_chalk_trait_id, traits::FnTrait, - Adjust, Adjustment, AdtId, AutoBorrow, Binders, CallableDefId, FnAbi, FnPointer, FnSig, - FnSubst, Interner, Rawness, Scalar, Substitution, TraitEnvironment, TraitRef, Ty, TyBuilder, - TyExt, TyKind, + Adjust, Adjustment, AdtId, AutoBorrow, Binders, CallableDefId, CallableSig, FnAbi, FnPointer, + FnSig, FnSubst, Interner, Rawness, Scalar, Substitution, TraitEnvironment, TraitRef, Ty, + TyBuilder, TyExt, TyKind, }; use super::{ @@ -924,9 +925,61 @@ impl InferenceContext<'_> { expected } Expr::OffsetOf(_) => TyKind::Scalar(Scalar::Uint(UintTy::Usize)).intern(Interner), - Expr::InlineAsm(it) => { - it.template.iter().for_each(|&expr| _ = self.infer_expr_no_expect(expr)); - self.result.standard_types.unit.clone() + Expr::InlineAsm(asm) => { + let mut check_expr_asm_operand = |expr, is_input: bool| { + let ty = self.infer_expr_no_expect(expr); + + // If this is an input value, we require its type to be fully resolved + // at this point. This allows us to provide helpful coercions which help + // pass the type candidate list in a later pass. + // + // We don't require output types to be resolved at this point, which + // allows them to be inferred based on how they are used later in the + // function. + if is_input { + let ty = self.resolve_ty_shallow(&ty); + match ty.kind(Interner) { + TyKind::FnDef(def, parameters) => { + let fnptr_ty = TyKind::Function( + CallableSig::from_def(self.db, *def, parameters).to_fn_ptr(), + ) + .intern(Interner); + _ = self.coerce(Some(expr), &ty, &fnptr_ty); + } + TyKind::Ref(mutbl, _, base_ty) => { + let ptr_ty = TyKind::Raw(*mutbl, base_ty.clone()).intern(Interner); + _ = self.coerce(Some(expr), &ty, &ptr_ty); + } + _ => {} + } + } + }; + + let diverge = asm.options.contains(AsmOptions::NORETURN); + asm.operands.iter().for_each(|operand| match *operand { + AsmOperand::In { expr, .. } => check_expr_asm_operand(expr, true), + AsmOperand::Out { expr: Some(expr), .. } | AsmOperand::InOut { expr, .. } => { + check_expr_asm_operand(expr, false) + } + AsmOperand::Out { expr: None, .. } => (), + AsmOperand::SplitInOut { in_expr, out_expr, .. } => { + check_expr_asm_operand(in_expr, true); + if let Some(out_expr) = out_expr { + check_expr_asm_operand(out_expr, false); + } + } + // FIXME + AsmOperand::Label(_) => (), + // FIXME + AsmOperand::Const(_) => (), + // FIXME + AsmOperand::Sym(_) => (), + }); + if diverge { + self.result.standard_types.never.clone() + } else { + self.result.standard_types.unit.clone() + } } }; // use a new type variable if we got unknown here diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer/mutability.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer/mutability.rs index e1b460d072d3f..e841c6630822a 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/infer/mutability.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer/mutability.rs @@ -3,7 +3,9 @@ use chalk_ir::{cast::Cast, Mutability}; use hir_def::{ - hir::{Array, BinaryOp, BindingAnnotation, Expr, ExprId, PatId, Statement, UnaryOp}, + hir::{ + Array, AsmOperand, BinaryOp, BindingAnnotation, Expr, ExprId, PatId, Statement, UnaryOp, + }, lang_item::LangItem, }; use hir_expand::name::Name; @@ -39,10 +41,25 @@ impl InferenceContext<'_> { fn infer_mut_expr_without_adjust(&mut self, tgt_expr: ExprId, mutability: Mutability) { match &self.body[tgt_expr] { Expr::Missing => (), - Expr::InlineAsm(e) => e - .template - .iter() - .for_each(|&expr| self.infer_mut_expr_without_adjust(expr, Mutability::Not)), + Expr::InlineAsm(e) => { + e.operands.iter().for_each(|op| match op { + AsmOperand::In { expr, .. } + | AsmOperand::Out { expr: Some(expr), .. } + | AsmOperand::InOut { expr, .. } => { + self.infer_mut_expr_without_adjust(*expr, Mutability::Not) + } + AsmOperand::SplitInOut { in_expr, out_expr, .. } => { + self.infer_mut_expr_without_adjust(*in_expr, Mutability::Not); + if let Some(out_expr) = out_expr { + self.infer_mut_expr_without_adjust(*out_expr, Mutability::Not); + } + } + AsmOperand::Out { expr: None, .. } + | AsmOperand::Label(_) + | AsmOperand::Sym(_) + | AsmOperand::Const(_) => (), + }); + } Expr::OffsetOf(_) => (), &Expr::If { condition, then_branch, else_branch } => { self.infer_mut_expr(condition, Mutability::Not); diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/tests/macros.rs b/src/tools/rust-analyzer/crates/hir-ty/src/tests/macros.rs index 5a6161f94289f..83aceec981a5a 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/tests/macros.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/tests/macros.rs @@ -1,7 +1,7 @@ use expect_test::expect; use test_utils::{bench, bench_fixture, skip_slow_tests}; -use crate::tests::check_infer_with_mismatches; +use crate::tests::{check_infer_with_mismatches, check_no_mismatches}; use super::{check_infer, check_types}; @@ -1406,3 +1406,100 @@ fn foo(t: Tensor) { "#, ); } + +#[test] +fn asm_unit() { + check_no_mismatches( + r#" +//- minicore: asm +fn unit() { + asm!("") +} +"#, + ); +} + +#[test] +fn asm_no_return() { + check_no_mismatches( + r#" +//- minicore: asm +fn unit() -> ! { + asm!("", options(noreturn)) +} +"#, + ); +} + +#[test] +fn asm_things() { + check_infer( + r#" +//- minicore: asm, concat +fn main() { + unsafe { + let foo = 1; + let mut o = 0; + asm!( + "%input = OpLoad _ {0}", + concat!("%result = ", bar, " _ %input"), + "OpStore {1} %result", + in(reg) &foo, + in(reg) &mut o, + ); + o + + let thread_id: usize; + asm!(" + mov {0}, gs:[0x30] + mov {0}, [{0}+0x48] + ", out(reg) thread_id, options(pure, readonly, nostack)); + + static UNMAP_BASE: usize; + const MEM_RELEASE: usize; + static VirtualFree: usize; + const OffPtr: usize; + const OffFn: usize; + asm!(" + push {free_type} + push {free_size} + push {base} + + mov eax, fs:[30h] + mov eax, [eax+8h] + add eax, {off_fn} + mov [eax-{off_fn}+{off_ptr}], eax + + push eax + + jmp {virtual_free} + ", + off_ptr = const OffPtr, + off_fn = const OffFn, + + free_size = const 0, + free_type = const MEM_RELEASE, + + virtual_free = sym VirtualFree, + + base = sym UNMAP_BASE, + options(noreturn), + ); + } +} +"#, + expect![[r#" + !0..122 'builti...muto,)': () + !0..190 'builti...tack))': () + !0..449 'builti...urn),)': ! + 10..1254 '{ ... } }': () + 16..1252 'unsafe... }': () + 37..40 'foo': i32 + 43..44 '1': i32 + 58..63 'mut o': i32 + 66..67 '0': i32 + 281..282 'o': i32 + 296..305 'thread_id': usize + "#]], + ) +} diff --git a/src/tools/rust-analyzer/crates/hir/src/semantics.rs b/src/tools/rust-analyzer/crates/hir/src/semantics.rs index c78b59826c955..4e6887295c8a3 100644 --- a/src/tools/rust-analyzer/crates/hir/src/semantics.rs +++ b/src/tools/rust-analyzer/crates/hir/src/semantics.rs @@ -368,7 +368,6 @@ impl<'db> SemanticsImpl<'db> { | BuiltinFnLikeExpander::File | BuiltinFnLikeExpander::ModulePath | BuiltinFnLikeExpander::Asm - | BuiltinFnLikeExpander::LlvmAsm | BuiltinFnLikeExpander::GlobalAsm | BuiltinFnLikeExpander::LogSyntax | BuiltinFnLikeExpander::TraceMacros diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_strings.html b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_strings.html index cb47fc68bc1b6..9376ef65a4e6a 100644 --- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_strings.html +++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_strings.html @@ -166,10 +166,10 @@ let i: u64 = 3; let o: u64; asm!( - "mov {0}, {1}", - "add {0}, 5", - out(reg) o, - in(reg) i, + "mov {0}, {1}", + "add {0}, 5", + out(reg) o, + in(reg) i, ); const CONSTANT: () = (): diff --git a/src/tools/rust-analyzer/crates/parser/src/grammar/expressions/atom.rs b/src/tools/rust-analyzer/crates/parser/src/grammar/expressions/atom.rs index 57f1e6e9f031f..f98ca5f403225 100644 --- a/src/tools/rust-analyzer/crates/parser/src/grammar/expressions/atom.rs +++ b/src/tools/rust-analyzer/crates/parser/src/grammar/expressions/atom.rs @@ -329,9 +329,11 @@ fn parse_asm_expr(p: &mut Parser<'_>, m: Marker) -> Option { break; } + let op = p.start(); // Parse clobber_abi if p.eat_contextual_kw(T![clobber_abi]) { parse_clobber_abi(p); + op.complete(p, ASM_CLOBBER_ABI); allow_templates = false; continue; } @@ -339,6 +341,7 @@ fn parse_asm_expr(p: &mut Parser<'_>, m: Marker) -> Option { // Parse options if p.eat_contextual_kw(T![options]) { parse_options(p); + op.complete(p, ASM_OPTIONS); allow_templates = false; continue; } @@ -353,27 +356,14 @@ fn parse_asm_expr(p: &mut Parser<'_>, m: Marker) -> Option { false }; - let op = p.start(); - if p.eat(T![in]) { - parse_reg(p); - expr(p); - op.complete(p, ASM_REG_OPERAND); - } else if p.eat_contextual_kw(T![out]) { - parse_reg(p); - expr(p); - op.complete(p, ASM_REG_OPERAND); - } else if p.eat_contextual_kw(T![lateout]) { + let dir_spec = p.start(); + if p.eat(T![in]) || p.eat_contextual_kw(T![out]) || p.eat_contextual_kw(T![lateout]) { + dir_spec.complete(p, ASM_DIR_SPEC); parse_reg(p); expr(p); op.complete(p, ASM_REG_OPERAND); - } else if p.eat_contextual_kw(T![inout]) { - parse_reg(p); - expr(p); - if p.eat(T![=>]) { - expr(p); - } - op.complete(p, ASM_REG_OPERAND); - } else if p.eat_contextual_kw(T![inlateout]) { + } else if p.eat_contextual_kw(T![inout]) || p.eat_contextual_kw(T![inlateout]) { + dir_spec.complete(p, ASM_DIR_SPEC); parse_reg(p); expr(p); if p.eat(T![=>]) { @@ -381,21 +371,26 @@ fn parse_asm_expr(p: &mut Parser<'_>, m: Marker) -> Option { } op.complete(p, ASM_REG_OPERAND); } else if p.eat_contextual_kw(T![label]) { + dir_spec.abandon(p); block_expr(p); op.complete(p, ASM_LABEL); } else if p.eat(T![const]) { + dir_spec.abandon(p); expr(p); op.complete(p, ASM_CONST); } else if p.eat_contextual_kw(T![sym]) { - expr(p); + dir_spec.abandon(p); + paths::type_path(p); op.complete(p, ASM_SYM); } else if allow_templates { + dir_spec.abandon(p); op.abandon(p); if expr(p).is_none() { p.err_and_bump("expected asm template"); } continue; } else { + dir_spec.abandon(p); op.abandon(p); p.err_and_bump("expected asm operand"); if p.at(T!['}']) { @@ -424,11 +419,12 @@ fn parse_options(p: &mut Parser<'_>) { T![att_syntax], T![raw], ]; - - if !OPTIONS.iter().any(|&syntax| p.eat(syntax)) { + let m = p.start(); + if !OPTIONS.iter().any(|&syntax| p.eat_contextual_kw(syntax)) { p.err_and_bump("expected asm option"); continue; } + m.complete(p, ASM_OPTION); // Allow trailing commas if p.eat(T![')']) { diff --git a/src/tools/rust-analyzer/crates/syntax/rust.ungram b/src/tools/rust-analyzer/crates/syntax/rust.ungram index 4d780ba28f310..5dace66c32d51 100644 --- a/src/tools/rust-analyzer/crates/syntax/rust.ungram +++ b/src/tools/rust-analyzer/crates/syntax/rust.ungram @@ -411,13 +411,11 @@ AsmClobberAbi = 'clobber_abi' '(' ('@string' (',' '@string')* ','?) ')' AsmOption = 'pure' | 'nomem' | 'readonly' | 'preserves_flags' | 'noreturn' | 'nostack' | 'att_syntax' | 'raw' | 'may_unwind' // options := "options(" option *("," option) [","] ")" AsmOptions = 'options' '(' AsmOption *(',' AsmOption) ','? ')' -// operand := reg_operand / clobber_abi / options -AsmOperand = AsmRegOperand | AsmClobberAbi | AsmOptions | AsmLabel AsmLabel = 'label' BlockExpr -AsmSym = 'sym' Expr +AsmSym = 'sym' Path AsmConst = 'const' Expr - - +// operand := reg_operand / clobber_abi / options +AsmOperand = AsmRegOperand | AsmClobberAbi | AsmOptions | AsmLabel | AsmSym | AsmConst FormatArgsExpr = Attr* 'builtin' '#' 'format_args' '(' diff --git a/src/tools/rust-analyzer/crates/syntax/src/ast/generated/nodes.rs b/src/tools/rust-analyzer/crates/syntax/src/ast/generated/nodes.rs index e5e1115e05a7b..01d47c34bbdf6 100644 --- a/src/tools/rust-analyzer/crates/syntax/src/ast/generated/nodes.rs +++ b/src/tools/rust-analyzer/crates/syntax/src/ast/generated/nodes.rs @@ -250,7 +250,7 @@ pub struct AsmSym { } impl AsmSym { #[inline] - pub fn expr(&self) -> Option { support::child(&self.syntax) } + pub fn path(&self) -> Option { support::child(&self.syntax) } #[inline] pub fn sym_token(&self) -> Option { support::token(&self.syntax, T![sym]) } } @@ -2225,9 +2225,11 @@ impl ast::HasVisibility for Adt {} #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub enum AsmOperand { AsmClobberAbi(AsmClobberAbi), + AsmConst(AsmConst), AsmLabel(AsmLabel), AsmOptions(AsmOptions), AsmRegOperand(AsmRegOperand), + AsmSym(AsmSym), } #[derive(Debug, Clone, PartialEq, Eq, Hash)] @@ -4591,6 +4593,10 @@ impl From for AsmOperand { #[inline] fn from(node: AsmClobberAbi) -> AsmOperand { AsmOperand::AsmClobberAbi(node) } } +impl From for AsmOperand { + #[inline] + fn from(node: AsmConst) -> AsmOperand { AsmOperand::AsmConst(node) } +} impl From for AsmOperand { #[inline] fn from(node: AsmLabel) -> AsmOperand { AsmOperand::AsmLabel(node) } @@ -4603,18 +4609,27 @@ impl From for AsmOperand { #[inline] fn from(node: AsmRegOperand) -> AsmOperand { AsmOperand::AsmRegOperand(node) } } +impl From for AsmOperand { + #[inline] + fn from(node: AsmSym) -> AsmOperand { AsmOperand::AsmSym(node) } +} impl AstNode for AsmOperand { #[inline] fn can_cast(kind: SyntaxKind) -> bool { - matches!(kind, ASM_CLOBBER_ABI | ASM_LABEL | ASM_OPTIONS | ASM_REG_OPERAND) + matches!( + kind, + ASM_CLOBBER_ABI | ASM_CONST | ASM_LABEL | ASM_OPTIONS | ASM_REG_OPERAND | ASM_SYM + ) } #[inline] fn cast(syntax: SyntaxNode) -> Option { let res = match syntax.kind() { ASM_CLOBBER_ABI => AsmOperand::AsmClobberAbi(AsmClobberAbi { syntax }), + ASM_CONST => AsmOperand::AsmConst(AsmConst { syntax }), ASM_LABEL => AsmOperand::AsmLabel(AsmLabel { syntax }), ASM_OPTIONS => AsmOperand::AsmOptions(AsmOptions { syntax }), ASM_REG_OPERAND => AsmOperand::AsmRegOperand(AsmRegOperand { syntax }), + ASM_SYM => AsmOperand::AsmSym(AsmSym { syntax }), _ => return None, }; Some(res) @@ -4623,9 +4638,11 @@ impl AstNode for AsmOperand { fn syntax(&self) -> &SyntaxNode { match self { AsmOperand::AsmClobberAbi(it) => &it.syntax, + AsmOperand::AsmConst(it) => &it.syntax, AsmOperand::AsmLabel(it) => &it.syntax, AsmOperand::AsmOptions(it) => &it.syntax, AsmOperand::AsmRegOperand(it) => &it.syntax, + AsmOperand::AsmSym(it) => &it.syntax, } } } From 44e3b7d205da25c4f7538b439bd6990416910d2e Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Thu, 5 Sep 2024 10:23:00 +0200 Subject: [PATCH 0517/2194] Add Definition kind for asm register classes --- .../crates/hir-ty/src/tests/macros.rs | 20 ++-- .../crates/ide-completion/src/item.rs | 1 + .../rust-analyzer/crates/ide-db/src/defs.rs | 11 ++- .../rust-analyzer/crates/ide-db/src/lib.rs | 1 + .../rust-analyzer/crates/ide-db/src/rename.rs | 3 +- .../rust-analyzer/crates/ide/src/doc_links.rs | 6 +- .../rust-analyzer/crates/ide/src/moniker.rs | 4 +- .../crates/ide/src/navigation_target.rs | 1 + .../ide/src/syntax_highlighting/highlight.rs | 3 + .../ide/src/syntax_highlighting/inject.rs | 1 + .../ide/src/syntax_highlighting/tags.rs | 1 + .../test_data/highlight_asm.html | 98 +++++++++++++++++++ .../test_data/highlight_strings.html | 2 +- .../ide/src/syntax_highlighting/tests.rs | 64 +++++++++++- .../crates/rust-analyzer/src/lsp/to_proto.rs | 3 + .../crates/test-utils/src/minicore.rs | 23 +++-- 16 files changed, 214 insertions(+), 28 deletions(-) create mode 100644 src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_asm.html diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/tests/macros.rs b/src/tools/rust-analyzer/crates/hir-ty/src/tests/macros.rs index 83aceec981a5a..10ab6d3ff8939 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/tests/macros.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/tests/macros.rs @@ -1413,7 +1413,7 @@ fn asm_unit() { r#" //- minicore: asm fn unit() { - asm!("") + core::arch::asm!("") } "#, ); @@ -1425,7 +1425,7 @@ fn asm_no_return() { r#" //- minicore: asm fn unit() -> ! { - asm!("", options(noreturn)) + core::arch::asm!("", options(noreturn)) } "#, ); @@ -1440,7 +1440,7 @@ fn main() { unsafe { let foo = 1; let mut o = 0; - asm!( + core::arch::asm!( "%input = OpLoad _ {0}", concat!("%result = ", bar, " _ %input"), "OpStore {1} %result", @@ -1450,7 +1450,7 @@ fn main() { o let thread_id: usize; - asm!(" + core::arch::asm!(" mov {0}, gs:[0x30] mov {0}, [{0}+0x48] ", out(reg) thread_id, options(pure, readonly, nostack)); @@ -1460,7 +1460,7 @@ fn main() { static VirtualFree: usize; const OffPtr: usize; const OffFn: usize; - asm!(" + core::arch::asm!(" push {free_type} push {free_size} push {base} @@ -1490,16 +1490,16 @@ fn main() { "#, expect![[r#" !0..122 'builti...muto,)': () - !0..190 'builti...tack))': () + !0..136 'builti...tack))': () !0..449 'builti...urn),)': ! - 10..1254 '{ ... } }': () - 16..1252 'unsafe... }': () + 10..1236 '{ ... } }': () + 16..1234 'unsafe... }': () 37..40 'foo': i32 43..44 '1': i32 58..63 'mut o': i32 66..67 '0': i32 - 281..282 'o': i32 - 296..305 'thread_id': usize + 293..294 'o': i32 + 308..317 'thread_id': usize "#]], ) } diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/item.rs b/src/tools/rust-analyzer/crates/ide-completion/src/item.rs index f8c8b12bd25af..8c97ebd550032 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/item.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/item.rs @@ -360,6 +360,7 @@ impl CompletionItemKind { SymbolKind::Field => "fd", SymbolKind::Function => "fn", SymbolKind::Impl => "im", + SymbolKind::InlineAsmRegOrRegClass => "ar", SymbolKind::Label => "lb", SymbolKind::LifetimeParam => "lt", SymbolKind::Local => "lc", diff --git a/src/tools/rust-analyzer/crates/ide-db/src/defs.rs b/src/tools/rust-analyzer/crates/ide-db/src/defs.rs index 5d4b1999088a0..3d372bab27471 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/defs.rs +++ b/src/tools/rust-analyzer/crates/ide-db/src/defs.rs @@ -50,6 +50,7 @@ pub enum Definition { BuiltinAttr(BuiltinAttr), ToolModule(ToolModule), ExternCrateDecl(ExternCrateDecl), + InlineAsmRegOrRegClass(()), } impl Definition { @@ -87,7 +88,8 @@ impl Definition { | Definition::BuiltinType(_) | Definition::BuiltinLifetime(_) | Definition::TupleField(_) - | Definition::ToolModule(_) => return None, + | Definition::ToolModule(_) + | Definition::InlineAsmRegOrRegClass(_) => return None, }; Some(module) } @@ -121,7 +123,8 @@ impl Definition { | Definition::Local(_) | Definition::GenericParam(_) | Definition::Label(_) - | Definition::DeriveHelper(_) => return None, + | Definition::DeriveHelper(_) + | Definition::InlineAsmRegOrRegClass(_) => return None, }; Some(vis) } @@ -150,6 +153,7 @@ impl Definition { Definition::ToolModule(_) => return None, // FIXME Definition::DeriveHelper(it) => it.name(db), Definition::ExternCrateDecl(it) => return it.alias_or_name(db), + Definition::InlineAsmRegOrRegClass(_) => return None, // FIXME }; Some(name) } @@ -212,6 +216,7 @@ impl Definition { Definition::ToolModule(_) => None, Definition::DeriveHelper(_) => None, Definition::TupleField(_) => None, + Definition::InlineAsmRegOrRegClass(_) => None, }; docs.or_else(|| { @@ -268,6 +273,8 @@ impl Definition { Definition::DeriveHelper(it) => { format!("derive_helper {}", it.name(db).display(db, edition)) } + // FIXME + Definition::InlineAsmRegOrRegClass(_) => "inline_asm_reg_or_reg_class".to_owned(), } } } diff --git a/src/tools/rust-analyzer/crates/ide-db/src/lib.rs b/src/tools/rust-analyzer/crates/ide-db/src/lib.rs index ab161f0ce5712..3435757ad3182 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/lib.rs +++ b/src/tools/rust-analyzer/crates/ide-db/src/lib.rs @@ -224,6 +224,7 @@ pub enum SymbolKind { Function, Method, Impl, + InlineAsmRegOrRegClass, Label, LifetimeParam, Local, diff --git a/src/tools/rust-analyzer/crates/ide-db/src/rename.rs b/src/tools/rust-analyzer/crates/ide-db/src/rename.rs index 262eefeec00e4..3a1a9aba8551c 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/rename.rs +++ b/src/tools/rust-analyzer/crates/ide-db/src/rename.rs @@ -205,7 +205,8 @@ impl Definition { | Definition::BuiltinAttr(_) | Definition::SelfType(_) | Definition::ToolModule(_) - | Definition::TupleField(_) => return None, + | Definition::TupleField(_) + | Definition::InlineAsmRegOrRegClass(_) => return None, // FIXME: This should be doable in theory Definition::DeriveHelper(_) => return None, }; diff --git a/src/tools/rust-analyzer/crates/ide/src/doc_links.rs b/src/tools/rust-analyzer/crates/ide/src/doc_links.rs index 925ae620231d2..aa632ab12f742 100644 --- a/src/tools/rust-analyzer/crates/ide/src/doc_links.rs +++ b/src/tools/rust-analyzer/crates/ide/src/doc_links.rs @@ -219,7 +219,8 @@ pub(crate) fn resolve_doc_path_for_def( | Definition::Local(_) | Definition::GenericParam(_) | Definition::Label(_) - | Definition::DeriveHelper(_) => None, + | Definition::DeriveHelper(_) + | Definition::InlineAsmRegOrRegClass(_) => None, } .map(Definition::from) } @@ -672,7 +673,8 @@ fn filename_and_frag_for_def( | Definition::BuiltinAttr(_) | Definition::BuiltinLifetime(_) | Definition::ToolModule(_) - | Definition::DeriveHelper(_) => return None, + | Definition::DeriveHelper(_) + | Definition::InlineAsmRegOrRegClass(_) => return None, }; Some((def, res, None)) diff --git a/src/tools/rust-analyzer/crates/ide/src/moniker.rs b/src/tools/rust-analyzer/crates/ide/src/moniker.rs index 4be1b570981f6..69c94bc357838 100644 --- a/src/tools/rust-analyzer/crates/ide/src/moniker.rs +++ b/src/tools/rust-analyzer/crates/ide/src/moniker.rs @@ -228,6 +228,7 @@ pub(crate) fn def_to_kind(db: &RootDatabase, def: Definition) -> SymbolInformati Definition::BuiltinAttr(..) => Attribute, Definition::ToolModule(..) => Module, Definition::ExternCrateDecl(..) => Module, + Definition::InlineAsmRegOrRegClass(..) => Module, } } @@ -320,7 +321,8 @@ pub(crate) fn def_to_moniker( | Definition::DeriveHelper(_) | Definition::BuiltinLifetime(_) | Definition::BuiltinAttr(_) - | Definition::ToolModule(_) => return None, + | Definition::ToolModule(_) + | Definition::InlineAsmRegOrRegClass(_) => return None, Definition::Local(local) => { if !local.is_param(db) { diff --git a/src/tools/rust-analyzer/crates/ide/src/navigation_target.rs b/src/tools/rust-analyzer/crates/ide/src/navigation_target.rs index 9ace9fda62b97..cf1412560ddf2 100644 --- a/src/tools/rust-analyzer/crates/ide/src/navigation_target.rs +++ b/src/tools/rust-analyzer/crates/ide/src/navigation_target.rs @@ -242,6 +242,7 @@ impl TryToNav for Definition { | Definition::BuiltinType(_) | Definition::TupleField(_) | Definition::ToolModule(_) + | Definition::InlineAsmRegOrRegClass(_) | Definition::BuiltinAttr(_) => None, // FIXME: The focus range should be set to the helper declaration Definition::DeriveHelper(it) => it.derive().try_to_nav(db), diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/highlight.rs b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/highlight.rs index eeba9cf35c997..2894cb9cf6dce 100644 --- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/highlight.rs +++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/highlight.rs @@ -534,6 +534,9 @@ pub(super) fn highlight_def( Definition::BuiltinAttr(_) => Highlight::new(HlTag::Symbol(SymbolKind::BuiltinAttr)), Definition::ToolModule(_) => Highlight::new(HlTag::Symbol(SymbolKind::ToolModule)), Definition::DeriveHelper(_) => Highlight::new(HlTag::Symbol(SymbolKind::DeriveHelper)), + Definition::InlineAsmRegOrRegClass(_) => { + Highlight::new(HlTag::Symbol(SymbolKind::InlineAsmRegOrRegClass)) + } }; let def_crate = def.krate(db); diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/inject.rs b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/inject.rs index bc1ec530076ce..e2b32c17d66a7 100644 --- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/inject.rs +++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/inject.rs @@ -315,6 +315,7 @@ fn module_def_to_hl_tag(def: Definition) -> HlTag { Definition::BuiltinAttr(_) => SymbolKind::BuiltinAttr, Definition::ToolModule(_) => SymbolKind::ToolModule, Definition::DeriveHelper(_) => SymbolKind::DeriveHelper, + Definition::InlineAsmRegOrRegClass(_) => SymbolKind::InlineAsmRegOrRegClass, }; HlTag::Symbol(symbol) } diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/tags.rs b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/tags.rs index e329023606a1b..3b5d1af0ac72a 100644 --- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/tags.rs +++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/tags.rs @@ -146,6 +146,7 @@ impl HlTag { SymbolKind::Field => "field", SymbolKind::Function => "function", SymbolKind::Impl => "self_type", + SymbolKind::InlineAsmRegOrRegClass => "reg", SymbolKind::Label => "label", SymbolKind::LifetimeParam => "lifetime", SymbolKind::Local => "variable", diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_asm.html b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_asm.html new file mode 100644 index 0000000000000..1280d78cc815e --- /dev/null +++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_asm.html @@ -0,0 +1,98 @@ + + +
fn main() {
+    unsafe {
+        let foo = 1;
+        let mut o = 0;
+        core::arch::asm!(
+            "%input = OpLoad _ {0}",
+            concat!("%result = ", bar, " _ %input"),
+            "OpStore {1} %result",
+            in(reg) &foo,
+            in(reg) &mut o,
+        );
+        o
+
+        let thread_id: usize;
+        core::arch::asm!("
+            mov {0}, gs:[0x30]
+            mov {0}, [{0}+0x48]
+        ", out(reg) thread_id, options(pure, readonly, nostack));
+
+        static UNMAP_BASE: usize;
+        const MEM_RELEASE: usize;
+        static VirtualFree: usize;
+        const OffPtr: usize;
+        const OffFn: usize;
+        core::arch::asm!("
+            push {free_type}
+            push {free_size}
+            push {base}
+
+            mov eax, fs:[30h]
+            mov eax, [eax+8h]
+            add eax, {off_fn}
+            mov [eax-{off_fn}+{off_ptr}], eax
+
+            push eax
+
+            jmp {virtual_free}
+            ",
+            off_ptr = const OffPtr,
+            off_fn  = const OffFn,
+
+            free_size = const 0,
+            free_type = const MEM_RELEASE,
+
+            virtual_free = sym VirtualFree,
+
+            base = sym UNMAP_BASE,
+            options(noreturn),
+        );
+    }
+}
\ No newline at end of file diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_strings.html b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_strings.html index 9376ef65a4e6a..ced522e7ebb21 100644 --- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_strings.html +++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_strings.html @@ -165,7 +165,7 @@ toho!("{}fmt", 0); let i: u64 = 3; let o: u64; - asm!( + core::arch::asm!( "mov {0}, {1}", "add {0}, 5", out(reg) o, diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/tests.rs b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/tests.rs index c06ea155fb86b..dbe8de8f91ffe 100644 --- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/tests.rs +++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/tests.rs @@ -549,7 +549,7 @@ fn main() { toho!("{}fmt", 0); let i: u64 = 3; let o: u64; - asm!( + core::arch::asm!( "mov {0}, {1}", "add {0}, 5", out(reg) o, @@ -1275,3 +1275,65 @@ fn f<'de, T: Deserialize<'de>>() { ); let _ = analysis.highlight(HL_CONFIG, file_id).unwrap(); } + +#[test] +fn test_asm_highlighting() { + check_highlighting( + r#" +//- minicore: asm, concat +fn main() { + unsafe { + let foo = 1; + let mut o = 0; + core::arch::asm!( + "%input = OpLoad _ {0}", + concat!("%result = ", bar, " _ %input"), + "OpStore {1} %result", + in(reg) &foo, + in(reg) &mut o, + ); + o + + let thread_id: usize; + core::arch::asm!(" + mov {0}, gs:[0x30] + mov {0}, [{0}+0x48] + ", out(reg) thread_id, options(pure, readonly, nostack)); + + static UNMAP_BASE: usize; + const MEM_RELEASE: usize; + static VirtualFree: usize; + const OffPtr: usize; + const OffFn: usize; + core::arch::asm!(" + push {free_type} + push {free_size} + push {base} + + mov eax, fs:[30h] + mov eax, [eax+8h] + add eax, {off_fn} + mov [eax-{off_fn}+{off_ptr}], eax + + push eax + + jmp {virtual_free} + ", + off_ptr = const OffPtr, + off_fn = const OffFn, + + free_size = const 0, + free_type = const MEM_RELEASE, + + virtual_free = sym VirtualFree, + + base = sym UNMAP_BASE, + options(noreturn), + ); + } +} +"#, + expect_file!["./test_data/highlight_asm.html"], + false, + ); +} diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/to_proto.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/to_proto.rs index b29268f133f3a..4902c9f88c143 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/to_proto.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/to_proto.rs @@ -80,6 +80,7 @@ pub(crate) fn symbol_kind(symbol_kind: SymbolKind) -> lsp_types::SymbolKind { | SymbolKind::ValueParam | SymbolKind::Label => lsp_types::SymbolKind::VARIABLE, SymbolKind::Union => lsp_types::SymbolKind::STRUCT, + SymbolKind::InlineAsmRegOrRegClass => lsp_types::SymbolKind::VARIABLE, } } @@ -159,6 +160,7 @@ pub(crate) fn completion_item_kind( SymbolKind::Variant => lsp_types::CompletionItemKind::ENUM_MEMBER, SymbolKind::BuiltinAttr => lsp_types::CompletionItemKind::FUNCTION, SymbolKind::ToolModule => lsp_types::CompletionItemKind::MODULE, + SymbolKind::InlineAsmRegOrRegClass => lsp_types::CompletionItemKind::KEYWORD, }, } } @@ -702,6 +704,7 @@ fn semantic_token_type_and_modifiers( SymbolKind::ProcMacro => types::PROC_MACRO, SymbolKind::BuiltinAttr => types::BUILTIN_ATTRIBUTE, SymbolKind::ToolModule => types::TOOL_MODULE, + SymbolKind::InlineAsmRegOrRegClass => types::KEYWORD, }, HlTag::AttributeBracket => types::ATTRIBUTE_BRACKET, HlTag::BoolLiteral => types::BOOLEAN, diff --git a/src/tools/rust-analyzer/crates/test-utils/src/minicore.rs b/src/tools/rust-analyzer/crates/test-utils/src/minicore.rs index 4b7e23388c7e9..fec270a556045 100644 --- a/src/tools/rust-analyzer/crates/test-utils/src/minicore.rs +++ b/src/tools/rust-analyzer/crates/test-utils/src/minicore.rs @@ -1475,6 +1475,19 @@ mod panicking { } // endregion:panic +// region:asm +mod arch { + #[rustc_builtin_macro] + pub macro asm("assembly template", $(operands,)* $(options($(option),*))?) { + /* compiler built-in */ + } + #[rustc_builtin_macro] + pub macro global_asm("assembly template", $(operands,)* $(options($(option),*))?) { + /* compiler built-in */ + } +} +// endregion:asm + #[macro_use] mod macros { // region:panic @@ -1487,16 +1500,6 @@ mod macros { } // endregion:panic - // region:asm - #[macro_export] - #[rustc_builtin_macro] - macro_rules! asm { - ($($arg:tt)*) => { - /* compiler built-in */ - }; - } - // endregion:asm - // region:assert #[macro_export] #[rustc_builtin_macro] From 2031eacbab664080e31a17e64c465ddb2905172d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=AE=B8=E6=9D=B0=E5=8F=8B=20Jieyou=20Xu=20=28Joe=29?= <39484203+jieyouxu@users.noreply.github.com> Date: Thu, 5 Sep 2024 07:28:52 +0800 Subject: [PATCH 0518/2194] run_make_support: rename `Command::stdin` to `stdin_buf` and add `std{in,out,err}` config helpers Previously `Command::stdin` was actually just a stdin buffer helper, but this is different from `std::process::Command::stdin`. This is needlessly confusing, and blocks support to add `std{in,out,err}` config that tests may want to use to e.g. redirect to `/dev/ptmx`. --- src/tools/run-make-support/src/command.rs | 68 +++++++++++++++---- .../src/external_deps/llvm.rs | 7 +- .../src/external_deps/rustc.rs | 6 +- .../src/external_deps/rustdoc.rs | 6 +- src/tools/run-make-support/src/lib.rs | 2 + 5 files changed, 67 insertions(+), 22 deletions(-) diff --git a/src/tools/run-make-support/src/command.rs b/src/tools/run-make-support/src/command.rs index a0b96e25a0cba..3f2ae078229dd 100644 --- a/src/tools/run-make-support/src/command.rs +++ b/src/tools/run-make-support/src/command.rs @@ -29,7 +29,14 @@ use crate::{ #[derive(Debug)] pub struct Command { cmd: StdCommand, - stdin: Option>, + // Convience for providing a quick stdin buffer. + stdin_buf: Option>, + + // Configurations for child process's std{in,out,err} handles. + stdin: Option, + stdout: Option, + stderr: Option, + drop_bomb: DropBomb, } @@ -37,12 +44,43 @@ impl Command { #[track_caller] pub fn new>(program: P) -> Self { let program = program.as_ref(); - Self { cmd: StdCommand::new(program), stdin: None, drop_bomb: DropBomb::arm(program) } + Self { + cmd: StdCommand::new(program), + stdin_buf: None, + drop_bomb: DropBomb::arm(program), + stdin: None, + stdout: None, + stderr: None, + } + } + + /// Specify a stdin input buffer. This is a convenience helper, + pub fn stdin_buf>(&mut self, input: I) -> &mut Self { + self.stdin_buf = Some(input.as_ref().to_vec().into_boxed_slice()); + self + } + + /// Configuration for the child process’s standard input (stdin) handle. + /// + /// See [`std::process::Command::stdin`]. + pub fn stdin>(&mut self, cfg: T) -> &mut Self { + self.stdin = Some(cfg.into()); + self + } + + /// Configuration for the child process’s standard output (stdout) handle. + /// + /// See [`std::process::Command::stdout`]. + pub fn stdout>(&mut self, cfg: T) -> &mut Self { + self.stdout = Some(cfg.into()); + self } - /// Specify a stdin input - pub fn stdin>(&mut self, input: I) -> &mut Self { - self.stdin = Some(input.as_ref().to_vec().into_boxed_slice()); + /// Configuration for the child process’s standard error (stderr) handle. + /// + /// See [`std::process::Command::stderr`]. + pub fn stderr>(&mut self, cfg: T) -> &mut Self { + self.stderr = Some(cfg.into()); self } @@ -105,6 +143,8 @@ impl Command { } /// Run the constructed command and assert that it is successfully run. + /// + /// By default, std{in,out,err} are [`Stdio::piped()`]. #[track_caller] pub fn run(&mut self) -> CompletedProcess { let output = self.command_output(); @@ -115,6 +155,8 @@ impl Command { } /// Run the constructed command and assert that it does not successfully run. + /// + /// By default, std{in,out,err} are [`Stdio::piped()`]. #[track_caller] pub fn run_fail(&mut self) -> CompletedProcess { let output = self.command_output(); @@ -124,10 +166,10 @@ impl Command { output } - /// Run the command but do not check its exit status. - /// Only use if you explicitly don't care about the exit status. - /// Prefer to use [`Self::run`] and [`Self::run_fail`] - /// whenever possible. + /// Run the command but do not check its exit status. Only use if you explicitly don't care + /// about the exit status. + /// + /// Prefer to use [`Self::run`] and [`Self::run_fail`] whenever possible. #[track_caller] pub fn run_unchecked(&mut self) -> CompletedProcess { self.command_output() @@ -137,11 +179,11 @@ impl Command { fn command_output(&mut self) -> CompletedProcess { self.drop_bomb.defuse(); // let's make sure we piped all the input and outputs - self.cmd.stdin(Stdio::piped()); - self.cmd.stdout(Stdio::piped()); - self.cmd.stderr(Stdio::piped()); + self.cmd.stdin(self.stdin.take().unwrap_or(Stdio::piped())); + self.cmd.stdout(self.stdout.take().unwrap_or(Stdio::piped())); + self.cmd.stderr(self.stderr.take().unwrap_or(Stdio::piped())); - let output = if let Some(input) = &self.stdin { + let output = if let Some(input) = &self.stdin_buf { let mut child = self.cmd.spawn().unwrap(); { diff --git a/src/tools/run-make-support/src/external_deps/llvm.rs b/src/tools/run-make-support/src/external_deps/llvm.rs index e9315856cd775..2522c4aeb9365 100644 --- a/src/tools/run-make-support/src/external_deps/llvm.rs +++ b/src/tools/run-make-support/src/external_deps/llvm.rs @@ -227,9 +227,10 @@ impl LlvmFilecheck { Self { cmd } } - /// Pipe a read file into standard input containing patterns that will be matched against the .patterns(path) call. - pub fn stdin>(&mut self, input: I) -> &mut Self { - self.cmd.stdin(input); + /// Provide a buffer representing standard input containing patterns that will be matched + /// against the `.patterns(path)` call. + pub fn stdin_buf>(&mut self, input: I) -> &mut Self { + self.cmd.stdin_buf(input); self } diff --git a/src/tools/run-make-support/src/external_deps/rustc.rs b/src/tools/run-make-support/src/external_deps/rustc.rs index cece58d29566c..f60ea972839c1 100644 --- a/src/tools/run-make-support/src/external_deps/rustc.rs +++ b/src/tools/run-make-support/src/external_deps/rustc.rs @@ -291,9 +291,9 @@ impl Rustc { self } - /// Specify a stdin input - pub fn stdin>(&mut self, input: I) -> &mut Self { - self.cmd.stdin(input); + /// Specify a stdin input buffer. + pub fn stdin_buf>(&mut self, input: I) -> &mut Self { + self.cmd.stdin_buf(input); self } diff --git a/src/tools/run-make-support/src/external_deps/rustdoc.rs b/src/tools/run-make-support/src/external_deps/rustdoc.rs index 96b1c719e2e3e..df5e5d8a2e84a 100644 --- a/src/tools/run-make-support/src/external_deps/rustdoc.rs +++ b/src/tools/run-make-support/src/external_deps/rustdoc.rs @@ -85,9 +85,9 @@ impl Rustdoc { self } - /// Specify a stdin input - pub fn stdin>(&mut self, input: I) -> &mut Self { - self.cmd.stdin(input); + /// Specify a stdin input buffer. + pub fn stdin_buf>(&mut self, input: I) -> &mut Self { + self.cmd.stdin_buf(input); self } diff --git a/src/tools/run-make-support/src/lib.rs b/src/tools/run-make-support/src/lib.rs index 989d00d4c2f97..fefafb95b33b1 100644 --- a/src/tools/run-make-support/src/lib.rs +++ b/src/tools/run-make-support/src/lib.rs @@ -34,6 +34,7 @@ pub mod rfs { } // Re-exports of third-party library crates. +// tidy-alphabetical-start pub use bstr; pub use gimli; pub use libc; @@ -41,6 +42,7 @@ pub use object; pub use regex; pub use serde_json; pub use wasmparser; +// tidy-alphabetical-end // Re-exports of external dependencies. pub use external_deps::{c_build, cc, clang, htmldocck, llvm, python, rustc, rustdoc}; From afed862b26335b37539ec2cd295e34ef3fb844be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=AE=B8=E6=9D=B0=E5=8F=8B=20Jieyou=20Xu=20=28Joe=29?= <39484203+jieyouxu@users.noreply.github.com> Date: Thu, 5 Sep 2024 08:02:32 +0800 Subject: [PATCH 0519/2194] tests: use renamed `stdin_buf` --- tests/run-make/clear-error-blank-output/rmake.rs | 2 +- tests/run-make/comment-section/rmake.rs | 2 +- tests/run-make/compile-stdin/rmake.rs | 2 +- tests/run-make/libtest-junit/rmake.rs | 2 +- tests/run-make/llvm-ident/rmake.rs | 2 +- tests/run-make/llvm-outputs/rmake.rs | 4 ++-- tests/run-make/no-builtins-attribute/rmake.rs | 2 +- tests/run-make/pgo-branch-weights/rmake.rs | 5 ++++- tests/run-make/pgo-indirect-call-promotion/rmake.rs | 5 ++++- tests/run-make/pgo-use/rmake.rs | 2 +- tests/run-make/separate-link/rmake.rs | 2 +- tests/run-make/static-pie/rmake.rs | 2 +- tests/run-make/stdin-rustc/rmake.rs | 4 ++-- tests/run-make/stdin-rustdoc/rmake.rs | 4 ++-- tests/run-make/sysroot-crates-are-unstable/rmake.rs | 2 +- tests/run-make/unknown-mod-stdin/rmake.rs | 2 +- .../x86_64-fortanix-unknown-sgx-lvi/rmake.rs | 12 ++++++++---- 17 files changed, 33 insertions(+), 23 deletions(-) diff --git a/tests/run-make/clear-error-blank-output/rmake.rs b/tests/run-make/clear-error-blank-output/rmake.rs index e0f042cf805b5..22e030691f289 100644 --- a/tests/run-make/clear-error-blank-output/rmake.rs +++ b/tests/run-make/clear-error-blank-output/rmake.rs @@ -8,6 +8,6 @@ use run_make_support::rustc; fn main() { - let output = rustc().output("").stdin(b"fn main() {}").run_fail(); + let output = rustc().output("").stdin_buf(b"fn main() {}").run_fail(); output.assert_stderr_not_contains("panic"); } diff --git a/tests/run-make/comment-section/rmake.rs b/tests/run-make/comment-section/rmake.rs index 1557f50dbd024..ccfc38e870d88 100644 --- a/tests/run-make/comment-section/rmake.rs +++ b/tests/run-make/comment-section/rmake.rs @@ -14,7 +14,7 @@ fn main() { rustc() .arg("-") - .stdin("fn main() {}") + .stdin_buf("fn main() {}") .emit("link,obj") .arg("-Csave-temps") .target(target) diff --git a/tests/run-make/compile-stdin/rmake.rs b/tests/run-make/compile-stdin/rmake.rs index f93080dfdc4fe..b8244335855c5 100644 --- a/tests/run-make/compile-stdin/rmake.rs +++ b/tests/run-make/compile-stdin/rmake.rs @@ -8,6 +8,6 @@ use run_make_support::{run, rustc}; fn main() { - rustc().arg("-").stdin("fn main() {}").run(); + rustc().arg("-").stdin_buf("fn main() {}").run(); run("rust_out"); } diff --git a/tests/run-make/libtest-junit/rmake.rs b/tests/run-make/libtest-junit/rmake.rs index d631313ed9210..5917660b6c7ff 100644 --- a/tests/run-make/libtest-junit/rmake.rs +++ b/tests/run-make/libtest-junit/rmake.rs @@ -21,7 +21,7 @@ fn run_tests(extra_args: &[&str], expected_file: &str) { .run_fail(); let test_stdout = &cmd_out.stdout_utf8(); - python_command().arg("validate_junit.py").stdin(test_stdout).run(); + python_command().arg("validate_junit.py").stdin_buf(test_stdout).run(); diff() .expected_file(expected_file) diff --git a/tests/run-make/llvm-ident/rmake.rs b/tests/run-make/llvm-ident/rmake.rs index 9699d0579f6ef..47e6fc4de15b3 100644 --- a/tests/run-make/llvm-ident/rmake.rs +++ b/tests/run-make/llvm-ident/rmake.rs @@ -17,7 +17,7 @@ fn main() { .codegen_units(16) .opt_level("2") .target(&env_var("TARGET")) - .stdin("fn main(){}") + .stdin_buf("fn main(){}") .run(); // `llvm-dis` is used here since `--emit=llvm-ir` does not emit LLVM IR diff --git a/tests/run-make/llvm-outputs/rmake.rs b/tests/run-make/llvm-outputs/rmake.rs index b8ac21c98a010..632e9a09ba503 100644 --- a/tests/run-make/llvm-outputs/rmake.rs +++ b/tests/run-make/llvm-outputs/rmake.rs @@ -11,8 +11,8 @@ fn main() { let p = cwd(); path_bc = p.join("nonexistant_dir_bc"); path_ir = p.join("nonexistant_dir_ir"); - rustc().input("-").stdin("fn main() {}").out_dir(&path_bc).emit("llvm-bc").run(); - rustc().input("-").stdin("fn main() {}").out_dir(&path_ir).emit("llvm-ir").run(); + rustc().input("-").stdin_buf("fn main() {}").out_dir(&path_bc).emit("llvm-bc").run(); + rustc().input("-").stdin_buf("fn main() {}").out_dir(&path_ir).emit("llvm-ir").run(); assert!(path_bc.exists()); assert!(path_ir.exists()); }); diff --git a/tests/run-make/no-builtins-attribute/rmake.rs b/tests/run-make/no-builtins-attribute/rmake.rs index 1e15b0c03f1d9..7182c65a2c59e 100644 --- a/tests/run-make/no-builtins-attribute/rmake.rs +++ b/tests/run-make/no-builtins-attribute/rmake.rs @@ -9,5 +9,5 @@ use run_make_support::{llvm_filecheck, rfs, rustc}; fn main() { rustc().input("no_builtins.rs").emit("link").run(); rustc().input("main.rs").emit("llvm-ir").run(); - llvm_filecheck().patterns("filecheck.main.txt").stdin(rfs::read("main.ll")).run(); + llvm_filecheck().patterns("filecheck.main.txt").stdin_buf(rfs::read("main.ll")).run(); } diff --git a/tests/run-make/pgo-branch-weights/rmake.rs b/tests/run-make/pgo-branch-weights/rmake.rs index ef33d009dbb20..105c2fafc5a10 100644 --- a/tests/run-make/pgo-branch-weights/rmake.rs +++ b/tests/run-make/pgo-branch-weights/rmake.rs @@ -35,5 +35,8 @@ fn main() { .codegen_units(1) .emit("llvm-ir") .run(); - llvm_filecheck().patterns("filecheck-patterns.txt").stdin(rfs::read("interesting.ll")).run(); + llvm_filecheck() + .patterns("filecheck-patterns.txt") + .stdin_buf(rfs::read("interesting.ll")) + .run(); } diff --git a/tests/run-make/pgo-indirect-call-promotion/rmake.rs b/tests/run-make/pgo-indirect-call-promotion/rmake.rs index d0ccfd8a4d7e4..28232eb256621 100644 --- a/tests/run-make/pgo-indirect-call-promotion/rmake.rs +++ b/tests/run-make/pgo-indirect-call-promotion/rmake.rs @@ -29,5 +29,8 @@ fn main() { .codegen_units(1) .emit("llvm-ir") .run(); - llvm_filecheck().patterns("filecheck-patterns.txt").stdin(rfs::read("interesting.ll")).run(); + llvm_filecheck() + .patterns("filecheck-patterns.txt") + .stdin_buf(rfs::read("interesting.ll")) + .run(); } diff --git a/tests/run-make/pgo-use/rmake.rs b/tests/run-make/pgo-use/rmake.rs index cad49372266e8..276af9ea263a7 100644 --- a/tests/run-make/pgo-use/rmake.rs +++ b/tests/run-make/pgo-use/rmake.rs @@ -51,5 +51,5 @@ fn main() { let lines: Vec<_> = ir.lines().rev().collect(); let mut reversed_ir = lines.join("\n"); reversed_ir.push('\n'); - llvm_filecheck().patterns("filecheck-patterns.txt").stdin(reversed_ir.as_bytes()).run(); + llvm_filecheck().patterns("filecheck-patterns.txt").stdin_buf(reversed_ir.as_bytes()).run(); } diff --git a/tests/run-make/separate-link/rmake.rs b/tests/run-make/separate-link/rmake.rs index e91b25489bc59..0ec7334e75de7 100644 --- a/tests/run-make/separate-link/rmake.rs +++ b/tests/run-make/separate-link/rmake.rs @@ -8,7 +8,7 @@ use run_make_support::{run, rustc}; fn main() { - rustc().stdin(b"fn main(){}").arg("-Zno-link").arg("-").run(); + rustc().stdin_buf(b"fn main(){}").arg("-Zno-link").arg("-").run(); rustc().arg("-Zlink-only").input("rust_out.rlink").run(); run("rust_out"); } diff --git a/tests/run-make/static-pie/rmake.rs b/tests/run-make/static-pie/rmake.rs index 74f86bb8163b0..1557c170f56de 100644 --- a/tests/run-make/static-pie/rmake.rs +++ b/tests/run-make/static-pie/rmake.rs @@ -28,7 +28,7 @@ fn ok_compiler_version(compiler: &str) -> bool { } let compiler_output = - cmd(compiler).stdin(trigger).arg("-").arg("-E").arg("-x").arg("c").run().stdout_utf8(); + cmd(compiler).stdin_buf(trigger).arg("-").arg("-E").arg("-x").arg("c").run().stdout_utf8(); let re = Regex::new(r"(?m)^(\d+)").unwrap(); let version: u32 = re.captures(&compiler_output).unwrap().get(1).unwrap().as_str().parse().unwrap(); diff --git a/tests/run-make/stdin-rustc/rmake.rs b/tests/run-make/stdin-rustc/rmake.rs index 68e9cf2fbd803..2d634dd455eb2 100644 --- a/tests/run-make/stdin-rustc/rmake.rs +++ b/tests/run-make/stdin-rustc/rmake.rs @@ -14,7 +14,7 @@ const NOT_UTF8: &[u8] = &[0xff, 0xff, 0xff]; fn main() { // echo $HELLO_WORLD | rustc - - rustc().arg("-").stdin(HELLO_WORLD).run(); + rustc().arg("-").stdin_buf(HELLO_WORLD).run(); assert!( PathBuf::from(if !is_windows() { "rust_out" } else { "rust_out.exe" }) .try_exists() @@ -22,7 +22,7 @@ fn main() { ); // echo $NOT_UTF8 | rustc - - rustc().arg("-").stdin(NOT_UTF8).run_fail().assert_stderr_contains( + rustc().arg("-").stdin_buf(NOT_UTF8).run_fail().assert_stderr_contains( "error: couldn't read from stdin, as it did not contain valid UTF-8", ); } diff --git a/tests/run-make/stdin-rustdoc/rmake.rs b/tests/run-make/stdin-rustdoc/rmake.rs index de47a24fbdd4f..30f97b8a2cd75 100644 --- a/tests/run-make/stdin-rustdoc/rmake.rs +++ b/tests/run-make/stdin-rustdoc/rmake.rs @@ -15,11 +15,11 @@ fn main() { let out_dir = PathBuf::from("doc"); // rustdoc - - rustdoc().arg("-").out_dir(&out_dir).stdin(INPUT).run(); + rustdoc().arg("-").out_dir(&out_dir).stdin_buf(INPUT).run(); assert!(out_dir.join("rust_out/struct.F.html").try_exists().unwrap()); // rustdoc --test - - rustdoc().arg("--test").arg("-").stdin(INPUT).run(); + rustdoc().arg("--test").arg("-").stdin_buf(INPUT).run(); // rustdoc file.rs - rustdoc().arg("file.rs").arg("-").run_fail(); diff --git a/tests/run-make/sysroot-crates-are-unstable/rmake.rs b/tests/run-make/sysroot-crates-are-unstable/rmake.rs index 2240d87237b1a..c81c7fafdab0b 100644 --- a/tests/run-make/sysroot-crates-are-unstable/rmake.rs +++ b/tests/run-make/sysroot-crates-are-unstable/rmake.rs @@ -34,7 +34,7 @@ fn check_crate_is_unstable(cr: &Crate) { .target(target()) .extern_(name, path) .input("-") - .stdin(format!("extern crate {name};")) + .stdin_buf(format!("extern crate {name};")) .run_fail(); // Make sure it failed for the intended reason, not some other reason. diff --git a/tests/run-make/unknown-mod-stdin/rmake.rs b/tests/run-make/unknown-mod-stdin/rmake.rs index 0fe5c78ed0ff0..6be3119c0fd15 100644 --- a/tests/run-make/unknown-mod-stdin/rmake.rs +++ b/tests/run-make/unknown-mod-stdin/rmake.rs @@ -12,7 +12,7 @@ use run_make_support::{diff, rustc}; fn main() { - let out = rustc().crate_type("rlib").stdin(b"mod unknown;").arg("-").run_fail(); + let out = rustc().crate_type("rlib").stdin_buf(b"mod unknown;").arg("-").run_fail(); diff() .actual_text("actual-stdout", out.stdout_utf8()) .expected_file("unknown-mod.stdout") diff --git a/tests/run-make/x86_64-fortanix-unknown-sgx-lvi/rmake.rs b/tests/run-make/x86_64-fortanix-unknown-sgx-lvi/rmake.rs index 130781a429371..e58762aeb6db7 100644 --- a/tests/run-make/x86_64-fortanix-unknown-sgx-lvi/rmake.rs +++ b/tests/run-make/x86_64-fortanix-unknown-sgx-lvi/rmake.rs @@ -78,19 +78,23 @@ fn check(func_re: &str, mut checks: &str) { // This is because frame pointers are optional, and them being enabled requires // an additional `popq` in the pattern checking file. if func_re == "std::io::stdio::_print::[[:alnum:]]+" { - let output = llvm_filecheck().stdin(&dump).patterns(checks).run_unchecked(); + let output = llvm_filecheck().stdin_buf(&dump).patterns(checks).run_unchecked(); if !output.status().success() { checks = "print.without_frame_pointers.checks"; - llvm_filecheck().stdin(&dump).patterns(checks).run(); + llvm_filecheck().stdin_buf(&dump).patterns(checks).run(); } } else { - llvm_filecheck().stdin(&dump).patterns(checks).run(); + llvm_filecheck().stdin_buf(&dump).patterns(checks).run(); } if !["rust_plus_one_global_asm", "cmake_plus_one_c_global_asm", "cmake_plus_one_cxx_global_asm"] .contains(&func_re) { // The assembler cannot avoid explicit `ret` instructions. Sequences // of `shlq $0x0, (%rsp); lfence; retq` are used instead. - llvm_filecheck().args(&["--implicit-check-not", "ret"]).stdin(dump).patterns(checks).run(); + llvm_filecheck() + .args(&["--implicit-check-not", "ret"]) + .stdin_buf(dump) + .patterns(checks) + .run(); } } From 304f54e023cf5784163a319b22316950c71c58f2 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Thu, 5 Sep 2024 10:53:07 +0200 Subject: [PATCH 0520/2194] Add Definition kind for asm register operand --- .../rust-analyzer/crates/ide-db/src/defs.rs | 17 ++++++--- .../rust-analyzer/crates/ide-db/src/rename.rs | 2 ++ .../rust-analyzer/crates/ide/src/doc_links.rs | 6 ++-- .../rust-analyzer/crates/ide/src/moniker.rs | 5 +-- .../crates/ide/src/navigation_target.rs | 2 ++ .../ide/src/syntax_highlighting/highlight.rs | 1 + .../ide/src/syntax_highlighting/inject.rs | 1 + .../test_data/highlight_asm.html | 9 +++-- .../test_data/highlight_strings.html | 4 +-- .../ide/src/syntax_highlighting/tests.rs | 3 +- .../parser/src/grammar/expressions/atom.rs | 8 +++-- .../test_data/parser/inline/ok/asm_expr.rast | 36 ++++++++++--------- 12 files changed, 59 insertions(+), 35 deletions(-) diff --git a/src/tools/rust-analyzer/crates/ide-db/src/defs.rs b/src/tools/rust-analyzer/crates/ide-db/src/defs.rs index 3d372bab27471..469f83644fc5f 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/defs.rs +++ b/src/tools/rust-analyzer/crates/ide-db/src/defs.rs @@ -51,6 +51,7 @@ pub enum Definition { ToolModule(ToolModule), ExternCrateDecl(ExternCrateDecl), InlineAsmRegOrRegClass(()), + InlineAsmRegOperand(()), } impl Definition { @@ -89,7 +90,8 @@ impl Definition { | Definition::BuiltinLifetime(_) | Definition::TupleField(_) | Definition::ToolModule(_) - | Definition::InlineAsmRegOrRegClass(_) => return None, + | Definition::InlineAsmRegOrRegClass(_) + | Definition::InlineAsmRegOperand(_) => return None, }; Some(module) } @@ -124,7 +126,8 @@ impl Definition { | Definition::GenericParam(_) | Definition::Label(_) | Definition::DeriveHelper(_) - | Definition::InlineAsmRegOrRegClass(_) => return None, + | Definition::InlineAsmRegOrRegClass(_) + | Definition::InlineAsmRegOperand(_) => return None, }; Some(vis) } @@ -153,7 +156,9 @@ impl Definition { Definition::ToolModule(_) => return None, // FIXME Definition::DeriveHelper(it) => it.name(db), Definition::ExternCrateDecl(it) => return it.alias_or_name(db), - Definition::InlineAsmRegOrRegClass(_) => return None, // FIXME + Definition::InlineAsmRegOrRegClass(_) | Definition::InlineAsmRegOperand(_) => { + return None + } // FIXME }; Some(name) } @@ -216,7 +221,7 @@ impl Definition { Definition::ToolModule(_) => None, Definition::DeriveHelper(_) => None, Definition::TupleField(_) => None, - Definition::InlineAsmRegOrRegClass(_) => None, + Definition::InlineAsmRegOrRegClass(_) | Definition::InlineAsmRegOperand(_) => None, }; docs.or_else(|| { @@ -275,6 +280,7 @@ impl Definition { } // FIXME Definition::InlineAsmRegOrRegClass(_) => "inline_asm_reg_or_reg_class".to_owned(), + Definition::InlineAsmRegOperand(_) => "inline_asm_reg_operand".to_owned(), } } } @@ -706,6 +712,9 @@ impl NameRefClass { NameRefClass::ExternCrateShorthand { krate, decl: extern_crate } }) }, + ast::AsmRegSpec(_) => { + Some(NameRefClass::Definition(Definition::InlineAsmRegOrRegClass(()))) + }, _ => None } } diff --git a/src/tools/rust-analyzer/crates/ide-db/src/rename.rs b/src/tools/rust-analyzer/crates/ide-db/src/rename.rs index 3a1a9aba8551c..e8299a4a46347 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/rename.rs +++ b/src/tools/rust-analyzer/crates/ide-db/src/rename.rs @@ -207,6 +207,8 @@ impl Definition { | Definition::ToolModule(_) | Definition::TupleField(_) | Definition::InlineAsmRegOrRegClass(_) => return None, + // FIXME: + Definition::InlineAsmRegOperand(_) => return None, // FIXME: This should be doable in theory Definition::DeriveHelper(_) => return None, }; diff --git a/src/tools/rust-analyzer/crates/ide/src/doc_links.rs b/src/tools/rust-analyzer/crates/ide/src/doc_links.rs index aa632ab12f742..184486ec0a1e7 100644 --- a/src/tools/rust-analyzer/crates/ide/src/doc_links.rs +++ b/src/tools/rust-analyzer/crates/ide/src/doc_links.rs @@ -220,7 +220,8 @@ pub(crate) fn resolve_doc_path_for_def( | Definition::GenericParam(_) | Definition::Label(_) | Definition::DeriveHelper(_) - | Definition::InlineAsmRegOrRegClass(_) => None, + | Definition::InlineAsmRegOrRegClass(_) + | Definition::InlineAsmRegOperand(_) => None, } .map(Definition::from) } @@ -674,7 +675,8 @@ fn filename_and_frag_for_def( | Definition::BuiltinLifetime(_) | Definition::ToolModule(_) | Definition::DeriveHelper(_) - | Definition::InlineAsmRegOrRegClass(_) => return None, + | Definition::InlineAsmRegOrRegClass(_) + | Definition::InlineAsmRegOperand(_) => return None, }; Some((def, res, None)) diff --git a/src/tools/rust-analyzer/crates/ide/src/moniker.rs b/src/tools/rust-analyzer/crates/ide/src/moniker.rs index 69c94bc357838..1f996f716d0eb 100644 --- a/src/tools/rust-analyzer/crates/ide/src/moniker.rs +++ b/src/tools/rust-analyzer/crates/ide/src/moniker.rs @@ -223,7 +223,7 @@ pub(crate) fn def_to_kind(db: &RootDatabase, def: Definition) -> SymbolInformati Variable } } - Definition::Label(..) => Variable, // For lack of a better variant + Definition::Label(..) | Definition::InlineAsmRegOperand(_) => Variable, // For lack of a better variant Definition::DeriveHelper(..) => Attribute, Definition::BuiltinAttr(..) => Attribute, Definition::ToolModule(..) => Module, @@ -322,7 +322,8 @@ pub(crate) fn def_to_moniker( | Definition::BuiltinLifetime(_) | Definition::BuiltinAttr(_) | Definition::ToolModule(_) - | Definition::InlineAsmRegOrRegClass(_) => return None, + | Definition::InlineAsmRegOrRegClass(_) + | Definition::InlineAsmRegOperand(_) => return None, Definition::Local(local) => { if !local.is_param(db) { diff --git a/src/tools/rust-analyzer/crates/ide/src/navigation_target.rs b/src/tools/rust-analyzer/crates/ide/src/navigation_target.rs index cf1412560ddf2..eb28b78e60ca5 100644 --- a/src/tools/rust-analyzer/crates/ide/src/navigation_target.rs +++ b/src/tools/rust-analyzer/crates/ide/src/navigation_target.rs @@ -244,6 +244,8 @@ impl TryToNav for Definition { | Definition::ToolModule(_) | Definition::InlineAsmRegOrRegClass(_) | Definition::BuiltinAttr(_) => None, + // FIXME + Definition::InlineAsmRegOperand(_) => None, // FIXME: The focus range should be set to the helper declaration Definition::DeriveHelper(it) => it.derive().try_to_nav(db), } diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/highlight.rs b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/highlight.rs index 2894cb9cf6dce..fe1d0b452aede 100644 --- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/highlight.rs +++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/highlight.rs @@ -537,6 +537,7 @@ pub(super) fn highlight_def( Definition::InlineAsmRegOrRegClass(_) => { Highlight::new(HlTag::Symbol(SymbolKind::InlineAsmRegOrRegClass)) } + Definition::InlineAsmRegOperand(_) => Highlight::new(HlTag::Symbol(SymbolKind::Local)), }; let def_crate = def.krate(db); diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/inject.rs b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/inject.rs index e2b32c17d66a7..bff52943afdf5 100644 --- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/inject.rs +++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/inject.rs @@ -316,6 +316,7 @@ fn module_def_to_hl_tag(def: Definition) -> HlTag { Definition::ToolModule(_) => SymbolKind::ToolModule, Definition::DeriveHelper(_) => SymbolKind::DeriveHelper, Definition::InlineAsmRegOrRegClass(_) => SymbolKind::InlineAsmRegOrRegClass, + Definition::InlineAsmRegOperand(_) => SymbolKind::Local, }; HlTag::Symbol(symbol) } diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_asm.html b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_asm.html index 1280d78cc815e..9cedf012f7fde 100644 --- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_asm.html +++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_asm.html @@ -51,18 +51,17 @@ let mut o = 0; core::arch::asm!( "%input = OpLoad _ {0}", - concat!("%result = ", bar, " _ %input"), + concat!("%result = ", "bar", " _ %input"), "OpStore {1} %result", - in(reg) &foo, - in(reg) &mut o, + in(reg) &foo, + in(reg) &mut o, ); - o let thread_id: usize; core::arch::asm!(" mov {0}, gs:[0x30] mov {0}, [{0}+0x48] - ", out(reg) thread_id, options(pure, readonly, nostack)); + "
, out(reg) thread_id, options(pure, readonly, nostack)); static UNMAP_BASE: usize; const MEM_RELEASE: usize; diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_strings.html b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_strings.html index ced522e7ebb21..b387808b297cd 100644 --- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_strings.html +++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_strings.html @@ -168,8 +168,8 @@ core::arch::asm!( "mov {0}, {1}", "add {0}, 5", - out(reg) o, - in(reg) i, + out(reg) o, + in(reg) i, ); const CONSTANT: () = (): diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/tests.rs b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/tests.rs index dbe8de8f91ffe..f47b2115bfc68 100644 --- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/tests.rs +++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/tests.rs @@ -1287,12 +1287,11 @@ fn main() { let mut o = 0; core::arch::asm!( "%input = OpLoad _ {0}", - concat!("%result = ", bar, " _ %input"), + concat!("%result = ", "bar", " _ %input"), "OpStore {1} %result", in(reg) &foo, in(reg) &mut o, ); - o let thread_id: usize; core::arch::asm!(" diff --git a/src/tools/rust-analyzer/crates/parser/src/grammar/expressions/atom.rs b/src/tools/rust-analyzer/crates/parser/src/grammar/expressions/atom.rs index f98ca5f403225..d6ccf38e7436e 100644 --- a/src/tools/rust-analyzer/crates/parser/src/grammar/expressions/atom.rs +++ b/src/tools/rust-analyzer/crates/parser/src/grammar/expressions/atom.rs @@ -453,9 +453,13 @@ fn parse_clobber_abi(p: &mut Parser<'_>) { fn parse_reg(p: &mut Parser<'_>) { p.expect(T!['(']); if p.at(T![ident]) { - name_ref(p) + let m = p.start(); + name_ref(p); + m.complete(p, ASM_REG_SPEC); } else if p.at(T![string]) { - p.bump_any() + let m = p.start(); + p.bump_any(); + m.complete(p, ASM_REG_SPEC); } else { p.err_and_bump("expected register name"); } diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/asm_expr.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/asm_expr.rast index f4d53fa9ae657..2360135db7cfe 100644 --- a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/asm_expr.rast +++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/asm_expr.rast @@ -35,16 +35,18 @@ SOURCE_FILE STRING "\"add {x}, {tmp}\"" COMMA "," WHITESPACE "\n " - NAME - IDENT "x" - WHITESPACE " " - EQ "=" - WHITESPACE " " ASM_REG_OPERAND - INOUT_KW "inout" + NAME + IDENT "x" + WHITESPACE " " + EQ "=" + WHITESPACE " " + ASM_DIR_SPEC + INOUT_KW "inout" L_PAREN "(" - NAME_REF - IDENT "reg" + ASM_REG_SPEC + NAME_REF + IDENT "reg" R_PAREN ")" WHITESPACE " " PATH_EXPR @@ -54,16 +56,18 @@ SOURCE_FILE IDENT "x" COMMA "," WHITESPACE "\n " - NAME - IDENT "tmp" - WHITESPACE " " - EQ "=" - WHITESPACE " " ASM_REG_OPERAND - OUT_KW "out" + NAME + IDENT "tmp" + WHITESPACE " " + EQ "=" + WHITESPACE " " + ASM_DIR_SPEC + OUT_KW "out" L_PAREN "(" - NAME_REF - IDENT "reg" + ASM_REG_SPEC + NAME_REF + IDENT "reg" R_PAREN ")" WHITESPACE " " UNDERSCORE_EXPR From 5f22103395c513a5dffcbe7c10b207900ce61967 Mon Sep 17 00:00:00 2001 From: Konstantinos Andrikopoulos Date: Sat, 27 Jul 2024 22:26:57 +0200 Subject: [PATCH 0521/2194] Detect pthread_mutex_t is moved See: #3749 --- src/tools/miri/src/concurrency/init_once.rs | 10 +- src/tools/miri/src/concurrency/sync.rs | 119 +++++++++- src/tools/miri/src/lib.rs | 5 +- src/tools/miri/src/shims/unix/macos/sync.rs | 2 +- src/tools/miri/src/shims/unix/sync.rs | 222 ++++++++++-------- .../libc_pthread_mutex_move.init.stderr | 20 ++ .../concurrency/libc_pthread_mutex_move.rs | 28 +++ ...hread_mutex_move.static_initializer.stderr | 20 ++ 8 files changed, 310 insertions(+), 116 deletions(-) create mode 100644 src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutex_move.init.stderr create mode 100644 src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutex_move.rs create mode 100644 src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutex_move.static_initializer.stderr diff --git a/src/tools/miri/src/concurrency/init_once.rs b/src/tools/miri/src/concurrency/init_once.rs index c23e5737280e7..d709e4e6eaedb 100644 --- a/src/tools/miri/src/concurrency/init_once.rs +++ b/src/tools/miri/src/concurrency/init_once.rs @@ -35,8 +35,14 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { offset: u64, ) -> InterpResult<'tcx, InitOnceId> { let this = self.eval_context_mut(); - this.get_or_create_id(lock_op, lock_layout, offset, |ecx| &mut ecx.machine.sync.init_onces)? - .ok_or_else(|| err_ub_format!("init_once has invalid ID").into()) + this.get_or_create_id( + lock_op, + lock_layout, + offset, + |ecx| &mut ecx.machine.sync.init_onces, + |_| Ok(Default::default()), + )? + .ok_or_else(|| err_ub_format!("init_once has invalid ID").into()) } #[inline] diff --git a/src/tools/miri/src/concurrency/sync.rs b/src/tools/miri/src/concurrency/sync.rs index d972831c7689f..97e910df6a2c0 100644 --- a/src/tools/miri/src/concurrency/sync.rs +++ b/src/tools/miri/src/concurrency/sync.rs @@ -66,6 +66,27 @@ pub(super) use declare_id; declare_id!(MutexId); +/// The mutex kind. +#[derive(Debug, Clone, Copy)] +#[non_exhaustive] +pub enum MutexKind { + Invalid, + Normal, + Default, + Recursive, + ErrorCheck, +} + +#[derive(Debug)] +/// Additional data that may be used by shim implementations. +pub struct AdditionalMutexData { + /// The mutex kind, used by some mutex implementations like pthreads mutexes. + pub kind: MutexKind, + + /// The address of the mutex. + pub address: u64, +} + /// The mutex state. #[derive(Default, Debug)] struct Mutex { @@ -77,6 +98,9 @@ struct Mutex { queue: VecDeque, /// Mutex clock. This tracks the moment of the last unlock. clock: VClock, + + /// Additional data that can be set by shim implementations. + data: Option, } declare_id!(RwLockId); @@ -168,13 +192,15 @@ pub(super) trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { /// Returns `None` if memory stores a non-zero invalid ID. /// /// `get_objs` must return the `IndexVec` that stores all the objects of this type. + /// `create_obj` must create the new object if initialization is needed. #[inline] - fn get_or_create_id( + fn get_or_create_id( &mut self, lock_op: &OpTy<'tcx>, lock_layout: TyAndLayout<'tcx>, offset: u64, get_objs: impl for<'a> Fn(&'a mut MiriInterpCx<'tcx>) -> &'a mut IndexVec, + create_obj: impl for<'a> FnOnce(&'a mut MiriInterpCx<'tcx>) -> InterpResult<'tcx, T>, ) -> InterpResult<'tcx, Option> { let this = self.eval_context_mut(); let value_place = @@ -196,7 +222,8 @@ pub(super) trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { Ok(if success.to_bool().expect("compare_exchange's second return value is a bool") { // We set the in-memory ID to `next_index`, now also create this object in the machine // state. - let new_index = get_objs(this).push(T::default()); + let obj = create_obj(this)?; + let new_index = get_objs(this).push(obj); assert_eq!(next_index, new_index); Some(new_index) } else { @@ -210,6 +237,32 @@ pub(super) trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { }) } + /// Eagerly creates a Miri sync structure. + /// + /// `create_id` will store the index of the sync_structure in the memory pointed to by + /// `lock_op`, so that future calls to `get_or_create_id` will see it as initialized. + /// - `lock_op` must hold a pointer to the sync structure. + /// - `lock_layout` must be the memory layout of the sync structure. + /// - `offset` must be the offset inside the sync structure where its miri id will be stored. + /// - `get_objs` is described in `get_or_create_id`. + /// - `obj` must be the new sync object. + fn create_id( + &mut self, + lock_op: &OpTy<'tcx>, + lock_layout: TyAndLayout<'tcx>, + offset: u64, + get_objs: impl for<'a> Fn(&'a mut MiriInterpCx<'tcx>) -> &'a mut IndexVec, + obj: T, + ) -> InterpResult<'tcx, Id> { + let this = self.eval_context_mut(); + let value_place = + this.deref_pointer_and_offset(lock_op, offset, lock_layout, this.machine.layouts.u32)?; + + let new_index = get_objs(this).push(obj); + this.write_scalar(Scalar::from_u32(new_index.to_u32()), &value_place)?; + Ok(new_index) + } + fn condvar_reacquire_mutex( &mut self, mutex: MutexId, @@ -236,15 +289,53 @@ pub(super) trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { // situations. impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {} pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { + /// Eagerly create and initialize a new mutex. + fn mutex_create( + &mut self, + lock_op: &OpTy<'tcx>, + lock_layout: TyAndLayout<'tcx>, + offset: u64, + data: Option, + ) -> InterpResult<'tcx, MutexId> { + let this = self.eval_context_mut(); + this.create_id( + lock_op, + lock_layout, + offset, + |ecx| &mut ecx.machine.sync.mutexes, + Mutex { data, ..Default::default() }, + ) + } + + /// Lazily create a new mutex. + /// `initialize_data` must return any additional data that a user wants to associate with the mutex. fn mutex_get_or_create_id( &mut self, lock_op: &OpTy<'tcx>, lock_layout: TyAndLayout<'tcx>, offset: u64, + initialize_data: impl for<'a> FnOnce( + &'a mut MiriInterpCx<'tcx>, + ) -> InterpResult<'tcx, Option>, ) -> InterpResult<'tcx, MutexId> { let this = self.eval_context_mut(); - this.get_or_create_id(lock_op, lock_layout, offset, |ecx| &mut ecx.machine.sync.mutexes)? - .ok_or_else(|| err_ub_format!("mutex has invalid ID").into()) + this.get_or_create_id( + lock_op, + lock_layout, + offset, + |ecx| &mut ecx.machine.sync.mutexes, + |ecx| initialize_data(ecx).map(|data| Mutex { data, ..Default::default() }), + )? + .ok_or_else(|| err_ub_format!("mutex has invalid ID").into()) + } + + /// Retrieve the additional data stored for a mutex. + fn mutex_get_data<'a>(&'a mut self, id: MutexId) -> Option<&'a AdditionalMutexData> + where + 'tcx: 'a, + { + let this = self.eval_context_ref(); + this.machine.sync.mutexes[id].data.as_ref() } fn rwlock_get_or_create_id( @@ -254,8 +345,14 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { offset: u64, ) -> InterpResult<'tcx, RwLockId> { let this = self.eval_context_mut(); - this.get_or_create_id(lock_op, lock_layout, offset, |ecx| &mut ecx.machine.sync.rwlocks)? - .ok_or_else(|| err_ub_format!("rwlock has invalid ID").into()) + this.get_or_create_id( + lock_op, + lock_layout, + offset, + |ecx| &mut ecx.machine.sync.rwlocks, + |_| Ok(Default::default()), + )? + .ok_or_else(|| err_ub_format!("rwlock has invalid ID").into()) } fn condvar_get_or_create_id( @@ -265,8 +362,14 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { offset: u64, ) -> InterpResult<'tcx, CondvarId> { let this = self.eval_context_mut(); - this.get_or_create_id(lock_op, lock_layout, offset, |ecx| &mut ecx.machine.sync.condvars)? - .ok_or_else(|| err_ub_format!("condvar has invalid ID").into()) + this.get_or_create_id( + lock_op, + lock_layout, + offset, + |ecx| &mut ecx.machine.sync.condvars, + |_| Ok(Default::default()), + )? + .ok_or_else(|| err_ub_format!("condvar has invalid ID").into()) } #[inline] diff --git a/src/tools/miri/src/lib.rs b/src/tools/miri/src/lib.rs index ece393caf9a1e..fdb12bd6912ad 100644 --- a/src/tools/miri/src/lib.rs +++ b/src/tools/miri/src/lib.rs @@ -130,7 +130,10 @@ pub use crate::concurrency::{ cpu_affinity::MAX_CPUS, data_race::{AtomicFenceOrd, AtomicReadOrd, AtomicRwOrd, AtomicWriteOrd, EvalContextExt as _}, init_once::{EvalContextExt as _, InitOnceId}, - sync::{CondvarId, EvalContextExt as _, MutexId, RwLockId, SynchronizationObjects}, + sync::{ + AdditionalMutexData, CondvarId, EvalContextExt as _, MutexId, MutexKind, RwLockId, + SynchronizationObjects, + }, thread::{ BlockReason, EvalContextExt as _, StackEmptyCallback, ThreadId, ThreadManager, TimeoutAnchor, TimeoutClock, UnblockCallback, diff --git a/src/tools/miri/src/shims/unix/macos/sync.rs b/src/tools/miri/src/shims/unix/macos/sync.rs index 5e5fccb587b4b..882c08cca154c 100644 --- a/src/tools/miri/src/shims/unix/macos/sync.rs +++ b/src/tools/miri/src/shims/unix/macos/sync.rs @@ -19,7 +19,7 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { // os_unfair_lock holds a 32-bit value, is initialized with zero and // must be assumed to be opaque. Therefore, we can just store our // internal mutex ID in the structure without anyone noticing. - this.mutex_get_or_create_id(lock_op, this.libc_ty_layout("os_unfair_lock"), 0) + this.mutex_get_or_create_id(lock_op, this.libc_ty_layout("os_unfair_lock"), 0, |_| Ok(None)) } } diff --git a/src/tools/miri/src/shims/unix/sync.rs b/src/tools/miri/src/shims/unix/sync.rs index 0b889b1182248..5da5cab8fe4f5 100644 --- a/src/tools/miri/src/shims/unix/sync.rs +++ b/src/tools/miri/src/shims/unix/sync.rs @@ -74,6 +74,8 @@ fn mutex_id_offset<'tcx>(ecx: &MiriInterpCx<'tcx>) -> InterpResult<'tcx, u64> { // Sanity-check this against PTHREAD_MUTEX_INITIALIZER (but only once): // the id must start out as 0. + // FIXME on some platforms (e.g linux) there are more static initializers for + // recursive or error checking mutexes. We should also add thme in this sanity check. static SANITY: AtomicBool = AtomicBool::new(false); if !SANITY.swap(true, Ordering::Relaxed) { let static_initializer = ecx.eval_path(&["libc", "PTHREAD_MUTEX_INITIALIZER"]); @@ -90,79 +92,92 @@ fn mutex_id_offset<'tcx>(ecx: &MiriInterpCx<'tcx>) -> InterpResult<'tcx, u64> { Ok(offset) } -fn mutex_kind_offset<'tcx>(ecx: &MiriInterpCx<'tcx>) -> u64 { - // These offsets are picked for compatibility with Linux's static initializer - // macros, e.g. PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP.) - let offset = if ecx.pointer_size().bytes() == 8 { 16 } else { 12 }; - - // Sanity-check this against PTHREAD_MUTEX_INITIALIZER (but only once): - // the kind must start out as PTHREAD_MUTEX_DEFAULT. - static SANITY: AtomicBool = AtomicBool::new(false); - if !SANITY.swap(true, Ordering::Relaxed) { - let static_initializer = ecx.eval_path(&["libc", "PTHREAD_MUTEX_INITIALIZER"]); - let kind_field = static_initializer - .offset(Size::from_bytes(mutex_kind_offset(ecx)), ecx.machine.layouts.i32, ecx) - .unwrap(); - let kind = ecx.read_scalar(&kind_field).unwrap().to_i32().unwrap(); - assert_eq!( - kind, - ecx.eval_libc_i32("PTHREAD_MUTEX_DEFAULT"), - "PTHREAD_MUTEX_INITIALIZER is incompatible with our pthread_mutex layout: kind is not PTHREAD_MUTEX_DEFAULT" - ); - } - - offset +/// Eagerly create and initialize a new mutex. +fn mutex_create<'tcx>( + ecx: &mut MiriInterpCx<'tcx>, + mutex_op: &OpTy<'tcx>, + kind: i32, +) -> InterpResult<'tcx> { + // FIXME: might be worth changing mutex_create to take the mplace + // rather than the `OpTy`. + let address = ecx.read_pointer(mutex_op)?.addr().bytes(); + let kind = translate_kind(ecx, kind)?; + let data = Some(AdditionalMutexData { address, kind }); + ecx.mutex_create(mutex_op, ecx.libc_ty_layout("pthread_mutex_t"), mutex_id_offset(ecx)?, data)?; + Ok(()) } +/// Returns the `MutexId` of the mutex stored at `mutex_op`. +/// +/// `mutex_get_id` will also check if the mutex has been moved since its first use and +/// return an error if it has. fn mutex_get_id<'tcx>( ecx: &mut MiriInterpCx<'tcx>, mutex_op: &OpTy<'tcx>, ) -> InterpResult<'tcx, MutexId> { - ecx.mutex_get_or_create_id( + let address = ecx.read_pointer(mutex_op)?.addr().bytes(); + + // FIXME: might be worth changing mutex_get_or_create_id to take the mplace + // rather than the `OpTy`. + let id = ecx.mutex_get_or_create_id( mutex_op, ecx.libc_ty_layout("pthread_mutex_t"), mutex_id_offset(ecx)?, - ) -} + |ecx| { + // This is called if a static initializer was used and the lock has not been assigned + // an ID yet. We have to determine the mutex kind from the static initializer. + let kind = kind_from_static_initializer(ecx, mutex_op)?; + + Ok(Some(AdditionalMutexData { kind, address })) + }, + )?; + + // Check that the mutex has not been moved since last use. + let data = ecx.mutex_get_data(id).expect("data should be always exist for pthreads"); + if data.address != address { + throw_ub_format!("pthread_mutex_t can't be moved after first use") + } -fn mutex_reset_id<'tcx>( - ecx: &mut MiriInterpCx<'tcx>, - mutex_op: &OpTy<'tcx>, -) -> InterpResult<'tcx, ()> { - ecx.deref_pointer_and_write( - mutex_op, - mutex_id_offset(ecx)?, - Scalar::from_u32(0), - ecx.libc_ty_layout("pthread_mutex_t"), - ecx.machine.layouts.u32, - ) + Ok(id) } -fn mutex_get_kind<'tcx>( +/// Returns the kind of a static initializer. +fn kind_from_static_initializer<'tcx>( ecx: &MiriInterpCx<'tcx>, mutex_op: &OpTy<'tcx>, -) -> InterpResult<'tcx, i32> { - ecx.deref_pointer_and_read( - mutex_op, - mutex_kind_offset(ecx), - ecx.libc_ty_layout("pthread_mutex_t"), - ecx.machine.layouts.i32, - )? - .to_i32() +) -> InterpResult<'tcx, MutexKind> { + // Only linux has static initializers other than PTHREAD_MUTEX_DEFAULT. + let kind = match &*ecx.tcx.sess.target.os { + "linux" => { + let offset = if ecx.pointer_size().bytes() == 8 { 16 } else { 12 }; + + ecx.deref_pointer_and_read( + mutex_op, + offset, + ecx.libc_ty_layout("pthread_mutex_t"), + ecx.machine.layouts.i32, + )? + .to_i32()? + } + | "illumos" | "solaris" | "macos" => ecx.eval_libc_i32("PTHREAD_MUTEX_DEFAULT"), + os => throw_unsup_format!("`pthread_mutex` is not supported on {os}"), + }; + + translate_kind(ecx, kind) } -fn mutex_set_kind<'tcx>( - ecx: &mut MiriInterpCx<'tcx>, - mutex_op: &OpTy<'tcx>, - kind: i32, -) -> InterpResult<'tcx, ()> { - ecx.deref_pointer_and_write( - mutex_op, - mutex_kind_offset(ecx), - Scalar::from_i32(kind), - ecx.libc_ty_layout("pthread_mutex_t"), - ecx.machine.layouts.i32, - ) +fn translate_kind<'tcx>(ecx: &MiriInterpCx<'tcx>, kind: i32) -> InterpResult<'tcx, MutexKind> { + Ok(if is_mutex_kind_default(ecx, kind)? { + MutexKind::Default + } else if is_mutex_kind_normal(ecx, kind)? { + MutexKind::Normal + } else if kind == ecx.eval_libc_i32("PTHREAD_MUTEX_ERRORCHECK") { + MutexKind::ErrorCheck + } else if kind == ecx.eval_libc_i32("PTHREAD_MUTEX_RECURSIVE") { + MutexKind::Recursive + } else { + throw_unsup_format!("unsupported type of mutex: {kind}"); + }) } // pthread_rwlock_t is between 32 and 56 bytes, depending on the platform. @@ -452,10 +467,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { mutexattr_get_kind(this, attr_op)? }; - // Write 0 to use the same code path as the static initializers. - mutex_reset_id(this, mutex_op)?; - - mutex_set_kind(this, mutex_op, kind)?; + mutex_create(this, mutex_op, kind)?; Ok(()) } @@ -467,8 +479,9 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { ) -> InterpResult<'tcx> { let this = self.eval_context_mut(); - let kind = mutex_get_kind(this, mutex_op)?; let id = mutex_get_id(this, mutex_op)?; + let kind = + this.mutex_get_data(id).expect("data should always exist for pthread mutexes").kind; let ret = if this.mutex_is_locked(id) { let owner_thread = this.mutex_get_owner(id); @@ -477,19 +490,19 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { return Ok(()); } else { // Trying to acquire the same mutex again. - if is_mutex_kind_default(this, kind)? { - throw_ub_format!("trying to acquire already locked default mutex"); - } else if is_mutex_kind_normal(this, kind)? { - throw_machine_stop!(TerminationInfo::Deadlock); - } else if kind == this.eval_libc_i32("PTHREAD_MUTEX_ERRORCHECK") { - this.eval_libc_i32("EDEADLK") - } else if kind == this.eval_libc_i32("PTHREAD_MUTEX_RECURSIVE") { - this.mutex_lock(id); - 0 - } else { - throw_unsup_format!( - "called pthread_mutex_lock on an unsupported type of mutex" - ); + match kind { + MutexKind::Default => + throw_ub_format!("trying to acquire already locked default mutex"), + MutexKind::Normal => throw_machine_stop!(TerminationInfo::Deadlock), + MutexKind::ErrorCheck => this.eval_libc_i32("EDEADLK"), + MutexKind::Recursive => { + this.mutex_lock(id); + 0 + } + _ => + throw_unsup_format!( + "called pthread_mutex_lock on an unsupported type of mutex" + ), } } } else { @@ -504,26 +517,26 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { fn pthread_mutex_trylock(&mut self, mutex_op: &OpTy<'tcx>) -> InterpResult<'tcx, Scalar> { let this = self.eval_context_mut(); - let kind = mutex_get_kind(this, mutex_op)?; let id = mutex_get_id(this, mutex_op)?; + let kind = + this.mutex_get_data(id).expect("data should always exist for pthread mutexes").kind; Ok(Scalar::from_i32(if this.mutex_is_locked(id) { let owner_thread = this.mutex_get_owner(id); if owner_thread != this.active_thread() { this.eval_libc_i32("EBUSY") } else { - if is_mutex_kind_default(this, kind)? - || is_mutex_kind_normal(this, kind)? - || kind == this.eval_libc_i32("PTHREAD_MUTEX_ERRORCHECK") - { - this.eval_libc_i32("EBUSY") - } else if kind == this.eval_libc_i32("PTHREAD_MUTEX_RECURSIVE") { - this.mutex_lock(id); - 0 - } else { - throw_unsup_format!( - "called pthread_mutex_trylock on an unsupported type of mutex" - ); + match kind { + MutexKind::Default | MutexKind::Normal | MutexKind::ErrorCheck => + this.eval_libc_i32("EBUSY"), + MutexKind::Recursive => { + this.mutex_lock(id); + 0 + } + _ => + throw_unsup_format!( + "called pthread_mutex_trylock on an unsupported type of mutex" + ), } } } else { @@ -536,8 +549,9 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { fn pthread_mutex_unlock(&mut self, mutex_op: &OpTy<'tcx>) -> InterpResult<'tcx, Scalar> { let this = self.eval_context_mut(); - let kind = mutex_get_kind(this, mutex_op)?; let id = mutex_get_id(this, mutex_op)?; + let kind = + this.mutex_get_data(id).expect("data should always exist for pthread mutexes").kind; if let Some(_old_locked_count) = this.mutex_unlock(id)? { // The mutex was locked by the current thread. @@ -546,20 +560,21 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // The mutex was locked by another thread or not locked at all. See // the “Unlock When Not Owner” column in // https://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_mutex_unlock.html. - if is_mutex_kind_default(this, kind)? { - throw_ub_format!( - "unlocked a default mutex that was not locked by the current thread" - ); - } else if is_mutex_kind_normal(this, kind)? { - throw_ub_format!( - "unlocked a PTHREAD_MUTEX_NORMAL mutex that was not locked by the current thread" - ); - } else if kind == this.eval_libc_i32("PTHREAD_MUTEX_ERRORCHECK") - || kind == this.eval_libc_i32("PTHREAD_MUTEX_RECURSIVE") - { - Ok(Scalar::from_i32(this.eval_libc_i32("EPERM"))) - } else { - throw_unsup_format!("called pthread_mutex_unlock on an unsupported type of mutex"); + match kind { + MutexKind::Default => + throw_ub_format!( + "unlocked a default mutex that was not locked by the current thread" + ), + MutexKind::Normal => + throw_ub_format!( + "unlocked a PTHREAD_MUTEX_NORMAL mutex that was not locked by the current thread" + ), + MutexKind::ErrorCheck | MutexKind::Recursive => + Ok(Scalar::from_i32(this.eval_libc_i32("EPERM"))), + _ => + throw_unsup_format!( + "called pthread_mutex_unlock on an unsupported type of mutex" + ), } } } @@ -574,7 +589,6 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { } // Destroying an uninit pthread_mutex is UB, so check to make sure it's not uninit. - mutex_get_kind(this, mutex_op)?; mutex_get_id(this, mutex_op)?; // This might lead to false positives, see comment in pthread_mutexattr_destroy diff --git a/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutex_move.init.stderr b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutex_move.init.stderr new file mode 100644 index 0000000000000..5ca6acc3fbe6e --- /dev/null +++ b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutex_move.init.stderr @@ -0,0 +1,20 @@ +error: Undefined Behavior: pthread_mutex_t can't be moved after first use + --> $DIR/libc_pthread_mutex_move.rs:LL:CC + | +LL | libc::pthread_mutex_lock(&mut m2 as *mut _); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pthread_mutex_t can't be moved after first use + | + = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior + = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information + = note: BACKTRACE: + = note: inside `check` at $DIR/libc_pthread_mutex_move.rs:LL:CC +note: inside `main` + --> $DIR/libc_pthread_mutex_move.rs:LL:CC + | +LL | check(); + | ^^^^^^^ + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to 1 previous error + diff --git a/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutex_move.rs b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutex_move.rs new file mode 100644 index 0000000000000..229335c97ce18 --- /dev/null +++ b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutex_move.rs @@ -0,0 +1,28 @@ +//@ignore-target-windows: No pthreads on Windows +//@revisions: static_initializer init + +fn main() { + check(); +} + +#[cfg(init)] +fn check() { + unsafe { + let mut m: libc::pthread_mutex_t = std::mem::zeroed(); + assert_eq!(libc::pthread_mutex_init(&mut m as *mut _, std::ptr::null()), 0); + + let mut m2 = m; // move the mutex + libc::pthread_mutex_lock(&mut m2 as *mut _); //~[init] ERROR: pthread_mutex_t can't be moved after first use + } +} + +#[cfg(static_initializer)] +fn check() { + unsafe { + let mut m: libc::pthread_mutex_t = libc::PTHREAD_MUTEX_INITIALIZER; + libc::pthread_mutex_lock(&mut m as *mut _); + + let mut m2 = m; // move the mutex + libc::pthread_mutex_unlock(&mut m2 as *mut _); //~[static_initializer] ERROR: pthread_mutex_t can't be moved after first use + } +} diff --git a/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutex_move.static_initializer.stderr b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutex_move.static_initializer.stderr new file mode 100644 index 0000000000000..c3632eca43ffa --- /dev/null +++ b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutex_move.static_initializer.stderr @@ -0,0 +1,20 @@ +error: Undefined Behavior: pthread_mutex_t can't be moved after first use + --> $DIR/libc_pthread_mutex_move.rs:LL:CC + | +LL | libc::pthread_mutex_unlock(&mut m2 as *mut _); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pthread_mutex_t can't be moved after first use + | + = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior + = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information + = note: BACKTRACE: + = note: inside `check` at $DIR/libc_pthread_mutex_move.rs:LL:CC +note: inside `main` + --> $DIR/libc_pthread_mutex_move.rs:LL:CC + | +LL | check(); + | ^^^^^^^ + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to 1 previous error + From 8871ce0e1f4bc9dbca91d567ab0332746f7facaa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=AE=B8=E6=9D=B0=E5=8F=8B=20Jieyou=20Xu=20=28Joe=29?= Date: Thu, 5 Sep 2024 09:14:08 +0000 Subject: [PATCH 0522/2194] run_make_support: make each command invocation only-run-once --- src/tools/run-make-support/src/command.rs | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/src/tools/run-make-support/src/command.rs b/src/tools/run-make-support/src/command.rs index 3f2ae078229dd..6b58173b34304 100644 --- a/src/tools/run-make-support/src/command.rs +++ b/src/tools/run-make-support/src/command.rs @@ -15,7 +15,7 @@ use crate::{ /// This is a custom command wrapper that simplifies working with commands and makes it easier to /// ensure that we check the exit status of executed processes. /// -/// # A [`Command`] must be executed +/// # A [`Command`] must be executed exactly once /// /// A [`Command`] is armed by a [`DropBomb`] on construction to enforce that it will be executed. If /// a [`Command`] is constructed but never executed, the drop bomb will explode and cause the test @@ -23,6 +23,12 @@ use crate::{ /// containing constructed but never executed commands is dangerous because it can give a false /// sense of confidence. /// +/// Each [`Command`] invocation can also only be executed once, because we want to enforce +/// `std{in,out,err}` config via [`std::process::Stdio`] but [`std::process::Stdio`] is not +/// cloneable. +/// +/// In this sense, [`Command`] exhibits linear type semantics but enforced at run-time. +/// /// [`run`]: Self::run /// [`run_fail`]: Self::run_fail /// [`run_unchecked`]: Self::run_unchecked @@ -37,7 +43,9 @@ pub struct Command { stdout: Option, stderr: Option, + // Emulate linear type semantics. drop_bomb: DropBomb, + already_executed: bool, } impl Command { @@ -51,6 +59,7 @@ impl Command { stdin: None, stdout: None, stderr: None, + already_executed: false, } } @@ -177,6 +186,12 @@ impl Command { #[track_caller] fn command_output(&mut self) -> CompletedProcess { + if self.already_executed { + panic!("command was already executed"); + } else { + self.already_executed = true; + } + self.drop_bomb.defuse(); // let's make sure we piped all the input and outputs self.cmd.stdin(self.stdin.take().unwrap_or(Stdio::piped())); From a4594032cf15ad3b0532f67d7b3b5ca517edd90e Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 23 Aug 2024 16:23:35 +0200 Subject: [PATCH 0523/2194] Sort impl associated items by kinds and then by appearance --- src/librustdoc/html/render/mod.rs | 53 ++++++++++++++++++++++++++++++- 1 file changed, 52 insertions(+), 1 deletion(-) diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index dc34c7844bfdd..9e9934992768d 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -1794,13 +1794,64 @@ fn render_impl( let mut default_impl_items = Buffer::empty_from(w); let impl_ = i.inner_impl(); + // Impl items are grouped by kinds: + // + // 1. Types + // 2. Constants + // 3. Functions + // + // This order is because you can have associated types in associated constants, and both in + // associcated functions. So with this order, when reading from top to bottom, you should always + // see all items definitions before they're actually used. + let mut assoc_consts = Vec::new(); + let mut methods = Vec::new(); + if !impl_.is_negative_trait_impl() { for trait_item in &impl_.items { + match *trait_item.kind { + clean::MethodItem(..) | clean::TyMethodItem(_) => methods.push(trait_item), + clean::TyAssocConstItem(..) | clean::AssocConstItem(_) => { + assoc_consts.push(trait_item) + } + clean::TyAssocTypeItem(..) | clean::AssocTypeItem(..) => { + // We render it directly since they're supposed to come first. + doc_impl_item( + &mut default_impl_items, + &mut impl_items, + cx, + trait_item, + if trait_.is_some() { &i.impl_item } else { parent }, + link, + render_mode, + false, + trait_, + rendering_params, + ); + } + _ => {} + } + } + + for assoc_const in assoc_consts { doc_impl_item( &mut default_impl_items, &mut impl_items, cx, - trait_item, + assoc_const, + if trait_.is_some() { &i.impl_item } else { parent }, + link, + render_mode, + false, + trait_, + rendering_params, + ); + } + for method in methods { + doc_impl_item( + &mut default_impl_items, + &mut impl_items, + cx, + method, if trait_.is_some() { &i.impl_item } else { parent }, link, render_mode, From f96aff95d591a35058ae82580f7e31615b2f3d3d Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 23 Aug 2024 16:24:18 +0200 Subject: [PATCH 0524/2194] Add regression test for impl associated items sorting --- tests/rustdoc/impl-associated-items-order.rs | 42 ++++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 tests/rustdoc/impl-associated-items-order.rs diff --git a/tests/rustdoc/impl-associated-items-order.rs b/tests/rustdoc/impl-associated-items-order.rs new file mode 100644 index 0000000000000..f8744be04ba81 --- /dev/null +++ b/tests/rustdoc/impl-associated-items-order.rs @@ -0,0 +1,42 @@ +// This test ensures that impl associated items always follow this order: +// +// 1. Types +// 2. Consts +// 3. Functions + +#![feature(inherent_associated_types)] +#![allow(incomplete_features)] +#![crate_name = "foo"] + +//@ has 'foo/struct.Bar.html' +pub struct Bar; + +impl Bar { + //@ has - '//*[@id="implementations-list"]//*[@class="impl-items"]/section[3]/h4' \ + // 'pub fn foo()' + pub fn foo() {} + //@ has - '//*[@id="implementations-list"]//*[@class="impl-items"]/section[2]/h4' \ + // 'pub const X: u8 = 12u8' + pub const X: u8 = 12; + //@ has - '//*[@id="implementations-list"]//*[@class="impl-items"]/section[1]/h4' \ + // 'pub type Y = u8' + pub type Y = u8; +} + +pub trait Foo { + const W: u32; + fn yeay(); + type Z; +} + +impl Foo for Bar { + //@ has - '//*[@id="trait-implementations-list"]//*[@class="impl-items"]/section[2]/h4' \ + // 'const W: u32 = 12u32' + const W: u32 = 12; + //@ has - '//*[@id="trait-implementations-list"]//*[@class="impl-items"]/section[1]/h4' \ + // 'type Z = u8' + type Z = u8; + //@ has - '//*[@id="trait-implementations-list"]//*[@class="impl-items"]/section[3]/h4' \ + // 'fn yeay()' + fn yeay() {} +} From 188498300129552c6ea38860a50debada7265fe3 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sun, 25 Aug 2024 22:02:57 +0200 Subject: [PATCH 0525/2194] Make impl associated constants sorted first --- src/librustdoc/html/render/mod.rs | 22 ++++++++++---------- src/librustdoc/html/render/sidebar.rs | 4 ++-- tests/rustdoc/impl-associated-items-order.rs | 14 ++++++------- 3 files changed, 20 insertions(+), 20 deletions(-) diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index 9e9934992768d..095bfe158ff19 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -1796,24 +1796,24 @@ fn render_impl( // Impl items are grouped by kinds: // - // 1. Types - // 2. Constants + // 1. Constants + // 2. Types // 3. Functions // - // This order is because you can have associated types in associated constants, and both in - // associcated functions. So with this order, when reading from top to bottom, you should always - // see all items definitions before they're actually used. - let mut assoc_consts = Vec::new(); + // This order is because you can have associated constants used in associated types (like array + // length), and both in associcated functions. So with this order, when reading from top to + // bottom, you should see items definitions before they're actually used most of the time. + let mut assoc_types = Vec::new(); let mut methods = Vec::new(); if !impl_.is_negative_trait_impl() { for trait_item in &impl_.items { match *trait_item.kind { clean::MethodItem(..) | clean::TyMethodItem(_) => methods.push(trait_item), - clean::TyAssocConstItem(..) | clean::AssocConstItem(_) => { - assoc_consts.push(trait_item) - } clean::TyAssocTypeItem(..) | clean::AssocTypeItem(..) => { + assoc_types.push(trait_item) + } + clean::TyAssocConstItem(..) | clean::AssocConstItem(_) => { // We render it directly since they're supposed to come first. doc_impl_item( &mut default_impl_items, @@ -1832,12 +1832,12 @@ fn render_impl( } } - for assoc_const in assoc_consts { + for assoc_type in assoc_types { doc_impl_item( &mut default_impl_items, &mut impl_items, cx, - assoc_const, + assoc_type, if trait_.is_some() { &i.impl_item } else { parent }, link, render_mode, diff --git a/src/librustdoc/html/render/sidebar.rs b/src/librustdoc/html/render/sidebar.rs index c75c28ef0a3b4..6d0345042707e 100644 --- a/src/librustdoc/html/render/sidebar.rs +++ b/src/librustdoc/html/render/sidebar.rs @@ -302,10 +302,10 @@ fn sidebar_trait<'a>( blocks.extend( [ - ("required-associated-types", "Required Associated Types", req_assoc), - ("provided-associated-types", "Provided Associated Types", prov_assoc), ("required-associated-consts", "Required Associated Constants", req_assoc_const), ("provided-associated-consts", "Provided Associated Constants", prov_assoc_const), + ("required-associated-types", "Required Associated Types", req_assoc), + ("provided-associated-types", "Provided Associated Types", prov_assoc), ("required-methods", "Required Methods", req_method), ("provided-methods", "Provided Methods", prov_method), ("foreign-impls", "Implementations on Foreign Types", foreign_impls), diff --git a/tests/rustdoc/impl-associated-items-order.rs b/tests/rustdoc/impl-associated-items-order.rs index f8744be04ba81..759e0f0b40095 100644 --- a/tests/rustdoc/impl-associated-items-order.rs +++ b/tests/rustdoc/impl-associated-items-order.rs @@ -1,7 +1,7 @@ // This test ensures that impl associated items always follow this order: // -// 1. Types -// 2. Consts +// 1. Consts +// 2. Types // 3. Functions #![feature(inherent_associated_types)] @@ -15,10 +15,10 @@ impl Bar { //@ has - '//*[@id="implementations-list"]//*[@class="impl-items"]/section[3]/h4' \ // 'pub fn foo()' pub fn foo() {} - //@ has - '//*[@id="implementations-list"]//*[@class="impl-items"]/section[2]/h4' \ + //@ has - '//*[@id="implementations-list"]//*[@class="impl-items"]/section[1]/h4' \ // 'pub const X: u8 = 12u8' pub const X: u8 = 12; - //@ has - '//*[@id="implementations-list"]//*[@class="impl-items"]/section[1]/h4' \ + //@ has - '//*[@id="implementations-list"]//*[@class="impl-items"]/section[2]/h4' \ // 'pub type Y = u8' pub type Y = u8; } @@ -31,11 +31,11 @@ pub trait Foo { impl Foo for Bar { //@ has - '//*[@id="trait-implementations-list"]//*[@class="impl-items"]/section[2]/h4' \ - // 'const W: u32 = 12u32' - const W: u32 = 12; - //@ has - '//*[@id="trait-implementations-list"]//*[@class="impl-items"]/section[1]/h4' \ // 'type Z = u8' type Z = u8; + //@ has - '//*[@id="trait-implementations-list"]//*[@class="impl-items"]/section[1]/h4' \ + // 'const W: u32 = 12u32' + const W: u32 = 12; //@ has - '//*[@id="trait-implementations-list"]//*[@class="impl-items"]/section[3]/h4' \ // 'fn yeay()' fn yeay() {} From d059f37724881d385546b1e7fd27eff4dad65645 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 26 Aug 2024 15:09:23 +0200 Subject: [PATCH 0526/2194] Add missing sidebar associated items --- src/librustdoc/html/render/print_item.rs | 32 ++++++------ src/librustdoc/html/render/sidebar.rs | 62 +++++++++++++++--------- 2 files changed, 56 insertions(+), 38 deletions(-) diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs index a0a72d59d123f..cda5409a460ee 100644 --- a/src/librustdoc/html/render/print_item.rs +++ b/src/librustdoc/html/render/print_item.rs @@ -843,55 +843,55 @@ fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean: } } - if !required_types.is_empty() { + if !required_consts.is_empty() { write_section_heading( w, - "Required Associated Types", - "required-associated-types", + "Required Associated Constants", + "required-associated-consts", None, "
", ); - for t in required_types { + for t in required_consts { trait_item(w, cx, t, it); } w.write_str("
"); } - if !provided_types.is_empty() { + if !provided_consts.is_empty() { write_section_heading( w, - "Provided Associated Types", - "provided-associated-types", + "Provided Associated Constants", + "provided-associated-consts", None, "
", ); - for t in provided_types { + for t in provided_consts { trait_item(w, cx, t, it); } w.write_str("
"); } - if !required_consts.is_empty() { + if !required_types.is_empty() { write_section_heading( w, - "Required Associated Constants", - "required-associated-consts", + "Required Associated Types", + "required-associated-types", None, "
", ); - for t in required_consts { + for t in required_types { trait_item(w, cx, t, it); } w.write_str("
"); } - if !provided_consts.is_empty() { + if !provided_types.is_empty() { write_section_heading( w, - "Provided Associated Constants", - "provided-associated-consts", + "Provided Associated Types", + "provided-associated-types", None, "
", ); - for t in provided_consts { + for t in provided_types { trait_item(w, cx, t, it); } w.write_str("
"); diff --git a/src/librustdoc/html/render/sidebar.rs b/src/librustdoc/html/render/sidebar.rs index 6d0345042707e..b9e46851465d4 100644 --- a/src/librustdoc/html/render/sidebar.rs +++ b/src/librustdoc/html/render/sidebar.rs @@ -394,6 +394,7 @@ fn sidebar_assoc_items<'a>( let cache = cx.cache(); let mut assoc_consts = Vec::new(); + let mut assoc_types = Vec::new(); let mut methods = Vec::new(); if let Some(v) = cache.impls.get(&did) { let mut used_links = FxHashSet::default(); @@ -401,22 +402,14 @@ fn sidebar_assoc_items<'a>( { let used_links_bor = &mut used_links; - assoc_consts.extend( - v.iter() - .filter(|i| i.inner_impl().trait_.is_none()) - .flat_map(|i| get_associated_constants(i.inner_impl(), used_links_bor)), - ); + for impl_ in v.iter().map(|i| i.inner_impl()).filter(|i| i.trait_.is_none()) { + assoc_consts.extend(get_associated_constants(impl_, used_links_bor)); + assoc_types.extend(get_associated_types(impl_, used_links_bor)); + methods.extend(get_methods(impl_, false, used_links_bor, false, cx.tcx())); + } // We want links' order to be reproducible so we don't use unstable sort. assoc_consts.sort(); - - #[rustfmt::skip] // rustfmt makes the pipeline less readable - methods.extend( - v.iter() - .filter(|i| i.inner_impl().trait_.is_none()) - .flat_map(|i| get_methods(i.inner_impl(), false, used_links_bor, false, cx.tcx())), - ); - - // We want links' order to be reproducible so we don't use unstable sort. + assoc_types.sort(); methods.sort(); } @@ -443,15 +436,24 @@ fn sidebar_assoc_items<'a>( let (blanket_impl, concrete): (Vec<&Impl>, Vec<&Impl>) = concrete.into_iter().partition::, _>(|i| i.inner_impl().kind.is_blanket()); - sidebar_render_assoc_items( - cx, - &mut id_map, - concrete, - synthetic, - blanket_impl, - &mut blocks, - ); + sidebar_render_assoc_items(cx, &mut id_map, concrete, synthetic, blanket_impl, &mut blocks); } + + blocks.extend([ + LinkBlock::new( + Link::new("implementations", "Associated Constants"), + "associatedconstant", + assoc_consts, + ), + LinkBlock::new( + Link::new("implementations", "Associated Types"), + "associatedtype", + assoc_types, + ), + LinkBlock::new(Link::new("implementations", "Methods"), "method", methods), + ]); + blocks.append(&mut deref_methods); + blocks.extend([concrete, synthetic, blanket]); links.append(&mut blocks); } } @@ -715,3 +717,19 @@ fn get_associated_constants<'a>( }) .collect::>() } + +fn get_associated_types<'a>( + i: &'a clean::Impl, + used_links: &mut FxHashSet, +) -> Vec> { + i.items + .iter() + .filter_map(|item| match item.name { + Some(ref name) if !name.is_empty() && item.is_associated_type() => Some(Link::new( + get_next_url(used_links, format!("{typ}.{name}", typ = ItemType::AssocType)), + name.as_str(), + )), + _ => None, + }) + .collect::>() +} From 238944c5d7035da09810d84179eeb81a9dac37f0 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 26 Aug 2024 15:09:35 +0200 Subject: [PATCH 0527/2194] Add regression test for sidebar associated items --- .../rustdoc/impl-associated-items-sidebar.rs | 42 +++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 tests/rustdoc/impl-associated-items-sidebar.rs diff --git a/tests/rustdoc/impl-associated-items-sidebar.rs b/tests/rustdoc/impl-associated-items-sidebar.rs new file mode 100644 index 0000000000000..d393a577e5009 --- /dev/null +++ b/tests/rustdoc/impl-associated-items-sidebar.rs @@ -0,0 +1,42 @@ +// This test ensures that impl/trait associated items are listed in the sidebar. + +// ignore-tidy-linelength + +#![feature(inherent_associated_types)] +#![feature(associated_type_defaults)] +#![allow(incomplete_features)] +#![crate_name = "foo"] + +//@ has 'foo/struct.Bar.html' +pub struct Bar; + +impl Bar { + //@ has - '//*[@class="sidebar-elems"]//h3[1]' 'Associated Constants' + //@ has - '//*[@class="sidebar-elems"]//ul[@class="block associatedconstant"]/li/a[@href="#associatedconstant.X"]' 'X' + pub const X: u8 = 12; + //@ has - '//*[@class="sidebar-elems"]//h3[2]' 'Associated Types' + //@ has - '//*[@class="sidebar-elems"]//ul[@class="block associatedtype"]/li/a[@href="#associatedtype.Y"]' 'Y' + pub type Y = u8; +} + +//@ has 'foo/trait.Foo.html' +pub trait Foo { + //@ has - '//*[@class="sidebar-elems"]//h3[5]' 'Required Methods' + //@ has - '//*[@class="sidebar-elems"]//ul[@class="block"][5]/li/a[@href="#tymethod.yeay"]' 'yeay' + fn yeay(); + //@ has - '//*[@class="sidebar-elems"]//h3[6]' 'Provided Methods' + //@ has - '//*[@class="sidebar-elems"]//ul[@class="block"][6]/li/a[@href="#method.boo"]' 'boo' + fn boo() {} + //@ has - '//*[@class="sidebar-elems"]//h3[1]' 'Required Associated Constants' + //@ has - '//*[@class="sidebar-elems"]//ul[@class="block"][1]/li/a[@href="#associatedconstant.W"]' 'W' + const W: u32; + //@ has - '//*[@class="sidebar-elems"]//h3[2]' 'Provided Associated Constants' + //@ has - '//*[@class="sidebar-elems"]//ul[@class="block"][2]/li/a[@href="#associatedconstant.U"]' 'U' + const U: u32 = 0; + //@ has - '//*[@class="sidebar-elems"]//h3[3]' 'Required Associated Types' + //@ has - '//*[@class="sidebar-elems"]//ul[@class="block"][3]/li/a[@href="#associatedtype.Z"]' 'Z' + type Z; + //@ has - '//*[@class="sidebar-elems"]//h3[4]' 'Provided Associated Types' + //@ has - '//*[@class="sidebar-elems"]//ul[@class="block"][4]/li/a[@href="#associatedtype.T"]' 'T' + type T = u32; +} From 8f9c4b36fe2a2308f24d66e1d75ec54e3f3fcdb7 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Thu, 5 Sep 2024 12:33:05 +0200 Subject: [PATCH 0528/2194] Update to new rustdoc internal API --- src/librustdoc/html/render/sidebar.rs | 29 ++++++++++++--------------- 1 file changed, 13 insertions(+), 16 deletions(-) diff --git a/src/librustdoc/html/render/sidebar.rs b/src/librustdoc/html/render/sidebar.rs index b9e46851465d4..06cc57b2a5536 100644 --- a/src/librustdoc/html/render/sidebar.rs +++ b/src/librustdoc/html/render/sidebar.rs @@ -419,6 +419,11 @@ fn sidebar_assoc_items<'a>( "associatedconstant", assoc_consts, ), + LinkBlock::new( + Link::new("implementations", "Associated Types"), + "associatedtype", + assoc_types, + ), LinkBlock::new(Link::new("implementations", "Methods"), "method", methods), ]; @@ -436,24 +441,16 @@ fn sidebar_assoc_items<'a>( let (blanket_impl, concrete): (Vec<&Impl>, Vec<&Impl>) = concrete.into_iter().partition::, _>(|i| i.inner_impl().kind.is_blanket()); - sidebar_render_assoc_items(cx, &mut id_map, concrete, synthetic, blanket_impl, &mut blocks); + sidebar_render_assoc_items( + cx, + &mut id_map, + concrete, + synthetic, + blanket_impl, + &mut blocks, + ); } - blocks.extend([ - LinkBlock::new( - Link::new("implementations", "Associated Constants"), - "associatedconstant", - assoc_consts, - ), - LinkBlock::new( - Link::new("implementations", "Associated Types"), - "associatedtype", - assoc_types, - ), - LinkBlock::new(Link::new("implementations", "Methods"), "method", methods), - ]); - blocks.append(&mut deref_methods); - blocks.extend([concrete, synthetic, blanket]); links.append(&mut blocks); } } From f8f4d50aa34640906e0315adbf4c487712fab0cd Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Mon, 12 Aug 2024 17:56:49 -0400 Subject: [PATCH 0529/2194] Don't worry about uncaptured contravariant lifetimes if they outlive a captured lifetime --- .../rustc_lint/src/impl_trait_overcaptures.rs | 247 ++++++++++++++++-- .../overcaptures-2024-but-fine.rs | 15 ++ 2 files changed, 241 insertions(+), 21 deletions(-) create mode 100644 tests/ui/impl-trait/precise-capturing/overcaptures-2024-but-fine.rs diff --git a/compiler/rustc_lint/src/impl_trait_overcaptures.rs b/compiler/rustc_lint/src/impl_trait_overcaptures.rs index 8824e1dfe50d8..42c800a81af8a 100644 --- a/compiler/rustc_lint/src/impl_trait_overcaptures.rs +++ b/compiler/rustc_lint/src/impl_trait_overcaptures.rs @@ -1,19 +1,28 @@ -use rustc_data_structures::fx::FxIndexSet; +use std::cell::LazyCell; + +use rustc_data_structures::fx::{FxHashMap, FxIndexMap, FxIndexSet}; use rustc_data_structures::unord::UnordSet; use rustc_errors::{Applicability, LintDiagnostic}; use rustc_hir as hir; use rustc_hir::def::DefKind; use rustc_hir::def_id::{DefId, LocalDefId}; +use rustc_infer::infer::outlives::env::OutlivesEnvironment; +use rustc_infer::infer::TyCtxtInferExt; use rustc_macros::LintDiagnostic; -use rustc_middle::bug; use rustc_middle::middle::resolve_bound_vars::ResolvedArg; +use rustc_middle::ty::relate::{ + structurally_relate_consts, structurally_relate_tys, Relate, RelateResult, TypeRelation, +}; use rustc_middle::ty::{ self, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor, }; +use rustc_middle::{bug, span_bug}; use rustc_session::lint::FutureIncompatibilityReason; use rustc_session::{declare_lint, declare_lint_pass}; use rustc_span::edition::Edition; -use rustc_span::Span; +use rustc_span::{Span, Symbol}; +use rustc_trait_selection::traits::outlives_bounds::InferCtxtExt; +use rustc_trait_selection::traits::ObligationCtxt; use crate::{fluent_generated as fluent, LateContext, LateLintPass}; @@ -119,20 +128,41 @@ impl<'tcx> LateLintPass<'tcx> for ImplTraitOvercaptures { } } +#[derive(PartialEq, Eq, Hash, Debug, Copy, Clone)] +enum ParamKind { + // Early-bound var. + Early(Symbol, u32), + // Late-bound var on function, not within a binder. We can capture these. + Free(DefId, Symbol), + // Late-bound var in a binder. We can't capture these yet. + Late, +} + fn check_fn(tcx: TyCtxt<'_>, parent_def_id: LocalDefId) { let sig = tcx.fn_sig(parent_def_id).instantiate_identity(); - let mut in_scope_parameters = FxIndexSet::default(); + let mut in_scope_parameters = FxIndexMap::default(); // Populate the in_scope_parameters list first with all of the generics in scope let mut current_def_id = Some(parent_def_id.to_def_id()); while let Some(def_id) = current_def_id { let generics = tcx.generics_of(def_id); for param in &generics.own_params { - in_scope_parameters.insert(param.def_id); + in_scope_parameters.insert(param.def_id, ParamKind::Early(param.name, param.index)); } current_def_id = generics.parent; } + for bound_var in sig.bound_vars() { + let ty::BoundVariableKind::Region(ty::BoundRegionKind::BrNamed(def_id, name)) = bound_var + else { + span_bug!(tcx.def_span(parent_def_id), "unexpected non-lifetime binder on fn sig"); + }; + + in_scope_parameters.insert(def_id, ParamKind::Free(def_id, name)); + } + + let sig = tcx.liberate_late_bound_regions(parent_def_id.to_def_id(), sig); + // Then visit the signature to walk through all the binders (incl. the late-bound // vars on the function itself, which we need to count too). sig.visit_with(&mut VisitOpaqueTypes { @@ -140,17 +170,44 @@ fn check_fn(tcx: TyCtxt<'_>, parent_def_id: LocalDefId) { parent_def_id, in_scope_parameters, seen: Default::default(), + // Lazily compute these two, since they're likely a bit expensive. + variances: LazyCell::new(|| { + let mut functional_variances = FunctionalVariances { + tcx: tcx, + variances: FxHashMap::default(), + ambient_variance: ty::Covariant, + generics: tcx.generics_of(parent_def_id), + }; + let _ = functional_variances.relate(sig, sig); + functional_variances.variances + }), + outlives_env: LazyCell::new(|| { + let param_env = tcx.param_env(parent_def_id); + let infcx = tcx.infer_ctxt().build(); + let ocx = ObligationCtxt::new(&infcx); + let assumed_wf_tys = ocx.assumed_wf_types(param_env, parent_def_id).unwrap_or_default(); + let implied_bounds = + infcx.implied_bounds_tys_compat(param_env, parent_def_id, &assumed_wf_tys, false); + OutlivesEnvironment::with_bounds(param_env, implied_bounds) + }), }); } -struct VisitOpaqueTypes<'tcx> { +struct VisitOpaqueTypes<'tcx, VarFn, OutlivesFn> { tcx: TyCtxt<'tcx>, parent_def_id: LocalDefId, - in_scope_parameters: FxIndexSet, + in_scope_parameters: FxIndexMap, + variances: LazyCell, VarFn>, + outlives_env: LazyCell, OutlivesFn>, seen: FxIndexSet, } -impl<'tcx> TypeVisitor> for VisitOpaqueTypes<'tcx> { +impl<'tcx, VarFn, OutlivesFn> TypeVisitor> + for VisitOpaqueTypes<'tcx, VarFn, OutlivesFn> +where + VarFn: FnOnce() -> FxHashMap, + OutlivesFn: FnOnce() -> OutlivesEnvironment<'tcx>, +{ fn visit_binder>>( &mut self, t: &ty::Binder<'tcx, T>, @@ -163,8 +220,8 @@ impl<'tcx> TypeVisitor> for VisitOpaqueTypes<'tcx> { ty::BoundVariableKind::Region(ty::BoundRegionKind::BrNamed(def_id, ..)) | ty::BoundVariableKind::Ty(ty::BoundTyKind::Param(def_id, _)) => { added.push(def_id); - let unique = self.in_scope_parameters.insert(def_id); - assert!(unique); + let unique = self.in_scope_parameters.insert(def_id, ParamKind::Late); + assert_eq!(unique, None); } _ => { self.tcx.dcx().span_delayed_bug( @@ -209,6 +266,7 @@ impl<'tcx> TypeVisitor> for VisitOpaqueTypes<'tcx> { { // Compute the set of args that are captured by the opaque... let mut captured = FxIndexSet::default(); + let mut captured_regions = FxIndexSet::default(); let variances = self.tcx.variances_of(opaque_def_id); let mut current_def_id = Some(opaque_def_id.to_def_id()); while let Some(def_id) = current_def_id { @@ -218,25 +276,60 @@ impl<'tcx> TypeVisitor> for VisitOpaqueTypes<'tcx> { if variances[param.index as usize] != ty::Invariant { continue; } + + let arg = opaque_ty.args[param.index as usize]; // We need to turn all `ty::Param`/`ConstKind::Param` and // `ReEarlyParam`/`ReBound` into def ids. - captured.insert(extract_def_id_from_arg( - self.tcx, - generics, - opaque_ty.args[param.index as usize], - )); + captured.insert(extract_def_id_from_arg(self.tcx, generics, arg)); + + captured_regions.extend(arg.as_region()); } current_def_id = generics.parent; } // Compute the set of in scope params that are not captured. Get their spans, // since that's all we really care about them for emitting the diagnostic. - let uncaptured_spans: Vec<_> = self + let mut uncaptured_args: FxIndexSet<_> = self .in_scope_parameters .iter() - .filter(|def_id| !captured.contains(*def_id)) - .map(|def_id| self.tcx.def_span(def_id)) + .filter(|&(def_id, _)| !captured.contains(def_id)) + .collect(); + + // These are args that we know are likely fine to "overcapture", since they can be + // contravariantly shortened to one of the already-captured lifetimes that they + // outlive. + let covariant_long_args: FxIndexSet<_> = uncaptured_args + .iter() + .copied() + .filter(|&(def_id, kind)| { + let Some(ty::Bivariant | ty::Contravariant) = self.variances.get(def_id) else { + return false; + }; + let DefKind::LifetimeParam = self.tcx.def_kind(def_id) else { + return false; + }; + let uncaptured = match *kind { + ParamKind::Early(name, index) => ty::Region::new_early_param( + self.tcx, + ty::EarlyParamRegion { name, index }, + ), + ParamKind::Free(def_id, name) => ty::Region::new_late_param( + self.tcx, + self.parent_def_id.to_def_id(), + ty::BoundRegionKind::BrNamed(def_id, name), + ), + ParamKind::Late => return false, + }; + // Does this region outlive any captured region? + captured_regions.iter().any(|r| { + self.outlives_env + .free_region_map() + .sub_free_regions(self.tcx, *r, uncaptured) + }) + }) .collect(); + // We don't care to warn on these args. + uncaptured_args.retain(|arg| !covariant_long_args.contains(arg)); let opaque_span = self.tcx.def_span(opaque_def_id); let new_capture_rules = @@ -246,7 +339,7 @@ impl<'tcx> TypeVisitor> for VisitOpaqueTypes<'tcx> { // `use<>` syntax on it, and we're < edition 2024, then warn the user. if !new_capture_rules && !opaque.bounds.iter().any(|bound| matches!(bound, hir::GenericBound::Use(..))) - && !uncaptured_spans.is_empty() + && !uncaptured_args.is_empty() { let suggestion = if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(opaque_span) @@ -274,6 +367,11 @@ impl<'tcx> TypeVisitor> for VisitOpaqueTypes<'tcx> { None }; + let uncaptured_spans: Vec<_> = uncaptured_args + .into_iter() + .map(|(def_id, _)| self.tcx.def_span(def_id)) + .collect(); + self.tcx.emit_node_span_lint( IMPL_TRAIT_OVERCAPTURES, self.tcx.local_def_id_to_hir_id(opaque_def_id), @@ -327,7 +425,7 @@ impl<'tcx> TypeVisitor> for VisitOpaqueTypes<'tcx> { if self .in_scope_parameters .iter() - .all(|def_id| explicitly_captured.contains(def_id)) + .all(|(def_id, _)| explicitly_captured.contains(def_id)) { self.tcx.emit_node_span_lint( IMPL_TRAIT_REDUNDANT_CAPTURES, @@ -396,7 +494,11 @@ fn extract_def_id_from_arg<'tcx>( ty::ReBound( _, ty::BoundRegion { kind: ty::BoundRegionKind::BrNamed(def_id, ..), .. }, - ) => def_id, + ) + | ty::ReLateParam(ty::LateParamRegion { + scope: _, + bound_region: ty::BoundRegionKind::BrNamed(def_id, ..), + }) => def_id, _ => unreachable!(), }, ty::GenericArgKind::Type(ty) => { @@ -413,3 +515,106 @@ fn extract_def_id_from_arg<'tcx>( } } } + +/// Computes the variances of regions that appear in the type, but considering +/// late-bound regions too, which don't have their variance computed usually. +/// +/// Like generalization, this is a unary operation implemented on top of the binary +/// relation infrastructure, mostly because it's much easier to have the relation +/// track the variance for you, rather than having to do it yourself. +struct FunctionalVariances<'tcx> { + tcx: TyCtxt<'tcx>, + variances: FxHashMap, + ambient_variance: ty::Variance, + generics: &'tcx ty::Generics, +} + +impl<'tcx> TypeRelation> for FunctionalVariances<'tcx> { + fn cx(&self) -> TyCtxt<'tcx> { + self.tcx + } + + fn relate_with_variance>>( + &mut self, + variance: rustc_type_ir::Variance, + _: ty::VarianceDiagInfo>, + a: T, + b: T, + ) -> RelateResult<'tcx, T> { + let old_variance = self.ambient_variance; + self.ambient_variance = self.ambient_variance.xform(variance); + self.relate(a, b)?; + self.ambient_variance = old_variance; + Ok(a) + } + + fn tys(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> { + structurally_relate_tys(self, a, b)?; + Ok(a) + } + + fn regions( + &mut self, + a: ty::Region<'tcx>, + _: ty::Region<'tcx>, + ) -> RelateResult<'tcx, ty::Region<'tcx>> { + let def_id = match *a { + ty::ReEarlyParam(ebr) => self.generics.region_param(ebr, self.tcx).def_id, + ty::ReBound( + _, + ty::BoundRegion { kind: ty::BoundRegionKind::BrNamed(def_id, ..), .. }, + ) + | ty::ReLateParam(ty::LateParamRegion { + scope: _, + bound_region: ty::BoundRegionKind::BrNamed(def_id, ..), + }) => def_id, + _ => { + return Ok(a); + } + }; + + if let Some(variance) = self.variances.get_mut(&def_id) { + *variance = unify(*variance, self.ambient_variance); + } else { + self.variances.insert(def_id, self.ambient_variance); + } + + Ok(a) + } + + fn consts( + &mut self, + a: ty::Const<'tcx>, + b: ty::Const<'tcx>, + ) -> RelateResult<'tcx, ty::Const<'tcx>> { + structurally_relate_consts(self, a, b)?; + Ok(a) + } + + fn binders( + &mut self, + a: ty::Binder<'tcx, T>, + b: ty::Binder<'tcx, T>, + ) -> RelateResult<'tcx, ty::Binder<'tcx, T>> + where + T: Relate>, + { + self.relate(a.skip_binder(), b.skip_binder())?; + Ok(a) + } +} + +/// What is the variance that satisfies the two variances? +fn unify(a: ty::Variance, b: ty::Variance) -> ty::Variance { + match (a, b) { + // Bivariance is lattice bottom. + (ty::Bivariant, other) | (other, ty::Bivariant) => other, + // Invariant is lattice top. + (ty::Invariant, _) | (_, ty::Invariant) => ty::Invariant, + // If type is required to be covariant and contravariant, then it's invariant. + (ty::Contravariant, ty::Covariant) | (ty::Covariant, ty::Contravariant) => ty::Invariant, + // Otherwise, co + co = co, contra + contra = contra. + (ty::Contravariant, ty::Contravariant) => ty::Contravariant, + (ty::Covariant, ty::Covariant) => ty::Covariant, + } +} diff --git a/tests/ui/impl-trait/precise-capturing/overcaptures-2024-but-fine.rs b/tests/ui/impl-trait/precise-capturing/overcaptures-2024-but-fine.rs new file mode 100644 index 0000000000000..e30f785b0ae33 --- /dev/null +++ b/tests/ui/impl-trait/precise-capturing/overcaptures-2024-but-fine.rs @@ -0,0 +1,15 @@ +//@ check-pass + +#![deny(impl_trait_overcaptures)] + +struct Ctxt<'tcx>(&'tcx ()); + +// In `compute`, we don't care that we're "overcapturing" `'tcx` +// in edition 2024, because it can be shortened at the call site +// and we know it outlives `'_`. + +impl<'tcx> Ctxt<'tcx> { + fn compute(&self) -> impl Sized + '_ {} +} + +fn main() {} From 70641356dced05df2f76eefa6c8aa441556e1595 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Mon, 12 Aug 2024 18:05:07 -0400 Subject: [PATCH 0530/2194] Do less work on the good path --- .../rustc_lint/src/impl_trait_overcaptures.rs | 223 +++++++++--------- 1 file changed, 113 insertions(+), 110 deletions(-) diff --git a/compiler/rustc_lint/src/impl_trait_overcaptures.rs b/compiler/rustc_lint/src/impl_trait_overcaptures.rs index 42c800a81af8a..9833079267347 100644 --- a/compiler/rustc_lint/src/impl_trait_overcaptures.rs +++ b/compiler/rustc_lint/src/impl_trait_overcaptures.rs @@ -264,130 +264,133 @@ where && let hir::OpaqueTyOrigin::FnReturn(parent_def_id) = opaque.origin && parent_def_id == self.parent_def_id { - // Compute the set of args that are captured by the opaque... - let mut captured = FxIndexSet::default(); - let mut captured_regions = FxIndexSet::default(); - let variances = self.tcx.variances_of(opaque_def_id); - let mut current_def_id = Some(opaque_def_id.to_def_id()); - while let Some(def_id) = current_def_id { - let generics = self.tcx.generics_of(def_id); - for param in &generics.own_params { - // A param is captured if it's invariant. - if variances[param.index as usize] != ty::Invariant { - continue; - } - - let arg = opaque_ty.args[param.index as usize]; - // We need to turn all `ty::Param`/`ConstKind::Param` and - // `ReEarlyParam`/`ReBound` into def ids. - captured.insert(extract_def_id_from_arg(self.tcx, generics, arg)); - - captured_regions.extend(arg.as_region()); - } - current_def_id = generics.parent; - } - - // Compute the set of in scope params that are not captured. Get their spans, - // since that's all we really care about them for emitting the diagnostic. - let mut uncaptured_args: FxIndexSet<_> = self - .in_scope_parameters - .iter() - .filter(|&(def_id, _)| !captured.contains(def_id)) - .collect(); - - // These are args that we know are likely fine to "overcapture", since they can be - // contravariantly shortened to one of the already-captured lifetimes that they - // outlive. - let covariant_long_args: FxIndexSet<_> = uncaptured_args - .iter() - .copied() - .filter(|&(def_id, kind)| { - let Some(ty::Bivariant | ty::Contravariant) = self.variances.get(def_id) else { - return false; - }; - let DefKind::LifetimeParam = self.tcx.def_kind(def_id) else { - return false; - }; - let uncaptured = match *kind { - ParamKind::Early(name, index) => ty::Region::new_early_param( - self.tcx, - ty::EarlyParamRegion { name, index }, - ), - ParamKind::Free(def_id, name) => ty::Region::new_late_param( - self.tcx, - self.parent_def_id.to_def_id(), - ty::BoundRegionKind::BrNamed(def_id, name), - ), - ParamKind::Late => return false, - }; - // Does this region outlive any captured region? - captured_regions.iter().any(|r| { - self.outlives_env - .free_region_map() - .sub_free_regions(self.tcx, *r, uncaptured) - }) - }) - .collect(); - // We don't care to warn on these args. - uncaptured_args.retain(|arg| !covariant_long_args.contains(arg)); - let opaque_span = self.tcx.def_span(opaque_def_id); let new_capture_rules = opaque_span.at_least_rust_2024() || self.tcx.features().lifetime_capture_rules_2024; - - // If we have uncaptured args, and if the opaque doesn't already have - // `use<>` syntax on it, and we're < edition 2024, then warn the user. if !new_capture_rules && !opaque.bounds.iter().any(|bound| matches!(bound, hir::GenericBound::Use(..))) - && !uncaptured_args.is_empty() { - let suggestion = if let Ok(snippet) = - self.tcx.sess.source_map().span_to_snippet(opaque_span) - && snippet.starts_with("impl ") - { - let (lifetimes, others): (Vec<_>, Vec<_>) = captured - .into_iter() - .partition(|def_id| self.tcx.def_kind(*def_id) == DefKind::LifetimeParam); - // Take all lifetime params first, then all others (ty/ct). - let generics: Vec<_> = lifetimes - .into_iter() - .chain(others) - .map(|def_id| self.tcx.item_name(def_id).to_string()) - .collect(); - // Make sure that we're not trying to name any APITs - if generics.iter().all(|name| !name.starts_with("impl ")) { - Some(( - format!(" + use<{}>", generics.join(", ")), - opaque_span.shrink_to_hi(), - )) - } else { - None + // Compute the set of args that are captured by the opaque... + let mut captured = FxIndexSet::default(); + let mut captured_regions = FxIndexSet::default(); + let variances = self.tcx.variances_of(opaque_def_id); + let mut current_def_id = Some(opaque_def_id.to_def_id()); + while let Some(def_id) = current_def_id { + let generics = self.tcx.generics_of(def_id); + for param in &generics.own_params { + // A param is captured if it's invariant. + if variances[param.index as usize] != ty::Invariant { + continue; + } + + let arg = opaque_ty.args[param.index as usize]; + // We need to turn all `ty::Param`/`ConstKind::Param` and + // `ReEarlyParam`/`ReBound` into def ids. + captured.insert(extract_def_id_from_arg(self.tcx, generics, arg)); + + captured_regions.extend(arg.as_region()); } - } else { - None - }; + current_def_id = generics.parent; + } + + // Compute the set of in scope params that are not captured. Get their spans, + // since that's all we really care about them for emitting the diagnostic. + let mut uncaptured_args: FxIndexSet<_> = self + .in_scope_parameters + .iter() + .filter(|&(def_id, _)| !captured.contains(def_id)) + .collect(); - let uncaptured_spans: Vec<_> = uncaptured_args - .into_iter() - .map(|(def_id, _)| self.tcx.def_span(def_id)) + // These are args that we know are likely fine to "overcapture", since they can be + // contravariantly shortened to one of the already-captured lifetimes that they + // outlive. + let covariant_long_args: FxIndexSet<_> = uncaptured_args + .iter() + .copied() + .filter(|&(def_id, kind)| { + let Some(ty::Bivariant | ty::Contravariant) = self.variances.get(def_id) + else { + return false; + }; + let DefKind::LifetimeParam = self.tcx.def_kind(def_id) else { + return false; + }; + let uncaptured = match *kind { + ParamKind::Early(name, index) => ty::Region::new_early_param( + self.tcx, + ty::EarlyParamRegion { name, index }, + ), + ParamKind::Free(def_id, name) => ty::Region::new_late_param( + self.tcx, + self.parent_def_id.to_def_id(), + ty::BoundRegionKind::BrNamed(def_id, name), + ), + ParamKind::Late => return false, + }; + // Does this region outlive any captured region? + captured_regions.iter().any(|r| { + self.outlives_env + .free_region_map() + .sub_free_regions(self.tcx, *r, uncaptured) + }) + }) .collect(); + // We don't care to warn on these args. + uncaptured_args.retain(|arg| !covariant_long_args.contains(arg)); + + // If we have uncaptured args, and if the opaque doesn't already have + // `use<>` syntax on it, and we're < edition 2024, then warn the user. + if !uncaptured_args.is_empty() { + let suggestion = if let Ok(snippet) = + self.tcx.sess.source_map().span_to_snippet(opaque_span) + && snippet.starts_with("impl ") + { + let (lifetimes, others): (Vec<_>, Vec<_>) = + captured.into_iter().partition(|def_id| { + self.tcx.def_kind(*def_id) == DefKind::LifetimeParam + }); + // Take all lifetime params first, then all others (ty/ct). + let generics: Vec<_> = lifetimes + .into_iter() + .chain(others) + .map(|def_id| self.tcx.item_name(def_id).to_string()) + .collect(); + // Make sure that we're not trying to name any APITs + if generics.iter().all(|name| !name.starts_with("impl ")) { + Some(( + format!(" + use<{}>", generics.join(", ")), + opaque_span.shrink_to_hi(), + )) + } else { + None + } + } else { + None + }; - self.tcx.emit_node_span_lint( - IMPL_TRAIT_OVERCAPTURES, - self.tcx.local_def_id_to_hir_id(opaque_def_id), - opaque_span, - ImplTraitOvercapturesLint { - self_ty: t, - num_captured: uncaptured_spans.len(), - uncaptured_spans, - suggestion, - }, - ); + let uncaptured_spans: Vec<_> = uncaptured_args + .into_iter() + .map(|(def_id, _)| self.tcx.def_span(def_id)) + .collect(); + + self.tcx.emit_node_span_lint( + IMPL_TRAIT_OVERCAPTURES, + self.tcx.local_def_id_to_hir_id(opaque_def_id), + opaque_span, + ImplTraitOvercapturesLint { + self_ty: t, + num_captured: uncaptured_spans.len(), + uncaptured_spans, + suggestion, + }, + ); + } } + // Otherwise, if we are edition 2024, have `use<>` syntax, and // have no uncaptured args, then we should warn to the user that // it's redundant to capture all args explicitly. - else if new_capture_rules + if new_capture_rules && let Some((captured_args, capturing_span)) = opaque.bounds.iter().find_map(|bound| match *bound { hir::GenericBound::Use(a, s) => Some((a, s)), From c1d041036e73ba514ca5fa1a8d2778ded416d3aa Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Mon, 19 Aug 2024 13:17:59 -0400 Subject: [PATCH 0531/2194] Review comments --- .../rustc_lint/src/impl_trait_overcaptures.rs | 87 +++++++++---------- compiler/rustc_lint/src/lib.rs | 1 + 2 files changed, 40 insertions(+), 48 deletions(-) diff --git a/compiler/rustc_lint/src/impl_trait_overcaptures.rs b/compiler/rustc_lint/src/impl_trait_overcaptures.rs index 9833079267347..c43c650a9f912 100644 --- a/compiler/rustc_lint/src/impl_trait_overcaptures.rs +++ b/compiler/rustc_lint/src/impl_trait_overcaptures.rs @@ -1,3 +1,4 @@ +use std::assert_matches::debug_assert_matches; use std::cell::LazyCell; use rustc_data_structures::fx::{FxHashMap, FxIndexMap, FxIndexSet}; @@ -178,7 +179,7 @@ fn check_fn(tcx: TyCtxt<'_>, parent_def_id: LocalDefId) { ambient_variance: ty::Covariant, generics: tcx.generics_of(parent_def_id), }; - let _ = functional_variances.relate(sig, sig); + functional_variances.relate(sig, sig).unwrap(); functional_variances.variances }), outlives_env: LazyCell::new(|| { @@ -208,10 +209,7 @@ where VarFn: FnOnce() -> FxHashMap, OutlivesFn: FnOnce() -> OutlivesEnvironment<'tcx>, { - fn visit_binder>>( - &mut self, - t: &ty::Binder<'tcx, T>, - ) -> Self::Result { + fn visit_binder>>(&mut self, t: &ty::Binder<'tcx, T>) { // When we get into a binder, we need to add its own bound vars to the scope. let mut added = vec![]; for arg in t.bound_vars() { @@ -241,7 +239,7 @@ where } } - fn visit_ty(&mut self, t: Ty<'tcx>) -> Self::Result { + fn visit_ty(&mut self, t: Ty<'tcx>) { if !t.has_aliases() { return; } @@ -293,50 +291,43 @@ where current_def_id = generics.parent; } - // Compute the set of in scope params that are not captured. Get their spans, - // since that's all we really care about them for emitting the diagnostic. + // Compute the set of in scope params that are not captured. let mut uncaptured_args: FxIndexSet<_> = self .in_scope_parameters .iter() .filter(|&(def_id, _)| !captured.contains(def_id)) .collect(); - - // These are args that we know are likely fine to "overcapture", since they can be - // contravariantly shortened to one of the already-captured lifetimes that they - // outlive. - let covariant_long_args: FxIndexSet<_> = uncaptured_args - .iter() - .copied() - .filter(|&(def_id, kind)| { - let Some(ty::Bivariant | ty::Contravariant) = self.variances.get(def_id) - else { - return false; - }; - let DefKind::LifetimeParam = self.tcx.def_kind(def_id) else { - return false; - }; - let uncaptured = match *kind { - ParamKind::Early(name, index) => ty::Region::new_early_param( - self.tcx, - ty::EarlyParamRegion { name, index }, - ), - ParamKind::Free(def_id, name) => ty::Region::new_late_param( - self.tcx, - self.parent_def_id.to_def_id(), - ty::BoundRegionKind::BrNamed(def_id, name), - ), - ParamKind::Late => return false, - }; - // Does this region outlive any captured region? - captured_regions.iter().any(|r| { - self.outlives_env - .free_region_map() - .sub_free_regions(self.tcx, *r, uncaptured) - }) + // Remove the set of lifetimes that are in-scope that outlive some other captured + // lifetime and are contravariant (i.e. covariant in argument position). + uncaptured_args.retain(|&(def_id, kind)| { + let Some(ty::Bivariant | ty::Contravariant) = self.variances.get(def_id) else { + // Keep all covariant/invariant args. Also if variance is `None`, + // then that means it's either not a lifetime, or it didn't show up + // anywhere in the signature. + return true; + }; + // We only computed variance of lifetimes... + debug_assert_matches!(self.tcx.def_kind(def_id), DefKind::LifetimeParam); + let uncaptured = match *kind { + ParamKind::Early(name, index) => ty::Region::new_early_param( + self.tcx, + ty::EarlyParamRegion { name, index }, + ), + ParamKind::Free(def_id, name) => ty::Region::new_late_param( + self.tcx, + self.parent_def_id.to_def_id(), + ty::BoundRegionKind::BrNamed(def_id, name), + ), + // Totally ignore late bound args from binders. + ParamKind::Late => return true, + }; + // Does this region outlive any captured region? + !captured_regions.iter().any(|r| { + self.outlives_env + .free_region_map() + .sub_free_regions(self.tcx, *r, uncaptured) }) - .collect(); - // We don't care to warn on these args. - uncaptured_args.retain(|arg| !covariant_long_args.contains(arg)); + }); // If we have uncaptured args, and if the opaque doesn't already have // `use<>` syntax on it, and we're < edition 2024, then warn the user. @@ -546,13 +537,13 @@ impl<'tcx> TypeRelation> for FunctionalVariances<'tcx> { ) -> RelateResult<'tcx, T> { let old_variance = self.ambient_variance; self.ambient_variance = self.ambient_variance.xform(variance); - self.relate(a, b)?; + self.relate(a, b).unwrap(); self.ambient_variance = old_variance; Ok(a) } fn tys(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> { - structurally_relate_tys(self, a, b)?; + structurally_relate_tys(self, a, b).unwrap(); Ok(a) } @@ -590,7 +581,7 @@ impl<'tcx> TypeRelation> for FunctionalVariances<'tcx> { a: ty::Const<'tcx>, b: ty::Const<'tcx>, ) -> RelateResult<'tcx, ty::Const<'tcx>> { - structurally_relate_consts(self, a, b)?; + structurally_relate_consts(self, a, b).unwrap(); Ok(a) } @@ -602,7 +593,7 @@ impl<'tcx> TypeRelation> for FunctionalVariances<'tcx> { where T: Relate>, { - self.relate(a.skip_binder(), b.skip_binder())?; + self.relate(a.skip_binder(), b.skip_binder()).unwrap(); Ok(a) } } diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs index c5a5c5b30afef..bb7de4739fbdd 100644 --- a/compiler/rustc_lint/src/lib.rs +++ b/compiler/rustc_lint/src/lib.rs @@ -30,6 +30,7 @@ #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![doc(rust_logo)] #![feature(array_windows)] +#![feature(assert_matches)] #![feature(box_patterns)] #![feature(control_flow_enum)] #![feature(extract_if)] From e8472e84e3e1ef614b97896d42e0a6976fb02855 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 13 Aug 2024 17:38:24 -0400 Subject: [PATCH 0532/2194] Check unnormalized signature on pointer cast --- compiler/rustc_borrowck/src/type_check/mod.rs | 71 +++++++++++++++++-- ...ed-references-plus-variance-early-bound.rs | 11 +++ ...eferences-plus-variance-early-bound.stderr | 10 +++ ...d-references-plus-variance-unnormalized.rs | 17 +++++ ...ferences-plus-variance-unnormalized.stderr | 14 ++++ ...unds-on-nested-references-plus-variance.rs | 7 +- ...-on-nested-references-plus-variance.stderr | 10 +++ 7 files changed, 127 insertions(+), 13 deletions(-) create mode 100644 tests/ui/implied-bounds/implied-bounds-on-nested-references-plus-variance-early-bound.rs create mode 100644 tests/ui/implied-bounds/implied-bounds-on-nested-references-plus-variance-early-bound.stderr create mode 100644 tests/ui/implied-bounds/implied-bounds-on-nested-references-plus-variance-unnormalized.rs create mode 100644 tests/ui/implied-bounds/implied-bounds-on-nested-references-plus-variance-unnormalized.stderr create mode 100644 tests/ui/implied-bounds/implied-bounds-on-nested-references-plus-variance.stderr diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index 224f8d5c893d7..3c9a43883ad64 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -1979,19 +1979,76 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { match cast_kind { CastKind::PointerCoercion(PointerCoercion::ReifyFnPointer) => { - let fn_sig = op.ty(body, tcx).fn_sig(tcx); + let src_sig = op.ty(body, tcx).fn_sig(tcx); + + // HACK: This shouldn't be necessary... We can remove this when we actually + // get binders with where clauses, then elaborate implied bounds into that + // binder, and implement a higher-ranked subtyping algorithm that actually + // respects these implied bounds. + // + // This protects against the case where we are casting from a higher-ranked + // fn item to a non-higher-ranked fn pointer, where the cast throws away + // implied bounds that would've needed to be checked at the call site. This + // only works when we're casting to a non-higher-ranked fn ptr, since + // placeholders in the target signature could have untracked implied + // bounds, resulting in incorrect errors. + // + // We check that this signature is WF before subtyping the signature with + // the target fn sig. + if src_sig.has_bound_regions() + && let ty::FnPtr(target_fn_tys, target_hdr) = *ty.kind() + && let target_sig = target_fn_tys.with(target_hdr) + && let Some(target_sig) = target_sig.no_bound_vars() + { + let src_sig = self.infcx.instantiate_binder_with_fresh_vars( + span, + BoundRegionConversionTime::HigherRankedType, + src_sig, + ); + let src_ty = Ty::new_fn_ptr(self.tcx(), ty::Binder::dummy(src_sig)); + self.prove_predicate( + ty::ClauseKind::WellFormed(src_ty.into()), + location.to_locations(), + ConstraintCategory::Cast { unsize_to: None }, + ); + + let src_ty = self.normalize(src_ty, location); + if let Err(terr) = self.sub_types( + src_ty, + *ty, + location.to_locations(), + ConstraintCategory::Cast { unsize_to: None }, + ) { + span_mirbug!( + self, + rvalue, + "equating {:?} with {:?} yields {:?}", + target_sig, + src_sig, + terr + ); + }; + } + + let src_ty = Ty::new_fn_ptr(tcx, src_sig); + // HACK: We want to assert that the signature of the source fn is + // well-formed, because we don't enforce that via the WF of FnDef + // types normally. This should be removed when we improve the tracking + // of implied bounds of fn signatures. + self.prove_predicate( + ty::ClauseKind::WellFormed(src_ty.into()), + location.to_locations(), + ConstraintCategory::Cast { unsize_to: None }, + ); // The type that we see in the fcx is like // `foo::<'a, 'b>`, where `foo` is the path to a // function definition. When we extract the // signature, it comes from the `fn_sig` query, // and hence may contain unnormalized results. - let fn_sig = self.normalize(fn_sig, location); - - let ty_fn_ptr_from = Ty::new_fn_ptr(tcx, fn_sig); - + let src_ty = self.normalize(src_ty, location); if let Err(terr) = self.sub_types( - ty_fn_ptr_from, + src_ty, *ty, location.to_locations(), ConstraintCategory::Cast { unsize_to: None }, @@ -2000,7 +2057,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { self, rvalue, "equating {:?} with {:?} yields {:?}", - ty_fn_ptr_from, + src_ty, ty, terr ); diff --git a/tests/ui/implied-bounds/implied-bounds-on-nested-references-plus-variance-early-bound.rs b/tests/ui/implied-bounds/implied-bounds-on-nested-references-plus-variance-early-bound.rs new file mode 100644 index 0000000000000..16095f66da715 --- /dev/null +++ b/tests/ui/implied-bounds/implied-bounds-on-nested-references-plus-variance-early-bound.rs @@ -0,0 +1,11 @@ +static UNIT: &'static &'static () = &&(); + +fn foo<'a: 'a, 'b: 'b, T>(_: &'a &'b (), v: &'b T) -> &'a T { v } + +fn bad<'a, T>(x: &'a T) -> &'static T { + let f: fn(_, &'a T) -> &'static T = foo; + //~^ ERROR lifetime may not live long enough + f(UNIT, x) +} + +fn main() {} diff --git a/tests/ui/implied-bounds/implied-bounds-on-nested-references-plus-variance-early-bound.stderr b/tests/ui/implied-bounds/implied-bounds-on-nested-references-plus-variance-early-bound.stderr new file mode 100644 index 0000000000000..4925576e5a09b --- /dev/null +++ b/tests/ui/implied-bounds/implied-bounds-on-nested-references-plus-variance-early-bound.stderr @@ -0,0 +1,10 @@ +error: lifetime may not live long enough + --> $DIR/implied-bounds-on-nested-references-plus-variance-early-bound.rs:6:12 + | +LL | fn bad<'a, T>(x: &'a T) -> &'static T { + | -- lifetime `'a` defined here +LL | let f: fn(_, &'a T) -> &'static T = foo; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static` + +error: aborting due to 1 previous error + diff --git a/tests/ui/implied-bounds/implied-bounds-on-nested-references-plus-variance-unnormalized.rs b/tests/ui/implied-bounds/implied-bounds-on-nested-references-plus-variance-unnormalized.rs new file mode 100644 index 0000000000000..b842b21224d4e --- /dev/null +++ b/tests/ui/implied-bounds/implied-bounds-on-nested-references-plus-variance-unnormalized.rs @@ -0,0 +1,17 @@ +trait ToArg { + type Arg; +} +impl ToArg for U { + type Arg = T; +} + +fn extend_inner<'a, 'b>(x: &'a str) -> <&'b &'a () as ToArg<&'b str>>::Arg { x } +fn extend<'a, 'b>(x: &'a str) -> &'b str { + (extend_inner as fn(_) -> _)(x) + //~^ ERROR lifetime may not live long enough +} + +fn main() { + let y = extend(&String::from("Hello World")); + println!("{}", y); +} diff --git a/tests/ui/implied-bounds/implied-bounds-on-nested-references-plus-variance-unnormalized.stderr b/tests/ui/implied-bounds/implied-bounds-on-nested-references-plus-variance-unnormalized.stderr new file mode 100644 index 0000000000000..a2ac0d897b666 --- /dev/null +++ b/tests/ui/implied-bounds/implied-bounds-on-nested-references-plus-variance-unnormalized.stderr @@ -0,0 +1,14 @@ +error: lifetime may not live long enough + --> $DIR/implied-bounds-on-nested-references-plus-variance-unnormalized.rs:10:5 + | +LL | fn extend<'a, 'b>(x: &'a str) -> &'b str { + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +LL | (extend_inner as fn(_) -> _)(x) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a` + | + = help: consider adding the following bound: `'a: 'b` + +error: aborting due to 1 previous error + diff --git a/tests/ui/implied-bounds/implied-bounds-on-nested-references-plus-variance.rs b/tests/ui/implied-bounds/implied-bounds-on-nested-references-plus-variance.rs index f3401f34eec73..d40418a4e9027 100644 --- a/tests/ui/implied-bounds/implied-bounds-on-nested-references-plus-variance.rs +++ b/tests/ui/implied-bounds/implied-bounds-on-nested-references-plus-variance.rs @@ -1,15 +1,10 @@ -//@ check-pass -//@ known-bug: #25860 - -// Should fail. The combination of variance and implied bounds for nested -// references allows us to infer a longer lifetime than we can prove. - static UNIT: &'static &'static () = &&(); fn foo<'a, 'b, T>(_: &'a &'b (), v: &'b T) -> &'a T { v } fn bad<'a, T>(x: &'a T) -> &'static T { let f: fn(_, &'a T) -> &'static T = foo; + //~^ ERROR lifetime may not live long enough f(UNIT, x) } diff --git a/tests/ui/implied-bounds/implied-bounds-on-nested-references-plus-variance.stderr b/tests/ui/implied-bounds/implied-bounds-on-nested-references-plus-variance.stderr new file mode 100644 index 0000000000000..1ad9ba31f37bc --- /dev/null +++ b/tests/ui/implied-bounds/implied-bounds-on-nested-references-plus-variance.stderr @@ -0,0 +1,10 @@ +error: lifetime may not live long enough + --> $DIR/implied-bounds-on-nested-references-plus-variance.rs:6:12 + | +LL | fn bad<'a, T>(x: &'a T) -> &'static T { + | -- lifetime `'a` defined here +LL | let f: fn(_, &'a T) -> &'static T = foo; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static` + +error: aborting due to 1 previous error + From 67804c57e7a53b96d79b49bf6e356e3ade4d943d Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sun, 25 Aug 2024 16:56:06 -0400 Subject: [PATCH 0533/2194] Adjust tests --- ...d-bounds-on-nested-references-plus-variance-2.rs | 13 +++++++++++++ ...n-nested-references-plus-variance-early-bound.rs | 2 ++ ...sted-references-plus-variance-early-bound.stderr | 2 +- ...-nested-references-plus-variance-unnormalized.rs | 2 ++ ...ted-references-plus-variance-unnormalized.stderr | 2 +- ...ied-bounds-on-nested-references-plus-variance.rs | 2 ++ ...bounds-on-nested-references-plus-variance.stderr | 2 +- 7 files changed, 22 insertions(+), 3 deletions(-) create mode 100644 tests/ui/implied-bounds/implied-bounds-on-nested-references-plus-variance-2.rs diff --git a/tests/ui/implied-bounds/implied-bounds-on-nested-references-plus-variance-2.rs b/tests/ui/implied-bounds/implied-bounds-on-nested-references-plus-variance-2.rs new file mode 100644 index 0000000000000..ca8b8b7e4d92b --- /dev/null +++ b/tests/ui/implied-bounds/implied-bounds-on-nested-references-plus-variance-2.rs @@ -0,0 +1,13 @@ +//@ check-pass +//@ known-bug: #25860 + +static UNIT: &'static &'static () = &&(); + +fn foo<'a, 'b, T>(_: &'a &'b (), v: &'b T, _: &()) -> &'a T { v } + +fn bad<'a, T>(x: &'a T) -> &'static T { + let f: fn(_, &'a T, &()) -> &'static T = foo; + f(UNIT, x, &()) +} + +fn main() {} diff --git a/tests/ui/implied-bounds/implied-bounds-on-nested-references-plus-variance-early-bound.rs b/tests/ui/implied-bounds/implied-bounds-on-nested-references-plus-variance-early-bound.rs index 16095f66da715..226a6fa30163c 100644 --- a/tests/ui/implied-bounds/implied-bounds-on-nested-references-plus-variance-early-bound.rs +++ b/tests/ui/implied-bounds/implied-bounds-on-nested-references-plus-variance-early-bound.rs @@ -1,3 +1,5 @@ +// Regression test for #129021. + static UNIT: &'static &'static () = &&(); fn foo<'a: 'a, 'b: 'b, T>(_: &'a &'b (), v: &'b T) -> &'a T { v } diff --git a/tests/ui/implied-bounds/implied-bounds-on-nested-references-plus-variance-early-bound.stderr b/tests/ui/implied-bounds/implied-bounds-on-nested-references-plus-variance-early-bound.stderr index 4925576e5a09b..84d2a6d2b6a62 100644 --- a/tests/ui/implied-bounds/implied-bounds-on-nested-references-plus-variance-early-bound.stderr +++ b/tests/ui/implied-bounds/implied-bounds-on-nested-references-plus-variance-early-bound.stderr @@ -1,5 +1,5 @@ error: lifetime may not live long enough - --> $DIR/implied-bounds-on-nested-references-plus-variance-early-bound.rs:6:12 + --> $DIR/implied-bounds-on-nested-references-plus-variance-early-bound.rs:8:12 | LL | fn bad<'a, T>(x: &'a T) -> &'static T { | -- lifetime `'a` defined here diff --git a/tests/ui/implied-bounds/implied-bounds-on-nested-references-plus-variance-unnormalized.rs b/tests/ui/implied-bounds/implied-bounds-on-nested-references-plus-variance-unnormalized.rs index b842b21224d4e..f30689901893c 100644 --- a/tests/ui/implied-bounds/implied-bounds-on-nested-references-plus-variance-unnormalized.rs +++ b/tests/ui/implied-bounds/implied-bounds-on-nested-references-plus-variance-unnormalized.rs @@ -1,3 +1,5 @@ +// Regression test for #129021. + trait ToArg { type Arg; } diff --git a/tests/ui/implied-bounds/implied-bounds-on-nested-references-plus-variance-unnormalized.stderr b/tests/ui/implied-bounds/implied-bounds-on-nested-references-plus-variance-unnormalized.stderr index a2ac0d897b666..4cdb959786a56 100644 --- a/tests/ui/implied-bounds/implied-bounds-on-nested-references-plus-variance-unnormalized.stderr +++ b/tests/ui/implied-bounds/implied-bounds-on-nested-references-plus-variance-unnormalized.stderr @@ -1,5 +1,5 @@ error: lifetime may not live long enough - --> $DIR/implied-bounds-on-nested-references-plus-variance-unnormalized.rs:10:5 + --> $DIR/implied-bounds-on-nested-references-plus-variance-unnormalized.rs:12:5 | LL | fn extend<'a, 'b>(x: &'a str) -> &'b str { | -- -- lifetime `'b` defined here diff --git a/tests/ui/implied-bounds/implied-bounds-on-nested-references-plus-variance.rs b/tests/ui/implied-bounds/implied-bounds-on-nested-references-plus-variance.rs index d40418a4e9027..6de81cba7281a 100644 --- a/tests/ui/implied-bounds/implied-bounds-on-nested-references-plus-variance.rs +++ b/tests/ui/implied-bounds/implied-bounds-on-nested-references-plus-variance.rs @@ -1,3 +1,5 @@ +// Regression test for #129021. + static UNIT: &'static &'static () = &&(); fn foo<'a, 'b, T>(_: &'a &'b (), v: &'b T) -> &'a T { v } diff --git a/tests/ui/implied-bounds/implied-bounds-on-nested-references-plus-variance.stderr b/tests/ui/implied-bounds/implied-bounds-on-nested-references-plus-variance.stderr index 1ad9ba31f37bc..c96fa92937b0c 100644 --- a/tests/ui/implied-bounds/implied-bounds-on-nested-references-plus-variance.stderr +++ b/tests/ui/implied-bounds/implied-bounds-on-nested-references-plus-variance.stderr @@ -1,5 +1,5 @@ error: lifetime may not live long enough - --> $DIR/implied-bounds-on-nested-references-plus-variance.rs:6:12 + --> $DIR/implied-bounds-on-nested-references-plus-variance.rs:8:12 | LL | fn bad<'a, T>(x: &'a T) -> &'static T { | -- lifetime `'a` defined here From f3b6965f90e764fc29ff627a6965ccfc68d38ead Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Thu, 5 Sep 2024 12:40:41 +0200 Subject: [PATCH 0534/2194] Give InlineAsmOperand a HIR representation --- .../rust-analyzer/crates/hir-def/src/body.rs | 27 +++- .../crates/hir-def/src/body/lower.rs | 2 +- .../crates/hir-def/src/body/lower/asm.rs | 148 ++++++++++-------- src/tools/rust-analyzer/crates/hir/src/lib.rs | 9 +- .../rust-analyzer/crates/hir/src/semantics.rs | 69 +++++--- .../crates/hir/src/semantics/source_to_def.rs | 21 ++- .../crates/hir/src/source_analyzer.rs | 22 +++ .../rust-analyzer/crates/ide-db/src/defs.rs | 32 ++-- .../rust-analyzer/crates/ide-db/src/rename.rs | 2 +- .../rust-analyzer/crates/ide-db/src/search.rs | 29 ++-- .../rust-analyzer/crates/ide/src/doc_links.rs | 4 +- .../rust-analyzer/crates/ide/src/moniker.rs | 4 +- .../crates/ide/src/navigation_target.rs | 2 +- .../ide/src/syntax_highlighting/format.rs | 24 +-- .../ide/src/syntax_highlighting/highlight.rs | 2 +- .../ide/src/syntax_highlighting/inject.rs | 2 +- .../test_data/highlight_asm.html | 32 ++-- .../test_data/highlight_strings.html | 8 +- .../parser/src/grammar/expressions/atom.rs | 16 +- .../parser/src/syntax_kind/generated.rs | 2 + .../test_data/parser/inline/ok/asm_expr.rast | 52 +++--- .../rust-analyzer/crates/syntax/rust.ungram | 8 +- .../crates/syntax/src/ast/generated/nodes.rs | 109 ++++++++++--- 23 files changed, 409 insertions(+), 217 deletions(-) diff --git a/src/tools/rust-analyzer/crates/hir-def/src/body.rs b/src/tools/rust-analyzer/crates/hir-def/src/body.rs index f5fe8f8770130..03507189fb99a 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/body.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/body.rs @@ -100,7 +100,14 @@ pub struct BodySourceMap { field_map_back: FxHashMap, pat_field_map_back: FxHashMap, - format_args_template_map: FxHashMap>, + template_map: Option< + Box<( + // format_args! + FxHashMap>, + // asm! + FxHashMap>, + )>, + >, expansions: FxHashMap>, MacroFileId>, @@ -426,7 +433,16 @@ impl BodySourceMap { node: InFile<&ast::FormatArgsExpr>, ) -> Option<&[(syntax::TextRange, Name)]> { let src = node.map(AstPtr::new).map(AstPtr::upcast::); - self.format_args_template_map.get(self.expr_map.get(&src)?).map(std::ops::Deref::deref) + self.template_map.as_ref()?.0.get(self.expr_map.get(&src)?).map(std::ops::Deref::deref) + } + + pub fn asm_template_args( + &self, + node: InFile<&ast::AsmExpr>, + ) -> Option<(ExprId, &[(syntax::TextRange, usize)])> { + let src = node.map(AstPtr::new).map(AstPtr::upcast::); + let expr = self.expr_map.get(&src)?; + Some(*expr).zip(self.template_map.as_ref()?.1.get(expr).map(std::ops::Deref::deref)) } /// Get a reference to the body source map's diagnostics. @@ -446,11 +462,14 @@ impl BodySourceMap { field_map_back, pat_field_map_back, expansions, - format_args_template_map, + template_map, diagnostics, binding_definitions, } = self; - format_args_template_map.shrink_to_fit(); + if let Some(template_map) = template_map { + template_map.0.shrink_to_fit(); + template_map.1.shrink_to_fit(); + } expr_map.shrink_to_fit(); expr_map_back.shrink_to_fit(); pat_map.shrink_to_fit(); diff --git a/src/tools/rust-analyzer/crates/hir-def/src/body/lower.rs b/src/tools/rust-analyzer/crates/hir-def/src/body/lower.rs index dfcb8b81204d2..9c547574ecb1f 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/body/lower.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/body/lower.rs @@ -1847,7 +1847,7 @@ impl ExprCollector<'_> { }, syntax_ptr, ); - self.source_map.format_args_template_map.insert(idx, mappings); + self.source_map.template_map.get_or_insert_with(Default::default).0.insert(idx, mappings); idx } diff --git a/src/tools/rust-analyzer/crates/hir-def/src/body/lower/asm.rs b/src/tools/rust-analyzer/crates/hir-def/src/body/lower/asm.rs index dafa3a859debd..59b348b77db00 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/body/lower/asm.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/body/lower/asm.rs @@ -1,4 +1,3 @@ -use hir_expand::name::Name; use intern::Symbol; use rustc_hash::{FxHashMap, FxHashSet}; use syntax::{ @@ -25,7 +24,7 @@ impl ExprCollector<'_> { let mut named_pos: FxHashMap = Default::default(); let mut named_args: FxHashMap = Default::default(); let mut reg_args: FxHashSet = Default::default(); - for operand in asm.asm_operands() { + for piece in asm.asm_pieces() { let slot = operands.len(); let mut lower_reg = |reg: Option| { let reg = reg?; @@ -39,14 +38,14 @@ impl ExprCollector<'_> { } }; - let op = match operand { - ast::AsmOperand::AsmClobberAbi(clobber_abi) => { + let op = match piece { + ast::AsmPiece::AsmClobberAbi(clobber_abi) => { if let Some(abi_name) = clobber_abi.string_token() { clobber_abis.insert(Symbol::intern(abi_name.text())); } continue; } - ast::AsmOperand::AsmOptions(opt) => { + ast::AsmPiece::AsmOptions(opt) => { opt.asm_options().for_each(|opt| { options |= match opt.syntax().first_token().map_or(T![$], |it| it.kind()) { T![att_syntax] => AsmOptions::ATT_SYNTAX, @@ -63,71 +62,82 @@ impl ExprCollector<'_> { }); continue; } - ast::AsmOperand::AsmRegOperand(op) => { - let Some(dir_spec) = op.asm_dir_spec() else { - continue; - }; - let Some(reg) = lower_reg(op.asm_reg_spec()) else { - continue; - }; + ast::AsmPiece::AsmOperandNamed(op) => { if let Some(name) = op.name() { let sym = Symbol::intern(&name.text()); named_args.insert(sym.clone(), slot); named_pos.insert(slot, sym); } - if dir_spec.in_token().is_some() { - let expr = self - .collect_expr_opt(op.asm_operand_expr().and_then(|it| it.in_expr())); - AsmOperand::In { reg, expr } - } else if dir_spec.out_token().is_some() { - let expr = self - .collect_expr_opt(op.asm_operand_expr().and_then(|it| it.in_expr())); - AsmOperand::Out { reg, expr: Some(expr), late: false } - } else if dir_spec.lateout_token().is_some() { - let expr = self - .collect_expr_opt(op.asm_operand_expr().and_then(|it| it.in_expr())); - AsmOperand::Out { reg, expr: Some(expr), late: true } - } else if dir_spec.inout_token().is_some() { - let Some(op_expr) = op.asm_operand_expr() else { continue }; - let in_expr = self.collect_expr_opt(op_expr.in_expr()); - let out_expr = op_expr.out_expr().map(|it| self.collect_expr(it)); - match out_expr { - Some(out_expr) => AsmOperand::SplitInOut { - reg, - in_expr, - out_expr: Some(out_expr), - late: false, - }, - None => AsmOperand::InOut { reg, expr: in_expr, late: false }, + let Some(op) = op.asm_operand() else { continue }; + match op { + ast::AsmOperand::AsmRegOperand(op) => { + let Some(dir_spec) = op.asm_dir_spec() else { + continue; + }; + let Some(reg) = lower_reg(op.asm_reg_spec()) else { + continue; + }; + if dir_spec.in_token().is_some() { + let expr = self.collect_expr_opt( + op.asm_operand_expr().and_then(|it| it.in_expr()), + ); + AsmOperand::In { reg, expr } + } else if dir_spec.out_token().is_some() { + let expr = self.collect_expr_opt( + op.asm_operand_expr().and_then(|it| it.in_expr()), + ); + AsmOperand::Out { reg, expr: Some(expr), late: false } + } else if dir_spec.lateout_token().is_some() { + let expr = self.collect_expr_opt( + op.asm_operand_expr().and_then(|it| it.in_expr()), + ); + AsmOperand::Out { reg, expr: Some(expr), late: true } + } else if dir_spec.inout_token().is_some() { + let Some(op_expr) = op.asm_operand_expr() else { continue }; + let in_expr = self.collect_expr_opt(op_expr.in_expr()); + let out_expr = op_expr.out_expr().map(|it| self.collect_expr(it)); + match out_expr { + Some(out_expr) => AsmOperand::SplitInOut { + reg, + in_expr, + out_expr: Some(out_expr), + late: false, + }, + None => AsmOperand::InOut { reg, expr: in_expr, late: false }, + } + } else if dir_spec.inlateout_token().is_some() { + let Some(op_expr) = op.asm_operand_expr() else { continue }; + let in_expr = self.collect_expr_opt(op_expr.in_expr()); + let out_expr = op_expr.out_expr().map(|it| self.collect_expr(it)); + match out_expr { + Some(out_expr) => AsmOperand::SplitInOut { + reg, + in_expr, + out_expr: Some(out_expr), + late: false, + }, + None => AsmOperand::InOut { reg, expr: in_expr, late: false }, + } + } else { + continue; + } } - } else if dir_spec.inlateout_token().is_some() { - let Some(op_expr) = op.asm_operand_expr() else { continue }; - let in_expr = self.collect_expr_opt(op_expr.in_expr()); - let out_expr = op_expr.out_expr().map(|it| self.collect_expr(it)); - match out_expr { - Some(out_expr) => AsmOperand::SplitInOut { - reg, - in_expr, - out_expr: Some(out_expr), - late: false, - }, - None => AsmOperand::InOut { reg, expr: in_expr, late: false }, + ast::AsmOperand::AsmLabel(l) => { + AsmOperand::Label(self.collect_block_opt(l.block_expr())) + } + ast::AsmOperand::AsmConst(c) => { + AsmOperand::Const(self.collect_expr_opt(c.expr())) + } + ast::AsmOperand::AsmSym(s) => { + let Some(path) = + s.path().and_then(|p| self.expander.parse_path(self.db, p)) + else { + continue; + }; + AsmOperand::Sym(path) } - } else { - continue; } } - ast::AsmOperand::AsmLabel(l) => { - AsmOperand::Label(self.collect_block_opt(l.block_expr())) - } - ast::AsmOperand::AsmConst(c) => AsmOperand::Const(self.collect_expr_opt(c.expr())), - ast::AsmOperand::AsmSym(s) => { - let Some(path) = s.path().and_then(|p| self.expander.parse_path(self.db, p)) - else { - continue; - }; - AsmOperand::Sym(path) - } }; operands.push(op); } @@ -192,7 +202,7 @@ impl ExprCollector<'_> { rustc_parse_format::Piece::NextArgument(arg) => { // let span = arg_spans.next(); - let _operand_idx = match arg.position { + let operand_idx = match arg.position { rustc_parse_format::ArgumentIs(idx) | rustc_parse_format::ArgumentImplicitlyIs(idx) => { if idx >= operands.len() @@ -206,15 +216,15 @@ impl ExprCollector<'_> { } rustc_parse_format::ArgumentNamed(name) => { let name = Symbol::intern(name); - if let Some(position_span) = to_span(arg.position_span) { - mappings.push(( - position_span, - Name::new_symbol_root(name.clone()), - )); - } named_args.get(&name).copied() } }; + + if let Some(operand_idx) = operand_idx { + if let Some(position_span) = to_span(arg.position_span) { + mappings.push((position_span, operand_idx)); + } + } } } } @@ -224,7 +234,7 @@ impl ExprCollector<'_> { Expr::InlineAsm(InlineAsm { operands: operands.into_boxed_slice(), options }), syntax_ptr, ); - self.source_map.format_args_template_map.insert(idx, mappings); + self.source_map.template_map.get_or_insert_with(Default::default).1.insert(idx, mappings); idx } } diff --git a/src/tools/rust-analyzer/crates/hir/src/lib.rs b/src/tools/rust-analyzer/crates/hir/src/lib.rs index 81d6466c2f31d..c8b227123f1c1 100644 --- a/src/tools/rust-analyzer/crates/hir/src/lib.rs +++ b/src/tools/rust-analyzer/crates/hir/src/lib.rs @@ -43,7 +43,7 @@ use hir_def::{ body::{BodyDiagnostic, SyntheticSyntax}, data::adt::VariantData, generics::{LifetimeParamData, TypeOrConstParamData, TypeParamProvenance}, - hir::{BindingAnnotation, BindingId, ExprOrPatId, LabelId, Pat}, + hir::{BindingAnnotation, BindingId, ExprId, ExprOrPatId, LabelId, Pat}, item_tree::{AttrOwner, FieldParent, ItemTreeFieldId, ItemTreeNode}, lang_item::LangItemTarget, layout::{self, ReprOptions, TargetDataLayout}, @@ -5246,6 +5246,13 @@ impl Type { } } +#[derive(Debug, PartialEq, Eq, Copy, Clone, Hash)] +pub struct InlineAsmOperand { + owner: DefWithBodyId, + expr: ExprId, + index: usize, +} + // FIXME: Document this #[derive(Debug)] pub struct Callable { diff --git a/src/tools/rust-analyzer/crates/hir/src/semantics.rs b/src/tools/rust-analyzer/crates/hir/src/semantics.rs index 4e6887295c8a3..0ba0e446578e7 100644 --- a/src/tools/rust-analyzer/crates/hir/src/semantics.rs +++ b/src/tools/rust-analyzer/crates/hir/src/semantics.rs @@ -47,9 +47,9 @@ use crate::{ source_analyzer::{resolve_hir_path, SourceAnalyzer}, Access, Adjust, Adjustment, Adt, AutoBorrow, BindingMode, BuiltinAttr, Callable, Const, ConstParam, Crate, DeriveHelper, Enum, Field, Function, HasSource, HirFileId, Impl, InFile, - ItemInNs, Label, LifetimeParam, Local, Macro, Module, ModuleDef, Name, OverloadedDeref, Path, - ScopeDef, Static, Struct, ToolModule, Trait, TraitAlias, TupleField, Type, TypeAlias, - TypeParam, Union, Variant, VariantDef, + InlineAsmOperand, ItemInNs, Label, LifetimeParam, Local, Macro, Module, ModuleDef, Name, + OverloadedDeref, Path, ScopeDef, Static, Struct, ToolModule, Trait, TraitAlias, TupleField, + Type, TypeAlias, TypeParam, Union, Variant, VariantDef, }; const CONTINUE_NO_BREAKS: ControlFlow = ControlFlow::Continue(()); @@ -546,11 +546,11 @@ impl<'db> SemanticsImpl<'db> { ) } - /// Retrieves all the formatting parts of the format_args! template string. + /// Retrieves all the formatting parts of the format_args! (or `asm!`) template string. pub fn as_format_args_parts( &self, string: &ast::String, - ) -> Option)>> { + ) -> Option>)>> { let quote = string.open_quote_text_range()?; let token = self.wrap_token_infile(string.syntax().clone()).into_real_file().ok()?; @@ -560,14 +560,31 @@ impl<'db> SemanticsImpl<'db> { let string = ast::String::cast(token)?; let literal = string.syntax().parent().filter(|it| it.kind() == SyntaxKind::LITERAL)?; - let format_args = ast::FormatArgsExpr::cast(literal.parent()?)?; - let source_analyzer = self.analyze_no_infer(format_args.syntax())?; - let format_args = self.wrap_node_infile(format_args); - let res = source_analyzer - .as_format_args_parts(self.db, format_args.as_ref())? - .map(|(range, res)| (range + quote.end(), res)) - .collect(); - Some(res) + let parent = literal.parent()?; + if let Some(format_args) = ast::FormatArgsExpr::cast(parent.clone()) { + let source_analyzer = self.analyze_no_infer(format_args.syntax())?; + let format_args = self.wrap_node_infile(format_args); + let res = source_analyzer + .as_format_args_parts(self.db, format_args.as_ref())? + .map(|(range, res)| (range + quote.end(), res.map(Either::Left))) + .collect(); + Some(res) + } else { + let asm = ast::AsmExpr::cast(parent)?; + let source_analyzer = self.analyze_no_infer(asm.syntax())?; + let asm = self.wrap_node_infile(asm); + let (owner, (expr, asm_parts)) = source_analyzer.as_asm_parts(asm.as_ref())?; + let res = asm_parts + .iter() + .map(|&(range, index)| { + ( + range + quote.end(), + Some(Either::Right(InlineAsmOperand { owner, expr, index })), + ) + }) + .collect(); + Some(res) + } })() .map_or(ControlFlow::Continue(()), ControlFlow::Break) }) @@ -578,7 +595,7 @@ impl<'db> SemanticsImpl<'db> { &self, original_token: SyntaxToken, offset: TextSize, - ) -> Option<(TextRange, Option)> { + ) -> Option<(TextRange, Option>)> { let original_string = ast::String::cast(original_token.clone())?; let original_token = self.wrap_token_infile(original_token).into_real_file().ok()?; let quote = original_string.open_quote_text_range()?; @@ -599,13 +616,26 @@ impl<'db> SemanticsImpl<'db> { &self, string: ast::String, offset: TextSize, - ) -> Option<(TextRange, Option)> { + ) -> Option<(TextRange, Option>)> { debug_assert!(offset <= string.syntax().text_range().len()); let literal = string.syntax().parent().filter(|it| it.kind() == SyntaxKind::LITERAL)?; - let format_args = ast::FormatArgsExpr::cast(literal.parent()?)?; - let source_analyzer = &self.analyze_no_infer(format_args.syntax())?; - let format_args = self.wrap_node_infile(format_args); - source_analyzer.resolve_offset_in_format_args(self.db, format_args.as_ref(), offset) + let parent = literal.parent()?; + if let Some(format_args) = ast::FormatArgsExpr::cast(parent.clone()) { + let source_analyzer = &self.analyze_no_infer(format_args.syntax())?; + let format_args = self.wrap_node_infile(format_args); + source_analyzer + .resolve_offset_in_format_args(self.db, format_args.as_ref(), offset) + .map(|(range, res)| (range, res.map(Either::Left))) + } else { + let asm = ast::AsmExpr::cast(parent)?; + let source_analyzer = &self.analyze_no_infer(asm.syntax())?; + let asm = self.wrap_node_infile(asm); + source_analyzer.resolve_offset_in_asm_template(asm.as_ref(), offset).map( + |(owner, (expr, range, index))| { + (range, Some(Either::Right(InlineAsmOperand { owner, expr, index }))) + }, + ) + } } /// Maps a node down by mapping its first and last token down. @@ -1781,6 +1811,7 @@ to_def_impls![ (crate::Label, ast::Label, label_to_def), (crate::Adt, ast::Adt, adt_to_def), (crate::ExternCrateDecl, ast::ExternCrate, extern_crate_to_def), + (crate::InlineAsmOperand, ast::AsmOperandNamed, asm_operand_to_def), (MacroCallId, ast::MacroCall, macro_call_to_macro_call), ]; diff --git a/src/tools/rust-analyzer/crates/hir/src/semantics/source_to_def.rs b/src/tools/rust-analyzer/crates/hir/src/semantics/source_to_def.rs index edeb19030ac00..fc629b9c6d077 100644 --- a/src/tools/rust-analyzer/crates/hir/src/semantics/source_to_def.rs +++ b/src/tools/rust-analyzer/crates/hir/src/semantics/source_to_def.rs @@ -110,7 +110,7 @@ use syntax::{ AstNode, AstPtr, SyntaxNode, }; -use crate::{db::HirDatabase, InFile}; +use crate::{db::HirDatabase, InFile, InlineAsmOperand}; #[derive(Default)] pub(super) struct SourceToDefCache { @@ -273,6 +273,25 @@ impl SourceToDefCtx<'_, '_> { ast::Adt::Union(it) => self.union_to_def(InFile::new(file_id, it)).map(AdtId::UnionId), } } + + pub(super) fn asm_operand_to_def( + &mut self, + src: InFile<&ast::AsmOperandNamed>, + ) -> Option { + let asm = src.value.syntax().parent().and_then(ast::AsmExpr::cast)?; + let index = asm + .asm_pieces() + .filter_map(|it| match it { + ast::AsmPiece::AsmOperandNamed(it) => Some(it), + _ => None, + }) + .position(|it| it == *src.value)?; + let container = self.find_pat_or_label_container(src.syntax_ref())?; + let (_, source_map) = self.db.body_with_source_map(container); + let expr = source_map.node_expr(src.with_value(&ast::Expr::AsmExpr(asm)))?; + Some(InlineAsmOperand { owner: container, expr, index }) + } + pub(super) fn bind_pat_to_def( &mut self, src: InFile<&ast::IdentPat>, diff --git a/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs b/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs index be0116862b9cf..f6f1da1b7d6bd 100644 --- a/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs +++ b/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs @@ -904,6 +904,20 @@ impl SourceAnalyzer { }) } + pub(crate) fn resolve_offset_in_asm_template( + &self, + asm: InFile<&ast::AsmExpr>, + offset: TextSize, + ) -> Option<(DefWithBodyId, (ExprId, TextRange, usize))> { + let (def, _, body_source_map) = self.def.as_ref()?; + let (expr, args) = body_source_map.asm_template_args(asm)?; + Some(*def).zip( + args.iter() + .find(|(range, _)| range.contains_inclusive(offset)) + .map(|(range, idx)| (expr, *range, *idx)), + ) + } + pub(crate) fn as_format_args_parts<'a>( &'a self, db: &'a dyn HirDatabase, @@ -927,6 +941,14 @@ impl SourceAnalyzer { )) } + pub(crate) fn as_asm_parts( + &self, + asm: InFile<&ast::AsmExpr>, + ) -> Option<(DefWithBodyId, (ExprId, &[(TextRange, usize)]))> { + let (def, _, body_source_map) = self.def.as_ref()?; + Some(*def).zip(body_source_map.asm_template_args(asm)) + } + fn resolve_impl_method_or_trait_def( &self, db: &dyn HirDatabase, diff --git a/src/tools/rust-analyzer/crates/ide-db/src/defs.rs b/src/tools/rust-analyzer/crates/ide-db/src/defs.rs index 469f83644fc5f..c134c9f672543 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/defs.rs +++ b/src/tools/rust-analyzer/crates/ide-db/src/defs.rs @@ -10,8 +10,8 @@ use either::Either; use hir::{ Adt, AsAssocItem, AsExternAssocItem, AssocItem, AttributeTemplate, BuiltinAttr, BuiltinType, Const, Crate, DefWithBody, DeriveHelper, DocLinkDef, ExternAssocItem, ExternCrateDecl, Field, - Function, GenericParam, HasVisibility, HirDisplay, Impl, Label, Local, Macro, Module, - ModuleDef, Name, PathResolution, Semantics, Static, StaticLifetime, ToolModule, Trait, + Function, GenericParam, HasVisibility, HirDisplay, Impl, InlineAsmOperand, Label, Local, Macro, + Module, ModuleDef, Name, PathResolution, Semantics, Static, StaticLifetime, ToolModule, Trait, TraitAlias, TupleField, TypeAlias, Variant, VariantDef, Visibility, }; use span::Edition; @@ -51,7 +51,7 @@ pub enum Definition { ToolModule(ToolModule), ExternCrateDecl(ExternCrateDecl), InlineAsmRegOrRegClass(()), - InlineAsmRegOperand(()), + InlineAsmOperand(InlineAsmOperand), } impl Definition { @@ -91,7 +91,7 @@ impl Definition { | Definition::TupleField(_) | Definition::ToolModule(_) | Definition::InlineAsmRegOrRegClass(_) - | Definition::InlineAsmRegOperand(_) => return None, + | Definition::InlineAsmOperand(_) => return None, }; Some(module) } @@ -127,7 +127,7 @@ impl Definition { | Definition::Label(_) | Definition::DeriveHelper(_) | Definition::InlineAsmRegOrRegClass(_) - | Definition::InlineAsmRegOperand(_) => return None, + | Definition::InlineAsmOperand(_) => return None, }; Some(vis) } @@ -156,9 +156,7 @@ impl Definition { Definition::ToolModule(_) => return None, // FIXME Definition::DeriveHelper(it) => it.name(db), Definition::ExternCrateDecl(it) => return it.alias_or_name(db), - Definition::InlineAsmRegOrRegClass(_) | Definition::InlineAsmRegOperand(_) => { - return None - } // FIXME + Definition::InlineAsmRegOrRegClass(_) | Definition::InlineAsmOperand(_) => return None, // FIXME }; Some(name) } @@ -221,7 +219,7 @@ impl Definition { Definition::ToolModule(_) => None, Definition::DeriveHelper(_) => None, Definition::TupleField(_) => None, - Definition::InlineAsmRegOrRegClass(_) | Definition::InlineAsmRegOperand(_) => None, + Definition::InlineAsmRegOrRegClass(_) | Definition::InlineAsmOperand(_) => None, }; docs.or_else(|| { @@ -280,7 +278,7 @@ impl Definition { } // FIXME Definition::InlineAsmRegOrRegClass(_) => "inline_asm_reg_or_reg_class".to_owned(), - Definition::InlineAsmRegOperand(_) => "inline_asm_reg_operand".to_owned(), + Definition::InlineAsmOperand(_) => "inline_asm_reg_operand".to_owned(), } } } @@ -442,7 +440,6 @@ impl NameClass { let _p = tracing::info_span!("NameClass::classify").entered(); let parent = name.syntax().parent()?; - let definition = match_ast! { match parent { ast::Item(it) => classify_item(sema, it)?, @@ -453,6 +450,7 @@ impl NameClass { ast::Variant(it) => Definition::Variant(sema.to_def(&it)?), ast::TypeParam(it) => Definition::GenericParam(sema.to_def(&it)?.into()), ast::ConstParam(it) => Definition::GenericParam(sema.to_def(&it)?.into()), + ast::AsmOperandNamed(it) => Definition::InlineAsmOperand(sema.to_def(&it)?), _ => return None, } }; @@ -769,6 +767,18 @@ impl From for Definition { } } +impl From for Definition { + fn from(value: InlineAsmOperand) -> Self { + Definition::InlineAsmOperand(value) + } +} + +impl From> for Definition { + fn from(value: Either) -> Self { + value.either(Definition::from, Definition::from) + } +} + impl AsAssocItem for Definition { fn as_assoc_item(self, db: &dyn hir::db::HirDatabase) -> Option { match self { diff --git a/src/tools/rust-analyzer/crates/ide-db/src/rename.rs b/src/tools/rust-analyzer/crates/ide-db/src/rename.rs index e8299a4a46347..0435b2f0c6fce 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/rename.rs +++ b/src/tools/rust-analyzer/crates/ide-db/src/rename.rs @@ -208,7 +208,7 @@ impl Definition { | Definition::TupleField(_) | Definition::InlineAsmRegOrRegClass(_) => return None, // FIXME: - Definition::InlineAsmRegOperand(_) => return None, + Definition::InlineAsmOperand(_) => return None, // FIXME: This should be doable in theory Definition::DeriveHelper(_) => return None, }; diff --git a/src/tools/rust-analyzer/crates/ide-db/src/search.rs b/src/tools/rust-analyzer/crates/ide-db/src/search.rs index 12ce5a403fe87..4d0668ffea8df 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/search.rs +++ b/src/tools/rust-analyzer/crates/ide-db/src/search.rs @@ -8,10 +8,11 @@ use std::mem; use std::{cell::LazyCell, cmp::Reverse}; use base_db::{salsa::Database, SourceDatabase, SourceRootDatabase}; +use either::Either; use hir::{ sym, Adt, AsAssocItem, DefWithBody, FileRange, FileRangeWrapper, HasAttrs, HasContainer, - HasSource, HirFileIdExt, InFile, InFileWrapper, InRealFile, ItemContainer, ModuleSource, - PathResolution, Semantics, Visibility, + HasSource, HirFileIdExt, InFile, InFileWrapper, InRealFile, InlineAsmOperand, ItemContainer, + ModuleSource, PathResolution, Semantics, Visibility, }; use memchr::memmem::Finder; use parser::SyntaxKind; @@ -917,7 +918,7 @@ impl<'a> FindUsages<'a> { for offset in Self::match_indices(&text, finder, search_range) { tree.token_at_offset(offset).for_each(|token| { let Some(str_token) = ast::String::cast(token.clone()) else { return }; - if let Some((range, nameres)) = + if let Some((range, Some(nameres))) = sema.check_for_format_args_template(token, offset) { if self.found_format_args_ref(file_id, range, str_token, nameres, sink) {} @@ -1087,19 +1088,19 @@ impl<'a> FindUsages<'a> { file_id: EditionedFileId, range: TextRange, token: ast::String, - res: Option, + res: Either, sink: &mut dyn FnMut(EditionedFileId, FileReference) -> bool, ) -> bool { - match res.map(Definition::from) { - Some(def) if def == self.def => { - let reference = FileReference { - range, - name: FileReferenceNode::FormatStringEntry(token, range), - category: ReferenceCategory::READ, - }; - sink(file_id, reference) - } - _ => false, + let def = res.either(Definition::from, Definition::from); + if def == self.def { + let reference = FileReference { + range, + name: FileReferenceNode::FormatStringEntry(token, range), + category: ReferenceCategory::READ, + }; + sink(file_id, reference) + } else { + false } } diff --git a/src/tools/rust-analyzer/crates/ide/src/doc_links.rs b/src/tools/rust-analyzer/crates/ide/src/doc_links.rs index 184486ec0a1e7..ea16a11d56d02 100644 --- a/src/tools/rust-analyzer/crates/ide/src/doc_links.rs +++ b/src/tools/rust-analyzer/crates/ide/src/doc_links.rs @@ -221,7 +221,7 @@ pub(crate) fn resolve_doc_path_for_def( | Definition::Label(_) | Definition::DeriveHelper(_) | Definition::InlineAsmRegOrRegClass(_) - | Definition::InlineAsmRegOperand(_) => None, + | Definition::InlineAsmOperand(_) => None, } .map(Definition::from) } @@ -676,7 +676,7 @@ fn filename_and_frag_for_def( | Definition::ToolModule(_) | Definition::DeriveHelper(_) | Definition::InlineAsmRegOrRegClass(_) - | Definition::InlineAsmRegOperand(_) => return None, + | Definition::InlineAsmOperand(_) => return None, }; Some((def, res, None)) diff --git a/src/tools/rust-analyzer/crates/ide/src/moniker.rs b/src/tools/rust-analyzer/crates/ide/src/moniker.rs index 1f996f716d0eb..14781b2129693 100644 --- a/src/tools/rust-analyzer/crates/ide/src/moniker.rs +++ b/src/tools/rust-analyzer/crates/ide/src/moniker.rs @@ -223,7 +223,7 @@ pub(crate) fn def_to_kind(db: &RootDatabase, def: Definition) -> SymbolInformati Variable } } - Definition::Label(..) | Definition::InlineAsmRegOperand(_) => Variable, // For lack of a better variant + Definition::Label(..) | Definition::InlineAsmOperand(_) => Variable, // For lack of a better variant Definition::DeriveHelper(..) => Attribute, Definition::BuiltinAttr(..) => Attribute, Definition::ToolModule(..) => Module, @@ -323,7 +323,7 @@ pub(crate) fn def_to_moniker( | Definition::BuiltinAttr(_) | Definition::ToolModule(_) | Definition::InlineAsmRegOrRegClass(_) - | Definition::InlineAsmRegOperand(_) => return None, + | Definition::InlineAsmOperand(_) => return None, Definition::Local(local) => { if !local.is_param(db) { diff --git a/src/tools/rust-analyzer/crates/ide/src/navigation_target.rs b/src/tools/rust-analyzer/crates/ide/src/navigation_target.rs index eb28b78e60ca5..68039ef309d3b 100644 --- a/src/tools/rust-analyzer/crates/ide/src/navigation_target.rs +++ b/src/tools/rust-analyzer/crates/ide/src/navigation_target.rs @@ -245,7 +245,7 @@ impl TryToNav for Definition { | Definition::InlineAsmRegOrRegClass(_) | Definition::BuiltinAttr(_) => None, // FIXME - Definition::InlineAsmRegOperand(_) => None, + Definition::InlineAsmOperand(_) => None, // FIXME: The focus range should be set to the helper declaration Definition::DeriveHelper(it) => it.derive().try_to_nav(db), } diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/format.rs b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/format.rs index 518e71454798f..7234108701a34 100644 --- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/format.rs +++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/format.rs @@ -19,21 +19,21 @@ pub(super) fn highlight_format_string( expanded_string: &ast::String, range: TextRange, ) { - if !is_format_string(expanded_string) { + if is_format_string(expanded_string) { + // FIXME: Replace this with the HIR info we have now. + lex_format_specifiers(string, &mut |piece_range, kind| { + if let Some(highlight) = highlight_format_specifier(kind) { + stack.add(HlRange { + range: piece_range + range.start(), + highlight: highlight.into(), + binding_hash: None, + }); + } + }); + return; } - // FIXME: Replace this with the HIR info we have now. - lex_format_specifiers(string, &mut |piece_range, kind| { - if let Some(highlight) = highlight_format_specifier(kind) { - stack.add(HlRange { - range: piece_range + range.start(), - highlight: highlight.into(), - binding_hash: None, - }); - } - }); - if let Some(parts) = sema.as_format_args_parts(string) { parts.into_iter().for_each(|(range, res)| { if let Some(res) = res { diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/highlight.rs b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/highlight.rs index fe1d0b452aede..96375937a12e8 100644 --- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/highlight.rs +++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/highlight.rs @@ -537,7 +537,7 @@ pub(super) fn highlight_def( Definition::InlineAsmRegOrRegClass(_) => { Highlight::new(HlTag::Symbol(SymbolKind::InlineAsmRegOrRegClass)) } - Definition::InlineAsmRegOperand(_) => Highlight::new(HlTag::Symbol(SymbolKind::Local)), + Definition::InlineAsmOperand(_) => Highlight::new(HlTag::Symbol(SymbolKind::Local)), }; let def_crate = def.krate(db); diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/inject.rs b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/inject.rs index bff52943afdf5..5583f1bc8df92 100644 --- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/inject.rs +++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/inject.rs @@ -316,7 +316,7 @@ fn module_def_to_hl_tag(def: Definition) -> HlTag { Definition::ToolModule(_) => SymbolKind::ToolModule, Definition::DeriveHelper(_) => SymbolKind::DeriveHelper, Definition::InlineAsmRegOrRegClass(_) => SymbolKind::InlineAsmRegOrRegClass, - Definition::InlineAsmRegOperand(_) => SymbolKind::Local, + Definition::InlineAsmOperand(_) => SymbolKind::Local, }; HlTag::Symbol(symbol) } diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_asm.html b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_asm.html index 9cedf012f7fde..d322a374b3420 100644 --- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_asm.html +++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_asm.html @@ -50,17 +50,17 @@ let foo = 1; let mut o = 0; core::arch::asm!( - "%input = OpLoad _ {0}", + "%input = OpLoad _ {0}", concat!("%result = ", "bar", " _ %input"), - "OpStore {1} %result", + "OpStore {1} %result", in(reg) &foo, in(reg) &mut o, ); let thread_id: usize; core::arch::asm!(" - mov {0}, gs:[0x30] - mov {0}, [{0}+0x48] + mov {0}, gs:[0x30] + mov {0}, [{0}+0x48] ", out(reg) thread_id, options(pure, readonly, nostack)); static UNMAP_BASE: usize; @@ -69,28 +69,28 @@ const OffPtr: usize; const OffFn: usize; core::arch::asm!(" - push {free_type} - push {free_size} - push {base} + push {free_type} + push {free_size} + push {base} mov eax, fs:[30h] mov eax, [eax+8h] - add eax, {off_fn} - mov [eax-{off_fn}+{off_ptr}], eax + add eax, {off_fn} + mov [eax-{off_fn}+{off_ptr}], eax push eax - jmp {virtual_free} + jmp {virtual_free} ", - off_ptr = const OffPtr, - off_fn = const OffFn, + off_ptr = const OffPtr, + off_fn = const OffFn, - free_size = const 0, - free_type = const MEM_RELEASE, + free_size = const 0, + free_type = const MEM_RELEASE, - virtual_free = sym VirtualFree, + virtual_free = sym VirtualFree, - base = sym UNMAP_BASE, + base = sym UNMAP_BASE, options(noreturn), ); } diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_strings.html b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_strings.html index b387808b297cd..37bbc1e1ee211 100644 --- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_strings.html +++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_strings.html @@ -166,8 +166,8 @@ let i: u64 = 3; let o: u64; core::arch::asm!( - "mov {0}, {1}", - "add {0}, 5", + "mov {0}, {1}", + "add {0}, 5", out(reg) o, in(reg) i, ); @@ -175,6 +175,6 @@ const CONSTANT: () = (): let mut m = (); format_args!(concat!("{}"), "{}"); - format_args!("{} {} {} {} {} {} {backslash} {CONSTANT} {m}", backslash, format_args!("{}", 0), foo, "bar", toho!(), backslash); - reuse_twice!("{backslash}"); + format_args!("{} {} {} {} {} {} {backslash} {CONSTANT} {m}", backslash, format_args!("{}", 0), foo, "bar", toho!(), backslash); + reuse_twice!("{backslash}"); } \ No newline at end of file diff --git a/src/tools/rust-analyzer/crates/parser/src/grammar/expressions/atom.rs b/src/tools/rust-analyzer/crates/parser/src/grammar/expressions/atom.rs index d6ccf38e7436e..39ca26fc508c4 100644 --- a/src/tools/rust-analyzer/crates/parser/src/grammar/expressions/atom.rs +++ b/src/tools/rust-analyzer/crates/parser/src/grammar/expressions/atom.rs @@ -329,11 +329,11 @@ fn parse_asm_expr(p: &mut Parser<'_>, m: Marker) -> Option { break; } - let op = p.start(); + let op_n = p.start(); // Parse clobber_abi if p.eat_contextual_kw(T![clobber_abi]) { parse_clobber_abi(p); - op.complete(p, ASM_CLOBBER_ABI); + op_n.complete(p, ASM_CLOBBER_ABI); allow_templates = false; continue; } @@ -341,7 +341,7 @@ fn parse_asm_expr(p: &mut Parser<'_>, m: Marker) -> Option { // Parse options if p.eat_contextual_kw(T![options]) { parse_options(p); - op.complete(p, ASM_OPTIONS); + op_n.complete(p, ASM_OPTIONS); allow_templates = false; continue; } @@ -356,12 +356,14 @@ fn parse_asm_expr(p: &mut Parser<'_>, m: Marker) -> Option { false }; + let op = p.start(); let dir_spec = p.start(); if p.eat(T![in]) || p.eat_contextual_kw(T![out]) || p.eat_contextual_kw(T![lateout]) { dir_spec.complete(p, ASM_DIR_SPEC); parse_reg(p); expr(p); op.complete(p, ASM_REG_OPERAND); + op_n.complete(p, ASM_OPERAND_NAMED); } else if p.eat_contextual_kw(T![inout]) || p.eat_contextual_kw(T![inlateout]) { dir_spec.complete(p, ASM_DIR_SPEC); parse_reg(p); @@ -370,21 +372,26 @@ fn parse_asm_expr(p: &mut Parser<'_>, m: Marker) -> Option { expr(p); } op.complete(p, ASM_REG_OPERAND); + op_n.complete(p, ASM_OPERAND_NAMED); } else if p.eat_contextual_kw(T![label]) { dir_spec.abandon(p); block_expr(p); - op.complete(p, ASM_LABEL); + op.complete(p, ASM_OPERAND_NAMED); + op_n.complete(p, ASM_LABEL); } else if p.eat(T![const]) { dir_spec.abandon(p); expr(p); op.complete(p, ASM_CONST); + op_n.complete(p, ASM_OPERAND_NAMED); } else if p.eat_contextual_kw(T![sym]) { dir_spec.abandon(p); paths::type_path(p); op.complete(p, ASM_SYM); + op_n.complete(p, ASM_OPERAND_NAMED); } else if allow_templates { dir_spec.abandon(p); op.abandon(p); + op_n.abandon(p); if expr(p).is_none() { p.err_and_bump("expected asm template"); } @@ -392,6 +399,7 @@ fn parse_asm_expr(p: &mut Parser<'_>, m: Marker) -> Option { } else { dir_spec.abandon(p); op.abandon(p); + op_n.abandon(p); p.err_and_bump("expected asm operand"); if p.at(T!['}']) { break; diff --git a/src/tools/rust-analyzer/crates/parser/src/syntax_kind/generated.rs b/src/tools/rust-analyzer/crates/parser/src/syntax_kind/generated.rs index ee3adac158f41..288a07ef44dc6 100644 --- a/src/tools/rust-analyzer/crates/parser/src/syntax_kind/generated.rs +++ b/src/tools/rust-analyzer/crates/parser/src/syntax_kind/generated.rs @@ -169,8 +169,10 @@ pub enum SyntaxKind { ASM_LABEL, ASM_OPERAND, ASM_OPERAND_EXPR, + ASM_OPERAND_NAMED, ASM_OPTION, ASM_OPTIONS, + ASM_PIECE, ASM_REG_OPERAND, ASM_REG_SPEC, ASM_SYM, diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/asm_expr.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/asm_expr.rast index 2360135db7cfe..4afa9daf5904b 100644 --- a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/asm_expr.rast +++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/asm_expr.rast @@ -35,43 +35,45 @@ SOURCE_FILE STRING "\"add {x}, {tmp}\"" COMMA "," WHITESPACE "\n " - ASM_REG_OPERAND + ASM_OPERAND_NAMED NAME IDENT "x" WHITESPACE " " EQ "=" WHITESPACE " " - ASM_DIR_SPEC - INOUT_KW "inout" - L_PAREN "(" - ASM_REG_SPEC - NAME_REF - IDENT "reg" - R_PAREN ")" - WHITESPACE " " - PATH_EXPR - PATH - PATH_SEGMENT - NAME_REF - IDENT "x" + ASM_REG_OPERAND + ASM_DIR_SPEC + INOUT_KW "inout" + L_PAREN "(" + ASM_REG_SPEC + NAME_REF + IDENT "reg" + R_PAREN ")" + WHITESPACE " " + PATH_EXPR + PATH + PATH_SEGMENT + NAME_REF + IDENT "x" COMMA "," WHITESPACE "\n " - ASM_REG_OPERAND + ASM_OPERAND_NAMED NAME IDENT "tmp" WHITESPACE " " EQ "=" WHITESPACE " " - ASM_DIR_SPEC - OUT_KW "out" - L_PAREN "(" - ASM_REG_SPEC - NAME_REF - IDENT "reg" - R_PAREN ")" - WHITESPACE " " - UNDERSCORE_EXPR - UNDERSCORE "_" + ASM_REG_OPERAND + ASM_DIR_SPEC + OUT_KW "out" + L_PAREN "(" + ASM_REG_SPEC + NAME_REF + IDENT "reg" + R_PAREN ")" + WHITESPACE " " + UNDERSCORE_EXPR + UNDERSCORE "_" COMMA "," WHITESPACE "\n " R_PAREN ")" diff --git a/src/tools/rust-analyzer/crates/syntax/rust.ungram b/src/tools/rust-analyzer/crates/syntax/rust.ungram index 5dace66c32d51..52ad439e4decc 100644 --- a/src/tools/rust-analyzer/crates/syntax/rust.ungram +++ b/src/tools/rust-analyzer/crates/syntax/rust.ungram @@ -395,7 +395,7 @@ OffsetOfExpr = // global_asm := "global_asm!(" format_string *("," format_string) *("," operand) [","] ")" // format_string := STRING_LITERAL / RAW_STRING_LITERAL AsmExpr = - Attr* 'builtin' '#' 'asm' '(' template:(Expr (',' Expr)*) (AsmOperand (',' AsmOperand)*)? ','? ')' + Attr* 'builtin' '#' 'asm' '(' template:(Expr (',' Expr)*) (AsmPiece (',' AsmPiece)*)? ','? ')' // operand_expr := expr / "_" / expr "=>" expr / expr "=>" "_" AsmOperandExpr = in_expr:Expr ('=>' out_expr:Expr)? @@ -404,7 +404,7 @@ AsmDirSpec = 'in' | 'out' | 'lateout' | 'inout' | 'inlateout' // reg_spec := / "\"" "\"" AsmRegSpec = '@string' | NameRef // reg_operand := [ident "="] dir_spec "(" reg_spec ")" operand_expr -AsmRegOperand = (Name '=')? AsmDirSpec '(' AsmRegSpec ')' AsmOperandExpr +AsmRegOperand = AsmDirSpec '(' AsmRegSpec ')' AsmOperandExpr // clobber_abi := "clobber_abi(" *("," ) [","] ")" AsmClobberAbi = 'clobber_abi' '(' ('@string' (',' '@string')* ','?) ')' // option := "pure" / "nomem" / "readonly" / "preserves_flags" / "noreturn" / "nostack" / "att_syntax" / "raw" @@ -415,7 +415,9 @@ AsmLabel = 'label' BlockExpr AsmSym = 'sym' Path AsmConst = 'const' Expr // operand := reg_operand / clobber_abi / options -AsmOperand = AsmRegOperand | AsmClobberAbi | AsmOptions | AsmLabel | AsmSym | AsmConst +AsmOperand = AsmRegOperand | AsmLabel | AsmSym | AsmConst +AsmOperandNamed = (Name '=')? AsmOperand +AsmPiece = AsmOperandNamed | AsmClobberAbi | AsmOptions FormatArgsExpr = Attr* 'builtin' '#' 'format_args' '(' diff --git a/src/tools/rust-analyzer/crates/syntax/src/ast/generated/nodes.rs b/src/tools/rust-analyzer/crates/syntax/src/ast/generated/nodes.rs index 01d47c34bbdf6..c81a19f3bda41 100644 --- a/src/tools/rust-analyzer/crates/syntax/src/ast/generated/nodes.rs +++ b/src/tools/rust-analyzer/crates/syntax/src/ast/generated/nodes.rs @@ -118,7 +118,7 @@ pub struct AsmExpr { impl ast::HasAttrs for AsmExpr {} impl AsmExpr { #[inline] - pub fn asm_operands(&self) -> AstChildren { support::children(&self.syntax) } + pub fn asm_pieces(&self) -> AstChildren { support::children(&self.syntax) } #[inline] pub fn template(&self) -> AstChildren { support::children(&self.syntax) } #[inline] @@ -159,6 +159,18 @@ impl AsmOperandExpr { pub fn fat_arrow_token(&self) -> Option { support::token(&self.syntax, T![=>]) } } +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct AsmOperandNamed { + pub(crate) syntax: SyntaxNode, +} +impl ast::HasName for AsmOperandNamed {} +impl AsmOperandNamed { + #[inline] + pub fn asm_operand(&self) -> Option { support::child(&self.syntax) } + #[inline] + pub fn eq_token(&self) -> Option { support::token(&self.syntax, T![=]) } +} + #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct AsmOption { pub(crate) syntax: SyntaxNode, @@ -217,7 +229,6 @@ impl AsmOptions { pub struct AsmRegOperand { pub(crate) syntax: SyntaxNode, } -impl ast::HasName for AsmRegOperand {} impl AsmRegOperand { #[inline] pub fn asm_dir_spec(&self) -> Option { support::child(&self.syntax) } @@ -229,8 +240,6 @@ impl AsmRegOperand { pub fn l_paren_token(&self) -> Option { support::token(&self.syntax, T!['(']) } #[inline] pub fn r_paren_token(&self) -> Option { support::token(&self.syntax, T![')']) } - #[inline] - pub fn eq_token(&self) -> Option { support::token(&self.syntax, T![=]) } } #[derive(Debug, Clone, PartialEq, Eq, Hash)] @@ -2224,14 +2233,19 @@ impl ast::HasVisibility for Adt {} #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub enum AsmOperand { - AsmClobberAbi(AsmClobberAbi), AsmConst(AsmConst), AsmLabel(AsmLabel), - AsmOptions(AsmOptions), AsmRegOperand(AsmRegOperand), AsmSym(AsmSym), } +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub enum AsmPiece { + AsmClobberAbi(AsmClobberAbi), + AsmOperandNamed(AsmOperandNamed), + AsmOptions(AsmOptions), +} + #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub enum AssocItem { Const(Const), @@ -2581,6 +2595,20 @@ impl AstNode for AsmOperandExpr { #[inline] fn syntax(&self) -> &SyntaxNode { &self.syntax } } +impl AstNode for AsmOperandNamed { + #[inline] + fn can_cast(kind: SyntaxKind) -> bool { kind == ASM_OPERAND_NAMED } + #[inline] + fn cast(syntax: SyntaxNode) -> Option { + if Self::can_cast(syntax.kind()) { + Some(Self { syntax }) + } else { + None + } + } + #[inline] + fn syntax(&self) -> &SyntaxNode { &self.syntax } +} impl AstNode for AsmOption { #[inline] fn can_cast(kind: SyntaxKind) -> bool { kind == ASM_OPTION } @@ -4589,10 +4617,6 @@ impl AstNode for Adt { } } } -impl From for AsmOperand { - #[inline] - fn from(node: AsmClobberAbi) -> AsmOperand { AsmOperand::AsmClobberAbi(node) } -} impl From for AsmOperand { #[inline] fn from(node: AsmConst) -> AsmOperand { AsmOperand::AsmConst(node) } @@ -4601,10 +4625,6 @@ impl From for AsmOperand { #[inline] fn from(node: AsmLabel) -> AsmOperand { AsmOperand::AsmLabel(node) } } -impl From for AsmOperand { - #[inline] - fn from(node: AsmOptions) -> AsmOperand { AsmOperand::AsmOptions(node) } -} impl From for AsmOperand { #[inline] fn from(node: AsmRegOperand) -> AsmOperand { AsmOperand::AsmRegOperand(node) } @@ -4616,18 +4636,13 @@ impl From for AsmOperand { impl AstNode for AsmOperand { #[inline] fn can_cast(kind: SyntaxKind) -> bool { - matches!( - kind, - ASM_CLOBBER_ABI | ASM_CONST | ASM_LABEL | ASM_OPTIONS | ASM_REG_OPERAND | ASM_SYM - ) + matches!(kind, ASM_CONST | ASM_LABEL | ASM_REG_OPERAND | ASM_SYM) } #[inline] fn cast(syntax: SyntaxNode) -> Option { let res = match syntax.kind() { - ASM_CLOBBER_ABI => AsmOperand::AsmClobberAbi(AsmClobberAbi { syntax }), ASM_CONST => AsmOperand::AsmConst(AsmConst { syntax }), ASM_LABEL => AsmOperand::AsmLabel(AsmLabel { syntax }), - ASM_OPTIONS => AsmOperand::AsmOptions(AsmOptions { syntax }), ASM_REG_OPERAND => AsmOperand::AsmRegOperand(AsmRegOperand { syntax }), ASM_SYM => AsmOperand::AsmSym(AsmSym { syntax }), _ => return None, @@ -4637,15 +4652,49 @@ impl AstNode for AsmOperand { #[inline] fn syntax(&self) -> &SyntaxNode { match self { - AsmOperand::AsmClobberAbi(it) => &it.syntax, AsmOperand::AsmConst(it) => &it.syntax, AsmOperand::AsmLabel(it) => &it.syntax, - AsmOperand::AsmOptions(it) => &it.syntax, AsmOperand::AsmRegOperand(it) => &it.syntax, AsmOperand::AsmSym(it) => &it.syntax, } } } +impl From for AsmPiece { + #[inline] + fn from(node: AsmClobberAbi) -> AsmPiece { AsmPiece::AsmClobberAbi(node) } +} +impl From for AsmPiece { + #[inline] + fn from(node: AsmOperandNamed) -> AsmPiece { AsmPiece::AsmOperandNamed(node) } +} +impl From for AsmPiece { + #[inline] + fn from(node: AsmOptions) -> AsmPiece { AsmPiece::AsmOptions(node) } +} +impl AstNode for AsmPiece { + #[inline] + fn can_cast(kind: SyntaxKind) -> bool { + matches!(kind, ASM_CLOBBER_ABI | ASM_OPERAND_NAMED | ASM_OPTIONS) + } + #[inline] + fn cast(syntax: SyntaxNode) -> Option { + let res = match syntax.kind() { + ASM_CLOBBER_ABI => AsmPiece::AsmClobberAbi(AsmClobberAbi { syntax }), + ASM_OPERAND_NAMED => AsmPiece::AsmOperandNamed(AsmOperandNamed { syntax }), + ASM_OPTIONS => AsmPiece::AsmOptions(AsmOptions { syntax }), + _ => return None, + }; + Some(res) + } + #[inline] + fn syntax(&self) -> &SyntaxNode { + match self { + AsmPiece::AsmClobberAbi(it) => &it.syntax, + AsmPiece::AsmOperandNamed(it) => &it.syntax, + AsmPiece::AsmOptions(it) => &it.syntax, + } + } +} impl From for AssocItem { #[inline] fn from(node: Const) -> AssocItem { AssocItem::Const(node) } @@ -6181,7 +6230,7 @@ impl AstNode for AnyHasName { fn can_cast(kind: SyntaxKind) -> bool { matches!( kind, - ASM_REG_OPERAND + ASM_OPERAND_NAMED | CONST | CONST_PARAM | ENUM @@ -6211,9 +6260,9 @@ impl AstNode for AnyHasName { #[inline] fn syntax(&self) -> &SyntaxNode { &self.syntax } } -impl From for AnyHasName { +impl From for AnyHasName { #[inline] - fn from(node: AsmRegOperand) -> AnyHasName { AnyHasName { syntax: node.syntax } } + fn from(node: AsmOperandNamed) -> AnyHasName { AnyHasName { syntax: node.syntax } } } impl From for AnyHasName { #[inline] @@ -6460,6 +6509,11 @@ impl std::fmt::Display for AsmOperand { std::fmt::Display::fmt(self.syntax(), f) } } +impl std::fmt::Display for AsmPiece { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} impl std::fmt::Display for AssocItem { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { std::fmt::Display::fmt(self.syntax(), f) @@ -6560,6 +6614,11 @@ impl std::fmt::Display for AsmOperandExpr { std::fmt::Display::fmt(self.syntax(), f) } } +impl std::fmt::Display for AsmOperandNamed { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} impl std::fmt::Display for AsmOption { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { std::fmt::Display::fmt(self.syntax(), f) From bdb734b63ad83b0e96520daa7ce70137b442ecd0 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Thu, 5 Sep 2024 13:19:02 +0200 Subject: [PATCH 0535/2194] Support more IDE features for asm operands --- .../rust-analyzer/crates/hir-def/src/body.rs | 13 ++++- .../crates/hir-def/src/body/lower/asm.rs | 14 ++++-- .../crates/hir/src/has_source.rs | 27 ++++++++++- src/tools/rust-analyzer/crates/hir/src/lib.rs | 16 +++++++ .../rust-analyzer/crates/hir/src/semantics.rs | 2 +- .../crates/hir/src/source_analyzer.rs | 6 +-- .../rust-analyzer/crates/ide-db/src/defs.rs | 7 +-- .../rust-analyzer/crates/ide-db/src/rename.rs | 3 +- .../rust-analyzer/crates/ide-db/src/search.rs | 18 ++++++- .../crates/ide/src/navigation_target.rs | 30 ++++++++++-- .../rust-analyzer/crates/ide/src/rename.rs | 48 +++++++++++++++++++ .../test_data/highlight_asm.html | 32 ++++++------- .../test_data/highlight_strings.html | 4 +- 13 files changed, 180 insertions(+), 40 deletions(-) diff --git a/src/tools/rust-analyzer/crates/hir-def/src/body.rs b/src/tools/rust-analyzer/crates/hir-def/src/body.rs index 03507189fb99a..af972c92469ca 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/body.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/body.rs @@ -105,7 +105,7 @@ pub struct BodySourceMap { // format_args! FxHashMap>, // asm! - FxHashMap>, + FxHashMap)>>, )>, >, @@ -439,7 +439,7 @@ impl BodySourceMap { pub fn asm_template_args( &self, node: InFile<&ast::AsmExpr>, - ) -> Option<(ExprId, &[(syntax::TextRange, usize)])> { + ) -> Option<(ExprId, &[(syntax::TextRange, usize, Option)])> { let src = node.map(AstPtr::new).map(AstPtr::upcast::); let expr = self.expr_map.get(&src)?; Some(*expr).zip(self.template_map.as_ref()?.1.get(expr).map(std::ops::Deref::deref)) @@ -482,4 +482,13 @@ impl BodySourceMap { diagnostics.shrink_to_fit(); binding_definitions.shrink_to_fit(); } + + pub fn template_map( + &self, + ) -> Option<&( + FxHashMap, Vec<(tt::TextRange, Name)>>, + FxHashMap, Vec<(tt::TextRange, usize, Option)>>, + )> { + self.template_map.as_deref() + } } diff --git a/src/tools/rust-analyzer/crates/hir-def/src/body/lower/asm.rs b/src/tools/rust-analyzer/crates/hir-def/src/body/lower/asm.rs index 59b348b77db00..8d2c0b3926f99 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/body/lower/asm.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/body/lower/asm.rs @@ -1,3 +1,4 @@ +use hir_expand::name::Name; use intern::Symbol; use rustc_hash::{FxHashMap, FxHashSet}; use syntax::{ @@ -202,27 +203,30 @@ impl ExprCollector<'_> { rustc_parse_format::Piece::NextArgument(arg) => { // let span = arg_spans.next(); - let operand_idx = match arg.position { + let (operand_idx, name) = match arg.position { rustc_parse_format::ArgumentIs(idx) | rustc_parse_format::ArgumentImplicitlyIs(idx) => { if idx >= operands.len() || named_pos.contains_key(&idx) || reg_args.contains(&idx) { - None + (None, None) } else { - Some(idx) + (Some(idx), None) } } rustc_parse_format::ArgumentNamed(name) => { let name = Symbol::intern(name); - named_args.get(&name).copied() + ( + named_args.get(&name).copied(), + Some(Name::new_symbol_root(name)), + ) } }; if let Some(operand_idx) = operand_idx { if let Some(position_span) = to_span(arg.position_span) { - mappings.push((position_span, operand_idx)); + mappings.push((position_span, operand_idx, name)); } } } diff --git a/src/tools/rust-analyzer/crates/hir/src/has_source.rs b/src/tools/rust-analyzer/crates/hir/src/has_source.rs index 7d52a28b91e91..82c90ac30101b 100644 --- a/src/tools/rust-analyzer/crates/hir/src/has_source.rs +++ b/src/tools/rust-analyzer/crates/hir/src/has_source.rs @@ -14,8 +14,8 @@ use tt::TextRange; use crate::{ db::HirDatabase, Adt, Callee, Const, Enum, ExternCrateDecl, Field, FieldSource, Function, Impl, - Label, LifetimeParam, LocalSource, Macro, Module, Param, SelfParam, Static, Struct, Trait, - TraitAlias, TypeAlias, TypeOrConstParam, Union, Variant, + InlineAsmOperand, Label, LifetimeParam, LocalSource, Macro, Module, Param, SelfParam, Static, + Struct, Trait, TraitAlias, TypeAlias, TypeOrConstParam, Union, Variant, }; pub trait HasSource { @@ -292,3 +292,26 @@ impl HasSource for ExternCrateDecl { Some(self.id.lookup(db.upcast()).source(db.upcast())) } } + +impl HasSource for InlineAsmOperand { + type Ast = ast::AsmOperandNamed; + fn source(self, db: &dyn HirDatabase) -> Option> { + let (_body, source_map) = db.body_with_source_map(self.owner); + if let Ok(src) = source_map.expr_syntax(self.expr) { + let root = src.file_syntax(db.upcast()); + return src + .map(|ast| match ast.to_node(&root) { + ast::Expr::AsmExpr(asm) => asm + .asm_pieces() + .filter_map(|it| match it { + ast::AsmPiece::AsmOperandNamed(it) => Some(it), + _ => None, + }) + .nth(self.index), + _ => None, + }) + .transpose(); + } + None + } +} diff --git a/src/tools/rust-analyzer/crates/hir/src/lib.rs b/src/tools/rust-analyzer/crates/hir/src/lib.rs index c8b227123f1c1..75969bd89940e 100644 --- a/src/tools/rust-analyzer/crates/hir/src/lib.rs +++ b/src/tools/rust-analyzer/crates/hir/src/lib.rs @@ -5253,6 +5253,22 @@ pub struct InlineAsmOperand { index: usize, } +impl InlineAsmOperand { + pub fn parent(self, _db: &dyn HirDatabase) -> DefWithBody { + self.owner.into() + } + + pub fn name(&self, db: &dyn HirDatabase) -> Option { + db.body_with_source_map(self.owner) + .1 + .template_map()? + .1 + .get(&self.expr)? + .get(self.index) + .and_then(|(_, _, name)| name.clone()) + } +} + // FIXME: Document this #[derive(Debug)] pub struct Callable { diff --git a/src/tools/rust-analyzer/crates/hir/src/semantics.rs b/src/tools/rust-analyzer/crates/hir/src/semantics.rs index 0ba0e446578e7..543f2fc089fb5 100644 --- a/src/tools/rust-analyzer/crates/hir/src/semantics.rs +++ b/src/tools/rust-analyzer/crates/hir/src/semantics.rs @@ -576,7 +576,7 @@ impl<'db> SemanticsImpl<'db> { let (owner, (expr, asm_parts)) = source_analyzer.as_asm_parts(asm.as_ref())?; let res = asm_parts .iter() - .map(|&(range, index)| { + .map(|&(range, index, _)| { ( range + quote.end(), Some(Either::Right(InlineAsmOperand { owner, expr, index })), diff --git a/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs b/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs index f6f1da1b7d6bd..4baf9079a055e 100644 --- a/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs +++ b/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs @@ -913,8 +913,8 @@ impl SourceAnalyzer { let (expr, args) = body_source_map.asm_template_args(asm)?; Some(*def).zip( args.iter() - .find(|(range, _)| range.contains_inclusive(offset)) - .map(|(range, idx)| (expr, *range, *idx)), + .find(|(range, _, _)| range.contains_inclusive(offset)) + .map(|(range, idx, _)| (expr, *range, *idx)), ) } @@ -944,7 +944,7 @@ impl SourceAnalyzer { pub(crate) fn as_asm_parts( &self, asm: InFile<&ast::AsmExpr>, - ) -> Option<(DefWithBodyId, (ExprId, &[(TextRange, usize)]))> { + ) -> Option<(DefWithBodyId, (ExprId, &[(TextRange, usize, Option)]))> { let (def, _, body_source_map) = self.def.as_ref()?; Some(*def).zip(body_source_map.asm_template_args(asm)) } diff --git a/src/tools/rust-analyzer/crates/ide-db/src/defs.rs b/src/tools/rust-analyzer/crates/ide-db/src/defs.rs index c134c9f672543..099f26eba78a9 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/defs.rs +++ b/src/tools/rust-analyzer/crates/ide-db/src/defs.rs @@ -85,13 +85,13 @@ impl Definition { Definition::Label(it) => it.module(db), Definition::ExternCrateDecl(it) => it.module(db), Definition::DeriveHelper(it) => it.derive().module(db), + Definition::InlineAsmOperand(it) => it.parent(db).module(db), Definition::BuiltinAttr(_) | Definition::BuiltinType(_) | Definition::BuiltinLifetime(_) | Definition::TupleField(_) | Definition::ToolModule(_) - | Definition::InlineAsmRegOrRegClass(_) - | Definition::InlineAsmOperand(_) => return None, + | Definition::InlineAsmRegOrRegClass(_) => return None, }; Some(module) } @@ -156,7 +156,8 @@ impl Definition { Definition::ToolModule(_) => return None, // FIXME Definition::DeriveHelper(it) => it.name(db), Definition::ExternCrateDecl(it) => return it.alias_or_name(db), - Definition::InlineAsmRegOrRegClass(_) | Definition::InlineAsmOperand(_) => return None, // FIXME + Definition::InlineAsmRegOrRegClass(_) => return None, + Definition::InlineAsmOperand(op) => return op.name(db), }; Some(name) } diff --git a/src/tools/rust-analyzer/crates/ide-db/src/rename.rs b/src/tools/rust-analyzer/crates/ide-db/src/rename.rs index 0435b2f0c6fce..f1404ed9f22cd 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/rename.rs +++ b/src/tools/rust-analyzer/crates/ide-db/src/rename.rs @@ -200,6 +200,7 @@ impl Definition { .and_then(syn_ctx_is_root) } } + Definition::InlineAsmOperand(it) => name_range(it, sema).and_then(syn_ctx_is_root), Definition::BuiltinType(_) | Definition::BuiltinLifetime(_) | Definition::BuiltinAttr(_) @@ -207,8 +208,6 @@ impl Definition { | Definition::ToolModule(_) | Definition::TupleField(_) | Definition::InlineAsmRegOrRegClass(_) => return None, - // FIXME: - Definition::InlineAsmOperand(_) => return None, // FIXME: This should be doable in theory Definition::DeriveHelper(_) => return None, }; diff --git a/src/tools/rust-analyzer/crates/ide-db/src/search.rs b/src/tools/rust-analyzer/crates/ide-db/src/search.rs index 4d0668ffea8df..ad30c624c417e 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/search.rs +++ b/src/tools/rust-analyzer/crates/ide-db/src/search.rs @@ -319,6 +319,23 @@ impl Definition { }; } + if let Definition::InlineAsmOperand(op) = self { + let def = match op.parent(db) { + DefWithBody::Function(f) => f.source(db).map(|src| src.syntax().cloned()), + DefWithBody::Const(c) => c.source(db).map(|src| src.syntax().cloned()), + DefWithBody::Static(s) => s.source(db).map(|src| src.syntax().cloned()), + DefWithBody::Variant(v) => v.source(db).map(|src| src.syntax().cloned()), + // FIXME: implement + DefWithBody::InTypeConst(_) => return SearchScope::empty(), + }; + return match def { + Some(def) => SearchScope::file_range( + def.as_ref().original_file_range_with_macro_call_body(db), + ), + None => SearchScope::single_file(file_id), + }; + } + if let Definition::SelfType(impl_) = self { return match impl_.source(db).map(|src| src.syntax().cloned()) { Some(def) => SearchScope::file_range( @@ -909,7 +926,6 @@ impl<'a> FindUsages<'a> { let finder = &Finder::new(name); let include_self_kw_refs = self.include_self_kw_refs.as_ref().map(|ty| (ty, Finder::new("Self"))); - for (text, file_id, search_range) in Self::scope_files(sema.db, &search_scope) { self.sema.db.unwind_if_cancelled(); let tree = LazyCell::new(move || sema.parse(file_id).syntax().clone()); diff --git a/src/tools/rust-analyzer/crates/ide/src/navigation_target.rs b/src/tools/rust-analyzer/crates/ide/src/navigation_target.rs index 68039ef309d3b..9bc7bf411f05e 100644 --- a/src/tools/rust-analyzer/crates/ide/src/navigation_target.rs +++ b/src/tools/rust-analyzer/crates/ide/src/navigation_target.rs @@ -237,15 +237,14 @@ impl TryToNav for Definition { Definition::Trait(it) => it.try_to_nav(db), Definition::TraitAlias(it) => it.try_to_nav(db), Definition::TypeAlias(it) => it.try_to_nav(db), - Definition::ExternCrateDecl(it) => Some(it.try_to_nav(db)?), + Definition::ExternCrateDecl(it) => it.try_to_nav(db), + Definition::InlineAsmOperand(it) => it.try_to_nav(db), Definition::BuiltinLifetime(_) | Definition::BuiltinType(_) | Definition::TupleField(_) | Definition::ToolModule(_) | Definition::InlineAsmRegOrRegClass(_) | Definition::BuiltinAttr(_) => None, - // FIXME - Definition::InlineAsmOperand(_) => None, // FIXME: The focus range should be set to the helper declaration Definition::DeriveHelper(it) => it.derive().try_to_nav(db), } @@ -696,6 +695,31 @@ impl TryToNav for hir::ConstParam { } } +impl TryToNav for hir::InlineAsmOperand { + fn try_to_nav(&self, db: &RootDatabase) -> Option> { + let InFile { file_id, value } = &self.source(db)?; + let file_id = *file_id; + Some(orig_range_with_focus(db, file_id, value.syntax(), value.name()).map( + |(FileRange { file_id, range: full_range }, focus_range)| { + let edition = self.parent(db).module(db).krate().edition(db); + NavigationTarget { + file_id, + name: self + .name(db) + .map_or_else(|| "_".into(), |it| it.display(db, edition).to_smolstr()), + alias: None, + kind: Some(SymbolKind::Local), + full_range, + focus_range, + container_name: None, + description: None, + docs: None, + } + }, + )) + } +} + #[derive(Debug)] pub struct UpmappingResult { /// The macro call site. diff --git a/src/tools/rust-analyzer/crates/ide/src/rename.rs b/src/tools/rust-analyzer/crates/ide/src/rename.rs index 42b7472c645f3..9b9344e98cd73 100644 --- a/src/tools/rust-analyzer/crates/ide/src/rename.rs +++ b/src/tools/rust-analyzer/crates/ide/src/rename.rs @@ -2975,6 +2975,54 @@ fn test() { ); } + #[test] + fn asm_operand() { + check( + "bose", + r#" +//- minicore: asm +fn test() { + core::arch::asm!( + "push {base}", + base$0 = const 0 + ); +} +"#, + r#" +fn test() { + core::arch::asm!( + "push {bose}", + bose = const 0 + ); +} +"#, + ); + } + + #[test] + fn asm_operand2() { + check( + "bose", + r#" +//- minicore: asm +fn test() { + core::arch::asm!( + "push {base$0}", + base = const 0 + ); +} +"#, + r#" +fn test() { + core::arch::asm!( + "push {bose}", + bose = const 0 + ); +} +"#, + ); + } + #[test] fn rename_path_inside_use_tree() { check( diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_asm.html b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_asm.html index d322a374b3420..d830a3887217b 100644 --- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_asm.html +++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_asm.html @@ -50,17 +50,17 @@ let foo = 1; let mut o = 0; core::arch::asm!( - "%input = OpLoad _ {0}", + "%input = OpLoad _ {0}", concat!("%result = ", "bar", " _ %input"), - "OpStore {1} %result", + "OpStore {1} %result", in(reg) &foo, in(reg) &mut o, ); let thread_id: usize; core::arch::asm!(" - mov {0}, gs:[0x30] - mov {0}, [{0}+0x48] + mov {0}, gs:[0x30] + mov {0}, [{0}+0x48] ", out(reg) thread_id, options(pure, readonly, nostack)); static UNMAP_BASE: usize; @@ -69,28 +69,28 @@ const OffPtr: usize; const OffFn: usize; core::arch::asm!(" - push {free_type} - push {free_size} - push {base} + push {free_type} + push {free_size} + push {base} mov eax, fs:[30h] mov eax, [eax+8h] - add eax, {off_fn} - mov [eax-{off_fn}+{off_ptr}], eax + add eax, {off_fn} + mov [eax-{off_fn}+{off_ptr}], eax push eax - jmp {virtual_free} + jmp {virtual_free} ", - off_ptr = const OffPtr, - off_fn = const OffFn, + off_ptr = const OffPtr, + off_fn = const OffFn, - free_size = const 0, - free_type = const MEM_RELEASE, + free_size = const 0, + free_type = const MEM_RELEASE, - virtual_free = sym VirtualFree, + virtual_free = sym VirtualFree, - base = sym UNMAP_BASE, + base = sym UNMAP_BASE, options(noreturn), ); } diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_strings.html b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_strings.html index 37bbc1e1ee211..d5b9fc0e2c421 100644 --- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_strings.html +++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_strings.html @@ -166,8 +166,8 @@ let i: u64 = 3; let o: u64; core::arch::asm!( - "mov {0}, {1}", - "add {0}, 5", + "mov {0}, {1}", + "add {0}, 5", out(reg) o, in(reg) i, ); From 2120b38adf4f2ee294460321bda4709eaa2509da Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Thu, 5 Sep 2024 13:19:32 +0200 Subject: [PATCH 0536/2194] Add missing doc comments --- src/tools/rust-analyzer/crates/hir-def/src/body/lower/asm.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/tools/rust-analyzer/crates/hir-def/src/body/lower/asm.rs b/src/tools/rust-analyzer/crates/hir-def/src/body/lower/asm.rs index 8d2c0b3926f99..300935db49676 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/body/lower/asm.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/body/lower/asm.rs @@ -1,3 +1,4 @@ +//! Lowering of inline assembly. use hir_expand::name::Name; use intern::Symbol; use rustc_hash::{FxHashMap, FxHashSet}; From 72980c417cb59c33d5814fd69eb958fb90363f26 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Thu, 5 Sep 2024 13:41:03 +0200 Subject: [PATCH 0537/2194] Fix name fetching being incorrect for asm operands --- .../rust-analyzer/crates/hir-def/src/body.rs | 6 +- .../crates/hir-def/src/body/lower/asm.rs | 153 +++++++++--------- .../rust-analyzer/crates/hir-def/src/hir.rs | 4 +- .../crates/hir-ty/src/infer/closure.rs | 2 +- .../crates/hir-ty/src/infer/expr.rs | 2 +- .../crates/hir-ty/src/infer/mutability.rs | 2 +- src/tools/rust-analyzer/crates/hir/src/lib.rs | 11 +- .../rust-analyzer/crates/hir/src/semantics.rs | 2 +- .../crates/hir/src/source_analyzer.rs | 6 +- .../rust-analyzer/crates/ide/src/rename.rs | 12 +- 10 files changed, 107 insertions(+), 93 deletions(-) diff --git a/src/tools/rust-analyzer/crates/hir-def/src/body.rs b/src/tools/rust-analyzer/crates/hir-def/src/body.rs index af972c92469ca..34db43939a7ca 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/body.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/body.rs @@ -105,7 +105,7 @@ pub struct BodySourceMap { // format_args! FxHashMap>, // asm! - FxHashMap)>>, + FxHashMap>, )>, >, @@ -439,7 +439,7 @@ impl BodySourceMap { pub fn asm_template_args( &self, node: InFile<&ast::AsmExpr>, - ) -> Option<(ExprId, &[(syntax::TextRange, usize, Option)])> { + ) -> Option<(ExprId, &[(syntax::TextRange, usize)])> { let src = node.map(AstPtr::new).map(AstPtr::upcast::); let expr = self.expr_map.get(&src)?; Some(*expr).zip(self.template_map.as_ref()?.1.get(expr).map(std::ops::Deref::deref)) @@ -487,7 +487,7 @@ impl BodySourceMap { &self, ) -> Option<&( FxHashMap, Vec<(tt::TextRange, Name)>>, - FxHashMap, Vec<(tt::TextRange, usize, Option)>>, + FxHashMap, Vec<(tt::TextRange, usize)>>, )> { self.template_map.as_deref() } diff --git a/src/tools/rust-analyzer/crates/hir-def/src/body/lower/asm.rs b/src/tools/rust-analyzer/crates/hir-def/src/body/lower/asm.rs index 300935db49676..bf6ba41482c47 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/body/lower/asm.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/body/lower/asm.rs @@ -65,80 +65,89 @@ impl ExprCollector<'_> { continue; } ast::AsmPiece::AsmOperandNamed(op) => { - if let Some(name) = op.name() { - let sym = Symbol::intern(&name.text()); - named_args.insert(sym.clone(), slot); - named_pos.insert(slot, sym); + let name = op.name().map(|name| Symbol::intern(&name.text())); + if let Some(name) = &name { + named_args.insert(name.clone(), slot); + named_pos.insert(slot, name.clone()); } let Some(op) = op.asm_operand() else { continue }; - match op { - ast::AsmOperand::AsmRegOperand(op) => { - let Some(dir_spec) = op.asm_dir_spec() else { - continue; - }; - let Some(reg) = lower_reg(op.asm_reg_spec()) else { - continue; - }; - if dir_spec.in_token().is_some() { - let expr = self.collect_expr_opt( - op.asm_operand_expr().and_then(|it| it.in_expr()), - ); - AsmOperand::In { reg, expr } - } else if dir_spec.out_token().is_some() { - let expr = self.collect_expr_opt( - op.asm_operand_expr().and_then(|it| it.in_expr()), - ); - AsmOperand::Out { reg, expr: Some(expr), late: false } - } else if dir_spec.lateout_token().is_some() { - let expr = self.collect_expr_opt( - op.asm_operand_expr().and_then(|it| it.in_expr()), - ); - AsmOperand::Out { reg, expr: Some(expr), late: true } - } else if dir_spec.inout_token().is_some() { - let Some(op_expr) = op.asm_operand_expr() else { continue }; - let in_expr = self.collect_expr_opt(op_expr.in_expr()); - let out_expr = op_expr.out_expr().map(|it| self.collect_expr(it)); - match out_expr { - Some(out_expr) => AsmOperand::SplitInOut { - reg, - in_expr, - out_expr: Some(out_expr), - late: false, - }, - None => AsmOperand::InOut { reg, expr: in_expr, late: false }, - } - } else if dir_spec.inlateout_token().is_some() { - let Some(op_expr) = op.asm_operand_expr() else { continue }; - let in_expr = self.collect_expr_opt(op_expr.in_expr()); - let out_expr = op_expr.out_expr().map(|it| self.collect_expr(it)); - match out_expr { - Some(out_expr) => AsmOperand::SplitInOut { - reg, - in_expr, - out_expr: Some(out_expr), - late: false, - }, - None => AsmOperand::InOut { reg, expr: in_expr, late: false }, + ( + name.map(Name::new_symbol_root), + match op { + ast::AsmOperand::AsmRegOperand(op) => { + let Some(dir_spec) = op.asm_dir_spec() else { + continue; + }; + let Some(reg) = lower_reg(op.asm_reg_spec()) else { + continue; + }; + if dir_spec.in_token().is_some() { + let expr = self.collect_expr_opt( + op.asm_operand_expr().and_then(|it| it.in_expr()), + ); + AsmOperand::In { reg, expr } + } else if dir_spec.out_token().is_some() { + let expr = self.collect_expr_opt( + op.asm_operand_expr().and_then(|it| it.in_expr()), + ); + AsmOperand::Out { reg, expr: Some(expr), late: false } + } else if dir_spec.lateout_token().is_some() { + let expr = self.collect_expr_opt( + op.asm_operand_expr().and_then(|it| it.in_expr()), + ); + AsmOperand::Out { reg, expr: Some(expr), late: true } + } else if dir_spec.inout_token().is_some() { + let Some(op_expr) = op.asm_operand_expr() else { continue }; + let in_expr = self.collect_expr_opt(op_expr.in_expr()); + let out_expr = + op_expr.out_expr().map(|it| self.collect_expr(it)); + match out_expr { + Some(out_expr) => AsmOperand::SplitInOut { + reg, + in_expr, + out_expr: Some(out_expr), + late: false, + }, + None => { + AsmOperand::InOut { reg, expr: in_expr, late: false } + } + } + } else if dir_spec.inlateout_token().is_some() { + let Some(op_expr) = op.asm_operand_expr() else { continue }; + let in_expr = self.collect_expr_opt(op_expr.in_expr()); + let out_expr = + op_expr.out_expr().map(|it| self.collect_expr(it)); + match out_expr { + Some(out_expr) => AsmOperand::SplitInOut { + reg, + in_expr, + out_expr: Some(out_expr), + late: false, + }, + None => { + AsmOperand::InOut { reg, expr: in_expr, late: false } + } + } + } else { + continue; } - } else { - continue; } - } - ast::AsmOperand::AsmLabel(l) => { - AsmOperand::Label(self.collect_block_opt(l.block_expr())) - } - ast::AsmOperand::AsmConst(c) => { - AsmOperand::Const(self.collect_expr_opt(c.expr())) - } - ast::AsmOperand::AsmSym(s) => { - let Some(path) = - s.path().and_then(|p| self.expander.parse_path(self.db, p)) - else { - continue; - }; - AsmOperand::Sym(path) - } - } + ast::AsmOperand::AsmLabel(l) => { + AsmOperand::Label(self.collect_block_opt(l.block_expr())) + } + ast::AsmOperand::AsmConst(c) => { + AsmOperand::Const(self.collect_expr_opt(c.expr())) + } + ast::AsmOperand::AsmSym(s) => { + let Some(path) = + s.path().and_then(|p| self.expander.parse_path(self.db, p)) + else { + continue; + }; + AsmOperand::Sym(path) + } + }, + ) } }; operands.push(op); @@ -204,7 +213,7 @@ impl ExprCollector<'_> { rustc_parse_format::Piece::NextArgument(arg) => { // let span = arg_spans.next(); - let (operand_idx, name) = match arg.position { + let (operand_idx, _name) = match arg.position { rustc_parse_format::ArgumentIs(idx) | rustc_parse_format::ArgumentImplicitlyIs(idx) => { if idx >= operands.len() @@ -227,7 +236,7 @@ impl ExprCollector<'_> { if let Some(operand_idx) = operand_idx { if let Some(position_span) = to_span(arg.position_span) { - mappings.push((position_span, operand_idx, name)); + mappings.push((position_span, operand_idx)); } } } diff --git a/src/tools/rust-analyzer/crates/hir-def/src/hir.rs b/src/tools/rust-analyzer/crates/hir-def/src/hir.rs index 7d2c573ebfed4..d9358a28822e7 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/hir.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/hir.rs @@ -307,7 +307,7 @@ pub struct OffsetOf { #[derive(Debug, Clone, PartialEq, Eq)] pub struct InlineAsm { - pub operands: Box<[AsmOperand]>, + pub operands: Box<[(Option, AsmOperand)]>, pub options: AsmOptions, } @@ -485,7 +485,7 @@ impl Expr { match self { Expr::Missing => {} Expr::Path(_) | Expr::OffsetOf(_) => {} - Expr::InlineAsm(it) => it.operands.iter().for_each(|op| match op { + Expr::InlineAsm(it) => it.operands.iter().for_each(|(_, op)| match op { AsmOperand::In { expr, .. } | AsmOperand::Out { expr: Some(expr), .. } | AsmOperand::InOut { expr, .. } => f(*expr), diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer/closure.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer/closure.rs index 3ad330c1a0b5d..5cad08b93956e 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/infer/closure.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer/closure.rs @@ -669,7 +669,7 @@ impl InferenceContext<'_> { fn walk_expr_without_adjust(&mut self, tgt_expr: ExprId) { match &self.body[tgt_expr] { Expr::OffsetOf(_) => (), - Expr::InlineAsm(e) => e.operands.iter().for_each(|op| match op { + Expr::InlineAsm(e) => e.operands.iter().for_each(|(_, op)| match op { AsmOperand::In { expr, .. } | AsmOperand::Out { expr: Some(expr), .. } | AsmOperand::InOut { expr, .. } => self.walk_expr_without_adjust(*expr), diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer/expr.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer/expr.rs index e6eaf2f446d43..a82d091cbb028 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/infer/expr.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer/expr.rs @@ -956,7 +956,7 @@ impl InferenceContext<'_> { }; let diverge = asm.options.contains(AsmOptions::NORETURN); - asm.operands.iter().for_each(|operand| match *operand { + asm.operands.iter().for_each(|(_, operand)| match *operand { AsmOperand::In { expr, .. } => check_expr_asm_operand(expr, true), AsmOperand::Out { expr: Some(expr), .. } | AsmOperand::InOut { expr, .. } => { check_expr_asm_operand(expr, false) diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer/mutability.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer/mutability.rs index e841c6630822a..8e52725e53600 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/infer/mutability.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer/mutability.rs @@ -42,7 +42,7 @@ impl InferenceContext<'_> { match &self.body[tgt_expr] { Expr::Missing => (), Expr::InlineAsm(e) => { - e.operands.iter().for_each(|op| match op { + e.operands.iter().for_each(|(_, op)| match op { AsmOperand::In { expr, .. } | AsmOperand::Out { expr: Some(expr), .. } | AsmOperand::InOut { expr, .. } => { diff --git a/src/tools/rust-analyzer/crates/hir/src/lib.rs b/src/tools/rust-analyzer/crates/hir/src/lib.rs index 75969bd89940e..3b8b901fa14e3 100644 --- a/src/tools/rust-analyzer/crates/hir/src/lib.rs +++ b/src/tools/rust-analyzer/crates/hir/src/lib.rs @@ -5259,13 +5259,10 @@ impl InlineAsmOperand { } pub fn name(&self, db: &dyn HirDatabase) -> Option { - db.body_with_source_map(self.owner) - .1 - .template_map()? - .1 - .get(&self.expr)? - .get(self.index) - .and_then(|(_, _, name)| name.clone()) + match &db.body(self.owner)[self.expr] { + hir_def::hir::Expr::InlineAsm(e) => e.operands.get(self.index)?.0.clone(), + _ => None, + } } } diff --git a/src/tools/rust-analyzer/crates/hir/src/semantics.rs b/src/tools/rust-analyzer/crates/hir/src/semantics.rs index 543f2fc089fb5..0ba0e446578e7 100644 --- a/src/tools/rust-analyzer/crates/hir/src/semantics.rs +++ b/src/tools/rust-analyzer/crates/hir/src/semantics.rs @@ -576,7 +576,7 @@ impl<'db> SemanticsImpl<'db> { let (owner, (expr, asm_parts)) = source_analyzer.as_asm_parts(asm.as_ref())?; let res = asm_parts .iter() - .map(|&(range, index, _)| { + .map(|&(range, index)| { ( range + quote.end(), Some(Either::Right(InlineAsmOperand { owner, expr, index })), diff --git a/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs b/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs index 4baf9079a055e..f6f1da1b7d6bd 100644 --- a/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs +++ b/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs @@ -913,8 +913,8 @@ impl SourceAnalyzer { let (expr, args) = body_source_map.asm_template_args(asm)?; Some(*def).zip( args.iter() - .find(|(range, _, _)| range.contains_inclusive(offset)) - .map(|(range, idx, _)| (expr, *range, *idx)), + .find(|(range, _)| range.contains_inclusive(offset)) + .map(|(range, idx)| (expr, *range, *idx)), ) } @@ -944,7 +944,7 @@ impl SourceAnalyzer { pub(crate) fn as_asm_parts( &self, asm: InFile<&ast::AsmExpr>, - ) -> Option<(DefWithBodyId, (ExprId, &[(TextRange, usize, Option)]))> { + ) -> Option<(DefWithBodyId, (ExprId, &[(TextRange, usize)]))> { let (def, _, body_source_map) = self.def.as_ref()?; Some(*def).zip(body_source_map.asm_template_args(asm)) } diff --git a/src/tools/rust-analyzer/crates/ide/src/rename.rs b/src/tools/rust-analyzer/crates/ide/src/rename.rs index 9b9344e98cd73..e46cb5a781f4a 100644 --- a/src/tools/rust-analyzer/crates/ide/src/rename.rs +++ b/src/tools/rust-analyzer/crates/ide/src/rename.rs @@ -3008,7 +3008,11 @@ fn test() { fn test() { core::arch::asm!( "push {base$0}", - base = const 0 + "push {base}", + boo = const 0, + virtual_free = sym VIRTUAL_FREE, + base = const 0, + boo = const 0, ); } "#, @@ -3016,7 +3020,11 @@ fn test() { fn test() { core::arch::asm!( "push {bose}", - bose = const 0 + "push {bose}", + boo = const 0, + virtual_free = sym VIRTUAL_FREE, + bose = const 0, + boo = const 0, ); } "#, From e04ede46bb172c0723c243b97720af18a1959de9 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Thu, 5 Sep 2024 08:42:50 -0400 Subject: [PATCH 0538/2194] Don't store region in CapturedPlace --- compiler/rustc_hir_typeck/src/upvar.rs | 59 ++++++++----------------- compiler/rustc_middle/src/ty/closure.rs | 3 -- 2 files changed, 19 insertions(+), 43 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/upvar.rs b/compiler/rustc_hir_typeck/src/upvar.rs index 5789e60ebbebe..7688a63a30a45 100644 --- a/compiler/rustc_hir_typeck/src/upvar.rs +++ b/compiler/rustc_hir_typeck/src/upvar.rs @@ -39,7 +39,6 @@ use rustc_hir as hir; use rustc_hir::def_id::LocalDefId; use rustc_hir::intravisit::{self, Visitor}; use rustc_hir::HirId; -use rustc_infer::infer::UpvarRegion; use rustc_middle::hir::place::{Place, PlaceBase, PlaceWithHirId, Projection, ProjectionKind}; use rustc_middle::mir::FakeReadCause; use rustc_middle::traits::ObligationCauseCode; @@ -425,7 +424,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.tcx, upvar_ty, capture, - if needs_ref { Some(closure_env_region) } else { child_capture.region }, + if needs_ref { + closure_env_region + } else { + self.tcx.lifetimes.re_erased + }, ); }, ), @@ -587,7 +590,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { debug!(?captured_place.place, ?upvar_ty, ?capture, ?captured_place.mutability); - apply_capture_kind_on_capture_ty(self.tcx, upvar_ty, capture, captured_place.region) + apply_capture_kind_on_capture_ty( + self.tcx, + upvar_ty, + capture, + self.tcx.lifetimes.re_erased, + ) }) .collect() } @@ -775,13 +783,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let Some(min_cap_list) = root_var_min_capture_list.get_mut(&var_hir_id) else { let mutability = self.determine_capture_mutability(&typeck_results, &place); - let min_cap_list = vec![ty::CapturedPlace { - var_ident, - place, - info: capture_info, - mutability, - region: None, - }]; + let min_cap_list = + vec![ty::CapturedPlace { var_ident, place, info: capture_info, mutability }]; root_var_min_capture_list.insert(var_hir_id, min_cap_list); continue; }; @@ -874,34 +877,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Only need to insert when we don't have an ancestor in the existing min capture list if !ancestor_found { let mutability = self.determine_capture_mutability(&typeck_results, &place); - let captured_place = ty::CapturedPlace { - var_ident, - place, - info: updated_capture_info, - mutability, - region: None, - }; + let captured_place = + ty::CapturedPlace { var_ident, place, info: updated_capture_info, mutability }; min_cap_list.push(captured_place); } } - // For each capture that is determined to be captured by ref, add region info. - for (_, captures) in &mut root_var_min_capture_list { - for capture in captures { - match capture.info.capture_kind { - ty::UpvarCapture::ByRef(_) => { - let PlaceBase::Upvar(upvar_id) = capture.place.base else { - bug!("expected upvar") - }; - let origin = UpvarRegion(upvar_id, closure_span); - let upvar_region = self.next_region_var(origin); - capture.region = Some(upvar_region); - } - _ => (), - } - } - } - debug!( "For closure={:?}, min_captures before sorting={:?}", closure_def_id, root_var_min_capture_list @@ -1195,7 +1176,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.tcx, ty, max_capture_info.capture_kind, - Some(self.tcx.lifetimes.re_erased), + self.tcx.lifetimes.re_erased, ) } }; @@ -1217,7 +1198,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.tcx, capture.place.ty(), capture.info.capture_kind, - Some(self.tcx.lifetimes.re_erased), + self.tcx.lifetimes.re_erased, ); // Checks if a capture implements any of the auto traits @@ -1935,13 +1916,11 @@ fn apply_capture_kind_on_capture_ty<'tcx>( tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, capture_kind: UpvarCapture, - region: Option>, + region: ty::Region<'tcx>, ) -> Ty<'tcx> { match capture_kind { ty::UpvarCapture::ByValue => ty, - ty::UpvarCapture::ByRef(kind) => { - Ty::new_ref(tcx, region.unwrap(), ty, kind.to_mutbl_lossy()) - } + ty::UpvarCapture::ByRef(kind) => Ty::new_ref(tcx, region, ty, kind.to_mutbl_lossy()), } } diff --git a/compiler/rustc_middle/src/ty/closure.rs b/compiler/rustc_middle/src/ty/closure.rs index 8eb3c0156796a..809801c33e1ad 100644 --- a/compiler/rustc_middle/src/ty/closure.rs +++ b/compiler/rustc_middle/src/ty/closure.rs @@ -88,9 +88,6 @@ pub struct CapturedPlace<'tcx> { /// Represents if `place` can be mutated or not. pub mutability: hir::Mutability, - - /// Region of the resulting reference if the upvar is captured by ref. - pub region: Option>, } impl<'tcx> CapturedPlace<'tcx> { From 588dce14211bdfb1305c495f01c697e29e946e10 Mon Sep 17 00:00:00 2001 From: Bryanskiy Date: Mon, 26 Aug 2024 19:57:59 +0300 Subject: [PATCH 0539/2194] Delegation: support generics in associated delegation items --- .../src/collect/generics_of.rs | 16 +- .../src/collect/predicates_of.rs | 16 +- compiler/rustc_hir_analysis/src/delegation.rs | 243 ++++++++++++++---- .../error_reporting/infer/need_type_info.rs | 3 + .../generics/impl-to-free-fn-pass.rs | 29 +++ .../generics/impl-to-trait-method.rs | 44 ++++ .../generics/impl-to-trait-method.stderr | 49 ++++ .../impl-trait-to-trait-method-pass.rs | 77 ++++++ .../inherent-impl-to-trait-method-pass.rs | 23 ++ .../generics/trait-method-to-other-pass.rs | 30 +++ tests/ui/delegation/ice-issue-124347.rs | 4 +- tests/ui/delegation/ice-issue-124347.stderr | 14 +- tests/ui/delegation/unsupported.rs | 59 ----- tests/ui/delegation/unsupported.stderr | 165 ++---------- 14 files changed, 500 insertions(+), 272 deletions(-) create mode 100644 tests/ui/delegation/generics/impl-to-free-fn-pass.rs create mode 100644 tests/ui/delegation/generics/impl-to-trait-method.rs create mode 100644 tests/ui/delegation/generics/impl-to-trait-method.stderr create mode 100644 tests/ui/delegation/generics/impl-trait-to-trait-method-pass.rs create mode 100644 tests/ui/delegation/generics/inherent-impl-to-trait-method-pass.rs create mode 100644 tests/ui/delegation/generics/trait-method-to-other-pass.rs diff --git a/compiler/rustc_hir_analysis/src/collect/generics_of.rs b/compiler/rustc_hir_analysis/src/collect/generics_of.rs index 28d6cab4b439a..e5f3d68caa5a9 100644 --- a/compiler/rustc_hir_analysis/src/collect/generics_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/generics_of.rs @@ -58,6 +58,12 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics { let hir_id = tcx.local_def_id_to_hir_id(def_id); let node = tcx.hir_node(hir_id); + if let Some(sig) = node.fn_sig() + && let Some(sig_id) = sig.decl.opt_delegation_sig_id() + { + return inherit_generics_for_delegation_item(tcx, def_id, sig_id); + } + let parent_def_id = match node { Node::ImplItem(_) | Node::TraitItem(_) @@ -228,16 +234,6 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics { // inherit the generics of the item. Some(parent.to_def_id()) } - ItemKind::Fn(sig, _, _) => { - // For a delegation item inherit generics from callee. - if let Some(sig_id) = sig.decl.opt_delegation_sig_id() - && let Some(generics) = - inherit_generics_for_delegation_item(tcx, def_id, sig_id) - { - return generics; - } - None - } _ => None, }, _ => None, diff --git a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs index 6ac4802b19514..61ba4346c61a5 100644 --- a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs @@ -120,6 +120,12 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen let hir_id = tcx.local_def_id_to_hir_id(def_id); let node = tcx.hir_node(hir_id); + if let Some(sig) = node.fn_sig() + && let Some(sig_id) = sig.decl.opt_delegation_sig_id() + { + return inherit_predicates_for_delegation_item(tcx, def_id, sig_id); + } + let mut is_trait = None; let mut is_default_impl_trait = None; @@ -146,16 +152,6 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen ItemKind::Trait(_, _, _, self_bounds, ..) | ItemKind::TraitAlias(_, self_bounds) => { is_trait = Some(self_bounds); } - - ItemKind::Fn(sig, _, _) => { - // For a delegation item inherit predicates from callee. - if let Some(sig_id) = sig.decl.opt_delegation_sig_id() - && let Some(predicates) = - inherit_predicates_for_delegation_item(tcx, def_id, sig_id) - { - return predicates; - } - } _ => {} } }; diff --git a/compiler/rustc_hir_analysis/src/delegation.rs b/compiler/rustc_hir_analysis/src/delegation.rs index d7a0698b6b3fb..2c9f20b7840f3 100644 --- a/compiler/rustc_hir_analysis/src/delegation.rs +++ b/compiler/rustc_hir_analysis/src/delegation.rs @@ -1,3 +1,7 @@ +//! Support inheriting generic parameters and predicates for function delegation. +//! +//! For more information about delegation design, see the tracking issue #118212. + use std::assert_matches::debug_assert_matches; use rustc_data_structures::fx::FxHashMap; @@ -5,7 +9,7 @@ use rustc_hir::def::DefKind; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_middle::ty::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable}; use rustc_middle::ty::{self, Ty, TyCtxt}; -use rustc_span::ErrorGuaranteed; +use rustc_span::{ErrorGuaranteed, Span}; use rustc_type_ir::visit::TypeVisitableExt; type RemapTable = FxHashMap; @@ -76,24 +80,60 @@ fn fn_kind<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> FnKind { } } +/// Given the current context(caller and callee `FnKind`), it specifies +/// the policy of predicates and generic parameters inheritance. +#[derive(Clone, Copy, Debug, PartialEq)] +enum InheritanceKind { + /// Copying all predicates and parameters, including those of the parent + /// container. + /// + /// Boolean value defines whether the `Self` parameter or `Self: Trait` + /// predicate are copied. It's always equal to `false` except when + /// delegating from a free function to a trait method. + /// + /// FIXME(fn_delegation): This often leads to type inference + /// errors. Support providing generic arguments or restrict use sites. + WithParent(bool), + /// The trait implementation should be compatible with the original trait. + /// Therefore, for trait implementations only the method's own parameters + /// and predicates are copied. + Own, +} + struct GenericsBuilder<'tcx> { tcx: TyCtxt<'tcx>, sig_id: DefId, parent: Option, + inh_kind: InheritanceKind, } impl<'tcx> GenericsBuilder<'tcx> { fn new(tcx: TyCtxt<'tcx>, sig_id: DefId) -> GenericsBuilder<'tcx> { - GenericsBuilder { tcx, sig_id, parent: None } + GenericsBuilder { tcx, sig_id, parent: None, inh_kind: InheritanceKind::WithParent(false) } + } + + fn with_parent(mut self, parent: DefId) -> Self { + self.parent = Some(parent); + self + } + + fn with_inheritance_kind(mut self, inh_kind: InheritanceKind) -> Self { + self.inh_kind = inh_kind; + self } fn build(self) -> ty::Generics { let mut own_params = vec![]; let sig_generics = self.tcx.generics_of(self.sig_id); - if let Some(parent_def_id) = sig_generics.parent { + if let InheritanceKind::WithParent(has_self) = self.inh_kind + && let Some(parent_def_id) = sig_generics.parent + { let sig_parent_generics = self.tcx.generics_of(parent_def_id); own_params.append(&mut sig_parent_generics.own_params.clone()); + if !has_self { + own_params.remove(0); + } } own_params.append(&mut sig_generics.own_params.clone()); @@ -115,8 +155,16 @@ impl<'tcx> GenericsBuilder<'tcx> { let param_def_id_to_index = own_params.iter().map(|param| (param.def_id, param.index)).collect(); + let (parent_count, has_self) = if let Some(def_id) = self.parent { + let parent_generics = self.tcx.generics_of(def_id); + let parent_kind = self.tcx.def_kind(def_id); + (parent_generics.count(), parent_kind == DefKind::Trait) + } else { + (0, false) + }; + for (idx, param) in own_params.iter_mut().enumerate() { - param.index = idx as u32; + param.index = (idx + parent_count) as u32; // FIXME(fn_delegation): Default parameters are not inherited, because they are // not permitted in functions. Therefore, there are 2 options here: // @@ -133,10 +181,10 @@ impl<'tcx> GenericsBuilder<'tcx> { ty::Generics { parent: self.parent, - parent_count: 0, + parent_count, own_params, param_def_id_to_index, - has_self: false, + has_self, has_late_bound_regions: sig_generics.has_late_bound_regions, host_effect_index: sig_generics.host_effect_index, } @@ -145,9 +193,10 @@ impl<'tcx> GenericsBuilder<'tcx> { struct PredicatesBuilder<'tcx> { tcx: TyCtxt<'tcx>, - args: ty::GenericArgsRef<'tcx>, - parent: Option, sig_id: DefId, + parent: Option, + inh_kind: InheritanceKind, + args: ty::GenericArgsRef<'tcx>, } impl<'tcx> PredicatesBuilder<'tcx> { @@ -156,18 +205,76 @@ impl<'tcx> PredicatesBuilder<'tcx> { args: ty::GenericArgsRef<'tcx>, sig_id: DefId, ) -> PredicatesBuilder<'tcx> { - PredicatesBuilder { tcx, args, parent: None, sig_id } + PredicatesBuilder { + tcx, + sig_id, + parent: None, + inh_kind: InheritanceKind::WithParent(false), + args, + } + } + + fn with_parent(mut self, parent: DefId) -> Self { + self.parent = Some(parent); + self + } + + fn with_inheritance_kind(mut self, inh_kind: InheritanceKind) -> Self { + self.inh_kind = inh_kind; + self } fn build(self) -> ty::GenericPredicates<'tcx> { - let mut preds = vec![]; + struct PredicatesCollector<'tcx> { + tcx: TyCtxt<'tcx>, + preds: Vec<(ty::Clause<'tcx>, Span)>, + args: ty::GenericArgsRef<'tcx>, + } + + impl<'tcx> PredicatesCollector<'tcx> { + fn new(tcx: TyCtxt<'tcx>, args: ty::GenericArgsRef<'tcx>) -> PredicatesCollector<'tcx> { + PredicatesCollector { tcx, preds: vec![], args } + } + + fn with_own_preds( + mut self, + f: impl Fn(DefId) -> ty::GenericPredicates<'tcx>, + def_id: DefId, + ) -> Self { + let preds = f(def_id).instantiate_own(self.tcx, self.args); + self.preds.extend(preds); + self + } - let sig_predicates = self.tcx.predicates_of(self.sig_id); - if let Some(parent) = sig_predicates.parent { - let sig_parent_preds = self.tcx.predicates_of(parent); - preds.extend(sig_parent_preds.instantiate_own(self.tcx, self.args)); + fn with_preds( + mut self, + f: impl Fn(DefId) -> ty::GenericPredicates<'tcx> + Copy, + def_id: DefId, + ) -> Self { + let preds = f(def_id); + if let Some(parent_def_id) = preds.parent { + self = self.with_own_preds(f, parent_def_id); + } + self.with_own_preds(f, def_id) + } + } + let collector = PredicatesCollector::new(self.tcx, self.args); + + // `explicit_predicates_of` is used here to avoid copying `Self: Trait` predicate. + // Note: `predicates_of` query can also add inferred outlives predicates, but that + // is not the case here as `sig_id` is either a trait or a function. + let preds = match self.inh_kind { + InheritanceKind::WithParent(false) => { + collector.with_preds(|def_id| self.tcx.explicit_predicates_of(def_id), self.sig_id) + } + InheritanceKind::WithParent(true) => { + collector.with_preds(|def_id| self.tcx.predicates_of(def_id), self.sig_id) + } + InheritanceKind::Own => { + collector.with_own_preds(|def_id| self.tcx.predicates_of(def_id), self.sig_id) + } } - preds.extend(sig_predicates.instantiate_own(self.tcx, self.args)); + .preds; ty::GenericPredicates { parent: self.parent, @@ -214,7 +321,6 @@ fn create_generic_args<'tcx>( let caller_kind = fn_kind(tcx, def_id.into()); let callee_kind = fn_kind(tcx, sig_id); - match (caller_kind, callee_kind) { (FnKind::Free, FnKind::Free) | (FnKind::Free, FnKind::AssocTrait) @@ -224,14 +330,32 @@ fn create_generic_args<'tcx>( let args = ty::GenericArgs::identity_for_item(tcx, sig_id); builder.build_from_args(args) } - // FIXME(fn_delegation): Only `Self` param supported here. - (FnKind::AssocTraitImpl, FnKind::AssocTrait) - | (FnKind::AssocInherentImpl, FnKind::AssocTrait) => { + + (FnKind::AssocTraitImpl, FnKind::AssocTrait) => { + let callee_generics = tcx.generics_of(sig_id); + let parent = tcx.parent(def_id.into()); + let parent_args = + tcx.impl_trait_header(parent).unwrap().trait_ref.instantiate_identity().args; + + let trait_args = ty::GenericArgs::identity_for_item(tcx, sig_id); + let method_args = tcx.mk_args_from_iter(trait_args.iter().skip(callee_generics.parent_count)); + let method_args = builder.build_from_args(method_args); + + tcx.mk_args_from_iter(parent_args.iter().chain(method_args)) + } + + (FnKind::AssocInherentImpl, FnKind::AssocTrait) => { let parent = tcx.parent(def_id.into()); let self_ty = tcx.type_of(parent).instantiate_identity(); let generic_self_ty = ty::GenericArg::from(self_ty); - tcx.mk_args_from_iter(std::iter::once(generic_self_ty)) + + let trait_args = ty::GenericArgs::identity_for_item(tcx, sig_id); + let trait_args = builder.build_from_args(trait_args); + + let args = std::iter::once(generic_self_ty).chain(trait_args.iter().skip(1)); + tcx.mk_args_from_iter(args) } + // For trait impl's `sig_id` is always equal to the corresponding trait method. (FnKind::AssocTraitImpl, _) | (_, FnKind::AssocTraitImpl) @@ -240,27 +364,50 @@ fn create_generic_args<'tcx>( } } +// FIXME(fn_delegation): Move generics inheritance to the AST->HIR lowering. +// For now, generic parameters are not propagated to the generated call, +// which leads to inference errors: +// +// fn foo(x: i32) {} +// +// reuse foo as bar; +// desugaring: +// fn bar() { +// foo::<_>() // ERROR: type annotations needed +// } pub(crate) fn inherit_generics_for_delegation_item<'tcx>( tcx: TyCtxt<'tcx>, def_id: LocalDefId, sig_id: DefId, -) -> Option { +) -> ty::Generics { let builder = GenericsBuilder::new(tcx, sig_id); let caller_kind = fn_kind(tcx, def_id.into()); let callee_kind = fn_kind(tcx, sig_id); - - // FIXME(fn_delegation): Support generics on associated delegation items. - // Error will be reported in `check_constraints`. match (caller_kind, callee_kind) { (FnKind::Free, FnKind::Free) - | (FnKind::Free, FnKind::AssocTrait) => Some(builder.build()), + | (FnKind::Free, FnKind::AssocTrait) => builder.with_inheritance_kind(InheritanceKind::WithParent(true)).build(), - (FnKind::AssocTraitImpl, FnKind::AssocTrait) - | (FnKind::AssocInherentImpl, FnKind::AssocTrait) - | (FnKind::AssocTrait, FnKind::AssocTrait) - | (FnKind::AssocInherentImpl, FnKind::Free) - | (FnKind::AssocTrait, FnKind::Free) => None, + (FnKind::AssocTraitImpl, FnKind::AssocTrait) => { + builder + .with_parent(tcx.parent(def_id.into())) + .with_inheritance_kind(InheritanceKind::Own) + .build() + } + + (FnKind::AssocInherentImpl, FnKind::AssocTrait) + | (FnKind::AssocTrait, FnKind::AssocTrait) => { + builder + .with_parent(tcx.parent(def_id.into())) + .build() + } + + (FnKind::AssocInherentImpl, FnKind::Free) + | (FnKind::AssocTrait, FnKind::Free) => { + builder + .with_parent(tcx.parent(def_id.into())) + .build() + } // For trait impl's `sig_id` is always equal to the corresponding trait method. (FnKind::AssocTraitImpl, _) @@ -274,26 +421,33 @@ pub(crate) fn inherit_predicates_for_delegation_item<'tcx>( tcx: TyCtxt<'tcx>, def_id: LocalDefId, sig_id: DefId, -) -> Option> { +) -> ty::GenericPredicates<'tcx> { let args = create_generic_args(tcx, def_id, sig_id); let builder = PredicatesBuilder::new(tcx, args, sig_id); let caller_kind = fn_kind(tcx, def_id.into()); let callee_kind = fn_kind(tcx, sig_id); - - // FIXME(fn_delegation): Support generics on associated delegation items. - // Error will be reported in `check_constraints`. match (caller_kind, callee_kind) { (FnKind::Free, FnKind::Free) | (FnKind::Free, FnKind::AssocTrait) => { - Some(builder.build()) + builder.with_inheritance_kind(InheritanceKind::WithParent(true)).build() + } + + (FnKind::AssocTraitImpl, FnKind::AssocTrait) => { + builder + .with_parent(tcx.parent(def_id.into())) + .with_inheritance_kind(InheritanceKind::Own) + .build() } - (FnKind::AssocTraitImpl, FnKind::AssocTrait) - | (FnKind::AssocInherentImpl, FnKind::AssocTrait) + (FnKind::AssocInherentImpl, FnKind::AssocTrait) | (FnKind::AssocTrait, FnKind::AssocTrait) | (FnKind::AssocInherentImpl, FnKind::Free) - | (FnKind::AssocTrait, FnKind::Free) => None, + | (FnKind::AssocTrait, FnKind::Free) => { + builder + .with_parent(tcx.parent(def_id.into())) + .build() + } // For trait impl's `sig_id` is always equal to the corresponding trait method. (FnKind::AssocTraitImpl, _) @@ -328,19 +482,6 @@ fn check_constraints<'tcx>( emit("recursive delegation is not supported yet"); } - if fn_kind(tcx, def_id.into()) != FnKind::Free { - let sig_generics = tcx.generics_of(sig_id); - let parent = tcx.parent(def_id.into()); - let parent_generics = tcx.generics_of(parent); - - let parent_has_self = parent_generics.has_self as usize; - let sig_has_self = sig_generics.has_self as usize; - - if sig_generics.count() > sig_has_self || parent_generics.count() > parent_has_self { - emit("early bound generics are not supported for associated delegation items"); - } - } - ret } diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs index f6dd7898fb28e..2d0a7ce47f6be 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs @@ -1253,6 +1253,9 @@ impl<'a, 'tcx> Visitor<'tcx> for FindInferSourceVisitor<'a, 'tcx> { && let Some(def_id) = self.typeck_results.type_dependent_def_id(expr.hir_id) && self.tecx.tcx.trait_of_item(def_id).is_some() && !has_impl_trait(def_id) + // FIXME(fn_delegation): In delegation item argument spans are equal to last path + // segment. This leads to ICE's when emitting `multipart_suggestion`. + && tcx.hir().opt_delegation_sig_id(expr.hir_id.owner.def_id).is_none() { let successor = method_args.get(0).map_or_else(|| (")", span.hi()), |arg| (", ", arg.span.lo())); diff --git a/tests/ui/delegation/generics/impl-to-free-fn-pass.rs b/tests/ui/delegation/generics/impl-to-free-fn-pass.rs new file mode 100644 index 0000000000000..3b39a45746758 --- /dev/null +++ b/tests/ui/delegation/generics/impl-to-free-fn-pass.rs @@ -0,0 +1,29 @@ +//@ run-pass +#![feature(fn_delegation)] +#![allow(incomplete_features)] + +mod to_reuse { + pub fn foo(_: T, y: U) -> U { y } +} + +trait Trait { + fn foo(&self, x: T) -> T { x } +} +struct F; +impl Trait for F {} + +struct S(F, T); + +impl Trait for S { + reuse to_reuse::foo { &self.0 } +} + +impl S { + reuse to_reuse::foo; +} + +fn main() { + let s = S(F, 42); + assert_eq!(S::::foo(F, 1), 1); + assert_eq!( as Trait<_>>::foo(&s, 1), 1); +} diff --git a/tests/ui/delegation/generics/impl-to-trait-method.rs b/tests/ui/delegation/generics/impl-to-trait-method.rs new file mode 100644 index 0000000000000..39e32e2ed1500 --- /dev/null +++ b/tests/ui/delegation/generics/impl-to-trait-method.rs @@ -0,0 +1,44 @@ +#![feature(fn_delegation)] +#![allow(incomplete_features)] + +mod bounds { + trait Trait0 {} + + trait Trait1 { + fn foo(&self) + where + T: Trait0, + U: Trait0, + Self: Trait0, + //~^ ERROR the trait bound `bounds::S: Trait0` is not satisfied + { + } + } + + struct F; + impl Trait1 for F {} + + struct S(F); + + impl Trait1 for S { + reuse Trait1::::foo { &self.0 } + //~^ ERROR the trait bound `bounds::F: Trait0` is not satisfied + } +} + +mod unconstrained_parameter { + trait Trait { + fn foo(&self) {} + } + + struct F; + impl Trait for F {} + + struct S(F); + impl S { + reuse Trait::foo { &self.0 } + //~^ ERROR type annotations needed + } +} + +fn main() {} diff --git a/tests/ui/delegation/generics/impl-to-trait-method.stderr b/tests/ui/delegation/generics/impl-to-trait-method.stderr new file mode 100644 index 0000000000000..aeba30de043f5 --- /dev/null +++ b/tests/ui/delegation/generics/impl-to-trait-method.stderr @@ -0,0 +1,49 @@ +error[E0277]: the trait bound `bounds::S: Trait0` is not satisfied + --> $DIR/impl-to-trait-method.rs:12:19 + | +LL | Self: Trait0, + | ^^^^^^ the trait `Trait0` is not implemented for `bounds::S` + | +help: this trait has no implementations, consider adding one + --> $DIR/impl-to-trait-method.rs:5:5 + | +LL | trait Trait0 {} + | ^^^^^^^^^^^^ + = help: see issue #48214 +help: add `#![feature(trivial_bounds)]` to the crate attributes to enable + | +LL + #![feature(trivial_bounds)] + | + +error[E0277]: the trait bound `bounds::F: Trait0` is not satisfied + --> $DIR/impl-to-trait-method.rs:24:34 + | +LL | reuse Trait1::::foo { &self.0 } + | --- ^^^^^^^ the trait `Trait0` is not implemented for `bounds::F` + | | + | required by a bound introduced by this call + | +help: this trait has no implementations, consider adding one + --> $DIR/impl-to-trait-method.rs:5:5 + | +LL | trait Trait0 {} + | ^^^^^^^^^^^^ +note: required by a bound in `Trait1::foo` + --> $DIR/impl-to-trait-method.rs:12:19 + | +LL | fn foo(&self) + | --- required by a bound in this associated function +... +LL | Self: Trait0, + | ^^^^^^ required by this bound in `Trait1::foo` + +error[E0282]: type annotations needed + --> $DIR/impl-to-trait-method.rs:39:22 + | +LL | reuse Trait::foo { &self.0 } + | ^^^ cannot infer type for type parameter `T` declared on the trait `Trait` + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0277, E0282. +For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/delegation/generics/impl-trait-to-trait-method-pass.rs b/tests/ui/delegation/generics/impl-trait-to-trait-method-pass.rs new file mode 100644 index 0000000000000..72440fe82d44d --- /dev/null +++ b/tests/ui/delegation/generics/impl-trait-to-trait-method-pass.rs @@ -0,0 +1,77 @@ +//@ run-pass + +#![feature(fn_delegation)] +#![allow(incomplete_features)] + +use std::iter::{Iterator, Map}; + +pub mod same_trait { + use super::*; + + pub struct MapOuter { + pub inner: Map + } + + impl Iterator for MapOuter + where + F: FnMut(I::Item) -> B, + { + type Item = as Iterator>::Item; + + reuse Iterator::{next, fold} { self.inner } + } +} +use same_trait::MapOuter; + +mod another_trait { + use super::*; + + trait ZipImpl { + type Item; + + fn next(&mut self) -> Option; + } + + pub struct Zip { + pub a: A, + pub b: B, + } + + impl ZipImpl for Zip { + type Item = (A::Item, B::Item); + + fn next(&mut self) -> Option<(A::Item, B::Item)> { + let x = self.a.next()?; + let y = self.b.next()?; + Some((x, y)) + } + } + + impl Iterator for Zip { + type Item = (A::Item, B::Item); + + // Parameters are inherited from `Iterator::next`, not from `ZipImpl::next`. + // Otherwise, there would be a compilation error due to an unconstrained parameter. + reuse ZipImpl::next; + } +} +use another_trait::Zip; + +fn main() { + { + let x = vec![1, 2, 3]; + let iter = x.iter().map(|val| val * 2); + let outer_iter = MapOuter { inner: iter }; + let val = outer_iter.fold(0, |acc, x| acc + x); + assert_eq!(val, 12); + } + + { + let x = vec![1, 2]; + let y = vec![4, 5]; + + let mut zip = Zip { a: x.iter(), b: y.iter() }; + assert_eq!(zip.next(), Some((&1, &4))); + assert_eq!(zip.next(), Some((&2, &5))); + } +} diff --git a/tests/ui/delegation/generics/inherent-impl-to-trait-method-pass.rs b/tests/ui/delegation/generics/inherent-impl-to-trait-method-pass.rs new file mode 100644 index 0000000000000..6f3bb17897169 --- /dev/null +++ b/tests/ui/delegation/generics/inherent-impl-to-trait-method-pass.rs @@ -0,0 +1,23 @@ +//@ run-pass + +#![feature(fn_delegation)] +#![allow(incomplete_features)] + +trait Trait { + fn foo(&self, x: T, y: U) -> (T, U) { + (x, y) + } +} + +impl Trait for () {} +struct S(T, ()); + +impl S { + reuse Trait::foo { self.1 } +} + + +fn main() { + let s = S((), ()); + assert_eq!(s.foo(1u32, 2i32), (1u32, 2i32)); +} diff --git a/tests/ui/delegation/generics/trait-method-to-other-pass.rs b/tests/ui/delegation/generics/trait-method-to-other-pass.rs new file mode 100644 index 0000000000000..2094705a05ce6 --- /dev/null +++ b/tests/ui/delegation/generics/trait-method-to-other-pass.rs @@ -0,0 +1,30 @@ +//@ run-pass + +#![feature(fn_delegation)] +#![allow(incomplete_features)] + +mod to_reuse { + pub fn foo(x: T) -> T { x } +} + +trait Trait1 { + fn foo(&self, _: T, x: U) -> U { x } +} + +#[derive(Default)] +struct F; + +impl Trait1 for F {} + +trait Trait2 { + fn get_f(&self) -> &F { &F } + reuse Trait1::foo as bar { self.get_f() } + reuse to_reuse::foo as baz; +} + +impl Trait2 for F {} + +fn main() { + assert_eq!(F.bar(1u8, 2u16), 2u16); + assert_eq!(F::baz(1u8), 1u8); +} diff --git a/tests/ui/delegation/ice-issue-124347.rs b/tests/ui/delegation/ice-issue-124347.rs index 3bfae8face597..ee2bf9e33eb89 100644 --- a/tests/ui/delegation/ice-issue-124347.rs +++ b/tests/ui/delegation/ice-issue-124347.rs @@ -1,12 +1,12 @@ #![feature(fn_delegation)] #![allow(incomplete_features)] +// FIXME(fn_delegation): `recursive delegation` error should be emitted here trait Trait { reuse Trait::foo { &self.0 } - //~^ ERROR recursive delegation is not supported yet + //~^ ERROR cycle detected when computing generics of `Trait::foo` } -// FIXME(fn_delegation): `recursive delegation` error should be emitted here reuse foo; //~^ ERROR cycle detected when computing generics of `foo` diff --git a/tests/ui/delegation/ice-issue-124347.stderr b/tests/ui/delegation/ice-issue-124347.stderr index 87dd75ffec82c..bd0bc970b94c2 100644 --- a/tests/ui/delegation/ice-issue-124347.stderr +++ b/tests/ui/delegation/ice-issue-124347.stderr @@ -1,8 +1,16 @@ -error: recursive delegation is not supported yet - --> $DIR/ice-issue-124347.rs:5:18 +error[E0391]: cycle detected when computing generics of `Trait::foo` + --> $DIR/ice-issue-124347.rs:6:18 | LL | reuse Trait::foo { &self.0 } - | ^^^ callee defined here + | ^^^ + | + = note: ...which immediately requires computing generics of `Trait::foo` again +note: cycle used when inheriting delegation signature + --> $DIR/ice-issue-124347.rs:6:18 + | +LL | reuse Trait::foo { &self.0 } + | ^^^ + = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information error[E0391]: cycle detected when computing generics of `foo` --> $DIR/ice-issue-124347.rs:10:7 diff --git a/tests/ui/delegation/unsupported.rs b/tests/ui/delegation/unsupported.rs index d5ac68ecf1b8a..e57effff48d81 100644 --- a/tests/ui/delegation/unsupported.rs +++ b/tests/ui/delegation/unsupported.rs @@ -4,65 +4,6 @@ #![feature(fn_delegation)] #![allow(incomplete_features)] -mod generics { - trait GenericTrait { - fn bar(&self, x: T) -> T { x } - fn bar1() {} - } - trait Trait { - fn foo(&self, x: i32) -> i32 { x } - fn foo1<'a>(&self, x: &'a i32) -> &'a i32 { x } - fn foo2(&self, x: T) -> T { x } - fn foo3<'a: 'a>(_: &'a u32) {} - - reuse GenericTrait::bar; - //~^ ERROR early bound generics are not supported for associated delegation items - reuse GenericTrait::bar1; - //~^ ERROR early bound generics are not supported for associated delegation items - } - - struct F; - impl Trait for F {} - impl GenericTrait for F {} - - struct S(F); - - impl GenericTrait for S { - reuse >::bar { &self.0 } - //~^ ERROR early bound generics are not supported for associated delegation items - reuse GenericTrait::::bar1; - //~^ ERROR early bound generics are not supported for associated delegation items - } - - impl GenericTrait<()> for () { - reuse GenericTrait::bar { &F } - //~^ ERROR early bound generics are not supported for associated delegation items - reuse GenericTrait::bar1; - //~^ ERROR early bound generics are not supported for associated delegation items - } - - impl Trait for &S { - reuse Trait::foo; - //~^ ERROR early bound generics are not supported for associated delegation items - } - - impl Trait for S { - reuse Trait::foo1 { &self.0 } - reuse Trait::foo2 { &self.0 } - //~^ ERROR early bound generics are not supported for associated delegation items - //~| ERROR method `foo2` has 0 type parameters but its trait declaration has 1 type parameter - reuse ::foo3; - //~^ ERROR early bound generics are not supported for associated delegation items - //~| ERROR lifetime parameters or bounds on associated function `foo3` do not match the trait declaration - } - - struct GenericS(T); - impl Trait for GenericS { - reuse Trait::foo { &self.0 } - //~^ ERROR early bound generics are not supported for associated delegation items - } -} - mod opaque { trait Trait {} impl Trait for () {} diff --git a/tests/ui/delegation/unsupported.stderr b/tests/ui/delegation/unsupported.stderr index bb150254f48b9..03ded300bb446 100644 --- a/tests/ui/delegation/unsupported.stderr +++ b/tests/ui/delegation/unsupported.stderr @@ -3,125 +3,8 @@ error: using `#![feature(effects)]` without enabling next trait solver globally = note: the next trait solver must be enabled globally for the effects feature to work correctly = help: use `-Znext-solver` to enable -error: early bound generics are not supported for associated delegation items - --> $DIR/unsupported.rs:18:29 - | -LL | fn bar(&self, x: T) -> T { x } - | ------------------------ callee defined here -... -LL | reuse GenericTrait::bar; - | ^^^ - -error: early bound generics are not supported for associated delegation items - --> $DIR/unsupported.rs:20:29 - | -LL | fn bar1() {} - | --------- callee defined here -... -LL | reuse GenericTrait::bar1; - | ^^^^ - -error: early bound generics are not supported for associated delegation items - --> $DIR/unsupported.rs:31:39 - | -LL | fn bar(&self, x: T) -> T { x } - | ------------------------ callee defined here -... -LL | reuse >::bar { &self.0 } - | ^^^ - -error: early bound generics are not supported for associated delegation items - --> $DIR/unsupported.rs:33:34 - | -LL | fn bar1() {} - | --------- callee defined here -... -LL | reuse GenericTrait::::bar1; - | ^^^^ - -error: early bound generics are not supported for associated delegation items - --> $DIR/unsupported.rs:38:29 - | -LL | fn bar(&self, x: T) -> T { x } - | ------------------------ callee defined here -... -LL | reuse GenericTrait::bar { &F } - | ^^^ - -error: early bound generics are not supported for associated delegation items - --> $DIR/unsupported.rs:40:29 - | -LL | fn bar1() {} - | --------- callee defined here -... -LL | reuse GenericTrait::bar1; - | ^^^^ - -error: early bound generics are not supported for associated delegation items - --> $DIR/unsupported.rs:45:22 - | -LL | fn foo(&self, x: i32) -> i32 { x } - | ---------------------------- callee defined here -... -LL | reuse Trait::foo; - | ^^^ - -error[E0049]: method `foo2` has 0 type parameters but its trait declaration has 1 type parameter - --> $DIR/unsupported.rs:51:22 - | -LL | fn foo2(&self, x: T) -> T { x } - | - expected 1 type parameter -... -LL | reuse Trait::foo2 { &self.0 } - | ^^^^ found 0 type parameters - -error: early bound generics are not supported for associated delegation items - --> $DIR/unsupported.rs:54:29 - | -LL | fn foo3<'a: 'a>(_: &'a u32) {} - | --------------------------- callee defined here -... -LL | reuse ::foo3; - | ^^^^ - -error[E0195]: lifetime parameters or bounds on associated function `foo3` do not match the trait declaration - --> $DIR/unsupported.rs:54:29 - | -LL | fn foo3<'a: 'a>(_: &'a u32) {} - | -------- lifetimes in impl do not match this associated function in trait -... -LL | reuse ::foo3; - | ^^^^ lifetimes do not match associated function in trait - -error: delegation to a function with effect parameter is not supported yet - --> $DIR/unsupported.rs:112:18 - | -LL | fn foo(); - | --------- callee defined here -... -LL | reuse Trait::foo; - | ^^^ - -error: early bound generics are not supported for associated delegation items - --> $DIR/unsupported.rs:61:22 - | -LL | fn foo(&self, x: i32) -> i32 { x } - | ---------------------------- callee defined here -... -LL | reuse Trait::foo { &self.0 } - | ^^^ - -error: early bound generics are not supported for associated delegation items - --> $DIR/unsupported.rs:51:22 - | -LL | fn foo2(&self, x: T) -> T { x } - | ---------------------------- callee defined here -... -LL | reuse Trait::foo2 { &self.0 } - | ^^^^ - warning: this function depends on never type fallback being `()` - --> $DIR/unsupported.rs:79:9 + --> $DIR/unsupported.rs:20:9 | LL | fn opaque_ret() -> impl Trait { unimplemented!() } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -130,33 +13,33 @@ LL | fn opaque_ret() -> impl Trait { unimplemented!() } = note: for more information, see issue #123748 = help: specify the types explicitly note: in edition 2024, the requirement `!: opaque::Trait` will fail - --> $DIR/unsupported.rs:79:28 + --> $DIR/unsupported.rs:20:28 | LL | fn opaque_ret() -> impl Trait { unimplemented!() } | ^^^^^^^^^^ = note: `#[warn(dependency_on_unit_never_type_fallback)]` on by default -error[E0391]: cycle detected when computing type of `opaque::::{synthetic#0}` - --> $DIR/unsupported.rs:86:25 +error[E0391]: cycle detected when computing type of `opaque::::{synthetic#0}` + --> $DIR/unsupported.rs:27:25 | LL | reuse to_reuse::opaque_ret; | ^^^^^^^^^^ | note: ...which requires comparing an impl and trait method signature, inferring any hidden `impl Trait` types in the process... - --> $DIR/unsupported.rs:86:25 + --> $DIR/unsupported.rs:27:25 | LL | reuse to_reuse::opaque_ret; | ^^^^^^^^^^ - = note: ...which again requires computing type of `opaque::::{synthetic#0}`, completing the cycle -note: cycle used when checking that `opaque::` is well-formed - --> $DIR/unsupported.rs:85:5 + = note: ...which again requires computing type of `opaque::::{synthetic#0}`, completing the cycle +note: cycle used when checking that `opaque::` is well-formed + --> $DIR/unsupported.rs:26:5 | LL | impl ToReuse for u8 { | ^^^^^^^^^^^^^^^^^^^ = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information warning: this function depends on never type fallback being `()` - --> $DIR/unsupported.rs:73:9 + --> $DIR/unsupported.rs:14:9 | LL | pub fn opaque_ret() -> impl Trait { unimplemented!() } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -165,32 +48,32 @@ LL | pub fn opaque_ret() -> impl Trait { unimplemented!() } = note: for more information, see issue #123748 = help: specify the types explicitly note: in edition 2024, the requirement `!: opaque::Trait` will fail - --> $DIR/unsupported.rs:73:32 + --> $DIR/unsupported.rs:14:32 | LL | pub fn opaque_ret() -> impl Trait { unimplemented!() } | ^^^^^^^^^^ -error[E0391]: cycle detected when computing type of `opaque::::{synthetic#0}` - --> $DIR/unsupported.rs:89:24 +error[E0391]: cycle detected when computing type of `opaque::::{synthetic#0}` + --> $DIR/unsupported.rs:30:24 | LL | reuse ToReuse::opaque_ret; | ^^^^^^^^^^ | note: ...which requires comparing an impl and trait method signature, inferring any hidden `impl Trait` types in the process... - --> $DIR/unsupported.rs:89:24 + --> $DIR/unsupported.rs:30:24 | LL | reuse ToReuse::opaque_ret; | ^^^^^^^^^^ - = note: ...which again requires computing type of `opaque::::{synthetic#0}`, completing the cycle -note: cycle used when checking that `opaque::` is well-formed - --> $DIR/unsupported.rs:88:5 + = note: ...which again requires computing type of `opaque::::{synthetic#0}`, completing the cycle +note: cycle used when checking that `opaque::` is well-formed + --> $DIR/unsupported.rs:29:5 | LL | impl ToReuse for u16 { | ^^^^^^^^^^^^^^^^^^^^ = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information error: recursive delegation is not supported yet - --> $DIR/unsupported.rs:102:22 + --> $DIR/unsupported.rs:43:22 | LL | pub reuse to_reuse2::foo; | --- callee defined here @@ -198,7 +81,15 @@ LL | pub reuse to_reuse2::foo; LL | reuse to_reuse1::foo; | ^^^ -error: aborting due to 17 previous errors; 2 warnings emitted +error: delegation to a function with effect parameter is not supported yet + --> $DIR/unsupported.rs:53:18 + | +LL | fn foo(); + | --------- callee defined here +... +LL | reuse Trait::foo; + | ^^^ + +error: aborting due to 5 previous errors; 2 warnings emitted -Some errors have detailed explanations: E0049, E0195, E0391. -For more information about an error, try `rustc --explain E0049`. +For more information about this error, try `rustc --explain E0391`. From 20e9c8d110d6259b8086c2ffd6268d0dd072a2ab Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Thu, 5 Sep 2024 15:06:37 +0200 Subject: [PATCH 0540/2194] asm! parsing and lowering fixes --- .../rust-analyzer/crates/hir-def/src/body.rs | 6 ++-- .../crates/hir-def/src/body/lower/asm.rs | 7 +++-- .../rust-analyzer/crates/hir/src/semantics.rs | 5 +++- .../crates/hir/src/source_analyzer.rs | 6 ++-- .../crates/ide/src/highlight_related.rs | 30 +++++++++++++++++++ .../test_data/highlight_asm.html | 26 ++++++++++++++-- .../test_data/highlight_strings.html | 2 +- .../ide/src/syntax_highlighting/tests.rs | 22 ++++++++++++++ .../parser/src/grammar/expressions/atom.rs | 4 +++ .../test_data/parser/inline/ok/asm_expr.rast | 16 +++++----- 10 files changed, 106 insertions(+), 18 deletions(-) diff --git a/src/tools/rust-analyzer/crates/hir-def/src/body.rs b/src/tools/rust-analyzer/crates/hir-def/src/body.rs index 34db43939a7ca..f18083d387356 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/body.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/body.rs @@ -105,7 +105,7 @@ pub struct BodySourceMap { // format_args! FxHashMap>, // asm! - FxHashMap>, + FxHashMap>>, )>, >, @@ -439,7 +439,7 @@ impl BodySourceMap { pub fn asm_template_args( &self, node: InFile<&ast::AsmExpr>, - ) -> Option<(ExprId, &[(syntax::TextRange, usize)])> { + ) -> Option<(ExprId, &[Vec<(syntax::TextRange, usize)>])> { let src = node.map(AstPtr::new).map(AstPtr::upcast::); let expr = self.expr_map.get(&src)?; Some(*expr).zip(self.template_map.as_ref()?.1.get(expr).map(std::ops::Deref::deref)) @@ -487,7 +487,7 @@ impl BodySourceMap { &self, ) -> Option<&( FxHashMap, Vec<(tt::TextRange, Name)>>, - FxHashMap, Vec<(tt::TextRange, usize)>>, + FxHashMap, Vec>>, )> { self.template_map.as_deref() } diff --git a/src/tools/rust-analyzer/crates/hir-def/src/body/lower/asm.rs b/src/tools/rust-analyzer/crates/hir-def/src/body/lower/asm.rs index bf6ba41482c47..448bc2f033f66 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/body/lower/asm.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/body/lower/asm.rs @@ -158,11 +158,14 @@ impl ExprCollector<'_> { if !options.contains(AsmOptions::RAW) { // Don't treat raw asm as a format string. asm.template() - .filter_map(|it| Some((it.clone(), self.expand_macros_to_string(it)?))) - .for_each(|(expr, (s, is_direct_literal))| { + .enumerate() + .filter_map(|(idx, it)| Some((idx, it.clone(), self.expand_macros_to_string(it)?))) + .for_each(|(idx, expr, (s, is_direct_literal))| { + mappings.resize_with(idx + 1, Vec::default); let Ok(text) = s.value() else { return; }; + let mappings = &mut mappings[idx]; let template_snippet = match expr { ast::Expr::Literal(literal) => match literal.kind() { ast::LiteralKind::String(s) => Some(s.text().to_owned()), diff --git a/src/tools/rust-analyzer/crates/hir/src/semantics.rs b/src/tools/rust-analyzer/crates/hir/src/semantics.rs index 0ba0e446578e7..2e67a5e454bfa 100644 --- a/src/tools/rust-analyzer/crates/hir/src/semantics.rs +++ b/src/tools/rust-analyzer/crates/hir/src/semantics.rs @@ -572,9 +572,11 @@ impl<'db> SemanticsImpl<'db> { } else { let asm = ast::AsmExpr::cast(parent)?; let source_analyzer = self.analyze_no_infer(asm.syntax())?; + let line = asm.template().position(|it| *it.syntax() == literal)?; let asm = self.wrap_node_infile(asm); let (owner, (expr, asm_parts)) = source_analyzer.as_asm_parts(asm.as_ref())?; let res = asm_parts + .get(line)? .iter() .map(|&(range, index)| { ( @@ -629,8 +631,9 @@ impl<'db> SemanticsImpl<'db> { } else { let asm = ast::AsmExpr::cast(parent)?; let source_analyzer = &self.analyze_no_infer(asm.syntax())?; + let line = asm.template().position(|it| *it.syntax() == literal)?; let asm = self.wrap_node_infile(asm); - source_analyzer.resolve_offset_in_asm_template(asm.as_ref(), offset).map( + source_analyzer.resolve_offset_in_asm_template(asm.as_ref(), line, offset).map( |(owner, (expr, range, index))| { (range, Some(Either::Right(InlineAsmOperand { owner, expr, index }))) }, diff --git a/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs b/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs index f6f1da1b7d6bd..3da67ae23f83b 100644 --- a/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs +++ b/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs @@ -907,12 +907,14 @@ impl SourceAnalyzer { pub(crate) fn resolve_offset_in_asm_template( &self, asm: InFile<&ast::AsmExpr>, + line: usize, offset: TextSize, ) -> Option<(DefWithBodyId, (ExprId, TextRange, usize))> { let (def, _, body_source_map) = self.def.as_ref()?; let (expr, args) = body_source_map.asm_template_args(asm)?; Some(*def).zip( - args.iter() + args.get(line)? + .iter() .find(|(range, _)| range.contains_inclusive(offset)) .map(|(range, idx)| (expr, *range, *idx)), ) @@ -944,7 +946,7 @@ impl SourceAnalyzer { pub(crate) fn as_asm_parts( &self, asm: InFile<&ast::AsmExpr>, - ) -> Option<(DefWithBodyId, (ExprId, &[(TextRange, usize)]))> { + ) -> Option<(DefWithBodyId, (ExprId, &[Vec<(TextRange, usize)>]))> { let (def, _, body_source_map) = self.def.as_ref()?; Some(*def).zip(body_source_map.asm_template_args(asm)) } diff --git a/src/tools/rust-analyzer/crates/ide/src/highlight_related.rs b/src/tools/rust-analyzer/crates/ide/src/highlight_related.rs index 5348e855be4b0..4c8e3fc3040c2 100644 --- a/src/tools/rust-analyzer/crates/ide/src/highlight_related.rs +++ b/src/tools/rust-analyzer/crates/ide/src/highlight_related.rs @@ -2004,6 +2004,36 @@ fn main() { { return; } +"#, + ) + } + + #[test] + fn asm() { + check( + r#" +//- minicore: asm +#[inline] +pub unsafe fn bootstrap() -> ! { + builtin#asm( + "blabla", + "mrs {tmp}, CONTROL", + // ^^^ read + "blabla", + "bics {tmp}, {spsel}", + // ^^^ read + "blabla", + "msr CONTROL, {tmp}", + // ^^^ read + "blabla", + tmp$0 = inout(reg) 0, + // ^^^ + aaa = in(reg) 2, + aaa = in(reg) msp, + aaa = in(reg) rv, + options(noreturn, nomem, nostack), + ); +} "#, ) } diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_asm.html b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_asm.html index d830a3887217b..15a6386aa3c88 100644 --- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_asm.html +++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_asm.html @@ -50,9 +50,9 @@ let foo = 1; let mut o = 0; core::arch::asm!( - "%input = OpLoad _ {0}", + "%input = OpLoad _ {0}", concat!("%result = ", "bar", " _ %input"), - "OpStore {1} %result", + "OpStore {1} %result", in(reg) &foo, in(reg) &mut o, ); @@ -94,4 +94,26 @@ options(noreturn), ); } +} +// taken from https://github.com/rust-embedded/cortex-m/blob/47921b51f8b960344fcfa1255a50a0d19efcde6d/cortex-m/src/asm.rs#L254-L274 +#[inline] +pub unsafe fn bootstrap(msp: *const u32, rv: *const u32) -> ! { + // Ensure thumb mode is set. + let rv = (rv as u32) | 1; + let msp = msp as u32; + core::arch::asm!( + "mrs {tmp}, CONTROL", + "bics {tmp}, {spsel}", + "msr CONTROL, {tmp}", + "isb", + "msr MSP, {msp}", + "bx {rv}", + // `out(reg) _` is not permitted in a `noreturn` asm! call, + // so instead use `in(reg) 0` and don't restore it afterwards. + tmp = in(reg) 0, + spsel = in(reg) 2, + msp = in(reg) msp, + rv = in(reg) rv, + options(noreturn, nomem, nostack), + ); } \ No newline at end of file diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_strings.html b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_strings.html index d5b9fc0e2c421..5594a36e7318f 100644 --- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_strings.html +++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_strings.html @@ -167,7 +167,7 @@ let o: u64; core::arch::asm!( "mov {0}, {1}", - "add {0}, 5", + "add {0}, 5", out(reg) o, in(reg) i, ); diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/tests.rs b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/tests.rs index f47b2115bfc68..82833d716b533 100644 --- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/tests.rs +++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/tests.rs @@ -1331,6 +1331,28 @@ fn main() { ); } } +// taken from https://github.com/rust-embedded/cortex-m/blob/47921b51f8b960344fcfa1255a50a0d19efcde6d/cortex-m/src/asm.rs#L254-L274 +#[inline] +pub unsafe fn bootstrap(msp: *const u32, rv: *const u32) -> ! { + // Ensure thumb mode is set. + let rv = (rv as u32) | 1; + let msp = msp as u32; + core::arch::asm!( + "mrs {tmp}, CONTROL", + "bics {tmp}, {spsel}", + "msr CONTROL, {tmp}", + "isb", + "msr MSP, {msp}", + "bx {rv}", + // `out(reg) _` is not permitted in a `noreturn` asm! call, + // so instead use `in(reg) 0` and don't restore it afterwards. + tmp = in(reg) 0, + spsel = in(reg) 2, + msp = in(reg) msp, + rv = in(reg) rv, + options(noreturn, nomem, nostack), + ); +} "#, expect_file!["./test_data/highlight_asm.html"], false, diff --git a/src/tools/rust-analyzer/crates/parser/src/grammar/expressions/atom.rs b/src/tools/rust-analyzer/crates/parser/src/grammar/expressions/atom.rs index 39ca26fc508c4..a1a3e9470923b 100644 --- a/src/tools/rust-analyzer/crates/parser/src/grammar/expressions/atom.rs +++ b/src/tools/rust-analyzer/crates/parser/src/grammar/expressions/atom.rs @@ -361,16 +361,20 @@ fn parse_asm_expr(p: &mut Parser<'_>, m: Marker) -> Option { if p.eat(T![in]) || p.eat_contextual_kw(T![out]) || p.eat_contextual_kw(T![lateout]) { dir_spec.complete(p, ASM_DIR_SPEC); parse_reg(p); + let op_expr = p.start(); expr(p); + op_expr.complete(p, ASM_OPERAND_EXPR); op.complete(p, ASM_REG_OPERAND); op_n.complete(p, ASM_OPERAND_NAMED); } else if p.eat_contextual_kw(T![inout]) || p.eat_contextual_kw(T![inlateout]) { dir_spec.complete(p, ASM_DIR_SPEC); parse_reg(p); + let op_expr = p.start(); expr(p); if p.eat(T![=>]) { expr(p); } + op_expr.complete(p, ASM_OPERAND_EXPR); op.complete(p, ASM_REG_OPERAND); op_n.complete(p, ASM_OPERAND_NAMED); } else if p.eat_contextual_kw(T![label]) { diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/asm_expr.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/asm_expr.rast index 4afa9daf5904b..f0213d0b5e36a 100644 --- a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/asm_expr.rast +++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/asm_expr.rast @@ -50,11 +50,12 @@ SOURCE_FILE IDENT "reg" R_PAREN ")" WHITESPACE " " - PATH_EXPR - PATH - PATH_SEGMENT - NAME_REF - IDENT "x" + ASM_OPERAND_EXPR + PATH_EXPR + PATH + PATH_SEGMENT + NAME_REF + IDENT "x" COMMA "," WHITESPACE "\n " ASM_OPERAND_NAMED @@ -72,8 +73,9 @@ SOURCE_FILE IDENT "reg" R_PAREN ")" WHITESPACE " " - UNDERSCORE_EXPR - UNDERSCORE "_" + ASM_OPERAND_EXPR + UNDERSCORE_EXPR + UNDERSCORE "_" COMMA "," WHITESPACE "\n " R_PAREN ")" From 13d56dc160a6bf9fca92b86307c50672e3906293 Mon Sep 17 00:00:00 2001 From: arnaudgolfouse Date: Thu, 5 Sep 2024 16:00:48 +0200 Subject: [PATCH 0541/2194] Use a `Vec` in `rustc_interface::Config::locale_resources` This allows a third-party tool to injects its own resources, when receiving the config via `rustc_driver::Callbacks::config`. --- compiler/rustc_driver_impl/src/lib.rs | 2 +- compiler/rustc_interface/src/interface.rs | 4 +++- src/librustdoc/core.rs | 2 +- src/librustdoc/doctest.rs | 2 +- tests/ui-fulldeps/run-compiler-twice.rs | 2 +- 5 files changed, 7 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index cb2fa6e9d746b..b32273fb0c93f 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -321,7 +321,7 @@ fn run_compiler( output_dir: odir, ice_file, file_loader, - locale_resources: DEFAULT_LOCALE_RESOURCES, + locale_resources: DEFAULT_LOCALE_RESOURCES.to_vec(), lint_caps: Default::default(), psess_created: None, hash_untracked_state: None, diff --git a/compiler/rustc_interface/src/interface.rs b/compiler/rustc_interface/src/interface.rs index 04e2b7d45dc93..347dc185043e4 100644 --- a/compiler/rustc_interface/src/interface.rs +++ b/compiler/rustc_interface/src/interface.rs @@ -311,7 +311,9 @@ pub struct Config { pub output_file: Option, pub ice_file: Option, pub file_loader: Option>, - pub locale_resources: &'static [&'static str], + /// The list of fluent resources, used for lints declared with + /// [`Diagnostic`](rustc_errors::Diagnostic) and [`LintDiagnostic`](rustc_errors::LintDiagnostic). + pub locale_resources: Vec<&'static str>, pub lint_caps: FxHashMap, diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index 2cde0ac5c5354..b93cd02fca639 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -262,7 +262,7 @@ pub(crate) fn create_config( output_file: None, output_dir: None, file_loader: None, - locale_resources: rustc_driver::DEFAULT_LOCALE_RESOURCES, + locale_resources: rustc_driver::DEFAULT_LOCALE_RESOURCES.to_vec(), lint_caps, psess_created: None, hash_untracked_state: None, diff --git a/src/librustdoc/doctest.rs b/src/librustdoc/doctest.rs index 8b6588ea75c83..04b0b6f08db77 100644 --- a/src/librustdoc/doctest.rs +++ b/src/librustdoc/doctest.rs @@ -139,7 +139,7 @@ pub(crate) fn run(dcx: DiagCtxtHandle<'_>, options: RustdocOptions) -> Result<() output_file: None, output_dir: None, file_loader: None, - locale_resources: rustc_driver::DEFAULT_LOCALE_RESOURCES, + locale_resources: rustc_driver::DEFAULT_LOCALE_RESOURCES.to_vec(), lint_caps, psess_created: None, hash_untracked_state: None, diff --git a/tests/ui-fulldeps/run-compiler-twice.rs b/tests/ui-fulldeps/run-compiler-twice.rs index 720fc42cc5700..cce4eac0d7c15 100644 --- a/tests/ui-fulldeps/run-compiler-twice.rs +++ b/tests/ui-fulldeps/run-compiler-twice.rs @@ -65,7 +65,7 @@ fn compile(code: String, output: PathBuf, sysroot: PathBuf, linker: Option<&Path output_dir: None, ice_file: None, file_loader: None, - locale_resources: &[], + locale_resources: Vec::new(), lint_caps: Default::default(), psess_created: None, hash_untracked_state: None, From 40fca8f7a8131129b75694109138891e607baab0 Mon Sep 17 00:00:00 2001 From: Philipp Krones Date: Thu, 5 Sep 2024 17:00:55 +0200 Subject: [PATCH 0542/2194] Bump Clippy version -> 0.1.83 --- Cargo.toml | 2 +- clippy_config/Cargo.toml | 2 +- clippy_lints/Cargo.toml | 2 +- clippy_utils/Cargo.toml | 2 +- declare_clippy_lint/Cargo.toml | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index b48b881097f47..5b62e387ac631 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy" -version = "0.1.82" +version = "0.1.83" description = "A bunch of helpful lints to avoid common pitfalls in Rust" repository = "https://github.com/rust-lang/rust-clippy" readme = "README.md" diff --git a/clippy_config/Cargo.toml b/clippy_config/Cargo.toml index 5c4e0761dbca7..9da7112345de9 100644 --- a/clippy_config/Cargo.toml +++ b/clippy_config/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy_config" -version = "0.1.82" +version = "0.1.83" edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/clippy_lints/Cargo.toml b/clippy_lints/Cargo.toml index fbd4566da58c7..d1188940b46a8 100644 --- a/clippy_lints/Cargo.toml +++ b/clippy_lints/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy_lints" -version = "0.1.82" +version = "0.1.83" description = "A bunch of helpful lints to avoid common pitfalls in Rust" repository = "https://github.com/rust-lang/rust-clippy" readme = "README.md" diff --git a/clippy_utils/Cargo.toml b/clippy_utils/Cargo.toml index 629ce9d04d432..fe30b10c435ed 100644 --- a/clippy_utils/Cargo.toml +++ b/clippy_utils/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy_utils" -version = "0.1.82" +version = "0.1.83" edition = "2021" publish = false diff --git a/declare_clippy_lint/Cargo.toml b/declare_clippy_lint/Cargo.toml index 31270241b0b2e..67a1f7cc72c54 100644 --- a/declare_clippy_lint/Cargo.toml +++ b/declare_clippy_lint/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "declare_clippy_lint" -version = "0.1.82" +version = "0.1.83" edition = "2021" publish = false From 3d027d75aff29983cb95da07352bcb8a55487400 Mon Sep 17 00:00:00 2001 From: Philipp Krones Date: Thu, 5 Sep 2024 17:01:08 +0200 Subject: [PATCH 0543/2194] Bump nightly version -> 2024-09-05 --- rust-toolchain | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust-toolchain b/rust-toolchain index 0be2e81810ebe..854fcda2dabda 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1,4 +1,4 @@ [toolchain] -channel = "nightly-2024-08-23" +channel = "nightly-2024-09-05" components = ["cargo", "llvm-tools", "rust-src", "rust-std", "rustc", "rustc-dev", "rustfmt"] profile = "minimal" From 4e2e1bf6edc75a75bfb86c912c6f1c23672e531c Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Thu, 5 Sep 2024 15:23:28 +0200 Subject: [PATCH 0544/2194] fix: Fix parser panicking on invalid asm options --- src/tools/rust-analyzer/crates/hir-ty/src/tests/macros.rs | 5 +++++ .../crates/parser/src/grammar/expressions/atom.rs | 1 + 2 files changed, 6 insertions(+) diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/tests/macros.rs b/src/tools/rust-analyzer/crates/hir-ty/src/tests/macros.rs index 10ab6d3ff8939..53b69c12f05d5 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/tests/macros.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/tests/macros.rs @@ -1498,6 +1498,11 @@ fn main() { 43..44 '1': i32 58..63 'mut o': i32 66..67 '0': i32 + !95..104 'thread_id': usize + !103..107 '&foo': &'? i32 + !104..107 'foo': i32 + !115..120 '&muto': &'? mut i32 + !119..120 'o': i32 293..294 'o': i32 308..317 'thread_id': usize "#]], diff --git a/src/tools/rust-analyzer/crates/parser/src/grammar/expressions/atom.rs b/src/tools/rust-analyzer/crates/parser/src/grammar/expressions/atom.rs index a1a3e9470923b..2333e6c862be5 100644 --- a/src/tools/rust-analyzer/crates/parser/src/grammar/expressions/atom.rs +++ b/src/tools/rust-analyzer/crates/parser/src/grammar/expressions/atom.rs @@ -434,6 +434,7 @@ fn parse_options(p: &mut Parser<'_>) { let m = p.start(); if !OPTIONS.iter().any(|&syntax| p.eat_contextual_kw(syntax)) { p.err_and_bump("expected asm option"); + m.abandon(p); continue; } m.complete(p, ASM_OPTION); From 0091b8ab2a16aea880e2fe5d3c876f4f743640d5 Mon Sep 17 00:00:00 2001 From: Boxy Date: Thu, 5 Sep 2024 17:23:40 +0100 Subject: [PATCH 0545/2194] update cfgs --- compiler/rustc_codegen_llvm/src/lib.rs | 1 - compiler/rustc_driver_impl/src/lib.rs | 1 - compiler/rustc_llvm/src/lib.rs | 1 - compiler/rustc_middle/src/lib.rs | 1 - compiler/rustc_target/src/lib.rs | 1 - compiler/rustc_transmute/src/layout/nfa.rs | 2 -- compiler/rustc_type_ir/src/fold.rs | 4 --- .../src/collections/vec_deque/into_iter.rs | 4 --- library/core/src/arch.rs | 9 ------ library/core/src/cell.rs | 6 ++-- library/core/src/clone.rs | 2 +- library/core/src/default.rs | 2 +- library/core/src/intrinsics.rs | 7 ----- library/core/src/lib.rs | 4 --- library/core/src/marker.rs | 17 +++-------- library/core/src/mem/manually_drop.rs | 2 +- library/core/src/mem/maybe_uninit.rs | 2 +- library/core/src/mem/mod.rs | 1 - library/core/src/mem/transmutability.rs | 29 +++++++------------ library/core/src/pin.rs | 2 +- library/core/src/tuple.rs | 2 +- library/core/tests/lib.rs | 1 - library/panic_unwind/src/seh.rs | 6 ---- library/std/src/env.rs | 16 +++------- library/std/src/lib.rs | 1 - library/std/src/os/unix/process.rs | 6 +--- src/tools/miri/src/eval.rs | 7 ----- 27 files changed, 28 insertions(+), 109 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/lib.rs b/compiler/rustc_codegen_llvm/src/lib.rs index 6a303e1e6024b..7f26bbd7f8757 100644 --- a/compiler/rustc_codegen_llvm/src/lib.rs +++ b/compiler/rustc_codegen_llvm/src/lib.rs @@ -6,7 +6,6 @@ // tidy-alphabetical-start #![allow(internal_features)] -#![cfg_attr(bootstrap, feature(unsafe_extern_blocks))] #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![doc(rust_logo)] #![feature(assert_matches)] diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index e49ae60e890ba..8e4d3c08006c9 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -7,7 +7,6 @@ // tidy-alphabetical-start #![allow(internal_features)] #![allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable -#![cfg_attr(bootstrap, feature(unsafe_extern_blocks))] #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![doc(rust_logo)] #![feature(decl_macro)] diff --git a/compiler/rustc_llvm/src/lib.rs b/compiler/rustc_llvm/src/lib.rs index 3532d50c64e87..055d2bd5bc976 100644 --- a/compiler/rustc_llvm/src/lib.rs +++ b/compiler/rustc_llvm/src/lib.rs @@ -1,6 +1,5 @@ // tidy-alphabetical-start #![allow(internal_features)] -#![cfg_attr(bootstrap, feature(unsafe_attributes, unsafe_extern_blocks))] #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![doc(rust_logo)] #![feature(rustdoc_internals)] diff --git a/compiler/rustc_middle/src/lib.rs b/compiler/rustc_middle/src/lib.rs index 2a85f85a9f4eb..fd6e2ad79b11d 100644 --- a/compiler/rustc_middle/src/lib.rs +++ b/compiler/rustc_middle/src/lib.rs @@ -28,7 +28,6 @@ #![allow(rustc::diagnostic_outside_of_impl)] #![allow(rustc::potential_query_instability)] #![allow(rustc::untranslatable_diagnostic)] -#![cfg_attr(bootstrap, feature(min_exhaustive_patterns, unsafe_extern_blocks))] #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![doc(rust_logo)] #![feature(allocator_api)] diff --git a/compiler/rustc_target/src/lib.rs b/compiler/rustc_target/src/lib.rs index d7c66d6f5e3d6..2121c4110dde6 100644 --- a/compiler/rustc_target/src/lib.rs +++ b/compiler/rustc_target/src/lib.rs @@ -9,7 +9,6 @@ // tidy-alphabetical-start #![allow(internal_features)] -#![cfg_attr(bootstrap, feature(min_exhaustive_patterns))] #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![doc(rust_logo)] #![feature(assert_matches)] diff --git a/compiler/rustc_transmute/src/layout/nfa.rs b/compiler/rustc_transmute/src/layout/nfa.rs index 5db5a8f222db0..3b49c59fa6867 100644 --- a/compiler/rustc_transmute/src/layout/nfa.rs +++ b/compiler/rustc_transmute/src/layout/nfa.rs @@ -87,8 +87,6 @@ where pub(crate) fn from_tree(tree: Tree) -> Result { Ok(match tree { Tree::Byte(b) => Self::from_byte(b), - #[cfg(bootstrap)] - Tree::Def(..) => unreachable!(), Tree::Ref(r) => Self::from_ref(r), Tree::Alt(alts) => { let mut alts = alts.into_iter().map(Self::from_tree); diff --git a/compiler/rustc_type_ir/src/fold.rs b/compiler/rustc_type_ir/src/fold.rs index f49aa3431b5c0..64ce6fd69e6ba 100644 --- a/compiler/rustc_type_ir/src/fold.rs +++ b/compiler/rustc_type_ir/src/fold.rs @@ -91,8 +91,6 @@ pub trait TypeFoldable: TypeVisitable { fn fold_with>(self, folder: &mut F) -> Self { match self.try_fold_with(folder) { Ok(t) => t, - #[cfg(bootstrap)] - Err(e) => match e {}, } } } @@ -116,8 +114,6 @@ pub trait TypeSuperFoldable: TypeFoldable { fn super_fold_with>(self, folder: &mut F) -> Self { match self.try_super_fold_with(folder) { Ok(t) => t, - #[cfg(bootstrap)] - Err(e) => match e {}, } } } diff --git a/library/alloc/src/collections/vec_deque/into_iter.rs b/library/alloc/src/collections/vec_deque/into_iter.rs index 7be3de16b2da7..2b09a5e7ddc58 100644 --- a/library/alloc/src/collections/vec_deque/into_iter.rs +++ b/library/alloc/src/collections/vec_deque/into_iter.rs @@ -121,8 +121,6 @@ impl Iterator for IntoIter { { match self.try_fold(init, |b, item| Ok::(f(b, item))) { Ok(b) => b, - #[cfg(bootstrap)] - Err(e) => match e {}, } } @@ -243,8 +241,6 @@ impl DoubleEndedIterator for IntoIter { { match self.try_rfold(init, |b, item| Ok::(f(b, item))) { Ok(b) => b, - #[cfg(bootstrap)] - Err(e) => match e {}, } } } diff --git a/library/core/src/arch.rs b/library/core/src/arch.rs index d681bd124fe13..31d6bc36fc8b9 100644 --- a/library/core/src/arch.rs +++ b/library/core/src/arch.rs @@ -4,15 +4,6 @@ #[stable(feature = "simd_arch", since = "1.27.0")] pub use crate::core_arch::arch::*; -#[cfg(bootstrap)] -#[allow(dead_code)] -#[unstable(feature = "sha512_sm_x86", issue = "126624")] -fn dummy() { - // AArch64 also has a target feature named `sm4`, so we need `#![feature(sha512_sm_x86)]` in lib.rs - // But as the bootstrap compiler doesn't know about this feature yet, we need to convert it to a - // library feature until bootstrap gets bumped -} - /// Inline assembly. /// /// Refer to [Rust By Example] for a usage guide and the [reference] for diff --git a/library/core/src/cell.rs b/library/core/src/cell.rs index 5dd9721d3fee8..a3a471a57c7aa 100644 --- a/library/core/src/cell.rs +++ b/library/core/src/cell.rs @@ -306,7 +306,7 @@ pub use once::OnceCell; /// See the [module-level documentation](self) for more. #[stable(feature = "rust1", since = "1.0.0")] #[repr(transparent)] -#[cfg_attr(not(bootstrap), rustc_pub_transparent)] +#[rustc_pub_transparent] pub struct Cell { value: UnsafeCell, } @@ -2056,7 +2056,7 @@ impl fmt::Display for RefMut<'_, T> { #[lang = "unsafe_cell"] #[stable(feature = "rust1", since = "1.0.0")] #[repr(transparent)] -#[cfg_attr(not(bootstrap), rustc_pub_transparent)] +#[rustc_pub_transparent] pub struct UnsafeCell { value: T, } @@ -2299,7 +2299,7 @@ impl UnsafeCell<*mut T> { /// See [`UnsafeCell`] for details. #[unstable(feature = "sync_unsafe_cell", issue = "95439")] #[repr(transparent)] -#[cfg_attr(not(bootstrap), rustc_pub_transparent)] +#[rustc_pub_transparent] pub struct SyncUnsafeCell { value: UnsafeCell, } diff --git a/library/core/src/clone.rs b/library/core/src/clone.rs index 2150463067205..c5f8bd7401e5e 100644 --- a/library/core/src/clone.rs +++ b/library/core/src/clone.rs @@ -161,7 +161,7 @@ pub trait Clone: Sized { #[must_use = "cloning is often expensive and is not expected to have side effects"] // Clone::clone is special because the compiler generates MIR to implement it for some types. // See InstanceKind::CloneShim. - #[cfg_attr(not(bootstrap), lang = "clone_fn")] + #[lang = "clone_fn"] fn clone(&self) -> Self; /// Performs copy-assignment from `source`. diff --git a/library/core/src/default.rs b/library/core/src/default.rs index 5cacedcb241a5..4c30290ff263b 100644 --- a/library/core/src/default.rs +++ b/library/core/src/default.rs @@ -103,7 +103,7 @@ use crate::ascii::Char as AsciiChar; /// ``` #[cfg_attr(not(test), rustc_diagnostic_item = "Default")] #[stable(feature = "rust1", since = "1.0.0")] -#[cfg_attr(not(bootstrap), rustc_trivial_field_reads)] +#[rustc_trivial_field_reads] pub trait Default: Sized { /// Returns the "default value" for a type. /// diff --git a/library/core/src/intrinsics.rs b/library/core/src/intrinsics.rs index 8cb9accd59db4..7870a62ea81cd 100644 --- a/library/core/src/intrinsics.rs +++ b/library/core/src/intrinsics.rs @@ -1020,7 +1020,6 @@ pub const fn unlikely(b: bool) -> bool { /// any safety invariants. /// /// This intrinsic does not have a stable counterpart. -#[cfg(not(bootstrap))] #[unstable(feature = "core_intrinsics", issue = "none")] #[rustc_intrinsic] #[rustc_nounwind] @@ -1030,12 +1029,6 @@ pub fn select_unpredictable(b: bool, true_val: T, false_val: T) -> T { if b { true_val } else { false_val } } -#[cfg(bootstrap)] -#[inline] -pub fn select_unpredictable(b: bool, true_val: T, false_val: T) -> T { - if b { true_val } else { false_val } -} - extern "rust-intrinsic" { /// Executes a breakpoint trap, for inspection by a debugger. /// diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index e60bcf3aa5db7..50e9884fea1b4 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -107,7 +107,6 @@ // // Library features: // tidy-alphabetical-start -#![cfg_attr(bootstrap, feature(offset_of_nested))] #![feature(array_ptr_get)] #![feature(asm_experimental_arch)] #![feature(const_align_of_val)] @@ -192,9 +191,6 @@ // // Language features: // tidy-alphabetical-start -#![cfg_attr(bootstrap, feature(asm_const))] -#![cfg_attr(bootstrap, feature(const_fn_floating_point_arithmetic))] -#![cfg_attr(bootstrap, feature(min_exhaustive_patterns))] #![feature(abi_unadjusted)] #![feature(adt_const_params)] #![feature(allow_internal_unsafe)] diff --git a/library/core/src/marker.rs b/library/core/src/marker.rs index 5654f5aa4b8d2..84bb0119453f2 100644 --- a/library/core/src/marker.rs +++ b/library/core/src/marker.rs @@ -992,7 +992,7 @@ pub macro ConstParamTy($item:item) { /* compiler built-in */ } -#[cfg_attr(not(bootstrap), lang = "unsized_const_param_ty")] +#[lang = "unsized_const_param_ty"] #[unstable(feature = "unsized_const_params", issue = "95174")] #[diagnostic::on_unimplemented(message = "`{Self}` can't be used as a const parameter type")] /// A marker for types which can be used as types of `const` generic parameters. @@ -1002,10 +1002,9 @@ pub macro ConstParamTy($item:item) { pub trait UnsizedConstParamTy: StructuralPartialEq + Eq {} /// Derive macro generating an impl of the trait `ConstParamTy`. -#[cfg(not(bootstrap))] -#[cfg_attr(not(bootstrap), rustc_builtin_macro)] -#[cfg_attr(not(bootstrap), allow_internal_unstable(unsized_const_params))] -#[cfg_attr(not(bootstrap), unstable(feature = "unsized_const_params", issue = "95174"))] +#[rustc_builtin_macro] +#[allow_internal_unstable(unsized_const_params)] +#[unstable(feature = "unsized_const_params", issue = "95174")] pub macro UnsizedConstParamTy($item:item) { /* compiler built-in */ } @@ -1021,14 +1020,6 @@ marker_impls! { (), {T: ConstParamTy_, const N: usize} [T; N], } -#[cfg(bootstrap)] -marker_impls! { - #[unstable(feature = "adt_const_params", issue = "95174")] - ConstParamTy_ for - str, - {T: ConstParamTy_} [T], - {T: ConstParamTy_ + ?Sized} &T, -} marker_impls! { #[unstable(feature = "unsized_const_params", issue = "95174")] diff --git a/library/core/src/mem/manually_drop.rs b/library/core/src/mem/manually_drop.rs index be5cee2e85267..3e47785ee488e 100644 --- a/library/core/src/mem/manually_drop.rs +++ b/library/core/src/mem/manually_drop.rs @@ -47,7 +47,7 @@ use crate::ptr; #[lang = "manually_drop"] #[derive(Copy, Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)] #[repr(transparent)] -#[cfg_attr(not(bootstrap), rustc_pub_transparent)] +#[rustc_pub_transparent] pub struct ManuallyDrop { value: T, } diff --git a/library/core/src/mem/maybe_uninit.rs b/library/core/src/mem/maybe_uninit.rs index c308def2f574a..4be2e5ef1eade 100644 --- a/library/core/src/mem/maybe_uninit.rs +++ b/library/core/src/mem/maybe_uninit.rs @@ -237,7 +237,7 @@ use crate::{fmt, intrinsics, ptr, slice}; #[lang = "maybe_uninit"] #[derive(Copy)] #[repr(transparent)] -#[cfg_attr(not(bootstrap), rustc_pub_transparent)] +#[rustc_pub_transparent] pub union MaybeUninit { uninit: (), value: ManuallyDrop, diff --git a/library/core/src/mem/mod.rs b/library/core/src/mem/mod.rs index fed484ae3cd12..414262fcf5ab1 100644 --- a/library/core/src/mem/mod.rs +++ b/library/core/src/mem/mod.rs @@ -1326,7 +1326,6 @@ impl SizedTypeProperties for T {} /// # Examples /// /// ``` -/// # #![cfg_attr(bootstrap, feature(offset_of_nested))] /// #![feature(offset_of_enum)] /// /// use std::mem; diff --git a/library/core/src/mem/transmutability.rs b/library/core/src/mem/transmutability.rs index cda999a7f0c91..7fa3c33439170 100644 --- a/library/core/src/mem/transmutability.rs +++ b/library/core/src/mem/transmutability.rs @@ -43,8 +43,7 @@ use crate::marker::{ConstParamTy_, UnsizedConstParamTy}; /// conversions that extend the bits of `Src` with trailing padding to fill /// trailing uninitialized bytes of `Self`; e.g.: /// -#[cfg_attr(bootstrap, doc = "```rust,ignore not runnable on bootstrap")] -#[cfg_attr(not(bootstrap), doc = "```rust")] +/// ```rust /// #![feature(transmutability)] /// /// use core::mem::{Assume, TransmuteFrom}; @@ -151,8 +150,7 @@ pub struct Assume { /// When `false`, [`TransmuteFrom`] is not implemented for transmutations /// that might violate the alignment requirements of references; e.g.: /// - #[cfg_attr(bootstrap, doc = "```rust,ignore not runnable on bootstrap")] - #[cfg_attr(not(bootstrap), doc = "```compile_fail,E0277")] + /// ```compile_fail,E0277 /// #![feature(transmutability)] /// use core::mem::{align_of, TransmuteFrom}; /// @@ -171,8 +169,7 @@ pub struct Assume { /// that references in the transmuted value satisfy the alignment /// requirements of their referent types; e.g.: /// - #[cfg_attr(bootstrap, doc = "```rust,ignore not runnable on bootstrap")] - #[cfg_attr(not(bootstrap), doc = "```rust")] + /// ```rust /// #![feature(pointer_is_aligned_to, transmutability)] /// use core::mem::{align_of, Assume, TransmuteFrom}; /// @@ -203,8 +200,7 @@ pub struct Assume { /// that might violate the library safety invariants of the destination /// type; e.g.: /// - #[cfg_attr(bootstrap, doc = "```rust,ignore not runnable on bootstrap")] - #[cfg_attr(not(bootstrap), doc = "```compile_fail,E0277")] + /// ```compile_fail,E0277 /// #![feature(transmutability)] /// use core::mem::TransmuteFrom; /// @@ -225,8 +221,7 @@ pub struct Assume { /// that undefined behavior does not arise from using the transmuted value; /// e.g.: /// - #[cfg_attr(bootstrap, doc = "```rust,ignore not runnable on bootstrap")] - #[cfg_attr(not(bootstrap), doc = "```rust")] + /// ```rust /// #![feature(transmutability)] /// use core::mem::{Assume, TransmuteFrom}; /// @@ -254,8 +249,7 @@ pub struct Assume { /// that might violate the language-level bit-validity invariant of the /// destination type; e.g.: /// - #[cfg_attr(bootstrap, doc = "```rust,ignore not runnable on bootstrap")] - #[cfg_attr(not(bootstrap), doc = "```compile_fail,E0277")] + /// ```compile_fail,E0277 /// #![feature(transmutability)] /// use core::mem::TransmuteFrom; /// @@ -271,8 +265,7 @@ pub struct Assume { /// that the value being transmuted is a bit-valid instance of the /// transmuted value; e.g.: /// - #[cfg_attr(bootstrap, doc = "```rust,ignore not runnable on bootstrap")] - #[cfg_attr(not(bootstrap), doc = "```rust")] + /// ```rust /// #![feature(transmutability)] /// use core::mem::{Assume, TransmuteFrom}; /// @@ -335,9 +328,7 @@ impl Assume { /// This is especially useful for extending [`Assume`] in generic contexts; /// e.g.: /// - #[cfg_attr(bootstrap, doc = "```rust,ignore not runnable on bootstrap")] - #[cfg_attr(not(bootstrap), doc = "```rust")] - #[unstable(feature = "transmutability", issue = "99571")] + /// ```rust /// #![feature( /// adt_const_params, /// generic_const_exprs, @@ -379,6 +370,7 @@ impl Assume { /// try_transmute_ref::<_, _, { Assume::NOTHING }>(src) /// }; ///``` + #[unstable(feature = "transmutability", issue = "99571")] pub const fn and(self, other_assumptions: Self) -> Self { Self { alignment: self.alignment || other_assumptions.alignment, @@ -390,8 +382,7 @@ impl Assume { /// Remove `other_assumptions` the obligations of `self`; e.g.: /// - #[cfg_attr(bootstrap, doc = "```rust,ignore not runnable on bootstrap")] - #[cfg_attr(not(bootstrap), doc = "```rust")] + /// ```rust /// #![feature(transmutability)] /// use core::mem::Assume; /// diff --git a/library/core/src/pin.rs b/library/core/src/pin.rs index 65f6bfb7ee176..9c13662e08e8f 100644 --- a/library/core/src/pin.rs +++ b/library/core/src/pin.rs @@ -1084,7 +1084,7 @@ use crate::{cmp, fmt}; #[lang = "pin"] #[fundamental] #[repr(transparent)] -#[cfg_attr(not(bootstrap), rustc_pub_transparent)] +#[rustc_pub_transparent] #[derive(Copy, Clone)] pub struct Pin { // FIXME(#93176): this field is made `#[unstable] #[doc(hidden)] pub` to: diff --git a/library/core/src/tuple.rs b/library/core/src/tuple.rs index 9ec92e2845034..206b5b9e2c24f 100644 --- a/library/core/src/tuple.rs +++ b/library/core/src/tuple.rs @@ -154,7 +154,7 @@ macro_rules! tuple_impls { // Otherwise, it hides the docs entirely. macro_rules! maybe_tuple_doc { ($a:ident @ #[$meta:meta] $item:item) => { - #[cfg_attr(not(bootstrap), doc(fake_variadic))] + #[doc(fake_variadic)] #[doc = "This trait is implemented for tuples up to twelve items long."] #[$meta] $item diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs index c205f028dd3a7..1bee17bc2b92c 100644 --- a/library/core/tests/lib.rs +++ b/library/core/tests/lib.rs @@ -1,5 +1,4 @@ // tidy-alphabetical-start -#![cfg_attr(bootstrap, feature(offset_of_nested))] #![cfg_attr(target_has_atomic = "128", feature(integer_atomics))] #![cfg_attr(test, feature(cfg_match))] #![feature(alloc_layout_extra)] diff --git a/library/panic_unwind/src/seh.rs b/library/panic_unwind/src/seh.rs index 82c248c5a7ba1..070c11926f6e0 100644 --- a/library/panic_unwind/src/seh.rs +++ b/library/panic_unwind/src/seh.rs @@ -157,9 +157,6 @@ mod imp { // going to be cross-lang LTOed anyway. However, using expose is shorter and // requires less unsafe. let addr: usize = ptr.expose_provenance(); - #[cfg(bootstrap)] - let image_base = unsafe { addr_of!(__ImageBase) }.addr(); - #[cfg(not(bootstrap))] let image_base = addr_of!(__ImageBase).addr(); let offset: usize = addr - image_base; Self(offset as u32) @@ -253,9 +250,6 @@ extern "C" { // This is fine since the MSVC runtime uses string comparison on the type name // to match TypeDescriptors rather than pointer equality. static mut TYPE_DESCRIPTOR: _TypeDescriptor = _TypeDescriptor { - #[cfg(bootstrap)] - pVFTable: unsafe { addr_of!(TYPE_INFO_VTABLE) } as *const _, - #[cfg(not(bootstrap))] pVFTable: addr_of!(TYPE_INFO_VTABLE) as *const _, spare: core::ptr::null_mut(), name: TYPE_NAME, diff --git a/library/std/src/env.rs b/library/std/src/env.rs index e06a851658c03..28916130b1900 100644 --- a/library/std/src/env.rs +++ b/library/std/src/env.rs @@ -354,12 +354,8 @@ impl Error for VarError { /// } /// assert_eq!(env::var(key), Ok("VALUE".to_string())); /// ``` -#[cfg_attr(bootstrap, rustc_deprecated_safe_2024)] -#[cfg_attr( - not(bootstrap), - rustc_deprecated_safe_2024( - audit_that = "the environment access only happens in single-threaded code" - ) +#[rustc_deprecated_safe_2024( + audit_that = "the environment access only happens in single-threaded code" )] #[stable(feature = "env", since = "1.0.0")] pub unsafe fn set_var, V: AsRef>(key: K, value: V) { @@ -424,12 +420,8 @@ pub unsafe fn set_var, V: AsRef>(key: K, value: V) { /// } /// assert!(env::var(key).is_err()); /// ``` -#[cfg_attr(bootstrap, rustc_deprecated_safe_2024)] -#[cfg_attr( - not(bootstrap), - rustc_deprecated_safe_2024( - audit_that = "the environment access only happens in single-threaded code" - ) +#[rustc_deprecated_safe_2024( + audit_that = "the environment access only happens in single-threaded code" )] #[stable(feature = "env", since = "1.0.0")] pub unsafe fn remove_var>(key: K) { diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index 606d75668c4d5..60969af3e8541 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -272,7 +272,6 @@ // // Language features: // tidy-alphabetical-start -#![cfg_attr(bootstrap, feature(min_exhaustive_patterns))] #![feature(alloc_error_handler)] #![feature(allocator_internals)] #![feature(allow_internal_unsafe)] diff --git a/library/std/src/os/unix/process.rs b/library/std/src/os/unix/process.rs index 46202441d4e38..9aadd9491169f 100644 --- a/library/std/src/os/unix/process.rs +++ b/library/std/src/os/unix/process.rs @@ -118,11 +118,7 @@ pub trait CommandExt: Sealed { /// [`pre_exec`]: CommandExt::pre_exec #[stable(feature = "process_exec", since = "1.15.0")] #[deprecated(since = "1.37.0", note = "should be unsafe, use `pre_exec` instead")] - #[cfg_attr(bootstrap, rustc_deprecated_safe_2024)] - #[cfg_attr( - not(bootstrap), - rustc_deprecated_safe_2024(audit_that = "the closure is async-signal-safe") - )] + #[rustc_deprecated_safe_2024(audit_that = "the closure is async-signal-safe")] unsafe fn before_exec(&mut self, f: F) -> &mut process::Command where F: FnMut() -> io::Result<()> + Send + Sync + 'static, diff --git a/src/tools/miri/src/eval.rs b/src/tools/miri/src/eval.rs index bb623c66892a0..0850a8f24d96c 100644 --- a/src/tools/miri/src/eval.rs +++ b/src/tools/miri/src/eval.rs @@ -458,14 +458,7 @@ pub fn eval_entry<'tcx>( panic::resume_unwind(panic_payload) }); // `Ok` can never happen. - #[cfg(not(bootstrap))] let Err(res) = res; - #[cfg(bootstrap)] - let res = match res { - Err(res) => res, - // `Ok` can never happen - Ok(never) => match never {}, - }; // Machine cleanup. Only do this if all threads have terminated; threads that are still running // might cause Stacked Borrows errors (https://github.com/rust-lang/miri/issues/2396). From 5396124aa3617458a3c70f128a6a5b74e93de613 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Thu, 5 Sep 2024 09:31:17 -0700 Subject: [PATCH 0546/2194] Update compiler-builtins to 0.1.125 This commit updates the compiler-builtins crate from 0.1.123 to 0.1.125. The changes in this update are: * https://github.com/rust-lang/compiler-builtins/pull/682 * https://github.com/rust-lang/compiler-builtins/pull/678 * https://github.com/rust-lang/compiler-builtins/pull/685 --- library/Cargo.lock | 4 ++-- library/alloc/Cargo.toml | 2 +- library/std/Cargo.toml | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/library/Cargo.lock b/library/Cargo.lock index 54ad052c52322..ded30dd82f7b4 100644 --- a/library/Cargo.lock +++ b/library/Cargo.lock @@ -58,9 +58,9 @@ dependencies = [ [[package]] name = "compiler_builtins" -version = "0.1.123" +version = "0.1.125" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b47fcbecb558bdad78c7d3a998523c60a50dd6cd046d5fe74163e309e878fff7" +checksum = "bd02a01d7bc069bed818e956600fe437ee222dd1d6ad92bfb9db87b43b71fd87" dependencies = [ "cc", "rustc-std-workspace-core", diff --git a/library/alloc/Cargo.toml b/library/alloc/Cargo.toml index 1bd4434d4f7e9..1da947d196fd6 100644 --- a/library/alloc/Cargo.toml +++ b/library/alloc/Cargo.toml @@ -10,7 +10,7 @@ edition = "2021" [dependencies] core = { path = "../core" } -compiler_builtins = { version = "0.1.123", features = ['rustc-dep-of-std'] } +compiler_builtins = { version = "0.1.125", features = ['rustc-dep-of-std'] } [dev-dependencies] rand = { version = "0.8.5", default-features = false, features = ["alloc"] } diff --git a/library/std/Cargo.toml b/library/std/Cargo.toml index e20fe9feff114..9a31fd21dc71a 100644 --- a/library/std/Cargo.toml +++ b/library/std/Cargo.toml @@ -17,7 +17,7 @@ cfg-if = { version = "1.0", features = ['rustc-dep-of-std'] } panic_unwind = { path = "../panic_unwind", optional = true } panic_abort = { path = "../panic_abort" } core = { path = "../core", public = true } -compiler_builtins = { version = "0.1.123" } +compiler_builtins = { version = "0.1.125" } profiler_builtins = { path = "../profiler_builtins", optional = true } unwind = { path = "../unwind" } hashbrown = { version = "0.14", default-features = false, features = [ From 76f352ceb6eab4bf97be3aa3fb7f01d1fd2c6346 Mon Sep 17 00:00:00 2001 From: Samuel Marks <807580+SamuelMarks@users.noreply.github.com> Date: Thu, 5 Sep 2024 11:37:05 -0500 Subject: [PATCH 0547/2194] [library/std/src/process.rs] Update docstring with @joshtriplett's replacement text --- library/std/src/process.rs | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/library/std/src/process.rs b/library/std/src/process.rs index 727f8f5ceb660..c25383405c43b 100644 --- a/library/std/src/process.rs +++ b/library/std/src/process.rs @@ -1937,10 +1937,14 @@ impl crate::error::Error for ExitStatusError {} /// to its parent under normal termination. /// /// `ExitCode` is intended to be consumed only by the standard library (via -/// [`Termination::report()`]), and intentionally does not provide accessors like -/// `PartialEq`, `Eq`, or `Hash`. Instead the standard library provides the -/// canonical `SUCCESS` and `FAILURE` exit codes as well as `From for -/// ExitCode` for constructing other arbitrary exit codes. +/// [`Termination::report()`]). For forwards compatibility with potentially +/// unusual targets, this type currently does not provide `Eq`, `Hash`, or +/// access to the raw value. This type does provide `PartialEq` for +/// comparison, but note that there may potentially be multiple failure +/// codes, some of which will _not_ compare equal to `ExitCode::FAILURE`. +/// The standard library provides the canonical `SUCCESS` and `FAILURE` +/// exit codes as well as `From for ExitCode` for constructing other +/// arbitrary exit codes. /// /// # Portability /// From a551cccb623e0c7c52f7db9bcc424c837f848ede Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Thu, 5 Sep 2024 10:06:54 -0700 Subject: [PATCH 0548/2194] Remove wasm32-wasip2's tier 2 status from release notes It turns out the stars did not actually align for this to get released in Rust 1.81 alas. Full tier 2 status for `wasm32-wasip2` required two PRs: * #126967 - this made it into Rust 1.81 * #127867 - this didn't make the cut and is in Rust 1.82 instead This wasn't caught until just after today's release so the plan is to remove the release notes for 1.81 and coordinate to instead add these as release notes to 1.82. --- RELEASES.md | 1 - 1 file changed, 1 deletion(-) diff --git a/RELEASES.md b/RELEASES.md index 29c872eb44896..82954fad1e094 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -34,7 +34,6 @@ Compiler - [Add Tier 3 `std` Xtensa targets:](https://github.com/rust-lang/rust/pull/126380/) `xtensa-esp32-espidf`, `xtensa-esp32s2-espidf`, `xtensa-esp32s3-espidf` - [Add Tier 3 i686 Redox OS target:](https://github.com/rust-lang/rust/pull/126192/) `i686-unknown-redox` - [Promote `arm64ec-pc-windows-msvc` to Tier 2.](https://github.com/rust-lang/rust/pull/126039/) - - [Promote `wasm32-wasip2` to Tier 2.](https://github.com/rust-lang/rust/pull/126967/) - [Promote `loongarch64-unknown-linux-musl` to Tier 2 with host tools.](https://github.com/rust-lang/rust/pull/126298/) - [Enable full tools and profiler for LoongArch Linux targets.](https://github.com/rust-lang/rust/pull/127078/) - [Unconditionally warn on usage of `wasm32-wasi`.](https://github.com/rust-lang/rust/pull/126662/) (see compatibility note below) From f44bdb5c78a726da1960856c973907de1eb68aec Mon Sep 17 00:00:00 2001 From: David Richey Date: Thu, 5 Sep 2024 10:57:16 -0500 Subject: [PATCH 0549/2194] Add command to report unresolved references --- .../crates/rust-analyzer/src/bin/main.rs | 1 + .../crates/rust-analyzer/src/cli.rs | 1 + .../crates/rust-analyzer/src/cli/flags.rs | 23 +++ .../src/cli/unresolved_references.rs | 175 ++++++++++++++++++ 4 files changed, 200 insertions(+) create mode 100644 src/tools/rust-analyzer/crates/rust-analyzer/src/cli/unresolved_references.rs diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/bin/main.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/bin/main.rs index 21b481c1fa29e..41b42573f0821 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/bin/main.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/bin/main.rs @@ -82,6 +82,7 @@ fn actual_main() -> anyhow::Result { flags::RustAnalyzerCmd::Highlight(cmd) => cmd.run()?, flags::RustAnalyzerCmd::AnalysisStats(cmd) => cmd.run(verbosity)?, flags::RustAnalyzerCmd::Diagnostics(cmd) => cmd.run()?, + flags::RustAnalyzerCmd::UnresolvedReferences(cmd) => cmd.run()?, flags::RustAnalyzerCmd::Ssr(cmd) => cmd.run()?, flags::RustAnalyzerCmd::Search(cmd) => cmd.run()?, flags::RustAnalyzerCmd::Lsif(cmd) => cmd.run()?, diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli.rs index 5eb6ff664f665..a7ec5af89fcbf 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli.rs @@ -13,6 +13,7 @@ mod rustc_tests; mod scip; mod ssr; mod symbols; +mod unresolved_references; mod progress_report; diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/flags.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/flags.rs index 16d90de661ad1..73e71658d17c5 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/flags.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/flags.rs @@ -124,6 +124,19 @@ xflags::xflags! { optional --proc-macro-srv path: PathBuf } + /// Report unresolved references + cmd unresolved-references { + /// Directory with Cargo.toml. + required path: PathBuf + + /// Don't run build scripts or load `OUT_DIR` values by running `cargo check` before analysis. + optional --disable-build-scripts + /// Don't use expand proc macros. + optional --disable-proc-macros + /// Run a custom proc-macro-srv binary. + optional --proc-macro-srv path: PathBuf + } + cmd ssr { /// A structured search replace rule (`$a.foo($b) ==>> bar($a, $b)`) repeated rule: SsrRule @@ -181,6 +194,7 @@ pub enum RustAnalyzerCmd { RunTests(RunTests), RustcTests(RustcTests), Diagnostics(Diagnostics), + UnresolvedReferences(UnresolvedReferences), Ssr(Ssr), Search(Search), Lsif(Lsif), @@ -250,6 +264,15 @@ pub struct Diagnostics { pub proc_macro_srv: Option, } +#[derive(Debug)] +pub struct UnresolvedReferences { + pub path: PathBuf, + + pub disable_build_scripts: bool, + pub disable_proc_macros: bool, + pub proc_macro_srv: Option, +} + #[derive(Debug)] pub struct Ssr { pub rule: Vec, diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/unresolved_references.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/unresolved_references.rs new file mode 100644 index 0000000000000..986bd018b424d --- /dev/null +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/unresolved_references.rs @@ -0,0 +1,175 @@ +//! Reports references in code that the IDE layer cannot resolve. +use hir::{db::HirDatabase, AnyDiagnostic, Crate, HirFileIdExt as _, Module, Semantics}; +use ide::{AnalysisHost, RootDatabase, TextRange}; +use ide_db::{ + base_db::{SourceDatabase, SourceRootDatabase}, + defs::NameRefClass, + EditionedFileId, FxHashSet, LineIndexDatabase as _, +}; +use load_cargo::{load_workspace_at, LoadCargoConfig, ProcMacroServerChoice}; +use parser::SyntaxKind; +use syntax::{ast, AstNode, WalkEvent}; +use vfs::FileId; + +use crate::cli::flags; + +impl flags::UnresolvedReferences { + pub fn run(self) -> anyhow::Result<()> { + const STACK_SIZE: usize = 1024 * 1024 * 8; + + let handle = stdx::thread::Builder::new(stdx::thread::ThreadIntent::LatencySensitive) + .name("BIG_STACK_THREAD".into()) + .stack_size(STACK_SIZE) + .spawn(|| self.run_()) + .unwrap(); + + handle.join() + } + + fn run_(self) -> anyhow::Result<()> { + let root = + vfs::AbsPathBuf::assert_utf8(std::env::current_dir()?.join(&self.path)).normalize(); + let config = crate::config::Config::new( + root.clone(), + lsp_types::ClientCapabilities::default(), + vec![], + None, + ); + let cargo_config = config.cargo(None); + let with_proc_macro_server = if let Some(p) = &self.proc_macro_srv { + let path = vfs::AbsPathBuf::assert_utf8(std::env::current_dir()?.join(p)); + ProcMacroServerChoice::Explicit(path) + } else { + ProcMacroServerChoice::Sysroot + }; + let load_cargo_config = LoadCargoConfig { + load_out_dirs_from_check: !self.disable_build_scripts, + with_proc_macro_server, + prefill_caches: false, + }; + let (db, vfs, _proc_macro) = + load_workspace_at(&self.path, &cargo_config, &load_cargo_config, &|_| {})?; + let host = AnalysisHost::with_database(db); + let db = host.raw_database(); + let sema = Semantics::new(db); + + let mut visited_files = FxHashSet::default(); + + let work = all_modules(db).into_iter().filter(|module| { + let file_id = module.definition_source_file_id(db).original_file(db); + let source_root = db.file_source_root(file_id.into()); + let source_root = db.source_root(source_root); + !source_root.is_library + }); + + for module in work { + let file_id = module.definition_source_file_id(db).original_file(db); + if !visited_files.contains(&file_id) { + let crate_name = + module.krate().display_name(db).as_deref().unwrap_or("unknown").to_owned(); + let file_path = vfs.file_path(file_id.into()); + eprintln!("processing crate: {crate_name}, module: {file_path}",); + + let line_index = db.line_index(file_id.into()); + let file_text = db.file_text(file_id.into()); + + for range in find_unresolved_references(db, &sema, file_id.into(), &module) { + let line_col = line_index.line_col(range.start()); + let line = line_col.line + 1; + let col = line_col.col + 1; + let text = &file_text[range]; + println!("{file_path}:{line}:{col}: {text}"); + } + + visited_files.insert(file_id); + } + } + + eprintln!(); + eprintln!("scan complete"); + + Ok(()) + } +} + +fn all_modules(db: &dyn HirDatabase) -> Vec { + let mut worklist: Vec<_> = + Crate::all(db).into_iter().map(|krate| krate.root_module()).collect(); + let mut modules = Vec::new(); + + while let Some(module) = worklist.pop() { + modules.push(module); + worklist.extend(module.children(db)); + } + + modules +} + +fn find_unresolved_references( + db: &RootDatabase, + sema: &Semantics<'_, RootDatabase>, + file_id: FileId, + module: &Module, +) -> Vec { + let mut unresolved_references = all_unresolved_references(sema, file_id); + + // remove unresolved references which are within inactive code + let mut diagnostics = Vec::new(); + module.diagnostics(db, &mut diagnostics, false); + for diagnostic in diagnostics { + let AnyDiagnostic::InactiveCode(inactive_code) = diagnostic else { + continue; + }; + + let node = inactive_code.node; + let range = node.map(|it| it.text_range()).original_node_file_range_rooted(db); + + if range.file_id != file_id { + continue; + } + + unresolved_references.retain(|r| !range.range.contains_range(*r)); + } + + unresolved_references +} + +fn all_unresolved_references( + sema: &Semantics<'_, RootDatabase>, + file_id: FileId, +) -> Vec { + let file_id = sema + .attach_first_edition(file_id) + .unwrap_or_else(|| EditionedFileId::current_edition(file_id)); + let file = sema.parse(file_id); + let root = file.syntax(); + + let mut unresolved_references = Vec::new(); + for event in root.preorder() { + let WalkEvent::Enter(syntax) = event else { + continue; + }; + let Some(name_ref) = ast::NameRef::cast(syntax) else { + continue; + }; + let Some(descended_name_ref) = name_ref.syntax().first_token().and_then(|tok| { + sema.descend_into_macros_single_exact(tok).parent().and_then(ast::NameRef::cast) + }) else { + continue; + }; + + // if we can classify the name_ref, it's not unresolved + if NameRefClass::classify(sema, &descended_name_ref).is_some() { + continue; + } + + // if we couldn't classify it, but it's in an attr, ignore it. See #10935 + if descended_name_ref.syntax().ancestors().any(|it| it.kind() == SyntaxKind::ATTR) { + continue; + } + + // otherwise, it's unresolved + unresolved_references.push(name_ref.syntax().text_range()); + } + unresolved_references +} From 757affd1a9147f4ccc0481df6037a867e0a21ad7 Mon Sep 17 00:00:00 2001 From: binarycat Date: Thu, 5 Sep 2024 15:12:15 -0400 Subject: [PATCH 0550/2194] bootstrap: pass long options to curl --- src/bootstrap/bootstrap.py | 17 ++++++++++------- src/bootstrap/src/core/download.rs | 20 +++++++++++--------- 2 files changed, 21 insertions(+), 16 deletions(-) diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py index 1de010dc08a49..f1d45c880ee69 100644 --- a/src/bootstrap/bootstrap.py +++ b/src/bootstrap/bootstrap.py @@ -106,9 +106,9 @@ def _download(path, url, probably_big, verbose, exception): try: if (probably_big or verbose) and "GITHUB_ACTIONS" not in os.environ: - option = "-#" + option = "--progress-bar" else: - option = "-s" + option = "--silent" # If curl is not present on Win32, we should not sys.exit # but raise `CalledProcessError` or `OSError` instead require(["curl", "--version"], exception=platform_is_win32()) @@ -120,12 +120,15 @@ def _download(path, url, probably_big, verbose, exception): # for consistency. # they are also more compreprensivly explained in that file. run(["curl", option] + extra_flags + [ - "-L", # Follow redirect. - "-y", "30", "-Y", "10", # timeout if speed is < 10 bytes/sec for > 30 seconds - "--connect-timeout", "30", # timeout if cannot connect within 30 seconds - "-o", path, + # Follow redirect. + "--location", + # timeout if speed is < 10 bytes/sec for > 30 seconds + "--speed-time", "30", "--speed-limit", "10", + # timeout if cannot connect within 30 seconds + "--connect-timeout", "30", + "--output", path, "--continue-at", "-", - "--retry", "3", "-SRf", url], + "--retry", "3", "--show-error", "--remote-time", "--fail", url], verbose=verbose, exception=True, # Will raise RuntimeError on failure ) diff --git a/src/bootstrap/src/core/download.rs b/src/bootstrap/src/core/download.rs index 038ca320e6b6e..77a4f4b0f3362 100644 --- a/src/bootstrap/src/core/download.rs +++ b/src/bootstrap/src/core/download.rs @@ -233,17 +233,17 @@ impl Config { let mut curl = command("curl"); curl.args([ // follow redirect - "-L", + "--location", // timeout if speed is < 10 bytes/sec for > 30 seconds - "-y", + "--speed-time", "30", - "-Y", + "--speed-limit", "10", // timeout if cannot connect within 30 seconds "--connect-timeout", "30", // output file - "-o", + "--output", tempfile.to_str().unwrap(), // if there is an error, don't restart the download, // instead continue where it left off. @@ -253,14 +253,16 @@ impl Config { // attempts will be made, since the first attempt isn't a *re*try. "--retry", "3", - // -S: show errors, even if -s is specified - // -R: set timestamp of downloaded file to that of the server - // -f: fail on non-ok http status - "-SRf", + // show errors, even if --silent is specified + "--show-error", + // set timestamp of downloaded file to that of the server + "--remote-time", + // fail on non-ok http status + "--fail", ]); // Don't print progress in CI; the \r wrapping looks bad and downloads don't take long enough for progress to be useful. if CiEnv::is_ci() { - curl.arg("-s"); + curl.arg("--silent"); } else { curl.arg("--progress-bar"); } From 6b4ff514d99511354ed206c2544b821b6986bf78 Mon Sep 17 00:00:00 2001 From: Orson Peters Date: Thu, 5 Sep 2024 22:50:41 +0200 Subject: [PATCH 0551/2194] better implementation of signed div_floor/ceil --- library/core/src/num/int_macros.rs | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/library/core/src/num/int_macros.rs b/library/core/src/num/int_macros.rs index 878a911dde50d..7241b3ff6a3b7 100644 --- a/library/core/src/num/int_macros.rs +++ b/library/core/src/num/int_macros.rs @@ -3023,8 +3023,16 @@ macro_rules! int_impl { pub const fn div_floor(self, rhs: Self) -> Self { let d = self / rhs; let r = self % rhs; - if (r > 0 && rhs < 0) || (r < 0 && rhs > 0) { - d - 1 + + // If the remainder is non-zero, we need to subtract one if the + // signs of self and rhs differ, as this means we rounded upwards + // instead of downwards. We do this branchlessly by creating a mask + // which is all-ones iff the signs differ, and 0 otherwise. Then by + // adding this mask (which corresponds to the signed value -1), we + // get our correction. + let correction = (self ^ rhs) >> (Self::BITS - 1); + if r != 0 { + d + correction } else { d } @@ -3059,8 +3067,12 @@ macro_rules! int_impl { pub const fn div_ceil(self, rhs: Self) -> Self { let d = self / rhs; let r = self % rhs; - if (r > 0 && rhs > 0) || (r < 0 && rhs < 0) { - d + 1 + + // When remainder is non-zero we have a.div_ceil(b) == 1 + a.div_floor(b), + // so we can re-use the algorithm from div_floor, just adding 1. + let correction = 1 + ((self ^ rhs) >> (Self::BITS - 1)); + if r != 0 { + d + correction } else { d } From 79081f1271222d4ea12c923d949fc4f1aece2362 Mon Sep 17 00:00:00 2001 From: Kevin Reid Date: Thu, 5 Sep 2024 14:30:27 -0700 Subject: [PATCH 0552/2194] Correct version of `too_long_first_doc_paragraph` `too_long_first_doc_paragraph` is, empirically, not in the Rust 1.81.0 release. --- clippy_lints/src/doc/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/doc/mod.rs b/clippy_lints/src/doc/mod.rs index 6db63b59e020e..f2c87f0fd70b3 100644 --- a/clippy_lints/src/doc/mod.rs +++ b/clippy_lints/src/doc/mod.rs @@ -450,7 +450,7 @@ declare_clippy_lint! { /// /// and probably spanning a many rows. /// struct Foo {} /// ``` - #[clippy::version = "1.81.0"] + #[clippy::version = "1.82.0"] pub TOO_LONG_FIRST_DOC_PARAGRAPH, style, "ensure that the first line of a documentation paragraph isn't too long" From f6e8a84eeae8b5f7291999966ab82d495ea7da26 Mon Sep 17 00:00:00 2001 From: Pavel Grigorenko Date: Thu, 5 Sep 2024 00:34:04 +0300 Subject: [PATCH 0553/2194] Make `Ty::boxed_ty` return an `Option` --- .../src/diagnostics/explain_borrow.rs | 3 ++- compiler/rustc_borrowck/src/diagnostics/mod.rs | 4 ++-- .../rustc_codegen_llvm/src/debuginfo/metadata.rs | 2 +- compiler/rustc_const_eval/src/interpret/call.rs | 2 +- .../src/method/prelude_edition_lints.rs | 3 +-- compiler/rustc_hir_typeck/src/method/probe.rs | 3 +-- compiler/rustc_lint/src/shadowed_into_iter.rs | 7 ++----- compiler/rustc_lint/src/types.rs | 6 ++++-- compiler/rustc_lint/src/unused.rs | 5 ++--- compiler/rustc_middle/src/ty/layout.rs | 6 ++++-- compiler/rustc_middle/src/ty/sty.rs | 15 ++++++++++----- compiler/rustc_middle/src/ty/util.rs | 2 +- .../src/elaborate_box_derefs.rs | 12 ++++++++---- compiler/rustc_monomorphize/src/collector.rs | 7 +++++-- compiler/rustc_monomorphize/src/lib.rs | 2 ++ .../src/error_reporting/infer/mod.rs | 3 +-- src/tools/clippy/clippy_lints/src/escape.rs | 6 +++--- src/tools/clippy/clippy_lints/src/methods/mod.rs | 4 ++-- .../clippy/clippy_lints/src/methods/utils.rs | 4 ++-- .../clippy_lints/src/unnecessary_box_returns.rs | 6 ++---- src/tools/clippy/clippy_utils/src/ty.rs | 4 ++-- 21 files changed, 58 insertions(+), 48 deletions(-) diff --git a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs index 91b02a36d0046..c720b0928feb0 100644 --- a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs +++ b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs @@ -662,9 +662,10 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, '_, 'tcx> { // `&dyn Trait` ty::Ref(_, ty, _) if ty.is_trait() => true, // `Box` - _ if ty.is_box() && ty.boxed_ty().is_trait() => { + _ if ty.boxed_ty().is_some_and(Ty::is_trait) => { true } + // `dyn Trait` _ if ty.is_trait() => true, // Anything else. diff --git a/compiler/rustc_borrowck/src/diagnostics/mod.rs b/compiler/rustc_borrowck/src/diagnostics/mod.rs index 5ab66963409a8..878ce6162e0f9 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mod.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mod.rs @@ -345,9 +345,9 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, '_, 'infcx, 'tcx> { variant_index: Option, including_tuple_field: IncludingTupleField, ) -> Option { - if ty.is_box() { + if let Some(boxed_ty) = ty.boxed_ty() { // If the type is a box, the field is described from the boxed type - self.describe_field_from_ty(ty.boxed_ty(), field, variant_index, including_tuple_field) + self.describe_field_from_ty(boxed_ty, field, variant_index, including_tuple_field) } else { match *ty.kind() { ty::Adt(def, _) => { diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs index 17a9630c6557b..d231b103964b6 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs @@ -456,7 +456,7 @@ pub(crate) fn type_di_node<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>, t: Ty<'tcx>) -> if def.is_box() && args.get(1).map_or(true, |arg| cx.layout_of(arg.expect_ty()).is_1zst()) => { - build_pointer_or_reference_di_node(cx, t, t.boxed_ty(), unique_type_id) + build_pointer_or_reference_di_node(cx, t, t.expect_boxed_ty(), unique_type_id) } ty::FnDef(..) | ty::FnPtr(..) => build_subroutine_type_di_node(cx, unique_type_id), ty::Closure(..) => build_closure_env_di_node(cx, unique_type_id), diff --git a/compiler/rustc_const_eval/src/interpret/call.rs b/compiler/rustc_const_eval/src/interpret/call.rs index 82438eb5e7828..568a9a3a637be 100644 --- a/compiler/rustc_const_eval/src/interpret/call.rs +++ b/compiler/rustc_const_eval/src/interpret/call.rs @@ -189,7 +189,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { ty::Ref(_, ty, _) => *ty, ty::RawPtr(ty, _) => *ty, // We only accept `Box` with the default allocator. - _ if ty.is_box_global(*self.tcx) => ty.boxed_ty(), + _ if ty.is_box_global(*self.tcx) => ty.expect_boxed_ty(), _ => return Ok(None), })) }; diff --git a/compiler/rustc_hir_typeck/src/method/prelude_edition_lints.rs b/compiler/rustc_hir_typeck/src/method/prelude_edition_lints.rs index 0790c6f9a5992..ac5e1040803e0 100644 --- a/compiler/rustc_hir_typeck/src/method/prelude_edition_lints.rs +++ b/compiler/rustc_hir_typeck/src/method/prelude_edition_lints.rs @@ -63,8 +63,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Instead, the problem is that the array-into_iter hack will no longer // apply in Rust 2021. (ARRAY_INTO_ITER, "2021") - } else if self_ty.is_box() - && self_ty.boxed_ty().is_slice() + } else if self_ty.boxed_ty().is_some_and(Ty::is_slice) && !span.at_least_rust_2024() { // In this case, it wasn't really a prelude addition that was the problem. diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs index 0cf5403b3c085..4b3c52a1ed604 100644 --- a/compiler/rustc_hir_typeck/src/method/probe.rs +++ b/compiler/rustc_hir_typeck/src/method/probe.rs @@ -1485,8 +1485,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { // Some trait methods are excluded for boxed slices before 2024. // (`boxed_slice.into_iter()` wants a slice iterator for compatibility.) - if self_ty.is_box() - && self_ty.boxed_ty().is_slice() + if self_ty.boxed_ty().is_some_and(Ty::is_slice) && !method_name.span.at_least_rust_2024() { let trait_def = self.tcx.trait_def(poly_trait_ref.def_id()); diff --git a/compiler/rustc_lint/src/shadowed_into_iter.rs b/compiler/rustc_lint/src/shadowed_into_iter.rs index bb9c7d85c2efc..bb122509d0a89 100644 --- a/compiler/rustc_lint/src/shadowed_into_iter.rs +++ b/compiler/rustc_lint/src/shadowed_into_iter.rs @@ -94,12 +94,9 @@ impl<'tcx> LateLintPass<'tcx> for ShadowedIntoIter { fn is_ref_to_array(ty: Ty<'_>) -> bool { if let ty::Ref(_, pointee_ty, _) = *ty.kind() { pointee_ty.is_array() } else { false } } - fn is_boxed_slice(ty: Ty<'_>) -> bool { - ty.is_box() && ty.boxed_ty().is_slice() - } fn is_ref_to_boxed_slice(ty: Ty<'_>) -> bool { if let ty::Ref(_, pointee_ty, _) = *ty.kind() { - is_boxed_slice(pointee_ty) + pointee_ty.boxed_ty().is_some_and(Ty::is_slice) } else { false } @@ -119,7 +116,7 @@ impl<'tcx> LateLintPass<'tcx> for ShadowedIntoIter { .iter() .copied() .take_while(|ty| !is_ref_to_boxed_slice(*ty)) - .position(|ty| is_boxed_slice(ty)) + .position(|ty| ty.boxed_ty().is_some_and(Ty::is_slice)) { (BOXED_SLICE_INTO_ITER, "Box<[T]>", "2024", idx == 0) } else { diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs index f2f7c0eaa4df8..b5e501b92f0d6 100644 --- a/compiler/rustc_lint/src/types.rs +++ b/compiler/rustc_lint/src/types.rs @@ -1304,8 +1304,10 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { match *ty.kind() { ty::Adt(def, args) => { - if def.is_box() && matches!(self.mode, CItemKind::Definition) { - if ty.boxed_ty().is_sized(tcx, self.cx.param_env) { + if let Some(boxed) = ty.boxed_ty() + && matches!(self.mode, CItemKind::Definition) + { + if boxed.is_sized(tcx, self.cx.param_env) { return FfiSafe; } else { return FfiUnsafe { diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs index 761d30bac715a..b7f7b782c7722 100644 --- a/compiler/rustc_lint/src/unused.rs +++ b/compiler/rustc_lint/src/unused.rs @@ -283,9 +283,8 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults { } match *ty.kind() { - ty::Adt(..) if ty.is_box() => { - let boxed_ty = ty.boxed_ty(); - is_ty_must_use(cx, boxed_ty, expr, span) + ty::Adt(..) if let Some(boxed) = ty.boxed_ty() => { + is_ty_must_use(cx, boxed, expr, span) .map(|inner| MustUsePath::Boxed(Box::new(inner))) } ty::Adt(def, args) if cx.tcx.is_lang_item(def.did(), LangItem::Pin) => { diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index d0a9039441dc4..8cec8eac1898a 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -1075,11 +1075,13 @@ where // the raw pointer, so size and align are set to the boxed type, but `pointee.safe` // will still be `None`. if let Some(ref mut pointee) = result { - if offset.bytes() == 0 && this.ty.is_box() { + if offset.bytes() == 0 + && let Some(boxed_ty) = this.ty.boxed_ty() + { debug_assert!(pointee.safe.is_none()); let optimize = tcx.sess.opts.optimize != OptLevel::No; pointee.safe = Some(PointerKind::Box { - unpin: optimize && this.ty.boxed_ty().is_unpin(tcx, cx.param_env()), + unpin: optimize && boxed_ty.is_unpin(tcx, cx.param_env()), global: this.ty.is_box_global(tcx), }); } diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index 89ef30fa768e0..1f4f2c62d7084 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -1170,14 +1170,19 @@ impl<'tcx> Ty<'tcx> { } } - /// Panics if called on any type other than `Box`. - pub fn boxed_ty(self) -> Ty<'tcx> { + pub fn boxed_ty(self) -> Option> { match self.kind() { - Adt(def, args) if def.is_box() => args.type_at(0), - _ => bug!("`boxed_ty` is called on non-box type {:?}", self), + Adt(def, args) if def.is_box() => Some(args.type_at(0)), + _ => None, } } + /// Panics if called on any type other than `Box`. + pub fn expect_boxed_ty(self) -> Ty<'tcx> { + self.boxed_ty() + .unwrap_or_else(|| bug!("`expect_boxed_ty` is called on non-box type {:?}", self)) + } + /// A scalar type is one that denotes an atomic datum, with no sub-components. /// (A RawPtr is scalar because it represents a non-managed pointer, so its /// contents are abstract to rustc.) @@ -1323,7 +1328,7 @@ impl<'tcx> Ty<'tcx> { /// Some types -- notably unsafe ptrs -- can only be dereferenced explicitly. pub fn builtin_deref(self, explicit: bool) -> Option> { match *self.kind() { - Adt(def, _) if def.is_box() => Some(self.boxed_ty()), + _ if let Some(boxed) = self.boxed_ty() => Some(boxed), Ref(_, ty, _) => Some(ty), RawPtr(ty, _) if explicit => Some(ty), _ => None, diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index efbccca77c1f0..d70ff8258d04c 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -1628,7 +1628,7 @@ impl<'tcx> ExplicitSelf<'tcx> { _ if is_self_ty(self_arg_ty) => ByValue, ty::Ref(region, ty, mutbl) if is_self_ty(ty) => ByReference(region, mutbl), ty::RawPtr(ty, mutbl) if is_self_ty(ty) => ByRawPointer(mutbl), - ty::Adt(def, _) if def.is_box() && is_self_ty(self_arg_ty.boxed_ty()) => ByBox, + _ if self_arg_ty.boxed_ty().is_some_and(is_self_ty) => ByBox, _ => Other, } } diff --git a/compiler/rustc_mir_transform/src/elaborate_box_derefs.rs b/compiler/rustc_mir_transform/src/elaborate_box_derefs.rs index e5778f8a05d2e..97beb728bbc28 100644 --- a/compiler/rustc_mir_transform/src/elaborate_box_derefs.rs +++ b/compiler/rustc_mir_transform/src/elaborate_box_derefs.rs @@ -62,11 +62,13 @@ impl<'tcx, 'a> MutVisitor<'tcx> for ElaborateBoxDerefVisitor<'tcx, 'a> { let base_ty = self.local_decls[place.local].ty; // Derefer ensures that derefs are always the first projection - if place.projection.first() == Some(&PlaceElem::Deref) && base_ty.is_box() { + if let Some(PlaceElem::Deref) = place.projection.first() + && let Some(boxed_ty) = base_ty.boxed_ty() + { let source_info = self.local_decls[place.local].source_info; let (unique_ty, nonnull_ty, ptr_ty) = - build_ptr_tys(tcx, base_ty.boxed_ty(), self.unique_did, self.nonnull_did); + build_ptr_tys(tcx, boxed_ty, self.unique_did, self.nonnull_did); let ptr_local = self.patch.new_temp(ptr_ty, source_info.span); @@ -120,13 +122,15 @@ impl<'tcx> MirPass<'tcx> for ElaborateBoxDerefs { for (base, elem) in place.iter_projections() { let base_ty = base.ty(&body.local_decls, tcx).ty; - if elem == PlaceElem::Deref && base_ty.is_box() { + if let PlaceElem::Deref = elem + && let Some(boxed_ty) = base_ty.boxed_ty() + { // Clone the projections before us, since now we need to mutate them. let new_projections = new_projections.get_or_insert_with(|| base.projection.to_vec()); let (unique_ty, nonnull_ty, ptr_ty) = - build_ptr_tys(tcx, base_ty.boxed_ty(), unique_did, nonnull_did); + build_ptr_tys(tcx, boxed_ty, unique_did, nonnull_did); new_projections.extend_from_slice(&build_projection( unique_ty, nonnull_ty, ptr_ty, diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs index 8515ab45de217..093697a290c00 100644 --- a/compiler/rustc_monomorphize/src/collector.rs +++ b/compiler/rustc_monomorphize/src/collector.rs @@ -1041,8 +1041,11 @@ fn find_vtable_types_for_unsizing<'tcx>( match (source_ty.kind(), target_ty.kind()) { (&ty::Ref(_, a, _), &ty::Ref(_, b, _) | &ty::RawPtr(b, _)) | (&ty::RawPtr(a, _), &ty::RawPtr(b, _)) => ptr_vtable(a, b), - (&ty::Adt(def_a, _), &ty::Adt(def_b, _)) if def_a.is_box() && def_b.is_box() => { - ptr_vtable(source_ty.boxed_ty(), target_ty.boxed_ty()) + (_, _) + if let Some(source_boxed) = source_ty.boxed_ty() + && let Some(target_boxed) = target_ty.boxed_ty() => + { + ptr_vtable(source_boxed, target_boxed) } // T as dyn* Trait diff --git a/compiler/rustc_monomorphize/src/lib.rs b/compiler/rustc_monomorphize/src/lib.rs index b22e8e30465ea..91101ddd59022 100644 --- a/compiler/rustc_monomorphize/src/lib.rs +++ b/compiler/rustc_monomorphize/src/lib.rs @@ -1,5 +1,7 @@ // tidy-alphabetical-start #![feature(array_windows)] +#![feature(if_let_guard)] +#![feature(let_chains)] #![warn(unreachable_pub)] // tidy-alphabetical-end diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs index bff2a184b19f0..65d21518491da 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs @@ -348,8 +348,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { } } if let Some(ty::error::ExpectedFound { found, .. }) = exp_found - && ty.is_box() - && ty.boxed_ty() == found + && ty.boxed_ty() == Some(found) && let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) { err.span_suggestion( diff --git a/src/tools/clippy/clippy_lints/src/escape.rs b/src/tools/clippy/clippy_lints/src/escape.rs index a5da52b0be50a..803606979410b 100644 --- a/src/tools/clippy/clippy_lints/src/escape.rs +++ b/src/tools/clippy/clippy_lints/src/escape.rs @@ -50,7 +50,7 @@ declare_clippy_lint! { } fn is_non_trait_box(ty: Ty<'_>) -> bool { - ty.is_box() && !ty.boxed_ty().is_trait() + ty.boxed_ty().is_some_and(|boxed| !boxed.is_trait()) } struct EscapeDelegate<'a, 'tcx> { @@ -191,8 +191,8 @@ impl<'a, 'tcx> Delegate<'tcx> for EscapeDelegate<'a, 'tcx> { impl<'a, 'tcx> EscapeDelegate<'a, 'tcx> { fn is_large_box(&self, ty: Ty<'tcx>) -> bool { // Large types need to be boxed to avoid stack overflows. - if ty.is_box() { - self.cx.layout_of(ty.boxed_ty()).map_or(0, |l| l.size.bytes()) > self.too_large_for_stack + if let Some(boxed_ty) = ty.boxed_ty() { + self.cx.layout_of(boxed_ty).map_or(0, |l| l.size.bytes()) > self.too_large_for_stack } else { false } diff --git a/src/tools/clippy/clippy_lints/src/methods/mod.rs b/src/tools/clippy/clippy_lints/src/methods/mod.rs index d7126990edb1d..f61bb3a6bf481 100644 --- a/src/tools/clippy/clippy_lints/src/methods/mod.rs +++ b/src/tools/clippy/clippy_lints/src/methods/mod.rs @@ -5187,8 +5187,8 @@ impl SelfKind { fn matches_value<'a>(cx: &LateContext<'a>, parent_ty: Ty<'a>, ty: Ty<'a>) -> bool { if ty == parent_ty { true - } else if ty.is_box() { - ty.boxed_ty() == parent_ty + } else if let Some(boxed_ty) = ty.boxed_ty() { + boxed_ty == parent_ty } else if is_type_diagnostic_item(cx, ty, sym::Rc) || is_type_diagnostic_item(cx, ty, sym::Arc) { if let ty::Adt(_, args) = ty.kind() { args.types().next().map_or(false, |t| t == parent_ty) diff --git a/src/tools/clippy/clippy_lints/src/methods/utils.rs b/src/tools/clippy/clippy_lints/src/methods/utils.rs index 0d2b0a3131763..fe860e5ae2601 100644 --- a/src/tools/clippy/clippy_lints/src/methods/utils.rs +++ b/src/tools/clippy/clippy_lints/src/methods/utils.rs @@ -16,7 +16,7 @@ pub(super) fn derefs_to_slice<'tcx>( fn may_slice<'a>(cx: &LateContext<'a>, ty: Ty<'a>) -> bool { match ty.kind() { ty::Slice(_) => true, - ty::Adt(def, _) if def.is_box() => may_slice(cx, ty.boxed_ty()), + ty::Adt(..) if let Some(boxed) = ty.boxed_ty() => may_slice(cx, boxed), ty::Adt(..) => is_type_diagnostic_item(cx, ty, sym::Vec), ty::Array(_, size) => size.try_eval_target_usize(cx.tcx, cx.param_env).is_some(), ty::Ref(_, inner, _) => may_slice(cx, *inner), @@ -33,7 +33,7 @@ pub(super) fn derefs_to_slice<'tcx>( } else { match ty.kind() { ty::Slice(_) => Some(expr), - ty::Adt(def, _) if def.is_box() && may_slice(cx, ty.boxed_ty()) => Some(expr), + _ if ty.boxed_ty().is_some_and(|boxed| may_slice(cx, boxed)) => Some(expr), ty::Ref(_, inner, _) => { if may_slice(cx, *inner) { Some(expr) diff --git a/src/tools/clippy/clippy_lints/src/unnecessary_box_returns.rs b/src/tools/clippy/clippy_lints/src/unnecessary_box_returns.rs index 3f130bf5a6731..14f4aa6676b65 100644 --- a/src/tools/clippy/clippy_lints/src/unnecessary_box_returns.rs +++ b/src/tools/clippy/clippy_lints/src/unnecessary_box_returns.rs @@ -75,11 +75,9 @@ impl UnnecessaryBoxReturns { .instantiate_bound_regions_with_erased(cx.tcx.fn_sig(def_id).skip_binder()) .output(); - if !return_ty.is_box() { + let Some(boxed_ty) = return_ty.boxed_ty() else { return; - } - - let boxed_ty = return_ty.boxed_ty(); + }; // It's sometimes useful to return Box if T is unsized, so don't lint those. // Also, don't lint if we know that T is very large, in which case returning diff --git a/src/tools/clippy/clippy_utils/src/ty.rs b/src/tools/clippy/clippy_utils/src/ty.rs index f80981c11af65..585134209ca3a 100644 --- a/src/tools/clippy/clippy_utils/src/ty.rs +++ b/src/tools/clippy/clippy_utils/src/ty.rs @@ -704,8 +704,8 @@ pub fn expr_sig<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'_>) -> Option(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> Option> { - if ty.is_box() { - return ty_sig(cx, ty.boxed_ty()); + if let Some(boxed_ty) = ty.boxed_ty() { + return ty_sig(cx, boxed_ty); } match *ty.kind() { ty::Closure(id, subs) => { From 0b8cb4a1ebdf3bb9b03f7befe48b3d5e36ba080b Mon Sep 17 00:00:00 2001 From: Pavel Grigorenko Date: Thu, 5 Sep 2024 00:34:04 +0300 Subject: [PATCH 0554/2194] Make `Ty::boxed_ty` return an `Option` --- clippy_lints/src/escape.rs | 6 +++--- clippy_lints/src/methods/mod.rs | 4 ++-- clippy_lints/src/methods/utils.rs | 4 ++-- clippy_lints/src/unnecessary_box_returns.rs | 6 ++---- clippy_utils/src/ty.rs | 4 ++-- 5 files changed, 11 insertions(+), 13 deletions(-) diff --git a/clippy_lints/src/escape.rs b/clippy_lints/src/escape.rs index a5da52b0be50a..803606979410b 100644 --- a/clippy_lints/src/escape.rs +++ b/clippy_lints/src/escape.rs @@ -50,7 +50,7 @@ declare_clippy_lint! { } fn is_non_trait_box(ty: Ty<'_>) -> bool { - ty.is_box() && !ty.boxed_ty().is_trait() + ty.boxed_ty().is_some_and(|boxed| !boxed.is_trait()) } struct EscapeDelegate<'a, 'tcx> { @@ -191,8 +191,8 @@ impl<'a, 'tcx> Delegate<'tcx> for EscapeDelegate<'a, 'tcx> { impl<'a, 'tcx> EscapeDelegate<'a, 'tcx> { fn is_large_box(&self, ty: Ty<'tcx>) -> bool { // Large types need to be boxed to avoid stack overflows. - if ty.is_box() { - self.cx.layout_of(ty.boxed_ty()).map_or(0, |l| l.size.bytes()) > self.too_large_for_stack + if let Some(boxed_ty) = ty.boxed_ty() { + self.cx.layout_of(boxed_ty).map_or(0, |l| l.size.bytes()) > self.too_large_for_stack } else { false } diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index d7126990edb1d..f61bb3a6bf481 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -5187,8 +5187,8 @@ impl SelfKind { fn matches_value<'a>(cx: &LateContext<'a>, parent_ty: Ty<'a>, ty: Ty<'a>) -> bool { if ty == parent_ty { true - } else if ty.is_box() { - ty.boxed_ty() == parent_ty + } else if let Some(boxed_ty) = ty.boxed_ty() { + boxed_ty == parent_ty } else if is_type_diagnostic_item(cx, ty, sym::Rc) || is_type_diagnostic_item(cx, ty, sym::Arc) { if let ty::Adt(_, args) = ty.kind() { args.types().next().map_or(false, |t| t == parent_ty) diff --git a/clippy_lints/src/methods/utils.rs b/clippy_lints/src/methods/utils.rs index 0d2b0a3131763..fe860e5ae2601 100644 --- a/clippy_lints/src/methods/utils.rs +++ b/clippy_lints/src/methods/utils.rs @@ -16,7 +16,7 @@ pub(super) fn derefs_to_slice<'tcx>( fn may_slice<'a>(cx: &LateContext<'a>, ty: Ty<'a>) -> bool { match ty.kind() { ty::Slice(_) => true, - ty::Adt(def, _) if def.is_box() => may_slice(cx, ty.boxed_ty()), + ty::Adt(..) if let Some(boxed) = ty.boxed_ty() => may_slice(cx, boxed), ty::Adt(..) => is_type_diagnostic_item(cx, ty, sym::Vec), ty::Array(_, size) => size.try_eval_target_usize(cx.tcx, cx.param_env).is_some(), ty::Ref(_, inner, _) => may_slice(cx, *inner), @@ -33,7 +33,7 @@ pub(super) fn derefs_to_slice<'tcx>( } else { match ty.kind() { ty::Slice(_) => Some(expr), - ty::Adt(def, _) if def.is_box() && may_slice(cx, ty.boxed_ty()) => Some(expr), + _ if ty.boxed_ty().is_some_and(|boxed| may_slice(cx, boxed)) => Some(expr), ty::Ref(_, inner, _) => { if may_slice(cx, *inner) { Some(expr) diff --git a/clippy_lints/src/unnecessary_box_returns.rs b/clippy_lints/src/unnecessary_box_returns.rs index 3f130bf5a6731..14f4aa6676b65 100644 --- a/clippy_lints/src/unnecessary_box_returns.rs +++ b/clippy_lints/src/unnecessary_box_returns.rs @@ -75,11 +75,9 @@ impl UnnecessaryBoxReturns { .instantiate_bound_regions_with_erased(cx.tcx.fn_sig(def_id).skip_binder()) .output(); - if !return_ty.is_box() { + let Some(boxed_ty) = return_ty.boxed_ty() else { return; - } - - let boxed_ty = return_ty.boxed_ty(); + }; // It's sometimes useful to return Box if T is unsized, so don't lint those. // Also, don't lint if we know that T is very large, in which case returning diff --git a/clippy_utils/src/ty.rs b/clippy_utils/src/ty.rs index f80981c11af65..585134209ca3a 100644 --- a/clippy_utils/src/ty.rs +++ b/clippy_utils/src/ty.rs @@ -704,8 +704,8 @@ pub fn expr_sig<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'_>) -> Option(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> Option> { - if ty.is_box() { - return ty_sig(cx, ty.boxed_ty()); + if let Some(boxed_ty) = ty.boxed_ty() { + return ty_sig(cx, boxed_ty); } match *ty.kind() { ty::Closure(id, subs) => { From fc28a2a506f66c739e6c059eb044ed98a3f805c2 Mon Sep 17 00:00:00 2001 From: kromych Date: Thu, 5 Sep 2024 15:26:34 -0700 Subject: [PATCH 0555/2194] Break into the debugger (if attached) on panics (Windows, macOS, Linux, FreeBSD) The developer experience for panics is to provide the backtrace and exit the program. When running under debugger, that might be improved by breaking into the debugger once the code panics thus enabling the developer to examine the program state at the exact time when the code panicked. Let the developer catch the panic in the debugger if it is attached. If the debugger is not attached, nothing changes. Providing this feature inside the standard library facilitates better debugging experience. Validated under Windows, Linux, macOS 14.6, and FreeBSD 13.3..14.1. --- library/std/src/panicking.rs | 18 ++- library/std/src/sys/dbg.rs | 229 +++++++++++++++++++++++++++++++++++ library/std/src/sys/mod.rs | 1 + 3 files changed, 247 insertions(+), 1 deletion(-) create mode 100644 library/std/src/sys/dbg.rs diff --git a/library/std/src/panicking.rs b/library/std/src/panicking.rs index 190eed94555ba..04882a6b22c56 100644 --- a/library/std/src/panicking.rs +++ b/library/std/src/panicking.rs @@ -23,8 +23,8 @@ use crate::mem::{self, ManuallyDrop}; use crate::panic::{BacktraceStyle, PanicHookInfo}; use crate::sync::atomic::{AtomicBool, Ordering}; use crate::sync::{PoisonError, RwLock}; -use crate::sys::backtrace; use crate::sys::stdio::panic_output; +use crate::sys::{backtrace, dbg}; use crate::{fmt, intrinsics, process, thread}; // Binary interface to the panic runtime that the standard library depends on. @@ -855,6 +855,14 @@ pub fn rust_panic_without_hook(payload: Box) -> ! { #[cfg_attr(not(test), rustc_std_internal_symbol)] #[cfg(not(feature = "panic_immediate_abort"))] fn rust_panic(msg: &mut dyn PanicPayload) -> ! { + // Break into the debugger if it is attached. + // The return value is not currently used. + // + // This function isn't used anywhere else, and + // using inside `#[panic_handler]` doesn't seem + // to count, so a warning is issued. + let _ = dbg::breakpoint_if_debugging(); + let code = unsafe { __rust_start_panic(msg) }; rtabort!("failed to initiate panic, error {code}") } @@ -862,6 +870,14 @@ fn rust_panic(msg: &mut dyn PanicPayload) -> ! { #[cfg_attr(not(test), rustc_std_internal_symbol)] #[cfg(feature = "panic_immediate_abort")] fn rust_panic(_: &mut dyn PanicPayload) -> ! { + // Break into the debugger if it is attached. + // The return value is not currently used. + // + // This function isn't used anywhere else, and + // using inside `#[panic_handler]` doesn't seem + // to count, so a warning is issued. + let _ = dbg::breakpoint_if_debugging(); + unsafe { crate::intrinsics::abort(); } diff --git a/library/std/src/sys/dbg.rs b/library/std/src/sys/dbg.rs new file mode 100644 index 0000000000000..a6e78db3c86f0 --- /dev/null +++ b/library/std/src/sys/dbg.rs @@ -0,0 +1,229 @@ +//! Debugging aids. + +/// Presence of a debugger. The debugger being concerned +/// is expected to use the OS API to debug this process. +#[derive(Copy, Clone, Debug)] +#[allow(unused)] +pub(crate) enum DebuggerPresence { + /// The debugger is attached to this process. + Detected, + /// The debugger is not attached to this process. + NotDetected, +} + +#[cfg(target_os = "windows")] +mod os { + use super::DebuggerPresence; + + #[link(name = "kernel32")] + extern "system" { + fn IsDebuggerPresent() -> i32; + } + + pub(super) fn is_debugger_present() -> Option { + // SAFETY: No state is shared between threads. The call reads + // a field from the Thread Environment Block using the OS API + // as required by the documentation. + if unsafe { IsDebuggerPresent() } != 0 { + Some(DebuggerPresence::Detected) + } else { + Some(DebuggerPresence::NotDetected) + } + } +} + +#[cfg(any(target_vendor = "apple", target_os = "freebsd"))] +mod os { + use libc::{c_int, sysctl, CTL_KERN, KERN_PROC, KERN_PROC_PID}; + + use super::DebuggerPresence; + use crate::io::{Cursor, Read, Seek, SeekFrom}; + use crate::process; + + const P_TRACED: i32 = 0x00000800; + + // The assumption is that the kernel structures available to the + // user space may not shrink or repurpose the existing fields over + // time. The kernels normally adhere to that for the backward + // compatibility of the user space. + + // The macOS 14.5 SDK comes with a header `MacOSX14.5.sdk/usr/include/sys/sysctl.h` + // that defines `struct kinfo_proc` be of `648` bytes on the 64-bit system. That has + // not changed since macOS 10.13 (released in 2017) at least, validated by building + // a C program in XCode while changing the build target. Apple provides this example + // for reference: https://developer.apple.com/library/archive/qa/qa1361/_index.html. + #[cfg(target_vendor = "apple")] + const KINFO_PROC_SIZE: usize = if cfg!(target_pointer_width = "64") { 648 } else { 492 }; + #[cfg(target_vendor = "apple")] + const KINFO_PROC_FLAGS_OFFSET: u64 = if cfg!(target_pointer_width = "64") { 32 } else { 16 }; + + // Works for FreeBSD stable (13.3, 13.4) and current (14.0, 14.1). + // The size of the structure has stayed the same for a long time, + // at least since 2005: + // https://lists.freebsd.org/pipermail/freebsd-stable/2005-November/019899.html + #[cfg(target_os = "freebsd")] + const KINFO_PROC_SIZE: usize = if cfg!(target_pointer_width = "64") { 1088 } else { 768 }; + #[cfg(target_os = "freebsd")] + const KINFO_PROC_FLAGS_OFFSET: u64 = if cfg!(target_pointer_width = "64") { 368 } else { 296 }; + + pub(super) fn is_debugger_present() -> Option { + debug_assert_ne!(KINFO_PROC_SIZE, 0); + + let mut flags = [0u8; 4]; // `ki_flag` under FreeBSD and `p_flag` under macOS. + let mut mib = [CTL_KERN, KERN_PROC, KERN_PROC_PID, process::id() as c_int]; + let mut info_size = KINFO_PROC_SIZE; + let mut kinfo_proc = [0u8; KINFO_PROC_SIZE]; + + // SAFETY: No state is shared with other threads. The sysctl call + // is safe according to the documentation. + if unsafe { + sysctl( + mib.as_mut_ptr(), + mib.len() as u32, + kinfo_proc.as_mut_ptr().cast(), + &mut info_size, + core::ptr::null_mut(), + 0, + ) + } != 0 + { + return None; + } + debug_assert_eq!(info_size, KINFO_PROC_SIZE); + + let mut reader = Cursor::new(kinfo_proc); + reader.seek(SeekFrom::Start(KINFO_PROC_FLAGS_OFFSET)).ok()?; + reader.read_exact(&mut flags).ok()?; + // Just in case, not limiting this to the little-endian systems. + let flags = i32::from_ne_bytes(flags); + + if flags & P_TRACED != 0 { + Some(DebuggerPresence::Detected) + } else { + Some(DebuggerPresence::NotDetected) + } + } +} + +#[cfg(target_os = "linux")] +mod os { + use super::DebuggerPresence; + use crate::fs::File; + use crate::io::Read; + + pub(super) fn is_debugger_present() -> Option { + // This function is crafted with the following goals: + // * Memory efficiency: It avoids crashing the panicking process due to + // out-of-memory (OOM) conditions by not using large heap buffers or + // allocating significant stack space, which could lead to stack overflow. + // * Minimal binary size: The function uses a minimal set of facilities + // from the standard library to avoid increasing the resulting binary size. + // + // To achieve these goals, the function does not use `[std::io::BufReader]` + // and instead reads the file byte by byte using a sliding window approach. + // It's important to note that the "/proc/self/status" pseudo-file is synthesized + // by the Virtual File System (VFS), meaning it is not read from a slow or + // non-volatile storage medium so buffering might not be as beneficial because + // all data is read from memory, though this approach does incur a syscall for + // each byte read. + // + // We cannot make assumptions about the file size or the position of the + // target prefix ("TracerPid:"), so the function does not use + // `[std::fs::read_to_string]` thus not employing UTF-8 to ASCII checking, + // conversion, or parsing as we're looking for an ASCII prefix. + // + // These condiderations make the function deviate from the familiar concise pattern + // of searching for a string in a text file. + + fn read_byte(file: &mut File) -> Option { + let mut buffer = [0]; + file.read_exact(&mut buffer).ok()?; + Some(buffer[0]) + } + + // The ASCII prefix of the datum we're interested in. + const TRACER_PID: &[u8] = b"TracerPid:\t"; + + let mut file = File::open("/proc/self/status").ok()?; + let mut matched = 0; + + // Look for the `TRACER_PID` prefix. + while let Some(byte) = read_byte(&mut file) { + if byte == TRACER_PID[matched] { + matched += 1; + if matched == TRACER_PID.len() { + break; + } + } else { + matched = 0; + } + } + + // Was the prefix found? + if matched != TRACER_PID.len() { + return None; + } + + // It was; get the ASCII representation of the first digit + // of the PID. That is enough to see if there is a debugger + // attached as the kernel does not pad the PID on the left + // with the leading zeroes. + let byte = read_byte(&mut file)?; + if byte.is_ascii_digit() && byte != b'0' { + Some(DebuggerPresence::Detected) + } else { + Some(DebuggerPresence::NotDetected) + } + } +} + +#[cfg(not(any( + target_os = "windows", + target_vendor = "apple", + target_os = "freebsd", + target_os = "linux" +)))] +mod os { + pub(super) fn is_debugger_present() -> Option { + None + } +} + +/// Detect the debugger presence. +/// +/// The code does not try to detect the debugger at all costs (e.g., when anti-debugger +/// tricks are at play), it relies on the interfaces provided by the OS. +/// +/// Return value: +/// * `None`: it's not possible to conclude whether the debugger is attached to this +/// process or not. When checking for the presence of the debugger, the detection logic +/// encountered an issue, such as the OS API throwing an error or the feature not being +/// implemented. +/// * `Some(DebuggerPresence::Detected)`: yes, the debugger is attached +/// to this process. +/// * `Some(DebuggerPresence::NotDetected)`: no, the debugger is not +/// attached to this process. +pub(crate) fn is_debugger_present() -> Option { + if cfg!(miri) { None } else { os::is_debugger_present() } +} + +/// Execute the breakpoint instruction if the debugger presence is detected. +/// Useful for breaking into the debugger without the need to set a breakpoint +/// in the debugger. +/// +/// Note that there is a race between attaching or detaching the debugger, and running the +/// breakpoint instruction. This is nonetheless memory-safe, like [`crate::process::abort`] +/// is. In case the debugger is attached and the function is about +/// to run the breakpoint instruction yet right before that the debugger detaches, the +/// process will crash due to running the breakpoint instruction and the debugger not +/// handling the trap exception. +pub(crate) fn breakpoint_if_debugging() -> Option { + let debugger_present = is_debugger_present(); + if let Some(DebuggerPresence::Detected) = debugger_present { + // SAFETY: Executing the breakpoint instruction. No state is shared + // or modified by this code. + unsafe { core::intrinsics::breakpoint() }; + } + + debugger_present +} diff --git a/library/std/src/sys/mod.rs b/library/std/src/sys/mod.rs index 1ef17dd530fd2..96d6f2c87c4c1 100644 --- a/library/std/src/sys/mod.rs +++ b/library/std/src/sys/mod.rs @@ -11,6 +11,7 @@ mod personality; pub mod anonymous_pipe; pub mod backtrace; pub mod cmath; +pub mod dbg; pub mod exit_guard; pub mod os_str; pub mod path; From 06c86a106915b5875391a7abdd749f1708dc3b50 Mon Sep 17 00:00:00 2001 From: Wilfred Hughes Date: Thu, 5 Sep 2024 12:36:38 -0700 Subject: [PATCH 0556/2194] fix: Updating settings should not clobber discovered projects `linkedProjects` is owned by the user's configuration, so when users update this setting, `linkedProjects` is reset. This is problematic when `linkedProjects` also contains projects discovered with `discoverCommand`. The buggy behaviour occurred when: (1) The user configures `discoverCommand` and loads a Rust project. (2) The user changes any setting in VS Code, so rust-analyzer receives `workspace/didChangeConfiguration`. (3) `handle_did_change_configuration` ultimately calls `Client::apply_change_with_sink()`, which updates `config.user_config` and discards any items we added in `linkedProjects`. Instead, separate out `discovered_projects_from_filesystem` and `discovered_projects_from_command` from user configuration, so user settings cannot affect any type of discovered project. This fixes the subtle issue mentioned here: https://github.com/rust-lang/rust-analyzer/pull/17246#issuecomment-2185259122 --- .../crates/project-model/src/lib.rs | 9 ++ .../crates/project-model/src/project_json.rs | 2 + .../crates/rust-analyzer/src/config.rs | 133 ++++++++++-------- .../crates/rust-analyzer/src/main_loop.rs | 2 +- 4 files changed, 85 insertions(+), 61 deletions(-) diff --git a/src/tools/rust-analyzer/crates/project-model/src/lib.rs b/src/tools/rust-analyzer/crates/project-model/src/lib.rs index b8ac55ed0d5d1..91bdef4889ca1 100644 --- a/src/tools/rust-analyzer/crates/project-model/src/lib.rs +++ b/src/tools/rust-analyzer/crates/project-model/src/lib.rs @@ -52,6 +52,15 @@ pub use crate::{ }; pub use cargo_metadata::Metadata; +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct ProjectJsonFromCommand { + /// The data describing this project, such as its dependencies. + pub data: ProjectJsonData, + /// The build system specific file that describes this project, + /// such as a `my-project/BUCK` file. + pub buildfile: AbsPathBuf, +} + #[derive(Debug, Clone, PartialEq, Eq, Hash, Ord, PartialOrd)] pub enum ProjectManifest { ProjectJson(ManifestPath), diff --git a/src/tools/rust-analyzer/crates/project-model/src/project_json.rs b/src/tools/rust-analyzer/crates/project-model/src/project_json.rs index a09c7a77abceb..6a88cf022dfb0 100644 --- a/src/tools/rust-analyzer/crates/project-model/src/project_json.rs +++ b/src/tools/rust-analyzer/crates/project-model/src/project_json.rs @@ -66,6 +66,8 @@ pub struct ProjectJson { /// e.g. `path/to/sysroot/lib/rustlib/src/rust` pub(crate) sysroot_src: Option, project_root: AbsPathBuf, + /// The path to the rust-project.json file. May be None if this + /// data was generated by the discoverConfig command. manifest: Option, crates: Vec, /// Configuration for CLI commands. diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs index 714c835812f33..e4e8c9c6d9f97 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs @@ -24,7 +24,8 @@ use ide_db::{ use itertools::Itertools; use paths::{Utf8Path, Utf8PathBuf}; use project_model::{ - CargoConfig, CargoFeatures, ProjectJson, ProjectJsonData, ProjectManifest, RustLibSource, + CargoConfig, CargoFeatures, ProjectJson, ProjectJsonData, ProjectJsonFromCommand, + ProjectManifest, RustLibSource, }; use rustc_hash::{FxHashMap, FxHashSet}; use semver::Version; @@ -761,7 +762,13 @@ enum RatomlFile { #[derive(Debug, Clone)] pub struct Config { - discovered_projects: Vec, + /// Projects that have a Cargo.toml or a rust-project.json in a + /// parent directory, so we can discover them by walking the + /// file system. + discovered_projects_from_filesystem: Vec, + /// Projects whose configuration was generated by a command + /// configured in discoverConfig. + discovered_projects_from_command: Vec, /// The workspace roots as registered by the LSP client workspace_roots: Vec, caps: ClientCapabilities, @@ -1054,19 +1061,19 @@ impl Config { (config, e, should_update) } - pub fn add_linked_projects(&mut self, data: ProjectJsonData, buildfile: AbsPathBuf) { - let linked_projects = &mut self.client_config.0.global.linkedProjects; - - let new_project = ManifestOrProjectJson::DiscoveredProjectJson { data, buildfile }; - match linked_projects { - Some(projects) => { - match projects.iter_mut().find(|p| p.manifest() == new_project.manifest()) { - Some(p) => *p = new_project, - None => projects.push(new_project), - } + pub fn add_discovered_project_from_command( + &mut self, + data: ProjectJsonData, + buildfile: AbsPathBuf, + ) { + for proj in self.discovered_projects_from_command.iter_mut() { + if proj.buildfile == buildfile { + proj.data = data; + return; } - None => *linked_projects = Some(vec![new_project]), } + + self.discovered_projects_from_command.push(ProjectJsonFromCommand { data, buildfile }); } } @@ -1344,7 +1351,8 @@ impl Config { Config { caps: ClientCapabilities::new(caps), - discovered_projects: Vec::new(), + discovered_projects_from_filesystem: Vec::new(), + discovered_projects_from_command: Vec::new(), root_path, snippets: Default::default(), workspace_roots, @@ -1365,7 +1373,7 @@ impl Config { if discovered.is_empty() { tracing::error!("failed to find any projects in {:?}", &self.workspace_roots); } - self.discovered_projects = discovered; + self.discovered_projects_from_filesystem = discovered; } pub fn remove_workspace(&mut self, path: &AbsPath) { @@ -1687,42 +1695,59 @@ impl Config { self.workspace_discoverConfig().as_ref() } - pub fn linked_or_discovered_projects(&self) -> Vec { - match self.linkedProjects().as_slice() { - [] => { - let exclude_dirs: Vec<_> = - self.files_excludeDirs().iter().map(|p| self.root_path.join(p)).collect(); - self.discovered_projects - .iter() - .filter(|project| { - !exclude_dirs.iter().any(|p| project.manifest_path().starts_with(p)) - }) - .cloned() - .map(LinkedProject::from) - .collect() + fn discovered_projects(&self) -> Vec { + let exclude_dirs: Vec<_> = + self.files_excludeDirs().iter().map(|p| self.root_path.join(p)).collect(); + + let mut projects = vec![]; + for fs_proj in &self.discovered_projects_from_filesystem { + let manifest_path = fs_proj.manifest_path(); + if exclude_dirs.iter().any(|p| manifest_path.starts_with(p)) { + continue; } - linked_projects => linked_projects - .iter() - .filter_map(|linked_project| match linked_project { - ManifestOrProjectJson::Manifest(it) => { - let path = self.root_path.join(it); - ProjectManifest::from_manifest_file(path) - .map_err(|e| tracing::error!("failed to load linked project: {}", e)) - .ok() - .map(Into::into) - } - ManifestOrProjectJson::DiscoveredProjectJson { data, buildfile } => { - let root_path = - buildfile.parent().expect("Unable to get parent of buildfile"); - Some(ProjectJson::new(None, root_path, data.clone()).into()) - } - ManifestOrProjectJson::ProjectJson(it) => { - Some(ProjectJson::new(None, &self.root_path, it.clone()).into()) - } - }) - .collect(), + let buf: Utf8PathBuf = manifest_path.to_path_buf().into(); + projects.push(ManifestOrProjectJson::Manifest(buf)); + } + + for dis_proj in &self.discovered_projects_from_command { + projects.push(ManifestOrProjectJson::DiscoveredProjectJson { + data: dis_proj.data.clone(), + buildfile: dis_proj.buildfile.clone(), + }); } + + projects + } + + pub fn linked_or_discovered_projects(&self) -> Vec { + let linked_projects = self.linkedProjects(); + let projects = if linked_projects.is_empty() { + self.discovered_projects() + } else { + linked_projects.clone() + }; + + projects + .iter() + .filter_map(|linked_project| match linked_project { + ManifestOrProjectJson::Manifest(it) => { + let path = self.root_path.join(it); + ProjectManifest::from_manifest_file(path) + .map_err(|e| tracing::error!("failed to load linked project: {}", e)) + .ok() + .map(Into::into) + } + ManifestOrProjectJson::DiscoveredProjectJson { data, buildfile } => { + let root_path = buildfile.parent().expect("Unable to get parent of buildfile"); + + Some(ProjectJson::new(None, root_path, data.clone()).into()) + } + ManifestOrProjectJson::ProjectJson(it) => { + Some(ProjectJson::new(None, &self.root_path, it.clone()).into()) + } + }) + .collect() } pub fn prefill_caches(&self) -> bool { @@ -2282,18 +2307,6 @@ where se.serialize_str(path.as_str()) } -impl ManifestOrProjectJson { - fn manifest(&self) -> Option<&Utf8Path> { - match self { - ManifestOrProjectJson::Manifest(manifest) => Some(manifest), - ManifestOrProjectJson::DiscoveredProjectJson { buildfile, .. } => { - Some(buildfile.as_ref()) - } - ManifestOrProjectJson::ProjectJson(_) => None, - } - } -} - #[derive(Serialize, Deserialize, Debug, Clone)] #[serde(rename_all = "snake_case")] enum ExprFillDefaultDef { diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/main_loop.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/main_loop.rs index ec71b4a7a122f..aa6ff20dc9b40 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/main_loop.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/main_loop.rs @@ -875,7 +875,7 @@ impl GlobalState { self.discover_workspace_queue.op_completed(()); let mut config = Config::clone(&*self.config); - config.add_linked_projects(project, buildfile); + config.add_discovered_project_from_command(project, buildfile); self.update_configuration(config); } DiscoverProjectMessage::Progress { message } => { From 9415e6e6eb9a570acecebd3dda0ed2b5db9fb910 Mon Sep 17 00:00:00 2001 From: Artem Belyakov Date: Sat, 27 Jul 2024 13:33:08 +0300 Subject: [PATCH 0557/2194] Add `manual_div_ceil` --- CHANGELOG.md | 1 + clippy_config/src/conf.rs | 2 +- clippy_config/src/msrvs.rs | 1 + clippy_lints/src/declared_lints.rs | 1 + clippy_lints/src/lib.rs | 2 + clippy_lints/src/manual_div_ceil.rs | 158 +++++++++++++++++++ tests/ui/manual_div_ceil.fixed | 30 ++++ tests/ui/manual_div_ceil.rs | 30 ++++ tests/ui/manual_div_ceil.stderr | 35 ++++ tests/ui/manual_div_ceil_with_feature.fixed | 25 +++ tests/ui/manual_div_ceil_with_feature.rs | 25 +++ tests/ui/manual_div_ceil_with_feature.stderr | 47 ++++++ 12 files changed, 356 insertions(+), 1 deletion(-) create mode 100644 clippy_lints/src/manual_div_ceil.rs create mode 100644 tests/ui/manual_div_ceil.fixed create mode 100644 tests/ui/manual_div_ceil.rs create mode 100644 tests/ui/manual_div_ceil.stderr create mode 100644 tests/ui/manual_div_ceil_with_feature.fixed create mode 100644 tests/ui/manual_div_ceil_with_feature.rs create mode 100644 tests/ui/manual_div_ceil_with_feature.stderr diff --git a/CHANGELOG.md b/CHANGELOG.md index 31fc74192ab11..44a569d1ab54a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5614,6 +5614,7 @@ Released 2018-09-13 [`manual_bits`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_bits [`manual_c_str_literals`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_c_str_literals [`manual_clamp`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_clamp +[`manual_div_ceil`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_div_ceil [`manual_filter`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_filter [`manual_filter_map`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_filter_map [`manual_find`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_find diff --git a/clippy_config/src/conf.rs b/clippy_config/src/conf.rs index a6f1b958bfb17..6c1dd232593a1 100644 --- a/clippy_config/src/conf.rs +++ b/clippy_config/src/conf.rs @@ -864,7 +864,7 @@ fn calculate_dimensions(fields: &[&str]) -> (usize, Vec) { cmp::max(1, terminal_width / (SEPARATOR_WIDTH + max_field_width)) }); - let rows = (fields.len() + (columns - 1)) / columns; + let rows = fields.len().div_ceil(columns); let column_widths = (0..columns) .map(|column| { diff --git a/clippy_config/src/msrvs.rs b/clippy_config/src/msrvs.rs index 0c673ba8046e6..a70effd637699 100644 --- a/clippy_config/src/msrvs.rs +++ b/clippy_config/src/msrvs.rs @@ -21,6 +21,7 @@ msrv_aliases! { 1,80,0 { BOX_INTO_ITER} 1,77,0 { C_STR_LITERALS } 1,76,0 { PTR_FROM_REF, OPTION_RESULT_INSPECT } + 1,73,0 { MANUAL_DIV_CEIL } 1,71,0 { TUPLE_ARRAY_CONVERSIONS, BUILD_HASHER_HASH_ONE } 1,70,0 { OPTION_RESULT_IS_VARIANT_AND, BINARY_HEAP_RETAIN } 1,68,0 { PATH_MAIN_SEPARATOR_STR } diff --git a/clippy_lints/src/declared_lints.rs b/clippy_lints/src/declared_lints.rs index e478ab330e8bc..4804399ef7da1 100644 --- a/clippy_lints/src/declared_lints.rs +++ b/clippy_lints/src/declared_lints.rs @@ -301,6 +301,7 @@ pub static LINTS: &[&crate::LintInfo] = &[ crate::manual_async_fn::MANUAL_ASYNC_FN_INFO, crate::manual_bits::MANUAL_BITS_INFO, crate::manual_clamp::MANUAL_CLAMP_INFO, + crate::manual_div_ceil::MANUAL_DIV_CEIL_INFO, crate::manual_float_methods::MANUAL_IS_FINITE_INFO, crate::manual_float_methods::MANUAL_IS_INFINITE_INFO, crate::manual_hash_one::MANUAL_HASH_ONE_INFO, diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index a9d5f82dfd2cf..9514ba8c315db 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -203,6 +203,7 @@ mod manual_assert; mod manual_async_fn; mod manual_bits; mod manual_clamp; +mod manual_div_ceil; mod manual_float_methods; mod manual_hash_one; mod manual_is_ascii_check; @@ -936,5 +937,6 @@ pub fn register_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) { store.register_early_pass(|| Box::new(cfg_not_test::CfgNotTest)); store.register_late_pass(|_| Box::new(zombie_processes::ZombieProcesses)); store.register_late_pass(|_| Box::new(pointers_in_nomem_asm_block::PointersInNomemAsmBlock)); + store.register_late_pass(move |_| Box::new(manual_div_ceil::ManualDivCeil::new(conf))); // add lints here, do not remove this comment, it's used in `new_lint` } diff --git a/clippy_lints/src/manual_div_ceil.rs b/clippy_lints/src/manual_div_ceil.rs new file mode 100644 index 0000000000000..024c2547dc6eb --- /dev/null +++ b/clippy_lints/src/manual_div_ceil.rs @@ -0,0 +1,158 @@ +use clippy_config::msrvs::{self, Msrv}; +use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::source::snippet_with_applicability; +use clippy_utils::sugg::Sugg; +use clippy_utils::SpanlessEq; +use rustc_ast::{BinOpKind, LitKind}; +use rustc_data_structures::packed::Pu128; +use rustc_errors::Applicability; +use rustc_hir::{Expr, ExprKind}; +use rustc_lint::{LateContext, LateLintPass}; +use rustc_middle::ty::{self}; +use rustc_session::impl_lint_pass; +use rustc_span::symbol::Symbol; + +use clippy_config::Conf; + +declare_clippy_lint! { + /// ### What it does + /// Checks for an expression like `(x + (y - 1)) / y` which is a common manual reimplementation + /// of `x.div_ceil(y)`. + /// + /// ### Why is this bad? + /// It's simpler, clearer and more readable. + /// + /// ### Example + /// ```no_run + /// let x: i32 = 7; + /// let y: i32 = 4; + /// let div = (x + (y - 1)) / y; + /// ``` + /// Use instead: + /// ```no_run + /// #![feature(int_roundings)] + /// let x: i32 = 7; + /// let y: i32 = 4; + /// let div = x.div_ceil(y); + /// ``` + #[clippy::version = "1.81.0"] + pub MANUAL_DIV_CEIL, + complexity, + "manually reimplementing `div_ceil`" +} + +pub struct ManualDivCeil { + msrv: Msrv, +} + +impl ManualDivCeil { + #[must_use] + pub fn new(conf: &'static Conf) -> Self { + Self { + msrv: conf.msrv.clone(), + } + } +} + +impl_lint_pass!(ManualDivCeil => [MANUAL_DIV_CEIL]); + +impl<'tcx> LateLintPass<'tcx> for ManualDivCeil { + fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &Expr<'_>) { + if !self.msrv.meets(msrvs::MANUAL_DIV_CEIL) { + return; + } + + let mut applicability = Applicability::MachineApplicable; + + if let ExprKind::Binary(div_op, div_lhs, div_rhs) = expr.kind + && div_op.node == BinOpKind::Div + && check_int_ty_and_feature(cx, div_lhs) + && check_int_ty_and_feature(cx, div_rhs) + && let ExprKind::Binary(inner_op, inner_lhs, inner_rhs) = div_lhs.kind + { + // (x + (y - 1)) / y + if let ExprKind::Binary(sub_op, sub_lhs, sub_rhs) = inner_rhs.kind + && inner_op.node == BinOpKind::Add + && sub_op.node == BinOpKind::Sub + && check_literal(sub_rhs) + && check_eq_expr(cx, sub_lhs, div_rhs) + { + build_suggestion(cx, expr, inner_lhs, div_rhs, &mut applicability); + return; + } + + // ((y - 1) + x) / y + if let ExprKind::Binary(sub_op, sub_lhs, sub_rhs) = inner_lhs.kind + && inner_op.node == BinOpKind::Add + && sub_op.node == BinOpKind::Sub + && check_literal(sub_rhs) + && check_eq_expr(cx, sub_lhs, div_rhs) + { + build_suggestion(cx, expr, inner_rhs, div_rhs, &mut applicability); + return; + } + + // (x + y - 1) / y + if let ExprKind::Binary(add_op, add_lhs, add_rhs) = inner_lhs.kind + && inner_op.node == BinOpKind::Sub + && add_op.node == BinOpKind::Add + && check_literal(inner_rhs) + && check_eq_expr(cx, add_rhs, div_rhs) + { + build_suggestion(cx, expr, add_lhs, div_rhs, &mut applicability); + } + } + } + + extract_msrv_attr!(LateContext); +} + +fn check_int_ty_and_feature(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { + let expr_ty = cx.typeck_results().expr_ty(expr); + match expr_ty.peel_refs().kind() { + ty::Uint(_) => true, + ty::Int(_) => cx + .tcx + .features() + .declared_features + .contains(&Symbol::intern("int_roundings")), + + _ => false, + } +} + +fn check_literal(expr: &Expr<'_>) -> bool { + if let ExprKind::Lit(lit) = expr.kind + && let LitKind::Int(Pu128(1), _) = lit.node + { + return true; + } + false +} + +fn check_eq_expr(cx: &LateContext<'_>, lhs: &Expr<'_>, rhs: &Expr<'_>) -> bool { + SpanlessEq::new(cx).eq_expr(lhs, rhs) +} + +fn build_suggestion( + cx: &LateContext<'_>, + expr: &Expr<'_>, + lhs: &Expr<'_>, + rhs: &Expr<'_>, + applicability: &mut Applicability, +) { + let dividend_sugg = Sugg::hir_with_applicability(cx, lhs, "..", applicability).maybe_par(); + let divisor_snippet = snippet_with_applicability(cx, rhs.span.source_callsite(), "..", applicability); + + let sugg = format!("{dividend_sugg}.div_ceil({divisor_snippet})"); + + span_lint_and_sugg( + cx, + MANUAL_DIV_CEIL, + expr.span, + "manually reimplementing `div_ceil`", + "consider using `.div_ceil()`", + sugg, + *applicability, + ); +} diff --git a/tests/ui/manual_div_ceil.fixed b/tests/ui/manual_div_ceil.fixed new file mode 100644 index 0000000000000..e7801f7376aaf --- /dev/null +++ b/tests/ui/manual_div_ceil.fixed @@ -0,0 +1,30 @@ +#![warn(clippy::manual_div_ceil)] + +fn main() { + let x = 7_u32; + let y = 4_u32; + let z = 11_u32; + + // Lint + let _ = x.div_ceil(y); //~ ERROR: manually reimplementing `div_ceil` + let _ = x.div_ceil(y); //~ ERROR: manually reimplementing `div_ceil` + let _ = x.div_ceil(y); //~ ERROR: manually reimplementing `div_ceil` + + let _ = 7_u32.div_ceil(4); //~ ERROR: manually reimplementing `div_ceil` + let _ = (7_i32 as u32).div_ceil(4); //~ ERROR: manually reimplementing `div_ceil` + + // No lint + let _ = (x + (y - 2)) / y; + let _ = (x + (y + 1)) / y; + + let _ = (x + (y - 1)) / z; + + let x_i = 7_i32; + let y_i = 4_i32; + let z_i = 11_i32; + + // No lint because `int_roundings` feature is not enabled. + let _ = (z as i32 + (y_i - 1)) / y_i; + let _ = (7_u32 as i32 + (y_i - 1)) / y_i; + let _ = (7_u32 as i32 + (4 - 1)) / 4; +} diff --git a/tests/ui/manual_div_ceil.rs b/tests/ui/manual_div_ceil.rs new file mode 100644 index 0000000000000..2de74c7eaa881 --- /dev/null +++ b/tests/ui/manual_div_ceil.rs @@ -0,0 +1,30 @@ +#![warn(clippy::manual_div_ceil)] + +fn main() { + let x = 7_u32; + let y = 4_u32; + let z = 11_u32; + + // Lint + let _ = (x + (y - 1)) / y; //~ ERROR: manually reimplementing `div_ceil` + let _ = ((y - 1) + x) / y; //~ ERROR: manually reimplementing `div_ceil` + let _ = (x + y - 1) / y; //~ ERROR: manually reimplementing `div_ceil` + + let _ = (7_u32 + (4 - 1)) / 4; //~ ERROR: manually reimplementing `div_ceil` + let _ = (7_i32 as u32 + (4 - 1)) / 4; //~ ERROR: manually reimplementing `div_ceil` + + // No lint + let _ = (x + (y - 2)) / y; + let _ = (x + (y + 1)) / y; + + let _ = (x + (y - 1)) / z; + + let x_i = 7_i32; + let y_i = 4_i32; + let z_i = 11_i32; + + // No lint because `int_roundings` feature is not enabled. + let _ = (z as i32 + (y_i - 1)) / y_i; + let _ = (7_u32 as i32 + (y_i - 1)) / y_i; + let _ = (7_u32 as i32 + (4 - 1)) / 4; +} diff --git a/tests/ui/manual_div_ceil.stderr b/tests/ui/manual_div_ceil.stderr new file mode 100644 index 0000000000000..dc652dff405f2 --- /dev/null +++ b/tests/ui/manual_div_ceil.stderr @@ -0,0 +1,35 @@ +error: manually reimplementing `div_ceil` + --> tests/ui/manual_div_ceil.rs:9:13 + | +LL | let _ = (x + (y - 1)) / y; + | ^^^^^^^^^^^^^^^^^ help: consider using `.div_ceil()`: `x.div_ceil(y)` + | + = note: `-D clippy::manual-div-ceil` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::manual_div_ceil)]` + +error: manually reimplementing `div_ceil` + --> tests/ui/manual_div_ceil.rs:10:13 + | +LL | let _ = ((y - 1) + x) / y; + | ^^^^^^^^^^^^^^^^^ help: consider using `.div_ceil()`: `x.div_ceil(y)` + +error: manually reimplementing `div_ceil` + --> tests/ui/manual_div_ceil.rs:11:13 + | +LL | let _ = (x + y - 1) / y; + | ^^^^^^^^^^^^^^^ help: consider using `.div_ceil()`: `x.div_ceil(y)` + +error: manually reimplementing `div_ceil` + --> tests/ui/manual_div_ceil.rs:13:13 + | +LL | let _ = (7_u32 + (4 - 1)) / 4; + | ^^^^^^^^^^^^^^^^^^^^^ help: consider using `.div_ceil()`: `7_u32.div_ceil(4)` + +error: manually reimplementing `div_ceil` + --> tests/ui/manual_div_ceil.rs:14:13 + | +LL | let _ = (7_i32 as u32 + (4 - 1)) / 4; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `.div_ceil()`: `(7_i32 as u32).div_ceil(4)` + +error: aborting due to 5 previous errors + diff --git a/tests/ui/manual_div_ceil_with_feature.fixed b/tests/ui/manual_div_ceil_with_feature.fixed new file mode 100644 index 0000000000000..a1d678c66898c --- /dev/null +++ b/tests/ui/manual_div_ceil_with_feature.fixed @@ -0,0 +1,25 @@ +#![warn(clippy::manual_div_ceil)] +#![feature(int_roundings)] + +fn main() { + let x = 7_i32; + let y = 4_i32; + let z = 3_i32; + let z_u: u32 = 11; + + // Lint. + let _ = x.div_ceil(y); + let _ = x.div_ceil(y); + let _ = x.div_ceil(y); + + let _ = 7_i32.div_ceil(4); + let _ = (7_i32 as u32).div_ceil(4); + let _ = (7_u32 as i32).div_ceil(4); + let _ = z_u.div_ceil(4); + + // No lint. + let _ = (x + (y - 2)) / y; + let _ = (x + (y + 1)) / y; + + let _ = (x + (y - 1)) / z; +} diff --git a/tests/ui/manual_div_ceil_with_feature.rs b/tests/ui/manual_div_ceil_with_feature.rs new file mode 100644 index 0000000000000..58cb1dbe34d1c --- /dev/null +++ b/tests/ui/manual_div_ceil_with_feature.rs @@ -0,0 +1,25 @@ +#![warn(clippy::manual_div_ceil)] +#![feature(int_roundings)] + +fn main() { + let x = 7_i32; + let y = 4_i32; + let z = 3_i32; + let z_u: u32 = 11; + + // Lint. + let _ = (x + (y - 1)) / y; + let _ = ((y - 1) + x) / y; + let _ = (x + y - 1) / y; + + let _ = (7_i32 + (4 - 1)) / 4; + let _ = (7_i32 as u32 + (4 - 1)) / 4; + let _ = (7_u32 as i32 + (4 - 1)) / 4; + let _ = (z_u + (4 - 1)) / 4; + + // No lint. + let _ = (x + (y - 2)) / y; + let _ = (x + (y + 1)) / y; + + let _ = (x + (y - 1)) / z; +} diff --git a/tests/ui/manual_div_ceil_with_feature.stderr b/tests/ui/manual_div_ceil_with_feature.stderr new file mode 100644 index 0000000000000..361ef9bd9f42a --- /dev/null +++ b/tests/ui/manual_div_ceil_with_feature.stderr @@ -0,0 +1,47 @@ +error: manually reimplementing `div_ceil` + --> tests/ui/manual_div_ceil_with_feature.rs:11:13 + | +LL | let _ = (x + (y - 1)) / y; + | ^^^^^^^^^^^^^^^^^ help: consider using `.div_ceil()`: `x.div_ceil(y)` + | + = note: `-D clippy::manual-div-ceil` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::manual_div_ceil)]` + +error: manually reimplementing `div_ceil` + --> tests/ui/manual_div_ceil_with_feature.rs:12:13 + | +LL | let _ = ((y - 1) + x) / y; + | ^^^^^^^^^^^^^^^^^ help: consider using `.div_ceil()`: `x.div_ceil(y)` + +error: manually reimplementing `div_ceil` + --> tests/ui/manual_div_ceil_with_feature.rs:13:13 + | +LL | let _ = (x + y - 1) / y; + | ^^^^^^^^^^^^^^^ help: consider using `.div_ceil()`: `x.div_ceil(y)` + +error: manually reimplementing `div_ceil` + --> tests/ui/manual_div_ceil_with_feature.rs:15:13 + | +LL | let _ = (7_i32 + (4 - 1)) / 4; + | ^^^^^^^^^^^^^^^^^^^^^ help: consider using `.div_ceil()`: `7_i32.div_ceil(4)` + +error: manually reimplementing `div_ceil` + --> tests/ui/manual_div_ceil_with_feature.rs:16:13 + | +LL | let _ = (7_i32 as u32 + (4 - 1)) / 4; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `.div_ceil()`: `(7_i32 as u32).div_ceil(4)` + +error: manually reimplementing `div_ceil` + --> tests/ui/manual_div_ceil_with_feature.rs:17:13 + | +LL | let _ = (7_u32 as i32 + (4 - 1)) / 4; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `.div_ceil()`: `(7_u32 as i32).div_ceil(4)` + +error: manually reimplementing `div_ceil` + --> tests/ui/manual_div_ceil_with_feature.rs:18:13 + | +LL | let _ = (z_u + (4 - 1)) / 4; + | ^^^^^^^^^^^^^^^^^^^ help: consider using `.div_ceil()`: `z_u.div_ceil(4)` + +error: aborting due to 7 previous errors + From 3699e939e8f6a2517806a219c082723d50dd4288 Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Thu, 5 Sep 2024 17:58:05 -0700 Subject: [PATCH 0558/2194] rustdoc-search: allow trailing `Foo ->` arg search --- src/librustdoc/html/static/js/externs.js | 1 + src/librustdoc/html/static/js/search.js | 10 ++-- tests/rustdoc-js-std/parser-errors.js | 9 ---- tests/rustdoc-js-std/parser-returned.js | 68 ++++++++++++++++++++++++ tests/rustdoc-js/never-search.js | 7 +++ 5 files changed, 81 insertions(+), 14 deletions(-) diff --git a/src/librustdoc/html/static/js/externs.js b/src/librustdoc/html/static/js/externs.js index 6fd60d6cc3461..3d3e0a8f8381c 100644 --- a/src/librustdoc/html/static/js/externs.js +++ b/src/librustdoc/html/static/js/externs.js @@ -41,6 +41,7 @@ let ParserState; * foundElems: number, * totalElems: number, * literalSearch: boolean, + * hasReturnArrow: boolean, * corrections: Array<{from: string, to: integer}> | null, * typeFingerprint: Uint32Array, * error: Array | null, diff --git a/src/librustdoc/html/static/js/search.js b/src/librustdoc/html/static/js/search.js index 6f575e60ed42b..4da0bbc787d9e 100644 --- a/src/librustdoc/html/static/js/search.js +++ b/src/librustdoc/html/static/js/search.js @@ -657,7 +657,7 @@ function createQueryElement(query, parserState, name, generics, isInGenerics) { } const typeFilter = parserState.typeFilter; parserState.typeFilter = null; - if (name === "!") { + if (name.trim() === "!") { if (typeFilter !== null && typeFilter !== "primitive") { throw [ "Invalid search type: primitive never type ", @@ -1795,6 +1795,7 @@ class DocSearch { // Total number of elements (includes generics). totalElems: 0, literalSearch: false, + hasReturnArrow: false, error: null, correction: null, proposeCorrectionFrom: null, @@ -1823,6 +1824,7 @@ class DocSearch { continue; } else if (c === "-" || c === ">") { if (isReturnArrow(parserState)) { + query.hasReturnArrow = true; break; } throw ["Unexpected ", c, " (did you mean ", "->", "?)"]; @@ -1889,9 +1891,7 @@ class DocSearch { // Get returned elements. getItemsBefore(query, parserState, query.returned, ""); // Nothing can come afterward! - if (query.returned.length === 0) { - throw ["Expected at least one item after ", "->"]; - } + query.hasReturnArrow = true; break; } else { parserState.pos += 1; @@ -3249,7 +3249,7 @@ class DocSearch { this.buildFunctionTypeFingerprint(elem, parsedQuery.typeFingerprint, fps); } - if (parsedQuery.foundElems === 1 && parsedQuery.returned.length === 0) { + if (parsedQuery.foundElems === 1 && !parsedQuery.hasReturnArrow) { if (parsedQuery.elems.length === 1) { const elem = parsedQuery.elems[0]; const length = this.searchIndex.length; diff --git a/tests/rustdoc-js-std/parser-errors.js b/tests/rustdoc-js-std/parser-errors.js index c4d7c2b0b8597..5ce35bf511d75 100644 --- a/tests/rustdoc-js-std/parser-errors.js +++ b/tests/rustdoc-js-std/parser-errors.js @@ -251,15 +251,6 @@ const PARSED = [ userQuery: "ab'", error: "Unexpected `'` after `b` (not a valid identifier)", }, - { - query: "a->", - elems: [], - foundElems: 0, - original: "a->", - returned: [], - userQuery: "a->", - error: "Expected at least one item after `->`", - }, { query: '"p"
', elems: [], diff --git a/tests/rustdoc-js-std/parser-returned.js b/tests/rustdoc-js-std/parser-returned.js index 44e517c49b59c..8f68209bb966f 100644 --- a/tests/rustdoc-js-std/parser-returned.js +++ b/tests/rustdoc-js-std/parser-returned.js @@ -94,4 +94,72 @@ const PARSED = [ userQuery: "-> !", error: null, }, + { + query: "a->", + elems: [{ + name: "a", + fullPath: ["a"], + pathWithoutLast: [], + pathLast: "a", + generics: [], + typeFilter: -1, + }], + foundElems: 1, + original: "a->", + returned: [], + userQuery: "a->", + hasReturnArrow: true, + error: null, + }, + { + query: "!->", + elems: [{ + name: "never", + fullPath: ["never"], + pathWithoutLast: [], + pathLast: "never", + generics: [], + typeFilter: 1, + }], + foundElems: 1, + original: "!->", + returned: [], + userQuery: "!->", + hasReturnArrow: true, + error: null, + }, + { + query: "! ->", + elems: [{ + name: "never", + fullPath: ["never"], + pathWithoutLast: [], + pathLast: "never", + generics: [], + typeFilter: 1, + }], + foundElems: 1, + original: "! ->", + returned: [], + userQuery: "! ->", + hasReturnArrow: true, + error: null, + }, + { + query: "primitive:!->", + elems: [{ + name: "never", + fullPath: ["never"], + pathWithoutLast: [], + pathLast: "never", + generics: [], + typeFilter: 1, + }], + foundElems: 1, + original: "primitive:!->", + returned: [], + userQuery: "primitive:!->", + hasReturnArrow: true, + error: null, + }, ]; diff --git a/tests/rustdoc-js/never-search.js b/tests/rustdoc-js/never-search.js index 9f18370c2f511..9cc62a5ed04a5 100644 --- a/tests/rustdoc-js/never-search.js +++ b/tests/rustdoc-js/never-search.js @@ -1,6 +1,13 @@ // exact-check const EXPECTED = [ + { + 'query': '! ->', + 'others': [ + { 'path': 'never_search', 'name': 'impossible' }, + { 'path': 'never_search', 'name': 'box_impossible' }, + ], + }, { 'query': '-> !', 'others': [ From cb0b5199ffbeec62ff622349c3bc15d9b9772a50 Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Thu, 5 Sep 2024 21:28:04 -0400 Subject: [PATCH 0559/2194] Add more SIMD intrinsics --- src/intrinsic/llvm.rs | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/src/intrinsic/llvm.rs b/src/intrinsic/llvm.rs index 89d5d582e4c71..e57dc1cc75f60 100644 --- a/src/intrinsic/llvm.rs +++ b/src/intrinsic/llvm.rs @@ -13,6 +13,11 @@ pub fn adjust_intrinsic_arguments<'a, 'b, 'gcc, 'tcx>( func_name: &str, original_function_name: Option<&String>, ) -> Cow<'b, [RValue<'gcc>]> { + // TODO: this might not be a good way to workaround the missing tile builtins. + if func_name == "__builtin_trap" { + return vec![].into(); + } + // Some LLVM intrinsics do not map 1-to-1 to GCC intrinsics, so we add the missing // arguments here. if gcc_func.get_param_count() != args.len() { @@ -287,7 +292,9 @@ pub fn adjust_intrinsic_arguments<'a, 'b, 'gcc, 'tcx>( new_args.push(last_arg); args = new_args.into(); } - "__builtin_ia32_vfmaddsubps512_mask" | "__builtin_ia32_vfmaddsubpd512_mask" => { + "__builtin_ia32_vfmaddsubps512_mask" + | "__builtin_ia32_vfmaddsubpd512_mask" + | "__builtin_ia32_cmpsh_mask_round" => { let mut new_args = args.to_vec(); let last_arg = new_args.pop().expect("last arg"); let arg4_type = gcc_func.get_param_type(3); @@ -1085,6 +1092,17 @@ pub fn intrinsic<'gcc, 'tcx>(name: &str, cx: &CodegenCx<'gcc, 'tcx>) -> Function "llvm.x86.avx512.mask.load.pd.512" => "__builtin_ia32_loadapd512_mask", "llvm.x86.avx512.mask.load.d.256" => "__builtin_ia32_movdqa32load256_mask", "llvm.x86.avx512.mask.load.q.256" => "__builtin_ia32_movdqa64load256_mask", + "llvm.x86.avx512fp16.mask.cmp.sh" => "__builtin_ia32_cmpsh_mask_round", + "llvm.x86.avx512fp16.vcomi.sh" => "__builtin_ia32_cmpsh_mask_round", + // TODO: support the tile builtins: + "llvm.x86.ldtilecfg" => "__builtin_trap", + "llvm.x86.sttilecfg" => "__builtin_trap", + "llvm.x86.tileloadd64" => "__builtin_trap", + "llvm.x86.tilerelease" => "__builtin_trap", + "llvm.x86.tilestored64" => "__builtin_trap", + "llvm.x86.tileloaddt164" => "__builtin_trap", + "llvm.x86.tilezero" => "__builtin_trap", + "llvm.x86.tdpbf16ps" => "__builtin_trap", // NOTE: this file is generated by https://github.com/GuillaumeGomez/llvmint/blob/master/generate_list.py _ => include!("archs.rs"), From d7996da9dae165c7d6e700f8b734392db30f9697 Mon Sep 17 00:00:00 2001 From: Sour1emon Date: Sat, 31 Aug 2024 16:30:03 -0700 Subject: [PATCH 0560/2194] Add `manual_is_power_of_two` --- CHANGELOG.md | 1 + clippy_lints/src/declared_lints.rs | 1 + clippy_lints/src/lib.rs | 2 + clippy_lints/src/manual_is_power_of_two.rs | 88 ++++++++++++++++++++++ tests/ui/manual_is_power_of_two.fixed | 14 ++++ tests/ui/manual_is_power_of_two.rs | 14 ++++ tests/ui/manual_is_power_of_two.stderr | 17 +++++ 7 files changed, 137 insertions(+) create mode 100644 clippy_lints/src/manual_is_power_of_two.rs create mode 100644 tests/ui/manual_is_power_of_two.fixed create mode 100644 tests/ui/manual_is_power_of_two.rs create mode 100644 tests/ui/manual_is_power_of_two.stderr diff --git a/CHANGELOG.md b/CHANGELOG.md index 44a569d1ab54a..f1de51c936ea0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5626,6 +5626,7 @@ Released 2018-09-13 [`manual_is_ascii_check`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_is_ascii_check [`manual_is_finite`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_is_finite [`manual_is_infinite`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_is_infinite +[`manual_is_power_of_two`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_is_power_of_two [`manual_is_variant_and`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_is_variant_and [`manual_let_else`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_let_else [`manual_main_separator_str`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_main_separator_str diff --git a/clippy_lints/src/declared_lints.rs b/clippy_lints/src/declared_lints.rs index 4804399ef7da1..6f468f01b2fde 100644 --- a/clippy_lints/src/declared_lints.rs +++ b/clippy_lints/src/declared_lints.rs @@ -306,6 +306,7 @@ pub static LINTS: &[&crate::LintInfo] = &[ crate::manual_float_methods::MANUAL_IS_INFINITE_INFO, crate::manual_hash_one::MANUAL_HASH_ONE_INFO, crate::manual_is_ascii_check::MANUAL_IS_ASCII_CHECK_INFO, + crate::manual_is_power_of_two::MANUAL_IS_POWER_OF_TWO_INFO, crate::manual_let_else::MANUAL_LET_ELSE_INFO, crate::manual_main_separator_str::MANUAL_MAIN_SEPARATOR_STR_INFO, crate::manual_non_exhaustive::MANUAL_NON_EXHAUSTIVE_INFO, diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 9514ba8c315db..bc16a3b0c014e 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -207,6 +207,7 @@ mod manual_div_ceil; mod manual_float_methods; mod manual_hash_one; mod manual_is_ascii_check; +mod manual_is_power_of_two; mod manual_let_else; mod manual_main_separator_str; mod manual_non_exhaustive; @@ -938,5 +939,6 @@ pub fn register_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) { store.register_late_pass(|_| Box::new(zombie_processes::ZombieProcesses)); store.register_late_pass(|_| Box::new(pointers_in_nomem_asm_block::PointersInNomemAsmBlock)); store.register_late_pass(move |_| Box::new(manual_div_ceil::ManualDivCeil::new(conf))); + store.register_late_pass(|_| Box::new(manual_is_power_of_two::ManualIsPowerOfTwo)); // add lints here, do not remove this comment, it's used in `new_lint` } diff --git a/clippy_lints/src/manual_is_power_of_two.rs b/clippy_lints/src/manual_is_power_of_two.rs new file mode 100644 index 0000000000000..a65401fc571aa --- /dev/null +++ b/clippy_lints/src/manual_is_power_of_two.rs @@ -0,0 +1,88 @@ +use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::source::snippet_with_applicability; +use rustc_ast::LitKind; +use rustc_data_structures::packed::Pu128; +use rustc_errors::Applicability; +use rustc_hir::{BinOpKind, Expr, ExprKind}; +use rustc_lint::{LateContext, LateLintPass}; +use rustc_middle::ty::Uint; +use rustc_session::declare_lint_pass; + +declare_clippy_lint! { + /// ### What it does + /// Checks for expressions like `x.count_ones() == 1` or `x & (x - 1) == 0` which are manual + /// reimplementations of `x.is_power_of_two()`` + /// ### Why is this bad? + /// It's simpler and clearer + /// ### Example + /// ```no_run + /// let x: u32 = 1; + /// let result = x.count_ones() == 1; + /// ``` + /// Use instead: + /// ```no_run + /// let x: u32 = 1; + /// let result = x.is_power_of_two(); + /// ``` + #[clippy::version = "1.82.0"] + pub MANUAL_IS_POWER_OF_TWO, + complexity, + "manually reimplementing `is_power_of_two`" +} + +declare_lint_pass!(ManualIsPowerOfTwo => [MANUAL_IS_POWER_OF_TWO]); + +impl LateLintPass<'_> for ManualIsPowerOfTwo { + fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) { + let mut applicability = Applicability::MachineApplicable; + + // x.count_ones() == 1 + if let ExprKind::Binary(op, left, right) = expr.kind + && BinOpKind::Eq == op.node + && let ExprKind::MethodCall(method_name, reciever, _, _) = left.kind + && method_name.ident.as_str() == "count_ones" + && let ExprKind::Lit(lit) = right.kind + && let LitKind::Int(Pu128(1), _) = lit.node + && let &Uint(_) = cx.typeck_results().expr_ty(reciever).kind() + { + let snippet = snippet_with_applicability(cx, reciever.span, "..", &mut applicability); + let sugg = format!("{snippet}.is_power_of_two()"); + span_lint_and_sugg( + cx, + MANUAL_IS_POWER_OF_TWO, + expr.span, + "manually reimplementing `is_power_of_two`", + "consider using `.is_power_of_two()`", + sugg, + applicability, + ); + } + + // x & (x - 1) == 0 + if let ExprKind::Binary(op, left, right) = expr.kind + && BinOpKind::Eq == op.node + && let ExprKind::Binary(op1, left1, right1) = left.kind + && BinOpKind::BitAnd == op1.node + && let ExprKind::Binary(op2, left2, right2) = right1.kind + && BinOpKind::Sub == op2.node + && left1.span.eq_ctxt(left2.span) + && let &Uint(_) = cx.typeck_results().expr_ty(left1).kind() + && let ExprKind::Lit(lit) = right2.kind + && let LitKind::Int(Pu128(1), _) = lit.node + && let ExprKind::Lit(lit1) = right.kind + && let LitKind::Int(Pu128(0), _) = lit1.node + { + let snippet = snippet_with_applicability(cx, left1.span, "..", &mut applicability); + let sugg = format!("{snippet}.is_power_of_two()"); + span_lint_and_sugg( + cx, + MANUAL_IS_POWER_OF_TWO, + expr.span, + "manually reimplementing `is_power_of_two`", + "consider using `.is_power_of_two()`", + sugg, + applicability, + ); + } + } +} diff --git a/tests/ui/manual_is_power_of_two.fixed b/tests/ui/manual_is_power_of_two.fixed new file mode 100644 index 0000000000000..beee2eaf665a9 --- /dev/null +++ b/tests/ui/manual_is_power_of_two.fixed @@ -0,0 +1,14 @@ +#![warn(clippy::manual_is_power_of_two)] + +fn main() { + let a = 16_u64; + + let _ = a.is_power_of_two(); + let _ = a.is_power_of_two(); + + let b = 4_i64; + + // is_power_of_two only works for unsigned integers + let _ = b.count_ones() == 1; + let _ = b & (b - 1) == 0; +} diff --git a/tests/ui/manual_is_power_of_two.rs b/tests/ui/manual_is_power_of_two.rs new file mode 100644 index 0000000000000..0810b4c28da75 --- /dev/null +++ b/tests/ui/manual_is_power_of_two.rs @@ -0,0 +1,14 @@ +#![warn(clippy::manual_is_power_of_two)] + +fn main() { + let a = 16_u64; + + let _ = a.count_ones() == 1; + let _ = a & (a - 1) == 0; + + let b = 4_i64; + + // is_power_of_two only works for unsigned integers + let _ = b.count_ones() == 1; + let _ = b & (b - 1) == 0; +} diff --git a/tests/ui/manual_is_power_of_two.stderr b/tests/ui/manual_is_power_of_two.stderr new file mode 100644 index 0000000000000..c7dfe6b11b99e --- /dev/null +++ b/tests/ui/manual_is_power_of_two.stderr @@ -0,0 +1,17 @@ +error: manually reimplementing `is_power_of_two` + --> tests/ui/manual_is_power_of_two.rs:6:13 + | +LL | let _ = a.count_ones() == 1; + | ^^^^^^^^^^^^^^^^^^^ help: consider using `.is_power_of_two()`: `a.is_power_of_two()` + | + = note: `-D clippy::manual-is-power-of-two` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::manual_is_power_of_two)]` + +error: manually reimplementing `is_power_of_two` + --> tests/ui/manual_is_power_of_two.rs:7:13 + | +LL | let _ = a & (a - 1) == 0; + | ^^^^^^^^^^^^^^^^ help: consider using `.is_power_of_two()`: `a.is_power_of_two()` + +error: aborting due to 2 previous errors + From 5515566829f3b7ba3c302c5058e986657c01cc7e Mon Sep 17 00:00:00 2001 From: Isaac Bess Date: Mon, 2 Sep 2024 17:00:32 -0700 Subject: [PATCH 0561/2194] Improve "Why this is bad" section Co-authored-by: Ruby Lazuli --- clippy_lints/src/manual_is_power_of_two.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/manual_is_power_of_two.rs b/clippy_lints/src/manual_is_power_of_two.rs index a65401fc571aa..daa1abf61f1a6 100644 --- a/clippy_lints/src/manual_is_power_of_two.rs +++ b/clippy_lints/src/manual_is_power_of_two.rs @@ -13,7 +13,7 @@ declare_clippy_lint! { /// Checks for expressions like `x.count_ones() == 1` or `x & (x - 1) == 0` which are manual /// reimplementations of `x.is_power_of_two()`` /// ### Why is this bad? - /// It's simpler and clearer + /// Manual reimplementations of `is_power_of_two` increase code complexity for little benefit. /// ### Example /// ```no_run /// let x: u32 = 1; From 6ecb48f6d0becb8ff365b787106a8be429b4637a Mon Sep 17 00:00:00 2001 From: Isaac Bess Date: Mon, 2 Sep 2024 17:01:20 -0700 Subject: [PATCH 0562/2194] Fixed extra backtick Co-authored-by: Ruby Lazuli --- clippy_lints/src/manual_is_power_of_two.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/manual_is_power_of_two.rs b/clippy_lints/src/manual_is_power_of_two.rs index daa1abf61f1a6..c7ac668267afb 100644 --- a/clippy_lints/src/manual_is_power_of_two.rs +++ b/clippy_lints/src/manual_is_power_of_two.rs @@ -10,8 +10,8 @@ use rustc_session::declare_lint_pass; declare_clippy_lint! { /// ### What it does - /// Checks for expressions like `x.count_ones() == 1` or `x & (x - 1) == 0` which are manual - /// reimplementations of `x.is_power_of_two()`` + /// Checks for expressions like `x.count_ones() == 1` or `x & (x - 1) == 0`, which are manual + /// reimplementations of `x.is_power_of_two()`. /// ### Why is this bad? /// Manual reimplementations of `is_power_of_two` increase code complexity for little benefit. /// ### Example From f994797e4612f97a0f489e794f30c2113ce8d61e Mon Sep 17 00:00:00 2001 From: Sour1emon Date: Thu, 5 Sep 2024 18:23:00 -0700 Subject: [PATCH 0563/2194] Add support for different orders of expression --- clippy_lints/src/manual_is_power_of_two.rs | 154 ++++++++++++++------- tests/ui/manual_is_power_of_two.fixed | 6 + tests/ui/manual_is_power_of_two.rs | 6 + tests/ui/manual_is_power_of_two.stderr | 26 +++- 4 files changed, 141 insertions(+), 51 deletions(-) diff --git a/clippy_lints/src/manual_is_power_of_two.rs b/clippy_lints/src/manual_is_power_of_two.rs index c7ac668267afb..d7879403ebb5a 100644 --- a/clippy_lints/src/manual_is_power_of_two.rs +++ b/clippy_lints/src/manual_is_power_of_two.rs @@ -1,5 +1,6 @@ use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::source::snippet_with_applicability; +use clippy_utils::SpanlessEq; use rustc_ast::LitKind; use rustc_data_structures::packed::Pu128; use rustc_errors::Applicability; @@ -10,19 +11,19 @@ use rustc_session::declare_lint_pass; declare_clippy_lint! { /// ### What it does - /// Checks for expressions like `x.count_ones() == 1` or `x & (x - 1) == 0`, which are manual + /// Checks for expressions like `x.count_ones() == 1` or `x & (x - 1) == 0`, with x and unsigned integer, which are manual /// reimplementations of `x.is_power_of_two()`. /// ### Why is this bad? /// Manual reimplementations of `is_power_of_two` increase code complexity for little benefit. /// ### Example /// ```no_run - /// let x: u32 = 1; - /// let result = x.count_ones() == 1; + /// let a: u32 = 4; + /// let result = a.count_ones() == 1; /// ``` /// Use instead: /// ```no_run - /// let x: u32 = 1; - /// let result = x.is_power_of_two(); + /// let a: u32 = 4; + /// let result = a.is_power_of_two(); /// ``` #[clippy::version = "1.82.0"] pub MANUAL_IS_POWER_OF_TWO, @@ -36,53 +37,106 @@ impl LateLintPass<'_> for ManualIsPowerOfTwo { fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) { let mut applicability = Applicability::MachineApplicable; - // x.count_ones() == 1 - if let ExprKind::Binary(op, left, right) = expr.kind - && BinOpKind::Eq == op.node - && let ExprKind::MethodCall(method_name, reciever, _, _) = left.kind - && method_name.ident.as_str() == "count_ones" - && let ExprKind::Lit(lit) = right.kind - && let LitKind::Int(Pu128(1), _) = lit.node - && let &Uint(_) = cx.typeck_results().expr_ty(reciever).kind() + if let ExprKind::Binary(bin_op, left, right) = expr.kind + && bin_op.node == BinOpKind::Eq { - let snippet = snippet_with_applicability(cx, reciever.span, "..", &mut applicability); - let sugg = format!("{snippet}.is_power_of_two()"); - span_lint_and_sugg( - cx, - MANUAL_IS_POWER_OF_TWO, - expr.span, - "manually reimplementing `is_power_of_two`", - "consider using `.is_power_of_two()`", - sugg, - applicability, - ); - } + // a.count_ones() == 1 + if let ExprKind::MethodCall(method_name, reciever, _, _) = left.kind + && method_name.ident.as_str() == "count_ones" + && let &Uint(_) = cx.typeck_results().expr_ty(reciever).kind() + && check_lit(right, 1) + { + build_sugg(cx, expr, reciever, &mut applicability); + } - // x & (x - 1) == 0 - if let ExprKind::Binary(op, left, right) = expr.kind - && BinOpKind::Eq == op.node - && let ExprKind::Binary(op1, left1, right1) = left.kind - && BinOpKind::BitAnd == op1.node - && let ExprKind::Binary(op2, left2, right2) = right1.kind - && BinOpKind::Sub == op2.node - && left1.span.eq_ctxt(left2.span) - && let &Uint(_) = cx.typeck_results().expr_ty(left1).kind() - && let ExprKind::Lit(lit) = right2.kind - && let LitKind::Int(Pu128(1), _) = lit.node - && let ExprKind::Lit(lit1) = right.kind - && let LitKind::Int(Pu128(0), _) = lit1.node - { - let snippet = snippet_with_applicability(cx, left1.span, "..", &mut applicability); - let sugg = format!("{snippet}.is_power_of_two()"); - span_lint_and_sugg( - cx, - MANUAL_IS_POWER_OF_TWO, - expr.span, - "manually reimplementing `is_power_of_two`", - "consider using `.is_power_of_two()`", - sugg, - applicability, - ); + // 1 == a.count_ones() + if let ExprKind::MethodCall(method_name, reciever, _, _) = right.kind + && method_name.ident.as_str() == "count_ones" + && let &Uint(_) = cx.typeck_results().expr_ty(reciever).kind() + && check_lit(left, 1) + { + build_sugg(cx, expr, reciever, &mut applicability); + } + + // a & (a - 1) == 0 + if let ExprKind::Binary(op1, left1, right1) = left.kind + && op1.node == BinOpKind::BitAnd + && let ExprKind::Binary(op2, left2, right2) = right1.kind + && op2.node == BinOpKind::Sub + && check_eq_expr(cx, left1, left2) + && let &Uint(_) = cx.typeck_results().expr_ty(left1).kind() + && check_lit(right2, 1) + && check_lit(right, 0) + { + build_sugg(cx, expr, left1, &mut applicability); + } + + // (a - 1) & a == 0; + if let ExprKind::Binary(op1, left1, right1) = left.kind + && op1.node == BinOpKind::BitAnd + && let ExprKind::Binary(op2, left2, right2) = left1.kind + && op2.node == BinOpKind::Sub + && check_eq_expr(cx, right1, left2) + && let &Uint(_) = cx.typeck_results().expr_ty(right1).kind() + && check_lit(right2, 1) + && check_lit(right, 0) + { + build_sugg(cx, expr, right1, &mut applicability); + } + + // 0 == a & (a - 1); + if let ExprKind::Binary(op1, left1, right1) = right.kind + && op1.node == BinOpKind::BitAnd + && let ExprKind::Binary(op2, left2, right2) = right1.kind + && op2.node == BinOpKind::Sub + && check_eq_expr(cx, left1, left2) + && let &Uint(_) = cx.typeck_results().expr_ty(left1).kind() + && check_lit(right2, 1) + && check_lit(left, 0) + { + build_sugg(cx, expr, left1, &mut applicability); + } + + // 0 == (a - 1) & a + if let ExprKind::Binary(op1, left1, right1) = right.kind + && op1.node == BinOpKind::BitAnd + && let ExprKind::Binary(op2, left2, right2) = left1.kind + && op2.node == BinOpKind::Sub + && check_eq_expr(cx, right1, left2) + && let &Uint(_) = cx.typeck_results().expr_ty(right1).kind() + && check_lit(right2, 1) + && check_lit(left, 0) + { + build_sugg(cx, expr, right1, &mut applicability); + } } } } + +fn build_sugg(cx: &LateContext<'_>, expr: &Expr<'_>, reciever: &Expr<'_>, applicability: &mut Applicability) { + let snippet = snippet_with_applicability(cx, reciever.span, "..", applicability); + + span_lint_and_sugg( + cx, + MANUAL_IS_POWER_OF_TWO, + expr.span, + "manually reimplementing `is_power_of_two`", + "consider using `.is_power_of_two()`", + format!("{snippet}.is_power_of_two()"), + *applicability, + ); +} + +fn check_lit(expr: &Expr<'_>, expected_num: u128) -> bool { + if let ExprKind::Lit(lit) = expr.kind + && let LitKind::Int(Pu128(num), _) = lit.node + && num == expected_num + { + return true; + } + false +} + +fn check_eq_expr(cx: &LateContext<'_>, lhs: &Expr<'_>, rhs: &Expr<'_>) -> bool { + SpanlessEq::new(cx).eq_expr(lhs, rhs) +} diff --git a/tests/ui/manual_is_power_of_two.fixed b/tests/ui/manual_is_power_of_two.fixed index beee2eaf665a9..dda5fe0ec3e77 100644 --- a/tests/ui/manual_is_power_of_two.fixed +++ b/tests/ui/manual_is_power_of_two.fixed @@ -6,6 +6,12 @@ fn main() { let _ = a.is_power_of_two(); let _ = a.is_power_of_two(); + // Test different orders of expression + let _ = a.is_power_of_two(); + let _ = a.is_power_of_two(); + let _ = a.is_power_of_two(); + let _ = a.is_power_of_two(); + let b = 4_i64; // is_power_of_two only works for unsigned integers diff --git a/tests/ui/manual_is_power_of_two.rs b/tests/ui/manual_is_power_of_two.rs index 0810b4c28da75..a1d3a95c4102b 100644 --- a/tests/ui/manual_is_power_of_two.rs +++ b/tests/ui/manual_is_power_of_two.rs @@ -6,6 +6,12 @@ fn main() { let _ = a.count_ones() == 1; let _ = a & (a - 1) == 0; + // Test different orders of expression + let _ = 1 == a.count_ones(); + let _ = (a - 1) & a == 0; + let _ = 0 == a & (a - 1); + let _ = 0 == (a - 1) & a; + let b = 4_i64; // is_power_of_two only works for unsigned integers diff --git a/tests/ui/manual_is_power_of_two.stderr b/tests/ui/manual_is_power_of_two.stderr index c7dfe6b11b99e..3cfc6297abf27 100644 --- a/tests/ui/manual_is_power_of_two.stderr +++ b/tests/ui/manual_is_power_of_two.stderr @@ -13,5 +13,29 @@ error: manually reimplementing `is_power_of_two` LL | let _ = a & (a - 1) == 0; | ^^^^^^^^^^^^^^^^ help: consider using `.is_power_of_two()`: `a.is_power_of_two()` -error: aborting due to 2 previous errors +error: manually reimplementing `is_power_of_two` + --> tests/ui/manual_is_power_of_two.rs:10:13 + | +LL | let _ = 1 == a.count_ones(); + | ^^^^^^^^^^^^^^^^^^^ help: consider using `.is_power_of_two()`: `a.is_power_of_two()` + +error: manually reimplementing `is_power_of_two` + --> tests/ui/manual_is_power_of_two.rs:11:13 + | +LL | let _ = (a - 1) & a == 0; + | ^^^^^^^^^^^^^^^^ help: consider using `.is_power_of_two()`: `a.is_power_of_two()` + +error: manually reimplementing `is_power_of_two` + --> tests/ui/manual_is_power_of_two.rs:12:13 + | +LL | let _ = 0 == a & (a - 1); + | ^^^^^^^^^^^^^^^^ help: consider using `.is_power_of_two()`: `a.is_power_of_two()` + +error: manually reimplementing `is_power_of_two` + --> tests/ui/manual_is_power_of_two.rs:13:13 + | +LL | let _ = 0 == (a - 1) & a; + | ^^^^^^^^^^^^^^^^ help: consider using `.is_power_of_two()`: `a.is_power_of_two()` + +error: aborting due to 6 previous errors From 4f5c16d62f250024a111aaf827927c32bc88e4da Mon Sep 17 00:00:00 2001 From: Manuel Drehwald Date: Wed, 4 Sep 2024 15:25:43 -0400 Subject: [PATCH 0564/2194] Enzyme backend Co-authored-by: Lorenz Schmidt --- .gitmodules | 4 + config.example.toml | 3 + src/bootstrap/configure.py | 1 + src/bootstrap/src/core/build_steps/compile.rs | 22 +++++ src/bootstrap/src/core/build_steps/llvm.rs | 95 +++++++++++++++++++ src/bootstrap/src/core/builder.rs | 7 ++ src/bootstrap/src/core/config/config.rs | 8 ++ src/bootstrap/src/lib.rs | 10 ++ src/bootstrap/src/utils/change_tracker.rs | 5 + src/tools/enzyme | 1 + src/tools/tidy/config/black.toml | 1 + src/tools/tidy/config/ruff.toml | 2 + src/tools/tidy/src/walk.rs | 1 + 13 files changed, 160 insertions(+) create mode 160000 src/tools/enzyme diff --git a/.gitmodules b/.gitmodules index b5250d493864e..926807336d791 100644 --- a/.gitmodules +++ b/.gitmodules @@ -47,3 +47,7 @@ path = src/tools/rustc-perf url = https://github.com/rust-lang/rustc-perf.git shallow = true +[submodule "src/tools/enzyme"] + path = src/tools/enzyme + url = https://github.com/EnzymeAD/Enzyme.git + shallow = true diff --git a/config.example.toml b/config.example.toml index 13f76933b1659..e9433c9c9bd08 100644 --- a/config.example.toml +++ b/config.example.toml @@ -78,6 +78,9 @@ # Indicates whether the LLVM plugin is enabled or not #plugins = false +# Wheter to build Enzyme as AutoDiff backend. +#enzyme = false + # Indicates whether ccache is used when building LLVM. Set to `true` to use the first `ccache` in # PATH, or set an absolute path to use a specific version. #ccache = false diff --git a/src/bootstrap/configure.py b/src/bootstrap/configure.py index 768aac912ce47..49d564642bd65 100755 --- a/src/bootstrap/configure.py +++ b/src/bootstrap/configure.py @@ -71,6 +71,7 @@ def v(*args): # channel, etc. o("optimize-llvm", "llvm.optimize", "build optimized LLVM") o("llvm-assertions", "llvm.assertions", "build LLVM with assertions") +o("llvm-enzyme", "llvm.enzyme", "build LLVM with enzyme") o("llvm-plugins", "llvm.plugins", "build LLVM with plugin interface") o("debug-assertions", "rust.debug-assertions", "build with debugging assertions") o("debug-assertions-std", "rust.debug-assertions-std", "build the standard library with debugging assertions") diff --git a/src/bootstrap/src/core/build_steps/compile.rs b/src/bootstrap/src/core/build_steps/compile.rs index eef548033f1c6..8467f2e21117d 100644 --- a/src/bootstrap/src/core/build_steps/compile.rs +++ b/src/bootstrap/src/core/build_steps/compile.rs @@ -1189,6 +1189,10 @@ pub fn rustc_cargo_env( cargo.env("RUSTC_VERIFY_LLVM_IR", "1"); } + if builder.config.llvm_enzyme { + cargo.rustflag("--cfg=llvm_enzyme"); + } + // Note that this is disabled if LLVM itself is disabled or we're in a check // build. If we are in a check build we still go ahead here presuming we've // detected that LLVM is already built and good to go which helps prevent @@ -1784,6 +1788,24 @@ impl Step for Assemble { // use that to bootstrap this compiler forward. let mut build_compiler = builder.compiler(target_compiler.stage - 1, builder.config.build); + // Build enzyme + let enzyme_install = if builder.config.llvm_enzyme { + Some(builder.ensure(llvm::Enzyme { target: build_compiler.host })) + } else { + None + }; + + if let Some(enzyme_install) = enzyme_install { + let lib_ext = std::env::consts::DLL_EXTENSION; + let src_lib = enzyme_install.join("build/Enzyme/libEnzyme-19").with_extension(lib_ext); + let libdir = builder.sysroot_libdir(build_compiler, build_compiler.host); + let target_libdir = builder.sysroot_libdir(target_compiler, target_compiler.host); + let dst_lib = libdir.join("libEnzyme-19").with_extension(lib_ext); + let target_dst_lib = target_libdir.join("libEnzyme-19").with_extension(lib_ext); + builder.copy_link(&src_lib, &dst_lib); + builder.copy_link(&src_lib, &target_dst_lib); + } + // Build the libraries for this compiler to link to (i.e., the libraries // it uses at runtime). NOTE: Crates the target compiler compiles don't // link to these. (FIXME: Is that correct? It seems to be correct most diff --git a/src/bootstrap/src/core/build_steps/llvm.rs b/src/bootstrap/src/core/build_steps/llvm.rs index e1eea31b3bbf3..442638d32034b 100644 --- a/src/bootstrap/src/core/build_steps/llvm.rs +++ b/src/bootstrap/src/core/build_steps/llvm.rs @@ -529,6 +529,7 @@ impl Step for Llvm { } }; + // FIXME(ZuseZ4): Do we need that for Enzyme too? // When building LLVM with LLVM_LINK_LLVM_DYLIB for macOS, an unversioned // libLLVM.dylib will be built. However, llvm-config will still look // for a versioned path like libLLVM-14.dylib. Manually create a symbolic @@ -849,6 +850,100 @@ fn get_var(var_base: &str, host: &str, target: &str) -> Option { .or_else(|| env::var_os(var_base)) } +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub struct Enzyme { + pub target: TargetSelection, +} + +impl Step for Enzyme { + type Output = PathBuf; + const ONLY_HOSTS: bool = true; + + fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { + run.path("src/tools/enzyme/enzyme") + } + + fn make_run(run: RunConfig<'_>) { + run.builder.ensure(Enzyme { target: run.target }); + } + + /// Compile Enzyme for `target`. + fn run(self, builder: &Builder<'_>) -> PathBuf { + builder.require_submodule( + "src/tools/enzyme", + Some("The Enzyme sources are required for autodiff."), + ); + if builder.config.dry_run() { + let out_dir = builder.enzyme_out(self.target); + return out_dir; + } + let target = self.target; + + let LlvmResult { llvm_config, .. } = builder.ensure(Llvm { target: self.target }); + + static STAMP_HASH_MEMO: OnceLock = OnceLock::new(); + let smart_stamp_hash = STAMP_HASH_MEMO.get_or_init(|| { + generate_smart_stamp_hash( + builder, + &builder.config.src.join("src/tools/enzyme"), + builder.enzyme_info.sha().unwrap_or_default(), + ) + }); + + let out_dir = builder.enzyme_out(target); + let stamp = out_dir.join("enzyme-finished-building"); + let stamp = HashStamp::new(stamp, Some(smart_stamp_hash)); + + if stamp.is_done() { + if stamp.hash.is_none() { + builder.info( + "Could not determine the Enzyme submodule commit hash. \ + Assuming that an Enzyme rebuild is not necessary.", + ); + builder.info(&format!( + "To force Enzyme to rebuild, remove the file `{}`", + stamp.path.display() + )); + } + return out_dir; + } + + builder.info(&format!("Building Enzyme for {}", target)); + t!(stamp.remove()); + let _time = helpers::timeit(builder); + t!(fs::create_dir_all(&out_dir)); + + builder + .config + .update_submodule(Path::new("src").join("tools").join("enzyme").to_str().unwrap()); + let mut cfg = cmake::Config::new(builder.src.join("src/tools/enzyme/enzyme/")); + // FIXME(ZuseZ4): Find a nicer way to use Enzyme Debug builds + //cfg.profile("Debug"); + //cfg.define("CMAKE_BUILD_TYPE", "Debug"); + configure_cmake(builder, target, &mut cfg, true, LdFlags::default(), &[]); + + // Re-use the same flags as llvm to control the level of debug information + // generated for lld. + let profile = match (builder.config.llvm_optimize, builder.config.llvm_release_debuginfo) { + (false, _) => "Debug", + (true, false) => "Release", + (true, true) => "RelWithDebInfo", + }; + + cfg.out_dir(&out_dir) + .profile(profile) + .env("LLVM_CONFIG_REAL", &llvm_config) + .define("LLVM_ENABLE_ASSERTIONS", "ON") + .define("ENZYME_EXTERNAL_SHARED_LIB", "ON") + .define("LLVM_DIR", builder.llvm_out(target)); + + cfg.build(); + + t!(stamp.write()); + out_dir + } +} + #[derive(Debug, Clone, Hash, PartialEq, Eq)] pub struct Lld { pub target: TargetSelection, diff --git a/src/bootstrap/src/core/builder.rs b/src/bootstrap/src/core/builder.rs index 304fe8da2bf52..a28b19d33a632 100644 --- a/src/bootstrap/src/core/builder.rs +++ b/src/bootstrap/src/core/builder.rs @@ -798,6 +798,7 @@ impl<'a> Builder<'a> { tool::Miri, tool::CargoMiri, llvm::Lld, + llvm::Enzyme, llvm::CrtBeginEnd, tool::RustdocGUITest, tool::OptimizedDist, @@ -1588,6 +1589,12 @@ impl<'a> Builder<'a> { rustflags.arg(sysroot_str); } + // https://rust-lang.zulipchat.com/#narrow/stream/182449-t-compiler.2Fhelp/topic/.E2.9C.94.20link.20new.20library.20into.20stage1.2Frustc + if self.config.llvm_enzyme { + rustflags.arg("-l"); + rustflags.arg("Enzyme-19"); + } + let use_new_symbol_mangling = match self.config.rust_new_symbol_mangling { Some(setting) => { // If an explicit setting is given, use that diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs index f7cc9ee7219b1..52c1c462788af 100644 --- a/src/bootstrap/src/core/config/config.rs +++ b/src/bootstrap/src/core/config/config.rs @@ -221,6 +221,7 @@ pub struct Config { // llvm codegen options pub llvm_assertions: bool, pub llvm_tests: bool, + pub llvm_enzyme: bool, pub llvm_plugins: bool, pub llvm_optimize: bool, pub llvm_thin_lto: bool, @@ -898,6 +899,7 @@ define_config! { release_debuginfo: Option = "release-debuginfo", assertions: Option = "assertions", tests: Option = "tests", + enzyme: Option = "enzyme", plugins: Option = "plugins", ccache: Option = "ccache", static_libstdcpp: Option = "static-libstdcpp", @@ -1603,6 +1605,7 @@ impl Config { // we'll infer default values for them later let mut llvm_assertions = None; let mut llvm_tests = None; + let mut llvm_enzyme = None; let mut llvm_plugins = None; let mut debug = None; let mut debug_assertions = None; @@ -1722,6 +1725,8 @@ impl Config { config.llvm_tools_enabled = llvm_tools.unwrap_or(true); config.rustc_parallel = parallel_compiler.unwrap_or(config.channel == "dev" || config.channel == "nightly"); + config.llvm_enzyme = + llvm_enzyme.unwrap_or(config.channel == "dev" || config.channel == "nightly"); config.rustc_default_linker = default_linker; config.musl_root = musl_root.map(PathBuf::from); config.save_toolstates = save_toolstates.map(PathBuf::from); @@ -1806,6 +1811,7 @@ impl Config { release_debuginfo, assertions, tests, + enzyme, plugins, ccache, static_libstdcpp, @@ -1839,6 +1845,7 @@ impl Config { set(&mut config.ninja_in_file, ninja); llvm_assertions = assertions; llvm_tests = tests; + llvm_enzyme = enzyme; llvm_plugins = plugins; set(&mut config.llvm_optimize, optimize_toml); set(&mut config.llvm_thin_lto, thin_lto); @@ -2055,6 +2062,7 @@ impl Config { config.llvm_assertions = llvm_assertions.unwrap_or(false); config.llvm_tests = llvm_tests.unwrap_or(false); + config.llvm_enzyme = llvm_enzyme.unwrap_or(false); config.llvm_plugins = llvm_plugins.unwrap_or(false); config.rust_optimize = optimize.unwrap_or(RustOptimize::Bool(true)); diff --git a/src/bootstrap/src/lib.rs b/src/bootstrap/src/lib.rs index 5751c398f30fc..624246479f738 100644 --- a/src/bootstrap/src/lib.rs +++ b/src/bootstrap/src/lib.rs @@ -77,6 +77,9 @@ const LLD_FILE_NAMES: &[&str] = &["ld.lld", "ld64.lld", "lld-link", "wasm-ld"]; #[allow(clippy::type_complexity)] // It's fine for hard-coded list and type is explained above. const EXTRA_CHECK_CFGS: &[(Option, &str, Option<&[&'static str]>)] = &[ (None, "bootstrap", None), + (Some(Mode::Rustc), "llvm_enzyme", None), + (Some(Mode::Codegen), "llvm_enzyme", None), + (Some(Mode::ToolRustc), "llvm_enzyme", None), (Some(Mode::Rustc), "parallel_compiler", None), (Some(Mode::ToolRustc), "parallel_compiler", None), (Some(Mode::ToolRustc), "rust_analyzer", None), @@ -140,6 +143,7 @@ pub struct Build { clippy_info: GitInfo, miri_info: GitInfo, rustfmt_info: GitInfo, + enzyme_info: GitInfo, in_tree_llvm_info: GitInfo, local_rebuild: bool, fail_fast: bool, @@ -306,6 +310,7 @@ impl Build { let clippy_info = GitInfo::new(omit_git_hash, &src.join("src/tools/clippy")); let miri_info = GitInfo::new(omit_git_hash, &src.join("src/tools/miri")); let rustfmt_info = GitInfo::new(omit_git_hash, &src.join("src/tools/rustfmt")); + let enzyme_info = GitInfo::new(omit_git_hash, &src.join("src/tools/enzyme")); // we always try to use git for LLVM builds let in_tree_llvm_info = GitInfo::new(false, &src.join("src/llvm-project")); @@ -393,6 +398,7 @@ impl Build { clippy_info, miri_info, rustfmt_info, + enzyme_info, in_tree_llvm_info, cc: RefCell::new(HashMap::new()), cxx: RefCell::new(HashMap::new()), @@ -740,6 +746,10 @@ impl Build { } } + fn enzyme_out(&self, target: TargetSelection) -> PathBuf { + self.out.join(&*target.triple).join("enzyme") + } + fn lld_out(&self, target: TargetSelection) -> PathBuf { self.out.join(target).join("lld") } diff --git a/src/bootstrap/src/utils/change_tracker.rs b/src/bootstrap/src/utils/change_tracker.rs index 3fec2d953d968..80ab09881fe1c 100644 --- a/src/bootstrap/src/utils/change_tracker.rs +++ b/src/bootstrap/src/utils/change_tracker.rs @@ -245,4 +245,9 @@ pub const CONFIG_CHANGE_HISTORY: &[ChangeInfo] = &[ severity: ChangeSeverity::Warning, summary: "Removed `rust.split-debuginfo` as it was deprecated long time ago.", }, + ChangeInfo { + change_id: 129176, + severity: ChangeSeverity::Info, + summary: "New option `llvm.enzyme` to control whether the llvm based autodiff tool (Enzyme) is built.", + }, ]; diff --git a/src/tools/enzyme b/src/tools/enzyme new file mode 160000 index 0000000000000..2fe5164a2423d --- /dev/null +++ b/src/tools/enzyme @@ -0,0 +1 @@ +Subproject commit 2fe5164a2423dd67ef25e2c4fb204fd06362494b diff --git a/src/tools/tidy/config/black.toml b/src/tools/tidy/config/black.toml index e73847a93ba49..a1e1eef987a5f 100644 --- a/src/tools/tidy/config/black.toml +++ b/src/tools/tidy/config/black.toml @@ -12,5 +12,6 @@ extend-exclude = """(\ src/llvm-project/|\ src/doc/embedded-book/|\ src/tools/rustc-perf/|\ + src/tools/enzyme/|\ library/backtrace/ )""" diff --git a/src/tools/tidy/config/ruff.toml b/src/tools/tidy/config/ruff.toml index c87c17f783312..2be109010a062 100644 --- a/src/tools/tidy/config/ruff.toml +++ b/src/tools/tidy/config/ruff.toml @@ -16,6 +16,7 @@ extend-exclude = [ "src/llvm-project/", "src/doc/embedded-book/", "library/backtrace/", + "src/tools/enzyme/", "src/tools/rustc-perf/", # Hack: CI runs from a subdirectory under the main checkout "../src/doc/nomicon/", @@ -29,6 +30,7 @@ extend-exclude = [ "../src/llvm-project/", "../src/doc/embedded-book/", "../library/backtrace/", + "../src/tools/enzyme/", "../src/tools/rustc-perf/", ] diff --git a/src/tools/tidy/src/walk.rs b/src/tools/tidy/src/walk.rs index d4721b5a5fd15..4a69022ebdc58 100644 --- a/src/tools/tidy/src/walk.rs +++ b/src/tools/tidy/src/walk.rs @@ -24,6 +24,7 @@ pub fn filter_dirs(path: &Path) -> bool { "src/tools/rust-analyzer", "src/tools/rustc-perf", "src/tools/rustfmt", + "src/tools/enzyme", "src/doc/book", "src/doc/edition-guide", "src/doc/embedded-book", From 3446ca535ecead268a4c8393ba7a48fd783b363a Mon Sep 17 00:00:00 2001 From: Jonathan Conder Date: Fri, 6 Sep 2024 12:52:32 +1200 Subject: [PATCH 0565/2194] coverage: Add test to codify existing behavior Currently `await` is only counted towards coverage if the containing function is suspended and resumed at least once. A future commit will fix this and update the test to reflect the new behavior. --- tests/coverage/await_ready.cov-map | 26 ++++++++++++++++++++ tests/coverage/await_ready.coverage | 38 +++++++++++++++++++++++++++++ tests/coverage/await_ready.rs | 37 ++++++++++++++++++++++++++++ 3 files changed, 101 insertions(+) create mode 100644 tests/coverage/await_ready.cov-map create mode 100644 tests/coverage/await_ready.coverage create mode 100644 tests/coverage/await_ready.rs diff --git a/tests/coverage/await_ready.cov-map b/tests/coverage/await_ready.cov-map new file mode 100644 index 0000000000000..c6dfc01e861f8 --- /dev/null +++ b/tests/coverage/await_ready.cov-map @@ -0,0 +1,26 @@ +Function name: await_ready::await_ready +Raw bytes (9): 0x[01, 01, 00, 01, 01, 0a, 01, 00, 1e] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 1 +- Code(Counter(0)) at (prev + 10, 1) to (start + 0, 30) + +Function name: await_ready::await_ready::{closure#0} +Raw bytes (19): 0x[01, 01, 00, 03, 01, 0a, 1e, 02, 0c, 05, 03, 0a, 00, 0f, 09, 01, 01, 00, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 3 +- Code(Counter(0)) at (prev + 10, 30) to (start + 2, 12) +- Code(Counter(1)) at (prev + 3, 10) to (start + 0, 15) +- Code(Counter(2)) at (prev + 1, 1) to (start + 0, 2) + +Function name: await_ready::main +Raw bytes (9): 0x[01, 01, 00, 01, 01, 10, 01, 03, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 1 +- Code(Counter(0)) at (prev + 16, 1) to (start + 3, 2) + diff --git a/tests/coverage/await_ready.coverage b/tests/coverage/await_ready.coverage new file mode 100644 index 0000000000000..bddaf15cf80d3 --- /dev/null +++ b/tests/coverage/await_ready.coverage @@ -0,0 +1,38 @@ + LL| |#![feature(coverage_attribute)] + LL| |#![feature(custom_inner_attributes)] // for #![rustfmt::skip] + LL| |#![feature(noop_waker)] + LL| |#![rustfmt::skip] + LL| |//@ edition: 2021 + LL| | + LL| |#[coverage(off)] + LL| |async fn ready() -> u8 { 1 } + LL| | + LL| 1|async fn await_ready() -> u8 { + LL| 1| // FIXME(#98712): await is only covered if the function yields + LL| 1| ready() + LL| 0| .await + LL| 1|} + LL| | + LL| 1|fn main() { + LL| 1| let mut future = Box::pin(await_ready()); + LL| 1| executor::block_on(future.as_mut()); + LL| 1|} + LL| | + LL| |mod executor { + LL| | use core::future::Future; + LL| | use core::pin::pin; + LL| | use core::task::{Context, Poll, Waker}; + LL| | + LL| | #[coverage(off)] + LL| | pub fn block_on(mut future: F) -> F::Output { + LL| | let mut future = pin!(future); + LL| | let mut context = Context::from_waker(Waker::noop()); + LL| | + LL| | loop { + LL| | if let Poll::Ready(val) = future.as_mut().poll(&mut context) { + LL| | break val; + LL| | } + LL| | } + LL| | } + LL| |} + diff --git a/tests/coverage/await_ready.rs b/tests/coverage/await_ready.rs new file mode 100644 index 0000000000000..884ff16fff68d --- /dev/null +++ b/tests/coverage/await_ready.rs @@ -0,0 +1,37 @@ +#![feature(coverage_attribute)] +#![feature(custom_inner_attributes)] // for #![rustfmt::skip] +#![feature(noop_waker)] +#![rustfmt::skip] +//@ edition: 2021 + +#[coverage(off)] +async fn ready() -> u8 { 1 } + +async fn await_ready() -> u8 { + // FIXME(#98712): await is only covered if the function yields + ready() + .await +} + +fn main() { + let mut future = Box::pin(await_ready()); + executor::block_on(future.as_mut()); +} + +mod executor { + use core::future::Future; + use core::pin::pin; + use core::task::{Context, Poll, Waker}; + + #[coverage(off)] + pub fn block_on(mut future: F) -> F::Output { + let mut future = pin!(future); + let mut context = Context::from_waker(Waker::noop()); + + loop { + if let Poll::Ready(val) = future.as_mut().poll(&mut context) { + break val; + } + } + } +} From 81a08bc67ab0d9186295d081e9579d8e0c2f1998 Mon Sep 17 00:00:00 2001 From: The Miri Cronjob Bot Date: Fri, 6 Sep 2024 05:01:31 +0000 Subject: [PATCH 0566/2194] Preparing for merge from rustc --- src/tools/miri/rust-version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/miri/rust-version b/src/tools/miri/rust-version index 4f14caf0e56c3..3fdad2a91e9fc 100644 --- a/src/tools/miri/rust-version +++ b/src/tools/miri/rust-version @@ -1 +1 @@ -e71f9529121ca8f687e4b725e3c9adc3f1ebab4d +54fdef7799d9ff9470bb5cabd29fde9471a99eaa From 25d183057edcf5d24ba0dcc8d5222a2a954aa80f Mon Sep 17 00:00:00 2001 From: Jonathan Conder Date: Fri, 6 Sep 2024 10:25:25 +1200 Subject: [PATCH 0567/2194] coverage: Treat await similar to a macro Currently `await` is only counted towards coverage if the containing function is suspended and resumed at least once. This is because it expands to code which contains a branch on the discriminant of `Poll`. By treating it like a branching macro (e.g. `assert!`), these implementation details will be hidden from the coverage results. --- .../rustc_mir_transform/src/coverage/spans.rs | 34 ++++++++----- .../src/coverage/spans/from_mir.rs | 22 ++++----- .../src/coverage/unexpand.rs | 15 ++---- tests/coverage/async.cov-map | 48 ++++++++----------- tests/coverage/async.coverage | 4 +- tests/coverage/await_ready.cov-map | 9 ++-- tests/coverage/await_ready.coverage | 4 +- tests/coverage/await_ready.rs | 2 +- 8 files changed, 67 insertions(+), 71 deletions(-) diff --git a/compiler/rustc_mir_transform/src/coverage/spans.rs b/compiler/rustc_mir_transform/src/coverage/spans.rs index fcc774503f45a..b904b0d2599b1 100644 --- a/compiler/rustc_mir_transform/src/coverage/spans.rs +++ b/compiler/rustc_mir_transform/src/coverage/spans.rs @@ -3,7 +3,7 @@ use std::collections::VecDeque; use rustc_data_structures::captures::Captures; use rustc_data_structures::fx::FxHashSet; use rustc_middle::mir; -use rustc_span::Span; +use rustc_span::{DesugaringKind, ExpnKind, MacroKind, Span}; use tracing::{debug, debug_span, instrument}; use crate::coverage::graph::{BasicCoverageBlock, CoverageGraph}; @@ -25,7 +25,7 @@ pub(super) fn extract_refined_covspans( // First, perform the passes that need macro information. covspans.sort_by(|a, b| basic_coverage_blocks.cmp_in_dominator_order(a.bcb, b.bcb)); - remove_unwanted_macro_spans(&mut covspans); + remove_unwanted_expansion_spans(&mut covspans); split_visible_macro_spans(&mut covspans); // We no longer need the extra information in `SpanFromMir`, so convert to `Covspan`. @@ -76,18 +76,24 @@ pub(super) fn extract_refined_covspans( /// invocation, which is unhelpful. Keeping only the first such span seems to /// give better mappings, so remove the others. /// +/// Similarly, `await` expands to a branch on the discriminant of `Poll`, which +/// leads to incorrect coverage if the `Future` is immediately ready (#98712). +/// /// (The input spans should be sorted in BCB dominator order, so that the /// retained "first" span is likely to dominate the others.) -fn remove_unwanted_macro_spans(covspans: &mut Vec) { - let mut seen_macro_spans = FxHashSet::default(); +fn remove_unwanted_expansion_spans(covspans: &mut Vec) { + let mut deduplicated_spans = FxHashSet::default(); + covspans.retain(|covspan| { - // Ignore (retain) non-macro-expansion spans. - if covspan.visible_macro.is_none() { - return true; + match covspan.expn_kind { + // Retain only the first await-related or macro-expanded covspan with this span. + Some(ExpnKind::Desugaring(kind)) if kind == DesugaringKind::Await => { + deduplicated_spans.insert(covspan.span) + } + Some(ExpnKind::Macro(MacroKind::Bang, _)) => deduplicated_spans.insert(covspan.span), + // Ignore (retain) other spans. + _ => true, } - - // Retain only the first macro-expanded covspan with this span. - seen_macro_spans.insert(covspan.span) }); } @@ -99,7 +105,9 @@ fn split_visible_macro_spans(covspans: &mut Vec) { let mut extra_spans = vec![]; covspans.retain(|covspan| { - let Some(visible_macro) = covspan.visible_macro else { return true }; + let Some(ExpnKind::Macro(MacroKind::Bang, visible_macro)) = covspan.expn_kind else { + return true; + }; let split_len = visible_macro.as_str().len() as u32 + 1; let (before, after) = covspan.span.split_at(split_len); @@ -111,8 +119,8 @@ fn split_visible_macro_spans(covspans: &mut Vec) { return true; } - extra_spans.push(SpanFromMir::new(before, covspan.visible_macro, covspan.bcb)); - extra_spans.push(SpanFromMir::new(after, covspan.visible_macro, covspan.bcb)); + extra_spans.push(SpanFromMir::new(before, covspan.expn_kind.clone(), covspan.bcb)); + extra_spans.push(SpanFromMir::new(after, covspan.expn_kind.clone(), covspan.bcb)); false // Discard the original covspan that we just split. }); diff --git a/compiler/rustc_mir_transform/src/coverage/spans/from_mir.rs b/compiler/rustc_mir_transform/src/coverage/spans/from_mir.rs index 32bd25bf4b966..7f5765c9462de 100644 --- a/compiler/rustc_mir_transform/src/coverage/spans/from_mir.rs +++ b/compiler/rustc_mir_transform/src/coverage/spans/from_mir.rs @@ -3,13 +3,13 @@ use rustc_middle::mir::coverage::CoverageKind; use rustc_middle::mir::{ self, FakeReadCause, Statement, StatementKind, Terminator, TerminatorKind, }; -use rustc_span::{Span, Symbol}; +use rustc_span::{ExpnKind, Span}; use crate::coverage::graph::{ BasicCoverageBlock, BasicCoverageBlockData, CoverageGraph, START_BCB, }; use crate::coverage::spans::Covspan; -use crate::coverage::unexpand::unexpand_into_body_span_with_visible_macro; +use crate::coverage::unexpand::unexpand_into_body_span_with_expn_kind; use crate::coverage::ExtractedHirInfo; pub(crate) struct ExtractedCovspans { @@ -60,7 +60,7 @@ fn bcb_to_initial_coverage_spans<'a, 'tcx>( let data = &mir_body[bb]; let unexpand = move |expn_span| { - unexpand_into_body_span_with_visible_macro(expn_span, body_span) + unexpand_into_body_span_with_expn_kind(expn_span, body_span) // Discard any spans that fill the entire body, because they tend // to represent compiler-inserted code, e.g. implicitly returning `()`. .filter(|(span, _)| !span.source_equal(body_span)) @@ -68,9 +68,9 @@ fn bcb_to_initial_coverage_spans<'a, 'tcx>( let mut extract_statement_span = |statement| { let expn_span = filtered_statement_span(statement)?; - let (span, visible_macro) = unexpand(expn_span)?; + let (span, expn_kind) = unexpand(expn_span)?; - initial_covspans.push(SpanFromMir::new(span, visible_macro, bcb)); + initial_covspans.push(SpanFromMir::new(span, expn_kind, bcb)); Some(()) }; for statement in data.statements.iter() { @@ -79,9 +79,9 @@ fn bcb_to_initial_coverage_spans<'a, 'tcx>( let mut extract_terminator_span = |terminator| { let expn_span = filtered_terminator_span(terminator)?; - let (span, visible_macro) = unexpand(expn_span)?; + let (span, expn_kind) = unexpand(expn_span)?; - initial_covspans.push(SpanFromMir::new(span, visible_macro, bcb)); + initial_covspans.push(SpanFromMir::new(span, expn_kind, bcb)); Some(()) }; extract_terminator_span(data.terminator()); @@ -214,7 +214,7 @@ pub(crate) struct SpanFromMir { /// With the exception of `fn_sig_span`, this should always be contained /// within `body_span`. pub(crate) span: Span, - pub(crate) visible_macro: Option, + pub(crate) expn_kind: Option, pub(crate) bcb: BasicCoverageBlock, } @@ -223,12 +223,12 @@ impl SpanFromMir { Self::new(fn_sig_span, None, START_BCB) } - pub(crate) fn new(span: Span, visible_macro: Option, bcb: BasicCoverageBlock) -> Self { - Self { span, visible_macro, bcb } + pub(crate) fn new(span: Span, expn_kind: Option, bcb: BasicCoverageBlock) -> Self { + Self { span, expn_kind, bcb } } pub(crate) fn into_covspan(self) -> Covspan { - let Self { span, visible_macro: _, bcb } = self; + let Self { span, expn_kind: _, bcb } = self; Covspan { span, bcb } } } diff --git a/compiler/rustc_mir_transform/src/coverage/unexpand.rs b/compiler/rustc_mir_transform/src/coverage/unexpand.rs index 8cde291b9073e..cb8615447362b 100644 --- a/compiler/rustc_mir_transform/src/coverage/unexpand.rs +++ b/compiler/rustc_mir_transform/src/coverage/unexpand.rs @@ -1,4 +1,4 @@ -use rustc_span::{ExpnKind, MacroKind, Span, Symbol}; +use rustc_span::{ExpnKind, Span}; /// Walks through the expansion ancestors of `original_span` to find a span that /// is contained in `body_span` and has the same [syntax context] as `body_span`. @@ -13,20 +13,15 @@ pub(crate) fn unexpand_into_body_span(original_span: Span, body_span: Span) -> O /// /// If the returned span represents a bang-macro invocation (e.g. `foo!(..)`), /// the returned symbol will be the name of that macro (e.g. `foo`). -pub(crate) fn unexpand_into_body_span_with_visible_macro( +pub(crate) fn unexpand_into_body_span_with_expn_kind( original_span: Span, body_span: Span, -) -> Option<(Span, Option)> { +) -> Option<(Span, Option)> { let (span, prev) = unexpand_into_body_span_with_prev(original_span, body_span)?; - let visible_macro = prev - .map(|prev| match prev.ctxt().outer_expn_data().kind { - ExpnKind::Macro(MacroKind::Bang, name) => Some(name), - _ => None, - }) - .flatten(); + let expn_kind = prev.map(|prev| prev.ctxt().outer_expn_data().kind); - Some((span, visible_macro)) + Some((span, expn_kind)) } /// Walks through the expansion ancestors of `original_span` to find a span that diff --git a/tests/coverage/async.cov-map b/tests/coverage/async.cov-map index 9e5a4bdc60fdd..1ba165f1e4991 100644 --- a/tests/coverage/async.cov-map +++ b/tests/coverage/async.cov-map @@ -92,20 +92,18 @@ Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 25, 1) to (start + 0, 23) Function name: async::g::{closure#0} (unused) -Raw bytes (69): 0x[01, 01, 00, 0d, 00, 19, 17, 01, 0c, 00, 02, 09, 00, 0a, 00, 00, 0e, 00, 11, 00, 00, 12, 00, 17, 00, 00, 1b, 00, 1c, 00, 00, 20, 00, 22, 00, 01, 09, 00, 0a, 00, 00, 0e, 00, 11, 00, 00, 12, 00, 17, 00, 00, 1b, 00, 1c, 00, 00, 20, 00, 22, 00, 01, 0e, 00, 10, 00, 02, 01, 00, 02] +Raw bytes (59): 0x[01, 01, 00, 0b, 00, 19, 17, 01, 0c, 00, 02, 09, 00, 0a, 00, 00, 0e, 00, 17, 00, 00, 1b, 00, 1c, 00, 00, 20, 00, 22, 00, 01, 09, 00, 0a, 00, 00, 0e, 00, 17, 00, 00, 1b, 00, 1c, 00, 00, 20, 00, 22, 00, 01, 0e, 00, 10, 00, 02, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 -Number of file 0 mappings: 13 +Number of file 0 mappings: 11 - Code(Zero) at (prev + 25, 23) to (start + 1, 12) - Code(Zero) at (prev + 2, 9) to (start + 0, 10) -- Code(Zero) at (prev + 0, 14) to (start + 0, 17) -- Code(Zero) at (prev + 0, 18) to (start + 0, 23) +- Code(Zero) at (prev + 0, 14) to (start + 0, 23) - Code(Zero) at (prev + 0, 27) to (start + 0, 28) - Code(Zero) at (prev + 0, 32) to (start + 0, 34) - Code(Zero) at (prev + 1, 9) to (start + 0, 10) -- Code(Zero) at (prev + 0, 14) to (start + 0, 17) -- Code(Zero) at (prev + 0, 18) to (start + 0, 23) +- Code(Zero) at (prev + 0, 14) to (start + 0, 23) - Code(Zero) at (prev + 0, 27) to (start + 0, 28) - Code(Zero) at (prev + 0, 32) to (start + 0, 34) - Code(Zero) at (prev + 1, 14) to (start + 0, 16) @@ -120,15 +118,14 @@ Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 33, 1) to (start + 0, 22) Function name: async::h::{closure#0} (unused) -Raw bytes (44): 0x[01, 01, 00, 08, 00, 21, 16, 03, 0c, 00, 04, 09, 00, 0a, 00, 00, 0e, 00, 13, 00, 00, 14, 00, 19, 00, 00, 1a, 00, 1b, 00, 00, 20, 00, 22, 00, 01, 0e, 00, 10, 00, 02, 01, 00, 02] +Raw bytes (39): 0x[01, 01, 00, 07, 00, 21, 16, 03, 0c, 00, 04, 09, 00, 0a, 00, 00, 0e, 00, 19, 00, 00, 1a, 00, 1b, 00, 00, 20, 00, 22, 00, 01, 0e, 00, 10, 00, 02, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 -Number of file 0 mappings: 8 +Number of file 0 mappings: 7 - Code(Zero) at (prev + 33, 22) to (start + 3, 12) - Code(Zero) at (prev + 4, 9) to (start + 0, 10) -- Code(Zero) at (prev + 0, 14) to (start + 0, 19) -- Code(Zero) at (prev + 0, 20) to (start + 0, 25) +- Code(Zero) at (prev + 0, 14) to (start + 0, 25) - Code(Zero) at (prev + 0, 26) to (start + 0, 27) - Code(Zero) at (prev + 0, 32) to (start + 0, 34) - Code(Zero) at (prev + 1, 14) to (start + 0, 16) @@ -143,28 +140,25 @@ Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 42, 1) to (start + 0, 19) Function name: async::i::{closure#0} -Raw bytes (78): 0x[01, 01, 02, 07, 21, 19, 1d, 0e, 01, 2a, 13, 04, 0c, 0d, 05, 09, 00, 0a, 01, 00, 0e, 00, 12, 05, 00, 13, 00, 18, 09, 00, 1c, 00, 21, 0d, 00, 27, 00, 2a, 15, 00, 2b, 00, 30, 1d, 01, 09, 00, 0a, 11, 00, 0e, 00, 11, 25, 00, 12, 00, 17, 29, 00, 1b, 00, 20, 1d, 00, 24, 00, 26, 21, 01, 0e, 00, 10, 03, 02, 01, 00, 02] +Raw bytes (63): 0x[01, 01, 02, 07, 19, 11, 15, 0b, 01, 2a, 13, 04, 0c, 09, 05, 09, 00, 0a, 01, 00, 0e, 00, 18, 05, 00, 1c, 00, 21, 09, 00, 27, 00, 30, 15, 01, 09, 00, 0a, 0d, 00, 0e, 00, 17, 1d, 00, 1b, 00, 20, 15, 00, 24, 00, 26, 19, 01, 0e, 00, 10, 03, 02, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 2 -- expression 0 operands: lhs = Expression(1, Add), rhs = Counter(8) -- expression 1 operands: lhs = Counter(6), rhs = Counter(7) -Number of file 0 mappings: 14 +- expression 0 operands: lhs = Expression(1, Add), rhs = Counter(6) +- expression 1 operands: lhs = Counter(4), rhs = Counter(5) +Number of file 0 mappings: 11 - Code(Counter(0)) at (prev + 42, 19) to (start + 4, 12) -- Code(Counter(3)) at (prev + 5, 9) to (start + 0, 10) -- Code(Counter(0)) at (prev + 0, 14) to (start + 0, 18) -- Code(Counter(1)) at (prev + 0, 19) to (start + 0, 24) -- Code(Counter(2)) at (prev + 0, 28) to (start + 0, 33) -- Code(Counter(3)) at (prev + 0, 39) to (start + 0, 42) -- Code(Counter(5)) at (prev + 0, 43) to (start + 0, 48) -- Code(Counter(7)) at (prev + 1, 9) to (start + 0, 10) -- Code(Counter(4)) at (prev + 0, 14) to (start + 0, 17) -- Code(Counter(9)) at (prev + 0, 18) to (start + 0, 23) -- Code(Counter(10)) at (prev + 0, 27) to (start + 0, 32) -- Code(Counter(7)) at (prev + 0, 36) to (start + 0, 38) -- Code(Counter(8)) at (prev + 1, 14) to (start + 0, 16) +- Code(Counter(2)) at (prev + 5, 9) to (start + 0, 10) +- Code(Counter(0)) at (prev + 0, 14) to (start + 0, 24) +- Code(Counter(1)) at (prev + 0, 28) to (start + 0, 33) +- Code(Counter(2)) at (prev + 0, 39) to (start + 0, 48) +- Code(Counter(5)) at (prev + 1, 9) to (start + 0, 10) +- Code(Counter(3)) at (prev + 0, 14) to (start + 0, 23) +- Code(Counter(7)) at (prev + 0, 27) to (start + 0, 32) +- Code(Counter(5)) at (prev + 0, 36) to (start + 0, 38) +- Code(Counter(6)) at (prev + 1, 14) to (start + 0, 16) - Code(Expression(0, Add)) at (prev + 2, 1) to (start + 0, 2) - = ((c6 + c7) + c8) + = ((c4 + c5) + c6) Function name: async::j Raw bytes (58): 0x[01, 01, 02, 07, 0d, 05, 09, 0a, 01, 35, 01, 00, 0d, 01, 0b, 0b, 00, 0c, 05, 01, 09, 00, 0a, 01, 00, 0e, 00, 1b, 05, 00, 1f, 00, 27, 09, 01, 09, 00, 0a, 11, 00, 0e, 00, 1a, 09, 00, 1e, 00, 20, 0d, 01, 0e, 00, 10, 03, 02, 01, 00, 02] diff --git a/tests/coverage/async.coverage b/tests/coverage/async.coverage index f5473829b028e..995674257c4af 100644 --- a/tests/coverage/async.coverage +++ b/tests/coverage/async.coverage @@ -45,9 +45,9 @@ LL| 1| // executed asynchronously. LL| 1| match x { LL| 1| y if c(x).await == y + 1 => { d().await; } - ^0 ^0 ^0 ^0 + ^0 ^0 LL| 1| y if f().await == y + 1 => (), - ^0 ^0 ^0 + ^0 ^0 LL| 1| _ => (), LL| | } LL| 1|} diff --git a/tests/coverage/await_ready.cov-map b/tests/coverage/await_ready.cov-map index c6dfc01e861f8..0c9f2ae29a8cf 100644 --- a/tests/coverage/await_ready.cov-map +++ b/tests/coverage/await_ready.cov-map @@ -7,14 +7,13 @@ Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 10, 1) to (start + 0, 30) Function name: await_ready::await_ready::{closure#0} -Raw bytes (19): 0x[01, 01, 00, 03, 01, 0a, 1e, 02, 0c, 05, 03, 0a, 00, 0f, 09, 01, 01, 00, 02] +Raw bytes (14): 0x[01, 01, 00, 02, 01, 0a, 1e, 03, 0f, 05, 04, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 -Number of file 0 mappings: 3 -- Code(Counter(0)) at (prev + 10, 30) to (start + 2, 12) -- Code(Counter(1)) at (prev + 3, 10) to (start + 0, 15) -- Code(Counter(2)) at (prev + 1, 1) to (start + 0, 2) +Number of file 0 mappings: 2 +- Code(Counter(0)) at (prev + 10, 30) to (start + 3, 15) +- Code(Counter(1)) at (prev + 4, 1) to (start + 0, 2) Function name: await_ready::main Raw bytes (9): 0x[01, 01, 00, 01, 01, 10, 01, 03, 02] diff --git a/tests/coverage/await_ready.coverage b/tests/coverage/await_ready.coverage index bddaf15cf80d3..0075f09426e05 100644 --- a/tests/coverage/await_ready.coverage +++ b/tests/coverage/await_ready.coverage @@ -8,9 +8,9 @@ LL| |async fn ready() -> u8 { 1 } LL| | LL| 1|async fn await_ready() -> u8 { - LL| 1| // FIXME(#98712): await is only covered if the function yields + LL| 1| // await should be covered even if the function never yields LL| 1| ready() - LL| 0| .await + LL| 1| .await LL| 1|} LL| | LL| 1|fn main() { diff --git a/tests/coverage/await_ready.rs b/tests/coverage/await_ready.rs index 884ff16fff68d..9212a4ba705a8 100644 --- a/tests/coverage/await_ready.rs +++ b/tests/coverage/await_ready.rs @@ -8,7 +8,7 @@ async fn ready() -> u8 { 1 } async fn await_ready() -> u8 { - // FIXME(#98712): await is only covered if the function yields + // await should be covered even if the function never yields ready() .await } From 7e5a0e5777715dfc5a4ffafeb643c04cc438d4be Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Fri, 6 Sep 2024 08:21:08 +0200 Subject: [PATCH 0568/2194] fix: Catch panics from diagnostics computation --- .../crates/rust-analyzer/src/main_loop.rs | 35 ++++++++++++------- 1 file changed, 23 insertions(+), 12 deletions(-) diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/main_loop.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/main_loop.rs index ec71b4a7a122f..4daf295a69d60 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/main_loop.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/main_loop.rs @@ -4,6 +4,7 @@ use std::{ fmt, ops::Div as _, + panic::AssertUnwindSafe, time::{Duration, Instant}, }; @@ -552,23 +553,33 @@ impl GlobalState { let fetch_semantic = self.vfs_done && self.fetch_workspaces_queue.last_op_result().is_some(); move |sender| { - let diags = fetch_native_diagnostics( - &snapshot, - subscriptions.clone(), - slice.clone(), - NativeDiagnosticsFetchKind::Syntax, - ); + // We aren't observing the semantics token cache here + let snapshot = AssertUnwindSafe(&snapshot); + let Ok(diags) = std::panic::catch_unwind(|| { + fetch_native_diagnostics( + &snapshot, + subscriptions.clone(), + slice.clone(), + NativeDiagnosticsFetchKind::Syntax, + ) + }) else { + return; + }; sender .send(Task::Diagnostics(DiagnosticsTaskKind::Syntax(generation, diags))) .unwrap(); if fetch_semantic { - let diags = fetch_native_diagnostics( - &snapshot, - subscriptions, - slice, - NativeDiagnosticsFetchKind::Semantic, - ); + let Ok(diags) = std::panic::catch_unwind(|| { + fetch_native_diagnostics( + &snapshot, + subscriptions.clone(), + slice.clone(), + NativeDiagnosticsFetchKind::Semantic, + ) + }) else { + return; + }; sender .send(Task::Diagnostics(DiagnosticsTaskKind::Semantic( generation, diags, From 2d6489ecc1c874a9ae0cfce4455d76c9c185fd80 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Fri, 6 Sep 2024 08:43:39 +0200 Subject: [PATCH 0569/2194] miri.bat: use nightly toolchain --- src/tools/miri/miri.bat | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/tools/miri/miri.bat b/src/tools/miri/miri.bat index 6f9a8f38d6559..b046b6310ddad 100644 --- a/src/tools/miri/miri.bat +++ b/src/tools/miri/miri.bat @@ -5,8 +5,8 @@ set MIRI_SCRIPT_TARGET_DIR=%0\..\miri-script\target :: If any other steps are added, the "|| exit /b" must be appended to early :: return from the script. If not, it will continue execution. -cargo +stable build %CARGO_EXTRA_FLAGS% -q --target-dir %MIRI_SCRIPT_TARGET_DIR% --manifest-path %0\..\miri-script\Cargo.toml ^ - || (echo Failed to build miri-script. Is the 'stable' toolchain installed? & exit /b) +cargo +nightly build %CARGO_EXTRA_FLAGS% -q --target-dir %MIRI_SCRIPT_TARGET_DIR% --manifest-path %0\..\miri-script\Cargo.toml ^ + || (echo Failed to build miri-script. Is the 'nightly' toolchain installed? & exit /b) :: Forwards all arguments to this file to the executable. :: We invoke the binary directly to avoid going through rustup, which would set some extra From 775c5c84a5ce996520f9cad9dab1981fb8532d64 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Fri, 6 Sep 2024 09:13:00 +0200 Subject: [PATCH 0570/2194] fix: Don't panic lsp writer thread on dropped receiver --- src/tools/rust-analyzer/Cargo.lock | 12 ++++++------ src/tools/rust-analyzer/lib/lsp-server/Cargo.toml | 2 +- src/tools/rust-analyzer/lib/lsp-server/src/stdio.rs | 10 ++++------ 3 files changed, 11 insertions(+), 13 deletions(-) diff --git a/src/tools/rust-analyzer/Cargo.lock b/src/tools/rust-analyzer/Cargo.lock index 85ef3a6ba92ca..9223a9cf4fd1e 100644 --- a/src/tools/rust-analyzer/Cargo.lock +++ b/src/tools/rust-analyzer/Cargo.lock @@ -998,23 +998,23 @@ checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" [[package]] name = "lsp-server" version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "248f65b78f6db5d8e1b1604b4098a28b43d21a8eb1deeca22b1c421b276c7095" dependencies = [ "crossbeam-channel", - "ctrlc", "log", - "lsp-types", "serde", "serde_json", ] [[package]] name = "lsp-server" -version = "0.7.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "248f65b78f6db5d8e1b1604b4098a28b43d21a8eb1deeca22b1c421b276c7095" +version = "0.7.7" dependencies = [ "crossbeam-channel", + "ctrlc", "log", + "lsp-types", "serde", "serde_json", ] @@ -1652,7 +1652,7 @@ dependencies = [ "intern", "itertools", "load-cargo", - "lsp-server 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)", + "lsp-server 0.7.6", "lsp-types", "memchr", "mimalloc", diff --git a/src/tools/rust-analyzer/lib/lsp-server/Cargo.toml b/src/tools/rust-analyzer/lib/lsp-server/Cargo.toml index fb3411c8ab431..cce007ae54c51 100644 --- a/src/tools/rust-analyzer/lib/lsp-server/Cargo.toml +++ b/src/tools/rust-analyzer/lib/lsp-server/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "lsp-server" -version = "0.7.6" +version = "0.7.7" description = "Generic LSP server scaffold." license = "MIT OR Apache-2.0" repository = "https://github.com/rust-lang/rust-analyzer/tree/master/lib/lsp-server" diff --git a/src/tools/rust-analyzer/lib/lsp-server/src/stdio.rs b/src/tools/rust-analyzer/lib/lsp-server/src/stdio.rs index c28545fb57412..279a6bce08072 100644 --- a/src/tools/rust-analyzer/lib/lsp-server/src/stdio.rs +++ b/src/tools/rust-analyzer/lib/lsp-server/src/stdio.rs @@ -30,7 +30,9 @@ pub(crate) fn stdio_transport() -> (Sender, Receiver, IoThread let is_exit = matches!(&msg, Message::Notification(n) if n.is_exit()); debug!("sending message {:#?}", msg); - reader_sender.send(msg).expect("receiver was dropped, failed to send a message"); + if let Err(e) = reader_sender.send(msg) { + return Err(io::Error::new(io::ErrorKind::Other, e)); + } if is_exit { break; @@ -60,15 +62,11 @@ impl IoThreads { pub fn join(self) -> io::Result<()> { match self.reader.join() { Ok(r) => r?, - Err(err) => { - println!("reader panicked!"); - std::panic::panic_any(err) - } + Err(err) => std::panic::panic_any(err), } match self.writer.join() { Ok(r) => r, Err(err) => { - println!("writer panicked!"); std::panic::panic_any(err); } } From 4dfafb1a8d34c6ee14af811b619801da782eb718 Mon Sep 17 00:00:00 2001 From: Konstantinos Andrikopoulos Date: Fri, 6 Sep 2024 12:13:55 +0200 Subject: [PATCH 0571/2194] Fix comment in mutex_id_offset We no longer store the kind inside the pthread_mutex_t, so this comment is outdated. --- src/tools/miri/src/shims/unix/sync.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/tools/miri/src/shims/unix/sync.rs b/src/tools/miri/src/shims/unix/sync.rs index 5da5cab8fe4f5..57cc9cf4618c8 100644 --- a/src/tools/miri/src/shims/unix/sync.rs +++ b/src/tools/miri/src/shims/unix/sync.rs @@ -62,7 +62,6 @@ fn is_mutex_kind_normal<'tcx>(ecx: &MiriInterpCx<'tcx>, kind: i32) -> InterpResu // pthread_mutex_t is between 24 and 48 bytes, depending on the platform. // We ignore the platform layout and store our own fields: // - id: u32 -// - kind: i32 fn mutex_id_offset<'tcx>(ecx: &MiriInterpCx<'tcx>) -> InterpResult<'tcx, u64> { let offset = match &*ecx.tcx.sess.target.os { From 7dd1be1d0d2911b16aa1347efa47e7c43c507ade Mon Sep 17 00:00:00 2001 From: Urgau Date: Fri, 6 Sep 2024 12:20:36 +0200 Subject: [PATCH 0572/2194] Also emit `missing_docs` lint with `--test` to fulfill expectations --- compiler/rustc_lint/src/builtin.rs | 6 ------ tests/ui/lint/lint-missing-doc-expect.rs | 13 +++++++++++++ 2 files changed, 13 insertions(+), 6 deletions(-) create mode 100644 tests/ui/lint/lint-missing-doc-expect.rs diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index d8482567bbe5b..5cb5195367402 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -426,12 +426,6 @@ impl MissingDoc { article: &'static str, desc: &'static str, ) { - // If we're building a test harness, then warning about - // documentation is probably not really relevant right now. - if cx.sess().opts.test { - return; - } - // Only check publicly-visible items, using the result from the privacy pass. // It's an option so the crate root can also use this function (it doesn't // have a `NodeId`). diff --git a/tests/ui/lint/lint-missing-doc-expect.rs b/tests/ui/lint/lint-missing-doc-expect.rs new file mode 100644 index 0000000000000..991f65003dc26 --- /dev/null +++ b/tests/ui/lint/lint-missing-doc-expect.rs @@ -0,0 +1,13 @@ +// Make sure that `#[expect(missing_docs)]` is always correctly fulfilled. + +//@ check-pass +//@ revisions: lib bin test +//@ [lib]compile-flags: --crate-type lib +//@ [bin]compile-flags: --crate-type bin +//@ [test]compile-flags: --test + +#[expect(missing_docs)] +pub fn foo() {} + +#[cfg(bin)] +fn main() {} From 96837dcade77185d270c90326f000fc057c29a8e Mon Sep 17 00:00:00 2001 From: Ulrik Mikaelsson Date: Mon, 26 Aug 2024 17:19:45 +0200 Subject: [PATCH 0573/2194] Adjust doc comment of Condvar::wait_while The existing phrasing implies that a notification must be received for `wait_while` to return. The phrasing is changed to better reflect the behavior. --- library/std/src/sync/condvar.rs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/library/std/src/sync/condvar.rs b/library/std/src/sync/condvar.rs index 08d46f356d9f2..e41cbc1a65c0f 100644 --- a/library/std/src/sync/condvar.rs +++ b/library/std/src/sync/condvar.rs @@ -195,8 +195,11 @@ impl Condvar { if poisoned { Err(PoisonError::new(guard)) } else { Ok(guard) } } - /// Blocks the current thread until this condition variable receives a - /// notification and the provided condition is false. + /// Blocks the current thread until the provided condition becomes false. + /// + /// `condition` is checked immediately; if not met (returns `true`), this + /// will [`wait`] for the next notification then check again. This repeats + /// until `condition` returns `false`, in which case this function returns. /// /// This function will atomically unlock the mutex specified (represented by /// `guard`) and block the current thread. This means that any calls @@ -210,6 +213,7 @@ impl Condvar { /// poisoned when this thread re-acquires the lock. For more information, /// see information about [poisoning] on the [`Mutex`] type. /// + /// [`wait`]: Self::wait /// [`notify_one`]: Self::notify_one /// [`notify_all`]: Self::notify_all /// [poisoning]: super::Mutex#poisoning From 5f8823bf8f96c842e7915fe7d0dbf8ac2b10d316 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Fri, 6 Sep 2024 09:40:22 +0200 Subject: [PATCH 0574/2194] Bump lsp-server --- src/tools/rust-analyzer/Cargo.lock | 12 ++++++------ .../crates/rust-analyzer/src/global_state.rs | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/tools/rust-analyzer/Cargo.lock b/src/tools/rust-analyzer/Cargo.lock index 9223a9cf4fd1e..6df73c2fd1bcf 100644 --- a/src/tools/rust-analyzer/Cargo.lock +++ b/src/tools/rust-analyzer/Cargo.lock @@ -997,12 +997,12 @@ checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" [[package]] name = "lsp-server" -version = "0.7.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "248f65b78f6db5d8e1b1604b4098a28b43d21a8eb1deeca22b1c421b276c7095" +version = "0.7.7" dependencies = [ "crossbeam-channel", + "ctrlc", "log", + "lsp-types", "serde", "serde_json", ] @@ -1010,11 +1010,11 @@ dependencies = [ [[package]] name = "lsp-server" version = "0.7.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "550446e84739dcaf6d48a4a093973850669e13e8a34d8f8d64851041be267cd9" dependencies = [ "crossbeam-channel", - "ctrlc", "log", - "lsp-types", "serde", "serde_json", ] @@ -1652,7 +1652,7 @@ dependencies = [ "intern", "itertools", "load-cargo", - "lsp-server 0.7.6", + "lsp-server 0.7.7 (registry+https://github.com/rust-lang/crates.io-index)", "lsp-types", "memchr", "mimalloc", diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/global_state.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/global_state.rs index 35e1da80bf673..89487aa673bf6 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/global_state.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/global_state.rs @@ -540,7 +540,7 @@ impl GlobalState { } pub(crate) fn respond(&mut self, response: lsp_server::Response) { - if let Some((method, start)) = self.req_queue.incoming.complete(response.id.clone()) { + if let Some((method, start)) = self.req_queue.incoming.complete(&response.id) { if let Some(err) = &response.error { if err.message.starts_with("server panicked") { self.poke_rust_analyzer_developer(format!("{}, check the log", err.message)) From 2c8e24e9e81b80f96ad7198102a0279681d408d6 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Fri, 6 Sep 2024 14:04:57 +0200 Subject: [PATCH 0575/2194] fix: Always explicitly set trait ref self types when lowering --- .../crates/hir-ty/src/consteval/tests.rs | 30 ++++++------ .../crates/hir-ty/src/infer/expr.rs | 2 +- .../crates/hir-ty/src/infer/path.rs | 8 ++- .../rust-analyzer/crates/hir-ty/src/lower.rs | 49 +++++++++---------- .../crates/hir-ty/src/mir/eval.rs | 18 ++++++- .../crates/hir-ty/src/mir/lower.rs | 21 ++++---- .../src/handlers/invalid_cast.rs | 2 +- .../crates/test-fixture/src/lib.rs | 6 ++- .../crates/test-utils/src/minicore.rs | 8 +-- 9 files changed, 80 insertions(+), 64 deletions(-) diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/consteval/tests.rs b/src/tools/rust-analyzer/crates/hir-ty/src/consteval/tests.rs index 203e21302cdda..7093fcadcb030 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/consteval/tests.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/consteval/tests.rs @@ -1556,7 +1556,7 @@ fn builtin_derive_macro() { Bar, } #[derive(Clone)] - struct X(i32, Z, i64) + struct X(i32, Z, i64); #[derive(Clone)] struct Y { field1: i32, @@ -1574,20 +1574,20 @@ fn builtin_derive_macro() { ); check_number( r#" - //- minicore: default, derive, builtin_impls - #[derive(Default)] - struct X(i32, Y, i64) - #[derive(Default)] - struct Y { - field1: i32, - field2: u8, - } +//- minicore: default, derive, builtin_impls +#[derive(Default)] +struct X(i32, Y, i64); +#[derive(Default)] +struct Y { + field1: i32, + field2: u8, +} - const GOAL: u8 = { - let x = X::default(); - x.1.field2 - }; - "#, +const GOAL: u8 = { + let x = X::default(); + x.1.field2 +}; +"#, 0, ); } @@ -2828,7 +2828,7 @@ fn type_error() { y.0 }; "#, - |e| matches!(e, ConstEvalError::MirLowerError(MirLowerError::TypeMismatch(_))), + |e| matches!(e, ConstEvalError::MirLowerError(MirLowerError::HasErrors)), ); } diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer/expr.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer/expr.rs index a82d091cbb028..b79aa89db4c54 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/infer/expr.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer/expr.rs @@ -851,7 +851,7 @@ impl InferenceContext<'_> { }; for (expr, ty) in exprs.iter().zip(tys.iter_mut()) { - self.infer_expr_coerce(*expr, &Expectation::has_type(ty.clone())); + *ty = self.infer_expr_coerce(*expr, &Expectation::has_type(ty.clone())); } TyKind::Tuple(tys.len(), Substitution::from_iter(Interner, tys)).intern(Interner) diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer/path.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer/path.rs index 0b44bbec70f75..e4841c7b15b60 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/infer/path.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer/path.rs @@ -247,8 +247,12 @@ impl InferenceContext<'_> { &self.resolver, self.owner.into(), ); - let trait_ref = - ctx.lower_trait_ref_from_resolved_path(trait_, resolved_segment, None); + let trait_ref = ctx.lower_trait_ref_from_resolved_path( + trait_, + resolved_segment, + self.table.new_type_var(), + ); + self.resolve_trait_assoc_item(trait_ref, segment, id) } (def, _) => { diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/lower.rs b/src/tools/rust-analyzer/crates/hir-ty/src/lower.rs index 213400d04a01e..c6c2108e34af4 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/lower.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/lower.rs @@ -516,8 +516,11 @@ impl<'a> TyLoweringContext<'a> { TypeNs::TraitId(trait_) => { let ty = match remaining_segments.len() { 1 => { - let trait_ref = - self.lower_trait_ref_from_resolved_path(trait_, resolved_segment, None); + let trait_ref = self.lower_trait_ref_from_resolved_path( + trait_, + resolved_segment, + TyKind::Error.intern(Interner), + ); let segment = remaining_segments.first().unwrap(); let found = self .db @@ -952,11 +955,17 @@ impl<'a> TyLoweringContext<'a> { Substitution::from_iter(Interner, substs) } - fn lower_trait_ref_from_path( + pub(crate) fn lower_trait_ref_from_resolved_path( &self, - path: &Path, - explicit_self_ty: Option, - ) -> Option { + resolved: TraitId, + segment: PathSegment<'_>, + explicit_self_ty: Ty, + ) -> TraitRef { + let substs = self.trait_ref_substs_from_path(segment, resolved, explicit_self_ty); + TraitRef { trait_id: to_chalk_trait_id(resolved), substitution: substs } + } + + fn lower_trait_ref_from_path(&self, path: &Path, explicit_self_ty: Ty) -> Option { let resolved = match self.resolver.resolve_path_in_type_ns_fully(self.db.upcast(), path)? { // FIXME(trait_alias): We need to handle trait alias here. TypeNs::TraitId(tr) => tr, @@ -966,21 +975,7 @@ impl<'a> TyLoweringContext<'a> { Some(self.lower_trait_ref_from_resolved_path(resolved, segment, explicit_self_ty)) } - pub(crate) fn lower_trait_ref_from_resolved_path( - &self, - resolved: TraitId, - segment: PathSegment<'_>, - explicit_self_ty: Option, - ) -> TraitRef { - let substs = self.trait_ref_substs_from_path(segment, resolved, explicit_self_ty); - TraitRef { trait_id: to_chalk_trait_id(resolved), substitution: substs } - } - - fn lower_trait_ref( - &self, - trait_ref: &HirTraitRef, - explicit_self_ty: Option, - ) -> Option { + fn lower_trait_ref(&self, trait_ref: &HirTraitRef, explicit_self_ty: Ty) -> Option { self.lower_trait_ref_from_path(&trait_ref.path, explicit_self_ty) } @@ -988,9 +983,9 @@ impl<'a> TyLoweringContext<'a> { &self, segment: PathSegment<'_>, resolved: TraitId, - explicit_self_ty: Option, + explicit_self_ty: Ty, ) -> Substitution { - self.substs_from_path_segment(segment, Some(resolved.into()), false, explicit_self_ty) + self.substs_from_path_segment(segment, Some(resolved.into()), false, Some(explicit_self_ty)) } pub(crate) fn lower_where_predicate<'b>( @@ -1041,7 +1036,7 @@ impl<'a> TyLoweringContext<'a> { let mut trait_ref = None; let clause = match bound.as_ref() { TypeBound::Path(path, TraitBoundModifier::None) => { - trait_ref = self.lower_trait_ref_from_path(path, Some(self_ty)); + trait_ref = self.lower_trait_ref_from_path(path, self_ty); trait_ref.clone().map(WhereClause::Implemented).map(crate::wrap_empty_binders) } TypeBound::Path(path, TraitBoundModifier::Maybe) => { @@ -1053,7 +1048,7 @@ impl<'a> TyLoweringContext<'a> { // `?Sized` has no of them. // If we got another trait here ignore the bound completely. let trait_id = self - .lower_trait_ref_from_path(path, Some(self_ty.clone())) + .lower_trait_ref_from_path(path, self_ty.clone()) .map(|trait_ref| trait_ref.hir_trait_id()); if trait_id == sized_trait { self.unsized_types.borrow_mut().insert(self_ty); @@ -1062,7 +1057,7 @@ impl<'a> TyLoweringContext<'a> { } TypeBound::ForLifetime(_, path) => { // FIXME Don't silently drop the hrtb lifetimes here - trait_ref = self.lower_trait_ref_from_path(path, Some(self_ty)); + trait_ref = self.lower_trait_ref_from_path(path, self_ty); trait_ref.clone().map(WhereClause::Implemented).map(crate::wrap_empty_binders) } TypeBound::Lifetime(l) => { @@ -2126,7 +2121,7 @@ pub(crate) fn impl_trait_query(db: &dyn HirDatabase, impl_id: ImplId) -> Option< .with_type_param_mode(ParamLoweringMode::Variable); let (self_ty, binders) = db.impl_self_ty(impl_id).into_value_and_skipped_binders(); let target_trait = impl_data.target_trait.as_ref()?; - Some(Binders::new(binders, ctx.lower_trait_ref(target_trait, Some(self_ty))?)) + Some(Binders::new(binders, ctx.lower_trait_ref(target_trait, self_ty)?)) } pub(crate) fn return_type_impl_traits( diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval.rs index 89b2ecb1a63e5..0d42617d185c4 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval.rs @@ -421,9 +421,25 @@ impl MirEvalError { } MirEvalError::MirLowerError(func, err) => { let function_name = db.function_data(*func); + let self_ = match func.lookup(db.upcast()).container { + ItemContainerId::ImplId(impl_id) => Some({ + let generics = crate::generics::generics(db.upcast(), impl_id.into()); + let substs = generics.placeholder_subst(db); + db.impl_self_ty(impl_id) + .substitute(Interner, &substs) + .display(db, edition) + .to_string() + }), + ItemContainerId::TraitId(it) => { + Some(db.trait_data(it).name.display(db.upcast(), edition).to_string()) + } + _ => None, + }; writeln!( f, - "MIR lowering for function `{}` ({:?}) failed due:", + "MIR lowering for function `{}{}{}` ({:?}) failed due:", + self_.as_deref().unwrap_or_default(), + if self_.is_some() { "::" } else { "" }, function_name.name.display(db.upcast(), edition), func )?; diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower.rs index 9cee494bbe743..a2cb122c54391 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower.rs @@ -94,7 +94,8 @@ pub enum MirLowerError { UnresolvedField, UnsizedTemporary(Ty), MissingFunctionDefinition(DefWithBodyId, ExprId), - TypeMismatch(Option), + TypeMismatch(TypeMismatch), + HasErrors, /// This should never happen. Type mismatch should catch everything. TypeError(&'static str), NotSupported(String), @@ -179,15 +180,13 @@ impl MirLowerError { body.pretty_print_expr(db.upcast(), *owner, *it, edition) )?; } - MirLowerError::TypeMismatch(e) => match e { - Some(e) => writeln!( - f, - "Type mismatch: Expected {}, found {}", - e.expected.display(db, edition), - e.actual.display(db, edition), - )?, - None => writeln!(f, "Type mismatch: types mismatch with {{unknown}}",)?, - }, + MirLowerError::HasErrors => writeln!(f, "Type inference result contains errors")?, + MirLowerError::TypeMismatch(e) => writeln!( + f, + "Type mismatch: Expected {}, found {}", + e.expected.display(db, edition), + e.actual.display(db, edition), + )?, MirLowerError::GenericArgNotProvided(id, subst) => { let parent = id.parent; let param = &db.generic_params(parent)[id.local_id]; @@ -2184,7 +2183,7 @@ pub fn lower_to_mir( root_expr: ExprId, ) -> Result { if infer.has_errors { - return Err(MirLowerError::TypeMismatch(None)); + return Err(MirLowerError::HasErrors); } let mut ctx = MirLowerCtx::new(db, owner, body, infer); // 0 is return local diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/invalid_cast.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/invalid_cast.rs index 2f6f033f25c7e..9eb4e618c01e9 100644 --- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/invalid_cast.rs +++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/invalid_cast.rs @@ -831,7 +831,7 @@ fn main() { //- minicore: sized fn main() { _ = ((), ()) as (); - //^^^^^^^^^^^^^^ error: non-primitive cast: `(_, _)` as `()` + //^^^^^^^^^^^^^^ error: non-primitive cast: `((), ())` as `()` } "#, ); diff --git a/src/tools/rust-analyzer/crates/test-fixture/src/lib.rs b/src/tools/rust-analyzer/crates/test-fixture/src/lib.rs index 03e85a898ab0c..faf9d22047d93 100644 --- a/src/tools/rust-analyzer/crates/test-fixture/src/lib.rs +++ b/src/tools/rust-analyzer/crates/test-fixture/src/lib.rs @@ -95,8 +95,10 @@ pub trait WithFixture: Default + ExpandDatabase + SourceRootDatabase + 'static { fn test_crate(&self) -> CrateId { let crate_graph = self.crate_graph(); let mut it = crate_graph.iter(); - let res = it.next().unwrap(); - assert!(it.next().is_none()); + let mut res = it.next().unwrap(); + while crate_graph[res].origin.is_lang() { + res = it.next().unwrap(); + } res } } diff --git a/src/tools/rust-analyzer/crates/test-utils/src/minicore.rs b/src/tools/rust-analyzer/crates/test-utils/src/minicore.rs index fec270a556045..67629fcf7cc5e 100644 --- a/src/tools/rust-analyzer/crates/test-utils/src/minicore.rs +++ b/src/tools/rust-analyzer/crates/test-utils/src/minicore.rs @@ -171,7 +171,7 @@ pub mod default { macro_rules! impl_default { ($v:literal; $($t:ty)*) => { $( - impl const Default for $t { + impl Default for $t { fn default() -> Self { $v } @@ -686,7 +686,7 @@ pub mod ops { // endregion:fn // region:try mod try_ { - use super::super::convert::Infallible; + use crate::convert::Infallible; pub enum ControlFlow { #[lang = "Continue"] @@ -756,7 +756,7 @@ pub mod ops { // endregion:option // region:result // region:from - use super::super::convert::From; + use crate::convert::From; impl Try for Result { type Output = T; @@ -777,7 +777,7 @@ pub mod ops { impl> FromResidual> for Result { fn from_residual(residual: Result) -> Self { match residual { - Err(e) => Err(From::from(e)), + Err(e) => Err(F::from(e)), Ok(_) => loop {}, } } From 54ebb9d4897c2f372e3b20f833c2ea4eaf656a0e Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Mon, 2 Sep 2024 15:45:06 +0200 Subject: [PATCH 0576/2194] Do not request sanitizers for naked functions Naked functions can only contain inline asm, so any instrumentation inserted by sanitizers is illegal. Don't request it. Fixes https://github.com/rust-lang/rust/issues/129224. --- compiler/rustc_codegen_llvm/src/attributes.rs | 46 ++++++++++--------- tests/codegen/naked-asan.rs | 22 +++++++++ 2 files changed, 47 insertions(+), 21 deletions(-) create mode 100644 tests/codegen/naked-asan.rs diff --git a/compiler/rustc_codegen_llvm/src/attributes.rs b/compiler/rustc_codegen_llvm/src/attributes.rs index 92a857c2adcf4..9d4497d73a8ae 100644 --- a/compiler/rustc_codegen_llvm/src/attributes.rs +++ b/compiler/rustc_codegen_llvm/src/attributes.rs @@ -411,26 +411,31 @@ pub(crate) fn llfn_attrs_from_instance<'ll, 'tcx>( // the string "false". Now it is disabled by absence of the attribute. to_add.push(llvm::CreateAttrStringValue(cx.llcx, "branch-target-enforcement", "false")); } - } else if llvm_util::get_version() >= (19, 0, 0) { - // For non-naked functions, set branch protection attributes on aarch64. - if let Some(BranchProtection { bti, pac_ret }) = - cx.sess().opts.unstable_opts.branch_protection - { - assert!(cx.sess().target.arch == "aarch64"); - if bti { - to_add.push(llvm::CreateAttrString(cx.llcx, "branch-target-enforcement")); - } - if let Some(PacRet { leaf, key }) = pac_ret { - to_add.push(llvm::CreateAttrStringValue( - cx.llcx, - "sign-return-address", - if leaf { "all" } else { "non-leaf" }, - )); - to_add.push(llvm::CreateAttrStringValue( - cx.llcx, - "sign-return-address-key", - if key == PAuthKey::A { "a_key" } else { "b_key" }, - )); + } else { + // Do not set sanitizer attributes for naked functions. + to_add.extend(sanitize_attrs(cx, codegen_fn_attrs.no_sanitize)); + + if llvm_util::get_version() >= (19, 0, 0) { + // For non-naked functions, set branch protection attributes on aarch64. + if let Some(BranchProtection { bti, pac_ret }) = + cx.sess().opts.unstable_opts.branch_protection + { + assert!(cx.sess().target.arch == "aarch64"); + if bti { + to_add.push(llvm::CreateAttrString(cx.llcx, "branch-target-enforcement")); + } + if let Some(PacRet { leaf, key }) = pac_ret { + to_add.push(llvm::CreateAttrStringValue( + cx.llcx, + "sign-return-address", + if leaf { "all" } else { "non-leaf" }, + )); + to_add.push(llvm::CreateAttrStringValue( + cx.llcx, + "sign-return-address-key", + if key == PAuthKey::A { "a_key" } else { "b_key" }, + )); + } } } } @@ -485,7 +490,6 @@ pub(crate) fn llfn_attrs_from_instance<'ll, 'tcx>( if let Some(backchain) = backchain_attr(cx) { to_add.push(backchain); } - to_add.extend(sanitize_attrs(cx, codegen_fn_attrs.no_sanitize)); to_add.extend(patchable_function_entry_attrs(cx, codegen_fn_attrs.patchable_function_entry)); // Always annotate functions with the target-cpu they are compiled for. diff --git a/tests/codegen/naked-asan.rs b/tests/codegen/naked-asan.rs new file mode 100644 index 0000000000000..a45b95780f793 --- /dev/null +++ b/tests/codegen/naked-asan.rs @@ -0,0 +1,22 @@ +// Make sure we do not request sanitizers for naked functions. + +//@ only-x86_64 +//@ needs-sanitizer-address +//@ compile-flags: -Zsanitizer=address -Ctarget-feature=-crt-static + +#![crate_type = "lib"] +#![no_std] +#![feature(abi_x86_interrupt, naked_functions)] + +// CHECK: define x86_intrcc void @page_fault_handler(ptr {{.*}}%0, i64 {{.*}}%1){{.*}}#[[ATTRS:[0-9]+]] { +// CHECK-NOT: memcpy +#[naked] +#[no_mangle] +pub extern "x86-interrupt" fn page_fault_handler(_: u64, _: u64) { + unsafe { + core::arch::asm!("ud2", options(noreturn)); + } +} + +// CHECK: #[[ATTRS]] = +// CHECK-NOT: sanitize_address From bdc9da9361922a76317c35e33a0226f6152bea63 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Fri, 6 Sep 2024 14:44:05 +0200 Subject: [PATCH 0577/2194] fix: Properly prevent mir building with unknown types present --- src/tools/rust-analyzer/crates/hir-ty/src/infer.rs | 13 +++++++++++-- src/tools/rust-analyzer/crates/hir-ty/src/mir.rs | 4 ++-- .../src/handlers/mutability_errors.rs | 2 +- 3 files changed, 14 insertions(+), 5 deletions(-) diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer.rs index 0e68ab4bfec5c..8bc3c50725d99 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/infer.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer.rs @@ -708,7 +708,6 @@ impl<'a> InferenceContext<'a> { tuple_field_access_types: _, coercion_casts, } = &mut result; - table.fallback_if_possible(); // Comment from rustc: @@ -754,7 +753,7 @@ impl<'a> InferenceContext<'a> { *has_errors = *has_errors || ty.contains_unknown(); } - *has_errors = !type_mismatches.is_empty(); + *has_errors |= !type_mismatches.is_empty(); type_mismatches.retain(|_, mismatch| { mismatch.expected = table.resolve_completely(mismatch.expected.clone()); @@ -797,20 +796,30 @@ impl<'a> InferenceContext<'a> { }); for (_, subst) in method_resolutions.values_mut() { *subst = table.resolve_completely(subst.clone()); + *has_errors = + *has_errors || subst.type_parameters(Interner).any(|ty| ty.contains_unknown()); } for (_, subst) in assoc_resolutions.values_mut() { *subst = table.resolve_completely(subst.clone()); + *has_errors = + *has_errors || subst.type_parameters(Interner).any(|ty| ty.contains_unknown()); } for adjustment in expr_adjustments.values_mut().flatten() { adjustment.target = table.resolve_completely(adjustment.target.clone()); + *has_errors = *has_errors || adjustment.target.contains_unknown(); } for adjustment in pat_adjustments.values_mut().flatten() { *adjustment = table.resolve_completely(adjustment.clone()); + *has_errors = *has_errors || adjustment.contains_unknown(); } result.tuple_field_access_types = tuple_field_accesses_rev .into_iter() .enumerate() .map(|(idx, subst)| (TupleId(idx as u32), table.resolve_completely(subst))) + .inspect(|(_, subst)| { + *has_errors = + *has_errors || subst.type_parameters(Interner).any(|ty| ty.contains_unknown()); + }) .collect(); result } diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir.rs index 8cd6ae1232691..8e815aabf2070 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/mir.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir.rs @@ -185,8 +185,8 @@ impl ProjectionElem { never!("Out of bound tuple field"); TyKind::Error.intern(Interner) }), - _ => { - never!("Only tuple has tuple field"); + ty => { + never!("Only tuple has tuple field: {:?}", ty); TyKind::Error.intern(Interner) } }, diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/mutability_errors.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/mutability_errors.rs index e4b1f3ca95998..955427939150b 100644 --- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/mutability_errors.rs +++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/mutability_errors.rs @@ -824,13 +824,13 @@ fn f() { #[test] fn or_pattern() { + // FIXME: `None` is inferred as unknown here for some reason check_diagnostics( r#" //- minicore: option fn f(_: i32) {} fn main() { let ((Some(mut x), None) | (_, Some(mut x))) = (None, Some(7)) else { return }; - //^^^^^ 💡 warn: variable does not need to be mutable f(x); } "#, From e38764d73b84eb625102233623e79f36515345e2 Mon Sep 17 00:00:00 2001 From: Pavel Grigorenko Date: Sun, 1 Sep 2024 01:14:06 +0300 Subject: [PATCH 0578/2194] elided_named_lifetimes: unify lint def & pass MissingLifetimeKind --- .../rustc_lint/src/context/diagnostics.rs | 23 +++++++++++-------- compiler/rustc_lint_defs/src/lib.rs | 17 ++++++++------ compiler/rustc_resolve/src/late.rs | 14 +++++++---- 3 files changed, 33 insertions(+), 21 deletions(-) diff --git a/compiler/rustc_lint/src/context/diagnostics.rs b/compiler/rustc_lint/src/context/diagnostics.rs index fd43afa174383..b1c1e4f4dd686 100644 --- a/compiler/rustc_lint/src/context/diagnostics.rs +++ b/compiler/rustc_lint/src/context/diagnostics.rs @@ -8,7 +8,7 @@ use rustc_errors::{ elided_lifetime_in_path_suggestion, Applicability, Diag, DiagArgValue, LintDiagnostic, }; use rustc_middle::middle::stability; -use rustc_session::lint::BuiltinLintDiag; +use rustc_session::lint::{BuiltinLintDiag, ElidedLifetimeResolution}; use rustc_session::Session; use rustc_span::symbol::kw; use rustc_span::BytePos; @@ -442,15 +442,18 @@ pub(super) fn decorate_lint(sess: &Session, diagnostic: BuiltinLintDiag, diag: & BuiltinLintDiag::UnexpectedBuiltinCfg { cfg, cfg_name, controlled_by } => { lints::UnexpectedBuiltinCfg { cfg, cfg_name, controlled_by }.decorate_lint(diag) } - BuiltinLintDiag::ElidedIsStatic { elided } => { - lints::ElidedNamedLifetime { elided, name: kw::StaticLifetime, named_declaration: None } - .decorate_lint(diag) - } - BuiltinLintDiag::ElidedIsParam { elided, param: (param_name, param_span) } => { - lints::ElidedNamedLifetime { - elided, - name: param_name, - named_declaration: Some(param_span), + BuiltinLintDiag::ElidedNamedLifetimes { elided: (elided, _kind), resolution } => { + match resolution { + ElidedLifetimeResolution::Static => lints::ElidedNamedLifetime { + elided, + name: kw::StaticLifetime, + named_declaration: None, + }, + ElidedLifetimeResolution::Param(name, declaration) => lints::ElidedNamedLifetime { + elided, + name, + named_declaration: Some(declaration), + }, } .decorate_lint(diag) } diff --git a/compiler/rustc_lint_defs/src/lib.rs b/compiler/rustc_lint_defs/src/lib.rs index 6ee330416236f..9a72e4f673934 100644 --- a/compiler/rustc_lint_defs/src/lib.rs +++ b/compiler/rustc_lint_defs/src/lib.rs @@ -10,7 +10,7 @@ use rustc_data_structures::stable_hasher::{ }; use rustc_error_messages::{DiagMessage, MultiSpan}; use rustc_hir::def::Namespace; -use rustc_hir::{HashStableContext, HirId}; +use rustc_hir::{HashStableContext, HirId, MissingLifetimeKind}; use rustc_macros::{Decodable, Encodable, HashStable_Generic}; use rustc_span::edition::Edition; use rustc_span::symbol::{Ident, MacroRulesNormalizedIdent}; @@ -556,6 +556,12 @@ pub enum DeprecatedSinceKind { InVersion(String), } +#[derive(Debug)] +pub enum ElidedLifetimeResolution { + Static, + Param(Symbol, Span), +} + // This could be a closure, but then implementing derive trait // becomes hacky (and it gets allocated). #[derive(Debug)] @@ -568,12 +574,9 @@ pub enum BuiltinLintDiag { }, MacroExpandedMacroExportsAccessedByAbsolutePaths(Span), ElidedLifetimesInPaths(usize, Span, bool, Span), - ElidedIsStatic { - elided: Span, - }, - ElidedIsParam { - elided: Span, - param: (Symbol, Span), + ElidedNamedLifetimes { + elided: (Span, MissingLifetimeKind), + resolution: ElidedLifetimeResolution, }, UnknownCrateTypes { span: Span, diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 79c42456cf8c9..917cb81aa511f 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -2062,7 +2062,10 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { lint::builtin::ELIDED_NAMED_LIFETIMES, missing.id_for_lint, missing.span, - BuiltinLintDiag::ElidedIsStatic { elided: missing.span }, + BuiltinLintDiag::ElidedNamedLifetimes { + elided: (missing.span, missing.kind), + resolution: lint::ElidedLifetimeResolution::Static, + }, ); } } @@ -2072,9 +2075,12 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { lint::builtin::ELIDED_NAMED_LIFETIMES, missing.id_for_lint, missing.span, - BuiltinLintDiag::ElidedIsParam { - elided: missing.span, - param: (tcx.item_name(param.into()), tcx.source_span(param)), + BuiltinLintDiag::ElidedNamedLifetimes { + elided: (missing.span, missing.kind), + resolution: lint::ElidedLifetimeResolution::Param( + tcx.item_name(param.into()), + tcx.source_span(param), + ), }, ); } From dcfc71310d560a77b4813f60511c2b15c5125b80 Mon Sep 17 00:00:00 2001 From: Pavel Grigorenko Date: Sun, 1 Sep 2024 03:42:18 +0300 Subject: [PATCH 0579/2194] elided_named_lifetimes: add suggestions --- compiler/rustc_lint/messages.ftl | 2 + .../rustc_lint/src/context/diagnostics.rs | 44 ++++++++++++------- compiler/rustc_lint/src/lints.rs | 2 +- .../async-await/issues/issue-63388-1.stderr | 4 ++ .../type-dependent/issue-71348.full.stderr | 4 ++ .../type-dependent/issue-71348.min.stderr | 4 ++ .../consts/min_const_fn/min_const_fn.stderr | 9 ++++ .../ui/impl-trait/impl-fn-hrtb-bounds.stderr | 4 ++ .../impl-fn-predefined-lifetimes.stderr | 4 ++ .../rpit-assoc-pair-with-lifetime.stderr | 4 ++ ...urn-type-requires-explicit-lifetime.stderr | 4 ++ ...-existing-name-if-else-using-impl-3.stderr | 4 ++ .../example-from-issue48686.stderr | 4 ++ .../missing-lifetime-kind.stderr | 19 ++++++++ .../not-tied-to-crate.stderr | 8 ++++ .../lint/elided-named-lifetimes/static.stderr | 19 ++++++++ .../object-lifetime-default-elision.stderr | 4 ++ .../ignore-non-reference-lifetimes.stderr | 9 ++++ tests/ui/self/self_lifetime-async.stderr | 9 ++++ tests/ui/self/self_lifetime.stderr | 9 ++++ .../impl-trait-missing-lifetime-gated.stderr | 4 ++ .../missing-lifetimes-in-signature.stderr | 4 ++ .../missing_lifetime_bound.stderr | 4 ++ 23 files changed, 166 insertions(+), 16 deletions(-) diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl index 759320b9eb65f..fe211355ac38a 100644 --- a/compiler/rustc_lint/messages.ftl +++ b/compiler/rustc_lint/messages.ftl @@ -256,6 +256,8 @@ lint_elided_named_lifetime = elided lifetime has a name .label_elided = this elided lifetime gets resolved as `{$name}` .label_named = lifetime `{$name}` declared here +lint_elided_named_lifetime_suggestion = consider specifying it explicitly + lint_enum_intrinsics_mem_discriminant = the return value of `mem::discriminant` is unspecified when called with a non-enum type .note = the argument to `discriminant` should be a reference to an enum, but it was passed a reference to a `{$ty_param}`, which is not an enum diff --git a/compiler/rustc_lint/src/context/diagnostics.rs b/compiler/rustc_lint/src/context/diagnostics.rs index b1c1e4f4dd686..a1a371a032e90 100644 --- a/compiler/rustc_lint/src/context/diagnostics.rs +++ b/compiler/rustc_lint/src/context/diagnostics.rs @@ -7,6 +7,7 @@ use rustc_ast::util::unicode::TEXT_FLOW_CONTROL_CHARS; use rustc_errors::{ elided_lifetime_in_path_suggestion, Applicability, Diag, DiagArgValue, LintDiagnostic, }; +use rustc_hir::MissingLifetimeKind; use rustc_middle::middle::stability; use rustc_session::lint::{BuiltinLintDiag, ElidedLifetimeResolution}; use rustc_session::Session; @@ -14,7 +15,8 @@ use rustc_span::symbol::kw; use rustc_span::BytePos; use tracing::debug; -use crate::lints; +use crate::fluent_generated; +use crate::lints::{self, ElidedNamedLifetime}; mod check_cfg; @@ -442,20 +444,32 @@ pub(super) fn decorate_lint(sess: &Session, diagnostic: BuiltinLintDiag, diag: & BuiltinLintDiag::UnexpectedBuiltinCfg { cfg, cfg_name, controlled_by } => { lints::UnexpectedBuiltinCfg { cfg, cfg_name, controlled_by }.decorate_lint(diag) } - BuiltinLintDiag::ElidedNamedLifetimes { elided: (elided, _kind), resolution } => { - match resolution { - ElidedLifetimeResolution::Static => lints::ElidedNamedLifetime { - elided, - name: kw::StaticLifetime, - named_declaration: None, - }, - ElidedLifetimeResolution::Param(name, declaration) => lints::ElidedNamedLifetime { - elided, - name, - named_declaration: Some(declaration), - }, - } - .decorate_lint(diag) + BuiltinLintDiag::ElidedNamedLifetimes { elided: (span, kind), resolution } => { + let (name, named_declaration) = match resolution { + ElidedLifetimeResolution::Static => (kw::StaticLifetime, None), + ElidedLifetimeResolution::Param(name, declaration) => (name, Some(declaration)), + }; + ElidedNamedLifetime { span, name, named_declaration }.decorate_lint(diag); + + let (applicability, suggestion) = match kind { + MissingLifetimeKind::Underscore => { + (Applicability::MachineApplicable, format!("{name}")) + } + MissingLifetimeKind::Ampersand => { + (Applicability::MachineApplicable, format!("&{name} ")) + } + MissingLifetimeKind::Comma => (Applicability::Unspecified, format!("<{name}, ")), + MissingLifetimeKind::Brackets => ( + Applicability::Unspecified, + format!("{}<{name}>", sess.source_map().span_to_snippet(span).unwrap()), + ), + }; + diag.span_suggestion_verbose( + span, + fluent_generated::lint_elided_named_lifetime_suggestion, + suggestion, + applicability, + ); } } } diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index 9050f36acba7b..426d671f8e0a6 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -2627,7 +2627,7 @@ pub(crate) struct ElidedLifetimesInPaths { #[diag(lint_elided_named_lifetime)] pub(crate) struct ElidedNamedLifetime { #[label(lint_label_elided)] - pub elided: Span, + pub span: Span, pub name: Symbol, #[label(lint_label_named)] pub named_declaration: Option, diff --git a/tests/ui/async-await/issues/issue-63388-1.stderr b/tests/ui/async-await/issues/issue-63388-1.stderr index ef74bfe32375e..c8b55977faf3a 100644 --- a/tests/ui/async-await/issues/issue-63388-1.stderr +++ b/tests/ui/async-await/issues/issue-63388-1.stderr @@ -8,6 +8,10 @@ LL | ) -> &dyn Foo | ^ this elided lifetime gets resolved as `'a` | = note: `#[warn(elided_named_lifetimes)]` on by default +help: consider specifying it explicitly + | +LL | ) -> &'a dyn Foo + | ~~~ error[E0621]: explicit lifetime required in the type of `foo` --> $DIR/issue-63388-1.rs:13:5 diff --git a/tests/ui/const-generics/type-dependent/issue-71348.full.stderr b/tests/ui/const-generics/type-dependent/issue-71348.full.stderr index 177ff20fbf9ea..8d1c1ea23a81c 100644 --- a/tests/ui/const-generics/type-dependent/issue-71348.full.stderr +++ b/tests/ui/const-generics/type-dependent/issue-71348.full.stderr @@ -5,6 +5,10 @@ LL | fn ask<'a, const N: &'static str>(&'a self) -> &'a >::Ta | -- lifetime `'a` declared here ^ this elided lifetime gets resolved as `'a` | = note: `#[warn(elided_named_lifetimes)]` on by default +help: consider specifying it explicitly + | +LL | fn ask<'a, const N: &'static str>(&'a self) -> &'a >::Target + | ~~~~ warning: 1 warning emitted diff --git a/tests/ui/const-generics/type-dependent/issue-71348.min.stderr b/tests/ui/const-generics/type-dependent/issue-71348.min.stderr index 5aee282952aa2..57da3ce21cecd 100644 --- a/tests/ui/const-generics/type-dependent/issue-71348.min.stderr +++ b/tests/ui/const-generics/type-dependent/issue-71348.min.stderr @@ -5,6 +5,10 @@ LL | fn ask<'a, const N: &'static str>(&'a self) -> &'a >::Ta | -- lifetime `'a` declared here ^ this elided lifetime gets resolved as `'a` | = note: `#[warn(elided_named_lifetimes)]` on by default +help: consider specifying it explicitly + | +LL | fn ask<'a, const N: &'static str>(&'a self) -> &'a >::Target + | ~~~~ error: `&'static str` is forbidden as the type of a const generic parameter --> $DIR/issue-71348.rs:10:24 diff --git a/tests/ui/consts/min_const_fn/min_const_fn.stderr b/tests/ui/consts/min_const_fn/min_const_fn.stderr index 4b348a182b87f..b7db403ad16b2 100644 --- a/tests/ui/consts/min_const_fn/min_const_fn.stderr +++ b/tests/ui/consts/min_const_fn/min_const_fn.stderr @@ -8,6 +8,10 @@ LL | const fn get_lt(&'a self) -> &T { &self.0 } | ^ this elided lifetime gets resolved as `'a` | = note: `#[warn(elided_named_lifetimes)]` on by default +help: consider specifying it explicitly + | +LL | const fn get_lt(&'a self) -> &'a T { &self.0 } + | ~~~ warning: elided lifetime has a name --> $DIR/min_const_fn.rs:48:42 @@ -17,6 +21,11 @@ LL | impl<'a, T> Foo { ... LL | const fn get_mut_lt(&'a mut self) -> &mut T { &mut self.0 } | ^ this elided lifetime gets resolved as `'a` + | +help: consider specifying it explicitly + | +LL | const fn get_mut_lt(&'a mut self) -> &'a mut T { &mut self.0 } + | ~~~ error[E0493]: destructor of `Foo` cannot be evaluated at compile-time --> $DIR/min_const_fn.rs:37:25 diff --git a/tests/ui/impl-trait/impl-fn-hrtb-bounds.stderr b/tests/ui/impl-trait/impl-fn-hrtb-bounds.stderr index d0f8f7689d17c..ccea9d5e6e92a 100644 --- a/tests/ui/impl-trait/impl-fn-hrtb-bounds.stderr +++ b/tests/ui/impl-trait/impl-fn-hrtb-bounds.stderr @@ -17,6 +17,10 @@ LL | fn c() -> impl for<'a> Fn(&'a u8) -> (impl Debug + '_) { | -- lifetime `'a` declared here ^^ this elided lifetime gets resolved as `'a` | = note: `#[warn(elided_named_lifetimes)]` on by default +help: consider specifying it explicitly + | +LL | fn c() -> impl for<'a> Fn(&'a u8) -> (impl Debug + 'a) { + | ~~ error[E0657]: `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait` --> $DIR/impl-fn-hrtb-bounds.rs:4:41 diff --git a/tests/ui/impl-trait/impl-fn-predefined-lifetimes.stderr b/tests/ui/impl-trait/impl-fn-predefined-lifetimes.stderr index 50a9f3ebeabb8..a60f398684330 100644 --- a/tests/ui/impl-trait/impl-fn-predefined-lifetimes.stderr +++ b/tests/ui/impl-trait/impl-fn-predefined-lifetimes.stderr @@ -5,6 +5,10 @@ LL | fn a<'a>() -> impl Fn(&'a u8) -> (impl Debug + '_) { | -- lifetime `'a` declared here ^^ this elided lifetime gets resolved as `'a` | = note: `#[warn(elided_named_lifetimes)]` on by default +help: consider specifying it explicitly + | +LL | fn a<'a>() -> impl Fn(&'a u8) -> (impl Debug + 'a) { + | ~~ error[E0792]: expected generic lifetime parameter, found `'_` --> $DIR/impl-fn-predefined-lifetimes.rs:7:9 diff --git a/tests/ui/impl-trait/rpit-assoc-pair-with-lifetime.stderr b/tests/ui/impl-trait/rpit-assoc-pair-with-lifetime.stderr index bff3ffd934ac6..ec0f0708b156f 100644 --- a/tests/ui/impl-trait/rpit-assoc-pair-with-lifetime.stderr +++ b/tests/ui/impl-trait/rpit-assoc-pair-with-lifetime.stderr @@ -5,6 +5,10 @@ LL | pub fn iter<'a>(v: Vec<(u32, &'a u32)>) -> impl DoubleEndedIterator(v: Vec<(u32, &'a u32)>) -> impl DoubleEndedIterator { + | ~~~ warning: 1 warning emitted diff --git a/tests/ui/lifetimes/lifetime-elision-return-type-requires-explicit-lifetime.stderr b/tests/ui/lifetimes/lifetime-elision-return-type-requires-explicit-lifetime.stderr index f835d2655bb01..a7512158661fb 100644 --- a/tests/ui/lifetimes/lifetime-elision-return-type-requires-explicit-lifetime.stderr +++ b/tests/ui/lifetimes/lifetime-elision-return-type-requires-explicit-lifetime.stderr @@ -114,6 +114,10 @@ LL | fn m<'a>(_: &'a Foo<'a>) -> &str { "" } | lifetime `'a` declared here | = note: `#[warn(elided_named_lifetimes)]` on by default +help: consider specifying it explicitly + | +LL | fn m<'a>(_: &'a Foo<'a>) -> &'a str { "" } + | ~~~ error: aborting due to 7 previous errors; 1 warning emitted diff --git a/tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-3.stderr b/tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-3.stderr index 2d5d4fb0e72ec..0943e0cc0d9d4 100644 --- a/tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-3.stderr +++ b/tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-3.stderr @@ -7,6 +7,10 @@ LL | fn foo<'a>(&'a self, x: &i32) -> &i32 { | lifetime `'a` declared here | = note: `#[warn(elided_named_lifetimes)]` on by default +help: consider specifying it explicitly + | +LL | fn foo<'a>(&'a self, x: &i32) -> &'a i32 { + | ~~~ error[E0621]: explicit lifetime required in the type of `x` --> $DIR/ex1-return-one-existing-name-if-else-using-impl-3.rs:9:36 diff --git a/tests/ui/lint/elided-named-lifetimes/example-from-issue48686.stderr b/tests/ui/lint/elided-named-lifetimes/example-from-issue48686.stderr index 8c5426a60cb72..5af5123c03237 100644 --- a/tests/ui/lint/elided-named-lifetimes/example-from-issue48686.stderr +++ b/tests/ui/lint/elided-named-lifetimes/example-from-issue48686.stderr @@ -9,6 +9,10 @@ note: the lint level is defined here | LL | #![deny(elided_named_lifetimes)] | ^^^^^^^^^^^^^^^^^^^^^^ +help: consider specifying it explicitly + | +LL | pub fn get_mut(&'static self, x: &mut u8) -> &'static mut u8 { + | ~~~~~~~~ error: aborting due to 1 previous error diff --git a/tests/ui/lint/elided-named-lifetimes/missing-lifetime-kind.stderr b/tests/ui/lint/elided-named-lifetimes/missing-lifetime-kind.stderr index 249ae146b1675..6abaad7f5d218 100644 --- a/tests/ui/lint/elided-named-lifetimes/missing-lifetime-kind.stderr +++ b/tests/ui/lint/elided-named-lifetimes/missing-lifetime-kind.stderr @@ -11,6 +11,10 @@ note: the lint level is defined here | LL | #![deny(elided_named_lifetimes)] | ^^^^^^^^^^^^^^^^^^^^^^ +help: consider specifying it explicitly + | +LL | fn ampersand<'a>(x: &'a u8) -> &'a u8 { + | ~~~ error: elided lifetime has a name --> $DIR/missing-lifetime-kind.rs:10:31 @@ -19,6 +23,11 @@ LL | fn brackets<'a>(x: &'a u8) -> Brackets { | -- ^^^^^^^^ this elided lifetime gets resolved as `'a` | | | lifetime `'a` declared here + | +help: consider specifying it explicitly + | +LL | fn brackets<'a>(x: &'a u8) -> Brackets<'a> { + | ~~~~~~~~~~~~ error: elided lifetime has a name --> $DIR/missing-lifetime-kind.rs:17:33 @@ -27,6 +36,11 @@ LL | fn comma<'a>(x: &'a u8) -> Comma { | -- ^ this elided lifetime gets resolved as `'a` | | | lifetime `'a` declared here + | +help: consider specifying it explicitly + | +LL | fn comma<'a>(x: &'a u8) -> Comma<'a, u8> { + | ~~~~ error: elided lifetime has a name --> $DIR/missing-lifetime-kind.rs:22:34 @@ -35,6 +49,11 @@ LL | fn underscore<'a>(x: &'a u8) -> &'_ u8 { | -- ^^ this elided lifetime gets resolved as `'a` | | | lifetime `'a` declared here + | +help: consider specifying it explicitly + | +LL | fn underscore<'a>(x: &'a u8) -> &'a u8 { + | ~~ error: aborting due to 4 previous errors diff --git a/tests/ui/lint/elided-named-lifetimes/not-tied-to-crate.stderr b/tests/ui/lint/elided-named-lifetimes/not-tied-to-crate.stderr index c465aab1a03d2..cbc1b862caabd 100644 --- a/tests/ui/lint/elided-named-lifetimes/not-tied-to-crate.stderr +++ b/tests/ui/lint/elided-named-lifetimes/not-tied-to-crate.stderr @@ -9,6 +9,10 @@ note: the lint level is defined here | LL | #[warn(elided_named_lifetimes)] | ^^^^^^^^^^^^^^^^^^^^^^ +help: consider specifying it explicitly + | +LL | fn bar(x: &'static u8) -> &'static u8 { + | ~~~~~~~~ error: elided lifetime has a name --> $DIR/not-tied-to-crate.rs:11:31 @@ -21,6 +25,10 @@ note: the lint level is defined here | LL | #[deny(elided_named_lifetimes)] | ^^^^^^^^^^^^^^^^^^^^^^ +help: consider specifying it explicitly + | +LL | fn baz(x: &'static u8) -> &'static u8 { + | ~~~~~~~~ error: aborting due to 1 previous error; 1 warning emitted diff --git a/tests/ui/lint/elided-named-lifetimes/static.stderr b/tests/ui/lint/elided-named-lifetimes/static.stderr index d2e9776cb4f0e..6c3944e5ea580 100644 --- a/tests/ui/lint/elided-named-lifetimes/static.stderr +++ b/tests/ui/lint/elided-named-lifetimes/static.stderr @@ -9,24 +9,43 @@ note: the lint level is defined here | LL | #![deny(elided_named_lifetimes)] | ^^^^^^^^^^^^^^^^^^^^^^ +help: consider specifying it explicitly + | +LL | fn ampersand(x: &'static u8) -> &'static u8 { + | ~~~~~~~~ error: elided lifetime has a name --> $DIR/static.rs:23:32 | LL | fn brackets(x: &'static u8) -> Brackets { | ^^^^^^^^ this elided lifetime gets resolved as `'static` + | +help: consider specifying it explicitly + | +LL | fn brackets(x: &'static u8) -> Brackets<'static> { + | ~~~~~~~~~~~~~~~~~ error: elided lifetime has a name --> $DIR/static.rs:30:34 | LL | fn comma(x: &'static u8) -> Comma { | ^ this elided lifetime gets resolved as `'static` + | +help: consider specifying it explicitly + | +LL | fn comma(x: &'static u8) -> Comma<'static, u8> { + | ~~~~~~~~~ error: elided lifetime has a name --> $DIR/static.rs:35:35 | LL | fn underscore(x: &'static u8) -> &'_ u8 { | ^^ this elided lifetime gets resolved as `'static` + | +help: consider specifying it explicitly + | +LL | fn underscore(x: &'static u8) -> &'static u8 { + | ~~~~~~~ error: aborting due to 4 previous errors diff --git a/tests/ui/object-lifetime/object-lifetime-default-elision.stderr b/tests/ui/object-lifetime/object-lifetime-default-elision.stderr index b44a184c6848f..7d239a54eda4f 100644 --- a/tests/ui/object-lifetime/object-lifetime-default-elision.stderr +++ b/tests/ui/object-lifetime/object-lifetime-default-elision.stderr @@ -7,6 +7,10 @@ LL | fn load2<'a>(ss: &'a dyn SomeTrait) -> &dyn SomeTrait { | lifetime `'a` declared here | = note: `#[warn(elided_named_lifetimes)]` on by default +help: consider specifying it explicitly + | +LL | fn load2<'a>(ss: &'a dyn SomeTrait) -> &'a dyn SomeTrait { + | ~~~ error: lifetime may not live long enough --> $DIR/object-lifetime-default-elision.rs:73:5 diff --git a/tests/ui/self/elision/ignore-non-reference-lifetimes.stderr b/tests/ui/self/elision/ignore-non-reference-lifetimes.stderr index 4465dbae52989..460d2ce2cc907 100644 --- a/tests/ui/self/elision/ignore-non-reference-lifetimes.stderr +++ b/tests/ui/self/elision/ignore-non-reference-lifetimes.stderr @@ -5,12 +5,21 @@ LL | fn a<'a>(self: Self, a: &'a str) -> &str { | -- lifetime `'a` declared here ^ this elided lifetime gets resolved as `'a` | = note: `#[warn(elided_named_lifetimes)]` on by default +help: consider specifying it explicitly + | +LL | fn a<'a>(self: Self, a: &'a str) -> &'a str { + | ~~~ warning: elided lifetime has a name --> $DIR/ignore-non-reference-lifetimes.rs:10:44 | LL | fn b<'a>(self: Foo<'b>, a: &'a str) -> &str { | -- lifetime `'a` declared here ^ this elided lifetime gets resolved as `'a` + | +help: consider specifying it explicitly + | +LL | fn b<'a>(self: Foo<'b>, a: &'a str) -> &'a str { + | ~~~ warning: 2 warnings emitted diff --git a/tests/ui/self/self_lifetime-async.stderr b/tests/ui/self/self_lifetime-async.stderr index 32de3fd18c97f..fd167cf392fb6 100644 --- a/tests/ui/self/self_lifetime-async.stderr +++ b/tests/ui/self/self_lifetime-async.stderr @@ -7,12 +7,21 @@ LL | async fn foo<'b>(self: &'b Foo<'a>) -> &() { self.0 } | lifetime `'b` declared here | = note: `#[warn(elided_named_lifetimes)]` on by default +help: consider specifying it explicitly + | +LL | async fn foo<'b>(self: &'b Foo<'a>) -> &'b () { self.0 } + | ~~~ warning: elided lifetime has a name --> $DIR/self_lifetime-async.rs:12:52 | LL | async fn bar<'a>(self: &Alias, arg: &'a ()) -> &() { arg } | -- lifetime `'a` declared here ^ this elided lifetime gets resolved as `'a` + | +help: consider specifying it explicitly + | +LL | async fn bar<'a>(self: &Alias, arg: &'a ()) -> &'a () { arg } + | ~~~ warning: 2 warnings emitted diff --git a/tests/ui/self/self_lifetime.stderr b/tests/ui/self/self_lifetime.stderr index cd8f4d8adf8b1..52189084f04c0 100644 --- a/tests/ui/self/self_lifetime.stderr +++ b/tests/ui/self/self_lifetime.stderr @@ -7,12 +7,21 @@ LL | fn foo<'b>(self: &'b Foo<'a>) -> &() { self.0 } | lifetime `'b` declared here | = note: `#[warn(elided_named_lifetimes)]` on by default +help: consider specifying it explicitly + | +LL | fn foo<'b>(self: &'b Foo<'a>) -> &'b () { self.0 } + | ~~~ warning: elided lifetime has a name --> $DIR/self_lifetime.rs:13:46 | LL | fn bar<'a>(self: &Alias, arg: &'a ()) -> &() { arg } | -- lifetime `'a` declared here ^ this elided lifetime gets resolved as `'a` + | +help: consider specifying it explicitly + | +LL | fn bar<'a>(self: &Alias, arg: &'a ()) -> &'a () { arg } + | ~~~ warning: 2 warnings emitted diff --git a/tests/ui/suggestions/impl-trait-missing-lifetime-gated.stderr b/tests/ui/suggestions/impl-trait-missing-lifetime-gated.stderr index 30f4509d49dee..92f774767c863 100644 --- a/tests/ui/suggestions/impl-trait-missing-lifetime-gated.stderr +++ b/tests/ui/suggestions/impl-trait-missing-lifetime-gated.stderr @@ -131,6 +131,10 @@ LL | fn resolved_anonymous<'a, T: 'a>(f: impl Fn(&'a str) -> &T) { | -- lifetime `'a` declared here ^ this elided lifetime gets resolved as `'a` | = note: `#[warn(elided_named_lifetimes)]` on by default +help: consider specifying it explicitly + | +LL | fn resolved_anonymous<'a, T: 'a>(f: impl Fn(&'a str) -> &'a T) { + | ~~~ error[E0658]: anonymous lifetimes in `impl Trait` are unstable --> $DIR/impl-trait-missing-lifetime-gated.rs:6:35 diff --git a/tests/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr b/tests/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr index ea01dcd5020cf..baa5fa949ec41 100644 --- a/tests/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr +++ b/tests/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr @@ -13,6 +13,10 @@ LL | fn ok2<'a, G: 'a, T>(g: G, dest: &'a mut T) -> impl FnOnce() + '_ + 'a | -- lifetime `'a` declared here ^^ this elided lifetime gets resolved as `'a` | = note: `#[warn(elided_named_lifetimes)]` on by default +help: consider specifying it explicitly + | +LL | fn ok2<'a, G: 'a, T>(g: G, dest: &'a mut T) -> impl FnOnce() + 'a + 'a + | ~~ error[E0700]: hidden type for `impl FnOnce()` captures lifetime that does not appear in bounds --> $DIR/missing-lifetimes-in-signature.rs:19:5 diff --git a/tests/ui/type-alias-impl-trait/missing_lifetime_bound.stderr b/tests/ui/type-alias-impl-trait/missing_lifetime_bound.stderr index e2c21f1636b0c..73a362d28e7d7 100644 --- a/tests/ui/type-alias-impl-trait/missing_lifetime_bound.stderr +++ b/tests/ui/type-alias-impl-trait/missing_lifetime_bound.stderr @@ -7,6 +7,10 @@ LL | fn defining<'a, T>(x: &'a i32) -> Opaque { x } | lifetime `'a` declared here | = note: `#[warn(elided_named_lifetimes)]` on by default +help: consider specifying it explicitly + | +LL | fn defining<'a, T>(x: &'a i32) -> Opaque<'a, T> { x } + | ~~~~ error[E0700]: hidden type for `Opaque2` captures lifetime that does not appear in bounds --> $DIR/missing_lifetime_bound.rs:5:47 From 547db4a4b7c9bfea52b519d0095510126a0a1cb0 Mon Sep 17 00:00:00 2001 From: Pavel Grigorenko Date: Sun, 1 Sep 2024 04:08:55 +0300 Subject: [PATCH 0580/2194] elided_named_lifetimes: manually implement `LintDiagnostic` --- compiler/rustc_lint/messages.ftl | 3 +- .../rustc_lint/src/context/diagnostics.rs | 32 +++---------- compiler/rustc_lint/src/lints.rs | 47 ++++++++++++++++--- .../async-await/issues/issue-63388-1.stderr | 2 +- .../type-dependent/issue-71348.full.stderr | 2 +- .../type-dependent/issue-71348.min.stderr | 2 +- .../consts/min_const_fn/min_const_fn.stderr | 4 +- .../rpit-assoc-pair-with-lifetime.stderr | 2 +- ...urn-type-requires-explicit-lifetime.stderr | 2 +- ...-existing-name-if-else-using-impl-3.stderr | 2 +- .../example-from-issue48686.stderr | 2 +- .../missing-lifetime-kind.stderr | 6 +-- .../not-tied-to-crate.stderr | 4 +- .../lint/elided-named-lifetimes/static.stderr | 6 +-- .../object-lifetime-default-elision.stderr | 2 +- .../ignore-non-reference-lifetimes.stderr | 4 +- tests/ui/self/self_lifetime-async.stderr | 4 +- tests/ui/self/self_lifetime.stderr | 4 +- .../impl-trait-missing-lifetime-gated.stderr | 2 +- .../missing_lifetime_bound.stderr | 2 +- 20 files changed, 75 insertions(+), 59 deletions(-) diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl index fe211355ac38a..5a368f4ed9a54 100644 --- a/compiler/rustc_lint/messages.ftl +++ b/compiler/rustc_lint/messages.ftl @@ -255,8 +255,7 @@ lint_duplicate_matcher_binding = duplicate matcher binding lint_elided_named_lifetime = elided lifetime has a name .label_elided = this elided lifetime gets resolved as `{$name}` .label_named = lifetime `{$name}` declared here - -lint_elided_named_lifetime_suggestion = consider specifying it explicitly + .suggestion = consider specifying it explicitly lint_enum_intrinsics_mem_discriminant = the return value of `mem::discriminant` is unspecified when called with a non-enum type diff --git a/compiler/rustc_lint/src/context/diagnostics.rs b/compiler/rustc_lint/src/context/diagnostics.rs index a1a371a032e90..de34b9bebe9f5 100644 --- a/compiler/rustc_lint/src/context/diagnostics.rs +++ b/compiler/rustc_lint/src/context/diagnostics.rs @@ -7,7 +7,6 @@ use rustc_ast::util::unicode::TEXT_FLOW_CONTROL_CHARS; use rustc_errors::{ elided_lifetime_in_path_suggestion, Applicability, Diag, DiagArgValue, LintDiagnostic, }; -use rustc_hir::MissingLifetimeKind; use rustc_middle::middle::stability; use rustc_session::lint::{BuiltinLintDiag, ElidedLifetimeResolution}; use rustc_session::Session; @@ -15,7 +14,6 @@ use rustc_span::symbol::kw; use rustc_span::BytePos; use tracing::debug; -use crate::fluent_generated; use crate::lints::{self, ElidedNamedLifetime}; mod check_cfg; @@ -445,31 +443,15 @@ pub(super) fn decorate_lint(sess: &Session, diagnostic: BuiltinLintDiag, diag: & lints::UnexpectedBuiltinCfg { cfg, cfg_name, controlled_by }.decorate_lint(diag) } BuiltinLintDiag::ElidedNamedLifetimes { elided: (span, kind), resolution } => { - let (name, named_declaration) = match resolution { - ElidedLifetimeResolution::Static => (kw::StaticLifetime, None), - ElidedLifetimeResolution::Param(name, declaration) => (name, Some(declaration)), - }; - ElidedNamedLifetime { span, name, named_declaration }.decorate_lint(diag); - - let (applicability, suggestion) = match kind { - MissingLifetimeKind::Underscore => { - (Applicability::MachineApplicable, format!("{name}")) + match resolution { + ElidedLifetimeResolution::Static => { + ElidedNamedLifetime { span, kind, name: kw::StaticLifetime, declaration: None } } - MissingLifetimeKind::Ampersand => { - (Applicability::MachineApplicable, format!("&{name} ")) + ElidedLifetimeResolution::Param(name, declaration) => { + ElidedNamedLifetime { span, kind, name, declaration: Some(declaration) } } - MissingLifetimeKind::Comma => (Applicability::Unspecified, format!("<{name}, ")), - MissingLifetimeKind::Brackets => ( - Applicability::Unspecified, - format!("{}<{name}>", sess.source_map().span_to_snippet(span).unwrap()), - ), - }; - diag.span_suggestion_verbose( - span, - fluent_generated::lint_elided_named_lifetime_suggestion, - suggestion, - applicability, - ); + } + .decorate_lint(diag) } } } diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index 426d671f8e0a6..693f1b2258745 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -9,7 +9,7 @@ use rustc_errors::{ }; use rustc_hir::def::Namespace; use rustc_hir::def_id::DefId; -use rustc_hir::{self as hir}; +use rustc_hir::{self as hir, MissingLifetimeKind}; use rustc_macros::{LintDiagnostic, Subdiagnostic}; use rustc_middle::ty::inhabitedness::InhabitedPredicate; use rustc_middle::ty::{Clause, PolyExistentialTraitRef, Ty, TyCtxt}; @@ -2623,14 +2623,49 @@ pub(crate) struct ElidedLifetimesInPaths { pub subdiag: ElidedLifetimeInPathSubdiag, } -#[derive(LintDiagnostic)] -#[diag(lint_elided_named_lifetime)] pub(crate) struct ElidedNamedLifetime { - #[label(lint_label_elided)] pub span: Span, + pub kind: MissingLifetimeKind, pub name: Symbol, - #[label(lint_label_named)] - pub named_declaration: Option, + pub declaration: Option, +} + +impl LintDiagnostic<'_, G> for ElidedNamedLifetime { + fn decorate_lint(self, diag: &mut rustc_errors::Diag<'_, G>) { + let Self { span, kind, name, declaration } = self; + diag.primary_message(fluent::lint_elided_named_lifetime); + diag.arg("name", name); + diag.span_label(span, fluent::lint_label_elided); + if let Some(declaration) = declaration { + diag.span_label(declaration, fluent::lint_label_named); + } + match kind { + MissingLifetimeKind::Underscore => diag.span_suggestion_verbose( + span, + fluent::lint_suggestion, + format!("{name}"), + Applicability::MachineApplicable, + ), + MissingLifetimeKind::Ampersand => diag.span_suggestion_verbose( + span.shrink_to_hi(), + fluent::lint_suggestion, + format!("{name} "), + Applicability::MachineApplicable, + ), + MissingLifetimeKind::Comma => diag.span_suggestion_verbose( + span.shrink_to_hi(), + fluent::lint_suggestion, + format!("{name}, "), + Applicability::MachineApplicable, + ), + MissingLifetimeKind::Brackets => diag.span_suggestion_verbose( + span.shrink_to_hi(), + fluent::lint_suggestion, + format!("<{name}>"), + Applicability::MachineApplicable, + ), + }; + } } #[derive(LintDiagnostic)] diff --git a/tests/ui/async-await/issues/issue-63388-1.stderr b/tests/ui/async-await/issues/issue-63388-1.stderr index c8b55977faf3a..713e4e4dcf5ca 100644 --- a/tests/ui/async-await/issues/issue-63388-1.stderr +++ b/tests/ui/async-await/issues/issue-63388-1.stderr @@ -11,7 +11,7 @@ LL | ) -> &dyn Foo help: consider specifying it explicitly | LL | ) -> &'a dyn Foo - | ~~~ + | ++ error[E0621]: explicit lifetime required in the type of `foo` --> $DIR/issue-63388-1.rs:13:5 diff --git a/tests/ui/const-generics/type-dependent/issue-71348.full.stderr b/tests/ui/const-generics/type-dependent/issue-71348.full.stderr index 8d1c1ea23a81c..394259ce55ddb 100644 --- a/tests/ui/const-generics/type-dependent/issue-71348.full.stderr +++ b/tests/ui/const-generics/type-dependent/issue-71348.full.stderr @@ -8,7 +8,7 @@ LL | fn ask<'a, const N: &'static str>(&'a self) -> &'a >::Ta help: consider specifying it explicitly | LL | fn ask<'a, const N: &'static str>(&'a self) -> &'a >::Target - | ~~~~ + | +++ warning: 1 warning emitted diff --git a/tests/ui/const-generics/type-dependent/issue-71348.min.stderr b/tests/ui/const-generics/type-dependent/issue-71348.min.stderr index 57da3ce21cecd..0f0d75dbac13e 100644 --- a/tests/ui/const-generics/type-dependent/issue-71348.min.stderr +++ b/tests/ui/const-generics/type-dependent/issue-71348.min.stderr @@ -8,7 +8,7 @@ LL | fn ask<'a, const N: &'static str>(&'a self) -> &'a >::Ta help: consider specifying it explicitly | LL | fn ask<'a, const N: &'static str>(&'a self) -> &'a >::Target - | ~~~~ + | +++ error: `&'static str` is forbidden as the type of a const generic parameter --> $DIR/issue-71348.rs:10:24 diff --git a/tests/ui/consts/min_const_fn/min_const_fn.stderr b/tests/ui/consts/min_const_fn/min_const_fn.stderr index b7db403ad16b2..1e88a908af083 100644 --- a/tests/ui/consts/min_const_fn/min_const_fn.stderr +++ b/tests/ui/consts/min_const_fn/min_const_fn.stderr @@ -11,7 +11,7 @@ LL | const fn get_lt(&'a self) -> &T { &self.0 } help: consider specifying it explicitly | LL | const fn get_lt(&'a self) -> &'a T { &self.0 } - | ~~~ + | ++ warning: elided lifetime has a name --> $DIR/min_const_fn.rs:48:42 @@ -25,7 +25,7 @@ LL | const fn get_mut_lt(&'a mut self) -> &mut T { &mut self.0 } help: consider specifying it explicitly | LL | const fn get_mut_lt(&'a mut self) -> &'a mut T { &mut self.0 } - | ~~~ + | ++ error[E0493]: destructor of `Foo` cannot be evaluated at compile-time --> $DIR/min_const_fn.rs:37:25 diff --git a/tests/ui/impl-trait/rpit-assoc-pair-with-lifetime.stderr b/tests/ui/impl-trait/rpit-assoc-pair-with-lifetime.stderr index ec0f0708b156f..6eea25b4fc8f8 100644 --- a/tests/ui/impl-trait/rpit-assoc-pair-with-lifetime.stderr +++ b/tests/ui/impl-trait/rpit-assoc-pair-with-lifetime.stderr @@ -8,7 +8,7 @@ LL | pub fn iter<'a>(v: Vec<(u32, &'a u32)>) -> impl DoubleEndedIterator(v: Vec<(u32, &'a u32)>) -> impl DoubleEndedIterator { - | ~~~ + | ++ warning: 1 warning emitted diff --git a/tests/ui/lifetimes/lifetime-elision-return-type-requires-explicit-lifetime.stderr b/tests/ui/lifetimes/lifetime-elision-return-type-requires-explicit-lifetime.stderr index a7512158661fb..1339c644f5339 100644 --- a/tests/ui/lifetimes/lifetime-elision-return-type-requires-explicit-lifetime.stderr +++ b/tests/ui/lifetimes/lifetime-elision-return-type-requires-explicit-lifetime.stderr @@ -117,7 +117,7 @@ LL | fn m<'a>(_: &'a Foo<'a>) -> &str { "" } help: consider specifying it explicitly | LL | fn m<'a>(_: &'a Foo<'a>) -> &'a str { "" } - | ~~~ + | ++ error: aborting due to 7 previous errors; 1 warning emitted diff --git a/tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-3.stderr b/tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-3.stderr index 0943e0cc0d9d4..144f9454513c5 100644 --- a/tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-3.stderr +++ b/tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-3.stderr @@ -10,7 +10,7 @@ LL | fn foo<'a>(&'a self, x: &i32) -> &i32 { help: consider specifying it explicitly | LL | fn foo<'a>(&'a self, x: &i32) -> &'a i32 { - | ~~~ + | ++ error[E0621]: explicit lifetime required in the type of `x` --> $DIR/ex1-return-one-existing-name-if-else-using-impl-3.rs:9:36 diff --git a/tests/ui/lint/elided-named-lifetimes/example-from-issue48686.stderr b/tests/ui/lint/elided-named-lifetimes/example-from-issue48686.stderr index 5af5123c03237..2d8c6e996439d 100644 --- a/tests/ui/lint/elided-named-lifetimes/example-from-issue48686.stderr +++ b/tests/ui/lint/elided-named-lifetimes/example-from-issue48686.stderr @@ -12,7 +12,7 @@ LL | #![deny(elided_named_lifetimes)] help: consider specifying it explicitly | LL | pub fn get_mut(&'static self, x: &mut u8) -> &'static mut u8 { - | ~~~~~~~~ + | +++++++ error: aborting due to 1 previous error diff --git a/tests/ui/lint/elided-named-lifetimes/missing-lifetime-kind.stderr b/tests/ui/lint/elided-named-lifetimes/missing-lifetime-kind.stderr index 6abaad7f5d218..834292d103dc8 100644 --- a/tests/ui/lint/elided-named-lifetimes/missing-lifetime-kind.stderr +++ b/tests/ui/lint/elided-named-lifetimes/missing-lifetime-kind.stderr @@ -14,7 +14,7 @@ LL | #![deny(elided_named_lifetimes)] help: consider specifying it explicitly | LL | fn ampersand<'a>(x: &'a u8) -> &'a u8 { - | ~~~ + | ++ error: elided lifetime has a name --> $DIR/missing-lifetime-kind.rs:10:31 @@ -27,7 +27,7 @@ LL | fn brackets<'a>(x: &'a u8) -> Brackets { help: consider specifying it explicitly | LL | fn brackets<'a>(x: &'a u8) -> Brackets<'a> { - | ~~~~~~~~~~~~ + | ++++ error: elided lifetime has a name --> $DIR/missing-lifetime-kind.rs:17:33 @@ -40,7 +40,7 @@ LL | fn comma<'a>(x: &'a u8) -> Comma { help: consider specifying it explicitly | LL | fn comma<'a>(x: &'a u8) -> Comma<'a, u8> { - | ~~~~ + | +++ error: elided lifetime has a name --> $DIR/missing-lifetime-kind.rs:22:34 diff --git a/tests/ui/lint/elided-named-lifetimes/not-tied-to-crate.stderr b/tests/ui/lint/elided-named-lifetimes/not-tied-to-crate.stderr index cbc1b862caabd..3c01375d50191 100644 --- a/tests/ui/lint/elided-named-lifetimes/not-tied-to-crate.stderr +++ b/tests/ui/lint/elided-named-lifetimes/not-tied-to-crate.stderr @@ -12,7 +12,7 @@ LL | #[warn(elided_named_lifetimes)] help: consider specifying it explicitly | LL | fn bar(x: &'static u8) -> &'static u8 { - | ~~~~~~~~ + | +++++++ error: elided lifetime has a name --> $DIR/not-tied-to-crate.rs:11:31 @@ -28,7 +28,7 @@ LL | #[deny(elided_named_lifetimes)] help: consider specifying it explicitly | LL | fn baz(x: &'static u8) -> &'static u8 { - | ~~~~~~~~ + | +++++++ error: aborting due to 1 previous error; 1 warning emitted diff --git a/tests/ui/lint/elided-named-lifetimes/static.stderr b/tests/ui/lint/elided-named-lifetimes/static.stderr index 6c3944e5ea580..fa2a2d3460fea 100644 --- a/tests/ui/lint/elided-named-lifetimes/static.stderr +++ b/tests/ui/lint/elided-named-lifetimes/static.stderr @@ -12,7 +12,7 @@ LL | #![deny(elided_named_lifetimes)] help: consider specifying it explicitly | LL | fn ampersand(x: &'static u8) -> &'static u8 { - | ~~~~~~~~ + | +++++++ error: elided lifetime has a name --> $DIR/static.rs:23:32 @@ -23,7 +23,7 @@ LL | fn brackets(x: &'static u8) -> Brackets { help: consider specifying it explicitly | LL | fn brackets(x: &'static u8) -> Brackets<'static> { - | ~~~~~~~~~~~~~~~~~ + | +++++++++ error: elided lifetime has a name --> $DIR/static.rs:30:34 @@ -34,7 +34,7 @@ LL | fn comma(x: &'static u8) -> Comma { help: consider specifying it explicitly | LL | fn comma(x: &'static u8) -> Comma<'static, u8> { - | ~~~~~~~~~ + | ++++++++ error: elided lifetime has a name --> $DIR/static.rs:35:35 diff --git a/tests/ui/object-lifetime/object-lifetime-default-elision.stderr b/tests/ui/object-lifetime/object-lifetime-default-elision.stderr index 7d239a54eda4f..f8ed92111a967 100644 --- a/tests/ui/object-lifetime/object-lifetime-default-elision.stderr +++ b/tests/ui/object-lifetime/object-lifetime-default-elision.stderr @@ -10,7 +10,7 @@ LL | fn load2<'a>(ss: &'a dyn SomeTrait) -> &dyn SomeTrait { help: consider specifying it explicitly | LL | fn load2<'a>(ss: &'a dyn SomeTrait) -> &'a dyn SomeTrait { - | ~~~ + | ++ error: lifetime may not live long enough --> $DIR/object-lifetime-default-elision.rs:73:5 diff --git a/tests/ui/self/elision/ignore-non-reference-lifetimes.stderr b/tests/ui/self/elision/ignore-non-reference-lifetimes.stderr index 460d2ce2cc907..13cc3a431a5d2 100644 --- a/tests/ui/self/elision/ignore-non-reference-lifetimes.stderr +++ b/tests/ui/self/elision/ignore-non-reference-lifetimes.stderr @@ -8,7 +8,7 @@ LL | fn a<'a>(self: Self, a: &'a str) -> &str { help: consider specifying it explicitly | LL | fn a<'a>(self: Self, a: &'a str) -> &'a str { - | ~~~ + | ++ warning: elided lifetime has a name --> $DIR/ignore-non-reference-lifetimes.rs:10:44 @@ -19,7 +19,7 @@ LL | fn b<'a>(self: Foo<'b>, a: &'a str) -> &str { help: consider specifying it explicitly | LL | fn b<'a>(self: Foo<'b>, a: &'a str) -> &'a str { - | ~~~ + | ++ warning: 2 warnings emitted diff --git a/tests/ui/self/self_lifetime-async.stderr b/tests/ui/self/self_lifetime-async.stderr index fd167cf392fb6..2892d790ac7b8 100644 --- a/tests/ui/self/self_lifetime-async.stderr +++ b/tests/ui/self/self_lifetime-async.stderr @@ -10,7 +10,7 @@ LL | async fn foo<'b>(self: &'b Foo<'a>) -> &() { self.0 } help: consider specifying it explicitly | LL | async fn foo<'b>(self: &'b Foo<'a>) -> &'b () { self.0 } - | ~~~ + | ++ warning: elided lifetime has a name --> $DIR/self_lifetime-async.rs:12:52 @@ -21,7 +21,7 @@ LL | async fn bar<'a>(self: &Alias, arg: &'a ()) -> &() { arg } help: consider specifying it explicitly | LL | async fn bar<'a>(self: &Alias, arg: &'a ()) -> &'a () { arg } - | ~~~ + | ++ warning: 2 warnings emitted diff --git a/tests/ui/self/self_lifetime.stderr b/tests/ui/self/self_lifetime.stderr index 52189084f04c0..ceb0ce345a3eb 100644 --- a/tests/ui/self/self_lifetime.stderr +++ b/tests/ui/self/self_lifetime.stderr @@ -10,7 +10,7 @@ LL | fn foo<'b>(self: &'b Foo<'a>) -> &() { self.0 } help: consider specifying it explicitly | LL | fn foo<'b>(self: &'b Foo<'a>) -> &'b () { self.0 } - | ~~~ + | ++ warning: elided lifetime has a name --> $DIR/self_lifetime.rs:13:46 @@ -21,7 +21,7 @@ LL | fn bar<'a>(self: &Alias, arg: &'a ()) -> &() { arg } help: consider specifying it explicitly | LL | fn bar<'a>(self: &Alias, arg: &'a ()) -> &'a () { arg } - | ~~~ + | ++ warning: 2 warnings emitted diff --git a/tests/ui/suggestions/impl-trait-missing-lifetime-gated.stderr b/tests/ui/suggestions/impl-trait-missing-lifetime-gated.stderr index 92f774767c863..3744dd9f996ce 100644 --- a/tests/ui/suggestions/impl-trait-missing-lifetime-gated.stderr +++ b/tests/ui/suggestions/impl-trait-missing-lifetime-gated.stderr @@ -134,7 +134,7 @@ LL | fn resolved_anonymous<'a, T: 'a>(f: impl Fn(&'a str) -> &T) { help: consider specifying it explicitly | LL | fn resolved_anonymous<'a, T: 'a>(f: impl Fn(&'a str) -> &'a T) { - | ~~~ + | ++ error[E0658]: anonymous lifetimes in `impl Trait` are unstable --> $DIR/impl-trait-missing-lifetime-gated.rs:6:35 diff --git a/tests/ui/type-alias-impl-trait/missing_lifetime_bound.stderr b/tests/ui/type-alias-impl-trait/missing_lifetime_bound.stderr index 73a362d28e7d7..376e58ef9e07e 100644 --- a/tests/ui/type-alias-impl-trait/missing_lifetime_bound.stderr +++ b/tests/ui/type-alias-impl-trait/missing_lifetime_bound.stderr @@ -10,7 +10,7 @@ LL | fn defining<'a, T>(x: &'a i32) -> Opaque { x } help: consider specifying it explicitly | LL | fn defining<'a, T>(x: &'a i32) -> Opaque<'a, T> { x } - | ~~~~ + | +++ error[E0700]: hidden type for `Opaque2` captures lifetime that does not appear in bounds --> $DIR/missing_lifetime_bound.rs:5:47 From 9028177115718b38c0a189c4fb9eda03a14841d7 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 22 May 2024 21:00:12 +0200 Subject: [PATCH 0581/2194] Add GCC submodule --- .gitmodules | 3 +++ src/gcc | 1 + 2 files changed, 4 insertions(+) create mode 160000 src/gcc diff --git a/.gitmodules b/.gitmodules index 926807336d791..b47b0e9e62107 100644 --- a/.gitmodules +++ b/.gitmodules @@ -51,3 +51,6 @@ path = src/tools/enzyme url = https://github.com/EnzymeAD/Enzyme.git shallow = true +[submodule "src/gcc"] + path = src/gcc + url = https://github.com/rust-lang/gcc.git diff --git a/src/gcc b/src/gcc new file mode 160000 index 0000000000000..272d0ccced960 --- /dev/null +++ b/src/gcc @@ -0,0 +1 @@ +Subproject commit 272d0ccced960394fe6ff2b40b01610208cb4940 From 30feef626fc8a82c645d561d9ffd208f21e75ca8 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 22 May 2024 21:00:30 +0200 Subject: [PATCH 0582/2194] Add libgccjit dist generation --- src/bootstrap/src/core/build_steps/dist.rs | 10 + src/bootstrap/src/core/build_steps/gcc.rs | 226 +++++++++++++++++++++ src/bootstrap/src/core/build_steps/llvm.rs | 14 +- src/bootstrap/src/core/build_steps/mod.rs | 1 + src/bootstrap/src/lib.rs | 4 + 5 files changed, 248 insertions(+), 7 deletions(-) create mode 100644 src/bootstrap/src/core/build_steps/gcc.rs diff --git a/src/bootstrap/src/core/build_steps/dist.rs b/src/bootstrap/src/core/build_steps/dist.rs index 4957de2e1b791..2928f169b1a09 100644 --- a/src/bootstrap/src/core/build_steps/dist.rs +++ b/src/bootstrap/src/core/build_steps/dist.rs @@ -2273,6 +2273,7 @@ impl Step for RustDev { tarball.permit_symlinks(true); builder.ensure(crate::core::build_steps::llvm::Llvm { target }); + builder.ensure(crate::core::build_steps::gcc::Gcc { target }); let src_bindir = builder.llvm_out(target).join("bin"); // If updating this, you likely want to change @@ -2308,6 +2309,15 @@ impl Step for RustDev { // just broadly useful to be able to link against the bundled LLVM. tarball.add_dir(builder.llvm_out(target).join("include"), "include"); + let libgccjit_path = builder.gcc_out(target).join("install/lib/libgccjit.so"); + if libgccjit_path.exists() { + tarball.add_dir(libgccjit_path, "libgccjit.so"); + tarball.add_dir( + builder.gcc_out(target).join("install/lib/libgccjit.so.0"), + "libgccjit.so.0", + ); + } + // Copy libLLVM.so to the target lib dir as well, so the RPATH like // `$ORIGIN/../lib` can find it. It may also be used as a dependency // of `rustc-dev` to support the inherited `-lLLVM` when using the diff --git a/src/bootstrap/src/core/build_steps/gcc.rs b/src/bootstrap/src/core/build_steps/gcc.rs new file mode 100644 index 0000000000000..c11782c5b14be --- /dev/null +++ b/src/bootstrap/src/core/build_steps/gcc.rs @@ -0,0 +1,226 @@ +//! Compilation of native dependencies like LLVM. +//! +//! Native projects like LLVM unfortunately aren't suited just yet for +//! compilation in build scripts that Cargo has. This is because the +//! compilation takes a *very* long time but also because we don't want to +//! compile LLVM 3 times as part of a normal bootstrap (we want it cached). +//! +//! LLVM and compiler-rt are essentially just wired up to everything else to +//! ensure that they're always in place if needed. + +use std::fs; +use std::path::{Path, PathBuf}; +use std::sync::OnceLock; + +use crate::core::builder::{Builder, RunConfig, ShouldRun, Step}; +use crate::core::config::TargetSelection; +use crate::utils::exec::command; +use crate::utils::helpers::{self, t}; +use crate::{generate_smart_stamp_hash, Kind}; + +use super::llvm::HashStamp; + +pub struct Meta { + stamp: HashStamp, + out_dir: PathBuf, + install_dir: PathBuf, + root: PathBuf, +} + +pub enum GccBuildStatus { + AlreadyBuilt, + ShouldBuild(Meta), +} + +/// This returns whether we've already previously built GCC. +/// +/// It's used to avoid busting caches during x.py check -- if we've already built +/// GCC, it's fine for us to not try to avoid doing so. +pub fn prebuilt_gcc_config(builder: &Builder<'_>, target: TargetSelection) -> GccBuildStatus { + // If we have gcc submodule initialized already, sync it. + builder.update_existing_submodule(&Path::new("src").join("gcc")); + + // FIXME (GuillaumeGomez): To be done once gccjit has been built in the CI. + // builder.config.maybe_download_ci_gcc(); + + // Initialize the llvm submodule if not initialized already. + builder.update_submodule(&Path::new("src").join("gcc")); + + let root = "src/gcc"; + let out_dir = builder.gcc_out(target).join("build"); + let install_dir = builder.gcc_out(target).join("install"); + + static STAMP_HASH_MEMO: OnceLock = OnceLock::new(); + let smart_stamp_hash = STAMP_HASH_MEMO.get_or_init(|| { + generate_smart_stamp_hash( + &builder.config.src.join("src/llvm-project"), + builder.in_tree_llvm_info.sha().unwrap_or_default(), + ) + }); + + let stamp = out_dir.join("gcc-finished-building"); + let stamp = HashStamp::new(stamp, Some(smart_stamp_hash)); + + if stamp.is_done() { + if stamp.hash.is_none() { + builder.info( + "Could not determine the GCC submodule commit hash. \ + Assuming that an GCC rebuild is not necessary.", + ); + builder.info(&format!( + "To force GCC to rebuild, remove the file `{}`", + stamp.path.display() + )); + } + return GccBuildStatus::AlreadyBuilt; + } + + GccBuildStatus::ShouldBuild(Meta { stamp, out_dir, install_dir, root: root.into() }) +} + +// FIXME (GuillaumeGomez): When gcc-ci-download option is added, uncomment this code. +// /// This retrieves the GCC sha we *want* to use, according to git history. +// pub(crate) fn detect_gcc_sha(config: &Config, is_git: bool) -> String { +// let gcc_sha = if is_git { +// // We proceed in 2 steps. First we get the closest commit that is actually upstream. Then we +// // walk back further to the last bors merge commit that actually changed GCC. The first +// // step will fail on CI because only the `auto` branch exists; we just fall back to `HEAD` +// // in that case. +// let closest_upstream = get_git_merge_base(&config.git_config(), Some(&config.src)) +// .unwrap_or_else(|_| "HEAD".into()); +// let mut rev_list = config.git(); +// rev_list.args(&[ +// PathBuf::from("rev-list"), +// format!("--author={}", config.stage0_metadata.config.git_merge_commit_email).into(), +// "-n1".into(), +// "--first-parent".into(), +// closest_upstream.into(), +// "--".into(), +// config.src.join("src/gcc"), +// config.src.join("src/bootstrap/download-ci-gcc-stamp"), +// // the GCC shared object file is named `gcc-12-rust-{version}-nightly` +// config.src.join("src/version"), +// ]); +// output(&mut rev_list).trim().to_owned() +// } else if let Some(info) = channel::read_commit_info_file(&config.src) { +// info.sha.trim().to_owned() +// } else { +// "".to_owned() +// }; + +// if gcc_sha.is_empty() { +// eprintln!("error: could not find commit hash for downloading LLVM"); +// eprintln!("HELP: maybe your repository history is too shallow?"); +// eprintln!("HELP: consider disabling `download-ci-gcc`"); +// eprintln!("HELP: or fetch enough history to include one upstream commit"); +// panic!(); +// } + +// gcc_sha +// } + +// /// Returns whether the CI-found GCC is currently usable. +// /// +// /// This checks both the build triple platform to confirm we're usable at all, +// /// and then verifies if the current HEAD matches the detected GCC SHA head, +// /// in which case GCC is indicated as not available. +// pub(crate) fn is_ci_gcc_available(config: &Config, asserts: bool) -> bool { +// // This is currently all tier 1 targets and tier 2 targets with host tools +// // (since others may not have CI artifacts) +// // https://doc.rust-lang.org/rustc/platform-support.html#tier-1 +// let supported_platforms = [ +// // tier 1 +// ("x86_64-unknown-linux-gnu", true), +// ]; + +// if !supported_platforms.contains(&(&*config.build.triple, asserts)) +// && (asserts || !supported_platforms.contains(&(&*config.build.triple, true))) +// { +// return false; +// } + +// if is_ci_gcc_modified(config) { +// eprintln!("Detected GCC as non-available: running in CI and modified GCC in this change"); +// return false; +// } + +// true +// } + +// /// Returns true if we're running in CI with modified GCC (and thus can't download it) +// pub(crate) fn is_ci_gcc_modified(config: &Config) -> bool { +// CiEnv::is_ci() && config.rust_info.is_managed_git_subrepository() && { +// // We assume we have access to git, so it's okay to unconditionally pass +// // `true` here. +// let gcc_sha = detect_gcc_sha(config, true); +// let head_sha = output(config.git().arg("rev-parse").arg("HEAD")); +// let head_sha = head_sha.trim(); +// gcc_sha == head_sha +// } +// } + +#[derive(Debug, Clone, Hash, PartialEq, Eq)] +pub struct Gcc { + pub target: TargetSelection, +} + +impl Step for Gcc { + type Output = bool; + + const ONLY_HOSTS: bool = true; + + fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { + run.path("src/gcc") + } + + fn make_run(run: RunConfig<'_>) { + run.builder.ensure(Gcc { target: run.target }); + } + + /// Compile GCC for `target`. + fn run(self, builder: &Builder<'_>) -> bool { + let target = self.target; + if !target.contains("linux") || !target.contains("x86_64") { + return false; + } + + // If GCC has already been built or been downloaded through download-ci-gcc, we avoid + // building it again. + let Meta { stamp, out_dir, install_dir, root } = match prebuilt_gcc_config(builder, target) + { + GccBuildStatus::AlreadyBuilt => return true, + GccBuildStatus::ShouldBuild(m) => m, + }; + + let _guard = builder.msg_unstaged(Kind::Build, "GCC", target); + t!(stamp.remove()); + let _time = helpers::timeit(builder); + t!(fs::create_dir_all(&out_dir)); + + if builder.config.dry_run() { + return true; + } + + builder.run( + command(root.join("configure")) + .current_dir(&out_dir) + .arg("--enable-host-shared") + .arg("--enable-languages=jit") + .arg("--enable-checking=release") + .arg("--disable-bootstrap") + .arg("--disable-multilib") + .arg(format!("--prefix={}", install_dir.display())), + ); + builder.run(command("make").current_dir(&out_dir).arg(format!("-j{}", builder.jobs()))); + builder.run(command("make").current_dir(&out_dir).arg("install")); + + t!(builder.symlink_file( + install_dir.join("lib/libgccjit.so"), + install_dir.join("lib/libgccjit.so.0") + )); + + t!(stamp.write()); + + true + } +} diff --git a/src/bootstrap/src/core/build_steps/llvm.rs b/src/bootstrap/src/core/build_steps/llvm.rs index 442638d32034b..d729952adcebf 100644 --- a/src/bootstrap/src/core/build_steps/llvm.rs +++ b/src/bootstrap/src/core/build_steps/llvm.rs @@ -1242,17 +1242,17 @@ fn supported_sanitizers( } } -struct HashStamp { - path: PathBuf, - hash: Option>, +pub(super) struct HashStamp { + pub(super) path: PathBuf, + pub(super) hash: Option>, } impl HashStamp { - fn new(path: PathBuf, hash: Option<&str>) -> Self { + pub(super) fn new(path: PathBuf, hash: Option<&str>) -> Self { HashStamp { path, hash: hash.map(|s| s.as_bytes().to_owned()) } } - fn is_done(&self) -> bool { + pub(super) fn is_done(&self) -> bool { match fs::read(&self.path) { Ok(h) => self.hash.as_deref().unwrap_or(b"") == h.as_slice(), Err(e) if e.kind() == io::ErrorKind::NotFound => false, @@ -1262,7 +1262,7 @@ impl HashStamp { } } - fn remove(&self) -> io::Result<()> { + pub(super) fn remove(&self) -> io::Result<()> { match fs::remove_file(&self.path) { Ok(()) => Ok(()), Err(e) => { @@ -1275,7 +1275,7 @@ impl HashStamp { } } - fn write(&self) -> io::Result<()> { + pub(super) fn write(&self) -> io::Result<()> { fs::write(&self.path, self.hash.as_deref().unwrap_or(b"")) } } diff --git a/src/bootstrap/src/core/build_steps/mod.rs b/src/bootstrap/src/core/build_steps/mod.rs index 004174e35e1d1..fcb6abea43472 100644 --- a/src/bootstrap/src/core/build_steps/mod.rs +++ b/src/bootstrap/src/core/build_steps/mod.rs @@ -5,6 +5,7 @@ pub(crate) mod compile; pub(crate) mod dist; pub(crate) mod doc; pub(crate) mod format; +pub(crate) mod gcc; pub(crate) mod install; pub(crate) mod llvm; pub(crate) mod perf; diff --git a/src/bootstrap/src/lib.rs b/src/bootstrap/src/lib.rs index c76ce3409562e..4ae7851166963 100644 --- a/src/bootstrap/src/lib.rs +++ b/src/bootstrap/src/lib.rs @@ -765,6 +765,10 @@ impl Build { self.out.join(&*target.triple).join("enzyme") } + fn gcc_out(&self, target: TargetSelection) -> PathBuf { + self.out.join(&*target.triple).join("gcc") + } + fn lld_out(&self, target: TargetSelection) -> PathBuf { self.out.join(target).join("lld") } From 71fe24824006ba9ffc54f8e166c53a90721ecebb Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Thu, 23 May 2024 10:53:04 +0200 Subject: [PATCH 0583/2194] Ignore gcc submodule for tidy checks --- src/tools/tidy/config/black.toml | 3 ++- src/tools/tidy/config/ruff.toml | 2 ++ src/tools/tidy/src/walk.rs | 1 + 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/tools/tidy/config/black.toml b/src/tools/tidy/config/black.toml index a1e1eef987a5f..d5b8b198afb3f 100644 --- a/src/tools/tidy/config/black.toml +++ b/src/tools/tidy/config/black.toml @@ -13,5 +13,6 @@ extend-exclude = """(\ src/doc/embedded-book/|\ src/tools/rustc-perf/|\ src/tools/enzyme/|\ - library/backtrace/ + library/backtrace/|\ + src/gcc/ )""" diff --git a/src/tools/tidy/config/ruff.toml b/src/tools/tidy/config/ruff.toml index 2be109010a062..de23d93593c13 100644 --- a/src/tools/tidy/config/ruff.toml +++ b/src/tools/tidy/config/ruff.toml @@ -18,6 +18,7 @@ extend-exclude = [ "library/backtrace/", "src/tools/enzyme/", "src/tools/rustc-perf/", + "src/gcc/", # Hack: CI runs from a subdirectory under the main checkout "../src/doc/nomicon/", "../src/tools/cargo/", @@ -32,6 +33,7 @@ extend-exclude = [ "../library/backtrace/", "../src/tools/enzyme/", "../src/tools/rustc-perf/", + "../src/gcc/", ] [lint] diff --git a/src/tools/tidy/src/walk.rs b/src/tools/tidy/src/walk.rs index 4a69022ebdc58..8cbc263689b89 100644 --- a/src/tools/tidy/src/walk.rs +++ b/src/tools/tidy/src/walk.rs @@ -32,6 +32,7 @@ pub fn filter_dirs(path: &Path) -> bool { "src/doc/rust-by-example", "src/doc/rustc-dev-guide", "src/doc/reference", + "src/gcc", // Filter RLS output directories "target/rls", "src/bootstrap/target", From eda4287fd6d4755fe9b96e76da6d39d09cf479cc Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Thu, 23 May 2024 14:53:28 +0200 Subject: [PATCH 0584/2194] Add missing licenses for GCC --- LICENSES/GCC-exception-3.1.txt | 30 +++++ LICENSES/GPL-2.0.txt | 133 ++++++++++++++++++++++ LICENSES/GPL-3.0-or-later.txt | 202 +++++++++++++++++++++++++++++++++ LICENSES/ISC.txt | 7 ++ 4 files changed, 372 insertions(+) create mode 100644 LICENSES/GCC-exception-3.1.txt create mode 100644 LICENSES/GPL-2.0.txt create mode 100644 LICENSES/GPL-3.0-or-later.txt create mode 100644 LICENSES/ISC.txt diff --git a/LICENSES/GCC-exception-3.1.txt b/LICENSES/GCC-exception-3.1.txt new file mode 100644 index 0000000000000..eecede4d0707e --- /dev/null +++ b/LICENSES/GCC-exception-3.1.txt @@ -0,0 +1,30 @@ +GCC RUNTIME LIBRARY EXCEPTION + +Version 3.1, 31 March 2009 + +Copyright © 2009 Free Software Foundation, Inc. + +Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. + +This GCC Runtime Library Exception ("Exception") is an additional permission under section 7 of the GNU General Public License, version 3 ("GPLv3"). It applies to a given file (the "Runtime Library") that bears a notice placed by the copyright holder of the file stating that the file is governed by GPLv3 along with this Exception. + +When you use GCC to compile a program, GCC may combine portions of certain GCC header files and runtime libraries with the compiled program. The purpose of this Exception is to allow compilation of non-GPL (including proprietary) programs to use, in this way, the header files and runtime libraries covered by this Exception. +0. Definitions. + +A file is an "Independent Module" if it either requires the Runtime Library for execution after a Compilation Process, or makes use of an interface provided by the Runtime Library, but is not otherwise based on the Runtime Library. + +"GCC" means a version of the GNU Compiler Collection, with or without modifications, governed by version 3 (or a specified later version) of the GNU General Public License (GPL) with the option of using any subsequent versions published by the FSF. + +"GPL-compatible Software" is software whose conditions of propagation, modification and use would permit combination with GCC in accord with the license of GCC. + +"Target Code" refers to output from any compiler for a real or virtual target processor architecture, in executable form or suitable for input to an assembler, loader, linker and/or execution phase. Notwithstanding that, Target Code does not include data in any format that is used as a compiler intermediate representation, or used for producing a compiler intermediate representation. + +The "Compilation Process" transforms code entirely represented in non-intermediate languages designed for human-written code, and/or in Java Virtual Machine byte code, into Target Code. Thus, for example, use of source code generators and preprocessors need not be considered part of the Compilation Process, since the Compilation Process can be understood as starting with the output of the generators or preprocessors. + +A Compilation Process is "Eligible" if it is done using GCC, alone or with other GPL-compatible software, or if it is done without using any work based on GCC. For example, using non-GPL-compatible Software to optimize any GCC intermediate representations would not qualify as an Eligible Compilation Process. +1. Grant of Additional Permission. + +You have permission to propagate a work of Target Code formed by combining the Runtime Library with Independent Modules, even if such propagation would otherwise violate the terms of GPLv3, provided that all Target Code was generated by Eligible Compilation Processes. You may then convey such a combination under terms of your choice, consistent with the licensing of the Independent Modules. +2. No Weakening of GCC Copyleft. + +The availability of this Exception does not imply any general presumption that third-party software is unaffected by the copyleft requirements of the license of GCC. diff --git a/LICENSES/GPL-2.0.txt b/LICENSES/GPL-2.0.txt new file mode 100644 index 0000000000000..492485e09b411 --- /dev/null +++ b/LICENSES/GPL-2.0.txt @@ -0,0 +1,133 @@ +GNU GENERAL PUBLIC LICENSE + +Version 2, June 1991 + +Copyright (C) 1989, 1991 Free Software Foundation, Inc. +51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + +Everyone is permitted to copy and distribute verbatim copies +of this license document, but changing it is not allowed. + +Preamble + +The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Lesser General Public License instead.) You can apply it to your programs, too. + +When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. + +To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. + +For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. + +We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. + +Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. + +Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. + +The precise terms and conditions for copying, distribution and modification follow. +TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + +0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. + +1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. + +You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. + +2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. + b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. + c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. + +3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, + b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, + c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. + +If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. + +4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. + +5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. + +6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. + +7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. + +This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. + +8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. + +9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. + +10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. + +NO WARRANTY + +11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + +12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. +END OF TERMS AND CONDITIONS +How to Apply These Terms to Your New Programs + +If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. + +To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. + +one line to give the program's name and an idea of what it does. +Copyright (C) yyyy name of author + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this when it starts in an interactive mode: + +Gnomovision version 69, Copyright (C) year name of author +Gnomovision comes with ABSOLUTELY NO WARRANTY; for details +type `show w'. This is free software, and you are welcome +to redistribute it under certain conditions; type `show c' +for details. + +The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: + +Yoyodyne, Inc., hereby disclaims all copyright +interest in the program `Gnomovision' +(which makes passes at compilers) written +by James Hacker. + +signature of Ty Coon, 1 April 1989 +Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. diff --git a/LICENSES/GPL-3.0-or-later.txt b/LICENSES/GPL-3.0-or-later.txt new file mode 100644 index 0000000000000..37b6b8e91b85e --- /dev/null +++ b/LICENSES/GPL-3.0-or-later.txt @@ -0,0 +1,202 @@ +GNU GENERAL PUBLIC LICENSE + +Version 3, 29 June 2007 + +Copyright © 2007 Free Software Foundation, Inc. + +Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. + +Preamble + +The GNU General Public License is a free, copyleft license for software and other kinds of works. + +The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change all versions of a program--to make sure it remains free software for all its users. We, the Free Software Foundation, use the GNU General Public License for most of our software; it applies also to any other work released this way by its authors. You can apply it to your programs, too. + +When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for them if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things. + +To protect your rights, we need to prevent others from denying you these rights or asking you to surrender the rights. Therefore, you have certain responsibilities if you distribute copies of the software, or if you modify it: responsibilities to respect the freedom of others. + +For example, if you distribute copies of such a program, whether gratis or for a fee, you must pass on to the recipients the same freedoms that you received. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. + +Developers that use the GNU GPL protect your rights with two steps: (1) assert copyright on the software, and (2) offer you this License giving you legal permission to copy, distribute and/or modify it. + +For the developers' and authors' protection, the GPL clearly explains that there is no warranty for this free software. For both users' and authors' sake, the GPL requires that modified versions be marked as changed, so that their problems will not be attributed erroneously to authors of previous versions. + +Some devices are designed to deny users access to install or run modified versions of the software inside them, although the manufacturer can do so. This is fundamentally incompatible with the aim of protecting users' freedom to change the software. The systematic pattern of such abuse occurs in the area of products for individuals to use, which is precisely where it is most unacceptable. Therefore, we have designed this version of the GPL to prohibit the practice for those products. If such problems arise substantially in other domains, we stand ready to extend this provision to those domains in future versions of the GPL, as needed to protect the freedom of users. + +Finally, every program is threatened constantly by software patents. States should not allow patents to restrict development and use of software on general-purpose computers, but in those that do, we wish to avoid the special danger that patents applied to a free program could make it effectively proprietary. To prevent this, the GPL assures that patents cannot be used to render the program non-free. + +The precise terms and conditions for copying, distribution and modification follow. + +TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this License. Each licensee is addressed as "you". "Licensees" and "recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a "modified version" of the earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based on the Program. + + To "propagate" a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion. + 1. Source Code. + The "source code" for a work means the preferred form of the work for making modifications to it. "Object code" means any non-source form of a work. + + A "Standard Interface" means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A "Major Component", in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work. + + The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source. + + The Corresponding Source for a work in source code form is that same work. + 2. Basic Permissions. + All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary. + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures. + + When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures. + 4. Conveying Verbatim Copies. + You may convey verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee. + 5. Conveying Modified Source Versions. + You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions: + a) The work must carry prominent notices stating that you modified it, and giving a relevant date. + b) The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to "keep intact all notices". + c) You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it. + d) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so. + + A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an "aggregate" if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate. + 6. Conveying Non-Source Forms. + You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways: + a) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange. + b) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge. + c) Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b. + d) Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements. + e) Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, "normally used" refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made. + + If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM). + + The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying. + 7. Additional Terms. + "Additional permissions" are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms: + a) Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or + b) Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or + c) Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or + d) Limiting the use for publicity purposes of names of licensors or authors of the material; or + e) Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or + f) Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors. + + All other non-permissive additional terms are considered "further restrictions" within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way. + 8. Termination. + You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11). + + However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice. + + Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10. + 9. Acceptance Not Required for Having Copies. + You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so. + 10. Automatic Licensing of Downstream Recipients. + Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it. + 11. Patents. + A "contributor" is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, "control" includes the right to grant patent sublicenses in a manner consistent with the requirements of this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To "grant" such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party. + + If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. "Knowingly relying" means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it. + + A patent license is "discriminatory" if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law. + 12. No Surrender of Others' Freedom. + If conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program. + 13. Use with the GNU Affero General Public License. + Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU Affero General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the special requirements of the GNU Affero General Public License, section 13, concerning interaction through a network will apply to the combination as such. + 14. Revised Versions of this License. + The Free Software Foundation may publish revised and/or new versions of the GNU General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. + + Each version is given a distinguishing version number. If the Program specifies that a certain numbered version of the GNU General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU General Public License, you may choose any version ever published by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future versions of the GNU General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program. + + Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version. + 15. Disclaimer of Warranty. + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + 16. Limitation of Liability. + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee. + +END OF TERMS AND CONDITIONS + +How to Apply These Terms to Your New Programs + +If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. + +To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively state the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. + + +Copyright (C) + +This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + +If the program does terminal interaction, make it output a short notice like this when it starts in an interactive mode: + + Copyright (C) +This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. +This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, your program's commands might be different; for a GUI interface, you would use an "about box". + +You should also get your employer (if you work as a programmer) or school, if any, to sign a "copyright disclaimer" for the program, if necessary. For more information on this, and how to apply and follow the GNU GPL, see . + +The GNU General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. But first, please read . diff --git a/LICENSES/ISC.txt b/LICENSES/ISC.txt new file mode 100644 index 0000000000000..6f41c8c63b96e --- /dev/null +++ b/LICENSES/ISC.txt @@ -0,0 +1,7 @@ +ISC License + + + +Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. From 1fd148d560a3d5ab2826c3827a4d9b4d8205ec96 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 16 Jul 2024 17:52:03 +0200 Subject: [PATCH 0585/2194] Rename `LICENSES/GPL-2.0.txt` into `LICENSES/GPL-2.0-only.txt` --- LICENSES/{GPL-2.0.txt => GPL-2.0-only.txt} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename LICENSES/{GPL-2.0.txt => GPL-2.0-only.txt} (100%) diff --git a/LICENSES/GPL-2.0.txt b/LICENSES/GPL-2.0-only.txt similarity index 100% rename from LICENSES/GPL-2.0.txt rename to LICENSES/GPL-2.0-only.txt From 3ba799227282f07c1a3aa5e23bbf0761867b0ada Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 16 Jul 2024 18:55:14 +0200 Subject: [PATCH 0586/2194] Correctly generate stamp for gcc --- src/bootstrap/src/core/build_steps/gcc.rs | 5 +++-- src/bootstrap/src/lib.rs | 3 +++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/bootstrap/src/core/build_steps/gcc.rs b/src/bootstrap/src/core/build_steps/gcc.rs index c11782c5b14be..01a7eee60a448 100644 --- a/src/bootstrap/src/core/build_steps/gcc.rs +++ b/src/bootstrap/src/core/build_steps/gcc.rs @@ -53,8 +53,9 @@ pub fn prebuilt_gcc_config(builder: &Builder<'_>, target: TargetSelection) -> Gc static STAMP_HASH_MEMO: OnceLock = OnceLock::new(); let smart_stamp_hash = STAMP_HASH_MEMO.get_or_init(|| { generate_smart_stamp_hash( - &builder.config.src.join("src/llvm-project"), - builder.in_tree_llvm_info.sha().unwrap_or_default(), + builder, + &builder.config.src.join("src/gcc"), + builder.in_tree_gcc_info.sha().unwrap_or_default(), ) }); diff --git a/src/bootstrap/src/lib.rs b/src/bootstrap/src/lib.rs index 4ae7851166963..21978153f65ea 100644 --- a/src/bootstrap/src/lib.rs +++ b/src/bootstrap/src/lib.rs @@ -145,6 +145,7 @@ pub struct Build { rustfmt_info: GitInfo, enzyme_info: GitInfo, in_tree_llvm_info: GitInfo, + in_tree_gcc_info: GitInfo, local_rebuild: bool, fail_fast: bool, doc_tests: DocTests, @@ -315,6 +316,7 @@ impl Build { // we always try to use git for LLVM builds let in_tree_llvm_info = GitInfo::new(false, &src.join("src/llvm-project")); + let in_tree_gcc_info = GitInfo::new(false, &src.join("src/gcc")); let initial_target_libdir_str = if config.dry_run() { "/dummy/lib/path/to/lib/".to_string() @@ -407,6 +409,7 @@ impl Build { rustfmt_info, enzyme_info, in_tree_llvm_info, + in_tree_gcc_info, cc: RefCell::new(HashMap::new()), cxx: RefCell::new(HashMap::new()), ar: RefCell::new(HashMap::new()), From ca52d30a75aaa7179c802bca2ae98ff2436b744f Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 16 Jul 2024 22:13:50 +0200 Subject: [PATCH 0587/2194] Remove `src/gcc` from `rustfmt` checks --- rustfmt.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/rustfmt.toml b/rustfmt.toml index 60cd03484007d..e62ab86d04e53 100644 --- a/rustfmt.toml +++ b/rustfmt.toml @@ -45,6 +45,7 @@ ignore = [ "src/tools/rust-analyzer", "src/tools/rustc-perf", "src/tools/rustfmt", + "src/gcc", # These are ignored by a standard cargo fmt run. "compiler/rustc_codegen_cranelift/scripts", From c53c3974253f78b4989378af53ff1ee6bdeccccc Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 22 Jul 2024 17:56:27 +0200 Subject: [PATCH 0588/2194] Update GCC version --- src/gcc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gcc b/src/gcc index 272d0ccced960..fd3498bff0b93 160000 --- a/src/gcc +++ b/src/gcc @@ -1 +1 @@ -Subproject commit 272d0ccced960394fe6ff2b40b01610208cb4940 +Subproject commit fd3498bff0b939dda91d56960acc33d55f2f9cdf From f5abc4204ffc1e4b82f06714f2d9a82e1b0c264e Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 22 Jul 2024 20:16:53 +0200 Subject: [PATCH 0589/2194] Update code comments to mention GCC and not LLVM --- src/bootstrap/src/core/build_steps/gcc.rs | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/src/bootstrap/src/core/build_steps/gcc.rs b/src/bootstrap/src/core/build_steps/gcc.rs index 01a7eee60a448..36896abe188f6 100644 --- a/src/bootstrap/src/core/build_steps/gcc.rs +++ b/src/bootstrap/src/core/build_steps/gcc.rs @@ -1,11 +1,11 @@ -//! Compilation of native dependencies like LLVM. +//! Compilation of native dependencies like GCC. //! -//! Native projects like LLVM unfortunately aren't suited just yet for +//! Native projects like GCC unfortunately aren't suited just yet for //! compilation in build scripts that Cargo has. This is because the //! compilation takes a *very* long time but also because we don't want to -//! compile LLVM 3 times as part of a normal bootstrap (we want it cached). +//! compile GCC 3 times as part of a normal bootstrap (we want it cached). //! -//! LLVM and compiler-rt are essentially just wired up to everything else to +//! GCC and compiler-rt are essentially just wired up to everything else to //! ensure that they're always in place if needed. use std::fs; @@ -43,7 +43,7 @@ pub fn prebuilt_gcc_config(builder: &Builder<'_>, target: TargetSelection) -> Gc // FIXME (GuillaumeGomez): To be done once gccjit has been built in the CI. // builder.config.maybe_download_ci_gcc(); - // Initialize the llvm submodule if not initialized already. + // Initialize the gcc submodule if not initialized already. builder.update_submodule(&Path::new("src").join("gcc")); let root = "src/gcc"; @@ -110,7 +110,7 @@ pub fn prebuilt_gcc_config(builder: &Builder<'_>, target: TargetSelection) -> Gc // }; // if gcc_sha.is_empty() { -// eprintln!("error: could not find commit hash for downloading LLVM"); +// eprintln!("error: could not find commit hash for downloading GCC"); // eprintln!("HELP: maybe your repository history is too shallow?"); // eprintln!("HELP: consider disabling `download-ci-gcc`"); // eprintln!("HELP: or fetch enough history to include one upstream commit"); @@ -126,9 +126,6 @@ pub fn prebuilt_gcc_config(builder: &Builder<'_>, target: TargetSelection) -> Gc // /// and then verifies if the current HEAD matches the detected GCC SHA head, // /// in which case GCC is indicated as not available. // pub(crate) fn is_ci_gcc_available(config: &Config, asserts: bool) -> bool { -// // This is currently all tier 1 targets and tier 2 targets with host tools -// // (since others may not have CI artifacts) -// // https://doc.rust-lang.org/rustc/platform-support.html#tier-1 // let supported_platforms = [ // // tier 1 // ("x86_64-unknown-linux-gnu", true), From 6db83ef8eb62e9ac1dd44e8ce31568324acad6d7 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Thu, 8 Aug 2024 17:26:37 +0200 Subject: [PATCH 0590/2194] Update to new bootstrap API --- src/bootstrap/src/core/build_steps/gcc.rs | 32 +++++++++++------------ 1 file changed, 15 insertions(+), 17 deletions(-) diff --git a/src/bootstrap/src/core/build_steps/gcc.rs b/src/bootstrap/src/core/build_steps/gcc.rs index 36896abe188f6..8c0257522c93a 100644 --- a/src/bootstrap/src/core/build_steps/gcc.rs +++ b/src/bootstrap/src/core/build_steps/gcc.rs @@ -9,17 +9,16 @@ //! ensure that they're always in place if needed. use std::fs; -use std::path::{Path, PathBuf}; +use std::path::PathBuf; use std::sync::OnceLock; +use super::llvm::HashStamp; use crate::core::builder::{Builder, RunConfig, ShouldRun, Step}; use crate::core::config::TargetSelection; use crate::utils::exec::command; use crate::utils::helpers::{self, t}; use crate::{generate_smart_stamp_hash, Kind}; -use super::llvm::HashStamp; - pub struct Meta { stamp: HashStamp, out_dir: PathBuf, @@ -38,13 +37,13 @@ pub enum GccBuildStatus { /// GCC, it's fine for us to not try to avoid doing so. pub fn prebuilt_gcc_config(builder: &Builder<'_>, target: TargetSelection) -> GccBuildStatus { // If we have gcc submodule initialized already, sync it. - builder.update_existing_submodule(&Path::new("src").join("gcc")); + builder.update_existing_submodule("src/gcc"); // FIXME (GuillaumeGomez): To be done once gccjit has been built in the CI. // builder.config.maybe_download_ci_gcc(); // Initialize the gcc submodule if not initialized already. - builder.update_submodule(&Path::new("src").join("gcc")); + builder.update_submodule("src/gcc"); let root = "src/gcc"; let out_dir = builder.gcc_out(target).join("build"); @@ -199,18 +198,17 @@ impl Step for Gcc { return true; } - builder.run( - command(root.join("configure")) - .current_dir(&out_dir) - .arg("--enable-host-shared") - .arg("--enable-languages=jit") - .arg("--enable-checking=release") - .arg("--disable-bootstrap") - .arg("--disable-multilib") - .arg(format!("--prefix={}", install_dir.display())), - ); - builder.run(command("make").current_dir(&out_dir).arg(format!("-j{}", builder.jobs()))); - builder.run(command("make").current_dir(&out_dir).arg("install")); + command(root.join("configure")) + .current_dir(&out_dir) + .arg("--enable-host-shared") + .arg("--enable-languages=jit") + .arg("--enable-checking=release") + .arg("--disable-bootstrap") + .arg("--disable-multilib") + .arg(format!("--prefix={}", install_dir.display())) + .run(builder); + command("make").current_dir(&out_dir).arg(format!("-j{}", builder.jobs())).run(builder); + command("make").current_dir(&out_dir).arg("install").run(builder); t!(builder.symlink_file( install_dir.join("lib/libgccjit.so"), From 2c4aa2960e57eace72ac3fc310faf5a59d5e2305 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 12 Aug 2024 16:54:07 +0200 Subject: [PATCH 0591/2194] Move HashStamp to helpers --- src/bootstrap/src/core/build_steps/gcc.rs | 3 +- src/bootstrap/src/core/build_steps/llvm.rs | 42 ++-------------------- src/bootstrap/src/utils/helpers.rs | 38 ++++++++++++++++++++ 3 files changed, 41 insertions(+), 42 deletions(-) diff --git a/src/bootstrap/src/core/build_steps/gcc.rs b/src/bootstrap/src/core/build_steps/gcc.rs index 8c0257522c93a..a9cdf2414f4fb 100644 --- a/src/bootstrap/src/core/build_steps/gcc.rs +++ b/src/bootstrap/src/core/build_steps/gcc.rs @@ -12,11 +12,10 @@ use std::fs; use std::path::PathBuf; use std::sync::OnceLock; -use super::llvm::HashStamp; use crate::core::builder::{Builder, RunConfig, ShouldRun, Step}; use crate::core::config::TargetSelection; use crate::utils::exec::command; -use crate::utils::helpers::{self, t}; +use crate::utils::helpers::{self, t, HashStamp}; use crate::{generate_smart_stamp_hash, Kind}; pub struct Meta { diff --git a/src/bootstrap/src/core/build_steps/llvm.rs b/src/bootstrap/src/core/build_steps/llvm.rs index d729952adcebf..50d0cffd36c6d 100644 --- a/src/bootstrap/src/core/build_steps/llvm.rs +++ b/src/bootstrap/src/core/build_steps/llvm.rs @@ -8,12 +8,12 @@ //! LLVM and compiler-rt are essentially just wired up to everything else to //! ensure that they're always in place if needed. +use std::env; use std::env::consts::EXE_EXTENSION; use std::ffi::{OsStr, OsString}; use std::fs::{self, File}; use std::path::{Path, PathBuf}; use std::sync::OnceLock; -use std::{env, io}; use build_helper::ci::CiEnv; @@ -22,7 +22,7 @@ use crate::core::config::{Config, TargetSelection}; use crate::utils::channel; use crate::utils::exec::command; use crate::utils::helpers::{ - self, exe, get_clang_cl_resource_dir, output, t, unhashed_basename, up_to_date, + self, exe, get_clang_cl_resource_dir, output, t, unhashed_basename, up_to_date, HashStamp, }; use crate::{generate_smart_stamp_hash, CLang, GitRepo, Kind}; @@ -1242,44 +1242,6 @@ fn supported_sanitizers( } } -pub(super) struct HashStamp { - pub(super) path: PathBuf, - pub(super) hash: Option>, -} - -impl HashStamp { - pub(super) fn new(path: PathBuf, hash: Option<&str>) -> Self { - HashStamp { path, hash: hash.map(|s| s.as_bytes().to_owned()) } - } - - pub(super) fn is_done(&self) -> bool { - match fs::read(&self.path) { - Ok(h) => self.hash.as_deref().unwrap_or(b"") == h.as_slice(), - Err(e) if e.kind() == io::ErrorKind::NotFound => false, - Err(e) => { - panic!("failed to read stamp file `{}`: {}", self.path.display(), e); - } - } - } - - pub(super) fn remove(&self) -> io::Result<()> { - match fs::remove_file(&self.path) { - Ok(()) => Ok(()), - Err(e) => { - if e.kind() == io::ErrorKind::NotFound { - Ok(()) - } else { - Err(e) - } - } - } - } - - pub(super) fn write(&self) -> io::Result<()> { - fs::write(&self.path, self.hash.as_deref().unwrap_or(b"")) - } -} - #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct CrtBeginEnd { pub target: TargetSelection, diff --git a/src/bootstrap/src/utils/helpers.rs b/src/bootstrap/src/utils/helpers.rs index a856c99ff55a5..11e0119018935 100644 --- a/src/bootstrap/src/utils/helpers.rs +++ b/src/bootstrap/src/utils/helpers.rs @@ -556,3 +556,41 @@ pub fn set_file_times>(path: P, times: fs::FileTimes) -> io::Resu }; f.set_times(times) } + +pub struct HashStamp { + pub path: PathBuf, + pub hash: Option>, +} + +impl HashStamp { + pub fn new(path: PathBuf, hash: Option<&str>) -> Self { + HashStamp { path, hash: hash.map(|s| s.as_bytes().to_owned()) } + } + + pub fn is_done(&self) -> bool { + match fs::read(&self.path) { + Ok(h) => self.hash.as_deref().unwrap_or(b"") == h.as_slice(), + Err(e) if e.kind() == io::ErrorKind::NotFound => false, + Err(e) => { + panic!("failed to read stamp file `{}`: {}", self.path.display(), e); + } + } + } + + pub fn remove(&self) -> io::Result<()> { + match fs::remove_file(&self.path) { + Ok(()) => Ok(()), + Err(e) => { + if e.kind() == io::ErrorKind::NotFound { + Ok(()) + } else { + Err(e) + } + } + } + } + + pub fn write(&self) -> io::Result<()> { + fs::write(&self.path, self.hash.as_deref().unwrap_or(b"")) + } +} From 9c165486d4bddc813e2e99495b7577d77dc6178f Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 12 Aug 2024 16:52:23 +0200 Subject: [PATCH 0592/2194] Clean code and move check for GCC backend build in `dist.rs` directly --- src/bootstrap/src/core/build_steps/dist.rs | 4 +- src/bootstrap/src/core/build_steps/gcc.rs | 91 +--------------------- 2 files changed, 6 insertions(+), 89 deletions(-) diff --git a/src/bootstrap/src/core/build_steps/dist.rs b/src/bootstrap/src/core/build_steps/dist.rs index 2928f169b1a09..630beb7a60971 100644 --- a/src/bootstrap/src/core/build_steps/dist.rs +++ b/src/bootstrap/src/core/build_steps/dist.rs @@ -2273,7 +2273,9 @@ impl Step for RustDev { tarball.permit_symlinks(true); builder.ensure(crate::core::build_steps::llvm::Llvm { target }); - builder.ensure(crate::core::build_steps::gcc::Gcc { target }); + if target.contains("linux") && target.contains("x86_64") { + builder.ensure(crate::core::build_steps::gcc::Gcc { target }); + } let src_bindir = builder.llvm_out(target).join("bin"); // If updating this, you likely want to change diff --git a/src/bootstrap/src/core/build_steps/gcc.rs b/src/bootstrap/src/core/build_steps/gcc.rs index a9cdf2414f4fb..21cb05898eb08 100644 --- a/src/bootstrap/src/core/build_steps/gcc.rs +++ b/src/bootstrap/src/core/build_steps/gcc.rs @@ -35,15 +35,12 @@ pub enum GccBuildStatus { /// It's used to avoid busting caches during x.py check -- if we've already built /// GCC, it's fine for us to not try to avoid doing so. pub fn prebuilt_gcc_config(builder: &Builder<'_>, target: TargetSelection) -> GccBuildStatus { - // If we have gcc submodule initialized already, sync it. - builder.update_existing_submodule("src/gcc"); + // Initialize the gcc submodule if not initialized already. + builder.update_submodule("src/gcc"); // FIXME (GuillaumeGomez): To be done once gccjit has been built in the CI. // builder.config.maybe_download_ci_gcc(); - // Initialize the gcc submodule if not initialized already. - builder.update_submodule("src/gcc"); - let root = "src/gcc"; let out_dir = builder.gcc_out(target).join("build"); let install_dir = builder.gcc_out(target).join("install"); @@ -77,84 +74,6 @@ pub fn prebuilt_gcc_config(builder: &Builder<'_>, target: TargetSelection) -> Gc GccBuildStatus::ShouldBuild(Meta { stamp, out_dir, install_dir, root: root.into() }) } -// FIXME (GuillaumeGomez): When gcc-ci-download option is added, uncomment this code. -// /// This retrieves the GCC sha we *want* to use, according to git history. -// pub(crate) fn detect_gcc_sha(config: &Config, is_git: bool) -> String { -// let gcc_sha = if is_git { -// // We proceed in 2 steps. First we get the closest commit that is actually upstream. Then we -// // walk back further to the last bors merge commit that actually changed GCC. The first -// // step will fail on CI because only the `auto` branch exists; we just fall back to `HEAD` -// // in that case. -// let closest_upstream = get_git_merge_base(&config.git_config(), Some(&config.src)) -// .unwrap_or_else(|_| "HEAD".into()); -// let mut rev_list = config.git(); -// rev_list.args(&[ -// PathBuf::from("rev-list"), -// format!("--author={}", config.stage0_metadata.config.git_merge_commit_email).into(), -// "-n1".into(), -// "--first-parent".into(), -// closest_upstream.into(), -// "--".into(), -// config.src.join("src/gcc"), -// config.src.join("src/bootstrap/download-ci-gcc-stamp"), -// // the GCC shared object file is named `gcc-12-rust-{version}-nightly` -// config.src.join("src/version"), -// ]); -// output(&mut rev_list).trim().to_owned() -// } else if let Some(info) = channel::read_commit_info_file(&config.src) { -// info.sha.trim().to_owned() -// } else { -// "".to_owned() -// }; - -// if gcc_sha.is_empty() { -// eprintln!("error: could not find commit hash for downloading GCC"); -// eprintln!("HELP: maybe your repository history is too shallow?"); -// eprintln!("HELP: consider disabling `download-ci-gcc`"); -// eprintln!("HELP: or fetch enough history to include one upstream commit"); -// panic!(); -// } - -// gcc_sha -// } - -// /// Returns whether the CI-found GCC is currently usable. -// /// -// /// This checks both the build triple platform to confirm we're usable at all, -// /// and then verifies if the current HEAD matches the detected GCC SHA head, -// /// in which case GCC is indicated as not available. -// pub(crate) fn is_ci_gcc_available(config: &Config, asserts: bool) -> bool { -// let supported_platforms = [ -// // tier 1 -// ("x86_64-unknown-linux-gnu", true), -// ]; - -// if !supported_platforms.contains(&(&*config.build.triple, asserts)) -// && (asserts || !supported_platforms.contains(&(&*config.build.triple, true))) -// { -// return false; -// } - -// if is_ci_gcc_modified(config) { -// eprintln!("Detected GCC as non-available: running in CI and modified GCC in this change"); -// return false; -// } - -// true -// } - -// /// Returns true if we're running in CI with modified GCC (and thus can't download it) -// pub(crate) fn is_ci_gcc_modified(config: &Config) -> bool { -// CiEnv::is_ci() && config.rust_info.is_managed_git_subrepository() && { -// // We assume we have access to git, so it's okay to unconditionally pass -// // `true` here. -// let gcc_sha = detect_gcc_sha(config, true); -// let head_sha = output(config.git().arg("rev-parse").arg("HEAD")); -// let head_sha = head_sha.trim(); -// gcc_sha == head_sha -// } -// } - #[derive(Debug, Clone, Hash, PartialEq, Eq)] pub struct Gcc { pub target: TargetSelection, @@ -176,12 +95,8 @@ impl Step for Gcc { /// Compile GCC for `target`. fn run(self, builder: &Builder<'_>) -> bool { let target = self.target; - if !target.contains("linux") || !target.contains("x86_64") { - return false; - } - // If GCC has already been built or been downloaded through download-ci-gcc, we avoid - // building it again. + // If GCC has already been built, we avoid building it again. let Meta { stamp, out_dir, install_dir, root } = match prebuilt_gcc_config(builder, target) { GccBuildStatus::AlreadyBuilt => return true, From cbef544596cfe66062a0763cc23cf96be0901a87 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 14 Aug 2024 15:00:39 +0200 Subject: [PATCH 0593/2194] Add `gcc` to the `build` commands list --- src/bootstrap/src/core/build_steps/gcc.rs | 2 +- src/bootstrap/src/core/builder.rs | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/bootstrap/src/core/build_steps/gcc.rs b/src/bootstrap/src/core/build_steps/gcc.rs index 21cb05898eb08..1ddf2e64223d0 100644 --- a/src/bootstrap/src/core/build_steps/gcc.rs +++ b/src/bootstrap/src/core/build_steps/gcc.rs @@ -85,7 +85,7 @@ impl Step for Gcc { const ONLY_HOSTS: bool = true; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { - run.path("src/gcc") + run.path("src/gcc").alias("gcc") } fn make_run(run: RunConfig<'_>) { diff --git a/src/bootstrap/src/core/builder.rs b/src/bootstrap/src/core/builder.rs index a28b19d33a632..2b5b8ecceab96 100644 --- a/src/bootstrap/src/core/builder.rs +++ b/src/bootstrap/src/core/builder.rs @@ -14,7 +14,7 @@ use clap::ValueEnum; use crate::core::build_steps::tool::{self, SourceType}; use crate::core::build_steps::{ - check, clean, clippy, compile, dist, doc, install, llvm, run, setup, test, vendor, + check, clean, clippy, compile, dist, doc, gcc, install, llvm, run, setup, test, vendor, }; use crate::core::config::flags::{Color, Subcommand}; use crate::core::config::{DryRun, SplitDebuginfo, TargetSelection}; @@ -793,6 +793,7 @@ impl<'a> Builder<'a> { tool::Clippy, tool::CargoClippy, llvm::Llvm, + gcc::Gcc, llvm::Sanitizers, tool::Rustfmt, tool::Miri, From b10a38b9d12ba7a2d362c19de909bfcc89abcebc Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 14 Aug 2024 15:12:40 +0200 Subject: [PATCH 0594/2194] Update declared licenses in `REUSE.toml` --- REUSE.toml | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/REUSE.toml b/REUSE.toml index efd705552478d..6f1a8f4a1fd46 100644 --- a/REUSE.toml +++ b/REUSE.toml @@ -168,3 +168,37 @@ SPDX-FileCopyrightText = [ "2003-2019 University of Illinois at Urbana-Champaign.", ] SPDX-License-Identifier = "NCSA AND Apache-2.0 WITH LLVM-exception" + +[[annotations]] +path = "src/gcc/gcc/testsuite/c-c++-common/analyzer/*.c" +precedence = "override" +SPDX-FileCopyrightText = [ + "Copyright (c) 2007-2011 Atheros Communications Inc.", + "Copyright (c) 2011-2012,2017 Qualcomm Atheros, Inc.", + "Copyright (c) 2016-2017 Erik Stromdahl ", +] +SPDX-License-Identifier = "ISC" + +[[annotations]] +path = "src/gcc/libstdc++-v3/config/os/aix/os_defines.h" +precedence = "override" +SPDX-FileCopyrightText = [ + "Copyright (C) 2000-2024 Free Software Foundation, Inc.", +] +SPDX-License-Identifier = "GCC-exception-3.1" + +[[annotations]] +path = "src/gcc/testsuite/**" +precedence = "override" +SPDX-FileCopyrightText = [ + "Copyright (C) 2000-2024 Free Software Foundation, Inc.", +] +SPDX-License-Identifier = "GPL-2.0-only" + +[[annotations]] +path = "src/gcc/**" +precedence = "override" +SPDX-FileCopyrightText = [ + "Copyright (C) 1997-2024 Free Software Foundation, Inc.", +] +SPDX-License-Identifier = "GPL-3.0-or-later" From 42d6f579d03763f3209078f07f53bde33da5268a Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 14 Aug 2024 15:21:41 +0200 Subject: [PATCH 0595/2194] Make gcc submodule shallow --- .gitmodules | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitmodules b/.gitmodules index b47b0e9e62107..2082ec9ef455f 100644 --- a/.gitmodules +++ b/.gitmodules @@ -54,3 +54,4 @@ [submodule "src/gcc"] path = src/gcc url = https://github.com/rust-lang/gcc.git + shallow = true From 1b39b43479f0a2e27594f8a5c1720411b74d7f79 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 14 Aug 2024 15:32:25 +0200 Subject: [PATCH 0596/2194] Make gcc `root` absolute --- src/bootstrap/src/core/build_steps/gcc.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/bootstrap/src/core/build_steps/gcc.rs b/src/bootstrap/src/core/build_steps/gcc.rs index 1ddf2e64223d0..e1a9096447a1c 100644 --- a/src/bootstrap/src/core/build_steps/gcc.rs +++ b/src/bootstrap/src/core/build_steps/gcc.rs @@ -41,7 +41,7 @@ pub fn prebuilt_gcc_config(builder: &Builder<'_>, target: TargetSelection) -> Gc // FIXME (GuillaumeGomez): To be done once gccjit has been built in the CI. // builder.config.maybe_download_ci_gcc(); - let root = "src/gcc"; + let root = builder.src.join("src/gcc"); let out_dir = builder.gcc_out(target).join("build"); let install_dir = builder.gcc_out(target).join("install"); @@ -71,7 +71,7 @@ pub fn prebuilt_gcc_config(builder: &Builder<'_>, target: TargetSelection) -> Gc return GccBuildStatus::AlreadyBuilt; } - GccBuildStatus::ShouldBuild(Meta { stamp, out_dir, install_dir, root: root.into() }) + GccBuildStatus::ShouldBuild(Meta { stamp, out_dir, install_dir, root }) } #[derive(Debug, Clone, Hash, PartialEq, Eq)] From 4e7808a5c3c24e4986ffe0e2fbbe748f3fa23850 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 4 Sep 2024 15:11:05 +0200 Subject: [PATCH 0597/2194] Update to new `Builder` API --- src/bootstrap/src/core/build_steps/gcc.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bootstrap/src/core/build_steps/gcc.rs b/src/bootstrap/src/core/build_steps/gcc.rs index e1a9096447a1c..969565e0fd5dd 100644 --- a/src/bootstrap/src/core/build_steps/gcc.rs +++ b/src/bootstrap/src/core/build_steps/gcc.rs @@ -36,7 +36,7 @@ pub enum GccBuildStatus { /// GCC, it's fine for us to not try to avoid doing so. pub fn prebuilt_gcc_config(builder: &Builder<'_>, target: TargetSelection) -> GccBuildStatus { // Initialize the gcc submodule if not initialized already. - builder.update_submodule("src/gcc"); + builder.config.update_submodule("src/gcc"); // FIXME (GuillaumeGomez): To be done once gccjit has been built in the CI. // builder.config.maybe_download_ci_gcc(); From 2a2422c3541323fa6362f25656ec4b825825e170 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Wed, 4 Sep 2024 16:20:53 +0200 Subject: [PATCH 0598/2194] Fix licensing information in REUSE.toml --- REUSE.toml | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/REUSE.toml b/REUSE.toml index 6f1a8f4a1fd46..3005bb56609b5 100644 --- a/REUSE.toml +++ b/REUSE.toml @@ -170,35 +170,35 @@ SPDX-FileCopyrightText = [ SPDX-License-Identifier = "NCSA AND Apache-2.0 WITH LLVM-exception" [[annotations]] -path = "src/gcc/gcc/testsuite/c-c++-common/analyzer/*.c" +path = "src/gcc/**" precedence = "override" SPDX-FileCopyrightText = [ - "Copyright (c) 2007-2011 Atheros Communications Inc.", - "Copyright (c) 2011-2012,2017 Qualcomm Atheros, Inc.", - "Copyright (c) 2016-2017 Erik Stromdahl ", + "Copyright (C) 1997-2024 Free Software Foundation, Inc.", ] -SPDX-License-Identifier = "ISC" +SPDX-License-Identifier = "GPL-3.0-or-later" [[annotations]] -path = "src/gcc/libstdc++-v3/config/os/aix/os_defines.h" +path = "src/gcc/gcc/testsuite/**" precedence = "override" SPDX-FileCopyrightText = [ "Copyright (C) 2000-2024 Free Software Foundation, Inc.", ] -SPDX-License-Identifier = "GCC-exception-3.1" +SPDX-License-Identifier = "GPL-2.0-only" [[annotations]] -path = "src/gcc/testsuite/**" +path = "src/gcc/gcc/testsuite/c-c++-common/analyzer/*.c" precedence = "override" SPDX-FileCopyrightText = [ - "Copyright (C) 2000-2024 Free Software Foundation, Inc.", + "Copyright (c) 2007-2011 Atheros Communications Inc.", + "Copyright (c) 2011-2012,2017 Qualcomm Atheros, Inc.", + "Copyright (c) 2016-2017 Erik Stromdahl ", ] -SPDX-License-Identifier = "GPL-2.0-only" +SPDX-License-Identifier = "ISC" [[annotations]] -path = "src/gcc/**" +path = "src/gcc/libstdc++-v3/config/os/aix/os_defines.h" precedence = "override" SPDX-FileCopyrightText = [ - "Copyright (C) 1997-2024 Free Software Foundation, Inc.", + "Copyright (C) 2000-2024 Free Software Foundation, Inc.", ] -SPDX-License-Identifier = "GPL-3.0-or-later" +SPDX-License-Identifier = "GCC-exception-3.1" From 103e04064f223a9e684bffd7c254d3dbf13e1d15 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Thu, 5 Sep 2024 23:40:32 +0200 Subject: [PATCH 0599/2194] Check if the `libgccjit.so.0` file exists before creating a symlink to it --- src/bootstrap/src/core/build_steps/gcc.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/bootstrap/src/core/build_steps/gcc.rs b/src/bootstrap/src/core/build_steps/gcc.rs index 969565e0fd5dd..b9be81166599e 100644 --- a/src/bootstrap/src/core/build_steps/gcc.rs +++ b/src/bootstrap/src/core/build_steps/gcc.rs @@ -124,10 +124,10 @@ impl Step for Gcc { command("make").current_dir(&out_dir).arg(format!("-j{}", builder.jobs())).run(builder); command("make").current_dir(&out_dir).arg("install").run(builder); - t!(builder.symlink_file( - install_dir.join("lib/libgccjit.so"), - install_dir.join("lib/libgccjit.so.0") - )); + let lib_alias = install_dir.join("lib/libgccjit.so.0"); + if !lib_alias.exists() { + t!(builder.symlink_file(install_dir.join("lib/libgccjit.so"), lib_alias,)); + } t!(stamp.write()); From 691751416e9ded004fe6aa4ede0c4ba5741a08e9 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Thu, 5 Sep 2024 23:42:19 +0200 Subject: [PATCH 0600/2194] Run `download_prerequisites` before running gcc `configure` --- src/bootstrap/src/core/build_steps/gcc.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/bootstrap/src/core/build_steps/gcc.rs b/src/bootstrap/src/core/build_steps/gcc.rs index b9be81166599e..f7a88930b8d54 100644 --- a/src/bootstrap/src/core/build_steps/gcc.rs +++ b/src/bootstrap/src/core/build_steps/gcc.rs @@ -112,6 +112,7 @@ impl Step for Gcc { return true; } + command(root.join("contrib/download_prerequisites")).current_dir(&root).run(builder); command(root.join("configure")) .current_dir(&out_dir) .arg("--enable-host-shared") From 9e2d264fa251f98780084382a071e10a123770d6 Mon Sep 17 00:00:00 2001 From: Pavel Grigorenko Date: Sun, 1 Sep 2024 16:49:55 +0300 Subject: [PATCH 0601/2194] Hack around a conflict with `clippy::needless_lifetimes` --- compiler/rustc_lint/src/lints.rs | 7 +++++++ .../async-await/issues/issue-63388-1.stderr | 4 ---- .../type-dependent/issue-71348.full.stderr | 4 ---- .../type-dependent/issue-71348.min.stderr | 4 ---- .../consts/min_const_fn/min_const_fn.stderr | 9 --------- .../ui/impl-trait/impl-fn-hrtb-bounds.stderr | 4 ---- .../impl-fn-predefined-lifetimes.stderr | 4 ---- .../rpit-assoc-pair-with-lifetime.stderr | 4 ---- ...urn-type-requires-explicit-lifetime.stderr | 4 ---- ...-existing-name-if-else-using-impl-3.stderr | 4 ---- .../missing-lifetime-kind.stderr | 19 ------------------- .../object-lifetime-default-elision.stderr | 4 ---- .../ignore-non-reference-lifetimes.stderr | 9 --------- tests/ui/self/self_lifetime-async.stderr | 9 --------- tests/ui/self/self_lifetime.stderr | 9 --------- .../impl-trait-missing-lifetime-gated.stderr | 4 ---- .../missing-lifetimes-in-signature.stderr | 4 ---- .../missing_lifetime_bound.stderr | 4 ---- 18 files changed, 7 insertions(+), 103 deletions(-) diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index 693f1b2258745..ae7e965985635 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -2639,6 +2639,13 @@ impl LintDiagnostic<'_, G> for ElidedNamedLifetime { if let Some(declaration) = declaration { diag.span_label(declaration, fluent::lint_label_named); } + // FIXME(GrigorenkoPV): this `if` and `return` should be removed, + // but currently this lint's suggestions can conflict with those of `clippy::needless_lifetimes`: + // https://github.com/rust-lang/rust/pull/129840#issuecomment-2323349119 + // HACK: `'static` suggestions will never sonflict, emit only those for now. + if name != rustc_span::symbol::kw::StaticLifetime { + return; + } match kind { MissingLifetimeKind::Underscore => diag.span_suggestion_verbose( span, diff --git a/tests/ui/async-await/issues/issue-63388-1.stderr b/tests/ui/async-await/issues/issue-63388-1.stderr index 713e4e4dcf5ca..ef74bfe32375e 100644 --- a/tests/ui/async-await/issues/issue-63388-1.stderr +++ b/tests/ui/async-await/issues/issue-63388-1.stderr @@ -8,10 +8,6 @@ LL | ) -> &dyn Foo | ^ this elided lifetime gets resolved as `'a` | = note: `#[warn(elided_named_lifetimes)]` on by default -help: consider specifying it explicitly - | -LL | ) -> &'a dyn Foo - | ++ error[E0621]: explicit lifetime required in the type of `foo` --> $DIR/issue-63388-1.rs:13:5 diff --git a/tests/ui/const-generics/type-dependent/issue-71348.full.stderr b/tests/ui/const-generics/type-dependent/issue-71348.full.stderr index 394259ce55ddb..177ff20fbf9ea 100644 --- a/tests/ui/const-generics/type-dependent/issue-71348.full.stderr +++ b/tests/ui/const-generics/type-dependent/issue-71348.full.stderr @@ -5,10 +5,6 @@ LL | fn ask<'a, const N: &'static str>(&'a self) -> &'a >::Ta | -- lifetime `'a` declared here ^ this elided lifetime gets resolved as `'a` | = note: `#[warn(elided_named_lifetimes)]` on by default -help: consider specifying it explicitly - | -LL | fn ask<'a, const N: &'static str>(&'a self) -> &'a >::Target - | +++ warning: 1 warning emitted diff --git a/tests/ui/const-generics/type-dependent/issue-71348.min.stderr b/tests/ui/const-generics/type-dependent/issue-71348.min.stderr index 0f0d75dbac13e..5aee282952aa2 100644 --- a/tests/ui/const-generics/type-dependent/issue-71348.min.stderr +++ b/tests/ui/const-generics/type-dependent/issue-71348.min.stderr @@ -5,10 +5,6 @@ LL | fn ask<'a, const N: &'static str>(&'a self) -> &'a >::Ta | -- lifetime `'a` declared here ^ this elided lifetime gets resolved as `'a` | = note: `#[warn(elided_named_lifetimes)]` on by default -help: consider specifying it explicitly - | -LL | fn ask<'a, const N: &'static str>(&'a self) -> &'a >::Target - | +++ error: `&'static str` is forbidden as the type of a const generic parameter --> $DIR/issue-71348.rs:10:24 diff --git a/tests/ui/consts/min_const_fn/min_const_fn.stderr b/tests/ui/consts/min_const_fn/min_const_fn.stderr index 1e88a908af083..4b348a182b87f 100644 --- a/tests/ui/consts/min_const_fn/min_const_fn.stderr +++ b/tests/ui/consts/min_const_fn/min_const_fn.stderr @@ -8,10 +8,6 @@ LL | const fn get_lt(&'a self) -> &T { &self.0 } | ^ this elided lifetime gets resolved as `'a` | = note: `#[warn(elided_named_lifetimes)]` on by default -help: consider specifying it explicitly - | -LL | const fn get_lt(&'a self) -> &'a T { &self.0 } - | ++ warning: elided lifetime has a name --> $DIR/min_const_fn.rs:48:42 @@ -21,11 +17,6 @@ LL | impl<'a, T> Foo { ... LL | const fn get_mut_lt(&'a mut self) -> &mut T { &mut self.0 } | ^ this elided lifetime gets resolved as `'a` - | -help: consider specifying it explicitly - | -LL | const fn get_mut_lt(&'a mut self) -> &'a mut T { &mut self.0 } - | ++ error[E0493]: destructor of `Foo` cannot be evaluated at compile-time --> $DIR/min_const_fn.rs:37:25 diff --git a/tests/ui/impl-trait/impl-fn-hrtb-bounds.stderr b/tests/ui/impl-trait/impl-fn-hrtb-bounds.stderr index ccea9d5e6e92a..d0f8f7689d17c 100644 --- a/tests/ui/impl-trait/impl-fn-hrtb-bounds.stderr +++ b/tests/ui/impl-trait/impl-fn-hrtb-bounds.stderr @@ -17,10 +17,6 @@ LL | fn c() -> impl for<'a> Fn(&'a u8) -> (impl Debug + '_) { | -- lifetime `'a` declared here ^^ this elided lifetime gets resolved as `'a` | = note: `#[warn(elided_named_lifetimes)]` on by default -help: consider specifying it explicitly - | -LL | fn c() -> impl for<'a> Fn(&'a u8) -> (impl Debug + 'a) { - | ~~ error[E0657]: `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait` --> $DIR/impl-fn-hrtb-bounds.rs:4:41 diff --git a/tests/ui/impl-trait/impl-fn-predefined-lifetimes.stderr b/tests/ui/impl-trait/impl-fn-predefined-lifetimes.stderr index a60f398684330..50a9f3ebeabb8 100644 --- a/tests/ui/impl-trait/impl-fn-predefined-lifetimes.stderr +++ b/tests/ui/impl-trait/impl-fn-predefined-lifetimes.stderr @@ -5,10 +5,6 @@ LL | fn a<'a>() -> impl Fn(&'a u8) -> (impl Debug + '_) { | -- lifetime `'a` declared here ^^ this elided lifetime gets resolved as `'a` | = note: `#[warn(elided_named_lifetimes)]` on by default -help: consider specifying it explicitly - | -LL | fn a<'a>() -> impl Fn(&'a u8) -> (impl Debug + 'a) { - | ~~ error[E0792]: expected generic lifetime parameter, found `'_` --> $DIR/impl-fn-predefined-lifetimes.rs:7:9 diff --git a/tests/ui/impl-trait/rpit-assoc-pair-with-lifetime.stderr b/tests/ui/impl-trait/rpit-assoc-pair-with-lifetime.stderr index 6eea25b4fc8f8..bff3ffd934ac6 100644 --- a/tests/ui/impl-trait/rpit-assoc-pair-with-lifetime.stderr +++ b/tests/ui/impl-trait/rpit-assoc-pair-with-lifetime.stderr @@ -5,10 +5,6 @@ LL | pub fn iter<'a>(v: Vec<(u32, &'a u32)>) -> impl DoubleEndedIterator(v: Vec<(u32, &'a u32)>) -> impl DoubleEndedIterator { - | ++ warning: 1 warning emitted diff --git a/tests/ui/lifetimes/lifetime-elision-return-type-requires-explicit-lifetime.stderr b/tests/ui/lifetimes/lifetime-elision-return-type-requires-explicit-lifetime.stderr index 1339c644f5339..f835d2655bb01 100644 --- a/tests/ui/lifetimes/lifetime-elision-return-type-requires-explicit-lifetime.stderr +++ b/tests/ui/lifetimes/lifetime-elision-return-type-requires-explicit-lifetime.stderr @@ -114,10 +114,6 @@ LL | fn m<'a>(_: &'a Foo<'a>) -> &str { "" } | lifetime `'a` declared here | = note: `#[warn(elided_named_lifetimes)]` on by default -help: consider specifying it explicitly - | -LL | fn m<'a>(_: &'a Foo<'a>) -> &'a str { "" } - | ++ error: aborting due to 7 previous errors; 1 warning emitted diff --git a/tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-3.stderr b/tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-3.stderr index 144f9454513c5..2d5d4fb0e72ec 100644 --- a/tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-3.stderr +++ b/tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-3.stderr @@ -7,10 +7,6 @@ LL | fn foo<'a>(&'a self, x: &i32) -> &i32 { | lifetime `'a` declared here | = note: `#[warn(elided_named_lifetimes)]` on by default -help: consider specifying it explicitly - | -LL | fn foo<'a>(&'a self, x: &i32) -> &'a i32 { - | ++ error[E0621]: explicit lifetime required in the type of `x` --> $DIR/ex1-return-one-existing-name-if-else-using-impl-3.rs:9:36 diff --git a/tests/ui/lint/elided-named-lifetimes/missing-lifetime-kind.stderr b/tests/ui/lint/elided-named-lifetimes/missing-lifetime-kind.stderr index 834292d103dc8..249ae146b1675 100644 --- a/tests/ui/lint/elided-named-lifetimes/missing-lifetime-kind.stderr +++ b/tests/ui/lint/elided-named-lifetimes/missing-lifetime-kind.stderr @@ -11,10 +11,6 @@ note: the lint level is defined here | LL | #![deny(elided_named_lifetimes)] | ^^^^^^^^^^^^^^^^^^^^^^ -help: consider specifying it explicitly - | -LL | fn ampersand<'a>(x: &'a u8) -> &'a u8 { - | ++ error: elided lifetime has a name --> $DIR/missing-lifetime-kind.rs:10:31 @@ -23,11 +19,6 @@ LL | fn brackets<'a>(x: &'a u8) -> Brackets { | -- ^^^^^^^^ this elided lifetime gets resolved as `'a` | | | lifetime `'a` declared here - | -help: consider specifying it explicitly - | -LL | fn brackets<'a>(x: &'a u8) -> Brackets<'a> { - | ++++ error: elided lifetime has a name --> $DIR/missing-lifetime-kind.rs:17:33 @@ -36,11 +27,6 @@ LL | fn comma<'a>(x: &'a u8) -> Comma { | -- ^ this elided lifetime gets resolved as `'a` | | | lifetime `'a` declared here - | -help: consider specifying it explicitly - | -LL | fn comma<'a>(x: &'a u8) -> Comma<'a, u8> { - | +++ error: elided lifetime has a name --> $DIR/missing-lifetime-kind.rs:22:34 @@ -49,11 +35,6 @@ LL | fn underscore<'a>(x: &'a u8) -> &'_ u8 { | -- ^^ this elided lifetime gets resolved as `'a` | | | lifetime `'a` declared here - | -help: consider specifying it explicitly - | -LL | fn underscore<'a>(x: &'a u8) -> &'a u8 { - | ~~ error: aborting due to 4 previous errors diff --git a/tests/ui/object-lifetime/object-lifetime-default-elision.stderr b/tests/ui/object-lifetime/object-lifetime-default-elision.stderr index f8ed92111a967..b44a184c6848f 100644 --- a/tests/ui/object-lifetime/object-lifetime-default-elision.stderr +++ b/tests/ui/object-lifetime/object-lifetime-default-elision.stderr @@ -7,10 +7,6 @@ LL | fn load2<'a>(ss: &'a dyn SomeTrait) -> &dyn SomeTrait { | lifetime `'a` declared here | = note: `#[warn(elided_named_lifetimes)]` on by default -help: consider specifying it explicitly - | -LL | fn load2<'a>(ss: &'a dyn SomeTrait) -> &'a dyn SomeTrait { - | ++ error: lifetime may not live long enough --> $DIR/object-lifetime-default-elision.rs:73:5 diff --git a/tests/ui/self/elision/ignore-non-reference-lifetimes.stderr b/tests/ui/self/elision/ignore-non-reference-lifetimes.stderr index 13cc3a431a5d2..4465dbae52989 100644 --- a/tests/ui/self/elision/ignore-non-reference-lifetimes.stderr +++ b/tests/ui/self/elision/ignore-non-reference-lifetimes.stderr @@ -5,21 +5,12 @@ LL | fn a<'a>(self: Self, a: &'a str) -> &str { | -- lifetime `'a` declared here ^ this elided lifetime gets resolved as `'a` | = note: `#[warn(elided_named_lifetimes)]` on by default -help: consider specifying it explicitly - | -LL | fn a<'a>(self: Self, a: &'a str) -> &'a str { - | ++ warning: elided lifetime has a name --> $DIR/ignore-non-reference-lifetimes.rs:10:44 | LL | fn b<'a>(self: Foo<'b>, a: &'a str) -> &str { | -- lifetime `'a` declared here ^ this elided lifetime gets resolved as `'a` - | -help: consider specifying it explicitly - | -LL | fn b<'a>(self: Foo<'b>, a: &'a str) -> &'a str { - | ++ warning: 2 warnings emitted diff --git a/tests/ui/self/self_lifetime-async.stderr b/tests/ui/self/self_lifetime-async.stderr index 2892d790ac7b8..32de3fd18c97f 100644 --- a/tests/ui/self/self_lifetime-async.stderr +++ b/tests/ui/self/self_lifetime-async.stderr @@ -7,21 +7,12 @@ LL | async fn foo<'b>(self: &'b Foo<'a>) -> &() { self.0 } | lifetime `'b` declared here | = note: `#[warn(elided_named_lifetimes)]` on by default -help: consider specifying it explicitly - | -LL | async fn foo<'b>(self: &'b Foo<'a>) -> &'b () { self.0 } - | ++ warning: elided lifetime has a name --> $DIR/self_lifetime-async.rs:12:52 | LL | async fn bar<'a>(self: &Alias, arg: &'a ()) -> &() { arg } | -- lifetime `'a` declared here ^ this elided lifetime gets resolved as `'a` - | -help: consider specifying it explicitly - | -LL | async fn bar<'a>(self: &Alias, arg: &'a ()) -> &'a () { arg } - | ++ warning: 2 warnings emitted diff --git a/tests/ui/self/self_lifetime.stderr b/tests/ui/self/self_lifetime.stderr index ceb0ce345a3eb..cd8f4d8adf8b1 100644 --- a/tests/ui/self/self_lifetime.stderr +++ b/tests/ui/self/self_lifetime.stderr @@ -7,21 +7,12 @@ LL | fn foo<'b>(self: &'b Foo<'a>) -> &() { self.0 } | lifetime `'b` declared here | = note: `#[warn(elided_named_lifetimes)]` on by default -help: consider specifying it explicitly - | -LL | fn foo<'b>(self: &'b Foo<'a>) -> &'b () { self.0 } - | ++ warning: elided lifetime has a name --> $DIR/self_lifetime.rs:13:46 | LL | fn bar<'a>(self: &Alias, arg: &'a ()) -> &() { arg } | -- lifetime `'a` declared here ^ this elided lifetime gets resolved as `'a` - | -help: consider specifying it explicitly - | -LL | fn bar<'a>(self: &Alias, arg: &'a ()) -> &'a () { arg } - | ++ warning: 2 warnings emitted diff --git a/tests/ui/suggestions/impl-trait-missing-lifetime-gated.stderr b/tests/ui/suggestions/impl-trait-missing-lifetime-gated.stderr index 3744dd9f996ce..30f4509d49dee 100644 --- a/tests/ui/suggestions/impl-trait-missing-lifetime-gated.stderr +++ b/tests/ui/suggestions/impl-trait-missing-lifetime-gated.stderr @@ -131,10 +131,6 @@ LL | fn resolved_anonymous<'a, T: 'a>(f: impl Fn(&'a str) -> &T) { | -- lifetime `'a` declared here ^ this elided lifetime gets resolved as `'a` | = note: `#[warn(elided_named_lifetimes)]` on by default -help: consider specifying it explicitly - | -LL | fn resolved_anonymous<'a, T: 'a>(f: impl Fn(&'a str) -> &'a T) { - | ++ error[E0658]: anonymous lifetimes in `impl Trait` are unstable --> $DIR/impl-trait-missing-lifetime-gated.rs:6:35 diff --git a/tests/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr b/tests/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr index baa5fa949ec41..ea01dcd5020cf 100644 --- a/tests/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr +++ b/tests/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr @@ -13,10 +13,6 @@ LL | fn ok2<'a, G: 'a, T>(g: G, dest: &'a mut T) -> impl FnOnce() + '_ + 'a | -- lifetime `'a` declared here ^^ this elided lifetime gets resolved as `'a` | = note: `#[warn(elided_named_lifetimes)]` on by default -help: consider specifying it explicitly - | -LL | fn ok2<'a, G: 'a, T>(g: G, dest: &'a mut T) -> impl FnOnce() + 'a + 'a - | ~~ error[E0700]: hidden type for `impl FnOnce()` captures lifetime that does not appear in bounds --> $DIR/missing-lifetimes-in-signature.rs:19:5 diff --git a/tests/ui/type-alias-impl-trait/missing_lifetime_bound.stderr b/tests/ui/type-alias-impl-trait/missing_lifetime_bound.stderr index 376e58ef9e07e..e2c21f1636b0c 100644 --- a/tests/ui/type-alias-impl-trait/missing_lifetime_bound.stderr +++ b/tests/ui/type-alias-impl-trait/missing_lifetime_bound.stderr @@ -7,10 +7,6 @@ LL | fn defining<'a, T>(x: &'a i32) -> Opaque { x } | lifetime `'a` declared here | = note: `#[warn(elided_named_lifetimes)]` on by default -help: consider specifying it explicitly - | -LL | fn defining<'a, T>(x: &'a i32) -> Opaque<'a, T> { x } - | +++ error[E0700]: hidden type for `Opaque2` captures lifetime that does not appear in bounds --> $DIR/missing_lifetime_bound.rs:5:47 From 9aaf873396186ea0c980cbea7d3449a355ccfeea Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Mon, 26 Aug 2024 11:11:13 -0400 Subject: [PATCH 0602/2194] Reserve prefix lifetimes too --- compiler/rustc_lexer/src/lib.rs | 26 ++++++++++++++++--------- compiler/rustc_parse/src/lexer/mod.rs | 10 ++++++++++ tests/ui/lexer/prefixed-lifetime.rs | 10 ++++++++++ tests/ui/lexer/prefixed-lifetime.stderr | 14 +++++++++++++ 4 files changed, 51 insertions(+), 9 deletions(-) create mode 100644 tests/ui/lexer/prefixed-lifetime.rs create mode 100644 tests/ui/lexer/prefixed-lifetime.stderr diff --git a/compiler/rustc_lexer/src/lib.rs b/compiler/rustc_lexer/src/lib.rs index 31fdd2d7cec70..be3e151ea61f9 100644 --- a/compiler/rustc_lexer/src/lib.rs +++ b/compiler/rustc_lexer/src/lib.rs @@ -91,6 +91,12 @@ pub enum TokenKind { /// tokens. UnknownPrefix, + /// An unknown prefix in a lifetime, like `'foo#`. + /// + /// Note that like above, only the `'` and prefix are included in the token + /// and not the separator. + UnknownPrefixLifetime, + /// Similar to the above, but *always* an error on every edition. This is used /// for emoji identifier recovery, as those are not meant to be ever accepted. InvalidPrefix, @@ -688,15 +694,17 @@ impl Cursor<'_> { self.bump(); self.eat_while(is_id_continue); - // Check if after skipping literal contents we've met a closing - // single quote (which means that user attempted to create a - // string with single quotes). - if self.first() == '\'' { - self.bump(); - let kind = Char { terminated: true }; - Literal { kind, suffix_start: self.pos_within_token() } - } else { - Lifetime { starts_with_number } + match self.first() { + // Check if after skipping literal contents we've met a closing + // single quote (which means that user attempted to create a + // string with single quotes). + '\'' => { + self.bump(); + let kind = Char { terminated: true }; + Literal { kind, suffix_start: self.pos_within_token() } + } + '#' if !starts_with_number => UnknownPrefixLifetime, + _ => Lifetime { starts_with_number }, } } diff --git a/compiler/rustc_parse/src/lexer/mod.rs b/compiler/rustc_parse/src/lexer/mod.rs index f30939093c2ec..5d2d5a6010f6f 100644 --- a/compiler/rustc_parse/src/lexer/mod.rs +++ b/compiler/rustc_parse/src/lexer/mod.rs @@ -205,6 +205,16 @@ impl<'psess, 'src> StringReader<'psess, 'src> { self.report_unknown_prefix(start); self.ident(start) } + rustc_lexer::TokenKind::UnknownPrefixLifetime => { + self.report_unknown_prefix(start); + // Include the leading `'` in the real identifier, for macro + // expansion purposes. See #12512 for the gory details of why + // this is necessary. + let lifetime_name = self.str_from(start); + self.last_lifetime = Some(self.mk_sp(start, start + BytePos(1))); + let ident = Symbol::intern(lifetime_name); + token::Lifetime(ident, IdentIsRaw::No) + } rustc_lexer::TokenKind::InvalidIdent | rustc_lexer::TokenKind::InvalidPrefix // Do not recover an identifier with emoji if the codepoint is a confusable diff --git a/tests/ui/lexer/prefixed-lifetime.rs b/tests/ui/lexer/prefixed-lifetime.rs new file mode 100644 index 0000000000000..6191b97d57697 --- /dev/null +++ b/tests/ui/lexer/prefixed-lifetime.rs @@ -0,0 +1,10 @@ +//@ edition: 2021 + +macro_rules! w { + ($($tt:tt)*) => {}; +} + +w!('foo#lifetime); +//~^ ERROR prefix `'foo` is unknown + +fn main() {} diff --git a/tests/ui/lexer/prefixed-lifetime.stderr b/tests/ui/lexer/prefixed-lifetime.stderr new file mode 100644 index 0000000000000..39e8b5a2a570a --- /dev/null +++ b/tests/ui/lexer/prefixed-lifetime.stderr @@ -0,0 +1,14 @@ +error: prefix `'foo` is unknown + --> $DIR/prefixed-lifetime.rs:7:4 + | +LL | w!('foo#lifetime); + | ^^^^ unknown prefix + | + = note: prefixed identifiers and literals are reserved since Rust 2021 +help: consider inserting whitespace here + | +LL | w!('foo #lifetime); + | + + +error: aborting due to 1 previous error + From 3b3e43a386a9b89609fe529921bdd49ba3511fb8 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Mon, 26 Aug 2024 11:26:36 -0400 Subject: [PATCH 0603/2194] Format lexer --- compiler/rustc_lexer/src/lib.rs | 2 +- compiler/rustc_parse/src/lexer/mod.rs | 41 ++++++++++++++------------- 2 files changed, 23 insertions(+), 20 deletions(-) diff --git a/compiler/rustc_lexer/src/lib.rs b/compiler/rustc_lexer/src/lib.rs index be3e151ea61f9..6561e416cfa4b 100644 --- a/compiler/rustc_lexer/src/lib.rs +++ b/compiler/rustc_lexer/src/lib.rs @@ -92,7 +92,7 @@ pub enum TokenKind { UnknownPrefix, /// An unknown prefix in a lifetime, like `'foo#`. - /// + /// /// Note that like above, only the `'` and prefix are included in the token /// and not the separator. UnknownPrefixLifetime, diff --git a/compiler/rustc_parse/src/lexer/mod.rs b/compiler/rustc_parse/src/lexer/mod.rs index 5d2d5a6010f6f..c0731cf31c333 100644 --- a/compiler/rustc_parse/src/lexer/mod.rs +++ b/compiler/rustc_parse/src/lexer/mod.rs @@ -188,9 +188,7 @@ impl<'psess, 'src> StringReader<'psess, 'src> { preceded_by_whitespace = true; continue; } - rustc_lexer::TokenKind::Ident => { - self.ident(start) - } + rustc_lexer::TokenKind::Ident => self.ident(start), rustc_lexer::TokenKind::RawIdent => { let sym = nfc_normalize(self.str_from(start + BytePos(2))); let span = self.mk_sp(start, self.pos); @@ -215,20 +213,21 @@ impl<'psess, 'src> StringReader<'psess, 'src> { let ident = Symbol::intern(lifetime_name); token::Lifetime(ident, IdentIsRaw::No) } - rustc_lexer::TokenKind::InvalidIdent - | rustc_lexer::TokenKind::InvalidPrefix + rustc_lexer::TokenKind::InvalidIdent | rustc_lexer::TokenKind::InvalidPrefix // Do not recover an identifier with emoji if the codepoint is a confusable // with a recoverable substitution token, like `➖`. - if !UNICODE_ARRAY - .iter() - .any(|&(c, _, _)| { - let sym = self.str_from(start); - sym.chars().count() == 1 && c == sym.chars().next().unwrap() - }) => + if !UNICODE_ARRAY.iter().any(|&(c, _, _)| { + let sym = self.str_from(start); + sym.chars().count() == 1 && c == sym.chars().next().unwrap() + }) => { let sym = nfc_normalize(self.str_from(start)); let span = self.mk_sp(start, self.pos); - self.psess.bad_unicode_identifiers.borrow_mut().entry(sym).or_default() + self.psess + .bad_unicode_identifiers + .borrow_mut() + .entry(sym) + .or_default() .push(span); token::Ident(sym, IdentIsRaw::No) } @@ -259,9 +258,9 @@ impl<'psess, 'src> StringReader<'psess, 'src> { let suffix = if suffix_start < self.pos { let string = self.str_from(suffix_start); if string == "_" { - self - .dcx() - .emit_err(errors::UnderscoreLiteralSuffix { span: self.mk_sp(suffix_start, self.pos) }); + self.dcx().emit_err(errors::UnderscoreLiteralSuffix { + span: self.mk_sp(suffix_start, self.pos), + }); None } else { Some(Symbol::intern(string)) @@ -279,7 +278,8 @@ impl<'psess, 'src> StringReader<'psess, 'src> { self.last_lifetime = Some(self.mk_sp(start, start + BytePos(1))); if starts_with_number { let span = self.mk_sp(start, self.pos); - self.dcx().struct_err("lifetimes cannot start with a number") + self.dcx() + .struct_err("lifetimes cannot start with a number") .with_span(span) .stash(span, StashKey::LifetimeIsChar); } @@ -341,16 +341,19 @@ impl<'psess, 'src> StringReader<'psess, 'src> { // first remove compound tokens like `<<` from `rustc_lexer`, and then add // fancier error recovery to it, as there will be less overall work to do this // way. - let (token, sugg) = unicode_chars::check_for_substitution(self, start, c, repeats+1); + let (token, sugg) = + unicode_chars::check_for_substitution(self, start, c, repeats + 1); self.dcx().emit_err(errors::UnknownTokenStart { span: self.mk_sp(start, self.pos + Pos::from_usize(repeats * c.len_utf8())), escaped: escaped_char(c), sugg, - null: if c == '\x00' {Some(errors::UnknownTokenNull)} else {None}, + null: if c == '\x00' { Some(errors::UnknownTokenNull) } else { None }, repeat: if repeats > 0 { swallow_next_invalid = repeats; Some(errors::UnknownTokenRepeat { repeats }) - } else {None} + } else { + None + }, }); if let Some(token) = token { From 97910580aadab067ef13b5d0094a57e124c743ea Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Thu, 5 Sep 2024 05:43:55 -0400 Subject: [PATCH 0604/2194] Add initial support for raw lifetimes --- compiler/rustc_ast/src/mut_visit.rs | 4 +- compiler/rustc_ast/src/token.rs | 18 +++++---- compiler/rustc_ast/src/tokenstream.rs | 4 +- compiler/rustc_ast_pretty/src/pprust/state.rs | 13 +++++-- compiler/rustc_expand/src/mbe/macro_parser.rs | 6 ++- compiler/rustc_expand/src/mbe/transcribe.rs | 4 +- .../rustc_expand/src/proc_macro_server.rs | 9 +++-- compiler/rustc_lexer/src/lib.rs | 13 ++++++- compiler/rustc_lint/messages.ftl | 4 ++ .../rustc_lint/src/context/diagnostics.rs | 4 ++ compiler/rustc_lint/src/lints.rs | 9 +++++ compiler/rustc_lint_defs/src/lib.rs | 2 + compiler/rustc_parse/src/lexer/mod.rs | 39 +++++++++++++++++-- compiler/rustc_parse/src/parser/expr.rs | 6 +-- compiler/rustc_parse/src/parser/mod.rs | 2 +- .../rustc_parse/src/parser/nonterminal.rs | 6 +-- compiler/rustc_parse/src/parser/pat.rs | 6 +-- compiler/rustc_parse/src/parser/ty.rs | 7 ++-- 18 files changed, 116 insertions(+), 40 deletions(-) diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs index 8a66894a35603..7c8af6c4a5564 100644 --- a/compiler/rustc_ast/src/mut_visit.rs +++ b/compiler/rustc_ast/src/mut_visit.rs @@ -752,7 +752,7 @@ fn visit_lazy_tts(vis: &mut T, lazy_tts: &mut Option(vis: &mut T, t: &mut Token) { let Token { kind, span } = t; match kind { - token::Ident(name, _ /*raw*/) | token::Lifetime(name) => { + token::Ident(name, _is_raw) | token::Lifetime(name, _is_raw) => { let mut ident = Ident::new(*name, *span); vis.visit_ident(&mut ident); *name = ident.name; @@ -762,7 +762,7 @@ pub fn visit_token(vis: &mut T, t: &mut Token) { token::NtIdent(ident, _is_raw) => { vis.visit_ident(ident); } - token::NtLifetime(ident) => { + token::NtLifetime(ident, _is_raw) => { vis.visit_ident(ident); } token::Interpolated(nt) => { diff --git a/compiler/rustc_ast/src/token.rs b/compiler/rustc_ast/src/token.rs index f1dddb3acacaa..a0082a41713be 100644 --- a/compiler/rustc_ast/src/token.rs +++ b/compiler/rustc_ast/src/token.rs @@ -331,11 +331,11 @@ pub enum TokenKind { /// Do not forget about `NtLifetime` when you want to match on lifetime identifiers. /// It's recommended to use `Token::(lifetime,uninterpolate,uninterpolated_span)` to /// treat regular and interpolated lifetime identifiers in the same way. - Lifetime(Symbol), + Lifetime(Symbol, IdentIsRaw), /// This identifier (and its span) is the lifetime passed to the /// declarative macro. The span in the surrounding `Token` is the span of /// the `lifetime` metavariable in the macro's RHS. - NtLifetime(Ident), + NtLifetime(Ident, IdentIsRaw), /// An embedded AST node, as produced by a macro. This only exists for /// historical reasons. We'd like to get rid of it, for multiple reasons. @@ -458,7 +458,7 @@ impl Token { /// if they keep spans or perform edition checks. pub fn uninterpolated_span(&self) -> Span { match self.kind { - NtIdent(ident, _) | NtLifetime(ident) => ident.span, + NtIdent(ident, _) | NtLifetime(ident, _) => ident.span, Interpolated(ref nt) => nt.use_span(), _ => self.span, } @@ -661,7 +661,9 @@ impl Token { pub fn uninterpolate(&self) -> Cow<'_, Token> { match self.kind { NtIdent(ident, is_raw) => Cow::Owned(Token::new(Ident(ident.name, is_raw), ident.span)), - NtLifetime(ident) => Cow::Owned(Token::new(Lifetime(ident.name), ident.span)), + NtLifetime(ident, is_raw) => { + Cow::Owned(Token::new(Lifetime(ident.name, is_raw), ident.span)) + } _ => Cow::Borrowed(self), } } @@ -679,11 +681,11 @@ impl Token { /// Returns a lifetime identifier if this token is a lifetime. #[inline] - pub fn lifetime(&self) -> Option { + pub fn lifetime(&self) -> Option<(Ident, IdentIsRaw)> { // We avoid using `Token::uninterpolate` here because it's slow. match self.kind { - Lifetime(name) => Some(Ident::new(name, self.span)), - NtLifetime(ident) => Some(ident), + Lifetime(name, is_raw) => Some((Ident::new(name, self.span), is_raw)), + NtLifetime(ident, is_raw) => Some((ident, is_raw)), _ => None, } } @@ -865,7 +867,7 @@ impl Token { _ => return None, }, SingleQuote => match joint.kind { - Ident(name, IdentIsRaw::No) => Lifetime(Symbol::intern(&format!("'{name}"))), + Ident(name, is_raw) => Lifetime(Symbol::intern(&format!("'{name}")), is_raw), _ => return None, }, diff --git a/compiler/rustc_ast/src/tokenstream.rs b/compiler/rustc_ast/src/tokenstream.rs index 057b4455dca89..fc1dd2caf681a 100644 --- a/compiler/rustc_ast/src/tokenstream.rs +++ b/compiler/rustc_ast/src/tokenstream.rs @@ -482,11 +482,11 @@ impl TokenStream { token::NtIdent(ident, is_raw) => { TokenTree::Token(Token::new(token::Ident(ident.name, is_raw), ident.span), spacing) } - token::NtLifetime(ident) => TokenTree::Delimited( + token::NtLifetime(ident, is_raw) => TokenTree::Delimited( DelimSpan::from_single(token.span), DelimSpacing::new(Spacing::JointHidden, spacing), Delimiter::Invisible, - TokenStream::token_alone(token::Lifetime(ident.name), ident.span), + TokenStream::token_alone(token::Lifetime(ident.name, is_raw), ident.span), ), token::Interpolated(ref nt) => TokenTree::Delimited( DelimSpan::from_single(token.span), diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs index c7ff39d23ed26..3b1449d9a9113 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state.rs @@ -11,7 +11,9 @@ use std::borrow::Cow; use ast::TraitBoundModifiers; use rustc_ast::attr::AttrIdGenerator; use rustc_ast::ptr::P; -use rustc_ast::token::{self, BinOpToken, CommentKind, Delimiter, Nonterminal, Token, TokenKind}; +use rustc_ast::token::{ + self, BinOpToken, CommentKind, Delimiter, IdentIsRaw, Nonterminal, Token, TokenKind, +}; use rustc_ast::tokenstream::{Spacing, TokenStream, TokenTree}; use rustc_ast::util::classify; use rustc_ast::util::comments::{Comment, CommentStyle}; @@ -947,8 +949,13 @@ pub trait PrintState<'a>: std::ops::Deref + std::ops::Dere token::NtIdent(ident, is_raw) => { IdentPrinter::for_ast_ident(ident, is_raw.into()).to_string().into() } - token::Lifetime(name) => name.to_string().into(), - token::NtLifetime(ident) => ident.name.to_string().into(), + + token::Lifetime(name, IdentIsRaw::No) + | token::NtLifetime(Ident { name, .. }, IdentIsRaw::No) => name.to_string().into(), + token::Lifetime(name, IdentIsRaw::Yes) + | token::NtLifetime(Ident { name, .. }, IdentIsRaw::Yes) => { + format!("'r#{}", &name.as_str()[1..]).into() + } /* Other */ token::DocComment(comment_kind, attr_style, data) => { diff --git a/compiler/rustc_expand/src/mbe/macro_parser.rs b/compiler/rustc_expand/src/mbe/macro_parser.rs index 9011d02da3358..501a2417fcf31 100644 --- a/compiler/rustc_expand/src/mbe/macro_parser.rs +++ b/compiler/rustc_expand/src/mbe/macro_parser.rs @@ -398,8 +398,10 @@ pub(crate) enum NamedMatch { fn token_name_eq(t1: &Token, t2: &Token) -> bool { if let (Some((ident1, is_raw1)), Some((ident2, is_raw2))) = (t1.ident(), t2.ident()) { ident1.name == ident2.name && is_raw1 == is_raw2 - } else if let (Some(ident1), Some(ident2)) = (t1.lifetime(), t2.lifetime()) { - ident1.name == ident2.name + } else if let (Some((ident1, is_raw1)), Some((ident2, is_raw2))) = + (t1.lifetime(), t2.lifetime()) + { + ident1.name == ident2.name && is_raw1 == is_raw2 } else { t1.kind == t2.kind } diff --git a/compiler/rustc_expand/src/mbe/transcribe.rs b/compiler/rustc_expand/src/mbe/transcribe.rs index b06910595bb25..39489a8df1bed 100644 --- a/compiler/rustc_expand/src/mbe/transcribe.rs +++ b/compiler/rustc_expand/src/mbe/transcribe.rs @@ -283,9 +283,9 @@ pub(super) fn transcribe<'a>( let kind = token::NtIdent(*ident, *is_raw); TokenTree::token_alone(kind, sp) } - MatchedSingle(ParseNtResult::Lifetime(ident)) => { + MatchedSingle(ParseNtResult::Lifetime(ident, is_raw)) => { marker.visit_span(&mut sp); - let kind = token::NtLifetime(*ident); + let kind = token::NtLifetime(*ident, *is_raw); TokenTree::token_alone(kind, sp) } MatchedSingle(ParseNtResult::Nt(nt)) => { diff --git a/compiler/rustc_expand/src/proc_macro_server.rs b/compiler/rustc_expand/src/proc_macro_server.rs index 4ff5da1a4bdfa..5798bcedc2263 100644 --- a/compiler/rustc_expand/src/proc_macro_server.rs +++ b/compiler/rustc_expand/src/proc_macro_server.rs @@ -229,15 +229,16 @@ impl FromInternal<(TokenStream, &mut Rustc<'_, '_>)> for Vec { + Lifetime(name, is_raw) => { let ident = symbol::Ident::new(name, span).without_first_quote(); trees.extend([ TokenTree::Punct(Punct { ch: b'\'', joint: true, span }), - TokenTree::Ident(Ident { sym: ident.name, is_raw: false, span }), + TokenTree::Ident(Ident { sym: ident.name, is_raw: is_raw.into(), span }), ]); } - NtLifetime(ident) => { - let stream = TokenStream::token_alone(token::Lifetime(ident.name), ident.span); + NtLifetime(ident, is_raw) => { + let stream = + TokenStream::token_alone(token::Lifetime(ident.name, is_raw), ident.span); trees.push(TokenTree::Group(Group { delimiter: pm::Delimiter::None, stream: Some(stream), diff --git a/compiler/rustc_lexer/src/lib.rs b/compiler/rustc_lexer/src/lib.rs index 6561e416cfa4b..60aab668cbaa6 100644 --- a/compiler/rustc_lexer/src/lib.rs +++ b/compiler/rustc_lexer/src/lib.rs @@ -97,6 +97,9 @@ pub enum TokenKind { /// and not the separator. UnknownPrefixLifetime, + /// `'r#lt`, which in edition < 2021 is split into several tokens: `'r # lt`. + RawLifetime, + /// Similar to the above, but *always* an error on every edition. This is used /// for emoji identifier recovery, as those are not meant to be ever accepted. InvalidPrefix, @@ -683,9 +686,17 @@ impl Cursor<'_> { return Literal { kind, suffix_start }; } + if self.first() == 'r' && self.second() == '#' && is_id_start(self.third()) { + // Eat "r" and `#`, and identifier start characters. + self.bump(); + self.bump(); + self.bump(); + self.eat_while(is_id_continue); + return RawLifetime; + } + // Either a lifetime or a character literal with // length greater than 1. - let starts_with_number = self.first().is_ascii_digit(); // Skip the literal contents. diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl index 759320b9eb65f..f7d5c27baef99 100644 --- a/compiler/rustc_lint/messages.ftl +++ b/compiler/rustc_lint/messages.ftl @@ -707,6 +707,10 @@ lint_range_endpoint_out_of_range = range endpoint is out of range for `{$ty}` lint_range_use_inclusive_range = use an inclusive range instead +lint_raw_prefix = prefix `'r` is reserved + .label = reserved prefix + .suggestion = insert whitespace here to avoid this being parsed as a prefix in Rust 2021 + lint_reason_must_be_string_literal = reason must be a string literal lint_reason_must_come_last = reason in lint attribute must come last diff --git a/compiler/rustc_lint/src/context/diagnostics.rs b/compiler/rustc_lint/src/context/diagnostics.rs index fd43afa174383..fbff210d87d21 100644 --- a/compiler/rustc_lint/src/context/diagnostics.rs +++ b/compiler/rustc_lint/src/context/diagnostics.rs @@ -172,6 +172,10 @@ pub(super) fn decorate_lint(sess: &Session, diagnostic: BuiltinLintDiag, diag: & } .decorate_lint(diag); } + BuiltinLintDiag::RawPrefix(label_span) => { + lints::RawPrefix { label: label_span, suggestion: label_span.shrink_to_hi() } + .decorate_lint(diag); + } BuiltinLintDiag::UnusedBuiltinAttribute { attr_name, macro_name, invoc_span } => { lints::UnusedBuiltinAttribute { invoc_span, attr_name, macro_name }.decorate_lint(diag); } diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index 9050f36acba7b..8b62e716929da 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -2772,6 +2772,15 @@ pub(crate) struct ReservedPrefix { pub prefix: String, } +#[derive(LintDiagnostic)] +#[diag(lint_raw_prefix)] +pub(crate) struct RawPrefix { + #[label] + pub label: Span, + #[suggestion(code = " ", applicability = "machine-applicable")] + pub suggestion: Span, +} + #[derive(LintDiagnostic)] #[diag(lint_unused_builtin_attribute)] pub(crate) struct UnusedBuiltinAttribute { diff --git a/compiler/rustc_lint_defs/src/lib.rs b/compiler/rustc_lint_defs/src/lib.rs index 6ee330416236f..2b2a67dc846f7 100644 --- a/compiler/rustc_lint_defs/src/lib.rs +++ b/compiler/rustc_lint_defs/src/lib.rs @@ -609,6 +609,8 @@ pub enum BuiltinLintDiag { LegacyDeriveHelpers(Span), OrPatternsBackCompat(Span, String), ReservedPrefix(Span, String), + /// `'r#` in edition < 2021. + RawPrefix(Span), TrailingMacro(bool, Ident), BreakWithLabelAndLoop(Span), UnicodeTextFlow(Span, String), diff --git a/compiler/rustc_parse/src/lexer/mod.rs b/compiler/rustc_parse/src/lexer/mod.rs index c0731cf31c333..a680e2a3bc257 100644 --- a/compiler/rustc_parse/src/lexer/mod.rs +++ b/compiler/rustc_parse/src/lexer/mod.rs @@ -13,7 +13,6 @@ use rustc_session::lint::builtin::{ }; use rustc_session::lint::BuiltinLintDiag; use rustc_session::parse::ParseSess; -use rustc_span::edition::Edition; use rustc_span::symbol::Symbol; use rustc_span::{BytePos, Pos, Span}; use tracing::debug; @@ -284,7 +283,41 @@ impl<'psess, 'src> StringReader<'psess, 'src> { .stash(span, StashKey::LifetimeIsChar); } let ident = Symbol::intern(lifetime_name); - token::Lifetime(ident) + token::Lifetime(ident, IdentIsRaw::No) + } + rustc_lexer::TokenKind::RawLifetime => { + self.last_lifetime = Some(self.mk_sp(start, start + BytePos(1))); + + let ident_start = start + BytePos(3); + let prefix_span = self.mk_sp(start, ident_start); + + if prefix_span.at_least_rust_2021() { + let lifetime_name_without_tick = self.str_from(ident_start); + // Put the `'` back onto the lifetime name. + let mut lifetime_name = String::with_capacity(lifetime_name_without_tick.len() + 1); + lifetime_name.push('\''); + lifetime_name += lifetime_name_without_tick; + let sym = Symbol::intern(&lifetime_name); + + token::Lifetime(sym, IdentIsRaw::Yes) + } else { + // Otherwise, this is just `'r`. Warn about it though. + self.psess.buffer_lint( + RUST_2021_PREFIXES_INCOMPATIBLE_SYNTAX, + prefix_span, + ast::CRATE_NODE_ID, + BuiltinLintDiag::RawPrefix(prefix_span), + ); + + // Reset the state so we just lex the `'r`. + let lt_start = start + BytePos(2); + self.pos = lt_start; + self.cursor = Cursor::new(&str_before[2 as usize..]); + + let lifetime_name = self.str_from(start); + let ident = Symbol::intern(lifetime_name); + token::Lifetime(ident, IdentIsRaw::No) + } } rustc_lexer::TokenKind::Semi => token::Semi, rustc_lexer::TokenKind::Comma => token::Comma, @@ -712,7 +745,7 @@ impl<'psess, 'src> StringReader<'psess, 'src> { let expn_data = prefix_span.ctxt().outer_expn_data(); - if expn_data.edition >= Edition::Edition2021 { + if expn_data.edition.at_least_rust_2021() { // In Rust 2021, this is a hard error. let sugg = if prefix == "rb" { Some(errors::UnknownPrefixSugg::UseBr(prefix_span)) diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 84684e808d940..ecc4cd96fafb0 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -2050,7 +2050,7 @@ impl<'a> Parser<'a> { }; // On an error path, eagerly consider a lifetime to be an unclosed character lit, if that // makes sense. - if let Some(ident) = self.token.lifetime() + if let Some((ident, IdentIsRaw::No)) = self.token.lifetime() && could_be_unclosed_char_literal(ident) { let lt = self.expect_lifetime(); @@ -2925,9 +2925,9 @@ impl<'a> Parser<'a> { } pub(crate) fn eat_label(&mut self) -> Option
section to close it, // since the section can be large and finding the [+] button is annoying. @@ -102,11 +119,11 @@ const moreExamples = toggle.querySelectorAll(".scraped-example"); toggle.querySelector("summary").addEventListener("click", () => { // Wrapping in setTimeout ensures the update happens after the elements are actually - // visible. This is necessary since updateScrapedExample calls scrollToLoc which + // visible. This is necessary since setupLoc calls scrollToLoc which // depends on offsetHeight, a property that requires an element to be visible to // compute correctly. setTimeout(() => { - onEachLazy(moreExamples, el => updateScrapedExample(el, true)); + onEachLazy(moreExamples, el => setupLoc(el, true)); }); }, {once: true}); }); diff --git a/src/librustdoc/html/templates/scraped_source.html b/src/librustdoc/html/templates/scraped_source.html index e1fc2e6937820..bd54bbf58d508 100644 --- a/src/librustdoc/html/templates/scraped_source.html +++ b/src/librustdoc/html/templates/scraped_source.html @@ -1,8 +1,8 @@
{# #} -
{# #} +
{# #} +
{# https://developers.google.com/search/docs/crawling-indexing/robots-meta-tag#data-nosnippet-attr Do not show "1 2 3 4 5 ..." in web search results. #}
{# #} @@ -18,16 +18,5 @@ {{code_html|safe}} {# #} {# #} - {% if info.needs_prev_next_buttons || info.needs_expansion %} -
- {% if info.needs_prev_next_buttons %} - {# #} - - {% endif %} - {% if info.needs_expansion %} - - {% endif %} -
- {% endif %}
{# #}
{# #} From 7358429c00bb874420866d5f78b7166e79ad9f1f Mon Sep 17 00:00:00 2001 From: Chris Denton Date: Sat, 7 Sep 2024 14:03:35 +0000 Subject: [PATCH 0646/2194] Split x86_64-msvc-ext into two jobs --- .../host-x86_64/x86_64-gnu-tools/checktools.sh | 12 +++++++----- src/ci/github-actions/jobs.yml | 14 ++++++++++++++ 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-tools/checktools.sh b/src/ci/docker/host-x86_64/x86_64-gnu-tools/checktools.sh index a5a5acc333be9..5b4da574efb65 100755 --- a/src/ci/docker/host-x86_64/x86_64-gnu-tools/checktools.sh +++ b/src/ci/docker/host-x86_64/x86_64-gnu-tools/checktools.sh @@ -58,8 +58,9 @@ case $HOST_TARGET in # Strangely, Linux targets do not work here. cargo always says # "error: cannot produce cdylib for ... as the target ... does not support these crate types". # Only run "pass" tests, which is quite a bit faster. - python3 "$X_PY" test --stage 2 src/tools/miri --target aarch64-apple-darwin --test-args pass - python3 "$X_PY" test --stage 2 src/tools/miri --target i686-pc-windows-gnu --test-args pass + #FIXME: Re-enable this once CI issues are fixed + #python3 "$X_PY" test --stage 2 src/tools/miri --target aarch64-apple-darwin --test-args pass + #python3 "$X_PY" test --stage 2 src/tools/miri --target i686-pc-windows-gnu --test-args pass ;; *) echo "FATAL: unexpected host $HOST_TARGET" @@ -68,6 +69,7 @@ case $HOST_TARGET in esac # Also smoke-test `x.py miri`. This doesn't run any actual tests (that would take too long), # but it ensures that the crates build properly when tested with Miri. -python3 "$X_PY" miri --stage 2 library/core --test-args notest -python3 "$X_PY" miri --stage 2 library/alloc --test-args notest -python3 "$X_PY" miri --stage 2 library/std --test-args notest +#FIXME: Re-enable this once CI issues are fixed +#python3 "$X_PY" miri --stage 2 library/core --test-args notest +#python3 "$X_PY" miri --stage 2 library/alloc --test-args notest +#python3 "$X_PY" miri --stage 2 library/std --test-args notest diff --git a/src/ci/github-actions/jobs.yml b/src/ci/github-actions/jobs.yml index 4de44c6dd39d7..7008d351a15d0 100644 --- a/src/ci/github-actions/jobs.yml +++ b/src/ci/github-actions/jobs.yml @@ -373,6 +373,20 @@ auto: DEPLOY_TOOLSTATES_JSON: toolstates-windows.json <<: *job-windows-8c + # Temporary builder to workaround CI issues + - image: x86_64-msvc-ext2 + env: + SCRIPT: > + python x.py test --stage 2 src/tools/miri --target aarch64-apple-darwin --test-args pass && + python x.py test --stage 2 src/tools/miri --target i686-pc-windows-gnu --test-args pass && + python x.py miri --stage 2 library/core --test-args notest && + python x.py miri --stage 2 library/alloc --test-args notest && + python x.py miri --stage 2 library/std --test-args notest + + HOST_TARGET: x86_64-pc-windows-msvc + RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc --enable-lld + <<: *job-windows-8c + # 32/64-bit MinGW builds. # # We are using MinGW with POSIX threads since LLVM requires From 79b87c57cbddc7ac4a6e9f7381616e77e3f443c5 Mon Sep 17 00:00:00 2001 From: "Tim (Theemathas) Chirananthavat" Date: Sat, 7 Sep 2024 21:06:49 +0700 Subject: [PATCH 0647/2194] Bless tests due to new method suggestions. --- tests/ui/privacy/suggest-box-new.stderr | 4 ++-- tests/ui/suggestions/deref-path-method.stderr | 2 +- tests/ui/ufcs/bad-builder.stderr | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/ui/privacy/suggest-box-new.stderr b/tests/ui/privacy/suggest-box-new.stderr index 8b01e8c3c10ef..1e28b9fbd86bd 100644 --- a/tests/ui/privacy/suggest-box-new.stderr +++ b/tests/ui/privacy/suggest-box-new.stderr @@ -44,7 +44,7 @@ LL | wtf: Some(Box::new_zeroed()), | ~~~~~~~~~~~~~~ LL | wtf: Some(Box::new_in(_, _)), | ~~~~~~~~~~~~~~ - and 10 other candidates + and 12 other candidates help: consider using the `Default` trait | LL | wtf: Some(::default()), @@ -89,7 +89,7 @@ LL | let _ = Box::new_zeroed(); | ~~~~~~~~~~~~~~ LL | let _ = Box::new_in(_, _); | ~~~~~~~~~~~~~~ - and 10 other candidates + and 12 other candidates help: consider using the `Default` trait | LL | let _ = ::default(); diff --git a/tests/ui/suggestions/deref-path-method.stderr b/tests/ui/suggestions/deref-path-method.stderr index b27d9aef06614..bfcc2307fd7fb 100644 --- a/tests/ui/suggestions/deref-path-method.stderr +++ b/tests/ui/suggestions/deref-path-method.stderr @@ -9,7 +9,7 @@ note: if you're trying to build a new `Vec<_, _>` consider using one of the foll Vec::::with_capacity Vec::::try_with_capacity Vec::::from_raw_parts - and 4 others + and 6 others --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL help: the function `contains` is implemented on `[_]` | diff --git a/tests/ui/ufcs/bad-builder.stderr b/tests/ui/ufcs/bad-builder.stderr index 9cfeb7a5d09d6..e466f94d0d842 100644 --- a/tests/ui/ufcs/bad-builder.stderr +++ b/tests/ui/ufcs/bad-builder.stderr @@ -9,7 +9,7 @@ note: if you're trying to build a new `Vec` consider using one of the followi Vec::::with_capacity Vec::::try_with_capacity Vec::::from_raw_parts - and 4 others + and 6 others --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL help: there is an associated function `new` with a similar name | From 896ccaa8acddcca4f44b7627210533d0f77459df Mon Sep 17 00:00:00 2001 From: Adam Sandberg Ericsson Date: Sun, 14 Apr 2024 16:47:44 +0100 Subject: [PATCH 0648/2194] restate GlobalAlloc method safety preconditions in terms of what the caller has to do for greater clarity --- library/core/src/alloc/global.rs | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/library/core/src/alloc/global.rs b/library/core/src/alloc/global.rs index a6f799c4a7deb..68f00d07529b1 100644 --- a/library/core/src/alloc/global.rs +++ b/library/core/src/alloc/global.rs @@ -124,8 +124,8 @@ pub unsafe trait GlobalAlloc { /// /// # Safety /// - /// This function is unsafe because undefined behavior can result - /// if the caller does not ensure that `layout` has non-zero size. + /// `layout` must have non-zero size. Attempting to allocate for a zero-sized `layout` may + /// result in undefined behavior. /// /// (Extension subtraits might provide more specific bounds on /// behavior, e.g., guarantee a sentinel address or a null pointer @@ -156,14 +156,14 @@ pub unsafe trait GlobalAlloc { /// /// # Safety /// - /// This function is unsafe because undefined behavior can result - /// if the caller does not ensure all of the following: + /// The caller must ensure: /// - /// * `ptr` must denote a block of memory currently allocated via - /// this allocator, + /// * `ptr` is a block of memory currently allocated via this allocator and, /// - /// * `layout` must be the same layout that was used - /// to allocate that block of memory. + /// * `layout` is the same layout that was used to allocate that block of + /// memory. + /// + /// Otherwise undefined behavior can result. #[stable(feature = "global_alloc", since = "1.28.0")] unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout); @@ -172,7 +172,8 @@ pub unsafe trait GlobalAlloc { /// /// # Safety /// - /// This function is unsafe for the same reasons that `alloc` is. + /// The caller has to ensure that `layout` has non-zero size. Like `alloc` + /// zero sized `layout` can result in undefined behaviour. /// However the allocated block of memory is guaranteed to be initialized. /// /// # Errors @@ -220,20 +221,21 @@ pub unsafe trait GlobalAlloc { /// /// # Safety /// - /// This function is unsafe because undefined behavior can result - /// if the caller does not ensure all of the following: + /// The caller must ensure that: /// - /// * `ptr` must be currently allocated via this allocator, + /// * `ptr` is allocated via this allocator, /// - /// * `layout` must be the same layout that was used + /// * `layout` is the same layout that was used /// to allocate that block of memory, /// - /// * `new_size` must be greater than zero. + /// * `new_size` is greater than zero. /// /// * `new_size`, when rounded up to the nearest multiple of `layout.align()`, - /// must not overflow `isize` (i.e., the rounded value must be less than or + /// does not overflow `isize` (i.e., the rounded value must be less than or /// equal to `isize::MAX`). /// + /// If these are not followed, undefined behaviour can result. + /// /// (Extension subtraits might provide more specific bounds on /// behavior, e.g., guarantee a sentinel address or a null pointer /// in response to a zero-size allocation request.) From 2f6307d1cca53c153bddee83f4331fe979c61fe4 Mon Sep 17 00:00:00 2001 From: Chris Denton Date: Sat, 7 Sep 2024 14:58:59 +0000 Subject: [PATCH 0649/2194] Fix checktools.sh non-msvc builds --- .../docker/host-x86_64/x86_64-gnu-tools/checktools.sh | 11 +++++++---- src/ci/github-actions/jobs.yml | 2 -- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-tools/checktools.sh b/src/ci/docker/host-x86_64/x86_64-gnu-tools/checktools.sh index 5b4da574efb65..d7a37712308b4 100755 --- a/src/ci/docker/host-x86_64/x86_64-gnu-tools/checktools.sh +++ b/src/ci/docker/host-x86_64/x86_64-gnu-tools/checktools.sh @@ -69,7 +69,10 @@ case $HOST_TARGET in esac # Also smoke-test `x.py miri`. This doesn't run any actual tests (that would take too long), # but it ensures that the crates build properly when tested with Miri. -#FIXME: Re-enable this once CI issues are fixed -#python3 "$X_PY" miri --stage 2 library/core --test-args notest -#python3 "$X_PY" miri --stage 2 library/alloc --test-args notest -#python3 "$X_PY" miri --stage 2 library/std --test-args notest + +#FIXME: Re-enable this for msvc once CI issues are fixed +if [ "$HOST_TARGET" != "x86_64-pc-windows-msvc" ] + python3 "$X_PY" miri --stage 2 library/core --test-args notest + python3 "$X_PY" miri --stage 2 library/alloc --test-args notest + python3 "$X_PY" miri --stage 2 library/std --test-args notest +fi diff --git a/src/ci/github-actions/jobs.yml b/src/ci/github-actions/jobs.yml index 7008d351a15d0..e237e98b7b788 100644 --- a/src/ci/github-actions/jobs.yml +++ b/src/ci/github-actions/jobs.yml @@ -382,8 +382,6 @@ auto: python x.py miri --stage 2 library/core --test-args notest && python x.py miri --stage 2 library/alloc --test-args notest && python x.py miri --stage 2 library/std --test-args notest - - HOST_TARGET: x86_64-pc-windows-msvc RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc --enable-lld <<: *job-windows-8c From ae5326b967d5a3d34d3c562882feeacd9839950c Mon Sep 17 00:00:00 2001 From: y21 <30553356+y21@users.noreply.github.com> Date: Sat, 7 Sep 2024 17:06:32 +0200 Subject: [PATCH 0650/2194] visit struct fields in uninit fallback check --- clippy_utils/src/ty.rs | 11 +++++++---- tests/ui/uninit_vec.rs | 32 ++++++++++++++++++++++++++++++++ tests/ui/uninit_vec.stderr | 24 +++++++++++++++++++++++- 3 files changed, 62 insertions(+), 5 deletions(-) diff --git a/clippy_utils/src/ty.rs b/clippy_utils/src/ty.rs index f80981c11af65..5756e56c262e0 100644 --- a/clippy_utils/src/ty.rs +++ b/clippy_utils/src/ty.rs @@ -606,10 +606,13 @@ fn is_uninit_value_valid_for_ty_fallback<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'t ty::Tuple(types) => types.iter().all(|ty| is_uninit_value_valid_for_ty(cx, ty)), // Unions are always fine right now. // This includes MaybeUninit, the main way people use uninitialized memory. - // For ADTs, we could look at all fields just like for tuples, but that's potentially - // exponential, so let's avoid doing that for now. Code doing that is sketchy enough to - // just use an `#[allow()]`. - ty::Adt(adt, _) => adt.is_union(), + ty::Adt(adt, _) if adt.is_union() => true, + // Types (e.g. `UnsafeCell>`) that recursively contain only types that can be uninit + // can themselves be uninit too. + // This purposefully ignores enums as they may have a discriminant that can't be uninit. + ty::Adt(adt, args) if adt.is_struct() => adt + .all_fields() + .all(|field| is_uninit_value_valid_for_ty(cx, field.ty(cx.tcx, args))), // For the rest, conservatively assume that they cannot be uninit. _ => false, } diff --git a/tests/ui/uninit_vec.rs b/tests/ui/uninit_vec.rs index 0cc77a8775d57..464f88140bdba 100644 --- a/tests/ui/uninit_vec.rs +++ b/tests/ui/uninit_vec.rs @@ -150,4 +150,36 @@ fn main() { vec.set_len(10); } } + + fn nested_union() { + let mut vec: Vec>> = Vec::with_capacity(1); + unsafe { + vec.set_len(1); + } + } + + struct Recursive(*const Recursive, MaybeUninit); + fn recursive_union() { + // Make sure we don't stack overflow on recursive types. + // The pointer acts as the base case because it can't be uninit regardless of its pointee. + + let mut vec: Vec> = Vec::with_capacity(1); + //~^ uninit_vec + unsafe { + vec.set_len(1); + } + } + + #[repr(u8)] + enum Enum { + Variant(T), + } + fn union_in_enum() { + // Enums can have a discriminant that can't be uninit, so this should still warn + let mut vec: Vec> = Vec::with_capacity(1); + //~^ uninit_vec + unsafe { + vec.set_len(1); + } + } } diff --git a/tests/ui/uninit_vec.stderr b/tests/ui/uninit_vec.stderr index e8b77d653f089..e7c81cf792f23 100644 --- a/tests/ui/uninit_vec.stderr +++ b/tests/ui/uninit_vec.stderr @@ -125,5 +125,27 @@ LL | vec.set_len(10); | = help: initialize the buffer or wrap the content in `MaybeUninit` -error: aborting due to 12 previous errors +error: calling `set_len()` immediately after reserving a buffer creates uninitialized values + --> tests/ui/uninit_vec.rs:166:9 + | +LL | let mut vec: Vec> = Vec::with_capacity(1); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | vec.set_len(1); + | ^^^^^^^^^^^^^^ + | + = help: initialize the buffer or wrap the content in `MaybeUninit` + +error: calling `set_len()` immediately after reserving a buffer creates uninitialized values + --> tests/ui/uninit_vec.rs:179:9 + | +LL | let mut vec: Vec> = Vec::with_capacity(1); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | vec.set_len(1); + | ^^^^^^^^^^^^^^ + | + = help: initialize the buffer or wrap the content in `MaybeUninit` + +error: aborting due to 14 previous errors From 0d94e6bac90a804041cf1847e034001b7517e29a Mon Sep 17 00:00:00 2001 From: Chris Denton Date: Sat, 7 Sep 2024 16:36:53 +0000 Subject: [PATCH 0651/2194] Fix bash syntax --- src/ci/docker/host-x86_64/x86_64-gnu-tools/checktools.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-tools/checktools.sh b/src/ci/docker/host-x86_64/x86_64-gnu-tools/checktools.sh index d7a37712308b4..303a2f26c0f82 100755 --- a/src/ci/docker/host-x86_64/x86_64-gnu-tools/checktools.sh +++ b/src/ci/docker/host-x86_64/x86_64-gnu-tools/checktools.sh @@ -71,7 +71,7 @@ esac # but it ensures that the crates build properly when tested with Miri. #FIXME: Re-enable this for msvc once CI issues are fixed -if [ "$HOST_TARGET" != "x86_64-pc-windows-msvc" ] +if [ "$HOST_TARGET" != "x86_64-pc-windows-msvc" ]; then python3 "$X_PY" miri --stage 2 library/core --test-args notest python3 "$X_PY" miri --stage 2 library/alloc --test-args notest python3 "$X_PY" miri --stage 2 library/std --test-args notest From 4db9c01f8b1e7cfc82a5bcd522d72f9e6a84fdf1 Mon Sep 17 00:00:00 2001 From: DeSevilla Date: Sat, 7 Sep 2024 13:36:09 -0400 Subject: [PATCH 0652/2194] Renamed variable and fixed comments referring to renamed FileDescriptor --- src/tools/miri/src/shims/unix/fd.rs | 14 +++++++------- src/tools/miri/src/shims/unix/fs.rs | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/tools/miri/src/shims/unix/fd.rs b/src/tools/miri/src/shims/unix/fd.rs index 3ca5f6bb2dff5..d756c06ebdb12 100644 --- a/src/tools/miri/src/shims/unix/fd.rs +++ b/src/tools/miri/src/shims/unix/fd.rs @@ -21,7 +21,7 @@ pub(crate) enum FlockOp { Unlock, } -/// Represents an open file descriptor. +/// Represents an open file description. pub trait FileDescription: std::fmt::Debug + Any { fn name(&self) -> &'static str; @@ -303,7 +303,7 @@ pub struct FdTable { impl VisitProvenance for FdTable { fn visit_provenance(&self, _visit: &mut VisitWith<'_>) { - // All our FileDescriptor do not have any tags. + // All our FileDescriptionRef do not have any tags. } } @@ -411,7 +411,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { fn flock(&mut self, fd: i32, op: i32) -> InterpResult<'tcx, Scalar> { let this = self.eval_context_mut(); - let Some(file_descriptor) = this.machine.fds.get(fd) else { + let Some(fd_ref) = this.machine.fds.get(fd) else { return Ok(Scalar::from_i32(this.fd_not_found()?)); }; @@ -436,8 +436,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { throw_unsup_format!("unsupported flags {:#x}", op); }; - let result = file_descriptor.flock(this.machine.communicate(), parsed_op)?; - drop(file_descriptor); + let result = fd_ref.flock(this.machine.communicate(), parsed_op)?; + drop(fd_ref); // return `0` if flock is successful let result = result.map(|()| 0i32); Ok(Scalar::from_i32(this.try_unwrap_io_result(result)?)) @@ -539,7 +539,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { ) -> InterpResult<'tcx, Scalar> { let this = self.eval_context_mut(); - // Isolation check is done via `FileDescriptor` trait. + // Isolation check is done via `FileDescription` trait. trace!("Reading from FD {}, size {}", fd, count); @@ -604,7 +604,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { ) -> InterpResult<'tcx, Scalar> { let this = self.eval_context_mut(); - // Isolation check is done via `FileDescriptor` trait. + // Isolation check is done via `FileDescription` trait. // Check that the *entire* buffer is actually valid memory. this.check_ptr_access(buf, Size::from_bytes(count), CheckInAllocMsg::MemoryAccessTest)?; diff --git a/src/tools/miri/src/shims/unix/fs.rs b/src/tools/miri/src/shims/unix/fs.rs index e00758bb98de6..58d3a73b481d2 100644 --- a/src/tools/miri/src/shims/unix/fs.rs +++ b/src/tools/miri/src/shims/unix/fs.rs @@ -557,7 +557,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { fn lseek64(&mut self, fd: i32, offset: i128, whence: i32) -> InterpResult<'tcx, Scalar> { let this = self.eval_context_mut(); - // Isolation check is done via `FileDescriptor` trait. + // Isolation check is done via `FileDescription` trait. let seek_from = if whence == this.eval_libc_i32("SEEK_SET") { if offset < 0 { From a8a7fd418e217f6b0e66eaa81c3139efdb9174cc Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 7 Sep 2024 21:00:10 +0200 Subject: [PATCH 0653/2194] str: make as_mut_ptr and as_bytes_mut unstably const --- library/core/src/str/mod.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/library/core/src/str/mod.rs b/library/core/src/str/mod.rs index cf9f1bfc0eb72..e947686487e06 100644 --- a/library/core/src/str/mod.rs +++ b/library/core/src/str/mod.rs @@ -338,9 +338,10 @@ impl str { /// assert_eq!("🍔∈🌏", s); /// ``` #[stable(feature = "str_mut_extras", since = "1.20.0")] + #[rustc_const_unstable(feature = "const_str_as_mut", issue = "130086")] #[must_use] #[inline(always)] - pub unsafe fn as_bytes_mut(&mut self) -> &mut [u8] { + pub const unsafe fn as_bytes_mut(&mut self) -> &mut [u8] { // SAFETY: the cast from `&str` to `&[u8]` is safe since `str` // has the same layout as `&[u8]` (only std can make this guarantee). // The pointer dereference is safe since it comes from a mutable reference which @@ -383,10 +384,11 @@ impl str { /// It is your responsibility to make sure that the string slice only gets /// modified in a way that it remains valid UTF-8. #[stable(feature = "str_as_mut_ptr", since = "1.36.0")] + #[rustc_const_unstable(feature = "const_str_as_mut", issue = "130086")] #[rustc_never_returns_null_ptr] #[must_use] #[inline(always)] - pub fn as_mut_ptr(&mut self) -> *mut u8 { + pub const fn as_mut_ptr(&mut self) -> *mut u8 { self as *mut str as *mut u8 } From f7d4da65c7df37c316d9e2793dff1ae6c994c44d Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 7 Sep 2024 21:41:28 +0200 Subject: [PATCH 0654/2194] remove 'const' from 'Option::iter' --- library/core/src/option.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/library/core/src/option.rs b/library/core/src/option.rs index 50cb22b7eb3f5..b48c6136a4577 100644 --- a/library/core/src/option.rs +++ b/library/core/src/option.rs @@ -1338,9 +1338,8 @@ impl Option { /// assert_eq!(x.iter().next(), None); /// ``` #[inline] - #[rustc_const_unstable(feature = "const_option", issue = "67441")] #[stable(feature = "rust1", since = "1.0.0")] - pub const fn iter(&self) -> Iter<'_, T> { + pub fn iter(&self) -> Iter<'_, T> { Iter { inner: Item { opt: self.as_ref() } } } From 25efc04ea554301374ac8e6270dbc7f65fead347 Mon Sep 17 00:00:00 2001 From: Jake Herrmann Date: Sat, 7 Sep 2024 12:00:34 -0800 Subject: [PATCH 0655/2194] Fix typo --- clippy_lints/src/ptr.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/ptr.rs b/clippy_lints/src/ptr.rs index 125f694996c1c..7d24d25dc2fa4 100644 --- a/clippy_lints/src/ptr.rs +++ b/clippy_lints/src/ptr.rs @@ -34,7 +34,7 @@ declare_clippy_lint! { /// with the appropriate `.to_owned()`/`to_string()` calls. /// /// ### Why is this bad? - /// Requiring the argument to be of the specific size + /// Requiring the argument to be of the specific type /// makes the function less useful for no benefit; slices in the form of `&[T]` /// or `&str` usually suffice and can be obtained from other types, too. /// From 03e0c8edb2114aaf92fb8d93a18dfb0028690765 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 7 Sep 2024 22:19:30 +0200 Subject: [PATCH 0656/2194] make Result::copied unstably const --- library/core/src/result.rs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/library/core/src/result.rs b/library/core/src/result.rs index 73b11f803d929..a7fd95e007982 100644 --- a/library/core/src/result.rs +++ b/library/core/src/result.rs @@ -1535,11 +1535,17 @@ impl Result<&T, E> { /// ``` #[inline] #[stable(feature = "result_copied", since = "1.59.0")] - pub fn copied(self) -> Result + #[rustc_const_unstable(feature = "const_result", issue = "82814")] + pub const fn copied(self) -> Result where T: Copy, { - self.map(|&t| t) + // FIXME: this implementation, which sidesteps using `Result::map` since it's not const + // ready yet, should be reverted when possible to avoid code repetition + match self { + Ok(&v) => Ok(v), + Err(e) => Err(e), + } } /// Maps a `Result<&T, E>` to a `Result` by cloning the contents of the From cfe85a3a73ab756acd5fb85cebcb7c89aa1df4c8 Mon Sep 17 00:00:00 2001 From: Zack Slayton Date: Sat, 7 Sep 2024 17:36:47 -0400 Subject: [PATCH 0657/2194] Fixes typo in wasm32-wasip2 doc comment --- compiler/rustc_target/src/spec/targets/wasm32_wasip2.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_target/src/spec/targets/wasm32_wasip2.rs b/compiler/rustc_target/src/spec/targets/wasm32_wasip2.rs index 40f026ca93814..876aa7073f812 100644 --- a/compiler/rustc_target/src/spec/targets/wasm32_wasip2.rs +++ b/compiler/rustc_target/src/spec/targets/wasm32_wasip2.rs @@ -1,6 +1,6 @@ //! The `wasm32-wasip2` 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 +//! active development, the preview 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 From 3782251c2c6e6e7fedb806a97664ee38ced1677b Mon Sep 17 00:00:00 2001 From: EtomicBomb Date: Mon, 26 Aug 2024 21:40:52 -0700 Subject: [PATCH 0658/2194] librustdoc::config: removed Input from Options The `librustdoc::config::Options` struct no longer includes `rustc_session::config::Input`. This is so that Input can be optional. In rfc#3662, the crate input is not required if `--merge=finalize`. Replacing Input with Option was decided against. In most places that Input is needed, it should be statically known to not be optional (means fewer unwraps). We just want to have an Input-free Options in librustdoc::main_args, where we can run the write shared procedure. --- src/librustdoc/config.rs | 18 ++++++------------ src/librustdoc/core.rs | 4 ++-- src/librustdoc/doctest.rs | 10 +++++++--- src/librustdoc/doctest/markdown.rs | 11 +++++------ src/librustdoc/lib.rs | 26 ++++++++++++++------------ 5 files changed, 34 insertions(+), 35 deletions(-) diff --git a/src/librustdoc/config.rs b/src/librustdoc/config.rs index 9e7b69ec45faa..7e4e8fd506f5f 100644 --- a/src/librustdoc/config.rs +++ b/src/librustdoc/config.rs @@ -57,8 +57,6 @@ impl TryFrom<&str> for OutputFormat { #[derive(Clone)] pub(crate) struct Options { // Basic options / Options passed directly to rustc - /// The crate root or Markdown file to load. - pub(crate) input: Input, /// The name of the crate being documented. pub(crate) crate_name: Option, /// Whether or not this is a bin crate @@ -179,7 +177,6 @@ impl fmt::Debug for Options { } f.debug_struct("Options") - .field("input", &self.input.source_name()) .field("crate_name", &self.crate_name) .field("bin_crate", &self.bin_crate) .field("proc_macro_crate", &self.proc_macro_crate) @@ -348,7 +345,7 @@ impl Options { early_dcx: &mut EarlyDiagCtxt, matches: &getopts::Matches, args: Vec, - ) -> Option<(Options, RenderOptions)> { + ) -> Option<(Input, Options, RenderOptions)> { // Check for unstable options. nightly_options::check_nightly_options(early_dcx, matches, &opts()); @@ -751,7 +748,6 @@ impl Options { let unstable_features = rustc_feature::UnstableFeatures::from_environment(crate_name.as_deref()); let options = Options { - input, bin_crate, proc_macro_crate, error_format, @@ -824,15 +820,13 @@ impl Options { html_no_source, output_to_stdout, }; - Some((options, render_options)) + Some((input, options, render_options)) } +} - /// Returns `true` if the file given as `self.input` is a Markdown file. - pub(crate) fn markdown_input(&self) -> Option<&Path> { - self.input - .opt_path() - .filter(|p| matches!(p.extension(), Some(e) if e == "md" || e == "markdown")) - } +/// Returns `true` if the file given as `self.input` is a Markdown file. +pub(crate) fn markdown_input(input: &Input) -> Option<&Path> { + input.opt_path().filter(|p| matches!(p.extension(), Some(e) if e == "md" || e == "markdown")) } fn parse_remap_path_prefix( diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index 2cde0ac5c5354..4fafef657925f 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -20,7 +20,7 @@ use rustc_interface::interface; use rustc_lint::{late_lint_mod, MissingDoc}; use rustc_middle::hir::nested_filter; use rustc_middle::ty::{ParamEnv, Ty, TyCtxt}; -use rustc_session::config::{self, CrateType, ErrorOutputType, ResolveDocLinks}; +use rustc_session::config::{self, CrateType, ErrorOutputType, Input, ResolveDocLinks}; pub(crate) use rustc_session::config::{Options, UnstableOptions}; use rustc_session::{lint, Session}; use rustc_span::symbol::sym; @@ -177,8 +177,8 @@ pub(crate) fn new_dcx( /// Parse, resolve, and typecheck the given crate. pub(crate) fn create_config( + input: Input, RustdocOptions { - input, crate_name, proc_macro_crate, error_format, diff --git a/src/librustdoc/doctest.rs b/src/librustdoc/doctest.rs index 8b6588ea75c83..05ef72892012d 100644 --- a/src/librustdoc/doctest.rs +++ b/src/librustdoc/doctest.rs @@ -19,7 +19,7 @@ use rustc_errors::{ColorConfig, DiagCtxtHandle, ErrorGuaranteed, FatalError}; use rustc_hir::def_id::LOCAL_CRATE; use rustc_hir::CRATE_HIR_ID; use rustc_interface::interface; -use rustc_session::config::{self, CrateType, ErrorOutputType}; +use rustc_session::config::{self, CrateType, ErrorOutputType, Input}; use rustc_session::lint; use rustc_span::edition::Edition; use rustc_span::symbol::sym; @@ -88,7 +88,11 @@ fn get_doctest_dir() -> io::Result { TempFileBuilder::new().prefix("rustdoctest").tempdir() } -pub(crate) fn run(dcx: DiagCtxtHandle<'_>, options: RustdocOptions) -> Result<(), ErrorGuaranteed> { +pub(crate) fn run( + dcx: DiagCtxtHandle<'_>, + input: Input, + options: RustdocOptions, +) -> Result<(), ErrorGuaranteed> { let invalid_codeblock_attributes_name = crate::lint::INVALID_CODEBLOCK_ATTRIBUTES.name; // See core::create_config for what's going on here. @@ -135,7 +139,7 @@ pub(crate) fn run(dcx: DiagCtxtHandle<'_>, options: RustdocOptions) -> Result<() opts: sessopts, crate_cfg: cfgs, crate_check_cfg: options.check_cfgs.clone(), - input: options.input.clone(), + input: input.clone(), output_file: None, output_dir: None, file_loader: None, diff --git a/src/librustdoc/doctest/markdown.rs b/src/librustdoc/doctest/markdown.rs index 9a237f8684d8f..4f83bd5e8826a 100644 --- a/src/librustdoc/doctest/markdown.rs +++ b/src/librustdoc/doctest/markdown.rs @@ -3,6 +3,7 @@ use std::fs::read_to_string; use std::sync::{Arc, Mutex}; +use rustc_session::config::Input; use rustc_span::FileName; use tempfile::tempdir; @@ -69,9 +70,8 @@ impl DocTestVisitor for MdCollector { } /// Runs any tests/code examples in the markdown file `options.input`. -pub(crate) fn test(options: Options) -> Result<(), String> { - use rustc_session::config::Input; - let input_str = match &options.input { +pub(crate) fn test(input: &Input, options: Options) -> Result<(), String> { + let input_str = match input { Input::File(path) => { read_to_string(path).map_err(|err| format!("{}: {err}", path.display()))? } @@ -79,7 +79,7 @@ pub(crate) fn test(options: Options) -> Result<(), String> { }; // Obviously not a real crate name, but close enough for purposes of doctests. - let crate_name = options.input.filestem().to_string(); + let crate_name = input.filestem().to_string(); let temp_dir = tempdir().map_err(|error| format!("failed to create temporary directory: {error:?}"))?; let args_file = temp_dir.path().join("rustdoc-cfgs"); @@ -96,8 +96,7 @@ pub(crate) fn test(options: Options) -> Result<(), String> { let mut md_collector = MdCollector { tests: vec![], cur_path: vec![], - filename: options - .input + filename: input .opt_path() .map(ToOwned::to_owned) .map(FileName::from) diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index f25acbe080ada..e470aef3643e9 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -727,22 +727,24 @@ fn main_args( // Note that we discard any distinction between different non-zero exit // codes from `from_matches` here. - let (options, render_options) = match config::Options::from_matches(early_dcx, &matches, args) { - Some(opts) => opts, - None => return Ok(()), - }; + let (input, options, render_options) = + match config::Options::from_matches(early_dcx, &matches, args) { + Some(opts) => opts, + None => return Ok(()), + }; let dcx = core::new_dcx(options.error_format, None, options.diagnostic_width, &options.unstable_opts); let dcx = dcx.handle(); - match (options.should_test, options.markdown_input()) { - (true, Some(_)) => return wrap_return(dcx, doctest::test_markdown(options)), - (true, None) => return doctest::run(dcx, options), - (false, Some(input)) => { - let input = input.to_owned(); + match (options.should_test, config::markdown_input(&input)) { + (true, Some(_)) => return wrap_return(dcx, doctest::test_markdown(&input, options)), + (true, None) => return doctest::run(dcx, input, options), + (false, Some(md_input)) => { + let md_input = md_input.to_owned(); let edition = options.edition; - let config = core::create_config(options, &render_options, using_internal_features); + let config = + core::create_config(input, options, &render_options, using_internal_features); // `markdown::render` can invoke `doctest::make_test`, which // requires session globals and a thread pool, so we use @@ -750,7 +752,7 @@ fn main_args( return wrap_return( dcx, interface::run_compiler(config, |_compiler| { - markdown::render(&input, render_options, edition) + markdown::render(&md_input, render_options, edition) }), ); } @@ -775,7 +777,7 @@ fn main_args( let scrape_examples_options = options.scrape_examples_options.clone(); let bin_crate = options.bin_crate; - let config = core::create_config(options, &render_options, using_internal_features); + let config = core::create_config(input, options, &render_options, using_internal_features); interface::run_compiler(config, |compiler| { let sess = &compiler.sess; From 2e1cba64157c9bf60f7bc010268ac0bd5ca9438c Mon Sep 17 00:00:00 2001 From: EtomicBomb Date: Tue, 20 Aug 2024 23:34:19 +0000 Subject: [PATCH 0659/2194] rfc#3662 changes under unstable flags * All new functionality is under unstable options * Adds `--merge=shared|none|finalize` flags * Adds `--parts-out-dir=` for `--merge=none` to write cross-crate info file for a single crate * Adds `--include-parts-dir=` for `--merge=finalize` to write cross-crate info files * update tests/run-make/rustdoc-default-output/rmake.rs golden --- src/librustdoc/config.rs | 109 ++++++++++- src/librustdoc/html/render/context.rs | 175 ++++++++--------- src/librustdoc/html/render/mod.rs | 1 + src/librustdoc/html/render/write_shared.rs | 178 +++++++++++++----- .../html/render/write_shared/tests.rs | 10 +- src/librustdoc/lib.rs | 64 +++++++ .../output-default.stdout | 17 ++ 7 files changed, 419 insertions(+), 135 deletions(-) diff --git a/src/librustdoc/config.rs b/src/librustdoc/config.rs index 7e4e8fd506f5f..b3c87a725080f 100644 --- a/src/librustdoc/config.rs +++ b/src/librustdoc/config.rs @@ -53,6 +53,14 @@ impl TryFrom<&str> for OutputFormat { } } +/// Either an input crate, markdown file, or nothing (--merge=finalize). +pub(crate) enum InputMode { + /// The `--merge=finalize` step does not need an input crate to rustdoc. + NoInputMergeFinalize, + /// A crate or markdown file. + HasFile(Input), +} + /// Configuration options for rustdoc. #[derive(Clone)] pub(crate) struct Options { @@ -286,6 +294,12 @@ pub(crate) struct RenderOptions { /// This field is only used for the JSON output. If it's set to true, no file will be created /// and content will be displayed in stdout directly. pub(crate) output_to_stdout: bool, + /// Whether we should read or write rendered cross-crate info in the doc root. + pub(crate) should_merge: ShouldMerge, + /// Path to crate-info for external crates. + pub(crate) include_parts_dir: Vec, + /// Where to write crate-info + pub(crate) parts_out_dir: Option, } #[derive(Copy, Clone, Debug, PartialEq, Eq)] @@ -345,7 +359,7 @@ impl Options { early_dcx: &mut EarlyDiagCtxt, matches: &getopts::Matches, args: Vec, - ) -> Option<(Input, Options, RenderOptions)> { + ) -> Option<(InputMode, Options, RenderOptions)> { // Check for unstable options. nightly_options::check_nightly_options(early_dcx, matches, &opts()); @@ -475,15 +489,17 @@ impl Options { let (lint_opts, describe_lints, lint_cap) = get_cmd_lint_options(early_dcx, matches); let input = if describe_lints { - "" // dummy, this won't be used + InputMode::HasFile(make_input(early_dcx, "")) } else { match matches.free.as_slice() { + [] if matches.opt_str("merge").as_deref() == Some("finalize") => { + InputMode::NoInputMergeFinalize + } [] => dcx.fatal("missing file operand"), - [input] => input, + [input] => InputMode::HasFile(make_input(early_dcx, input)), _ => dcx.fatal("too many file operands"), } }; - let input = make_input(early_dcx, input); let externs = parse_externs(early_dcx, matches, &unstable_opts); let extern_html_root_urls = match parse_extern_html_roots(matches) { @@ -491,6 +507,16 @@ impl Options { Err(err) => dcx.fatal(err), }; + let parts_out_dir = + match matches.opt_str("parts-out-dir").map(|p| PathToParts::from_flag(p)).transpose() { + Ok(parts_out_dir) => parts_out_dir, + Err(e) => dcx.fatal(e), + }; + let include_parts_dir = match parse_include_parts_dir(matches) { + Ok(include_parts_dir) => include_parts_dir, + Err(e) => dcx.fatal(e), + }; + let default_settings: Vec> = vec![ matches .opt_str("default-theme") @@ -732,6 +758,10 @@ impl Options { let extern_html_root_takes_precedence = matches.opt_present("extern-html-root-takes-precedence"); let html_no_source = matches.opt_present("html-no-source"); + let should_merge = match parse_merge(matches) { + Ok(result) => result, + Err(e) => dcx.fatal(format!("--merge option error: {e}")), + }; if generate_link_to_definition && (show_coverage || output_format != OutputFormat::Html) { dcx.struct_warn( @@ -819,6 +849,9 @@ impl Options { no_emit_shared: false, html_no_source, output_to_stdout, + should_merge, + include_parts_dir, + parts_out_dir, }; Some((input, options, render_options)) } @@ -894,3 +927,71 @@ fn parse_extern_html_roots( } Ok(externs) } + +/// Path directly to crate-info file. +/// +/// For example, `/home/user/project/target/doc.parts//crate-info`. +#[derive(Clone, Debug)] +pub(crate) struct PathToParts(pub(crate) PathBuf); + +impl PathToParts { + fn from_flag(path: String) -> Result { + let mut path = PathBuf::from(path); + // check here is for diagnostics + if path.exists() && !path.is_dir() { + Err(format!( + "--parts-out-dir and --include-parts-dir expect directories, found: {}", + path.display(), + )) + } else { + // if it doesn't exist, we'll create it. worry about that in write_shared + path.push("crate-info"); + Ok(PathToParts(path)) + } + } +} + +/// Reports error if --include-parts-dir / crate-info is not a file +fn parse_include_parts_dir(m: &getopts::Matches) -> Result, String> { + let mut ret = Vec::new(); + for p in m.opt_strs("include-parts-dir") { + let p = PathToParts::from_flag(p)?; + // this is just for diagnostic + if !p.0.is_file() { + return Err(format!("--include-parts-dir expected {} to be a file", p.0.display())); + } + ret.push(p); + } + Ok(ret) +} + +/// Controls merging of cross-crate information +#[derive(Debug, Clone)] +pub(crate) struct ShouldMerge { + /// Should we append to existing cci in the doc root + pub(crate) read_rendered_cci: bool, + /// Should we write cci to the doc root + pub(crate) write_rendered_cci: bool, +} + +/// Extracts read_rendered_cci and write_rendered_cci from command line arguments, or +/// reports an error if an invalid option was provided +fn parse_merge(m: &getopts::Matches) -> Result { + match m.opt_str("merge").as_deref() { + // default = read-write + None => Ok(ShouldMerge { read_rendered_cci: true, write_rendered_cci: true }), + Some("none") if m.opt_present("include-parts-dir") => { + Err("--include-parts-dir not allowed if --merge=none") + } + Some("none") => Ok(ShouldMerge { read_rendered_cci: false, write_rendered_cci: false }), + Some("shared") if m.opt_present("parts-out-dir") || m.opt_present("include-parts-dir") => { + Err("--parts-out-dir and --include-parts-dir not allowed if --merge=shared") + } + Some("shared") => Ok(ShouldMerge { read_rendered_cci: true, write_rendered_cci: true }), + Some("finalize") if m.opt_present("parts-out-dir") => { + Err("--parts-out-dir not allowed if --merge=finalize") + } + Some("finalize") => Ok(ShouldMerge { read_rendered_cci: false, write_rendered_cci: true }), + Some(_) => Err("argument to --merge must be `none`, `shared`, or `finalize`"), + } +} diff --git a/src/librustdoc/html/render/context.rs b/src/librustdoc/html/render/context.rs index 9fe43e428f2ae..902ccd23e8afc 100644 --- a/src/librustdoc/html/render/context.rs +++ b/src/librustdoc/html/render/context.rs @@ -16,12 +16,11 @@ use tracing::info; use super::print_item::{full_path, item_path, print_item}; use super::sidebar::{print_sidebar, sidebar_module_like, ModuleLike, Sidebar}; -use super::write_shared::write_shared; use super::{collect_spans_and_sources, scrape_examples_help, AllTypes, LinkFromSrc, StylePath}; use crate::clean::types::ExternalLocation; use crate::clean::utils::has_doc_flag; use crate::clean::{self, ExternalCrate}; -use crate::config::{ModuleSorting, RenderOptions}; +use crate::config::{ModuleSorting, RenderOptions, ShouldMerge}; use crate::docfs::{DocFS, PathError}; use crate::error::Error; use crate::formats::cache::Cache; @@ -30,6 +29,7 @@ use crate::formats::FormatRenderer; use crate::html::escape::Escape; use crate::html::format::{join_with_double_colon, Buffer}; use crate::html::markdown::{self, plain_text_summary, ErrorCodes, IdMap}; +use crate::html::render::write_shared::write_shared; use crate::html::url_parts_builder::UrlPartsBuilder; use crate::html::{layout, sources, static_files}; use crate::scrape_examples::AllCallLocations; @@ -128,8 +128,10 @@ pub(crate) struct SharedContext<'tcx> { pub(crate) span_correspondence_map: FxHashMap, /// The [`Cache`] used during rendering. pub(crate) cache: Cache, - pub(crate) call_locations: AllCallLocations, + /// Controls whether we read / write to cci files in the doc root. Defaults read=true, + /// write=true + should_merge: ShouldMerge, } impl SharedContext<'_> { @@ -551,6 +553,7 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> { span_correspondence_map: matches, cache, call_locations, + should_merge: options.should_merge, }; let dst = output; @@ -640,92 +643,96 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> { ); shared.fs.write(final_file, v)?; - // Generating settings page. - page.title = "Settings"; - page.description = "Settings of Rustdoc"; - page.root_path = "./"; - page.rust_logo = true; + // if to avoid writing help, settings files to doc root unless we're on the final invocation + if shared.should_merge.write_rendered_cci { + // Generating settings page. + page.title = "Settings"; + page.description = "Settings of Rustdoc"; + page.root_path = "./"; + page.rust_logo = true; - let sidebar = "

Settings

"; - let v = layout::render( - &shared.layout, - &page, - sidebar, - |buf: &mut Buffer| { - write!( - buf, - "
\ -

Rustdoc settings

\ - \ - \ - Back\ - \ - \ -
\ - \ - ", - static_root_path = page.get_static_root_path(), - settings_js = static_files::STATIC_FILES.settings_js, - ); - // Pre-load all theme CSS files, so that switching feels seamless. - // - // When loading settings.html as a popover, the equivalent HTML is - // generated in main.js. - for file in &shared.style_files { - if let Ok(theme) = file.basename() { - write!( - buf, - "", - root_path = page.static_root_path.unwrap_or(""), - suffix = page.resource_suffix, - ); + let sidebar = "

Settings

"; + let v = layout::render( + &shared.layout, + &page, + sidebar, + |buf: &mut Buffer| { + write!( + buf, + "
\ +

Rustdoc settings

\ + \ + \ + Back\ + \ + \ +
\ + \ + ", + static_root_path = page.get_static_root_path(), + settings_js = static_files::STATIC_FILES.settings_js, + ); + // Pre-load all theme CSS files, so that switching feels seamless. + // + // When loading settings.html as a popover, the equivalent HTML is + // generated in main.js. + for file in &shared.style_files { + if let Ok(theme) = file.basename() { + write!( + buf, + "", + root_path = page.static_root_path.unwrap_or(""), + suffix = page.resource_suffix, + ); + } } - } - }, - &shared.style_files, - ); - shared.fs.write(settings_file, v)?; + }, + &shared.style_files, + ); + shared.fs.write(settings_file, v)?; - // Generating help page. - page.title = "Help"; - page.description = "Documentation for Rustdoc"; - page.root_path = "./"; - page.rust_logo = true; + // Generating help page. + page.title = "Help"; + page.description = "Documentation for Rustdoc"; + page.root_path = "./"; + page.rust_logo = true; - let sidebar = "

Help

"; - let v = layout::render( - &shared.layout, - &page, - sidebar, - |buf: &mut Buffer| { - write!( - buf, - "
\ -

Rustdoc help

\ - \ - \ - Back\ - \ - \ -
\ - ", - ) - }, - &shared.style_files, - ); - shared.fs.write(help_file, v)?; + let sidebar = "

Help

"; + let v = layout::render( + &shared.layout, + &page, + sidebar, + |buf: &mut Buffer| { + write!( + buf, + "
\ +

Rustdoc help

\ + \ + \ + Back\ + \ + \ +
\ + ", + ) + }, + &shared.style_files, + ); + shared.fs.write(help_file, v)?; + } - if shared.layout.scrape_examples_extension { + // if to avoid writing files to doc root unless we're on the final invocation + if shared.layout.scrape_examples_extension && shared.should_merge.write_rendered_cci { page.title = "About scraped examples"; page.description = "How the scraped examples feature works in Rustdoc"; let v = layout::render( diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index f67d006116cb6..245d805555229 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -61,6 +61,7 @@ use tracing::{debug, info}; pub(crate) use self::context::*; pub(crate) use self::span_map::{collect_spans_and_sources, LinkFromSrc}; +pub(crate) use self::write_shared::*; use crate::clean::{self, ItemId, RenderedLink}; use crate::error::Error; use crate::formats::cache::Cache; diff --git a/src/librustdoc/html/render/write_shared.rs b/src/librustdoc/html/render/write_shared.rs index b0af8d8c23ee5..302c454b2a11e 100644 --- a/src/librustdoc/html/render/write_shared.rs +++ b/src/librustdoc/html/render/write_shared.rs @@ -39,7 +39,7 @@ use serde::{Deserialize, Serialize, Serializer}; use super::{collect_paths_for_type, ensure_trailing_slash, Context, RenderMode}; use crate::clean::{Crate, Item, ItemId, ItemKind}; -use crate::config::{EmitType, RenderOptions}; +use crate::config::{EmitType, PathToParts, RenderOptions, ShouldMerge}; use crate::docfs::PathError; use crate::error::Error; use crate::formats::cache::Cache; @@ -50,12 +50,11 @@ use crate::html::layout; use crate::html::render::ordered_json::{EscapedJson, OrderedJson}; use crate::html::render::search_index::{build_index, SerializedSearchIndex}; use crate::html::render::sorted_template::{self, FileFormat, SortedTemplate}; -use crate::html::render::{AssocItemLink, ImplRenderingParameters}; +use crate::html::render::{AssocItemLink, ImplRenderingParameters, StylePath}; use crate::html::static_files::{self, suffix_path}; use crate::visit::DocVisitor; use crate::{try_err, try_none}; -/// Write cross-crate information files, static files, invocation-specific files, etc. to disk pub(crate) fn write_shared( cx: &mut Context<'_>, krate: &Crate, @@ -70,13 +69,14 @@ pub(crate) fn write_shared( let SerializedSearchIndex { index, desc } = build_index(&krate, &mut Rc::get_mut(&mut cx.shared).unwrap().cache, tcx); - write_search_desc(cx, &krate, &desc)?; // does not need to be merged; written unconditionally + write_search_desc(cx, &krate, &desc)?; // does not need to be merged let crate_name = krate.name(cx.tcx()); let crate_name = crate_name.as_str(); // rand let crate_name_json = OrderedJson::serialize(crate_name).unwrap(); // "rand" let external_crates = hack_get_external_crate_names(&cx.dst, &cx.shared.resource_suffix)?; let info = CrateInfo { + version: CrateInfoVersion::V1, src_files_js: SourcesPart::get(cx, &crate_name_json)?, search_index_js: SearchIndexPart::get(index, &cx.shared.resource_suffix)?, all_crates: AllCratesPart::get(crate_name_json.clone(), &cx.shared.resource_suffix)?, @@ -85,47 +85,103 @@ pub(crate) fn write_shared( type_impl: TypeAliasPart::get(cx, krate, &crate_name_json)?, }; - let crates = vec![info]; // we have info from just one crate. rest will found in out dir + if let Some(parts_out_dir) = &opt.parts_out_dir { + create_parents(&parts_out_dir.0)?; + try_err!( + fs::write(&parts_out_dir.0, serde_json::to_string(&info).unwrap()), + &parts_out_dir.0 + ); + } - write_static_files(cx, &opt)?; - let dst = &cx.dst; - if opt.emit.is_empty() || opt.emit.contains(&EmitType::InvocationSpecific) { - if cx.include_sources { - write_rendered_cci::(SourcesPart::blank, dst, &crates)?; - } - write_rendered_cci::(SearchIndexPart::blank, dst, &crates)?; - write_rendered_cci::(AllCratesPart::blank, dst, &crates)?; - } - write_rendered_cci::(TraitAliasPart::blank, dst, &crates)?; - write_rendered_cci::(TypeAliasPart::blank, dst, &crates)?; - match &opt.index_page { - Some(index_page) if opt.enable_index_page => { - let mut md_opts = opt.clone(); - md_opts.output = cx.dst.clone(); - md_opts.external_html = cx.shared.layout.external_html.clone(); - try_err!( - crate::markdown::render(&index_page, md_opts, cx.shared.edition()), - &index_page - ); - } - None if opt.enable_index_page => { - write_rendered_cci::(|| CratesIndexPart::blank(cx), dst, &crates)?; + let mut crates = CrateInfo::read_many(&opt.include_parts_dir)?; + crates.push(info); + + if opt.should_merge.write_rendered_cci { + write_not_crate_specific( + &crates, + &cx.dst, + opt, + &cx.shared.style_files, + cx.shared.layout.css_file_extension.as_deref(), + &cx.shared.resource_suffix, + cx.include_sources, + )?; + match &opt.index_page { + Some(index_page) if opt.enable_index_page => { + let mut md_opts = opt.clone(); + md_opts.output = cx.dst.clone(); + md_opts.external_html = cx.shared.layout.external_html.clone(); + try_err!( + crate::markdown::render(&index_page, md_opts, cx.shared.edition()), + &index_page + ); + } + None if opt.enable_index_page => { + write_rendered_cci::( + || CratesIndexPart::blank(cx), + &cx.dst, + &crates, + &opt.should_merge, + )?; + } + _ => {} // they don't want an index page } - _ => {} // they don't want an index page } Rc::get_mut(&mut cx.shared).unwrap().fs.set_sync_only(false); Ok(()) } -/// Writes the static files, the style files, and the css extensions -fn write_static_files(cx: &mut Context<'_>, options: &RenderOptions) -> Result<(), Error> { - let static_dir = cx.dst.join("static.files"); +/// Writes files that are written directly to the `--out-dir`, without the prefix from the current +/// crate. These are the rendered cross-crate files that encode info from multiple crates (e.g. +/// search index), and the static files. +pub(crate) fn write_not_crate_specific( + crates: &[CrateInfo], + dst: &Path, + opt: &RenderOptions, + style_files: &[StylePath], + css_file_extension: Option<&Path>, + resource_suffix: &str, + include_sources: bool, +) -> Result<(), Error> { + write_rendered_cross_crate_info(crates, dst, opt, include_sources)?; + write_static_files(dst, opt, style_files, css_file_extension, resource_suffix)?; + Ok(()) +} - cx.shared.fs.create_dir_all(&static_dir).map_err(|e| PathError::new(e, "static.files"))?; +fn write_rendered_cross_crate_info( + crates: &[CrateInfo], + dst: &Path, + opt: &RenderOptions, + include_sources: bool, +) -> Result<(), Error> { + let m = &opt.should_merge; + if opt.emit.is_empty() || opt.emit.contains(&EmitType::InvocationSpecific) { + if include_sources { + write_rendered_cci::(SourcesPart::blank, dst, &crates, m)?; + } + write_rendered_cci::(SearchIndexPart::blank, dst, &crates, m)?; + write_rendered_cci::(AllCratesPart::blank, dst, &crates, m)?; + } + write_rendered_cci::(TraitAliasPart::blank, dst, &crates, m)?; + write_rendered_cci::(TypeAliasPart::blank, dst, &crates, m)?; + Ok(()) +} + +/// Writes the static files, the style files, and the css extensions. +/// Have to be careful about these, because they write to the root out dir. +fn write_static_files( + dst: &Path, + opt: &RenderOptions, + style_files: &[StylePath], + css_file_extension: Option<&Path>, + resource_suffix: &str, +) -> Result<(), Error> { + let static_dir = dst.join("static.files"); + try_err!(fs::create_dir_all(&static_dir), &static_dir); // Handle added third-party themes - for entry in &cx.shared.style_files { + for entry in style_files { let theme = entry.basename()?; let extension = try_none!(try_none!(entry.path.extension(), &entry.path).to_str(), &entry.path); @@ -136,22 +192,24 @@ fn write_static_files(cx: &mut Context<'_>, options: &RenderOptions) -> Result<( } let bytes = try_err!(fs::read(&entry.path), &entry.path); - let filename = format!("{theme}{suffix}.{extension}", suffix = cx.shared.resource_suffix); - cx.shared.fs.write(cx.dst.join(filename), bytes)?; + let filename = format!("{theme}{resource_suffix}.{extension}"); + let dst_filename = dst.join(filename); + try_err!(fs::write(&dst_filename, bytes), &dst_filename); } // When the user adds their own CSS files with --extend-css, we write that as an // invocation-specific file (that is, with a resource suffix). - if let Some(ref css) = cx.shared.layout.css_file_extension { + if let Some(css) = css_file_extension { let buffer = try_err!(fs::read_to_string(css), css); - let path = static_files::suffix_path("theme.css", &cx.shared.resource_suffix); - cx.shared.fs.write(cx.dst.join(path), buffer)?; + let path = static_files::suffix_path("theme.css", resource_suffix); + let dst_path = dst.join(path); + try_err!(fs::write(&dst_path, buffer), &dst_path); } - if options.emit.is_empty() || options.emit.contains(&EmitType::Toolchain) { + if opt.emit.is_empty() || opt.emit.contains(&EmitType::Toolchain) { static_files::for_each(|f: &static_files::StaticFile| { let filename = static_dir.join(f.output_filename()); - cx.shared.fs.write(filename, f.minified()) + fs::write(&filename, f.minified()).map_err(|e| PathError::new(e, &filename)) })?; } @@ -186,7 +244,8 @@ fn write_search_desc( /// Contains pre-rendered contents to insert into the CCI template #[derive(Serialize, Deserialize, Clone, Debug)] -struct CrateInfo { +pub(crate) struct CrateInfo { + version: CrateInfoVersion, src_files_js: PartsAndLocations, search_index_js: PartsAndLocations, all_crates: PartsAndLocations, @@ -195,6 +254,33 @@ struct CrateInfo { type_impl: PartsAndLocations, } +impl CrateInfo { + /// Read all of the crate info from its location on the filesystem + pub(crate) fn read_many(parts_paths: &[PathToParts]) -> Result, Error> { + parts_paths + .iter() + .map(|parts_path| { + let path = &parts_path.0; + let parts = try_err!(fs::read(&path), &path); + let parts: CrateInfo = try_err!(serde_json::from_slice(&parts), &path); + Ok::<_, Error>(parts) + }) + .collect::, Error>>() + } +} + +/// Version for the format of the crate-info file. +/// +/// This enum should only ever have one variant, representing the current version. +/// Gives pretty good error message about expecting the current version on deserialize. +/// +/// Must be incremented (V2, V3, etc.) upon any changes to the search index or CrateInfo, +/// to provide better diagnostics about including an invalid file. +#[derive(Serialize, Deserialize, Clone, Debug)] +enum CrateInfoVersion { + V1, +} + /// Paths (relative to the doc root) and their pre-merge contents #[derive(Serialize, Deserialize, Debug, Clone)] #[serde(transparent)] @@ -900,10 +986,14 @@ fn create_parents(path: &Path) -> Result<(), Error> { fn read_template_or_blank( mut make_blank: F, path: &Path, + should_merge: &ShouldMerge, ) -> Result, Error> where F: FnMut() -> SortedTemplate, { + if !should_merge.read_rendered_cci { + return Ok(make_blank()); + } match fs::read_to_string(&path) { Ok(template) => Ok(try_err!(SortedTemplate::from_str(&template), &path)), Err(e) if e.kind() == io::ErrorKind::NotFound => Ok(make_blank()), @@ -916,6 +1006,7 @@ fn write_rendered_cci( mut make_blank: F, dst: &Path, crates_info: &[CrateInfo], + should_merge: &ShouldMerge, ) -> Result<(), Error> where F: FnMut() -> SortedTemplate, @@ -924,7 +1015,8 @@ where for (path, parts) in get_path_parts::(dst, crates_info) { create_parents(&path)?; // read previous rendered cci from storage, append to them - let mut template = read_template_or_blank::<_, T::FileFormat>(&mut make_blank, &path)?; + let mut template = + read_template_or_blank::<_, T::FileFormat>(&mut make_blank, &path, should_merge)?; for part in parts { template.append(part); } diff --git a/src/librustdoc/html/render/write_shared/tests.rs b/src/librustdoc/html/render/write_shared/tests.rs index e282cd99e43cc..a235f1d37243a 100644 --- a/src/librustdoc/html/render/write_shared/tests.rs +++ b/src/librustdoc/html/render/write_shared/tests.rs @@ -1,3 +1,4 @@ +use crate::config::ShouldMerge; use crate::html::render::ordered_json::{EscapedJson, OrderedJson}; use crate::html::render::sorted_template::{Html, SortedTemplate}; use crate::html::render::write_shared::*; @@ -192,16 +193,17 @@ fn read_template_test() { let path = path.path().join("file.html"); let make_blank = || SortedTemplate::::from_before_after("
", "
"); - let template = read_template_or_blank(make_blank, &path).unwrap(); + let should_merge = ShouldMerge { read_rendered_cci: true, write_rendered_cci: true }; + let template = read_template_or_blank(make_blank, &path, &should_merge).unwrap(); assert_eq!(but_last_line(&template.to_string()), "
"); fs::write(&path, template.to_string()).unwrap(); - let mut template = read_template_or_blank(make_blank, &path).unwrap(); + let mut template = read_template_or_blank(make_blank, &path, &should_merge).unwrap(); template.append("".to_string()); fs::write(&path, template.to_string()).unwrap(); - let mut template = read_template_or_blank(make_blank, &path).unwrap(); + let mut template = read_template_or_blank(make_blank, &path, &should_merge).unwrap(); template.append("
".to_string()); fs::write(&path, template.to_string()).unwrap(); - let template = read_template_or_blank(make_blank, &path).unwrap(); + let template = read_template_or_blank(make_blank, &path, &should_merge).unwrap(); assert_eq!(but_last_line(&template.to_string()), "

"); } diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index e470aef3643e9..6649e1721a48b 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -603,6 +603,33 @@ fn opts() -> Vec { "path to function call information (for displaying examples in the documentation)", ) }), + unstable("merge", |o| { + o.optopt( + "", + "merge", + "Controls how rustdoc handles files from previously documented crates in the doc root + none = Do not write cross-crate information to the --out-dir + shared = Append current crate's info to files found in the --out-dir + finalize = Write current crate's info and --include-parts-dir info to the --out-dir, overwriting conflicting files", + "none|shared|finalize", + ) + }), + unstable("parts-out-dir", |o| { + o.optopt( + "", + "parts-out-dir", + "Writes trait implementations and other info for the current crate to provided path. Only use with --merge=none", + "path/to/doc.parts/", + ) + }), + unstable("include-parts-dir", |o| { + o.optmulti( + "", + "include-parts-dir", + "Includes trait implementations and other crate info from provided path. Only use with --merge=finalize", + "path/to/doc.parts/", + ) + }), // deprecated / removed options unstable("disable-minification", |o| o.optflagmulti("", "disable-minification", "removed")), stable("plugin-path", |o| { @@ -697,6 +724,32 @@ fn run_renderer<'tcx, T: formats::FormatRenderer<'tcx>>( } } +/// Renders and writes cross-crate info files, like the search index. This function exists so that +/// we can run rustdoc without a crate root in the `--merge=finalize` mode. Cross-crate info files +/// discovered via `--include-parts-dir` are combined and written to the doc root. +fn run_merge_finalize(opt: config::RenderOptions) -> Result<(), error::Error> { + assert!( + opt.should_merge.write_rendered_cci, + "config.rs only allows us to return InputMode::NoInputMergeFinalize if --merge=finalize" + ); + assert!( + !opt.should_merge.read_rendered_cci, + "config.rs only allows us to return InputMode::NoInputMergeFinalize if --merge=finalize" + ); + let crates = html::render::CrateInfo::read_many(&opt.include_parts_dir)?; + let include_sources = !opt.html_no_source; + html::render::write_not_crate_specific( + &crates, + &opt.output, + &opt, + &opt.themes, + opt.extension_css.as_deref(), + &opt.resource_suffix, + include_sources, + )?; + Ok(()) +} + fn main_args( early_dcx: &mut EarlyDiagCtxt, at_args: &[String], @@ -737,6 +790,17 @@ fn main_args( core::new_dcx(options.error_format, None, options.diagnostic_width, &options.unstable_opts); let dcx = dcx.handle(); + let input = match input { + config::InputMode::HasFile(input) => input, + config::InputMode::NoInputMergeFinalize => { + return wrap_return( + dcx, + run_merge_finalize(render_options) + .map_err(|e| format!("could not write merged cross-crate info: {e}")), + ); + } + }; + match (options.should_test, config::markdown_input(&input)) { (true, Some(_)) => return wrap_return(dcx, doctest::test_markdown(&input, options)), (true, None) => return doctest::run(dcx, input, options), diff --git a/tests/run-make/rustdoc-default-output/output-default.stdout b/tests/run-make/rustdoc-default-output/output-default.stdout index bc38d9e9dc6b3..125443ce61964 100644 --- a/tests/run-make/rustdoc-default-output/output-default.stdout +++ b/tests/run-make/rustdoc-default-output/output-default.stdout @@ -172,6 +172,23 @@ Options: --scrape-tests Include test code when scraping examples --with-examples path to function call information (for displaying examples in the documentation) + --merge none|shared|finalize + Controls how rustdoc handles files from previously + documented crates in the doc root + none = Do not write cross-crate information to the + --out-dir + shared = Append current crate's info to files found in + the --out-dir + finalize = Write current crate's info and + --include-parts-dir info to the --out-dir, overwriting + conflicting files + --parts-out-dir path/to/doc.parts/ + Writes trait implementations and other info for the + current crate to provided path. Only use with + --merge=none + --include-parts-dir path/to/doc.parts/ + Includes trait implementations and other crate info + from provided path. Only use with --merge=finalize --disable-minification removed --plugin-path DIR From 548b6e197d9bafef6fae86098ea2afabbe99a90a Mon Sep 17 00:00:00 2001 From: EtomicBomb Date: Sat, 7 Sep 2024 19:02:22 -0400 Subject: [PATCH 0660/2194] add tests for behavior in rfc#3662 * Adds tests for the behavior from rfc#3662 in `tests/rustdoc/` --- .../auxiliary/quebec.rs | 5 +++ .../auxiliary/tango.rs | 8 +++++ .../cargo-transitive-read-write/sierra.rs | 25 +++++++++++++ .../auxiliary/quebec.rs | 7 ++++ .../auxiliary/romeo.rs | 10 ++++++ .../auxiliary/sierra.rs | 11 ++++++ .../auxiliary/tango.rs | 10 ++++++ .../kitchen-sink-separate-dirs/indigo.rs | 35 +++++++++++++++++++ .../no-merge-separate/auxiliary/quebec.rs | 6 ++++ .../no-merge-separate/auxiliary/tango.rs | 9 +++++ .../no-merge-separate/sierra.rs | 17 +++++++++ .../no-merge-write-anyway/auxiliary/quebec.rs | 6 ++++ .../no-merge-write-anyway/auxiliary/tango.rs | 9 +++++ .../no-merge-write-anyway/sierra.rs | 18 ++++++++++ .../overwrite-but-include/auxiliary/quebec.rs | 6 ++++ .../overwrite-but-include/auxiliary/tango.rs | 9 +++++ .../overwrite-but-include/sierra.rs | 22 ++++++++++++ .../auxiliary/quebec.rs | 7 ++++ .../overwrite-but-separate/auxiliary/tango.rs | 10 ++++++ .../overwrite-but-separate/sierra.rs | 25 +++++++++++++ .../overwrite/auxiliary/quebec.rs | 5 +++ .../overwrite/auxiliary/tango.rs | 8 +++++ .../overwrite/sierra.rs | 20 +++++++++++ .../single-crate-finalize/quebec.rs | 13 +++++++ .../single-crate-read-write/quebec.rs | 12 +++++++ .../single-crate-write-anyway/quebec.rs | 13 +++++++ .../single-merge-none-useless-write/quebec.rs | 11 ++++++ .../transitive-finalize/auxiliary/quebec.rs | 5 +++ .../transitive-finalize/auxiliary/tango.rs | 8 +++++ .../transitive-finalize/sierra.rs | 20 +++++++++++ .../transitive-merge-none/auxiliary/quebec.rs | 6 ++++ .../transitive-merge-none/auxiliary/tango.rs | 9 +++++ .../transitive-merge-none/sierra.rs | 27 ++++++++++++++ .../auxiliary/quebec.rs | 5 +++ .../auxiliary/tango.rs | 8 +++++ .../transitive-merge-read-write/sierra.rs | 25 +++++++++++++ .../transitive-no-info/auxiliary/quebec.rs | 5 +++ .../transitive-no-info/auxiliary/tango.rs | 8 +++++ .../transitive-no-info/sierra.rs | 17 +++++++++ .../two-separate-out-dir/auxiliary/foxtrot.rs | 5 +++ .../two-separate-out-dir/echo.rs | 16 +++++++++ 41 files changed, 501 insertions(+) create mode 100644 tests/rustdoc/merge-cross-crate-info/cargo-transitive-read-write/auxiliary/quebec.rs create mode 100644 tests/rustdoc/merge-cross-crate-info/cargo-transitive-read-write/auxiliary/tango.rs create mode 100644 tests/rustdoc/merge-cross-crate-info/cargo-transitive-read-write/sierra.rs create mode 100644 tests/rustdoc/merge-cross-crate-info/kitchen-sink-separate-dirs/auxiliary/quebec.rs create mode 100644 tests/rustdoc/merge-cross-crate-info/kitchen-sink-separate-dirs/auxiliary/romeo.rs create mode 100644 tests/rustdoc/merge-cross-crate-info/kitchen-sink-separate-dirs/auxiliary/sierra.rs create mode 100644 tests/rustdoc/merge-cross-crate-info/kitchen-sink-separate-dirs/auxiliary/tango.rs create mode 100644 tests/rustdoc/merge-cross-crate-info/kitchen-sink-separate-dirs/indigo.rs create mode 100644 tests/rustdoc/merge-cross-crate-info/no-merge-separate/auxiliary/quebec.rs create mode 100644 tests/rustdoc/merge-cross-crate-info/no-merge-separate/auxiliary/tango.rs create mode 100644 tests/rustdoc/merge-cross-crate-info/no-merge-separate/sierra.rs create mode 100644 tests/rustdoc/merge-cross-crate-info/no-merge-write-anyway/auxiliary/quebec.rs create mode 100644 tests/rustdoc/merge-cross-crate-info/no-merge-write-anyway/auxiliary/tango.rs create mode 100644 tests/rustdoc/merge-cross-crate-info/no-merge-write-anyway/sierra.rs create mode 100644 tests/rustdoc/merge-cross-crate-info/overwrite-but-include/auxiliary/quebec.rs create mode 100644 tests/rustdoc/merge-cross-crate-info/overwrite-but-include/auxiliary/tango.rs create mode 100644 tests/rustdoc/merge-cross-crate-info/overwrite-but-include/sierra.rs create mode 100644 tests/rustdoc/merge-cross-crate-info/overwrite-but-separate/auxiliary/quebec.rs create mode 100644 tests/rustdoc/merge-cross-crate-info/overwrite-but-separate/auxiliary/tango.rs create mode 100644 tests/rustdoc/merge-cross-crate-info/overwrite-but-separate/sierra.rs create mode 100644 tests/rustdoc/merge-cross-crate-info/overwrite/auxiliary/quebec.rs create mode 100644 tests/rustdoc/merge-cross-crate-info/overwrite/auxiliary/tango.rs create mode 100644 tests/rustdoc/merge-cross-crate-info/overwrite/sierra.rs create mode 100644 tests/rustdoc/merge-cross-crate-info/single-crate-finalize/quebec.rs create mode 100644 tests/rustdoc/merge-cross-crate-info/single-crate-read-write/quebec.rs create mode 100644 tests/rustdoc/merge-cross-crate-info/single-crate-write-anyway/quebec.rs create mode 100644 tests/rustdoc/merge-cross-crate-info/single-merge-none-useless-write/quebec.rs create mode 100644 tests/rustdoc/merge-cross-crate-info/transitive-finalize/auxiliary/quebec.rs create mode 100644 tests/rustdoc/merge-cross-crate-info/transitive-finalize/auxiliary/tango.rs create mode 100644 tests/rustdoc/merge-cross-crate-info/transitive-finalize/sierra.rs create mode 100644 tests/rustdoc/merge-cross-crate-info/transitive-merge-none/auxiliary/quebec.rs create mode 100644 tests/rustdoc/merge-cross-crate-info/transitive-merge-none/auxiliary/tango.rs create mode 100644 tests/rustdoc/merge-cross-crate-info/transitive-merge-none/sierra.rs create mode 100644 tests/rustdoc/merge-cross-crate-info/transitive-merge-read-write/auxiliary/quebec.rs create mode 100644 tests/rustdoc/merge-cross-crate-info/transitive-merge-read-write/auxiliary/tango.rs create mode 100644 tests/rustdoc/merge-cross-crate-info/transitive-merge-read-write/sierra.rs create mode 100644 tests/rustdoc/merge-cross-crate-info/transitive-no-info/auxiliary/quebec.rs create mode 100644 tests/rustdoc/merge-cross-crate-info/transitive-no-info/auxiliary/tango.rs create mode 100644 tests/rustdoc/merge-cross-crate-info/transitive-no-info/sierra.rs create mode 100644 tests/rustdoc/merge-cross-crate-info/two-separate-out-dir/auxiliary/foxtrot.rs create mode 100644 tests/rustdoc/merge-cross-crate-info/two-separate-out-dir/echo.rs diff --git a/tests/rustdoc/merge-cross-crate-info/cargo-transitive-read-write/auxiliary/quebec.rs b/tests/rustdoc/merge-cross-crate-info/cargo-transitive-read-write/auxiliary/quebec.rs new file mode 100644 index 0000000000000..fdafb3b7ac341 --- /dev/null +++ b/tests/rustdoc/merge-cross-crate-info/cargo-transitive-read-write/auxiliary/quebec.rs @@ -0,0 +1,5 @@ +//@ doc-flags:--merge=shared +//@ doc-flags:--enable-index-page +//@ doc-flags:-Zunstable-options + +pub struct Quebec; diff --git a/tests/rustdoc/merge-cross-crate-info/cargo-transitive-read-write/auxiliary/tango.rs b/tests/rustdoc/merge-cross-crate-info/cargo-transitive-read-write/auxiliary/tango.rs new file mode 100644 index 0000000000000..ff12fe98d82c2 --- /dev/null +++ b/tests/rustdoc/merge-cross-crate-info/cargo-transitive-read-write/auxiliary/tango.rs @@ -0,0 +1,8 @@ +//@ aux-build:quebec.rs +//@ build-aux-docs +//@ doc-flags:--merge=shared +//@ doc-flags:--enable-index-page +//@ doc-flags:-Zunstable-options + +extern crate quebec; +pub trait Tango {} diff --git a/tests/rustdoc/merge-cross-crate-info/cargo-transitive-read-write/sierra.rs b/tests/rustdoc/merge-cross-crate-info/cargo-transitive-read-write/sierra.rs new file mode 100644 index 0000000000000..665f9567ba2d2 --- /dev/null +++ b/tests/rustdoc/merge-cross-crate-info/cargo-transitive-read-write/sierra.rs @@ -0,0 +1,25 @@ +//@ aux-build:tango.rs +//@ build-aux-docs +//@ doc-flags:--merge=shared +//@ doc-flags:--enable-index-page +//@ doc-flags:-Zunstable-options + +//@ has index.html +//@ has index.html '//h1' 'List of all crates' +//@ has index.html '//ul[@class="all-items"]//a[@href="quebec/index.html"]' 'quebec' +//@ has index.html '//ul[@class="all-items"]//a[@href="sierra/index.html"]' 'sierra' +//@ has index.html '//ul[@class="all-items"]//a[@href="tango/index.html"]' 'tango' +//@ has quebec/struct.Quebec.html +//@ has sierra/struct.Sierra.html +//@ has tango/trait.Tango.html +//@ hasraw sierra/struct.Sierra.html 'Tango' +//@ hasraw trait.impl/tango/trait.Tango.js 'struct.Sierra.html' +//@ hasraw search-index.js 'Tango' +//@ hasraw search-index.js 'Sierra' +//@ hasraw search-index.js 'Quebec' + +// similar to cargo-workflow-transitive, but we use --merge=read-write, +// which is the default. +extern crate tango; +pub struct Sierra; +impl tango::Tango for Sierra {} diff --git a/tests/rustdoc/merge-cross-crate-info/kitchen-sink-separate-dirs/auxiliary/quebec.rs b/tests/rustdoc/merge-cross-crate-info/kitchen-sink-separate-dirs/auxiliary/quebec.rs new file mode 100644 index 0000000000000..d10bc0316ccad --- /dev/null +++ b/tests/rustdoc/merge-cross-crate-info/kitchen-sink-separate-dirs/auxiliary/quebec.rs @@ -0,0 +1,7 @@ +//@ unique-doc-out-dir +//@ doc-flags:--merge=none +//@ doc-flags:--parts-out-dir=info/doc.parts/quebec +//@ doc-flags:--enable-index-page +//@ doc-flags:-Zunstable-options + +pub struct Quebec; diff --git a/tests/rustdoc/merge-cross-crate-info/kitchen-sink-separate-dirs/auxiliary/romeo.rs b/tests/rustdoc/merge-cross-crate-info/kitchen-sink-separate-dirs/auxiliary/romeo.rs new file mode 100644 index 0000000000000..6d0c8651db53f --- /dev/null +++ b/tests/rustdoc/merge-cross-crate-info/kitchen-sink-separate-dirs/auxiliary/romeo.rs @@ -0,0 +1,10 @@ +//@ aux-build:sierra.rs +//@ build-aux-docs +//@ unique-doc-out-dir +//@ doc-flags:--merge=none +//@ doc-flags:--parts-out-dir=info/doc.parts/romeo +//@ doc-flags:--enable-index-page +//@ doc-flags:-Zunstable-options + +extern crate sierra; +pub type Romeo = sierra::Sierra; diff --git a/tests/rustdoc/merge-cross-crate-info/kitchen-sink-separate-dirs/auxiliary/sierra.rs b/tests/rustdoc/merge-cross-crate-info/kitchen-sink-separate-dirs/auxiliary/sierra.rs new file mode 100644 index 0000000000000..10898f3886477 --- /dev/null +++ b/tests/rustdoc/merge-cross-crate-info/kitchen-sink-separate-dirs/auxiliary/sierra.rs @@ -0,0 +1,11 @@ +//@ aux-build:tango.rs +//@ build-aux-docs +//@ unique-doc-out-dir +//@ doc-flags:--merge=none +//@ doc-flags:--parts-out-dir=info/doc.parts/sierra +//@ doc-flags:--enable-index-page +//@ doc-flags:-Zunstable-options + +extern crate tango; +pub struct Sierra; +impl tango::Tango for Sierra {} diff --git a/tests/rustdoc/merge-cross-crate-info/kitchen-sink-separate-dirs/auxiliary/tango.rs b/tests/rustdoc/merge-cross-crate-info/kitchen-sink-separate-dirs/auxiliary/tango.rs new file mode 100644 index 0000000000000..3c3721ee6eb7d --- /dev/null +++ b/tests/rustdoc/merge-cross-crate-info/kitchen-sink-separate-dirs/auxiliary/tango.rs @@ -0,0 +1,10 @@ +//@ aux-build:quebec.rs +//@ build-aux-docs +//@ unique-doc-out-dir +//@ doc-flags:--merge=none +//@ doc-flags:--parts-out-dir=info/doc.parts/tango +//@ doc-flags:--enable-index-page +//@ doc-flags:-Zunstable-options + +extern crate quebec; +pub trait Tango {} diff --git a/tests/rustdoc/merge-cross-crate-info/kitchen-sink-separate-dirs/indigo.rs b/tests/rustdoc/merge-cross-crate-info/kitchen-sink-separate-dirs/indigo.rs new file mode 100644 index 0000000000000..f03f6bd6026fa --- /dev/null +++ b/tests/rustdoc/merge-cross-crate-info/kitchen-sink-separate-dirs/indigo.rs @@ -0,0 +1,35 @@ +//@ aux-build:tango.rs +//@ aux-build:romeo.rs +//@ aux-build:quebec.rs +//@ aux-build:sierra.rs +//@ build-aux-docs +//@ doc-flags:--merge=finalize +//@ doc-flags:--include-parts-dir=info/doc.parts/tango +//@ doc-flags:--include-parts-dir=info/doc.parts/romeo +//@ doc-flags:--include-parts-dir=info/doc.parts/quebec +//@ doc-flags:--include-parts-dir=info/doc.parts/sierra +//@ doc-flags:--enable-index-page +//@ doc-flags:-Zunstable-options + +//@ has index.html '//h1' 'List of all crates' +//@ has index.html +//@ has index.html '//ul[@class="all-items"]//a[@href="indigo/index.html"]' 'indigo' +//@ has index.html '//ul[@class="all-items"]//a[@href="quebec/index.html"]' 'quebec' +//@ has index.html '//ul[@class="all-items"]//a[@href="romeo/index.html"]' 'romeo' +//@ has index.html '//ul[@class="all-items"]//a[@href="sierra/index.html"]' 'sierra' +//@ has index.html '//ul[@class="all-items"]//a[@href="tango/index.html"]' 'tango' +//@ !has quebec/struct.Quebec.html +//@ !has romeo/type.Romeo.html +//@ !has sierra/struct.Sierra.html +//@ !has tango/trait.Tango.html +//@ hasraw trait.impl/tango/trait.Tango.js 'struct.Sierra.html' +//@ hasraw search-index.js 'Quebec' +//@ hasraw search-index.js 'Romeo' +//@ hasraw search-index.js 'Sierra' +//@ hasraw search-index.js 'Tango' +//@ has type.impl/sierra/struct.Sierra.js +//@ hasraw type.impl/sierra/struct.Sierra.js 'Tango' +//@ hasraw type.impl/sierra/struct.Sierra.js 'Romeo' + +// document everything in the default mode, there are separate out +// directories that are linked together diff --git a/tests/rustdoc/merge-cross-crate-info/no-merge-separate/auxiliary/quebec.rs b/tests/rustdoc/merge-cross-crate-info/no-merge-separate/auxiliary/quebec.rs new file mode 100644 index 0000000000000..61210529fa6bc --- /dev/null +++ b/tests/rustdoc/merge-cross-crate-info/no-merge-separate/auxiliary/quebec.rs @@ -0,0 +1,6 @@ +//@ unique-doc-out-dir +//@ doc-flags:--merge=none +//@ doc-flags:--enable-index-page +//@ doc-flags:-Zunstable-options + +pub struct Quebec; diff --git a/tests/rustdoc/merge-cross-crate-info/no-merge-separate/auxiliary/tango.rs b/tests/rustdoc/merge-cross-crate-info/no-merge-separate/auxiliary/tango.rs new file mode 100644 index 0000000000000..70d8a4b91f549 --- /dev/null +++ b/tests/rustdoc/merge-cross-crate-info/no-merge-separate/auxiliary/tango.rs @@ -0,0 +1,9 @@ +//@ aux-build:quebec.rs +//@ build-aux-docs +//@ unique-doc-out-dir +//@ doc-flags:--merge=none +//@ doc-flags:--enable-index-page +//@ doc-flags:-Zunstable-options + +extern crate quebec; +pub trait Tango {} diff --git a/tests/rustdoc/merge-cross-crate-info/no-merge-separate/sierra.rs b/tests/rustdoc/merge-cross-crate-info/no-merge-separate/sierra.rs new file mode 100644 index 0000000000000..7eac207e51886 --- /dev/null +++ b/tests/rustdoc/merge-cross-crate-info/no-merge-separate/sierra.rs @@ -0,0 +1,17 @@ +//@ aux-build:tango.rs +//@ build-aux-docs +//@ doc-flags:--merge=none +//@ doc-flags:--enable-index-page +//@ doc-flags:-Zunstable-options + +//@ !has index.html +//@ has sierra/struct.Sierra.html +//@ hasraw sierra/struct.Sierra.html 'Tango' +//@ !has trait.impl/tango/trait.Tango.js +//@ !has search-index.js + +// we don't generate any cross-crate info if --merge=none, even if we +// document crates separately +extern crate tango; +pub struct Sierra; +impl tango::Tango for Sierra {} diff --git a/tests/rustdoc/merge-cross-crate-info/no-merge-write-anyway/auxiliary/quebec.rs b/tests/rustdoc/merge-cross-crate-info/no-merge-write-anyway/auxiliary/quebec.rs new file mode 100644 index 0000000000000..6ab921533b037 --- /dev/null +++ b/tests/rustdoc/merge-cross-crate-info/no-merge-write-anyway/auxiliary/quebec.rs @@ -0,0 +1,6 @@ +//@ doc-flags:--merge=none +//@ doc-flags:--parts-out-dir=info/doc.parts/quebec +//@ doc-flags:--enable-index-page +//@ doc-flags:-Zunstable-options + +pub struct Quebec; diff --git a/tests/rustdoc/merge-cross-crate-info/no-merge-write-anyway/auxiliary/tango.rs b/tests/rustdoc/merge-cross-crate-info/no-merge-write-anyway/auxiliary/tango.rs new file mode 100644 index 0000000000000..9fa99d3be8af4 --- /dev/null +++ b/tests/rustdoc/merge-cross-crate-info/no-merge-write-anyway/auxiliary/tango.rs @@ -0,0 +1,9 @@ +//@ aux-build:quebec.rs +//@ build-aux-docs +//@ doc-flags:--merge=none +//@ doc-flags:--parts-out-dir=info/doc.parts/tango +//@ doc-flags:--enable-index-page +//@ doc-flags:-Zunstable-options + +extern crate quebec; +pub trait Tango {} diff --git a/tests/rustdoc/merge-cross-crate-info/no-merge-write-anyway/sierra.rs b/tests/rustdoc/merge-cross-crate-info/no-merge-write-anyway/sierra.rs new file mode 100644 index 0000000000000..f3340a80c848b --- /dev/null +++ b/tests/rustdoc/merge-cross-crate-info/no-merge-write-anyway/sierra.rs @@ -0,0 +1,18 @@ +//@ aux-build:tango.rs +//@ build-aux-docs +//@ doc-flags:--merge=none +//@ doc-flags:--parts-out-dir=info/doc.parts/sierra +//@ doc-flags:--enable-index-page +//@ doc-flags:-Zunstable-options + +//@ !has index.html +//@ has sierra/struct.Sierra.html +//@ has tango/trait.Tango.html +//@ hasraw sierra/struct.Sierra.html 'Tango' +//@ !has trait.impl/tango/trait.Tango.js +//@ !has search-index.js + +// we --merge=none, so --parts-out-dir doesn't do anything +extern crate tango; +pub struct Sierra; +impl tango::Tango for Sierra {} diff --git a/tests/rustdoc/merge-cross-crate-info/overwrite-but-include/auxiliary/quebec.rs b/tests/rustdoc/merge-cross-crate-info/overwrite-but-include/auxiliary/quebec.rs new file mode 100644 index 0000000000000..6ab921533b037 --- /dev/null +++ b/tests/rustdoc/merge-cross-crate-info/overwrite-but-include/auxiliary/quebec.rs @@ -0,0 +1,6 @@ +//@ doc-flags:--merge=none +//@ doc-flags:--parts-out-dir=info/doc.parts/quebec +//@ doc-flags:--enable-index-page +//@ doc-flags:-Zunstable-options + +pub struct Quebec; diff --git a/tests/rustdoc/merge-cross-crate-info/overwrite-but-include/auxiliary/tango.rs b/tests/rustdoc/merge-cross-crate-info/overwrite-but-include/auxiliary/tango.rs new file mode 100644 index 0000000000000..9fa99d3be8af4 --- /dev/null +++ b/tests/rustdoc/merge-cross-crate-info/overwrite-but-include/auxiliary/tango.rs @@ -0,0 +1,9 @@ +//@ aux-build:quebec.rs +//@ build-aux-docs +//@ doc-flags:--merge=none +//@ doc-flags:--parts-out-dir=info/doc.parts/tango +//@ doc-flags:--enable-index-page +//@ doc-flags:-Zunstable-options + +extern crate quebec; +pub trait Tango {} diff --git a/tests/rustdoc/merge-cross-crate-info/overwrite-but-include/sierra.rs b/tests/rustdoc/merge-cross-crate-info/overwrite-but-include/sierra.rs new file mode 100644 index 0000000000000..8eb0f1d049831 --- /dev/null +++ b/tests/rustdoc/merge-cross-crate-info/overwrite-but-include/sierra.rs @@ -0,0 +1,22 @@ +//@ aux-build:tango.rs +//@ build-aux-docs +//@ doc-flags:--merge=finalize +//@ doc-flags:--include-parts-dir=info/doc.parts/tango +//@ doc-flags:--enable-index-page +//@ doc-flags:-Zunstable-options + +//@ has quebec/struct.Quebec.html +//@ has sierra/struct.Sierra.html +//@ has tango/trait.Tango.html +//@ hasraw sierra/struct.Sierra.html 'Tango' +//@ hasraw trait.impl/tango/trait.Tango.js 'struct.Sierra.html' +//@ hasraw search-index.js 'Tango' +//@ hasraw search-index.js 'Sierra' +//@ !hasraw search-index.js 'Quebec' + +// we overwrite quebec and tango's cross-crate information, but we +// include the info from tango meaning that it should appear in the out +// dir +extern crate tango; +pub struct Sierra; +impl tango::Tango for Sierra {} diff --git a/tests/rustdoc/merge-cross-crate-info/overwrite-but-separate/auxiliary/quebec.rs b/tests/rustdoc/merge-cross-crate-info/overwrite-but-separate/auxiliary/quebec.rs new file mode 100644 index 0000000000000..d10bc0316ccad --- /dev/null +++ b/tests/rustdoc/merge-cross-crate-info/overwrite-but-separate/auxiliary/quebec.rs @@ -0,0 +1,7 @@ +//@ unique-doc-out-dir +//@ doc-flags:--merge=none +//@ doc-flags:--parts-out-dir=info/doc.parts/quebec +//@ doc-flags:--enable-index-page +//@ doc-flags:-Zunstable-options + +pub struct Quebec; diff --git a/tests/rustdoc/merge-cross-crate-info/overwrite-but-separate/auxiliary/tango.rs b/tests/rustdoc/merge-cross-crate-info/overwrite-but-separate/auxiliary/tango.rs new file mode 100644 index 0000000000000..3c3721ee6eb7d --- /dev/null +++ b/tests/rustdoc/merge-cross-crate-info/overwrite-but-separate/auxiliary/tango.rs @@ -0,0 +1,10 @@ +//@ aux-build:quebec.rs +//@ build-aux-docs +//@ unique-doc-out-dir +//@ doc-flags:--merge=none +//@ doc-flags:--parts-out-dir=info/doc.parts/tango +//@ doc-flags:--enable-index-page +//@ doc-flags:-Zunstable-options + +extern crate quebec; +pub trait Tango {} diff --git a/tests/rustdoc/merge-cross-crate-info/overwrite-but-separate/sierra.rs b/tests/rustdoc/merge-cross-crate-info/overwrite-but-separate/sierra.rs new file mode 100644 index 0000000000000..4ee036238b4b1 --- /dev/null +++ b/tests/rustdoc/merge-cross-crate-info/overwrite-but-separate/sierra.rs @@ -0,0 +1,25 @@ +//@ aux-build:tango.rs +//@ build-aux-docs +//@ doc-flags:--merge=finalize +//@ doc-flags:--include-parts-dir=info/doc.parts/tango +//@ doc-flags:--include-parts-dir=info/doc.parts/quebec +//@ doc-flags:--enable-index-page +//@ doc-flags:-Zunstable-options + +//@ has index.html +//@ has index.html '//h1' 'List of all crates' +//@ has index.html '//ul[@class="all-items"]//a[@href="quebec/index.html"]' 'quebec' +//@ has index.html '//ul[@class="all-items"]//a[@href="sierra/index.html"]' 'sierra' +//@ has index.html '//ul[@class="all-items"]//a[@href="tango/index.html"]' 'tango' +//@ has sierra/struct.Sierra.html +//@ hasraw trait.impl/tango/trait.Tango.js 'struct.Sierra.html' +//@ hasraw search-index.js 'Tango' +//@ hasraw search-index.js 'Sierra' +//@ hasraw search-index.js 'Quebec' + +// If these were documeted into the same directory, the info would be +// overwritten. However, since they are merged, we can still recover all +// of the cross-crate information +extern crate tango; +pub struct Sierra; +impl tango::Tango for Sierra {} diff --git a/tests/rustdoc/merge-cross-crate-info/overwrite/auxiliary/quebec.rs b/tests/rustdoc/merge-cross-crate-info/overwrite/auxiliary/quebec.rs new file mode 100644 index 0000000000000..0e28d8e646647 --- /dev/null +++ b/tests/rustdoc/merge-cross-crate-info/overwrite/auxiliary/quebec.rs @@ -0,0 +1,5 @@ +//@ doc-flags:--merge=none +//@ doc-flags:--enable-index-page +//@ doc-flags:-Zunstable-options + +pub struct Quebec; diff --git a/tests/rustdoc/merge-cross-crate-info/overwrite/auxiliary/tango.rs b/tests/rustdoc/merge-cross-crate-info/overwrite/auxiliary/tango.rs new file mode 100644 index 0000000000000..363b2d5508e63 --- /dev/null +++ b/tests/rustdoc/merge-cross-crate-info/overwrite/auxiliary/tango.rs @@ -0,0 +1,8 @@ +//@ aux-build:quebec.rs +//@ build-aux-docs +//@ doc-flags:--merge=finalize +//@ doc-flags:--enable-index-page +//@ doc-flags:-Zunstable-options + +extern crate quebec; +pub trait Tango {} diff --git a/tests/rustdoc/merge-cross-crate-info/overwrite/sierra.rs b/tests/rustdoc/merge-cross-crate-info/overwrite/sierra.rs new file mode 100644 index 0000000000000..11e61dd2744b6 --- /dev/null +++ b/tests/rustdoc/merge-cross-crate-info/overwrite/sierra.rs @@ -0,0 +1,20 @@ +//@ aux-build:tango.rs +//@ build-aux-docs +//@ doc-flags:--merge=shared +//@ doc-flags:--enable-index-page +//@ doc-flags:-Zunstable-options + +//@ has quebec/struct.Quebec.html +//@ has sierra/struct.Sierra.html +//@ has tango/trait.Tango.html +//@ hasraw sierra/struct.Sierra.html 'Tango' +//@ hasraw trait.impl/tango/trait.Tango.js 'struct.Sierra.html' +//@ hasraw search-index.js 'Tango' +//@ hasraw search-index.js 'Sierra' +//@ !hasraw search-index.js 'Quebec' + +// since tango is documented with --merge=finalize, we overwrite q's +// cross-crate information +extern crate tango; +pub struct Sierra; +impl tango::Tango for Sierra {} diff --git a/tests/rustdoc/merge-cross-crate-info/single-crate-finalize/quebec.rs b/tests/rustdoc/merge-cross-crate-info/single-crate-finalize/quebec.rs new file mode 100644 index 0000000000000..09bb78c06f1c2 --- /dev/null +++ b/tests/rustdoc/merge-cross-crate-info/single-crate-finalize/quebec.rs @@ -0,0 +1,13 @@ +//@ doc-flags:--merge=finalize +//@ doc-flags:--enable-index-page +//@ doc-flags:-Zunstable-options + +//@ has index.html +//@ has index.html '//h1' 'List of all crates' +//@ has index.html '//ul[@class="all-items"]//a[@href="quebec/index.html"]' 'quebec' +//@ has quebec/struct.Quebec.html +//@ hasraw search-index.js 'Quebec' + +// there is nothing to read from the output directory if we use a single +// crate +pub struct Quebec; diff --git a/tests/rustdoc/merge-cross-crate-info/single-crate-read-write/quebec.rs b/tests/rustdoc/merge-cross-crate-info/single-crate-read-write/quebec.rs new file mode 100644 index 0000000000000..72475426f6edd --- /dev/null +++ b/tests/rustdoc/merge-cross-crate-info/single-crate-read-write/quebec.rs @@ -0,0 +1,12 @@ +//@ doc-flags:--merge=shared +//@ doc-flags:--enable-index-page +//@ doc-flags:-Zunstable-options + +//@ has index.html +//@ has index.html '//h1' 'List of all crates' +//@ has index.html '//ul[@class="all-items"]//a[@href="quebec/index.html"]' 'quebec' +//@ has quebec/struct.Quebec.html +//@ hasraw search-index.js 'Quebec' + +// read-write is the default and this does the same as `single-crate` +pub struct Quebec; diff --git a/tests/rustdoc/merge-cross-crate-info/single-crate-write-anyway/quebec.rs b/tests/rustdoc/merge-cross-crate-info/single-crate-write-anyway/quebec.rs new file mode 100644 index 0000000000000..b20e173a8307e --- /dev/null +++ b/tests/rustdoc/merge-cross-crate-info/single-crate-write-anyway/quebec.rs @@ -0,0 +1,13 @@ +//@ doc-flags:--parts-out-dir=info/doc.parts/quebec +//@ doc-flags:--enable-index-page +//@ doc-flags:-Zunstable-options + +//@ has index.html +//@ has index.html '//h1' 'List of all crates' +//@ has index.html '//ul[@class="all-items"]//a[@href="quebec/index.html"]' 'quebec' +//@ has quebec/struct.Quebec.html +//@ hasraw search-index.js 'Quebec' + +// we can --parts-out-dir, but that doesn't do anything other than create +// the file +pub struct Quebec; diff --git a/tests/rustdoc/merge-cross-crate-info/single-merge-none-useless-write/quebec.rs b/tests/rustdoc/merge-cross-crate-info/single-merge-none-useless-write/quebec.rs new file mode 100644 index 0000000000000..e888a43c46042 --- /dev/null +++ b/tests/rustdoc/merge-cross-crate-info/single-merge-none-useless-write/quebec.rs @@ -0,0 +1,11 @@ +//@ doc-flags:--merge=none +//@ doc-flags:--parts-out-dir=info/doc.parts/quebec +//@ doc-flags:--enable-index-page +//@ doc-flags:-Zunstable-options + +//@ !has index.html +//@ has quebec/struct.Quebec.html +//@ !has search-index.js + +// --merge=none doesn't write anything, despite --parts-out-dir +pub struct Quebec; diff --git a/tests/rustdoc/merge-cross-crate-info/transitive-finalize/auxiliary/quebec.rs b/tests/rustdoc/merge-cross-crate-info/transitive-finalize/auxiliary/quebec.rs new file mode 100644 index 0000000000000..1beca543f814f --- /dev/null +++ b/tests/rustdoc/merge-cross-crate-info/transitive-finalize/auxiliary/quebec.rs @@ -0,0 +1,5 @@ +//@ doc-flags:--merge=finalize +//@ doc-flags:--enable-index-page +//@ doc-flags:-Zunstable-options + +pub struct Quebec; diff --git a/tests/rustdoc/merge-cross-crate-info/transitive-finalize/auxiliary/tango.rs b/tests/rustdoc/merge-cross-crate-info/transitive-finalize/auxiliary/tango.rs new file mode 100644 index 0000000000000..363b2d5508e63 --- /dev/null +++ b/tests/rustdoc/merge-cross-crate-info/transitive-finalize/auxiliary/tango.rs @@ -0,0 +1,8 @@ +//@ aux-build:quebec.rs +//@ build-aux-docs +//@ doc-flags:--merge=finalize +//@ doc-flags:--enable-index-page +//@ doc-flags:-Zunstable-options + +extern crate quebec; +pub trait Tango {} diff --git a/tests/rustdoc/merge-cross-crate-info/transitive-finalize/sierra.rs b/tests/rustdoc/merge-cross-crate-info/transitive-finalize/sierra.rs new file mode 100644 index 0000000000000..68fc4b13fa8f7 --- /dev/null +++ b/tests/rustdoc/merge-cross-crate-info/transitive-finalize/sierra.rs @@ -0,0 +1,20 @@ +//@ aux-build:tango.rs +//@ build-aux-docs +//@ doc-flags:--merge=finalize +//@ doc-flags:--enable-index-page +//@ doc-flags:-Zunstable-options + +//@ has index.html +//@ has index.html '//h1' 'List of all crates' +//@ has index.html '//ul[@class="all-items"]//a[@href="sierra/index.html"]' 'sierra' +//@ has index.html '//ul[@class="all-items"]//a[@href="tango/index.html"]' 'tango' +//@ has sierra/struct.Sierra.html +//@ has tango/trait.Tango.html +//@ hasraw sierra/struct.Sierra.html 'Tango' +//@ hasraw trait.impl/tango/trait.Tango.js 'struct.Sierra.html' +//@ hasraw search-index.js 'Sierra' + +// write only overwrites stuff in the output directory +extern crate tango; +pub struct Sierra; +impl tango::Tango for Sierra {} diff --git a/tests/rustdoc/merge-cross-crate-info/transitive-merge-none/auxiliary/quebec.rs b/tests/rustdoc/merge-cross-crate-info/transitive-merge-none/auxiliary/quebec.rs new file mode 100644 index 0000000000000..6ab921533b037 --- /dev/null +++ b/tests/rustdoc/merge-cross-crate-info/transitive-merge-none/auxiliary/quebec.rs @@ -0,0 +1,6 @@ +//@ doc-flags:--merge=none +//@ doc-flags:--parts-out-dir=info/doc.parts/quebec +//@ doc-flags:--enable-index-page +//@ doc-flags:-Zunstable-options + +pub struct Quebec; diff --git a/tests/rustdoc/merge-cross-crate-info/transitive-merge-none/auxiliary/tango.rs b/tests/rustdoc/merge-cross-crate-info/transitive-merge-none/auxiliary/tango.rs new file mode 100644 index 0000000000000..9fa99d3be8af4 --- /dev/null +++ b/tests/rustdoc/merge-cross-crate-info/transitive-merge-none/auxiliary/tango.rs @@ -0,0 +1,9 @@ +//@ aux-build:quebec.rs +//@ build-aux-docs +//@ doc-flags:--merge=none +//@ doc-flags:--parts-out-dir=info/doc.parts/tango +//@ doc-flags:--enable-index-page +//@ doc-flags:-Zunstable-options + +extern crate quebec; +pub trait Tango {} diff --git a/tests/rustdoc/merge-cross-crate-info/transitive-merge-none/sierra.rs b/tests/rustdoc/merge-cross-crate-info/transitive-merge-none/sierra.rs new file mode 100644 index 0000000000000..b407228085e88 --- /dev/null +++ b/tests/rustdoc/merge-cross-crate-info/transitive-merge-none/sierra.rs @@ -0,0 +1,27 @@ +//@ aux-build:tango.rs +//@ build-aux-docs +//@ doc-flags:--merge=finalize +//@ doc-flags:--include-parts-dir=info/doc.parts/tango +//@ doc-flags:--include-parts-dir=info/doc.parts/quebec +//@ doc-flags:--enable-index-page +//@ doc-flags:-Zunstable-options + +//@ has index.html +//@ has index.html '//h1' 'List of all crates' +//@ has index.html '//ul[@class="all-items"]//a[@href="quebec/index.html"]' 'quebec' +//@ has index.html '//ul[@class="all-items"]//a[@href="sierra/index.html"]' 'sierra' +//@ has index.html '//ul[@class="all-items"]//a[@href="tango/index.html"]' 'tango' +//@ has quebec/struct.Quebec.html +//@ has sierra/struct.Sierra.html +//@ has tango/trait.Tango.html +//@ hasraw sierra/struct.Sierra.html 'Tango' +//@ hasraw trait.impl/tango/trait.Tango.js 'struct.Sierra.html' +//@ hasraw search-index.js 'Tango' +//@ hasraw search-index.js 'Sierra' +//@ hasraw search-index.js 'Quebec' + +// We avoid writing any cross-crate information, preferring to include it +// with --include-parts-dir. +extern crate tango; +pub struct Sierra; +impl tango::Tango for Sierra {} diff --git a/tests/rustdoc/merge-cross-crate-info/transitive-merge-read-write/auxiliary/quebec.rs b/tests/rustdoc/merge-cross-crate-info/transitive-merge-read-write/auxiliary/quebec.rs new file mode 100644 index 0000000000000..1beca543f814f --- /dev/null +++ b/tests/rustdoc/merge-cross-crate-info/transitive-merge-read-write/auxiliary/quebec.rs @@ -0,0 +1,5 @@ +//@ doc-flags:--merge=finalize +//@ doc-flags:--enable-index-page +//@ doc-flags:-Zunstable-options + +pub struct Quebec; diff --git a/tests/rustdoc/merge-cross-crate-info/transitive-merge-read-write/auxiliary/tango.rs b/tests/rustdoc/merge-cross-crate-info/transitive-merge-read-write/auxiliary/tango.rs new file mode 100644 index 0000000000000..ff12fe98d82c2 --- /dev/null +++ b/tests/rustdoc/merge-cross-crate-info/transitive-merge-read-write/auxiliary/tango.rs @@ -0,0 +1,8 @@ +//@ aux-build:quebec.rs +//@ build-aux-docs +//@ doc-flags:--merge=shared +//@ doc-flags:--enable-index-page +//@ doc-flags:-Zunstable-options + +extern crate quebec; +pub trait Tango {} diff --git a/tests/rustdoc/merge-cross-crate-info/transitive-merge-read-write/sierra.rs b/tests/rustdoc/merge-cross-crate-info/transitive-merge-read-write/sierra.rs new file mode 100644 index 0000000000000..15e32d5941fb2 --- /dev/null +++ b/tests/rustdoc/merge-cross-crate-info/transitive-merge-read-write/sierra.rs @@ -0,0 +1,25 @@ +//@ aux-build:tango.rs +//@ build-aux-docs +//@ doc-flags:--merge=shared +//@ doc-flags:--enable-index-page +//@ doc-flags:-Zunstable-options + +//@ has index.html +//@ has index.html '//h1' 'List of all crates' +//@ has index.html '//ul[@class="all-items"]//a[@href="quebec/index.html"]' 'quebec' +//@ has index.html '//ul[@class="all-items"]//a[@href="sierra/index.html"]' 'sierra' +//@ has index.html '//ul[@class="all-items"]//a[@href="tango/index.html"]' 'tango' +//@ has quebec/struct.Quebec.html +//@ has sierra/struct.Sierra.html +//@ has tango/trait.Tango.html +//@ hasraw sierra/struct.Sierra.html 'Tango' +//@ hasraw trait.impl/tango/trait.Tango.js 'struct.Sierra.html' +//@ hasraw search-index.js 'Tango' +//@ hasraw search-index.js 'Sierra' +//@ hasraw search-index.js 'Quebec' + +// We can use read-write to emulate the default behavior of rustdoc, when +// --merge is left out. +extern crate tango; +pub struct Sierra; +impl tango::Tango for Sierra {} diff --git a/tests/rustdoc/merge-cross-crate-info/transitive-no-info/auxiliary/quebec.rs b/tests/rustdoc/merge-cross-crate-info/transitive-no-info/auxiliary/quebec.rs new file mode 100644 index 0000000000000..0e28d8e646647 --- /dev/null +++ b/tests/rustdoc/merge-cross-crate-info/transitive-no-info/auxiliary/quebec.rs @@ -0,0 +1,5 @@ +//@ doc-flags:--merge=none +//@ doc-flags:--enable-index-page +//@ doc-flags:-Zunstable-options + +pub struct Quebec; diff --git a/tests/rustdoc/merge-cross-crate-info/transitive-no-info/auxiliary/tango.rs b/tests/rustdoc/merge-cross-crate-info/transitive-no-info/auxiliary/tango.rs new file mode 100644 index 0000000000000..3827119f696f5 --- /dev/null +++ b/tests/rustdoc/merge-cross-crate-info/transitive-no-info/auxiliary/tango.rs @@ -0,0 +1,8 @@ +//@ aux-build:quebec.rs +//@ build-aux-docs +//@ doc-flags:--merge=none +//@ doc-flags:--enable-index-page +//@ doc-flags:-Zunstable-options + +extern crate quebec; +pub trait Tango {} diff --git a/tests/rustdoc/merge-cross-crate-info/transitive-no-info/sierra.rs b/tests/rustdoc/merge-cross-crate-info/transitive-no-info/sierra.rs new file mode 100644 index 0000000000000..3eb2cebd74363 --- /dev/null +++ b/tests/rustdoc/merge-cross-crate-info/transitive-no-info/sierra.rs @@ -0,0 +1,17 @@ +//@ aux-build:tango.rs +//@ build-aux-docs +//@ doc-flags:--merge=none +//@ doc-flags:--enable-index-page +//@ doc-flags:-Zunstable-options + +//@ !has index.html +//@ has sierra/struct.Sierra.html +//@ has tango/trait.Tango.html +//@ hasraw sierra/struct.Sierra.html 'Tango' +//@ !has trait.impl/tango/trait.Tango.js +//@ !has search-index.js + +// --merge=none on all crates does not generate any cross-crate info +extern crate tango; +pub struct Sierra; +impl tango::Tango for Sierra {} diff --git a/tests/rustdoc/merge-cross-crate-info/two-separate-out-dir/auxiliary/foxtrot.rs b/tests/rustdoc/merge-cross-crate-info/two-separate-out-dir/auxiliary/foxtrot.rs new file mode 100644 index 0000000000000..e492b700dbc2b --- /dev/null +++ b/tests/rustdoc/merge-cross-crate-info/two-separate-out-dir/auxiliary/foxtrot.rs @@ -0,0 +1,5 @@ +//@ unique-doc-out-dir +//@ doc-flags:--parts-out-dir=info/doc.parts/foxtrot +//@ doc-flags:-Zunstable-options + +pub trait Foxtrot {} diff --git a/tests/rustdoc/merge-cross-crate-info/two-separate-out-dir/echo.rs b/tests/rustdoc/merge-cross-crate-info/two-separate-out-dir/echo.rs new file mode 100644 index 0000000000000..ee2b646e43cda --- /dev/null +++ b/tests/rustdoc/merge-cross-crate-info/two-separate-out-dir/echo.rs @@ -0,0 +1,16 @@ +//@ aux-build:foxtrot.rs +//@ build-aux-docs +//@ doc-flags:--include-parts-dir=info/doc.parts/foxtrot +//@ doc-flags:-Zunstable-options + +//@ has echo/enum.Echo.html +//@ hasraw echo/enum.Echo.html 'Foxtrot' +//@ hasraw trait.impl/foxtrot/trait.Foxtrot.js 'enum.Echo.html' +//@ hasraw search-index.js 'Foxtrot' +//@ hasraw search-index.js 'Echo' + +// document two crates in different places, and merge their docs after +// they are generated +extern crate foxtrot; +pub enum Echo {} +impl foxtrot::Foxtrot for Echo {} From 42d03f6633e3ebc939d3d04d7605301f99d22a54 Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Sat, 7 Sep 2024 20:02:24 -0400 Subject: [PATCH 0661/2194] Add support for more SIMD intrinsics --- build_system/src/build.rs | 1 + src/intrinsic/simd.rs | 32 ++++++++++++++++++++++---------- 2 files changed, 23 insertions(+), 10 deletions(-) diff --git a/build_system/src/build.rs b/build_system/src/build.rs index d96683afa359c..d5d099fb14cfa 100644 --- a/build_system/src/build.rs +++ b/build_system/src/build.rs @@ -136,6 +136,7 @@ pub fn build_sysroot(env: &HashMap, config: &ConfigInfo) -> Resu &"build", &"--target", &config.target, + // TODO: remove this feature? &"--features", &"std/compiler-builtins-no-f16-f128", ]; diff --git a/src/intrinsic/simd.rs b/src/intrinsic/simd.rs index a0d8ff6346f3e..79b345982c6e0 100644 --- a/src/intrinsic/simd.rs +++ b/src/intrinsic/simd.rs @@ -739,11 +739,12 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( return Err(()); }}; } - let (elem_ty_str, elem_ty) = if let ty::Float(ref f) = *in_elem.kind() { + let (elem_ty_str, elem_ty, cast_type) = if let ty::Float(ref f) = *in_elem.kind() { let elem_ty = bx.cx.type_float_from_ty(*f); match f.bit_width() { - 32 => ("f", elem_ty), - 64 => ("", elem_ty), + 16 => ("", elem_ty, Some(bx.cx.double_type)), + 32 => ("f", elem_ty, None), + 64 => ("", elem_ty, None), _ => { return_error!(InvalidMonomorphization::FloatingPointVector { span, @@ -787,17 +788,28 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( for i in 0..in_len { let index = bx.context.new_rvalue_from_long(bx.ulong_type, i as i64); // we have to treat fpowi specially, since fpowi's second argument is always an i32 - let arguments = if name == sym::simd_fpowi { - vec![ + let mut arguments = vec![]; + if name == sym::simd_fpowi { + arguments = vec![ bx.extract_element(args[0].immediate(), index).to_rvalue(), args[1].immediate(), - ] + ]; } else { - args.iter() - .map(|arg| bx.extract_element(arg.immediate(), index).to_rvalue()) - .collect() + for arg in args { + let mut element = bx.extract_element(arg.immediate(), index).to_rvalue(); + // FIXME: it would probably be better to not have casts here and use the proper + // instructions. + if let Some(typ) = cast_type { + element = bx.context.new_cast(None, element, typ); + } + arguments.push(element); + } }; - vector_elements.push(bx.context.new_call(None, function, &arguments)); + let mut result = bx.context.new_call(None, function, &arguments); + if cast_type.is_some() { + result = bx.context.new_cast(None, result, elem_ty); + } + vector_elements.push(result); } let c = bx.context.new_rvalue_from_vector(None, vec_ty, &vector_elements); Ok(c) From e80c9ac3e213c0c2e6d1a80ea2d4bf074ff8f887 Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Fri, 30 Aug 2024 10:16:41 -0700 Subject: [PATCH 0662/2194] rustdoc: use `LocalDefId` for inline stmt It's never a cross-crate DefId, so save space by not storing it. --- src/librustdoc/clean/inline.rs | 22 +++++++++++----------- src/librustdoc/clean/mod.rs | 12 ++++++------ src/librustdoc/clean/types.rs | 8 +++++--- 3 files changed, 22 insertions(+), 20 deletions(-) diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index d22c4cc4b76b7..7978ce6e22e3b 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -5,7 +5,7 @@ use std::sync::Arc; use rustc_data_structures::fx::FxHashSet; use rustc_hir::def::{DefKind, Res}; -use rustc_hir::def_id::{DefId, DefIdSet, LocalModDefId}; +use rustc_hir::def_id::{DefId, DefIdSet, LocalDefId, LocalModDefId}; use rustc_hir::Mutability; use rustc_metadata::creader::{CStore, LoadedMacro}; use rustc_middle::ty::fast_reject::SimplifiedType; @@ -43,7 +43,7 @@ pub(crate) fn try_inline( cx: &mut DocContext<'_>, res: Res, name: Symbol, - attrs: Option<(&[ast::Attribute], Option)>, + attrs: Option<(&[ast::Attribute], Option)>, visited: &mut DefIdSet, ) -> Option> { let did = res.opt_def_id()?; @@ -157,7 +157,7 @@ pub(crate) fn try_inline( kind, did, name, - import_def_id.and_then(|def_id| def_id.as_local()), + import_def_id, None, ); // The visibility needs to reflect the one from the reexport and not from the "source" DefId. @@ -198,7 +198,7 @@ pub(crate) fn try_inline_glob( visited, inlined_names, Some(&reexports), - Some((attrs, Some(import.owner_id.def_id.to_def_id()))), + Some((attrs, Some(import.owner_id.def_id))), ); items.retain(|item| { if let Some(name) = item.name { @@ -372,7 +372,7 @@ fn build_type_alias( pub(crate) fn build_impls( cx: &mut DocContext<'_>, did: DefId, - attrs: Option<(&[ast::Attribute], Option)>, + attrs: Option<(&[ast::Attribute], Option)>, ret: &mut Vec, ) { let _prof_timer = cx.tcx.sess.prof.generic_activity("build_inherent_impls"); @@ -405,7 +405,7 @@ pub(crate) fn build_impls( pub(crate) fn merge_attrs( cx: &mut DocContext<'_>, old_attrs: &[ast::Attribute], - new_attrs: Option<(&[ast::Attribute], Option)>, + new_attrs: Option<(&[ast::Attribute], Option)>, ) -> (clean::Attributes, Option>) { // NOTE: If we have additional attributes (from a re-export), // always insert them first. This ensure that re-export @@ -416,7 +416,7 @@ pub(crate) fn merge_attrs( both.extend_from_slice(old_attrs); ( if let Some(item_id) = item_id { - Attributes::from_ast_with_additional(old_attrs, (inner, item_id)) + Attributes::from_ast_with_additional(old_attrs, (inner, item_id.to_def_id())) } else { Attributes::from_ast(&both) }, @@ -431,7 +431,7 @@ pub(crate) fn merge_attrs( pub(crate) fn build_impl( cx: &mut DocContext<'_>, did: DefId, - attrs: Option<(&[ast::Attribute], Option)>, + attrs: Option<(&[ast::Attribute], Option)>, ret: &mut Vec, ) { if !cx.inlined.insert(did.into()) { @@ -641,7 +641,7 @@ fn build_module_items( visited: &mut DefIdSet, inlined_names: &mut FxHashSet<(ItemType, Symbol)>, allowed_def_ids: Option<&DefIdSet>, - attrs: Option<(&[ast::Attribute], Option)>, + attrs: Option<(&[ast::Attribute], Option)>, ) -> Vec { let mut items = Vec::new(); @@ -745,7 +745,7 @@ fn build_macro( cx: &mut DocContext<'_>, def_id: DefId, name: Symbol, - import_def_id: Option, + import_def_id: Option, macro_kind: MacroKind, is_doc_hidden: bool, ) -> clean::ItemKind { @@ -753,7 +753,7 @@ fn build_macro( LoadedMacro::MacroDef(item_def, _) => match macro_kind { MacroKind::Bang => { if let ast::ItemKind::MacroDef(ref def) = item_def.kind { - let vis = cx.tcx.visibility(import_def_id.unwrap_or(def_id)); + let vis = cx.tcx.visibility(import_def_id.map(|d| d.to_def_id()).unwrap_or(def_id)); clean::MacroItem(clean::Macro { source: utils::display_macro_source( cx, diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 710bd4a5fdff7..1dc6d820780de 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -204,7 +204,7 @@ fn generate_item_with_correct_attrs( let name = renamed.or(Some(name)); let mut item = Item::from_def_id_and_attrs_and_parts(def_id, name, kind, Box::new(attrs), cfg); - item.inline_stmt_id = import_id.map(|local| local.to_def_id()); + item.inline_stmt_id = import_id; item } @@ -2927,7 +2927,7 @@ fn clean_extern_crate<'tcx>( }) && !cx.output_format.is_json(); - let krate_owner_def_id = krate.owner_id.to_def_id(); + let krate_owner_def_id = krate.owner_id.def_id; if please_inline { if let Some(items) = inline::try_inline( cx, @@ -2941,7 +2941,7 @@ fn clean_extern_crate<'tcx>( } vec![Item::from_def_id_and_parts( - krate_owner_def_id, + krate_owner_def_id.to_def_id(), Some(name), ExternCrateItem { src: orig_name }, cx, @@ -2988,7 +2988,7 @@ fn clean_use_statement_inner<'tcx>( let inline_attr = attrs.lists(sym::doc).get_word_attr(sym::inline); let pub_underscore = visibility.is_public() && name == kw::Underscore; let current_mod = cx.tcx.parent_module_from_def_id(import.owner_id.def_id); - let import_def_id = import.owner_id.def_id.to_def_id(); + let import_def_id = import.owner_id.def_id; // The parent of the module in which this import resides. This // is the same as `current_mod` if that's already the top @@ -3071,7 +3071,7 @@ fn clean_use_statement_inner<'tcx>( ) { items.push(Item::from_def_id_and_parts( - import_def_id, + import_def_id.to_def_id(), None, ImportItem(Import::new_simple(name, resolve_use_source(cx, path), false)), cx, @@ -3081,7 +3081,7 @@ fn clean_use_statement_inner<'tcx>( Import::new_simple(name, resolve_use_source(cx, path), true) }; - vec![Item::from_def_id_and_parts(import_def_id, None, ImportItem(inner), cx)] + vec![Item::from_def_id_and_parts(import_def_id.to_def_id(), None, ImportItem(inner), cx)] } fn clean_maybe_renamed_foreign_item<'tcx>( diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index 5666b229078b4..19aab2116585d 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -325,8 +325,10 @@ pub(crate) struct Item { /// E.g., struct vs enum vs function. pub(crate) kind: Box, pub(crate) item_id: ItemId, - /// This is the `DefId` of the `use` statement if the item was inlined. - pub(crate) inline_stmt_id: Option, + /// This is the `LocalDefId` of the `use` statement if the item was inlined. + /// The crate metadata doesn't hold this information, so the `use` statement + /// always belongs to the current crate. + pub(crate) inline_stmt_id: Option, pub(crate) cfg: Option>, } @@ -702,7 +704,7 @@ impl Item { _ => {} } let def_id = match self.inline_stmt_id { - Some(inlined) => inlined, + Some(inlined) => inlined.to_def_id(), None => def_id, }; Some(tcx.visibility(def_id)) From 65903362ad810c572e8ae742f6ed5ae3548238e4 Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Fri, 30 Aug 2024 10:52:45 -0700 Subject: [PATCH 0663/2194] rustdoc: use a single box to store Attributes and ItemKind --- src/librustdoc/clean/auto_trait.rs | 22 +++--- src/librustdoc/clean/blanket_impl.rs | 72 ++++++++++--------- src/librustdoc/clean/inline.rs | 51 +++++++------ src/librustdoc/clean/mod.rs | 2 +- src/librustdoc/clean/types.rs | 55 ++++++++------ src/librustdoc/clean/utils.rs | 6 +- src/librustdoc/fold.rs | 10 +-- src/librustdoc/formats/cache.rs | 26 ++++--- src/librustdoc/formats/item_type.rs | 2 +- src/librustdoc/formats/mod.rs | 2 +- src/librustdoc/formats/renderer.rs | 2 +- src/librustdoc/html/render/context.rs | 2 +- src/librustdoc/html/render/mod.rs | 22 +++--- src/librustdoc/html/render/print_item.rs | 38 +++++----- src/librustdoc/html/render/search_index.rs | 4 +- src/librustdoc/html/render/sidebar.rs | 10 +-- src/librustdoc/html/render/write_shared.rs | 2 +- src/librustdoc/json/conversions.rs | 6 +- src/librustdoc/json/import_finder.rs | 2 +- src/librustdoc/json/mod.rs | 4 +- .../passes/calculate_doc_coverage.rs | 2 +- .../passes/check_doc_test_visibility.rs | 2 +- src/librustdoc/passes/collect_trait_impls.rs | 10 +-- src/librustdoc/passes/propagate_doc_cfg.rs | 2 +- .../passes/strip_aliased_non_local.rs | 2 +- src/librustdoc/passes/strip_hidden.rs | 4 +- src/librustdoc/passes/stripper.rs | 8 +-- src/librustdoc/visit.rs | 4 +- 28 files changed, 195 insertions(+), 179 deletions(-) diff --git a/src/librustdoc/clean/auto_trait.rs b/src/librustdoc/clean/auto_trait.rs index 654901080278d..7e3881c798b53 100644 --- a/src/librustdoc/clean/auto_trait.rs +++ b/src/librustdoc/clean/auto_trait.rs @@ -115,17 +115,19 @@ fn synthesize_auto_trait_impl<'tcx>( Some(clean::Item { name: None, - attrs: Default::default(), + inner: Box::new(clean::ItemInner { + attrs: Default::default(), + kind: clean::ImplItem(Box::new(clean::Impl { + safety: hir::Safety::Safe, + generics, + trait_: Some(clean_trait_ref_with_constraints(cx, trait_ref, ThinVec::new())), + for_: clean_middle_ty(ty::Binder::dummy(ty), cx, None, None), + items: Vec::new(), + polarity, + kind: clean::ImplKind::Auto, + })), + }), item_id: clean::ItemId::Auto { trait_: trait_def_id, for_: item_def_id }, - kind: Box::new(clean::ImplItem(Box::new(clean::Impl { - safety: hir::Safety::Safe, - generics, - trait_: Some(clean_trait_ref_with_constraints(cx, trait_ref, ThinVec::new())), - for_: clean_middle_ty(ty::Binder::dummy(ty), cx, None, None), - items: Vec::new(), - polarity, - kind: clean::ImplKind::Auto, - }))), cfg: None, inline_stmt_id: None, }) diff --git a/src/librustdoc/clean/blanket_impl.rs b/src/librustdoc/clean/blanket_impl.rs index 1f5f6602b9f23..95f6616cec345 100644 --- a/src/librustdoc/clean/blanket_impl.rs +++ b/src/librustdoc/clean/blanket_impl.rs @@ -84,42 +84,44 @@ pub(crate) fn synthesize_blanket_impls( blanket_impls.push(clean::Item { name: None, - attrs: Default::default(), item_id: clean::ItemId::Blanket { impl_id: impl_def_id, for_: item_def_id }, - kind: Box::new(clean::ImplItem(Box::new(clean::Impl { - safety: hir::Safety::Safe, - generics: clean_ty_generics( - cx, - tcx.generics_of(impl_def_id), - tcx.explicit_predicates_of(impl_def_id), - ), - // FIXME(eddyb) compute both `trait_` and `for_` from - // the post-inference `trait_ref`, as it's more accurate. - trait_: Some(clean_trait_ref_with_constraints( - cx, - ty::Binder::dummy(trait_ref.instantiate_identity()), - ThinVec::new(), - )), - for_: clean_middle_ty( - ty::Binder::dummy(ty.instantiate_identity()), - cx, - None, - None, - ), - items: tcx - .associated_items(impl_def_id) - .in_definition_order() - .filter(|item| !item.is_impl_trait_in_trait()) - .map(|item| clean_middle_assoc_item(item, cx)) - .collect(), - polarity: ty::ImplPolarity::Positive, - kind: clean::ImplKind::Blanket(Box::new(clean_middle_ty( - ty::Binder::dummy(trait_ref.instantiate_identity().self_ty()), - cx, - None, - None, - ))), - }))), + inner: Box::new(clean::ItemInner { + attrs: Default::default(), + kind: clean::ImplItem(Box::new(clean::Impl { + safety: hir::Safety::Safe, + generics: clean_ty_generics( + cx, + tcx.generics_of(impl_def_id), + tcx.explicit_predicates_of(impl_def_id), + ), + // FIXME(eddyb) compute both `trait_` and `for_` from + // the post-inference `trait_ref`, as it's more accurate. + trait_: Some(clean_trait_ref_with_constraints( + cx, + ty::Binder::dummy(trait_ref.instantiate_identity()), + ThinVec::new(), + )), + for_: clean_middle_ty( + ty::Binder::dummy(ty.instantiate_identity()), + cx, + None, + None, + ), + items: tcx + .associated_items(impl_def_id) + .in_definition_order() + .filter(|item| !item.is_impl_trait_in_trait()) + .map(|item| clean_middle_assoc_item(item, cx)) + .collect(), + polarity: ty::ImplPolarity::Positive, + kind: clean::ImplKind::Blanket(Box::new(clean_middle_ty( + ty::Binder::dummy(trait_ref.instantiate_identity().self_ty()), + cx, + None, + None, + ))), + })), + }), cfg: None, inline_stmt_id: None, }); diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index 7978ce6e22e3b..8383012885f96 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -152,14 +152,8 @@ pub(crate) fn try_inline( }; cx.inlined.insert(did.into()); - let mut item = crate::clean::generate_item_with_correct_attrs( - cx, - kind, - did, - name, - import_def_id, - None, - ); + let mut item = + crate::clean::generate_item_with_correct_attrs(cx, kind, did, name, import_def_id, None); // The visibility needs to reflect the one from the reexport and not from the "source" DefId. item.inline_stmt_id = import_def_id; ret.push(item); @@ -623,7 +617,7 @@ pub(crate) fn build_impl( ImplKind::Normal }, })), - Box::new(merged_attrs), + merged_attrs, cfg, )); } @@ -673,27 +667,29 @@ fn build_module_items( let prim_ty = clean::PrimitiveType::from(p); items.push(clean::Item { name: None, - attrs: Box::default(), // We can use the item's `DefId` directly since the only information ever used // from it is `DefId.krate`. item_id: ItemId::DefId(did), - kind: Box::new(clean::ImportItem(clean::Import::new_simple( - item.ident.name, - clean::ImportSource { - path: clean::Path { - res, - segments: thin_vec![clean::PathSegment { - name: prim_ty.as_sym(), - args: clean::GenericArgs::AngleBracketed { - args: Default::default(), - constraints: ThinVec::new(), - }, - }], + inner: Box::new(clean::ItemInner { + attrs: Default::default(), + kind: clean::ImportItem(clean::Import::new_simple( + item.ident.name, + clean::ImportSource { + path: clean::Path { + res, + segments: thin_vec![clean::PathSegment { + name: prim_ty.as_sym(), + args: clean::GenericArgs::AngleBracketed { + args: Default::default(), + constraints: ThinVec::new(), + }, + }], + }, + did: None, }, - did: None, - }, - true, - ))), + true, + )), + }), cfg: None, inline_stmt_id: None, }); @@ -753,7 +749,8 @@ fn build_macro( LoadedMacro::MacroDef(item_def, _) => match macro_kind { MacroKind::Bang => { if let ast::ItemKind::MacroDef(ref def) = item_def.kind { - let vis = cx.tcx.visibility(import_def_id.map(|d| d.to_def_id()).unwrap_or(def_id)); + let vis = + cx.tcx.visibility(import_def_id.map(|d| d.to_def_id()).unwrap_or(def_id)); clean::MacroItem(clean::Macro { source: utils::display_macro_source( cx, diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 1dc6d820780de..e47ae7df77fb6 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -203,7 +203,7 @@ fn generate_item_with_correct_attrs( let attrs = Attributes::from_ast_iter(attrs.iter().map(|(attr, did)| (&**attr, *did)), false); let name = renamed.or(Some(name)); - let mut item = Item::from_def_id_and_attrs_and_parts(def_id, name, kind, Box::new(attrs), cfg); + let mut item = Item::from_def_id_and_attrs_and_parts(def_id, name, kind, attrs, cfg); item.inline_stmt_id = import_id; item } diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index 19aab2116585d..383efe568ae09 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -320,10 +320,7 @@ pub(crate) struct Item { /// The name of this item. /// Optional because not every item has a name, e.g. impls. pub(crate) name: Option, - pub(crate) attrs: Box, - /// Information about this item that is specific to what kind of item it is. - /// E.g., struct vs enum vs function. - pub(crate) kind: Box, + pub(crate) inner: Box, pub(crate) item_id: ItemId, /// This is the `LocalDefId` of the `use` statement if the item was inlined. /// The crate metadata doesn't hold this information, so the `use` statement @@ -332,6 +329,21 @@ pub(crate) struct Item { pub(crate) cfg: Option>, } +#[derive(Clone)] +pub(crate) struct ItemInner { + /// Information about this item that is specific to what kind of item it is. + /// E.g., struct vs enum vs function. + pub(crate) kind: ItemKind, + pub(crate) attrs: Attributes, +} + +impl std::ops::Deref for Item { + type Target = ItemInner; + fn deref(&self) -> &ItemInner { + &*self.inner + } +} + /// NOTE: this does NOT unconditionally print every item, to avoid thousands of lines of logs. /// If you want to see the debug output for attributes and the `kind` as well, use `{:#?}` instead of `{:?}`. impl fmt::Debug for Item { @@ -391,9 +403,9 @@ impl Item { } pub(crate) fn span(&self, tcx: TyCtxt<'_>) -> Option { - let kind = match &*self.kind { - ItemKind::StrippedItem(k) => k, - _ => &*self.kind, + let kind = match &self.kind { + ItemKind::StrippedItem(k) => &*k, + _ => &self.kind, }; match kind { ItemKind::ModuleItem(Module { span, .. }) => Some(*span), @@ -438,7 +450,7 @@ impl Item { def_id, name, kind, - Box::new(Attributes::from_ast(ast_attrs)), + Attributes::from_ast(ast_attrs), ast_attrs.cfg(cx.tcx, &cx.cache.hidden_cfg), ) } @@ -447,16 +459,15 @@ impl Item { def_id: DefId, name: Option, kind: ItemKind, - attrs: Box, + attrs: Attributes, cfg: Option>, ) -> Item { trace!("name={name:?}, def_id={def_id:?} cfg={cfg:?}"); Item { item_id: def_id.into(), - kind: Box::new(kind), + inner: Box::new(ItemInner { kind, attrs }), name, - attrs, cfg, inline_stmt_id: None, } @@ -524,16 +535,16 @@ impl Item { self.type_() == ItemType::Variant } pub(crate) fn is_associated_type(&self) -> bool { - matches!(&*self.kind, AssocTypeItem(..) | StrippedItem(box AssocTypeItem(..))) + matches!(self.kind, AssocTypeItem(..) | StrippedItem(box AssocTypeItem(..))) } pub(crate) fn is_ty_associated_type(&self) -> bool { - matches!(&*self.kind, TyAssocTypeItem(..) | StrippedItem(box TyAssocTypeItem(..))) + matches!(self.kind, TyAssocTypeItem(..) | StrippedItem(box TyAssocTypeItem(..))) } pub(crate) fn is_associated_const(&self) -> bool { - matches!(&*self.kind, AssocConstItem(..) | StrippedItem(box AssocConstItem(..))) + matches!(self.kind, AssocConstItem(..) | StrippedItem(box AssocConstItem(..))) } pub(crate) fn is_ty_associated_const(&self) -> bool { - matches!(&*self.kind, TyAssocConstItem(..) | StrippedItem(box TyAssocConstItem(..))) + matches!(self.kind, TyAssocConstItem(..) | StrippedItem(box TyAssocConstItem(..))) } pub(crate) fn is_method(&self) -> bool { self.type_() == ItemType::Method @@ -557,14 +568,14 @@ impl Item { self.type_() == ItemType::Keyword } pub(crate) fn is_stripped(&self) -> bool { - match *self.kind { + match self.kind { StrippedItem(..) => true, ImportItem(ref i) => !i.should_be_displayed, _ => false, } } pub(crate) fn has_stripped_entries(&self) -> Option { - match *self.kind { + match self.kind { StructItem(ref struct_) => Some(struct_.has_stripped_entries()), UnionItem(ref union_) => Some(union_.has_stripped_entries()), EnumItem(ref enum_) => Some(enum_.has_stripped_entries()), @@ -607,7 +618,7 @@ impl Item { } pub(crate) fn is_default(&self) -> bool { - match *self.kind { + match self.kind { ItemKind::MethodItem(_, Some(defaultness)) => { defaultness.has_value() && !defaultness.is_final() } @@ -635,7 +646,7 @@ impl Item { }; hir::FnHeader { safety: sig.safety(), abi: sig.abi(), constness, asyncness } } - let header = match *self.kind { + let header = match self.kind { ItemKind::ForeignFunctionItem(_, safety) => { let def_id = self.def_id().unwrap(); let abi = tcx.fn_sig(def_id).skip_binder().abi(); @@ -674,7 +685,7 @@ impl Item { ItemId::DefId(def_id) => def_id, }; - match *self.kind { + match self.kind { // Primitives and Keywords are written in the source code as private modules. // The modules need to be private so that nobody actually uses them, but the // keywords and primitives that they are documenting are public. @@ -2561,13 +2572,13 @@ mod size_asserts { use super::*; // tidy-alphabetical-start - static_assert_size!(Crate, 64); // frequently moved by-value + static_assert_size!(Crate, 56); // frequently moved by-value static_assert_size!(DocFragment, 32); static_assert_size!(GenericArg, 32); static_assert_size!(GenericArgs, 32); static_assert_size!(GenericParamDef, 40); static_assert_size!(Generics, 16); - static_assert_size!(Item, 56); + static_assert_size!(Item, 48); static_assert_size!(ItemKind, 48); static_assert_size!(PathSegment, 40); static_assert_size!(Type, 32); diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs index 5686307d83dda..885758c17cf8e 100644 --- a/src/librustdoc/clean/utils.rs +++ b/src/librustdoc/clean/utils.rs @@ -36,7 +36,7 @@ pub(crate) fn krate(cx: &mut DocContext<'_>) -> Crate { // understood by rustdoc. let mut module = clean_doc_module(&module, cx); - match *module.kind { + match module.kind { ItemKind::ModuleItem(ref module) => { for it in &module.items { // `compiler_builtins` should be masked too, but we can't apply @@ -60,7 +60,7 @@ pub(crate) fn krate(cx: &mut DocContext<'_>) -> Crate { let primitives = local_crate.primitives(cx.tcx); let keywords = local_crate.keywords(cx.tcx); { - let ItemKind::ModuleItem(ref mut m) = *module.kind else { unreachable!() }; + let ItemKind::ModuleItem(ref mut m) = &mut module.inner.kind else { unreachable!() }; m.items.extend(primitives.iter().map(|&(def_id, prim)| { Item::from_def_id_and_parts( def_id, @@ -281,7 +281,7 @@ pub(crate) fn build_deref_target_impls( let tcx = cx.tcx; for item in items { - let target = match *item.kind { + let target = match item.kind { ItemKind::AssocTypeItem(ref t, _) => &t.type_, _ => continue, }; diff --git a/src/librustdoc/fold.rs b/src/librustdoc/fold.rs index bf82c911f290f..c25a4ddb6f369 100644 --- a/src/librustdoc/fold.rs +++ b/src/librustdoc/fold.rs @@ -1,8 +1,8 @@ use crate::clean::*; pub(crate) fn strip_item(mut item: Item) -> Item { - if !matches!(*item.kind, StrippedItem(..)) { - item.kind = Box::new(StrippedItem(item.kind)); + if !matches!(item.inner.kind, StrippedItem(..)) { + item.inner.kind = StrippedItem(Box::new(item.inner.kind)); } item } @@ -99,10 +99,10 @@ pub(crate) trait DocFolder: Sized { /// don't override! fn fold_item_recur(&mut self, mut item: Item) -> Item { - item.kind = Box::new(match *item.kind { + item.inner.kind = match item.inner.kind { StrippedItem(box i) => StrippedItem(Box::new(self.fold_inner_recur(i))), - _ => self.fold_inner_recur(*item.kind), - }); + _ => self.fold_inner_recur(item.inner.kind), + }; item } diff --git a/src/librustdoc/formats/cache.rs b/src/librustdoc/formats/cache.rs index c5e2b33ccf874..1b3176e7918b7 100644 --- a/src/librustdoc/formats/cache.rs +++ b/src/librustdoc/formats/cache.rs @@ -216,7 +216,7 @@ impl<'a, 'tcx> DocFolder for CacheBuilder<'a, 'tcx> { // If this is a stripped module, // we don't want it or its children in the search index. - let orig_stripped_mod = match *item.kind { + let orig_stripped_mod = match item.kind { clean::StrippedItem(box clean::ModuleItem(..)) => { mem::replace(&mut self.cache.stripped_mod, true) } @@ -232,7 +232,7 @@ impl<'a, 'tcx> DocFolder for CacheBuilder<'a, 'tcx> { // If the impl is from a masked crate or references something from a // masked crate then remove it completely. - if let clean::ImplItem(ref i) = *item.kind + if let clean::ImplItem(ref i) = item.kind && (self.cache.masked_crates.contains(&item.item_id.krate()) || i.trait_ .as_ref() @@ -246,9 +246,9 @@ impl<'a, 'tcx> DocFolder for CacheBuilder<'a, 'tcx> { // Propagate a trait method's documentation to all implementors of the // trait. - if let clean::TraitItem(ref t) = *item.kind { + if let clean::TraitItem(ref t) = item.kind { self.cache.traits.entry(item.item_id.expect_def_id()).or_insert_with(|| (**t).clone()); - } else if let clean::ImplItem(ref i) = *item.kind + } else if let clean::ImplItem(ref i) = item.kind && let Some(trait_) = &i.trait_ && !i.kind.is_blanket() { @@ -263,7 +263,7 @@ impl<'a, 'tcx> DocFolder for CacheBuilder<'a, 'tcx> { // Index this method for searching later on. let search_name = if !item.is_stripped() { item.name.or_else(|| { - if let clean::ImportItem(ref i) = *item.kind + if let clean::ImportItem(ref i) = item.kind && let clean::ImportKind::Simple(s) = i.kind { Some(s) @@ -287,7 +287,7 @@ impl<'a, 'tcx> DocFolder for CacheBuilder<'a, 'tcx> { _ => false, }; - match *item.kind { + match item.kind { clean::StructItem(..) | clean::EnumItem(..) | clean::TypeAliasItem(..) @@ -350,7 +350,7 @@ impl<'a, 'tcx> DocFolder for CacheBuilder<'a, 'tcx> { } // Maintain the parent stack. - let (item, parent_pushed) = match *item.kind { + let (item, parent_pushed) = match item.kind { clean::TraitItem(..) | clean::EnumItem(..) | clean::ForeignTypeItem @@ -367,7 +367,11 @@ impl<'a, 'tcx> DocFolder for CacheBuilder<'a, 'tcx> { // Once we've recursively found all the generics, hoard off all the // implementations elsewhere. - let ret = if let clean::Item { kind: box clean::ImplItem(ref i), .. } = item { + let ret = if let clean::Item { + inner: box clean::ItemInner { kind: clean::ImplItem(ref i), .. }, + .. + } = item + { // Figure out the id of this impl. This may map to a // primitive rather than always to a struct/enum. // Note: matching twice to restrict the lifetime of the `i` borrow. @@ -436,7 +440,7 @@ impl<'a, 'tcx> DocFolder for CacheBuilder<'a, 'tcx> { fn add_item_to_search_index(tcx: TyCtxt<'_>, cache: &mut Cache, item: &clean::Item, name: Symbol) { // Item has a name, so it must also have a DefId (can't be an impl, let alone a blanket or auto impl). let item_def_id = item.item_id.as_def_id().unwrap(); - let (parent_did, parent_path) = match *item.kind { + let (parent_did, parent_path) = match item.kind { clean::StrippedItem(..) => return, clean::AssocConstItem(..) | clean::AssocTypeItem(..) if cache.parent_stack.last().is_some_and(|parent| parent.is_trait_impl()) => @@ -528,7 +532,7 @@ fn add_item_to_search_index(tcx: TyCtxt<'_>, cache: &mut Cache, item: &clean::It // - It's either an inline, or a true re-export // - It's got the same name // - Both of them have the same exact path - let defid = match &*item.kind { + let defid = match &item.kind { clean::ItemKind::ImportItem(import) => import.source.did.unwrap_or(item_def_id), _ => item_def_id, }; @@ -605,7 +609,7 @@ enum ParentStackItem { impl ParentStackItem { fn new(item: &clean::Item) -> Self { - match &*item.kind { + match &item.kind { clean::ItemKind::ImplItem(box clean::Impl { for_, trait_, generics, kind, .. }) => { ParentStackItem::Impl { for_: for_.clone(), diff --git a/src/librustdoc/formats/item_type.rs b/src/librustdoc/formats/item_type.rs index 9754e1e6f74d4..383e3135faa86 100644 --- a/src/librustdoc/formats/item_type.rs +++ b/src/librustdoc/formats/item_type.rs @@ -70,7 +70,7 @@ impl Serialize for ItemType { impl<'a> From<&'a clean::Item> for ItemType { fn from(item: &'a clean::Item) -> ItemType { - let kind = match *item.kind { + let kind = match item.kind { clean::StrippedItem(box ref item) => item, ref kind => kind, }; diff --git a/src/librustdoc/formats/mod.rs b/src/librustdoc/formats/mod.rs index 84adca8efa997..0bdea36043ca6 100644 --- a/src/librustdoc/formats/mod.rs +++ b/src/librustdoc/formats/mod.rs @@ -16,7 +16,7 @@ pub(crate) struct Impl { impl Impl { pub(crate) fn inner_impl(&self) -> &clean::Impl { - match *self.impl_item.kind { + match self.impl_item.kind { clean::ImplItem(ref impl_) => impl_, _ => panic!("non-impl item found in impl"), } diff --git a/src/librustdoc/formats/renderer.rs b/src/librustdoc/formats/renderer.rs index cc57dca86c341..edd7d56b17983 100644 --- a/src/librustdoc/formats/renderer.rs +++ b/src/librustdoc/formats/renderer.rs @@ -77,7 +77,7 @@ pub(crate) fn run_format<'tcx, T: FormatRenderer<'tcx>>( cx.mod_item_in(&item)?; let (clean::StrippedItem(box clean::ModuleItem(module)) | clean::ModuleItem(module)) = - *item.kind + item.inner.kind else { unreachable!() }; diff --git a/src/librustdoc/html/render/context.rs b/src/librustdoc/html/render/context.rs index 9fe43e428f2ae..58a228b74fcf3 100644 --- a/src/librustdoc/html/render/context.rs +++ b/src/librustdoc/html/render/context.rs @@ -800,7 +800,7 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> { // Render sidebar-items.js used throughout this module. if !self.render_redirect_pages { let (clean::StrippedItem(box clean::ModuleItem(ref module)) - | clean::ModuleItem(ref module)) = *item.kind + | clean::ModuleItem(ref module)) = item.kind else { unreachable!() }; diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index f67d006116cb6..3b8eda08372e6 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -620,7 +620,7 @@ fn document_full_inner<'a, 'cx: 'a>( } } - let kind = match &*item.kind { + let kind = match &item.kind { clean::ItemKind::StrippedItem(box kind) | kind => kind, }; @@ -1072,7 +1072,7 @@ fn render_assoc_item( cx: &mut Context<'_>, render_mode: RenderMode, ) { - match &*item.kind { + match &item.kind { clean::StrippedItem(..) => {} clean::TyMethodItem(m) => { assoc_method(w, item, &m.generics, &m.decl, link, parent, cx, render_mode) @@ -1350,7 +1350,7 @@ fn render_deref_methods( .inner_impl() .items .iter() - .find_map(|item| match *item.kind { + .find_map(|item| match item.kind { clean::AssocTypeItem(box ref t, _) => Some(match *t { clean::TypeAlias { item_type: Some(ref type_), .. } => (type_, &t.type_), _ => (&t.type_, &t.type_), @@ -1381,7 +1381,7 @@ fn render_deref_methods( } fn should_render_item(item: &clean::Item, deref_mut_: bool, tcx: TyCtxt<'_>) -> bool { - let self_type_opt = match *item.kind { + let self_type_opt = match item.kind { clean::MethodItem(ref method, _) => method.decl.receiver_type(), clean::TyMethodItem(ref method) => method.decl.receiver_type(), _ => None, @@ -1491,7 +1491,7 @@ fn notable_traits_decl(ty: &clean::Type, cx: &Context<'_>) -> (String, String) { write!(&mut out, "
{}
", impl_.print(false, cx)); for it in &impl_.items { - if let clean::AssocTypeItem(ref tydef, ref _bounds) = *it.kind { + if let clean::AssocTypeItem(ref tydef, ref _bounds) = it.kind { out.push_str("
"); let empty_set = FxHashSet::default(); let src_link = AssocItemLink::GotoSource(trait_did.into(), &empty_set); @@ -1659,7 +1659,7 @@ fn render_impl( let method_toggle_class = if item_type.is_method() { " method-toggle" } else { "" }; write!(w, "
"); } - match &*item.kind { + match &item.kind { clean::MethodItem(..) | clean::TyMethodItem(_) => { // Only render when the method is not static or we allow static methods if render_method_item { @@ -1690,7 +1690,7 @@ fn render_impl( w.write_str(""); } } - clean::TyAssocConstItem(generics, ty) => { + clean::TyAssocConstItem(ref generics, ref ty) => { let source_id = format!("{item_type}.{name}"); let id = cx.derive_id(&source_id); write!(w, "
"); @@ -1734,7 +1734,7 @@ fn render_impl( ); w.write_str("
"); } - clean::TyAssocTypeItem(generics, bounds) => { + clean::TyAssocTypeItem(ref generics, ref bounds) => { let source_id = format!("{item_type}.{name}"); let id = cx.derive_id(&source_id); write!(w, "
"); @@ -1808,7 +1808,7 @@ fn render_impl( if !impl_.is_negative_trait_impl() { for trait_item in &impl_.items { - match *trait_item.kind { + match trait_item.kind { clean::MethodItem(..) | clean::TyMethodItem(_) => methods.push(trait_item), clean::TyAssocTypeItem(..) | clean::AssocTypeItem(..) => { assoc_types.push(trait_item) @@ -2051,7 +2051,7 @@ pub(crate) fn render_impl_summary( write!(w, "{}", inner_impl.print(use_absolute, cx)); if show_def_docs { for it in &inner_impl.items { - if let clean::AssocTypeItem(ref tydef, ref _bounds) = *it.kind { + if let clean::AssocTypeItem(ref tydef, ref _bounds) = it.kind { w.write_str("
"); assoc_type( w, @@ -2172,7 +2172,7 @@ fn get_id_for_impl<'tcx>(tcx: TyCtxt<'tcx>, impl_id: ItemId) -> String { } fn extract_for_impl_name(item: &clean::Item, cx: &Context<'_>) -> Option<(String, String)> { - match *item.kind { + match item.kind { clean::ItemKind::ImplItem(ref i) if i.trait_.is_some() => { // Alternative format produces no URLs, // so this parameter does nothing. diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs index cda5409a460ee..52e2515277087 100644 --- a/src/librustdoc/html/render/print_item.rs +++ b/src/librustdoc/html/render/print_item.rs @@ -178,7 +178,7 @@ fn print_where_clause_and_check<'a, 'tcx: 'a>( pub(super) fn print_item(cx: &mut Context<'_>, item: &clean::Item, buf: &mut Buffer) { debug_assert!(!item.is_stripped()); - let typ = match *item.kind { + let typ = match item.kind { clean::ModuleItem(_) => { if item.is_crate() { "Crate " @@ -252,7 +252,7 @@ pub(super) fn print_item(cx: &mut Context<'_>, item: &clean::Item, buf: &mut Buf item_vars.render_into(buf).unwrap(); - match &*item.kind { + match &item.kind { clean::ModuleItem(ref m) => item_module(buf, cx, item, &m.items), clean::FunctionItem(ref f) | clean::ForeignFunctionItem(ref f, _) => { item_function(buf, cx, item, f) @@ -411,7 +411,7 @@ fn item_module(w: &mut Buffer, cx: &mut Context<'_>, item: &clean::Item, items: ); } - match *myitem.kind { + match myitem.kind { clean::ExternCrateItem { ref src } => { use crate::html::format::anchor; @@ -477,7 +477,7 @@ fn item_module(w: &mut Buffer, cx: &mut Context<'_>, item: &clean::Item, items: continue; } - let unsafety_flag = match *myitem.kind { + let unsafety_flag = match myitem.kind { clean::FunctionItem(_) | clean::ForeignFunctionItem(..) if myitem.fn_header(tcx).unwrap().safety == hir::Safety::Unsafe => { @@ -1439,7 +1439,7 @@ fn item_union(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, s: &clean: self.s .fields .iter() - .filter_map(|f| match *f.kind { + .filter_map(|f| match f.kind { clean::StructFieldItem(ref ty) => Some((f, ty)), _ => None, }) @@ -1457,7 +1457,7 @@ fn print_tuple_struct_fields<'a, 'cx: 'a>( display_fn(|f| { if !s.is_empty() && s.iter().all(|field| { - matches!(*field.kind, clean::StrippedItem(box clean::StructFieldItem(..))) + matches!(field.kind, clean::StrippedItem(box clean::StructFieldItem(..))) }) { return f.write_str("/* private fields */"); @@ -1467,7 +1467,7 @@ fn print_tuple_struct_fields<'a, 'cx: 'a>( if i > 0 { f.write_str(", ")?; } - match *ty.kind { + match ty.kind { clean::StrippedItem(box clean::StructFieldItem(_)) => f.write_str("_")?, clean::StructFieldItem(ref ty) => write!(f, "{}", ty.print(cx))?, _ => unreachable!(), @@ -1521,7 +1521,7 @@ fn should_show_enum_discriminant( ) -> bool { let mut has_variants_with_value = false; for variant in variants { - if let clean::VariantItem(ref var) = *variant.kind + if let clean::VariantItem(ref var) = variant.kind && matches!(var.kind, clean::VariantKind::CLike) { has_variants_with_value |= var.discriminant.is_some(); @@ -1592,7 +1592,7 @@ fn render_enum_fields( continue; } w.write_str(TAB); - match *v.kind { + match v.kind { clean::VariantItem(ref var) => match var.kind { clean::VariantKind::CLike => display_c_like_variant( w, @@ -1659,7 +1659,7 @@ fn item_variants( " rightside", ); w.write_str("

"); - if let clean::VariantItem(ref var) = *variant.kind + if let clean::VariantItem(ref var) = variant.kind && let clean::VariantKind::CLike = var.kind { display_c_like_variant( @@ -1675,7 +1675,7 @@ fn item_variants( w.write_str(variant.name.unwrap().as_str()); } - let clean::VariantItem(variant_data) = &*variant.kind else { unreachable!() }; + let clean::VariantItem(variant_data) = &variant.kind else { unreachable!() }; if let clean::VariantKind::Tuple(ref s) = variant_data.kind { write!(w, "({})", print_tuple_struct_fields(cx, s)); @@ -1716,7 +1716,7 @@ fn item_variants( document_non_exhaustive(variant) ); for field in fields { - match *field.kind { + match field.kind { clean::StrippedItem(box clean::StructFieldItem(_)) => {} clean::StructFieldItem(ref ty) => { let id = cx.derive_id(format!( @@ -1886,7 +1886,7 @@ fn item_fields( ) { let mut fields = fields .iter() - .filter_map(|f| match *f.kind { + .filter_map(|f| match f.kind { clean::StructFieldItem(ref ty) => Some((f, ty)), _ => None, }) @@ -2196,14 +2196,14 @@ fn render_union<'a, 'cx: 'a>( write!(f, "{{\n")?; let count_fields = - fields.iter().filter(|field| matches!(*field.kind, clean::StructFieldItem(..))).count(); + fields.iter().filter(|field| matches!(field.kind, clean::StructFieldItem(..))).count(); let toggle = should_hide_fields(count_fields); if toggle { toggle_open(&mut f, format_args!("{count_fields} fields")); } for field in fields { - if let clean::StructFieldItem(ref ty) = *field.kind { + if let clean::StructFieldItem(ref ty) = field.kind { write!( f, " {}{}: {},\n", @@ -2279,14 +2279,14 @@ fn render_struct_fields( w.write_str("{"); } let count_fields = - fields.iter().filter(|f| matches!(*f.kind, clean::StructFieldItem(..))).count(); + fields.iter().filter(|f| matches!(f.kind, clean::StructFieldItem(..))).count(); let has_visible_fields = count_fields > 0; let toggle = should_hide_fields(count_fields); if toggle { toggle_open(&mut w, format_args!("{count_fields} fields")); } for field in fields { - if let clean::StructFieldItem(ref ty) = *field.kind { + if let clean::StructFieldItem(ref ty) = field.kind { write!( w, "\n{tab} {vis}{name}: {ty},", @@ -2314,7 +2314,7 @@ fn render_struct_fields( w.write_str("("); if !fields.is_empty() && fields.iter().all(|field| { - matches!(*field.kind, clean::StrippedItem(box clean::StructFieldItem(..))) + matches!(field.kind, clean::StrippedItem(box clean::StructFieldItem(..))) }) { write!(w, "/* private fields */"); @@ -2323,7 +2323,7 @@ fn render_struct_fields( if i > 0 { w.write_str(", "); } - match *field.kind { + match field.kind { clean::StrippedItem(box clean::StructFieldItem(..)) => write!(w, "_"), clean::StructFieldItem(ref ty) => { write!(w, "{}{}", visibility_print_with_space(field, cx), ty.print(cx),) diff --git a/src/librustdoc/html/render/search_index.rs b/src/librustdoc/html/render/search_index.rs index bfdf457c529d5..b84c22ac746c5 100644 --- a/src/librustdoc/html/render/search_index.rs +++ b/src/librustdoc/html/render/search_index.rs @@ -758,7 +758,7 @@ pub(crate) fn get_function_type_for_search<'tcx>( None } }); - let (mut inputs, mut output, where_clause) = match *item.kind { + let (mut inputs, mut output, where_clause) = match item.kind { clean::FunctionItem(ref f) | clean::MethodItem(ref f, _) | clean::TyMethodItem(ref f) => { get_fn_inputs_and_outputs(f, tcx, impl_or_trait_generics, cache) } @@ -1132,7 +1132,7 @@ fn simplify_fn_type<'tcx, 'a>( && trait_.items.iter().any(|at| at.is_ty_associated_type()) { for assoc_ty in &trait_.items { - if let clean::ItemKind::TyAssocTypeItem(_generics, bounds) = &*assoc_ty.kind + if let clean::ItemKind::TyAssocTypeItem(_generics, bounds) = &assoc_ty.kind && let Some(name) = assoc_ty.name { let idx = -isize::try_from(rgen.len() + 1).unwrap(); diff --git a/src/librustdoc/html/render/sidebar.rs b/src/librustdoc/html/render/sidebar.rs index 06cc57b2a5536..842ee81624ef2 100644 --- a/src/librustdoc/html/render/sidebar.rs +++ b/src/librustdoc/html/render/sidebar.rs @@ -119,7 +119,7 @@ pub(crate) mod filters { pub(super) fn print_sidebar(cx: &Context<'_>, it: &clean::Item, buffer: &mut Buffer) { let mut ids = IdMap::new(); let mut blocks: Vec> = docblock_toc(cx, it, &mut ids).into_iter().collect(); - match *it.kind { + match it.kind { clean::StructItem(ref s) => sidebar_struct(cx, it, s, &mut blocks), clean::TraitItem(ref t) => sidebar_trait(cx, it, t, &mut blocks), clean::PrimitiveItem(_) => sidebar_primitive(cx, it, &mut blocks), @@ -143,7 +143,7 @@ pub(super) fn print_sidebar(cx: &Context<'_>, it: &clean::Item, buffer: &mut Buf // crate title is displayed as part of logo lockup let (title_prefix, title) = if !blocks.is_empty() && !it.is_crate() { ( - match *it.kind { + match it.kind { clean::ModuleItem(..) => "Module ", _ => "", }, @@ -181,7 +181,7 @@ pub(super) fn print_sidebar(cx: &Context<'_>, it: &clean::Item, buffer: &mut Buf fn get_struct_fields_name<'a>(fields: &'a [clean::Item]) -> Vec> { let mut fields = fields .iter() - .filter(|f| matches!(*f.kind, clean::StructFieldItem(..))) + .filter(|f| matches!(f.kind, clean::StructFieldItem(..))) .filter_map(|f| { f.name.as_ref().map(|name| Link::new(format!("structfield.{name}"), name.as_str())) }) @@ -467,7 +467,7 @@ fn sidebar_deref_methods<'a>( debug!("found Deref: {impl_:?}"); if let Some((target, real_target)) = - impl_.inner_impl().items.iter().find_map(|item| match *item.kind { + impl_.inner_impl().items.iter().find_map(|item| match item.kind { clean::AssocTypeItem(box ref t, _) => Some(match *t { clean::TypeAlias { item_type: Some(ref type_), .. } => (type_, &t.type_), _ => (&t.type_, &t.type_), @@ -587,7 +587,7 @@ fn sidebar_module( && it .name .or_else(|| { - if let clean::ImportItem(ref i) = *it.kind + if let clean::ImportItem(ref i) = it.kind && let clean::ImportKind::Simple(s) = i.kind { Some(s) diff --git a/src/librustdoc/html/render/write_shared.rs b/src/librustdoc/html/render/write_shared.rs index b0af8d8c23ee5..e8d12320f82fd 100644 --- a/src/librustdoc/html/render/write_shared.rs +++ b/src/librustdoc/html/render/write_shared.rs @@ -783,7 +783,7 @@ impl<'cx, 'cache> DocVisitor for TypeImplCollector<'cx, 'cache> { fn visit_item(&mut self, it: &Item) { self.visit_item_recur(it); let cache = self.cache; - let ItemKind::TypeAliasItem(ref t) = *it.kind else { return }; + let ItemKind::TypeAliasItem(ref t) = it.kind else { return }; let Some(self_did) = it.item_id.as_def_id() else { return }; if !self.visited_aliases.insert(self_did) { return; diff --git a/src/librustdoc/json/conversions.rs b/src/librustdoc/json/conversions.rs index b97d710c007ce..cae8d107da415 100644 --- a/src/librustdoc/json/conversions.rs +++ b/src/librustdoc/json/conversions.rs @@ -49,7 +49,7 @@ impl JsonRenderer<'_> { let visibility = item.visibility(self.tcx); let clean::Item { name, item_id, .. } = item; let id = id_from_item(&item, self.tcx); - let inner = match *item.kind { + let inner = match item.kind { clean::KeywordItem => return None, clean::StrippedItem(ref inner) => { match &**inner { @@ -294,7 +294,7 @@ pub(crate) fn id_from_item_inner( } pub(crate) fn id_from_item(item: &clean::Item, tcx: TyCtxt<'_>) -> Id { - match *item.kind { + match item.kind { clean::ItemKind::ImportItem(ref import) => { let extra = import.source.did.map(ItemId::from).map(|i| id_from_item_inner(i, tcx, None, None)); @@ -310,7 +310,7 @@ fn from_clean_item(item: clean::Item, tcx: TyCtxt<'_>) -> ItemEnum { let is_crate = item.is_crate(); let header = item.fn_header(tcx); - match *item.kind { + match item.inner.kind { ModuleItem(m) => { ItemEnum::Module(Module { is_crate, items: ids(m.items, tcx), is_stripped: false }) } diff --git a/src/librustdoc/json/import_finder.rs b/src/librustdoc/json/import_finder.rs index 976a7fd69aeee..e21fe9668d400 100644 --- a/src/librustdoc/json/import_finder.rs +++ b/src/librustdoc/json/import_finder.rs @@ -24,7 +24,7 @@ struct ImportFinder { impl DocFolder for ImportFinder { fn fold_item(&mut self, i: Item) -> Option { - match *i.kind { + match i.kind { clean::ImportItem(Import { source: ImportSource { did: Some(did), .. }, .. }) => { self.imported.insert(did); Some(i) diff --git a/src/librustdoc/json/mod.rs b/src/librustdoc/json/mod.rs index 1b2d61a763797..d375946a8c853 100644 --- a/src/librustdoc/json/mod.rs +++ b/src/librustdoc/json/mod.rs @@ -85,7 +85,7 @@ impl<'tcx> JsonRenderer<'tcx> { // document primitive items in an arbitrary crate by using // `rustc_doc_primitive`. let mut is_primitive_impl = false; - if let clean::types::ItemKind::ImplItem(ref impl_) = *item.kind + if let clean::types::ItemKind::ImplItem(ref impl_) = item.kind && impl_.trait_.is_none() && let clean::types::Type::Primitive(_) = impl_.for_ { @@ -164,7 +164,7 @@ impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> { // Flatten items that recursively store other items. We include orphaned items from // stripped modules and etc that are otherwise reachable. - if let ItemKind::StrippedItem(inner) = &*item.kind { + if let ItemKind::StrippedItem(inner) = &item.kind { inner.inner_items().for_each(|i| self.item(i.clone()).unwrap()); } diff --git a/src/librustdoc/passes/calculate_doc_coverage.rs b/src/librustdoc/passes/calculate_doc_coverage.rs index 1d0b41fc429c5..7391909406e36 100644 --- a/src/librustdoc/passes/calculate_doc_coverage.rs +++ b/src/librustdoc/passes/calculate_doc_coverage.rs @@ -195,7 +195,7 @@ impl<'a, 'b> DocVisitor for CoverageCalculator<'a, 'b> { return; } - match *i.kind { + match i.kind { clean::StrippedItem(..) => { // don't count items in stripped modules return; diff --git a/src/librustdoc/passes/check_doc_test_visibility.rs b/src/librustdoc/passes/check_doc_test_visibility.rs index d456e8e24e6f1..733fd919e712b 100644 --- a/src/librustdoc/passes/check_doc_test_visibility.rs +++ b/src/librustdoc/passes/check_doc_test_visibility.rs @@ -57,7 +57,7 @@ impl crate::doctest::DocTestVisitor for Tests { pub(crate) fn should_have_doc_example(cx: &DocContext<'_>, item: &clean::Item) -> bool { if !cx.cache.effective_visibilities.is_directly_public(cx.tcx, item.item_id.expect_def_id()) || matches!( - *item.kind, + item.kind, clean::StructFieldItem(_) | clean::VariantItem(_) | clean::AssocConstItem(..) diff --git a/src/librustdoc/passes/collect_trait_impls.rs b/src/librustdoc/passes/collect_trait_impls.rs index 394a64df4bc41..a9edc485d5e7a 100644 --- a/src/librustdoc/passes/collect_trait_impls.rs +++ b/src/librustdoc/passes/collect_trait_impls.rs @@ -160,13 +160,13 @@ pub(crate) fn collect_trait_impls(mut krate: Crate, cx: &mut DocContext<'_>) -> // scan through included items ahead of time to splice in Deref targets to the "valid" sets for it in new_items_external.iter().chain(new_items_local.iter()) { - if let ImplItem(box Impl { ref for_, ref trait_, ref items, .. }) = *it.kind + if let ImplItem(box Impl { ref for_, ref trait_, ref items, .. }) = it.kind && trait_.as_ref().map(|t| t.def_id()) == tcx.lang_items().deref_trait() && cleaner.keep_impl(for_, true) { let target = items .iter() - .find_map(|item| match *item.kind { + .find_map(|item| match item.kind { AssocTypeItem(ref t, _) => Some(&t.type_), _ => None, }) @@ -200,7 +200,7 @@ pub(crate) fn collect_trait_impls(mut krate: Crate, cx: &mut DocContext<'_>) -> // Filter out external items that are not needed new_items_external.retain(|it| { - if let ImplItem(box Impl { ref for_, ref trait_, ref kind, .. }) = *it.kind { + if let ImplItem(box Impl { ref for_, ref trait_, ref kind, .. }) = it.kind { cleaner.keep_impl( for_, trait_.as_ref().map(|t| t.def_id()) == tcx.lang_items().deref_trait(), @@ -211,7 +211,7 @@ pub(crate) fn collect_trait_impls(mut krate: Crate, cx: &mut DocContext<'_>) -> } }); - if let ModuleItem(Module { items, .. }) = &mut *krate.module.kind { + if let ModuleItem(Module { items, .. }) = &mut krate.module.inner.kind { items.extend(synth_impls); items.extend(new_items_external); items.extend(new_items_local); @@ -258,7 +258,7 @@ impl<'cache> DocVisitor for ItemAndAliasCollector<'cache> { fn visit_item(&mut self, i: &Item) { self.items.insert(i.item_id); - if let TypeAliasItem(alias) = &*i.kind + if let TypeAliasItem(alias) = &i.inner.kind && let Some(did) = alias.type_.def_id(self.cache) { self.items.insert(ItemId::DefId(did)); diff --git a/src/librustdoc/passes/propagate_doc_cfg.rs b/src/librustdoc/passes/propagate_doc_cfg.rs index 5aa6a5ee6045b..6be51dd156066 100644 --- a/src/librustdoc/passes/propagate_doc_cfg.rs +++ b/src/librustdoc/passes/propagate_doc_cfg.rs @@ -31,7 +31,7 @@ impl<'a, 'tcx> CfgPropagator<'a, 'tcx> { // Some items need to merge their attributes with their parents' otherwise a few of them // (mostly `cfg` ones) will be missing. fn merge_with_parent_attributes(&mut self, item: &mut Item) { - let check_parent = match &*item.kind { + let check_parent = match &item.kind { // impl blocks can be in different modules with different cfg and we need to get them // as well. ItemKind::ImplItem(_) => false, diff --git a/src/librustdoc/passes/strip_aliased_non_local.rs b/src/librustdoc/passes/strip_aliased_non_local.rs index e1dd2d3af0feb..6078ab3652891 100644 --- a/src/librustdoc/passes/strip_aliased_non_local.rs +++ b/src/librustdoc/passes/strip_aliased_non_local.rs @@ -23,7 +23,7 @@ struct AliasedNonLocalStripper<'tcx> { impl<'tcx> DocFolder for AliasedNonLocalStripper<'tcx> { fn fold_item(&mut self, i: Item) -> Option { - Some(match *i.kind { + Some(match i.kind { clean::TypeAliasItem(..) => { let mut stripper = NonLocalStripper { tcx: self.tcx }; // don't call `fold_item` as that could strip the type-alias it-self diff --git a/src/librustdoc/passes/strip_hidden.rs b/src/librustdoc/passes/strip_hidden.rs index 86f14ddbe8506..7c5fbac94e4fc 100644 --- a/src/librustdoc/passes/strip_hidden.rs +++ b/src/librustdoc/passes/strip_hidden.rs @@ -89,7 +89,7 @@ impl<'a, 'tcx> Stripper<'a, 'tcx> { impl<'a, 'tcx> DocFolder for Stripper<'a, 'tcx> { fn fold_item(&mut self, i: Item) -> Option { let has_doc_hidden = i.is_doc_hidden(); - let is_impl_or_exported_macro = match *i.kind { + let is_impl_or_exported_macro = match i.kind { clean::ImplItem(..) => true, // If the macro has the `#[macro_export]` attribute, it means it's accessible at the // crate level so it should be handled differently. @@ -138,7 +138,7 @@ impl<'a, 'tcx> DocFolder for Stripper<'a, 'tcx> { // module it's defined in. Both of these are marked "stripped," and // not included in the final docs, but since they still have an effect // on the final doc, cannot be completely removed from the Clean IR. - match *i.kind { + match i.kind { clean::StructFieldItem(..) | clean::ModuleItem(..) | clean::VariantItem(..) => { // We need to recurse into stripped modules to // strip things like impl methods but when doing so diff --git a/src/librustdoc/passes/stripper.rs b/src/librustdoc/passes/stripper.rs index 3f706ac951f25..a85428f8742a0 100644 --- a/src/librustdoc/passes/stripper.rs +++ b/src/librustdoc/passes/stripper.rs @@ -39,7 +39,7 @@ fn is_item_reachable( impl<'a, 'tcx> DocFolder for Stripper<'a, 'tcx> { fn fold_item(&mut self, i: Item) -> Option { - match *i.kind { + match i.kind { clean::StrippedItem(..) => { // We need to recurse into stripped modules to strip things // like impl methods but when doing so we must not add any @@ -130,7 +130,7 @@ impl<'a, 'tcx> DocFolder for Stripper<'a, 'tcx> { clean::KeywordItem => {} } - let fastreturn = match *i.kind { + let fastreturn = match i.kind { // nothing left to do for traits (don't want to filter their // methods out, visibility controlled by the trait) clean::TraitItem(..) => true, @@ -195,7 +195,7 @@ impl<'a> ImplStripper<'a, '_> { impl<'a> DocFolder for ImplStripper<'a, '_> { fn fold_item(&mut self, i: Item) -> Option { - if let clean::ImplItem(ref imp) = *i.kind { + if let clean::ImplItem(ref imp) = i.kind { // Impl blocks can be skipped if they are: empty; not a trait impl; and have no // documentation. // @@ -272,7 +272,7 @@ impl<'tcx> ImportStripper<'tcx> { impl<'tcx> DocFolder for ImportStripper<'tcx> { fn fold_item(&mut self, i: Item) -> Option { - match *i.kind { + match &i.kind { clean::ImportItem(imp) if !self.document_hidden && self.import_should_be_hidden(&i, &imp) => { diff --git a/src/librustdoc/visit.rs b/src/librustdoc/visit.rs index 430bbe991eaaf..7fb0a32cc9495 100644 --- a/src/librustdoc/visit.rs +++ b/src/librustdoc/visit.rs @@ -48,8 +48,8 @@ pub(crate) trait DocVisitor: Sized { /// don't override! fn visit_item_recur(&mut self, item: &Item) { - match &*item.kind { - StrippedItem(i) => self.visit_inner_recur(i), + match &item.kind { + StrippedItem(i) => self.visit_inner_recur(&*i), _ => self.visit_inner_recur(&item.kind), } } From 3de6838238dd72004acf0e6b3f158837952c1dc3 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 8 Sep 2024 08:30:28 +0200 Subject: [PATCH 0664/2194] add some FIXME(const-hack) --- library/core/src/option.rs | 2 +- library/core/src/result.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/library/core/src/option.rs b/library/core/src/option.rs index 50cb22b7eb3f5..b62eec1897b09 100644 --- a/library/core/src/option.rs +++ b/library/core/src/option.rs @@ -1894,7 +1894,7 @@ impl Option<&T> { where T: Copy, { - // FIXME: this implementation, which sidesteps using `Option::map` since it's not const + // FIXME(const-hack): this implementation, which sidesteps using `Option::map` since it's not const // ready yet, should be reverted when possible to avoid code repetition match self { Some(&v) => Some(v), diff --git a/library/core/src/result.rs b/library/core/src/result.rs index a7fd95e007982..5b6a81c8dae91 100644 --- a/library/core/src/result.rs +++ b/library/core/src/result.rs @@ -1540,7 +1540,7 @@ impl Result<&T, E> { where T: Copy, { - // FIXME: this implementation, which sidesteps using `Result::map` since it's not const + // FIXME(const-hack): this implementation, which sidesteps using `Result::map` since it's not const // ready yet, should be reverted when possible to avoid code repetition match self { Ok(&v) => Ok(v), From 7f9a541059b1bf5322e94668792e933a48975917 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 8 Sep 2024 08:45:41 +0200 Subject: [PATCH 0665/2194] remove pointless rustc_const_unstable on trait impls --- library/core/src/ptr/alignment.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/library/core/src/ptr/alignment.rs b/library/core/src/ptr/alignment.rs index 19fe03d57cc0a..834cec9dcfc26 100644 --- a/library/core/src/ptr/alignment.rs +++ b/library/core/src/ptr/alignment.rs @@ -199,7 +199,6 @@ impl From for usize { } } -#[rustc_const_unstable(feature = "const_alloc_layout", issue = "67521")] #[unstable(feature = "ptr_alignment_type", issue = "102070")] impl cmp::Ord for Alignment { #[inline] @@ -208,7 +207,6 @@ impl cmp::Ord for Alignment { } } -#[rustc_const_unstable(feature = "const_alloc_layout", issue = "67521")] #[unstable(feature = "ptr_alignment_type", issue = "102070")] impl cmp::PartialOrd for Alignment { #[inline] From f98ca32b0a594b1ee59e22e1927198ed03eb0ce7 Mon Sep 17 00:00:00 2001 From: Mads Marquart Date: Sat, 7 Sep 2024 17:57:47 +0200 Subject: [PATCH 0666/2194] Fix linking error when compiling for 32-bit watchOS In https://github.com/rust-lang/rust/pull/124748, I mistakenly conflated "not SjLj" to mean "ARM EHABI", which isn't true, watchOS armv7k (specifically only that architecture) uses a third unwinding method called "DWARF CFI". --- library/std/src/sys/personality/dwarf/eh.rs | 6 +++--- library/std/src/sys/personality/gcc.rs | 13 +++++++------ library/unwind/src/libunwind.rs | 13 ++++++++----- 3 files changed, 18 insertions(+), 14 deletions(-) diff --git a/library/std/src/sys/personality/dwarf/eh.rs b/library/std/src/sys/personality/dwarf/eh.rs index c37c3e442aea6..778d8686f023e 100644 --- a/library/std/src/sys/personality/dwarf/eh.rs +++ b/library/std/src/sys/personality/dwarf/eh.rs @@ -54,10 +54,10 @@ pub enum EHAction { Terminate, } -/// 32-bit Apple ARM uses SjLj exceptions, except for watchOS. +/// 32-bit ARM Darwin platforms uses SjLj exceptions. /// -/// I.e. iOS and tvOS, as those are the only Apple OSes that used 32-bit ARM -/// devices. +/// The exception is watchOS armv7k (specifically that subarchitecture), which +/// instead uses DWARF Call Frame Information (CFI) unwinding. /// /// pub const USING_SJLJ_EXCEPTIONS: bool = diff --git a/library/std/src/sys/personality/gcc.rs b/library/std/src/sys/personality/gcc.rs index f6b1844e153fd..ad596ecff65d5 100644 --- a/library/std/src/sys/personality/gcc.rs +++ b/library/std/src/sys/personality/gcc.rs @@ -95,14 +95,15 @@ const UNWIND_DATA_REG: (i32, i32) = (4, 5); // a0, a1 cfg_if::cfg_if! { if #[cfg(all( - target_arch = "arm", - not(all(target_vendor = "apple", not(target_os = "watchos"))), - not(target_os = "netbsd"), - ))] { + target_arch = "arm", + not(target_vendor = "apple"), + not(target_os = "netbsd"), + ))] { /// personality fn called by [ARM EHABI][armeabi-eh] /// - /// Apple 32-bit ARM (but not watchOS) uses the default routine instead - /// since it uses "setjmp-longjmp" unwinding. + /// 32-bit ARM on iOS/tvOS/watchOS does not use ARM EHABI, it uses + /// either "setjmp-longjmp" unwinding or DWARF CFI unwinding, which is + /// handled by the default routine. /// /// [armeabi-eh]: https://web.archive.org/web/20190728160938/https://infocenter.arm.com/help/topic/com.arm.doc.ihi0038b/IHI0038B_ehabi.pdf #[lang = "eh_personality"] diff --git a/library/unwind/src/libunwind.rs b/library/unwind/src/libunwind.rs index e5e28f32e4dbf..1d856ce1879a5 100644 --- a/library/unwind/src/libunwind.rs +++ b/library/unwind/src/libunwind.rs @@ -33,10 +33,10 @@ pub const unwinder_private_data_size: usize = 2; #[cfg(all(target_arch = "x86_64", target_os = "windows"))] pub const unwinder_private_data_size: usize = 6; -#[cfg(all(target_arch = "arm", not(all(target_vendor = "apple", not(target_os = "watchos")))))] +#[cfg(all(target_arch = "arm", not(target_vendor = "apple")))] pub const unwinder_private_data_size: usize = 20; -#[cfg(all(target_arch = "arm", all(target_vendor = "apple", not(target_os = "watchos"))))] +#[cfg(all(target_arch = "arm", target_vendor = "apple"))] pub const unwinder_private_data_size: usize = 5; #[cfg(all(target_arch = "aarch64", target_pointer_width = "64", not(target_os = "windows")))] @@ -123,8 +123,11 @@ extern "C" { } cfg_if::cfg_if! { -if #[cfg(any(all(target_vendor = "apple", not(target_os = "watchos")), target_os = "netbsd", not(target_arch = "arm")))] { +if #[cfg(any(target_vendor = "apple", target_os = "netbsd", not(target_arch = "arm")))] { // Not ARM EHABI + // + // 32-bit ARM on iOS/tvOS/watchOS use either DWARF/Compact unwinding or + // "setjmp-longjmp" / SjLj unwinding. #[repr(C)] #[derive(Copy, Clone, PartialEq)] pub enum _Unwind_Action { @@ -259,8 +262,8 @@ if #[cfg(any(all(target_vendor = "apple", not(target_os = "watchos")), target_os cfg_if::cfg_if! { if #[cfg(all(target_vendor = "apple", not(target_os = "watchos"), target_arch = "arm"))] { - // 32-bit ARM Apple (except for watchOS) uses SjLj and does not provide - // _Unwind_Backtrace() + // 32-bit ARM Apple (except for watchOS armv7k specifically) uses SjLj and + // does not provide _Unwind_Backtrace() extern "C-unwind" { pub fn _Unwind_SjLj_RaiseException(e: *mut _Unwind_Exception) -> _Unwind_Reason_Code; } From ec11001f2b4b3fae70fc118ffaf533af0716d585 Mon Sep 17 00:00:00 2001 From: Florian Schmiderer Date: Fri, 6 Sep 2024 23:35:18 +0200 Subject: [PATCH 0667/2194] run-make-support: Add llvm-pdbutil --- .../src/external_deps/llvm.rs | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/src/tools/run-make-support/src/external_deps/llvm.rs b/src/tools/run-make-support/src/external_deps/llvm.rs index 2522c4aeb9365..16c4251998fb2 100644 --- a/src/tools/run-make-support/src/external_deps/llvm.rs +++ b/src/tools/run-make-support/src/external_deps/llvm.rs @@ -110,6 +110,13 @@ pub struct LlvmDwarfdump { cmd: Command, } +/// A `llvm-pdbutil` invocation builder. +#[derive(Debug)] +#[must_use] +pub struct LlvmPdbutil { + cmd: Command, +} + crate::macros::impl_common_helpers!(LlvmReadobj); crate::macros::impl_common_helpers!(LlvmProfdata); crate::macros::impl_common_helpers!(LlvmFilecheck); @@ -118,6 +125,7 @@ crate::macros::impl_common_helpers!(LlvmAr); crate::macros::impl_common_helpers!(LlvmNm); crate::macros::impl_common_helpers!(LlvmBcanalyzer); crate::macros::impl_common_helpers!(LlvmDwarfdump); +crate::macros::impl_common_helpers!(LlvmPdbutil); /// Generate the path to the bin directory of LLVM. #[must_use] @@ -360,3 +368,19 @@ impl LlvmDwarfdump { self } } + +impl LlvmPdbutil { + /// Construct a new `llvm-pdbutil` invocation. This assumes that `llvm-pdbutil` is available + /// at `$LLVM_BIN_DIR/llvm-pdbutil`. + pub fn new() -> Self { + let llvm_pdbutil = llvm_bin_dir().join("llvm-pdbutil"); + let cmd = Command::new(llvm_pdbutil); + Self { cmd } + } + + /// Provide an input file. + pub fn input>(&mut self, path: P) -> &mut Self { + self.cmd.arg(path.as_ref()); + self + } +} From 98481be353b3be34be684a11c467b72992561fde Mon Sep 17 00:00:00 2001 From: "L. E. Segovia" Date: Wed, 3 Apr 2024 20:08:56 -0300 Subject: [PATCH 0668/2194] MsvcLinker: allow linking dynamically to Meson and MinGW-style named libraries Fixes #122455 --- compiler/rustc_codegen_ssa/src/back/linker.rs | 12 +++++- compiler/rustc_metadata/src/lib.rs | 3 +- compiler/rustc_metadata/src/native_libs.rs | 38 +++++++++++++++++++ 3 files changed, 50 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/back/linker.rs b/compiler/rustc_codegen_ssa/src/back/linker.rs index cb266247e0dde..1ff0f9cbadb6c 100644 --- a/compiler/rustc_codegen_ssa/src/back/linker.rs +++ b/compiler/rustc_codegen_ssa/src/back/linker.rs @@ -7,7 +7,9 @@ use std::{env, iter, mem, str}; use cc::windows_registry; use rustc_hir::def_id::{CrateNum, LOCAL_CRATE}; -use rustc_metadata::{find_native_static_library, try_find_native_static_library}; +use rustc_metadata::{ + find_native_static_library, try_find_native_dynamic_library, try_find_native_static_library, +}; use rustc_middle::bug; use rustc_middle::middle::dependency_format::Linkage; use rustc_middle::middle::exported_symbols; @@ -878,7 +880,13 @@ impl<'a> Linker for MsvcLinker<'a> { } fn link_dylib_by_name(&mut self, name: &str, verbatim: bool, _as_needed: bool) { - self.link_arg(format!("{}{}", name, if verbatim { "" } else { ".lib" })); + // On MSVC-like targets rustc supports import libraries using alternative naming + // scheme (`libfoo.a`) unsupported by linker, search for such libraries manually. + if let Some(path) = try_find_native_dynamic_library(self.sess, name, verbatim) { + self.link_arg(path); + } else { + self.link_arg(format!("{}{}", name, if verbatim { "" } else { ".lib" })); + } } fn link_dylib_by_path(&mut self, path: &Path, _as_needed: bool) { diff --git a/compiler/rustc_metadata/src/lib.rs b/compiler/rustc_metadata/src/lib.rs index 58b352f263de6..02a9ce455b280 100644 --- a/compiler/rustc_metadata/src/lib.rs +++ b/compiler/rustc_metadata/src/lib.rs @@ -37,7 +37,8 @@ pub mod locator; pub use creader::{load_symbol_from_dylib, DylibError}; pub use fs::{emit_wrapper_file, METADATA_FILENAME}; pub use native_libs::{ - find_native_static_library, try_find_native_static_library, walk_native_lib_search_dirs, + find_native_static_library, try_find_native_dynamic_library, try_find_native_static_library, + walk_native_lib_search_dirs, }; pub use rmeta::{encode_metadata, rendered_const, EncodedMetadata, METADATA_HEADER}; diff --git a/compiler/rustc_metadata/src/native_libs.rs b/compiler/rustc_metadata/src/native_libs.rs index a6ad449cb53e8..0329a193d89dd 100644 --- a/compiler/rustc_metadata/src/native_libs.rs +++ b/compiler/rustc_metadata/src/native_libs.rs @@ -109,6 +109,44 @@ pub fn try_find_native_static_library( .break_value() } +pub fn try_find_native_dynamic_library( + sess: &Session, + name: &str, + verbatim: bool, +) -> Option { + let formats = if verbatim { + vec![("".into(), "".into())] + } else { + // While the official naming convention for MSVC import libraries + // is foo.lib... + let os = (sess.target.staticlib_prefix.clone(), sess.target.staticlib_suffix.clone()); + // ... Meson follows the libfoo.dll.a convention to + // disambiguate .a for static libraries + let meson = ("lib".into(), ".dll.a".into()); + // and MinGW uses .a altogether + let mingw = ("lib".into(), ".a".into()); + vec![os, meson, mingw] + }; + + walk_native_lib_search_dirs( + sess, + LinkSelfContainedComponents::empty(), + None, + |dir, is_framework| { + if !is_framework { + for (prefix, suffix) in &formats { + let test = dir.join(format!("{prefix}{name}{suffix}")); + if test.exists() { + return ControlFlow::Break(test); + } + } + } + ControlFlow::Continue(()) + }, + ) + .break_value() +} + pub fn find_native_static_library(name: &str, verbatim: bool, sess: &Session) -> PathBuf { try_find_native_static_library(sess, name, verbatim) .unwrap_or_else(|| sess.dcx().emit_fatal(errors::MissingNativeLibrary::new(name, verbatim))) From 9df7680ecf698bf7087616b595774ee1023d3c7b Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Fri, 30 Aug 2024 19:48:16 +0300 Subject: [PATCH 0669/2194] detect incompatible CI LLVM options more precisely Previously, the logic here was simply checking whether the option was set in `config.toml`. This approach was not manageable in our CI runners as we set so many options in config.toml. In reality, those values are not incompatible since they are usually the same value used to generate the CI llvm. Now, the new logic compares the configuration values with the values used to generate the CI llvm, so we get more precise results and make the process more manageable. Signed-off-by: onur-ozkan --- src/bootstrap/src/core/config/config.rs | 112 +++++++++++++++++++++++- src/bootstrap/src/core/download.rs | 31 ++++++- 2 files changed, 140 insertions(+), 3 deletions(-) diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs index 52c1c462788af..57c260a062486 100644 --- a/src/bootstrap/src/core/config/config.rs +++ b/src/bootstrap/src/core/config/config.rs @@ -1216,13 +1216,19 @@ impl Config { } } + pub(crate) fn get_builder_toml(&self, build_name: &str) -> Result { + let builder_config_path = + self.out.join(self.build.triple).join(build_name).join(BUILDER_CONFIG_FILENAME); + Self::get_toml(&builder_config_path) + } + #[cfg(test)] - fn get_toml(_: &Path) -> Result { + pub(crate) fn get_toml(_: &Path) -> Result { Ok(TomlConfig::default()) } #[cfg(not(test))] - fn get_toml(file: &Path) -> Result { + pub(crate) fn get_toml(file: &Path) -> Result { let contents = t!(fs::read_to_string(file), format!("config file {} not found", file.display())); // Deserialize to Value and then TomlConfig to prevent the Deserialize impl of @@ -2846,6 +2852,108 @@ impl Config { } } +/// Compares the current `Llvm` options against those in the CI LLVM builder and detects any incompatible options. +/// It does this by destructuring the `Llvm` instance to make sure every `Llvm` field is covered and not missing. +pub(crate) fn check_incompatible_options_for_ci_llvm( + current_config_toml: TomlConfig, + ci_config_toml: TomlConfig, +) -> Result<(), String> { + macro_rules! err { + ($current:expr, $expected:expr) => { + if let Some(current) = &$current { + if Some(current) != $expected.as_ref() { + return Err(format!( + "ERROR: Setting `llvm.{}` is incompatible with `llvm.download-ci-llvm`. \ + Current value: {:?}, Expected value(s): {}{:?}", + stringify!($expected).replace("_", "-"), + $current, + if $expected.is_some() { "None/" } else { "" }, + $expected, + )); + }; + }; + }; + } + + macro_rules! warn { + ($current:expr, $expected:expr) => { + if let Some(current) = &$current { + if Some(current) != $expected.as_ref() { + println!( + "WARNING: `llvm.{}` has no effect with `llvm.download-ci-llvm`. \ + Current value: {:?}, Expected value(s): {}{:?}", + stringify!($expected).replace("_", "-"), + $current, + if $expected.is_some() { "None/" } else { "" }, + $expected, + ); + }; + }; + }; + } + + let (Some(current_llvm_config), Some(ci_llvm_config)) = + (current_config_toml.llvm, ci_config_toml.llvm) + else { + return Ok(()); + }; + + let Llvm { + optimize, + thin_lto, + release_debuginfo, + assertions: _, + tests: _, + plugins, + ccache: _, + static_libstdcpp: _, + libzstd, + ninja: _, + targets, + experimental_targets, + link_jobs: _, + link_shared: _, + version_suffix, + clang_cl, + cflags, + cxxflags, + ldflags, + use_libcxx, + use_linker, + allow_old_toolchain, + polly, + clang, + enable_warnings, + download_ci_llvm: _, + build_config, + enzyme, + } = ci_llvm_config; + + err!(current_llvm_config.optimize, optimize); + err!(current_llvm_config.thin_lto, thin_lto); + err!(current_llvm_config.release_debuginfo, release_debuginfo); + err!(current_llvm_config.libzstd, libzstd); + err!(current_llvm_config.targets, targets); + err!(current_llvm_config.experimental_targets, experimental_targets); + err!(current_llvm_config.clang_cl, clang_cl); + err!(current_llvm_config.version_suffix, version_suffix); + err!(current_llvm_config.cflags, cflags); + err!(current_llvm_config.cxxflags, cxxflags); + err!(current_llvm_config.ldflags, ldflags); + err!(current_llvm_config.use_libcxx, use_libcxx); + err!(current_llvm_config.use_linker, use_linker); + err!(current_llvm_config.allow_old_toolchain, allow_old_toolchain); + err!(current_llvm_config.polly, polly); + err!(current_llvm_config.clang, clang); + err!(current_llvm_config.build_config, build_config); + err!(current_llvm_config.plugins, plugins); + err!(current_llvm_config.enzyme, enzyme); + + warn!(current_llvm_config.enable_warnings, enable_warnings); + + Ok(()) +} + /// Compares the current Rust options against those in the CI rustc builder and detects any incompatible options. /// It does this by destructuring the `Rust` instance to make sure every `Rust` field is covered and not missing. fn check_incompatible_options_for_ci_rustc( diff --git a/src/bootstrap/src/core/download.rs b/src/bootstrap/src/core/download.rs index 3f5ec70b9abc9..25493c1f55b6c 100644 --- a/src/bootstrap/src/core/download.rs +++ b/src/bootstrap/src/core/download.rs @@ -316,6 +316,7 @@ impl Config { let mut tar = tar::Archive::new(decompressor); let is_ci_rustc = dst.ends_with("ci-rustc"); + let is_ci_llvm = dst.ends_with("ci-llvm"); // `compile::Sysroot` needs to know the contents of the `rustc-dev` tarball to avoid adding // it to the sysroot unless it was explicitly requested. But parsing the 100 MB tarball is slow. @@ -332,7 +333,9 @@ impl Config { let mut short_path = t!(original_path.strip_prefix(directory_prefix)); let is_builder_config = short_path.to_str() == Some(BUILDER_CONFIG_FILENAME); - if !(short_path.starts_with(pattern) || (is_ci_rustc && is_builder_config)) { + if !(short_path.starts_with(pattern) + || ((is_ci_rustc || is_ci_llvm) && is_builder_config)) + { continue; } short_path = short_path.strip_prefix(pattern).unwrap_or(short_path); @@ -717,17 +720,43 @@ download-rustc = false #[cfg(not(feature = "bootstrap-self-test"))] pub(crate) fn maybe_download_ci_llvm(&self) { + use build_helper::exit; + use crate::core::build_steps::llvm::detect_llvm_sha; + use crate::core::config::check_incompatible_options_for_ci_llvm; if !self.llvm_from_ci { return; } + let llvm_root = self.ci_llvm_root(); let llvm_stamp = llvm_root.join(".llvm-stamp"); let llvm_sha = detect_llvm_sha(self, self.rust_info.is_managed_git_subrepository()); let key = format!("{}{}", llvm_sha, self.llvm_assertions); if program_out_of_date(&llvm_stamp, &key) && !self.dry_run() { self.download_ci_llvm(&llvm_sha); + + if let Some(config_path) = &self.config { + let current_config_toml = Self::get_toml(config_path).unwrap(); + + match self.get_builder_toml("ci-llvm") { + Ok(ci_config_toml) => { + check_incompatible_options_for_ci_llvm(current_config_toml, ci_config_toml) + .unwrap(); + } + Err(e) if e.to_string().contains("unknown field") => { + println!( + "WARNING: CI rustc has some fields that are no longer supported in bootstrap; download-rustc will be disabled." + ); + println!("HELP: Consider rebasing to a newer commit if available."); + } + Err(e) => { + eprintln!("ERROR: Failed to parse CI LLVM config.toml: {e}"); + exit!(2); + } + }; + }; + if self.should_fix_bins_and_dylibs() { for entry in t!(fs::read_dir(llvm_root.join("bin"))) { self.fix_bin_or_dylib(&t!(entry).path()); From 23df3a9eeb01d3a50b2ce02db9f69e1d3e37caec Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Fri, 30 Aug 2024 19:50:52 +0300 Subject: [PATCH 0670/2194] remove `check_ci_llvm` usage Signed-off-by: onur-ozkan --- src/bootstrap/src/core/config/config.rs | 24 ------------------------ 1 file changed, 24 deletions(-) diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs index 57c260a062486..824f65cb6b8e5 100644 --- a/src/bootstrap/src/core/config/config.rs +++ b/src/bootstrap/src/core/config/config.rs @@ -1914,30 +1914,6 @@ impl Config { "HELP: To use `llvm.libzstd` for LLVM/LLD builds, set `download-ci-llvm` option to false." ); } - - // None of the LLVM options, except assertions, are supported - // when using downloaded LLVM. We could just ignore these but - // that's potentially confusing, so force them to not be - // explicitly set. The defaults and CI defaults don't - // necessarily match but forcing people to match (somewhat - // arbitrary) CI configuration locally seems bad/hard. - check_ci_llvm!(optimize_toml); - check_ci_llvm!(thin_lto); - check_ci_llvm!(release_debuginfo); - check_ci_llvm!(targets); - check_ci_llvm!(experimental_targets); - check_ci_llvm!(clang_cl); - check_ci_llvm!(version_suffix); - check_ci_llvm!(cflags); - check_ci_llvm!(cxxflags); - check_ci_llvm!(ldflags); - check_ci_llvm!(use_libcxx); - check_ci_llvm!(use_linker); - check_ci_llvm!(allow_old_toolchain); - check_ci_llvm!(polly); - check_ci_llvm!(clang); - check_ci_llvm!(build_config); - check_ci_llvm!(plugins); } // NOTE: can never be hit when downloading from CI, since we call `check_ci_llvm!(thin_lto)` above. From ea34bb045264466c6b3bc63caf64264de219ad77 Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Fri, 30 Aug 2024 19:56:58 +0300 Subject: [PATCH 0671/2194] print incompatible options even if we don't download Signed-off-by: onur-ozkan --- src/bootstrap/src/core/download.rs | 41 +++++++++++++++--------------- 1 file changed, 20 insertions(+), 21 deletions(-) diff --git a/src/bootstrap/src/core/download.rs b/src/bootstrap/src/core/download.rs index 25493c1f55b6c..d8b39ac0b6dac 100644 --- a/src/bootstrap/src/core/download.rs +++ b/src/bootstrap/src/core/download.rs @@ -736,27 +736,6 @@ download-rustc = false if program_out_of_date(&llvm_stamp, &key) && !self.dry_run() { self.download_ci_llvm(&llvm_sha); - if let Some(config_path) = &self.config { - let current_config_toml = Self::get_toml(config_path).unwrap(); - - match self.get_builder_toml("ci-llvm") { - Ok(ci_config_toml) => { - check_incompatible_options_for_ci_llvm(current_config_toml, ci_config_toml) - .unwrap(); - } - Err(e) if e.to_string().contains("unknown field") => { - println!( - "WARNING: CI rustc has some fields that are no longer supported in bootstrap; download-rustc will be disabled." - ); - println!("HELP: Consider rebasing to a newer commit if available."); - } - Err(e) => { - eprintln!("ERROR: Failed to parse CI LLVM config.toml: {e}"); - exit!(2); - } - }; - }; - if self.should_fix_bins_and_dylibs() { for entry in t!(fs::read_dir(llvm_root.join("bin"))) { self.fix_bin_or_dylib(&t!(entry).path()); @@ -789,6 +768,26 @@ download-rustc = false t!(fs::write(llvm_stamp, key)); } + + if let Some(config_path) = &self.config { + let current_config_toml = Self::get_toml(config_path).unwrap(); + + match self.get_builder_toml("ci-llvm") { + Ok(ci_config_toml) => { + t!(check_incompatible_options_for_ci_llvm(current_config_toml, ci_config_toml)); + } + Err(e) if e.to_string().contains("unknown field") => { + println!( + "WARNING: CI LLVM has some fields that are no longer supported in bootstrap; download-ci-llvm will be disabled." + ); + println!("HELP: Consider rebasing to a newer commit if available."); + } + Err(e) => { + eprintln!("ERROR: Failed to parse CI LLVM config.toml: {e}"); + exit!(2); + } + }; + }; } #[cfg(not(feature = "bootstrap-self-test"))] From 018ed9abb92496373da0dcf594767846eaeec4e3 Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Fri, 30 Aug 2024 20:01:05 +0300 Subject: [PATCH 0672/2194] fix llvm ThinLTO behaviour Signed-off-by: onur-ozkan --- src/bootstrap/src/core/config/config.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs index 824f65cb6b8e5..327cf6c575a57 100644 --- a/src/bootstrap/src/core/config/config.rs +++ b/src/bootstrap/src/core/config/config.rs @@ -1916,8 +1916,7 @@ impl Config { } } - // NOTE: can never be hit when downloading from CI, since we call `check_ci_llvm!(thin_lto)` above. - if config.llvm_thin_lto && link_shared.is_none() { + if !config.llvm_from_ci && config.llvm_thin_lto && link_shared.is_none() { // If we're building with ThinLTO on, by default we want to link // to LLVM shared, to avoid re-doing ThinLTO (which happens in // the link step) with each stage. From 13e16a910144492ed3896fb22c9c980bc474b174 Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Fri, 30 Aug 2024 20:05:55 +0300 Subject: [PATCH 0673/2194] use `Config::get_builder_toml` for ci-rustc config parsing Signed-off-by: onur-ozkan --- src/bootstrap/src/core/config/config.rs | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs index 327cf6c575a57..8f7195aba9a8c 100644 --- a/src/bootstrap/src/core/config/config.rs +++ b/src/bootstrap/src/core/config/config.rs @@ -2355,10 +2355,7 @@ impl Config { self.download_ci_rustc(commit); if let Some(config_path) = &self.config { - let builder_config_path = - self.out.join(self.build.triple).join("ci-rustc").join(BUILDER_CONFIG_FILENAME); - - let ci_config_toml = match Self::get_toml(&builder_config_path) { + let ci_config_toml = match self.get_builder_toml("ci-rustc") { Ok(ci_config_toml) => ci_config_toml, Err(e) if e.to_string().contains("unknown field") => { println!("WARNING: CI rustc has some fields that are no longer supported in bootstrap; download-rustc will be disabled."); @@ -2366,7 +2363,7 @@ impl Config { return None; }, Err(e) => { - eprintln!("ERROR: Failed to parse CI rustc config at '{}': {e}", builder_config_path.display()); + eprintln!("ERROR: Failed to parse CI rustc config.toml: {e}"); exit!(2); }, }; @@ -2829,6 +2826,7 @@ impl Config { /// Compares the current `Llvm` options against those in the CI LLVM builder and detects any incompatible options. /// It does this by destructuring the `Llvm` instance to make sure every `Llvm` field is covered and not missing. +#[cfg(not(feature = "bootstrap-self-test"))] pub(crate) fn check_incompatible_options_for_ci_llvm( current_config_toml: TomlConfig, ci_config_toml: TomlConfig, From 7b8cbe4f1ca1d870b2bb2196d8c3a4bc2a978f55 Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Fri, 30 Aug 2024 22:56:11 +0300 Subject: [PATCH 0674/2194] handle dry-run mode in `Config::get_builder_toml` Signed-off-by: onur-ozkan --- src/bootstrap/src/core/config/config.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs index 8f7195aba9a8c..68b42305fdcc8 100644 --- a/src/bootstrap/src/core/config/config.rs +++ b/src/bootstrap/src/core/config/config.rs @@ -1217,6 +1217,10 @@ impl Config { } pub(crate) fn get_builder_toml(&self, build_name: &str) -> Result { + if self.dry_run() { + return Ok(TomlConfig::default()); + } + let builder_config_path = self.out.join(self.build.triple).join(build_name).join(BUILDER_CONFIG_FILENAME); Self::get_toml(&builder_config_path) From f7b4f4a73bcaa2987fddfa86c240a497780c88c8 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 8 Sep 2024 09:24:06 +0200 Subject: [PATCH 0675/2194] Option, Result: put the &mut variants of 'copied' under the same feature as the '&' variants --- library/core/src/option.rs | 2 +- library/core/src/result.rs | 10 ++++++++-- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/library/core/src/option.rs b/library/core/src/option.rs index b62eec1897b09..80598b8852955 100644 --- a/library/core/src/option.rs +++ b/library/core/src/option.rs @@ -1942,7 +1942,7 @@ impl Option<&mut T> { /// ``` #[must_use = "`self` will be dropped if the result is not used"] #[stable(feature = "copied", since = "1.35.0")] - #[rustc_const_unstable(feature = "const_option_ext", issue = "91930")] + #[rustc_const_unstable(feature = "const_option", issue = "67441")] pub const fn copied(self) -> Option where T: Copy, diff --git a/library/core/src/result.rs b/library/core/src/result.rs index 5b6a81c8dae91..02f6f783b512c 100644 --- a/library/core/src/result.rs +++ b/library/core/src/result.rs @@ -1585,11 +1585,17 @@ impl Result<&mut T, E> { /// ``` #[inline] #[stable(feature = "result_copied", since = "1.59.0")] - pub fn copied(self) -> Result + #[rustc_const_unstable(feature = "const_result", issue = "82814")] + pub const fn copied(self) -> Result where T: Copy, { - self.map(|&mut t| t) + // FIXME(const-hack): this implementation, which sidesteps using `Result::map` since it's not const + // ready yet, should be reverted when possible to avoid code repetition + match self { + Ok(&mut v) => Ok(v), + Err(e) => Err(e), + } } /// Maps a `Result<&mut T, E>` to a `Result` by cloning the contents of the From fa60ea7d388890169683ad397aba1edf4979738a Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 28 Aug 2024 17:39:09 +0200 Subject: [PATCH 0676/2194] interpret: remove Readable trait, we can use Projectable instead --- .../src/interpret/discriminant.rs | 4 +- .../rustc_const_eval/src/interpret/mod.rs | 2 +- .../rustc_const_eval/src/interpret/operand.rs | 40 ++++--------------- .../rustc_const_eval/src/interpret/place.rs | 14 +++---- src/tools/miri/src/helpers.rs | 8 ++-- 5 files changed, 21 insertions(+), 47 deletions(-) diff --git a/compiler/rustc_const_eval/src/interpret/discriminant.rs b/compiler/rustc_const_eval/src/interpret/discriminant.rs index 0008a15722bde..de93ed85704b5 100644 --- a/compiler/rustc_const_eval/src/interpret/discriminant.rs +++ b/compiler/rustc_const_eval/src/interpret/discriminant.rs @@ -7,7 +7,7 @@ use rustc_target::abi::{self, TagEncoding, VariantIdx, Variants}; use tracing::{instrument, trace}; use super::{ - err_ub, throw_ub, ImmTy, InterpCx, InterpResult, Machine, Readable, Scalar, Writeable, + err_ub, throw_ub, ImmTy, InterpCx, InterpResult, Machine, Projectable, Scalar, Writeable, }; impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { @@ -60,7 +60,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { #[instrument(skip(self), level = "trace")] pub fn read_discriminant( &self, - op: &impl Readable<'tcx, M::Provenance>, + op: &impl Projectable<'tcx, M::Provenance>, ) -> InterpResult<'tcx, VariantIdx> { let ty = op.layout().ty; trace!("read_discriminant_value {:#?}", op.layout()); diff --git a/compiler/rustc_const_eval/src/interpret/mod.rs b/compiler/rustc_const_eval/src/interpret/mod.rs index 511756e3f86c9..c1e46cc3a15b4 100644 --- a/compiler/rustc_const_eval/src/interpret/mod.rs +++ b/compiler/rustc_const_eval/src/interpret/mod.rs @@ -33,7 +33,7 @@ pub(crate) use self::intrinsics::eval_nullary_intrinsic; pub use self::machine::{compile_time_machine, AllocMap, Machine, MayLeak, ReturnAction}; pub use self::memory::{AllocKind, AllocRef, AllocRefMut, FnVal, Memory, MemoryKind}; use self::operand::Operand; -pub use self::operand::{ImmTy, Immediate, OpTy, Readable}; +pub use self::operand::{ImmTy, Immediate, OpTy}; pub use self::place::{MPlaceTy, MemPlaceMeta, PlaceTy, Writeable}; use self::place::{MemPlace, Place}; pub use self::projection::{OffsetMode, Projectable}; diff --git a/compiler/rustc_const_eval/src/interpret/operand.rs b/compiler/rustc_const_eval/src/interpret/operand.rs index 9a8ccaa7cc5ca..4e6159080056e 100644 --- a/compiler/rustc_const_eval/src/interpret/operand.rs +++ b/compiler/rustc_const_eval/src/interpret/operand.rs @@ -490,32 +490,6 @@ impl<'tcx, Prov: Provenance> Projectable<'tcx, Prov> for OpTy<'tcx, Prov> { } } -/// The `Readable` trait describes interpreter values that one can read from. -pub trait Readable<'tcx, Prov: Provenance>: Projectable<'tcx, Prov> { - fn as_mplace_or_imm(&self) -> Either, ImmTy<'tcx, Prov>>; -} - -impl<'tcx, Prov: Provenance> Readable<'tcx, Prov> for OpTy<'tcx, Prov> { - #[inline(always)] - fn as_mplace_or_imm(&self) -> Either, ImmTy<'tcx, Prov>> { - self.as_mplace_or_imm() - } -} - -impl<'tcx, Prov: Provenance> Readable<'tcx, Prov> for MPlaceTy<'tcx, Prov> { - #[inline(always)] - fn as_mplace_or_imm(&self) -> Either, ImmTy<'tcx, Prov>> { - Left(self.clone()) - } -} - -impl<'tcx, Prov: Provenance> Readable<'tcx, Prov> for ImmTy<'tcx, Prov> { - #[inline(always)] - fn as_mplace_or_imm(&self) -> Either, ImmTy<'tcx, Prov>> { - Right(self.clone()) - } -} - impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { /// Try reading an immediate in memory; this is interesting particularly for `ScalarPair`. /// Returns `None` if the layout does not permit loading this as a value. @@ -588,9 +562,9 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { /// ConstProp needs it, though. pub fn read_immediate_raw( &self, - src: &impl Readable<'tcx, M::Provenance>, + src: &impl Projectable<'tcx, M::Provenance>, ) -> InterpResult<'tcx, Either, ImmTy<'tcx, M::Provenance>>> { - Ok(match src.as_mplace_or_imm() { + Ok(match src.to_op(self)?.as_mplace_or_imm() { Left(ref mplace) => { if let Some(val) = self.read_immediate_from_mplace_raw(mplace)? { Right(val) @@ -608,7 +582,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { #[inline(always)] pub fn read_immediate( &self, - op: &impl Readable<'tcx, M::Provenance>, + op: &impl Projectable<'tcx, M::Provenance>, ) -> InterpResult<'tcx, ImmTy<'tcx, M::Provenance>> { if !matches!( op.layout().abi, @@ -627,7 +601,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { /// Read a scalar from a place pub fn read_scalar( &self, - op: &impl Readable<'tcx, M::Provenance>, + op: &impl Projectable<'tcx, M::Provenance>, ) -> InterpResult<'tcx, Scalar> { Ok(self.read_immediate(op)?.to_scalar()) } @@ -638,21 +612,21 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { /// Read a pointer from a place. pub fn read_pointer( &self, - op: &impl Readable<'tcx, M::Provenance>, + op: &impl Projectable<'tcx, M::Provenance>, ) -> InterpResult<'tcx, Pointer>> { self.read_scalar(op)?.to_pointer(self) } /// Read a pointer-sized unsigned integer from a place. pub fn read_target_usize( &self, - op: &impl Readable<'tcx, M::Provenance>, + op: &impl Projectable<'tcx, M::Provenance>, ) -> InterpResult<'tcx, u64> { self.read_scalar(op)?.to_target_usize(self) } /// Read a pointer-sized signed integer from a place. pub fn read_target_isize( &self, - op: &impl Readable<'tcx, M::Provenance>, + op: &impl Projectable<'tcx, M::Provenance>, ) -> InterpResult<'tcx, i64> { self.read_scalar(op)?.to_target_isize(self) } diff --git a/compiler/rustc_const_eval/src/interpret/place.rs b/compiler/rustc_const_eval/src/interpret/place.rs index 840f7986c6e0a..224fac2f22045 100644 --- a/compiler/rustc_const_eval/src/interpret/place.rs +++ b/compiler/rustc_const_eval/src/interpret/place.rs @@ -15,7 +15,7 @@ use tracing::{instrument, trace}; use super::{ alloc_range, mir_assign_valid_types, AllocRef, AllocRefMut, CheckAlignMsg, CtfeProvenance, ImmTy, Immediate, InterpCx, InterpResult, Machine, MemoryKind, Misalignment, OffsetMode, OpTy, - Operand, Pointer, Projectable, Provenance, Readable, Scalar, + Operand, Pointer, Projectable, Provenance, Scalar, }; #[derive(Copy, Clone, Hash, PartialEq, Eq, Debug)] @@ -436,7 +436,7 @@ where #[instrument(skip(self), level = "trace")] pub fn deref_pointer( &self, - src: &impl Readable<'tcx, M::Provenance>, + src: &impl Projectable<'tcx, M::Provenance>, ) -> InterpResult<'tcx, MPlaceTy<'tcx, M::Provenance>> { if src.layout().ty.is_box() { // Derefer should have removed all Box derefs. @@ -768,7 +768,7 @@ where #[inline(always)] pub(super) fn copy_op_no_dest_validation( &mut self, - src: &impl Readable<'tcx, M::Provenance>, + src: &impl Projectable<'tcx, M::Provenance>, dest: &impl Writeable<'tcx, M::Provenance>, ) -> InterpResult<'tcx> { self.copy_op_inner( @@ -781,7 +781,7 @@ where #[inline(always)] pub fn copy_op_allow_transmute( &mut self, - src: &impl Readable<'tcx, M::Provenance>, + src: &impl Projectable<'tcx, M::Provenance>, dest: &impl Writeable<'tcx, M::Provenance>, ) -> InterpResult<'tcx> { self.copy_op_inner( @@ -794,7 +794,7 @@ where #[inline(always)] pub fn copy_op( &mut self, - src: &impl Readable<'tcx, M::Provenance>, + src: &impl Projectable<'tcx, M::Provenance>, dest: &impl Writeable<'tcx, M::Provenance>, ) -> InterpResult<'tcx> { self.copy_op_inner( @@ -808,7 +808,7 @@ where #[instrument(skip(self), level = "trace")] fn copy_op_inner( &mut self, - src: &impl Readable<'tcx, M::Provenance>, + src: &impl Projectable<'tcx, M::Provenance>, dest: &impl Writeable<'tcx, M::Provenance>, allow_transmute: bool, validate_dest: bool, @@ -843,7 +843,7 @@ where #[instrument(skip(self), level = "trace")] fn copy_op_no_validate( &mut self, - src: &impl Readable<'tcx, M::Provenance>, + src: &impl Projectable<'tcx, M::Provenance>, dest: &impl Writeable<'tcx, M::Provenance>, allow_transmute: bool, ) -> InterpResult<'tcx> { diff --git a/src/tools/miri/src/helpers.rs b/src/tools/miri/src/helpers.rs index a546ad20fef98..cba99c0bd7a81 100644 --- a/src/tools/miri/src/helpers.rs +++ b/src/tools/miri/src/helpers.rs @@ -869,7 +869,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { /// Dereference a pointer operand to a place using `layout` instead of the pointer's declared type fn deref_pointer_as( &self, - op: &impl Readable<'tcx, Provenance>, + op: &impl Projectable<'tcx, Provenance>, layout: TyAndLayout<'tcx>, ) -> InterpResult<'tcx, MPlaceTy<'tcx>> { let this = self.eval_context_ref(); @@ -880,7 +880,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { /// Calculates the MPlaceTy given the offset and layout of an access on an operand fn deref_pointer_and_offset( &self, - op: &impl Readable<'tcx, Provenance>, + op: &impl Projectable<'tcx, Provenance>, offset: u64, base_layout: TyAndLayout<'tcx>, value_layout: TyAndLayout<'tcx>, @@ -897,7 +897,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { fn deref_pointer_and_read( &self, - op: &impl Readable<'tcx, Provenance>, + op: &impl Projectable<'tcx, Provenance>, offset: u64, base_layout: TyAndLayout<'tcx>, value_layout: TyAndLayout<'tcx>, @@ -909,7 +909,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { fn deref_pointer_and_write( &mut self, - op: &impl Readable<'tcx, Provenance>, + op: &impl Projectable<'tcx, Provenance>, offset: u64, value: impl Into, base_layout: TyAndLayout<'tcx>, From 8ad808db7e73bd445216ea004fd655f86758ee08 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 28 Aug 2024 17:42:05 +0200 Subject: [PATCH 0677/2194] interpret: make Writeable trait about a to_place operation --- .../rustc_const_eval/src/interpret/operand.rs | 2 +- .../rustc_const_eval/src/interpret/place.rs | 29 ++++++++----------- 2 files changed, 13 insertions(+), 18 deletions(-) diff --git a/compiler/rustc_const_eval/src/interpret/operand.rs b/compiler/rustc_const_eval/src/interpret/operand.rs index 4e6159080056e..d9da0b3e00acb 100644 --- a/compiler/rustc_const_eval/src/interpret/operand.rs +++ b/compiler/rustc_const_eval/src/interpret/operand.rs @@ -691,7 +691,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { ) -> InterpResult<'tcx, OpTy<'tcx, M::Provenance>> { match place.as_mplace_or_local() { Left(mplace) => Ok(mplace.into()), - Right((local, offset, locals_addr)) => { + Right((local, offset, locals_addr, _)) => { debug_assert!(place.layout.is_sized()); // only sized locals can ever be `Place::Local`. debug_assert_eq!(locals_addr, self.frame().locals_addr()); let base = self.local_to_op(local, None)?; diff --git a/compiler/rustc_const_eval/src/interpret/place.rs b/compiler/rustc_const_eval/src/interpret/place.rs index 224fac2f22045..45695186ff0f2 100644 --- a/compiler/rustc_const_eval/src/interpret/place.rs +++ b/compiler/rustc_const_eval/src/interpret/place.rs @@ -231,10 +231,12 @@ impl<'tcx, Prov: Provenance> PlaceTy<'tcx, Prov> { #[inline(always)] pub fn as_mplace_or_local( &self, - ) -> Either, (mir::Local, Option, usize)> { + ) -> Either, (mir::Local, Option, usize, TyAndLayout<'tcx>)> { match self.place { Place::Ptr(mplace) => Left(MPlaceTy { mplace, layout: self.layout }), - Place::Local { local, offset, locals_addr } => Right((local, offset, locals_addr)), + Place::Local { local, offset, locals_addr } => { + Right((local, offset, locals_addr, self.layout)) + } } } @@ -277,7 +279,7 @@ impl<'tcx, Prov: Provenance> Projectable<'tcx, Prov> for PlaceTy<'tcx, Prov> { ) -> InterpResult<'tcx, Self> { Ok(match self.as_mplace_or_local() { Left(mplace) => mplace.offset_with_meta(offset, mode, meta, layout, ecx)?.into(), - Right((local, old_offset, locals_addr)) => { + Right((local, old_offset, locals_addr, _)) => { debug_assert!(layout.is_sized(), "unsized locals should live in memory"); assert_matches!(meta, MemPlaceMeta::None); // we couldn't store it anyway... // `Place::Local` are always in-bounds of their surrounding local, so we can just @@ -328,9 +330,7 @@ impl<'tcx, Prov: Provenance> OpTy<'tcx, Prov> { /// The `Weiteable` trait describes interpreter values that can be written to. pub trait Writeable<'tcx, Prov: Provenance>: Projectable<'tcx, Prov> { - fn as_mplace_or_local( - &self, - ) -> Either, (mir::Local, Option, usize, TyAndLayout<'tcx>)>; + fn to_place(&self) -> PlaceTy<'tcx, Prov>; fn force_mplace>( &self, @@ -340,11 +340,8 @@ pub trait Writeable<'tcx, Prov: Provenance>: Projectable<'tcx, Prov> { impl<'tcx, Prov: Provenance> Writeable<'tcx, Prov> for PlaceTy<'tcx, Prov> { #[inline(always)] - fn as_mplace_or_local( - &self, - ) -> Either, (mir::Local, Option, usize, TyAndLayout<'tcx>)> { - self.as_mplace_or_local() - .map_right(|(local, offset, locals_addr)| (local, offset, locals_addr, self.layout)) + fn to_place(&self) -> PlaceTy<'tcx, Prov> { + self.clone() } #[inline(always)] @@ -358,10 +355,8 @@ impl<'tcx, Prov: Provenance> Writeable<'tcx, Prov> for PlaceTy<'tcx, Prov> { impl<'tcx, Prov: Provenance> Writeable<'tcx, Prov> for MPlaceTy<'tcx, Prov> { #[inline(always)] - fn as_mplace_or_local( - &self, - ) -> Either, (mir::Local, Option, usize, TyAndLayout<'tcx>)> { - Left(self.clone()) + fn to_place(&self) -> PlaceTy<'tcx, Prov> { + self.clone().into() } #[inline(always)] @@ -615,7 +610,7 @@ where // See if we can avoid an allocation. This is the counterpart to `read_immediate_raw`, // but not factored as a separate function. - let mplace = match dest.as_mplace_or_local() { + let mplace = match dest.to_place().as_mplace_or_local() { Right((local, offset, locals_addr, layout)) => { if offset.is_some() { // This has been projected to a part of this local. We could have complicated @@ -728,7 +723,7 @@ where &mut self, dest: &impl Writeable<'tcx, M::Provenance>, ) -> InterpResult<'tcx> { - let mplace = match dest.as_mplace_or_local() { + let mplace = match dest.to_place().as_mplace_or_local() { Left(mplace) => mplace, Right((local, offset, locals_addr, layout)) => { if offset.is_some() { From 85dc22f2cfc6328501dddfaa25b67618ee5d48e4 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Thu, 29 Aug 2024 13:56:01 +0200 Subject: [PATCH 0678/2194] interpret: factor out common code for place mutation --- .../rustc_const_eval/src/interpret/operand.rs | 26 ++++ .../rustc_const_eval/src/interpret/place.rs | 143 ++++++++---------- .../rustc_const_eval/src/interpret/visitor.rs | 1 + 3 files changed, 89 insertions(+), 81 deletions(-) diff --git a/compiler/rustc_const_eval/src/interpret/operand.rs b/compiler/rustc_const_eval/src/interpret/operand.rs index d9da0b3e00acb..72842fd6f1dcc 100644 --- a/compiler/rustc_const_eval/src/interpret/operand.rs +++ b/compiler/rustc_const_eval/src/interpret/operand.rs @@ -111,6 +111,32 @@ impl Immediate { Immediate::Uninit => bug!("Got uninit where a scalar or scalar pair was expected"), } } + + /// Assert that this immediate is a valid value for the given ABI. + pub fn assert_matches_abi(self, abi: Abi, cx: &impl HasDataLayout) { + match (self, abi) { + (Immediate::Scalar(scalar), Abi::Scalar(s)) => { + assert_eq!(scalar.size(), s.size(cx)); + if !matches!(s.primitive(), abi::Pointer(..)) { + assert!(matches!(scalar, Scalar::Int(..))); + } + } + (Immediate::ScalarPair(a_val, b_val), Abi::ScalarPair(a, b)) => { + assert_eq!(a_val.size(), a.size(cx)); + if !matches!(a.primitive(), abi::Pointer(..)) { + assert!(matches!(a_val, Scalar::Int(..))); + } + assert_eq!(b_val.size(), b.size(cx)); + if !matches!(b.primitive(), abi::Pointer(..)) { + assert!(matches!(b_val, Scalar::Int(..))); + } + } + (Immediate::Uninit, _) => {} + _ => { + bug!("value {self:?} does not match ABI {abi:?})",) + } + } + } } // ScalarPair needs a type to interpret, so we often have an immediate and a type together diff --git a/compiler/rustc_const_eval/src/interpret/place.rs b/compiler/rustc_const_eval/src/interpret/place.rs index 45695186ff0f2..551a4012ddd45 100644 --- a/compiler/rustc_const_eval/src/interpret/place.rs +++ b/compiler/rustc_const_eval/src/interpret/place.rs @@ -180,7 +180,8 @@ pub(super) enum Place { Ptr(MemPlace), /// To support alloc-free locals, we are able to write directly to a local. The offset indicates - /// where in the local this place is located; if it is `None`, no projection has been applied. + /// where in the local this place is located; if it is `None`, no projection has been applied + /// and the type of the place is exactly the type of the local. /// Such projections are meaningful even if the offset is 0, since they can change layouts. /// (Without that optimization, we'd just always be a `MemPlace`.) /// `Local` places always refer to the current stack frame, so they are unstable under @@ -557,6 +558,40 @@ where Ok(place) } + /// Given a place, returns either the underlying mplace or a reference to where the value of + /// this place is stored. + fn as_mplace_or_mutable_local( + &mut self, + place: &PlaceTy<'tcx, M::Provenance>, + ) -> InterpResult< + 'tcx, + Either, (&mut Immediate, TyAndLayout<'tcx>)>, + > { + Ok(match place.to_place().as_mplace_or_local() { + Left(mplace) => Left(mplace), + Right((local, offset, locals_addr, layout)) => { + if offset.is_some() { + // This has been projected to a part of this local, or had the type changed. + // FIMXE: there are cases where we could still avoid allocating an mplace. + Left(place.force_mplace(self)?) + } else { + debug_assert_eq!(locals_addr, self.frame().locals_addr()); + debug_assert_eq!(self.layout_of_local(self.frame(), local, None)?, layout); + match self.frame_mut().locals[local].access_mut()? { + Operand::Indirect(mplace) => { + // The local is in memory. + Left(MPlaceTy { mplace: *mplace, layout }) + } + Operand::Immediate(local_val) => { + // The local still has the optimized representation. + Right((local_val, layout)) + } + } + } + } + }) + } + /// Write an immediate to a place #[inline(always)] #[instrument(skip(self), level = "trace")] @@ -608,60 +643,20 @@ where ) -> InterpResult<'tcx> { assert!(dest.layout().is_sized(), "Cannot write unsized immediate data"); - // See if we can avoid an allocation. This is the counterpart to `read_immediate_raw`, - // but not factored as a separate function. - let mplace = match dest.to_place().as_mplace_or_local() { - Right((local, offset, locals_addr, layout)) => { - if offset.is_some() { - // This has been projected to a part of this local. We could have complicated - // logic to still keep this local as an `Operand`... but it's much easier to - // just fall back to the indirect path. - dest.force_mplace(self)? - } else { - debug_assert_eq!(locals_addr, self.frame().locals_addr()); - match self.frame_mut().locals[local].access_mut()? { - Operand::Immediate(local_val) => { - // Local can be updated in-place. - *local_val = src; - // Double-check that the value we are storing and the local fit to each other. - // (*After* doing the update for borrow checker reasons.) - if cfg!(debug_assertions) { - let local_layout = - self.layout_of_local(&self.frame(), local, None)?; - match (src, local_layout.abi) { - (Immediate::Scalar(scalar), Abi::Scalar(s)) => { - assert_eq!(scalar.size(), s.size(self)) - } - ( - Immediate::ScalarPair(a_val, b_val), - Abi::ScalarPair(a, b), - ) => { - assert_eq!(a_val.size(), a.size(self)); - assert_eq!(b_val.size(), b.size(self)); - } - (Immediate::Uninit, _) => {} - (src, abi) => { - bug!( - "value {src:?} cannot be written into local with type {} (ABI {abi:?})", - local_layout.ty - ) - } - }; - } - return Ok(()); - } - Operand::Indirect(mplace) => { - // The local is in memory, go on below. - MPlaceTy { mplace: *mplace, layout } - } - } + match self.as_mplace_or_mutable_local(&dest.to_place())? { + Right((local_val, local_layout)) => { + // Local can be updated in-place. + *local_val = src; + // Double-check that the value we are storing and the local fit to each other. + if cfg!(debug_assertions) { + src.assert_matches_abi(local_layout.abi, self); } } - Left(mplace) => mplace, // already referring to memory - }; - - // This is already in memory, write there. - self.write_immediate_to_mplace_no_validate(src, mplace.layout, mplace.mplace) + Left(mplace) => { + self.write_immediate_to_mplace_no_validate(src, mplace.layout, mplace.mplace)?; + } + } + Ok(()) } /// Write an immediate to memory. @@ -673,6 +668,9 @@ where layout: TyAndLayout<'tcx>, dest: MemPlace, ) -> InterpResult<'tcx> { + if cfg!(debug_assertions) { + value.assert_matches_abi(layout.abi, self); + } // Note that it is really important that the type here is the right one, and matches the // type things are read at. In case `value` is a `ScalarPair`, we don't do any magic here // to handle padding properly, which is only correct if we never look at this data with the @@ -723,35 +721,18 @@ where &mut self, dest: &impl Writeable<'tcx, M::Provenance>, ) -> InterpResult<'tcx> { - let mplace = match dest.to_place().as_mplace_or_local() { - Left(mplace) => mplace, - Right((local, offset, locals_addr, layout)) => { - if offset.is_some() { - // This has been projected to a part of this local. We could have complicated - // logic to still keep this local as an `Operand`... but it's much easier to - // just fall back to the indirect path. - // FIXME: share the logic with `write_immediate_no_validate`. - dest.force_mplace(self)? - } else { - debug_assert_eq!(locals_addr, self.frame().locals_addr()); - match self.frame_mut().locals[local].access_mut()? { - Operand::Immediate(local) => { - *local = Immediate::Uninit; - return Ok(()); - } - Operand::Indirect(mplace) => { - // The local is in memory, go on below. - MPlaceTy { mplace: *mplace, layout } - } - } - } + match self.as_mplace_or_mutable_local(&dest.to_place())? { + Right((local_val, _local_layout)) => { + *local_val = Immediate::Uninit; } - }; - let Some(mut alloc) = self.get_place_alloc_mut(&mplace)? else { - // Zero-sized access - return Ok(()); - }; - alloc.write_uninit()?; + Left(mplace) => { + let Some(mut alloc) = self.get_place_alloc_mut(&mplace)? else { + // Zero-sized access + return Ok(()); + }; + alloc.write_uninit()?; + } + } Ok(()) } diff --git a/compiler/rustc_const_eval/src/interpret/visitor.rs b/compiler/rustc_const_eval/src/interpret/visitor.rs index b02f12e3c7f0b..08b39fe8751be 100644 --- a/compiler/rustc_const_eval/src/interpret/visitor.rs +++ b/compiler/rustc_const_eval/src/interpret/visitor.rs @@ -82,6 +82,7 @@ pub trait ValueVisitor<'tcx, M: Machine<'tcx>>: Sized { self.visit_value(new_val) } + /// Traversal logic; should not be overloaded. fn walk_value(&mut self, v: &Self::V) -> InterpResult<'tcx> { let ty = v.layout().ty; trace!("walk_value: type: {ty}"); From cbdcbf0d6a586792c5e0a0b8965a3179bac56120 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Thu, 29 Aug 2024 08:59:52 +0200 Subject: [PATCH 0679/2194] interpret: reset provenance on typed copies --- .../src/const_eval/eval_queries.rs | 4 +- .../rustc_const_eval/src/interpret/memory.rs | 38 ++- .../rustc_const_eval/src/interpret/operand.rs | 14 + .../rustc_const_eval/src/interpret/place.rs | 69 +++-- .../src/interpret/validity.rs | 259 ++++++++++++------ .../src/util/check_validity_requirement.rs | 12 +- .../src/mir/interpret/allocation.rs | 6 + .../rustc_middle/src/mir/interpret/value.rs | 7 + src/tools/miri/src/concurrency/data_race.rs | 2 +- src/tools/miri/src/intrinsics/mod.rs | 6 +- .../provenance/int_copy_looses_provenance0.rs | 10 + .../int_copy_looses_provenance0.stderr | 15 + .../provenance/int_copy_looses_provenance1.rs | 10 + .../int_copy_looses_provenance1.stderr | 15 + .../provenance/int_copy_looses_provenance2.rs | 12 + .../int_copy_looses_provenance2.stderr | 15 + .../provenance/int_copy_looses_provenance3.rs | 29 ++ .../int_copy_looses_provenance3.stderr | 15 + .../ptr_copy_loses_partial_provenance0.rs | 17 ++ .../ptr_copy_loses_partial_provenance0.stderr | 15 + .../ptr_copy_loses_partial_provenance1.rs | 17 ++ .../ptr_copy_loses_partial_provenance1.stderr | 15 + src/tools/miri/tests/pass/provenance.rs | 22 ++ 23 files changed, 489 insertions(+), 135 deletions(-) create mode 100644 src/tools/miri/tests/fail/provenance/int_copy_looses_provenance0.rs create mode 100644 src/tools/miri/tests/fail/provenance/int_copy_looses_provenance0.stderr create mode 100644 src/tools/miri/tests/fail/provenance/int_copy_looses_provenance1.rs create mode 100644 src/tools/miri/tests/fail/provenance/int_copy_looses_provenance1.stderr create mode 100644 src/tools/miri/tests/fail/provenance/int_copy_looses_provenance2.rs create mode 100644 src/tools/miri/tests/fail/provenance/int_copy_looses_provenance2.stderr create mode 100644 src/tools/miri/tests/fail/provenance/int_copy_looses_provenance3.rs create mode 100644 src/tools/miri/tests/fail/provenance/int_copy_looses_provenance3.stderr create mode 100644 src/tools/miri/tests/fail/provenance/ptr_copy_loses_partial_provenance0.rs create mode 100644 src/tools/miri/tests/fail/provenance/ptr_copy_loses_partial_provenance0.stderr create mode 100644 src/tools/miri/tests/fail/provenance/ptr_copy_loses_partial_provenance1.rs create mode 100644 src/tools/miri/tests/fail/provenance/ptr_copy_loses_partial_provenance1.stderr diff --git a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs index 96b3ec6f18728..7ccebd83f24f7 100644 --- a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs +++ b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs @@ -94,7 +94,7 @@ fn eval_body_using_ecx<'tcx, R: InterpretationResult<'tcx>>( let intern_result = intern_const_alloc_recursive(ecx, intern_kind, &ret); // Since evaluation had no errors, validate the resulting constant. - const_validate_mplace(&ecx, &ret, cid)?; + const_validate_mplace(ecx, &ret, cid)?; // Only report this after validation, as validaiton produces much better diagnostics. // FIXME: ensure validation always reports this and stop making interning care about it. @@ -391,7 +391,7 @@ fn eval_in_interpreter<'tcx, R: InterpretationResult<'tcx>>( #[inline(always)] fn const_validate_mplace<'tcx>( - ecx: &InterpCx<'tcx, CompileTimeMachine<'tcx>>, + ecx: &mut InterpCx<'tcx, CompileTimeMachine<'tcx>>, mplace: &MPlaceTy<'tcx>, cid: GlobalId<'tcx>, ) -> Result<(), ErrorHandled> { diff --git a/compiler/rustc_const_eval/src/interpret/memory.rs b/compiler/rustc_const_eval/src/interpret/memory.rs index 45a5eb9bd52fc..53a9cd0b9ad6d 100644 --- a/compiler/rustc_const_eval/src/interpret/memory.rs +++ b/compiler/rustc_const_eval/src/interpret/memory.rs @@ -8,9 +8,8 @@ use std::assert_matches::assert_matches; use std::borrow::Cow; -use std::cell::Cell; use std::collections::VecDeque; -use std::{fmt, ptr}; +use std::{fmt, mem, ptr}; use rustc_ast::Mutability; use rustc_data_structures::fx::{FxHashSet, FxIndexMap}; @@ -118,7 +117,7 @@ pub struct Memory<'tcx, M: Machine<'tcx>> { /// This stores whether we are currently doing reads purely for the purpose of validation. /// Those reads do not trigger the machine's hooks for memory reads. /// Needless to say, this must only be set with great care! - validation_in_progress: Cell, + validation_in_progress: bool, } /// A reference to some allocation that was already bounds-checked for the given region @@ -145,7 +144,7 @@ impl<'tcx, M: Machine<'tcx>> Memory<'tcx, M> { alloc_map: M::MemoryMap::default(), extra_fn_ptr_map: FxIndexMap::default(), dead_alloc_map: FxIndexMap::default(), - validation_in_progress: Cell::new(false), + validation_in_progress: false, } } @@ -682,7 +681,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { // We want to call the hook on *all* accesses that involve an AllocId, including zero-sized // accesses. That means we cannot rely on the closure above or the `Some` branch below. We // do this after `check_and_deref_ptr` to ensure some basic sanity has already been checked. - if !self.memory.validation_in_progress.get() { + if !self.memory.validation_in_progress { if let Ok((alloc_id, ..)) = self.ptr_try_get_alloc_id(ptr, size_i64) { M::before_alloc_read(self, alloc_id)?; } @@ -690,7 +689,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { if let Some((alloc_id, offset, prov, alloc)) = ptr_and_alloc { let range = alloc_range(offset, size); - if !self.memory.validation_in_progress.get() { + if !self.memory.validation_in_progress { M::before_memory_read( self.tcx, &self.machine, @@ -766,11 +765,14 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { let parts = self.get_ptr_access(ptr, size)?; if let Some((alloc_id, offset, prov)) = parts { let tcx = self.tcx; + let validation_in_progress = self.memory.validation_in_progress; // FIXME: can we somehow avoid looking up the allocation twice here? // We cannot call `get_raw_mut` inside `check_and_deref_ptr` as that would duplicate `&mut self`. let (alloc, machine) = self.get_alloc_raw_mut(alloc_id)?; let range = alloc_range(offset, size); - M::before_memory_write(tcx, machine, &mut alloc.extra, (alloc_id, prov), range)?; + if !validation_in_progress { + M::before_memory_write(tcx, machine, &mut alloc.extra, (alloc_id, prov), range)?; + } Ok(Some(AllocRefMut { alloc, range, tcx: *tcx, alloc_id })) } else { Ok(None) @@ -1014,16 +1016,16 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { /// /// We do this so Miri's allocation access tracking does not show the validation /// reads as spurious accesses. - pub fn run_for_validation(&self, f: impl FnOnce() -> R) -> R { + pub fn run_for_validation(&mut self, f: impl FnOnce(&mut Self) -> R) -> R { // This deliberately uses `==` on `bool` to follow the pattern // `assert!(val.replace(new) == old)`. assert!( - self.memory.validation_in_progress.replace(true) == false, + mem::replace(&mut self.memory.validation_in_progress, true) == false, "`validation_in_progress` was already set" ); - let res = f(); + let res = f(self); assert!( - self.memory.validation_in_progress.replace(false) == true, + mem::replace(&mut self.memory.validation_in_progress, false) == true, "`validation_in_progress` was unset by someone else" ); res @@ -1115,6 +1117,10 @@ impl<'a, 'tcx, M: Machine<'tcx>> std::fmt::Debug for DumpAllocs<'a, 'tcx, M> { impl<'tcx, 'a, Prov: Provenance, Extra, Bytes: AllocBytes> AllocRefMut<'a, 'tcx, Prov, Extra, Bytes> { + pub fn as_ref<'b>(&'b self) -> AllocRef<'b, 'tcx, Prov, Extra, Bytes> { + AllocRef { alloc: self.alloc, range: self.range, tcx: self.tcx, alloc_id: self.alloc_id } + } + /// `range` is relative to this allocation reference, not the base of the allocation. pub fn write_scalar(&mut self, range: AllocRange, val: Scalar) -> InterpResult<'tcx> { let range = self.range.subrange(range); @@ -1137,6 +1143,14 @@ impl<'tcx, 'a, Prov: Provenance, Extra, Bytes: AllocBytes> .write_uninit(&self.tcx, self.range) .map_err(|e| e.to_interp_error(self.alloc_id))?) } + + /// Remove all provenance in the reference range. + pub fn clear_provenance(&mut self) -> InterpResult<'tcx> { + Ok(self + .alloc + .clear_provenance(&self.tcx, self.range) + .map_err(|e| e.to_interp_error(self.alloc_id))?) + } } impl<'tcx, 'a, Prov: Provenance, Extra, Bytes: AllocBytes> AllocRef<'a, 'tcx, Prov, Extra, Bytes> { @@ -1278,7 +1292,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { }; let src_alloc = self.get_alloc_raw(src_alloc_id)?; let src_range = alloc_range(src_offset, size); - assert!(!self.memory.validation_in_progress.get(), "we can't be copying during validation"); + assert!(!self.memory.validation_in_progress, "we can't be copying during validation"); M::before_memory_read( tcx, &self.machine, diff --git a/compiler/rustc_const_eval/src/interpret/operand.rs b/compiler/rustc_const_eval/src/interpret/operand.rs index 72842fd6f1dcc..b906e3422dba5 100644 --- a/compiler/rustc_const_eval/src/interpret/operand.rs +++ b/compiler/rustc_const_eval/src/interpret/operand.rs @@ -137,6 +137,20 @@ impl Immediate { } } } + + pub fn clear_provenance<'tcx>(&mut self) -> InterpResult<'tcx> { + match self { + Immediate::Scalar(s) => { + s.clear_provenance()?; + } + Immediate::ScalarPair(a, b) => { + a.clear_provenance()?; + b.clear_provenance()?; + } + Immediate::Uninit => {} + } + Ok(()) + } } // ScalarPair needs a type to interpret, so we often have an immediate and a type together diff --git a/compiler/rustc_const_eval/src/interpret/place.rs b/compiler/rustc_const_eval/src/interpret/place.rs index 551a4012ddd45..e2aef0519186e 100644 --- a/compiler/rustc_const_eval/src/interpret/place.rs +++ b/compiler/rustc_const_eval/src/interpret/place.rs @@ -605,8 +605,9 @@ where if M::enforce_validity(self, dest.layout()) { // Data got changed, better make sure it matches the type! self.validate_operand( - &dest.to_op(self)?, + &dest.to_place(), M::enforce_validity_recursively(self, dest.layout()), + /*reset_provenance*/ true, )?; } @@ -636,7 +637,7 @@ where /// Write an immediate to a place. /// If you use this you are responsible for validating that things got copied at the /// right type. - fn write_immediate_no_validate( + pub(super) fn write_immediate_no_validate( &mut self, src: Immediate, dest: &impl Writeable<'tcx, M::Provenance>, @@ -684,15 +685,7 @@ where match value { Immediate::Scalar(scalar) => { - let Abi::Scalar(s) = layout.abi else { - span_bug!( - self.cur_span(), - "write_immediate_to_mplace: invalid Scalar layout: {layout:#?}", - ) - }; - let size = s.size(&tcx); - assert_eq!(size, layout.size, "abi::Scalar size does not match layout size"); - alloc.write_scalar(alloc_range(Size::ZERO, size), scalar) + alloc.write_scalar(alloc_range(Size::ZERO, scalar.size()), scalar) } Immediate::ScalarPair(a_val, b_val) => { let Abi::ScalarPair(a, b) = layout.abi else { @@ -702,16 +695,15 @@ where layout ) }; - let (a_size, b_size) = (a.size(&tcx), b.size(&tcx)); - let b_offset = a_size.align_to(b.align(&tcx).abi); + let b_offset = a.size(&tcx).align_to(b.align(&tcx).abi); assert!(b_offset.bytes() > 0); // in `operand_field` we use the offset to tell apart the fields // It is tempting to verify `b_offset` against `layout.fields.offset(1)`, // but that does not work: We could be a newtype around a pair, then the // fields do not match the `ScalarPair` components. - alloc.write_scalar(alloc_range(Size::ZERO, a_size), a_val)?; - alloc.write_scalar(alloc_range(b_offset, b_size), b_val) + alloc.write_scalar(alloc_range(Size::ZERO, a_val.size()), a_val)?; + alloc.write_scalar(alloc_range(b_offset, b_val.size()), b_val) } Immediate::Uninit => alloc.write_uninit(), } @@ -736,6 +728,26 @@ where Ok(()) } + /// Remove all provenance in the given place. + pub fn clear_provenance( + &mut self, + dest: &impl Writeable<'tcx, M::Provenance>, + ) -> InterpResult<'tcx> { + match self.as_mplace_or_mutable_local(&dest.to_place())? { + Right((local_val, _local_layout)) => { + local_val.clear_provenance()?; + } + Left(mplace) => { + let Some(mut alloc) = self.get_place_alloc_mut(&mplace)? else { + // Zero-sized access + return Ok(()); + }; + alloc.clear_provenance()?; + } + } + Ok(()) + } + /// Copies the data from an operand to a place. /// The layouts of the `src` and `dest` may disagree. /// Does not perform validation of the destination. @@ -789,23 +801,30 @@ where allow_transmute: bool, validate_dest: bool, ) -> InterpResult<'tcx> { - // Generally for transmutation, data must be valid both at the old and new type. - // But if the types are the same, the 2nd validation below suffices. - if src.layout().ty != dest.layout().ty && M::enforce_validity(self, src.layout()) { - self.validate_operand( - &src.to_op(self)?, - M::enforce_validity_recursively(self, src.layout()), - )?; - } + // These are technically *two* typed copies: `src` is a not-yet-loaded value, + // so we're going a typed copy at `src` type from there to some intermediate storage. + // And then we're doing a second typed copy from that intermediate storage to `dest`. + // But as an optimization, we only make a single direct copy here. // Do the actual copy. self.copy_op_no_validate(src, dest, allow_transmute)?; if validate_dest && M::enforce_validity(self, dest.layout()) { - // Data got changed, better make sure it matches the type! + let dest = dest.to_place(); + // Given that there were two typed copies, we have to ensure this is valid at both types, + // and we have to ensure this loses provenance and padding according to both types. + // But if the types are identical, we only do one pass. + if src.layout().ty != dest.layout().ty { + self.validate_operand( + &dest.transmute(src.layout(), self)?, + M::enforce_validity_recursively(self, src.layout()), + /*reset_provenance*/ true, + )?; + } self.validate_operand( - &dest.to_op(self)?, + &dest, M::enforce_validity_recursively(self, dest.layout()), + /*reset_provenance*/ true, )?; } diff --git a/compiler/rustc_const_eval/src/interpret/validity.rs b/compiler/rustc_const_eval/src/interpret/validity.rs index 26b7251f6dbc5..953831a55e5ed 100644 --- a/compiler/rustc_const_eval/src/interpret/validity.rs +++ b/compiler/rustc_const_eval/src/interpret/validity.rs @@ -30,8 +30,8 @@ use tracing::trace; use super::machine::AllocMap; use super::{ err_ub, format_interp_error, throw_ub, AllocId, AllocKind, CheckInAllocMsg, GlobalAlloc, ImmTy, - Immediate, InterpCx, InterpResult, MPlaceTy, Machine, MemPlaceMeta, OpTy, Pointer, Projectable, - Scalar, ValueVisitor, + Immediate, InterpCx, InterpResult, MPlaceTy, Machine, MemPlaceMeta, PlaceTy, Pointer, + Projectable, Scalar, ValueVisitor, }; // for the validation errors @@ -163,22 +163,22 @@ impl RefTracking pub fn empty() -> Self { RefTracking { seen: FxHashSet::default(), todo: vec![] } } - pub fn new(op: T) -> Self { + pub fn new(val: T) -> Self { let mut ref_tracking_for_consts = - RefTracking { seen: FxHashSet::default(), todo: vec![(op.clone(), PATH::default())] }; - ref_tracking_for_consts.seen.insert(op); + RefTracking { seen: FxHashSet::default(), todo: vec![(val.clone(), PATH::default())] }; + ref_tracking_for_consts.seen.insert(val); ref_tracking_for_consts } pub fn next(&mut self) -> Option<(T, PATH)> { self.todo.pop() } - fn track(&mut self, op: T, path: impl FnOnce() -> PATH) { - if self.seen.insert(op.clone()) { - trace!("Recursing below ptr {:#?}", op); + fn track(&mut self, val: T, path: impl FnOnce() -> PATH) { + if self.seen.insert(val.clone()) { + trace!("Recursing below ptr {:#?}", val); let path = path(); // Remember to come back to this later. - self.todo.push((op, path)); + self.todo.push((val, path)); } } } @@ -217,7 +217,10 @@ struct ValidityVisitor<'rt, 'tcx, M: Machine<'tcx>> { ref_tracking: Option<&'rt mut RefTracking, Vec>>, /// `None` indicates this is not validating for CTFE (but for runtime). ctfe_mode: Option, - ecx: &'rt InterpCx<'tcx, M>, + ecx: &'rt mut InterpCx<'tcx, M>, + /// Whether provenance should be reset outside of pointers (emulating the effect of a typed + /// copy). + reset_provenance: bool, } impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> { @@ -314,11 +317,11 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> { fn read_immediate( &self, - op: &OpTy<'tcx, M::Provenance>, + val: &PlaceTy<'tcx, M::Provenance>, expected: ExpectedKind, ) -> InterpResult<'tcx, ImmTy<'tcx, M::Provenance>> { Ok(try_validation!( - self.ecx.read_immediate(op), + self.ecx.read_immediate(val), self.path, Ub(InvalidUninitBytes(None)) => Uninit { expected }, @@ -332,10 +335,38 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> { fn read_scalar( &self, - op: &OpTy<'tcx, M::Provenance>, + val: &PlaceTy<'tcx, M::Provenance>, expected: ExpectedKind, ) -> InterpResult<'tcx, Scalar> { - Ok(self.read_immediate(op, expected)?.to_scalar()) + Ok(self.read_immediate(val, expected)?.to_scalar()) + } + + fn deref_pointer( + &mut self, + val: &PlaceTy<'tcx, M::Provenance>, + expected: ExpectedKind, + ) -> InterpResult<'tcx, MPlaceTy<'tcx, M::Provenance>> { + // Not using `ecx.deref_pointer` since we want to use our `read_immediate` wrapper. + let imm = self.read_immediate(val, expected)?; + // Reset provenance: ensure slice tail metadata does not preserve provenance, + // and ensure all pointers do not preserve partial provenance. + if self.reset_provenance { + if matches!(imm.layout.abi, Abi::Scalar(..)) { + // A thin pointer. If it has provenance, we don't have to do anything. + // If it does not, ensure we clear the provenance in memory. + if matches!(imm.to_scalar(), Scalar::Int(..)) { + self.ecx.clear_provenance(val)?; + } + } else { + // A wide pointer. This means we have to worry both about the pointer itself and the + // metadata. We do the lazy thing and just write back the value we got. Just + // clearing provenance in a targeted manner would be more efficient, but unless this + // is a perf hotspot it's just not worth the effort. + self.ecx.write_immediate_no_validate(*imm, val)?; + } + } + // Now turn it into a place. + self.ecx.ref_to_mplace(&imm) } fn check_wide_ptr_meta( @@ -376,11 +407,10 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> { /// Check a reference or `Box`. fn check_safe_pointer( &mut self, - value: &OpTy<'tcx, M::Provenance>, + value: &PlaceTy<'tcx, M::Provenance>, ptr_kind: PointerKind, ) -> InterpResult<'tcx> { - // Not using `deref_pointer` since we want to use our `read_immediate` wrapper. - let place = self.ecx.ref_to_mplace(&self.read_immediate(value, ptr_kind.into())?)?; + let place = self.deref_pointer(value, ptr_kind.into())?; // Handle wide pointers. // Check metadata early, for better diagnostics if place.layout.is_unsized() { @@ -564,31 +594,37 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> { /// Note that not all of these have `FieldsShape::Primitive`, e.g. wide references. fn try_visit_primitive( &mut self, - value: &OpTy<'tcx, M::Provenance>, + value: &PlaceTy<'tcx, M::Provenance>, ) -> InterpResult<'tcx, bool> { // Go over all the primitive types let ty = value.layout.ty; match ty.kind() { ty::Bool => { - let value = self.read_scalar(value, ExpectedKind::Bool)?; + let scalar = self.read_scalar(value, ExpectedKind::Bool)?; try_validation!( - value.to_bool(), + scalar.to_bool(), self.path, Ub(InvalidBool(..)) => ValidationErrorKind::InvalidBool { - value: format!("{value:x}"), + value: format!("{scalar:x}"), } ); + if self.reset_provenance { + self.ecx.clear_provenance(value)?; + } Ok(true) } ty::Char => { - let value = self.read_scalar(value, ExpectedKind::Char)?; + let scalar = self.read_scalar(value, ExpectedKind::Char)?; try_validation!( - value.to_char(), + scalar.to_char(), self.path, Ub(InvalidChar(..)) => ValidationErrorKind::InvalidChar { - value: format!("{value:x}"), + value: format!("{scalar:x}"), } ); + if self.reset_provenance { + self.ecx.clear_provenance(value)?; + } Ok(true) } ty::Float(_) | ty::Int(_) | ty::Uint(_) => { @@ -602,11 +638,13 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> { ExpectedKind::Int }, )?; + if self.reset_provenance { + self.ecx.clear_provenance(value)?; + } Ok(true) } ty::RawPtr(..) => { - let place = - self.ecx.ref_to_mplace(&self.read_immediate(value, ExpectedKind::RawPtr)?)?; + let place = self.deref_pointer(value, ExpectedKind::RawPtr)?; if place.layout.is_unsized() { self.check_wide_ptr_meta(place.meta(), place.layout)?; } @@ -617,11 +655,11 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> { Ok(true) } ty::FnPtr(..) => { - let value = self.read_scalar(value, ExpectedKind::FnPtr)?; + let scalar = self.read_scalar(value, ExpectedKind::FnPtr)?; // If we check references recursively, also check that this points to a function. if let Some(_) = self.ref_tracking { - let ptr = value.to_pointer(self.ecx)?; + let ptr = scalar.to_pointer(self.ecx)?; let _fn = try_validation!( self.ecx.get_ptr_fn(ptr), self.path, @@ -631,10 +669,17 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> { // FIXME: Check if the signature matches } else { // Otherwise (for standalone Miri), we have to still check it to be non-null. - if self.ecx.scalar_may_be_null(value)? { + if self.ecx.scalar_may_be_null(scalar)? { throw_validation_failure!(self.path, NullFnPtr); } } + if self.reset_provenance { + // Make sure we do not preserve partial provenance. This matches the thin + // pointer handling in `deref_pointer`. + if matches!(scalar, Scalar::Int(..)) { + self.ecx.clear_provenance(value)?; + } + } Ok(true) } ty::Never => throw_validation_failure!(self.path, NeverVal), @@ -716,13 +761,18 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> { } } - fn in_mutable_memory(&self, op: &OpTy<'tcx, M::Provenance>) -> bool { - if let Some(mplace) = op.as_mplace_or_imm().left() { + fn in_mutable_memory(&self, val: &PlaceTy<'tcx, M::Provenance>) -> bool { + if let Some(mplace) = val.as_mplace_or_local().left() { if let Some(alloc_id) = mplace.ptr().provenance.and_then(|p| p.get_alloc_id()) { - return mutability(self.ecx, alloc_id).is_mut(); + mutability(self.ecx, alloc_id).is_mut() + } else { + // No memory at all. + false } + } else { + // A local variable -- definitely mutable. + true } - false } } @@ -774,7 +824,7 @@ fn mutability<'tcx>(ecx: &InterpCx<'tcx, impl Machine<'tcx>>, alloc_id: AllocId) } impl<'rt, 'tcx, M: Machine<'tcx>> ValueVisitor<'tcx, M> for ValidityVisitor<'rt, 'tcx, M> { - type V = OpTy<'tcx, M::Provenance>; + type V = PlaceTy<'tcx, M::Provenance>; #[inline(always)] fn ecx(&self) -> &InterpCx<'tcx, M> { @@ -783,11 +833,11 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValueVisitor<'tcx, M> for ValidityVisitor<'rt, fn read_discriminant( &mut self, - op: &OpTy<'tcx, M::Provenance>, + val: &PlaceTy<'tcx, M::Provenance>, ) -> InterpResult<'tcx, VariantIdx> { self.with_elem(PathElem::EnumTag, move |this| { Ok(try_validation!( - this.ecx.read_discriminant(op), + this.ecx.read_discriminant(val), this.path, Ub(InvalidTag(val)) => InvalidEnumTag { value: format!("{val:x}"), @@ -802,40 +852,40 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValueVisitor<'tcx, M> for ValidityVisitor<'rt, #[inline] fn visit_field( &mut self, - old_op: &OpTy<'tcx, M::Provenance>, + old_val: &PlaceTy<'tcx, M::Provenance>, field: usize, - new_op: &OpTy<'tcx, M::Provenance>, + new_val: &PlaceTy<'tcx, M::Provenance>, ) -> InterpResult<'tcx> { - let elem = self.aggregate_field_path_elem(old_op.layout, field); - self.with_elem(elem, move |this| this.visit_value(new_op)) + let elem = self.aggregate_field_path_elem(old_val.layout, field); + self.with_elem(elem, move |this| this.visit_value(new_val)) } #[inline] fn visit_variant( &mut self, - old_op: &OpTy<'tcx, M::Provenance>, + old_val: &PlaceTy<'tcx, M::Provenance>, variant_id: VariantIdx, - new_op: &OpTy<'tcx, M::Provenance>, + new_val: &PlaceTy<'tcx, M::Provenance>, ) -> InterpResult<'tcx> { - let name = match old_op.layout.ty.kind() { + let name = match old_val.layout.ty.kind() { ty::Adt(adt, _) => PathElem::Variant(adt.variant(variant_id).name), // Coroutines also have variants ty::Coroutine(..) => PathElem::CoroutineState(variant_id), - _ => bug!("Unexpected type with variant: {:?}", old_op.layout.ty), + _ => bug!("Unexpected type with variant: {:?}", old_val.layout.ty), }; - self.with_elem(name, move |this| this.visit_value(new_op)) + self.with_elem(name, move |this| this.visit_value(new_val)) } #[inline(always)] fn visit_union( &mut self, - op: &OpTy<'tcx, M::Provenance>, + val: &PlaceTy<'tcx, M::Provenance>, _fields: NonZero, ) -> InterpResult<'tcx> { // Special check for CTFE validation, preventing `UnsafeCell` inside unions in immutable memory. if self.ctfe_mode.is_some_and(|c| !c.allow_immutable_unsafe_cell()) { - if !op.layout.is_zst() && !op.layout.ty.is_freeze(*self.ecx.tcx, self.ecx.param_env) { - if !self.in_mutable_memory(op) { + if !val.layout.is_zst() && !val.layout.ty.is_freeze(*self.ecx.tcx, self.ecx.param_env) { + if !self.in_mutable_memory(val) { throw_validation_failure!(self.path, UnsafeCellInImmutable); } } @@ -847,39 +897,41 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValueVisitor<'tcx, M> for ValidityVisitor<'rt, fn visit_box( &mut self, _box_ty: Ty<'tcx>, - op: &OpTy<'tcx, M::Provenance>, + val: &PlaceTy<'tcx, M::Provenance>, ) -> InterpResult<'tcx> { - self.check_safe_pointer(op, PointerKind::Box)?; + self.check_safe_pointer(val, PointerKind::Box)?; Ok(()) } #[inline] - fn visit_value(&mut self, op: &OpTy<'tcx, M::Provenance>) -> InterpResult<'tcx> { - trace!("visit_value: {:?}, {:?}", *op, op.layout); + fn visit_value(&mut self, val: &PlaceTy<'tcx, M::Provenance>) -> InterpResult<'tcx> { + trace!("visit_value: {:?}, {:?}", *val, val.layout); // Check primitive types -- the leaves of our recursive descent. + // This is called even for enum discriminants (which are "fields" of their enum), + // so for integer-typed discriminants the provenance reset will happen here. // We assume that the Scalar validity range does not restrict these values // any further than `try_visit_primitive` does! - if self.try_visit_primitive(op)? { + if self.try_visit_primitive(val)? { return Ok(()); } // Special check preventing `UnsafeCell` in the inner part of constants if self.ctfe_mode.is_some_and(|c| !c.allow_immutable_unsafe_cell()) { - if !op.layout.is_zst() - && let Some(def) = op.layout.ty.ty_adt_def() + if !val.layout.is_zst() + && let Some(def) = val.layout.ty.ty_adt_def() && def.is_unsafe_cell() { - if !self.in_mutable_memory(op) { + if !self.in_mutable_memory(val) { throw_validation_failure!(self.path, UnsafeCellInImmutable); } } } // Recursively walk the value at its type. Apply optimizations for some large types. - match op.layout.ty.kind() { + match val.layout.ty.kind() { ty::Str => { - let mplace = op.assert_mem_place(); // strings are unsized and hence never immediate + let mplace = val.assert_mem_place(); // strings are unsized and hence never immediate let len = mplace.len(self.ecx)?; try_validation!( self.ecx.read_bytes_ptr_strip_provenance(mplace.ptr(), Size::from_bytes(len)), @@ -889,11 +941,10 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValueVisitor<'tcx, M> for ValidityVisitor<'rt, ); } ty::Array(tys, ..) | ty::Slice(tys) - // This optimization applies for types that can hold arbitrary bytes (such as - // integer and floating point types) or for structs or tuples with no fields. - // FIXME(wesleywiser) This logic could be extended further to arbitrary structs - // or tuples made up of integer/floating point types or inhabited ZSTs with no - // padding. + // This optimization applies for types that can hold arbitrary non-provenance bytes (such as + // integer and floating point types). + // FIXME(wesleywiser) This logic could be extended further to arbitrary structs or + // tuples made up of integer/floating point types or inhabited ZSTs with no padding. if matches!(tys.kind(), ty::Int(..) | ty::Uint(..) | ty::Float(..)) => { @@ -901,7 +952,7 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValueVisitor<'tcx, M> for ValidityVisitor<'rt, // Optimized handling for arrays of integer/float type. // This is the length of the array/slice. - let len = op.len(self.ecx)?; + let len = val.len(self.ecx)?; // This is the element type size. let layout = self.ecx.layout_of(*tys)?; // This is the size in bytes of the whole array. (This checks for overflow.) @@ -911,8 +962,9 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValueVisitor<'tcx, M> for ValidityVisitor<'rt, if size == Size::ZERO { return Ok(()); } - // Now that we definitely have a non-ZST array, we know it lives in memory. - let mplace = match op.as_mplace_or_imm() { + // Now that we definitely have a non-ZST array, we know it lives in memory -- except it may + // be an uninitialized local variable, those are also "immediate". + let mplace = match val.to_op(self.ecx)?.as_mplace_or_imm() { Left(mplace) => mplace, Right(imm) => match *imm { Immediate::Uninit => @@ -958,20 +1010,28 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValueVisitor<'tcx, M> for ValidityVisitor<'rt, } } } + + // Don't forget that these are all non-pointer types, and thus do not preserve + // provenance. + if self.reset_provenance { + // We can't share this with above as above, we might be looking at read-only memory. + let mut alloc = self.ecx.get_ptr_alloc_mut(mplace.ptr(), size)?.expect("we already excluded size 0"); + alloc.clear_provenance()?; + } } // Fast path for arrays and slices of ZSTs. We only need to check a single ZST element // of an array and not all of them, because there's only a single value of a specific // ZST type, so either validation fails for all elements or none. ty::Array(tys, ..) | ty::Slice(tys) if self.ecx.layout_of(*tys)?.is_zst() => { // Validate just the first element (if any). - if op.len(self.ecx)? > 0 { - self.visit_field(op, 0, &self.ecx.project_index(op, 0)?)?; + if val.len(self.ecx)? > 0 { + self.visit_field(val, 0, &self.ecx.project_index(val, 0)?)?; } } _ => { // default handler try_validation!( - self.walk_value(op), + self.walk_value(val), self.path, // It's not great to catch errors here, since we can't give a very good path, // but it's better than ICEing. @@ -992,15 +1052,15 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValueVisitor<'tcx, M> for ValidityVisitor<'rt, // FIXME: We could avoid some redundant checks here. For newtypes wrapping // scalars, we do the same check on every "level" (e.g., first we check // MyNewtype and then the scalar in there). - match op.layout.abi { + match val.layout.abi { Abi::Uninhabited => { - let ty = op.layout.ty; + let ty = val.layout.ty; throw_validation_failure!(self.path, UninhabitedVal { ty }); } Abi::Scalar(scalar_layout) => { if !scalar_layout.is_uninit_valid() { // There is something to check here. - let scalar = self.read_scalar(op, ExpectedKind::InitScalar)?; + let scalar = self.read_scalar(val, ExpectedKind::InitScalar)?; self.visit_scalar(scalar, scalar_layout)?; } } @@ -1010,7 +1070,7 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValueVisitor<'tcx, M> for ValidityVisitor<'rt, // the other must be init. if !a_layout.is_uninit_valid() && !b_layout.is_uninit_valid() { let (a, b) = - self.read_immediate(op, ExpectedKind::InitScalar)?.to_scalar_pair(); + self.read_immediate(val, ExpectedKind::InitScalar)?.to_scalar_pair(); self.visit_scalar(a, a_layout)?; self.visit_scalar(b, b_layout)?; } @@ -1031,19 +1091,20 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValueVisitor<'tcx, M> for ValidityVisitor<'rt, impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { fn validate_operand_internal( - &self, - op: &OpTy<'tcx, M::Provenance>, + &mut self, + val: &PlaceTy<'tcx, M::Provenance>, path: Vec, ref_tracking: Option<&mut RefTracking, Vec>>, ctfe_mode: Option, + reset_provenance: bool, ) -> InterpResult<'tcx> { - trace!("validate_operand_internal: {:?}, {:?}", *op, op.layout.ty); - - // Construct a visitor - let mut visitor = ValidityVisitor { path, ref_tracking, ctfe_mode, ecx: self }; + trace!("validate_operand_internal: {:?}, {:?}", *val, val.layout.ty); - // Run it. - match self.run_for_validation(|| visitor.visit_value(op)) { + // Run the visitor. + match self.run_for_validation(|ecx| { + let mut v = ValidityVisitor { path, ref_tracking, ctfe_mode, ecx, reset_provenance }; + v.visit_value(val) + }) { Ok(()) => Ok(()), // Pass through validation failures and "invalid program" issues. Err(err) @@ -1079,13 +1140,19 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { /// - no `UnsafeCell` or non-ZST `&mut`. #[inline(always)] pub(crate) fn const_validate_operand( - &self, - op: &OpTy<'tcx, M::Provenance>, + &mut self, + val: &PlaceTy<'tcx, M::Provenance>, path: Vec, ref_tracking: &mut RefTracking, Vec>, ctfe_mode: CtfeValidationMode, ) -> InterpResult<'tcx> { - self.validate_operand_internal(op, path, Some(ref_tracking), Some(ctfe_mode)) + self.validate_operand_internal( + val, + path, + Some(ref_tracking), + Some(ctfe_mode), + /*reset_provenance*/ false, + ) } /// This function checks the data at `op` to be runtime-valid. @@ -1093,21 +1160,35 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { /// It will error if the bits at the destination do not match the ones described by the layout. #[inline(always)] pub fn validate_operand( - &self, - op: &OpTy<'tcx, M::Provenance>, + &mut self, + val: &PlaceTy<'tcx, M::Provenance>, recursive: bool, + reset_provenance: bool, ) -> InterpResult<'tcx> { // Note that we *could* actually be in CTFE here with `-Zextra-const-ub-checks`, but it's // still correct to not use `ctfe_mode`: that mode is for validation of the final constant // value, it rules out things like `UnsafeCell` in awkward places. if !recursive { - return self.validate_operand_internal(op, vec![], None, None); + return self.validate_operand_internal(val, vec![], None, None, reset_provenance); } // Do a recursive check. let mut ref_tracking = RefTracking::empty(); - self.validate_operand_internal(op, vec![], Some(&mut ref_tracking), None)?; + self.validate_operand_internal( + val, + vec![], + Some(&mut ref_tracking), + None, + reset_provenance, + )?; while let Some((mplace, path)) = ref_tracking.todo.pop() { - self.validate_operand_internal(&mplace.into(), path, Some(&mut ref_tracking), None)?; + // Things behind reference do *not* have the provenance reset. + self.validate_operand_internal( + &mplace.into(), + path, + Some(&mut ref_tracking), + None, + /*reset_provenance*/ false, + )?; } Ok(()) } diff --git a/compiler/rustc_const_eval/src/util/check_validity_requirement.rs b/compiler/rustc_const_eval/src/util/check_validity_requirement.rs index cbd1fdeea2aa3..5e424190d07dd 100644 --- a/compiler/rustc_const_eval/src/util/check_validity_requirement.rs +++ b/compiler/rustc_const_eval/src/util/check_validity_requirement.rs @@ -4,7 +4,7 @@ use rustc_middle::ty::{ParamEnvAnd, Ty, TyCtxt}; use rustc_target::abi::{Abi, FieldsShape, Scalar, Variants}; use crate::const_eval::{CanAccessMutGlobal, CheckAlignment, CompileTimeMachine}; -use crate::interpret::{InterpCx, MemoryKind, OpTy}; +use crate::interpret::{InterpCx, MemoryKind}; /// Determines if this type permits "raw" initialization by just transmuting some memory into an /// instance of `T`. @@ -61,13 +61,17 @@ fn might_permit_raw_init_strict<'tcx>( .expect("failed to write bytes for zero valid check"); } - let ot: OpTy<'_, _> = allocated.into(); - // Assume that if it failed, it's a validation failure. // This does *not* actually check that references are dereferenceable, but since all types that // require dereferenceability also require non-null, we don't actually get any false negatives // due to this. - Ok(cx.validate_operand(&ot, /*recursive*/ false).is_ok()) + Ok(cx + .validate_operand( + &allocated.into(), + /*recursive*/ false, + /*reset_provenance*/ false, + ) + .is_ok()) } /// Implements the 'lax' (default) version of the `might_permit_raw_init` checks; see that function for diff --git a/compiler/rustc_middle/src/mir/interpret/allocation.rs b/compiler/rustc_middle/src/mir/interpret/allocation.rs index 5fb8af576ae93..cd56d0edc0585 100644 --- a/compiler/rustc_middle/src/mir/interpret/allocation.rs +++ b/compiler/rustc_middle/src/mir/interpret/allocation.rs @@ -644,6 +644,12 @@ impl Allocation return Ok(()); } + /// Remove all provenance in the given memory range. + pub fn clear_provenance(&mut self, cx: &impl HasDataLayout, range: AllocRange) -> AllocResult { + self.provenance.clear(range, cx)?; + return Ok(()); + } + /// Applies a previously prepared provenance copy. /// The affected range, as defined in the parameters to `provenance().prepare_copy` is expected /// to be clear of provenance. diff --git a/compiler/rustc_middle/src/mir/interpret/value.rs b/compiler/rustc_middle/src/mir/interpret/value.rs index 84c17b39a623e..989f03d3d1399 100644 --- a/compiler/rustc_middle/src/mir/interpret/value.rs +++ b/compiler/rustc_middle/src/mir/interpret/value.rs @@ -307,6 +307,13 @@ impl<'tcx, Prov: Provenance> Scalar { } } + pub fn clear_provenance(&mut self) -> InterpResult<'tcx> { + if matches!(self, Scalar::Ptr(..)) { + *self = self.to_scalar_int()?.into(); + } + Ok(()) + } + #[inline(always)] pub fn to_scalar_int(self) -> InterpResult<'tcx, ScalarInt> { self.try_to_scalar_int().map_err(|_| err_unsup!(ReadPointerAsInt(None)).into()) diff --git a/src/tools/miri/src/concurrency/data_race.rs b/src/tools/miri/src/concurrency/data_race.rs index 6fd207c92b937..b604fd868a02a 100644 --- a/src/tools/miri/src/concurrency/data_race.rs +++ b/src/tools/miri/src/concurrency/data_race.rs @@ -637,7 +637,7 @@ pub trait EvalContextExt<'tcx>: MiriInterpCxExt<'tcx> { // The program didn't actually do a read, so suppress the memory access hooks. // This is also a very special exception where we just ignore an error -- if this read // was UB e.g. because the memory is uninitialized, we don't want to know! - let old_val = this.run_for_validation(|| this.read_scalar(dest)).ok(); + let old_val = this.run_for_validation(|this| this.read_scalar(dest)).ok(); this.allow_data_races_mut(move |this| this.write_scalar(val, dest))?; this.validate_atomic_store(dest, atomic)?; this.buffered_atomic_write(val, dest, atomic, old_val) diff --git a/src/tools/miri/src/intrinsics/mod.rs b/src/tools/miri/src/intrinsics/mod.rs index 18b22827bdb15..0ab1b9dfb61e9 100644 --- a/src/tools/miri/src/intrinsics/mod.rs +++ b/src/tools/miri/src/intrinsics/mod.rs @@ -152,8 +152,10 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // ``` // Would not be considered UB, or the other way around (`is_val_statically_known(0)`). "is_val_statically_known" => { - let [arg] = check_arg_count(args)?; - this.validate_operand(arg, /*recursive*/ false)?; + let [_arg] = check_arg_count(args)?; + // FIXME: should we check for validity here? It's tricky because we do not have a + // place. Codegen does not seem to set any attributes like `noundef` for intrinsic + // calls, so we don't *have* to do anything. let branch: bool = this.machine.rng.get_mut().gen(); this.write_scalar(Scalar::from_bool(branch), dest)?; } diff --git a/src/tools/miri/tests/fail/provenance/int_copy_looses_provenance0.rs b/src/tools/miri/tests/fail/provenance/int_copy_looses_provenance0.rs new file mode 100644 index 0000000000000..fd0773ed916b7 --- /dev/null +++ b/src/tools/miri/tests/fail/provenance/int_copy_looses_provenance0.rs @@ -0,0 +1,10 @@ +use std::mem; + +// Doing a copy at integer type should lose provenance. +// This tests the unoptimized base case. +fn main() { + let ptrs = [(&42, true)]; + let ints: [(usize, bool); 1] = unsafe { mem::transmute(ptrs) }; + let ptr = (&raw const ints[0].0).cast::<&i32>(); + let _val = unsafe { *ptr.read() }; //~ERROR: dangling +} diff --git a/src/tools/miri/tests/fail/provenance/int_copy_looses_provenance0.stderr b/src/tools/miri/tests/fail/provenance/int_copy_looses_provenance0.stderr new file mode 100644 index 0000000000000..fc012af3ad877 --- /dev/null +++ b/src/tools/miri/tests/fail/provenance/int_copy_looses_provenance0.stderr @@ -0,0 +1,15 @@ +error: Undefined Behavior: constructing invalid value: encountered a dangling reference ($HEX[noalloc] has no provenance) + --> $DIR/int_copy_looses_provenance0.rs:LL:CC + | +LL | let _val = unsafe { *ptr.read() }; + | ^^^^^^^^^^ constructing invalid value: encountered a dangling reference ($HEX[noalloc] has no provenance) + | + = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior + = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information + = note: BACKTRACE: + = note: inside `main` at $DIR/int_copy_looses_provenance0.rs:LL:CC + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to 1 previous error + diff --git a/src/tools/miri/tests/fail/provenance/int_copy_looses_provenance1.rs b/src/tools/miri/tests/fail/provenance/int_copy_looses_provenance1.rs new file mode 100644 index 0000000000000..ce64dcc1a07c4 --- /dev/null +++ b/src/tools/miri/tests/fail/provenance/int_copy_looses_provenance1.rs @@ -0,0 +1,10 @@ +use std::mem; + +// Doing a copy at integer type should lose provenance. +// This tests the optimized-array case of integer copies. +fn main() { + let ptrs = [&42]; + let ints: [usize; 1] = unsafe { mem::transmute(ptrs) }; + let ptr = (&raw const ints[0]).cast::<&i32>(); + let _val = unsafe { *ptr.read() }; //~ERROR: dangling +} diff --git a/src/tools/miri/tests/fail/provenance/int_copy_looses_provenance1.stderr b/src/tools/miri/tests/fail/provenance/int_copy_looses_provenance1.stderr new file mode 100644 index 0000000000000..375262655d0cf --- /dev/null +++ b/src/tools/miri/tests/fail/provenance/int_copy_looses_provenance1.stderr @@ -0,0 +1,15 @@ +error: Undefined Behavior: constructing invalid value: encountered a dangling reference ($HEX[noalloc] has no provenance) + --> $DIR/int_copy_looses_provenance1.rs:LL:CC + | +LL | let _val = unsafe { *ptr.read() }; + | ^^^^^^^^^^ constructing invalid value: encountered a dangling reference ($HEX[noalloc] has no provenance) + | + = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior + = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information + = note: BACKTRACE: + = note: inside `main` at $DIR/int_copy_looses_provenance1.rs:LL:CC + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to 1 previous error + diff --git a/src/tools/miri/tests/fail/provenance/int_copy_looses_provenance2.rs b/src/tools/miri/tests/fail/provenance/int_copy_looses_provenance2.rs new file mode 100644 index 0000000000000..e8966c53d7059 --- /dev/null +++ b/src/tools/miri/tests/fail/provenance/int_copy_looses_provenance2.rs @@ -0,0 +1,12 @@ +use std::mem; + +// Doing a copy at integer type should lose provenance. +// This tests the case where provenacne is hiding in the metadata of a pointer. +fn main() { + let ptrs = [(&42, &42)]; + // Typed copy at wide pointer type (with integer-typed metadata). + let ints: [*const [usize]; 1] = unsafe { mem::transmute(ptrs) }; + // Get a pointer to the metadata field. + let ptr = (&raw const ints[0]).wrapping_byte_add(mem::size_of::<*const ()>()).cast::<&i32>(); + let _val = unsafe { *ptr.read() }; //~ERROR: dangling +} diff --git a/src/tools/miri/tests/fail/provenance/int_copy_looses_provenance2.stderr b/src/tools/miri/tests/fail/provenance/int_copy_looses_provenance2.stderr new file mode 100644 index 0000000000000..8402c7b5e130f --- /dev/null +++ b/src/tools/miri/tests/fail/provenance/int_copy_looses_provenance2.stderr @@ -0,0 +1,15 @@ +error: Undefined Behavior: constructing invalid value: encountered a dangling reference ($HEX[noalloc] has no provenance) + --> $DIR/int_copy_looses_provenance2.rs:LL:CC + | +LL | let _val = unsafe { *ptr.read() }; + | ^^^^^^^^^^ constructing invalid value: encountered a dangling reference ($HEX[noalloc] has no provenance) + | + = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior + = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information + = note: BACKTRACE: + = note: inside `main` at $DIR/int_copy_looses_provenance2.rs:LL:CC + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to 1 previous error + diff --git a/src/tools/miri/tests/fail/provenance/int_copy_looses_provenance3.rs b/src/tools/miri/tests/fail/provenance/int_copy_looses_provenance3.rs new file mode 100644 index 0000000000000..48a48ce4587ee --- /dev/null +++ b/src/tools/miri/tests/fail/provenance/int_copy_looses_provenance3.rs @@ -0,0 +1,29 @@ +#![feature(strict_provenance)] +use std::mem; + +#[repr(C, usize)] +#[allow(unused)] +enum E { + Var1(usize), + Var2(usize), +} + +// Doing a copy at integer type should lose provenance. +// This tests the case where provenacne is hiding in the discriminant of an enum. +fn main() { + assert_eq!(mem::size_of::(), 2*mem::size_of::()); + + // We want to store provenance in the enum discriminant, but the value still needs to + // be valid atfor the type. So we split provenance and data. + let ptr = &42; + let ptr = ptr as *const i32; + let ptrs = [(ptr.with_addr(0), ptr)]; + // Typed copy at the enum type. + let ints: [E; 1] = unsafe { mem::transmute(ptrs) }; + // Read the discriminant. + let discr = unsafe { (&raw const ints[0]).cast::<*const i32>().read() }; + // Take the provenance from there, together with the original address. + let ptr = discr.with_addr(ptr.addr()); + // There should be no provenance is `discr`, so this should be UB. + let _val = unsafe { *ptr }; //~ERROR: dangling +} diff --git a/src/tools/miri/tests/fail/provenance/int_copy_looses_provenance3.stderr b/src/tools/miri/tests/fail/provenance/int_copy_looses_provenance3.stderr new file mode 100644 index 0000000000000..b50e23da96a7e --- /dev/null +++ b/src/tools/miri/tests/fail/provenance/int_copy_looses_provenance3.stderr @@ -0,0 +1,15 @@ +error: Undefined Behavior: memory access failed: expected a pointer to 4 bytes of memory, but got $HEX[noalloc] which is a dangling pointer (it has no provenance) + --> $DIR/int_copy_looses_provenance3.rs:LL:CC + | +LL | let _val = unsafe { *ptr }; + | ^^^^ memory access failed: expected a pointer to 4 bytes of memory, but got $HEX[noalloc] which is a dangling pointer (it has no provenance) + | + = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior + = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information + = note: BACKTRACE: + = note: inside `main` at $DIR/int_copy_looses_provenance3.rs:LL:CC + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to 1 previous error + diff --git a/src/tools/miri/tests/fail/provenance/ptr_copy_loses_partial_provenance0.rs b/src/tools/miri/tests/fail/provenance/ptr_copy_loses_partial_provenance0.rs new file mode 100644 index 0000000000000..0c6666b424e55 --- /dev/null +++ b/src/tools/miri/tests/fail/provenance/ptr_copy_loses_partial_provenance0.rs @@ -0,0 +1,17 @@ +fn main() { + unsafe { + let mut bytes = [1u8; 16]; + let bytes = bytes.as_mut_ptr(); + + // Put a pointer in the middle. + bytes.add(4).cast::<&i32>().write_unaligned(&42); + // Typed copy of the entire thing as two pointers, but not perfectly + // overlapping with the pointer we have in there. + let copy = bytes.cast::<[*const (); 2]>().read_unaligned(); + let copy_bytes = copy.as_ptr().cast::(); + // Now go to the middle of the copy and get the pointer back out. + let ptr = copy_bytes.add(4).cast::<*const i32>().read_unaligned(); + // Dereferencing this should fail as the copy has removed the provenance. + let _val = *ptr; //~ERROR: dangling + } +} diff --git a/src/tools/miri/tests/fail/provenance/ptr_copy_loses_partial_provenance0.stderr b/src/tools/miri/tests/fail/provenance/ptr_copy_loses_partial_provenance0.stderr new file mode 100644 index 0000000000000..ed38572a5f398 --- /dev/null +++ b/src/tools/miri/tests/fail/provenance/ptr_copy_loses_partial_provenance0.stderr @@ -0,0 +1,15 @@ +error: Undefined Behavior: memory access failed: expected a pointer to 4 bytes of memory, but got $HEX[noalloc] which is a dangling pointer (it has no provenance) + --> $DIR/ptr_copy_loses_partial_provenance0.rs:LL:CC + | +LL | let _val = *ptr; + | ^^^^ memory access failed: expected a pointer to 4 bytes of memory, but got $HEX[noalloc] which is a dangling pointer (it has no provenance) + | + = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior + = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information + = note: BACKTRACE: + = note: inside `main` at $DIR/ptr_copy_loses_partial_provenance0.rs:LL:CC + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to 1 previous error + diff --git a/src/tools/miri/tests/fail/provenance/ptr_copy_loses_partial_provenance1.rs b/src/tools/miri/tests/fail/provenance/ptr_copy_loses_partial_provenance1.rs new file mode 100644 index 0000000000000..30d826413d2f9 --- /dev/null +++ b/src/tools/miri/tests/fail/provenance/ptr_copy_loses_partial_provenance1.rs @@ -0,0 +1,17 @@ +fn main() { + unsafe { + let mut bytes = [1u8; 16]; + let bytes = bytes.as_mut_ptr(); + + // Put a pointer in the middle. + bytes.add(4).cast::<&i32>().write_unaligned(&42); + // Typed copy of the entire thing as two *function* pointers, but not perfectly + // overlapping with the pointer we have in there. + let copy = bytes.cast::<[fn(); 2]>().read_unaligned(); + let copy_bytes = copy.as_ptr().cast::(); + // Now go to the middle of the copy and get the pointer back out. + let ptr = copy_bytes.add(4).cast::<*const i32>().read_unaligned(); + // Dereferencing this should fail as the copy has removed the provenance. + let _val = *ptr; //~ERROR: dangling + } +} diff --git a/src/tools/miri/tests/fail/provenance/ptr_copy_loses_partial_provenance1.stderr b/src/tools/miri/tests/fail/provenance/ptr_copy_loses_partial_provenance1.stderr new file mode 100644 index 0000000000000..2e11687175afe --- /dev/null +++ b/src/tools/miri/tests/fail/provenance/ptr_copy_loses_partial_provenance1.stderr @@ -0,0 +1,15 @@ +error: Undefined Behavior: memory access failed: expected a pointer to 4 bytes of memory, but got $HEX[noalloc] which is a dangling pointer (it has no provenance) + --> $DIR/ptr_copy_loses_partial_provenance1.rs:LL:CC + | +LL | let _val = *ptr; + | ^^^^ memory access failed: expected a pointer to 4 bytes of memory, but got $HEX[noalloc] which is a dangling pointer (it has no provenance) + | + = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior + = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information + = note: BACKTRACE: + = note: inside `main` at $DIR/ptr_copy_loses_partial_provenance1.rs:LL:CC + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to 1 previous error + diff --git a/src/tools/miri/tests/pass/provenance.rs b/src/tools/miri/tests/pass/provenance.rs index 9e8a9651b3d96..2e4d240cc48a1 100644 --- a/src/tools/miri/tests/pass/provenance.rs +++ b/src/tools/miri/tests/pass/provenance.rs @@ -12,6 +12,7 @@ fn main() { bytewise_custom_memcpy(); bytewise_custom_memcpy_chunked(); int_load_strip_provenance(); + maybe_uninit_preserves_partial_provenance(); } /// Some basic smoke tests for provenance. @@ -145,3 +146,24 @@ fn int_load_strip_provenance() { let ints: [usize; 1] = unsafe { mem::transmute(ptrs) }; assert_eq!(ptrs[0] as *const _ as usize, ints[0]); } + +fn maybe_uninit_preserves_partial_provenance() { + // This is the same test as ptr_copy_loses_partial_provenance.rs, but using MaybeUninit and thus + // properly preserving partial provenance. + unsafe { + let mut bytes = [1u8; 16]; + let bytes = bytes.as_mut_ptr(); + + // Put a pointer in the middle. + bytes.add(4).cast::<&i32>().write_unaligned(&42); + // Copy the entire thing as two pointers but not perfectly + // overlapping with the pointer we have in there. + let copy = bytes.cast::<[mem::MaybeUninit<*const ()>; 2]>().read_unaligned(); + let copy_bytes = copy.as_ptr().cast::(); + // Now go to the middle of the copy and get the pointer back out. + let ptr = copy_bytes.add(4).cast::<*const i32>().read_unaligned(); + // And deref this to ensure we get the right value. + let val = *ptr; + assert_eq!(val, 42); + } +} From 8cd982caa1221c54dbdb036083d659c619024d45 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Thu, 29 Aug 2024 19:24:31 +0200 Subject: [PATCH 0680/2194] interpret: reset padding during validation --- .../src/const_eval/machine.rs | 27 +- .../rustc_const_eval/src/interpret/machine.rs | 12 +- .../rustc_const_eval/src/interpret/memory.rs | 11 +- .../rustc_const_eval/src/interpret/mod.rs | 2 +- .../rustc_const_eval/src/interpret/place.rs | 17 +- .../src/interpret/validity.rs | 287 ++++++++++++++++-- .../rustc_const_eval/src/interpret/visitor.rs | 12 + .../src/util/check_validity_requirement.rs | 2 +- src/tools/miri/src/machine.rs | 13 + .../ptr_copy_loses_partial_provenance0.rs | 11 +- .../ptr_copy_loses_partial_provenance1.rs | 11 +- .../miri/tests/fail/uninit/padding-enum.rs | 23 ++ .../tests/fail/uninit/padding-enum.stderr | 15 + .../miri/tests/fail/uninit/padding-pair.rs | 25 ++ .../tests/fail/uninit/padding-pair.stderr | 15 + .../fail/uninit/padding-struct-in-union.rs | 32 ++ .../uninit/padding-struct-in-union.stderr | 15 + .../miri/tests/fail/uninit/padding-struct.rs | 11 + .../tests/fail/uninit/padding-struct.stderr | 15 + .../miri/tests/fail/uninit/padding-union.rs | 14 + .../tests/fail/uninit/padding-union.stderr | 15 + .../{ => uninit}/transmute-pair-uninit.rs | 11 +- .../{ => uninit}/transmute-pair-uninit.stderr | 0 src/tools/miri/tests/pass/enums.rs | 38 +++ 24 files changed, 584 insertions(+), 50 deletions(-) create mode 100644 src/tools/miri/tests/fail/uninit/padding-enum.rs create mode 100644 src/tools/miri/tests/fail/uninit/padding-enum.stderr create mode 100644 src/tools/miri/tests/fail/uninit/padding-pair.rs create mode 100644 src/tools/miri/tests/fail/uninit/padding-pair.stderr create mode 100644 src/tools/miri/tests/fail/uninit/padding-struct-in-union.rs create mode 100644 src/tools/miri/tests/fail/uninit/padding-struct-in-union.stderr create mode 100644 src/tools/miri/tests/fail/uninit/padding-struct.rs create mode 100644 src/tools/miri/tests/fail/uninit/padding-struct.stderr create mode 100644 src/tools/miri/tests/fail/uninit/padding-union.rs create mode 100644 src/tools/miri/tests/fail/uninit/padding-union.stderr rename src/tools/miri/tests/fail/{ => uninit}/transmute-pair-uninit.rs (61%) rename src/tools/miri/tests/fail/{ => uninit}/transmute-pair-uninit.stderr (100%) diff --git a/compiler/rustc_const_eval/src/const_eval/machine.rs b/compiler/rustc_const_eval/src/const_eval/machine.rs index 9c1fef095f552..7405ca09342da 100644 --- a/compiler/rustc_const_eval/src/const_eval/machine.rs +++ b/compiler/rustc_const_eval/src/const_eval/machine.rs @@ -1,16 +1,16 @@ -use std::borrow::Borrow; +use std::borrow::{Borrow, Cow}; use std::fmt; use std::hash::Hash; use std::ops::ControlFlow; use rustc_ast::Mutability; -use rustc_data_structures::fx::{FxIndexMap, IndexEntry}; +use rustc_data_structures::fx::{FxHashMap, FxIndexMap, IndexEntry}; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::{self as hir, LangItem, CRATE_HIR_ID}; use rustc_middle::mir::AssertMessage; use rustc_middle::query::TyCtxtAt; use rustc_middle::ty::layout::{FnAbiOf, TyAndLayout}; -use rustc_middle::ty::{self, TyCtxt}; +use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_middle::{bug, mir}; use rustc_span::symbol::{sym, Symbol}; use rustc_span::Span; @@ -24,8 +24,8 @@ use crate::fluent_generated as fluent; use crate::interpret::{ self, compile_time_machine, err_ub, throw_exhaust, throw_inval, throw_ub_custom, throw_unsup, throw_unsup_format, AllocId, AllocRange, ConstAllocation, CtfeProvenance, FnArg, Frame, - GlobalAlloc, ImmTy, InterpCx, InterpResult, MPlaceTy, OpTy, Pointer, PointerArithmetic, Scalar, - StackPopCleanup, + GlobalAlloc, ImmTy, InterpCx, InterpResult, MPlaceTy, OpTy, Pointer, PointerArithmetic, + RangeSet, Scalar, StackPopCleanup, }; /// When hitting this many interpreted terminators we emit a deny by default lint @@ -65,6 +65,9 @@ pub struct CompileTimeMachine<'tcx> { /// storing the result in the given `AllocId`. /// Used to prevent reads from a static's base allocation, as that may allow for self-initialization loops. pub(crate) static_root_ids: Option<(AllocId, LocalDefId)>, + + /// A cache of "data range" computations for unions (i.e., the offsets of non-padding bytes). + union_data_ranges: FxHashMap, RangeSet>, } #[derive(Copy, Clone)] @@ -99,6 +102,7 @@ impl<'tcx> CompileTimeMachine<'tcx> { can_access_mut_global, check_alignment, static_root_ids: None, + union_data_ranges: FxHashMap::default(), } } } @@ -766,6 +770,19 @@ impl<'tcx> interpret::Machine<'tcx> for CompileTimeMachine<'tcx> { } Ok(()) } + + fn cached_union_data_range<'e>( + ecx: &'e mut InterpCx<'tcx, Self>, + ty: Ty<'tcx>, + compute_range: impl FnOnce() -> RangeSet, + ) -> Cow<'e, RangeSet> { + if ecx.tcx.sess.opts.unstable_opts.extra_const_ub_checks { + Cow::Borrowed(ecx.machine.union_data_ranges.entry(ty).or_insert_with(compute_range)) + } else { + // Don't bother caching, we're only doing one validation at the end anyway. + Cow::Owned(compute_range()) + } + } } // Please do not add any code below the above `Machine` trait impl. I (oli-obk) plan more cleanups diff --git a/compiler/rustc_const_eval/src/interpret/machine.rs b/compiler/rustc_const_eval/src/interpret/machine.rs index 6cfd7be48e624..8cab3c34eedfb 100644 --- a/compiler/rustc_const_eval/src/interpret/machine.rs +++ b/compiler/rustc_const_eval/src/interpret/machine.rs @@ -10,6 +10,7 @@ use rustc_apfloat::{Float, FloatConvert}; use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece}; use rustc_middle::query::TyCtxtAt; use rustc_middle::ty::layout::TyAndLayout; +use rustc_middle::ty::Ty; use rustc_middle::{mir, ty}; use rustc_span::def_id::DefId; use rustc_span::Span; @@ -19,7 +20,7 @@ use rustc_target::spec::abi::Abi as CallAbi; use super::{ throw_unsup, throw_unsup_format, AllocBytes, AllocId, AllocKind, AllocRange, Allocation, ConstAllocation, CtfeProvenance, FnArg, Frame, ImmTy, InterpCx, InterpResult, MPlaceTy, - MemoryKind, Misalignment, OpTy, PlaceTy, Pointer, Provenance, CTFE_ALLOC_SALT, + MemoryKind, Misalignment, OpTy, PlaceTy, Pointer, Provenance, RangeSet, CTFE_ALLOC_SALT, }; /// Data returned by [`Machine::after_stack_pop`], and consumed by @@ -578,6 +579,15 @@ pub trait Machine<'tcx>: Sized { ecx: &InterpCx<'tcx, Self>, instance: Option>, ) -> usize; + + fn cached_union_data_range<'e>( + _ecx: &'e mut InterpCx<'tcx, Self>, + _ty: Ty<'tcx>, + compute_range: impl FnOnce() -> RangeSet, + ) -> Cow<'e, RangeSet> { + // Default to no caching. + Cow::Owned(compute_range()) + } } /// A lot of the flexibility above is just needed for `Miri`, but all "compile-time" machines diff --git a/compiler/rustc_const_eval/src/interpret/memory.rs b/compiler/rustc_const_eval/src/interpret/memory.rs index 53a9cd0b9ad6d..d87588496c0bd 100644 --- a/compiler/rustc_const_eval/src/interpret/memory.rs +++ b/compiler/rustc_const_eval/src/interpret/memory.rs @@ -1136,8 +1136,17 @@ impl<'tcx, 'a, Prov: Provenance, Extra, Bytes: AllocBytes> self.write_scalar(alloc_range(offset, self.tcx.data_layout().pointer_size), val) } + /// Mark the given sub-range (relative to this allocation reference) as uninitialized. + pub fn write_uninit(&mut self, range: AllocRange) -> InterpResult<'tcx> { + let range = self.range.subrange(range); + Ok(self + .alloc + .write_uninit(&self.tcx, range) + .map_err(|e| e.to_interp_error(self.alloc_id))?) + } + /// Mark the entire referenced range as uninitialized - pub fn write_uninit(&mut self) -> InterpResult<'tcx> { + pub fn write_uninit_full(&mut self) -> InterpResult<'tcx> { Ok(self .alloc .write_uninit(&self.tcx, self.range) diff --git a/compiler/rustc_const_eval/src/interpret/mod.rs b/compiler/rustc_const_eval/src/interpret/mod.rs index c1e46cc3a15b4..561d681f804a1 100644 --- a/compiler/rustc_const_eval/src/interpret/mod.rs +++ b/compiler/rustc_const_eval/src/interpret/mod.rs @@ -39,5 +39,5 @@ use self::place::{MemPlace, Place}; pub use self::projection::{OffsetMode, Projectable}; pub use self::stack::{Frame, FrameInfo, LocalState, StackPopCleanup, StackPopInfo}; pub(crate) use self::util::create_static_alloc; -pub use self::validity::{CtfeValidationMode, RefTracking}; +pub use self::validity::{CtfeValidationMode, RangeSet, RefTracking}; pub use self::visitor::ValueVisitor; diff --git a/compiler/rustc_const_eval/src/interpret/place.rs b/compiler/rustc_const_eval/src/interpret/place.rs index e2aef0519186e..3b14142da02ed 100644 --- a/compiler/rustc_const_eval/src/interpret/place.rs +++ b/compiler/rustc_const_eval/src/interpret/place.rs @@ -604,10 +604,11 @@ where if M::enforce_validity(self, dest.layout()) { // Data got changed, better make sure it matches the type! + // Also needed to reset padding. self.validate_operand( &dest.to_place(), M::enforce_validity_recursively(self, dest.layout()), - /*reset_provenance*/ true, + /*reset_provenance_and_padding*/ true, )?; } @@ -703,9 +704,11 @@ where // fields do not match the `ScalarPair` components. alloc.write_scalar(alloc_range(Size::ZERO, a_val.size()), a_val)?; - alloc.write_scalar(alloc_range(b_offset, b_val.size()), b_val) + alloc.write_scalar(alloc_range(b_offset, b_val.size()), b_val)?; + // We don't have to reset padding here, `write_immediate` will anyway do a validation run. + Ok(()) } - Immediate::Uninit => alloc.write_uninit(), + Immediate::Uninit => alloc.write_uninit_full(), } } @@ -722,7 +725,7 @@ where // Zero-sized access return Ok(()); }; - alloc.write_uninit()?; + alloc.write_uninit_full()?; } } Ok(()) @@ -814,17 +817,17 @@ where // Given that there were two typed copies, we have to ensure this is valid at both types, // and we have to ensure this loses provenance and padding according to both types. // But if the types are identical, we only do one pass. - if src.layout().ty != dest.layout().ty { + if allow_transmute && src.layout().ty != dest.layout().ty { self.validate_operand( &dest.transmute(src.layout(), self)?, M::enforce_validity_recursively(self, src.layout()), - /*reset_provenance*/ true, + /*reset_provenance_and_padding*/ true, )?; } self.validate_operand( &dest, M::enforce_validity_recursively(self, dest.layout()), - /*reset_provenance*/ true, + /*reset_provenance_and_padding*/ true, )?; } diff --git a/compiler/rustc_const_eval/src/interpret/validity.rs b/compiler/rustc_const_eval/src/interpret/validity.rs index 953831a55e5ed..806ebb9dfed4d 100644 --- a/compiler/rustc_const_eval/src/interpret/validity.rs +++ b/compiler/rustc_const_eval/src/interpret/validity.rs @@ -4,6 +4,7 @@ //! That's useful because it means other passes (e.g. promotion) can rely on `const`s //! to be const-safe. +use std::borrow::Cow; use std::fmt::Write; use std::hash::Hash; use std::num::NonZero; @@ -16,14 +17,14 @@ use rustc_hir as hir; use rustc_middle::bug; use rustc_middle::mir::interpret::ValidationErrorKind::{self, *}; use rustc_middle::mir::interpret::{ - ExpectedKind, InterpError, InvalidMetaKind, Misalignment, PointerKind, Provenance, + alloc_range, ExpectedKind, InterpError, InvalidMetaKind, Misalignment, PointerKind, Provenance, UnsupportedOpInfo, ValidationErrorInfo, }; -use rustc_middle::ty::layout::{LayoutOf, TyAndLayout}; -use rustc_middle::ty::{self, Ty}; +use rustc_middle::ty::layout::{LayoutCx, LayoutOf, TyAndLayout}; +use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_span::symbol::{sym, Symbol}; use rustc_target::abi::{ - Abi, FieldIdx, Scalar as ScalarAbi, Size, VariantIdx, Variants, WrappingRange, + Abi, FieldIdx, FieldsShape, Scalar as ScalarAbi, Size, VariantIdx, Variants, WrappingRange, }; use tracing::trace; @@ -125,6 +126,7 @@ pub enum PathElem { EnumTag, CoroutineTag, DynDowncast, + Vtable, } /// Extra things to check for during validation of CTFE results. @@ -204,11 +206,58 @@ fn write_path(out: &mut String, path: &[PathElem]) { // not the root. Deref => write!(out, "."), DynDowncast => write!(out, "."), + Vtable => write!(out, "."), } .unwrap() } } +/// Represents a set of `Size` values as a sorted list of ranges. +// These are (offset, length) pairs, and they are sorted and mutually disjoint, +// and never adjacent (i.e. there's always a gap between two of them). +#[derive(Debug, Clone)] +pub struct RangeSet(Vec<(Size, Size)>); + +impl RangeSet { + fn add_range(&mut self, offset: Size, size: Size) { + let v = &mut self.0; + // We scan for a partition point where the left partition is all the elements that end + // strictly before we start. Those are elements that are too "low" to merge with us. + let idx = + v.partition_point(|&(other_offset, other_size)| other_offset + other_size < offset); + // Now we want to either merge with the first element of the second partition, or insert ourselves before that. + if let Some(&(other_offset, other_size)) = v.get(idx) + && offset + size >= other_offset + { + // Their end is >= our start (otherwise it would not be in the 2nd partition) and + // our end is >= their start. This means we can merge the ranges. + let new_start = other_offset.min(offset); + let mut new_end = (other_offset + other_size).max(offset + size); + // We grew to the right, so merge with overlapping/adjacent elements. + // (We also may have grown to the left, but that can never make us adjacent with + // anything there since we selected the first such candidate via `partition_point`.) + let mut scan_right = 1; + while let Some(&(next_offset, next_size)) = v.get(idx + scan_right) + && new_end >= next_offset + { + // Increase our size to absorb the next element. + new_end = new_end.max(next_offset + next_size); + // Look at the next element. + scan_right += 1; + } + // Update the element we grew. + v[idx] = (new_start, new_end - new_start); + // Remove the elements we absorbed (if any). + if scan_right > 1 { + drop(v.drain((idx + 1)..(idx + scan_right))); + } + } else { + // Insert new element. + v.insert(idx, (offset, size)); + } + } +} + struct ValidityVisitor<'rt, 'tcx, M: Machine<'tcx>> { /// The `path` may be pushed to, but the part that is present when a function /// starts must not be changed! `visit_fields` and `visit_array` rely on @@ -220,7 +269,14 @@ struct ValidityVisitor<'rt, 'tcx, M: Machine<'tcx>> { ecx: &'rt mut InterpCx<'tcx, M>, /// Whether provenance should be reset outside of pointers (emulating the effect of a typed /// copy). - reset_provenance: bool, + reset_provenance_and_padding: bool, + /// This tracks which byte ranges in this value contain data; the remaining bytes are padding. + /// The ideal representation here would be pointer-length pairs, but to keep things more compact + /// we only store a (range) set of offsets -- the base pointer is the same throughout the entire + /// visit, after all. + /// If this is `Some`, then `reset_provenance_and_padding` must be true (but not vice versa: + /// we might not track data vs padding bytes if the operand isn't stored in memory anyway). + data_bytes: Option, } impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> { @@ -290,8 +346,14 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> { // arrays/slices ty::Array(..) | ty::Slice(..) => PathElem::ArrayElem(field), + // dyn* vtables + ty::Dynamic(_, _, ty::DynKind::DynStar) if field == 1 => PathElem::Vtable, + // dyn traits - ty::Dynamic(..) => PathElem::DynDowncast, + ty::Dynamic(..) => { + assert_eq!(field, 0); + PathElem::DynDowncast + } // nothing else has an aggregate layout _ => bug!("aggregate_field_path_elem: got non-aggregate type {:?}", layout.ty), @@ -350,7 +412,7 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> { let imm = self.read_immediate(val, expected)?; // Reset provenance: ensure slice tail metadata does not preserve provenance, // and ensure all pointers do not preserve partial provenance. - if self.reset_provenance { + if self.reset_provenance_and_padding { if matches!(imm.layout.abi, Abi::Scalar(..)) { // A thin pointer. If it has provenance, we don't have to do anything. // If it does not, ensure we clear the provenance in memory. @@ -364,6 +426,8 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> { // is a perf hotspot it's just not worth the effort. self.ecx.write_immediate_no_validate(*imm, val)?; } + // The entire thing is data, not padding. + self.add_data_range_place(val); } // Now turn it into a place. self.ecx.ref_to_mplace(&imm) @@ -608,8 +672,9 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> { value: format!("{scalar:x}"), } ); - if self.reset_provenance { + if self.reset_provenance_and_padding { self.ecx.clear_provenance(value)?; + self.add_data_range_place(value); } Ok(true) } @@ -622,8 +687,9 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> { value: format!("{scalar:x}"), } ); - if self.reset_provenance { + if self.reset_provenance_and_padding { self.ecx.clear_provenance(value)?; + self.add_data_range_place(value); } Ok(true) } @@ -638,8 +704,9 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> { ExpectedKind::Int }, )?; - if self.reset_provenance { + if self.reset_provenance_and_padding { self.ecx.clear_provenance(value)?; + self.add_data_range_place(value); } Ok(true) } @@ -673,12 +740,13 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> { throw_validation_failure!(self.path, NullFnPtr); } } - if self.reset_provenance { + if self.reset_provenance_and_padding { // Make sure we do not preserve partial provenance. This matches the thin // pointer handling in `deref_pointer`. if matches!(scalar, Scalar::Int(..)) { self.ecx.clear_provenance(value)?; } + self.add_data_range_place(value); } Ok(true) } @@ -774,6 +842,155 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> { true } } + + /// Add the given pointer-length pair to the "data" range of this visit. + fn add_data_range(&mut self, ptr: Pointer>, size: Size) { + if let Some(data_bytes) = self.data_bytes.as_mut() { + // We only have to store the offset, the rest is the same for all pointers here. + let (_prov, offset) = ptr.into_parts(); + // Add this. + data_bytes.add_range(offset, size); + }; + } + + /// Add the entire given place to the "data" range of this visit. + fn add_data_range_place(&mut self, place: &PlaceTy<'tcx, M::Provenance>) { + // Only sized places can be added this way. + debug_assert!(place.layout.abi.is_sized()); + if let Some(data_bytes) = self.data_bytes.as_mut() { + let offset = Self::data_range_offset(self.ecx, place); + data_bytes.add_range(offset, place.layout.size); + } + } + + /// Convert a place into the offset it starts at, for the purpose of data_range tracking. + /// Must only be called if `data_bytes` is `Some(_)`. + fn data_range_offset(ecx: &InterpCx<'tcx, M>, place: &PlaceTy<'tcx, M::Provenance>) -> Size { + // The presence of `data_bytes` implies that our place is in memory. + let ptr = ecx + .place_to_op(place) + .expect("place must be in memory") + .as_mplace_or_imm() + .expect_left("place must be in memory") + .ptr(); + let (_prov, offset) = ptr.into_parts(); + offset + } + + fn reset_padding(&mut self, place: &PlaceTy<'tcx, M::Provenance>) -> InterpResult<'tcx> { + let Some(data_bytes) = self.data_bytes.as_mut() else { return Ok(()) }; + // Our value must be in memory, otherwise we would not have set up `data_bytes`. + let mplace = self.ecx.force_allocation(place)?; + // Determine starting offset and size. + let (_prov, start_offset) = mplace.ptr().into_parts(); + let (size, _align) = self + .ecx + .size_and_align_of_mplace(&mplace)? + .unwrap_or((mplace.layout.size, mplace.layout.align.abi)); + // If there is no padding at all, we can skip the rest: check for + // a single data range covering the entire value. + if data_bytes.0 == &[(start_offset, size)] { + return Ok(()); + } + // Get a handle for the allocation. Do this only once, to avoid looking up the same + // allocation over and over again. (Though to be fair, iterating the value already does + // exactly that.) + let Some(mut alloc) = self.ecx.get_ptr_alloc_mut(mplace.ptr(), size)? else { + // A ZST, no padding to clear. + return Ok(()); + }; + // Add a "finalizer" data range at the end, so that the iteration below finds all gaps + // between ranges. + data_bytes.0.push((start_offset + size, Size::ZERO)); + // Iterate, and reset gaps. + let mut padding_cleared_until = start_offset; + for &(offset, size) in data_bytes.0.iter() { + assert!( + offset >= padding_cleared_until, + "reset_padding on {}: previous field ended at offset {}, next field starts at {} (and has a size of {} bytes)", + mplace.layout.ty, + (padding_cleared_until - start_offset).bytes(), + (offset - start_offset).bytes(), + size.bytes(), + ); + if offset > padding_cleared_until { + // We found padding. Adjust the range to be relative to `alloc`, and make it uninit. + let padding_start = padding_cleared_until - start_offset; + let padding_size = offset - padding_cleared_until; + let range = alloc_range(padding_start, padding_size); + trace!("reset_padding on {}: resetting padding range {range:?}", mplace.layout.ty); + alloc.write_uninit(range)?; + } + padding_cleared_until = offset + size; + } + assert!(padding_cleared_until == start_offset + size); + Ok(()) + } + + /// Computes the data range of this union type: + /// which bytes are inside a field (i.e., not padding.) + fn union_data_range<'e>( + ecx: &'e mut InterpCx<'tcx, M>, + layout: TyAndLayout<'tcx>, + ) -> Cow<'e, RangeSet> { + assert!(layout.ty.is_union()); + assert!(layout.abi.is_sized(), "there are no unsized unions"); + let layout_cx = LayoutCx { tcx: *ecx.tcx, param_env: ecx.param_env }; + return M::cached_union_data_range(ecx, layout.ty, || { + let mut out = RangeSet(Vec::new()); + union_data_range_(&layout_cx, layout, Size::ZERO, &mut out); + out + }); + + /// Helper for recursive traversal: add data ranges of the given type to `out`. + fn union_data_range_<'tcx>( + cx: &LayoutCx<'tcx, TyCtxt<'tcx>>, + layout: TyAndLayout<'tcx>, + base_offset: Size, + out: &mut RangeSet, + ) { + // Just recursively add all the fields of everything to the output. + match &layout.fields { + FieldsShape::Primitive => { + out.add_range(base_offset, layout.size); + } + &FieldsShape::Union(fields) => { + // Currently, all fields start at offset 0. + for field in 0..fields.get() { + let field = layout.field(cx, field); + union_data_range_(cx, field, base_offset, out); + } + } + &FieldsShape::Array { stride, count } => { + let elem = layout.field(cx, 0); + for idx in 0..count { + // This repeats the same computation for every array elements... but the alternative + // is to allocate temporary storage for a dedicated `out` set for the array element, + // and replicating that N times. Is that better? + union_data_range_(cx, elem, base_offset + idx * stride, out); + } + } + FieldsShape::Arbitrary { offsets, .. } => { + for (field, &offset) in offsets.iter_enumerated() { + let field = layout.field(cx, field.as_usize()); + union_data_range_(cx, field, base_offset + offset, out); + } + } + } + // Don't forget potential other variants. + match &layout.variants { + Variants::Single { .. } => { + // Fully handled above. + } + Variants::Multiple { variants, .. } => { + for variant in variants.indices() { + let variant = layout.for_variant(cx, variant); + union_data_range_(cx, variant, base_offset, out); + } + } + } + } + } } /// Returns whether the allocation is mutable, and whether it's actually a static. @@ -890,6 +1107,16 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValueVisitor<'tcx, M> for ValidityVisitor<'rt, } } } + if self.reset_provenance_and_padding + && let Some(data_bytes) = self.data_bytes.as_mut() + { + let base_offset = Self::data_range_offset(self.ecx, val); + // Determine and add data range for this union. + let union_data_range = Self::union_data_range(self.ecx, val.layout); + for &(offset, size) in union_data_range.0.iter() { + data_bytes.add_range(base_offset + offset, size); + } + } Ok(()) } @@ -1013,10 +1240,12 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValueVisitor<'tcx, M> for ValidityVisitor<'rt, // Don't forget that these are all non-pointer types, and thus do not preserve // provenance. - if self.reset_provenance { + if self.reset_provenance_and_padding { // We can't share this with above as above, we might be looking at read-only memory. let mut alloc = self.ecx.get_ptr_alloc_mut(mplace.ptr(), size)?.expect("we already excluded size 0"); alloc.clear_provenance()?; + // Also, mark this as containing data, not padding. + self.add_data_range(mplace.ptr(), size); } } // Fast path for arrays and slices of ZSTs. We only need to check a single ZST element @@ -1096,14 +1325,28 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { path: Vec, ref_tracking: Option<&mut RefTracking, Vec>>, ctfe_mode: Option, - reset_provenance: bool, + reset_provenance_and_padding: bool, ) -> InterpResult<'tcx> { trace!("validate_operand_internal: {:?}, {:?}", *val, val.layout.ty); // Run the visitor. match self.run_for_validation(|ecx| { - let mut v = ValidityVisitor { path, ref_tracking, ctfe_mode, ecx, reset_provenance }; - v.visit_value(val) + let reset_padding = reset_provenance_and_padding && { + // Check if `val` is actually stored in memory. If not, padding is not even + // represented and we need not reset it. + ecx.place_to_op(val)?.as_mplace_or_imm().is_left() + }; + let mut v = ValidityVisitor { + path, + ref_tracking, + ctfe_mode, + ecx, + reset_provenance_and_padding, + data_bytes: reset_padding.then_some(RangeSet(Vec::new())), + }; + v.visit_value(val)?; + v.reset_padding(val)?; + InterpResult::Ok(()) }) { Ok(()) => Ok(()), // Pass through validation failures and "invalid program" issues. @@ -1163,13 +1406,19 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { &mut self, val: &PlaceTy<'tcx, M::Provenance>, recursive: bool, - reset_provenance: bool, + reset_provenance_and_padding: bool, ) -> InterpResult<'tcx> { // Note that we *could* actually be in CTFE here with `-Zextra-const-ub-checks`, but it's // still correct to not use `ctfe_mode`: that mode is for validation of the final constant // value, it rules out things like `UnsafeCell` in awkward places. if !recursive { - return self.validate_operand_internal(val, vec![], None, None, reset_provenance); + return self.validate_operand_internal( + val, + vec![], + None, + None, + reset_provenance_and_padding, + ); } // Do a recursive check. let mut ref_tracking = RefTracking::empty(); @@ -1178,7 +1427,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { vec![], Some(&mut ref_tracking), None, - reset_provenance, + reset_provenance_and_padding, )?; while let Some((mplace, path)) = ref_tracking.todo.pop() { // Things behind reference do *not* have the provenance reset. @@ -1187,7 +1436,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { path, Some(&mut ref_tracking), None, - /*reset_provenance*/ false, + /*reset_provenance_and_padding*/ false, )?; } Ok(()) diff --git a/compiler/rustc_const_eval/src/interpret/visitor.rs b/compiler/rustc_const_eval/src/interpret/visitor.rs index 08b39fe8751be..d8af67bd0e705 100644 --- a/compiler/rustc_const_eval/src/interpret/visitor.rs +++ b/compiler/rustc_const_eval/src/interpret/visitor.rs @@ -5,6 +5,7 @@ use std::num::NonZero; use rustc_index::IndexVec; use rustc_middle::mir::interpret::InterpResult; +use rustc_middle::ty::layout::LayoutOf; use rustc_middle::ty::{self, Ty}; use rustc_target::abi::{FieldIdx, FieldsShape, VariantIdx, Variants}; use tracing::trace; @@ -105,6 +106,17 @@ pub trait ValueVisitor<'tcx, M: Machine<'tcx>>: Sized { // DynStar types. Very different from a dyn type (but strangely part of the // same variant in `TyKind`): These are pairs where the 2nd component is the // vtable, and the first component is the data (which must be ptr-sized). + + // First make sure the vtable can be read at its type. + // The type of this vtable is fake, it claims to be a reference to some actual memory but that isn't true. + // So we transmute it to a raw pointer. + let raw_ptr_ty = Ty::new_mut_ptr(*self.ecx().tcx, self.ecx().tcx.types.unit); + let raw_ptr_ty = self.ecx().layout_of(raw_ptr_ty)?; + let vtable_field = + self.ecx().project_field(v, 1)?.transmute(raw_ptr_ty, self.ecx())?; + self.visit_field(v, 1, &vtable_field)?; + + // Then unpack the first field, and continue. let data = self.ecx().unpack_dyn_star(v, data)?; return self.visit_field(v, 0, &data); } diff --git a/compiler/rustc_const_eval/src/util/check_validity_requirement.rs b/compiler/rustc_const_eval/src/util/check_validity_requirement.rs index 5e424190d07dd..26fd59bc6ef77 100644 --- a/compiler/rustc_const_eval/src/util/check_validity_requirement.rs +++ b/compiler/rustc_const_eval/src/util/check_validity_requirement.rs @@ -69,7 +69,7 @@ fn might_permit_raw_init_strict<'tcx>( .validate_operand( &allocated.into(), /*recursive*/ false, - /*reset_provenance*/ false, + /*reset_provenance_and_padding*/ false, ) .is_ok()) } diff --git a/src/tools/miri/src/machine.rs b/src/tools/miri/src/machine.rs index 66c6966d1a6c3..d1267cd68668a 100644 --- a/src/tools/miri/src/machine.rs +++ b/src/tools/miri/src/machine.rs @@ -572,6 +572,9 @@ pub struct MiriMachine<'tcx> { /// Invariant: the promised alignment will never be less than the native alignment of the /// allocation. pub(crate) symbolic_alignment: RefCell>, + + /// A cache of "data range" computations for unions (i.e., the offsets of non-padding bytes). + union_data_ranges: FxHashMap, RangeSet>, } impl<'tcx> MiriMachine<'tcx> { @@ -714,6 +717,7 @@ impl<'tcx> MiriMachine<'tcx> { allocation_spans: RefCell::new(FxHashMap::default()), const_cache: RefCell::new(FxHashMap::default()), symbolic_alignment: RefCell::new(FxHashMap::default()), + union_data_ranges: FxHashMap::default(), } } @@ -826,6 +830,7 @@ impl VisitProvenance for MiriMachine<'_> { allocation_spans: _, const_cache: _, symbolic_alignment: _, + union_data_ranges: _, } = self; threads.visit_provenance(visit); @@ -1627,4 +1632,12 @@ impl<'tcx> Machine<'tcx> for MiriMachine<'tcx> { ecx.machine.rng.borrow_mut().gen::() % ADDRS_PER_ANON_GLOBAL } } + + fn cached_union_data_range<'e>( + ecx: &'e mut InterpCx<'tcx, Self>, + ty: Ty<'tcx>, + compute_range: impl FnOnce() -> RangeSet, + ) -> Cow<'e, RangeSet> { + Cow::Borrowed(ecx.machine.union_data_ranges.entry(ty).or_insert_with(compute_range)) + } } diff --git a/src/tools/miri/tests/fail/provenance/ptr_copy_loses_partial_provenance0.rs b/src/tools/miri/tests/fail/provenance/ptr_copy_loses_partial_provenance0.rs index 0c6666b424e55..ff94f2263c517 100644 --- a/src/tools/miri/tests/fail/provenance/ptr_copy_loses_partial_provenance0.rs +++ b/src/tools/miri/tests/fail/provenance/ptr_copy_loses_partial_provenance0.rs @@ -1,16 +1,17 @@ fn main() { - unsafe { - let mut bytes = [1u8; 16]; - let bytes = bytes.as_mut_ptr(); + let half_ptr = std::mem::size_of::<*const ()>() / 2; + let mut bytes = [1u8; 16]; + let bytes = bytes.as_mut_ptr(); + unsafe { // Put a pointer in the middle. - bytes.add(4).cast::<&i32>().write_unaligned(&42); + bytes.add(half_ptr).cast::<&i32>().write_unaligned(&42); // Typed copy of the entire thing as two pointers, but not perfectly // overlapping with the pointer we have in there. let copy = bytes.cast::<[*const (); 2]>().read_unaligned(); let copy_bytes = copy.as_ptr().cast::(); // Now go to the middle of the copy and get the pointer back out. - let ptr = copy_bytes.add(4).cast::<*const i32>().read_unaligned(); + let ptr = copy_bytes.add(half_ptr).cast::<*const i32>().read_unaligned(); // Dereferencing this should fail as the copy has removed the provenance. let _val = *ptr; //~ERROR: dangling } diff --git a/src/tools/miri/tests/fail/provenance/ptr_copy_loses_partial_provenance1.rs b/src/tools/miri/tests/fail/provenance/ptr_copy_loses_partial_provenance1.rs index 30d826413d2f9..d0e3dac7792b0 100644 --- a/src/tools/miri/tests/fail/provenance/ptr_copy_loses_partial_provenance1.rs +++ b/src/tools/miri/tests/fail/provenance/ptr_copy_loses_partial_provenance1.rs @@ -1,16 +1,17 @@ fn main() { - unsafe { - let mut bytes = [1u8; 16]; - let bytes = bytes.as_mut_ptr(); + let half_ptr = std::mem::size_of::<*const ()>() / 2; + let mut bytes = [1u8; 16]; + let bytes = bytes.as_mut_ptr(); + unsafe { // Put a pointer in the middle. - bytes.add(4).cast::<&i32>().write_unaligned(&42); + bytes.add(half_ptr).cast::<&i32>().write_unaligned(&42); // Typed copy of the entire thing as two *function* pointers, but not perfectly // overlapping with the pointer we have in there. let copy = bytes.cast::<[fn(); 2]>().read_unaligned(); let copy_bytes = copy.as_ptr().cast::(); // Now go to the middle of the copy and get the pointer back out. - let ptr = copy_bytes.add(4).cast::<*const i32>().read_unaligned(); + let ptr = copy_bytes.add(half_ptr).cast::<*const i32>().read_unaligned(); // Dereferencing this should fail as the copy has removed the provenance. let _val = *ptr; //~ERROR: dangling } diff --git a/src/tools/miri/tests/fail/uninit/padding-enum.rs b/src/tools/miri/tests/fail/uninit/padding-enum.rs new file mode 100644 index 0000000000000..0ab9be275815d --- /dev/null +++ b/src/tools/miri/tests/fail/uninit/padding-enum.rs @@ -0,0 +1,23 @@ +use std::mem; + +// We have three fields to avoid the ScalarPair optimization. +#[allow(unused)] +enum E { + None, + Some(&'static (), &'static (), usize), +} + +fn main() { unsafe { + let mut p: mem::MaybeUninit = mem::MaybeUninit::zeroed(); + // The copy when `E` is returned from `transmute` should destroy padding + // (even when we use `write_unaligned`, which under the hood uses an untyped copy). + p.as_mut_ptr().write_unaligned(mem::transmute((0usize, 0usize, 0usize))); + // This is a `None`, so everything but the discriminant is padding. + assert!(matches!(*p.as_ptr(), E::None)); + + // Turns out the discriminant is (currently) stored + // in the 2nd pointer, so the first half is padding. + let c = &p as *const _ as *const u8; + let _val = *c.add(0); // Get the padding byte. + //~^ERROR: uninitialized +} } diff --git a/src/tools/miri/tests/fail/uninit/padding-enum.stderr b/src/tools/miri/tests/fail/uninit/padding-enum.stderr new file mode 100644 index 0000000000000..a507a5d49bc2c --- /dev/null +++ b/src/tools/miri/tests/fail/uninit/padding-enum.stderr @@ -0,0 +1,15 @@ +error: Undefined Behavior: using uninitialized data, but this operation requires initialized memory + --> $DIR/padding-enum.rs:LL:CC + | +LL | let _val = *c.add(0); // Get the padding byte. + | ^^^^^^^^^ using uninitialized data, but this operation requires initialized memory + | + = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior + = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information + = note: BACKTRACE: + = note: inside `main` at $DIR/padding-enum.rs:LL:CC + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to 1 previous error + diff --git a/src/tools/miri/tests/fail/uninit/padding-pair.rs b/src/tools/miri/tests/fail/uninit/padding-pair.rs new file mode 100644 index 0000000000000..c8c00b3c65a06 --- /dev/null +++ b/src/tools/miri/tests/fail/uninit/padding-pair.rs @@ -0,0 +1,25 @@ +#![feature(core_intrinsics)] + +use std::mem::{self, MaybeUninit}; + +fn main() { + // This constructs a `(usize, bool)` pair: 9 bytes initialized, the rest not. + // Ensure that these 9 bytes are indeed initialized, and the rest is indeed not. + // This should be the case even if we write into previously initialized storage. + let mut x: MaybeUninit> = MaybeUninit::zeroed(); + let z = std::intrinsics::add_with_overflow(0usize, 0usize); + unsafe { x.as_mut_ptr().cast::<(usize, bool)>().write(z) }; + // Now read this bytewise. There should be (`ptr_size + 1`) def bytes followed by + // (`ptr_size - 1`) undef bytes (the padding after the bool) in there. + let z: *const u8 = &x as *const _ as *const _; + let first_undef = mem::size_of::() as isize + 1; + for i in 0..first_undef { + let byte = unsafe { *z.offset(i) }; + assert_eq!(byte, 0); + } + let v = unsafe { *z.offset(first_undef) }; + //~^ ERROR: uninitialized + if v == 0 { + println!("it is zero"); + } +} diff --git a/src/tools/miri/tests/fail/uninit/padding-pair.stderr b/src/tools/miri/tests/fail/uninit/padding-pair.stderr new file mode 100644 index 0000000000000..d35934d83d58f --- /dev/null +++ b/src/tools/miri/tests/fail/uninit/padding-pair.stderr @@ -0,0 +1,15 @@ +error: Undefined Behavior: using uninitialized data, but this operation requires initialized memory + --> $DIR/padding-pair.rs:LL:CC + | +LL | let v = unsafe { *z.offset(first_undef) }; + | ^^^^^^^^^^^^^^^^^^^^^^ using uninitialized data, but this operation requires initialized memory + | + = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior + = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information + = note: BACKTRACE: + = note: inside `main` at $DIR/padding-pair.rs:LL:CC + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to 1 previous error + diff --git a/src/tools/miri/tests/fail/uninit/padding-struct-in-union.rs b/src/tools/miri/tests/fail/uninit/padding-struct-in-union.rs new file mode 100644 index 0000000000000..132b85828362d --- /dev/null +++ b/src/tools/miri/tests/fail/uninit/padding-struct-in-union.rs @@ -0,0 +1,32 @@ +#[repr(C)] +#[derive(Debug, Copy, Clone)] +struct Foo { + val16: u16, + // Padding bytes go here! + val32: u32, +} + +#[repr(C)] +#[derive(Debug, Copy, Clone)] +struct Bar { + bytes: [u8; 8], +} + +#[repr(C)] +union FooBar { + foo: Foo, + bar: Bar, +} + +pub fn main() { + // Initialize as u8 to ensure padding bytes are zeroed. + let mut foobar = FooBar { bar: Bar { bytes: [0u8; 8] } }; + // Reading either field is ok. + let _val = unsafe { (foobar.foo, foobar.bar) }; + // Does this assignment copy the uninitialized padding bytes + // over the initialized padding bytes? miri doesn't seem to think so. + foobar.foo = Foo { val16: 1, val32: 2 }; + // This resets the padding to uninit. + let _val = unsafe { (foobar.foo, foobar.bar) }; + //~^ ERROR: uninitialized +} diff --git a/src/tools/miri/tests/fail/uninit/padding-struct-in-union.stderr b/src/tools/miri/tests/fail/uninit/padding-struct-in-union.stderr new file mode 100644 index 0000000000000..e122249af16e5 --- /dev/null +++ b/src/tools/miri/tests/fail/uninit/padding-struct-in-union.stderr @@ -0,0 +1,15 @@ +error: Undefined Behavior: constructing invalid value at .bytes[2]: encountered uninitialized memory, but expected an integer + --> $DIR/padding-struct-in-union.rs:LL:CC + | +LL | let _val = unsafe { (foobar.foo, foobar.bar) }; + | ^^^^^^^^^^ constructing invalid value at .bytes[2]: encountered uninitialized memory, but expected an integer + | + = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior + = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information + = note: BACKTRACE: + = note: inside `main` at $DIR/padding-struct-in-union.rs:LL:CC + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to 1 previous error + diff --git a/src/tools/miri/tests/fail/uninit/padding-struct.rs b/src/tools/miri/tests/fail/uninit/padding-struct.rs new file mode 100644 index 0000000000000..dd3be50343902 --- /dev/null +++ b/src/tools/miri/tests/fail/uninit/padding-struct.rs @@ -0,0 +1,11 @@ +use std::mem; + +#[repr(C)] +struct Pair(u8, u16); + +fn main() { unsafe { + let p: Pair = mem::transmute(0u32); // The copy when `Pair` is returned from `transmute` should destroy padding. + let c = &p as *const _ as *const u8; + let _val = *c.add(1); // Get the padding byte. + //~^ERROR: uninitialized +} } diff --git a/src/tools/miri/tests/fail/uninit/padding-struct.stderr b/src/tools/miri/tests/fail/uninit/padding-struct.stderr new file mode 100644 index 0000000000000..8dc40a482ac52 --- /dev/null +++ b/src/tools/miri/tests/fail/uninit/padding-struct.stderr @@ -0,0 +1,15 @@ +error: Undefined Behavior: using uninitialized data, but this operation requires initialized memory + --> $DIR/padding-struct.rs:LL:CC + | +LL | let _val = *c.add(1); // Get the padding byte. + | ^^^^^^^^^ using uninitialized data, but this operation requires initialized memory + | + = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior + = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information + = note: BACKTRACE: + = note: inside `main` at $DIR/padding-struct.rs:LL:CC + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to 1 previous error + diff --git a/src/tools/miri/tests/fail/uninit/padding-union.rs b/src/tools/miri/tests/fail/uninit/padding-union.rs new file mode 100644 index 0000000000000..2e9e0a40d6c68 --- /dev/null +++ b/src/tools/miri/tests/fail/uninit/padding-union.rs @@ -0,0 +1,14 @@ +use std::mem; + +#[allow(unused)] +#[repr(C)] +union U { + field: (u8, u16), +} + +fn main() { unsafe { + let p: U = mem::transmute(0u32); // The copy when `U` is returned from `transmute` should destroy padding. + let c = &p as *const _ as *const [u8; 4]; + let _val = *c; // Read the entire thing, definitely contains the padding byte. + //~^ERROR: uninitialized +} } diff --git a/src/tools/miri/tests/fail/uninit/padding-union.stderr b/src/tools/miri/tests/fail/uninit/padding-union.stderr new file mode 100644 index 0000000000000..04002da4f195c --- /dev/null +++ b/src/tools/miri/tests/fail/uninit/padding-union.stderr @@ -0,0 +1,15 @@ +error: Undefined Behavior: constructing invalid value at [1]: encountered uninitialized memory, but expected an integer + --> $DIR/padding-union.rs:LL:CC + | +LL | let _val = *c; // Read the entire thing, definitely contains the padding byte. + | ^^ constructing invalid value at [1]: encountered uninitialized memory, but expected an integer + | + = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior + = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information + = note: BACKTRACE: + = note: inside `main` at $DIR/padding-union.rs:LL:CC + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to 1 previous error + diff --git a/src/tools/miri/tests/fail/transmute-pair-uninit.rs b/src/tools/miri/tests/fail/uninit/transmute-pair-uninit.rs similarity index 61% rename from src/tools/miri/tests/fail/transmute-pair-uninit.rs rename to src/tools/miri/tests/fail/uninit/transmute-pair-uninit.rs index bc95f3cb7ad3a..0ba5520a54468 100644 --- a/src/tools/miri/tests/fail/transmute-pair-uninit.rs +++ b/src/tools/miri/tests/fail/uninit/transmute-pair-uninit.rs @@ -1,16 +1,17 @@ #![feature(core_intrinsics)] -use std::mem; +use std::mem::{self, MaybeUninit}; fn main() { - let x: Option> = unsafe { + // This constructs a `(usize, bool)` pair: 9 bytes initialized, the rest not. + // Ensure that these 9 bytes are indeed initialized, and the rest is indeed not. + let x: MaybeUninit> = unsafe { let z = std::intrinsics::add_with_overflow(0usize, 0usize); - std::mem::transmute::<(usize, bool), Option>>(z) + std::mem::transmute::<(usize, bool), MaybeUninit>>(z) }; - let y = &x; // Now read this bytewise. There should be (`ptr_size + 1`) def bytes followed by // (`ptr_size - 1`) undef bytes (the padding after the bool) in there. - let z: *const u8 = y as *const _ as *const _; + let z: *const u8 = &x as *const _ as *const _; let first_undef = mem::size_of::() as isize + 1; for i in 0..first_undef { let byte = unsafe { *z.offset(i) }; diff --git a/src/tools/miri/tests/fail/transmute-pair-uninit.stderr b/src/tools/miri/tests/fail/uninit/transmute-pair-uninit.stderr similarity index 100% rename from src/tools/miri/tests/fail/transmute-pair-uninit.stderr rename to src/tools/miri/tests/fail/uninit/transmute-pair-uninit.stderr diff --git a/src/tools/miri/tests/pass/enums.rs b/src/tools/miri/tests/pass/enums.rs index 1dafef025e958..9fc61f07c047f 100644 --- a/src/tools/miri/tests/pass/enums.rs +++ b/src/tools/miri/tests/pass/enums.rs @@ -132,6 +132,43 @@ fn overaligned_casts() { assert_eq!(aligned as u8, 0); } +// This hits a corner case in the logic for clearing padding on typed copies. +fn padding_clear_corner_case() { + #[allow(unused)] + #[derive(Copy, Clone)] + #[repr(C)] + pub struct Decoded { + /// The scaled mantissa. + pub mant: u64, + /// The lower error range. + pub minus: u64, + /// The upper error range. + pub plus: u64, + /// The shared exponent in base 2. + pub exp: i16, + /// True when the error range is inclusive. + /// + /// In IEEE 754, this is true when the original mantissa was even. + pub inclusive: bool, + } + + #[allow(unused)] + #[derive(Copy, Clone)] + pub enum FullDecoded { + /// Not-a-number. + Nan, + /// Infinities, either positive or negative. + Infinite, + /// Zero, either positive or negative. + Zero, + /// Finite numbers with further decoded fields. + Finite(Decoded), + } + + let val = FullDecoded::Finite(Decoded { mant: 0, minus: 0, plus: 0, exp: 0, inclusive: false }); + let _val2 = val; // trigger typed copy +} + fn main() { test(MyEnum::MyEmptyVariant); test(MyEnum::MyNewtypeVariant(42)); @@ -141,4 +178,5 @@ fn main() { discriminant_overflow(); more_discriminant_overflow(); overaligned_casts(); + padding_clear_corner_case(); } From a2410425b3ee0fa75533ada2ea1bb7ebfb2bc84d Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Thu, 5 Sep 2024 07:44:03 +0200 Subject: [PATCH 0681/2194] clarify comments and names in check_validity_requirement --- .../src/util/check_validity_requirement.rs | 20 ++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/compiler/rustc_const_eval/src/util/check_validity_requirement.rs b/compiler/rustc_const_eval/src/util/check_validity_requirement.rs index 26fd59bc6ef77..611a8e1a88497 100644 --- a/compiler/rustc_const_eval/src/util/check_validity_requirement.rs +++ b/compiler/rustc_const_eval/src/util/check_validity_requirement.rs @@ -32,15 +32,15 @@ pub fn check_validity_requirement<'tcx>( let layout_cx = LayoutCx { tcx, param_env: param_env_and_ty.param_env }; if kind == ValidityRequirement::Uninit || tcx.sess.opts.unstable_opts.strict_init_checks { - might_permit_raw_init_strict(layout, &layout_cx, kind) + check_validity_requirement_strict(layout, &layout_cx, kind) } else { - might_permit_raw_init_lax(layout, &layout_cx, kind) + check_validity_requirement_lax(layout, &layout_cx, kind) } } -/// Implements the 'strict' version of the `might_permit_raw_init` checks; see that function for -/// details. -fn might_permit_raw_init_strict<'tcx>( +/// Implements the 'strict' version of the [`check_validity_requirement`] checks; see that function +/// for details. +fn check_validity_requirement_strict<'tcx>( ty: TyAndLayout<'tcx>, cx: &LayoutCx<'tcx, TyCtxt<'tcx>>, kind: ValidityRequirement, @@ -65,6 +65,8 @@ fn might_permit_raw_init_strict<'tcx>( // This does *not* actually check that references are dereferenceable, but since all types that // require dereferenceability also require non-null, we don't actually get any false negatives // due to this. + // The value we are validating is temporary and discarded at the end of this function, so + // there is no point in reseting provenance and padding. Ok(cx .validate_operand( &allocated.into(), @@ -74,9 +76,9 @@ fn might_permit_raw_init_strict<'tcx>( .is_ok()) } -/// Implements the 'lax' (default) version of the `might_permit_raw_init` checks; see that function for -/// details. -fn might_permit_raw_init_lax<'tcx>( +/// Implements the 'lax' (default) version of the [`check_validity_requirement`] checks; see that +/// function for details. +fn check_validity_requirement_lax<'tcx>( this: TyAndLayout<'tcx>, cx: &LayoutCx<'tcx, TyCtxt<'tcx>>, init_kind: ValidityRequirement, @@ -141,7 +143,7 @@ fn might_permit_raw_init_lax<'tcx>( } FieldsShape::Arbitrary { offsets, .. } => { for idx in 0..offsets.len() { - if !might_permit_raw_init_lax(this.field(cx, idx), cx, init_kind)? { + if !check_validity_requirement_lax(this.field(cx, idx), cx, init_kind)? { // We found a field that is unhappy with this kind of initialization. return Ok(false); } From 11bd99de8cc67683f215317dba55c91aaf3b5767 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Thu, 5 Sep 2024 08:21:19 +0200 Subject: [PATCH 0682/2194] IntervalSet: add comment about representation --- compiler/rustc_index/src/interval.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_index/src/interval.rs b/compiler/rustc_index/src/interval.rs index 503470f896d09..34f541a8cc639 100644 --- a/compiler/rustc_index/src/interval.rs +++ b/compiler/rustc_index/src/interval.rs @@ -17,7 +17,7 @@ mod tests; /// first value of the following element. #[derive(Debug, Clone)] pub struct IntervalSet { - // Start, end + // Start, end (both inclusive) map: SmallVec<[(u32, u32); 2]>, domain: usize, _data: PhantomData, From 3bcc2b788886ba12585b9be8d6cc088d60ca0416 Mon Sep 17 00:00:00 2001 From: David Barsky Date: Wed, 4 Sep 2024 08:52:57 -0400 Subject: [PATCH 0683/2194] assist: ensure replace_qualified_name_with_use applies to the first path segment --- .../replace_qualified_name_with_use.rs | 34 ++++++++++++++----- 1 file changed, 25 insertions(+), 9 deletions(-) diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_qualified_name_with_use.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_qualified_name_with_use.rs index 65330b34c4ad2..1101c20f1b785 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_qualified_name_with_use.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_qualified_name_with_use.rs @@ -29,7 +29,7 @@ pub(crate) fn replace_qualified_name_with_use( acc: &mut Assists, ctx: &AssistContext<'_>, ) -> Option<()> { - let original_path: ast::Path = ctx.find_node_at_offset()?; + let mut original_path: ast::Path = ctx.find_node_at_offset()?; // We don't want to mess with use statements if original_path.syntax().ancestors().find_map(ast::UseTree::cast).is_some() { cov_mark::hit!(not_applicable_in_use); @@ -37,8 +37,7 @@ pub(crate) fn replace_qualified_name_with_use( } if original_path.qualifier().is_none() { - cov_mark::hit!(dont_import_trivial_paths); - return None; + original_path = original_path.parent_path()?; } // only offer replacement for non assoc items @@ -236,12 +235,6 @@ fs::Path ); } - #[test] - fn dont_import_trivial_paths() { - cov_mark::check!(dont_import_trivial_paths); - check_assist_not_applicable(replace_qualified_name_with_use, r"impl foo$0 for () {}"); - } - #[test] fn test_replace_not_applicable_in_use() { cov_mark::check!(not_applicable_in_use); @@ -271,6 +264,29 @@ fn main() { ); } + #[test] + fn assist_runs_on_first_segment() { + check_assist( + replace_qualified_name_with_use, + r" +mod std { pub mod fmt { pub trait Debug {} } } +fn main() { + $0std::fmt::Debug; + let x: std::fmt::Debug = std::fmt::Debug; +} + ", + r" +use std::fmt; + +mod std { pub mod fmt { pub trait Debug {} } } +fn main() { + fmt::Debug; + let x: fmt::Debug = fmt::Debug; +} + ", + ); + } + #[test] fn does_not_replace_in_submodules() { check_assist( From 11d51aae863d46a73ad39ec607bd7592fdb836e3 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 8 Sep 2024 18:59:30 +0200 Subject: [PATCH 0684/2194] const: make ptr.is_null() stop execution on ambiguity --- library/core/src/ptr/const_ptr.rs | 10 ++++++---- library/core/src/ptr/mut_ptr.rs | 17 +---------------- tests/ui/consts/const-ptr-is-null.rs | 20 ++++++++++++++++++++ tests/ui/consts/const-ptr-is-null.stderr | 19 +++++++++++++++++++ 4 files changed, 46 insertions(+), 20 deletions(-) create mode 100644 tests/ui/consts/const-ptr-is-null.rs create mode 100644 tests/ui/consts/const-ptr-is-null.stderr diff --git a/library/core/src/ptr/const_ptr.rs b/library/core/src/ptr/const_ptr.rs index 3b635e2a4aa9e..febb3fed96302 100644 --- a/library/core/src/ptr/const_ptr.rs +++ b/library/core/src/ptr/const_ptr.rs @@ -40,15 +40,17 @@ impl *const T { #[inline] const fn const_impl(ptr: *const u8) -> bool { - // Compare via a cast to a thin pointer, so fat pointers are only - // considering their "data" part for null-ness. match (ptr).guaranteed_eq(null_mut()) { - None => false, Some(res) => res, + // To remain maximally convervative, we stop execution when we don't + // know whether the pointer is null or not. + // We can *not* return `false` here, that would be unsound in `NonNull::new`! + None => panic!("null-ness of this pointer cannot be determined in const context"), } } - #[allow(unused_unsafe)] + // Compare via a cast to a thin pointer, so fat pointers are only + // considering their "data" part for null-ness. const_eval_select((self as *const u8,), const_impl, runtime_impl) } diff --git a/library/core/src/ptr/mut_ptr.rs b/library/core/src/ptr/mut_ptr.rs index 42975cc927b8e..bebc4b2f271eb 100644 --- a/library/core/src/ptr/mut_ptr.rs +++ b/library/core/src/ptr/mut_ptr.rs @@ -33,22 +33,7 @@ impl *mut T { #[rustc_diagnostic_item = "ptr_is_null"] #[inline] pub const fn is_null(self) -> bool { - #[inline] - fn runtime_impl(ptr: *mut u8) -> bool { - ptr.addr() == 0 - } - - #[inline] - const fn const_impl(ptr: *mut u8) -> bool { - // Compare via a cast to a thin pointer, so fat pointers are only - // considering their "data" part for null-ness. - match (ptr).guaranteed_eq(null_mut()) { - None => false, - Some(res) => res, - } - } - - const_eval_select((self as *mut u8,), const_impl, runtime_impl) + self.cast_const().is_null() } /// Casts to a pointer of another type. diff --git a/tests/ui/consts/const-ptr-is-null.rs b/tests/ui/consts/const-ptr-is-null.rs new file mode 100644 index 0000000000000..82c293c0ad6e3 --- /dev/null +++ b/tests/ui/consts/const-ptr-is-null.rs @@ -0,0 +1,20 @@ +#![feature(const_ptr_is_null)] +use std::ptr; + +const IS_NULL: () = { + assert!(ptr::null::().is_null()); +}; +const IS_NOT_NULL: () = { + assert!(!ptr::null::().wrapping_add(1).is_null()); +}; + +const MAYBE_NULL: () = { + let x = 15; + let ptr = &x as *const i32; + // This one is still unambiguous... + assert!(!ptr.is_null()); + // but once we shift outside the allocation, we might become null. + assert!(!ptr.wrapping_sub(512).is_null()); //~inside `MAYBE_NULL` +}; + +fn main() {} diff --git a/tests/ui/consts/const-ptr-is-null.stderr b/tests/ui/consts/const-ptr-is-null.stderr new file mode 100644 index 0000000000000..20e44a1401f9e --- /dev/null +++ b/tests/ui/consts/const-ptr-is-null.stderr @@ -0,0 +1,19 @@ +error[E0080]: evaluation of constant value failed + --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL + | + = note: the evaluated program panicked at 'null-ness of this pointer cannot be determined in const context', $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL + | +note: inside `std::ptr::const_ptr::::is_null::const_impl` + --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL +note: inside `std::ptr::const_ptr::::is_null` + --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL +note: inside `MAYBE_NULL` + --> $DIR/const-ptr-is-null.rs:17:14 + | +LL | assert!(!ptr.wrapping_sub(512).is_null()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: this error originates in the macro `$crate::panic::panic_2021` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0080`. From 5f3fdd14dfc47b0c6ab7f5887052d6e628b56919 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Eduardo=20S=C3=A1nchez=20Mu=C3=B1oz?= Date: Sun, 8 Sep 2024 21:51:00 +0200 Subject: [PATCH 0685/2194] Remove needless returns detected by clippy in libraries --- library/alloc/src/collections/vec_deque/iter.rs | 4 ++-- library/alloc/src/collections/vec_deque/iter_mut.rs | 4 ++-- library/alloc/src/vec/in_place_collect.rs | 2 +- library/alloc/src/vec/into_iter.rs | 4 ++-- library/core/src/ptr/metadata.rs | 4 ++-- library/core/src/str/pattern.rs | 4 ++-- library/std/src/sys/pal/unix/linux/pidfd.rs | 11 ++++++----- library/std/src/sys/pal/wasi/fs.rs | 4 ++-- library/std/src/sys/pal/wasi/helpers.rs | 2 +- 9 files changed, 20 insertions(+), 19 deletions(-) diff --git a/library/alloc/src/collections/vec_deque/iter.rs b/library/alloc/src/collections/vec_deque/iter.rs index bf4dd66f47638..6922ea9b79bfd 100644 --- a/library/alloc/src/collections/vec_deque/iter.rs +++ b/library/alloc/src/collections/vec_deque/iter.rs @@ -73,7 +73,7 @@ impl<'a, T> Iterator for Iter<'a, T> { fn advance_by(&mut self, n: usize) -> Result<(), NonZero> { let remaining = self.i1.advance_by(n); match remaining { - Ok(()) => return Ok(()), + Ok(()) => Ok(()), Err(n) => { mem::swap(&mut self.i1, &mut self.i2); self.i1.advance_by(n.get()) @@ -144,7 +144,7 @@ impl<'a, T> DoubleEndedIterator for Iter<'a, T> { fn advance_back_by(&mut self, n: usize) -> Result<(), NonZero> { match self.i2.advance_back_by(n) { - Ok(()) => return Ok(()), + Ok(()) => Ok(()), Err(n) => { mem::swap(&mut self.i1, &mut self.i2); self.i2.advance_back_by(n.get()) diff --git a/library/alloc/src/collections/vec_deque/iter_mut.rs b/library/alloc/src/collections/vec_deque/iter_mut.rs index 7a349a1b4edd0..84b7410958013 100644 --- a/library/alloc/src/collections/vec_deque/iter_mut.rs +++ b/library/alloc/src/collections/vec_deque/iter_mut.rs @@ -64,7 +64,7 @@ impl<'a, T> Iterator for IterMut<'a, T> { fn advance_by(&mut self, n: usize) -> Result<(), NonZero> { match self.i1.advance_by(n) { - Ok(()) => return Ok(()), + Ok(()) => Ok(()), Err(remaining) => { mem::swap(&mut self.i1, &mut self.i2); self.i1.advance_by(remaining.get()) @@ -135,7 +135,7 @@ impl<'a, T> DoubleEndedIterator for IterMut<'a, T> { fn advance_back_by(&mut self, n: usize) -> Result<(), NonZero> { match self.i2.advance_back_by(n) { - Ok(()) => return Ok(()), + Ok(()) => Ok(()), Err(remaining) => { mem::swap(&mut self.i1, &mut self.i2); self.i2.advance_back_by(remaining.get()) diff --git a/library/alloc/src/vec/in_place_collect.rs b/library/alloc/src/vec/in_place_collect.rs index d119e6ca397c5..ec0ab8ee7289c 100644 --- a/library/alloc/src/vec/in_place_collect.rs +++ b/library/alloc/src/vec/in_place_collect.rs @@ -208,7 +208,7 @@ const fn needs_realloc(src_cap: usize, dst_cap: usize) -> bool { // type layouts don't guarantee a fit, so do a runtime check to see if // the allocations happen to match - return src_cap > 0 && src_cap * mem::size_of::() != dst_cap * mem::size_of::(); + src_cap > 0 && src_cap * mem::size_of::() != dst_cap * mem::size_of::() } /// This provides a shorthand for the source type since local type aliases aren't a thing. diff --git a/library/alloc/src/vec/into_iter.rs b/library/alloc/src/vec/into_iter.rs index fad8abad49353..92c5e360da453 100644 --- a/library/alloc/src/vec/into_iter.rs +++ b/library/alloc/src/vec/into_iter.rs @@ -288,11 +288,11 @@ impl Iterator for IntoIter { // Safety: `len` is larger than the array size. Copy a fixed amount here to fully initialize // the array. - return unsafe { + unsafe { ptr::copy_nonoverlapping(self.ptr.as_ptr(), raw_ary.as_mut_ptr() as *mut T, N); self.ptr = self.ptr.add(N); Ok(raw_ary.transpose().assume_init()) - }; + } } fn fold(mut self, mut accum: B, mut f: F) -> B diff --git a/library/core/src/ptr/metadata.rs b/library/core/src/ptr/metadata.rs index ccc9f8754f00c..76a0e2ba77483 100644 --- a/library/core/src/ptr/metadata.rs +++ b/library/core/src/ptr/metadata.rs @@ -187,14 +187,14 @@ impl DynMetadata { // Consider a reference like `&(i32, dyn Send)`: the vtable will only store the size of the // `Send` part! // SAFETY: DynMetadata always contains a valid vtable pointer - return unsafe { crate::intrinsics::vtable_size(self.vtable_ptr() as *const ()) }; + unsafe { crate::intrinsics::vtable_size(self.vtable_ptr() as *const ()) } } /// Returns the alignment of the type associated with this vtable. #[inline] pub fn align_of(self) -> usize { // SAFETY: DynMetadata always contains a valid vtable pointer - return unsafe { crate::intrinsics::vtable_align(self.vtable_ptr() as *const ()) }; + unsafe { crate::intrinsics::vtable_align(self.vtable_ptr() as *const ()) } } /// Returns the size and alignment together as a `Layout` diff --git a/library/core/src/str/pattern.rs b/library/core/src/str/pattern.rs index 2f1096db8f00c..9f1294d760647 100644 --- a/library/core/src/str/pattern.rs +++ b/library/core/src/str/pattern.rs @@ -1814,7 +1814,7 @@ fn simd_contains(needle: &str, haystack: &str) -> Option { } mask &= !(1 << trailing); } - return false; + false }; let test_chunk = |idx| -> u16 { @@ -1830,7 +1830,7 @@ fn simd_contains(needle: &str, haystack: &str) -> Option { let both = eq_first.bitand(eq_last); let mask = both.to_bitmask() as u16; - return mask; + mask }; let mut i = 0; diff --git a/library/std/src/sys/pal/unix/linux/pidfd.rs b/library/std/src/sys/pal/unix/linux/pidfd.rs index 7474f80e94f9d..78744430f3b51 100644 --- a/library/std/src/sys/pal/unix/linux/pidfd.rs +++ b/library/std/src/sys/pal/unix/linux/pidfd.rs @@ -13,7 +13,7 @@ pub(crate) struct PidFd(FileDesc); impl PidFd { pub fn kill(&self) -> io::Result<()> { - return cvt(unsafe { + cvt(unsafe { libc::syscall( libc::SYS_pidfd_send_signal, self.0.as_raw_fd(), @@ -22,7 +22,7 @@ impl PidFd { 0, ) }) - .map(drop); + .map(drop) } pub fn wait(&self) -> io::Result { @@ -30,7 +30,7 @@ impl PidFd { cvt(unsafe { libc::waitid(libc::P_PIDFD, self.0.as_raw_fd() as u32, &mut siginfo, libc::WEXITED) })?; - return Ok(ExitStatus::from_waitid_siginfo(siginfo)); + Ok(ExitStatus::from_waitid_siginfo(siginfo)) } pub fn try_wait(&self) -> io::Result> { @@ -45,9 +45,10 @@ impl PidFd { ) })?; if unsafe { siginfo.si_pid() } == 0 { - return Ok(None); + Ok(None) + } else { + Ok(Some(ExitStatus::from_waitid_siginfo(siginfo))) } - return Ok(Some(ExitStatus::from_waitid_siginfo(siginfo))); } } diff --git a/library/std/src/sys/pal/wasi/fs.rs b/library/std/src/sys/pal/wasi/fs.rs index 88b1e543ec7c2..e1c61cae9f810 100644 --- a/library/std/src/sys/pal/wasi/fs.rs +++ b/library/std/src/sys/pal/wasi/fs.rs @@ -265,7 +265,7 @@ impl OpenOptions { pub fn new() -> OpenOptions { let mut base = OpenOptions::default(); base.dirflags = wasi::LOOKUPFLAGS_SYMLINK_FOLLOW; - return base; + base } pub fn read(&mut self, read: bool) { @@ -382,7 +382,7 @@ impl OpenOptions { base |= wasi::RIGHTS_PATH_UNLINK_FILE; base |= wasi::RIGHTS_POLL_FD_READWRITE; - return base; + base } fn rights_inheriting(&self) -> wasi::Rights { diff --git a/library/std/src/sys/pal/wasi/helpers.rs b/library/std/src/sys/pal/wasi/helpers.rs index d047bf2fce857..37ef17858cb96 100644 --- a/library/std/src/sys/pal/wasi/helpers.rs +++ b/library/std/src/sys/pal/wasi/helpers.rs @@ -115,7 +115,7 @@ pub fn hashmap_random_keys() -> (u64, u64) { let len = mem::size_of_val(&ret); wasi::random_get(base, len).expect("random_get failure"); } - return ret; + ret } #[inline] From ca262a34acdde2f72d15535e9f535021a9cb8d62 Mon Sep 17 00:00:00 2001 From: Chayim Refael Friedman Date: Sun, 1 Sep 2024 07:02:40 +0300 Subject: [PATCH 0686/2194] Automatically add semicolon when completing unit-returning functions But provide a config to suppress that. I didn't check whether we are in statement expression position, because this is hard in completion (due to the natural incompleteness of source code when completion is invoked), and anyway using function returning unit as an argument to something seems... dubious. --- .../ide-completion/src/completions/dot.rs | 2 +- .../crates/ide-completion/src/config.rs | 1 + .../crates/ide-completion/src/render.rs | 18 +- .../ide-completion/src/render/function.rs | 184 ++++++++++++++++-- .../crates/ide-completion/src/tests.rs | 1 + .../ide-completion/src/tests/flyimport.rs | 16 +- .../src/tests/raw_identifiers.rs | 8 +- .../ide-completion/src/tests/special.rs | 2 +- .../crates/rust-analyzer/src/config.rs | 5 + .../src/integrated_benchmarks.rs | 3 + .../docs/user/generated_config.adoc | 7 + .../rust-analyzer/editors/code/package.json | 10 + 12 files changed, 217 insertions(+), 40 deletions(-) diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/dot.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/dot.rs index d55bc3ea5d03a..f2c360a9d5bfd 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/dot.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/dot.rs @@ -600,7 +600,7 @@ fn foo(a: A) { a.$0 } struct A {} trait Trait { fn the_method(&self); } impl Trait for A {} -fn foo(a: A) { a.the_method()$0 } +fn foo(a: A) { a.the_method();$0 } "#, ); } diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/config.rs b/src/tools/rust-analyzer/crates/ide-completion/src/config.rs index d885b82ec90df..0d403f49b7a87 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/config.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/config.rs @@ -19,6 +19,7 @@ pub struct CompletionConfig { pub term_search_fuel: u64, pub full_function_signatures: bool, pub callable: Option, + pub add_semicolon_to_unit: bool, pub snippet_cap: Option, pub insert_use: InsertUseConfig, pub prefer_no_std: bool, diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/render.rs b/src/tools/rust-analyzer/crates/ide-completion/src/render.rs index 2bec2eb87bc4b..f2e9de9382c6b 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/render.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/render.rs @@ -1185,7 +1185,7 @@ fn main() { fo$0 } label: "main()", source_range: 68..70, delete: 68..70, - insert: "main()$0", + insert: "main();$0", kind: SymbolKind( Function, ), @@ -1244,7 +1244,7 @@ fn main() { let _: m::Spam = S$0 } label: "main()", source_range: 75..76, delete: 75..76, - insert: "main()$0", + insert: "main();$0", kind: SymbolKind( Function, ), @@ -1331,7 +1331,7 @@ fn main() { som$0 } label: "main()", source_range: 56..59, delete: 56..59, - insert: "main()$0", + insert: "main();$0", kind: SymbolKind( Function, ), @@ -1342,7 +1342,7 @@ fn main() { som$0 } label: "something_deprecated()", source_range: 56..59, delete: 56..59, - insert: "something_deprecated()$0", + insert: "something_deprecated();$0", kind: SymbolKind( Function, ), @@ -1413,7 +1413,7 @@ impl S { label: "bar()", source_range: 94..94, delete: 94..94, - insert: "bar()$0", + insert: "bar();$0", kind: SymbolKind( Method, ), @@ -1540,7 +1540,7 @@ fn foo(s: S) { s.$0 } label: "the_method()", source_range: 81..81, delete: 81..81, - insert: "the_method()$0", + insert: "the_method();$0", kind: SymbolKind( Method, ), @@ -2789,7 +2789,7 @@ fn main() { r#" mod m { pub fn r#type {} } fn main() { - m::r#type()$0 + m::r#type();$0 } "#, ) @@ -2963,7 +2963,7 @@ fn main() { label: "flush()", source_range: 193..193, delete: 193..193, - insert: "flush()$0", + insert: "flush();$0", kind: SymbolKind( Method, ), @@ -2990,7 +2990,7 @@ fn main() { label: "write()", source_range: 193..193, delete: 193..193, - insert: "write()$0", + insert: "write();$0", kind: SymbolKind( Method, ), diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/render/function.rs b/src/tools/rust-analyzer/crates/ide-completion/src/render/function.rs index 29820cb2036de..7e5e69665f1fa 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/render/function.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/render/function.rs @@ -1,10 +1,12 @@ //! Renderer for function calls. +use std::ops::ControlFlow; + use hir::{db::HirDatabase, AsAssocItem, HirDisplay}; use ide_db::{SnippetCap, SymbolKind}; use itertools::Itertools; use stdx::{format_to, to_lower_snake_case}; -use syntax::{format_smolstr, AstNode, Edition, SmolStr, ToSmolStr}; +use syntax::{ast, format_smolstr, AstNode, Edition, SmolStr, SyntaxKind, ToSmolStr, T}; use crate::{ context::{CompletionContext, DotAccess, DotAccessKind, PathCompletionCtx, PathKind}, @@ -160,7 +162,16 @@ fn render( .lookup_by(name.unescaped().display(db).to_smolstr()); if let Some((cap, (self_param, params))) = complete_call_parens { - add_call_parens(&mut item, completion, cap, call, escaped_call, self_param, params); + add_call_parens( + &mut item, + completion, + cap, + call, + escaped_call, + self_param, + params, + &ret_type, + ); } match ctx.import_to_add { @@ -217,10 +228,11 @@ pub(super) fn add_call_parens<'b>( escaped_name: SmolStr, self_param: Option, params: Vec, + ret_type: &hir::Type, ) -> &'b mut Builder { cov_mark::hit!(inserts_parens_for_function_calls); - let (snippet, label_suffix) = if self_param.is_none() && params.is_empty() { + let (mut snippet, label_suffix) = if self_param.is_none() && params.is_empty() { (format!("{escaped_name}()$0"), "()") } else { builder.trigger_call_info(); @@ -265,6 +277,35 @@ pub(super) fn add_call_parens<'b>( (snippet, "(…)") }; + if ret_type.is_unit() && ctx.config.add_semicolon_to_unit { + let next_non_trivia_token = + std::iter::successors(ctx.token.next_token(), |it| it.next_token()) + .find(|it| !it.kind().is_trivia()); + let in_match_arm = ctx.token.parent_ancestors().try_for_each(|ancestor| { + if ast::MatchArm::can_cast(ancestor.kind()) { + ControlFlow::Break(true) + } else if matches!(ancestor.kind(), SyntaxKind::EXPR_STMT | SyntaxKind::BLOCK_EXPR) { + ControlFlow::Break(false) + } else { + ControlFlow::Continue(()) + } + }); + // FIXME: This will assume expr macros are not inside match, we need to somehow go to the "parent" of the root node. + let in_match_arm = match in_match_arm { + ControlFlow::Continue(()) => false, + ControlFlow::Break(it) => it, + }; + let complete_token = if in_match_arm { T![,] } else { T![;] }; + if next_non_trivia_token.map(|it| it.kind()) != Some(complete_token) { + cov_mark::hit!(complete_semicolon); + let ch = if in_match_arm { ',' } else { ';' }; + if snippet.ends_with("$0") { + snippet.insert(snippet.len() - "$0".len(), ch); + } else { + snippet.push(ch); + } + } + } builder.label(SmolStr::from_iter([&name, label_suffix])).insert_snippet(cap, snippet) } @@ -393,7 +434,7 @@ fn main() { no_$0 } "#, r#" fn no_args() {} -fn main() { no_args()$0 } +fn main() { no_args();$0 } "#, ); @@ -405,7 +446,7 @@ fn main() { with_$0 } "#, r#" fn with_args(x: i32, y: String) {} -fn main() { with_args(${1:x}, ${2:y})$0 } +fn main() { with_args(${1:x}, ${2:y});$0 } "#, ); @@ -414,14 +455,14 @@ fn main() { with_args(${1:x}, ${2:y})$0 } r#" struct S; impl S { - fn foo(&self) {} + fn foo(&self) -> i32 { 0 } } fn bar(s: &S) { s.f$0 } "#, r#" struct S; impl S { - fn foo(&self) {} + fn foo(&self) -> i32 { 0 } } fn bar(s: &S) { s.foo()$0 } "#, @@ -444,7 +485,7 @@ impl S { fn foo(&self, x: i32) {} } fn bar(s: &S) { - s.foo(${1:x})$0 + s.foo(${1:x});$0 } "#, ); @@ -463,7 +504,7 @@ impl S { struct S {} impl S { fn foo(&self, x: i32) { - self.foo(${1:x})$0 + self.foo(${1:x});$0 } } "#, @@ -486,7 +527,7 @@ struct S; impl S { fn foo(&self) {} } -fn main() { S::foo(${1:&self})$0 } +fn main() { S::foo(${1:&self});$0 } "#, ); } @@ -503,7 +544,7 @@ fn main() { with_$0 } "#, r#" fn with_args(x: i32, y: String) {} -fn main() { with_args($0) } +fn main() { with_args($0); } "#, ); } @@ -518,7 +559,7 @@ fn main() { f$0 } "#, r#" fn foo(_foo: i32, ___bar: bool, ho_ge_: String) {} -fn main() { foo(${1:foo}, ${2:bar}, ${3:ho_ge_})$0 } +fn main() { foo(${1:foo}, ${2:bar}, ${3:ho_ge_});$0 } "#, ); } @@ -540,7 +581,7 @@ struct Foo {} fn ref_arg(x: &Foo) {} fn main() { let x = Foo {}; - ref_arg(${1:&x})$0 + ref_arg(${1:&x});$0 } "#, ); @@ -563,7 +604,7 @@ struct Foo {} fn ref_arg(x: &mut Foo) {} fn main() { let x = Foo {}; - ref_arg(${1:&mut x})$0 + ref_arg(${1:&mut x});$0 } "#, ); @@ -596,7 +637,7 @@ impl Bar { fn main() { let x = Foo {}; let y = Bar {}; - y.apply_foo(${1:&x})$0 + y.apply_foo(${1:&x});$0 } "#, ); @@ -617,7 +658,7 @@ fn main() { fn take_mutably(mut x: &i32) {} fn main() { - take_mutably(${1:x})$0 + take_mutably(${1:x});$0 } "#, ); @@ -650,7 +691,7 @@ fn qux(Foo { bar }: Foo) { } fn main() { - qux(${1:foo})$0 + qux(${1:foo});$0 } "#, ); @@ -736,6 +777,115 @@ fn g(foo: ()#[baz = "qux"] mut ba$0) r#" fn f(foo: (), #[baz = "qux"] mut bar: u32) {} fn g(foo: (), #[baz = "qux"] mut bar: u32) +"#, + ); + } + + #[test] + fn complete_semicolon_for_unit() { + cov_mark::check!(complete_semicolon); + check_edit( + r#"foo"#, + r#" +fn foo() {} +fn bar() { + foo$0 +} +"#, + r#" +fn foo() {} +fn bar() { + foo();$0 +} +"#, + ); + check_edit( + r#"foo"#, + r#" +fn foo(a: i32) {} +fn bar() { + foo$0 +} +"#, + r#" +fn foo(a: i32) {} +fn bar() { + foo(${1:a});$0 +} +"#, + ); + check_edit( + r#"foo"#, + r#" +fn foo(a: i32) {} +fn bar() { + foo$0; +} +"#, + r#" +fn foo(a: i32) {} +fn bar() { + foo(${1:a})$0; +} +"#, + ); + check_edit_with_config( + CompletionConfig { add_semicolon_to_unit: false, ..TEST_CONFIG }, + r#"foo"#, + r#" +fn foo(a: i32) {} +fn bar() { + foo$0 +} +"#, + r#" +fn foo(a: i32) {} +fn bar() { + foo(${1:a})$0 +} +"#, + ); + } + + #[test] + fn complete_comma_for_unit_match_arm() { + cov_mark::check!(complete_semicolon); + check_edit( + r#"foo"#, + r#" +fn foo() {} +fn bar() { + match Some(false) { + v => fo$0 + } +} +"#, + r#" +fn foo() {} +fn bar() { + match Some(false) { + v => foo(),$0 + } +} +"#, + ); + check_edit( + r#"foo"#, + r#" +fn foo() {} +fn bar() { + match Some(false) { + v => fo$0, + } +} +"#, + r#" +fn foo() {} +fn bar() { + match Some(false) { + v => foo()$0, + } +} "#, ); } diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/tests.rs b/src/tools/rust-analyzer/crates/ide-completion/src/tests.rs index 04ba7e1f41b62..9d77d9700718c 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/tests.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/tests.rs @@ -70,6 +70,7 @@ pub(crate) const TEST_CONFIG: CompletionConfig = CompletionConfig { term_search_fuel: 200, full_function_signatures: false, callable: Some(CallableSnippets::FillArguments), + add_semicolon_to_unit: true, snippet_cap: SnippetCap::new(true), insert_use: InsertUseConfig { granularity: ImportGranularity::Crate, diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/tests/flyimport.rs b/src/tools/rust-analyzer/crates/ide-completion/src/tests/flyimport.rs index 8350fdcc4c07c..0b532064fb2be 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/tests/flyimport.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/tests/flyimport.rs @@ -53,7 +53,7 @@ fn main() { use dep::io::stdin; fn main() { - stdin()$0 + stdin();$0 } "#, ); @@ -274,7 +274,7 @@ fn trait_function_fuzzy_completion() { use dep::test_mod::TestTrait; fn main() { - dep::test_mod::TestStruct::weird_function()$0 + dep::test_mod::TestStruct::weird_function();$0 } "#, ); @@ -368,7 +368,7 @@ use dep::test_mod::TestTrait; fn main() { let test_struct = dep::test_mod::TestStruct {}; - test_struct.random_method()$0 + test_struct.random_method();$0 } "#, ); @@ -419,7 +419,7 @@ impl foo::TestTrait for fundamental::Box { fn main() { let t = fundamental::Box(TestStruct); - t.some_method()$0 + t.some_method();$0 } "#, ); @@ -466,7 +466,7 @@ impl foo::TestTrait for &TestStruct { fn main() { let t = &TestStruct; - t.some_method()$0 + t.some_method();$0 } "#, ); @@ -507,7 +507,7 @@ fn completion(whatever: T) { use foo::{NotInScope, Wrapper}; fn completion(whatever: T) { - whatever.inner().not_in_scope()$0 + whatever.inner().not_in_scope();$0 } "#, ); @@ -579,7 +579,7 @@ fn main() { use dep::test_mod::TestTrait; fn main() { - dep::test_mod::TestAlias::random_method()$0 + dep::test_mod::TestAlias::random_method();$0 } "#, ); @@ -702,7 +702,7 @@ fn main() { use dep::test_mod::TestTrait; fn main() { - dep::test_mod::TestStruct::another_function()$0 + dep::test_mod::TestStruct::another_function();$0 } "#, ); diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/tests/raw_identifiers.rs b/src/tools/rust-analyzer/crates/ide-completion/src/tests/raw_identifiers.rs index bc630189edc91..d81b3d697aa8a 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/tests/raw_identifiers.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/tests/raw_identifiers.rs @@ -30,7 +30,7 @@ fn foo() { "#, expect![[r#" fn foo() { - a::dyn()$0 + a::dyn();$0 "#]], ); @@ -45,7 +45,7 @@ fn foo() { "#, expect![[r#" fn foo() { - a::dyn()$0 + a::dyn();$0 "#]], ); } @@ -63,7 +63,7 @@ fn foo() { "#, expect![[r#" fn foo() { - a::r#dyn()$0 + a::r#dyn();$0 "#]], ); @@ -78,7 +78,7 @@ fn foo() { "#, expect![[r#" fn foo() { - a::r#dyn()$0 + a::r#dyn();$0 "#]], ); } diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/tests/special.rs b/src/tools/rust-analyzer/crates/ide-completion/src/tests/special.rs index 2ae7d37889e53..508f6248dd414 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/tests/special.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/tests/special.rs @@ -63,7 +63,7 @@ fn _alpha() {} "#, r#" fn main() { - _alpha()$0 + _alpha();$0 } fn _alpha() {} "#, diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs index e4e8c9c6d9f97..35be6d0cf7a13 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs @@ -420,6 +420,10 @@ config_data! { assist_termSearch_fuel: usize = 1800, + /// Whether to automatically add a semicolon when completing unit-returning functions. + /// + /// In `match` arms it completes a comma instead. + completion_addSemicolonToUnit: bool = true, /// Toggles the additional completions that automatically add imports when completed. /// Note that your client must specify the `additionalTextEdits` LSP client capability to truly have this feature enabled. completion_autoimport_enable: bool = true, @@ -1441,6 +1445,7 @@ impl Config { CallableCompletionDef::AddParentheses => Some(CallableSnippets::AddParentheses), CallableCompletionDef::None => None, }, + add_semicolon_to_unit: *self.completion_addSemicolonToUnit(source_root), snippet_cap: SnippetCap::new(self.completion_snippet()), insert_use: self.insert_use_config(source_root), prefer_no_std: self.imports_preferNoStd(source_root).to_owned(), diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/integrated_benchmarks.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/integrated_benchmarks.rs index 28f4b809d6c82..118469df730ce 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/integrated_benchmarks.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/integrated_benchmarks.rs @@ -167,6 +167,7 @@ fn integrated_completion_benchmark() { prefer_absolute: false, snippets: Vec::new(), limit: None, + add_semicolon_to_unit: true, }; let position = FilePosition { file_id, offset: TextSize::try_from(completion_offset).unwrap() }; @@ -213,6 +214,7 @@ fn integrated_completion_benchmark() { prefer_absolute: false, snippets: Vec::new(), limit: None, + add_semicolon_to_unit: true, }; let position = FilePosition { file_id, offset: TextSize::try_from(completion_offset).unwrap() }; @@ -257,6 +259,7 @@ fn integrated_completion_benchmark() { prefer_absolute: false, snippets: Vec::new(), limit: None, + add_semicolon_to_unit: true, }; let position = FilePosition { file_id, offset: TextSize::try_from(completion_offset).unwrap() }; diff --git a/src/tools/rust-analyzer/docs/user/generated_config.adoc b/src/tools/rust-analyzer/docs/user/generated_config.adoc index 4fcf580e75f5a..f37fd7f4ab3c4 100644 --- a/src/tools/rust-analyzer/docs/user/generated_config.adoc +++ b/src/tools/rust-analyzer/docs/user/generated_config.adoc @@ -261,6 +261,13 @@ Aliased as `"checkOnSave.targets"`. Whether `--workspace` should be passed to `cargo check`. If false, `-p ` will be passed instead. -- +[[rust-analyzer.completion.addSemicolonToUnit]]rust-analyzer.completion.addSemicolonToUnit (default: `true`):: ++ +-- +Whether to automatically add a semicolon when completing unit-returning functions. + +In `match` arms it completes a comma instead. +-- [[rust-analyzer.completion.autoimport.enable]]rust-analyzer.completion.autoimport.enable (default: `true`):: + -- diff --git a/src/tools/rust-analyzer/editors/code/package.json b/src/tools/rust-analyzer/editors/code/package.json index 0b029460b3220..b66f0a64d575a 100644 --- a/src/tools/rust-analyzer/editors/code/package.json +++ b/src/tools/rust-analyzer/editors/code/package.json @@ -1027,6 +1027,16 @@ } } }, + { + "title": "completion", + "properties": { + "rust-analyzer.completion.addSemicolonToUnit": { + "markdownDescription": "Whether to automatically add a semicolon when completing unit-returning functions.\n\nIn `match` arms it completes a comma instead.", + "default": true, + "type": "boolean" + } + } + }, { "title": "completion", "properties": { From 7ec01e453c8edead75822574433b6e6fe6ad7ca0 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 8 Sep 2024 23:04:16 +0200 Subject: [PATCH 0687/2194] move Option::unwrap_unchecked into const_option feature gate --- library/core/src/option.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/core/src/option.rs b/library/core/src/option.rs index 212e4f0215463..3634c61e0ba2a 100644 --- a/library/core/src/option.rs +++ b/library/core/src/option.rs @@ -1065,7 +1065,7 @@ impl Option { #[inline] #[track_caller] #[stable(feature = "option_result_unwrap_unchecked", since = "1.58.0")] - #[rustc_const_unstable(feature = "const_option_ext", issue = "91930")] + #[rustc_const_unstable(feature = "const_option", issue = "67441")] pub const unsafe fn unwrap_unchecked(self) -> T { match self { Some(val) => val, From 332fa6aa6ed70e285c155d112a30027947cad12b Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 8 Sep 2024 16:35:34 +0200 Subject: [PATCH 0688/2194] add FIXME(const-hack) --- .../rustc_mir_transform/src/pass_manager.rs | 6 ++--- .../alloc/src/collections/vec_deque/mod.rs | 4 ++-- library/alloc/src/raw_vec.rs | 15 +----------- library/alloc/src/vec/in_place_collect.rs | 2 +- library/alloc/src/vec/into_iter.rs | 2 +- library/alloc/src/vec/mod.rs | 2 +- library/core/src/char/convert.rs | 2 +- library/core/src/char/methods.rs | 2 +- library/core/src/num/mod.rs | 2 +- library/core/src/option.rs | 24 ++++++------------- library/core/src/slice/index.rs | 9 ++++--- library/core/src/slice/mod.rs | 6 ++--- library/core/src/str/converts.rs | 4 ++-- library/core/src/str/error.rs | 2 +- library/core/src/time.rs | 2 ++ library/core/src/unicode/unicode_data.rs | 6 ++--- library/core/tests/hash/mod.rs | 7 ++---- library/std/src/sys/pal/windows/args.rs | 2 +- 18 files changed, 38 insertions(+), 61 deletions(-) diff --git a/compiler/rustc_mir_transform/src/pass_manager.rs b/compiler/rustc_mir_transform/src/pass_manager.rs index 28d4e1a1c9184..e5f145ea31ae8 100644 --- a/compiler/rustc_mir_transform/src/pass_manager.rs +++ b/compiler/rustc_mir_transform/src/pass_manager.rs @@ -42,7 +42,7 @@ fn to_profiler_name(type_name: &'static str) -> &'static str { // const wrapper for `if let Some((_, tail)) = name.rsplit_once(':') { tail } else { name }` const fn c_name(name: &'static str) -> &'static str { - // FIXME Simplify the implementation once more `str` methods get const-stable. + // FIXME(const-hack) Simplify the implementation once more `str` methods get const-stable. // and inline into call site let bytes = name.as_bytes(); let mut i = bytes.len(); @@ -61,7 +61,7 @@ const fn c_name(name: &'static str) -> &'static str { /// loop that goes over each available MIR and applies `run_pass`. pub(super) trait MirPass<'tcx> { fn name(&self) -> &'static str { - // FIXME Simplify the implementation once more `str` methods get const-stable. + // FIXME(const-hack) Simplify the implementation once more `str` methods get const-stable. // See copypaste in `MirLint` const { let name = std::any::type_name::(); @@ -89,7 +89,7 @@ pub(super) trait MirPass<'tcx> { /// disabled (via the `Lint` adapter). pub(super) trait MirLint<'tcx> { fn name(&self) -> &'static str { - // FIXME Simplify the implementation once more `str` methods get const-stable. + // FIXME(const-hack) Simplify the implementation once more `str` methods get const-stable. // See copypaste in `MirPass` const { let name = std::any::type_name::(); diff --git a/library/alloc/src/collections/vec_deque/mod.rs b/library/alloc/src/collections/vec_deque/mod.rs index dc725ec0f56e4..8c9db063105ce 100644 --- a/library/alloc/src/collections/vec_deque/mod.rs +++ b/library/alloc/src/collections/vec_deque/mod.rs @@ -554,8 +554,8 @@ impl VecDeque { #[rustc_const_stable(feature = "const_vec_deque_new", since = "1.68.0")] #[must_use] pub const fn new() -> VecDeque { - // FIXME: This should just be `VecDeque::new_in(Global)` once that hits stable. - VecDeque { head: 0, len: 0, buf: RawVec::NEW } + // FIXME(const-hack): This should just be `VecDeque::new_in(Global)` once that hits stable. + VecDeque { head: 0, len: 0, buf: RawVec::new() } } /// Creates an empty deque with space for at least `capacity` elements. diff --git a/library/alloc/src/raw_vec.rs b/library/alloc/src/raw_vec.rs index a651ba067e47c..436e0596e3d5e 100644 --- a/library/alloc/src/raw_vec.rs +++ b/library/alloc/src/raw_vec.rs @@ -96,13 +96,6 @@ struct RawVecInner { } impl RawVec { - /// HACK(Centril): This exists because stable `const fn` can only call stable `const fn`, so - /// they cannot call `Self::new()`. - /// - /// If you change `RawVec::new` or dependencies, please take care to not introduce anything - /// that would truly const-call something unstable. - pub const NEW: Self = Self::new(); - /// Creates the biggest possible `RawVec` (on the system heap) /// without allocating. If `T` has positive size, then this makes a /// `RawVec` with capacity `0`. If `T` is zero-sized, then it makes a @@ -111,7 +104,7 @@ impl RawVec { #[must_use] #[rustc_const_stable(feature = "raw_vec_internals_const", since = "1.81")] pub const fn new() -> Self { - Self { inner: RawVecInner::new::(), _marker: PhantomData } + Self::new_in(Global) } /// Creates a `RawVec` (on the system heap) with exactly the @@ -149,12 +142,6 @@ impl RawVec { } impl RawVecInner { - #[must_use] - #[rustc_const_stable(feature = "raw_vec_internals_const", since = "1.81")] - const fn new() -> Self { - Self::new_in(Global, core::mem::align_of::()) - } - #[cfg(not(any(no_global_oom_handling, test)))] #[must_use] #[inline] diff --git a/library/alloc/src/vec/in_place_collect.rs b/library/alloc/src/vec/in_place_collect.rs index d119e6ca397c5..2604843994506 100644 --- a/library/alloc/src/vec/in_place_collect.rs +++ b/library/alloc/src/vec/in_place_collect.rs @@ -191,7 +191,7 @@ const fn in_place_collectible( const fn needs_realloc(src_cap: usize, dst_cap: usize) -> bool { if const { mem::align_of::() != mem::align_of::() } { - // FIXME: use unreachable! once that works in const + // FIXME(const-hack): use unreachable! once that works in const panic!("in_place_collectible() prevents this"); } diff --git a/library/alloc/src/vec/into_iter.rs b/library/alloc/src/vec/into_iter.rs index fad8abad49353..487d5cc7224bc 100644 --- a/library/alloc/src/vec/into_iter.rs +++ b/library/alloc/src/vec/into_iter.rs @@ -142,7 +142,7 @@ impl IntoIter { // struct and then overwriting &mut self. // this creates less assembly self.cap = 0; - self.buf = RawVec::NEW.non_null(); + self.buf = RawVec::new().non_null(); self.ptr = self.buf; self.end = self.buf.as_ptr(); diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index 162791ba59d03..ff084edba8dc8 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -419,7 +419,7 @@ impl Vec { #[stable(feature = "rust1", since = "1.0.0")] #[must_use] pub const fn new() -> Self { - Vec { buf: RawVec::NEW, len: 0 } + Vec { buf: RawVec::new(), len: 0 } } /// Constructs a new, empty `Vec` with at least the specified capacity. diff --git a/library/core/src/char/convert.rs b/library/core/src/char/convert.rs index f0c2636307fcf..73ab4f1e52ade 100644 --- a/library/core/src/char/convert.rs +++ b/library/core/src/char/convert.rs @@ -11,7 +11,7 @@ use crate::ub_checks::assert_unsafe_precondition; #[must_use] #[inline] pub(super) const fn from_u32(i: u32) -> Option { - // FIXME: once Result::ok is const fn, use it here + // FIXME(const-hack): once Result::ok is const fn, use it here match char_try_from_u32(i) { Ok(c) => Some(c), Err(_) => None, diff --git a/library/core/src/char/methods.rs b/library/core/src/char/methods.rs index 41a19665779b6..6e7494af12f8e 100644 --- a/library/core/src/char/methods.rs +++ b/library/core/src/char/methods.rs @@ -386,7 +386,7 @@ impl char { // Force the 6th bit to be set to ensure ascii is lower case. digit = (self as u32 | 0b10_0000).wrapping_sub('a' as u32).saturating_add(10); } - // FIXME: once then_some is const fn, use it here + // FIXME(const-hack): once then_some is const fn, use it here if digit < radix { Some(digit) } else { None } } diff --git a/library/core/src/num/mod.rs b/library/core/src/num/mod.rs index 37c9db7f474b5..dca644ebef4ad 100644 --- a/library/core/src/num/mod.rs +++ b/library/core/src/num/mod.rs @@ -6,7 +6,7 @@ use crate::str::FromStr; use crate::ub_checks::assert_unsafe_precondition; use crate::{ascii, intrinsics, mem}; -// Used because the `?` operator is not allowed in a const context. +// FIXME(const-hack): Used because the `?` operator is not allowed in a const context. macro_rules! try_opt { ($e:expr) => { match $e { diff --git a/library/core/src/option.rs b/library/core/src/option.rs index 212e4f0215463..18604a8ae3532 100644 --- a/library/core/src/option.rs +++ b/library/core/src/option.rs @@ -739,6 +739,7 @@ impl Option { #[stable(feature = "pin", since = "1.33.0")] #[rustc_const_unstable(feature = "const_option_ext", issue = "91930")] pub const fn as_pin_ref(self: Pin<&Self>) -> Option> { + // FIXME(const-hack): use `map` once that is possible match Pin::get_ref(self).as_ref() { // SAFETY: `x` is guaranteed to be pinned because it comes from `self` // which is pinned. @@ -758,6 +759,7 @@ impl Option { // SAFETY: `get_unchecked_mut` is never used to move the `Option` inside `self`. // `x` is guaranteed to be pinned because it comes from `self` which is pinned. unsafe { + // FIXME(const-hack): use `map` once that is possible match Pin::get_unchecked_mut(self).as_mut() { Some(x) => Some(Pin::new_unchecked(x)), None => None, @@ -1290,10 +1292,7 @@ impl Option { where T: Deref, { - match self.as_ref() { - Some(t) => Some(t.deref()), - None => None, - } + self.as_ref().map(|t| t.deref()) } /// Converts from `Option` (or `&mut Option`) to `Option<&mut T::Target>`. @@ -1316,10 +1315,7 @@ impl Option { where T: DerefMut, { - match self.as_mut() { - Some(t) => Some(t.deref_mut()), - None => None, - } + self.as_mut().map(|t| t.deref_mut()) } ///////////////////////////////////////////////////////////////////////// @@ -1633,13 +1629,7 @@ impl Option { #[inline] #[stable(feature = "option_entry", since = "1.20.0")] pub fn get_or_insert(&mut self, value: T) -> &mut T { - if let None = *self { - *self = Some(value); - } - - // SAFETY: a `None` variant for `self` would have been replaced by a `Some` - // variant in the code above. - unsafe { self.as_mut().unwrap_unchecked() } + self.get_or_insert_with(|| value) } /// Inserts the default value into the option if it is [`None`], then @@ -1725,7 +1715,7 @@ impl Option { #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_unstable(feature = "const_option", issue = "67441")] pub const fn take(&mut self) -> Option { - // FIXME replace `mem::replace` by `mem::take` when the latter is const ready + // FIXME(const-hack) replace `mem::replace` by `mem::take` when the latter is const ready mem::replace(self, None) } @@ -1894,7 +1884,7 @@ impl Option<&T> { where T: Copy, { - // FIXME: this implementation, which sidesteps using `Option::map` since it's not const + // FIXME(const-hack): this implementation, which sidesteps using `Option::map` since it's not const // ready yet, should be reverted when possible to avoid code repetition match self { Some(&v) => Some(v), diff --git a/library/core/src/slice/index.rs b/library/core/src/slice/index.rs index de1492e82ce7d..7adcee1ed6b64 100644 --- a/library/core/src/slice/index.rs +++ b/library/core/src/slice/index.rs @@ -33,10 +33,11 @@ where #[track_caller] #[rustc_const_unstable(feature = "const_slice_index", issue = "none")] const fn slice_start_index_len_fail(index: usize, len: usize) -> ! { + // FIXME(const-hack): once integer formatting in panics is possible, we + // should use the same implementation at compiletime and runtime. const_eval_select((index, len), slice_start_index_len_fail_ct, slice_start_index_len_fail_rt) } -// FIXME const-hack #[inline] #[track_caller] fn slice_start_index_len_fail_rt(index: usize, len: usize) -> ! { @@ -54,10 +55,11 @@ const fn slice_start_index_len_fail_ct(_: usize, _: usize) -> ! { #[track_caller] #[rustc_const_unstable(feature = "const_slice_index", issue = "none")] const fn slice_end_index_len_fail(index: usize, len: usize) -> ! { + // FIXME(const-hack): once integer formatting in panics is possible, we + // should use the same implementation at compiletime and runtime. const_eval_select((index, len), slice_end_index_len_fail_ct, slice_end_index_len_fail_rt) } -// FIXME const-hack #[inline] #[track_caller] fn slice_end_index_len_fail_rt(index: usize, len: usize) -> ! { @@ -75,10 +77,11 @@ const fn slice_end_index_len_fail_ct(_: usize, _: usize) -> ! { #[track_caller] #[rustc_const_unstable(feature = "const_slice_index", issue = "none")] const fn slice_index_order_fail(index: usize, end: usize) -> ! { + // FIXME(const-hack): once integer formatting in panics is possible, we + // should use the same implementation at compiletime and runtime. const_eval_select((index, end), slice_index_order_fail_ct, slice_index_order_fail_rt) } -// FIXME const-hack #[inline] #[track_caller] fn slice_index_order_fail_rt(index: usize, end: usize) -> ! { diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs index 166189f4b6cf3..3a02966a168a7 100644 --- a/library/core/src/slice/mod.rs +++ b/library/core/src/slice/mod.rs @@ -529,7 +529,7 @@ impl [T] { None } else { // SAFETY: We manually verified the bounds of the slice. - // FIXME: Without const traits, we need this instead of `get_unchecked`. + // FIXME(const-hack): Without const traits, we need this instead of `get_unchecked`. let last = unsafe { self.split_at_unchecked(self.len() - N).1 }; // SAFETY: We explicitly check for the correct number of elements, @@ -563,7 +563,7 @@ impl [T] { None } else { // SAFETY: We manually verified the bounds of the slice. - // FIXME: Without const traits, we need this instead of `get_unchecked`. + // FIXME(const-hack): Without const traits, we need this instead of `get_unchecked`. let last = unsafe { self.split_at_mut_unchecked(self.len() - N).1 }; // SAFETY: We explicitly check for the correct number of elements, @@ -1952,7 +1952,7 @@ impl [T] { #[inline] #[must_use] pub const unsafe fn split_at_unchecked(&self, mid: usize) -> (&[T], &[T]) { - // HACK: the const function `from_raw_parts` is used to make this + // FIXME(const-hack): the const function `from_raw_parts` is used to make this // function const; previously the implementation used // `(self.get_unchecked(..mid), self.get_unchecked(mid..))` diff --git a/library/core/src/str/converts.rs b/library/core/src/str/converts.rs index 1956a04829d1d..dcddc40ba4b99 100644 --- a/library/core/src/str/converts.rs +++ b/library/core/src/str/converts.rs @@ -85,7 +85,7 @@ use crate::{mem, ptr}; #[rustc_allow_const_fn_unstable(str_internals)] #[rustc_diagnostic_item = "str_from_utf8"] pub const fn from_utf8(v: &[u8]) -> Result<&str, Utf8Error> { - // FIXME: This should use `?` again, once it's `const` + // FIXME(const-hack): This should use `?` again, once it's `const` match run_utf8_validation(v) { Ok(_) => { // SAFETY: validation succeeded. @@ -129,7 +129,7 @@ pub const fn from_utf8(v: &[u8]) -> Result<&str, Utf8Error> { #[rustc_const_unstable(feature = "const_str_from_utf8", issue = "91006")] #[rustc_diagnostic_item = "str_from_utf8_mut"] pub const fn from_utf8_mut(v: &mut [u8]) -> Result<&mut str, Utf8Error> { - // This should use `?` again, once it's `const` + // FIXME(const-hack): This should use `?` again, once it's `const` match run_utf8_validation(v) { Ok(_) => { // SAFETY: validation succeeded. diff --git a/library/core/src/str/error.rs b/library/core/src/str/error.rs index a11b5add42ebf..4c8231a2286e1 100644 --- a/library/core/src/str/error.rs +++ b/library/core/src/str/error.rs @@ -100,7 +100,7 @@ impl Utf8Error { #[must_use] #[inline] pub const fn error_len(&self) -> Option { - // FIXME: This should become `map` again, once it's `const` + // FIXME(const-hack): This should become `map` again, once it's `const` match self.error_len { Some(len) => Some(len as usize), None => None, diff --git a/library/core/src/time.rs b/library/core/src/time.rs index c19eeedb35426..65560dfcf9d2d 100644 --- a/library/core/src/time.rs +++ b/library/core/src/time.rs @@ -213,6 +213,7 @@ impl Duration { // SAFETY: nanos < NANOS_PER_SEC, therefore nanos is within the valid range Duration { secs, nanos: unsafe { Nanoseconds(nanos) } } } else { + // FIXME(const-hack): use `.expect` once that is possible. let secs = match secs.checked_add((nanos / NANOS_PER_SEC) as u64) { Some(secs) => secs, None => panic!("overflow in Duration::new"), @@ -768,6 +769,7 @@ impl Duration { let total_nanos = self.nanos.0 as u64 * rhs as u64; let extra_secs = total_nanos / (NANOS_PER_SEC as u64); let nanos = (total_nanos % (NANOS_PER_SEC as u64)) as u32; + // FIXME(const-hack): use `and_then` once that is possible. if let Some(s) = self.secs.checked_mul(rhs as u64) { if let Some(secs) = s.checked_add(extra_secs) { debug_assert!(nanos < NANOS_PER_SEC); diff --git a/library/core/src/unicode/unicode_data.rs b/library/core/src/unicode/unicode_data.rs index 1b3d6729663b5..9783e81608403 100644 --- a/library/core/src/unicode/unicode_data.rs +++ b/library/core/src/unicode/unicode_data.rs @@ -18,16 +18,14 @@ const fn bitset_search< let bucket_idx = (needle / 64) as usize; let chunk_map_idx = bucket_idx / CHUNK_SIZE; let chunk_piece = bucket_idx % CHUNK_SIZE; - // FIXME: const-hack: Revert to `slice::get` after `const_slice_index` - // feature stabilizes. + // FIXME(const-hack): Revert to `slice::get` when slice indexing becomes possible in const. let chunk_idx = if chunk_map_idx < chunk_idx_map.len() { chunk_idx_map[chunk_map_idx] } else { return false; }; let idx = bitset_chunk_idx[chunk_idx as usize][chunk_piece] as usize; - // FIXME: const-hack: Revert to `slice::get` after `const_slice_index` - // feature stabilizes. + // FIXME(const-hack): Revert to `slice::get` when slice indexing becomes possible in const. let word = if idx < bitset_canonical.len() { bitset_canonical[idx] } else { diff --git a/library/core/tests/hash/mod.rs b/library/core/tests/hash/mod.rs index bdd1c2579ded8..03826fc4c92cd 100644 --- a/library/core/tests/hash/mod.rs +++ b/library/core/tests/hash/mod.rs @@ -16,11 +16,8 @@ impl Default for MyHasher { impl Hasher for MyHasher { fn write(&mut self, buf: &[u8]) { - // FIXME(const_trait_impl): change to for loop - let mut i = 0; - while i < buf.len() { - self.hash += buf[i] as u64; - i += 1; + for byte in buf { + self.hash += *byte as u64; } } fn write_str(&mut self, s: &str) { diff --git a/library/std/src/sys/pal/windows/args.rs b/library/std/src/sys/pal/windows/args.rs index 66e75a8357149..77d82678f1dcc 100644 --- a/library/std/src/sys/pal/windows/args.rs +++ b/library/std/src/sys/pal/windows/args.rs @@ -20,7 +20,7 @@ use crate::{fmt, io, iter, vec}; /// This is the const equivalent to `NonZero::new(n).unwrap()` /// -/// FIXME: This can be removed once `Option::unwrap` is stably const. +/// FIXME(const-hack): This can be removed once `Option::unwrap` is stably const. /// See the `const_option` feature (#67441). const fn non_zero_u16(n: u16) -> NonZero { match NonZero::new(n) { From 7a3a317618885a8949c8b95c9a38f3f9729b1f3c Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 8 Sep 2024 08:54:01 +0200 Subject: [PATCH 0689/2194] remove const_slice_index annotations, it never had a feature gate anyway --- library/core/src/lib.rs | 1 - library/core/src/slice/index.rs | 10 ---------- library/core/src/slice/memchr.rs | 1 - library/core/src/str/traits.rs | 6 ------ tests/ui/consts/const-eval/ub-slice-get-unchecked.rs | 2 -- .../ui/consts/const-eval/ub-slice-get-unchecked.stderr | 2 +- 6 files changed, 1 insertion(+), 21 deletions(-) diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index bda3825436273..5b5d5d1a9610e 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -149,7 +149,6 @@ #![feature(const_size_of_val_raw)] #![feature(const_slice_from_raw_parts_mut)] #![feature(const_slice_from_ref)] -#![feature(const_slice_index)] #![feature(const_slice_split_at_mut)] #![feature(const_str_from_utf8_unchecked_mut)] #![feature(const_strict_overflow_ops)] diff --git a/library/core/src/slice/index.rs b/library/core/src/slice/index.rs index 7adcee1ed6b64..bc8571c8503e9 100644 --- a/library/core/src/slice/index.rs +++ b/library/core/src/slice/index.rs @@ -31,7 +31,6 @@ where #[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold)] #[cfg_attr(feature = "panic_immediate_abort", inline)] #[track_caller] -#[rustc_const_unstable(feature = "const_slice_index", issue = "none")] const fn slice_start_index_len_fail(index: usize, len: usize) -> ! { // FIXME(const-hack): once integer formatting in panics is possible, we // should use the same implementation at compiletime and runtime. @@ -53,7 +52,6 @@ const fn slice_start_index_len_fail_ct(_: usize, _: usize) -> ! { #[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold)] #[cfg_attr(feature = "panic_immediate_abort", inline)] #[track_caller] -#[rustc_const_unstable(feature = "const_slice_index", issue = "none")] const fn slice_end_index_len_fail(index: usize, len: usize) -> ! { // FIXME(const-hack): once integer formatting in panics is possible, we // should use the same implementation at compiletime and runtime. @@ -75,7 +73,6 @@ const fn slice_end_index_len_fail_ct(_: usize, _: usize) -> ! { #[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold)] #[cfg_attr(feature = "panic_immediate_abort", inline)] #[track_caller] -#[rustc_const_unstable(feature = "const_slice_index", issue = "none")] const fn slice_index_order_fail(index: usize, end: usize) -> ! { // FIXME(const-hack): once integer formatting in panics is possible, we // should use the same implementation at compiletime and runtime. @@ -249,7 +246,6 @@ pub unsafe trait SliceIndex: private_slice_index::Sealed { /// The methods `index` and `index_mut` panic if the index is out of bounds. #[stable(feature = "slice_get_slice_impls", since = "1.15.0")] -#[rustc_const_unstable(feature = "const_slice_index", issue = "none")] unsafe impl SliceIndex<[T]> for usize { type Output = T; @@ -389,7 +385,6 @@ unsafe impl SliceIndex<[T]> for ops::IndexRange { /// - the start of the range is greater than the end of the range or /// - the end of the range is out of bounds. #[stable(feature = "slice_get_slice_impls", since = "1.15.0")] -#[rustc_const_unstable(feature = "const_slice_index", issue = "none")] unsafe impl SliceIndex<[T]> for ops::Range { type Output = [T]; @@ -525,7 +520,6 @@ unsafe impl SliceIndex<[T]> for range::Range { /// The methods `index` and `index_mut` panic if the end of the range is out of bounds. #[stable(feature = "slice_get_slice_impls", since = "1.15.0")] -#[rustc_const_unstable(feature = "const_slice_index", issue = "none")] unsafe impl SliceIndex<[T]> for ops::RangeTo { type Output = [T]; @@ -564,7 +558,6 @@ unsafe impl SliceIndex<[T]> for ops::RangeTo { /// The methods `index` and `index_mut` panic if the start of the range is out of bounds. #[stable(feature = "slice_get_slice_impls", since = "1.15.0")] -#[rustc_const_unstable(feature = "const_slice_index", issue = "none")] unsafe impl SliceIndex<[T]> for ops::RangeFrom { type Output = [T]; @@ -647,7 +640,6 @@ unsafe impl SliceIndex<[T]> for range::RangeFrom { } #[stable(feature = "slice_get_slice_impls", since = "1.15.0")] -#[rustc_const_unstable(feature = "const_slice_index", issue = "none")] unsafe impl SliceIndex<[T]> for ops::RangeFull { type Output = [T]; @@ -687,7 +679,6 @@ unsafe impl SliceIndex<[T]> for ops::RangeFull { /// - the start of the range is greater than the end of the range or /// - the end of the range is out of bounds. #[stable(feature = "inclusive_range", since = "1.26.0")] -#[rustc_const_unstable(feature = "const_slice_index", issue = "none")] unsafe impl SliceIndex<[T]> for ops::RangeInclusive { type Output = [T]; @@ -769,7 +760,6 @@ unsafe impl SliceIndex<[T]> for range::RangeInclusive { /// The methods `index` and `index_mut` panic if the end of the range is out of bounds. #[stable(feature = "inclusive_range", since = "1.26.0")] -#[rustc_const_unstable(feature = "const_slice_index", issue = "none")] unsafe impl SliceIndex<[T]> for ops::RangeToInclusive { type Output = [T]; diff --git a/library/core/src/slice/memchr.rs b/library/core/src/slice/memchr.rs index da7ceb2dd0a0d..be19c3d3bc153 100644 --- a/library/core/src/slice/memchr.rs +++ b/library/core/src/slice/memchr.rs @@ -51,7 +51,6 @@ const fn memchr_naive(x: u8, text: &[u8]) -> Option { } #[rustc_allow_const_fn_unstable(const_cmp)] -#[rustc_allow_const_fn_unstable(const_slice_index)] #[rustc_allow_const_fn_unstable(const_align_offset)] #[rustc_const_stable(feature = "const_memchr", since = "1.65.0")] const fn memchr_aligned(x: u8, text: &[u8]) -> Option { diff --git a/library/core/src/str/traits.rs b/library/core/src/str/traits.rs index b69c476ae5e53..77c70b978fd15 100644 --- a/library/core/src/str/traits.rs +++ b/library/core/src/str/traits.rs @@ -92,7 +92,6 @@ const fn str_index_overflow_fail() -> ! { /// /// Equivalent to `&self[0 .. len]` or `&mut self[0 .. len]`. #[stable(feature = "str_checked_slicing", since = "1.20.0")] -#[rustc_const_unstable(feature = "const_slice_index", issue = "none")] unsafe impl SliceIndex for ops::RangeFull { type Output = str; #[inline] @@ -157,7 +156,6 @@ unsafe impl SliceIndex for ops::RangeFull { /// // &s[3 .. 100]; /// ``` #[stable(feature = "str_checked_slicing", since = "1.20.0")] -#[rustc_const_unstable(feature = "const_slice_index", issue = "none")] unsafe impl SliceIndex for ops::Range { type Output = str; #[inline] @@ -429,7 +427,6 @@ unsafe impl SliceIndex for (ops::Bound, ops::Bound) { /// Panics if `end` does not point to the starting byte offset of a /// character (as defined by `is_char_boundary`), or if `end > len`. #[stable(feature = "str_checked_slicing", since = "1.20.0")] -#[rustc_const_unstable(feature = "const_slice_index", issue = "none")] unsafe impl SliceIndex for ops::RangeTo { type Output = str; #[inline] @@ -498,7 +495,6 @@ unsafe impl SliceIndex for ops::RangeTo { /// Panics if `begin` does not point to the starting byte offset of /// a character (as defined by `is_char_boundary`), or if `begin > len`. #[stable(feature = "str_checked_slicing", since = "1.20.0")] -#[rustc_const_unstable(feature = "const_slice_index", issue = "none")] unsafe impl SliceIndex for ops::RangeFrom { type Output = str; #[inline] @@ -625,7 +621,6 @@ unsafe impl SliceIndex for range::RangeFrom { /// to the ending byte offset of a character (`end + 1` is either a starting /// byte offset or equal to `len`), if `begin > end`, or if `end >= len`. #[stable(feature = "inclusive_range", since = "1.26.0")] -#[rustc_const_unstable(feature = "const_slice_index", issue = "none")] unsafe impl SliceIndex for ops::RangeInclusive { type Output = str; #[inline] @@ -714,7 +709,6 @@ unsafe impl SliceIndex for range::RangeInclusive { /// (`end + 1` is either a starting byte offset as defined by /// `is_char_boundary`, or equal to `len`), or if `end >= len`. #[stable(feature = "inclusive_range", since = "1.26.0")] -#[rustc_const_unstable(feature = "const_slice_index", issue = "none")] unsafe impl SliceIndex for ops::RangeToInclusive { type Output = str; #[inline] diff --git a/tests/ui/consts/const-eval/ub-slice-get-unchecked.rs b/tests/ui/consts/const-eval/ub-slice-get-unchecked.rs index 3800abddd4240..e805ac01c9d06 100644 --- a/tests/ui/consts/const-eval/ub-slice-get-unchecked.rs +++ b/tests/ui/consts/const-eval/ub-slice-get-unchecked.rs @@ -1,7 +1,5 @@ //@ known-bug: #110395 -#![feature(const_slice_index)] - const A: [(); 5] = [(), (), (), (), ()]; // Since the indexing is on a ZST, the addresses are all fine, diff --git a/tests/ui/consts/const-eval/ub-slice-get-unchecked.stderr b/tests/ui/consts/const-eval/ub-slice-get-unchecked.stderr index de96821e8b987..94aa3ee4d7a1f 100644 --- a/tests/ui/consts/const-eval/ub-slice-get-unchecked.stderr +++ b/tests/ui/consts/const-eval/ub-slice-get-unchecked.stderr @@ -1,5 +1,5 @@ error[E0015]: cannot call non-const fn `core::slice::::get_unchecked::>` in constants - --> $DIR/ub-slice-get-unchecked.rs:9:29 + --> $DIR/ub-slice-get-unchecked.rs:7:29 | LL | const B: &[()] = unsafe { A.get_unchecked(3..1) }; | ^^^^^^^^^^^^^^^^^^^ From 76260158484b53551caa913772f25a0c8f9a24a2 Mon Sep 17 00:00:00 2001 From: Samuel Thibault Date: Fri, 26 Jul 2024 12:04:05 +0200 Subject: [PATCH 0690/2194] added support for GNU/Hurd on x86_64 --- compiler/rustc_target/src/spec/mod.rs | 1 + .../spec/targets/x86_64_unknown_hurd_gnu.rs | 26 +++++++++++++++++++ src/doc/rustc/src/platform-support.md | 1 + src/doc/rustc/src/platform-support/hurd.md | 7 ++--- tests/assembly/targets/targets-elf.rs | 3 +++ 5 files changed, 35 insertions(+), 3 deletions(-) create mode 100644 compiler/rustc_target/src/spec/targets/x86_64_unknown_hurd_gnu.rs diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index 58d47c201f018..c3e7f74c56410 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -1645,6 +1645,7 @@ supported_targets! { ("x86_64-unknown-haiku", x86_64_unknown_haiku), ("i686-unknown-hurd-gnu", i686_unknown_hurd_gnu), + ("x86_64-unknown-hurd-gnu", x86_64_unknown_hurd_gnu), ("aarch64-apple-darwin", aarch64_apple_darwin), ("arm64e-apple-darwin", arm64e_apple_darwin), diff --git a/compiler/rustc_target/src/spec/targets/x86_64_unknown_hurd_gnu.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_hurd_gnu.rs new file mode 100644 index 0000000000000..6461ece5dd141 --- /dev/null +++ b/compiler/rustc_target/src/spec/targets/x86_64_unknown_hurd_gnu.rs @@ -0,0 +1,26 @@ +use crate::spec::{base, Cc, LinkerFlavor, Lld, StackProbeType, Target}; + +pub(crate) fn target() -> Target { + let mut base = base::hurd_gnu::opts(); + base.cpu = "x86-64".into(); + base.plt_by_default = false; + base.max_atomic_width = Some(64); + base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m64"]); + base.stack_probes = StackProbeType::Inline; + base.supports_xray = true; + + Target { + llvm_target: "x86_64-unknown-hurd-gnu".into(), + metadata: crate::spec::TargetMetadata { + description: Some("64-bit GNU/Hurd".into()), + tier: Some(3), + host_tools: Some(true), + std: Some(true), + }, + pointer_width: 64, + data_layout: + "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128".into(), + arch: "x86_64".into(), + options: base, + } +} diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md index 319dc9a7c08cb..9a35b35af713b 100644 --- a/src/doc/rustc/src/platform-support.md +++ b/src/doc/rustc/src/platform-support.md @@ -382,6 +382,7 @@ target | std | host | notes [`x86_64-unikraft-linux-musl`](platform-support/unikraft-linux-musl.md) | ✓ | | 64-bit Unikraft with musl 1.2.3 `x86_64-unknown-dragonfly` | ✓ | ✓ | 64-bit DragonFlyBSD `x86_64-unknown-haiku` | ✓ | ✓ | 64-bit Haiku +[`x86_64-unknown-hurd-gnu`](platform-support/hurd.md) | ✓ | ✓ | 64-bit GNU/Hurd [`x86_64-unknown-hermit`](platform-support/hermit.md) | ✓ | | x86_64 Hermit `x86_64-unknown-l4re-uclibc` | ? | | [`x86_64-unknown-openbsd`](platform-support/openbsd.md) | ✓ | ✓ | 64-bit OpenBSD diff --git a/src/doc/rustc/src/platform-support/hurd.md b/src/doc/rustc/src/platform-support/hurd.md index ddf40213ed49d..2521f79dc5e65 100644 --- a/src/doc/rustc/src/platform-support/hurd.md +++ b/src/doc/rustc/src/platform-support/hurd.md @@ -1,4 +1,4 @@ -# `i686-unknown-hurd-gnu` +# `i686-unknown-hurd-gnu` and `x86_64-unknown-hurd-gnu` **Tier: 3** @@ -16,7 +16,8 @@ The GNU/Hurd target supports `std` and uses the standard ELF file format. ## Building the target -This target can be built by adding `i686-unknown-hurd-gnu` as target in the rustc list. +This target can be built by adding `i686-unknown-hurd-gnu` and +`x86_64-unknown-hurd-gnu` as targets in the rustc list. ## Building Rust programs @@ -32,4 +33,4 @@ Tests can be run in the same way as a regular binary. ## Cross-compilation toolchains and C code The target supports C code, the GNU toolchain calls the target -`i686-unknown-gnu`. +`i686-unknown-gnu` and `x86_64-unknown-gnu`. diff --git a/tests/assembly/targets/targets-elf.rs b/tests/assembly/targets/targets-elf.rs index c8610e03939da..4e1c5e6806e80 100644 --- a/tests/assembly/targets/targets-elf.rs +++ b/tests/assembly/targets/targets-elf.rs @@ -552,6 +552,9 @@ //@ revisions: x86_64_unknown_haiku //@ [x86_64_unknown_haiku] compile-flags: --target x86_64-unknown-haiku //@ [x86_64_unknown_haiku] needs-llvm-components: x86 +//@ revisions: x86_64_unknown_hurd_gnu +//@ [x86_64_unknown_hurd_gnu] compile-flags: --target x86_64-unknown-hurd-gnu +//@ [x86_64_unknown_hurd_gnu] needs-llvm-components: x86 //@ revisions: x86_64_unknown_hermit //@ [x86_64_unknown_hermit] compile-flags: --target x86_64-unknown-hermit //@ [x86_64_unknown_hermit] needs-llvm-components: x86 From 81227a309c63a6f721bf5552b0579e53790064f3 Mon Sep 17 00:00:00 2001 From: Ali Bektas Date: Sun, 1 Sep 2024 22:07:47 +0200 Subject: [PATCH 0691/2194] Better testing infra for ratoml --- .../crates/rust-analyzer/src/config.rs | 95 +++++---- .../rust-analyzer/src/handlers/request.rs | 28 ++- .../crates/rust-analyzer/src/lsp/ext.rs | 17 +- .../rust-analyzer/tests/slow-tests/ratoml.rs | 189 +++++++++++++----- .../rust-analyzer/docs/dev/lsp-extensions.md | 2 +- 5 files changed, 228 insertions(+), 103 deletions(-) diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs index e4e8c9c6d9f97..b6a1bd158663c 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs @@ -75,6 +75,8 @@ config_data! { /// How many worker threads to handle priming caches. The default `0` means to pick automatically. cachePriming_numThreads: NumThreads = NumThreads::Physical, + /// Custom completion snippets. + completion_snippets_custom: FxHashMap = Config::completion_snippets_default(), /// These directories will be ignored by rust-analyzer. They are @@ -438,48 +440,6 @@ config_data! { completion_postfix_enable: bool = true, /// Enables completions of private items and fields that are defined in the current workspace even if they are not visible at the current position. completion_privateEditable_enable: bool = false, - /// Custom completion snippets. - completion_snippets_custom: FxHashMap = serde_json::from_str(r#"{ - "Arc::new": { - "postfix": "arc", - "body": "Arc::new(${receiver})", - "requires": "std::sync::Arc", - "description": "Put the expression into an `Arc`", - "scope": "expr" - }, - "Rc::new": { - "postfix": "rc", - "body": "Rc::new(${receiver})", - "requires": "std::rc::Rc", - "description": "Put the expression into an `Rc`", - "scope": "expr" - }, - "Box::pin": { - "postfix": "pinbox", - "body": "Box::pin(${receiver})", - "requires": "std::boxed::Box", - "description": "Put the expression into a pinned `Box`", - "scope": "expr" - }, - "Ok": { - "postfix": "ok", - "body": "Ok(${receiver})", - "description": "Wrap the expression in a `Result::Ok`", - "scope": "expr" - }, - "Err": { - "postfix": "err", - "body": "Err(${receiver})", - "description": "Wrap the expression in a `Result::Err`", - "scope": "expr" - }, - "Some": { - "postfix": "some", - "body": "Some(${receiver})", - "description": "Wrap the expression in an `Option::Some`", - "scope": "expr" - } - }"#).unwrap(), /// Whether to enable term search based snippets like `Some(foo.bar().baz())`. completion_termSearch_enable: bool = false, /// Term search fuel in "units of work" for autocompletion (Defaults to 1000). @@ -889,7 +849,7 @@ impl Config { // IMPORTANT : This holds as long as ` completion_snippets_custom` is declared `client`. config.snippets.clear(); - let snips = self.completion_snippets_custom(None).to_owned(); + let snips = self.completion_snippets_custom().to_owned(); for (name, def) in snips.iter() { if def.prefix.is_empty() && def.postfix.is_empty() { @@ -1266,7 +1226,7 @@ pub struct NotificationsConfig { pub cargo_toml_not_found: bool, } -#[derive(Debug, Clone)] +#[derive(Deserialize, Serialize, Debug, Clone)] pub enum RustfmtConfig { Rustfmt { extra_args: Vec, enable_range_formatting: bool }, CustomCommand { command: String, args: Vec }, @@ -1897,6 +1857,53 @@ impl Config { } } + pub(crate) fn completion_snippets_default() -> FxHashMap { + serde_json::from_str( + r#"{ + "Arc::new": { + "postfix": "arc", + "body": "Arc::new(${receiver})", + "requires": "std::sync::Arc", + "description": "Put the expression into an `Arc`", + "scope": "expr" + }, + "Rc::new": { + "postfix": "rc", + "body": "Rc::new(${receiver})", + "requires": "std::rc::Rc", + "description": "Put the expression into an `Rc`", + "scope": "expr" + }, + "Box::pin": { + "postfix": "pinbox", + "body": "Box::pin(${receiver})", + "requires": "std::boxed::Box", + "description": "Put the expression into a pinned `Box`", + "scope": "expr" + }, + "Ok": { + "postfix": "ok", + "body": "Ok(${receiver})", + "description": "Wrap the expression in a `Result::Ok`", + "scope": "expr" + }, + "Err": { + "postfix": "err", + "body": "Err(${receiver})", + "description": "Wrap the expression in a `Result::Err`", + "scope": "expr" + }, + "Some": { + "postfix": "some", + "body": "Some(${receiver})", + "description": "Wrap the expression in an `Option::Some`", + "scope": "expr" + } + }"#, + ) + .unwrap() + } + pub fn rustfmt(&self, source_root_id: Option) -> RustfmtConfig { match &self.rustfmt_overrideCommand(source_root_id) { Some(args) if !args.is_empty() => { diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/request.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/request.rs index 09d5086201779..bcbd970a0d214 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/request.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/request.rs @@ -40,7 +40,10 @@ use crate::{ hack_recover_crate_name, line_index::LineEndings, lsp::{ - ext::InternalTestingFetchConfigParams, + ext::{ + InternalTestingFetchConfigOption, InternalTestingFetchConfigParams, + InternalTestingFetchConfigResponse, + }, from_proto, to_proto, utils::{all_edits_are_disjoint, invalid_params_error}, LspError, @@ -2292,7 +2295,7 @@ pub(crate) fn fetch_dependency_list( pub(crate) fn internal_testing_fetch_config( state: GlobalStateSnapshot, params: InternalTestingFetchConfigParams, -) -> anyhow::Result { +) -> anyhow::Result> { let source_root = params .text_document .map(|it| { @@ -2302,15 +2305,18 @@ pub(crate) fn internal_testing_fetch_config( .map_err(anyhow::Error::from) }) .transpose()?; - serde_json::to_value(match &*params.config { - "local" => state.config.assist(source_root).assist_emit_must_use, - "workspace" => matches!( - state.config.rustfmt(source_root), - RustfmtConfig::Rustfmt { enable_range_formatting: true, .. } - ), - _ => return Err(anyhow::anyhow!("Unknown test config key: {}", params.config)), - }) - .map_err(Into::into) + Ok(Some(match params.config { + InternalTestingFetchConfigOption::AssistEmitMustUse => { + InternalTestingFetchConfigResponse::AssistEmitMustUse( + state.config.assist(source_root).assist_emit_must_use, + ) + } + InternalTestingFetchConfigOption::CheckWorkspace => { + InternalTestingFetchConfigResponse::CheckWorkspace( + state.config.flycheck_workspace(source_root), + ) + } + })) } /// Searches for the directory of a Rust crate given this crate's root file path. diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/ext.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/ext.rs index ed6f16a17302b..618481bbc66b6 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/ext.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/ext.rs @@ -16,9 +16,22 @@ use serde::{Deserialize, Serialize}; pub enum InternalTestingFetchConfig {} +#[derive(Deserialize, Serialize, Debug)] +pub enum InternalTestingFetchConfigOption { + AssistEmitMustUse, + CheckWorkspace, +} + +#[derive(Deserialize, Serialize, Debug, PartialEq, Eq)] +pub enum InternalTestingFetchConfigResponse { + AssistEmitMustUse(bool), + CheckWorkspace(bool), +} + impl Request for InternalTestingFetchConfig { type Params = InternalTestingFetchConfigParams; - type Result = serde_json::Value; + // Option is solely to circumvent Default bound. + type Result = Option; const METHOD: &'static str = "rust-analyzer-internal/internalTestingFetchConfig"; } @@ -26,7 +39,7 @@ impl Request for InternalTestingFetchConfig { #[serde(rename_all = "camelCase")] pub struct InternalTestingFetchConfigParams { pub text_document: Option, - pub config: String, + pub config: InternalTestingFetchConfigOption, } pub enum AnalyzerStatus {} diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/ratoml.rs b/src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/ratoml.rs index 295d1d4e8e909..77048ad83d484 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/ratoml.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/ratoml.rs @@ -9,18 +9,13 @@ use lsp_types::{ use paths::Utf8PathBuf; use rust_analyzer::config::Config; -use rust_analyzer::lsp::ext::{InternalTestingFetchConfig, InternalTestingFetchConfigParams}; +use rust_analyzer::lsp::ext::{ + InternalTestingFetchConfig, InternalTestingFetchConfigOption, InternalTestingFetchConfigParams, + InternalTestingFetchConfigResponse, +}; use serde_json::json; use test_utils::skip_slow_tests; -enum QueryType { - Local, - /// A query whose config key is a part of the global configs, so that - /// testing for changes to this config means testing if global changes - /// take affect. - Workspace, -} - struct RatomlTest { urls: Vec, server: Server, @@ -158,20 +153,24 @@ impl RatomlTest { }); } - fn query(&self, query: QueryType, source_file_idx: usize) -> bool { - let config = match query { - QueryType::Local => "local".to_owned(), - QueryType::Workspace => "workspace".to_owned(), - }; + fn query( + &self, + query: InternalTestingFetchConfigOption, + source_file_idx: usize, + expected: InternalTestingFetchConfigResponse, + ) { let res = self.server.send_request::( InternalTestingFetchConfigParams { text_document: Some(TextDocumentIdentifier { uri: self.urls[source_file_idx].clone(), }), - config, + config: query, }, ); - res.as_bool().unwrap() + assert_eq!( + serde_json::from_value::(res).unwrap(), + expected + ) } } @@ -206,7 +205,11 @@ enum Value { })), ); - assert!(server.query(QueryType::Local, 1)); + server.query( + InternalTestingFetchConfigOption::AssistEmitMustUse, + 1, + InternalTestingFetchConfigResponse::AssistEmitMustUse(true), + ); } /// Checks if client config can be modified. @@ -311,7 +314,11 @@ enum Value { None, ); - assert!(server.query(QueryType::Local, 2)); + server.query( + InternalTestingFetchConfigOption::AssistEmitMustUse, + 2, + InternalTestingFetchConfigResponse::AssistEmitMustUse(true), + ); } #[test] @@ -341,12 +348,20 @@ enum Value { None, ); - assert!(!server.query(QueryType::Local, 1)); + server.query( + InternalTestingFetchConfigOption::AssistEmitMustUse, + 1, + InternalTestingFetchConfigResponse::AssistEmitMustUse(false), + ); server.create( "//- /$$CONFIG_DIR$$/rust-analyzer/rust-analyzer.toml", RatomlTest::EMIT_MUST_USE.to_owned(), ); - assert!(server.query(QueryType::Local, 1)); + server.query( + InternalTestingFetchConfigOption::AssistEmitMustUse, + 1, + InternalTestingFetchConfigResponse::AssistEmitMustUse(true), + ); } #[test] @@ -378,9 +393,17 @@ assist.emitMustUse = true"#, None, ); - assert!(server.query(QueryType::Local, 1)); + server.query( + InternalTestingFetchConfigOption::AssistEmitMustUse, + 1, + InternalTestingFetchConfigResponse::AssistEmitMustUse(true), + ); server.edit(2, String::new()); - assert!(!server.query(QueryType::Local, 1)); + server.query( + InternalTestingFetchConfigOption::AssistEmitMustUse, + 1, + InternalTestingFetchConfigResponse::AssistEmitMustUse(false), + ); } #[test] @@ -412,9 +435,17 @@ assist.emitMustUse = true"#, None, ); - assert!(server.query(QueryType::Local, 1)); + server.query( + InternalTestingFetchConfigOption::AssistEmitMustUse, + 1, + InternalTestingFetchConfigResponse::AssistEmitMustUse(true), + ); server.delete(2); - assert!(!server.query(QueryType::Local, 1)); + server.query( + InternalTestingFetchConfigOption::AssistEmitMustUse, + 1, + InternalTestingFetchConfigResponse::AssistEmitMustUse(false), + ); } #[test] @@ -461,7 +492,11 @@ pub fn add(left: usize, right: usize) -> usize { None, ); - assert!(server.query(QueryType::Local, 3)); + server.query( + InternalTestingFetchConfigOption::AssistEmitMustUse, + 3, + InternalTestingFetchConfigResponse::AssistEmitMustUse(true), + ); } #[test] @@ -508,9 +543,17 @@ pub fn add(left: usize, right: usize) -> usize { None, ); - assert!(!server.query(QueryType::Local, 3)); + server.query( + InternalTestingFetchConfigOption::AssistEmitMustUse, + 3, + InternalTestingFetchConfigResponse::AssistEmitMustUse(false), + ); server.edit(1, "assist.emitMustUse = true".to_owned()); - assert!(server.query(QueryType::Local, 3)); + server.query( + InternalTestingFetchConfigOption::AssistEmitMustUse, + 3, + InternalTestingFetchConfigResponse::AssistEmitMustUse(true), + ); } #[test] @@ -557,9 +600,17 @@ pub fn add(left: usize, right: usize) -> usize { None, ); - assert!(server.query(QueryType::Local, 3)); + server.query( + InternalTestingFetchConfigOption::AssistEmitMustUse, + 3, + InternalTestingFetchConfigResponse::AssistEmitMustUse(true), + ); server.delete(1); - assert!(!server.query(QueryType::Local, 3)); + server.query( + InternalTestingFetchConfigOption::AssistEmitMustUse, + 3, + InternalTestingFetchConfigResponse::AssistEmitMustUse(false), + ); } #[test] @@ -606,9 +657,17 @@ pub fn add(left: usize, right: usize) -> usize { None, ); - assert!(server.query(QueryType::Local, 3)); + server.query( + InternalTestingFetchConfigOption::AssistEmitMustUse, + 3, + InternalTestingFetchConfigResponse::AssistEmitMustUse(true), + ); server.create("//- /p1/p2/rust-analyzer.toml", RatomlTest::EMIT_MUST_NOT_USE.to_owned()); - assert!(!server.query(QueryType::Local, 3)); + server.query( + InternalTestingFetchConfigOption::AssistEmitMustUse, + 3, + InternalTestingFetchConfigResponse::AssistEmitMustUse(false), + ); } #[test] @@ -656,9 +715,17 @@ pub fn add(left: usize, right: usize) -> usize { None, ); - assert!(server.query(QueryType::Local, 3)); + server.query( + InternalTestingFetchConfigOption::AssistEmitMustUse, + 3, + InternalTestingFetchConfigResponse::AssistEmitMustUse(true), + ); server.delete(1); - assert!(!server.query(QueryType::Local, 3)); + server.query( + InternalTestingFetchConfigOption::AssistEmitMustUse, + 3, + InternalTestingFetchConfigResponse::AssistEmitMustUse(false), + ); } #[test] @@ -705,8 +772,16 @@ enum Value { None, ); - assert!(server.query(QueryType::Local, 3)); - assert!(server.query(QueryType::Local, 4)); + server.query( + InternalTestingFetchConfigOption::AssistEmitMustUse, + 3, + InternalTestingFetchConfigResponse::AssistEmitMustUse(true), + ); + server.query( + InternalTestingFetchConfigOption::AssistEmitMustUse, + 4, + InternalTestingFetchConfigResponse::AssistEmitMustUse(true), + ); } #[test] @@ -744,7 +819,11 @@ fn ratoml_multiple_ratoml_in_single_source_root() { None, ); - assert!(server.query(QueryType::Local, 3)); + server.query( + InternalTestingFetchConfigOption::AssistEmitMustUse, + 3, + InternalTestingFetchConfigResponse::AssistEmitMustUse(true), + ); } /// If a root is non-local, so we cannot find what its parent is @@ -836,7 +915,7 @@ edition = "2021" "#, r#" //- /p1/rust-analyzer.toml -rustfmt.rangeFormatting.enable = true +check.workspace = false "#, r#" //- /p1/src/lib.rs @@ -848,7 +927,11 @@ fn main() { None, ); - assert!(server.query(QueryType::Workspace, 2)); + server.query( + InternalTestingFetchConfigOption::CheckWorkspace, + 2, + InternalTestingFetchConfigResponse::CheckWorkspace(false), + ) } #[test] @@ -868,7 +951,7 @@ edition = "2021" "#, r#" //- /p1/rust-analyzer.toml -rustfmt.rangeFormatting.enable = true +check.workspace = false "#, r#" //- /p1/src/lib.rs @@ -880,9 +963,17 @@ fn main() { None, ); - assert!(server.query(QueryType::Workspace, 2)); - server.edit(1, "rustfmt.rangeFormatting.enable = false".to_owned()); - assert!(!server.query(QueryType::Workspace, 2)); + server.query( + InternalTestingFetchConfigOption::CheckWorkspace, + 2, + InternalTestingFetchConfigResponse::CheckWorkspace(false), + ); + server.edit(1, "check.workspace = true".to_owned()); + server.query( + InternalTestingFetchConfigOption::CheckWorkspace, + 2, + InternalTestingFetchConfigResponse::CheckWorkspace(true), + ); } #[test] @@ -902,7 +993,7 @@ edition = "2021" "#, r#" //- /p1/rust-analyzer.toml -rustfmt.rangeFormatting.enable = true +check.workspace = false "#, r#" //- /p1/src/lib.rs @@ -914,7 +1005,15 @@ fn main() { None, ); - assert!(server.query(QueryType::Workspace, 2)); + server.query( + InternalTestingFetchConfigOption::CheckWorkspace, + 2, + InternalTestingFetchConfigResponse::CheckWorkspace(false), + ); server.delete(1); - assert!(!server.query(QueryType::Workspace, 2)); + server.query( + InternalTestingFetchConfigOption::CheckWorkspace, + 2, + InternalTestingFetchConfigResponse::CheckWorkspace(true), + ); } diff --git a/src/tools/rust-analyzer/docs/dev/lsp-extensions.md b/src/tools/rust-analyzer/docs/dev/lsp-extensions.md index 68afacf2db5cb..b7bac4d29fad9 100644 --- a/src/tools/rust-analyzer/docs/dev/lsp-extensions.md +++ b/src/tools/rust-analyzer/docs/dev/lsp-extensions.md @@ -1,5 +1,5 @@ $DIR/libx_pthread_rwlock_moved.rs:LL:CC + | +LL | libc::pthread_rwlock_unlock(&mut rw2 as *mut _); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pthread_rwlock_t can't be moved after first use + | + = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior + = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information + = note: BACKTRACE: + = note: inside `main` at $DIR/libx_pthread_rwlock_moved.rs:LL:CC + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to 1 previous error + From a6735e44ca28207d0f2c87c1f47769fed82b56fe Mon Sep 17 00:00:00 2001 From: Zalathar Date: Mon, 9 Sep 2024 14:11:43 +1000 Subject: [PATCH 0698/2194] Add an explicit ignore message for "up-to-date" tests When running tests without the `--force-rerun` flag, compiletest will automatically skip any tests that (in its judgement) don't need to be run again since the last time they were run. This patch adds an explicit reason to those skipped tests, which is visible when running with `rust.verbose-tests = true` in `config.toml`. --- src/tools/compiletest/src/lib.rs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/tools/compiletest/src/lib.rs b/src/tools/compiletest/src/lib.rs index 5402e69bc664e..3294a3bd080b3 100644 --- a/src/tools/compiletest/src/lib.rs +++ b/src/tools/compiletest/src/lib.rs @@ -808,8 +808,11 @@ fn make_test( &config, cache, test_name, &test_path, src_file, revision, poisoned, ); // Ignore tests that already run and are up to date with respect to inputs. - if !config.force_rerun { - desc.ignore |= is_up_to_date(&config, testpaths, &early_props, revision, inputs); + if !config.force_rerun + && is_up_to_date(&config, testpaths, &early_props, revision, inputs) + { + desc.ignore = true; + desc.ignore_message = Some("up-to-date"); } test::TestDescAndFn { desc, From ec6fe4e19881bafa048e4b9c7c45610a555ff888 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 28 Aug 2024 15:27:51 +1000 Subject: [PATCH 0699/2194] Streamline `AbortUnwindingCalls`. Currently it constructs two vectors `calls_to_terminated` and `cleanups_to_remove` in the main loop, and then processes them after the main loop. But the processing can be done in the main loop, avoiding the need for the vectors. --- .../src/abort_unwinding_calls.rs | 41 +++++++------------ 1 file changed, 14 insertions(+), 27 deletions(-) diff --git a/compiler/rustc_mir_transform/src/abort_unwinding_calls.rs b/compiler/rustc_mir_transform/src/abort_unwinding_calls.rs index 06ec065c91a21..8291df9be5349 100644 --- a/compiler/rustc_mir_transform/src/abort_unwinding_calls.rs +++ b/compiler/rustc_mir_transform/src/abort_unwinding_calls.rs @@ -50,9 +50,7 @@ impl<'tcx> crate::MirPass<'tcx> for AbortUnwindingCalls { // with a function call, and whose function we're calling may unwind. // This will filter to functions with `extern "C-unwind"` ABIs, for // example. - let mut calls_to_terminate = Vec::new(); - let mut cleanups_to_remove = Vec::new(); - for (id, block) in body.basic_blocks.iter_enumerated() { + for block in body.basic_blocks.as_mut() { if block.is_cleanup { continue; } @@ -61,7 +59,7 @@ impl<'tcx> crate::MirPass<'tcx> for AbortUnwindingCalls { let call_can_unwind = match &terminator.kind { TerminatorKind::Call { func, .. } => { - let ty = func.ty(body, tcx); + let ty = func.ty(&body.local_decls, tcx); let sig = ty.fn_sig(tcx); let fn_def_id = match ty.kind() { ty::FnPtr(..) => None, @@ -86,33 +84,22 @@ impl<'tcx> crate::MirPass<'tcx> for AbortUnwindingCalls { _ => continue, }; - // If this function call can't unwind, then there's no need for it - // to have a landing pad. This means that we can remove any cleanup - // registered for it. if !call_can_unwind { - cleanups_to_remove.push(id); - continue; - } - - // Otherwise if this function can unwind, then if the outer function - // can also unwind there's nothing to do. If the outer function - // can't unwind, however, we need to change the landing pad for this - // function call to one that aborts. - if !body_can_unwind { - calls_to_terminate.push(id); + // If this function call can't unwind, then there's no need for it + // to have a landing pad. This means that we can remove any cleanup + // registered for it. + let cleanup = block.terminator_mut().unwind_mut().unwrap(); + *cleanup = UnwindAction::Unreachable; + } else if !body_can_unwind { + // Otherwise if this function can unwind, then if the outer function + // can also unwind there's nothing to do. If the outer function + // can't unwind, however, we need to change the landing pad for this + // function call to one that aborts. + let cleanup = block.terminator_mut().unwind_mut().unwrap(); + *cleanup = UnwindAction::Terminate(UnwindTerminateReason::Abi); } } - for id in calls_to_terminate { - let cleanup = body.basic_blocks_mut()[id].terminator_mut().unwind_mut().unwrap(); - *cleanup = UnwindAction::Terminate(UnwindTerminateReason::Abi); - } - - for id in cleanups_to_remove { - let cleanup = body.basic_blocks_mut()[id].terminator_mut().unwind_mut().unwrap(); - *cleanup = UnwindAction::Unreachable; - } - // We may have invalidated some `cleanup` blocks so clean those up now. super::simplify::remove_dead_blocks(body); } From cc09ab3c7510548ab5bcc23ca2e9e9517cd6acdf Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 29 Aug 2024 15:36:24 +1000 Subject: [PATCH 0700/2194] Simplify `verify_candidate_branch`. Let chains are perfect for this kind of function. --- .../src/early_otherwise_branch.rs | 60 +++++++------------ 1 file changed, 23 insertions(+), 37 deletions(-) diff --git a/compiler/rustc_mir_transform/src/early_otherwise_branch.rs b/compiler/rustc_mir_transform/src/early_otherwise_branch.rs index c18344c3aa3a9..3884321df2a2c 100644 --- a/compiler/rustc_mir_transform/src/early_otherwise_branch.rs +++ b/compiler/rustc_mir_transform/src/early_otherwise_branch.rs @@ -310,42 +310,28 @@ fn verify_candidate_branch<'tcx>( ) -> bool { // In order for the optimization to be correct, the branch must... // ...have exactly one statement - let [statement] = branch.statements.as_slice() else { - return false; - }; - // ...assign the discriminant of `place` in that statement - let StatementKind::Assign(boxed) = &statement.kind else { return false }; - let (discr_place, Rvalue::Discriminant(from_place)) = &**boxed else { return false }; - if *from_place != place { - return false; - } - // ...make that assignment to a local - if discr_place.projection.len() != 0 { - return false; - } - // ...terminate on a `SwitchInt` that invalidates that local - let TerminatorKind::SwitchInt { discr: switch_op, targets, .. } = &branch.terminator().kind - else { - return false; - }; - if *switch_op != Operand::Move(*discr_place) { - return false; - } - // ...fall through to `destination` if the switch misses - if destination != targets.otherwise() { - return false; - } - // ...have a branch for value `value` - let mut iter = targets.iter(); - let Some((target_value, _)) = iter.next() else { - return false; - }; - if target_value != value { - return false; - } - // ...and have no more branches - if let Some(_) = iter.next() { - return false; + if let [statement] = branch.statements.as_slice() + // ...assign the discriminant of `place` in that statement + && let StatementKind::Assign(boxed) = &statement.kind + && let (discr_place, Rvalue::Discriminant(from_place)) = &**boxed + && *from_place == place + // ...make that assignment to a local + && discr_place.projection.is_empty() + // ...terminate on a `SwitchInt` that invalidates that local + && let TerminatorKind::SwitchInt { discr: switch_op, targets, .. } = + &branch.terminator().kind + && *switch_op == Operand::Move(*discr_place) + // ...fall through to `destination` if the switch misses + && destination == targets.otherwise() + // ...have a branch for value `value` + && let mut iter = targets.iter() + && let Some((target_value, _)) = iter.next() + && target_value == value + // ...and have no more branches + && iter.next().is_none() + { + true + } else { + false } - true } From 181fbd5ce8bd943e9b78fdd71dfb8f069ea44072 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 9 Sep 2024 08:49:47 +1000 Subject: [PATCH 0701/2194] Use `let`/`else` to de-indent `ElaborateBoxDerefs::run_pass`. --- .../src/elaborate_box_derefs.rs | 91 +++++++++---------- 1 file changed, 44 insertions(+), 47 deletions(-) diff --git a/compiler/rustc_mir_transform/src/elaborate_box_derefs.rs b/compiler/rustc_mir_transform/src/elaborate_box_derefs.rs index d2ef648a20ffa..367a8c0759315 100644 --- a/compiler/rustc_mir_transform/src/elaborate_box_derefs.rs +++ b/compiler/rustc_mir_transform/src/elaborate_box_derefs.rs @@ -92,64 +92,61 @@ pub(super) struct ElaborateBoxDerefs; impl<'tcx> crate::MirPass<'tcx> for ElaborateBoxDerefs { fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { - if let Some(def_id) = tcx.lang_items().owned_box() { - let unique_did = tcx.adt_def(def_id).non_enum_variant().fields[FieldIdx::ZERO].did; + // If box is not present, this pass doesn't need to do anything. + let Some(def_id) = tcx.lang_items().owned_box() else { return }; - let Some(nonnull_def) = tcx.type_of(unique_did).instantiate_identity().ty_adt_def() - else { - span_bug!(tcx.def_span(unique_did), "expected Box to contain Unique") - }; + let unique_did = tcx.adt_def(def_id).non_enum_variant().fields[FieldIdx::ZERO].did; - let nonnull_did = nonnull_def.non_enum_variant().fields[FieldIdx::ZERO].did; + let Some(nonnull_def) = tcx.type_of(unique_did).instantiate_identity().ty_adt_def() else { + span_bug!(tcx.def_span(unique_did), "expected Box to contain Unique") + }; - let patch = MirPatch::new(body); + let nonnull_did = nonnull_def.non_enum_variant().fields[FieldIdx::ZERO].did; - let local_decls = &mut body.local_decls; + let patch = MirPatch::new(body); - let mut visitor = - ElaborateBoxDerefVisitor { tcx, unique_did, nonnull_did, local_decls, patch }; + let local_decls = &mut body.local_decls; - for (block, data) in body.basic_blocks.as_mut_preserves_cfg().iter_enumerated_mut() { - visitor.visit_basic_block_data(block, data); - } + let mut visitor = + ElaborateBoxDerefVisitor { tcx, unique_did, nonnull_did, local_decls, patch }; - visitor.patch.apply(body); - - for debug_info in body.var_debug_info.iter_mut() { - if let VarDebugInfoContents::Place(place) = &mut debug_info.value { - let mut new_projections: Option> = None; - - for (base, elem) in place.iter_projections() { - let base_ty = base.ty(&body.local_decls, tcx).ty; - - if let PlaceElem::Deref = elem - && let Some(boxed_ty) = base_ty.boxed_ty() - { - // Clone the projections before us, since now we need to mutate them. - let new_projections = - new_projections.get_or_insert_with(|| base.projection.to_vec()); - - let (unique_ty, nonnull_ty, ptr_ty) = - build_ptr_tys(tcx, boxed_ty, unique_did, nonnull_did); - - new_projections.extend_from_slice(&build_projection( - unique_ty, nonnull_ty, ptr_ty, - )); - new_projections.push(PlaceElem::Deref); - } else if let Some(new_projections) = new_projections.as_mut() { - // Keep building up our projections list once we've started it. - new_projections.push(elem); - } - } + for (block, data) in body.basic_blocks.as_mut_preserves_cfg().iter_enumerated_mut() { + visitor.visit_basic_block_data(block, data); + } + + visitor.patch.apply(body); + + for debug_info in body.var_debug_info.iter_mut() { + if let VarDebugInfoContents::Place(place) = &mut debug_info.value { + let mut new_projections: Option> = None; - // Store the mutated projections if we actually changed something. - if let Some(new_projections) = new_projections { - place.projection = tcx.mk_place_elems(&new_projections); + for (base, elem) in place.iter_projections() { + let base_ty = base.ty(&body.local_decls, tcx).ty; + + if let PlaceElem::Deref = elem + && let Some(boxed_ty) = base_ty.boxed_ty() + { + // Clone the projections before us, since now we need to mutate them. + let new_projections = + new_projections.get_or_insert_with(|| base.projection.to_vec()); + + let (unique_ty, nonnull_ty, ptr_ty) = + build_ptr_tys(tcx, boxed_ty, unique_did, nonnull_did); + + new_projections + .extend_from_slice(&build_projection(unique_ty, nonnull_ty, ptr_ty)); + new_projections.push(PlaceElem::Deref); + } else if let Some(new_projections) = new_projections.as_mut() { + // Keep building up our projections list once we've started it. + new_projections.push(elem); } } + + // Store the mutated projections if we actually changed something. + if let Some(new_projections) = new_projections { + place.projection = tcx.mk_place_elems(&new_projections); + } } - } else { - // box is not present, this pass doesn't need to do anything } } } From 4f2588f23a8e71bc9244990b7331accf02f83348 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 30 Aug 2024 15:57:43 +1000 Subject: [PATCH 0702/2194] Remove an unnecessary `continue`. Nothing comes after it within the loop. --- compiler/rustc_mir_transform/src/inline.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/compiler/rustc_mir_transform/src/inline.rs b/compiler/rustc_mir_transform/src/inline.rs index 9d2addecb6e50..b65e8c097d12d 100644 --- a/compiler/rustc_mir_transform/src/inline.rs +++ b/compiler/rustc_mir_transform/src/inline.rs @@ -158,7 +158,6 @@ impl<'tcx> Inliner<'tcx> { match self.try_inlining(caller_body, &callsite) { Err(reason) => { debug!("not-inlined {} [{}]", callsite.callee, reason); - continue; } Ok(new_blocks) => { debug!("inlined {}", callsite.callee); From 9cf90b9fc987a58c873643fbd0e26296b9675943 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 30 Aug 2024 16:09:47 +1000 Subject: [PATCH 0703/2194] Remove some unnecessary dereferences. --- compiler/rustc_mir_transform/src/inline.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_mir_transform/src/inline.rs b/compiler/rustc_mir_transform/src/inline.rs index b65e8c097d12d..702efabe87193 100644 --- a/compiler/rustc_mir_transform/src/inline.rs +++ b/compiler/rustc_mir_transform/src/inline.rs @@ -639,7 +639,7 @@ impl<'tcx> Inliner<'tcx> { ); let dest_ty = dest.ty(caller_body, self.tcx); let temp = - Place::from(self.new_call_temp(caller_body, &callsite, dest_ty, return_block)); + Place::from(self.new_call_temp(caller_body, callsite, dest_ty, return_block)); caller_body[callsite.block].statements.push(Statement { source_info: callsite.source_info, kind: StatementKind::Assign(Box::new((temp, dest))), @@ -658,7 +658,7 @@ impl<'tcx> Inliner<'tcx> { true, self.new_call_temp( caller_body, - &callsite, + callsite, destination.ty(caller_body, self.tcx).ty, return_block, ), @@ -666,7 +666,7 @@ impl<'tcx> Inliner<'tcx> { }; // Copy the arguments if needed. - let args = self.make_call_args(args, &callsite, caller_body, &callee_body, return_block); + let args = self.make_call_args(args, callsite, caller_body, &callee_body, return_block); let mut integrator = Integrator { args: &args, From 7adde3f07494df316698c330f39a00e8105d53b1 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 30 Aug 2024 16:10:03 +1000 Subject: [PATCH 0704/2194] Make `CallSite` non-`Copy`. It doesn't need to be, and it's 72 bytes on 64-bit platforms, which is fairly large. --- compiler/rustc_mir_transform/src/inline.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_mir_transform/src/inline.rs b/compiler/rustc_mir_transform/src/inline.rs index 702efabe87193..03ef808efecb6 100644 --- a/compiler/rustc_mir_transform/src/inline.rs +++ b/compiler/rustc_mir_transform/src/inline.rs @@ -36,7 +36,7 @@ const TOP_DOWN_DEPTH_LIMIT: usize = 5; // by custom rustc drivers, running all the steps by themselves. See #114628. pub struct Inline; -#[derive(Copy, Clone, Debug)] +#[derive(Clone, Debug)] struct CallSite<'tcx> { callee: Instance<'tcx>, fn_sig: ty::PolyFnSig<'tcx>, From 751c8b481b71f47f8e337bd8e097af06bdcca0bc Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 30 Aug 2024 17:08:51 +1000 Subject: [PATCH 0705/2194] Use `LocalDecls` in a couple of places. It's nicer than the `IndexVec` type. --- compiler/rustc_mir_transform/src/add_subtyping_projections.rs | 3 +-- compiler/rustc_mir_transform/src/deref_separator.rs | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_mir_transform/src/add_subtyping_projections.rs b/compiler/rustc_mir_transform/src/add_subtyping_projections.rs index 5e43937fbe69c..ab6bf18b30cb3 100644 --- a/compiler/rustc_mir_transform/src/add_subtyping_projections.rs +++ b/compiler/rustc_mir_transform/src/add_subtyping_projections.rs @@ -1,4 +1,3 @@ -use rustc_index::IndexVec; use rustc_middle::mir::patch::MirPatch; use rustc_middle::mir::visit::MutVisitor; use rustc_middle::mir::*; @@ -9,7 +8,7 @@ pub(super) struct Subtyper; struct SubTypeChecker<'a, 'tcx> { tcx: TyCtxt<'tcx>, patcher: MirPatch<'tcx>, - local_decls: &'a IndexVec>, + local_decls: &'a LocalDecls<'tcx>, } impl<'a, 'tcx> MutVisitor<'tcx> for SubTypeChecker<'a, 'tcx> { diff --git a/compiler/rustc_mir_transform/src/deref_separator.rs b/compiler/rustc_mir_transform/src/deref_separator.rs index 60bf323613d29..ad7ccef4976aa 100644 --- a/compiler/rustc_mir_transform/src/deref_separator.rs +++ b/compiler/rustc_mir_transform/src/deref_separator.rs @@ -1,4 +1,3 @@ -use rustc_index::IndexVec; use rustc_middle::mir::patch::MirPatch; use rustc_middle::mir::visit::NonUseContext::VarDebugInfo; use rustc_middle::mir::visit::{MutVisitor, PlaceContext}; @@ -10,7 +9,7 @@ pub(super) struct Derefer; struct DerefChecker<'a, 'tcx> { tcx: TyCtxt<'tcx>, patcher: MirPatch<'tcx>, - local_decls: &'a IndexVec>, + local_decls: &'a LocalDecls<'tcx>, } impl<'a, 'tcx> MutVisitor<'tcx> for DerefChecker<'a, 'tcx> { From 54459536591630d33a864e89520638c52d8bcf56 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 3 Sep 2024 11:31:46 +1000 Subject: [PATCH 0706/2194] Improve consistency in `LowerIntrinsics`. In some cases `target` and `arg` are obtained fallibly, and in some cases they are obtained infallibly. This commit changes them all to infallible. --- .../src/lower_intrinsics.rs | 125 +++++++++--------- 1 file changed, 63 insertions(+), 62 deletions(-) diff --git a/compiler/rustc_mir_transform/src/lower_intrinsics.rs b/compiler/rustc_mir_transform/src/lower_intrinsics.rs index 134a4cad265b4..6d635606687a9 100644 --- a/compiler/rustc_mir_transform/src/lower_intrinsics.rs +++ b/compiler/rustc_mir_transform/src/lower_intrinsics.rs @@ -35,20 +35,19 @@ impl<'tcx> crate::MirPass<'tcx> for LowerIntrinsics { terminator.kind = TerminatorKind::Goto { target }; } sym::forget => { - if let Some(target) = *target { - block.statements.push(Statement { - source_info: terminator.source_info, - kind: StatementKind::Assign(Box::new(( - *destination, - Rvalue::Use(Operand::Constant(Box::new(ConstOperand { - span: terminator.source_info.span, - user_ty: None, - const_: Const::zero_sized(tcx.types.unit), - }))), - ))), - }); - terminator.kind = TerminatorKind::Goto { target }; - } + let target = target.unwrap(); + block.statements.push(Statement { + source_info: terminator.source_info, + kind: StatementKind::Assign(Box::new(( + *destination, + Rvalue::Use(Operand::Constant(Box::new(ConstOperand { + span: terminator.source_info.span, + user_ty: None, + const_: Const::zero_sized(tcx.types.unit), + }))), + ))), + }); + terminator.kind = TerminatorKind::Goto { target }; } sym::copy_nonoverlapping => { let target = target.unwrap(); @@ -121,43 +120,41 @@ impl<'tcx> crate::MirPass<'tcx> for LowerIntrinsics { terminator.kind = TerminatorKind::Goto { target }; } sym::add_with_overflow | sym::sub_with_overflow | sym::mul_with_overflow => { - if let Some(target) = *target { - let Ok([lhs, rhs]) = take_array(args) else { - bug!("Wrong arguments for {} intrinsic", intrinsic.name); - }; - let bin_op = match intrinsic.name { - sym::add_with_overflow => BinOp::AddWithOverflow, - sym::sub_with_overflow => BinOp::SubWithOverflow, - sym::mul_with_overflow => BinOp::MulWithOverflow, - _ => bug!("unexpected intrinsic"), - }; - block.statements.push(Statement { - source_info: terminator.source_info, - kind: StatementKind::Assign(Box::new(( - *destination, - Rvalue::BinaryOp(bin_op, Box::new((lhs.node, rhs.node))), - ))), - }); - terminator.kind = TerminatorKind::Goto { target }; - } + let target = target.unwrap(); + let Ok([lhs, rhs]) = take_array(args) else { + bug!("Wrong arguments for {} intrinsic", intrinsic.name); + }; + let bin_op = match intrinsic.name { + sym::add_with_overflow => BinOp::AddWithOverflow, + sym::sub_with_overflow => BinOp::SubWithOverflow, + sym::mul_with_overflow => BinOp::MulWithOverflow, + _ => bug!("unexpected intrinsic"), + }; + block.statements.push(Statement { + source_info: terminator.source_info, + kind: StatementKind::Assign(Box::new(( + *destination, + Rvalue::BinaryOp(bin_op, Box::new((lhs.node, rhs.node))), + ))), + }); + terminator.kind = TerminatorKind::Goto { target }; } sym::size_of | sym::min_align_of => { - if let Some(target) = *target { - let tp_ty = generic_args.type_at(0); - let null_op = match intrinsic.name { - sym::size_of => NullOp::SizeOf, - sym::min_align_of => NullOp::AlignOf, - _ => bug!("unexpected intrinsic"), - }; - block.statements.push(Statement { - source_info: terminator.source_info, - kind: StatementKind::Assign(Box::new(( - *destination, - Rvalue::NullaryOp(null_op, tp_ty), - ))), - }); - terminator.kind = TerminatorKind::Goto { target }; - } + let target = target.unwrap(); + let tp_ty = generic_args.type_at(0); + let null_op = match intrinsic.name { + sym::size_of => NullOp::SizeOf, + sym::min_align_of => NullOp::AlignOf, + _ => bug!("unexpected intrinsic"), + }; + block.statements.push(Statement { + source_info: terminator.source_info, + kind: StatementKind::Assign(Box::new(( + *destination, + Rvalue::NullaryOp(null_op, tp_ty), + ))), + }); + terminator.kind = TerminatorKind::Goto { target }; } sym::read_via_copy => { let Ok([arg]) = take_array(args) else { @@ -219,17 +216,23 @@ impl<'tcx> crate::MirPass<'tcx> for LowerIntrinsics { terminator.kind = TerminatorKind::Goto { target }; } sym::discriminant_value => { - if let (Some(target), Some(arg)) = (*target, args[0].node.place()) { - let arg = tcx.mk_place_deref(arg); - block.statements.push(Statement { - source_info: terminator.source_info, - kind: StatementKind::Assign(Box::new(( - *destination, - Rvalue::Discriminant(arg), - ))), - }); - terminator.kind = TerminatorKind::Goto { target }; - } + let target = target.unwrap(); + let Ok([arg]) = take_array(args) else { + span_bug!( + terminator.source_info.span, + "Wrong arguments for discriminant_value intrinsic" + ); + }; + let arg = arg.node.place().unwrap(); + let arg = tcx.mk_place_deref(arg); + block.statements.push(Statement { + source_info: terminator.source_info, + kind: StatementKind::Assign(Box::new(( + *destination, + Rvalue::Discriminant(arg), + ))), + }); + terminator.kind = TerminatorKind::Goto { target }; } sym::offset => { let target = target.unwrap(); @@ -267,7 +270,6 @@ impl<'tcx> crate::MirPass<'tcx> for LowerIntrinsics { Rvalue::Cast(CastKind::Transmute, arg.node, dst_ty), ))), }); - if let Some(target) = *target { terminator.kind = TerminatorKind::Goto { target }; } else { @@ -299,7 +301,6 @@ impl<'tcx> crate::MirPass<'tcx> for LowerIntrinsics { Rvalue::Aggregate(Box::new(kind), fields.into()), ))), }); - terminator.kind = TerminatorKind::Goto { target }; } sym::ptr_metadata => { From acccb39bff3c589b286c2dfe0d2f2afc8d1a3775 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Mon, 9 Sep 2024 14:30:02 +1000 Subject: [PATCH 0707/2194] Print a helpful message if any tests were skipped for being up-to-date --- src/bootstrap/src/utils/render_tests.rs | 15 +++++++++++++++ src/tools/compiletest/src/lib.rs | 1 + 2 files changed, 16 insertions(+) diff --git a/src/bootstrap/src/utils/render_tests.rs b/src/bootstrap/src/utils/render_tests.rs index b8aebc2854906..eb2c8254dc0f4 100644 --- a/src/bootstrap/src/utils/render_tests.rs +++ b/src/bootstrap/src/utils/render_tests.rs @@ -88,6 +88,9 @@ struct Renderer<'a> { builder: &'a Builder<'a>, tests_count: Option, executed_tests: usize, + /// Number of tests that were skipped due to already being up-to-date + /// (i.e. no relevant changes occurred since they last ran). + up_to_date_tests: usize, terse_tests_in_line: usize, } @@ -100,6 +103,7 @@ impl<'a> Renderer<'a> { builder, tests_count: None, executed_tests: 0, + up_to_date_tests: 0, terse_tests_in_line: 0, } } @@ -127,6 +131,12 @@ impl<'a> Renderer<'a> { } } } + + if self.up_to_date_tests > 0 { + let n = self.up_to_date_tests; + let s = if n > 1 { "s" } else { "" }; + println!("help: ignored {n} up-to-date test{s}; use `--force-rerun` to prevent this\n"); + } } /// Renders the stdout characters one by one @@ -149,6 +159,11 @@ impl<'a> Renderer<'a> { fn render_test_outcome(&mut self, outcome: Outcome<'_>, test: &TestOutcome) { self.executed_tests += 1; + // Keep this in sync with the "up-to-date" ignore message inserted by compiletest. + if let Outcome::Ignored { reason: Some("up-to-date") } = outcome { + self.up_to_date_tests += 1; + } + #[cfg(feature = "build-metrics")] self.builder.metrics.record_test( &test.name, diff --git a/src/tools/compiletest/src/lib.rs b/src/tools/compiletest/src/lib.rs index 3294a3bd080b3..33687a3dad35b 100644 --- a/src/tools/compiletest/src/lib.rs +++ b/src/tools/compiletest/src/lib.rs @@ -812,6 +812,7 @@ fn make_test( && is_up_to_date(&config, testpaths, &early_props, revision, inputs) { desc.ignore = true; + // Keep this in sync with the "up-to-date" message detected by bootstrap. desc.ignore_message = Some("up-to-date"); } test::TestDescAndFn { From 3fe7dd6893aa1ee6d02f6112697e2a4abb62254f Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 6 Sep 2024 09:18:17 +1000 Subject: [PATCH 0708/2194] Remove unnecessary lifetimes in dataflow structs. There are four related dataflow structs: `MaybeInitializedPlaces`, `MaybeUninitializedPlaces`, and `EverInitializedPlaces`, `DefinitelyInitializedPlaces`. They all have a `&Body` and a `&MoveData<'tcx>` field. The first three use different lifetimes for the two fields, but the last one uses the same lifetime for both. This commit changes the first three to use the same lifetime, removing the need for one of the lifetimes. Other structs that also lose a lifetime as a result of this are `LivenessContext`, `LivenessResults`, `InitializationData`. It then does similar things in various other structs. --- .../rustc_borrowck/src/borrowck_errors.rs | 2 +- compiler/rustc_borrowck/src/dataflow.rs | 39 +++++----- .../src/diagnostics/bound_region_errors.rs | 14 ++-- .../src/diagnostics/conflict_errors.rs | 8 +- .../src/diagnostics/explain_borrow.rs | 2 +- .../rustc_borrowck/src/diagnostics/mod.rs | 4 +- .../src/diagnostics/move_errors.rs | 2 +- .../src/diagnostics/mutability_errors.rs | 2 +- .../src/diagnostics/outlives_suggestion.rs | 8 +- .../src/diagnostics/region_errors.rs | 2 +- .../src/diagnostics/region_name.rs | 2 +- compiler/rustc_borrowck/src/lib.rs | 73 +++++++++---------- compiler/rustc_borrowck/src/nll.rs | 4 +- compiler/rustc_borrowck/src/prefixes.rs | 2 +- .../src/type_check/liveness/mod.rs | 4 +- .../src/type_check/liveness/trace.rs | 28 +++---- compiler/rustc_borrowck/src/type_check/mod.rs | 4 +- compiler/rustc_borrowck/src/used_muts.rs | 12 +-- .../src/impls/initialized.rs | 46 ++++++------ .../src/elaborate_drops.rs | 34 ++++----- 20 files changed, 141 insertions(+), 151 deletions(-) diff --git a/compiler/rustc_borrowck/src/borrowck_errors.rs b/compiler/rustc_borrowck/src/borrowck_errors.rs index 2c672dbf8c4ae..3a7e407f3e7a6 100644 --- a/compiler/rustc_borrowck/src/borrowck_errors.rs +++ b/compiler/rustc_borrowck/src/borrowck_errors.rs @@ -8,7 +8,7 @@ use rustc_middle::span_bug; use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_span::Span; -impl<'infcx, 'tcx> crate::MirBorrowckCtxt<'_, '_, 'infcx, 'tcx> { +impl<'infcx, 'tcx> crate::MirBorrowckCtxt<'_, 'infcx, 'tcx> { pub(crate) fn dcx(&self) -> DiagCtxtHandle<'infcx> { self.infcx.dcx() } diff --git a/compiler/rustc_borrowck/src/dataflow.rs b/compiler/rustc_borrowck/src/dataflow.rs index 9bb6109e66d95..39994ad784a95 100644 --- a/compiler/rustc_borrowck/src/dataflow.rs +++ b/compiler/rustc_borrowck/src/dataflow.rs @@ -15,24 +15,24 @@ use tracing::debug; use crate::{places_conflict, BorrowSet, PlaceConflictBias, PlaceExt, RegionInferenceContext}; /// The results of the dataflow analyses used by the borrow checker. -pub(crate) struct BorrowckResults<'a, 'mir, 'tcx> { - pub(crate) borrows: Results<'tcx, Borrows<'a, 'mir, 'tcx>>, - pub(crate) uninits: Results<'tcx, MaybeUninitializedPlaces<'a, 'mir, 'tcx>>, - pub(crate) ever_inits: Results<'tcx, EverInitializedPlaces<'a, 'mir, 'tcx>>, +pub(crate) struct BorrowckResults<'a, 'tcx> { + pub(crate) borrows: Results<'tcx, Borrows<'a, 'tcx>>, + pub(crate) uninits: Results<'tcx, MaybeUninitializedPlaces<'a, 'tcx>>, + pub(crate) ever_inits: Results<'tcx, EverInitializedPlaces<'a, 'tcx>>, } /// The transient state of the dataflow analyses used by the borrow checker. #[derive(Debug)] -pub(crate) struct BorrowckFlowState<'a, 'mir, 'tcx> { - pub(crate) borrows: as AnalysisDomain<'tcx>>::Domain, - pub(crate) uninits: as AnalysisDomain<'tcx>>::Domain, - pub(crate) ever_inits: as AnalysisDomain<'tcx>>::Domain, +pub(crate) struct BorrowckFlowState<'a, 'tcx> { + pub(crate) borrows: as AnalysisDomain<'tcx>>::Domain, + pub(crate) uninits: as AnalysisDomain<'tcx>>::Domain, + pub(crate) ever_inits: as AnalysisDomain<'tcx>>::Domain, } -impl<'a, 'mir, 'tcx> ResultsVisitable<'tcx> for BorrowckResults<'a, 'mir, 'tcx> { +impl<'a, 'tcx> ResultsVisitable<'tcx> for BorrowckResults<'a, 'tcx> { // All three analyses are forward, but we have to use just one here. - type Direction = as AnalysisDomain<'tcx>>::Direction; - type FlowState = BorrowckFlowState<'a, 'mir, 'tcx>; + type Direction = as AnalysisDomain<'tcx>>::Direction; + type FlowState = BorrowckFlowState<'a, 'tcx>; fn new_flow_state(&self, body: &mir::Body<'tcx>) -> Self::FlowState { BorrowckFlowState { @@ -106,10 +106,9 @@ rustc_index::newtype_index! { /// `BorrowIndex`, and maps each such index to a `BorrowData` /// describing the borrow. These indexes are used for representing the /// borrows in compact bitvectors. -pub struct Borrows<'a, 'mir, 'tcx> { +pub struct Borrows<'a, 'tcx> { tcx: TyCtxt<'tcx>, - body: &'mir Body<'tcx>, - + body: &'a Body<'tcx>, borrow_set: &'a BorrowSet<'tcx>, borrows_out_of_scope_at_location: FxIndexMap>, } @@ -389,10 +388,10 @@ impl<'tcx> PoloniusOutOfScopePrecomputer<'_, 'tcx> { } } -impl<'a, 'mir, 'tcx> Borrows<'a, 'mir, 'tcx> { +impl<'a, 'tcx> Borrows<'a, 'tcx> { pub fn new( tcx: TyCtxt<'tcx>, - body: &'mir Body<'tcx>, + body: &'a Body<'tcx>, regioncx: &RegionInferenceContext<'tcx>, borrow_set: &'a BorrowSet<'tcx>, ) -> Self { @@ -494,7 +493,7 @@ impl<'a, 'mir, 'tcx> Borrows<'a, 'mir, 'tcx> { } } -impl<'tcx> rustc_mir_dataflow::AnalysisDomain<'tcx> for Borrows<'_, '_, 'tcx> { +impl<'tcx> rustc_mir_dataflow::AnalysisDomain<'tcx> for Borrows<'_, 'tcx> { type Domain = BitSet; const NAME: &'static str = "borrows"; @@ -517,7 +516,7 @@ impl<'tcx> rustc_mir_dataflow::AnalysisDomain<'tcx> for Borrows<'_, '_, 'tcx> { /// region stops containing the CFG points reachable from the issuing location. /// - we also kill loans of conflicting places when overwriting a shared path: e.g. borrows of /// `a.b.c` when `a` is overwritten. -impl<'tcx> rustc_mir_dataflow::GenKillAnalysis<'tcx> for Borrows<'_, '_, 'tcx> { +impl<'tcx> rustc_mir_dataflow::GenKillAnalysis<'tcx> for Borrows<'_, 'tcx> { type Idx = BorrowIndex; fn domain_size(&self, _: &mir::Body<'tcx>) -> usize { @@ -617,8 +616,8 @@ impl<'tcx> rustc_mir_dataflow::GenKillAnalysis<'tcx> for Borrows<'_, '_, 'tcx> { } } -impl DebugWithContext> for BorrowIndex { - fn fmt_with(&self, ctxt: &Borrows<'_, '_, '_>, f: &mut fmt::Formatter<'_>) -> fmt::Result { +impl DebugWithContext> for BorrowIndex { + fn fmt_with(&self, ctxt: &Borrows<'_, '_>, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "{:?}", ctxt.location(*self)) } } diff --git a/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs index 8a4e89d47bdc0..ee28e556cbc34 100644 --- a/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs @@ -52,7 +52,7 @@ impl<'tcx> UniverseInfo<'tcx> { pub(crate) fn report_error( &self, - mbcx: &mut MirBorrowckCtxt<'_, '_, '_, 'tcx>, + mbcx: &mut MirBorrowckCtxt<'_, '_, 'tcx>, placeholder: ty::PlaceholderRegion, error_element: RegionElement, cause: ObligationCause<'tcx>, @@ -151,7 +151,7 @@ trait TypeOpInfo<'tcx> { fn nice_error<'infcx>( &self, - mbcx: &mut MirBorrowckCtxt<'_, '_, 'infcx, 'tcx>, + mbcx: &mut MirBorrowckCtxt<'_, 'infcx, 'tcx>, cause: ObligationCause<'tcx>, placeholder_region: ty::Region<'tcx>, error_region: Option>, @@ -160,7 +160,7 @@ trait TypeOpInfo<'tcx> { #[instrument(level = "debug", skip(self, mbcx))] fn report_error( &self, - mbcx: &mut MirBorrowckCtxt<'_, '_, '_, 'tcx>, + mbcx: &mut MirBorrowckCtxt<'_, '_, 'tcx>, placeholder: ty::PlaceholderRegion, error_element: RegionElement, cause: ObligationCause<'tcx>, @@ -233,7 +233,7 @@ impl<'tcx> TypeOpInfo<'tcx> for PredicateQuery<'tcx> { fn nice_error<'infcx>( &self, - mbcx: &mut MirBorrowckCtxt<'_, '_, 'infcx, 'tcx>, + mbcx: &mut MirBorrowckCtxt<'_, 'infcx, 'tcx>, cause: ObligationCause<'tcx>, placeholder_region: ty::Region<'tcx>, error_region: Option>, @@ -277,7 +277,7 @@ where fn nice_error<'infcx>( &self, - mbcx: &mut MirBorrowckCtxt<'_, '_, 'infcx, 'tcx>, + mbcx: &mut MirBorrowckCtxt<'_, 'infcx, 'tcx>, cause: ObligationCause<'tcx>, placeholder_region: ty::Region<'tcx>, error_region: Option>, @@ -324,7 +324,7 @@ impl<'tcx> TypeOpInfo<'tcx> for AscribeUserTypeQuery<'tcx> { fn nice_error<'infcx>( &self, - mbcx: &mut MirBorrowckCtxt<'_, '_, 'infcx, 'tcx>, + mbcx: &mut MirBorrowckCtxt<'_, 'infcx, 'tcx>, cause: ObligationCause<'tcx>, placeholder_region: ty::Region<'tcx>, error_region: Option>, @@ -357,7 +357,7 @@ impl<'tcx> TypeOpInfo<'tcx> for crate::type_check::InstantiateOpaqueType<'tcx> { fn nice_error<'infcx>( &self, - mbcx: &mut MirBorrowckCtxt<'_, '_, 'infcx, 'tcx>, + mbcx: &mut MirBorrowckCtxt<'_, 'infcx, 'tcx>, _cause: ObligationCause<'tcx>, placeholder_region: ty::Region<'tcx>, error_region: Option>, diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index c817b6fac7134..a47518fca3f9b 100644 --- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs @@ -69,7 +69,7 @@ enum StorageDeadOrDrop<'tcx> { Destructor(Ty<'tcx>), } -impl<'infcx, 'tcx> MirBorrowckCtxt<'_, '_, 'infcx, 'tcx> { +impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { pub(crate) fn report_use_of_moved_or_uninitialized( &mut self, location: Location, @@ -4358,11 +4358,7 @@ enum AnnotatedBorrowFnSignature<'tcx> { impl<'tcx> AnnotatedBorrowFnSignature<'tcx> { /// Annotate the provided diagnostic with information about borrow from the fn signature that /// helps explain. - pub(crate) fn emit( - &self, - cx: &MirBorrowckCtxt<'_, '_, '_, 'tcx>, - diag: &mut Diag<'_>, - ) -> String { + pub(crate) fn emit(&self, cx: &MirBorrowckCtxt<'_, '_, 'tcx>, diag: &mut Diag<'_>) -> String { match self { &AnnotatedBorrowFnSignature::Closure { argument_ty, argument_span } => { diag.span_label( diff --git a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs index c720b0928feb0..419e72df00b02 100644 --- a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs +++ b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs @@ -390,7 +390,7 @@ impl<'tcx> BorrowExplanation<'tcx> { } } -impl<'tcx> MirBorrowckCtxt<'_, '_, '_, 'tcx> { +impl<'tcx> MirBorrowckCtxt<'_, '_, 'tcx> { fn free_region_constraint_info( &self, borrow_region: RegionVid, diff --git a/compiler/rustc_borrowck/src/diagnostics/mod.rs b/compiler/rustc_borrowck/src/diagnostics/mod.rs index 878ce6162e0f9..e52ddfa3eb543 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mod.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mod.rs @@ -68,7 +68,7 @@ pub(super) struct DescribePlaceOpt { pub(super) struct IncludingTupleField(pub(super) bool); -impl<'infcx, 'tcx> MirBorrowckCtxt<'_, '_, 'infcx, 'tcx> { +impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { /// Adds a suggestion when a closure is invoked twice with a moved variable or when a closure /// is moved after being invoked. /// @@ -772,7 +772,7 @@ struct CapturedMessageOpt { maybe_reinitialized_locations_is_empty: bool, } -impl<'infcx, 'tcx> MirBorrowckCtxt<'_, '_, 'infcx, 'tcx> { +impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { /// Finds the spans associated to a move or copy of move_place at location. pub(super) fn move_spans( &self, diff --git a/compiler/rustc_borrowck/src/diagnostics/move_errors.rs b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs index 3dab027bff057..5a9eba34d07f1 100644 --- a/compiler/rustc_borrowck/src/diagnostics/move_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs @@ -93,7 +93,7 @@ enum GroupedMoveError<'tcx> { }, } -impl<'infcx, 'tcx> MirBorrowckCtxt<'_, '_, 'infcx, 'tcx> { +impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { pub(crate) fn report_move_errors(&mut self) { let grouped_errors = self.group_move_errors(); for error in grouped_errors { diff --git a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs index 337125f5ecc11..6e3fac1e68075 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs @@ -32,7 +32,7 @@ pub(crate) enum AccessKind { Mutate, } -impl<'infcx, 'tcx> MirBorrowckCtxt<'_, '_, 'infcx, 'tcx> { +impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { pub(crate) fn report_mutability_error( &mut self, access_place: Place<'tcx>, diff --git a/compiler/rustc_borrowck/src/diagnostics/outlives_suggestion.rs b/compiler/rustc_borrowck/src/diagnostics/outlives_suggestion.rs index b205dc9ff4922..bd0cf3578c2bb 100644 --- a/compiler/rustc_borrowck/src/diagnostics/outlives_suggestion.rs +++ b/compiler/rustc_borrowck/src/diagnostics/outlives_suggestion.rs @@ -76,7 +76,7 @@ impl OutlivesSuggestionBuilder { /// Returns a name for the region if it is suggestable. See `region_name_is_suggestable`. fn region_vid_to_name( &self, - mbcx: &MirBorrowckCtxt<'_, '_, '_, '_>, + mbcx: &MirBorrowckCtxt<'_, '_, '_>, region: RegionVid, ) -> Option { mbcx.give_region_a_name(region).filter(Self::region_name_is_suggestable) @@ -85,7 +85,7 @@ impl OutlivesSuggestionBuilder { /// Compiles a list of all suggestions to be printed in the final big suggestion. fn compile_all_suggestions( &self, - mbcx: &MirBorrowckCtxt<'_, '_, '_, '_>, + mbcx: &MirBorrowckCtxt<'_, '_, '_>, ) -> SmallVec<[SuggestedConstraint; 2]> { let mut suggested = SmallVec::new(); @@ -161,7 +161,7 @@ impl OutlivesSuggestionBuilder { /// Emit an intermediate note on the given `Diag` if the involved regions are suggestable. pub(crate) fn intermediate_suggestion( &mut self, - mbcx: &MirBorrowckCtxt<'_, '_, '_, '_>, + mbcx: &MirBorrowckCtxt<'_, '_, '_>, errci: &ErrorConstraintInfo<'_>, diag: &mut Diag<'_>, ) { @@ -180,7 +180,7 @@ impl OutlivesSuggestionBuilder { /// If there is a suggestion to emit, add a diagnostic to the buffer. This is the final /// suggestion including all collected constraints. - pub(crate) fn add_suggestion(&self, mbcx: &mut MirBorrowckCtxt<'_, '_, '_, '_>) { + pub(crate) fn add_suggestion(&self, mbcx: &mut MirBorrowckCtxt<'_, '_, '_>) { // No constraints to add? Done. if self.constraints_to_add.is_empty() { debug!("No constraints to suggest."); diff --git a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs index d49d36dedafc1..57c3a0843a694 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs @@ -156,7 +156,7 @@ pub(crate) struct ErrorConstraintInfo<'tcx> { pub(super) span: Span, } -impl<'infcx, 'tcx> MirBorrowckCtxt<'_, '_, 'infcx, 'tcx> { +impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { /// Converts a region inference variable into a `ty::Region` that /// we can use for error reporting. If `r` is universally bound, /// then we use the name that we have on record for it. If `r` is diff --git a/compiler/rustc_borrowck/src/diagnostics/region_name.rs b/compiler/rustc_borrowck/src/diagnostics/region_name.rs index cb05812ec7b5c..58fcda2571cc0 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_name.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_name.rs @@ -200,7 +200,7 @@ impl rustc_errors::IntoDiagArg for RegionName { } } -impl<'tcx> MirBorrowckCtxt<'_, '_, '_, 'tcx> { +impl<'tcx> MirBorrowckCtxt<'_, '_, 'tcx> { pub(crate) fn mir_def_id(&self) -> hir::def_id::LocalDefId { self.body.source.def_id().expect_local() } diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs index d40dcfa58054a..d5f297a591382 100644 --- a/compiler/rustc_borrowck/src/lib.rs +++ b/compiler/rustc_borrowck/src/lib.rs @@ -304,11 +304,11 @@ fn do_mir_borrowck<'tcx>( promoted_mbcx.report_move_errors(); diags = promoted_mbcx.diags; - struct MoveVisitor<'a, 'b, 'mir, 'infcx, 'tcx> { - ctxt: &'a mut MirBorrowckCtxt<'b, 'mir, 'infcx, 'tcx>, + struct MoveVisitor<'a, 'b, 'infcx, 'tcx> { + ctxt: &'a mut MirBorrowckCtxt<'b, 'infcx, 'tcx>, } - impl<'tcx> Visitor<'tcx> for MoveVisitor<'_, '_, '_, '_, 'tcx> { + impl<'tcx> Visitor<'tcx> for MoveVisitor<'_, '_, '_, 'tcx> { fn visit_operand(&mut self, operand: &Operand<'tcx>, location: Location) { if let Operand::Move(place) = operand { self.ctxt.check_movable_place(location, *place); @@ -522,10 +522,10 @@ impl<'tcx> Deref for BorrowckInferCtxt<'tcx> { } } -struct MirBorrowckCtxt<'a, 'mir, 'infcx, 'tcx> { +struct MirBorrowckCtxt<'a, 'infcx, 'tcx> { infcx: &'infcx BorrowckInferCtxt<'tcx>, param_env: ParamEnv<'tcx>, - body: &'mir Body<'tcx>, + body: &'a Body<'tcx>, move_data: &'a MoveData<'tcx>, /// Map from MIR `Location` to `LocationIndex`; created @@ -599,16 +599,16 @@ struct MirBorrowckCtxt<'a, 'mir, 'infcx, 'tcx> { // 2. loans made in overlapping scopes do not conflict // 3. assignments do not affect things loaned out as immutable // 4. moves do not affect things loaned out in any way -impl<'a, 'mir, 'tcx, R> rustc_mir_dataflow::ResultsVisitor<'mir, 'tcx, R> - for MirBorrowckCtxt<'a, 'mir, '_, 'tcx> +impl<'a, 'tcx, R> rustc_mir_dataflow::ResultsVisitor<'a, 'tcx, R> + for MirBorrowckCtxt<'a, '_, 'tcx> { - type FlowState = Flows<'a, 'mir, 'tcx>; + type FlowState = Flows<'a, 'tcx>; fn visit_statement_before_primary_effect( &mut self, _results: &mut R, - flow_state: &Flows<'_, 'mir, 'tcx>, - stmt: &'mir Statement<'tcx>, + flow_state: &Flows<'a, 'tcx>, + stmt: &'a Statement<'tcx>, location: Location, ) { debug!("MirBorrowckCtxt::process_statement({:?}, {:?}): {:?}", location, stmt, flow_state); @@ -677,8 +677,8 @@ impl<'a, 'mir, 'tcx, R> rustc_mir_dataflow::ResultsVisitor<'mir, 'tcx, R> fn visit_terminator_before_primary_effect( &mut self, _results: &mut R, - flow_state: &Flows<'_, 'mir, 'tcx>, - term: &'mir Terminator<'tcx>, + flow_state: &Flows<'a, 'tcx>, + term: &'a Terminator<'tcx>, loc: Location, ) { debug!("MirBorrowckCtxt::process_terminator({:?}, {:?}): {:?}", loc, term, flow_state); @@ -794,8 +794,8 @@ impl<'a, 'mir, 'tcx, R> rustc_mir_dataflow::ResultsVisitor<'mir, 'tcx, R> fn visit_terminator_after_primary_effect( &mut self, _results: &mut R, - flow_state: &Flows<'_, 'mir, 'tcx>, - term: &'mir Terminator<'tcx>, + flow_state: &Flows<'a, 'tcx>, + term: &'a Terminator<'tcx>, loc: Location, ) { let span = term.source_info.span; @@ -972,8 +972,8 @@ impl InitializationRequiringAction { } } -impl<'mir, 'tcx> MirBorrowckCtxt<'_, 'mir, '_, 'tcx> { - fn body(&self) -> &'mir Body<'tcx> { +impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> { + fn body(&self) -> &'a Body<'tcx> { self.body } @@ -989,7 +989,7 @@ impl<'mir, 'tcx> MirBorrowckCtxt<'_, 'mir, '_, 'tcx> { place_span: (Place<'tcx>, Span), kind: (AccessDepth, ReadOrWrite), is_local_mutation_allowed: LocalMutationIsAllowed, - flow_state: &Flows<'_, 'mir, 'tcx>, + flow_state: &Flows<'a, 'tcx>, ) { let (sd, rw) = kind; @@ -1039,7 +1039,7 @@ impl<'mir, 'tcx> MirBorrowckCtxt<'_, 'mir, '_, 'tcx> { place_span: (Place<'tcx>, Span), sd: AccessDepth, rw: ReadOrWrite, - flow_state: &Flows<'_, 'mir, 'tcx>, + flow_state: &Flows<'a, 'tcx>, ) -> bool { let mut error_reported = false; let borrow_set = Rc::clone(&self.borrow_set); @@ -1180,7 +1180,7 @@ impl<'mir, 'tcx> MirBorrowckCtxt<'_, 'mir, '_, 'tcx> { location: Location, place_span: (Place<'tcx>, Span), kind: AccessDepth, - flow_state: &Flows<'_, 'mir, 'tcx>, + flow_state: &Flows<'a, 'tcx>, ) { // Write of P[i] or *P requires P init'd. self.check_if_assigned_path_is_moved(location, place_span, flow_state); @@ -1197,8 +1197,8 @@ impl<'mir, 'tcx> MirBorrowckCtxt<'_, 'mir, '_, 'tcx> { fn consume_rvalue( &mut self, location: Location, - (rvalue, span): (&'mir Rvalue<'tcx>, Span), - flow_state: &Flows<'_, 'mir, 'tcx>, + (rvalue, span): (&'a Rvalue<'tcx>, Span), + flow_state: &Flows<'a, 'tcx>, ) { match rvalue { &Rvalue::Ref(_ /*rgn*/, bk, place) => { @@ -1455,8 +1455,8 @@ impl<'mir, 'tcx> MirBorrowckCtxt<'_, 'mir, '_, 'tcx> { fn consume_operand( &mut self, location: Location, - (operand, span): (&'mir Operand<'tcx>, Span), - flow_state: &Flows<'_, 'mir, 'tcx>, + (operand, span): (&'a Operand<'tcx>, Span), + flow_state: &Flows<'a, 'tcx>, ) { match *operand { Operand::Copy(place) => { @@ -1576,12 +1576,7 @@ impl<'mir, 'tcx> MirBorrowckCtxt<'_, 'mir, '_, 'tcx> { } } - fn check_activations( - &mut self, - location: Location, - span: Span, - flow_state: &Flows<'_, 'mir, 'tcx>, - ) { + fn check_activations(&mut self, location: Location, span: Span, flow_state: &Flows<'a, 'tcx>) { // Two-phase borrow support: For each activation that is newly // generated at this statement, check if it interferes with // another borrow. @@ -1744,7 +1739,7 @@ impl<'mir, 'tcx> MirBorrowckCtxt<'_, 'mir, '_, 'tcx> { location: Location, desired_action: InitializationRequiringAction, place_span: (PlaceRef<'tcx>, Span), - flow_state: &Flows<'_, 'mir, 'tcx>, + flow_state: &Flows<'a, 'tcx>, ) { let maybe_uninits = &flow_state.uninits; @@ -1849,7 +1844,7 @@ impl<'mir, 'tcx> MirBorrowckCtxt<'_, 'mir, '_, 'tcx> { location: Location, desired_action: InitializationRequiringAction, place_span: (PlaceRef<'tcx>, Span), - flow_state: &Flows<'_, 'mir, 'tcx>, + flow_state: &Flows<'a, 'tcx>, ) { let maybe_uninits = &flow_state.uninits; @@ -1948,7 +1943,7 @@ impl<'mir, 'tcx> MirBorrowckCtxt<'_, 'mir, '_, 'tcx> { &mut self, location: Location, (place, span): (Place<'tcx>, Span), - flow_state: &Flows<'_, 'mir, 'tcx>, + flow_state: &Flows<'a, 'tcx>, ) { debug!("check_if_assigned_path_is_moved place: {:?}", place); @@ -2009,12 +2004,12 @@ impl<'mir, 'tcx> MirBorrowckCtxt<'_, 'mir, '_, 'tcx> { } } - fn check_parent_of_field<'mir, 'tcx>( - this: &mut MirBorrowckCtxt<'_, 'mir, '_, 'tcx>, + fn check_parent_of_field<'a, 'tcx>( + this: &mut MirBorrowckCtxt<'a, '_, 'tcx>, location: Location, base: PlaceRef<'tcx>, span: Span, - flow_state: &Flows<'_, 'mir, 'tcx>, + flow_state: &Flows<'a, 'tcx>, ) { // rust-lang/rust#21232: Until Rust allows reads from the // initialized parts of partially initialized structs, we @@ -2105,7 +2100,7 @@ impl<'mir, 'tcx> MirBorrowckCtxt<'_, 'mir, '_, 'tcx> { (place, span): (Place<'tcx>, Span), kind: ReadOrWrite, is_local_mutation_allowed: LocalMutationIsAllowed, - flow_state: &Flows<'_, 'mir, 'tcx>, + flow_state: &Flows<'a, 'tcx>, location: Location, ) -> bool { debug!( @@ -2221,7 +2216,7 @@ impl<'mir, 'tcx> MirBorrowckCtxt<'_, 'mir, '_, 'tcx> { fn is_local_ever_initialized( &self, local: Local, - flow_state: &Flows<'_, 'mir, 'tcx>, + flow_state: &Flows<'a, 'tcx>, ) -> Option { let mpi = self.move_data.rev_lookup.find_local(local)?; let ii = &self.move_data.init_path_map[mpi]; @@ -2229,7 +2224,7 @@ impl<'mir, 'tcx> MirBorrowckCtxt<'_, 'mir, '_, 'tcx> { } /// Adds the place into the used mutable variables set - fn add_used_mut(&mut self, root_place: RootPlace<'tcx>, flow_state: &Flows<'_, 'mir, 'tcx>) { + fn add_used_mut(&mut self, root_place: RootPlace<'tcx>, flow_state: &Flows<'a, 'tcx>) { match root_place { RootPlace { place_local: local, place_projection: [], is_local_mutation_allowed } => { // If the local may have been initialized, and it is now currently being @@ -2484,7 +2479,7 @@ mod diags { } } - impl<'infcx, 'tcx> MirBorrowckCtxt<'_, '_, 'infcx, 'tcx> { + impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { pub(crate) fn buffer_error(&mut self, diag: Diag<'infcx>) { self.diags.buffer_error(diag); } diff --git a/compiler/rustc_borrowck/src/nll.rs b/compiler/rustc_borrowck/src/nll.rs index 6525befc13b99..0d6ecab7d27ca 100644 --- a/compiler/rustc_borrowck/src/nll.rs +++ b/compiler/rustc_borrowck/src/nll.rs @@ -75,14 +75,14 @@ pub(crate) fn replace_regions_in_mir<'tcx>( /// Computes the (non-lexical) regions from the input MIR. /// /// This may result in errors being reported. -pub(crate) fn compute_regions<'cx, 'tcx>( +pub(crate) fn compute_regions<'a, 'tcx>( infcx: &BorrowckInferCtxt<'tcx>, universal_regions: UniversalRegions<'tcx>, body: &Body<'tcx>, promoted: &IndexSlice>, location_table: &LocationTable, param_env: ty::ParamEnv<'tcx>, - flow_inits: &mut ResultsCursor<'cx, 'tcx, MaybeInitializedPlaces<'_, 'cx, 'tcx>>, + flow_inits: &mut ResultsCursor<'a, 'tcx, MaybeInitializedPlaces<'a, 'tcx>>, move_data: &MoveData<'tcx>, borrow_set: &BorrowSet<'tcx>, upvars: &[&ty::CapturedPlace<'tcx>], diff --git a/compiler/rustc_borrowck/src/prefixes.rs b/compiler/rustc_borrowck/src/prefixes.rs index 39d831378cde6..aeb8a6c014a4f 100644 --- a/compiler/rustc_borrowck/src/prefixes.rs +++ b/compiler/rustc_borrowck/src/prefixes.rs @@ -34,7 +34,7 @@ pub(super) enum PrefixSet { Shallow, } -impl<'tcx> MirBorrowckCtxt<'_, '_, '_, 'tcx> { +impl<'tcx> MirBorrowckCtxt<'_, '_, 'tcx> { /// Returns an iterator over the prefixes of `place` /// (inclusive) from longest to smallest, potentially /// terminating the iteration early based on `kind`. diff --git a/compiler/rustc_borrowck/src/type_check/liveness/mod.rs b/compiler/rustc_borrowck/src/type_check/liveness/mod.rs index a24fd95e3e650..79db8f4252b55 100644 --- a/compiler/rustc_borrowck/src/type_check/liveness/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/liveness/mod.rs @@ -30,11 +30,11 @@ mod trace; /// /// N.B., this computation requires normalization; therefore, it must be /// performed before -pub(super) fn generate<'mir, 'tcx>( +pub(super) fn generate<'a, 'tcx>( typeck: &mut TypeChecker<'_, 'tcx>, body: &Body<'tcx>, elements: &Rc, - flow_inits: &mut ResultsCursor<'mir, 'tcx, MaybeInitializedPlaces<'_, 'mir, 'tcx>>, + flow_inits: &mut ResultsCursor<'a, 'tcx, MaybeInitializedPlaces<'a, 'tcx>>, move_data: &MoveData<'tcx>, ) { debug!("liveness::generate"); diff --git a/compiler/rustc_borrowck/src/type_check/liveness/trace.rs b/compiler/rustc_borrowck/src/type_check/liveness/trace.rs index 6186904e5fbb6..4d47863ae76ad 100644 --- a/compiler/rustc_borrowck/src/type_check/liveness/trace.rs +++ b/compiler/rustc_borrowck/src/type_check/liveness/trace.rs @@ -37,11 +37,11 @@ use crate::type_check::{NormalizeLocation, TypeChecker}; /// DROP-LIVE set are to the liveness sets for regions found in the /// `dropck_outlives` result of the variable's type (in particular, /// this respects `#[may_dangle]` annotations). -pub(super) fn trace<'mir, 'tcx>( +pub(super) fn trace<'a, 'tcx>( typeck: &mut TypeChecker<'_, 'tcx>, body: &Body<'tcx>, elements: &Rc, - flow_inits: &mut ResultsCursor<'mir, 'tcx, MaybeInitializedPlaces<'_, 'mir, 'tcx>>, + flow_inits: &mut ResultsCursor<'a, 'tcx, MaybeInitializedPlaces<'a, 'tcx>>, move_data: &MoveData<'tcx>, relevant_live_locals: Vec, boring_locals: Vec, @@ -99,29 +99,29 @@ pub(super) fn trace<'mir, 'tcx>( } /// Contextual state for the type-liveness coroutine. -struct LivenessContext<'a, 'me, 'typeck, 'flow, 'tcx> { +struct LivenessContext<'a, 'typeck, 'b, 'tcx> { /// Current type-checker, giving us our inference context etc. - typeck: &'me mut TypeChecker<'typeck, 'tcx>, + typeck: &'a mut TypeChecker<'typeck, 'tcx>, /// Defines the `PointIndex` mapping - elements: &'me DenseLocationMap, + elements: &'a DenseLocationMap, /// MIR we are analyzing. - body: &'me Body<'tcx>, + body: &'a Body<'tcx>, /// Mapping to/from the various indices used for initialization tracking. - move_data: &'me MoveData<'tcx>, + move_data: &'a MoveData<'tcx>, /// Cache for the results of `dropck_outlives` query. drop_data: FxIndexMap, DropData<'tcx>>, /// Results of dataflow tracking which variables (and paths) have been /// initialized. - flow_inits: &'me mut ResultsCursor<'flow, 'tcx, MaybeInitializedPlaces<'a, 'flow, 'tcx>>, + flow_inits: &'a mut ResultsCursor<'b, 'tcx, MaybeInitializedPlaces<'b, 'tcx>>, /// Index indicating where each variable is assigned, used, or /// dropped. - local_use_map: &'me LocalUseMap, + local_use_map: &'a LocalUseMap, } struct DropData<'tcx> { @@ -129,8 +129,8 @@ struct DropData<'tcx> { region_constraint_data: Option<&'tcx QueryRegionConstraints<'tcx>>, } -struct LivenessResults<'a, 'me, 'typeck, 'flow, 'tcx> { - cx: LivenessContext<'a, 'me, 'typeck, 'flow, 'tcx>, +struct LivenessResults<'a, 'typeck, 'b, 'tcx> { + cx: LivenessContext<'a, 'typeck, 'b, 'tcx>, /// Set of points that define the current local. defs: BitSet, @@ -151,8 +151,8 @@ struct LivenessResults<'a, 'me, 'typeck, 'flow, 'tcx> { stack: Vec, } -impl<'a, 'me, 'typeck, 'flow, 'tcx> LivenessResults<'a, 'me, 'typeck, 'flow, 'tcx> { - fn new(cx: LivenessContext<'a, 'me, 'typeck, 'flow, 'tcx>) -> Self { +impl<'a, 'typeck, 'b, 'tcx> LivenessResults<'a, 'typeck, 'b, 'tcx> { + fn new(cx: LivenessContext<'a, 'typeck, 'b, 'tcx>) -> Self { let num_points = cx.elements.num_points(); LivenessResults { cx, @@ -505,7 +505,7 @@ impl<'a, 'me, 'typeck, 'flow, 'tcx> LivenessResults<'a, 'me, 'typeck, 'flow, 'tc } } -impl<'tcx> LivenessContext<'_, '_, '_, '_, 'tcx> { +impl<'tcx> LivenessContext<'_, '_, '_, 'tcx> { /// Returns `true` if the local variable (or some part of it) is initialized at the current /// cursor position. Callers should call one of the `seek` methods immediately before to point /// the cursor to the desired location. diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index 3c9a43883ad64..3e5a6ad85fa56 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -116,7 +116,7 @@ mod relate_tys; /// - `flow_inits` -- results of a maybe-init dataflow analysis /// - `move_data` -- move-data constructed when performing the maybe-init dataflow analysis /// - `elements` -- MIR region map -pub(crate) fn type_check<'mir, 'tcx>( +pub(crate) fn type_check<'a, 'tcx>( infcx: &BorrowckInferCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>, body: &Body<'tcx>, @@ -125,7 +125,7 @@ pub(crate) fn type_check<'mir, 'tcx>( location_table: &LocationTable, borrow_set: &BorrowSet<'tcx>, all_facts: &mut Option, - flow_inits: &mut ResultsCursor<'mir, 'tcx, MaybeInitializedPlaces<'_, 'mir, 'tcx>>, + flow_inits: &mut ResultsCursor<'a, 'tcx, MaybeInitializedPlaces<'a, 'tcx>>, move_data: &MoveData<'tcx>, elements: &Rc, upvars: &[&ty::CapturedPlace<'tcx>], diff --git a/compiler/rustc_borrowck/src/used_muts.rs b/compiler/rustc_borrowck/src/used_muts.rs index 981e7daf6702e..bde07c05c0e16 100644 --- a/compiler/rustc_borrowck/src/used_muts.rs +++ b/compiler/rustc_borrowck/src/used_muts.rs @@ -7,7 +7,7 @@ use tracing::debug; use crate::MirBorrowckCtxt; -impl<'tcx> MirBorrowckCtxt<'_, '_, '_, 'tcx> { +impl<'tcx> MirBorrowckCtxt<'_, '_, 'tcx> { /// Walks the MIR adding to the set of `used_mut` locals that will be ignored for the purposes /// of the `unused_mut` lint. /// @@ -46,13 +46,13 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, '_, 'tcx> { /// MIR visitor for collecting used mutable variables. /// The 'visit lifetime represents the duration of the MIR walk. -struct GatherUsedMutsVisitor<'visit, 'a, 'mir, 'infcx, 'tcx> { +struct GatherUsedMutsVisitor<'a, 'b, 'infcx, 'tcx> { temporary_used_locals: FxIndexSet, - never_initialized_mut_locals: &'visit mut FxIndexSet, - mbcx: &'visit mut MirBorrowckCtxt<'a, 'mir, 'infcx, 'tcx>, + never_initialized_mut_locals: &'a mut FxIndexSet, + mbcx: &'a mut MirBorrowckCtxt<'b, 'infcx, 'tcx>, } -impl GatherUsedMutsVisitor<'_, '_, '_, '_, '_> { +impl GatherUsedMutsVisitor<'_, '_, '_, '_> { fn remove_never_initialized_mut_locals(&mut self, into: Place<'_>) { // Remove any locals that we found were initialized from the // `never_initialized_mut_locals` set. At the end, the only remaining locals will @@ -64,7 +64,7 @@ impl GatherUsedMutsVisitor<'_, '_, '_, '_, '_> { } } -impl<'tcx> Visitor<'tcx> for GatherUsedMutsVisitor<'_, '_, '_, '_, 'tcx> { +impl<'tcx> Visitor<'tcx> for GatherUsedMutsVisitor<'_, '_, '_, 'tcx> { fn visit_terminator(&mut self, terminator: &Terminator<'tcx>, location: Location) { debug!("visit_terminator: terminator={:?}", terminator); match &terminator.kind { diff --git a/compiler/rustc_mir_dataflow/src/impls/initialized.rs b/compiler/rustc_mir_dataflow/src/impls/initialized.rs index ddfd0739358d1..a88927427bac2 100644 --- a/compiler/rustc_mir_dataflow/src/impls/initialized.rs +++ b/compiler/rustc_mir_dataflow/src/impls/initialized.rs @@ -51,15 +51,15 @@ use crate::{ /// Similarly, at a given `drop` statement, the set-intersection /// between this data and `MaybeUninitializedPlaces` yields the set of /// places that would require a dynamic drop-flag at that statement. -pub struct MaybeInitializedPlaces<'a, 'mir, 'tcx> { +pub struct MaybeInitializedPlaces<'a, 'tcx> { tcx: TyCtxt<'tcx>, - body: &'mir Body<'tcx>, + body: &'a Body<'tcx>, move_data: &'a MoveData<'tcx>, skip_unreachable_unwind: bool, } -impl<'a, 'mir, 'tcx> MaybeInitializedPlaces<'a, 'mir, 'tcx> { - pub fn new(tcx: TyCtxt<'tcx>, body: &'mir Body<'tcx>, move_data: &'a MoveData<'tcx>) -> Self { +impl<'a, 'tcx> MaybeInitializedPlaces<'a, 'tcx> { + pub fn new(tcx: TyCtxt<'tcx>, body: &'a Body<'tcx>, move_data: &'a MoveData<'tcx>) -> Self { MaybeInitializedPlaces { tcx, body, move_data, skip_unreachable_unwind: false } } @@ -85,7 +85,7 @@ impl<'a, 'mir, 'tcx> MaybeInitializedPlaces<'a, 'mir, 'tcx> { } } -impl<'a, 'mir, 'tcx> HasMoveData<'tcx> for MaybeInitializedPlaces<'a, 'mir, 'tcx> { +impl<'a, 'tcx> HasMoveData<'tcx> for MaybeInitializedPlaces<'a, 'tcx> { fn move_data(&self) -> &MoveData<'tcx> { self.move_data } @@ -126,17 +126,17 @@ impl<'a, 'mir, 'tcx> HasMoveData<'tcx> for MaybeInitializedPlaces<'a, 'mir, 'tcx /// Similarly, at a given `drop` statement, the set-intersection /// between this data and `MaybeInitializedPlaces` yields the set of /// places that would require a dynamic drop-flag at that statement. -pub struct MaybeUninitializedPlaces<'a, 'mir, 'tcx> { +pub struct MaybeUninitializedPlaces<'a, 'tcx> { tcx: TyCtxt<'tcx>, - body: &'mir Body<'tcx>, + body: &'a Body<'tcx>, move_data: &'a MoveData<'tcx>, mark_inactive_variants_as_uninit: bool, skip_unreachable_unwind: BitSet, } -impl<'a, 'mir, 'tcx> MaybeUninitializedPlaces<'a, 'mir, 'tcx> { - pub fn new(tcx: TyCtxt<'tcx>, body: &'mir Body<'tcx>, move_data: &'a MoveData<'tcx>) -> Self { +impl<'a, 'tcx> MaybeUninitializedPlaces<'a, 'tcx> { + pub fn new(tcx: TyCtxt<'tcx>, body: &'a Body<'tcx>, move_data: &'a MoveData<'tcx>) -> Self { MaybeUninitializedPlaces { tcx, body, @@ -165,7 +165,7 @@ impl<'a, 'mir, 'tcx> MaybeUninitializedPlaces<'a, 'mir, 'tcx> { } } -impl<'a, 'tcx> HasMoveData<'tcx> for MaybeUninitializedPlaces<'a, '_, 'tcx> { +impl<'tcx> HasMoveData<'tcx> for MaybeUninitializedPlaces<'_, 'tcx> { fn move_data(&self) -> &MoveData<'tcx> { self.move_data } @@ -251,24 +251,24 @@ impl<'a, 'tcx> HasMoveData<'tcx> for DefinitelyInitializedPlaces<'a, 'tcx> { /// c = S; // {a, b, c, d } /// } /// ``` -pub struct EverInitializedPlaces<'a, 'mir, 'tcx> { - body: &'mir Body<'tcx>, +pub struct EverInitializedPlaces<'a, 'tcx> { + body: &'a Body<'tcx>, move_data: &'a MoveData<'tcx>, } -impl<'a, 'mir, 'tcx> EverInitializedPlaces<'a, 'mir, 'tcx> { - pub fn new(body: &'mir Body<'tcx>, move_data: &'a MoveData<'tcx>) -> Self { +impl<'a, 'tcx> EverInitializedPlaces<'a, 'tcx> { + pub fn new(body: &'a Body<'tcx>, move_data: &'a MoveData<'tcx>) -> Self { EverInitializedPlaces { body, move_data } } } -impl<'a, 'tcx> HasMoveData<'tcx> for EverInitializedPlaces<'a, '_, 'tcx> { +impl<'tcx> HasMoveData<'tcx> for EverInitializedPlaces<'_, 'tcx> { fn move_data(&self) -> &MoveData<'tcx> { self.move_data } } -impl<'a, 'mir, 'tcx> MaybeInitializedPlaces<'a, 'mir, 'tcx> { +impl<'a, 'tcx> MaybeInitializedPlaces<'a, 'tcx> { fn update_bits( trans: &mut impl GenKill, path: MovePathIndex, @@ -281,7 +281,7 @@ impl<'a, 'mir, 'tcx> MaybeInitializedPlaces<'a, 'mir, 'tcx> { } } -impl<'a, 'tcx> MaybeUninitializedPlaces<'a, '_, 'tcx> { +impl<'tcx> MaybeUninitializedPlaces<'_, 'tcx> { fn update_bits( trans: &mut impl GenKill, path: MovePathIndex, @@ -307,7 +307,7 @@ impl<'a, 'tcx> DefinitelyInitializedPlaces<'a, 'tcx> { } } -impl<'tcx> AnalysisDomain<'tcx> for MaybeInitializedPlaces<'_, '_, 'tcx> { +impl<'tcx> AnalysisDomain<'tcx> for MaybeInitializedPlaces<'_, 'tcx> { /// There can be many more `MovePathIndex` than there are locals in a MIR body. /// We use a chunked bitset to avoid paying too high a memory footprint. type Domain = MaybeReachable>; @@ -329,7 +329,7 @@ impl<'tcx> AnalysisDomain<'tcx> for MaybeInitializedPlaces<'_, '_, 'tcx> { } } -impl<'tcx> GenKillAnalysis<'tcx> for MaybeInitializedPlaces<'_, '_, 'tcx> { +impl<'tcx> GenKillAnalysis<'tcx> for MaybeInitializedPlaces<'_, 'tcx> { type Idx = MovePathIndex; fn domain_size(&self, _: &Body<'tcx>) -> usize { @@ -442,7 +442,7 @@ impl<'tcx> GenKillAnalysis<'tcx> for MaybeInitializedPlaces<'_, '_, 'tcx> { } } -impl<'tcx> AnalysisDomain<'tcx> for MaybeUninitializedPlaces<'_, '_, 'tcx> { +impl<'tcx> AnalysisDomain<'tcx> for MaybeUninitializedPlaces<'_, 'tcx> { /// There can be many more `MovePathIndex` than there are locals in a MIR body. /// We use a chunked bitset to avoid paying too high a memory footprint. type Domain = ChunkedBitSet; @@ -466,7 +466,7 @@ impl<'tcx> AnalysisDomain<'tcx> for MaybeUninitializedPlaces<'_, '_, 'tcx> { } } -impl<'tcx> GenKillAnalysis<'tcx> for MaybeUninitializedPlaces<'_, '_, 'tcx> { +impl<'tcx> GenKillAnalysis<'tcx> for MaybeUninitializedPlaces<'_, 'tcx> { type Idx = MovePathIndex; fn domain_size(&self, _: &Body<'tcx>) -> usize { @@ -643,7 +643,7 @@ impl<'tcx> GenKillAnalysis<'tcx> for DefinitelyInitializedPlaces<'_, 'tcx> { } } -impl<'tcx> AnalysisDomain<'tcx> for EverInitializedPlaces<'_, '_, 'tcx> { +impl<'tcx> AnalysisDomain<'tcx> for EverInitializedPlaces<'_, 'tcx> { /// There can be many more `InitIndex` than there are locals in a MIR body. /// We use a chunked bitset to avoid paying too high a memory footprint. type Domain = ChunkedBitSet; @@ -662,7 +662,7 @@ impl<'tcx> AnalysisDomain<'tcx> for EverInitializedPlaces<'_, '_, 'tcx> { } } -impl<'tcx> GenKillAnalysis<'tcx> for EverInitializedPlaces<'_, '_, 'tcx> { +impl<'tcx> GenKillAnalysis<'tcx> for EverInitializedPlaces<'_, 'tcx> { type Idx = InitIndex; fn domain_size(&self, _: &Body<'tcx>) -> usize { diff --git a/compiler/rustc_mir_transform/src/elaborate_drops.rs b/compiler/rustc_mir_transform/src/elaborate_drops.rs index f4a951ebde600..ffffdf53916a7 100644 --- a/compiler/rustc_mir_transform/src/elaborate_drops.rs +++ b/compiler/rustc_mir_transform/src/elaborate_drops.rs @@ -98,9 +98,9 @@ impl<'tcx> crate::MirPass<'tcx> for ElaborateDrops { /// Records unwind edges which are known to be unreachable, because they are in `drop` terminators /// that can't drop anything. #[instrument(level = "trace", skip(body, flow_inits), ret)] -fn compute_dead_unwinds<'mir, 'tcx>( - body: &'mir Body<'tcx>, - flow_inits: &mut ResultsCursor<'mir, 'tcx, MaybeInitializedPlaces<'_, 'mir, 'tcx>>, +fn compute_dead_unwinds<'a, 'tcx>( + body: &'a Body<'tcx>, + flow_inits: &mut ResultsCursor<'a, 'tcx, MaybeInitializedPlaces<'a, 'tcx>>, ) -> BitSet { // We only need to do this pass once, because unwind edges can only // reach cleanup blocks, which can't have unwind edges themselves. @@ -121,12 +121,12 @@ fn compute_dead_unwinds<'mir, 'tcx>( dead_unwinds } -struct InitializationData<'a, 'mir, 'tcx> { - inits: ResultsCursor<'mir, 'tcx, MaybeInitializedPlaces<'a, 'mir, 'tcx>>, - uninits: ResultsCursor<'mir, 'tcx, MaybeUninitializedPlaces<'a, 'mir, 'tcx>>, +struct InitializationData<'a, 'tcx> { + inits: ResultsCursor<'a, 'tcx, MaybeInitializedPlaces<'a, 'tcx>>, + uninits: ResultsCursor<'a, 'tcx, MaybeUninitializedPlaces<'a, 'tcx>>, } -impl InitializationData<'_, '_, '_> { +impl InitializationData<'_, '_> { fn seek_before(&mut self, loc: Location) { self.inits.seek_before_primary_effect(loc); self.uninits.seek_before_primary_effect(loc); @@ -137,24 +137,24 @@ impl InitializationData<'_, '_, '_> { } } -struct Elaborator<'a, 'b, 'mir, 'tcx> { - ctxt: &'a mut ElaborateDropsCtxt<'b, 'mir, 'tcx>, +struct Elaborator<'a, 'b, 'tcx> { + ctxt: &'a mut ElaborateDropsCtxt<'b, 'tcx>, } -impl fmt::Debug for Elaborator<'_, '_, '_, '_> { +impl fmt::Debug for Elaborator<'_, '_, '_> { fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result { Ok(()) } } -impl<'a, 'tcx> DropElaborator<'a, 'tcx> for Elaborator<'a, '_, '_, 'tcx> { +impl<'b, 'tcx> DropElaborator<'b, 'tcx> for Elaborator<'_, 'b, 'tcx> { type Path = MovePathIndex; fn patch(&mut self) -> &mut MirPatch<'tcx> { &mut self.ctxt.patch } - fn body(&self) -> &'a Body<'tcx> { + fn body(&self) -> &'b Body<'tcx> { self.ctxt.body } @@ -241,17 +241,17 @@ impl<'a, 'tcx> DropElaborator<'a, 'tcx> for Elaborator<'a, '_, '_, 'tcx> { } } -struct ElaborateDropsCtxt<'a, 'mir, 'tcx> { +struct ElaborateDropsCtxt<'a, 'tcx> { tcx: TyCtxt<'tcx>, - body: &'mir Body<'tcx>, + body: &'a Body<'tcx>, env: &'a MoveDataParamEnv<'tcx>, - init_data: InitializationData<'a, 'mir, 'tcx>, + init_data: InitializationData<'a, 'tcx>, drop_flags: IndexVec>, patch: MirPatch<'tcx>, } -impl<'b, 'mir, 'tcx> ElaborateDropsCtxt<'b, 'mir, 'tcx> { - fn move_data(&self) -> &'b MoveData<'tcx> { +impl<'a, 'tcx> ElaborateDropsCtxt<'a, 'tcx> { + fn move_data(&self) -> &'a MoveData<'tcx> { &self.env.move_data } From bed91f506559d17add56379f565372be031cdb36 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 6 Sep 2024 10:29:32 +1000 Subject: [PATCH 0709/2194] Remove unnecessary lifetime in `PlaceCollector`. --- compiler/rustc_mir_dataflow/src/value_analysis.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_mir_dataflow/src/value_analysis.rs b/compiler/rustc_mir_dataflow/src/value_analysis.rs index 2b20a35b61e29..0540436632014 100644 --- a/compiler/rustc_mir_dataflow/src/value_analysis.rs +++ b/compiler/rustc_mir_dataflow/src/value_analysis.rs @@ -923,14 +923,14 @@ impl<'tcx> Map<'tcx> { } } -struct PlaceCollector<'a, 'b, 'tcx> { +struct PlaceCollector<'a, 'tcx> { tcx: TyCtxt<'tcx>, - body: &'b Body<'tcx>, + body: &'a Body<'tcx>, map: &'a mut Map<'tcx>, assignments: FxIndexSet<(PlaceIndex, PlaceIndex)>, } -impl<'tcx> PlaceCollector<'_, '_, 'tcx> { +impl<'tcx> PlaceCollector<'_, 'tcx> { #[tracing::instrument(level = "trace", skip(self))] fn register_place(&mut self, place: Place<'tcx>) -> Option { // Create a place for this projection. @@ -967,7 +967,7 @@ impl<'tcx> PlaceCollector<'_, '_, 'tcx> { } } -impl<'tcx> Visitor<'tcx> for PlaceCollector<'_, '_, 'tcx> { +impl<'tcx> Visitor<'tcx> for PlaceCollector<'_, 'tcx> { #[tracing::instrument(level = "trace", skip(self))] fn visit_place(&mut self, place: &Place<'tcx>, ctxt: PlaceContext, _: Location) { if !ctxt.is_use() { From 1aafeb2d5a07f98d5fab4f5627666396ed292f68 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 6 Sep 2024 14:23:30 +1000 Subject: [PATCH 0710/2194] Remove unnecessary lifetime from `OperandCollector`. Also put the remaining lifetimes into the usual order. --- compiler/rustc_mir_transform/src/dataflow_const_prop.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs index 46f7408ef8064..5fe5ba76dbc34 100644 --- a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs +++ b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs @@ -838,14 +838,14 @@ impl<'tcx> MutVisitor<'tcx> for Patch<'tcx> { } } -struct OperandCollector<'tcx, 'map, 'locals, 'a> { +struct OperandCollector<'a, 'locals, 'tcx> { state: &'a State>, visitor: &'a mut Collector<'tcx, 'locals>, - ecx: &'map mut InterpCx<'tcx, DummyMachine>, - map: &'map Map<'tcx>, + ecx: &'a mut InterpCx<'tcx, DummyMachine>, + map: &'a Map<'tcx>, } -impl<'tcx> Visitor<'tcx> for OperandCollector<'tcx, '_, '_, '_> { +impl<'tcx> Visitor<'tcx> for OperandCollector<'_, '_, 'tcx> { fn visit_projection_elem( &mut self, _: PlaceRef<'tcx>, From 28a6dc4d1e8140ea22fadef82ce999926e3881f1 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 6 Sep 2024 13:40:20 +1000 Subject: [PATCH 0711/2194] Rename some lifetimes. Give them the names used in most places. --- compiler/rustc_borrowck/src/nll.rs | 6 +++--- compiler/rustc_borrowck/src/universal_regions.rs | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_borrowck/src/nll.rs b/compiler/rustc_borrowck/src/nll.rs index 0d6ecab7d27ca..8575eb9e9a52d 100644 --- a/compiler/rustc_borrowck/src/nll.rs +++ b/compiler/rustc_borrowck/src/nll.rs @@ -301,13 +301,13 @@ pub(super) fn dump_nll_mir<'tcx>( #[allow(rustc::diagnostic_outside_of_impl)] #[allow(rustc::untranslatable_diagnostic)] -pub(super) fn dump_annotation<'tcx, 'cx>( - infcx: &'cx BorrowckInferCtxt<'tcx>, +pub(super) fn dump_annotation<'tcx, 'infcx>( + infcx: &'infcx BorrowckInferCtxt<'tcx>, body: &Body<'tcx>, regioncx: &RegionInferenceContext<'tcx>, closure_region_requirements: &Option>, opaque_type_values: &FxIndexMap>, - diags: &mut crate::diags::BorrowckDiags<'cx, 'tcx>, + diags: &mut crate::diags::BorrowckDiags<'infcx, 'tcx>, ) { let tcx = infcx.tcx; let base_def_id = tcx.typeck_root_def_id(body.source.def_id()); diff --git a/compiler/rustc_borrowck/src/universal_regions.rs b/compiler/rustc_borrowck/src/universal_regions.rs index 164be73f49296..c3edbcb50cc3d 100644 --- a/compiler/rustc_borrowck/src/universal_regions.rs +++ b/compiler/rustc_borrowck/src/universal_regions.rs @@ -423,8 +423,8 @@ impl<'tcx> UniversalRegions<'tcx> { } } -struct UniversalRegionsBuilder<'cx, 'tcx> { - infcx: &'cx BorrowckInferCtxt<'tcx>, +struct UniversalRegionsBuilder<'infcx, 'tcx> { + infcx: &'infcx BorrowckInferCtxt<'tcx>, mir_def: LocalDefId, param_env: ty::ParamEnv<'tcx>, } From dc62f07458078d1e80a316a2f5b9990a43486f5d Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 6 Sep 2024 16:35:17 +1000 Subject: [PATCH 0712/2194] Remove `Gatherer`. It's a very thin wrapper that pairs `MoveDataBuilder` with a `Location`, and it has four lifetime arguments. This commit removes it by just adding a `Location` to `MoveDataBuilder`. --- .../src/move_paths/builder.rs | 75 +++++++------------ 1 file changed, 29 insertions(+), 46 deletions(-) diff --git a/compiler/rustc_mir_dataflow/src/move_paths/builder.rs b/compiler/rustc_mir_dataflow/src/move_paths/builder.rs index 14390723ba4b6..87ea729923895 100644 --- a/compiler/rustc_mir_dataflow/src/move_paths/builder.rs +++ b/compiler/rustc_mir_dataflow/src/move_paths/builder.rs @@ -16,6 +16,7 @@ use super::{ struct MoveDataBuilder<'a, 'tcx, F> { body: &'a Body<'tcx>, + loc: Location, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>, data: MoveData<'tcx>, @@ -56,6 +57,7 @@ impl<'a, 'tcx, F: Fn(Ty<'tcx>) -> bool> MoveDataBuilder<'a, 'tcx, F> { MoveDataBuilder { body, + loc: Location::START, tcx, param_env, data: MoveData { @@ -107,7 +109,7 @@ enum MovePathResult { Error, } -impl<'b, 'a, 'tcx, F: Fn(Ty<'tcx>) -> bool> Gatherer<'b, 'a, 'tcx, F> { +impl<'a, 'tcx, F: Fn(Ty<'tcx>) -> bool> MoveDataBuilder<'a, 'tcx, F> { /// This creates a MovePath for a given place, returning an `MovePathError` /// if that place can't be moved from. /// @@ -116,7 +118,7 @@ impl<'b, 'a, 'tcx, F: Fn(Ty<'tcx>) -> bool> Gatherer<'b, 'a, 'tcx, F> { /// /// Maybe we should have separate "borrowck" and "moveck" modes. fn move_path_for(&mut self, place: Place<'tcx>) -> MovePathResult { - let data = &mut self.builder.data; + let data = &mut self.data; debug!("lookup({:?})", place); let Some(mut base) = data.rev_lookup.find_local(place.local) else { @@ -131,8 +133,8 @@ impl<'b, 'a, 'tcx, F: Fn(Ty<'tcx>) -> bool> Gatherer<'b, 'a, 'tcx, F> { let mut union_path = None; for (place_ref, elem) in data.rev_lookup.un_derefer.iter_projections(place.as_ref()) { - let body = self.builder.body; - let tcx = self.builder.tcx; + let body = self.body; + let tcx = self.tcx; let place_ty = place_ref.ty(body, tcx).ty; if place_ty.references_error() { return MovePathResult::Error; @@ -238,7 +240,7 @@ impl<'b, 'a, 'tcx, F: Fn(Ty<'tcx>) -> bool> Gatherer<'b, 'a, 'tcx, F> { | ProjectionElem::Downcast(_, _) => (), } let elem_ty = PlaceTy::from_ty(place_ty).projection_ty(tcx, elem).ty; - if !(self.builder.filter)(elem_ty) { + if !(self.filter)(elem_ty) { return MovePathResult::Error; } if union_path.is_none() { @@ -274,7 +276,7 @@ impl<'b, 'a, 'tcx, F: Fn(Ty<'tcx>) -> bool> Gatherer<'b, 'a, 'tcx, F> { data: MoveData { rev_lookup, move_paths, path_map, init_path_map, .. }, tcx, .. - } = self.builder; + } = self; *rev_lookup.projections.entry((base, elem.lift())).or_insert_with(move || { new_move_path(move_paths, path_map, init_path_map, Some(base), mk_place(*tcx)) }) @@ -285,9 +287,7 @@ impl<'b, 'a, 'tcx, F: Fn(Ty<'tcx>) -> bool> Gatherer<'b, 'a, 'tcx, F> { // drop), so this not being a valid move path is OK. let _ = self.move_path_for(place); } -} -impl<'a, 'tcx, F> MoveDataBuilder<'a, 'tcx, F> { fn finalize(self) -> MoveData<'tcx> { debug!("{}", { debug!("moves for {:?}:", self.body.span); @@ -317,12 +317,12 @@ pub(super) fn gather_moves<'tcx>( for (bb, block) in body.basic_blocks.iter_enumerated() { for (i, stmt) in block.statements.iter().enumerate() { - let source = Location { block: bb, statement_index: i }; - builder.gather_statement(source, stmt); + builder.loc = Location { block: bb, statement_index: i }; + builder.gather_statement(stmt); } - let terminator_loc = Location { block: bb, statement_index: block.statements.len() }; - builder.gather_terminator(terminator_loc, block.terminator()); + builder.loc = Location { block: bb, statement_index: block.statements.len() }; + builder.gather_terminator(block.terminator()); } builder.finalize() @@ -345,30 +345,14 @@ impl<'a, 'tcx, F: Fn(Ty<'tcx>) -> bool> MoveDataBuilder<'a, 'tcx, F> { } } - fn gather_statement(&mut self, loc: Location, stmt: &Statement<'tcx>) { - debug!("gather_statement({:?}, {:?})", loc, stmt); - (Gatherer { builder: self, loc }).gather_statement(stmt); - } - - fn gather_terminator(&mut self, loc: Location, term: &Terminator<'tcx>) { - debug!("gather_terminator({:?}, {:?})", loc, term); - (Gatherer { builder: self, loc }).gather_terminator(term); - } -} - -struct Gatherer<'b, 'a, 'tcx, F> { - builder: &'b mut MoveDataBuilder<'a, 'tcx, F>, - loc: Location, -} - -impl<'b, 'a, 'tcx, F: Fn(Ty<'tcx>) -> bool> Gatherer<'b, 'a, 'tcx, F> { fn gather_statement(&mut self, stmt: &Statement<'tcx>) { + debug!("gather_statement({:?}, {:?})", self.loc, stmt); match &stmt.kind { StatementKind::Assign(box (place, Rvalue::CopyForDeref(reffed))) => { let local = place.as_local().unwrap(); - assert!(self.builder.body.local_decls[local].is_deref_temp()); + assert!(self.body.local_decls[local].is_deref_temp()); - let rev_lookup = &mut self.builder.data.rev_lookup; + let rev_lookup = &mut self.data.rev_lookup; rev_lookup.un_derefer.insert(local, reffed.as_ref()); let base_local = rev_lookup.un_derefer.deref_chain(local).first().unwrap().local; @@ -380,7 +364,7 @@ impl<'b, 'a, 'tcx, F: Fn(Ty<'tcx>) -> bool> Gatherer<'b, 'a, 'tcx, F> { // Box starts out uninitialized - need to create a separate // move-path for the interior so it will be separate from // the exterior. - self.create_move_path(self.builder.tcx.mk_place_deref(*place)); + self.create_move_path(self.tcx.mk_place_deref(*place)); self.gather_init(place.as_ref(), InitKind::Shallow); } else { self.gather_init(place.as_ref(), InitKind::Deep); @@ -393,7 +377,7 @@ impl<'b, 'a, 'tcx, F: Fn(Ty<'tcx>) -> bool> Gatherer<'b, 'a, 'tcx, F> { StatementKind::StorageLive(_) => {} StatementKind::StorageDead(local) => { // DerefTemp locals (results of CopyForDeref) don't actually move anything. - if !self.builder.body.local_decls[*local].is_deref_temp() { + if !self.body.local_decls[*local].is_deref_temp() { self.gather_move(Place::from(*local)); } } @@ -443,6 +427,7 @@ impl<'b, 'a, 'tcx, F: Fn(Ty<'tcx>) -> bool> Gatherer<'b, 'a, 'tcx, F> { } fn gather_terminator(&mut self, term: &Terminator<'tcx>) { + debug!("gather_terminator({:?}, {:?})", self.loc, term); match term.kind { TerminatorKind::Goto { target: _ } | TerminatorKind::FalseEdge { .. } @@ -551,7 +536,7 @@ impl<'b, 'a, 'tcx, F: Fn(Ty<'tcx>) -> bool> Gatherer<'b, 'a, 'tcx, F> { // `ConstIndex` patterns. This is done to ensure that all move paths // are disjoint, which is expected by drop elaboration. let base_place = - Place { local: place.local, projection: self.builder.tcx.mk_place_elems(base) }; + Place { local: place.local, projection: self.tcx.mk_place_elems(base) }; let base_path = match self.move_path_for(base_place) { MovePathResult::Path(path) => path, MovePathResult::Union(path) => { @@ -562,11 +547,9 @@ impl<'b, 'a, 'tcx, F: Fn(Ty<'tcx>) -> bool> Gatherer<'b, 'a, 'tcx, F> { return; } }; - let base_ty = base_place.ty(self.builder.body, self.builder.tcx).ty; + let base_ty = base_place.ty(self.body, self.tcx).ty; let len: u64 = match base_ty.kind() { - ty::Array(_, size) => { - size.eval_target_usize(self.builder.tcx, self.builder.param_env) - } + ty::Array(_, size) => size.eval_target_usize(self.tcx, self.param_env), _ => bug!("from_end: false slice pattern of non-array type"), }; for offset in from..to { @@ -587,13 +570,13 @@ impl<'b, 'a, 'tcx, F: Fn(Ty<'tcx>) -> bool> Gatherer<'b, 'a, 'tcx, F> { } fn record_move(&mut self, place: Place<'tcx>, path: MovePathIndex) { - let move_out = self.builder.data.moves.push(MoveOut { path, source: self.loc }); + let move_out = self.data.moves.push(MoveOut { path, source: self.loc }); debug!( "gather_move({:?}, {:?}): adding move {:?} of {:?}", self.loc, place, move_out, path ); - self.builder.data.path_map[path].push(move_out); - self.builder.data.loc_map[self.loc].push(move_out); + self.data.path_map[path].push(move_out); + self.data.loc_map[self.loc].push(move_out); } fn gather_init(&mut self, place: PlaceRef<'tcx>, kind: InitKind) { @@ -604,13 +587,13 @@ impl<'b, 'a, 'tcx, F: Fn(Ty<'tcx>) -> bool> Gatherer<'b, 'a, 'tcx, F> { // Check if we are assigning into a field of a union, if so, lookup the place // of the union so it is marked as initialized again. if let Some((place_base, ProjectionElem::Field(_, _))) = place.last_projection() { - if place_base.ty(self.builder.body, self.builder.tcx).ty.is_union() { + if place_base.ty(self.body, self.tcx).ty.is_union() { place = place_base; } } - if let LookupResult::Exact(path) = self.builder.data.rev_lookup.find(place) { - let init = self.builder.data.inits.push(Init { + if let LookupResult::Exact(path) = self.data.rev_lookup.find(place) { + let init = self.data.inits.push(Init { location: InitLocation::Statement(self.loc), path, kind, @@ -621,8 +604,8 @@ impl<'b, 'a, 'tcx, F: Fn(Ty<'tcx>) -> bool> Gatherer<'b, 'a, 'tcx, F> { self.loc, place, init, path ); - self.builder.data.init_path_map[path].push(init); - self.builder.data.init_loc_map[self.loc].push(init); + self.data.init_path_map[path].push(init); + self.data.init_loc_map[self.loc].push(init); } } } From 0b032f8f83216b1bee09562d07d113657ddc6527 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 6 Sep 2024 16:47:28 +1000 Subject: [PATCH 0713/2194] Remove `Elaborator`. It's a trivial wrapper around `ElaborateDropsCtxt` that serves no apparent purpose. --- .../src/elaborate_drops.rs | 60 ++++++++----------- 1 file changed, 24 insertions(+), 36 deletions(-) diff --git a/compiler/rustc_mir_transform/src/elaborate_drops.rs b/compiler/rustc_mir_transform/src/elaborate_drops.rs index ffffdf53916a7..af110878e9c28 100644 --- a/compiler/rustc_mir_transform/src/elaborate_drops.rs +++ b/compiler/rustc_mir_transform/src/elaborate_drops.rs @@ -137,45 +137,35 @@ impl InitializationData<'_, '_> { } } -struct Elaborator<'a, 'b, 'tcx> { - ctxt: &'a mut ElaborateDropsCtxt<'b, 'tcx>, -} - -impl fmt::Debug for Elaborator<'_, '_, '_> { - fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result { - Ok(()) - } -} - -impl<'b, 'tcx> DropElaborator<'b, 'tcx> for Elaborator<'_, 'b, 'tcx> { +impl<'a, 'tcx> DropElaborator<'a, 'tcx> for ElaborateDropsCtxt<'a, 'tcx> { type Path = MovePathIndex; fn patch(&mut self) -> &mut MirPatch<'tcx> { - &mut self.ctxt.patch + &mut self.patch } - fn body(&self) -> &'b Body<'tcx> { - self.ctxt.body + fn body(&self) -> &'a Body<'tcx> { + self.body } fn tcx(&self) -> TyCtxt<'tcx> { - self.ctxt.tcx + self.tcx } fn param_env(&self) -> ty::ParamEnv<'tcx> { - self.ctxt.param_env() + self.param_env() } #[instrument(level = "debug", skip(self), ret)] fn drop_style(&self, path: Self::Path, mode: DropFlagMode) -> DropStyle { let ((maybe_live, maybe_dead), multipart) = match mode { - DropFlagMode::Shallow => (self.ctxt.init_data.maybe_live_dead(path), false), + DropFlagMode::Shallow => (self.init_data.maybe_live_dead(path), false), DropFlagMode::Deep => { let mut some_live = false; let mut some_dead = false; let mut children_count = 0; - on_all_children_bits(self.ctxt.move_data(), path, |child| { - let (live, dead) = self.ctxt.init_data.maybe_live_dead(child); + on_all_children_bits(self.move_data(), path, |child| { + let (live, dead) = self.init_data.maybe_live_dead(child); debug!("elaborate_drop: state({:?}) = {:?}", child, (live, dead)); some_live |= live; some_dead |= dead; @@ -195,25 +185,25 @@ impl<'b, 'tcx> DropElaborator<'b, 'tcx> for Elaborator<'_, 'b, 'tcx> { fn clear_drop_flag(&mut self, loc: Location, path: Self::Path, mode: DropFlagMode) { match mode { DropFlagMode::Shallow => { - self.ctxt.set_drop_flag(loc, path, DropFlagState::Absent); + self.set_drop_flag(loc, path, DropFlagState::Absent); } DropFlagMode::Deep => { - on_all_children_bits(self.ctxt.move_data(), path, |child| { - self.ctxt.set_drop_flag(loc, child, DropFlagState::Absent) + on_all_children_bits(self.move_data(), path, |child| { + self.set_drop_flag(loc, child, DropFlagState::Absent) }); } } } fn field_subpath(&self, path: Self::Path, field: FieldIdx) -> Option { - rustc_mir_dataflow::move_path_children_matching(self.ctxt.move_data(), path, |e| match e { + rustc_mir_dataflow::move_path_children_matching(self.move_data(), path, |e| match e { ProjectionElem::Field(idx, _) => idx == field, _ => false, }) } fn array_subpath(&self, path: Self::Path, index: u64, size: u64) -> Option { - rustc_mir_dataflow::move_path_children_matching(self.ctxt.move_data(), path, |e| match e { + rustc_mir_dataflow::move_path_children_matching(self.move_data(), path, |e| match e { ProjectionElem::ConstantIndex { offset, min_length, from_end } => { debug_assert!(size == min_length, "min_length should be exact for arrays"); assert!(!from_end, "from_end should not be used for array element ConstantIndex"); @@ -224,20 +214,20 @@ impl<'b, 'tcx> DropElaborator<'b, 'tcx> for Elaborator<'_, 'b, 'tcx> { } fn deref_subpath(&self, path: Self::Path) -> Option { - rustc_mir_dataflow::move_path_children_matching(self.ctxt.move_data(), path, |e| { + rustc_mir_dataflow::move_path_children_matching(self.move_data(), path, |e| { e == ProjectionElem::Deref }) } fn downcast_subpath(&self, path: Self::Path, variant: VariantIdx) -> Option { - rustc_mir_dataflow::move_path_children_matching(self.ctxt.move_data(), path, |e| match e { + rustc_mir_dataflow::move_path_children_matching(self.move_data(), path, |e| match e { ProjectionElem::Downcast(_, idx) => idx == variant, _ => false, }) } fn get_drop_flag(&mut self, path: Self::Path) -> Option> { - self.ctxt.drop_flag(path).map(Operand::Copy) + self.drop_flag(path).map(Operand::Copy) } } @@ -250,6 +240,12 @@ struct ElaborateDropsCtxt<'a, 'tcx> { patch: MirPatch<'tcx>, } +impl fmt::Debug for ElaborateDropsCtxt<'_, '_> { + fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result { + Ok(()) + } +} + impl<'a, 'tcx> ElaborateDropsCtxt<'a, 'tcx> { fn move_data(&self) -> &'a MoveData<'tcx> { &self.env.move_data @@ -370,15 +366,7 @@ impl<'a, 'tcx> ElaborateDropsCtxt<'a, 'tcx> { } }; self.init_data.seek_before(self.body.terminator_loc(bb)); - elaborate_drop( - &mut Elaborator { ctxt: self }, - terminator.source_info, - place, - path, - target, - unwind, - bb, - ) + elaborate_drop(self, terminator.source_info, place, path, target, unwind, bb) } LookupResult::Parent(None) => {} LookupResult::Parent(Some(_)) => { From 5c3502772ae8298b82d1a0e5b4cb4fb15f930766 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 6 Sep 2024 16:55:42 +1000 Subject: [PATCH 0714/2194] Remove unnecessary lifetime from `StorageConflictVisitor`. --- compiler/rustc_mir_transform/src/coroutine.rs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/compiler/rustc_mir_transform/src/coroutine.rs b/compiler/rustc_mir_transform/src/coroutine.rs index eefb748e49d51..cb84149df69fe 100644 --- a/compiler/rustc_mir_transform/src/coroutine.rs +++ b/compiler/rustc_mir_transform/src/coroutine.rs @@ -872,9 +872,9 @@ fn compute_storage_conflicts<'mir, 'tcx>( storage_conflicts } -struct StorageConflictVisitor<'mir, 'tcx, 's> { - body: &'mir Body<'tcx>, - saved_locals: &'s CoroutineSavedLocals, +struct StorageConflictVisitor<'a, 'tcx> { + body: &'a Body<'tcx>, + saved_locals: &'a CoroutineSavedLocals, // FIXME(tmandry): Consider using sparse bitsets here once we have good // benchmarks for coroutines. local_conflicts: BitMatrix, @@ -882,8 +882,8 @@ struct StorageConflictVisitor<'mir, 'tcx, 's> { eligible_storage_live: BitSet, } -impl<'mir, 'tcx, R> rustc_mir_dataflow::ResultsVisitor<'mir, 'tcx, R> - for StorageConflictVisitor<'mir, 'tcx, '_> +impl<'a, 'tcx, R> rustc_mir_dataflow::ResultsVisitor<'a, 'tcx, R> + for StorageConflictVisitor<'a, 'tcx> { type FlowState = BitSet; @@ -891,7 +891,7 @@ impl<'mir, 'tcx, R> rustc_mir_dataflow::ResultsVisitor<'mir, 'tcx, R> &mut self, _results: &mut R, state: &Self::FlowState, - _statement: &'mir Statement<'tcx>, + _statement: &'a Statement<'tcx>, loc: Location, ) { self.apply_state(state, loc); @@ -901,14 +901,14 @@ impl<'mir, 'tcx, R> rustc_mir_dataflow::ResultsVisitor<'mir, 'tcx, R> &mut self, _results: &mut R, state: &Self::FlowState, - _terminator: &'mir Terminator<'tcx>, + _terminator: &'a Terminator<'tcx>, loc: Location, ) { self.apply_state(state, loc); } } -impl StorageConflictVisitor<'_, '_, '_> { +impl StorageConflictVisitor<'_, '_> { fn apply_state(&mut self, flow_state: &BitSet, loc: Location) { // Ignore unreachable blocks. if let TerminatorKind::Unreachable = self.body.basic_blocks[loc.block].terminator().kind { From 0f8efb3b5c628ac3162d5f9f37539ce19956ad80 Mon Sep 17 00:00:00 2001 From: Gurinder Singh Date: Mon, 9 Sep 2024 12:27:36 +0530 Subject: [PATCH 0715/2194] Fix ICE caused by missing span in a region error --- .../src/error_reporting/infer/region.rs | 14 +++++-- .../wf/ice-wf-missing-span-in-error-130012.rs | 18 ++++++++ ...ice-wf-missing-span-in-error-130012.stderr | 41 +++++++++++++++++++ 3 files changed, 70 insertions(+), 3 deletions(-) create mode 100644 tests/ui/wf/ice-wf-missing-span-in-error-130012.rs create mode 100644 tests/ui/wf/ice-wf-missing-span-in-error-130012.stderr diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs index e4a4ec125a5c4..5bd63ab1fee10 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs @@ -625,11 +625,19 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { if let ObligationCauseCode::WhereClause(_, span) | ObligationCauseCode::WhereClauseInExpr(_, span, ..) = &trace.cause.code().peel_derives() - && !span.is_dummy() { let span = *span; - self.report_concrete_failure(generic_param_scope, placeholder_origin, sub, sup) - .with_span_note(span, "the lifetime requirement is introduced here") + let mut err = self.report_concrete_failure( + generic_param_scope, + placeholder_origin, + sub, + sup, + ); + if !span.is_dummy() { + err = + err.with_span_note(span, "the lifetime requirement is introduced here"); + } + err } else { unreachable!( "control flow ensures we have a `BindingObligation` or `WhereClauseInExpr` here..." diff --git a/tests/ui/wf/ice-wf-missing-span-in-error-130012.rs b/tests/ui/wf/ice-wf-missing-span-in-error-130012.rs new file mode 100644 index 0000000000000..e107069d0dfa9 --- /dev/null +++ b/tests/ui/wf/ice-wf-missing-span-in-error-130012.rs @@ -0,0 +1,18 @@ +// Regression test for ICE #130012 +// Checks that we do not ICE while reporting +// lifetime mistmatch error + +trait Fun { + type Assoc; +} + +trait MyTrait: for<'a> Fun {} +//~^ ERROR binding for associated type `Assoc` references lifetime `'a`, which does not appear in the trait input types +//~| ERROR binding for associated type `Assoc` references lifetime `'a`, which does not appear in the trait input types +//~| ERROR binding for associated type `Assoc` references lifetime `'a`, which does not appear in the trait input types + +impl Fun> MyTrait for F {} +//~^ ERROR binding for associated type `Assoc` references lifetime `'b`, which does not appear in the trait input types +//~| ERROR mismatched types + +fn main() {} diff --git a/tests/ui/wf/ice-wf-missing-span-in-error-130012.stderr b/tests/ui/wf/ice-wf-missing-span-in-error-130012.stderr new file mode 100644 index 0000000000000..357e504bd5eb9 --- /dev/null +++ b/tests/ui/wf/ice-wf-missing-span-in-error-130012.stderr @@ -0,0 +1,41 @@ +error[E0582]: binding for associated type `Assoc` references lifetime `'a`, which does not appear in the trait input types + --> $DIR/ice-wf-missing-span-in-error-130012.rs:9:28 + | +LL | trait MyTrait: for<'a> Fun {} + | ^^^^^^^^^^^^^^ + +error[E0582]: binding for associated type `Assoc` references lifetime `'a`, which does not appear in the trait input types + --> $DIR/ice-wf-missing-span-in-error-130012.rs:9:28 + | +LL | trait MyTrait: for<'a> Fun {} + | ^^^^^^^^^^^^^^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error[E0582]: binding for associated type `Assoc` references lifetime `'a`, which does not appear in the trait input types + --> $DIR/ice-wf-missing-span-in-error-130012.rs:9:28 + | +LL | trait MyTrait: for<'a> Fun {} + | ^^^^^^^^^^^^^^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error[E0582]: binding for associated type `Assoc` references lifetime `'b`, which does not appear in the trait input types + --> $DIR/ice-wf-missing-span-in-error-130012.rs:14:21 + | +LL | impl Fun> MyTrait for F {} + | ^^^^^^^^^^^^^^ + +error[E0308]: mismatched types + --> $DIR/ice-wf-missing-span-in-error-130012.rs:14:50 + | +LL | impl Fun> MyTrait for F {} + | ^ lifetime mismatch + | + = note: expected reference `&()` + found reference `&'b ()` + +error: aborting due to 5 previous errors + +Some errors have detailed explanations: E0308, E0582. +For more information about an error, try `rustc --explain E0308`. From 54672ac392e3a4af640f59db01e93200b96c97d5 Mon Sep 17 00:00:00 2001 From: Rain Date: Mon, 9 Sep 2024 06:48:56 +0000 Subject: [PATCH 0716/2194] [illumos] enable SIGSEGV handler to detect stack overflows Use the same code as Solaris. I couldn't find any tests regarding this, but I did test a stage0 build against my stack-exhaust-test binary [1]. Before: ``` running with use_stacker = No, new_thread = false, make_large_local = false zsh: segmentation fault (core dumped) cargo run ``` After: ``` running with use_stacker = No, new_thread = false, make_large_local = false thread 'main' has overflowed its stack fatal runtime error: stack overflow zsh: IOT instruction (core dumped) cargo +stage0 run ``` Fixes #128568. [1] https://github.com/sunshowers/stack-exhaust-test/ --- library/std/src/sys/pal/unix/stack_overflow.rs | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/library/std/src/sys/pal/unix/stack_overflow.rs b/library/std/src/sys/pal/unix/stack_overflow.rs index 9ff44b54c41a1..728ce8d60f639 100644 --- a/library/std/src/sys/pal/unix/stack_overflow.rs +++ b/library/std/src/sys/pal/unix/stack_overflow.rs @@ -32,7 +32,8 @@ impl Drop for Handler { target_os = "macos", target_os = "netbsd", target_os = "openbsd", - target_os = "solaris" + target_os = "solaris", + target_os = "illumos", ))] mod imp { #[cfg(not(all(target_os = "linux", target_env = "gnu")))] @@ -280,7 +281,7 @@ mod imp { libc::SIGSTKSZ } - #[cfg(target_os = "solaris")] + #[cfg(any(target_os = "solaris", target_os = "illumos"))] unsafe fn get_stack_start() -> Option<*mut libc::c_void> { let mut current_stack: libc::stack_t = crate::mem::zeroed(); assert_eq!(libc::stack_getbounds(&mut current_stack), 0); @@ -486,7 +487,12 @@ mod imp { Some(guardaddr..guardaddr + page_size) } - #[cfg(any(target_os = "macos", target_os = "openbsd", target_os = "solaris"))] + #[cfg(any( + target_os = "macos", + target_os = "openbsd", + target_os = "solaris", + target_os = "illumos", + ))] // FIXME: I am probably not unsafe. unsafe fn current_guard() -> Option> { let stackptr = get_stack_start()?; @@ -569,7 +575,8 @@ mod imp { target_os = "macos", target_os = "netbsd", target_os = "openbsd", - target_os = "solaris" + target_os = "solaris", + target_os = "illumos", )))] mod imp { pub unsafe fn init() {} From c33aa863f8852ab0388aed6e578ba015eae702a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Mon, 9 Sep 2024 09:45:59 +0200 Subject: [PATCH 0717/2194] Do not skip linker configuration for `check` builds It was causing unexpected rebuilds. --- src/bootstrap/src/core/builder.rs | 5 +++-- src/bootstrap/src/utils/cc_detect.rs | 1 - 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/bootstrap/src/core/builder.rs b/src/bootstrap/src/core/builder.rs index 8f7ade7940342..1e8779817fb71 100644 --- a/src/bootstrap/src/core/builder.rs +++ b/src/bootstrap/src/core/builder.rs @@ -2465,8 +2465,9 @@ impl Cargo { let mut cargo = builder.cargo(compiler, mode, source_type, target, cmd_kind); match cmd_kind { - // No need to configure the target linker for these command types. - Kind::Clean | Kind::Check | Kind::Suggest | Kind::Format | Kind::Setup => {} + // No need to configure the target linker for these command types, + // as they don't invoke rustc at all. + Kind::Clean | Kind::Suggest | Kind::Format | Kind::Setup => {} _ => { cargo.configure_linker(builder); } diff --git a/src/bootstrap/src/utils/cc_detect.rs b/src/bootstrap/src/utils/cc_detect.rs index a2c7ab31df8a5..c39415e7c1865 100644 --- a/src/bootstrap/src/utils/cc_detect.rs +++ b/src/bootstrap/src/utils/cc_detect.rs @@ -90,7 +90,6 @@ pub fn find(build: &Build) { let targets: HashSet<_> = match build.config.cmd { // We don't need to check cross targets for these commands. crate::Subcommand::Clean { .. } - | crate::Subcommand::Check { .. } | crate::Subcommand::Suggest { .. } | crate::Subcommand::Format { .. } | crate::Subcommand::Setup { .. } => { From 9e9526c6ab12fce8113d6c18d348572f4f98492b Mon Sep 17 00:00:00 2001 From: Samuel Tardieu Date: Sat, 7 Sep 2024 16:18:45 +0200 Subject: [PATCH 0718/2194] Special-case suggestions for null pointers constness cast --- clippy_lints/src/casts/mod.rs | 6 +- clippy_lints/src/casts/ptr_cast_constness.rs | 62 ++++++++++++++------ tests/ui/ptr_cast_constness.fixed | 13 ++++ tests/ui/ptr_cast_constness.rs | 13 ++++ tests/ui/ptr_cast_constness.stderr | 22 ++++++- 5 files changed, 97 insertions(+), 19 deletions(-) diff --git a/clippy_lints/src/casts/mod.rs b/clippy_lints/src/casts/mod.rs index c31716fbcee1d..fccddf558ed82 100644 --- a/clippy_lints/src/casts/mod.rs +++ b/clippy_lints/src/casts/mod.rs @@ -410,19 +410,23 @@ declare_clippy_lint! { /// ### Why is this bad? /// Though `as` casts between raw pointers are not terrible, `pointer::cast_mut` and /// `pointer::cast_const` are safer because they cannot accidentally cast the pointer to another - /// type. + /// type. Or, when null pointers are involved, `null()` and `null_mut()` can be used directly. /// /// ### Example /// ```no_run /// let ptr: *const u32 = &42_u32; /// let mut_ptr = ptr as *mut u32; /// let ptr = mut_ptr as *const u32; + /// let ptr1 = std::ptr::null::() as *mut u32; + /// let ptr2 = std::ptr::null_mut::() as *const u32; /// ``` /// Use instead: /// ```no_run /// let ptr: *const u32 = &42_u32; /// let mut_ptr = ptr.cast_mut(); /// let ptr = mut_ptr.cast_const(); + /// let ptr1 = std::ptr::null_mut::(); + /// let ptr2 = std::ptr::null::(); /// ``` #[clippy::version = "1.72.0"] pub PTR_CAST_CONSTNESS, diff --git a/clippy_lints/src/casts/ptr_cast_constness.rs b/clippy_lints/src/casts/ptr_cast_constness.rs index 7513e18d408b1..98bc38ed134df 100644 --- a/clippy_lints/src/casts/ptr_cast_constness.rs +++ b/clippy_lints/src/casts/ptr_cast_constness.rs @@ -1,10 +1,12 @@ use clippy_config::msrvs::{self, Msrv}; use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::std_or_core; use clippy_utils::sugg::Sugg; use rustc_errors::Applicability; -use rustc_hir::{Expr, Mutability}; +use rustc_hir::{Expr, ExprKind, Mutability, QPath}; use rustc_lint::LateContext; use rustc_middle::ty::{self, Ty, TypeVisitableExt}; +use rustc_span::sym; use super::PTR_CAST_CONSTNESS; @@ -16,8 +18,7 @@ pub(super) fn check<'tcx>( cast_to: Ty<'tcx>, msrv: &Msrv, ) { - if msrv.meets(msrvs::POINTER_CAST_CONSTNESS) - && let ty::RawPtr(from_ty, from_mutbl) = cast_from.kind() + if let ty::RawPtr(from_ty, from_mutbl) = cast_from.kind() && let ty::RawPtr(to_ty, to_mutbl) = cast_to.kind() && matches!( (from_mutbl, to_mutbl), @@ -26,20 +27,47 @@ pub(super) fn check<'tcx>( && from_ty == to_ty && !from_ty.has_erased_regions() { - let sugg = Sugg::hir(cx, cast_expr, "_"); - let constness = match *to_mutbl { - Mutability::Not => "const", - Mutability::Mut => "mut", - }; + if let ExprKind::Call(func, []) = cast_expr.kind + && let ExprKind::Path(QPath::Resolved(None, path)) = func.kind + && let Some(defid) = path.res.opt_def_id() + && let Some(prefix) = std_or_core(cx) + && let mut app = Applicability::MachineApplicable + && let sugg = format!("{}", Sugg::hir_with_applicability(cx, cast_expr, "_", &mut app)) + && let Some((_, after_lt)) = sugg.split_once("::<") + && let Some((source, target, target_func)) = match cx.tcx.get_diagnostic_name(defid) { + Some(sym::ptr_null) => Some(("const", "mutable", "null_mut")), + Some(sym::ptr_null_mut) => Some(("mutable", "const", "null")), + _ => None, + } + { + span_lint_and_sugg( + cx, + PTR_CAST_CONSTNESS, + expr.span, + format!("`as` casting to make a {source} null pointer into a {target} null pointer"), + format!("use `{target_func}()` directly instead"), + format!("{prefix}::ptr::{target_func}::<{after_lt}"), + app, + ); + return; + } - span_lint_and_sugg( - cx, - PTR_CAST_CONSTNESS, - expr.span, - "`as` casting between raw pointers while changing only its constness", - format!("try `pointer::cast_{constness}`, a safer alternative"), - format!("{}.cast_{constness}()", sugg.maybe_par()), - Applicability::MachineApplicable, - ); + if msrv.meets(msrvs::POINTER_CAST_CONSTNESS) { + let sugg = Sugg::hir(cx, cast_expr, "_"); + let constness = match *to_mutbl { + Mutability::Not => "const", + Mutability::Mut => "mut", + }; + + span_lint_and_sugg( + cx, + PTR_CAST_CONSTNESS, + expr.span, + "`as` casting between raw pointers while changing only its constness", + format!("try `pointer::cast_{constness}`, a safer alternative"), + format!("{}.cast_{constness}()", sugg.maybe_par()), + Applicability::MachineApplicable, + ); + } } } diff --git a/tests/ui/ptr_cast_constness.fixed b/tests/ui/ptr_cast_constness.fixed index 21ac42196e1bb..5bf9a30b01617 100644 --- a/tests/ui/ptr_cast_constness.fixed +++ b/tests/ui/ptr_cast_constness.fixed @@ -68,3 +68,16 @@ fn _msrv_1_65() { let _ = ptr.cast_mut(); let _ = mut_ptr.cast_const(); } + +#[inline_macros] +fn null_pointers() { + use std::ptr; + let _ = std::ptr::null_mut::(); + let _ = std::ptr::null::(); + + // Make sure the lint is triggered inside a macro + let _ = inline!(std::ptr::null_mut::()); + + // Do not lint inside macros from external crates + let _ = external!(ptr::null::() as *mut u32); +} diff --git a/tests/ui/ptr_cast_constness.rs b/tests/ui/ptr_cast_constness.rs index 5ce590b2b7e47..2575a5923e124 100644 --- a/tests/ui/ptr_cast_constness.rs +++ b/tests/ui/ptr_cast_constness.rs @@ -68,3 +68,16 @@ fn _msrv_1_65() { let _ = ptr as *mut u32; let _ = mut_ptr as *const u32; } + +#[inline_macros] +fn null_pointers() { + use std::ptr; + let _ = ptr::null::() as *mut String; + let _ = ptr::null_mut::() as *const u32; + + // Make sure the lint is triggered inside a macro + let _ = inline!(ptr::null::() as *mut u32); + + // Do not lint inside macros from external crates + let _ = external!(ptr::null::() as *mut u32); +} diff --git a/tests/ui/ptr_cast_constness.stderr b/tests/ui/ptr_cast_constness.stderr index 2c52ebd3464d6..0806ca62806d1 100644 --- a/tests/ui/ptr_cast_constness.stderr +++ b/tests/ui/ptr_cast_constness.stderr @@ -43,5 +43,25 @@ error: `as` casting between raw pointers while changing only its constness LL | let _ = mut_ptr as *const u32; | ^^^^^^^^^^^^^^^^^^^^^ help: try `pointer::cast_const`, a safer alternative: `mut_ptr.cast_const()` -error: aborting due to 7 previous errors +error: `as` casting to make a const null pointer into a mutable null pointer + --> tests/ui/ptr_cast_constness.rs:75:13 + | +LL | let _ = ptr::null::() as *mut String; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `null_mut()` directly instead: `std::ptr::null_mut::()` + +error: `as` casting to make a mutable null pointer into a const null pointer + --> tests/ui/ptr_cast_constness.rs:76:13 + | +LL | let _ = ptr::null_mut::() as *const u32; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `null()` directly instead: `std::ptr::null::()` + +error: `as` casting to make a const null pointer into a mutable null pointer + --> tests/ui/ptr_cast_constness.rs:79:21 + | +LL | let _ = inline!(ptr::null::() as *mut u32); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `null_mut()` directly instead: `std::ptr::null_mut::()` + | + = note: this error originates in the macro `__inline_mac_fn_null_pointers` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 10 previous errors From 30608732c2f68c423e4a62e6c20cdf28f6d38559 Mon Sep 17 00:00:00 2001 From: Samuel Tardieu Date: Sat, 7 Sep 2024 21:57:29 +0200 Subject: [PATCH 0719/2194] Handle null pointer constness cast through methods This covers two cases: - `core::ptr::null::().cast_mut()` -> `core::ptr::null_mut::()` - `core::ptr::null_mut::().cast_const()` -> `core::ptr::null::()` --- clippy_lints/src/casts/mod.rs | 5 ++++ clippy_lints/src/casts/ptr_cast_constness.rs | 27 ++++++++++++++++++++ tests/ui/ptr_cast_constness.fixed | 4 +++ tests/ui/ptr_cast_constness.rs | 4 +++ tests/ui/ptr_cast_constness.stderr | 24 +++++++++++++++-- 5 files changed, 62 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/casts/mod.rs b/clippy_lints/src/casts/mod.rs index fccddf558ed82..39f50a347c064 100644 --- a/clippy_lints/src/casts/mod.rs +++ b/clippy_lints/src/casts/mod.rs @@ -419,6 +419,8 @@ declare_clippy_lint! { /// let ptr = mut_ptr as *const u32; /// let ptr1 = std::ptr::null::() as *mut u32; /// let ptr2 = std::ptr::null_mut::() as *const u32; + /// let ptr3 = std::ptr::null::().cast_mut(); + /// let ptr4 = std::ptr::null_mut::().cast_const(); /// ``` /// Use instead: /// ```no_run @@ -427,6 +429,8 @@ declare_clippy_lint! { /// let ptr = mut_ptr.cast_const(); /// let ptr1 = std::ptr::null_mut::(); /// let ptr2 = std::ptr::null::(); + /// let ptr3 = std::ptr::null_mut::(); + /// let ptr4 = std::ptr::null::(); /// ``` #[clippy::version = "1.72.0"] pub PTR_CAST_CONSTNESS, @@ -813,6 +817,7 @@ impl<'tcx> LateLintPass<'tcx> for Casts { char_lit_as_u8::check(cx, expr); ptr_as_ptr::check(cx, expr, &self.msrv); cast_slice_different_sizes::check(cx, expr, &self.msrv); + ptr_cast_constness::check_null_ptr_cast_method(cx, expr); } extract_msrv_attr!(LateContext); diff --git a/clippy_lints/src/casts/ptr_cast_constness.rs b/clippy_lints/src/casts/ptr_cast_constness.rs index 98bc38ed134df..7518dd2435aee 100644 --- a/clippy_lints/src/casts/ptr_cast_constness.rs +++ b/clippy_lints/src/casts/ptr_cast_constness.rs @@ -71,3 +71,30 @@ pub(super) fn check<'tcx>( } } } + +pub(super) fn check_null_ptr_cast_method(cx: &LateContext<'_>, expr: &Expr<'_>) { + if let ExprKind::MethodCall(method, cast_expr, [], _) = expr.kind + && let ExprKind::Call(func, []) = cast_expr.kind + && let ExprKind::Path(QPath::Resolved(None, path)) = func.kind + && let Some(defid) = path.res.opt_def_id() + && let method = match (cx.tcx.get_diagnostic_name(defid), method.ident.as_str()) { + (Some(sym::ptr_null), "cast_mut") => "null_mut", + (Some(sym::ptr_null_mut), "cast_const") => "null", + _ => return, + } + && let Some(prefix) = std_or_core(cx) + && let mut app = Applicability::MachineApplicable + && let sugg = format!("{}", Sugg::hir_with_applicability(cx, cast_expr, "_", &mut app)) + && let Some((_, after_lt)) = sugg.split_once("::<") + { + span_lint_and_sugg( + cx, + PTR_CAST_CONSTNESS, + expr.span, + "changing constness of a null pointer", + format!("use `{method}()` directly instead"), + format!("{prefix}::ptr::{method}::<{after_lt}"), + app, + ); + } +} diff --git a/tests/ui/ptr_cast_constness.fixed b/tests/ui/ptr_cast_constness.fixed index 5bf9a30b01617..9a5272c7adc36 100644 --- a/tests/ui/ptr_cast_constness.fixed +++ b/tests/ui/ptr_cast_constness.fixed @@ -74,10 +74,14 @@ fn null_pointers() { use std::ptr; let _ = std::ptr::null_mut::(); let _ = std::ptr::null::(); + let _ = std::ptr::null_mut::(); + let _ = std::ptr::null::(); // Make sure the lint is triggered inside a macro let _ = inline!(std::ptr::null_mut::()); + let _ = inline!(std::ptr::null_mut::()); // Do not lint inside macros from external crates let _ = external!(ptr::null::() as *mut u32); + let _ = external!(ptr::null::().cast_mut()); } diff --git a/tests/ui/ptr_cast_constness.rs b/tests/ui/ptr_cast_constness.rs index 2575a5923e124..43ab5f5ba7ccc 100644 --- a/tests/ui/ptr_cast_constness.rs +++ b/tests/ui/ptr_cast_constness.rs @@ -74,10 +74,14 @@ fn null_pointers() { use std::ptr; let _ = ptr::null::() as *mut String; let _ = ptr::null_mut::() as *const u32; + let _ = ptr::null::().cast_mut(); + let _ = ptr::null_mut::().cast_const(); // Make sure the lint is triggered inside a macro let _ = inline!(ptr::null::() as *mut u32); + let _ = inline!(ptr::null::().cast_mut()); // Do not lint inside macros from external crates let _ = external!(ptr::null::() as *mut u32); + let _ = external!(ptr::null::().cast_mut()); } diff --git a/tests/ui/ptr_cast_constness.stderr b/tests/ui/ptr_cast_constness.stderr index 0806ca62806d1..a693793a4ae96 100644 --- a/tests/ui/ptr_cast_constness.stderr +++ b/tests/ui/ptr_cast_constness.stderr @@ -55,13 +55,33 @@ error: `as` casting to make a mutable null pointer into a const null pointer LL | let _ = ptr::null_mut::() as *const u32; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `null()` directly instead: `std::ptr::null::()` +error: changing constness of a null pointer + --> tests/ui/ptr_cast_constness.rs:77:13 + | +LL | let _ = ptr::null::().cast_mut(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `null_mut()` directly instead: `std::ptr::null_mut::()` + +error: changing constness of a null pointer + --> tests/ui/ptr_cast_constness.rs:78:13 + | +LL | let _ = ptr::null_mut::().cast_const(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `null()` directly instead: `std::ptr::null::()` + error: `as` casting to make a const null pointer into a mutable null pointer - --> tests/ui/ptr_cast_constness.rs:79:21 + --> tests/ui/ptr_cast_constness.rs:81:21 | LL | let _ = inline!(ptr::null::() as *mut u32); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `null_mut()` directly instead: `std::ptr::null_mut::()` | = note: this error originates in the macro `__inline_mac_fn_null_pointers` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to 10 previous errors +error: changing constness of a null pointer + --> tests/ui/ptr_cast_constness.rs:82:21 + | +LL | let _ = inline!(ptr::null::().cast_mut()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `null_mut()` directly instead: `std::ptr::null_mut::()` + | + = note: this error originates in the macro `__inline_mac_fn_null_pointers` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 13 previous errors From 06d1aa257e4809cee5364e4f0a0ee6faf0706dc6 Mon Sep 17 00:00:00 2001 From: cuishuang Date: Mon, 9 Sep 2024 16:36:37 +0800 Subject: [PATCH 0720/2194] Remove unnecessary symbols and add missing symbols Signed-off-by: cuishuang --- src/tools/rust-analyzer/crates/hir-expand/src/declarative.rs | 2 +- .../crates/ide-assists/src/handlers/inline_type_alias.rs | 1 + .../crates/ide-assists/src/handlers/wrap_unwrap_cfg_attr.rs | 1 + src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs | 2 +- .../crates/rust-analyzer/tests/slow-tests/ratoml.rs | 2 +- 5 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/declarative.rs b/src/tools/rust-analyzer/crates/hir-expand/src/declarative.rs index b1a6eed2fbc71..86dd4aef090ff 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/declarative.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/declarative.rs @@ -1,4 +1,4 @@ -//! Compiled declarative macro expanders (`macro_rules!`` and `macro`) +//! Compiled declarative macro expanders (`macro_rules!` and `macro`) use base_db::CrateId; use intern::sym; diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/inline_type_alias.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/inline_type_alias.rs index f6624d6c872d0..66dffde505c13 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/inline_type_alias.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/inline_type_alias.rs @@ -43,6 +43,7 @@ use super::inline_call::split_refs_and_uses; // fn foo() { // let _: i32 = 3; // } +// ``` pub(crate) fn inline_type_alias_uses(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> { let name = ctx.find_node_at_offset::()?; let ast_alias = name.syntax().parent().and_then(ast::TypeAlias::cast)?; diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/wrap_unwrap_cfg_attr.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/wrap_unwrap_cfg_attr.rs index 0fa46ef43a1ef..149cb4c43849d 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/wrap_unwrap_cfg_attr.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/wrap_unwrap_cfg_attr.rs @@ -25,6 +25,7 @@ use crate::{AssistContext, AssistId, AssistKind, Assists}; // struct S { // field: i32 // } +// ``` enum WrapUnwrapOption { WrapDerive { derive: TextRange, attr: ast::Attr }, diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs index e4e8c9c6d9f97..3295ec258e2f0 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs @@ -60,7 +60,7 @@ mod patch_old_style; // However, editor specific config, which the server doesn't know about, should // be specified directly in `package.json`. // -// To deprecate an option by replacing it with another name use `new_name | `old_name` so that we keep +// To deprecate an option by replacing it with another name use `new_name` | `old_name` so that we keep // parsing the old name. config_data! { /// Configs that apply on a workspace-wide scope. There are 2 levels on which a global configuration can be configured diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/ratoml.rs b/src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/ratoml.rs index 295d1d4e8e909..a3e7528b39b1b 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/ratoml.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/ratoml.rs @@ -765,7 +765,7 @@ fn ratoml_multiple_ratoml_in_single_source_root() { // [dependencies] // p2 = { path = "../p2" } -// #, +// "#, // r#" // //- /p1/src/lib.rs // enum Value { From e186cc6df8e22341036560f79cb99691bb54b483 Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Mon, 9 Sep 2024 11:09:22 +0200 Subject: [PATCH 0721/2194] do `PolyFnSig` -> `FnSig` conversion later --- .../rustc_hir_analysis/src/hir_ty_lowering/cmse.rs | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/cmse.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/cmse.rs index dd519fb92d951..5150db7f51b19 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/cmse.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/cmse.rs @@ -18,9 +18,6 @@ pub(crate) fn validate_cmse_abi<'tcx>( abi: abi::Abi, fn_sig: ty::PolyFnSig<'tcx>, ) { - // this type is only used for layout computation, which does not rely on regions - let fn_sig = tcx.instantiate_bound_regions_with_erased(fn_sig); - if let abi::Abi::CCmseNonSecureCall = abi { let hir_node = tcx.hir_node(hir_id); let hir::Node::Ty(hir::Ty { @@ -70,11 +67,14 @@ pub(crate) fn validate_cmse_abi<'tcx>( /// Returns whether the inputs will fit into the available registers fn is_valid_cmse_inputs<'tcx>( tcx: TyCtxt<'tcx>, - fn_sig: ty::FnSig<'tcx>, + fn_sig: ty::PolyFnSig<'tcx>, ) -> Result, &'tcx LayoutError<'tcx>> { let mut span = None; let mut accum = 0u64; + // this type is only used for layout computation, which does not rely on regions + let fn_sig = tcx.instantiate_bound_regions_with_erased(fn_sig); + for (index, ty) in fn_sig.inputs().iter().enumerate() { let layout = tcx.layout_of(ParamEnv::reveal_all().and(*ty))?; @@ -99,8 +99,11 @@ fn is_valid_cmse_inputs<'tcx>( /// Returns whether the output will fit into the available registers fn is_valid_cmse_output<'tcx>( tcx: TyCtxt<'tcx>, - fn_sig: ty::FnSig<'tcx>, + fn_sig: ty::PolyFnSig<'tcx>, ) -> Result> { + // this type is only used for layout computation, which does not rely on regions + let fn_sig = tcx.instantiate_bound_regions_with_erased(fn_sig); + let mut ret_ty = fn_sig.output(); let layout = tcx.layout_of(ParamEnv::reveal_all().and(ret_ty))?; let size = layout.layout.size().bytes(); From 62d196feb1607c93fb4bc9dc54bf08883496a6a2 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 9 Sep 2024 11:20:22 +0200 Subject: [PATCH 0722/2194] bootstrap/Makefile.in: miri: add missing BOOTSTRAP ARGS also don't unnecessarily set BOOTSTRAP_SKIP_TARGET_SANITY while we are at it --- src/bootstrap/mk/Makefile.in | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/bootstrap/mk/Makefile.in b/src/bootstrap/mk/Makefile.in index 9acd85cddde6a..3fa2b3c22921e 100644 --- a/src/bootstrap/mk/Makefile.in +++ b/src/bootstrap/mk/Makefile.in @@ -54,30 +54,34 @@ check-aux: src/etc/test-float-parse \ $(BOOTSTRAP_ARGS) # Run standard library tests in Miri. - $(Q)BOOTSTRAP_SKIP_TARGET_SANITY=1 \ - $(BOOTSTRAP) miri --stage 2 \ + $(Q)$(BOOTSTRAP) miri --stage 2 \ library/core \ library/alloc \ + $(BOOTSTRAP_ARGS) \ --no-doc # Some doctests use file system operations to demonstrate dealing with `Result`. $(Q)MIRIFLAGS="-Zmiri-disable-isolation" \ $(BOOTSTRAP) miri --stage 2 \ library/core \ library/alloc \ + $(BOOTSTRAP_ARGS) \ --doc # In `std` we cannot test everything, so we skip some modules. $(Q)MIRIFLAGS="-Zmiri-disable-isolation" \ $(BOOTSTRAP) miri --stage 2 library/std \ + $(BOOTSTRAP_ARGS) \ --no-doc -- \ --skip fs:: --skip net:: --skip process:: --skip sys::pal:: $(Q)MIRIFLAGS="-Zmiri-disable-isolation" \ $(BOOTSTRAP) miri --stage 2 library/std \ + $(BOOTSTRAP_ARGS) \ --doc -- \ --skip fs:: --skip net:: --skip process:: --skip sys::pal:: # Also test some very target-specific modules on other targets # (making sure to cover an i686 target as well). $(Q)MIRIFLAGS="-Zmiri-disable-isolation" BOOTSTRAP_SKIP_TARGET_SANITY=1 \ $(BOOTSTRAP) miri --stage 2 library/std \ + $(BOOTSTRAP_ARGS) \ --target aarch64-apple-darwin,i686-pc-windows-msvc \ --no-doc -- \ time:: sync:: thread:: env:: From 02378997ea98b17973a14298a59568700435965d Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Mon, 9 Sep 2024 12:47:40 +0200 Subject: [PATCH 0723/2194] bootstrap `naked_asm!` for `compiler-builtins` in this commit, `naked_asm!` is an alias for `asm!` with one difference: `options(noreturn)` is always enabled by `naked_asm!`. That makes it future-compatible for when `naked_asm!` starts disallowing `options(noreturn)` later. --- compiler/rustc_builtin_macros/src/asm.rs | 38 ++++++++++++++++++++++++ compiler/rustc_builtin_macros/src/lib.rs | 1 + compiler/rustc_span/src/symbol.rs | 1 + library/core/src/arch.rs | 14 +++++++++ tests/ui/asm/naked-functions-inline.rs | 12 ++++---- 5 files changed, 60 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_builtin_macros/src/asm.rs b/compiler/rustc_builtin_macros/src/asm.rs index ae2627d693867..e313016e3d863 100644 --- a/compiler/rustc_builtin_macros/src/asm.rs +++ b/compiler/rustc_builtin_macros/src/asm.rs @@ -812,6 +812,44 @@ pub(super) fn expand_asm<'cx>( }) } +pub(super) fn expand_naked_asm<'cx>( + ecx: &'cx mut ExtCtxt<'_>, + sp: Span, + tts: TokenStream, +) -> MacroExpanderResult<'cx> { + ExpandResult::Ready(match parse_args(ecx, sp, tts, false) { + Ok(args) => { + let ExpandResult::Ready(mac) = expand_preparsed_asm(ecx, args) else { + return ExpandResult::Retry(()); + }; + let expr = match mac { + Ok(mut inline_asm) => { + // for future compatibility, we always set the NORETURN option. + // + // When we turn `asm!` into `naked_asm!` with this implementation, we can drop + // the `options(noreturn)`, which makes the upgrade smooth when `naked_asm!` + // starts disallowing the `noreturn` option in the future + inline_asm.options |= ast::InlineAsmOptions::NORETURN; + + P(ast::Expr { + id: ast::DUMMY_NODE_ID, + kind: ast::ExprKind::InlineAsm(P(inline_asm)), + span: sp, + attrs: ast::AttrVec::new(), + tokens: None, + }) + } + Err(guar) => DummyResult::raw_expr(sp, Some(guar)), + }; + MacEager::expr(expr) + } + Err(err) => { + let guar = err.emit(); + DummyResult::any(sp, guar) + } + }) +} + pub(super) fn expand_global_asm<'cx>( ecx: &'cx mut ExtCtxt<'_>, sp: Span, diff --git a/compiler/rustc_builtin_macros/src/lib.rs b/compiler/rustc_builtin_macros/src/lib.rs index 30e1c8d262216..ebe5e2b544292 100644 --- a/compiler/rustc_builtin_macros/src/lib.rs +++ b/compiler/rustc_builtin_macros/src/lib.rs @@ -94,6 +94,7 @@ pub fn register_builtin_macros(resolver: &mut dyn ResolverExpand) { line: source_util::expand_line, log_syntax: log_syntax::expand_log_syntax, module_path: source_util::expand_mod, + naked_asm: asm::expand_naked_asm, option_env: env::expand_option_env, pattern_type: pattern_type::expand, std_panic: edition_panic::expand_panic, diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 418d1078900ac..1f3fb71909bc6 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1254,6 +1254,7 @@ symbols! { mut_preserve_binding_mode_2024, mut_ref, naked, + naked_asm, naked_functions, name, names, diff --git a/library/core/src/arch.rs b/library/core/src/arch.rs index d681bd124fe13..b07cc9a71a8a0 100644 --- a/library/core/src/arch.rs +++ b/library/core/src/arch.rs @@ -26,6 +26,20 @@ pub macro asm("assembly template", $(operands,)* $(options($(option),*))?) { /* compiler built-in */ } +/// Inline assembly used in combination with `#[naked]` functions. +/// +/// Refer to [Rust By Example] for a usage guide and the [reference] for +/// detailed information about the syntax and available options. +/// +/// [Rust By Example]: https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html +/// [reference]: https://doc.rust-lang.org/nightly/reference/inline-assembly.html +#[unstable(feature = "naked_functions", issue = "90957")] +#[rustc_builtin_macro] +#[cfg(not(bootstrap))] +pub macro naked_asm("assembly template", $(operands,)* $(options($(option),*))?) { + /* compiler built-in */ +} + /// Module-level inline assembly. /// /// Refer to [Rust By Example] for a usage guide and the [reference] for diff --git a/tests/ui/asm/naked-functions-inline.rs b/tests/ui/asm/naked-functions-inline.rs index cfb38f2e73848..74049e8ecbc7c 100644 --- a/tests/ui/asm/naked-functions-inline.rs +++ b/tests/ui/asm/naked-functions-inline.rs @@ -2,37 +2,37 @@ #![feature(naked_functions)] #![crate_type = "lib"] -use std::arch::asm; +use std::arch::naked_asm; #[naked] pub unsafe extern "C" fn inline_none() { - asm!("", options(noreturn)); + naked_asm!(""); } #[naked] #[inline] //~^ ERROR [E0736] pub unsafe extern "C" fn inline_hint() { - asm!("", options(noreturn)); + naked_asm!(""); } #[naked] #[inline(always)] //~^ ERROR [E0736] pub unsafe extern "C" fn inline_always() { - asm!("", options(noreturn)); + naked_asm!(""); } #[naked] #[inline(never)] //~^ ERROR [E0736] pub unsafe extern "C" fn inline_never() { - asm!("", options(noreturn)); + naked_asm!(""); } #[naked] #[cfg_attr(all(), inline(never))] //~^ ERROR [E0736] pub unsafe extern "C" fn conditional_inline_never() { - asm!("", options(noreturn)); + naked_asm!(""); } From 4c8b84ae82ce66ea62e323c8dff68475d5d375b3 Mon Sep 17 00:00:00 2001 From: Deadbeef Date: Mon, 9 Sep 2024 18:36:21 +0800 Subject: [PATCH 0724/2194] `RepeatN`: use MaybeUninit --- library/core/src/iter/sources/repeat_n.rs | 60 +++++++++++++++++------ library/core/tests/iter/sources.rs | 24 +++++++++ 2 files changed, 69 insertions(+), 15 deletions(-) diff --git a/library/core/src/iter/sources/repeat_n.rs b/library/core/src/iter/sources/repeat_n.rs index 9c0621933638e..7e162ff387baf 100644 --- a/library/core/src/iter/sources/repeat_n.rs +++ b/library/core/src/iter/sources/repeat_n.rs @@ -1,5 +1,6 @@ +use crate::fmt; use crate::iter::{FusedIterator, TrustedLen, UncheckedIterator}; -use crate::mem::ManuallyDrop; +use crate::mem::{self, MaybeUninit}; use crate::num::NonZero; /// Creates a new iterator that repeats a single element a given number of times. @@ -58,14 +59,12 @@ use crate::num::NonZero; #[inline] #[stable(feature = "iter_repeat_n", since = "1.82.0")] pub fn repeat_n(element: T, count: usize) -> RepeatN { - let mut element = ManuallyDrop::new(element); - - if count == 0 { - // SAFETY: we definitely haven't dropped it yet, since we only just got - // passed it in, and because the count is zero the instance we're about - // to create won't drop it, so to avoid leaking we need to now. - unsafe { ManuallyDrop::drop(&mut element) }; - } + let element = if count == 0 { + // `element` gets dropped eagerly. + MaybeUninit::uninit() + } else { + MaybeUninit::new(element) + }; RepeatN { element, count } } @@ -74,15 +73,23 @@ pub fn repeat_n(element: T, count: usize) -> RepeatN { /// /// This `struct` is created by the [`repeat_n()`] function. /// See its documentation for more. -#[derive(Clone, Debug)] #[stable(feature = "iter_repeat_n", since = "1.82.0")] pub struct RepeatN { count: usize, - // Invariant: has been dropped iff count == 0. - element: ManuallyDrop, + // Invariant: uninit iff count == 0. + element: MaybeUninit, } impl RepeatN { + /// Returns the element if it hasn't been dropped already. + fn element_ref(&self) -> Option<&A> { + if self.count > 0 { + // SAFETY: The count is non-zero, so it must be initialized. + Some(unsafe { self.element.assume_init_ref() }) + } else { + None + } + } /// If we haven't already dropped the element, return it in an option. /// /// Clears the count so it won't be dropped again later. @@ -90,15 +97,36 @@ impl RepeatN { fn take_element(&mut self) -> Option { if self.count > 0 { self.count = 0; + let element = mem::replace(&mut self.element, MaybeUninit::uninit()); // SAFETY: We just set count to zero so it won't be dropped again, // and it used to be non-zero so it hasn't already been dropped. - unsafe { Some(ManuallyDrop::take(&mut self.element)) } + unsafe { Some(element.assume_init()) } } else { None } } } +#[stable(feature = "iter_repeat_n", since = "1.82.0")] +impl Clone for RepeatN { + fn clone(&self) -> RepeatN { + RepeatN { + count: self.count, + element: self.element_ref().cloned().map_or_else(MaybeUninit::uninit, MaybeUninit::new), + } + } +} + +#[stable(feature = "iter_repeat_n", since = "1.82.0")] +impl fmt::Debug for RepeatN { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("RepeatN") + .field("count", &self.count) + .field("element", &self.element_ref()) + .finish() + } +} + #[stable(feature = "iter_repeat_n", since = "1.82.0")] impl Drop for RepeatN { fn drop(&mut self) { @@ -194,9 +222,11 @@ impl UncheckedIterator for RepeatN { // SAFETY: the check above ensured that the count used to be non-zero, // so element hasn't been dropped yet, and we just lowered the count to // zero so it won't be dropped later, and thus it's okay to take it here. - unsafe { ManuallyDrop::take(&mut self.element) } + unsafe { mem::replace(&mut self.element, MaybeUninit::uninit()).assume_init() } } else { - A::clone(&self.element) + // SAFETY: the count is non-zero, so it must have not been dropped yet. + let element = unsafe { self.element.assume_init_ref() }; + A::clone(element) } } } diff --git a/library/core/tests/iter/sources.rs b/library/core/tests/iter/sources.rs index eb8c80dd08724..506febaa056a8 100644 --- a/library/core/tests/iter/sources.rs +++ b/library/core/tests/iter/sources.rs @@ -156,3 +156,27 @@ fn test_repeat_n_drop() { drop((x0, x1, x2)); assert_eq!(count.get(), 3); } + +#[test] +fn test_repeat_n_soundness() { + let x = std::iter::repeat_n(String::from("use after free"), 0); + println!("{x:?}"); + + pub struct PanicOnClone; + + impl Clone for PanicOnClone { + fn clone(&self) -> Self { + unreachable!() + } + } + + // `repeat_n` should drop the element immediately if `count` is zero. + // `Clone` should then not try to clone the element. + let x = std::iter::repeat_n(PanicOnClone, 0); + let _ = x.clone(); + + let mut y = std::iter::repeat_n(Box::new(0), 1); + let x = y.next().unwrap(); + let _z = y; + assert_eq!(0, *x); +} From 0b20ffcb63b00acbbe70ae6f59a746bcde4c8b96 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Eduardo=20S=C3=A1nchez=20Mu=C3=B1oz?= Date: Mon, 9 Sep 2024 12:22:00 +0200 Subject: [PATCH 0725/2194] Remove needless returns detected by clippy in the compiler --- compiler/rustc_ast/src/ast_traits.rs | 4 ++-- compiler/rustc_attr/src/builtin.rs | 2 +- .../src/diagnostics/conflict_errors.rs | 2 +- .../rustc_borrowck/src/type_check/relate_tys.rs | 2 +- compiler/rustc_codegen_llvm/src/llvm_util.rs | 2 +- compiler/rustc_codegen_ssa/src/back/link.rs | 6 +++--- compiler/rustc_codegen_ssa/src/back/linker.rs | 1 - compiler/rustc_codegen_ssa/src/back/metadata.rs | 8 ++++---- compiler/rustc_const_eval/src/interpret/call.rs | 4 ++-- compiler/rustc_expand/src/mbe/transcribe.rs | 16 ++++++++-------- .../src/check/compare_impl_item.rs | 2 +- .../rustc_hir_analysis/src/coherence/builtin.rs | 2 +- compiler/rustc_hir_typeck/src/closure.rs | 2 +- compiler/rustc_hir_typeck/src/demand.rs | 2 +- .../rustc_hir_typeck/src/fn_ctxt/arg_matrix.rs | 4 ++-- .../rustc_hir_typeck/src/fn_ctxt/suggestions.rs | 2 +- compiler/rustc_infer/src/infer/mod.rs | 4 ++-- .../rustc_lint/src/for_loops_over_fallibles.rs | 2 +- compiler/rustc_middle/src/hir/map/mod.rs | 12 ++++++------ .../rustc_middle/src/mir/interpret/allocation.rs | 2 +- compiler/rustc_middle/src/mir/mod.rs | 5 ++--- compiler/rustc_middle/src/ty/context.rs | 2 +- compiler/rustc_middle/src/ty/region.rs | 2 +- .../rustc_mir_build/src/build/custom/parse.rs | 12 +++++------- compiler/rustc_monomorphize/src/collector.rs | 2 +- compiler/rustc_parse/src/lexer/tokentrees.rs | 2 +- compiler/rustc_parse/src/parser/diagnostics.rs | 2 +- compiler/rustc_parse/src/parser/item.rs | 2 +- compiler/rustc_passes/src/check_attr.rs | 5 +---- compiler/rustc_passes/src/dead.rs | 2 +- compiler/rustc_resolve/src/diagnostics.rs | 2 +- compiler/rustc_resolve/src/late.rs | 2 +- compiler/rustc_resolve/src/late/diagnostics.rs | 2 +- compiler/rustc_session/src/filesearch.rs | 2 +- compiler/rustc_session/src/options.rs | 2 +- compiler/rustc_span/src/source_map.rs | 2 +- compiler/rustc_target/src/abi/call/mod.rs | 6 ++---- compiler/rustc_target/src/abi/call/sparc64.rs | 6 +++--- 38 files changed, 66 insertions(+), 75 deletions(-) diff --git a/compiler/rustc_ast/src/ast_traits.rs b/compiler/rustc_ast/src/ast_traits.rs index 6b95fb7dd36b8..60f8c6e10481b 100644 --- a/compiler/rustc_ast/src/ast_traits.rs +++ b/compiler/rustc_ast/src/ast_traits.rs @@ -153,7 +153,7 @@ impl HasTokens for StmtKind { StmtKind::Let(local) => local.tokens.as_ref(), StmtKind::Item(item) => item.tokens(), StmtKind::Expr(expr) | StmtKind::Semi(expr) => expr.tokens(), - StmtKind::Empty => return None, + StmtKind::Empty => None, StmtKind::MacCall(mac) => mac.tokens.as_ref(), } } @@ -162,7 +162,7 @@ impl HasTokens for StmtKind { StmtKind::Let(local) => Some(&mut local.tokens), StmtKind::Item(item) => item.tokens_mut(), StmtKind::Expr(expr) | StmtKind::Semi(expr) => expr.tokens_mut(), - StmtKind::Empty => return None, + StmtKind::Empty => None, StmtKind::MacCall(mac) => Some(&mut mac.tokens), } } diff --git a/compiler/rustc_attr/src/builtin.rs b/compiler/rustc_attr/src/builtin.rs index e46dabc7a6e22..309049b98f0e2 100644 --- a/compiler/rustc_attr/src/builtin.rs +++ b/compiler/rustc_attr/src/builtin.rs @@ -1240,5 +1240,5 @@ pub fn parse_confusables(attr: &Attribute) -> Option> { candidates.push(meta_lit.symbol); } - return Some(candidates); + Some(candidates) } diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index c817b6fac7134..30e6f1acf1031 100644 --- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs @@ -3669,7 +3669,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, '_, 'infcx, 'tcx> { reinits.push(location); return true; } - return false; + false }; while let Some(location) = stack.pop() { diff --git a/compiler/rustc_borrowck/src/type_check/relate_tys.rs b/compiler/rustc_borrowck/src/type_check/relate_tys.rs index bb4a58930e1bb..421f4e2efe0e8 100644 --- a/compiler/rustc_borrowck/src/type_check/relate_tys.rs +++ b/compiler/rustc_borrowck/src/type_check/relate_tys.rs @@ -214,7 +214,7 @@ impl<'me, 'bccx, 'tcx> NllTypeRelating<'me, 'bccx, 'tcx> { let delegate = FnMutDelegate { regions: &mut |br: ty::BoundRegion| { if let Some(ex_reg_var) = reg_map.get(&br) { - return *ex_reg_var; + *ex_reg_var } else { let ex_reg_var = self.next_existential_region_var(true, br.kind.get_name()); debug!(?ex_reg_var); diff --git a/compiler/rustc_codegen_llvm/src/llvm_util.rs b/compiler/rustc_codegen_llvm/src/llvm_util.rs index d55220ba5c3a4..6e4ddbb6f3b6a 100644 --- a/compiler/rustc_codegen_llvm/src/llvm_util.rs +++ b/compiler/rustc_codegen_llvm/src/llvm_util.rs @@ -290,7 +290,7 @@ pub(crate) fn check_tied_features( } } } - return None; + None } /// Used to generate cfg variables and apply features diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index e8143b9a5f38f..dbb65707bd23b 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -438,7 +438,7 @@ fn link_rlib<'a>( ab.add_file(&lib) } - return Ok(ab); + Ok(ab) } /// Extract all symbols defined in raw-dylib libraries, collated by library name. @@ -1319,7 +1319,7 @@ fn link_sanitizer_runtime( fn find_sanitizer_runtime(sess: &Session, filename: &str) -> PathBuf { let path = sess.target_tlib_path.dir.join(filename); if path.exists() { - return sess.target_tlib_path.dir.clone(); + sess.target_tlib_path.dir.clone() } else { let default_sysroot = filesearch::get_or_default_sysroot().expect("Failed finding sysroot"); @@ -1327,7 +1327,7 @@ fn link_sanitizer_runtime( &default_sysroot, sess.opts.target_triple.triple(), ); - return default_tlib; + default_tlib } } diff --git a/compiler/rustc_codegen_ssa/src/back/linker.rs b/compiler/rustc_codegen_ssa/src/back/linker.rs index cb266247e0dde..ea71b92de3ae7 100644 --- a/compiler/rustc_codegen_ssa/src/back/linker.rs +++ b/compiler/rustc_codegen_ssa/src/back/linker.rs @@ -1484,7 +1484,6 @@ impl<'a> Linker for L4Bender<'a> { fn export_symbols(&mut self, _: &Path, _: CrateType, _: &[String]) { // ToDo, not implemented, copy from GCC self.sess.dcx().emit_warn(errors::L4BenderExportingSymbolsUnimplemented); - return; } fn subsystem(&mut self, subsystem: &str) { diff --git a/compiler/rustc_codegen_ssa/src/back/metadata.rs b/compiler/rustc_codegen_ssa/src/back/metadata.rs index 0fd9d7fffe8f9..6215616e51000 100644 --- a/compiler/rustc_codegen_ssa/src/back/metadata.rs +++ b/compiler/rustc_codegen_ssa/src/back/metadata.rs @@ -171,10 +171,10 @@ pub(super) fn get_metadata_xcoff<'a>(path: &Path, data: &'a [u8]) -> Result<&'a "Metadata at offset {offset} with size {len} is beyond .info section" )); } - return Ok(&info_data[offset..(offset + len)]); + Ok(&info_data[offset..(offset + len)]) } else { - return Err(format!("Unable to find symbol {AIX_METADATA_SYMBOL_NAME}")); - }; + Err(format!("Unable to find symbol {AIX_METADATA_SYMBOL_NAME}")) + } } pub(crate) fn create_object_file(sess: &Session) -> Option> { @@ -413,7 +413,7 @@ fn macho_object_build_version_for_target(target: &Target) -> object::write::Mach /// Is Apple's CPU subtype `arm64e`s fn macho_is_arm64e(target: &Target) -> bool { - return target.llvm_target.starts_with("arm64e"); + target.llvm_target.starts_with("arm64e") } pub enum MetadataPosition { diff --git a/compiler/rustc_const_eval/src/interpret/call.rs b/compiler/rustc_const_eval/src/interpret/call.rs index 568a9a3a637be..419d412b0630b 100644 --- a/compiler/rustc_const_eval/src/interpret/call.rs +++ b/compiler/rustc_const_eval/src/interpret/call.rs @@ -235,13 +235,13 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { if self.layout_compat(caller_abi.layout, callee_abi.layout)? { // Ensure that our checks imply actual ABI compatibility for this concrete call. assert!(caller_abi.eq_abi(callee_abi)); - return Ok(true); + Ok(true) } else { trace!( "check_argument_compat: incompatible ABIs:\ncaller: {:?}\ncallee: {:?}", caller_abi, callee_abi ); - return Ok(false); + Ok(false) } } diff --git a/compiler/rustc_expand/src/mbe/transcribe.rs b/compiler/rustc_expand/src/mbe/transcribe.rs index 39489a8df1bed..2bd78d347368a 100644 --- a/compiler/rustc_expand/src/mbe/transcribe.rs +++ b/compiler/rustc_expand/src/mbe/transcribe.rs @@ -773,18 +773,20 @@ fn extract_symbol_from_pnr<'a>( match pnr { ParseNtResult::Ident(nt_ident, is_raw) => { if let IdentIsRaw::Yes = is_raw { - return Err(dcx.struct_span_err(span_err, RAW_IDENT_ERR)); + Err(dcx.struct_span_err(span_err, RAW_IDENT_ERR)) + } else { + Ok(nt_ident.name) } - return Ok(nt_ident.name); } ParseNtResult::Tt(TokenTree::Token( Token { kind: TokenKind::Ident(symbol, is_raw), .. }, _, )) => { if let IdentIsRaw::Yes = is_raw { - return Err(dcx.struct_span_err(span_err, RAW_IDENT_ERR)); + Err(dcx.struct_span_err(span_err, RAW_IDENT_ERR)) + } else { + Ok(*symbol) } - return Ok(*symbol); } ParseNtResult::Tt(TokenTree::Token( Token { @@ -792,15 +794,13 @@ fn extract_symbol_from_pnr<'a>( .. }, _, - )) => { - return Ok(*symbol); - } + )) => Ok(*symbol), ParseNtResult::Nt(nt) if let Nonterminal::NtLiteral(expr) = &**nt && let ExprKind::Lit(Lit { kind: LitKind::Str, symbol, suffix: None }) = &expr.kind => { - return Ok(*symbol); + Ok(*symbol) } _ => Err(dcx .struct_err( diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs index 2afed04c5bcd5..388e02b36e02c 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs @@ -1038,7 +1038,7 @@ fn report_trait_method_mismatch<'tcx>( false, ); - return diag.emit(); + diag.emit() } fn check_region_bounds_on_impl_item<'tcx>( diff --git a/compiler/rustc_hir_analysis/src/coherence/builtin.rs b/compiler/rustc_hir_analysis/src/coherence/builtin.rs index 30fc06829ed8e..480116a624921 100644 --- a/compiler/rustc_hir_analysis/src/coherence/builtin.rs +++ b/compiler/rustc_hir_analysis/src/coherence/builtin.rs @@ -274,7 +274,7 @@ fn visit_implementation_of_dispatch_from_dyn(checker: &Checker<'_>) -> Result<() return false; } - return true; + true }) .collect::>(); diff --git a/compiler/rustc_hir_typeck/src/closure.rs b/compiler/rustc_hir_typeck/src/closure.rs index 5117eef9ed8f5..f71427e42d4a5 100644 --- a/compiler/rustc_hir_typeck/src/closure.rs +++ b/compiler/rustc_hir_typeck/src/closure.rs @@ -605,7 +605,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { Abi::Rust, )); - return Some(ExpectedSig { cause_span, sig }); + Some(ExpectedSig { cause_span, sig }) } fn sig_of_closure( diff --git a/compiler/rustc_hir_typeck/src/demand.rs b/compiler/rustc_hir_typeck/src/demand.rs index 0da299f017942..80a71f27a9990 100644 --- a/compiler/rustc_hir_typeck/src/demand.rs +++ b/compiler/rustc_hir_typeck/src/demand.rs @@ -1042,7 +1042,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { return true; } } - return false; + false } fn explain_self_literal( diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/arg_matrix.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/arg_matrix.rs index cb77d3f85d935..358bc389bd138 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/arg_matrix.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/arg_matrix.rs @@ -307,7 +307,7 @@ impl<'tcx> ArgMatrix<'tcx> { permutation.into_iter().map(|x| x.unwrap()).collect(); return Some(Issue::Permutation(final_permutation)); } - return None; + None } // Obviously, detecting exact user intention is impossible, so the goal here is to @@ -410,6 +410,6 @@ impl<'tcx> ArgMatrix<'tcx> { // sort errors with same type by the order they appear in the source // so that suggestion will be handled properly, see #112507 errors.sort(); - return (errors, matched_inputs); + (errors, matched_inputs) } } diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs index 4454703645e79..c9ffdeea998e7 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs @@ -2028,7 +2028,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let span = expr.span.find_oldest_ancestor_in_same_ctxt(); err.span_suggestion_verbose(span.shrink_to_hi(), msg, sugg, Applicability::HasPlaceholders); - return true; + true } pub(crate) fn suggest_coercing_result_via_try_operator( diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index 234dc5133f8db..5ebc67a7f2cc3 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -1481,7 +1481,7 @@ impl<'tcx> InferCtxt<'tcx> { // This hoists the borrow/release out of the loop body. let inner = self.inner.try_borrow(); - return move |infer_var: TyOrConstInferVar| match (infer_var, &inner) { + move |infer_var: TyOrConstInferVar| match (infer_var, &inner) { (TyOrConstInferVar::Ty(ty_var), Ok(inner)) => { use self::type_variable::TypeVariableValue; @@ -1491,7 +1491,7 @@ impl<'tcx> InferCtxt<'tcx> { ) } _ => false, - }; + } } /// `ty_or_const_infer_var_changed` is equivalent to one of these two: diff --git a/compiler/rustc_lint/src/for_loops_over_fallibles.rs b/compiler/rustc_lint/src/for_loops_over_fallibles.rs index 2793d48dc512b..1b25f21ef84dd 100644 --- a/compiler/rustc_lint/src/for_loops_over_fallibles.rs +++ b/compiler/rustc_lint/src/for_loops_over_fallibles.rs @@ -133,7 +133,7 @@ fn extract_iterator_next_call<'tcx>( { Some(recv) } else { - return None; + None } } diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs index 3d346b9cc5d0a..8b0a855612c19 100644 --- a/compiler/rustc_middle/src/hir/map/mod.rs +++ b/compiler/rustc_middle/src/hir/map/mod.rs @@ -71,7 +71,7 @@ impl<'hir> Iterator for ParentHirIterator<'hir> { debug_assert_ne!(parent_id, self.current_id); self.current_id = parent_id; - return Some(parent_id); + Some(parent_id) } } @@ -103,7 +103,7 @@ impl<'hir> Iterator for ParentOwnerIterator<'hir> { self.current_id = HirId::make_owner(parent_id.def_id); let node = self.map.tcx.hir_owner_node(self.current_id.owner); - return Some((self.current_id.owner, node)); + Some((self.current_id.owner, node)) } } @@ -1233,14 +1233,14 @@ pub(super) fn hir_module_items(tcx: TyCtxt<'_>, module_id: LocalModDefId) -> Mod body_owners, .. } = collector; - return ModuleItems { + ModuleItems { submodules: submodules.into_boxed_slice(), free_items: items.into_boxed_slice(), trait_items: trait_items.into_boxed_slice(), impl_items: impl_items.into_boxed_slice(), foreign_items: foreign_items.into_boxed_slice(), body_owners: body_owners.into_boxed_slice(), - }; + } } pub(crate) fn hir_crate_items(tcx: TyCtxt<'_>, _: ()) -> ModuleItems { @@ -1262,14 +1262,14 @@ pub(crate) fn hir_crate_items(tcx: TyCtxt<'_>, _: ()) -> ModuleItems { .. } = collector; - return ModuleItems { + ModuleItems { submodules: submodules.into_boxed_slice(), free_items: items.into_boxed_slice(), trait_items: trait_items.into_boxed_slice(), impl_items: impl_items.into_boxed_slice(), foreign_items: foreign_items.into_boxed_slice(), body_owners: body_owners.into_boxed_slice(), - }; + } } struct ItemCollector<'tcx> { diff --git a/compiler/rustc_middle/src/mir/interpret/allocation.rs b/compiler/rustc_middle/src/mir/interpret/allocation.rs index 5fb8af576ae93..ca3bc82184ff4 100644 --- a/compiler/rustc_middle/src/mir/interpret/allocation.rs +++ b/compiler/rustc_middle/src/mir/interpret/allocation.rs @@ -641,7 +641,7 @@ impl Allocation pub fn write_uninit(&mut self, cx: &impl HasDataLayout, range: AllocRange) -> AllocResult { self.mark_init(range, false); self.provenance.clear(range, cx)?; - return Ok(()); + Ok(()) } /// Applies a previously prepared provenance copy. diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index 081a23b6ff317..26addb1e357f5 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -1166,10 +1166,9 @@ impl<'tcx> LocalDecl<'tcx> { /// Returns `true` if this is a DerefTemp pub fn is_deref_temp(&self) -> bool { match self.local_info() { - LocalInfo::DerefTemp => return true, - _ => (), + LocalInfo::DerefTemp => true, + _ => false, } - return false; } /// Returns `true` is the local is from a compiler desugaring, e.g., diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 2a3008897c676..2571cbbf29965 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -2003,7 +2003,7 @@ impl<'tcx> TyCtxt<'tcx> { )); } } - return None; + None } /// Checks if the bound region is in Impl Item. diff --git a/compiler/rustc_middle/src/ty/region.rs b/compiler/rustc_middle/src/ty/region.rs index a2a961057771a..44956d5b0a6bd 100644 --- a/compiler/rustc_middle/src/ty/region.rs +++ b/compiler/rustc_middle/src/ty/region.rs @@ -431,7 +431,7 @@ impl BoundRegionKind { pub fn get_id(&self) -> Option { match *self { - BoundRegionKind::BrNamed(id, _) => return Some(id), + BoundRegionKind::BrNamed(id, _) => Some(id), _ => None, } } diff --git a/compiler/rustc_mir_build/src/build/custom/parse.rs b/compiler/rustc_mir_build/src/build/custom/parse.rs index 646aefa08829e..1f186c8f99afe 100644 --- a/compiler/rustc_mir_build/src/build/custom/parse.rs +++ b/compiler/rustc_mir_build/src/build/custom/parse.rs @@ -82,13 +82,11 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> { fn statement_as_expr(&self, stmt_id: StmtId) -> PResult { match &self.thir[stmt_id].kind { StmtKind::Expr { expr, .. } => Ok(*expr), - kind @ StmtKind::Let { pattern, .. } => { - return Err(ParseError { - span: pattern.span, - item_description: format!("{kind:?}"), - expected: "expression".to_string(), - }); - } + kind @ StmtKind::Let { pattern, .. } => Err(ParseError { + span: pattern.span, + item_description: format!("{kind:?}"), + expected: "expression".to_string(), + }), } } diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs index 093697a290c00..c3f228962005b 100644 --- a/compiler/rustc_monomorphize/src/collector.rs +++ b/compiler/rustc_monomorphize/src/collector.rs @@ -1193,7 +1193,7 @@ fn assoc_fn_of_type<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, fn_ident: Ident) -> return Some(new.def_id); } } - return None; + None } /// Scans the MIR in order to find function calls, closures, and drop-glue. diff --git a/compiler/rustc_parse/src/lexer/tokentrees.rs b/compiler/rustc_parse/src/lexer/tokentrees.rs index e7a7105803fcd..c83d8bf4021ee 100644 --- a/compiler/rustc_parse/src/lexer/tokentrees.rs +++ b/compiler/rustc_parse/src/lexer/tokentrees.rs @@ -299,7 +299,7 @@ impl<'psess, 'src> TokenTreesReader<'psess, 'src> { } return diff_errs; } - return errs; + errs } fn close_delim_err(&mut self, delim: Delimiter) -> PErr<'psess> { diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index f6f66821df7fb..bee73c58cb794 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -2553,7 +2553,7 @@ impl<'a> Parser<'a> { err.delay_as_bug(); } } - return Ok(false); // Don't continue. + Ok(false) // Don't continue. } /// Attempt to parse a generic const argument that has not been enclosed in braces. diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index c6a5e1908f704..83d10dea6a8fb 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -457,7 +457,7 @@ impl<'a> Parser<'a> { fn parse_item_builtin(&mut self) -> PResult<'a, Option> { // To be expanded - return Ok(None); + Ok(None) } /// Parses an item macro, e.g., `item!();`. diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index e41f89a3c9da9..4fb9b93b80c8d 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -1905,10 +1905,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { || (int_reprs == 1 && is_c && item.is_some_and(|item| { - if let ItemLike::Item(item) = item { - return is_c_like_enum(item); - } - return false; + if let ItemLike::Item(item) = item { is_c_like_enum(item) } else { false } })) { self.tcx.emit_node_span_lint( diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs index 7f1e906ffd737..ef534c645a461 100644 --- a/compiler/rustc_passes/src/dead.rs +++ b/compiler/rustc_passes/src/dead.rs @@ -394,7 +394,7 @@ impl<'tcx> MarkSymbolVisitor<'tcx> { } } - return false; + false } fn visit_node(&mut self, node: Node<'tcx>) { diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index bcbdf627b5662..182577b82c49d 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -3076,7 +3076,7 @@ fn search_for_any_use_in_items(items: &[P]) -> Option { } } } - return None; + None } fn is_span_suitable_for_use_injection(s: Span) -> bool { diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 917cb81aa511f..40a6ac70bfdd8 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -5016,5 +5016,5 @@ fn def_id_matches_path(tcx: TyCtxt<'_>, mut def_id: DefId, expected_path: &[&str } def_id = parent; } - return true; + true } diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index 8f516c2db0900..098509cd1d508 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -779,7 +779,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { candidates = self.smart_resolve_partial_mod_path_errors(path, following_seg); } - return (false, candidates); + (false, candidates) } fn suggest_trait_and_bounds( diff --git a/compiler/rustc_session/src/filesearch.rs b/compiler/rustc_session/src/filesearch.rs index d78f4a78de732..e72d4face3c87 100644 --- a/compiler/rustc_session/src/filesearch.rs +++ b/compiler/rustc_session/src/filesearch.rs @@ -182,7 +182,7 @@ pub fn sysroot_candidates() -> SmallVec<[PathBuf; 2]> { } } - return sysroot_candidates; + sysroot_candidates } /// Returns the provided sysroot or calls [`get_or_default_sysroot`] if it's none. diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index a57dc80b3168d..982a3d5cf110d 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -353,7 +353,7 @@ fn build_options( None => early_dcx.early_fatal(format!("unknown {outputname} option: `{key}`")), } } - return op; + op } #[allow(non_upper_case_globals)] diff --git a/compiler/rustc_span/src/source_map.rs b/compiler/rustc_span/src/source_map.rs index f914e8dc1baaa..98447147d3e13 100644 --- a/compiler/rustc_span/src/source_map.rs +++ b/compiler/rustc_span/src/source_map.rs @@ -779,7 +779,7 @@ impl SourceMap { return Ok(false); } } - return Ok(true); + Ok(true) }) .is_ok_and(|is_accessible| is_accessible) } diff --git a/compiler/rustc_target/src/abi/call/mod.rs b/compiler/rustc_target/src/abi/call/mod.rs index 082c169b210f8..c2826b55dc5b1 100644 --- a/compiler/rustc_target/src/abi/call/mod.rs +++ b/compiler/rustc_target/src/abi/call/mod.rs @@ -188,7 +188,7 @@ impl ArgAttributes { if self.arg_ext != other.arg_ext { return false; } - return true; + true } } @@ -632,7 +632,7 @@ impl<'a, Ty> ArgAbi<'a, Ty> { PassMode::Indirect { .. } => { self.mode = PassMode::Direct(ArgAttributes::new()); } - PassMode::Ignore | PassMode::Direct(_) | PassMode::Pair(_, _) => return, // already direct + PassMode::Ignore | PassMode::Direct(_) | PassMode::Pair(_, _) => {} // already direct _ => panic!("Tried to make {:?} direct", self.mode), } } @@ -646,7 +646,6 @@ impl<'a, Ty> ArgAbi<'a, Ty> { } PassMode::Indirect { attrs: _, meta_attrs: _, on_stack: false } => { // already indirect - return; } _ => panic!("Tried to make {:?} indirect", self.mode), } @@ -661,7 +660,6 @@ impl<'a, Ty> ArgAbi<'a, Ty> { } PassMode::Indirect { attrs: _, meta_attrs: _, on_stack: false } => { // already indirect - return; } _ => panic!("Tried to make {:?} indirect (expected `PassMode::Ignore`)", self.mode), } diff --git a/compiler/rustc_target/src/abi/call/sparc64.rs b/compiler/rustc_target/src/abi/call/sparc64.rs index 2954d9642df95..835353f76fc9a 100644 --- a/compiler/rustc_target/src/abi/call/sparc64.rs +++ b/compiler/rustc_target/src/abi/call/sparc64.rs @@ -66,7 +66,7 @@ where data.last_offset = offset + Reg::f64().size; } data.prefix_index += 1; - return data; + data } fn arg_scalar_pair( @@ -92,7 +92,7 @@ where offset += Size::from_bytes(4 - (offset.bytes() % 4)); } data = arg_scalar(cx, scalar2, offset, data); - return data; + data } fn parse_structure<'a, Ty, C>( @@ -128,7 +128,7 @@ where } } - return data; + data } fn classify_arg<'a, Ty, C>(cx: &C, arg: &mut ArgAbi<'a, Ty>, in_registers_max: Size) From db6361184e49e7eaba3c1bf854b9d8345b462680 Mon Sep 17 00:00:00 2001 From: Pavel Grigorenko Date: Mon, 9 Sep 2024 14:33:48 +0300 Subject: [PATCH 0726/2194] Helper function for formatting with `LifetimeSuggestionPosition` --- compiler/rustc_hir/src/hir.rs | 13 +++++++++++++ .../src/collect/resolve_bound_vars.rs | 18 +----------------- .../src/error_reporting/infer/region.rs | 13 +------------ 3 files changed, 15 insertions(+), 29 deletions(-) diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 57c47d29857c3..b01c24cf3053e 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -168,6 +168,19 @@ impl Lifetime { (LifetimeSuggestionPosition::Normal, self.ident.span) } } + + pub fn suggestion(&self, new_lifetime: &str) -> (Span, String) { + debug_assert!(new_lifetime.starts_with('\'')); + let (pos, span) = self.suggestion_position(); + let code = match pos { + LifetimeSuggestionPosition::Normal => format!("{new_lifetime}"), + LifetimeSuggestionPosition::Ampersand => format!("{new_lifetime} "), + LifetimeSuggestionPosition::ElidedPath => format!("<{new_lifetime}>"), + LifetimeSuggestionPosition::ElidedPathArgument => format!("{new_lifetime}, "), + LifetimeSuggestionPosition::ObjectDefault => format!("+ {new_lifetime}"), + }; + (span, code) + } } /// A `Path` is essentially Rust's notion of a name; for instance, diff --git a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs index fe46eb583f1df..b4cbd1f309c97 100644 --- a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs +++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs @@ -1191,23 +1191,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> { (generics.span, "<'a>".to_owned()) }; - let lifetime_sugg = match lifetime_ref.suggestion_position() { - (hir::LifetimeSuggestionPosition::Normal, span) => { - (span, "'a".to_owned()) - } - (hir::LifetimeSuggestionPosition::Ampersand, span) => { - (span, "'a ".to_owned()) - } - (hir::LifetimeSuggestionPosition::ElidedPath, span) => { - (span, "<'a>".to_owned()) - } - (hir::LifetimeSuggestionPosition::ElidedPathArgument, span) => { - (span, "'a, ".to_owned()) - } - (hir::LifetimeSuggestionPosition::ObjectDefault, span) => { - (span, "+ 'a".to_owned()) - } - }; + let lifetime_sugg = lifetime_ref.suggestion("'a"); let suggestions = vec![lifetime_sugg, new_param_sugg]; diag.span_label( diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs index e4a4ec125a5c4..30f3face11b85 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs @@ -844,18 +844,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { impl<'hir, 'tcx> hir::intravisit::Visitor<'hir> for LifetimeReplaceVisitor<'tcx, '_> { fn visit_lifetime(&mut self, lt: &'hir hir::Lifetime) { if lt.res == self.needle { - let (pos, span) = lt.suggestion_position(); - let new_lt = &self.new_lt; - let sugg = match pos { - hir::LifetimeSuggestionPosition::Normal => format!("{new_lt}"), - hir::LifetimeSuggestionPosition::Ampersand => format!("{new_lt} "), - hir::LifetimeSuggestionPosition::ElidedPath => format!("<{new_lt}>"), - hir::LifetimeSuggestionPosition::ElidedPathArgument => { - format!("{new_lt}, ") - } - hir::LifetimeSuggestionPosition::ObjectDefault => format!("+ {new_lt}"), - }; - self.add_lt_suggs.push((span, sugg)); + self.add_lt_suggs.push(lt.suggestion(self.new_lt)); } } From 843708a32ee8e0c75a98b2b95927b348e3089b24 Mon Sep 17 00:00:00 2001 From: Urgau Date: Fri, 6 Sep 2024 13:48:17 +0200 Subject: [PATCH 0727/2194] Add missing `#[allow(missing_docs)]` on hack functions in alloc --- library/alloc/src/slice.rs | 2 ++ library/alloc/src/string.rs | 1 + library/std/src/io/buffered/bufreader.rs | 1 + 3 files changed, 4 insertions(+) diff --git a/library/alloc/src/slice.rs b/library/alloc/src/slice.rs index 9d70487032699..8cdba166c9dff 100644 --- a/library/alloc/src/slice.rs +++ b/library/alloc/src/slice.rs @@ -96,6 +96,7 @@ pub(crate) mod hack { // We shouldn't add inline attribute to this since this is used in // `vec!` macro mostly and causes perf regression. See #71204 for // discussion and perf results. + #[allow(missing_docs)] pub fn into_vec(b: Box<[T], A>) -> Vec { unsafe { let len = b.len(); @@ -105,6 +106,7 @@ pub(crate) mod hack { } #[cfg(not(no_global_oom_handling))] + #[allow(missing_docs)] #[inline] pub fn to_vec(s: &[T], alloc: A) -> Vec { T::to_vec(s, alloc) diff --git a/library/alloc/src/string.rs b/library/alloc/src/string.rs index bc8b7e24bf12b..05617669ed231 100644 --- a/library/alloc/src/string.rs +++ b/library/alloc/src/string.rs @@ -508,6 +508,7 @@ impl String { // NB see the slice::hack module in slice.rs for more information #[inline] #[cfg(test)] + #[allow(missing_docs)] pub fn from_str(_: &str) -> String { panic!("not available with cfg(test)"); } diff --git a/library/std/src/io/buffered/bufreader.rs b/library/std/src/io/buffered/bufreader.rs index cf226bd28d005..035afbb8368b4 100644 --- a/library/std/src/io/buffered/bufreader.rs +++ b/library/std/src/io/buffered/bufreader.rs @@ -267,6 +267,7 @@ impl BufReader { // This is only used by a test which asserts that the initialization-tracking is correct. #[cfg(test)] impl BufReader { + #[allow(missing_docs)] pub fn initialized(&self) -> usize { self.buf.initialized() } From 97df8fb7ecce4ff77d1da199742a822dfddeac2f Mon Sep 17 00:00:00 2001 From: Mads Marquart Date: Wed, 21 Aug 2024 18:21:39 +0200 Subject: [PATCH 0728/2194] Fix default/minimum deployment target for Aarch64 simulator targets The minimum that `rustc` encoded did not match the version in Clang, and that meant that that when linking, we ended up bumping the version. Specifically, this sets the correct deployment target of the following simulator and Mac Catalyst targets: - `aarch64-apple-ios-sim` from 10.0 to 14.0 - `aarch64-apple-tvos-sim` from 10.0 to 14.0 - `aarch64-apple-watchos-sim` from 5.0 to 7.0 - `aarch64-apple-ios-macabi` from 13.1 to 14.0 I have chosen to not document the simulator target versions in the platform support docs, as it is fundamentally uninteresting; the normal targets (e.g. `aarch64-apple-ios`, `aarch64-apple-tvos`) still have the same deployment target as before, and that's what developers should actually target. --- .../rustc_target/src/spec/base/apple/mod.rs | 10 +++++-- .../src/platform-support/apple-ios-macabi.md | 2 +- .../src/platform-support/arm64e-apple-ios.md | 2 +- .../run-make/apple-deployment-target/rmake.rs | 28 +++++++++++-------- 4 files changed, 26 insertions(+), 16 deletions(-) diff --git a/compiler/rustc_target/src/spec/base/apple/mod.rs b/compiler/rustc_target/src/spec/base/apple/mod.rs index b1fe49f76caa3..5da47322b92a8 100644 --- a/compiler/rustc_target/src/spec/base/apple/mod.rs +++ b/compiler/rustc_target/src/spec/base/apple/mod.rs @@ -323,12 +323,18 @@ fn deployment_target(os: &str, arch: Arch, abi: TargetAbi) -> (u16, u8, u8) { }; // On certain targets it makes sense to raise the minimum OS version. + // + // This matches what LLVM does, see: + // let min = match (os, arch, abi) { - // Use 11.0 on Aarch64 as that's the earliest version with M1 support. ("macos", Arch::Arm64 | Arch::Arm64e, _) => (11, 0, 0), - ("ios", Arch::Arm64e, _) => (14, 0, 0), + ("ios", Arch::Arm64 | Arch::Arm64e, TargetAbi::MacCatalyst) => (14, 0, 0), + ("ios", Arch::Arm64 | Arch::Arm64e, TargetAbi::Simulator) => (14, 0, 0), + ("ios", Arch::Arm64e, TargetAbi::Normal) => (14, 0, 0), // Mac Catalyst defaults to 13.1 in Clang. ("ios", _, TargetAbi::MacCatalyst) => (13, 1, 0), + ("tvos", Arch::Arm64 | Arch::Arm64e, TargetAbi::Simulator) => (14, 0, 0), + ("watchos", Arch::Arm64 | Arch::Arm64e, TargetAbi::Simulator) => (7, 0, 0), _ => os_min, }; diff --git a/src/doc/rustc/src/platform-support/apple-ios-macabi.md b/src/doc/rustc/src/platform-support/apple-ios-macabi.md index 678630873b135..a54656190d1f3 100644 --- a/src/doc/rustc/src/platform-support/apple-ios-macabi.md +++ b/src/doc/rustc/src/platform-support/apple-ios-macabi.md @@ -24,7 +24,7 @@ environment variable. ### OS version -The minimum supported version is iOS 13.1. +The minimum supported version is iOS 13.1 on x86 and 14.0 on Aarch64. This can be raised per-binary by changing the deployment target. `rustc` respects the common environment variables used by Xcode to do so, in this diff --git a/src/doc/rustc/src/platform-support/arm64e-apple-ios.md b/src/doc/rustc/src/platform-support/arm64e-apple-ios.md index 3c878f7250e97..fc4ec5e373fb0 100644 --- a/src/doc/rustc/src/platform-support/arm64e-apple-ios.md +++ b/src/doc/rustc/src/platform-support/arm64e-apple-ios.md @@ -2,7 +2,7 @@ **Tier: 3** -ARM64e iOS (12.0+) +ARM64e iOS (14.0+) ## Target maintainers diff --git a/tests/run-make/apple-deployment-target/rmake.rs b/tests/run-make/apple-deployment-target/rmake.rs index b2d1af65177ef..230f33a8d7867 100644 --- a/tests/run-make/apple-deployment-target/rmake.rs +++ b/tests/run-make/apple-deployment-target/rmake.rs @@ -55,11 +55,8 @@ fn main() { rustc().env(env_var, example_version).run(); minos("foo.o", example_version); - // FIXME(madsmtm): Doesn't work on Mac Catalyst and the simulator. - if !target().contains("macabi") && !target().contains("sim") { - rustc().env_remove(env_var).run(); - minos("foo.o", default_version); - } + rustc().env_remove(env_var).run(); + minos("foo.o", default_version); }); // Test that version makes it to the linker when linking dylibs. @@ -105,8 +102,18 @@ fn main() { rustc }; - // FIXME(madsmtm): Doesn't work on watchOS for some reason? - if !target().contains("watchos") { + // FIXME(madsmtm): Xcode's version of Clang seems to require a minimum + // version of 9.0 on aarch64-apple-watchos for some reason? Which is + // odd, because the first Aarch64 watch was Apple Watch Series 4, + // which runs on as low as watchOS 5.0. + // + // You can see Clang's behaviour by running: + // ``` + // echo "int main() { return 0; }" > main.c + // xcrun --sdk watchos clang --target=aarch64-apple-watchos main.c + // vtool -show a.out + // ``` + if target() != "aarch64-apple-watchos" { rustc().env(env_var, example_version).run(); minos("foo", example_version); @@ -148,10 +155,7 @@ fn main() { rustc().env(env_var, higher_example_version).run(); minos("foo.o", higher_example_version); - // FIXME(madsmtm): Doesn't work on Mac Catalyst and the simulator. - if !target().contains("macabi") && !target().contains("sim") { - rustc().env_remove(env_var).run(); - minos("foo.o", default_version); - } + rustc().env_remove(env_var).run(); + minos("foo.o", default_version); }); } From dd35398545006f5ad4da8fc2ef0190c55ffda29c Mon Sep 17 00:00:00 2001 From: Mads Marquart Date: Wed, 21 Aug 2024 17:23:50 +0200 Subject: [PATCH 0729/2194] Pass deployment target when linking with cc on Apple targets When linking macOS targets with cc, pass the `-mmacosx-version-min=.` option to specify the desired deployment target. Also, no longer pass `-m32`/`-m64`, these are redundant since we already pass `-arch`. When linking with cc on other Apple targets, always pass `-target`. (We assume for these targets that cc => clang). --- .../rustc_target/src/spec/base/apple/mod.rs | 30 ++++++++++++++++++- .../src/spec/targets/i686_apple_darwin.rs | 6 ++-- .../src/spec/targets/x86_64_apple_darwin.rs | 5 ++-- .../src/spec/targets/x86_64h_apple_darwin.rs | 3 +- .../run-make/apple-deployment-target/rmake.rs | 10 +++---- 5 files changed, 38 insertions(+), 16 deletions(-) diff --git a/compiler/rustc_target/src/spec/base/apple/mod.rs b/compiler/rustc_target/src/spec/base/apple/mod.rs index b1fe49f76caa3..d2886a89b53aa 100644 --- a/compiler/rustc_target/src/spec/base/apple/mod.rs +++ b/compiler/rustc_target/src/spec/base/apple/mod.rs @@ -168,7 +168,26 @@ fn pre_link_args(os: &'static str, arch: Arch, abi: TargetAbi) -> LinkArgs { ["-platform_version".into(), platform_name, min_version, sdk_version].into_iter(), ); - if abi != TargetAbi::MacCatalyst { + // We need to communicate four things to the C compiler to be able to link: + // - The architecture. + // - The operating system (and that it's an Apple platform). + // - The deployment target. + // - The environment / ABI. + // + // We'd like to use `-target` everywhere, since that can uniquely + // communicate all of these, but that doesn't work on GCC, and since we + // don't know whether the `cc` compiler is Clang, GCC, or something else, + // we fall back to other options that also work on GCC when compiling for + // macOS. + // + // Targets other than macOS are ill-supported by GCC (it doesn't even + // support e.g. `-miphoneos-version-min`), so in those cases we can fairly + // safely use `-target`. See also the following, where it is made explicit + // that the recommendation by LLVM developers is to use `-target`: + // + if os == "macos" { + // `-arch` communicates the architecture. + // // CC forwards the `-arch` to the linker, so we use the same value // here intentionally. add_link_args( @@ -176,6 +195,15 @@ fn pre_link_args(os: &'static str, arch: Arch, abi: TargetAbi) -> LinkArgs { LinkerFlavor::Darwin(Cc::Yes, Lld::No), &["-arch", arch.ld_arch()], ); + // The presence of `-mmacosx-version-min` makes CC default to macOS, + // and it sets the deployment target. + let (major, minor, patch) = deployment_target(os, arch, abi); + let opt = format!("-mmacosx-version-min={major}.{minor}.{patch}").into(); + add_link_args_iter(&mut args, LinkerFlavor::Darwin(Cc::Yes, Lld::No), [opt].into_iter()); + // macOS has no environment, so with these two, we've told CC all the + // desired parameters. + // + // We avoid `-m32`/`-m64`, as this is already encoded by `-arch`. } else { add_link_args_iter( &mut args, diff --git a/compiler/rustc_target/src/spec/targets/i686_apple_darwin.rs b/compiler/rustc_target/src/spec/targets/i686_apple_darwin.rs index 67afe35bee402..3e27f1f899b72 100644 --- a/compiler/rustc_target/src/spec/targets/i686_apple_darwin.rs +++ b/compiler/rustc_target/src/spec/targets/i686_apple_darwin.rs @@ -1,10 +1,8 @@ use crate::spec::base::apple::{base, Arch, TargetAbi}; -use crate::spec::{Cc, FramePointer, LinkerFlavor, Lld, Target, TargetOptions}; +use crate::spec::{FramePointer, Target, TargetOptions}; pub(crate) fn target() -> Target { - let (mut opts, llvm_target, arch) = base("macos", Arch::I686, TargetAbi::Normal); - opts.add_pre_link_args(LinkerFlavor::Darwin(Cc::Yes, Lld::No), &["-m32"]); - + let (opts, llvm_target, arch) = base("macos", Arch::I686, TargetAbi::Normal); Target { llvm_target, metadata: crate::spec::TargetMetadata { diff --git a/compiler/rustc_target/src/spec/targets/x86_64_apple_darwin.rs b/compiler/rustc_target/src/spec/targets/x86_64_apple_darwin.rs index e7f14aa920963..4304dfc3f682d 100644 --- a/compiler/rustc_target/src/spec/targets/x86_64_apple_darwin.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_apple_darwin.rs @@ -1,9 +1,8 @@ use crate::spec::base::apple::{base, Arch, TargetAbi}; -use crate::spec::{Cc, FramePointer, LinkerFlavor, Lld, SanitizerSet, Target, TargetOptions}; +use crate::spec::{FramePointer, SanitizerSet, Target, TargetOptions}; pub(crate) fn target() -> Target { - let (mut opts, llvm_target, arch) = base("macos", Arch::X86_64, TargetAbi::Normal); - opts.add_pre_link_args(LinkerFlavor::Darwin(Cc::Yes, Lld::No), &["-m64"]); + let (opts, llvm_target, arch) = base("macos", Arch::X86_64, TargetAbi::Normal); Target { llvm_target, metadata: crate::spec::TargetMetadata { diff --git a/compiler/rustc_target/src/spec/targets/x86_64h_apple_darwin.rs b/compiler/rustc_target/src/spec/targets/x86_64h_apple_darwin.rs index f44bc660a62f9..9fb5a46187a31 100644 --- a/compiler/rustc_target/src/spec/targets/x86_64h_apple_darwin.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64h_apple_darwin.rs @@ -1,11 +1,10 @@ use crate::spec::base::apple::{base, Arch, TargetAbi}; -use crate::spec::{Cc, FramePointer, LinkerFlavor, Lld, SanitizerSet, Target, TargetOptions}; +use crate::spec::{FramePointer, SanitizerSet, Target, TargetOptions}; pub(crate) fn target() -> Target { let (mut opts, llvm_target, arch) = base("macos", Arch::X86_64h, TargetAbi::Normal); opts.max_atomic_width = Some(128); opts.frame_pointer = FramePointer::Always; - opts.add_pre_link_args(LinkerFlavor::Darwin(Cc::Yes, Lld::No), &["-m64"]); opts.supported_sanitizers = SanitizerSet::ADDRESS | SanitizerSet::CFI | SanitizerSet::LEAK | SanitizerSet::THREAD; diff --git a/tests/run-make/apple-deployment-target/rmake.rs b/tests/run-make/apple-deployment-target/rmake.rs index b2d1af65177ef..304b008563127 100644 --- a/tests/run-make/apple-deployment-target/rmake.rs +++ b/tests/run-make/apple-deployment-target/rmake.rs @@ -81,9 +81,8 @@ fn main() { rustc().env(env_var, example_version).run(); minos("libfoo.dylib", example_version); - // FIXME(madsmtm): Deployment target is not currently passed properly to linker - // rustc().env_remove(env_var).run(); - // minos("libfoo.dylib", default_version); + rustc().env_remove(env_var).run(); + minos("libfoo.dylib", default_version); // Test with ld64 instead @@ -110,9 +109,8 @@ fn main() { rustc().env(env_var, example_version).run(); minos("foo", example_version); - // FIXME(madsmtm): Deployment target is not currently passed properly to linker - // rustc().env_remove(env_var).run(); - // minos("foo", default_version); + rustc().env_remove(env_var).run(); + minos("foo", default_version); } // Test with ld64 instead From ebe4fc4e1269157e018cc127d69c8128d1a56702 Mon Sep 17 00:00:00 2001 From: Chris Denton Date: Mon, 9 Sep 2024 12:05:29 +0000 Subject: [PATCH 0730/2194] Use small runner for msvc-ext2 job --- src/ci/github-actions/jobs.yml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/ci/github-actions/jobs.yml b/src/ci/github-actions/jobs.yml index e237e98b7b788..04ea1bdc08274 100644 --- a/src/ci/github-actions/jobs.yml +++ b/src/ci/github-actions/jobs.yml @@ -24,6 +24,10 @@ runners: os: macos-14 <<: *base-job + - &job-windows + os: windows-2022 + <<: *base-job + - &job-windows-8c os: windows-2022-8core-32gb <<: *base-job @@ -383,7 +387,7 @@ auto: python x.py miri --stage 2 library/alloc --test-args notest && python x.py miri --stage 2 library/std --test-args notest RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc --enable-lld - <<: *job-windows-8c + <<: *job-windows # 32/64-bit MinGW builds. # From 65c70900ceda1c276c8eef1dad4e2c4f7a0756d0 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 9 Sep 2024 14:42:03 +0200 Subject: [PATCH 0731/2194] union padding computation: add fast-path for ZST Also avoid even tracking empty ranges, and add fast-path for arrays of scalars --- .../src/interpret/validity.rs | 39 +++++++++++++------ compiler/rustc_middle/src/ty/sty.rs | 1 + src/tools/miri/tests/pass/arrays.rs | 15 +++++++ 3 files changed, 43 insertions(+), 12 deletions(-) diff --git a/compiler/rustc_const_eval/src/interpret/validity.rs b/compiler/rustc_const_eval/src/interpret/validity.rs index 806ebb9dfed4d..fb24f983ca9c3 100644 --- a/compiler/rustc_const_eval/src/interpret/validity.rs +++ b/compiler/rustc_const_eval/src/interpret/validity.rs @@ -220,6 +220,10 @@ pub struct RangeSet(Vec<(Size, Size)>); impl RangeSet { fn add_range(&mut self, offset: Size, size: Size) { + if size.bytes() == 0 { + // No need to track empty ranges. + return; + } let v = &mut self.0; // We scan for a partition point where the left partition is all the elements that end // strictly before we start. Those are elements that are too "low" to merge with us. @@ -938,42 +942,53 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> { let layout_cx = LayoutCx { tcx: *ecx.tcx, param_env: ecx.param_env }; return M::cached_union_data_range(ecx, layout.ty, || { let mut out = RangeSet(Vec::new()); - union_data_range_(&layout_cx, layout, Size::ZERO, &mut out); + union_data_range_uncached(&layout_cx, layout, Size::ZERO, &mut out); out }); /// Helper for recursive traversal: add data ranges of the given type to `out`. - fn union_data_range_<'tcx>( + fn union_data_range_uncached<'tcx>( cx: &LayoutCx<'tcx, TyCtxt<'tcx>>, layout: TyAndLayout<'tcx>, base_offset: Size, out: &mut RangeSet, ) { + // If this is a ZST, we don't contain any data. In particular, this helps us to quickly + // skip over huge arrays of ZST. + if layout.is_zst() { + return; + } // Just recursively add all the fields of everything to the output. match &layout.fields { FieldsShape::Primitive => { out.add_range(base_offset, layout.size); } &FieldsShape::Union(fields) => { - // Currently, all fields start at offset 0. + // Currently, all fields start at offset 0 (relative to `base_offset`). for field in 0..fields.get() { let field = layout.field(cx, field); - union_data_range_(cx, field, base_offset, out); + union_data_range_uncached(cx, field, base_offset, out); } } &FieldsShape::Array { stride, count } => { let elem = layout.field(cx, 0); - for idx in 0..count { - // This repeats the same computation for every array elements... but the alternative - // is to allocate temporary storage for a dedicated `out` set for the array element, - // and replicating that N times. Is that better? - union_data_range_(cx, elem, base_offset + idx * stride, out); + + // Fast-path for large arrays of simple types that do not contain any padding. + if elem.abi.is_scalar() { + out.add_range(base_offset, elem.size * count); + } else { + for idx in 0..count { + // This repeats the same computation for every array element... but the alternative + // is to allocate temporary storage for a dedicated `out` set for the array element, + // and replicating that N times. Is that better? + union_data_range_uncached(cx, elem, base_offset + idx * stride, out); + } } } FieldsShape::Arbitrary { offsets, .. } => { for (field, &offset) in offsets.iter_enumerated() { let field = layout.field(cx, field.as_usize()); - union_data_range_(cx, field, base_offset + offset, out); + union_data_range_uncached(cx, field, base_offset + offset, out); } } } @@ -985,7 +1000,7 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> { Variants::Multiple { variants, .. } => { for variant in variants.indices() { let variant = layout.for_variant(cx, variant); - union_data_range_(cx, variant, base_offset, out); + union_data_range_uncached(cx, variant, base_offset, out); } } } @@ -1185,7 +1200,7 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValueVisitor<'tcx, M> for ValidityVisitor<'rt, // This is the size in bytes of the whole array. (This checks for overflow.) let size = layout.size * len; // If the size is 0, there is nothing to check. - // (`size` can only be 0 of `len` is 0, and empty arrays are always valid.) + // (`size` can only be 0 if `len` is 0, and empty arrays are always valid.) if size == Size::ZERO { return Ok(()); } diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index 1f4f2c62d7084..730ba265b19d6 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -1136,6 +1136,7 @@ impl<'tcx> Ty<'tcx> { } /// Tests if this is any kind of primitive pointer type (reference, raw pointer, fn pointer). + /// `Box` is *not* considered a pointer here! #[inline] pub fn is_any_ptr(self) -> bool { self.is_ref() || self.is_unsafe_ptr() || self.is_fn_ptr() diff --git a/src/tools/miri/tests/pass/arrays.rs b/src/tools/miri/tests/pass/arrays.rs index 61b44453e9bd9..b0c6f54cab87c 100644 --- a/src/tools/miri/tests/pass/arrays.rs +++ b/src/tools/miri/tests/pass/arrays.rs @@ -61,6 +61,20 @@ fn debug() { println!("{:?}", array); } +fn huge_zst() { + fn id(x: T) -> T { x } + + // A "huge" zero-sized array. Make sure we don't loop over it in any part of Miri. + let val = [(); usize::MAX]; + id(val); // make a copy + + let val = [val; 2]; + id(val); + + // Also wrap it in a union (which, in particular, hits the logic for computing union padding). + let _copy = std::mem::MaybeUninit::new(val); +} + fn main() { assert_eq!(empty_array(), []); assert_eq!(index_unsafe(), 20); @@ -73,4 +87,5 @@ fn main() { from(); eq(); debug(); + huge_zst(); } From a1a8627dd789bd7444c78b7a5d360328709a54eb Mon Sep 17 00:00:00 2001 From: Urgau Date: Mon, 9 Sep 2024 13:43:25 +0200 Subject: [PATCH 0732/2194] Allow `missing_docs` lint on the generated test harness --- compiler/rustc_builtin_macros/src/test_harness.rs | 4 +++- compiler/rustc_span/src/symbol.rs | 1 + tests/pretty/tests-are-sorted.pp | 1 + tests/ui/lint/lint-missing-doc-test.rs | 5 +++++ 4 files changed, 10 insertions(+), 1 deletion(-) create mode 100644 tests/ui/lint/lint-missing-doc-test.rs diff --git a/compiler/rustc_builtin_macros/src/test_harness.rs b/compiler/rustc_builtin_macros/src/test_harness.rs index a9e4434581163..a694d3b8c2857 100644 --- a/compiler/rustc_builtin_macros/src/test_harness.rs +++ b/compiler/rustc_builtin_macros/src/test_harness.rs @@ -326,6 +326,8 @@ fn mk_main(cx: &mut TestCtxt<'_>) -> P { let main_attr = ecx.attr_word(sym::rustc_main, sp); // #[coverage(off)] let coverage_attr = ecx.attr_nested_word(sym::coverage, sym::off, sp); + // #[allow(missing_docs)] + let missing_docs_attr = ecx.attr_nested_word(sym::allow, sym::missing_docs, sp); // pub fn main() { ... } let main_ret_ty = ecx.ty(sp, ast::TyKind::Tup(ThinVec::new())); @@ -355,7 +357,7 @@ fn mk_main(cx: &mut TestCtxt<'_>) -> P { let main = P(ast::Item { ident: main_id, - attrs: thin_vec![main_attr, coverage_attr], + attrs: thin_vec![main_attr, coverage_attr, missing_docs_attr], id: ast::DUMMY_NODE_ID, kind: main, vis: ast::Visibility { span: sp, kind: ast::VisibilityKind::Public, tokens: None }, diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 36b31d10c4d29..db4f44ebcbc33 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1235,6 +1235,7 @@ symbols! { mir_unwind_unreachable, mir_variant, miri, + missing_docs, mmx_reg, modifiers, module, diff --git a/tests/pretty/tests-are-sorted.pp b/tests/pretty/tests-are-sorted.pp index 816cd5a5c072c..a4b15dde4530e 100644 --- a/tests/pretty/tests-are-sorted.pp +++ b/tests/pretty/tests-are-sorted.pp @@ -83,6 +83,7 @@ fn a_test() {} #[rustc_main] #[coverage(off)] +#[allow(missing_docs)] pub fn main() -> () { extern crate test; test::test_main_static(&[&a_test, &m_test, &z_test]) diff --git a/tests/ui/lint/lint-missing-doc-test.rs b/tests/ui/lint/lint-missing-doc-test.rs new file mode 100644 index 0000000000000..93d4e4a44e928 --- /dev/null +++ b/tests/ui/lint/lint-missing-doc-test.rs @@ -0,0 +1,5 @@ +//! This test checks that denying the missing_docs lint does not trigger +//! on the generated test harness. + +//@ check-pass +//@ compile-flags: --test -Dmissing_docs From 0f9cb070bc312df3c9cadd358efaa1d1efe4a9d0 Mon Sep 17 00:00:00 2001 From: Urgau Date: Mon, 9 Sep 2024 14:07:36 +0200 Subject: [PATCH 0733/2194] Add test about missing docs at crate level --- tests/ui/lint/lint-missing-doc-crate.rs | 4 ++++ tests/ui/lint/lint-missing-doc-crate.stderr | 10 ++++++++++ 2 files changed, 14 insertions(+) create mode 100644 tests/ui/lint/lint-missing-doc-crate.rs create mode 100644 tests/ui/lint/lint-missing-doc-crate.stderr diff --git a/tests/ui/lint/lint-missing-doc-crate.rs b/tests/ui/lint/lint-missing-doc-crate.rs new file mode 100644 index 0000000000000..afda73cbc603a --- /dev/null +++ b/tests/ui/lint/lint-missing-doc-crate.rs @@ -0,0 +1,4 @@ +// This test checks that we lint on the crate when it's missing a documentation. +// +//@ compile-flags: -Dmissing-docs --crate-type=lib +//~ ERROR missing documentation for the crate diff --git a/tests/ui/lint/lint-missing-doc-crate.stderr b/tests/ui/lint/lint-missing-doc-crate.stderr new file mode 100644 index 0000000000000..8efd3a17263fe --- /dev/null +++ b/tests/ui/lint/lint-missing-doc-crate.stderr @@ -0,0 +1,10 @@ +error: missing documentation for the crate + --> $DIR/lint-missing-doc-crate.rs:4:47 + | +LL | + | ^ + | + = note: requested on the command line with `-D missing-docs` + +error: aborting due to 1 previous error + From 544ccedd552ddbeda9a63adffdd8fcc1b39cb3fe Mon Sep 17 00:00:00 2001 From: roife Date: Mon, 9 Sep 2024 03:50:54 +0800 Subject: [PATCH 0734/2194] feat: Allow hir-def prettifier formatting into one-line --- .../crates/hir-def/src/body/pretty.rs | 70 +++++++++++++++---- 1 file changed, 55 insertions(+), 15 deletions(-) diff --git a/src/tools/rust-analyzer/crates/hir-def/src/body/pretty.rs b/src/tools/rust-analyzer/crates/hir-def/src/body/pretty.rs index 55740a68acd6e..6555d8061e7c4 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/body/pretty.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/body/pretty.rs @@ -16,6 +16,13 @@ use crate::{ use super::*; +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub(super) enum LineFormat { + Oneline, + Newline, + Indentation, +} + pub(super) fn print_body_hir( db: &dyn DefDatabase, body: &Body, @@ -52,7 +59,14 @@ pub(super) fn print_body_hir( } }; - let mut p = Printer { db, body, buf: header, indent_level: 0, needs_indent: false, edition }; + let mut p = Printer { + db, + body, + buf: header, + indent_level: 0, + line_format: LineFormat::Newline, + edition, + }; if let DefWithBodyId::FunctionId(it) = owner { p.buf.push('('); let function_data = &db.function_data(it); @@ -95,8 +109,14 @@ pub(super) fn print_expr_hir( expr: ExprId, edition: Edition, ) -> String { - let mut p = - Printer { db, body, buf: String::new(), indent_level: 0, needs_indent: false, edition }; + let mut p = Printer { + db, + body, + buf: String::new(), + indent_level: 0, + line_format: LineFormat::Newline, + edition, + }; p.print_expr(expr); p.buf } @@ -109,10 +129,10 @@ macro_rules! w { macro_rules! wln { ($dst:expr) => { - { let _ = writeln!($dst); } + { $dst.newline(); } }; ($dst:expr, $($arg:tt)*) => { - { let _ = writeln!($dst, $($arg)*); } + { let _ = w!($dst, $($arg)*); $dst.newline(); } }; } @@ -121,24 +141,30 @@ struct Printer<'a> { body: &'a Body, buf: String, indent_level: usize, - needs_indent: bool, + line_format: LineFormat, edition: Edition, } impl Write for Printer<'_> { fn write_str(&mut self, s: &str) -> fmt::Result { for line in s.split_inclusive('\n') { - if self.needs_indent { + if matches!(self.line_format, LineFormat::Indentation) { match self.buf.chars().rev().find(|ch| *ch != ' ') { Some('\n') | None => {} _ => self.buf.push('\n'), } self.buf.push_str(&" ".repeat(self.indent_level)); - self.needs_indent = false; } self.buf.push_str(line); - self.needs_indent = line.ends_with('\n'); + + if matches!(self.line_format, LineFormat::Newline | LineFormat::Indentation) { + self.line_format = if line.ends_with('\n') { + LineFormat::Indentation + } else { + LineFormat::Newline + }; + } } Ok(()) @@ -161,14 +187,28 @@ impl Printer<'_> { } } + // Add a newline if the current line is not empty. + // If the current line is empty, add a space instead. + // + // Do not use [`writeln!()`] or [`wln!()`] here, which will result in + // infinite recursive calls to this function. fn newline(&mut self) { - match self.buf.chars().rev().find_position(|ch| *ch != ' ') { - Some((_, '\n')) | None => {} - Some((idx, _)) => { - if idx != 0 { - self.buf.drain(self.buf.len() - idx..); + if matches!(self.line_format, LineFormat::Oneline) { + match self.buf.chars().last() { + Some(' ') | None => {} + Some(_) => { + w!(self, " "); + } + } + } else { + match self.buf.chars().rev().find_position(|ch| *ch != ' ') { + Some((_, '\n')) | None => {} + Some((idx, _)) => { + if idx != 0 { + self.buf.drain(self.buf.len() - idx..); + } + w!(self, "\n"); } - writeln!(self).unwrap() } } } From 352bd9f8e1c68dfdc1f4758566832e17b1543804 Mon Sep 17 00:00:00 2001 From: roife Date: Mon, 9 Sep 2024 03:52:04 +0800 Subject: [PATCH 0735/2194] feat: add prettifier for Pat --- .../rust-analyzer/crates/hir-def/src/body.rs | 11 ++++++++++ .../crates/hir-def/src/body/pretty.rs | 20 +++++++++++++++++++ 2 files changed, 31 insertions(+) diff --git a/src/tools/rust-analyzer/crates/hir-def/src/body.rs b/src/tools/rust-analyzer/crates/hir-def/src/body.rs index f18083d387356..6493826f073a7 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/body.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/body.rs @@ -227,6 +227,17 @@ impl Body { pretty::print_expr_hir(db, self, owner, expr, edition) } + pub fn pretty_print_pat( + &self, + db: &dyn DefDatabase, + owner: DefWithBodyId, + pat: PatId, + oneline: bool, + edition: Edition, + ) -> String { + pretty::print_pat_hir(db, self, owner, pat, oneline, edition) + } + fn new( db: &dyn DefDatabase, owner: DefWithBodyId, diff --git a/src/tools/rust-analyzer/crates/hir-def/src/body/pretty.rs b/src/tools/rust-analyzer/crates/hir-def/src/body/pretty.rs index 6555d8061e7c4..3333956adb22c 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/body/pretty.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/body/pretty.rs @@ -121,6 +121,26 @@ pub(super) fn print_expr_hir( p.buf } +pub(super) fn print_pat_hir( + db: &dyn DefDatabase, + body: &Body, + _owner: DefWithBodyId, + pat: PatId, + oneline: bool, + edition: Edition, +) -> String { + let mut p = Printer { + db, + body, + buf: String::new(), + indent_level: 0, + line_format: if oneline { LineFormat::Oneline } else { LineFormat::Newline }, + edition, + }; + p.print_pat(pat); + p.buf +} + macro_rules! w { ($dst:expr, $($arg:tt)*) => { { let _ = write!($dst, $($arg)*); } From 81fae18c9e3eff9b69a466beba9e7081278b3a90 Mon Sep 17 00:00:00 2001 From: roife Date: Mon, 9 Sep 2024 03:53:09 +0800 Subject: [PATCH 0736/2194] fix: use `pretty_print_pat` for params in fn --- .../rust-analyzer/crates/hir/src/display.rs | 13 +- .../crates/ide/src/hover/tests.rs | 115 ++++++++++++++++++ 2 files changed, 123 insertions(+), 5 deletions(-) diff --git a/src/tools/rust-analyzer/crates/hir/src/display.rs b/src/tools/rust-analyzer/crates/hir/src/display.rs index 923dca646673c..c2b2fbef75177 100644 --- a/src/tools/rust-analyzer/crates/hir/src/display.rs +++ b/src/tools/rust-analyzer/crates/hir/src/display.rs @@ -99,17 +99,20 @@ impl HirDisplay for Function { } // FIXME: Use resolved `param.ty` once we no longer discard lifetimes + let body = db.body(self.id.into()); for (type_ref, param) in data.params.iter().zip(self.assoc_fn_params(db)).skip(skip_self) { - let local = param.as_local(db).map(|it| it.name(db)); if !first { f.write_str(", ")?; } else { first = false; } - match local { - Some(name) => write!(f, "{}: ", name.display(f.db.upcast(), f.edition()))?, - None => f.write_str("_: ")?, - } + + let pat_id = body.params[param.idx - body.self_param.is_some() as usize]; + let pat_str = + body.pretty_print_pat(db.upcast(), self.id.into(), pat_id, true, f.edition()); + f.write_str(&pat_str)?; + + f.write_str(": ")?; type_ref.hir_fmt(f)?; } diff --git a/src/tools/rust-analyzer/crates/ide/src/hover/tests.rs b/src/tools/rust-analyzer/crates/ide/src/hover/tests.rs index f4528dd754c21..d1e51a2d28a53 100644 --- a/src/tools/rust-analyzer/crates/ide/src/hover/tests.rs +++ b/src/tools/rust-analyzer/crates/ide/src/hover/tests.rs @@ -8742,3 +8742,118 @@ fn foo() { "#]], ); } + + +#[test] +fn test_hover_function_with_pat_param() { + check( + r#"fn test_1$0((start_range, end_range): (u32, u32), a: i32) {}"#, + expect![[r#" + *test_1* + + ```rust + test + ``` + + ```rust + fn test_1((start_range, end_range): (u32, u32), a: i32) + ``` + "#]], + ); + + // Test case with tuple pattern and mutable parameters + check( + r#"fn test_2$0((mut x, y): (i32, i32)) {}"#, + expect![[r#" + *test_2* + + ```rust + test + ``` + + ```rust + fn test_2((mut x, y): (i32, i32)) + ``` + "#]], + ); + + // Test case with a pattern in a reference type + check( + r#"fn test_3$0(&(a, b): &(i32, i32)) {}"#, + expect![[r#" + *test_3* + + ```rust + test + ``` + + ```rust + fn test_3(&(a, b): &(i32, i32)) + ``` + "#]], + ); + + // Test case with complex pattern (struct destructuring) + check( + r#"struct Point { x: i32, y: i32 } fn test_4$0(Point { x, y }: Point) {}"#, + expect![[r#" + *test_4* + + ```rust + test + ``` + + ```rust + fn test_4(Point { x: x, y: y, }: Point) + ``` + "#]], + ); + + // Test case with a nested pattern + check( + r#"fn test_5$0(((a, b), c): ((i32, i32), i32)) {}"#, + expect![[r#" + *test_5* + + ```rust + test + ``` + + ```rust + fn test_5(((a, b), c): ((i32, i32), i32)) + ``` + "#]], + ); + + // Test case with an unused variable in the pattern + check( + r#"fn test_6$0((_, y): (i32, i64)) {}"#, + expect![[r#" + *test_6* + + ```rust + test + ``` + + ```rust + fn test_6((_, y): (i32, i64)) + ``` + "#]], + ); + + // Test case with a complex pattern involving both tuple and struct + check( + r#"struct Foo { a: i32, b: i32 } fn test_7$0((x, Foo { a, b }): (i32, Foo)) {}"#, + expect![[r#" + *test_7* + + ```rust + test + ``` + + ```rust + fn test_7((x, Foo { a: a, b: b, }): (i32, Foo)) + ``` + "#]], + ); +} From cbfa3578134e09a5a296cba3dc8b7951569ca603 Mon Sep 17 00:00:00 2001 From: roife Date: Mon, 9 Sep 2024 03:55:59 +0800 Subject: [PATCH 0737/2194] fix: add parenthesis for or-pattern --- .../crates/hir-def/src/body/pretty.rs | 2 ++ .../rust-analyzer/crates/ide/src/hover/tests.rs | 17 ++++++++++++++++- 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/src/tools/rust-analyzer/crates/hir-def/src/body/pretty.rs b/src/tools/rust-analyzer/crates/hir-def/src/body/pretty.rs index 3333956adb22c..64d0c16f525f7 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/body/pretty.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/body/pretty.rs @@ -599,12 +599,14 @@ impl Printer<'_> { w!(self, ")"); } Pat::Or(pats) => { + w!(self, "("); for (i, pat) in pats.iter().enumerate() { if i != 0 { w!(self, " | "); } self.print_pat(*pat); } + w!(self, ")"); } Pat::Record { path, args, ellipsis } => { match path { diff --git a/src/tools/rust-analyzer/crates/ide/src/hover/tests.rs b/src/tools/rust-analyzer/crates/ide/src/hover/tests.rs index d1e51a2d28a53..1a97d99f05129 100644 --- a/src/tools/rust-analyzer/crates/ide/src/hover/tests.rs +++ b/src/tools/rust-analyzer/crates/ide/src/hover/tests.rs @@ -8743,7 +8743,6 @@ fn foo() { ); } - #[test] fn test_hover_function_with_pat_param() { check( @@ -8856,4 +8855,20 @@ fn test_hover_function_with_pat_param() { ``` "#]], ); + + // Test case with Enum and Or pattern + check( + r#"enum MyEnum { A(i32), B(i32) } fn test_8$0((MyEnum::A(x) | MyEnum::B(x)): MyEnum) {}"#, + expect![[r#" + *test_8* + + ```rust + test + ``` + + ```rust + fn test_8((MyEnum::A(x) | MyEnum::B(x)): MyEnum) + ``` + "#]], + ); } From 383f50622774357b80eb9f0904f22fe89552a562 Mon Sep 17 00:00:00 2001 From: Krasimir Georgiev Date: Mon, 9 Sep 2024 13:29:47 +0000 Subject: [PATCH 0738/2194] adapt a test for llvm 20 No functional changes intended. --- tests/codegen/naked-asan.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/codegen/naked-asan.rs b/tests/codegen/naked-asan.rs index a45b95780f793..ac36018eed3a1 100644 --- a/tests/codegen/naked-asan.rs +++ b/tests/codegen/naked-asan.rs @@ -20,3 +20,4 @@ pub extern "x86-interrupt" fn page_fault_handler(_: u64, _: u64) { // CHECK: #[[ATTRS]] = // CHECK-NOT: sanitize_address +// CHECK: !llvm.module.flags From b0db9c285dae65fc30a72d6862264df23feae430 Mon Sep 17 00:00:00 2001 From: cuishuang Date: Mon, 9 Sep 2024 16:43:46 +0800 Subject: [PATCH 0739/2194] Remove unnecessary symbols and add missing symbols Signed-off-by: cuishuang --- clippy_lints/src/methods/unnecessary_to_owned.rs | 2 +- tests/ui/crashes/ice-3969.rs | 4 ++-- tests/ui/crashes/ice-6251.rs | 2 +- tests/ui/floating_point_arithmetic_nostd.rs | 2 +- tests/ui/unsafe_removed_from_name.rs | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/clippy_lints/src/methods/unnecessary_to_owned.rs b/clippy_lints/src/methods/unnecessary_to_owned.rs index 69c5bc57e2996..9e198c7e55cd7 100644 --- a/clippy_lints/src/methods/unnecessary_to_owned.rs +++ b/clippy_lints/src/methods/unnecessary_to_owned.rs @@ -717,7 +717,7 @@ fn check_if_applicable_to_argument<'tcx>(cx: &LateContext<'tcx>, arg: &Expr<'tcx // check that: // 1. This is a method with only one argument that doesn't come from a trait. // 2. That it has `Borrow` in its generic predicates. -// 3. `Self` is a std "map type" (ie `HashSet`, `HashMap`, BTreeSet`, `BTreeMap`). +// 3. `Self` is a std "map type" (ie `HashSet`, `HashMap`, `BTreeSet`, `BTreeMap`). fn check_borrow_predicate<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'tcx>) { if let ExprKind::MethodCall(_, caller, &[arg], _) = expr.kind && let Some(method_def_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id) diff --git a/tests/ui/crashes/ice-3969.rs b/tests/ui/crashes/ice-3969.rs index d5676cbd91d19..ac09ce08753af 100644 --- a/tests/ui/crashes/ice-3969.rs +++ b/tests/ui/crashes/ice-3969.rs @@ -1,7 +1,7 @@ // https://github.com/rust-lang/rust-clippy/issues/3969 // used to crash: error: internal compiler error: // src/librustc_traits/normalize_erasing_regions.rs:43: could not fully normalize `::Item test from rustc ./ui/trivial-bounds/trivial-bounds-inconsistent.rs +// std::iter::Iterator>::Item` test from rustc ./ui/trivial-bounds/trivial-bounds-inconsistent.rs // Check that tautalogically false bounds are accepted, and are used // in type inference. @@ -18,7 +18,7 @@ struct Dst { struct TwoStrs(str, str) where str: Sized; -//~^ ERROR: trait bound str: std::marker::Sized does not depend on any type or lifetim +//~^ ERROR: trait bound str: std::marker::Sized does not depend on any type or lifetime //~| NOTE: `-D trivial-bounds` implied by `-D warnings` fn unsized_local() diff --git a/tests/ui/crashes/ice-6251.rs b/tests/ui/crashes/ice-6251.rs index a81137a646558..73e919b6dd2eb 100644 --- a/tests/ui/crashes/ice-6251.rs +++ b/tests/ui/crashes/ice-6251.rs @@ -1,5 +1,5 @@ // originally from glacier/fixed/77329.rs -// assertion failed: `(left == right) ; different DefIds +// assertion failed: `(left == right)` ; different DefIds //@no-rustfix fn bug() -> impl Iterator { std::iter::empty() diff --git a/tests/ui/floating_point_arithmetic_nostd.rs b/tests/ui/floating_point_arithmetic_nostd.rs index 47c113d61c041..8ea75fae89b65 100644 --- a/tests/ui/floating_point_arithmetic_nostd.rs +++ b/tests/ui/floating_point_arithmetic_nostd.rs @@ -4,7 +4,7 @@ #![no_std] // The following should not lint, as the suggested methods `{f16,f32,f64,f128}.mul_add()` -// and ``{f16,f32,f64,f128}::abs()` are not available in no_std +// and `{f16,f32,f64,f128}::abs()` are not available in no_std pub fn mul_add() { let a: f64 = 1234.567; diff --git a/tests/ui/unsafe_removed_from_name.rs b/tests/ui/unsafe_removed_from_name.rs index e0e0ded140fc0..e9e6c8312f5eb 100644 --- a/tests/ui/unsafe_removed_from_name.rs +++ b/tests/ui/unsafe_removed_from_name.rs @@ -7,7 +7,7 @@ use std::cell::UnsafeCell as TotallySafeCell; //~| NOTE: `-D clippy::unsafe-removed-from-name` implied by `-D warnings` use std::cell::UnsafeCell as TotallySafeCellAgain; -//~^ ERROR: removed `unsafe` from the name of `UnsafeCell` in use as `TotallySafeCellAgain +//~^ ERROR: removed `unsafe` from the name of `UnsafeCell` in use as `TotallySafeCellAgain` // Shouldn't error use std::cell::RefCell as ProbablyNotUnsafe; From 1185eb081aae651fc6324630ed01203f92100d02 Mon Sep 17 00:00:00 2001 From: Trivikram Kamat <16024985+trivikr@users.noreply.github.com> Date: Mon, 9 Sep 2024 06:49:03 -0700 Subject: [PATCH 0740/2194] ci: bump actions/checkout to v4 --- src/tools/miri/.github/workflows/sysroots.yml | 2 +- src/tools/miri/README.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/tools/miri/.github/workflows/sysroots.yml b/src/tools/miri/.github/workflows/sysroots.yml index 73a10768db908..6a4f44ddd507a 100644 --- a/src/tools/miri/.github/workflows/sysroots.yml +++ b/src/tools/miri/.github/workflows/sysroots.yml @@ -13,7 +13,7 @@ jobs: name: Build the sysroots runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Build the sysroots run: | cargo install -f rustup-toolchain-install-master diff --git a/src/tools/miri/README.md b/src/tools/miri/README.md index dbb0e8a2925b3..72555e8c40d4f 100644 --- a/src/tools/miri/README.md +++ b/src/tools/miri/README.md @@ -187,7 +187,7 @@ Here is an example job for GitHub Actions: name: "Miri" runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Install Miri run: | rustup toolchain install nightly --component miri From e1653b6d5e39612a7731d209f1eb6b5d5cbe656e Mon Sep 17 00:00:00 2001 From: roife Date: Wed, 4 Sep 2024 03:29:56 +0800 Subject: [PATCH 0741/2194] feat: better name suggestions for fn --- .../ide-db/src/syntax_helpers/suggest_name.rs | 96 ++++++++++++++++++- 1 file changed, 95 insertions(+), 1 deletion(-) diff --git a/src/tools/rust-analyzer/crates/ide-db/src/syntax_helpers/suggest_name.rs b/src/tools/rust-analyzer/crates/ide-db/src/syntax_helpers/suggest_name.rs index 6ee526a67ea56..e60deb3bf59b1 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/syntax_helpers/suggest_name.rs +++ b/src/tools/rust-analyzer/crates/ide-db/src/syntax_helpers/suggest_name.rs @@ -18,7 +18,9 @@ const USELESS_TRAITS: &[&str] = &["Send", "Sync", "Copy", "Clone", "Eq", "Partia /// /// **NOTE**: they all must be snake lower case const USELESS_NAMES: &[&str] = - &["new", "default", "option", "some", "none", "ok", "err", "str", "string"]; + &["new", "default", "option", "some", "none", "ok", "err", "str", "string", "from", "into"]; + +const USELESS_NAME_PREFIXES: &[&str] = &["from_", "with_", "into_"]; /// Generic types replaced by their first argument /// @@ -189,6 +191,10 @@ fn normalize(name: &str) -> Option { return None; } + if USELESS_NAME_PREFIXES.iter().any(|prefix| name.starts_with(prefix)) { + return None; + } + if !is_valid_name(&name) { return None; } @@ -831,4 +837,92 @@ fn foo(some_struct: S) { $0some_struct.some_field$0 } "some_field", ); } + + #[test] + fn from_and_to_func() { + check( + r#" +//- minicore: from +struct Foo; +struct Bar; + +impl From for Bar { + fn from(_: Foo) -> Self { + Bar; + } +} + +fn f(_: Bar) {} + +fn main() { + let foo = Foo {}; + f($0Bar::from(foo)$0); +} +"#, + "bar", + ); + + check( + r#" +//- minicore: from +struct Foo; +struct Bar; + +impl From for Bar { + fn from(_: Foo) -> Self { + Bar; + } +} + +fn f(_: Bar) {} + +fn main() { + let foo = Foo {}; + f($0Into::::into(foo)$0); +} +"#, + "bar", + ); + } + + #[test] + fn useless_name_prefix() { + check( + r#" +struct Foo; +struct Bar; + +impl Bar { + fn from_foo(_: Foo) -> Self { + Foo {} + } +} + +fn main() { + let foo = Foo {}; + let _ = $0Bar::from_foo(foo)$0; +} +"#, + "bar", + ); + + check( + r#" +struct Foo; +struct Bar; + +impl Bar { + fn with_foo(_: Foo) -> Self { + Bar {} + } +} + +fn main() { + let foo = Foo {}; + let _ = $0Bar::with_foo(foo)$0; +} +"#, + "bar", + ); + } } From d4eeb31c2eb4bee9f2e5791d01c8d55048b46a31 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 9 Sep 2024 16:01:47 +0200 Subject: [PATCH 0742/2194] use fd_num for file descriptors, so we can use fd for file description --- src/tools/miri/src/shims/unix/fd.rs | 85 ++++++++++---------- src/tools/miri/src/shims/unix/fs.rs | 78 ++++++++---------- src/tools/miri/src/shims/unix/linux/epoll.rs | 12 +-- 3 files changed, 83 insertions(+), 92 deletions(-) diff --git a/src/tools/miri/src/shims/unix/fd.rs b/src/tools/miri/src/shims/unix/fd.rs index d756c06ebdb12..48bf959538b4f 100644 --- a/src/tools/miri/src/shims/unix/fd.rs +++ b/src/tools/miri/src/shims/unix/fd.rs @@ -303,7 +303,7 @@ pub struct FdTable { impl VisitProvenance for FdTable { fn visit_provenance(&self, _visit: &mut VisitWith<'_>) { - // All our FileDescriptionRef do not have any tags. + // All our FileDescription instances do not have any tags. } } @@ -337,18 +337,18 @@ impl FdTable { } pub fn insert(&mut self, fd_ref: FileDescriptionRef) -> i32 { - self.insert_ref_with_min_fd(fd_ref, 0) + self.insert_with_min_num(fd_ref, 0) } - /// Insert a file description, giving it a file descriptor that is at least `min_fd`. - fn insert_ref_with_min_fd(&mut self, file_handle: FileDescriptionRef, min_fd: i32) -> i32 { + /// Insert a file description, giving it a file descriptor that is at least `min_fd_num`. + fn insert_with_min_num(&mut self, file_handle: FileDescriptionRef, min_fd_num: i32) -> i32 { // Find the lowest unused FD, starting from min_fd. If the first such unused FD is in // between used FDs, the find_map combinator will return it. If the first such unused FD // is after all other used FDs, the find_map combinator will return None, and we will use // the FD following the greatest FD thus far. let candidate_new_fd = - self.fds.range(min_fd..).zip(min_fd..).find_map(|((fd, _fh), counter)| { - if *fd != counter { + self.fds.range(min_fd_num..).zip(min_fd_num..).find_map(|((fd_num, _fd), counter)| { + if *fd_num != counter { // There was a gap in the fds stored, return the first unused one // (note that this relies on BTreeMap iterating in key order) Some(counter) @@ -357,61 +357,61 @@ impl FdTable { None } }); - let new_fd = candidate_new_fd.unwrap_or_else(|| { + let new_fd_num = candidate_new_fd.unwrap_or_else(|| { // find_map ran out of BTreeMap entries before finding a free fd, use one plus the // maximum fd in the map - self.fds.last_key_value().map(|(fd, _)| fd.strict_add(1)).unwrap_or(min_fd) + self.fds.last_key_value().map(|(fd_num, _)| fd_num.strict_add(1)).unwrap_or(min_fd_num) }); - self.fds.try_insert(new_fd, file_handle).unwrap(); - new_fd + self.fds.try_insert(new_fd_num, file_handle).unwrap(); + new_fd_num } - pub fn get(&self, fd: i32) -> Option { - let fd = self.fds.get(&fd)?; + pub fn get(&self, fd_num: i32) -> Option { + let fd = self.fds.get(&fd_num)?; Some(fd.clone()) } - pub fn remove(&mut self, fd: i32) -> Option { - self.fds.remove(&fd) + pub fn remove(&mut self, fd_num: i32) -> Option { + self.fds.remove(&fd_num) } - pub fn is_fd(&self, fd: i32) -> bool { - self.fds.contains_key(&fd) + pub fn is_fd_num(&self, fd_num: i32) -> bool { + self.fds.contains_key(&fd_num) } } impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {} pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { - fn dup(&mut self, old_fd: i32) -> InterpResult<'tcx, Scalar> { + fn dup(&mut self, old_fd_num: i32) -> InterpResult<'tcx, Scalar> { let this = self.eval_context_mut(); - let Some(dup_fd) = this.machine.fds.get(old_fd) else { + let Some(fd) = this.machine.fds.get(old_fd_num) else { return Ok(Scalar::from_i32(this.fd_not_found()?)); }; - Ok(Scalar::from_i32(this.machine.fds.insert_ref_with_min_fd(dup_fd, 0))) + Ok(Scalar::from_i32(this.machine.fds.insert(fd))) } - fn dup2(&mut self, old_fd: i32, new_fd: i32) -> InterpResult<'tcx, Scalar> { + fn dup2(&mut self, old_fd_num: i32, new_fd_num: i32) -> InterpResult<'tcx, Scalar> { let this = self.eval_context_mut(); - let Some(dup_fd) = this.machine.fds.get(old_fd) else { + let Some(fd) = this.machine.fds.get(old_fd_num) else { return Ok(Scalar::from_i32(this.fd_not_found()?)); }; - if new_fd != old_fd { + if new_fd_num != old_fd_num { // Close new_fd if it is previously opened. // If old_fd and new_fd point to the same description, then `dup_fd` ensures we keep the underlying file description alive. - if let Some(file_description) = this.machine.fds.fds.insert(new_fd, dup_fd) { + if let Some(old_new_fd) = this.machine.fds.fds.insert(new_fd_num, fd) { // Ignore close error (not interpreter's) according to dup2() doc. - file_description.close(this.machine.communicate(), this)?.ok(); + old_new_fd.close(this.machine.communicate(), this)?.ok(); } } - Ok(Scalar::from_i32(new_fd)) + Ok(Scalar::from_i32(new_fd_num)) } - fn flock(&mut self, fd: i32, op: i32) -> InterpResult<'tcx, Scalar> { + fn flock(&mut self, fd_num: i32, op: i32) -> InterpResult<'tcx, Scalar> { let this = self.eval_context_mut(); - let Some(fd_ref) = this.machine.fds.get(fd) else { + let Some(fd) = this.machine.fds.get(fd_num) else { return Ok(Scalar::from_i32(this.fd_not_found()?)); }; @@ -436,8 +436,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { throw_unsup_format!("unsupported flags {:#x}", op); }; - let result = fd_ref.flock(this.machine.communicate(), parsed_op)?; - drop(fd_ref); + let result = fd.flock(this.machine.communicate(), parsed_op)?; + drop(fd); // return `0` if flock is successful let result = result.map(|()| 0i32); Ok(Scalar::from_i32(this.try_unwrap_io_result(result)?)) @@ -452,7 +452,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { args.len() ); } - let fd = this.read_scalar(&args[0])?.to_i32()?; + let fd_num = this.read_scalar(&args[0])?.to_i32()?; let cmd = this.read_scalar(&args[1])?.to_i32()?; // We only support getting the flags for a descriptor. @@ -461,7 +461,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // `FD_CLOEXEC` value without checking if the flag is set for the file because `std` // always sets this flag when opening a file. However we still need to check that the // file itself is open. - Ok(Scalar::from_i32(if this.machine.fds.is_fd(fd) { + Ok(Scalar::from_i32(if this.machine.fds.is_fd_num(fd_num) { this.eval_libc_i32("FD_CLOEXEC") } else { this.fd_not_found()? @@ -481,9 +481,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { } let start = this.read_scalar(&args[2])?.to_i32()?; - match this.machine.fds.get(fd) { - Some(dup_fd) => - Ok(Scalar::from_i32(this.machine.fds.insert_ref_with_min_fd(dup_fd, start))), + match this.machine.fds.get(fd_num) { + Some(fd) => Ok(Scalar::from_i32(this.machine.fds.insert_with_min_num(fd, start))), None => Ok(Scalar::from_i32(this.fd_not_found()?)), } } else if this.tcx.sess.target.os == "macos" && cmd == this.eval_libc_i32("F_FULLFSYNC") { @@ -494,7 +493,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { return Ok(Scalar::from_i32(-1)); } - this.ffullsync_fd(fd) + this.ffullsync_fd(fd_num) } else { throw_unsup_format!("the {:#x} command is not supported for `fcntl`)", cmd); } @@ -503,12 +502,12 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { fn close(&mut self, fd_op: &OpTy<'tcx>) -> InterpResult<'tcx, Scalar> { let this = self.eval_context_mut(); - let fd = this.read_scalar(fd_op)?.to_i32()?; + let fd_num = this.read_scalar(fd_op)?.to_i32()?; - let Some(file_description) = this.machine.fds.remove(fd) else { + let Some(fd) = this.machine.fds.remove(fd_num) else { return Ok(Scalar::from_i32(this.fd_not_found()?)); }; - let result = file_description.close(this.machine.communicate(), this)?; + let result = fd.close(this.machine.communicate(), this)?; // return `0` if close is successful let result = result.map(|()| 0i32); Ok(Scalar::from_i32(this.try_unwrap_io_result(result)?)) @@ -532,7 +531,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { /// and keeps the cursor unchanged. fn read( &mut self, - fd: i32, + fd_num: i32, buf: Pointer, count: u64, offset: Option, @@ -541,7 +540,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // Isolation check is done via `FileDescription` trait. - trace!("Reading from FD {}, size {}", fd, count); + trace!("Reading from FD {}, size {}", fd_num, count); // Check that the *entire* buffer is actually valid memory. this.check_ptr_access(buf, Size::from_bytes(count), CheckInAllocMsg::MemoryAccessTest)?; @@ -554,7 +553,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { let communicate = this.machine.communicate(); // We temporarily dup the FD to be able to retain mutable access to `this`. - let Some(fd) = this.machine.fds.get(fd) else { + let Some(fd) = this.machine.fds.get(fd_num) else { trace!("read: FD not found"); return Ok(Scalar::from_target_isize(this.fd_not_found()?, this)); }; @@ -597,7 +596,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { fn write( &mut self, - fd: i32, + fd_num: i32, buf: Pointer, count: u64, offset: Option, @@ -618,7 +617,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { let bytes = this.read_bytes_ptr_strip_provenance(buf, Size::from_bytes(count))?.to_owned(); // We temporarily dup the FD to be able to retain mutable access to `this`. - let Some(fd) = this.machine.fds.get(fd) else { + let Some(fd) = this.machine.fds.get(fd_num) else { return Ok(Scalar::from_target_isize(this.fd_not_found()?, this)); }; diff --git a/src/tools/miri/src/shims/unix/fs.rs b/src/tools/miri/src/shims/unix/fs.rs index 58d3a73b481d2..e1697a4741559 100644 --- a/src/tools/miri/src/shims/unix/fs.rs +++ b/src/tools/miri/src/shims/unix/fs.rs @@ -554,7 +554,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { Ok(Scalar::from_i32(this.try_unwrap_io_result(fd)?)) } - fn lseek64(&mut self, fd: i32, offset: i128, whence: i32) -> InterpResult<'tcx, Scalar> { + fn lseek64(&mut self, fd_num: i32, offset: i128, whence: i32) -> InterpResult<'tcx, Scalar> { let this = self.eval_context_mut(); // Isolation check is done via `FileDescription` trait. @@ -580,13 +580,11 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { let communicate = this.machine.communicate(); - let Some(file_description) = this.machine.fds.get(fd) else { + let Some(fd) = this.machine.fds.get(fd_num) else { return Ok(Scalar::from_i64(this.fd_not_found()?)); }; - let result = file_description - .seek(communicate, seek_from)? - .map(|offset| i64::try_from(offset).unwrap()); - drop(file_description); + let result = fd.seek(communicate, seek_from)?.map(|offset| i64::try_from(offset).unwrap()); + drop(fd); let result = this.try_unwrap_io_result(result)?; Ok(Scalar::from_i64(result)) @@ -721,7 +719,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { return Ok(Scalar::from_i32(this.fd_not_found()?)); } - let metadata = match FileMetadata::from_fd(this, fd)? { + let metadata = match FileMetadata::from_fd_num(this, fd)? { Some(metadata) => metadata, None => return Ok(Scalar::from_i32(-1)), }; @@ -808,7 +806,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // If the path is empty, and the AT_EMPTY_PATH flag is set, we query the open file // represented by dirfd, whether it's a directory or otherwise. let metadata = if path.as_os_str().is_empty() && empty_path_flag { - FileMetadata::from_fd(this, dirfd)? + FileMetadata::from_fd_num(this, dirfd)? } else { FileMetadata::from_path(this, &path, follow_symlink)? }; @@ -1260,7 +1258,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { })) } - fn ftruncate64(&mut self, fd: i32, length: i128) -> InterpResult<'tcx, Scalar> { + fn ftruncate64(&mut self, fd_num: i32, length: i128) -> InterpResult<'tcx, Scalar> { let this = self.eval_context_mut(); // Reject if isolation is enabled. @@ -1270,30 +1268,29 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { return Ok(Scalar::from_i32(this.fd_not_found()?)); } - let Some(file_description) = this.machine.fds.get(fd) else { + let Some(fd) = this.machine.fds.get(fd_num) else { return Ok(Scalar::from_i32(this.fd_not_found()?)); }; // FIXME: Support ftruncate64 for all FDs - let FileHandle { file, writable } = - file_description.downcast::().ok_or_else(|| { - err_unsup_format!("`ftruncate64` is only supported on file-backed file descriptors") - })?; + let FileHandle { file, writable } = fd.downcast::().ok_or_else(|| { + err_unsup_format!("`ftruncate64` is only supported on file-backed file descriptors") + })?; if *writable { if let Ok(length) = length.try_into() { let result = file.set_len(length); - drop(file_description); + drop(fd); let result = this.try_unwrap_io_result(result.map(|_| 0i32))?; Ok(Scalar::from_i32(result)) } else { - drop(file_description); + drop(fd); let einval = this.eval_libc("EINVAL"); this.set_last_error(einval)?; Ok(Scalar::from_i32(-1)) } } else { - drop(file_description); + drop(fd); // The file is not writable let einval = this.eval_libc("EINVAL"); this.set_last_error(einval)?; @@ -1321,18 +1318,17 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { self.ffullsync_fd(fd) } - fn ffullsync_fd(&mut self, fd: i32) -> InterpResult<'tcx, Scalar> { + fn ffullsync_fd(&mut self, fd_num: i32) -> InterpResult<'tcx, Scalar> { let this = self.eval_context_mut(); - let Some(file_description) = this.machine.fds.get(fd) else { + let Some(fd) = this.machine.fds.get(fd_num) else { return Ok(Scalar::from_i32(this.fd_not_found()?)); }; // Only regular files support synchronization. - let FileHandle { file, writable } = - file_description.downcast::().ok_or_else(|| { - err_unsup_format!("`fsync` is only supported on file-backed file descriptors") - })?; + let FileHandle { file, writable } = fd.downcast::().ok_or_else(|| { + err_unsup_format!("`fsync` is only supported on file-backed file descriptors") + })?; let io_result = maybe_sync_file(file, *writable, File::sync_all); - drop(file_description); + drop(fd); Ok(Scalar::from_i32(this.try_unwrap_io_result(io_result)?)) } @@ -1348,16 +1344,15 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { return Ok(Scalar::from_i32(this.fd_not_found()?)); } - let Some(file_description) = this.machine.fds.get(fd) else { + let Some(fd) = this.machine.fds.get(fd) else { return Ok(Scalar::from_i32(this.fd_not_found()?)); }; // Only regular files support synchronization. - let FileHandle { file, writable } = - file_description.downcast::().ok_or_else(|| { - err_unsup_format!("`fdatasync` is only supported on file-backed file descriptors") - })?; + let FileHandle { file, writable } = fd.downcast::().ok_or_else(|| { + err_unsup_format!("`fdatasync` is only supported on file-backed file descriptors") + })?; let io_result = maybe_sync_file(file, *writable, File::sync_data); - drop(file_description); + drop(fd); Ok(Scalar::from_i32(this.try_unwrap_io_result(io_result)?)) } @@ -1396,18 +1391,15 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { return Ok(Scalar::from_i32(this.fd_not_found()?)); } - let Some(file_description) = this.machine.fds.get(fd) else { + let Some(fd) = this.machine.fds.get(fd) else { return Ok(Scalar::from_i32(this.fd_not_found()?)); }; // Only regular files support synchronization. - let FileHandle { file, writable } = - file_description.downcast::().ok_or_else(|| { - err_unsup_format!( - "`sync_data_range` is only supported on file-backed file descriptors" - ) - })?; + let FileHandle { file, writable } = fd.downcast::().ok_or_else(|| { + err_unsup_format!("`sync_data_range` is only supported on file-backed file descriptors") + })?; let io_result = maybe_sync_file(file, *writable, File::sync_data); - drop(file_description); + drop(fd); Ok(Scalar::from_i32(this.try_unwrap_io_result(io_result)?)) } @@ -1699,15 +1691,15 @@ impl FileMetadata { FileMetadata::from_meta(ecx, metadata) } - fn from_fd<'tcx>( + fn from_fd_num<'tcx>( ecx: &mut MiriInterpCx<'tcx>, - fd: i32, + fd_num: i32, ) -> InterpResult<'tcx, Option> { - let Some(file_description) = ecx.machine.fds.get(fd) else { + let Some(fd) = ecx.machine.fds.get(fd_num) else { return ecx.fd_not_found().map(|_: i32| None); }; - let file = &file_description + let file = &fd .downcast::() .ok_or_else(|| { err_unsup_format!( @@ -1717,7 +1709,7 @@ impl FileMetadata { .file; let metadata = file.metadata(); - drop(file_description); + drop(fd); FileMetadata::from_meta(ecx, metadata) } diff --git a/src/tools/miri/src/shims/unix/linux/epoll.rs b/src/tools/miri/src/shims/unix/linux/epoll.rs index ee86cf5f26d7f..d91ce45e101d9 100644 --- a/src/tools/miri/src/shims/unix/linux/epoll.rs +++ b/src/tools/miri/src/shims/unix/linux/epoll.rs @@ -51,7 +51,7 @@ impl EpollEventInstance { #[derive(Clone, Debug)] pub struct EpollEventInterest { /// The file descriptor value of the file description registered. - file_descriptor: i32, + fd_num: i32, /// The events bitmask retrieved from `epoll_event`. events: u32, /// The data retrieved from `epoll_event`. @@ -62,7 +62,7 @@ pub struct EpollEventInterest { /// Ready list of the epoll instance under which this EpollEventInterest is registered. ready_list: Rc>>, /// The file descriptor value that this EpollEventInterest is registered under. - epfd: i32, + epfd_num: i32, } /// EpollReadyEvents reflects the readiness of a file description. @@ -339,11 +339,11 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // Create an epoll_interest. let interest = Rc::new(RefCell::new(EpollEventInterest { - file_descriptor: fd, + fd_num: fd, events, data, ready_list: Rc::clone(ready_list), - epfd: epfd_value, + epfd_num: epfd_value, })); if op == epoll_ctl_add { @@ -553,7 +553,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { if is_updated { // Edge-triggered notification only notify one thread even if there are // multiple threads block on the same epfd. - let epfd = this.machine.fds.get(epoll_interest.borrow().epfd).unwrap(); + let epfd = this.machine.fds.get(epoll_interest.borrow().epfd_num).unwrap(); // This unwrap can never fail because if the current epoll instance were // closed and its epfd value reused, the upgrade of weak_epoll_interest @@ -615,7 +615,7 @@ fn check_and_update_one_event_interest<'tcx>( // If there is any event that we are interested in being specified as ready, // insert an epoll_return to the ready list. if flags != 0 { - let epoll_key = (id, epoll_event_interest.file_descriptor); + let epoll_key = (id, epoll_event_interest.fd_num); let ready_list = &mut epoll_event_interest.ready_list.borrow_mut(); let event_instance = EpollEventInstance::new(flags, epoll_event_interest.data); // Triggers the notification by inserting it to the ready list. From 0a70924c2160c8f93a446328e207a1983e62596a Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 9 Sep 2024 16:11:17 +0200 Subject: [PATCH 0743/2194] fix UB in a test also add an explicit test for the fact that a Option has padding when it is None --- library/core/tests/mem.rs | 7 ++++++- .../miri/tests/fail/uninit/padding-enum.rs | 2 +- .../miri/tests/fail/uninit/padding-enum.stderr | 2 +- .../miri/tests/fail/uninit/padding-wide-ptr.rs | 18 ++++++++++++++++++ .../tests/fail/uninit/padding-wide-ptr.stderr | 15 +++++++++++++++ 5 files changed, 41 insertions(+), 3 deletions(-) create mode 100644 src/tools/miri/tests/fail/uninit/padding-wide-ptr.rs create mode 100644 src/tools/miri/tests/fail/uninit/padding-wide-ptr.stderr diff --git a/library/core/tests/mem.rs b/library/core/tests/mem.rs index b7eee10ec3f9c..f3b4387f6a898 100644 --- a/library/core/tests/mem.rs +++ b/library/core/tests/mem.rs @@ -773,15 +773,20 @@ fn offset_of_addr() { #[test] fn const_maybe_uninit_zeroed() { // Sanity check for `MaybeUninit::zeroed` in a realistic const situation (plugin array term) + + // It is crucial that this type has no padding! #[repr(C)] struct Foo { - a: Option<&'static str>, + a: Option<&'static u8>, b: Bar, c: f32, + _pad: u32, d: *const u8, } + #[repr(C)] struct Bar(usize); + struct FooPtr(*const Foo); unsafe impl Sync for FooPtr {} diff --git a/src/tools/miri/tests/fail/uninit/padding-enum.rs b/src/tools/miri/tests/fail/uninit/padding-enum.rs index 0ab9be275815d..3852ac5c477d5 100644 --- a/src/tools/miri/tests/fail/uninit/padding-enum.rs +++ b/src/tools/miri/tests/fail/uninit/padding-enum.rs @@ -18,6 +18,6 @@ fn main() { unsafe { // Turns out the discriminant is (currently) stored // in the 2nd pointer, so the first half is padding. let c = &p as *const _ as *const u8; - let _val = *c.add(0); // Get the padding byte. + let _val = *c.add(0); // Get a padding byte. //~^ERROR: uninitialized } } diff --git a/src/tools/miri/tests/fail/uninit/padding-enum.stderr b/src/tools/miri/tests/fail/uninit/padding-enum.stderr index a507a5d49bc2c..c571f18874076 100644 --- a/src/tools/miri/tests/fail/uninit/padding-enum.stderr +++ b/src/tools/miri/tests/fail/uninit/padding-enum.stderr @@ -1,7 +1,7 @@ error: Undefined Behavior: using uninitialized data, but this operation requires initialized memory --> $DIR/padding-enum.rs:LL:CC | -LL | let _val = *c.add(0); // Get the padding byte. +LL | let _val = *c.add(0); // Get a padding byte. | ^^^^^^^^^ using uninitialized data, but this operation requires initialized memory | = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior diff --git a/src/tools/miri/tests/fail/uninit/padding-wide-ptr.rs b/src/tools/miri/tests/fail/uninit/padding-wide-ptr.rs new file mode 100644 index 0000000000000..0403a9caba66d --- /dev/null +++ b/src/tools/miri/tests/fail/uninit/padding-wide-ptr.rs @@ -0,0 +1,18 @@ +use std::mem; + +// If this is `None`, the metadata becomes padding. +type T = Option<&'static str>; + +fn main() { unsafe { + let mut p: mem::MaybeUninit = mem::MaybeUninit::zeroed(); + // The copy when `T` is returned from `transmute` should destroy padding + // (even when we use `write_unaligned`, which under the hood uses an untyped copy). + p.as_mut_ptr().write_unaligned(mem::transmute((0usize, 0usize))); + // Null epresents `None`. + assert!(matches!(*p.as_ptr(), None)); + + // The second part, with the length, becomes padding. + let c = &p as *const _ as *const u8; + let _val = *c.add(mem::size_of::<*const u8>()); // Get a padding byte. + //~^ERROR: uninitialized +} } diff --git a/src/tools/miri/tests/fail/uninit/padding-wide-ptr.stderr b/src/tools/miri/tests/fail/uninit/padding-wide-ptr.stderr new file mode 100644 index 0000000000000..0da72550b2e08 --- /dev/null +++ b/src/tools/miri/tests/fail/uninit/padding-wide-ptr.stderr @@ -0,0 +1,15 @@ +error: Undefined Behavior: using uninitialized data, but this operation requires initialized memory + --> $DIR/padding-wide-ptr.rs:LL:CC + | +LL | let _val = *c.add(mem::size_of::<*const u8>()); // Get a padding byte. + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using uninitialized data, but this operation requires initialized memory + | + = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior + = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information + = note: BACKTRACE: + = note: inside `main` at $DIR/padding-wide-ptr.rs:LL:CC + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to 1 previous error + From 1f1363335922b76e6940cf632a391f3315f564cf Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Sat, 17 Aug 2024 21:38:10 +0200 Subject: [PATCH 0744/2194] Bump ui_test --- Cargo.toml | 2 +- tests/compile-test.rs | 10 ++- tests/ui/asm_syntax_not_x86.rs | 3 +- tests/ui/asm_syntax_x86.rs | 4 +- tests/ui/asm_syntax_x86.stderr | 70 +++++++++++++++++++ tests/ui/crashes/ice-7410.rs | 3 +- .../entrypoint_recursion.rs | 2 +- .../no_std_main_recursion.rs | 2 +- tests/ui/def_id_nocore.rs | 2 +- tests/ui/empty_loop_no_std.rs | 2 +- tests/ui/enum_clike_unportable_variant.rs | 2 +- tests/ui/macro_use_imports.fixed | 2 +- tests/ui/macro_use_imports.rs | 2 +- tests/ui/macro_use_imports_expect.rs | 2 +- tests/ui/mixed_attributes_style.rs | 3 +- tests/ui/mixed_attributes_style.stderr | 3 +- tests/ui/non_octal_unix_permissions.fixed | 2 +- tests/ui/non_octal_unix_permissions.rs | 2 +- tests/ui/result_large_err.rs | 2 +- tests/ui/single_call_fn.rs | 2 +- tests/ui/transmute_32bit.rs | 2 +- tests/ui/transmute_64bit.rs | 2 +- 22 files changed, 96 insertions(+), 30 deletions(-) create mode 100644 tests/ui/asm_syntax_x86.stderr diff --git a/Cargo.toml b/Cargo.toml index 5b62e387ac631..cf810798d8cc1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -31,7 +31,7 @@ anstream = "0.6.0" [dev-dependencies] cargo_metadata = "0.18.1" -ui_test = "0.25" +ui_test = "0.26.4" regex = "1.5.5" serde = { version = "1.0.145", features = ["derive"] } serde_json = "1.0.122" diff --git a/tests/compile-test.rs b/tests/compile-test.rs index 9754254cdd0df..c7243348ce46f 100644 --- a/tests/compile-test.rs +++ b/tests/compile-test.rs @@ -13,7 +13,6 @@ use test_utils::IS_RUSTC_TEST_SUITE; use ui_test::custom_flags::rustfix::RustfixMode; use ui_test::custom_flags::Flag; use ui_test::spanned::Spanned; -use ui_test::test_result::TestRun; use ui_test::{status_emitter, Args, CommandBuilder, Config, Match, OutputConflictHandling}; use std::collections::{BTreeMap, HashMap}; @@ -469,15 +468,14 @@ fn applicability_ord(applicability: &Applicability) -> u8 { impl Flag for DiagnosticCollector { fn post_test_action( &self, - _config: &ui_test::per_test_config::TestConfig<'_>, - _cmd: &mut std::process::Command, + _config: &ui_test::per_test_config::TestConfig, output: &std::process::Output, - _build_manager: &ui_test::build_manager::BuildManager<'_>, - ) -> Result, ui_test::Errored> { + _build_manager: &ui_test::build_manager::BuildManager, + ) -> Result<(), ui_test::Errored> { if !output.stderr.is_empty() { self.sender.send(output.stderr.clone()).unwrap(); } - Ok(Vec::new()) + Ok(()) } fn clone_inner(&self) -> Box { diff --git a/tests/ui/asm_syntax_not_x86.rs b/tests/ui/asm_syntax_not_x86.rs index 33cea4806814b..a7d29cc239e53 100644 --- a/tests/ui/asm_syntax_not_x86.rs +++ b/tests/ui/asm_syntax_not_x86.rs @@ -1,5 +1,4 @@ -//@ignore-target-i686 -//@ignore-target-x86 +//@ignore-target: i686 x86 //@needs-asm-support #[warn(clippy::inline_asm_x86_intel_syntax)] diff --git a/tests/ui/asm_syntax_x86.rs b/tests/ui/asm_syntax_x86.rs index 835943b43894c..5ceaceb7527b3 100644 --- a/tests/ui/asm_syntax_x86.rs +++ b/tests/ui/asm_syntax_x86.rs @@ -1,6 +1,4 @@ -//@revisions: i686 x86_64 -//@[i686] only-target-i686 -//@[x86_64] only-target-x86_64 +//@only-target: i686 x86_64 #[warn(clippy::inline_asm_x86_intel_syntax)] mod warn_intel { diff --git a/tests/ui/asm_syntax_x86.stderr b/tests/ui/asm_syntax_x86.stderr new file mode 100644 index 0000000000000..1911ef66e2391 --- /dev/null +++ b/tests/ui/asm_syntax_x86.stderr @@ -0,0 +1,70 @@ +error: Intel x86 assembly syntax used + --> tests/ui/asm_syntax_x86.rs:8:9 + | +LL | asm!(""); + | ^^^^^^^^ + | + = help: use AT&T x86 assembly syntax + = note: `-D clippy::inline-asm-x86-intel-syntax` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::inline_asm_x86_intel_syntax)]` + +error: Intel x86 assembly syntax used + --> tests/ui/asm_syntax_x86.rs:10:9 + | +LL | asm!("", options()); + | ^^^^^^^^^^^^^^^^^^^ + | + = help: use AT&T x86 assembly syntax + +error: Intel x86 assembly syntax used + --> tests/ui/asm_syntax_x86.rs:12:9 + | +LL | asm!("", options(nostack)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: use AT&T x86 assembly syntax + +error: Intel x86 assembly syntax used + --> tests/ui/asm_syntax_x86.rs:18:5 + | +LL | global_asm!(""); + | ^^^^^^^^^^^^^^^ + | + = help: use AT&T x86 assembly syntax + +error: Intel x86 assembly syntax used + --> tests/ui/asm_syntax_x86.rs:20:5 + | +LL | global_asm!("", options()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: use AT&T x86 assembly syntax + +error: AT&T x86 assembly syntax used + --> tests/ui/asm_syntax_x86.rs:33:9 + | +LL | asm!("", options(att_syntax)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: use Intel x86 assembly syntax + = note: `-D clippy::inline-asm-x86-att-syntax` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::inline_asm_x86_att_syntax)]` + +error: AT&T x86 assembly syntax used + --> tests/ui/asm_syntax_x86.rs:35:9 + | +LL | asm!("", options(nostack, att_syntax)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: use Intel x86 assembly syntax + +error: AT&T x86 assembly syntax used + --> tests/ui/asm_syntax_x86.rs:41:5 + | +LL | global_asm!("", options(att_syntax)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: use Intel x86 assembly syntax + +error: aborting due to 8 previous errors + diff --git a/tests/ui/crashes/ice-7410.rs b/tests/ui/crashes/ice-7410.rs index a2683b3ce3402..ccf6d7ff94f23 100644 --- a/tests/ui/crashes/ice-7410.rs +++ b/tests/ui/crashes/ice-7410.rs @@ -1,6 +1,5 @@ //@compile-flags: -Clink-arg=-nostartfiles -//@ignore-target-apple -//@ignore-target-windows +//@ignore-target: apple windows #![feature(lang_items, start, libc)] #![no_std] diff --git a/tests/ui/crate_level_checks/entrypoint_recursion.rs b/tests/ui/crate_level_checks/entrypoint_recursion.rs index aa76688d80101..5d853d97bc35b 100644 --- a/tests/ui/crate_level_checks/entrypoint_recursion.rs +++ b/tests/ui/crate_level_checks/entrypoint_recursion.rs @@ -1,4 +1,4 @@ -//@ignore-target-apple +//@ignore-target: apple #![feature(rustc_attrs)] diff --git a/tests/ui/crate_level_checks/no_std_main_recursion.rs b/tests/ui/crate_level_checks/no_std_main_recursion.rs index 32eba9695920c..9e5b2a4890348 100644 --- a/tests/ui/crate_level_checks/no_std_main_recursion.rs +++ b/tests/ui/crate_level_checks/no_std_main_recursion.rs @@ -1,5 +1,5 @@ //@compile-flags: -Clink-arg=-nostartfiles -//@ignore-target-apple +//@ignore-target: apple #![feature(lang_items, start, libc)] #![no_std] diff --git a/tests/ui/def_id_nocore.rs b/tests/ui/def_id_nocore.rs index 190d636ebf34a..c9650312db878 100644 --- a/tests/ui/def_id_nocore.rs +++ b/tests/ui/def_id_nocore.rs @@ -1,4 +1,4 @@ -//@ignore-target-apple +//@ignore-target: apple #![feature(no_core, lang_items, start)] #![no_core] diff --git a/tests/ui/empty_loop_no_std.rs b/tests/ui/empty_loop_no_std.rs index 5fe32351ed450..1bb895bda75d7 100644 --- a/tests/ui/empty_loop_no_std.rs +++ b/tests/ui/empty_loop_no_std.rs @@ -1,5 +1,5 @@ //@compile-flags: -Clink-arg=-nostartfiles -//@ignore-target-apple +//@ignore-target: apple #![warn(clippy::empty_loop)] #![feature(lang_items, start, libc)] diff --git a/tests/ui/enum_clike_unportable_variant.rs b/tests/ui/enum_clike_unportable_variant.rs index c50404c5047bb..37849179d6a0b 100644 --- a/tests/ui/enum_clike_unportable_variant.rs +++ b/tests/ui/enum_clike_unportable_variant.rs @@ -1,4 +1,4 @@ -//@ignore-32bit +//@ignore-bitwidth: 32 #![warn(clippy::enum_clike_unportable_variant)] #![allow(unused, non_upper_case_globals)] diff --git a/tests/ui/macro_use_imports.fixed b/tests/ui/macro_use_imports.fixed index 38ed5a957e73e..28844fab74793 100644 --- a/tests/ui/macro_use_imports.fixed +++ b/tests/ui/macro_use_imports.fixed @@ -2,7 +2,7 @@ //@aux-build:macro_use_helper.rs //@aux-build:proc_macro_derive.rs -//@ignore-32bit +//@ignore-bitwidth: 32 #![allow(unused_imports, unreachable_code, unused_variables, dead_code, unused_attributes)] #![allow(clippy::single_component_path_imports)] diff --git a/tests/ui/macro_use_imports.rs b/tests/ui/macro_use_imports.rs index ae6cc16ed2769..5381f29598987 100644 --- a/tests/ui/macro_use_imports.rs +++ b/tests/ui/macro_use_imports.rs @@ -2,7 +2,7 @@ //@aux-build:macro_use_helper.rs //@aux-build:proc_macro_derive.rs -//@ignore-32bit +//@ignore-bitwidth: 32 #![allow(unused_imports, unreachable_code, unused_variables, dead_code, unused_attributes)] #![allow(clippy::single_component_path_imports)] diff --git a/tests/ui/macro_use_imports_expect.rs b/tests/ui/macro_use_imports_expect.rs index df6d5b9fbabf2..60cce1d24a289 100644 --- a/tests/ui/macro_use_imports_expect.rs +++ b/tests/ui/macro_use_imports_expect.rs @@ -1,7 +1,7 @@ //@aux-build:macro_rules.rs //@aux-build:macro_use_helper.rs //@aux-build:proc_macro_derive.rs -//@ignore-32bit +//@ignore-bitwidth: 32 #![allow(unused_imports, unreachable_code, unused_variables, dead_code, unused_attributes)] #![allow(clippy::single_component_path_imports)] diff --git a/tests/ui/mixed_attributes_style.rs b/tests/ui/mixed_attributes_style.rs index 1a646c2652236..93ab9392cf8bd 100644 --- a/tests/ui/mixed_attributes_style.rs +++ b/tests/ui/mixed_attributes_style.rs @@ -82,7 +82,8 @@ mod issue_12530 { #![allow(dead_code)] } } - /// Nested mod //~ ERROR: item has both inner and outer attributes + /// Nested mod + //~^ ERROR: item has both inner and outer attributes #[allow(unused)] mod nest_mod_2 { #![allow(unused)] diff --git a/tests/ui/mixed_attributes_style.stderr b/tests/ui/mixed_attributes_style.stderr index a1d3fc430f6cf..abdc2df23cf12 100644 --- a/tests/ui/mixed_attributes_style.stderr +++ b/tests/ui/mixed_attributes_style.stderr @@ -46,13 +46,14 @@ error: item has both inner and outer attributes --> tests/ui/mixed_attributes_style.rs:85:5 | LL | / /// Nested mod +LL | | LL | | #[allow(unused)] LL | | mod nest_mod_2 { LL | | #![allow(unused)] | |_________________________^ error: item has both inner and outer attributes - --> tests/ui/mixed_attributes_style.rs:90:9 + --> tests/ui/mixed_attributes_style.rs:91:9 | LL | / #[allow(dead_code)] LL | | mod inner_mod { diff --git a/tests/ui/non_octal_unix_permissions.fixed b/tests/ui/non_octal_unix_permissions.fixed index 237f5f5b97a4f..f68d5e30d27e7 100644 --- a/tests/ui/non_octal_unix_permissions.fixed +++ b/tests/ui/non_octal_unix_permissions.fixed @@ -1,4 +1,4 @@ -//@ignore-target-windows +//@ignore-target: windows #![warn(clippy::non_octal_unix_permissions)] use std::fs::{DirBuilder, File, OpenOptions, Permissions}; diff --git a/tests/ui/non_octal_unix_permissions.rs b/tests/ui/non_octal_unix_permissions.rs index c8da5dbcec282..647c3769d2c3f 100644 --- a/tests/ui/non_octal_unix_permissions.rs +++ b/tests/ui/non_octal_unix_permissions.rs @@ -1,4 +1,4 @@ -//@ignore-target-windows +//@ignore-target: windows #![warn(clippy::non_octal_unix_permissions)] use std::fs::{DirBuilder, File, OpenOptions, Permissions}; diff --git a/tests/ui/result_large_err.rs b/tests/ui/result_large_err.rs index b25348bf99617..9c39f023da2da 100644 --- a/tests/ui/result_large_err.rs +++ b/tests/ui/result_large_err.rs @@ -1,4 +1,4 @@ -//@ignore-32bit +//@ignore-bitwidth: 32 #![warn(clippy::result_large_err)] #![allow(clippy::large_enum_variant)] diff --git a/tests/ui/single_call_fn.rs b/tests/ui/single_call_fn.rs index 55e7508a9573a..a0597664da55c 100644 --- a/tests/ui/single_call_fn.rs +++ b/tests/ui/single_call_fn.rs @@ -1,4 +1,4 @@ -//@ignore-32bit +//@ignore-bitwidth: 32 //@aux-build:proc_macros.rs #![allow(clippy::redundant_closure_call, unused)] #![warn(clippy::single_call_fn)] diff --git a/tests/ui/transmute_32bit.rs b/tests/ui/transmute_32bit.rs index 8e1316ca39d4f..e162bbb2d9296 100644 --- a/tests/ui/transmute_32bit.rs +++ b/tests/ui/transmute_32bit.rs @@ -1,4 +1,4 @@ -//@ignore-64bit +//@ignore-bitwidth: 64 #[warn(clippy::wrong_transmute)] fn main() { diff --git a/tests/ui/transmute_64bit.rs b/tests/ui/transmute_64bit.rs index 767cc503a39df..fd0ad74bcfa0a 100644 --- a/tests/ui/transmute_64bit.rs +++ b/tests/ui/transmute_64bit.rs @@ -1,4 +1,4 @@ -//@ignore-32bit +//@ignore-bitwidth: 32 #[warn(clippy::wrong_transmute)] fn main() { From 129acd2e08cbe614be11acb7a4f1f5169dba3a23 Mon Sep 17 00:00:00 2001 From: roife Date: Mon, 9 Sep 2024 23:14:31 +0800 Subject: [PATCH 0745/2194] feat: use shorthand when pretty-print record pat --- .../crates/hir-def/src/body/pretty.rs | 33 ++++++++++-- .../crates/ide/src/hover/tests.rs | 52 ++++++++++++++++++- 2 files changed, 79 insertions(+), 6 deletions(-) diff --git a/src/tools/rust-analyzer/crates/hir-def/src/body/pretty.rs b/src/tools/rust-analyzer/crates/hir-def/src/body/pretty.rs index 64d0c16f525f7..37167fcb8155b 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/body/pretty.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/body/pretty.rs @@ -616,12 +616,37 @@ impl Printer<'_> { w!(self, " {{"); let edition = self.edition; + let oneline = matches!(self.line_format, LineFormat::Oneline); self.indented(|p| { - for arg in args.iter() { - w!(p, "{}: ", arg.name.display(self.db.upcast(), edition)); - p.print_pat(arg.pat); - wln!(p, ","); + for (idx, arg) in args.iter().enumerate() { + let field_name = arg.name.display(self.db.upcast(), edition).to_string(); + + let mut same_name = false; + if let Pat::Bind { id, subpat: None } = &self.body[arg.pat] { + if let Binding { name, mode: BindingAnnotation::Unannotated, .. } = + &self.body.bindings[*id] + { + if name.as_str() == field_name { + same_name = true; + } + } + } + + w!(p, "{}", field_name); + + if !same_name { + w!(p, ": "); + p.print_pat(arg.pat); + } + + // Do not print the extra comma if the line format is oneline + if oneline && idx == args.len() - 1 { + w!(p, " "); + } else { + wln!(p, ","); + } } + if *ellipsis { wln!(p, ".."); } diff --git a/src/tools/rust-analyzer/crates/ide/src/hover/tests.rs b/src/tools/rust-analyzer/crates/ide/src/hover/tests.rs index 1a97d99f05129..f2e5d24fcc682 100644 --- a/src/tools/rust-analyzer/crates/ide/src/hover/tests.rs +++ b/src/tools/rust-analyzer/crates/ide/src/hover/tests.rs @@ -8803,7 +8803,7 @@ fn test_hover_function_with_pat_param() { ``` ```rust - fn test_4(Point { x: x, y: y, }: Point) + fn test_4(Point { x, y }: Point) ``` "#]], ); @@ -8851,7 +8851,7 @@ fn test_hover_function_with_pat_param() { ``` ```rust - fn test_7((x, Foo { a: a, b: b, }): (i32, Foo)) + fn test_7((x, Foo { a, b }): (i32, Foo)) ``` "#]], ); @@ -8871,4 +8871,52 @@ fn test_hover_function_with_pat_param() { ``` "#]], ); + + // Test case with a pattern as a function parameter + check( + r#"struct Foo { a: i32, b: i32 } fn test_9$0(Foo { a, b }: Foo) {}"#, + expect![[r#" + *test_9* + + ```rust + test + ``` + + ```rust + fn test_9(Foo { a, b }: Foo) + ``` + "#]], + ); + + // Test case with a pattern as a function parameter with a different name + check( + r#"struct Foo { a: i32, b: i32 } fn test_10$0(Foo { a, b: b1 }: Foo) {}"#, + expect![[r#" + *test_10* + + ```rust + test + ``` + + ```rust + fn test_10(Foo { a, b: b1 }: Foo) + ``` + "#]], + ); + + // Test case with a pattern as a function parameter with annotations + check( + r#"struct Foo { a: i32, b: i32 } fn test_10$0(Foo { a, b: mut b }: Foo) {}"#, + expect![[r#" + *test_10* + + ```rust + test + ``` + + ```rust + fn test_10(Foo { a, b: mut b }: Foo) + ``` + "#]], + ); } From 91b2c17ffb0f0e34e586fabff47d915c5caeed95 Mon Sep 17 00:00:00 2001 From: cui fliter Date: Mon, 9 Sep 2024 23:23:15 +0800 Subject: [PATCH 0746/2194] Add missing backtick in comment (#6317) Signed-off-by: cuishuang --- src/config/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/config/mod.rs b/src/config/mod.rs index d35a249a80a31..80515077abd59 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -448,7 +448,7 @@ pub fn load_config( }) } -// Check for the presence of known config file names (`rustfmt.toml, `.rustfmt.toml`) in `dir` +// Check for the presence of known config file names (`rustfmt.toml`, `.rustfmt.toml`) in `dir` // // Return the path if a config file exists, empty if no file exists, and Error for IO errors fn get_toml_path(dir: &Path) -> Result, Error> { From 19b8f9e17cf86cf83bd1fc742cf159605d0504dd Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Mon, 9 Sep 2024 18:47:38 +0300 Subject: [PATCH 0747/2194] use verbose flag as a default value for `rust.verbose-tests` Signed-off-by: onur-ozkan --- src/bootstrap/src/core/config/config.rs | 3 +++ src/bootstrap/src/core/config/tests.rs | 9 +++++++++ 2 files changed, 12 insertions(+) diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs index 68b42305fdcc8..de861c42c4c4e 100644 --- a/src/bootstrap/src/core/config/config.rs +++ b/src/bootstrap/src/core/config/config.rs @@ -1600,6 +1600,9 @@ impl Config { config.verbose = cmp::max(config.verbose, flags.verbose as usize); + // Verbose flag is a good default for `rust.verbose-tests`. + config.verbose_tests = config.is_verbose(); + if let Some(install) = toml.install { let Install { prefix, sysconfdir, docdir, bindir, libdir, mandir, datadir } = install; config.prefix = prefix.map(PathBuf::from); diff --git a/src/bootstrap/src/core/config/tests.rs b/src/bootstrap/src/core/config/tests.rs index 219c5a6ec914e..f54a5d3b5125d 100644 --- a/src/bootstrap/src/core/config/tests.rs +++ b/src/bootstrap/src/core/config/tests.rs @@ -317,3 +317,12 @@ fn order_of_clippy_rules() { assert_eq!(expected, actual); } + +#[test] +fn verbose_tests_default_value() { + let config = Config::parse(Flags::parse(&["build".into(), "compiler".into()])); + assert_eq!(config.verbose_tests, false); + + let config = Config::parse(Flags::parse(&["build".into(), "compiler".into(), "-v".into()])); + assert_eq!(config.verbose_tests, true); +} From bc70fa2f223181dc6bf20c1da8f986a46dac3ae5 Mon Sep 17 00:00:00 2001 From: okaneco <47607823+okaneco@users.noreply.github.com> Date: Mon, 9 Sep 2024 11:46:44 -0400 Subject: [PATCH 0748/2194] Stabilize `char::MIN` --- library/core/src/char/methods.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/library/core/src/char/methods.rs b/library/core/src/char/methods.rs index 41a19665779b6..113a2d6a2b171 100644 --- a/library/core/src/char/methods.rs +++ b/library/core/src/char/methods.rs @@ -15,7 +15,6 @@ impl char { /// for you: /// /// ``` - /// #![feature(char_min)] /// let dist = u32::from(char::MAX) - u32::from(char::MIN); /// let size = (char::MIN..=char::MAX).count() as u32; /// assert!(size < dist); @@ -29,7 +28,6 @@ impl char { /// # Examples /// /// ``` - /// #![feature(char_min)] /// # fn something_which_returns_char() -> char { 'a' } /// let c: char = something_which_returns_char(); /// assert!(char::MIN <= c); @@ -37,7 +35,7 @@ impl char { /// let value_at_min = u32::from(char::MIN); /// assert_eq!(char::from_u32(value_at_min), Some('\0')); /// ``` - #[unstable(feature = "char_min", issue = "114298")] + #[stable(feature = "char_min", since = "CURRENT_RUSTC_VERSION")] pub const MIN: char = '\0'; /// The highest valid code point a `char` can have, `'\u{10FFFF}'`. @@ -48,7 +46,6 @@ impl char { /// for you: /// /// ``` - /// #![feature(char_min)] /// let dist = u32::from(char::MAX) - u32::from(char::MIN); /// let size = (char::MIN..=char::MAX).count() as u32; /// assert!(size < dist); From 13ea104798dfdb31613963d49be43e615c6f6dfe Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Mon, 9 Sep 2024 18:56:37 +0300 Subject: [PATCH 0749/2194] update `rust.verbose-tests` doc in `config.example.toml` Signed-off-by: onur-ozkan --- config.example.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config.example.toml b/config.example.toml index e9433c9c9bd08..17fe9be7d567f 100644 --- a/config.example.toml +++ b/config.example.toml @@ -641,7 +641,7 @@ #stack-protector = "none" # Prints each test name as it is executed, to help debug issues in the test harness itself. -#verbose-tests = false +#verbose-tests = if is_verbose { true } else { false } # Flag indicating whether tests are compiled with optimizations (the -O flag). #optimize-tests = true From 182a20378b3a844e3677ff93d96f8ac70b9f009a Mon Sep 17 00:00:00 2001 From: Trivikram Kamat <16024985+trivikr@users.noreply.github.com> Date: Mon, 9 Sep 2024 06:51:19 -0700 Subject: [PATCH 0750/2194] ci: bump actions/checkout to v4 --- .github/workflows/check_diff.yml | 2 +- .github/workflows/integration.yml | 2 +- .github/workflows/linux.yml | 2 +- .github/workflows/mac.yml | 2 +- .github/workflows/rustdoc_check.yml | 2 +- .github/workflows/upload-assets.yml | 2 +- .github/workflows/windows.yml | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/check_diff.yml b/.github/workflows/check_diff.yml index 2f2beb7691595..99daa0addf571 100644 --- a/.github/workflows/check_diff.yml +++ b/.github/workflows/check_diff.yml @@ -21,7 +21,7 @@ jobs: steps: - name: checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: install rustup run: | diff --git a/.github/workflows/integration.yml b/.github/workflows/integration.yml index f0dd0cf73bbd4..bda374562bc1b 100644 --- a/.github/workflows/integration.yml +++ b/.github/workflows/integration.yml @@ -64,7 +64,7 @@ jobs: steps: - name: checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 # Run build - name: install rustup diff --git a/.github/workflows/linux.yml b/.github/workflows/linux.yml index bce9b0c8d5a95..3a5e6ab54047b 100644 --- a/.github/workflows/linux.yml +++ b/.github/workflows/linux.yml @@ -26,7 +26,7 @@ jobs: steps: - name: checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 # Run build - name: install rustup diff --git a/.github/workflows/mac.yml b/.github/workflows/mac.yml index f98c9830a4d22..2c766d0573b96 100644 --- a/.github/workflows/mac.yml +++ b/.github/workflows/mac.yml @@ -22,7 +22,7 @@ jobs: steps: - name: checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 # Run build - name: install rustup diff --git a/.github/workflows/rustdoc_check.yml b/.github/workflows/rustdoc_check.yml index cd0c3218971e2..6e8a7ecd7ad81 100644 --- a/.github/workflows/rustdoc_check.yml +++ b/.github/workflows/rustdoc_check.yml @@ -11,7 +11,7 @@ jobs: name: rustdoc check steps: - name: checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: install rustup run: | diff --git a/.github/workflows/upload-assets.yml b/.github/workflows/upload-assets.yml index 7dfaa4b9204c2..7a639b469e849 100644 --- a/.github/workflows/upload-assets.yml +++ b/.github/workflows/upload-assets.yml @@ -31,7 +31,7 @@ jobs: target: x86_64-pc-windows-msvc runs-on: ${{ matrix.os }} steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 # Run build - name: install rustup diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml index ec37c714b0851..728f1b90b13f5 100644 --- a/.github/workflows/windows.yml +++ b/.github/workflows/windows.yml @@ -33,7 +33,7 @@ jobs: - name: disable git eol translation run: git config --global core.autocrlf false - name: checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 # Run build - name: Install Rustup using win.rustup.rs From 32d9597200ab93cd64dee1751991a994372bad45 Mon Sep 17 00:00:00 2001 From: roife Date: Tue, 3 Sep 2024 23:07:41 +0800 Subject: [PATCH 0751/2194] refactor: introduce NameGenerator in suggest_name --- .../src/handlers/generate_delegate_trait.rs | 35 ++- .../src/handlers/introduce_named_generic.rs | 21 +- .../ide-completion/src/completions/pattern.rs | 3 +- .../ide-db/src/syntax_helpers/suggest_name.rs | 212 +++++++++++++----- .../rust-analyzer/crates/syntax/src/lib.rs | 2 +- 5 files changed, 192 insertions(+), 81 deletions(-) diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_delegate_trait.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_delegate_trait.rs index c22d19574fb49..a55323eb59d8d 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_delegate_trait.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_delegate_trait.rs @@ -584,7 +584,7 @@ fn resolve_name_conflicts( for old_strukt_param in old_strukt_params.generic_params() { // Get old name from `strukt` - let mut name = SmolStr::from(match &old_strukt_param { + let name = SmolStr::from(match &old_strukt_param { ast::GenericParam::ConstParam(c) => c.name()?.to_string(), ast::GenericParam::LifetimeParam(l) => { l.lifetime()?.lifetime_ident_token()?.to_string() @@ -593,8 +593,19 @@ fn resolve_name_conflicts( }); // The new name cannot be conflicted with generics in trait, and the renamed names. - name = suggest_name::for_unique_generic_name(&name, old_impl_params); - name = suggest_name::for_unique_generic_name(&name, ¶ms); + let param_list_to_names = |param_list: &GenericParamList| { + param_list.generic_params().flat_map(|param| match param { + ast::GenericParam::TypeParam(t) => t.name().map(|name| name.to_string()), + p => Some(p.to_string()), + }) + }; + let existing_names = param_list_to_names(old_impl_params) + .chain(param_list_to_names(¶ms)) + .collect_vec(); + let mut name_generator = suggest_name::NameGenerator::new_with_names( + existing_names.iter().map(|s| s.as_str()), + ); + let name = name_generator.suggest_name(&name); match old_strukt_param { ast::GenericParam::ConstParam(c) => { if let Some(const_ty) = c.ty() { @@ -1213,9 +1224,9 @@ struct S { b : B, } -impl Trait for S { - fn f(&self, a: T0) -> T0 { - as Trait>::f(&self.b, a) +impl Trait for S { + fn f(&self, a: T1) -> T1 { + as Trait>::f(&self.b, a) } } "#, @@ -1527,12 +1538,12 @@ where b : B, } -impl Trait for S +impl Trait for S where - T10: AnotherTrait + T3: AnotherTrait { fn f(&self, a: T) -> T { - as Trait>::f(&self.b, a) + as Trait>::f(&self.b, a) } }"#, ); @@ -1589,12 +1600,12 @@ where b : B, } -impl Trait for S +impl Trait for S where - T0: AnotherTrait + T2: AnotherTrait { fn f(&self, a: T) -> T { - as Trait>::f(&self.b, a) + as Trait>::f(&self.b, a) } }"#, ); diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/introduce_named_generic.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/introduce_named_generic.rs index a734a6cc2bc88..bf6ac1719f318 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/introduce_named_generic.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/introduce_named_generic.rs @@ -1,6 +1,7 @@ use ide_db::syntax_helpers::suggest_name; +use itertools::Itertools; use syntax::{ - ast::{self, edit_in_place::GenericParamsOwnerEdit, make, AstNode, HasGenericParams}, + ast::{self, edit_in_place::GenericParamsOwnerEdit, make, AstNode, HasGenericParams, HasName}, ted, }; @@ -33,8 +34,18 @@ pub(crate) fn introduce_named_generic(acc: &mut Assists, ctx: &AssistContext<'_> let impl_trait_type = edit.make_mut(impl_trait_type); let fn_ = edit.make_mut(fn_); let fn_generic_param_list = fn_.get_or_create_generic_param_list(); - let type_param_name = - suggest_name::for_impl_trait_as_generic(&impl_trait_type, &fn_generic_param_list); + + let existing_names = fn_generic_param_list + .generic_params() + .flat_map(|param| match param { + ast::GenericParam::TypeParam(t) => t.name().map(|name| name.to_string()), + p => Some(p.to_string()), + }) + .collect_vec(); + let type_param_name = suggest_name::NameGenerator::new_with_names( + existing_names.iter().map(|s| s.as_str()), + ) + .for_impl_trait_as_generic(&impl_trait_type); let type_param = make::type_param(make::name(&type_param_name), Some(type_bound_list)) .clone_for_update(); @@ -116,7 +127,7 @@ fn foo<$0B: Bar check_assist( introduce_named_generic, r#"fn foo(bar: $0impl Bar) {}"#, - r#"fn foo(bar: B0) {}"#, + r#"fn foo(bar: B1) {}"#, ); } @@ -125,7 +136,7 @@ fn foo<$0B: Bar check_assist( introduce_named_generic, r#"fn foo(bar: $0impl Bar) {}"#, - r#"fn foo(bar: B2) {}"#, + r#"fn foo(bar: B4) {}"#, ); } diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/pattern.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/pattern.rs index 2a06fc4017557..8f38e02ed7685 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/pattern.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/pattern.rs @@ -48,11 +48,12 @@ pub(crate) fn complete_pattern( // Suggest name only in let-stmt and fn param if pattern_ctx.should_suggest_name { + let mut name_generator = suggest_name::NameGenerator::new(); if let Some(suggested) = ctx .expected_type .as_ref() .map(|ty| ty.strip_references()) - .and_then(|ty| suggest_name::for_type(&ty, ctx.db, ctx.edition)) + .and_then(|ty| name_generator.for_type(&ty, ctx.db, ctx.edition)) { acc.suggest_name(ctx, &suggested); } diff --git a/src/tools/rust-analyzer/crates/ide-db/src/syntax_helpers/suggest_name.rs b/src/tools/rust-analyzer/crates/ide-db/src/syntax_helpers/suggest_name.rs index e60deb3bf59b1..2679cbef61b3b 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/syntax_helpers/suggest_name.rs +++ b/src/tools/rust-analyzer/crates/ide-db/src/syntax_helpers/suggest_name.rs @@ -1,12 +1,14 @@ //! This module contains functions to suggest names for expressions, functions and other items +use std::{collections::hash_map::Entry, str::FromStr}; + use hir::Semantics; use itertools::Itertools; -use rustc_hash::FxHashSet; +use rustc_hash::FxHashMap; use stdx::to_lower_snake_case; use syntax::{ ast::{self, HasName}, - match_ast, AstNode, Edition, SmolStr, + match_ast, AstNode, Edition, SmolStr, SmolStrBuilder, }; use crate::RootDatabase; @@ -62,71 +64,131 @@ const USELESS_METHODS: &[&str] = &[ "into_future", ]; -/// Suggest a name for given type. +/// Generator for new names /// -/// The function will strip references first, and suggest name from the inner type. +/// The generator keeps track of existing names and suggests new names that do +/// not conflict with existing names. /// -/// - If `ty` is an ADT, it will suggest the name of the ADT. -/// + If `ty` is wrapped in `Box`, `Option` or `Result`, it will suggest the name from the inner type. -/// - If `ty` is a trait, it will suggest the name of the trait. -/// - If `ty` is an `impl Trait`, it will suggest the name of the first trait. +/// The generator will try to resolve conflicts by adding a numeric suffix to +/// the name, e.g. `a`, `a1`, `a2`, ... /// -/// If the suggested name conflicts with reserved keywords, it will return `None`. -pub fn for_type(ty: &hir::Type, db: &RootDatabase, edition: Edition) -> Option { - let ty = ty.strip_references(); - name_of_type(&ty, db, edition) -} - -/// Suggest a unique name for generic parameter. -/// -/// `existing_params` is used to check if the name conflicts with existing -/// generic parameters. +/// # Examples +/// ```rust +/// let mut generator = NameGenerator::new(); +/// assert_eq!(generator.suggest_name("a"), "a"); +/// assert_eq!(generator.suggest_name("a"), "a1"); /// -/// The function checks if the name conflicts with existing generic parameters. -/// If so, it will try to resolve the conflict by adding a number suffix, e.g. -/// `T`, `T0`, `T1`, ... -pub fn for_unique_generic_name(name: &str, existing_params: &ast::GenericParamList) -> SmolStr { - let param_names = existing_params - .generic_params() - .map(|param| match param { - ast::GenericParam::TypeParam(t) => t.name().unwrap().to_string(), - p => p.to_string(), - }) - .collect::>(); - let mut name = name.to_owned(); - let base_len = name.len(); - let mut count = 0; - while param_names.contains(&name) { - name.truncate(base_len); - name.push_str(&count.to_string()); - count += 1; - } - - name.into() +/// assert_eq!(generator.suggest_name("b2"), "b2"); +/// assert_eq!(generator.suggest_name("b"), "b3"); +/// ``` +#[derive(Debug, Default)] +pub struct NameGenerator { + pool: FxHashMap, } -/// Suggest name of impl trait type -/// -/// `existing_params` is used to check if the name conflicts with existing -/// generic parameters. -/// -/// # Current implementation -/// -/// In current implementation, the function tries to get the name from the first -/// character of the name for the first type bound. -/// -/// If the name conflicts with existing generic parameters, it will try to -/// resolve the conflict with `for_unique_generic_name`. -pub fn for_impl_trait_as_generic( - ty: &ast::ImplTraitType, - existing_params: &ast::GenericParamList, -) -> SmolStr { - let c = ty - .type_bound_list() - .and_then(|bounds| bounds.syntax().text().char_at(0.into())) - .unwrap_or('T'); - - for_unique_generic_name(c.encode_utf8(&mut [0; 4]), existing_params) +impl NameGenerator { + /// Create a new empty generator + pub fn new() -> Self { + Self { pool: FxHashMap::default() } + } + + /// Create a new generator with existing names. When suggesting a name, it will + /// avoid conflicts with existing names. + pub fn new_with_names<'a>(existing_names: impl Iterator) -> Self { + let mut generator = Self::new(); + existing_names.for_each(|name| generator.insert(name)); + generator + } + + /// Suggest a name without conflicts. If the name conflicts with existing names, + /// it will try to resolve the conflict by adding a numeric suffix. + pub fn suggest_name(&mut self, name: &str) -> SmolStr { + let (prefix, suffix) = Self::split_numeric_suffix(name); + let prefix = SmolStr::new(prefix); + let suffix = suffix.unwrap_or(0); + + match self.pool.entry(prefix.clone()) { + Entry::Vacant(entry) => { + entry.insert(suffix); + SmolStr::from_str(name).unwrap() + } + Entry::Occupied(mut entry) => { + let count = entry.get_mut(); + *count = (*count + 1).max(suffix); + + let mut new_name = SmolStrBuilder::new(); + new_name.push_str(&prefix); + new_name.push_str(count.to_string().as_str()); + new_name.finish() + } + } + } + + /// Suggest a name for given type. + /// + /// The function will strip references first, and suggest name from the inner type. + /// + /// - If `ty` is an ADT, it will suggest the name of the ADT. + /// + If `ty` is wrapped in `Box`, `Option` or `Result`, it will suggest the name from the inner type. + /// - If `ty` is a trait, it will suggest the name of the trait. + /// - If `ty` is an `impl Trait`, it will suggest the name of the first trait. + /// + /// If the suggested name conflicts with reserved keywords, it will return `None`. + pub fn for_type( + &mut self, + ty: &hir::Type, + db: &RootDatabase, + edition: Edition, + ) -> Option { + let name = name_of_type(ty, db, edition)?; + Some(self.suggest_name(&name)) + } + + /// Suggest name of impl trait type + /// + /// # Current implementation + /// + /// In current implementation, the function tries to get the name from the first + /// character of the name for the first type bound. + /// + /// If the name conflicts with existing generic parameters, it will try to + /// resolve the conflict with `for_unique_generic_name`. + pub fn for_impl_trait_as_generic(&mut self, ty: &ast::ImplTraitType) -> SmolStr { + let c = ty + .type_bound_list() + .and_then(|bounds| bounds.syntax().text().char_at(0.into())) + .unwrap_or('T'); + + self.suggest_name(&c.to_string()) + } + + /// Insert a name into the pool + fn insert(&mut self, name: &str) { + let (prefix, suffix) = Self::split_numeric_suffix(name); + let prefix = SmolStr::new(prefix); + let suffix = suffix.unwrap_or(0); + + match self.pool.entry(prefix) { + Entry::Vacant(entry) => { + entry.insert(suffix); + } + Entry::Occupied(mut entry) => { + let count = entry.get_mut(); + *count = (*count).max(suffix); + } + } + } + + /// Remove the numeric suffix from the name + /// + /// # Examples + /// `a1b2c3` -> `a1b2c` + fn split_numeric_suffix(name: &str) -> (&str, Option) { + let pos = + name.rfind(|c: char| !c.is_numeric()).expect("Name cannot be empty or all-numeric"); + let (prefix, suffix) = name.split_at(pos + 1); + (prefix, suffix.parse().ok()) + } } /// Suggest name of variable for given expression @@ -290,9 +352,10 @@ fn var_name_from_pat(pat: &ast::Pat) -> Option { fn from_type(expr: &ast::Expr, sema: &Semantics<'_, RootDatabase>) -> Option { let ty = sema.type_of_expr(expr)?.adjusted(); + let ty = ty.remove_ref().unwrap_or(ty); let edition = sema.scope(expr.syntax())?.krate().edition(sema.db); - for_type(&ty, sema.db, edition) + name_of_type(&ty, sema.db, edition) } fn name_of_type(ty: &hir::Type, db: &RootDatabase, edition: Edition) -> Option { @@ -925,4 +988,29 @@ fn main() { "bar", ); } + + #[test] + fn conflicts_with_existing_names() { + let mut generator = NameGenerator::new(); + assert_eq!(generator.suggest_name("a"), "a"); + assert_eq!(generator.suggest_name("a"), "a1"); + assert_eq!(generator.suggest_name("a"), "a2"); + assert_eq!(generator.suggest_name("a"), "a3"); + + assert_eq!(generator.suggest_name("b"), "b"); + assert_eq!(generator.suggest_name("b2"), "b2"); + assert_eq!(generator.suggest_name("b"), "b3"); + assert_eq!(generator.suggest_name("b"), "b4"); + assert_eq!(generator.suggest_name("b3"), "b5"); + + // --------- + let mut generator = NameGenerator::new_with_names(["a", "b", "b2", "c4"].into_iter()); + assert_eq!(generator.suggest_name("a"), "a1"); + assert_eq!(generator.suggest_name("a"), "a2"); + + assert_eq!(generator.suggest_name("b"), "b3"); + assert_eq!(generator.suggest_name("b2"), "b4"); + + assert_eq!(generator.suggest_name("c"), "c5"); + } } diff --git a/src/tools/rust-analyzer/crates/syntax/src/lib.rs b/src/tools/rust-analyzer/crates/syntax/src/lib.rs index b68374848b90c..7fb80b2e7d81d 100644 --- a/src/tools/rust-analyzer/crates/syntax/src/lib.rs +++ b/src/tools/rust-analyzer/crates/syntax/src/lib.rs @@ -65,7 +65,7 @@ pub use rowan::{ TokenAtOffset, WalkEvent, }; pub use rustc_lexer::unescape; -pub use smol_str::{format_smolstr, SmolStr, ToSmolStr}; +pub use smol_str::{format_smolstr, SmolStr, SmolStrBuilder, ToSmolStr}; /// `Parse` is the result of the parsing: a syntax tree and a collection of /// errors. From b304701b670e45d4d1a43691f0b3083423d41e31 Mon Sep 17 00:00:00 2001 From: roife Date: Wed, 4 Sep 2024 01:38:34 +0800 Subject: [PATCH 0752/2194] feat: generate names for tuple-struct in add-missing-match-arms --- .../src/handlers/add_missing_match_arms.rs | 130 ++++++++++++++---- 1 file changed, 106 insertions(+), 24 deletions(-) diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_missing_match_arms.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_missing_match_arms.rs index b6abb06a2afc1..a211ca8f2d675 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_missing_match_arms.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_missing_match_arms.rs @@ -1,12 +1,13 @@ use std::iter::{self, Peekable}; use either::Either; -use hir::{sym, Adt, Crate, HasAttrs, HasSource, ImportPathConfig, ModuleDef, Semantics}; +use hir::{sym, Adt, Crate, HasAttrs, ImportPathConfig, ModuleDef, Semantics}; +use ide_db::syntax_helpers::suggest_name; use ide_db::RootDatabase; use ide_db::{famous_defs::FamousDefs, helpers::mod_path_to_ast}; use itertools::Itertools; use syntax::ast::edit_in_place::Removable; -use syntax::ast::{self, make, AstNode, HasName, MatchArmList, MatchExpr, Pat}; +use syntax::ast::{self, make, AstNode, MatchArmList, MatchExpr, Pat}; use crate::{utils, AssistContext, AssistId, AssistKind, Assists}; @@ -90,7 +91,7 @@ pub(crate) fn add_missing_match_arms(acc: &mut Assists, ctx: &AssistContext<'_>) .into_iter() .filter_map(|variant| { Some(( - build_pat(ctx.db(), module, variant, cfg)?, + build_pat(ctx, module, variant, cfg)?, variant.should_be_hidden(ctx.db(), module.krate()), )) }) @@ -141,9 +142,8 @@ pub(crate) fn add_missing_match_arms(acc: &mut Assists, ctx: &AssistContext<'_>) let is_hidden = variants .iter() .any(|variant| variant.should_be_hidden(ctx.db(), module.krate())); - let patterns = variants - .into_iter() - .filter_map(|variant| build_pat(ctx.db(), module, variant, cfg)); + let patterns = + variants.into_iter().filter_map(|variant| build_pat(ctx, module, variant, cfg)); (ast::Pat::from(make::tuple_pat(patterns)), is_hidden) }) @@ -174,9 +174,8 @@ pub(crate) fn add_missing_match_arms(acc: &mut Assists, ctx: &AssistContext<'_>) let is_hidden = variants .iter() .any(|variant| variant.should_be_hidden(ctx.db(), module.krate())); - let patterns = variants - .into_iter() - .filter_map(|variant| build_pat(ctx.db(), module, variant, cfg)); + let patterns = + variants.into_iter().filter_map(|variant| build_pat(ctx, module, variant, cfg)); (ast::Pat::from(make::slice_pat(patterns)), is_hidden) }) .filter(|(variant_pat, _)| is_variant_missing(&top_lvl_pats, variant_pat)); @@ -438,33 +437,39 @@ fn resolve_array_of_enum_def( } fn build_pat( - db: &RootDatabase, + ctx: &AssistContext<'_>, module: hir::Module, var: ExtendedVariant, cfg: ImportPathConfig, ) -> Option { + let db = ctx.db(); match var { ExtendedVariant::Variant(var) => { let edition = module.krate().edition(db); let path = mod_path_to_ast(&module.find_path(db, ModuleDef::from(var), cfg)?, edition); - // FIXME: use HIR for this; it doesn't currently expose struct vs. tuple vs. unit variants though - Some(match var.source(db)?.value.kind() { - ast::StructKind::Tuple(field_list) => { - let pats = - iter::repeat(make::wildcard_pat().into()).take(field_list.fields().count()); + let fields = var.fields(db); + let pat = match var.kind(db) { + hir::StructKind::Tuple => { + let mut name_generator = suggest_name::NameGenerator::new(); + let pats = fields.into_iter().map(|f| { + let name = name_generator.for_type(&f.ty(db), db, edition); + match name { + Some(name) => make::ext::simple_ident_pat(make::name(&name)).into(), + None => make::wildcard_pat().into(), + } + }); make::tuple_struct_pat(path, pats).into() } - ast::StructKind::Record(field_list) => { - let pats = field_list.fields().map(|f| { - make::ext::simple_ident_pat( - f.name().expect("Record field must have a name"), - ) - .into() - }); + hir::StructKind::Record => { + let pats = fields + .into_iter() + .map(|f| make::name(f.name(db).as_str())) + .map(|name| make::ext::simple_ident_pat(name).into()); make::record_pat(path, pats).into() } - ast::StructKind::Unit => make::path_pat(path), - }) + hir::StructKind::Unit => make::path_pat(path), + }; + Some(pat) } ExtendedVariant::True => Some(ast::Pat::from(make::literal_pat("true"))), ExtendedVariant::False => Some(ast::Pat::from(make::literal_pat("false"))), @@ -1976,4 +1981,81 @@ fn a() { }"#, ) } + + #[test] + fn suggest_name_for_tuple_struct_patterns() { + // single tuple struct + check_assist( + add_missing_match_arms, + r#" +struct S; + +pub enum E { + A + B(S), +} + +fn f() { + let value = E::A; + match value { + $0 + } +} +"#, + r#" +struct S; + +pub enum E { + A + B(S), +} + +fn f() { + let value = E::A; + match value { + $0E::A => todo!(), + E::B(s) => todo!(), + } +} +"#, + ); + + // multiple tuple struct patterns + check_assist( + add_missing_match_arms, + r#" +struct S1; +struct S2; + +pub enum E { + A + B(S1, S2), +} + +fn f() { + let value = E::A; + match value { + $0 + } +} +"#, + r#" +struct S1; +struct S2; + +pub enum E { + A + B(S1, S2), +} + +fn f() { + let value = E::A; + match value { + $0E::A => todo!(), + E::B(s1, s2) => todo!(), + } +} +"#, + ); + } } From 8b052eaad15d77e96a95b6ff9e89ebfd20ab1e55 Mon Sep 17 00:00:00 2001 From: rustbot <47979223+rustbot@users.noreply.github.com> Date: Mon, 9 Sep 2024 13:00:45 -0400 Subject: [PATCH 0753/2194] Update books --- src/doc/edition-guide | 2 +- src/doc/embedded-book | 2 +- src/doc/reference | 2 +- src/doc/rust-by-example | 2 +- src/doc/rustc-dev-guide | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/doc/edition-guide b/src/doc/edition-guide index eeba2cb9c37ab..b3ca7ade0f87d 160000 --- a/src/doc/edition-guide +++ b/src/doc/edition-guide @@ -1 +1 @@ -Subproject commit eeba2cb9c37ab74118a4fb5e5233f7397e4a91f8 +Subproject commit b3ca7ade0f87d7e3fb538776defc5b2cc4188172 diff --git a/src/doc/embedded-book b/src/doc/embedded-book index ff5d61d56f11e..dbae36bf3f841 160000 --- a/src/doc/embedded-book +++ b/src/doc/embedded-book @@ -1 +1 @@ -Subproject commit ff5d61d56f11e1986bfa9652c6aff7731576c37d +Subproject commit dbae36bf3f8410aa4313b3bad42e374735d48a9d diff --git a/src/doc/reference b/src/doc/reference index 0668397076da3..687faf9958c52 160000 --- a/src/doc/reference +++ b/src/doc/reference @@ -1 +1 @@ -Subproject commit 0668397076da350c404dadcf07b6cbc433ad3743 +Subproject commit 687faf9958c52116d003b41dfd29cc1cf44f5311 diff --git a/src/doc/rust-by-example b/src/doc/rust-by-example index 859786c5bc993..c79ec345f08a1 160000 --- a/src/doc/rust-by-example +++ b/src/doc/rust-by-example @@ -1 +1 @@ -Subproject commit 859786c5bc99301bbc22fc631a5c2b341860da08 +Subproject commit c79ec345f08a1e94494cdc8c999709a90203fd88 diff --git a/src/doc/rustc-dev-guide b/src/doc/rustc-dev-guide index fa928a6d19e16..0ed9229f5b6f7 160000 --- a/src/doc/rustc-dev-guide +++ b/src/doc/rustc-dev-guide @@ -1 +1 @@ -Subproject commit fa928a6d19e1666d8d811dfe3fd35cdad3b4e459 +Subproject commit 0ed9229f5b6f7824b333beabd7e3d5ba4b9bd971 From 51dbed2482577a33c20e4c4f08a33fbb372a2703 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 9 Sep 2024 18:59:35 +0200 Subject: [PATCH 0754/2194] sync methods: pass around places, not pointer-typed operands --- src/tools/miri/src/concurrency/init_once.rs | 7 +- src/tools/miri/src/concurrency/sync.rs | 46 ++++----- src/tools/miri/src/shims/unix/macos/sync.rs | 5 +- src/tools/miri/src/shims/unix/sync.rs | 101 ++++++++------------ src/tools/miri/src/shims/windows/sync.rs | 5 +- 5 files changed, 69 insertions(+), 95 deletions(-) diff --git a/src/tools/miri/src/concurrency/init_once.rs b/src/tools/miri/src/concurrency/init_once.rs index d709e4e6eaedb..9c2c6ae133023 100644 --- a/src/tools/miri/src/concurrency/init_once.rs +++ b/src/tools/miri/src/concurrency/init_once.rs @@ -1,7 +1,6 @@ use std::collections::VecDeque; use rustc_index::Idx; -use rustc_middle::ty::layout::TyAndLayout; use super::sync::EvalContextExtPriv as _; use super::vector_clock::VClock; @@ -30,14 +29,12 @@ impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {} pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { fn init_once_get_or_create_id( &mut self, - lock_op: &OpTy<'tcx>, - lock_layout: TyAndLayout<'tcx>, + lock: &MPlaceTy<'tcx>, offset: u64, ) -> InterpResult<'tcx, InitOnceId> { let this = self.eval_context_mut(); this.get_or_create_id( - lock_op, - lock_layout, + lock, offset, |ecx| &mut ecx.machine.sync.init_onces, |_| Ok(Default::default()), diff --git a/src/tools/miri/src/concurrency/sync.rs b/src/tools/miri/src/concurrency/sync.rs index a6a2a03b1b080..ff55af60ee82b 100644 --- a/src/tools/miri/src/concurrency/sync.rs +++ b/src/tools/miri/src/concurrency/sync.rs @@ -4,7 +4,7 @@ use std::time::Duration; use rustc_data_structures::fx::FxHashMap; use rustc_index::{Idx, IndexVec}; -use rustc_middle::ty::layout::TyAndLayout; +use rustc_target::abi::Size; use super::init_once::InitOnce; use super::vector_clock::VClock; @@ -206,21 +206,21 @@ pub(super) trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { #[inline] fn get_or_create_id( &mut self, - lock_op: &OpTy<'tcx>, - lock_layout: TyAndLayout<'tcx>, + lock: &MPlaceTy<'tcx>, offset: u64, get_objs: impl for<'a> Fn(&'a mut MiriInterpCx<'tcx>) -> &'a mut IndexVec, create_obj: impl for<'a> FnOnce(&'a mut MiriInterpCx<'tcx>) -> InterpResult<'tcx, T>, ) -> InterpResult<'tcx, Option> { let this = self.eval_context_mut(); - let value_place = - this.deref_pointer_and_offset(lock_op, offset, lock_layout, this.machine.layouts.u32)?; + let offset = Size::from_bytes(offset); + assert!(lock.layout.size >= offset + this.machine.layouts.u32.size); + let id_place = lock.offset(offset, this.machine.layouts.u32, this)?; let next_index = get_objs(this).next_index(); // Since we are lazy, this update has to be atomic. let (old, success) = this .atomic_compare_exchange_scalar( - &value_place, + &id_place, &ImmTy::from_uint(0u32, this.machine.layouts.u32), Scalar::from_u32(next_index.to_u32()), AtomicRwOrd::Relaxed, // deliberately *no* synchronization @@ -258,18 +258,18 @@ pub(super) trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { /// - `obj` must be the new sync object. fn create_id( &mut self, - lock_op: &OpTy<'tcx>, - lock_layout: TyAndLayout<'tcx>, + lock: &MPlaceTy<'tcx>, offset: u64, get_objs: impl for<'a> Fn(&'a mut MiriInterpCx<'tcx>) -> &'a mut IndexVec, obj: T, ) -> InterpResult<'tcx, Id> { let this = self.eval_context_mut(); - let value_place = - this.deref_pointer_and_offset(lock_op, offset, lock_layout, this.machine.layouts.u32)?; + let offset = Size::from_bytes(offset); + assert!(lock.layout.size >= offset + this.machine.layouts.u32.size); + let id_place = lock.offset(offset, this.machine.layouts.u32, this)?; let new_index = get_objs(this).push(obj); - this.write_scalar(Scalar::from_u32(new_index.to_u32()), &value_place)?; + this.write_scalar(Scalar::from_u32(new_index.to_u32()), &id_place)?; Ok(new_index) } @@ -302,15 +302,13 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { /// Eagerly create and initialize a new mutex. fn mutex_create( &mut self, - lock_op: &OpTy<'tcx>, - lock_layout: TyAndLayout<'tcx>, + lock: &MPlaceTy<'tcx>, offset: u64, data: Option, ) -> InterpResult<'tcx, MutexId> { let this = self.eval_context_mut(); this.create_id( - lock_op, - lock_layout, + lock, offset, |ecx| &mut ecx.machine.sync.mutexes, Mutex { data, ..Default::default() }, @@ -321,8 +319,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { /// `initialize_data` must return any additional data that a user wants to associate with the mutex. fn mutex_get_or_create_id( &mut self, - lock_op: &OpTy<'tcx>, - lock_layout: TyAndLayout<'tcx>, + lock: &MPlaceTy<'tcx>, offset: u64, initialize_data: impl for<'a> FnOnce( &'a mut MiriInterpCx<'tcx>, @@ -330,8 +327,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { ) -> InterpResult<'tcx, MutexId> { let this = self.eval_context_mut(); this.get_or_create_id( - lock_op, - lock_layout, + lock, offset, |ecx| &mut ecx.machine.sync.mutexes, |ecx| initialize_data(ecx).map(|data| Mutex { data, ..Default::default() }), @@ -350,8 +346,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { fn rwlock_get_or_create_id( &mut self, - lock_op: &OpTy<'tcx>, - lock_layout: TyAndLayout<'tcx>, + lock: &MPlaceTy<'tcx>, offset: u64, initialize_data: impl for<'a> FnOnce( &'a mut MiriInterpCx<'tcx>, @@ -360,8 +355,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { ) -> InterpResult<'tcx, RwLockId> { let this = self.eval_context_mut(); this.get_or_create_id( - lock_op, - lock_layout, + lock, offset, |ecx| &mut ecx.machine.sync.rwlocks, |ecx| initialize_data(ecx).map(|data| RwLock { data, ..Default::default() }), @@ -380,14 +374,12 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { fn condvar_get_or_create_id( &mut self, - lock_op: &OpTy<'tcx>, - lock_layout: TyAndLayout<'tcx>, + lock: &MPlaceTy<'tcx>, offset: u64, ) -> InterpResult<'tcx, CondvarId> { let this = self.eval_context_mut(); this.get_or_create_id( - lock_op, - lock_layout, + lock, offset, |ecx| &mut ecx.machine.sync.condvars, |_| Ok(Default::default()), diff --git a/src/tools/miri/src/shims/unix/macos/sync.rs b/src/tools/miri/src/shims/unix/macos/sync.rs index 882c08cca154c..8f9237a1d46ea 100644 --- a/src/tools/miri/src/shims/unix/macos/sync.rs +++ b/src/tools/miri/src/shims/unix/macos/sync.rs @@ -14,12 +14,13 @@ use crate::*; impl<'tcx> EvalContextExtPriv<'tcx> for crate::MiriInterpCx<'tcx> {} trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { - fn os_unfair_lock_getid(&mut self, lock_op: &OpTy<'tcx>) -> InterpResult<'tcx, MutexId> { + fn os_unfair_lock_getid(&mut self, lock_ptr: &OpTy<'tcx>) -> InterpResult<'tcx, MutexId> { let this = self.eval_context_mut(); + let lock = this.deref_pointer(lock_ptr)?; // os_unfair_lock holds a 32-bit value, is initialized with zero and // must be assumed to be opaque. Therefore, we can just store our // internal mutex ID in the structure without anyone noticing. - this.mutex_get_or_create_id(lock_op, this.libc_ty_layout("os_unfair_lock"), 0, |_| Ok(None)) + this.mutex_get_or_create_id(&lock, 0, |_| Ok(None)) } } diff --git a/src/tools/miri/src/shims/unix/sync.rs b/src/tools/miri/src/shims/unix/sync.rs index 9d664985fd41e..31de1362638cc 100644 --- a/src/tools/miri/src/shims/unix/sync.rs +++ b/src/tools/miri/src/shims/unix/sync.rs @@ -18,10 +18,10 @@ fn mutexattr_kind_offset<'tcx>(ecx: &MiriInterpCx<'tcx>) -> InterpResult<'tcx, u fn mutexattr_get_kind<'tcx>( ecx: &MiriInterpCx<'tcx>, - attr_op: &OpTy<'tcx>, + attr_ptr: &OpTy<'tcx>, ) -> InterpResult<'tcx, i32> { ecx.deref_pointer_and_read( - attr_op, + attr_ptr, mutexattr_kind_offset(ecx)?, ecx.libc_ty_layout("pthread_mutexattr_t"), ecx.machine.layouts.i32, @@ -31,11 +31,11 @@ fn mutexattr_get_kind<'tcx>( fn mutexattr_set_kind<'tcx>( ecx: &mut MiriInterpCx<'tcx>, - attr_op: &OpTy<'tcx>, + attr_ptr: &OpTy<'tcx>, kind: i32, ) -> InterpResult<'tcx, ()> { ecx.deref_pointer_and_write( - attr_op, + attr_ptr, mutexattr_kind_offset(ecx)?, Scalar::from_i32(kind), ecx.libc_ty_layout("pthread_mutexattr_t"), @@ -94,15 +94,14 @@ fn mutex_id_offset<'tcx>(ecx: &MiriInterpCx<'tcx>) -> InterpResult<'tcx, u64> { /// Eagerly create and initialize a new mutex. fn mutex_create<'tcx>( ecx: &mut MiriInterpCx<'tcx>, - mutex_op: &OpTy<'tcx>, + mutex_ptr: &OpTy<'tcx>, kind: i32, ) -> InterpResult<'tcx> { - // FIXME: might be worth changing mutex_create to take the mplace - // rather than the `OpTy`. - let address = ecx.read_pointer(mutex_op)?.addr().bytes(); + let mutex = ecx.deref_pointer(mutex_ptr)?; + let address = mutex.ptr().addr().bytes(); let kind = translate_kind(ecx, kind)?; let data = Some(AdditionalMutexData { address, kind }); - ecx.mutex_create(mutex_op, ecx.libc_ty_layout("pthread_mutex_t"), mutex_id_offset(ecx)?, data)?; + ecx.mutex_create(&mutex, mutex_id_offset(ecx)?, data)?; Ok(()) } @@ -112,24 +111,18 @@ fn mutex_create<'tcx>( /// return an error if it has. fn mutex_get_id<'tcx>( ecx: &mut MiriInterpCx<'tcx>, - mutex_op: &OpTy<'tcx>, + mutex_ptr: &OpTy<'tcx>, ) -> InterpResult<'tcx, MutexId> { - let address = ecx.read_pointer(mutex_op)?.addr().bytes(); - - // FIXME: might be worth changing mutex_get_or_create_id to take the mplace - // rather than the `OpTy`. - let id = ecx.mutex_get_or_create_id( - mutex_op, - ecx.libc_ty_layout("pthread_mutex_t"), - mutex_id_offset(ecx)?, - |ecx| { - // This is called if a static initializer was used and the lock has not been assigned - // an ID yet. We have to determine the mutex kind from the static initializer. - let kind = kind_from_static_initializer(ecx, mutex_op)?; - - Ok(Some(AdditionalMutexData { kind, address })) - }, - )?; + let mutex = ecx.deref_pointer(mutex_ptr)?; + let address = mutex.ptr().addr().bytes(); + + let id = ecx.mutex_get_or_create_id(&mutex, mutex_id_offset(ecx)?, |ecx| { + // This is called if a static initializer was used and the lock has not been assigned + // an ID yet. We have to determine the mutex kind from the static initializer. + let kind = kind_from_static_initializer(ecx, &mutex)?; + + Ok(Some(AdditionalMutexData { kind, address })) + })?; // Check that the mutex has not been moved since last use. let data = ecx.mutex_get_data(id).expect("data should be always exist for pthreads"); @@ -143,20 +136,15 @@ fn mutex_get_id<'tcx>( /// Returns the kind of a static initializer. fn kind_from_static_initializer<'tcx>( ecx: &MiriInterpCx<'tcx>, - mutex_op: &OpTy<'tcx>, + mutex: &MPlaceTy<'tcx>, ) -> InterpResult<'tcx, MutexKind> { // Only linux has static initializers other than PTHREAD_MUTEX_DEFAULT. let kind = match &*ecx.tcx.sess.target.os { "linux" => { let offset = if ecx.pointer_size().bytes() == 8 { 16 } else { 12 }; - - ecx.deref_pointer_and_read( - mutex_op, - offset, - ecx.libc_ty_layout("pthread_mutex_t"), - ecx.machine.layouts.i32, - )? - .to_i32()? + let kind_place = + mutex.offset(Size::from_bytes(offset), ecx.machine.layouts.i32, ecx)?; + ecx.read_scalar(&kind_place)?.to_i32()? } | "illumos" | "solaris" | "macos" => ecx.eval_libc_i32("PTHREAD_MUTEX_DEFAULT"), os => throw_unsup_format!("`pthread_mutex` is not supported on {os}"), @@ -211,16 +199,14 @@ fn rwlock_id_offset<'tcx>(ecx: &MiriInterpCx<'tcx>) -> InterpResult<'tcx, u64> { fn rwlock_get_id<'tcx>( ecx: &mut MiriInterpCx<'tcx>, - rwlock_op: &OpTy<'tcx>, + rwlock_ptr: &OpTy<'tcx>, ) -> InterpResult<'tcx, RwLockId> { - let address = ecx.read_pointer(rwlock_op)?.addr().bytes(); + let rwlock = ecx.deref_pointer(rwlock_ptr)?; + let address = rwlock.ptr().addr().bytes(); - let id = ecx.rwlock_get_or_create_id( - rwlock_op, - ecx.libc_ty_layout("pthread_rwlock_t"), - rwlock_id_offset(ecx)?, - |_| Ok(Some(AdditionalRwLockData { address })), - )?; + let id = ecx.rwlock_get_or_create_id(&rwlock, rwlock_id_offset(ecx)?, |_| { + Ok(Some(AdditionalRwLockData { address })) + })?; // Check that the rwlock has not been moved since last use. let data = ecx.rwlock_get_data(id).expect("data should be always exist for pthreads"); @@ -246,10 +232,10 @@ fn condattr_clock_offset<'tcx>(ecx: &MiriInterpCx<'tcx>) -> InterpResult<'tcx, u fn condattr_get_clock_id<'tcx>( ecx: &MiriInterpCx<'tcx>, - attr_op: &OpTy<'tcx>, + attr_ptr: &OpTy<'tcx>, ) -> InterpResult<'tcx, i32> { ecx.deref_pointer_and_read( - attr_op, + attr_ptr, condattr_clock_offset(ecx)?, ecx.libc_ty_layout("pthread_condattr_t"), ecx.machine.layouts.i32, @@ -259,11 +245,11 @@ fn condattr_get_clock_id<'tcx>( fn condattr_set_clock_id<'tcx>( ecx: &mut MiriInterpCx<'tcx>, - attr_op: &OpTy<'tcx>, + attr_ptr: &OpTy<'tcx>, clock_id: i32, ) -> InterpResult<'tcx, ()> { ecx.deref_pointer_and_write( - attr_op, + attr_ptr, condattr_clock_offset(ecx)?, Scalar::from_i32(clock_id), ecx.libc_ty_layout("pthread_condattr_t"), @@ -337,21 +323,18 @@ fn cond_clock_offset<'tcx>(ecx: &MiriInterpCx<'tcx>) -> u64 { fn cond_get_id<'tcx>( ecx: &mut MiriInterpCx<'tcx>, - cond_op: &OpTy<'tcx>, + cond_ptr: &OpTy<'tcx>, ) -> InterpResult<'tcx, CondvarId> { - ecx.condvar_get_or_create_id( - cond_op, - ecx.libc_ty_layout("pthread_cond_t"), - cond_id_offset(ecx)?, - ) + let cond = ecx.deref_pointer(cond_ptr)?; + ecx.condvar_get_or_create_id(&cond, cond_id_offset(ecx)?) } fn cond_reset_id<'tcx>( ecx: &mut MiriInterpCx<'tcx>, - cond_op: &OpTy<'tcx>, + cond_ptr: &OpTy<'tcx>, ) -> InterpResult<'tcx, ()> { ecx.deref_pointer_and_write( - cond_op, + cond_ptr, cond_id_offset(ecx)?, Scalar::from_i32(0), ecx.libc_ty_layout("pthread_cond_t"), @@ -361,10 +344,10 @@ fn cond_reset_id<'tcx>( fn cond_get_clock_id<'tcx>( ecx: &MiriInterpCx<'tcx>, - cond_op: &OpTy<'tcx>, + cond_ptr: &OpTy<'tcx>, ) -> InterpResult<'tcx, i32> { ecx.deref_pointer_and_read( - cond_op, + cond_ptr, cond_clock_offset(ecx), ecx.libc_ty_layout("pthread_cond_t"), ecx.machine.layouts.i32, @@ -374,11 +357,11 @@ fn cond_get_clock_id<'tcx>( fn cond_set_clock_id<'tcx>( ecx: &mut MiriInterpCx<'tcx>, - cond_op: &OpTy<'tcx>, + cond_ptr: &OpTy<'tcx>, clock_id: i32, ) -> InterpResult<'tcx, ()> { ecx.deref_pointer_and_write( - cond_op, + cond_ptr, cond_clock_offset(ecx), Scalar::from_i32(clock_id), ecx.libc_ty_layout("pthread_cond_t"), diff --git a/src/tools/miri/src/shims/windows/sync.rs b/src/tools/miri/src/shims/windows/sync.rs index e1fbb77037cfb..51b0129356baa 100644 --- a/src/tools/miri/src/shims/windows/sync.rs +++ b/src/tools/miri/src/shims/windows/sync.rs @@ -10,9 +10,10 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { // Windows sync primitives are pointer sized. // We only use the first 4 bytes for the id. - fn init_once_get_id(&mut self, init_once_op: &OpTy<'tcx>) -> InterpResult<'tcx, InitOnceId> { + fn init_once_get_id(&mut self, init_once_ptr: &OpTy<'tcx>) -> InterpResult<'tcx, InitOnceId> { let this = self.eval_context_mut(); - this.init_once_get_or_create_id(init_once_op, this.windows_ty_layout("INIT_ONCE"), 0) + let init_once = this.deref_pointer(init_once_ptr)?; + this.init_once_get_or_create_id(&init_once, 0) } /// Returns `true` if we were succssful, `false` if we would block. From 99cad123edfa915723a5e5c0537d43b71f2cc0c5 Mon Sep 17 00:00:00 2001 From: "James C. Wise" Date: Mon, 9 Sep 2024 13:13:45 -0400 Subject: [PATCH 0755/2194] Fix slice::first_mut docs pointer -> reference --- library/core/src/slice/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs index 166189f4b6cf3..fb732f82989c0 100644 --- a/library/core/src/slice/mod.rs +++ b/library/core/src/slice/mod.rs @@ -156,7 +156,7 @@ impl [T] { if let [first, ..] = self { Some(first) } else { None } } - /// Returns a mutable pointer to the first element of the slice, or `None` if it is empty. + /// Returns a mutable reference to the first element of the slice, or `None` if it is empty. /// /// # Examples /// From 218057c56543957e1519fad88095a2c14e77024d Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 9 Sep 2024 19:07:51 +0200 Subject: [PATCH 0756/2194] sync: store extra sync primitive data in a Box so the type can be kept local --- src/tools/miri/src/concurrency/sync.rs | 48 ++++------------- src/tools/miri/src/lib.rs | 5 +- src/tools/miri/src/shims/unix/sync.rs | 72 +++++++++++++++++--------- 3 files changed, 59 insertions(+), 66 deletions(-) diff --git a/src/tools/miri/src/concurrency/sync.rs b/src/tools/miri/src/concurrency/sync.rs index ff55af60ee82b..7098cc5b95bef 100644 --- a/src/tools/miri/src/concurrency/sync.rs +++ b/src/tools/miri/src/concurrency/sync.rs @@ -1,3 +1,4 @@ +use std::any::Any; use std::collections::{hash_map::Entry, VecDeque}; use std::ops::Not; use std::time::Duration; @@ -66,27 +67,6 @@ pub(super) use declare_id; declare_id!(MutexId); -/// The mutex kind. -#[derive(Debug, Clone, Copy)] -#[non_exhaustive] -pub enum MutexKind { - Invalid, - Normal, - Default, - Recursive, - ErrorCheck, -} - -#[derive(Debug)] -/// Additional data that may be used by shim implementations. -pub struct AdditionalMutexData { - /// The mutex kind, used by some mutex implementations like pthreads mutexes. - pub kind: MutexKind, - - /// The address of the mutex. - pub address: u64, -} - /// The mutex state. #[derive(Default, Debug)] struct Mutex { @@ -100,18 +80,11 @@ struct Mutex { clock: VClock, /// Additional data that can be set by shim implementations. - data: Option, + data: Option>, } declare_id!(RwLockId); -#[derive(Debug)] -/// Additional data that may be used by shim implementations. -pub struct AdditionalRwLockData { - /// The address of the rwlock. - pub address: u64, -} - /// The read-write lock state. #[derive(Default, Debug)] struct RwLock { @@ -146,7 +119,7 @@ struct RwLock { clock_current_readers: VClock, /// Additional data that can be set by shim implementations. - data: Option, + data: Option>, } declare_id!(CondvarId); @@ -304,7 +277,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { &mut self, lock: &MPlaceTy<'tcx>, offset: u64, - data: Option, + data: Option>, ) -> InterpResult<'tcx, MutexId> { let this = self.eval_context_mut(); this.create_id( @@ -323,7 +296,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { offset: u64, initialize_data: impl for<'a> FnOnce( &'a mut MiriInterpCx<'tcx>, - ) -> InterpResult<'tcx, Option>, + ) -> InterpResult<'tcx, Option>>, ) -> InterpResult<'tcx, MutexId> { let this = self.eval_context_mut(); this.get_or_create_id( @@ -336,12 +309,12 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { } /// Retrieve the additional data stored for a mutex. - fn mutex_get_data<'a>(&'a mut self, id: MutexId) -> Option<&'a AdditionalMutexData> + fn mutex_get_data<'a, T: 'static>(&'a mut self, id: MutexId) -> Option<&'a T> where 'tcx: 'a, { let this = self.eval_context_ref(); - this.machine.sync.mutexes[id].data.as_ref() + this.machine.sync.mutexes[id].data.as_deref().and_then(|p| p.downcast_ref::()) } fn rwlock_get_or_create_id( @@ -350,8 +323,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { offset: u64, initialize_data: impl for<'a> FnOnce( &'a mut MiriInterpCx<'tcx>, - ) - -> InterpResult<'tcx, Option>, + ) -> InterpResult<'tcx, Option>>, ) -> InterpResult<'tcx, RwLockId> { let this = self.eval_context_mut(); this.get_or_create_id( @@ -364,12 +336,12 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { } /// Retrieve the additional data stored for a rwlock. - fn rwlock_get_data<'a>(&'a mut self, id: RwLockId) -> Option<&'a AdditionalRwLockData> + fn rwlock_get_data<'a, T: 'static>(&'a mut self, id: RwLockId) -> Option<&'a T> where 'tcx: 'a, { let this = self.eval_context_ref(); - this.machine.sync.rwlocks[id].data.as_ref() + this.machine.sync.rwlocks[id].data.as_deref().and_then(|p| p.downcast_ref::()) } fn condvar_get_or_create_id( diff --git a/src/tools/miri/src/lib.rs b/src/tools/miri/src/lib.rs index 273b1107ed0b9..8a59206943d18 100644 --- a/src/tools/miri/src/lib.rs +++ b/src/tools/miri/src/lib.rs @@ -133,10 +133,7 @@ pub use crate::concurrency::{ cpu_affinity::MAX_CPUS, data_race::{AtomicFenceOrd, AtomicReadOrd, AtomicRwOrd, AtomicWriteOrd, EvalContextExt as _}, init_once::{EvalContextExt as _, InitOnceId}, - sync::{ - AdditionalMutexData, AdditionalRwLockData, CondvarId, EvalContextExt as _, MutexId, - MutexKind, RwLockId, SynchronizationObjects, - }, + sync::{CondvarId, EvalContextExt as _, MutexId, RwLockId, SynchronizationObjects}, thread::{ BlockReason, EvalContextExt as _, StackEmptyCallback, ThreadId, ThreadManager, TimeoutAnchor, TimeoutClock, UnblockCallback, diff --git a/src/tools/miri/src/shims/unix/sync.rs b/src/tools/miri/src/shims/unix/sync.rs index 31de1362638cc..dacbe973af260 100644 --- a/src/tools/miri/src/shims/unix/sync.rs +++ b/src/tools/miri/src/shims/unix/sync.rs @@ -59,6 +59,25 @@ fn is_mutex_kind_normal<'tcx>(ecx: &MiriInterpCx<'tcx>, kind: i32) -> InterpResu Ok(kind == (mutex_normal_kind | PTHREAD_MUTEX_NORMAL_FLAG)) } +/// The mutex kind. +#[derive(Debug, Clone, Copy)] +pub enum MutexKind { + Normal, + Default, + Recursive, + ErrorCheck, +} + +#[derive(Debug)] +/// Additional data that we attach with each mutex instance. +pub struct AdditionalMutexData { + /// The mutex kind, used by some mutex implementations like pthreads mutexes. + pub kind: MutexKind, + + /// The address of the mutex. + pub address: u64, +} + // pthread_mutex_t is between 24 and 48 bytes, depending on the platform. // We ignore the platform layout and store our own fields: // - id: u32 @@ -100,8 +119,8 @@ fn mutex_create<'tcx>( let mutex = ecx.deref_pointer(mutex_ptr)?; let address = mutex.ptr().addr().bytes(); let kind = translate_kind(ecx, kind)?; - let data = Some(AdditionalMutexData { address, kind }); - ecx.mutex_create(&mutex, mutex_id_offset(ecx)?, data)?; + let data = Box::new(AdditionalMutexData { address, kind }); + ecx.mutex_create(&mutex, mutex_id_offset(ecx)?, Some(data))?; Ok(()) } @@ -121,11 +140,13 @@ fn mutex_get_id<'tcx>( // an ID yet. We have to determine the mutex kind from the static initializer. let kind = kind_from_static_initializer(ecx, &mutex)?; - Ok(Some(AdditionalMutexData { kind, address })) + Ok(Some(Box::new(AdditionalMutexData { kind, address }))) })?; // Check that the mutex has not been moved since last use. - let data = ecx.mutex_get_data(id).expect("data should be always exist for pthreads"); + let data = ecx + .mutex_get_data::(id) + .expect("data should always exist for pthreads"); if data.address != address { throw_ub_format!("pthread_mutex_t can't be moved after first use") } @@ -171,6 +192,13 @@ fn translate_kind<'tcx>(ecx: &MiriInterpCx<'tcx>, kind: i32) -> InterpResult<'tc // We ignore the platform layout and store our own fields: // - id: u32 +#[derive(Debug)] +/// Additional data that may be used by shim implementations. +pub struct AdditionalRwLockData { + /// The address of the rwlock. + pub address: u64, +} + fn rwlock_id_offset<'tcx>(ecx: &MiriInterpCx<'tcx>) -> InterpResult<'tcx, u64> { let offset = match &*ecx.tcx.sess.target.os { "linux" | "illumos" | "solaris" => 0, @@ -205,11 +233,13 @@ fn rwlock_get_id<'tcx>( let address = rwlock.ptr().addr().bytes(); let id = ecx.rwlock_get_or_create_id(&rwlock, rwlock_id_offset(ecx)?, |_| { - Ok(Some(AdditionalRwLockData { address })) + Ok(Some(Box::new(AdditionalRwLockData { address }))) })?; // Check that the rwlock has not been moved since last use. - let data = ecx.rwlock_get_data(id).expect("data should be always exist for pthreads"); + let data = ecx + .rwlock_get_data::(id) + .expect("data should always exist for pthreads"); if data.address != address { throw_ub_format!("pthread_rwlock_t can't be moved after first use") } @@ -473,8 +503,10 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { let this = self.eval_context_mut(); let id = mutex_get_id(this, mutex_op)?; - let kind = - this.mutex_get_data(id).expect("data should always exist for pthread mutexes").kind; + let kind = this + .mutex_get_data::(id) + .expect("data should always exist for pthread mutexes") + .kind; let ret = if this.mutex_is_locked(id) { let owner_thread = this.mutex_get_owner(id); @@ -492,10 +524,6 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { this.mutex_lock(id); 0 } - _ => - throw_unsup_format!( - "called pthread_mutex_lock on an unsupported type of mutex" - ), } } } else { @@ -511,8 +539,10 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { let this = self.eval_context_mut(); let id = mutex_get_id(this, mutex_op)?; - let kind = - this.mutex_get_data(id).expect("data should always exist for pthread mutexes").kind; + let kind = this + .mutex_get_data::(id) + .expect("data should always exist for pthread mutexes") + .kind; Ok(Scalar::from_i32(if this.mutex_is_locked(id) { let owner_thread = this.mutex_get_owner(id); @@ -526,10 +556,6 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { this.mutex_lock(id); 0 } - _ => - throw_unsup_format!( - "called pthread_mutex_trylock on an unsupported type of mutex" - ), } } } else { @@ -543,8 +569,10 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { let this = self.eval_context_mut(); let id = mutex_get_id(this, mutex_op)?; - let kind = - this.mutex_get_data(id).expect("data should always exist for pthread mutexes").kind; + let kind = this + .mutex_get_data::(id) + .expect("data should always exist for pthread mutexes") + .kind; if let Some(_old_locked_count) = this.mutex_unlock(id)? { // The mutex was locked by the current thread. @@ -564,10 +592,6 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { ), MutexKind::ErrorCheck | MutexKind::Recursive => Ok(Scalar::from_i32(this.eval_libc_i32("EPERM"))), - _ => - throw_unsup_format!( - "called pthread_mutex_unlock on an unsupported type of mutex" - ), } } } From 05043a370a77f8647b5fa609488dbdfebb71d1a4 Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Mon, 9 Sep 2024 20:17:34 +0300 Subject: [PATCH 0757/2194] add `git_merge_commit_email` into `GitConfig` Signed-off-by: onur-ozkan --- src/bootstrap/src/core/config/config.rs | 1 + src/tools/build_helper/src/git.rs | 1 + 2 files changed, 2 insertions(+) diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs index 68b42305fdcc8..646e76d46b680 100644 --- a/src/bootstrap/src/core/config/config.rs +++ b/src/bootstrap/src/core/config/config.rs @@ -2509,6 +2509,7 @@ impl Config { GitConfig { git_repository: &self.stage0_metadata.config.git_repository, nightly_branch: &self.stage0_metadata.config.nightly_branch, + git_merge_commit_email: &self.stage0_metadata.config.git_merge_commit_email, } } diff --git a/src/tools/build_helper/src/git.rs b/src/tools/build_helper/src/git.rs index cc48a8964a372..98e5b7a328eb9 100644 --- a/src/tools/build_helper/src/git.rs +++ b/src/tools/build_helper/src/git.rs @@ -4,6 +4,7 @@ use std::process::{Command, Stdio}; pub struct GitConfig<'a> { pub git_repository: &'a str, pub nightly_branch: &'a str, + pub git_merge_commit_email: &'a str, } /// Runs a command and returns the output From dc9c5f251c06c2c0193aff779a5074cff3d233ee Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Mon, 9 Sep 2024 20:18:06 +0300 Subject: [PATCH 0758/2194] implement `build_helper::git::get_closest_merge_commit` Compare to `get_git_merge_base`, this doesn't require configuring the upstream remote. Signed-off-by: onur-ozkan --- src/tools/build_helper/src/git.rs | 40 ++++++++++++++++++++++++++----- 1 file changed, 34 insertions(+), 6 deletions(-) diff --git a/src/tools/build_helper/src/git.rs b/src/tools/build_helper/src/git.rs index 98e5b7a328eb9..7da3c9de60c45 100644 --- a/src/tools/build_helper/src/git.rs +++ b/src/tools/build_helper/src/git.rs @@ -1,4 +1,4 @@ -use std::path::Path; +use std::path::{Path, PathBuf}; use std::process::{Command, Stdio}; pub struct GitConfig<'a> { @@ -96,10 +96,7 @@ pub fn updated_master_branch( Err("Cannot find any suitable upstream master branch".to_owned()) } -pub fn get_git_merge_base( - config: &GitConfig<'_>, - git_dir: Option<&Path>, -) -> Result { +fn get_git_merge_base(config: &GitConfig<'_>, git_dir: Option<&Path>) -> Result { let updated_master = updated_master_branch(config, git_dir)?; let mut git = Command::new("git"); if let Some(git_dir) = git_dir { @@ -108,6 +105,37 @@ pub fn get_git_merge_base( Ok(output_result(git.arg("merge-base").arg(&updated_master).arg("HEAD"))?.trim().to_owned()) } +/// Resolves the closest merge commit by the given `author` and `target_paths`. +/// +/// If it fails to find the commit from upstream using `git merge-base`, fallbacks to HEAD. +pub fn get_closest_merge_commit( + git_dir: Option<&Path>, + config: &GitConfig<'_>, + target_paths: &[PathBuf], +) -> Result { + let mut git = Command::new("git"); + + if let Some(git_dir) = git_dir { + git.current_dir(git_dir); + } + + let merge_base = get_git_merge_base(config, git_dir).unwrap_or_else(|_| "HEAD".into()); + + git.args([ + "rev-list", + &format!("--author={}", config.git_merge_commit_email), + "-n1", + "--first-parent", + &merge_base, + ]); + + if !target_paths.is_empty() { + git.arg("--").args(target_paths); + } + + Ok(output_result(&mut git)?.trim().to_owned()) +} + /// Returns the files that have been modified in the current branch compared to the master branch. /// The `extensions` parameter can be used to filter the files by their extension. /// Does not include removed files. @@ -117,7 +145,7 @@ pub fn get_git_modified_files( git_dir: Option<&Path>, extensions: &[&str], ) -> Result>, String> { - let merge_base = get_git_merge_base(config, git_dir)?; + let merge_base = get_closest_merge_commit(git_dir, config, &[])?; let mut git = Command::new("git"); if let Some(git_dir) = git_dir { From 9aa823cc6727fd4c68cf3fdc50478e47b5ef5989 Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Mon, 9 Sep 2024 20:19:29 +0300 Subject: [PATCH 0759/2194] replace `get_closest_merge_base_commit` with `get_closest_merge_commit` Signed-off-by: onur-ozkan --- src/bootstrap/src/core/build_steps/compile.rs | 14 ++++------- src/bootstrap/src/core/build_steps/llvm.rs | 4 ++-- src/bootstrap/src/core/build_steps/tool.rs | 7 +++--- src/bootstrap/src/core/config/config.rs | 20 ++++------------ src/bootstrap/src/utils/helpers.rs | 23 ------------------- 5 files changed, 15 insertions(+), 53 deletions(-) diff --git a/src/bootstrap/src/core/build_steps/compile.rs b/src/bootstrap/src/core/build_steps/compile.rs index 102c9fd255432..bb07d478f71aa 100644 --- a/src/bootstrap/src/core/build_steps/compile.rs +++ b/src/bootstrap/src/core/build_steps/compile.rs @@ -15,6 +15,7 @@ use std::path::{Path, PathBuf}; use std::process::Stdio; use std::{env, fs, str}; +use build_helper::git::get_closest_merge_commit; use serde_derive::Deserialize; use crate::core::build_steps::tool::SourceType; @@ -26,8 +27,7 @@ use crate::core::builder::{ use crate::core::config::{DebuginfoLevel, LlvmLibunwind, RustcLto, TargetSelection}; use crate::utils::exec::command; use crate::utils::helpers::{ - self, exe, get_clang_cl_resource_dir, get_closest_merge_base_commit, is_debug_info, is_dylib, - symlink_dir, t, up_to_date, + self, exe, get_clang_cl_resource_dir, is_debug_info, is_dylib, symlink_dir, t, up_to_date, }; use crate::{CLang, Compiler, DependencyType, GitRepo, Mode, LLVM_TOOLS}; @@ -127,13 +127,9 @@ impl Step for Std { // the `rust.download-rustc=true` option. let force_recompile = if builder.rust_info().is_managed_git_subrepository() && builder.download_rustc() { - let closest_merge_commit = get_closest_merge_base_commit( - Some(&builder.src), - &builder.config.git_config(), - &builder.config.stage0_metadata.config.git_merge_commit_email, - &[], - ) - .unwrap(); + let closest_merge_commit = + get_closest_merge_commit(Some(&builder.src), &builder.config.git_config(), &[]) + .unwrap(); // Check if `library` has changes (returns false otherwise) !t!(helpers::git(Some(&builder.src)) diff --git a/src/bootstrap/src/core/build_steps/llvm.rs b/src/bootstrap/src/core/build_steps/llvm.rs index 442638d32034b..94b03b1b1386b 100644 --- a/src/bootstrap/src/core/build_steps/llvm.rs +++ b/src/bootstrap/src/core/build_steps/llvm.rs @@ -16,6 +16,7 @@ use std::sync::OnceLock; use std::{env, io}; use build_helper::ci::CiEnv; +use build_helper::git::get_closest_merge_commit; use crate::core::builder::{Builder, RunConfig, ShouldRun, Step}; use crate::core::config::{Config, TargetSelection}; @@ -153,10 +154,9 @@ pub fn prebuilt_llvm_config(builder: &Builder<'_>, target: TargetSelection) -> L /// This retrieves the LLVM sha we *want* to use, according to git history. pub(crate) fn detect_llvm_sha(config: &Config, is_git: bool) -> String { let llvm_sha = if is_git { - helpers::get_closest_merge_base_commit( + get_closest_merge_commit( Some(&config.src), &config.git_config(), - &config.stage0_metadata.config.git_merge_commit_email, &[ config.src.join("src/llvm-project"), config.src.join("src/bootstrap/download-ci-llvm-stamp"), diff --git a/src/bootstrap/src/core/build_steps/tool.rs b/src/bootstrap/src/core/build_steps/tool.rs index 3c2d791c2090e..a437f829ba5a6 100644 --- a/src/bootstrap/src/core/build_steps/tool.rs +++ b/src/bootstrap/src/core/build_steps/tool.rs @@ -1,6 +1,8 @@ use std::path::PathBuf; use std::{env, fs}; +use build_helper::git::get_closest_merge_commit; + use crate::core::build_steps::compile; use crate::core::build_steps::toolstate::ToolState; use crate::core::builder; @@ -8,7 +10,7 @@ use crate::core::builder::{Builder, Cargo as CargoCommand, RunConfig, ShouldRun, use crate::core::config::TargetSelection; use crate::utils::channel::GitInfo; use crate::utils::exec::{command, BootstrapCommand}; -use crate::utils::helpers::{add_dylib_path, exe, get_closest_merge_base_commit, git, t}; +use crate::utils::helpers::{add_dylib_path, exe, git, t}; use crate::{gha, Compiler, Kind, Mode}; #[derive(Debug, Clone, Hash, PartialEq, Eq)] @@ -576,10 +578,9 @@ impl Step for Rustdoc { && target_compiler.stage > 0 && builder.rust_info().is_managed_git_subrepository() { - let commit = get_closest_merge_base_commit( + let commit = get_closest_merge_commit( Some(&builder.config.src), &builder.config.git_config(), - &builder.config.stage0_metadata.config.git_merge_commit_email, &[], ) .unwrap(); diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs index 646e76d46b680..9be4f59bfbba4 100644 --- a/src/bootstrap/src/core/config/config.rs +++ b/src/bootstrap/src/core/config/config.rs @@ -14,7 +14,7 @@ use std::sync::OnceLock; use std::{cmp, env, fs}; use build_helper::exit; -use build_helper::git::{output_result, GitConfig}; +use build_helper::git::{get_closest_merge_commit, output_result, GitConfig}; use serde::{Deserialize, Deserializer}; use serde_derive::Deserialize; @@ -24,7 +24,7 @@ pub use crate::core::config::flags::Subcommand; use crate::core::config::flags::{Color, Flags, Warnings}; use crate::utils::cache::{Interned, INTERNER}; use crate::utils::channel::{self, GitInfo}; -use crate::utils::helpers::{self, exe, get_closest_merge_base_commit, output, t}; +use crate::utils::helpers::{self, exe, output, t}; macro_rules! check_ci_llvm { ($name:expr) => { @@ -2686,13 +2686,7 @@ impl Config { // Look for a version to compare to based on the current commit. // Only commits merged by bors will have CI artifacts. - let commit = get_closest_merge_base_commit( - Some(&self.src), - &self.git_config(), - &self.stage0_metadata.config.git_merge_commit_email, - &[], - ) - .unwrap(); + let commit = get_closest_merge_commit(Some(&self.src), &self.git_config(), &[]).unwrap(); if commit.is_empty() { println!("ERROR: could not find commit hash for downloading rustc"); println!("HELP: maybe your repository history is too shallow?"); @@ -2783,13 +2777,7 @@ impl Config { ) -> Option { // Look for a version to compare to based on the current commit. // Only commits merged by bors will have CI artifacts. - let commit = get_closest_merge_base_commit( - Some(&self.src), - &self.git_config(), - &self.stage0_metadata.config.git_merge_commit_email, - &[], - ) - .unwrap(); + let commit = get_closest_merge_commit(Some(&self.src), &self.git_config(), &[]).unwrap(); if commit.is_empty() { println!("error: could not find commit hash for downloading components from CI"); println!("help: maybe your repository history is too shallow?"); diff --git a/src/bootstrap/src/utils/helpers.rs b/src/bootstrap/src/utils/helpers.rs index a856c99ff55a5..beb3c5fb09842 100644 --- a/src/bootstrap/src/utils/helpers.rs +++ b/src/bootstrap/src/utils/helpers.rs @@ -10,7 +10,6 @@ use std::sync::OnceLock; use std::time::{Instant, SystemTime, UNIX_EPOCH}; use std::{env, fs, io, str}; -use build_helper::git::{get_git_merge_base, output_result, GitConfig}; use build_helper::util::fail; use crate::core::builder::Builder; @@ -523,28 +522,6 @@ pub fn git(source_dir: Option<&Path>) -> BootstrapCommand { git } -/// Returns the closest commit available from upstream for the given `author` and `target_paths`. -/// -/// If it fails to find the commit from upstream using `git merge-base`, fallbacks to HEAD. -pub fn get_closest_merge_base_commit( - source_dir: Option<&Path>, - config: &GitConfig<'_>, - author: &str, - target_paths: &[PathBuf], -) -> Result { - let mut git = git(source_dir); - - let merge_base = get_git_merge_base(config, source_dir).unwrap_or_else(|_| "HEAD".into()); - - git.args(["rev-list", &format!("--author={author}"), "-n1", "--first-parent", &merge_base]); - - if !target_paths.is_empty() { - git.arg("--").args(target_paths); - } - - Ok(output_result(git.as_command_mut())?.trim().to_owned()) -} - /// Sets the file times for a given file at `path`. pub fn set_file_times>(path: P, times: fs::FileTimes) -> io::Result<()> { // Windows requires file to be writable to modify file times. But on Linux CI the file does not From 667cf22f486cf16dfa1d26e7c4d670bce7293629 Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Mon, 9 Sep 2024 20:31:58 +0300 Subject: [PATCH 0760/2194] bump download-ci-llvm-stamp Signed-off-by: onur-ozkan --- src/bootstrap/download-ci-llvm-stamp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bootstrap/download-ci-llvm-stamp b/src/bootstrap/download-ci-llvm-stamp index 909015305015b..42cecbf5df9bb 100644 --- a/src/bootstrap/download-ci-llvm-stamp +++ b/src/bootstrap/download-ci-llvm-stamp @@ -1,4 +1,4 @@ Change this file to make users of the `download-ci-llvm` configuration download a new version of LLVM from CI, even if the LLVM submodule hasn’t changed. -Last change is for: https://github.com/rust-lang/rust/pull/129116 +Last change is for: https://github.com/rust-lang/rust/pull/129788 From 720bd0dd6cdb3192886bc822c2fa8576d6772a38 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 9 Sep 2024 19:59:16 +0200 Subject: [PATCH 0761/2194] move some const fn out of the const_ptr_as_ref feature --- library/core/src/ptr/const_ptr.rs | 6 +++--- library/core/src/ptr/mut_ptr.rs | 12 ++++++------ library/core/src/ptr/non_null.rs | 8 ++++---- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/library/core/src/ptr/const_ptr.rs b/library/core/src/ptr/const_ptr.rs index 3b635e2a4aa9e..81149b2061c5e 100644 --- a/library/core/src/ptr/const_ptr.rs +++ b/library/core/src/ptr/const_ptr.rs @@ -300,7 +300,7 @@ impl *const T { /// ``` // FIXME: mention it in the docs for `as_ref` and `as_uninit_ref` once stabilized. #[unstable(feature = "ptr_as_ref_unchecked", issue = "122034")] - #[rustc_const_unstable(feature = "const_ptr_as_ref", issue = "91822")] + #[rustc_const_unstable(feature = "ptr_as_ref_unchecked", issue = "122034")] #[inline] #[must_use] pub const unsafe fn as_ref_unchecked<'a>(self) -> &'a T { @@ -334,7 +334,7 @@ impl *const T { /// ``` #[inline] #[unstable(feature = "ptr_as_uninit", issue = "75402")] - #[rustc_const_unstable(feature = "const_ptr_as_ref", issue = "91822")] + #[rustc_const_unstable(feature = "ptr_as_uninit", issue = "75402")] pub const unsafe fn as_uninit_ref<'a>(self) -> Option<&'a MaybeUninit> where T: Sized, @@ -1662,7 +1662,7 @@ impl *const [T] { /// [allocated object]: crate::ptr#allocated-object #[inline] #[unstable(feature = "ptr_as_uninit", issue = "75402")] - #[rustc_const_unstable(feature = "const_ptr_as_ref", issue = "91822")] + #[rustc_const_unstable(feature = "ptr_as_uninit", issue = "75402")] pub const unsafe fn as_uninit_slice<'a>(self) -> Option<&'a [MaybeUninit]> { if self.is_null() { None diff --git a/library/core/src/ptr/mut_ptr.rs b/library/core/src/ptr/mut_ptr.rs index 42975cc927b8e..595c583cffc64 100644 --- a/library/core/src/ptr/mut_ptr.rs +++ b/library/core/src/ptr/mut_ptr.rs @@ -310,7 +310,7 @@ impl *mut T { /// ``` // FIXME: mention it in the docs for `as_ref` and `as_uninit_ref` once stabilized. #[unstable(feature = "ptr_as_ref_unchecked", issue = "122034")] - #[rustc_const_unstable(feature = "const_ptr_as_ref", issue = "91822")] + #[rustc_const_unstable(feature = "ptr_as_ref_unchecked", issue = "122034")] #[inline] #[must_use] pub const unsafe fn as_ref_unchecked<'a>(self) -> &'a T { @@ -349,7 +349,7 @@ impl *mut T { /// ``` #[inline] #[unstable(feature = "ptr_as_uninit", issue = "75402")] - #[rustc_const_unstable(feature = "const_ptr_as_ref", issue = "91822")] + #[rustc_const_unstable(feature = "ptr_as_uninit", issue = "75402")] pub const unsafe fn as_uninit_ref<'a>(self) -> Option<&'a MaybeUninit> where T: Sized, @@ -631,7 +631,7 @@ impl *mut T { /// ``` // FIXME: mention it in the docs for `as_mut` and `as_uninit_mut` once stabilized. #[unstable(feature = "ptr_as_ref_unchecked", issue = "122034")] - #[rustc_const_unstable(feature = "const_ptr_as_ref", issue = "91822")] + #[rustc_const_unstable(feature = "ptr_as_ref_unchecked", issue = "122034")] #[inline] #[must_use] pub const unsafe fn as_mut_unchecked<'a>(self) -> &'a mut T { @@ -654,7 +654,7 @@ impl *mut T { /// the pointer is [convertible to a reference](crate::ptr#pointer-to-reference-conversion). #[inline] #[unstable(feature = "ptr_as_uninit", issue = "75402")] - #[rustc_const_unstable(feature = "const_ptr_as_ref", issue = "91822")] + #[rustc_const_unstable(feature = "ptr_as_uninit", issue = "75402")] pub const unsafe fn as_uninit_mut<'a>(self) -> Option<&'a mut MaybeUninit> where T: Sized, @@ -2031,7 +2031,7 @@ impl *mut [T] { /// [allocated object]: crate::ptr#allocated-object #[inline] #[unstable(feature = "ptr_as_uninit", issue = "75402")] - #[rustc_const_unstable(feature = "const_ptr_as_ref", issue = "91822")] + #[rustc_const_unstable(feature = "ptr_as_uninit", issue = "75402")] pub const unsafe fn as_uninit_slice<'a>(self) -> Option<&'a [MaybeUninit]> { if self.is_null() { None @@ -2083,7 +2083,7 @@ impl *mut [T] { /// [allocated object]: crate::ptr#allocated-object #[inline] #[unstable(feature = "ptr_as_uninit", issue = "75402")] - #[rustc_const_unstable(feature = "const_ptr_as_ref", issue = "91822")] + #[rustc_const_unstable(feature = "ptr_as_uninit", issue = "75402")] pub const unsafe fn as_uninit_slice_mut<'a>(self) -> Option<&'a mut [MaybeUninit]> { if self.is_null() { None diff --git a/library/core/src/ptr/non_null.rs b/library/core/src/ptr/non_null.rs index b1429fff74434..673acc2972fe4 100644 --- a/library/core/src/ptr/non_null.rs +++ b/library/core/src/ptr/non_null.rs @@ -133,7 +133,7 @@ impl NonNull { #[inline] #[must_use] #[unstable(feature = "ptr_as_uninit", issue = "75402")] - #[rustc_const_unstable(feature = "const_ptr_as_ref", issue = "91822")] + #[rustc_const_unstable(feature = "ptr_as_uninit", issue = "75402")] pub const unsafe fn as_uninit_ref<'a>(self) -> &'a MaybeUninit { // SAFETY: the caller must guarantee that `self` meets all the // requirements for a reference. @@ -157,7 +157,7 @@ impl NonNull { #[inline] #[must_use] #[unstable(feature = "ptr_as_uninit", issue = "75402")] - #[rustc_const_unstable(feature = "const_ptr_as_ref", issue = "91822")] + #[rustc_const_unstable(feature = "ptr_as_uninit", issue = "75402")] pub const unsafe fn as_uninit_mut<'a>(self) -> &'a mut MaybeUninit { // SAFETY: the caller must guarantee that `self` meets all the // requirements for a reference. @@ -1563,7 +1563,7 @@ impl NonNull<[T]> { #[inline] #[must_use] #[unstable(feature = "ptr_as_uninit", issue = "75402")] - #[rustc_const_unstable(feature = "const_ptr_as_ref", issue = "91822")] + #[rustc_const_unstable(feature = "ptr_as_uninit", issue = "75402")] pub const unsafe fn as_uninit_slice<'a>(self) -> &'a [MaybeUninit] { // SAFETY: the caller must uphold the safety contract for `as_uninit_slice`. unsafe { slice::from_raw_parts(self.cast().as_ptr(), self.len()) } @@ -1628,7 +1628,7 @@ impl NonNull<[T]> { #[inline] #[must_use] #[unstable(feature = "ptr_as_uninit", issue = "75402")] - #[rustc_const_unstable(feature = "const_ptr_as_ref", issue = "91822")] + #[rustc_const_unstable(feature = "ptr_as_uninit", issue = "75402")] pub const unsafe fn as_uninit_slice_mut<'a>(self) -> &'a mut [MaybeUninit] { // SAFETY: the caller must uphold the safety contract for `as_uninit_slice_mut`. unsafe { slice::from_raw_parts_mut(self.cast().as_ptr(), self.len()) } From 12998c2e11a089e6c591e1704a63a7942826208e Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Mon, 9 Sep 2024 21:03:51 +0300 Subject: [PATCH 0762/2194] handle `GitConfig` for `tools/suggest-tests` Signed-off-by: onur-ozkan --- src/bootstrap/src/core/build_steps/suggest.rs | 1 + src/tools/suggest-tests/src/main.rs | 1 + 2 files changed, 2 insertions(+) diff --git a/src/bootstrap/src/core/build_steps/suggest.rs b/src/bootstrap/src/core/build_steps/suggest.rs index 8aaffab514d88..ba9b1b2fc3317 100644 --- a/src/bootstrap/src/core/build_steps/suggest.rs +++ b/src/bootstrap/src/core/build_steps/suggest.rs @@ -17,6 +17,7 @@ pub fn suggest(builder: &Builder<'_>, run: bool) { .tool_cmd(Tool::SuggestTests) .env("SUGGEST_TESTS_GIT_REPOSITORY", git_config.git_repository) .env("SUGGEST_TESTS_NIGHTLY_BRANCH", git_config.nightly_branch) + .env("SUGGEST_TESTS_MERGE_COMMIT_EMAIL", git_config.git_merge_commit_email) .run_capture_stdout(builder) .stdout(); diff --git a/src/tools/suggest-tests/src/main.rs b/src/tools/suggest-tests/src/main.rs index 8e3625c244916..6f09bddcf60b8 100644 --- a/src/tools/suggest-tests/src/main.rs +++ b/src/tools/suggest-tests/src/main.rs @@ -8,6 +8,7 @@ fn main() -> ExitCode { &GitConfig { git_repository: &env("SUGGEST_TESTS_GIT_REPOSITORY"), nightly_branch: &env("SUGGEST_TESTS_NIGHTLY_BRANCH"), + git_merge_commit_email: &env("SUGGEST_TESTS_MERGE_COMMIT_EMAIL"), }, None, &Vec::new(), From e10224a7c3b7dbe5942e021d0b7f8230128cb9af Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 9 Sep 2024 20:09:13 +0200 Subject: [PATCH 0763/2194] move const fn with a null check into const_ptr_is_null gate --- library/core/src/ptr/const_ptr.rs | 2 +- library/core/src/ptr/mut_ptr.rs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/library/core/src/ptr/const_ptr.rs b/library/core/src/ptr/const_ptr.rs index 81149b2061c5e..6dbc5e210ad3a 100644 --- a/library/core/src/ptr/const_ptr.rs +++ b/library/core/src/ptr/const_ptr.rs @@ -268,7 +268,7 @@ impl *const T { /// } /// ``` #[stable(feature = "ptr_as_ref", since = "1.9.0")] - #[rustc_const_unstable(feature = "const_ptr_as_ref", issue = "91822")] + #[rustc_const_unstable(feature = "const_ptr_is_null", issue = "74939")] #[inline] pub const unsafe fn as_ref<'a>(self) -> Option<&'a T> { // SAFETY: the caller must guarantee that `self` is valid diff --git a/library/core/src/ptr/mut_ptr.rs b/library/core/src/ptr/mut_ptr.rs index 595c583cffc64..d0b4e493107c9 100644 --- a/library/core/src/ptr/mut_ptr.rs +++ b/library/core/src/ptr/mut_ptr.rs @@ -276,7 +276,7 @@ impl *mut T { /// } /// ``` #[stable(feature = "ptr_as_ref", since = "1.9.0")] - #[rustc_const_unstable(feature = "const_ptr_as_ref", issue = "91822")] + #[rustc_const_unstable(feature = "const_ptr_is_null", issue = "74939")] #[inline] pub const unsafe fn as_ref<'a>(self) -> Option<&'a T> { // SAFETY: the caller must guarantee that `self` is valid for a @@ -595,7 +595,7 @@ impl *mut T { /// println!("{s:?}"); // It'll print: "[4, 2, 3]". /// ``` #[stable(feature = "ptr_as_ref", since = "1.9.0")] - #[rustc_const_unstable(feature = "const_ptr_as_ref", issue = "91822")] + #[rustc_const_unstable(feature = "const_ptr_is_null", issue = "74939")] #[inline] pub const unsafe fn as_mut<'a>(self) -> Option<&'a mut T> { // SAFETY: the caller must guarantee that `self` is be valid for From 2f1e1be6ffbf39e3a7b219343e4be38cab599cf4 Mon Sep 17 00:00:00 2001 From: Julius Liu Date: Mon, 9 Sep 2024 11:55:44 -0700 Subject: [PATCH 0764/2194] maint: update docs for change_time ext and doc links --- library/std/src/os/windows/fs.rs | 29 ++++++++++++++++++++--------- 1 file changed, 20 insertions(+), 9 deletions(-) diff --git a/library/std/src/os/windows/fs.rs b/library/std/src/os/windows/fs.rs index 7cac8c39ea89f..285d9c3fc78d6 100644 --- a/library/std/src/os/windows/fs.rs +++ b/library/std/src/os/windows/fs.rs @@ -299,7 +299,7 @@ impl OpenOptionsExt for OpenOptions { /// of the [`BY_HANDLE_FILE_INFORMATION`] structure. /// /// [`BY_HANDLE_FILE_INFORMATION`]: -/// https://docs.microsoft.com/en-us/windows/win32/api/fileapi/ns-fileapi-by_handle_file_information +/// https://docs.microsoft.com/windows/win32/api/fileapi/ns-fileapi-by_handle_file_information #[stable(feature = "metadata_ext", since = "1.1.0")] pub trait MetadataExt { /// Returns the value of the `dwFileAttributes` field of this metadata. @@ -323,7 +323,7 @@ pub trait MetadataExt { /// ``` /// /// [File Attribute Constants]: - /// https://docs.microsoft.com/en-us/windows/win32/fileio/file-attribute-constants + /// https://docs.microsoft.com/windows/win32/fileio/file-attribute-constants #[stable(feature = "metadata_ext", since = "1.1.0")] fn file_attributes(&self) -> u32; @@ -352,7 +352,7 @@ pub trait MetadataExt { /// } /// ``` /// - /// [`FILETIME`]: https://docs.microsoft.com/en-us/windows/win32/api/minwinbase/ns-minwinbase-filetime + /// [`FILETIME`]: https://docs.microsoft.com/windows/win32/api/minwinbase/ns-minwinbase-filetime #[stable(feature = "metadata_ext", since = "1.1.0")] fn creation_time(&self) -> u64; @@ -387,7 +387,7 @@ pub trait MetadataExt { /// } /// ``` /// - /// [`FILETIME`]: https://docs.microsoft.com/en-us/windows/win32/api/minwinbase/ns-minwinbase-filetime + /// [`FILETIME`]: https://docs.microsoft.com/windows/win32/api/minwinbase/ns-minwinbase-filetime #[stable(feature = "metadata_ext", since = "1.1.0")] fn last_access_time(&self) -> u64; @@ -420,7 +420,7 @@ pub trait MetadataExt { /// } /// ``` /// - /// [`FILETIME`]: https://docs.microsoft.com/en-us/windows/win32/api/minwinbase/ns-minwinbase-filetime + /// [`FILETIME`]: https://docs.microsoft.com/windows/win32/api/minwinbase/ns-minwinbase-filetime #[stable(feature = "metadata_ext", since = "1.1.0")] fn last_write_time(&self) -> u64; @@ -472,10 +472,21 @@ pub trait MetadataExt { #[unstable(feature = "windows_by_handle", issue = "63010")] fn file_index(&self) -> Option; - /// Returns the change time, which is the last time file metadata was changed, such as - /// renames, attributes, etc - /// - /// This will return `None` if the `Metadata` instance was not created using the `FILE_BASIC_INFO` type. + /// Returns the value of the `ChangeTime{Low,High}` field from the + /// [`FILE_BASIC_INFO`] struct associated with the current file handle. + /// [`ChangeTime`] is the last time file metadata was changed, such as + /// renames, attributes, etc. + /// + /// This will return `None` if `Metadata` was populated without access to + /// [`FILE_BASIC_INFO`]. For example, the result of `std::fs::read_dir` + /// will be derived from [`WIN32_FIND_DATA`] which does not have access to + /// `ChangeTime`. + /// + /// [`FILE_BASIC_INFO`]: https://learn.microsoft.com/windows/win32/api/winbase/ns-winbase-file_basic_info + /// [`WIN32_FIND_DATA`]: https://learn.microsoft.com/windows/win32/api/minwinbase/ns-minwinbase-win32_find_dataw + /// [`FindFirstFile`]: https://learn.microsoft.com/windows/win32/api/fileapi/nf-fileapi-findfirstfilea + /// [`FindNextFile`]: https://learn.microsoft.com/windows/win32/api/fileapi/nf-fileapi-findnextfilea + /// [`ChangeTime`]: https://devblogs.microsoft.com/oldnewthing/20100709-00/?p=13463. #[unstable(feature = "windows_change_time", issue = "121478")] fn change_time(&self) -> Option; } From d243c8fbc4e55885f94a74c271aa9c8fe3425a03 Mon Sep 17 00:00:00 2001 From: Jubilee Young Date: Sat, 7 Sep 2024 18:29:08 -0700 Subject: [PATCH 0765/2194] compiler: Inform the solver of concurrency Parallel compilation of a program can cause unexpected event sequencing. Inform the solver when this is true so it can skip invalid asserts, then assert replaced solutions are equal if Some --- compiler/rustc_middle/src/ty/context.rs | 4 +++ compiler/rustc_type_ir/src/interner.rs | 5 ++++ .../src/search_graph/global_cache.rs | 14 +++++++--- .../rustc_type_ir/src/search_graph/mod.rs | 2 ++ .../global-cache-and-parallel-frontend.rs | 27 +++++++++++++++++++ .../global-cache-and-parallel-frontend.stderr | 24 +++++++++++++++++ 6 files changed, 72 insertions(+), 4 deletions(-) create mode 100644 tests/ui/traits/next-solver/global-cache-and-parallel-frontend.rs create mode 100644 tests/ui/traits/next-solver/global-cache-and-parallel-frontend.stderr diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 5334e7677664d..56fcfe8e798b1 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -181,6 +181,10 @@ impl<'tcx> Interner for TyCtxt<'tcx> { } } + fn evaluation_is_concurrent(&self) -> bool { + self.sess.threads() > 1 + } + fn expand_abstract_consts>>(self, t: T) -> T { self.expand_abstract_consts(t) } diff --git a/compiler/rustc_type_ir/src/interner.rs b/compiler/rustc_type_ir/src/interner.rs index f2492ede4f5ea..8dec2133a45dd 100644 --- a/compiler/rustc_type_ir/src/interner.rs +++ b/compiler/rustc_type_ir/src/interner.rs @@ -137,6 +137,8 @@ pub trait Interner: f: impl FnOnce(&mut search_graph::GlobalCache) -> R, ) -> R; + fn evaluation_is_concurrent(&self) -> bool; + fn expand_abstract_consts>(self, t: T) -> T; type GenericsOf: GenericsOf; @@ -404,4 +406,7 @@ impl search_graph::Cx for I { ) -> R { I::with_global_cache(self, mode, f) } + fn evaluation_is_concurrent(&self) -> bool { + self.evaluation_is_concurrent() + } } diff --git a/compiler/rustc_type_ir/src/search_graph/global_cache.rs b/compiler/rustc_type_ir/src/search_graph/global_cache.rs index 47f7cefac6ad1..0ce927b58bb38 100644 --- a/compiler/rustc_type_ir/src/search_graph/global_cache.rs +++ b/compiler/rustc_type_ir/src/search_graph/global_cache.rs @@ -44,22 +44,28 @@ impl GlobalCache { cx: X, input: X::Input, - result: X::Result, + origin_result: X::Result, dep_node: X::DepNodeIndex, additional_depth: usize, encountered_overflow: bool, nested_goals: NestedGoals, ) { - let result = cx.mk_tracked(result, dep_node); + let result = cx.mk_tracked(origin_result, dep_node); let entry = self.map.entry(input).or_default(); if encountered_overflow { let with_overflow = WithOverflow { nested_goals, result }; let prev = entry.with_overflow.insert(additional_depth, with_overflow); - assert!(prev.is_none()); + if let Some(prev) = &prev { + assert!(cx.evaluation_is_concurrent()); + assert_eq!(cx.get_tracked(&prev.result), origin_result); + } } else { let prev = entry.success.replace(Success { additional_depth, nested_goals, result }); - assert!(prev.is_none()); + if let Some(prev) = &prev { + assert!(cx.evaluation_is_concurrent()); + assert_eq!(cx.get_tracked(&prev.result), origin_result); + } } } diff --git a/compiler/rustc_type_ir/src/search_graph/mod.rs b/compiler/rustc_type_ir/src/search_graph/mod.rs index 418139c3aadc0..ac4d0795a92e8 100644 --- a/compiler/rustc_type_ir/src/search_graph/mod.rs +++ b/compiler/rustc_type_ir/src/search_graph/mod.rs @@ -53,6 +53,8 @@ pub trait Cx: Copy { mode: SolverMode, f: impl FnOnce(&mut GlobalCache) -> R, ) -> R; + + fn evaluation_is_concurrent(&self) -> bool; } pub trait Delegate { diff --git a/tests/ui/traits/next-solver/global-cache-and-parallel-frontend.rs b/tests/ui/traits/next-solver/global-cache-and-parallel-frontend.rs new file mode 100644 index 0000000000000..2b4f7ba9fa29e --- /dev/null +++ b/tests/ui/traits/next-solver/global-cache-and-parallel-frontend.rs @@ -0,0 +1,27 @@ +//@ compile-flags: -Zthreads=16 + +// original issue: https://github.com/rust-lang/rust/issues/129112 +// Previously, the "next" solver asserted that each successful solution is only obtained once. +// This test exhibits a repro that, with next-solver + -Zthreads, triggered that old assert. +// In the presence of multithreaded solving, it's possible to concurrently evaluate things twice, +// which leads to replacing already-solved solutions in the global solution cache! +// We assume this is fine if we check to make sure they are solved the same way each time. + +// This test only nondeterministically fails but that's okay, as it will be rerun by CI many times, +// so it should almost always fail before anything is merged. As other thread tests already exist, +// we already face this difficulty, probably. If we need to fix this by reducing the error margin, +// we should improve compiletest. + +#[derive(Clone, Eq)] //~ ERROR [E0277] +pub struct Struct(T); + +impl PartialEq for Struct +where + U: Into> + Clone +{ + fn eq(&self, _other: &U) -> bool { + todo!() + } +} + +fn main() {} diff --git a/tests/ui/traits/next-solver/global-cache-and-parallel-frontend.stderr b/tests/ui/traits/next-solver/global-cache-and-parallel-frontend.stderr new file mode 100644 index 0000000000000..65e7dd2ab34bc --- /dev/null +++ b/tests/ui/traits/next-solver/global-cache-and-parallel-frontend.stderr @@ -0,0 +1,24 @@ +error[E0277]: the trait bound `T: Clone` is not satisfied + --> $DIR/global-cache-and-parallel-frontend.rs:15:17 + | +LL | #[derive(Clone, Eq)] + | ^^ the trait `Clone` is not implemented for `T`, which is required by `Struct: PartialEq` + | +note: required for `Struct` to implement `PartialEq` + --> $DIR/global-cache-and-parallel-frontend.rs:18:19 + | +LL | impl PartialEq for Struct + | ----- ^^^^^^^^^^^^ ^^^^^^^^^ + | | + | unsatisfied trait bound introduced here +note: required by a bound in `Eq` + --> $SRC_DIR/core/src/cmp.rs:LL:COL + = note: this error originates in the derive macro `Eq` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider restricting type parameter `T` + | +LL | pub struct Struct(T); + | +++++++++++++++++++ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0277`. From 6d61dfd2e48d4f183ca4bca4aaa60b2e2ffb4fa0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Le=C3=B3n=20Orell=20Valerian=20Liehr?= Date: Mon, 9 Sep 2024 22:35:10 +0200 Subject: [PATCH 0766/2194] rustdoc: add two regression tests --- .../projection-as-union-type-error.rs | 14 +++++++++++ .../projection-as-union-type-error.stderr | 15 ++++++++++++ ...ias-impl-trait-declaration-too-subtle-2.rs | 23 +++++++++++++++++++ 3 files changed, 52 insertions(+) create mode 100644 tests/rustdoc-ui/projection-as-union-type-error.rs create mode 100644 tests/rustdoc-ui/projection-as-union-type-error.stderr create mode 100644 tests/rustdoc-ui/recursive-type-alias-impl-trait-declaration-too-subtle-2.rs diff --git a/tests/rustdoc-ui/projection-as-union-type-error.rs b/tests/rustdoc-ui/projection-as-union-type-error.rs new file mode 100644 index 0000000000000..d1d2e72249dc0 --- /dev/null +++ b/tests/rustdoc-ui/projection-as-union-type-error.rs @@ -0,0 +1,14 @@ +// Test to ensure that there is no ICE when normalizing a projection. +// See also . +// issue: rust-lang/rust#107872 + +pub trait Identity { + type Identity; +} + +pub type Foo = u8; + +pub union Bar { + a: ::Identity, //~ ERROR the trait bound `u8: Identity` is not satisfied + b: u8, +} diff --git a/tests/rustdoc-ui/projection-as-union-type-error.stderr b/tests/rustdoc-ui/projection-as-union-type-error.stderr new file mode 100644 index 0000000000000..32598015864cb --- /dev/null +++ b/tests/rustdoc-ui/projection-as-union-type-error.stderr @@ -0,0 +1,15 @@ +error[E0277]: the trait bound `u8: Identity` is not satisfied + --> $DIR/projection-as-union-type-error.rs:12:9 + | +LL | a: ::Identity, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Identity` is not implemented for `u8` + | +help: this trait has no implementations, consider adding one + --> $DIR/projection-as-union-type-error.rs:5:1 + | +LL | pub trait Identity { + | ^^^^^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/rustdoc-ui/recursive-type-alias-impl-trait-declaration-too-subtle-2.rs b/tests/rustdoc-ui/recursive-type-alias-impl-trait-declaration-too-subtle-2.rs new file mode 100644 index 0000000000000..9f8053d553876 --- /dev/null +++ b/tests/rustdoc-ui/recursive-type-alias-impl-trait-declaration-too-subtle-2.rs @@ -0,0 +1,23 @@ +// issue: rust-lang/rust#98250 +//@ check-pass + +#![feature(type_alias_impl_trait)] + +mod foo { + pub type Foo = impl PartialEq<(Foo, i32)>; + + fn foo() -> Foo { + super::Bar + } +} +use foo::Foo; + +struct Bar; + +impl PartialEq<(Foo, i32)> for Bar { + fn eq(&self, _other: &(Foo, i32)) -> bool { + true + } +} + +fn main() {} From a0a89e55387dc4291442e5fc401bd1e35b94fbe8 Mon Sep 17 00:00:00 2001 From: Julius Liu Date: Mon, 9 Sep 2024 13:56:41 -0700 Subject: [PATCH 0767/2194] chore: removing supporting links in favor of existing doc-comment style --- library/std/src/os/windows/fs.rs | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/library/std/src/os/windows/fs.rs b/library/std/src/os/windows/fs.rs index 285d9c3fc78d6..d03f9e0e330dd 100644 --- a/library/std/src/os/windows/fs.rs +++ b/library/std/src/os/windows/fs.rs @@ -472,21 +472,14 @@ pub trait MetadataExt { #[unstable(feature = "windows_by_handle", issue = "63010")] fn file_index(&self) -> Option; - /// Returns the value of the `ChangeTime{Low,High}` field from the - /// [`FILE_BASIC_INFO`] struct associated with the current file handle. - /// [`ChangeTime`] is the last time file metadata was changed, such as - /// renames, attributes, etc. + /// Returns the value of the `ChangeTime{Low,High}` fields of this metadata. /// - /// This will return `None` if `Metadata` was populated without access to - /// [`FILE_BASIC_INFO`]. For example, the result of `std::fs::read_dir` - /// will be derived from [`WIN32_FIND_DATA`] which does not have access to - /// `ChangeTime`. + /// `ChangeTime` is the last time file metadata was changed, such as + /// renames, attributes, etc. /// - /// [`FILE_BASIC_INFO`]: https://learn.microsoft.com/windows/win32/api/winbase/ns-winbase-file_basic_info - /// [`WIN32_FIND_DATA`]: https://learn.microsoft.com/windows/win32/api/minwinbase/ns-minwinbase-win32_find_dataw - /// [`FindFirstFile`]: https://learn.microsoft.com/windows/win32/api/fileapi/nf-fileapi-findfirstfilea - /// [`FindNextFile`]: https://learn.microsoft.com/windows/win32/api/fileapi/nf-fileapi-findnextfilea - /// [`ChangeTime`]: https://devblogs.microsoft.com/oldnewthing/20100709-00/?p=13463. + /// This will return `None` if `Metadata` instance was created from a call to + /// `DirEntry::metadata` or if the `target_vendor` is outside the current platform + /// support for this api. #[unstable(feature = "windows_change_time", issue = "121478")] fn change_time(&self) -> Option; } From 8235af07d21d60012acbd217f24049e1386081bd Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 28 Aug 2024 08:24:10 +1000 Subject: [PATCH 0768/2194] Improve comment formatting. By reflowing comment lines that are too long, and a few that are very short. Plus some other very minor formatting tweaks. --- compiler/rustc_mir_transform/src/add_retag.rs | 10 +++-- .../src/check_const_item_mutation.rs | 1 + compiler/rustc_mir_transform/src/copy_prop.rs | 3 +- .../rustc_mir_transform/src/coverage/mod.rs | 3 +- .../src/dataflow_const_prop.rs | 3 +- .../src/deduce_param_attrs.rs | 6 +-- .../src/deduplicate_blocks.rs | 7 ++-- .../src/early_otherwise_branch.rs | 4 +- .../src/elaborate_drops.rs | 16 ++++---- .../src/ffi_unwind_calls.rs | 5 ++- .../src/function_item_references.rs | 4 +- compiler/rustc_mir_transform/src/gvn.rs | 10 +++-- compiler/rustc_mir_transform/src/inline.rs | 3 +- .../src/known_panics_lint.rs | 11 +++--- .../rustc_mir_transform/src/large_enums.rs | 5 ++- compiler/rustc_mir_transform/src/lib.rs | 31 +++++++++------ .../rustc_mir_transform/src/match_branches.rs | 14 ++++--- .../src/mentioned_items.rs | 4 +- compiler/rustc_mir_transform/src/prettify.rs | 4 +- .../rustc_mir_transform/src/promote_consts.rs | 38 ++++++++++--------- .../src/remove_uninit_drops.rs | 5 ++- .../rustc_mir_transform/src/reveal_all.rs | 6 +-- compiler/rustc_mir_transform/src/shim.rs | 3 +- .../src/simplify_comparison_integral.rs | 22 +++++++---- .../src/unreachable_enum_branching.rs | 6 +-- .../src/unreachable_prop.rs | 8 ++-- compiler/rustc_mir_transform/src/validate.rs | 30 ++++++++------- 27 files changed, 151 insertions(+), 111 deletions(-) diff --git a/compiler/rustc_mir_transform/src/add_retag.rs b/compiler/rustc_mir_transform/src/add_retag.rs index 794e85fbfedfb..8ad364ed05502 100644 --- a/compiler/rustc_mir_transform/src/add_retag.rs +++ b/compiler/rustc_mir_transform/src/add_retag.rs @@ -60,7 +60,9 @@ impl<'tcx> crate::MirPass<'tcx> for AddRetag { let basic_blocks = body.basic_blocks.as_mut(); let local_decls = &body.local_decls; let needs_retag = |place: &Place<'tcx>| { - !place.is_indirect_first_projection() // we're not really interested in stores to "outside" locations, they are hard to keep track of anyway + // We're not really interested in stores to "outside" locations, they are hard to keep + // track of anyway. + !place.is_indirect_first_projection() && may_contain_reference(place.ty(&*local_decls, tcx).ty, /*depth*/ 3, tcx) && !local_decls[place.local].is_deref_temp() }; @@ -129,9 +131,9 @@ impl<'tcx> crate::MirPass<'tcx> for AddRetag { StatementKind::Assign(box (ref place, ref rvalue)) => { let add_retag = match rvalue { // Ptr-creating operations already do their own internal retagging, no - // need to also add a retag statement. - // *Except* if we are deref'ing a Box, because those get desugared to directly working - // with the inner raw pointer! That's relevant for `RawPtr` as Miri otherwise makes it + // need to also add a retag statement. *Except* if we are deref'ing a + // Box, because those get desugared to directly working with the inner + // raw pointer! That's relevant for `RawPtr` as Miri otherwise makes it // a NOP when the original pointer is already raw. Rvalue::RawPtr(_mutbl, place) => { // Using `is_box_global` here is a bit sketchy: if this code is diff --git a/compiler/rustc_mir_transform/src/check_const_item_mutation.rs b/compiler/rustc_mir_transform/src/check_const_item_mutation.rs index 234ed8206f5d5..048dd9ccb8f3c 100644 --- a/compiler/rustc_mir_transform/src/check_const_item_mutation.rs +++ b/compiler/rustc_mir_transform/src/check_const_item_mutation.rs @@ -123,6 +123,7 @@ impl<'tcx> Visitor<'tcx> for ConstMutationChecker<'_, 'tcx> { self.super_statement(stmt, loc); self.target_local = None; } + fn visit_rvalue(&mut self, rvalue: &Rvalue<'tcx>, loc: Location) { if let Rvalue::Ref(_, BorrowKind::Mut { .. }, place) = rvalue { let local = place.local; diff --git a/compiler/rustc_mir_transform/src/copy_prop.rs b/compiler/rustc_mir_transform/src/copy_prop.rs index dc4ee58ea83e3..1cb56d29b85e0 100644 --- a/compiler/rustc_mir_transform/src/copy_prop.rs +++ b/compiler/rustc_mir_transform/src/copy_prop.rs @@ -140,7 +140,8 @@ impl<'tcx> MutVisitor<'tcx> for Replacer<'_, 'tcx> { fn visit_operand(&mut self, operand: &mut Operand<'tcx>, loc: Location) { if let Operand::Move(place) = *operand - // A move out of a projection of a copy is equivalent to a copy of the original projection. + // A move out of a projection of a copy is equivalent to a copy of the original + // projection. && !place.is_indirect_first_projection() && !self.fully_moved.contains(place.local) { diff --git a/compiler/rustc_mir_transform/src/coverage/mod.rs b/compiler/rustc_mir_transform/src/coverage/mod.rs index 042f589768a99..f78fc7931f9f9 100644 --- a/compiler/rustc_mir_transform/src/coverage/mod.rs +++ b/compiler/rustc_mir_transform/src/coverage/mod.rs @@ -279,7 +279,8 @@ fn inject_mcdc_statements<'tcx>( basic_coverage_blocks: &CoverageGraph, extracted_mappings: &ExtractedMappings, ) { - // Inject test vector update first because `inject_statement` always insert new statement at head. + // Inject test vector update first because `inject_statement` always insert new statement at + // head. for &mappings::MCDCDecision { span: _, ref end_bcbs, diff --git a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs index 79f12be4bc353..7ac019ce81216 100644 --- a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs +++ b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs @@ -647,7 +647,8 @@ fn try_write_constant<'tcx>( ty::FnDef(..) => {} // Those are scalars, must be handled above. - ty::Bool | ty::Int(_) | ty::Uint(_) | ty::Float(_) | ty::Char => throw_machine_stop_str!("primitive type with provenance"), + ty::Bool | ty::Int(_) | ty::Uint(_) | ty::Float(_) | ty::Char => + throw_machine_stop_str!("primitive type with provenance"), ty::Tuple(elem_tys) => { for (i, elem) in elem_tys.iter().enumerate() { diff --git a/compiler/rustc_mir_transform/src/deduce_param_attrs.rs b/compiler/rustc_mir_transform/src/deduce_param_attrs.rs index e870a71b05aa7..c645bbee08a54 100644 --- a/compiler/rustc_mir_transform/src/deduce_param_attrs.rs +++ b/compiler/rustc_mir_transform/src/deduce_param_attrs.rs @@ -42,9 +42,9 @@ impl<'tcx> Visitor<'tcx> for DeduceReadOnly { } PlaceContext::NonMutatingUse(NonMutatingUseContext::RawBorrow) => { // Whether mutating though a `&raw const` is allowed is still undecided, so we - // disable any sketchy `readonly` optimizations for now. - // But we only need to do this if the pointer would point into the argument. - // IOW: for indirect places, like `&raw (*local).field`, this surely cannot mutate `local`. + // disable any sketchy `readonly` optimizations for now. But we only need to do + // this if the pointer would point into the argument. IOW: for indirect places, + // like `&raw (*local).field`, this surely cannot mutate `local`. !place.is_indirect() } PlaceContext::NonMutatingUse(..) | PlaceContext::NonUse(..) => { diff --git a/compiler/rustc_mir_transform/src/deduplicate_blocks.rs b/compiler/rustc_mir_transform/src/deduplicate_blocks.rs index c8179d513c7ce..ad204e76d0d15 100644 --- a/compiler/rustc_mir_transform/src/deduplicate_blocks.rs +++ b/compiler/rustc_mir_transform/src/deduplicate_blocks.rs @@ -69,8 +69,8 @@ fn find_duplicates(body: &Body<'_>) -> FxHashMap { // For example, if bb1, bb2 and bb3 are duplicates, we will first insert bb3 in same_hashes. // Then we will see that bb2 is a duplicate of bb3, // and insert bb2 with the replacement bb3 in the duplicates list. - // When we see bb1, we see that it is a duplicate of bb3, and therefore insert it in the duplicates list - // with replacement bb3. + // When we see bb1, we see that it is a duplicate of bb3, and therefore insert it in the + // duplicates list with replacement bb3. // When the duplicates are removed, we will end up with only bb3. for (bb, bbd) in body.basic_blocks.iter_enumerated().rev().filter(|(_, bbd)| !bbd.is_cleanup) { // Basic blocks can get really big, so to avoid checking for duplicates in basic blocks @@ -105,7 +105,8 @@ struct BasicBlockHashable<'tcx, 'a> { impl Hash for BasicBlockHashable<'_, '_> { fn hash(&self, state: &mut H) { hash_statements(state, self.basic_block_data.statements.iter()); - // Note that since we only hash the kind, we lose span information if we deduplicate the blocks + // Note that since we only hash the kind, we lose span information if we deduplicate the + // blocks. self.basic_block_data.terminator().kind.hash(state); } } diff --git a/compiler/rustc_mir_transform/src/early_otherwise_branch.rs b/compiler/rustc_mir_transform/src/early_otherwise_branch.rs index 3884321df2a2c..704ed508b22a8 100644 --- a/compiler/rustc_mir_transform/src/early_otherwise_branch.rs +++ b/compiler/rustc_mir_transform/src/early_otherwise_branch.rs @@ -261,8 +261,8 @@ fn evaluate_candidate<'tcx>( // }; // ``` // - // Hoisting the `discriminant(Q)` out of the `A` arm causes us to compute the discriminant of an - // invalid value, which is UB. + // Hoisting the `discriminant(Q)` out of the `A` arm causes us to compute the discriminant + // of an invalid value, which is UB. // In order to fix this, **we would either need to show that the discriminant computation of // `place` is computed in all branches**. // FIXME(#95162) For the moment, we adopt a conservative approach and diff --git a/compiler/rustc_mir_transform/src/elaborate_drops.rs b/compiler/rustc_mir_transform/src/elaborate_drops.rs index cb729792dc538..42d13fa3613ab 100644 --- a/compiler/rustc_mir_transform/src/elaborate_drops.rs +++ b/compiler/rustc_mir_transform/src/elaborate_drops.rs @@ -20,8 +20,8 @@ use tracing::{debug, instrument}; use crate::deref_separator::deref_finder; /// During MIR building, Drop terminators are inserted in every place where a drop may occur. -/// However, in this phase, the presence of these terminators does not guarantee that a destructor will run, -/// as the target of the drop may be uninitialized. +/// However, in this phase, the presence of these terminators does not guarantee that a destructor +/// will run, as the target of the drop may be uninitialized. /// In general, the compiler cannot determine at compile time whether a destructor will run or not. /// /// At a high level, this pass refines Drop to only run the destructor if the @@ -30,10 +30,10 @@ use crate::deref_separator::deref_finder; /// Once this is complete, Drop terminators in the MIR correspond to a call to the "drop glue" or /// "drop shim" for the type of the dropped place. /// -/// This pass relies on dropped places having an associated move path, which is then used to determine -/// the initialization status of the place and its descendants. -/// It's worth noting that a MIR containing a Drop without an associated move path is probably ill formed, -/// as it would allow running a destructor on a place behind a reference: +/// This pass relies on dropped places having an associated move path, which is then used to +/// determine the initialization status of the place and its descendants. +/// It's worth noting that a MIR containing a Drop without an associated move path is probably ill +/// formed, as it would allow running a destructor on a place behind a reference: /// /// ```text /// fn drop_term(t: &mut T) { @@ -377,8 +377,8 @@ impl<'a, 'tcx> ElaborateDropsCtxt<'a, 'tcx> { ); } // A drop and replace behind a pointer/array/whatever. - // The borrow checker requires that these locations are initialized before the assignment, - // so we just leave an unconditional drop. + // The borrow checker requires that these locations are initialized before the + // assignment, so we just leave an unconditional drop. assert!(!data.is_cleanup); } } diff --git a/compiler/rustc_mir_transform/src/ffi_unwind_calls.rs b/compiler/rustc_mir_transform/src/ffi_unwind_calls.rs index 81875e3d01246..8490b7e235818 100644 --- a/compiler/rustc_mir_transform/src/ffi_unwind_calls.rs +++ b/compiler/rustc_mir_transform/src/ffi_unwind_calls.rs @@ -60,8 +60,9 @@ fn has_ffi_unwind_calls(tcx: TyCtxt<'_>, local_def_id: LocalDefId) -> bool { let fn_def_id = match ty.kind() { ty::FnPtr(..) => None, &ty::FnDef(def_id, _) => { - // Rust calls cannot themselves create foreign unwinds (even if they use a non-Rust ABI). - // So the leak of the foreign unwind into Rust can only be elsewhere, not here. + // Rust calls cannot themselves create foreign unwinds (even if they use a non-Rust + // ABI). So the leak of the foreign unwind into Rust can only be elsewhere, not + // here. if !tcx.is_foreign_item(def_id) { continue; } diff --git a/compiler/rustc_mir_transform/src/function_item_references.rs b/compiler/rustc_mir_transform/src/function_item_references.rs index 0efaa172e0c6f..eb09a7d3b2114 100644 --- a/compiler/rustc_mir_transform/src/function_item_references.rs +++ b/compiler/rustc_mir_transform/src/function_item_references.rs @@ -92,8 +92,8 @@ impl<'tcx> FunctionItemRefChecker<'_, 'tcx> { { let mut span = self.nth_arg_span(args, arg_num); if span.from_expansion() { - // The operand's ctxt wouldn't display the lint since it's inside a macro so - // we have to use the callsite's ctxt. + // The operand's ctxt wouldn't display the lint since it's + // inside a macro so we have to use the callsite's ctxt. let callsite_ctxt = span.source_callsite().ctxt(); span = span.with_ctxt(callsite_ctxt); } diff --git a/compiler/rustc_mir_transform/src/gvn.rs b/compiler/rustc_mir_transform/src/gvn.rs index e5d2b13efd8fe..715461de06482 100644 --- a/compiler/rustc_mir_transform/src/gvn.rs +++ b/compiler/rustc_mir_transform/src/gvn.rs @@ -139,8 +139,8 @@ fn propagate_ssa<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { // Try to get some insight. AssignedValue::Rvalue(rvalue) => { let value = state.simplify_rvalue(rvalue, location); - // FIXME(#112651) `rvalue` may have a subtype to `local`. We can only mark `local` as - // reusable if we have an exact type match. + // FIXME(#112651) `rvalue` may have a subtype to `local`. We can only mark + // `local` as reusable if we have an exact type match. if state.local_decls[local].ty != rvalue.ty(state.local_decls, tcx) { return; } @@ -480,7 +480,8 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { let pointer = self.evaluated[local].as_ref()?; let mut mplace = self.ecx.deref_pointer(pointer).ok()?; for proj in place.projection.iter().skip(1) { - // We have no call stack to associate a local with a value, so we cannot interpret indexing. + // We have no call stack to associate a local with a value, so we cannot + // interpret indexing. if matches!(proj, ProjectionElem::Index(_)) { return None; } @@ -1382,7 +1383,8 @@ fn op_to_prop_const<'tcx>( return Some(ConstValue::ZeroSized); } - // Do not synthetize too large constants. Codegen will just memcpy them, which we'd like to avoid. + // Do not synthetize too large constants. Codegen will just memcpy them, which we'd like to + // avoid. if !matches!(op.layout.abi, Abi::Scalar(..) | Abi::ScalarPair(..)) { return None; } diff --git a/compiler/rustc_mir_transform/src/inline.rs b/compiler/rustc_mir_transform/src/inline.rs index 03ef808efecb6..870cb180ce1be 100644 --- a/compiler/rustc_mir_transform/src/inline.rs +++ b/compiler/rustc_mir_transform/src/inline.rs @@ -568,7 +568,8 @@ impl<'tcx> Inliner<'tcx> { // if the no-attribute function ends up with the same instruction set anyway. return Err("Cannot move inline-asm across instruction sets"); } else if let TerminatorKind::TailCall { .. } = term.kind { - // FIXME(explicit_tail_calls): figure out how exactly functions containing tail calls can be inlined (and if they even should) + // FIXME(explicit_tail_calls): figure out how exactly functions containing tail + // calls can be inlined (and if they even should) return Err("can't inline functions with tail calls"); } else { work_list.extend(term.successors()) diff --git a/compiler/rustc_mir_transform/src/known_panics_lint.rs b/compiler/rustc_mir_transform/src/known_panics_lint.rs index e964310c5429e..46b17c3c7e04d 100644 --- a/compiler/rustc_mir_transform/src/known_panics_lint.rs +++ b/compiler/rustc_mir_transform/src/known_panics_lint.rs @@ -1,8 +1,6 @@ -//! A lint that checks for known panics like -//! overflows, division by zero, -//! out-of-bound access etc. -//! Uses const propagation to determine the -//! values of operands during checks. +//! A lint that checks for known panics like overflows, division by zero, +//! out-of-bound access etc. Uses const propagation to determine the values of +//! operands during checks. use std::fmt::Debug; @@ -562,7 +560,8 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { let val = self.use_ecx(|this| this.ecx.binary_op(bin_op, &left, &right))?; if matches!(val.layout.abi, Abi::ScalarPair(..)) { - // FIXME `Value` should properly support pairs in `Immediate`... but currently it does not. + // FIXME `Value` should properly support pairs in `Immediate`... but currently + // it does not. let (val, overflow) = val.to_pair(&self.ecx); Value::Aggregate { variant: VariantIdx::ZERO, diff --git a/compiler/rustc_mir_transform/src/large_enums.rs b/compiler/rustc_mir_transform/src/large_enums.rs index f61cf236f77cc..45edcff29eb28 100644 --- a/compiler/rustc_mir_transform/src/large_enums.rs +++ b/compiler/rustc_mir_transform/src/large_enums.rs @@ -16,8 +16,7 @@ use rustc_target::abi::{HasDataLayout, Size, TagEncoding, Variants}; /// Large([u32; 1024]), /// } /// ``` -/// Instead of emitting moves of the large variant, -/// Perform a memcpy instead. +/// Instead of emitting moves of the large variant, perform a memcpy instead. /// Based off of [this HackMD](https://hackmd.io/@ft4bxUsFT5CEUBmRKYHr7w/rJM8BBPzD). /// /// In summary, what this does is at runtime determine which enum variant is active, @@ -34,6 +33,7 @@ impl<'tcx> crate::MirPass<'tcx> for EnumSizeOpt { // https://github.com/rust-lang/rust/pull/85158#issuecomment-1101836457 sess.opts.unstable_opts.unsound_mir_opts || sess.mir_opt_level() >= 3 } + fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { // NOTE: This pass may produce different MIR based on the alignment of the target // platform, but it will still be valid. @@ -116,6 +116,7 @@ impl EnumSizeOpt { let alloc = tcx.reserve_and_set_memory_alloc(tcx.mk_const_alloc(alloc)); Some((*adt_def, num_discrs, *alloc_cache.entry(ty).or_insert(alloc))) } + fn optim<'tcx>(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { let mut alloc_cache = FxHashMap::default(); let body_did = body.source.def_id(); diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs index 0bbbf047f634c..dcfcad7cc7c5b 100644 --- a/compiler/rustc_mir_transform/src/lib.rs +++ b/compiler/rustc_mir_transform/src/lib.rs @@ -168,8 +168,9 @@ fn remap_mir_for_const_eval_select<'tcx>( let (method, place): (fn(Place<'tcx>) -> Operand<'tcx>, Place<'tcx>) = match tupled_args.node { Operand::Constant(_) => { - // there is no good way of extracting a tuple arg from a constant (const generic stuff) - // so we just create a temporary and deconstruct that. + // There is no good way of extracting a tuple arg from a constant + // (const generic stuff) so we just create a temporary and deconstruct + // that. let local = body.local_decls.push(LocalDecl::new(ty, fn_span)); bb.statements.push(Statement { source_info: SourceInfo::outermost(fn_span), @@ -480,7 +481,8 @@ pub fn run_analysis_to_runtime_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<' &[&remove_uninit_drops::RemoveUninitDrops, &simplify::SimplifyCfg::RemoveFalseEdges], None, ); - check_consts::post_drop_elaboration::check_live_drops(tcx, body); // FIXME: make this a MIR lint + // FIXME: make this a MIR lint + check_consts::post_drop_elaboration::check_live_drops(tcx, body); } debug!("runtime_mir_lowering({:?})", did); @@ -509,10 +511,12 @@ fn run_analysis_cleanup_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { /// Returns the sequence of passes that lowers analysis to runtime MIR. fn run_runtime_lowering_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { let passes: &[&dyn MirPass<'tcx>] = &[ - // These next passes must be executed together + // These next passes must be executed together. &add_call_guards::CriticalCallEdges, - &reveal_all::RevealAll, // has to be done before drop elaboration, since we need to drop opaque types, too. - &add_subtyping_projections::Subtyper, // calling this after reveal_all ensures that we don't deal with opaque types + // Must be done before drop elaboration because we need to drop opaque types, too. + &reveal_all::RevealAll, + // Calling this after reveal_all ensures that we don't deal with opaque types. + &add_subtyping_projections::Subtyper, &elaborate_drops::ElaborateDrops, // This will remove extraneous landing pads which are no longer // necessary as well as forcing any call in a non-unwinding @@ -521,8 +525,8 @@ fn run_runtime_lowering_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { // AddMovesForPackedDrops needs to run after drop // elaboration. &add_moves_for_packed_drops::AddMovesForPackedDrops, - // `AddRetag` needs to run after `ElaborateDrops` but before `ElaborateBoxDerefs`. Otherwise it should run fairly late, - // but before optimizations begin. + // `AddRetag` needs to run after `ElaborateDrops` but before `ElaborateBoxDerefs`. + // Otherwise it should run fairly late, but before optimizations begin. &add_retag::AddRetag, &elaborate_box_derefs::ElaborateBoxDerefs, &coroutine::StateTransform, @@ -563,13 +567,15 @@ fn run_optimization_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { // Before inlining: trim down MIR with passes to reduce inlining work. // Has to be done before inlining, otherwise actual call will be almost always inlined. - // Also simple, so can just do first + // Also simple, so can just do first. &lower_slice_len::LowerSliceLenCalls, - // Perform instsimplify before inline to eliminate some trivial calls (like clone shims). + // Perform instsimplify before inline to eliminate some trivial calls (like clone + // shims). &instsimplify::InstSimplify::BeforeInline, // Perform inlining, which may add a lot of code. &inline::Inline, - // Code from other crates may have storage markers, so this needs to happen after inlining. + // Code from other crates may have storage markers, so this needs to happen after + // inlining. &remove_storage_markers::RemoveStorageMarkers, // Inlining and instantiation may introduce ZST and useless drops. &remove_zsts::RemoveZsts, @@ -586,7 +592,8 @@ fn run_optimization_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { &match_branches::MatchBranchSimplification, // inst combine is after MatchBranchSimplification to clean up Ne(_1, false) &multiple_return_terminators::MultipleReturnTerminators, - // After simplifycfg, it allows us to discover new opportunities for peephole optimizations. + // After simplifycfg, it allows us to discover new opportunities for peephole + // optimizations. &instsimplify::InstSimplify::AfterSimplifyCfg, &simplify::SimplifyLocals::BeforeConstProp, &dead_store_elimination::DeadStoreElimination::Initial, diff --git a/compiler/rustc_mir_transform/src/match_branches.rs b/compiler/rustc_mir_transform/src/match_branches.rs index 2a2616b20a6de..0f981425cfd0d 100644 --- a/compiler/rustc_mir_transform/src/match_branches.rs +++ b/compiler/rustc_mir_transform/src/match_branches.rs @@ -57,8 +57,9 @@ impl<'tcx> crate::MirPass<'tcx> for MatchBranchSimplification { } trait SimplifyMatch<'tcx> { - /// Simplifies a match statement, returning true if the simplification succeeds, false otherwise. - /// Generic code is written here, and we generally don't need a custom implementation. + /// Simplifies a match statement, returning true if the simplification succeeds, false + /// otherwise. Generic code is written here, and we generally don't need a custom + /// implementation. fn simplify( &mut self, tcx: TyCtxt<'tcx>, @@ -240,7 +241,8 @@ impl<'tcx> SimplifyMatch<'tcx> for SimplifyToIf { // Same value in both blocks. Use statement as is. patch.add_statement(parent_end, f.kind.clone()); } else { - // Different value between blocks. Make value conditional on switch condition. + // Different value between blocks. Make value conditional on switch + // condition. let size = tcx.layout_of(param_env.and(discr_ty)).unwrap().size; let const_cmp = Operand::const_from_scalar( tcx, @@ -394,14 +396,16 @@ impl<'tcx> SimplifyMatch<'tcx> for SimplifyToExp { return None; } - // We first compare the two branches, and then the other branches need to fulfill the same conditions. + // We first compare the two branches, and then the other branches need to fulfill the same + // conditions. let mut expected_transform_kinds = Vec::new(); for (f, s) in iter::zip(first_stmts, second_stmts) { let compare_type = match (&f.kind, &s.kind) { // If two statements are exactly the same, we can optimize. (f_s, s_s) if f_s == s_s => ExpectedTransformKind::Same(f_s), - // If two statements are assignments with the match values to the same place, we can optimize. + // If two statements are assignments with the match values to the same place, we + // can optimize. ( StatementKind::Assign(box (lhs_f, Rvalue::Use(Operand::Constant(f_c)))), StatementKind::Assign(box (lhs_s, Rvalue::Use(Operand::Constant(s_c)))), diff --git a/compiler/rustc_mir_transform/src/mentioned_items.rs b/compiler/rustc_mir_transform/src/mentioned_items.rs index 7f9d0a5b6985c..4402e0dd42d40 100644 --- a/compiler/rustc_mir_transform/src/mentioned_items.rs +++ b/compiler/rustc_mir_transform/src/mentioned_items.rs @@ -82,7 +82,9 @@ impl<'tcx> Visitor<'tcx> for MentionedItemsVisitor<'_, 'tcx> { source_ty.builtin_deref(true).map(|t| t.kind()), target_ty.builtin_deref(true).map(|t| t.kind()), ) { - (Some(ty::Array(..)), Some(ty::Str | ty::Slice(..))) => false, // &str/&[T] unsizing + // &str/&[T] unsizing + (Some(ty::Array(..)), Some(ty::Str | ty::Slice(..))) => false, + _ => true, }; if may_involve_vtable { diff --git a/compiler/rustc_mir_transform/src/prettify.rs b/compiler/rustc_mir_transform/src/prettify.rs index ef011d230c279..937c207776b35 100644 --- a/compiler/rustc_mir_transform/src/prettify.rs +++ b/compiler/rustc_mir_transform/src/prettify.rs @@ -63,7 +63,7 @@ impl<'tcx> crate::MirPass<'tcx> for ReorderLocals { finder.visit_basic_block_data(bb, bbd); } - // track everything in case there are some locals that we never saw, + // Track everything in case there are some locals that we never saw, // such as in non-block things like debug info or in non-uses. for local in body.local_decls.indices() { finder.track(local); @@ -87,7 +87,7 @@ impl<'tcx> crate::MirPass<'tcx> for ReorderLocals { fn permute(data: &mut IndexVec, map: &IndexSlice) { // FIXME: It would be nice to have a less-awkward way to apply permutations, - // but I don't know one that exists. `sort_by_cached_key` has logic for it + // but I don't know one that exists. `sort_by_cached_key` has logic for it // internally, but not in a way that we're allowed to use here. let mut enumerated: Vec<_> = std::mem::take(data).into_iter_enumerated().collect(); enumerated.sort_by_key(|p| map[p.0]); diff --git a/compiler/rustc_mir_transform/src/promote_consts.rs b/compiler/rustc_mir_transform/src/promote_consts.rs index 65309f63d5937..c968053a6d6e8 100644 --- a/compiler/rustc_mir_transform/src/promote_consts.rs +++ b/compiler/rustc_mir_transform/src/promote_consts.rs @@ -1,16 +1,14 @@ //! A pass that promotes borrows of constant rvalues. //! -//! The rvalues considered constant are trees of temps, -//! each with exactly one initialization, and holding -//! a constant value with no interior mutability. -//! They are placed into a new MIR constant body in -//! `promoted` and the borrow rvalue is replaced with -//! a `Literal::Promoted` using the index into `promoted` -//! of that constant MIR. +//! The rvalues considered constant are trees of temps, each with exactly one +//! initialization, and holding a constant value with no interior mutability. +//! They are placed into a new MIR constant body in `promoted` and the borrow +//! rvalue is replaced with a `Literal::Promoted` using the index into +//! `promoted` of that constant MIR. //! -//! This pass assumes that every use is dominated by an -//! initialization and can otherwise silence errors, if -//! move analysis runs after promotion on broken MIR. +//! This pass assumes that every use is dominated by an initialization and can +//! otherwise silence errors, if move analysis runs after promotion on broken +//! MIR. use std::assert_matches::assert_matches; use std::cell::Cell; @@ -386,7 +384,8 @@ impl<'tcx> Validator<'_, 'tcx> { fn validate_ref(&mut self, kind: BorrowKind, place: &Place<'tcx>) -> Result<(), Unpromotable> { match kind { // Reject these borrow types just to be safe. - // FIXME(RalfJung): could we allow them? Should we? No point in it until we have a usecase. + // FIXME(RalfJung): could we allow them? Should we? No point in it until we have a + // usecase. BorrowKind::Fake(_) | BorrowKind::Mut { kind: MutBorrowKind::ClosureCapture } => { return Err(Unpromotable); } @@ -468,7 +467,8 @@ impl<'tcx> Validator<'_, 'tcx> { let lhs_ty = lhs.ty(self.body, self.tcx); if let ty::RawPtr(_, _) | ty::FnPtr(..) = lhs_ty.kind() { - // Raw and fn pointer operations are not allowed inside consts and thus not promotable. + // Raw and fn pointer operations are not allowed inside consts and thus not + // promotable. assert_matches!( op, BinOp::Eq @@ -498,7 +498,8 @@ impl<'tcx> Validator<'_, 'tcx> { Some(x) if x != 0 => {} // okay _ => return Err(Unpromotable), // value not known or 0 -- not okay } - // Furthermore, for signed division, we also have to exclude `int::MIN / -1`. + // Furthermore, for signed division, we also have to exclude `int::MIN / + // -1`. if lhs_ty.is_signed() { match rhs_val.map(|x| x.to_int(sz)) { Some(-1) | None => { @@ -512,8 +513,11 @@ impl<'tcx> Validator<'_, 'tcx> { }; let lhs_min = sz.signed_int_min(); match lhs_val.map(|x| x.to_int(sz)) { - Some(x) if x != lhs_min => {} // okay - _ => return Err(Unpromotable), // value not known or int::MIN -- not okay + // okay + Some(x) if x != lhs_min => {} + + // value not known or int::MIN -- not okay + _ => return Err(Unpromotable), } } _ => {} @@ -815,8 +819,8 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> { TerminatorKind::Call { mut func, mut args, call_source: desugar, fn_span, .. } => { - // This promoted involves a function call, so it may fail to evaluate. - // Let's make sure it is added to `required_consts` so that failure cannot get lost. + // This promoted involves a function call, so it may fail to evaluate. Let's + // make sure it is added to `required_consts` so that failure cannot get lost. self.add_to_required = true; self.visit_operand(&mut func, loc); diff --git a/compiler/rustc_mir_transform/src/remove_uninit_drops.rs b/compiler/rustc_mir_transform/src/remove_uninit_drops.rs index c58f492655a84..d80a4edecdf37 100644 --- a/compiler/rustc_mir_transform/src/remove_uninit_drops.rs +++ b/compiler/rustc_mir_transform/src/remove_uninit_drops.rs @@ -106,8 +106,9 @@ fn is_needs_drop_and_init<'tcx>( // If its projection *is* present in `MoveData`, then the field may have been moved // from separate from its parent. Recurse. adt.variants().iter_enumerated().any(|(vid, variant)| { - // Enums have multiple variants, which are discriminated with a `Downcast` projection. - // Structs have a single variant, and don't use a `Downcast` projection. + // Enums have multiple variants, which are discriminated with a `Downcast` + // projection. Structs have a single variant, and don't use a `Downcast` + // projection. let mpi = if adt.is_enum() { let downcast = move_path_children_matching(move_data, mpi, |x| x.is_downcast_to(vid)); diff --git a/compiler/rustc_mir_transform/src/reveal_all.rs b/compiler/rustc_mir_transform/src/reveal_all.rs index 3db962bd94aee..f3b2f78b31c3a 100644 --- a/compiler/rustc_mir_transform/src/reveal_all.rs +++ b/compiler/rustc_mir_transform/src/reveal_all.rs @@ -35,9 +35,9 @@ impl<'tcx> MutVisitor<'tcx> for RevealAllVisitor<'tcx> { if place.projection.iter().all(|elem| !matches!(elem, ProjectionElem::OpaqueCast(_))) { return; } - // `OpaqueCast` projections are only needed if there are opaque types on which projections are performed. - // After the `RevealAll` pass, all opaque types are replaced with their hidden types, so we don't need these - // projections anymore. + // `OpaqueCast` projections are only needed if there are opaque types on which projections + // are performed. After the `RevealAll` pass, all opaque types are replaced with their + // hidden types, so we don't need these projections anymore. place.projection = self.tcx.mk_place_elems( &place .projection diff --git a/compiler/rustc_mir_transform/src/shim.rs b/compiler/rustc_mir_transform/src/shim.rs index cf8ef580b2720..e1615c76bb6f9 100644 --- a/compiler/rustc_mir_transform/src/shim.rs +++ b/compiler/rustc_mir_transform/src/shim.rs @@ -1003,7 +1003,8 @@ fn build_fn_ptr_addr_shim<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, self_ty: Ty<'t let locals = local_decls_for_sig(&sig, span); let source_info = SourceInfo::outermost(span); - // FIXME: use `expose_provenance` once we figure out whether function pointers have meaningful provenance. + // FIXME: use `expose_provenance` once we figure out whether function pointers have meaningful + // provenance. let rvalue = Rvalue::Cast( CastKind::FnPtrToPtr, Operand::Move(Place::from(Local::new(1))), diff --git a/compiler/rustc_mir_transform/src/simplify_comparison_integral.rs b/compiler/rustc_mir_transform/src/simplify_comparison_integral.rs index 644bcb58d567d..e8d8335b136b5 100644 --- a/compiler/rustc_mir_transform/src/simplify_comparison_integral.rs +++ b/compiler/rustc_mir_transform/src/simplify_comparison_integral.rs @@ -73,12 +73,13 @@ impl<'tcx> crate::MirPass<'tcx> for SimplifyComparisonIntegral { _ => unreachable!(), } - // delete comparison statement if it the value being switched on was moved, which means it can not be user later on + // delete comparison statement if it the value being switched on was moved, which means + // it can not be user later on if opt.can_remove_bin_op_stmt { bb.statements[opt.bin_op_stmt_idx].make_nop(); } else { - // if the integer being compared to a const integral is being moved into the comparison, - // e.g `_2 = Eq(move _3, const 'x');` + // if the integer being compared to a const integral is being moved into the + // comparison, e.g `_2 = Eq(move _3, const 'x');` // we want to avoid making a double move later on in the switchInt on _3. // So to avoid `switchInt(move _3) -> ['x': bb2, otherwise: bb1];`, // we convert the move in the comparison statement to a copy. @@ -102,12 +103,15 @@ impl<'tcx> crate::MirPass<'tcx> for SimplifyComparisonIntegral { // remove StorageDead (if it exists) being used in the assign of the comparison for (stmt_idx, stmt) in bb.statements.iter().enumerate() { - if !matches!(stmt.kind, StatementKind::StorageDead(local) if local == opt.to_switch_on.local) - { + if !matches!( + stmt.kind, + StatementKind::StorageDead(local) if local == opt.to_switch_on.local + ) { continue; } storage_deads_to_remove.push((stmt_idx, opt.bb_idx)); - // if we have StorageDeads to remove then make sure to insert them at the top of each target + // if we have StorageDeads to remove then make sure to insert them at the top of + // each target for bb_idx in new_targets.all_targets() { storage_deads_to_insert.push(( *bb_idx, @@ -207,7 +211,8 @@ fn find_branch_value_info<'tcx>( (Constant(branch_value), Copy(to_switch_on) | Move(to_switch_on)) | (Copy(to_switch_on) | Move(to_switch_on), Constant(branch_value)) => { let branch_value_ty = branch_value.const_.ty(); - // we only want to apply this optimization if we are matching on integrals (and chars), as it is not possible to switch on floats + // we only want to apply this optimization if we are matching on integrals (and chars), + // as it is not possible to switch on floats if !branch_value_ty.is_integral() && !branch_value_ty.is_char() { return None; }; @@ -222,7 +227,8 @@ fn find_branch_value_info<'tcx>( struct OptimizationInfo<'tcx> { /// Basic block to apply the optimization bb_idx: BasicBlock, - /// Statement index of Eq/Ne assignment that can be removed. None if the assignment can not be removed - i.e the statement is used later on + /// Statement index of Eq/Ne assignment that can be removed. None if the assignment can not be + /// removed - i.e the statement is used later on bin_op_stmt_idx: usize, /// Can remove Eq/Ne assignment can_remove_bin_op_stmt: bool, diff --git a/compiler/rustc_mir_transform/src/unreachable_enum_branching.rs b/compiler/rustc_mir_transform/src/unreachable_enum_branching.rs index 6957394ed1044..5612e779d6bca 100644 --- a/compiler/rustc_mir_transform/src/unreachable_enum_branching.rs +++ b/compiler/rustc_mir_transform/src/unreachable_enum_branching.rs @@ -156,9 +156,9 @@ impl<'tcx> crate::MirPass<'tcx> for UnreachableEnumBranching { }; true } - // If and only if there is a variant that does not have a branch set, - // change the current of otherwise as the variant branch and set otherwise to unreachable. - // It transforms following code + // If and only if there is a variant that does not have a branch set, change the + // current of otherwise as the variant branch and set otherwise to unreachable. It + // transforms following code // ```rust // match c { // Ordering::Less => 1, diff --git a/compiler/rustc_mir_transform/src/unreachable_prop.rs b/compiler/rustc_mir_transform/src/unreachable_prop.rs index c60cbae21422c..f3dafd13824f3 100644 --- a/compiler/rustc_mir_transform/src/unreachable_prop.rs +++ b/compiler/rustc_mir_transform/src/unreachable_prop.rs @@ -26,7 +26,8 @@ impl crate::MirPass<'_> for UnreachablePropagation { let terminator = bb_data.terminator(); let is_unreachable = match &terminator.kind { TerminatorKind::Unreachable => true, - // This will unconditionally run into an unreachable and is therefore unreachable as well. + // This will unconditionally run into an unreachable and is therefore unreachable + // as well. TerminatorKind::Goto { target } if unreachable_blocks.contains(target) => { patch.patch_terminator(bb, TerminatorKind::Unreachable); true @@ -85,8 +86,9 @@ fn remove_successors_from_switch<'tcx>( // } // } // - // This generates a `switchInt() -> [0: 0, 1: 1, otherwise: unreachable]`, which allows us or LLVM to - // turn it into just `x` later. Without the unreachable, such a transformation would be illegal. + // This generates a `switchInt() -> [0: 0, 1: 1, otherwise: unreachable]`, which allows us or + // LLVM to turn it into just `x` later. Without the unreachable, such a transformation would be + // illegal. // // In order to preserve this information, we record reachable and unreachable targets as // `Assume` statements in MIR. diff --git a/compiler/rustc_mir_transform/src/validate.rs b/compiler/rustc_mir_transform/src/validate.rs index 18865c73f75b1..3b84755ddedde 100644 --- a/compiler/rustc_mir_transform/src/validate.rs +++ b/compiler/rustc_mir_transform/src/validate.rs @@ -388,10 +388,11 @@ impl<'a, 'tcx> Visitor<'tcx> for CfgChecker<'a, 'tcx> { } self.check_unwind_edge(location, unwind); - // The code generation assumes that there are no critical call edges. The assumption - // is used to simplify inserting code that should be executed along the return edge - // from the call. FIXME(tmiasko): Since this is a strictly code generation concern, - // the code generation should be responsible for handling it. + // The code generation assumes that there are no critical call edges. The + // assumption is used to simplify inserting code that should be executed along + // the return edge from the call. FIXME(tmiasko): Since this is a strictly code + // generation concern, the code generation should be responsible for handling + // it. if self.mir_phase >= MirPhase::Runtime(RuntimePhase::Optimized) && self.is_critical_call_edge(target, unwind) { @@ -404,8 +405,8 @@ impl<'a, 'tcx> Visitor<'tcx> for CfgChecker<'a, 'tcx> { ); } - // The call destination place and Operand::Move place used as an argument might be - // passed by a reference to the callee. Consequently they cannot be packed. + // The call destination place and Operand::Move place used as an argument might + // be passed by a reference to the callee. Consequently they cannot be packed. if is_within_packed(self.tcx, &self.body.local_decls, destination).is_some() { // This is bad! The callee will expect the memory to be aligned. self.fail( @@ -953,9 +954,9 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { } AggregateKind::RawPtr(pointee_ty, mutability) => { if !matches!(self.mir_phase, MirPhase::Runtime(_)) { - // It would probably be fine to support this in earlier phases, - // but at the time of writing it's only ever introduced from intrinsic lowering, - // so earlier things just `bug!` on it. + // It would probably be fine to support this in earlier phases, but at the + // time of writing it's only ever introduced from intrinsic lowering, so + // earlier things just `bug!` on it. self.fail(location, "RawPtr should be in runtime MIR only"); } @@ -1109,10 +1110,10 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { } UnOp::PtrMetadata => { if !matches!(self.mir_phase, MirPhase::Runtime(_)) { - // It would probably be fine to support this in earlier phases, - // but at the time of writing it's only ever introduced from intrinsic lowering - // or other runtime-phase optimization passes, - // so earlier things can just `bug!` on it. + // It would probably be fine to support this in earlier phases, but at + // the time of writing it's only ever introduced from intrinsic + // lowering or other runtime-phase optimization passes, so earlier + // things can just `bug!` on it. self.fail(location, "PtrMetadata should be in runtime MIR only"); } @@ -1506,7 +1507,8 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { } if let TerminatorKind::TailCall { .. } = terminator.kind { - // FIXME(explicit_tail_calls): implement tail-call specific checks here (such as signature matching, forbidding closures, etc) + // FIXME(explicit_tail_calls): implement tail-call specific checks here (such + // as signature matching, forbidding closures, etc) } } TerminatorKind::Assert { cond, .. } => { From 48064d44982d505412d9328004ed5cc67cb5f210 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 28 Aug 2024 10:13:17 +1000 Subject: [PATCH 0769/2194] Inline and remove some functions. These are all functions with a single callsite, where having a separate function does nothing to help with readability. These changes make the code a little shorter and easier to read. --- .../src/add_call_guards.rs | 6 - .../src/add_moves_for_packed_drops.rs | 45 ++- .../src/add_subtyping_projections.rs | 18 +- compiler/rustc_mir_transform/src/copy_prop.rs | 45 ++- compiler/rustc_mir_transform/src/gvn.rs | 85 +++-- .../rustc_mir_transform/src/instsimplify.rs | 8 +- .../rustc_mir_transform/src/large_enums.rs | 345 +++++++++--------- .../src/lower_slice_len.rs | 26 +- .../src/remove_noop_landing_pads.rs | 113 +++--- compiler/rustc_mir_transform/src/simplify.rs | 48 ++- 10 files changed, 344 insertions(+), 395 deletions(-) diff --git a/compiler/rustc_mir_transform/src/add_call_guards.rs b/compiler/rustc_mir_transform/src/add_call_guards.rs index 18a0746f54f08..24c955c0c78c6 100644 --- a/compiler/rustc_mir_transform/src/add_call_guards.rs +++ b/compiler/rustc_mir_transform/src/add_call_guards.rs @@ -32,12 +32,6 @@ pub(super) use self::AddCallGuards::*; impl<'tcx> crate::MirPass<'tcx> for AddCallGuards { fn run_pass(&self, _tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { - self.add_call_guards(body); - } -} - -impl AddCallGuards { - pub(super) fn add_call_guards(&self, body: &mut Body<'_>) { let mut pred_count: IndexVec<_, _> = body.basic_blocks.predecessors().iter().map(|ps| ps.len()).collect(); pred_count[START_BLOCK] += 1; diff --git a/compiler/rustc_mir_transform/src/add_moves_for_packed_drops.rs b/compiler/rustc_mir_transform/src/add_moves_for_packed_drops.rs index 47572d8d3b22b..74df5f7479e06 100644 --- a/compiler/rustc_mir_transform/src/add_moves_for_packed_drops.rs +++ b/compiler/rustc_mir_transform/src/add_moves_for_packed_drops.rs @@ -40,35 +40,34 @@ pub(super) struct AddMovesForPackedDrops; impl<'tcx> crate::MirPass<'tcx> for AddMovesForPackedDrops { fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { debug!("add_moves_for_packed_drops({:?} @ {:?})", body.source, body.span); - add_moves_for_packed_drops(tcx, body); - } -} - -fn add_moves_for_packed_drops<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { - let patch = add_moves_for_packed_drops_patch(tcx, body); - patch.apply(body); -} -fn add_moves_for_packed_drops_patch<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>) -> MirPatch<'tcx> { - let def_id = body.source.def_id(); - let mut patch = MirPatch::new(body); - let param_env = tcx.param_env(def_id); + let def_id = body.source.def_id(); + let mut patch = MirPatch::new(body); + let param_env = tcx.param_env(def_id); - for (bb, data) in body.basic_blocks.iter_enumerated() { - let loc = Location { block: bb, statement_index: data.statements.len() }; - let terminator = data.terminator(); + for (bb, data) in body.basic_blocks.iter_enumerated() { + let loc = Location { block: bb, statement_index: data.statements.len() }; + let terminator = data.terminator(); - match terminator.kind { - TerminatorKind::Drop { place, .. } - if util::is_disaligned(tcx, body, param_env, place) => - { - add_move_for_packed_drop(tcx, body, &mut patch, terminator, loc, data.is_cleanup); + match terminator.kind { + TerminatorKind::Drop { place, .. } + if util::is_disaligned(tcx, body, param_env, place) => + { + add_move_for_packed_drop( + tcx, + body, + &mut patch, + terminator, + loc, + data.is_cleanup, + ); + } + _ => {} } - _ => {} } - } - patch + patch.apply(body); + } } fn add_move_for_packed_drop<'tcx>( diff --git a/compiler/rustc_mir_transform/src/add_subtyping_projections.rs b/compiler/rustc_mir_transform/src/add_subtyping_projections.rs index ab6bf18b30cb3..e585e338613d8 100644 --- a/compiler/rustc_mir_transform/src/add_subtyping_projections.rs +++ b/compiler/rustc_mir_transform/src/add_subtyping_projections.rs @@ -51,18 +51,14 @@ impl<'a, 'tcx> MutVisitor<'tcx> for SubTypeChecker<'a, 'tcx> { // // gets transformed to // let temp: rval_ty = rval; // let place: place_ty = temp as place_ty; -fn subtype_finder<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { - let patch = MirPatch::new(body); - let mut checker = SubTypeChecker { tcx, patcher: patch, local_decls: &body.local_decls }; - - for (bb, data) in body.basic_blocks.as_mut_preserves_cfg().iter_enumerated_mut() { - checker.visit_basic_block_data(bb, data); - } - checker.patcher.apply(body); -} - impl<'tcx> crate::MirPass<'tcx> for Subtyper { fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { - subtype_finder(tcx, body); + let patch = MirPatch::new(body); + let mut checker = SubTypeChecker { tcx, patcher: patch, local_decls: &body.local_decls }; + + for (bb, data) in body.basic_blocks.as_mut_preserves_cfg().iter_enumerated_mut() { + checker.visit_basic_block_data(bb, data); + } + checker.patcher.apply(body); } } diff --git a/compiler/rustc_mir_transform/src/copy_prop.rs b/compiler/rustc_mir_transform/src/copy_prop.rs index 1cb56d29b85e0..b3db566912108 100644 --- a/compiler/rustc_mir_transform/src/copy_prop.rs +++ b/compiler/rustc_mir_transform/src/copy_prop.rs @@ -27,37 +27,34 @@ impl<'tcx> crate::MirPass<'tcx> for CopyProp { #[instrument(level = "trace", skip(self, tcx, body))] fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { debug!(def_id = ?body.source.def_id()); - propagate_ssa(tcx, body); - } -} -fn propagate_ssa<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { - let param_env = tcx.param_env_reveal_all_normalized(body.source.def_id()); - let ssa = SsaLocals::new(tcx, body, param_env); + let param_env = tcx.param_env_reveal_all_normalized(body.source.def_id()); + let ssa = SsaLocals::new(tcx, body, param_env); - let fully_moved = fully_moved_locals(&ssa, body); - debug!(?fully_moved); + let fully_moved = fully_moved_locals(&ssa, body); + debug!(?fully_moved); - let mut storage_to_remove = BitSet::new_empty(fully_moved.domain_size()); - for (local, &head) in ssa.copy_classes().iter_enumerated() { - if local != head { - storage_to_remove.insert(head); + let mut storage_to_remove = BitSet::new_empty(fully_moved.domain_size()); + for (local, &head) in ssa.copy_classes().iter_enumerated() { + if local != head { + storage_to_remove.insert(head); + } } - } - let any_replacement = ssa.copy_classes().iter_enumerated().any(|(l, &h)| l != h); + let any_replacement = ssa.copy_classes().iter_enumerated().any(|(l, &h)| l != h); - Replacer { - tcx, - copy_classes: ssa.copy_classes(), - fully_moved, - borrowed_locals: ssa.borrowed_locals(), - storage_to_remove, - } - .visit_body_preserves_cfg(body); + Replacer { + tcx, + copy_classes: ssa.copy_classes(), + fully_moved, + borrowed_locals: ssa.borrowed_locals(), + storage_to_remove, + } + .visit_body_preserves_cfg(body); - if any_replacement { - crate::simplify::remove_unused_definitions(body); + if any_replacement { + crate::simplify::remove_unused_definitions(body); + } } } diff --git a/compiler/rustc_mir_transform/src/gvn.rs b/compiler/rustc_mir_transform/src/gvn.rs index 715461de06482..d514664f368d6 100644 --- a/compiler/rustc_mir_transform/src/gvn.rs +++ b/compiler/rustc_mir_transform/src/gvn.rs @@ -119,53 +119,50 @@ impl<'tcx> crate::MirPass<'tcx> for GVN { #[instrument(level = "trace", skip(self, tcx, body))] fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { debug!(def_id = ?body.source.def_id()); - propagate_ssa(tcx, body); - } -} -fn propagate_ssa<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { - let param_env = tcx.param_env_reveal_all_normalized(body.source.def_id()); - let ssa = SsaLocals::new(tcx, body, param_env); - // Clone dominators as we need them while mutating the body. - let dominators = body.basic_blocks.dominators().clone(); - - let mut state = VnState::new(tcx, body, param_env, &ssa, &dominators, &body.local_decls); - ssa.for_each_assignment_mut( - body.basic_blocks.as_mut_preserves_cfg(), - |local, value, location| { - let value = match value { - // We do not know anything of this assigned value. - AssignedValue::Arg | AssignedValue::Terminator => None, - // Try to get some insight. - AssignedValue::Rvalue(rvalue) => { - let value = state.simplify_rvalue(rvalue, location); - // FIXME(#112651) `rvalue` may have a subtype to `local`. We can only mark - // `local` as reusable if we have an exact type match. - if state.local_decls[local].ty != rvalue.ty(state.local_decls, tcx) { - return; + let param_env = tcx.param_env_reveal_all_normalized(body.source.def_id()); + let ssa = SsaLocals::new(tcx, body, param_env); + // Clone dominators as we need them while mutating the body. + let dominators = body.basic_blocks.dominators().clone(); + + let mut state = VnState::new(tcx, body, param_env, &ssa, &dominators, &body.local_decls); + ssa.for_each_assignment_mut( + body.basic_blocks.as_mut_preserves_cfg(), + |local, value, location| { + let value = match value { + // We do not know anything of this assigned value. + AssignedValue::Arg | AssignedValue::Terminator => None, + // Try to get some insight. + AssignedValue::Rvalue(rvalue) => { + let value = state.simplify_rvalue(rvalue, location); + // FIXME(#112651) `rvalue` may have a subtype to `local`. We can only mark + // `local` as reusable if we have an exact type match. + if state.local_decls[local].ty != rvalue.ty(state.local_decls, tcx) { + return; + } + value } - value - } - }; - // `next_opaque` is `Some`, so `new_opaque` must return `Some`. - let value = value.or_else(|| state.new_opaque()).unwrap(); - state.assign(local, value); - }, - ); - - // Stop creating opaques during replacement as it is useless. - state.next_opaque = None; - - let reverse_postorder = body.basic_blocks.reverse_postorder().to_vec(); - for bb in reverse_postorder { - let data = &mut body.basic_blocks.as_mut_preserves_cfg()[bb]; - state.visit_basic_block_data(bb, data); - } + }; + // `next_opaque` is `Some`, so `new_opaque` must return `Some`. + let value = value.or_else(|| state.new_opaque()).unwrap(); + state.assign(local, value); + }, + ); + + // Stop creating opaques during replacement as it is useless. + state.next_opaque = None; - // For each local that is reused (`y` above), we remove its storage statements do avoid any - // difficulty. Those locals are SSA, so should be easy to optimize by LLVM without storage - // statements. - StorageRemover { tcx, reused_locals: state.reused_locals }.visit_body_preserves_cfg(body); + let reverse_postorder = body.basic_blocks.reverse_postorder().to_vec(); + for bb in reverse_postorder { + let data = &mut body.basic_blocks.as_mut_preserves_cfg()[bb]; + state.visit_basic_block_data(bb, data); + } + + // For each local that is reused (`y` above), we remove its storage statements do avoid any + // difficulty. Those locals are SSA, so should be easy to optimize by LLVM without storage + // statements. + StorageRemover { tcx, reused_locals: state.reused_locals }.visit_body_preserves_cfg(body); + } } newtype_index! { diff --git a/compiler/rustc_mir_transform/src/instsimplify.rs b/compiler/rustc_mir_transform/src/instsimplify.rs index a9591bf39848f..0b344f29b078b 100644 --- a/compiler/rustc_mir_transform/src/instsimplify.rs +++ b/compiler/rustc_mir_transform/src/instsimplify.rs @@ -18,19 +18,13 @@ pub(super) enum InstSimplify { AfterSimplifyCfg, } -impl InstSimplify { +impl<'tcx> crate::MirPass<'tcx> for InstSimplify { fn name(&self) -> &'static str { match self { InstSimplify::BeforeInline => "InstSimplify-before-inline", InstSimplify::AfterSimplifyCfg => "InstSimplify-after-simplifycfg", } } -} - -impl<'tcx> crate::MirPass<'tcx> for InstSimplify { - fn name(&self) -> &'static str { - self.name() - } fn is_enabled(&self, sess: &rustc_session::Session) -> bool { sess.mir_opt_level() > 0 diff --git a/compiler/rustc_mir_transform/src/large_enums.rs b/compiler/rustc_mir_transform/src/large_enums.rs index 45edcff29eb28..8a33849f20e0b 100644 --- a/compiler/rustc_mir_transform/src/large_enums.rs +++ b/compiler/rustc_mir_transform/src/large_enums.rs @@ -37,7 +37,169 @@ impl<'tcx> crate::MirPass<'tcx> for EnumSizeOpt { fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { // NOTE: This pass may produce different MIR based on the alignment of the target // platform, but it will still be valid. - self.optim(tcx, body); + + let mut alloc_cache = FxHashMap::default(); + let body_did = body.source.def_id(); + let param_env = tcx.param_env_reveal_all_normalized(body_did); + + let blocks = body.basic_blocks.as_mut(); + let local_decls = &mut body.local_decls; + + for bb in blocks { + bb.expand_statements(|st| { + let StatementKind::Assign(box ( + lhs, + Rvalue::Use(Operand::Copy(rhs) | Operand::Move(rhs)), + )) = &st.kind + else { + return None; + }; + + let ty = lhs.ty(local_decls, tcx).ty; + + let (adt_def, num_variants, alloc_id) = + self.candidate(tcx, param_env, ty, &mut alloc_cache)?; + + let source_info = st.source_info; + let span = source_info.span; + + let tmp_ty = Ty::new_array(tcx, tcx.types.usize, num_variants as u64); + let size_array_local = local_decls.push(LocalDecl::new(tmp_ty, span)); + let store_live = + Statement { source_info, kind: StatementKind::StorageLive(size_array_local) }; + + let place = Place::from(size_array_local); + let constant_vals = ConstOperand { + span, + user_ty: None, + const_: Const::Val( + ConstValue::Indirect { alloc_id, offset: Size::ZERO }, + tmp_ty, + ), + }; + let rval = Rvalue::Use(Operand::Constant(Box::new(constant_vals))); + let const_assign = + Statement { source_info, kind: StatementKind::Assign(Box::new((place, rval))) }; + + let discr_place = Place::from( + local_decls.push(LocalDecl::new(adt_def.repr().discr_type().to_ty(tcx), span)), + ); + let store_discr = Statement { + source_info, + kind: StatementKind::Assign(Box::new(( + discr_place, + Rvalue::Discriminant(*rhs), + ))), + }; + + let discr_cast_place = + Place::from(local_decls.push(LocalDecl::new(tcx.types.usize, span))); + let cast_discr = Statement { + source_info, + kind: StatementKind::Assign(Box::new(( + discr_cast_place, + Rvalue::Cast( + CastKind::IntToInt, + Operand::Copy(discr_place), + tcx.types.usize, + ), + ))), + }; + + let size_place = + Place::from(local_decls.push(LocalDecl::new(tcx.types.usize, span))); + let store_size = Statement { + source_info, + kind: StatementKind::Assign(Box::new(( + size_place, + Rvalue::Use(Operand::Copy(Place { + local: size_array_local, + projection: tcx + .mk_place_elems(&[PlaceElem::Index(discr_cast_place.local)]), + })), + ))), + }; + + let dst = + Place::from(local_decls.push(LocalDecl::new(Ty::new_mut_ptr(tcx, ty), span))); + let dst_ptr = Statement { + source_info, + kind: StatementKind::Assign(Box::new(( + dst, + Rvalue::RawPtr(Mutability::Mut, *lhs), + ))), + }; + + let dst_cast_ty = Ty::new_mut_ptr(tcx, tcx.types.u8); + let dst_cast_place = + Place::from(local_decls.push(LocalDecl::new(dst_cast_ty, span))); + let dst_cast = Statement { + source_info, + kind: StatementKind::Assign(Box::new(( + dst_cast_place, + Rvalue::Cast(CastKind::PtrToPtr, Operand::Copy(dst), dst_cast_ty), + ))), + }; + + let src = + Place::from(local_decls.push(LocalDecl::new(Ty::new_imm_ptr(tcx, ty), span))); + let src_ptr = Statement { + source_info, + kind: StatementKind::Assign(Box::new(( + src, + Rvalue::RawPtr(Mutability::Not, *rhs), + ))), + }; + + let src_cast_ty = Ty::new_imm_ptr(tcx, tcx.types.u8); + let src_cast_place = + Place::from(local_decls.push(LocalDecl::new(src_cast_ty, span))); + let src_cast = Statement { + source_info, + kind: StatementKind::Assign(Box::new(( + src_cast_place, + Rvalue::Cast(CastKind::PtrToPtr, Operand::Copy(src), src_cast_ty), + ))), + }; + + let deinit_old = + Statement { source_info, kind: StatementKind::Deinit(Box::new(dst)) }; + + let copy_bytes = Statement { + source_info, + kind: StatementKind::Intrinsic(Box::new( + NonDivergingIntrinsic::CopyNonOverlapping(CopyNonOverlapping { + src: Operand::Copy(src_cast_place), + dst: Operand::Copy(dst_cast_place), + count: Operand::Copy(size_place), + }), + )), + }; + + let store_dead = + Statement { source_info, kind: StatementKind::StorageDead(size_array_local) }; + + let iter = [ + store_live, + const_assign, + store_discr, + cast_discr, + store_size, + dst_ptr, + dst_cast, + src_ptr, + src_cast, + deinit_old, + copy_bytes, + store_dead, + ] + .into_iter(); + + st.make_nop(); + + Some(iter) + }); + } } } @@ -116,185 +278,4 @@ impl EnumSizeOpt { let alloc = tcx.reserve_and_set_memory_alloc(tcx.mk_const_alloc(alloc)); Some((*adt_def, num_discrs, *alloc_cache.entry(ty).or_insert(alloc))) } - - fn optim<'tcx>(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { - let mut alloc_cache = FxHashMap::default(); - let body_did = body.source.def_id(); - let param_env = tcx.param_env_reveal_all_normalized(body_did); - - let blocks = body.basic_blocks.as_mut(); - let local_decls = &mut body.local_decls; - - for bb in blocks { - bb.expand_statements(|st| { - if let StatementKind::Assign(box ( - lhs, - Rvalue::Use(Operand::Copy(rhs) | Operand::Move(rhs)), - )) = &st.kind - { - let ty = lhs.ty(local_decls, tcx).ty; - - let source_info = st.source_info; - let span = source_info.span; - - let (adt_def, num_variants, alloc_id) = - self.candidate(tcx, param_env, ty, &mut alloc_cache)?; - - let tmp_ty = Ty::new_array(tcx, tcx.types.usize, num_variants as u64); - - let size_array_local = local_decls.push(LocalDecl::new(tmp_ty, span)); - let store_live = Statement { - source_info, - kind: StatementKind::StorageLive(size_array_local), - }; - - let place = Place::from(size_array_local); - let constant_vals = ConstOperand { - span, - user_ty: None, - const_: Const::Val( - ConstValue::Indirect { alloc_id, offset: Size::ZERO }, - tmp_ty, - ), - }; - let rval = Rvalue::Use(Operand::Constant(Box::new(constant_vals))); - - let const_assign = Statement { - source_info, - kind: StatementKind::Assign(Box::new((place, rval))), - }; - - let discr_place = Place::from( - local_decls - .push(LocalDecl::new(adt_def.repr().discr_type().to_ty(tcx), span)), - ); - - let store_discr = Statement { - source_info, - kind: StatementKind::Assign(Box::new(( - discr_place, - Rvalue::Discriminant(*rhs), - ))), - }; - - let discr_cast_place = - Place::from(local_decls.push(LocalDecl::new(tcx.types.usize, span))); - - let cast_discr = Statement { - source_info, - kind: StatementKind::Assign(Box::new(( - discr_cast_place, - Rvalue::Cast( - CastKind::IntToInt, - Operand::Copy(discr_place), - tcx.types.usize, - ), - ))), - }; - - let size_place = - Place::from(local_decls.push(LocalDecl::new(tcx.types.usize, span))); - - let store_size = Statement { - source_info, - kind: StatementKind::Assign(Box::new(( - size_place, - Rvalue::Use(Operand::Copy(Place { - local: size_array_local, - projection: tcx - .mk_place_elems(&[PlaceElem::Index(discr_cast_place.local)]), - })), - ))), - }; - - let dst = Place::from( - local_decls.push(LocalDecl::new(Ty::new_mut_ptr(tcx, ty), span)), - ); - - let dst_ptr = Statement { - source_info, - kind: StatementKind::Assign(Box::new(( - dst, - Rvalue::RawPtr(Mutability::Mut, *lhs), - ))), - }; - - let dst_cast_ty = Ty::new_mut_ptr(tcx, tcx.types.u8); - let dst_cast_place = - Place::from(local_decls.push(LocalDecl::new(dst_cast_ty, span))); - - let dst_cast = Statement { - source_info, - kind: StatementKind::Assign(Box::new(( - dst_cast_place, - Rvalue::Cast(CastKind::PtrToPtr, Operand::Copy(dst), dst_cast_ty), - ))), - }; - - let src = Place::from( - local_decls.push(LocalDecl::new(Ty::new_imm_ptr(tcx, ty), span)), - ); - - let src_ptr = Statement { - source_info, - kind: StatementKind::Assign(Box::new(( - src, - Rvalue::RawPtr(Mutability::Not, *rhs), - ))), - }; - - let src_cast_ty = Ty::new_imm_ptr(tcx, tcx.types.u8); - let src_cast_place = - Place::from(local_decls.push(LocalDecl::new(src_cast_ty, span))); - - let src_cast = Statement { - source_info, - kind: StatementKind::Assign(Box::new(( - src_cast_place, - Rvalue::Cast(CastKind::PtrToPtr, Operand::Copy(src), src_cast_ty), - ))), - }; - - let deinit_old = - Statement { source_info, kind: StatementKind::Deinit(Box::new(dst)) }; - - let copy_bytes = Statement { - source_info, - kind: StatementKind::Intrinsic(Box::new( - NonDivergingIntrinsic::CopyNonOverlapping(CopyNonOverlapping { - src: Operand::Copy(src_cast_place), - dst: Operand::Copy(dst_cast_place), - count: Operand::Copy(size_place), - }), - )), - }; - - let store_dead = Statement { - source_info, - kind: StatementKind::StorageDead(size_array_local), - }; - let iter = [ - store_live, - const_assign, - store_discr, - cast_discr, - store_size, - dst_ptr, - dst_cast, - src_ptr, - src_cast, - deinit_old, - copy_bytes, - store_dead, - ] - .into_iter(); - - st.make_nop(); - Some(iter) - } else { - None - } - }); - } - } } diff --git a/compiler/rustc_mir_transform/src/lower_slice_len.rs b/compiler/rustc_mir_transform/src/lower_slice_len.rs index ca59d4d12acad..420661f29c8cf 100644 --- a/compiler/rustc_mir_transform/src/lower_slice_len.rs +++ b/compiler/rustc_mir_transform/src/lower_slice_len.rs @@ -13,22 +13,18 @@ impl<'tcx> crate::MirPass<'tcx> for LowerSliceLenCalls { } fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { - lower_slice_len_calls(tcx, body) - } -} - -fn lower_slice_len_calls<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { - let language_items = tcx.lang_items(); - let Some(slice_len_fn_item_def_id) = language_items.slice_len_fn() else { - // there is no lang item to compare to :) - return; - }; + let language_items = tcx.lang_items(); + let Some(slice_len_fn_item_def_id) = language_items.slice_len_fn() else { + // there is no lang item to compare to :) + return; + }; - // The one successor remains unchanged, so no need to invalidate - let basic_blocks = body.basic_blocks.as_mut_preserves_cfg(); - for block in basic_blocks { - // lower `<[_]>::len` calls - lower_slice_len_call(block, slice_len_fn_item_def_id); + // The one successor remains unchanged, so no need to invalidate + let basic_blocks = body.basic_blocks.as_mut_preserves_cfg(); + for block in basic_blocks { + // lower `<[_]>::len` calls + lower_slice_len_call(block, slice_len_fn_item_def_id); + } } } diff --git a/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs b/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs index 37197c3f573d3..55394e93a5cb7 100644 --- a/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs +++ b/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs @@ -18,7 +18,61 @@ impl<'tcx> crate::MirPass<'tcx> for RemoveNoopLandingPads { fn run_pass(&self, _tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { let def_id = body.source.def_id(); debug!(?def_id); - self.remove_nop_landing_pads(body) + + // Skip the pass if there are no blocks with a resume terminator. + let has_resume = body + .basic_blocks + .iter_enumerated() + .any(|(_bb, block)| matches!(block.terminator().kind, TerminatorKind::UnwindResume)); + if !has_resume { + debug!("remove_noop_landing_pads: no resume block in MIR"); + return; + } + + // make sure there's a resume block without any statements + let resume_block = { + let mut patch = MirPatch::new(body); + let resume_block = patch.resume_block(); + patch.apply(body); + resume_block + }; + debug!("remove_noop_landing_pads: resume block is {:?}", resume_block); + + let mut jumps_folded = 0; + let mut landing_pads_removed = 0; + let mut nop_landing_pads = BitSet::new_empty(body.basic_blocks.len()); + + // This is a post-order traversal, so that if A post-dominates B + // then A will be visited before B. + let postorder: Vec<_> = traversal::postorder(body).map(|(bb, _)| bb).collect(); + for bb in postorder { + debug!(" processing {:?}", bb); + if let Some(unwind) = body[bb].terminator_mut().unwind_mut() { + if let UnwindAction::Cleanup(unwind_bb) = *unwind { + if nop_landing_pads.contains(unwind_bb) { + debug!(" removing noop landing pad"); + landing_pads_removed += 1; + *unwind = UnwindAction::Continue; + } + } + } + + for target in body[bb].terminator_mut().successors_mut() { + if *target != resume_block && nop_landing_pads.contains(*target) { + debug!(" folding noop jump to {:?} to resume block", target); + *target = resume_block; + jumps_folded += 1; + } + } + + let is_nop_landing_pad = self.is_nop_landing_pad(bb, body, &nop_landing_pads); + if is_nop_landing_pad { + nop_landing_pads.insert(bb); + } + debug!(" is_nop_landing_pad({:?}) = {}", bb, is_nop_landing_pad); + } + + debug!("removed {:?} jumps and {:?} landing pads", jumps_folded, landing_pads_removed); } } @@ -82,61 +136,4 @@ impl RemoveNoopLandingPads { | TerminatorKind::InlineAsm { .. } => false, } } - - fn remove_nop_landing_pads(&self, body: &mut Body<'_>) { - // Skip the pass if there are no blocks with a resume terminator. - let has_resume = body - .basic_blocks - .iter_enumerated() - .any(|(_bb, block)| matches!(block.terminator().kind, TerminatorKind::UnwindResume)); - if !has_resume { - debug!("remove_noop_landing_pads: no resume block in MIR"); - return; - } - - // make sure there's a resume block without any statements - let resume_block = { - let mut patch = MirPatch::new(body); - let resume_block = patch.resume_block(); - patch.apply(body); - resume_block - }; - debug!("remove_noop_landing_pads: resume block is {:?}", resume_block); - - let mut jumps_folded = 0; - let mut landing_pads_removed = 0; - let mut nop_landing_pads = BitSet::new_empty(body.basic_blocks.len()); - - // This is a post-order traversal, so that if A post-dominates B - // then A will be visited before B. - let postorder: Vec<_> = traversal::postorder(body).map(|(bb, _)| bb).collect(); - for bb in postorder { - debug!(" processing {:?}", bb); - if let Some(unwind) = body[bb].terminator_mut().unwind_mut() { - if let UnwindAction::Cleanup(unwind_bb) = *unwind { - if nop_landing_pads.contains(unwind_bb) { - debug!(" removing noop landing pad"); - landing_pads_removed += 1; - *unwind = UnwindAction::Continue; - } - } - } - - for target in body[bb].terminator_mut().successors_mut() { - if *target != resume_block && nop_landing_pads.contains(*target) { - debug!(" folding noop jump to {:?} to resume block", target); - *target = resume_block; - jumps_folded += 1; - } - } - - let is_nop_landing_pad = self.is_nop_landing_pad(bb, body, &nop_landing_pads); - if is_nop_landing_pad { - nop_landing_pads.insert(bb); - } - debug!(" is_nop_landing_pad({:?}) = {}", bb, is_nop_landing_pad); - } - - debug!("removed {:?} jumps and {:?} landing pads", jumps_folded, landing_pads_removed); - } } diff --git a/compiler/rustc_mir_transform/src/simplify.rs b/compiler/rustc_mir_transform/src/simplify.rs index cb8e1dfda98ba..7ed43547e1127 100644 --- a/compiler/rustc_mir_transform/src/simplify.rs +++ b/compiler/rustc_mir_transform/src/simplify.rs @@ -381,23 +381,33 @@ impl<'tcx> crate::MirPass<'tcx> for SimplifyLocals { fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { trace!("running SimplifyLocals on {:?}", body.source); - simplify_locals(body, tcx); - } -} -pub(super) fn remove_unused_definitions<'tcx>(body: &mut Body<'tcx>) { - // First, we're going to get a count of *actual* uses for every `Local`. - let mut used_locals = UsedLocals::new(body); + // First, we're going to get a count of *actual* uses for every `Local`. + let mut used_locals = UsedLocals::new(body); - // Next, we're going to remove any `Local` with zero actual uses. When we remove those - // `Locals`, we're also going to subtract any uses of other `Locals` from the `used_locals` - // count. For example, if we removed `_2 = discriminant(_1)`, then we'll subtract one from - // `use_counts[_1]`. That in turn might make `_1` unused, so we loop until we hit a - // fixedpoint where there are no more unused locals. - remove_unused_definitions_helper(&mut used_locals, body); + // Next, we're going to remove any `Local` with zero actual uses. When we remove those + // `Locals`, we're also going to subtract any uses of other `Locals` from the `used_locals` + // count. For example, if we removed `_2 = discriminant(_1)`, then we'll subtract one from + // `use_counts[_1]`. That in turn might make `_1` unused, so we loop until we hit a + // fixedpoint where there are no more unused locals. + remove_unused_definitions_helper(&mut used_locals, body); + + // Finally, we'll actually do the work of shrinking `body.local_decls` and remapping the + // `Local`s. + let map = make_local_map(&mut body.local_decls, &used_locals); + + // Only bother running the `LocalUpdater` if we actually found locals to remove. + if map.iter().any(Option::is_none) { + // Update references to all vars and tmps now + let mut updater = LocalUpdater { map, tcx }; + updater.visit_body_preserves_cfg(body); + + body.local_decls.shrink_to_fit(); + } + } } -fn simplify_locals<'tcx>(body: &mut Body<'tcx>, tcx: TyCtxt<'tcx>) { +pub(super) fn remove_unused_definitions<'tcx>(body: &mut Body<'tcx>) { // First, we're going to get a count of *actual* uses for every `Local`. let mut used_locals = UsedLocals::new(body); @@ -407,18 +417,6 @@ fn simplify_locals<'tcx>(body: &mut Body<'tcx>, tcx: TyCtxt<'tcx>) { // `use_counts[_1]`. That in turn might make `_1` unused, so we loop until we hit a // fixedpoint where there are no more unused locals. remove_unused_definitions_helper(&mut used_locals, body); - - // Finally, we'll actually do the work of shrinking `body.local_decls` and remapping the `Local`s. - let map = make_local_map(&mut body.local_decls, &used_locals); - - // Only bother running the `LocalUpdater` if we actually found locals to remove. - if map.iter().any(Option::is_none) { - // Update references to all vars and tmps now - let mut updater = LocalUpdater { map, tcx }; - updater.visit_body_preserves_cfg(body); - - body.local_decls.shrink_to_fit(); - } } /// Construct the mapping while swapping out unused stuff out from the `vec`. From baa16d24715abeed857202ad917a0f05e364b8a5 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 30 Aug 2024 13:51:59 +1000 Subject: [PATCH 0770/2194] Clarify a comment. The "as" is equivalent to "because", but I originally read it more like "when", which was confusing. --- compiler/rustc_mir_transform/src/gvn.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_mir_transform/src/gvn.rs b/compiler/rustc_mir_transform/src/gvn.rs index d514664f368d6..0b78affc31cc1 100644 --- a/compiler/rustc_mir_transform/src/gvn.rs +++ b/compiler/rustc_mir_transform/src/gvn.rs @@ -122,7 +122,7 @@ impl<'tcx> crate::MirPass<'tcx> for GVN { let param_env = tcx.param_env_reveal_all_normalized(body.source.def_id()); let ssa = SsaLocals::new(tcx, body, param_env); - // Clone dominators as we need them while mutating the body. + // Clone dominators because we need them while mutating the body. let dominators = body.basic_blocks.dominators().clone(); let mut state = VnState::new(tcx, body, param_env, &ssa, &dominators, &body.local_decls); From e26692d559c3b564a3efdd5b6db316c0c67fb52e Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 3 Sep 2024 11:00:15 +1000 Subject: [PATCH 0771/2194] Add a useful comment. --- compiler/rustc_mir_transform/src/large_enums.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/compiler/rustc_mir_transform/src/large_enums.rs b/compiler/rustc_mir_transform/src/large_enums.rs index 8a33849f20e0b..3e263aa406774 100644 --- a/compiler/rustc_mir_transform/src/large_enums.rs +++ b/compiler/rustc_mir_transform/src/large_enums.rs @@ -244,6 +244,8 @@ impl EnumSizeOpt { let ptr_sized_int = data_layout.ptr_sized_integer(); let target_bytes = ptr_sized_int.size().bytes() as usize; let mut data = vec![0; target_bytes * num_discrs]; + + // We use a macro because `$bytes` can be u32 or u64. macro_rules! encode_store { ($curr_idx: expr, $endian: expr, $bytes: expr) => { let bytes = match $endian { From 51e1c3958dd68372c4a4499d59223ccecc1a7955 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 4 Sep 2024 13:20:20 +1000 Subject: [PATCH 0772/2194] Add a useful comment about `PromoteTemps`. This was non-obvious to me. --- compiler/rustc_mir_transform/src/promote_consts.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/compiler/rustc_mir_transform/src/promote_consts.rs b/compiler/rustc_mir_transform/src/promote_consts.rs index c968053a6d6e8..59df99f858dcf 100644 --- a/compiler/rustc_mir_transform/src/promote_consts.rs +++ b/compiler/rustc_mir_transform/src/promote_consts.rs @@ -36,6 +36,7 @@ use tracing::{debug, instrument}; /// newly created `Constant`. #[derive(Default)] pub(super) struct PromoteTemps<'tcx> { + // Must use `Cell` because `run_pass` takes `&self`, not `&mut self`. pub promoted_fragments: Cell>>, } From d1c55a305eefedbe3153c7348c4b373ecd07d144 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 4 Sep 2024 13:58:26 +1000 Subject: [PATCH 0773/2194] Use `IndexVec::from_raw` to construct a const `IndexVec`. --- compiler/rustc_mir_transform/src/shim.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_mir_transform/src/shim.rs b/compiler/rustc_mir_transform/src/shim.rs index e1615c76bb6f9..f1bd803d83530 100644 --- a/compiler/rustc_mir_transform/src/shim.rs +++ b/compiler/rustc_mir_transform/src/shim.rs @@ -404,8 +404,7 @@ fn build_thread_local_shim<'tcx>( let span = tcx.def_span(def_id); let source_info = SourceInfo::outermost(span); - let mut blocks = IndexVec::with_capacity(1); - blocks.push(BasicBlockData { + let blocks = IndexVec::from_raw(vec![BasicBlockData { statements: vec![Statement { source_info, kind: StatementKind::Assign(Box::new(( @@ -415,7 +414,7 @@ fn build_thread_local_shim<'tcx>( }], terminator: Some(Terminator { source_info, kind: TerminatorKind::Return }), is_cleanup: false, - }); + }]); new_body( MirSource::from_instance(instance), From 702340269136b9818359a82c5f7fc659ec26a0bf Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 4 Sep 2024 13:47:26 +1000 Subject: [PATCH 0774/2194] Remove references from some structs. In all cases the struct can own the relevant thing instead of having a reference to it. This makes the code simpler, and in some cases removes a struct lifetime. --- compiler/rustc_mir_transform/src/dest_prop.rs | 14 +++---- compiler/rustc_mir_transform/src/gvn.rs | 8 ++-- .../rustc_mir_transform/src/jump_threading.rs | 42 +++++++++---------- compiler/rustc_mir_transform/src/lib.rs | 14 ++++--- .../src/mentioned_items.rs | 8 ++-- compiler/rustc_mir_transform/src/ref_prop.rs | 15 +++---- .../src/required_consts.rs | 19 ++++----- 7 files changed, 56 insertions(+), 64 deletions(-) diff --git a/compiler/rustc_mir_transform/src/dest_prop.rs b/compiler/rustc_mir_transform/src/dest_prop.rs index 175097e30ee30..f123658580da4 100644 --- a/compiler/rustc_mir_transform/src/dest_prop.rs +++ b/compiler/rustc_mir_transform/src/dest_prop.rs @@ -242,7 +242,7 @@ impl<'tcx> crate::MirPass<'tcx> for DestinationPropagation { } round_count += 1; - apply_merges(body, tcx, &merges, &merged_locals); + apply_merges(body, tcx, merges, merged_locals); } trace!(round_count); @@ -281,20 +281,20 @@ struct Candidates { fn apply_merges<'tcx>( body: &mut Body<'tcx>, tcx: TyCtxt<'tcx>, - merges: &FxIndexMap, - merged_locals: &BitSet, + merges: FxIndexMap, + merged_locals: BitSet, ) { let mut merger = Merger { tcx, merges, merged_locals }; merger.visit_body_preserves_cfg(body); } -struct Merger<'a, 'tcx> { +struct Merger<'tcx> { tcx: TyCtxt<'tcx>, - merges: &'a FxIndexMap, - merged_locals: &'a BitSet, + merges: FxIndexMap, + merged_locals: BitSet, } -impl<'a, 'tcx> MutVisitor<'tcx> for Merger<'a, 'tcx> { +impl<'tcx> MutVisitor<'tcx> for Merger<'tcx> { fn tcx(&self) -> TyCtxt<'tcx> { self.tcx } diff --git a/compiler/rustc_mir_transform/src/gvn.rs b/compiler/rustc_mir_transform/src/gvn.rs index 0b78affc31cc1..598bf61483d2f 100644 --- a/compiler/rustc_mir_transform/src/gvn.rs +++ b/compiler/rustc_mir_transform/src/gvn.rs @@ -125,7 +125,7 @@ impl<'tcx> crate::MirPass<'tcx> for GVN { // Clone dominators because we need them while mutating the body. let dominators = body.basic_blocks.dominators().clone(); - let mut state = VnState::new(tcx, body, param_env, &ssa, &dominators, &body.local_decls); + let mut state = VnState::new(tcx, body, param_env, &ssa, dominators, &body.local_decls); ssa.for_each_assignment_mut( body.basic_blocks.as_mut_preserves_cfg(), |local, value, location| { @@ -258,7 +258,7 @@ struct VnState<'body, 'tcx> { /// Cache the value of the `unsized_locals` features, to avoid fetching it repeatedly in a loop. feature_unsized_locals: bool, ssa: &'body SsaLocals, - dominators: &'body Dominators, + dominators: Dominators, reused_locals: BitSet, } @@ -268,7 +268,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { body: &Body<'tcx>, param_env: ty::ParamEnv<'tcx>, ssa: &'body SsaLocals, - dominators: &'body Dominators, + dominators: Dominators, local_decls: &'body LocalDecls<'tcx>, ) -> Self { // Compute a rough estimate of the number of values in the body from the number of @@ -1490,7 +1490,7 @@ impl<'tcx> VnState<'_, 'tcx> { let other = self.rev_locals.get(index)?; other .iter() - .find(|&&other| self.ssa.assignment_dominates(self.dominators, other, loc)) + .find(|&&other| self.ssa.assignment_dominates(&self.dominators, other, loc)) .copied() } } diff --git a/compiler/rustc_mir_transform/src/jump_threading.rs b/compiler/rustc_mir_transform/src/jump_threading.rs index e950c2cb72ab8..d48df59ada860 100644 --- a/compiler/rustc_mir_transform/src/jump_threading.rs +++ b/compiler/rustc_mir_transform/src/jump_threading.rs @@ -78,18 +78,16 @@ impl<'tcx> crate::MirPass<'tcx> for JumpThreading { } let param_env = tcx.param_env_reveal_all_normalized(def_id); - let map = Map::new(tcx, body, Some(MAX_PLACES)); - let loop_headers = loop_headers(body); - let arena = DroplessArena::default(); + let arena = &DroplessArena::default(); let mut finder = TOFinder { tcx, param_env, ecx: InterpCx::new(tcx, DUMMY_SP, param_env, DummyMachine), body, - arena: &arena, - map: &map, - loop_headers: &loop_headers, + arena, + map: Map::new(tcx, body, Some(MAX_PLACES)), + loop_headers: loop_headers(body), opportunities: Vec::new(), }; @@ -105,7 +103,7 @@ impl<'tcx> crate::MirPass<'tcx> for JumpThreading { // Verify that we do not thread through a loop header. for to in opportunities.iter() { - assert!(to.chain.iter().all(|&block| !loop_headers.contains(block))); + assert!(to.chain.iter().all(|&block| !finder.loop_headers.contains(block))); } OpportunitySet::new(body, opportunities).apply(body); } @@ -124,8 +122,8 @@ struct TOFinder<'tcx, 'a> { param_env: ty::ParamEnv<'tcx>, ecx: InterpCx<'tcx, DummyMachine>, body: &'a Body<'tcx>, - map: &'a Map<'tcx>, - loop_headers: &'a BitSet, + map: Map<'tcx>, + loop_headers: BitSet, /// We use an arena to avoid cloning the slices when cloning `state`. arena: &'a DroplessArena, opportunities: Vec, @@ -223,7 +221,7 @@ impl<'tcx, 'a> TOFinder<'tcx, 'a> { })) }; let conds = ConditionSet(conds); - state.insert_value_idx(discr, conds, self.map); + state.insert_value_idx(discr, conds, &self.map); self.find_opportunity(bb, state, cost, 0); } @@ -264,7 +262,7 @@ impl<'tcx, 'a> TOFinder<'tcx, 'a> { // _1 = 5 // Whatever happens here, it won't change the result of a `SwitchInt`. // _1 = 6 if let Some((lhs, tail)) = self.mutated_statement(stmt) { - state.flood_with_tail_elem(lhs.as_ref(), tail, self.map, ConditionSet::BOTTOM); + state.flood_with_tail_elem(lhs.as_ref(), tail, &self.map, ConditionSet::BOTTOM); } } @@ -370,7 +368,7 @@ impl<'tcx, 'a> TOFinder<'tcx, 'a> { self.opportunities.push(ThreadingOpportunity { chain: vec![bb], target: c.target }) }; - if let Some(conditions) = state.try_get_idx(lhs, self.map) + if let Some(conditions) = state.try_get_idx(lhs, &self.map) && let Immediate::Scalar(Scalar::Int(int)) = *rhs { conditions.iter_matches(int).for_each(register_opportunity); @@ -406,7 +404,7 @@ impl<'tcx, 'a> TOFinder<'tcx, 'a> { } }, &mut |place, op| { - if let Some(conditions) = state.try_get_idx(place, self.map) + if let Some(conditions) = state.try_get_idx(place, &self.map) && let Ok(imm) = self.ecx.read_immediate_raw(op) && let Some(imm) = imm.right() && let Immediate::Scalar(Scalar::Int(int)) = *imm @@ -441,7 +439,7 @@ impl<'tcx, 'a> TOFinder<'tcx, 'a> { // Transfer the conditions on the copied rhs. Operand::Move(rhs) | Operand::Copy(rhs) => { let Some(rhs) = self.map.find(rhs.as_ref()) else { return }; - state.insert_place_idx(rhs, lhs, self.map); + state.insert_place_idx(rhs, lhs, &self.map); } } } @@ -461,7 +459,7 @@ impl<'tcx, 'a> TOFinder<'tcx, 'a> { Rvalue::CopyForDeref(rhs) => self.process_operand(bb, lhs, &Operand::Copy(*rhs), state), Rvalue::Discriminant(rhs) => { let Some(rhs) = self.map.find_discr(rhs.as_ref()) else { return }; - state.insert_place_idx(rhs, lhs, self.map); + state.insert_place_idx(rhs, lhs, &self.map); } // If we expect `lhs ?= A`, we have an opportunity if we assume `constant == A`. Rvalue::Aggregate(box ref kind, ref operands) => { @@ -492,10 +490,10 @@ impl<'tcx, 'a> TOFinder<'tcx, 'a> { } // Transfer the conditions on the copy rhs, after inversing polarity. Rvalue::UnaryOp(UnOp::Not, Operand::Move(place) | Operand::Copy(place)) => { - let Some(conditions) = state.try_get_idx(lhs, self.map) else { return }; + let Some(conditions) = state.try_get_idx(lhs, &self.map) else { return }; let Some(place) = self.map.find(place.as_ref()) else { return }; let conds = conditions.map(self.arena, Condition::inv); - state.insert_value_idx(place, conds, self.map); + state.insert_value_idx(place, conds, &self.map); } // We expect `lhs ?= A`. We found `lhs = Eq(rhs, B)`. // Create a condition on `rhs ?= B`. @@ -504,7 +502,7 @@ impl<'tcx, 'a> TOFinder<'tcx, 'a> { box (Operand::Move(place) | Operand::Copy(place), Operand::Constant(value)) | box (Operand::Constant(value), Operand::Move(place) | Operand::Copy(place)), ) => { - let Some(conditions) = state.try_get_idx(lhs, self.map) else { return }; + let Some(conditions) = state.try_get_idx(lhs, &self.map) else { return }; let Some(place) = self.map.find(place.as_ref()) else { return }; let equals = match op { BinOp::Eq => ScalarInt::TRUE, @@ -528,7 +526,7 @@ impl<'tcx, 'a> TOFinder<'tcx, 'a> { polarity: if c.matches(equals) { Polarity::Eq } else { Polarity::Ne }, ..c }); - state.insert_value_idx(place, conds, self.map); + state.insert_value_idx(place, conds, &self.map); } _ => {} @@ -583,7 +581,7 @@ impl<'tcx, 'a> TOFinder<'tcx, 'a> { StatementKind::Intrinsic(box NonDivergingIntrinsic::Assume( Operand::Copy(place) | Operand::Move(place), )) => { - let Some(conditions) = state.try_get(place.as_ref(), self.map) else { return }; + let Some(conditions) = state.try_get(place.as_ref(), &self.map) else { return }; conditions.iter_matches(ScalarInt::TRUE).for_each(register_opportunity); } StatementKind::Assign(box (lhs_place, rhs)) => { @@ -631,7 +629,7 @@ impl<'tcx, 'a> TOFinder<'tcx, 'a> { // We can recurse through this terminator. let mut state = state(); if let Some(place_to_flood) = place_to_flood { - state.flood_with(place_to_flood.as_ref(), self.map, ConditionSet::BOTTOM); + state.flood_with(place_to_flood.as_ref(), &self.map, ConditionSet::BOTTOM); } self.find_opportunity(bb, state, cost.clone(), depth + 1); } @@ -650,7 +648,7 @@ impl<'tcx, 'a> TOFinder<'tcx, 'a> { let Some(discr) = discr.place() else { return }; let discr_ty = discr.ty(self.body, self.tcx).ty; let Ok(discr_layout) = self.ecx.layout_of(discr_ty) else { return }; - let Some(conditions) = state.try_get(discr.as_ref(), self.map) else { return }; + let Some(conditions) = state.try_get(discr.as_ref(), &self.map) else { return }; if let Some((value, _)) = targets.iter().find(|&(_, target)| target == target_bb) { let Some(value) = ScalarInt::try_from_uint(value, discr_layout.size) else { return }; diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs index dcfcad7cc7c5b..6c9b46d8b6f6a 100644 --- a/compiler/rustc_mir_transform/src/lib.rs +++ b/compiler/rustc_mir_transform/src/lib.rs @@ -223,14 +223,14 @@ fn is_mir_available(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool { /// MIR associated with them. fn mir_keys(tcx: TyCtxt<'_>, (): ()) -> FxIndexSet { // All body-owners have MIR associated with them. - let mut set: FxIndexSet<_> = tcx.hir().body_owners().collect(); + let set: FxIndexSet<_> = tcx.hir().body_owners().collect(); // Additionally, tuple struct/variant constructors have MIR, but // they don't have a BodyId, so we need to build them separately. - struct GatherCtors<'a> { - set: &'a mut FxIndexSet, + struct GatherCtors { + set: FxIndexSet, } - impl<'tcx> Visitor<'tcx> for GatherCtors<'_> { + impl<'tcx> Visitor<'tcx> for GatherCtors { fn visit_variant_data(&mut self, v: &'tcx hir::VariantData<'tcx>) { if let hir::VariantData::Tuple(_, _, def_id) = *v { self.set.insert(def_id); @@ -238,9 +238,11 @@ fn mir_keys(tcx: TyCtxt<'_>, (): ()) -> FxIndexSet { intravisit::walk_struct_def(self, v) } } - tcx.hir().visit_all_item_likes_in_crate(&mut GatherCtors { set: &mut set }); - set + let mut gather_ctors = GatherCtors { set }; + tcx.hir().visit_all_item_likes_in_crate(&mut gather_ctors); + + gather_ctors.set } fn mir_const_qualif(tcx: TyCtxt<'_>, def: LocalDefId) -> ConstQualifs { diff --git a/compiler/rustc_mir_transform/src/mentioned_items.rs b/compiler/rustc_mir_transform/src/mentioned_items.rs index 4402e0dd42d40..f24de609e6b29 100644 --- a/compiler/rustc_mir_transform/src/mentioned_items.rs +++ b/compiler/rustc_mir_transform/src/mentioned_items.rs @@ -10,7 +10,7 @@ pub(super) struct MentionedItems; struct MentionedItemsVisitor<'a, 'tcx> { tcx: TyCtxt<'tcx>, body: &'a mir::Body<'tcx>, - mentioned_items: &'a mut Vec>>, + mentioned_items: Vec>>, } impl<'tcx> crate::MirPass<'tcx> for MentionedItems { @@ -23,9 +23,9 @@ impl<'tcx> crate::MirPass<'tcx> for MentionedItems { } fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut mir::Body<'tcx>) { - let mut mentioned_items = Vec::new(); - MentionedItemsVisitor { tcx, body, mentioned_items: &mut mentioned_items }.visit_body(body); - body.set_mentioned_items(mentioned_items); + let mut visitor = MentionedItemsVisitor { tcx, body, mentioned_items: Vec::new() }; + visitor.visit_body(body); + body.set_mentioned_items(visitor.mentioned_items); } } diff --git a/compiler/rustc_mir_transform/src/ref_prop.rs b/compiler/rustc_mir_transform/src/ref_prop.rs index 25b98786c66b7..4c3a99b79d4f2 100644 --- a/compiler/rustc_mir_transform/src/ref_prop.rs +++ b/compiler/rustc_mir_transform/src/ref_prop.rs @@ -253,11 +253,8 @@ fn compute_replacement<'tcx>( debug!(?targets); - let mut finder = ReplacementFinder { - targets: &mut targets, - can_perform_opt, - allowed_replacements: FxHashSet::default(), - }; + let mut finder = + ReplacementFinder { targets, can_perform_opt, allowed_replacements: FxHashSet::default() }; let reachable_blocks = traversal::reachable_as_bitset(body); for (bb, bbdata) in body.basic_blocks.iter_enumerated() { // Only visit reachable blocks as we rely on dataflow. @@ -269,19 +266,19 @@ fn compute_replacement<'tcx>( let allowed_replacements = finder.allowed_replacements; return Replacer { tcx, - targets, + targets: finder.targets, storage_to_remove, allowed_replacements, any_replacement: false, }; - struct ReplacementFinder<'a, 'tcx, F> { - targets: &'a mut IndexVec>, + struct ReplacementFinder<'tcx, F> { + targets: IndexVec>, can_perform_opt: F, allowed_replacements: FxHashSet<(Local, Location)>, } - impl<'tcx, F> Visitor<'tcx> for ReplacementFinder<'_, 'tcx, F> + impl<'tcx, F> Visitor<'tcx> for ReplacementFinder<'tcx, F> where F: FnMut(Place<'tcx>, Location) -> bool, { diff --git a/compiler/rustc_mir_transform/src/required_consts.rs b/compiler/rustc_mir_transform/src/required_consts.rs index ebcf5b5d27b84..99d1cd6f63ecf 100644 --- a/compiler/rustc_mir_transform/src/required_consts.rs +++ b/compiler/rustc_mir_transform/src/required_consts.rs @@ -1,26 +1,21 @@ use rustc_middle::mir::visit::Visitor; use rustc_middle::mir::{traversal, Body, ConstOperand, Location}; -pub(super) struct RequiredConstsVisitor<'a, 'tcx> { - required_consts: &'a mut Vec>, +pub(super) struct RequiredConstsVisitor<'tcx> { + required_consts: Vec>, } -impl<'a, 'tcx> RequiredConstsVisitor<'a, 'tcx> { - fn new(required_consts: &'a mut Vec>) -> Self { - RequiredConstsVisitor { required_consts } - } - +impl<'tcx> RequiredConstsVisitor<'tcx> { pub(super) fn compute_required_consts(body: &mut Body<'tcx>) { - let mut required_consts = Vec::new(); - let mut required_consts_visitor = RequiredConstsVisitor::new(&mut required_consts); + let mut visitor = RequiredConstsVisitor { required_consts: Vec::new() }; for (bb, bb_data) in traversal::reverse_postorder(&body) { - required_consts_visitor.visit_basic_block_data(bb, bb_data); + visitor.visit_basic_block_data(bb, bb_data); } - body.set_required_consts(required_consts); + body.set_required_consts(visitor.required_consts); } } -impl<'tcx> Visitor<'tcx> for RequiredConstsVisitor<'_, 'tcx> { +impl<'tcx> Visitor<'tcx> for RequiredConstsVisitor<'tcx> { fn visit_const_operand(&mut self, constant: &ConstOperand<'tcx>, _: Location) { if constant.const_.is_required_const() { self.required_consts.push(*constant); From 8949b443d5d0415c0c95fc931b1e4ee54de2f301 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 5 Sep 2024 10:39:11 +1000 Subject: [PATCH 0775/2194] Make `check_live_drops` into a `MirLint`. It's a thin wrapper around `check_live_drops`, but it's enough to fix the FIXME comment. --- compiler/rustc_mir_transform/src/lib.rs | 9 ++++++--- .../src/post_drop_elaboration.rs | 13 +++++++++++++ 2 files changed, 19 insertions(+), 3 deletions(-) create mode 100644 compiler/rustc_mir_transform/src/post_drop_elaboration.rs diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs index 6c9b46d8b6f6a..84d07d3833071 100644 --- a/compiler/rustc_mir_transform/src/lib.rs +++ b/compiler/rustc_mir_transform/src/lib.rs @@ -87,6 +87,7 @@ mod match_branches; mod mentioned_items; mod multiple_return_terminators; mod nrvo; +mod post_drop_elaboration; mod prettify; mod promote_consts; mod ref_prop; @@ -480,11 +481,13 @@ pub fn run_analysis_to_runtime_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<' pm::run_passes( tcx, body, - &[&remove_uninit_drops::RemoveUninitDrops, &simplify::SimplifyCfg::RemoveFalseEdges], + &[ + &remove_uninit_drops::RemoveUninitDrops, + &simplify::SimplifyCfg::RemoveFalseEdges, + &Lint(post_drop_elaboration::CheckLiveDrops), + ], None, ); - // FIXME: make this a MIR lint - check_consts::post_drop_elaboration::check_live_drops(tcx, body); } debug!("runtime_mir_lowering({:?})", did); diff --git a/compiler/rustc_mir_transform/src/post_drop_elaboration.rs b/compiler/rustc_mir_transform/src/post_drop_elaboration.rs new file mode 100644 index 0000000000000..75721d4607626 --- /dev/null +++ b/compiler/rustc_mir_transform/src/post_drop_elaboration.rs @@ -0,0 +1,13 @@ +use rustc_const_eval::check_consts; +use rustc_middle::mir::*; +use rustc_middle::ty::TyCtxt; + +use crate::MirLint; + +pub(super) struct CheckLiveDrops; + +impl<'tcx> MirLint<'tcx> for CheckLiveDrops { + fn run_lint(&self, tcx: TyCtxt<'tcx>, body: &Body<'tcx>) { + check_consts::post_drop_elaboration::check_live_drops(tcx, body); + } +} From d2309c2a9d308ddcd94c0ee8f4d2a01d1bd93560 Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Thu, 22 Aug 2024 01:28:20 -0700 Subject: [PATCH 0776/2194] Ban non-array SIMD --- .../src/error_codes/E0074.md | 4 +- .../src/error_codes/E0075.md | 18 +- .../src/error_codes/E0076.md | 10 +- .../src/error_codes/E0077.md | 4 +- .../src/error_codes/E0511.md | 4 +- .../rustc_hir_analysis/src/check/check.rs | 42 ++-- compiler/rustc_middle/src/ty/sty.rs | 38 ++-- library/alloc/benches/slice.rs | 4 +- tests/assembly/asm/aarch64-types.rs | 31 +-- tests/assembly/asm/arm-modifiers.rs | 5 +- tests/assembly/asm/arm-types.rs | 27 ++- tests/assembly/asm/x86-types.rs | 209 ++---------------- tests/codegen/align-byval-vector.rs | 8 +- tests/codegen/const-vector.rs | 36 +-- tests/codegen/repr/transparent.rs | 2 +- .../simd-intrinsic-float-abs.rs | 19 +- .../simd-intrinsic-float-ceil.rs | 19 +- .../simd-intrinsic-float-cos.rs | 19 +- .../simd-intrinsic-float-exp.rs | 19 +- .../simd-intrinsic-float-exp2.rs | 19 +- .../simd-intrinsic-float-floor.rs | 19 +- .../simd-intrinsic-float-fma.rs | 19 +- .../simd-intrinsic-float-fsqrt.rs | 19 +- .../simd-intrinsic-float-log.rs | 19 +- .../simd-intrinsic-float-log10.rs | 19 +- .../simd-intrinsic-float-log2.rs | 19 +- .../simd-intrinsic-float-minmax.rs | 2 +- .../simd-intrinsic-float-pow.rs | 19 +- .../simd-intrinsic-float-powi.rs | 19 +- .../simd-intrinsic-float-sin.rs | 19 +- ...intrinsic-generic-arithmetic-saturating.rs | 146 ++++-------- .../simd-intrinsic-generic-bitmask.rs | 10 +- .../simd-intrinsic-generic-gather.rs | 4 +- .../simd-intrinsic-generic-masked-load.rs | 4 +- .../simd-intrinsic-generic-masked-store.rs | 4 +- .../simd-intrinsic-generic-scatter.rs | 4 +- .../simd-intrinsic-generic-select.rs | 6 +- .../simd-intrinsic-transmute-array.rs | 25 +-- tests/codegen/simd/unpadded-simd.rs | 2 +- tests/codegen/union-abi.rs | 2 +- tests/codegen/zst-offset.rs | 2 +- tests/debuginfo/simd.rs | 64 +++--- tests/incremental/issue-61530.rs | 6 +- tests/run-make/simd-ffi/simd.rs | 6 +- tests/rustdoc/inline_cross/auxiliary/repr.rs | 2 +- tests/ui/abi/arm-unadjusted-intrinsic.rs | 9 +- .../homogenous-floats-target-feature-mixup.rs | 30 +-- tests/ui/asm/aarch64/type-check-2-2.rs | 4 +- tests/ui/asm/aarch64/type-check-2.rs | 8 +- tests/ui/asm/aarch64/type-check-2.stderr | 4 +- tests/ui/asm/aarch64/type-check-3.rs | 4 +- tests/ui/asm/aarch64/type-check-4.rs | 2 +- tests/ui/asm/x86_64/type-check-2.rs | 4 +- tests/ui/asm/x86_64/type-check-2.stderr | 4 +- tests/ui/asm/x86_64/type-check-5.rs | 5 +- tests/ui/asm/x86_64/type-check-5.stderr | 6 +- .../consts/const-eval/simd/insert_extract.rs | 23 +- tests/ui/error-codes/E0075.rs | 3 + tests/ui/error-codes/E0075.stderr | 8 +- tests/ui/error-codes/E0076.rs | 2 +- tests/ui/error-codes/E0076.stderr | 6 +- tests/ui/error-codes/E0077.rs | 2 +- tests/ui/error-codes/E0077.stderr | 2 +- .../feature-gates/feature-gate-repr-simd.rs | 4 +- .../ui/feature-gates/feature-gate-simd-ffi.rs | 2 +- tests/ui/feature-gates/feature-gate-simd.rs | 5 +- tests/ui/layout/debug.rs | 2 +- tests/ui/repr/attr-usage-repr.rs | 2 +- tests/ui/repr/explicit-rust-repr-conflicts.rs | 2 +- tests/ui/simd/const-err-trumps-simd-err.rs | 4 +- .../ui/simd/const-err-trumps-simd-err.stderr | 4 +- tests/ui/simd/generics.rs | 6 +- tests/ui/simd/intrinsic/float-math-pass.rs | 18 +- tests/ui/simd/intrinsic/float-minmax-pass.rs | 12 +- .../ui/simd/intrinsic/generic-arithmetic-2.rs | 12 +- .../simd/intrinsic/generic-arithmetic-pass.rs | 168 +++++++------- .../generic-arithmetic-saturating-2.rs | 12 +- .../generic-arithmetic-saturating-pass.rs | 12 +- .../ui/simd/intrinsic/generic-bitmask-pass.rs | 16 +- tests/ui/simd/intrinsic/generic-cast.rs | 12 +- tests/ui/simd/intrinsic/generic-cast.stderr | 8 +- .../simd/intrinsic/generic-comparison-pass.rs | 34 +-- tests/ui/simd/intrinsic/generic-comparison.rs | 7 +- .../simd/intrinsic/generic-comparison.stderr | 36 +-- .../simd/intrinsic/generic-elements-pass.rs | 65 +++--- tests/ui/simd/intrinsic/generic-elements.rs | 14 +- .../ui/simd/intrinsic/generic-gather-pass.rs | 40 ++-- .../simd/intrinsic/generic-reduction-pass.rs | 28 +-- tests/ui/simd/intrinsic/generic-reduction.rs | 8 +- .../ui/simd/intrinsic/generic-select-pass.rs | 80 +++---- tests/ui/simd/intrinsic/generic-select.rs | 16 +- .../simd/intrinsic/inlining-issue67557-ice.rs | 4 +- .../ui/simd/intrinsic/inlining-issue67557.rs | 10 +- tests/ui/simd/issue-17170.rs | 4 +- tests/ui/simd/issue-32947.rs | 4 +- tests/ui/simd/issue-39720.rs | 6 +- tests/ui/simd/issue-89193.rs | 20 +- tests/ui/simd/monomorphize-heterogeneous.rs | 6 +- .../ui/simd/monomorphize-heterogeneous.stderr | 15 +- tests/ui/simd/monomorphize-too-long.rs | 11 + tests/ui/simd/monomorphize-too-long.stderr | 4 + tests/ui/simd/monomorphize-zero-length.rs | 11 + tests/ui/simd/monomorphize-zero-length.stderr | 4 + tests/ui/simd/target-feature-mixup.rs | 30 +-- ...ric-monomorphisation-extern-nonnull-ptr.rs | 4 +- .../type-generic-monomorphisation-wide-ptr.rs | 6 +- ...e-generic-monomorphisation-wide-ptr.stderr | 2 +- .../ui/simd/type-generic-monomorphisation.rs | 4 +- tests/ui/simd/type-len.rs | 9 +- tests/ui/simd/type-len.stderr | 30 ++- tests/ui/span/gated-features-attr-spans.rs | 3 +- 111 files changed, 826 insertions(+), 1113 deletions(-) create mode 100644 tests/ui/simd/monomorphize-too-long.rs create mode 100644 tests/ui/simd/monomorphize-too-long.stderr create mode 100644 tests/ui/simd/monomorphize-zero-length.rs create mode 100644 tests/ui/simd/monomorphize-zero-length.stderr diff --git a/compiler/rustc_error_codes/src/error_codes/E0074.md b/compiler/rustc_error_codes/src/error_codes/E0074.md index 785d6de226d3d..71d89f5eb60a4 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0074.md +++ b/compiler/rustc_error_codes/src/error_codes/E0074.md @@ -11,7 +11,7 @@ This will cause an error: #![feature(repr_simd)] #[repr(simd)] -struct Bad(T, T, T, T); +struct Bad([T; 4]); ``` This will not: @@ -20,5 +20,5 @@ This will not: #![feature(repr_simd)] #[repr(simd)] -struct Good(u32, u32, u32, u32); +struct Good([u32; 4]); ``` diff --git a/compiler/rustc_error_codes/src/error_codes/E0075.md b/compiler/rustc_error_codes/src/error_codes/E0075.md index 969c1ee71313e..b58018eafc30c 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0075.md +++ b/compiler/rustc_error_codes/src/error_codes/E0075.md @@ -1,6 +1,6 @@ -A `#[simd]` attribute was applied to an empty tuple struct. +A `#[simd]` attribute was applied to an empty or multi-field struct. -Erroneous code example: +Erroneous code examples: ```compile_fail,E0075 #![feature(repr_simd)] @@ -9,9 +9,15 @@ Erroneous code example: struct Bad; // error! ``` -The `#[simd]` attribute can only be applied to non empty tuple structs, because -it doesn't make sense to try to use SIMD operations when there are no values to -operate on. +```compile_fail,E0075 +#![feature(repr_simd)] + +#[repr(simd)] +struct Bad([u32; 1], [u32; 1]); // error! +``` + +The `#[simd]` attribute can only be applied to a single-field struct, because +the one field must be the array of values in the vector. Fixed example: @@ -19,5 +25,5 @@ Fixed example: #![feature(repr_simd)] #[repr(simd)] -struct Good(u32); // ok! +struct Good([u32; 2]); // ok! ``` diff --git a/compiler/rustc_error_codes/src/error_codes/E0076.md b/compiler/rustc_error_codes/src/error_codes/E0076.md index 1da8caa9506d7..b1943de63e5d4 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0076.md +++ b/compiler/rustc_error_codes/src/error_codes/E0076.md @@ -1,4 +1,4 @@ -All types in a tuple struct aren't the same when using the `#[simd]` +The type of the field in a tuple struct isn't an array when using the `#[simd]` attribute. Erroneous code example: @@ -7,12 +7,12 @@ Erroneous code example: #![feature(repr_simd)] #[repr(simd)] -struct Bad(u16, u32, u32 u32); // error! +struct Bad(u16); // error! ``` When using the `#[simd]` attribute to automatically use SIMD operations in tuple -struct, the types in the struct must all be of the same type, or the compiler -will trigger this error. +structs, if you want a single-lane vector then the field must be a 1-element +array, or the compiler will trigger this error. Fixed example: @@ -20,5 +20,5 @@ Fixed example: #![feature(repr_simd)] #[repr(simd)] -struct Good(u32, u32, u32, u32); // ok! +struct Good([u16; 1]); // ok! ``` diff --git a/compiler/rustc_error_codes/src/error_codes/E0077.md b/compiler/rustc_error_codes/src/error_codes/E0077.md index 91aa24d1f52f4..688bfd3e72795 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0077.md +++ b/compiler/rustc_error_codes/src/error_codes/E0077.md @@ -7,7 +7,7 @@ Erroneous code example: #![feature(repr_simd)] #[repr(simd)] -struct Bad(String); // error! +struct Bad([String; 2]); // error! ``` When using the `#[simd]` attribute on a tuple struct, the elements in the tuple @@ -19,5 +19,5 @@ Fixed example: #![feature(repr_simd)] #[repr(simd)] -struct Good(u32, u32, u32, u32); // ok! +struct Good([u32; 4]); // ok! ``` diff --git a/compiler/rustc_error_codes/src/error_codes/E0511.md b/compiler/rustc_error_codes/src/error_codes/E0511.md index 681f4e611c32d..45ff49bdebb29 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0511.md +++ b/compiler/rustc_error_codes/src/error_codes/E0511.md @@ -23,11 +23,11 @@ The generic type has to be a SIMD type. Example: #[repr(simd)] #[derive(Copy, Clone)] -struct i32x2(i32, i32); +struct i32x2([i32; 2]); extern "rust-intrinsic" { fn simd_add(a: T, b: T) -> T; } -unsafe { simd_add(i32x2(0, 0), i32x2(1, 2)); } // ok! +unsafe { simd_add(i32x2([0, 0]), i32x2([1, 2])); } // ok! ``` diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index e47c707ee18d9..d7b2510a1dffa 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -1064,20 +1064,29 @@ fn check_simd(tcx: TyCtxt<'_>, sp: Span, def_id: LocalDefId) { struct_span_code_err!(tcx.dcx(), sp, E0075, "SIMD vector cannot be empty").emit(); return; } - let e = fields[FieldIdx::ZERO].ty(tcx, args); - if !fields.iter().all(|f| f.ty(tcx, args) == e) { - struct_span_code_err!(tcx.dcx(), sp, E0076, "SIMD vector should be homogeneous") - .with_span_label(sp, "SIMD elements must have the same type") + + let array_field = &fields[FieldIdx::ZERO]; + let array_ty = array_field.ty(tcx, args); + let ty::Array(element_ty, len_const) = array_ty.kind() else { + struct_span_code_err!( + tcx.dcx(), + sp, + E0076, + "SIMD vector's only field must be an array" + ) + .with_span_label(tcx.def_span(array_field.did), "not an array") + .emit(); + return; + }; + + if let Some(second_field) = fields.get(FieldIdx::from_u32(1)) { + struct_span_code_err!(tcx.dcx(), sp, E0075, "SIMD vector cannot have multiple fields") + .with_span_label(tcx.def_span(second_field.did), "excess field") .emit(); return; } - let len = if let ty::Array(_ty, c) = e.kind() { - c.try_eval_target_usize(tcx, tcx.param_env(def.did())) - } else { - Some(fields.len() as u64) - }; - if let Some(len) = len { + if let Some(len) = len_const.try_eval_target_usize(tcx, tcx.param_env(def.did())) { if len == 0 { struct_span_code_err!(tcx.dcx(), sp, E0075, "SIMD vector cannot be empty").emit(); return; @@ -1097,16 +1106,9 @@ fn check_simd(tcx: TyCtxt<'_>, sp: Span, def_id: LocalDefId) { // These are scalar types which directly match a "machine" type // Yes: Integers, floats, "thin" pointers // No: char, "fat" pointers, compound types - match e.kind() { - ty::Param(_) => (), // pass struct(T, T, T, T) through, let monomorphization catch errors - ty::Int(_) | ty::Uint(_) | ty::Float(_) | ty::RawPtr(_, _) => (), // struct(u8, u8, u8, u8) is ok - ty::Array(t, _) if matches!(t.kind(), ty::Param(_)) => (), // pass struct([T; N]) through, let monomorphization catch errors - ty::Array(t, _clen) - if matches!( - t.kind(), - ty::Int(_) | ty::Uint(_) | ty::Float(_) | ty::RawPtr(_, _) - ) => - { /* struct([f32; 4]) is ok */ } + match element_ty.kind() { + ty::Param(_) => (), // pass struct([T; 4]) through, let monomorphization catch errors + ty::Int(_) | ty::Uint(_) | ty::Float(_) | ty::RawPtr(_, _) => (), // struct([u8; 4]) is ok _ => { struct_span_code_err!( tcx.dcx(), diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index 1f4f2c62d7084..4dd81659da830 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -1091,29 +1091,21 @@ impl<'tcx> Ty<'tcx> { } pub fn simd_size_and_type(self, tcx: TyCtxt<'tcx>) -> (u64, Ty<'tcx>) { - match self.kind() { - Adt(def, args) => { - assert!(def.repr().simd(), "`simd_size_and_type` called on non-SIMD type"); - let variant = def.non_enum_variant(); - let f0_ty = variant.fields[FieldIdx::ZERO].ty(tcx, args); - - match f0_ty.kind() { - // If the first field is an array, we assume it is the only field and its - // elements are the SIMD components. - Array(f0_elem_ty, f0_len) => { - // FIXME(repr_simd): https://github.com/rust-lang/rust/pull/78863#discussion_r522784112 - // The way we evaluate the `N` in `[T; N]` here only works since we use - // `simd_size_and_type` post-monomorphization. It will probably start to ICE - // if we use it in generic code. See the `simd-array-trait` ui test. - (f0_len.eval_target_usize(tcx, ParamEnv::empty()), *f0_elem_ty) - } - // Otherwise, the fields of this Adt are the SIMD components (and we assume they - // all have the same type). - _ => (variant.fields.len() as u64, f0_ty), - } - } - _ => bug!("`simd_size_and_type` called on invalid type"), - } + let Adt(def, args) = self.kind() else { + bug!("`simd_size_and_type` called on invalid type") + }; + assert!(def.repr().simd(), "`simd_size_and_type` called on non-SIMD type"); + let variant = def.non_enum_variant(); + assert_eq!(variant.fields.len(), 1); + let field_ty = variant.fields[FieldIdx::ZERO].ty(tcx, args); + let Array(f0_elem_ty, f0_len) = field_ty.kind() else { + bug!("Simd type has non-array field type {field_ty:?}") + }; + // FIXME(repr_simd): https://github.com/rust-lang/rust/pull/78863#discussion_r522784112 + // The way we evaluate the `N` in `[T; N]` here only works since we use + // `simd_size_and_type` post-monomorphization. It will probably start to ICE + // if we use it in generic code. See the `simd-array-trait` ui test. + (f0_len.eval_target_usize(tcx, ParamEnv::empty()), *f0_elem_ty) } #[inline] diff --git a/library/alloc/benches/slice.rs b/library/alloc/benches/slice.rs index b62be9d39a1cd..ab46603d7739c 100644 --- a/library/alloc/benches/slice.rs +++ b/library/alloc/benches/slice.rs @@ -336,10 +336,10 @@ reverse!(reverse_u32, u32, |x| x as u32); reverse!(reverse_u64, u64, |x| x as u64); reverse!(reverse_u128, u128, |x| x as u128); #[repr(simd)] -struct F64x4(f64, f64, f64, f64); +struct F64x4([f64; 4]); reverse!(reverse_simd_f64x4, F64x4, |x| { let x = x as f64; - F64x4(x, x, x, x) + F64x4([x, x, x, x]) }); macro_rules! rotate { diff --git a/tests/assembly/asm/aarch64-types.rs b/tests/assembly/asm/aarch64-types.rs index cf1882ba1a22e..1173ba8a4eb56 100644 --- a/tests/assembly/asm/aarch64-types.rs +++ b/tests/assembly/asm/aarch64-types.rs @@ -31,36 +31,39 @@ trait Sized {} #[lang = "copy"] trait Copy {} +// Do we really need to use no_core for this?!? +impl Copy for [T; N] {} + type ptr = *mut u8; #[repr(simd)] -pub struct i8x8(i8, i8, i8, i8, i8, i8, i8, i8); +pub struct i8x8([i8; 8]); #[repr(simd)] -pub struct i16x4(i16, i16, i16, i16); +pub struct i16x4([i16; 4]); #[repr(simd)] -pub struct i32x2(i32, i32); +pub struct i32x2([i32; 2]); #[repr(simd)] -pub struct i64x1(i64); +pub struct i64x1([i64; 1]); #[repr(simd)] -pub struct f16x4(f16, f16, f16, f16); +pub struct f16x4([f16; 4]); #[repr(simd)] -pub struct f32x2(f32, f32); +pub struct f32x2([f32; 2]); #[repr(simd)] -pub struct f64x1(f64); +pub struct f64x1([f64; 1]); #[repr(simd)] -pub struct i8x16(i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8); +pub struct i8x16([i8; 16]); #[repr(simd)] -pub struct i16x8(i16, i16, i16, i16, i16, i16, i16, i16); +pub struct i16x8([i16; 8]); #[repr(simd)] -pub struct i32x4(i32, i32, i32, i32); +pub struct i32x4([i32; 4]); #[repr(simd)] -pub struct i64x2(i64, i64); +pub struct i64x2([i64; 2]); #[repr(simd)] -pub struct f16x8(f16, f16, f16, f16, f16, f16, f16, f16); +pub struct f16x8([f16; 8]); #[repr(simd)] -pub struct f32x4(f32, f32, f32, f32); +pub struct f32x4([f32; 4]); #[repr(simd)] -pub struct f64x2(f64, f64); +pub struct f64x2([f64; 2]); impl Copy for i8 {} impl Copy for i16 {} diff --git a/tests/assembly/asm/arm-modifiers.rs b/tests/assembly/asm/arm-modifiers.rs index d421e0e6954cc..7d8d7e8387037 100644 --- a/tests/assembly/asm/arm-modifiers.rs +++ b/tests/assembly/asm/arm-modifiers.rs @@ -28,8 +28,11 @@ trait Sized {} #[lang = "copy"] trait Copy {} +// Do we really need to use no_core for this?!? +impl Copy for [T; N] {} + #[repr(simd)] -pub struct f32x4(f32, f32, f32, f32); +pub struct f32x4([f32; 4]); impl Copy for i32 {} impl Copy for f32 {} diff --git a/tests/assembly/asm/arm-types.rs b/tests/assembly/asm/arm-types.rs index 448b92aa8399a..9cebb588aaf86 100644 --- a/tests/assembly/asm/arm-types.rs +++ b/tests/assembly/asm/arm-types.rs @@ -31,32 +31,35 @@ trait Sized {} #[lang = "copy"] trait Copy {} +// Do we really need to use no_core for this?!? +impl Copy for [T; N] {} + type ptr = *mut u8; #[repr(simd)] -pub struct i8x8(i8, i8, i8, i8, i8, i8, i8, i8); +pub struct i8x8([i8; 8]); #[repr(simd)] -pub struct i16x4(i16, i16, i16, i16); +pub struct i16x4([i16; 4]); #[repr(simd)] -pub struct i32x2(i32, i32); +pub struct i32x2([i32; 2]); #[repr(simd)] -pub struct i64x1(i64); +pub struct i64x1([i64; 1]); #[repr(simd)] -pub struct f16x4(f16, f16, f16, f16); +pub struct f16x4([f16; 4]); #[repr(simd)] -pub struct f32x2(f32, f32); +pub struct f32x2([f32; 2]); #[repr(simd)] -pub struct i8x16(i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8); +pub struct i8x16([i8; 16]); #[repr(simd)] -pub struct i16x8(i16, i16, i16, i16, i16, i16, i16, i16); +pub struct i16x8([i16; 8]); #[repr(simd)] -pub struct i32x4(i32, i32, i32, i32); +pub struct i32x4([i32; 4]); #[repr(simd)] -pub struct i64x2(i64, i64); +pub struct i64x2([i64; 2]); #[repr(simd)] -pub struct f16x8(f16, f16, f16, f16, f16, f16, f16, f16); +pub struct f16x8([f16; 8]); #[repr(simd)] -pub struct f32x4(f32, f32, f32, f32); +pub struct f32x4([f32; 4]); impl Copy for i8 {} impl Copy for i16 {} diff --git a/tests/assembly/asm/x86-types.rs b/tests/assembly/asm/x86-types.rs index a40bc10d9915c..567dc7a8245fe 100644 --- a/tests/assembly/asm/x86-types.rs +++ b/tests/assembly/asm/x86-types.rs @@ -31,216 +31,55 @@ trait Sized {} #[lang = "copy"] trait Copy {} +// Do we really need to use no_core for this?!? +impl Copy for [T; N] {} + type ptr = *mut u8; #[repr(simd)] -pub struct i8x16(i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8); +pub struct i8x16([i8; 16]); #[repr(simd)] -pub struct i16x8(i16, i16, i16, i16, i16, i16, i16, i16); +pub struct i16x8([i16; 8]); #[repr(simd)] -pub struct i32x4(i32, i32, i32, i32); +pub struct i32x4([i32; 4]); #[repr(simd)] -pub struct i64x2(i64, i64); +pub struct i64x2([i64; 2]); #[repr(simd)] -pub struct f16x8(f16, f16, f16, f16, f16, f16, f16, f16); +pub struct f16x8([f16; 8]); #[repr(simd)] -pub struct f32x4(f32, f32, f32, f32); +pub struct f32x4([f32; 4]); #[repr(simd)] -pub struct f64x2(f64, f64); +pub struct f64x2([f64; 2]); #[repr(simd)] -pub struct i8x32( - i8, - i8, - i8, - i8, - i8, - i8, - i8, - i8, - i8, - i8, - i8, - i8, - i8, - i8, - i8, - i8, - i8, - i8, - i8, - i8, - i8, - i8, - i8, - i8, - i8, - i8, - i8, - i8, - i8, - i8, - i8, - i8, -); +pub struct i8x32([i8; 32]); #[repr(simd)] -pub struct i16x16(i16, i16, i16, i16, i16, i16, i16, i16, i16, i16, i16, i16, i16, i16, i16, i16); +pub struct i16x16([i16; 16]); #[repr(simd)] -pub struct i32x8(i32, i32, i32, i32, i32, i32, i32, i32); +pub struct i32x8([i32; 8]); #[repr(simd)] -pub struct i64x4(i64, i64, i64, i64); +pub struct i64x4([i64; 4]); #[repr(simd)] -pub struct f16x16(f16, f16, f16, f16, f16, f16, f16, f16, f16, f16, f16, f16, f16, f16, f16, f16); +pub struct f16x16([f16; 16]); #[repr(simd)] -pub struct f32x8(f32, f32, f32, f32, f32, f32, f32, f32); +pub struct f32x8([f32; 8]); #[repr(simd)] -pub struct f64x4(f64, f64, f64, f64); +pub struct f64x4([f64; 4]); #[repr(simd)] -pub struct i8x64( - i8, - i8, - i8, - i8, - i8, - i8, - i8, - i8, - i8, - i8, - i8, - i8, - i8, - i8, - i8, - i8, - i8, - i8, - i8, - i8, - i8, - i8, - i8, - i8, - i8, - i8, - i8, - i8, - i8, - i8, - i8, - i8, - i8, - i8, - i8, - i8, - i8, - i8, - i8, - i8, - i8, - i8, - i8, - i8, - i8, - i8, - i8, - i8, - i8, - i8, - i8, - i8, - i8, - i8, - i8, - i8, - i8, - i8, - i8, - i8, - i8, - i8, - i8, - i8, -); +pub struct i8x64([i8; 64]); #[repr(simd)] -pub struct i16x32( - i16, - i16, - i16, - i16, - i16, - i16, - i16, - i16, - i16, - i16, - i16, - i16, - i16, - i16, - i16, - i16, - i16, - i16, - i16, - i16, - i16, - i16, - i16, - i16, - i16, - i16, - i16, - i16, - i16, - i16, - i16, - i16, -); +pub struct i16x32([i16; 32]); #[repr(simd)] -pub struct i32x16(i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32); +pub struct i32x16([i32; 16]); #[repr(simd)] -pub struct i64x8(i64, i64, i64, i64, i64, i64, i64, i64); +pub struct i64x8([i64; 8]); #[repr(simd)] -pub struct f16x32( - f16, - f16, - f16, - f16, - f16, - f16, - f16, - f16, - f16, - f16, - f16, - f16, - f16, - f16, - f16, - f16, - f16, - f16, - f16, - f16, - f16, - f16, - f16, - f16, - f16, - f16, - f16, - f16, - f16, - f16, - f16, - f16, -); +pub struct f16x32([f16; 32]); #[repr(simd)] -pub struct f32x16(f32, f32, f32, f32, f32, f32, f32, f32, f32, f32, f32, f32, f32, f32, f32, f32); +pub struct f32x16([f32; 16]); #[repr(simd)] -pub struct f64x8(f64, f64, f64, f64, f64, f64, f64, f64); +pub struct f64x8([f64; 8]); macro_rules! impl_copy { ($($ty:ident)*) => { diff --git a/tests/codegen/align-byval-vector.rs b/tests/codegen/align-byval-vector.rs index 02b7d6b0c5e28..60d49f9308197 100644 --- a/tests/codegen/align-byval-vector.rs +++ b/tests/codegen/align-byval-vector.rs @@ -21,7 +21,7 @@ trait Freeze {} trait Copy {} #[repr(simd)] -pub struct i32x4(i32, i32, i32, i32); +pub struct i32x4([i32; 4]); #[repr(C)] pub struct Foo { @@ -47,12 +47,12 @@ extern "C" { } pub fn main() { - unsafe { f(Foo { a: i32x4(1, 2, 3, 4), b: 0 }) } + unsafe { f(Foo { a: i32x4([1, 2, 3, 4]), b: 0 }) } unsafe { g(DoubleFoo { - one: Foo { a: i32x4(1, 2, 3, 4), b: 0 }, - two: Foo { a: i32x4(1, 2, 3, 4), b: 0 }, + one: Foo { a: i32x4([1, 2, 3, 4]), b: 0 }, + two: Foo { a: i32x4([1, 2, 3, 4]), b: 0 }, }) } } diff --git a/tests/codegen/const-vector.rs b/tests/codegen/const-vector.rs index d368838201e2b..8343594e5d23c 100644 --- a/tests/codegen/const-vector.rs +++ b/tests/codegen/const-vector.rs @@ -13,19 +13,11 @@ // Setting up structs that can be used as const vectors #[repr(simd)] #[derive(Clone)] -pub struct i8x2(i8, i8); +pub struct i8x2([i8; 2]); #[repr(simd)] #[derive(Clone)] -pub struct i8x2_arr([i8; 2]); - -#[repr(simd)] -#[derive(Clone)] -pub struct f32x2(f32, f32); - -#[repr(simd)] -#[derive(Clone)] -pub struct f32x2_arr([f32; 2]); +pub struct f32x2([f32; 2]); #[repr(simd, packed)] #[derive(Copy, Clone)] @@ -35,42 +27,34 @@ pub struct Simd([T; N]); // that they are called with a const vector extern "unadjusted" { - #[no_mangle] fn test_i8x2(a: i8x2); } extern "unadjusted" { - #[no_mangle] fn test_i8x2_two_args(a: i8x2, b: i8x2); } extern "unadjusted" { - #[no_mangle] fn test_i8x2_mixed_args(a: i8x2, c: i32, b: i8x2); } extern "unadjusted" { - #[no_mangle] - fn test_i8x2_arr(a: i8x2_arr); + fn test_i8x2_arr(a: i8x2); } extern "unadjusted" { - #[no_mangle] fn test_f32x2(a: f32x2); } extern "unadjusted" { - #[no_mangle] - fn test_f32x2_arr(a: f32x2_arr); + fn test_f32x2_arr(a: f32x2); } extern "unadjusted" { - #[no_mangle] fn test_simd(a: Simd); } extern "unadjusted" { - #[no_mangle] fn test_simd_unaligned(a: Simd); } @@ -81,22 +65,22 @@ extern "unadjusted" { pub fn do_call() { unsafe { // CHECK: call void @test_i8x2(<2 x i8> - test_i8x2(const { i8x2(32, 64) }); + test_i8x2(const { i8x2([32, 64]) }); // CHECK: call void @test_i8x2_two_args(<2 x i8> , <2 x i8> - test_i8x2_two_args(const { i8x2(32, 64) }, const { i8x2(8, 16) }); + test_i8x2_two_args(const { i8x2([32, 64]) }, const { i8x2([8, 16]) }); // CHECK: call void @test_i8x2_mixed_args(<2 x i8> , i32 43, <2 x i8> - test_i8x2_mixed_args(const { i8x2(32, 64) }, 43, const { i8x2(8, 16) }); + test_i8x2_mixed_args(const { i8x2([32, 64]) }, 43, const { i8x2([8, 16]) }); // CHECK: call void @test_i8x2_arr(<2 x i8> - test_i8x2_arr(const { i8x2_arr([32, 64]) }); + test_i8x2_arr(const { i8x2([32, 64]) }); // CHECK: call void @test_f32x2(<2 x float> - test_f32x2(const { f32x2(0.32, 0.64) }); + test_f32x2(const { f32x2([0.32, 0.64]) }); // CHECK: void @test_f32x2_arr(<2 x float> - test_f32x2_arr(const { f32x2_arr([0.32, 0.64]) }); + test_f32x2_arr(const { f32x2([0.32, 0.64]) }); // CHECK: call void @test_simd(<4 x i32> test_simd(const { Simd::([2, 4, 6, 8]) }); diff --git a/tests/codegen/repr/transparent.rs b/tests/codegen/repr/transparent.rs index 9140b8542ecac..adcd3aacd2ace 100644 --- a/tests/codegen/repr/transparent.rs +++ b/tests/codegen/repr/transparent.rs @@ -132,7 +132,7 @@ pub extern "C" fn test_Nested2(_: Nested2) -> Nested2 { } #[repr(simd)] -struct f32x4(f32, f32, f32, f32); +struct f32x4([f32; 4]); #[repr(transparent)] pub struct Vector(f32x4); diff --git a/tests/codegen/simd-intrinsic/simd-intrinsic-float-abs.rs b/tests/codegen/simd-intrinsic/simd-intrinsic-float-abs.rs index f8efb678f76ef..4a5a6391c052f 100644 --- a/tests/codegen/simd-intrinsic/simd-intrinsic-float-abs.rs +++ b/tests/codegen/simd-intrinsic/simd-intrinsic-float-abs.rs @@ -7,23 +7,19 @@ #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f32x2(pub f32, pub f32); +pub struct f32x2(pub [f32; 2]); #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f32x4(pub f32, pub f32, pub f32, pub f32); +pub struct f32x4(pub [f32; 4]); #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f32x8(pub f32, pub f32, pub f32, pub f32, - pub f32, pub f32, pub f32, pub f32); +pub struct f32x8(pub [f32; 8]); #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f32x16(pub f32, pub f32, pub f32, pub f32, - pub f32, pub f32, pub f32, pub f32, - pub f32, pub f32, pub f32, pub f32, - pub f32, pub f32, pub f32, pub f32); +pub struct f32x16(pub [f32; 16]); extern "rust-intrinsic" { fn simd_fabs(x: T) -> T; @@ -59,16 +55,15 @@ pub unsafe fn fabs_32x16(a: f32x16) -> f32x16 { #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f64x2(pub f64, pub f64); +pub struct f64x2(pub [f64; 2]); #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f64x4(pub f64, pub f64, pub f64, pub f64); +pub struct f64x4(pub [f64; 4]); #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f64x8(pub f64, pub f64, pub f64, pub f64, - pub f64, pub f64, pub f64, pub f64); +pub struct f64x8(pub [f64; 8]); // CHECK-LABEL: @fabs_64x4 #[no_mangle] diff --git a/tests/codegen/simd-intrinsic/simd-intrinsic-float-ceil.rs b/tests/codegen/simd-intrinsic/simd-intrinsic-float-ceil.rs index a3ebec174b679..89e54f579ff7c 100644 --- a/tests/codegen/simd-intrinsic/simd-intrinsic-float-ceil.rs +++ b/tests/codegen/simd-intrinsic/simd-intrinsic-float-ceil.rs @@ -7,23 +7,19 @@ #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f32x2(pub f32, pub f32); +pub struct f32x2(pub [f32; 2]); #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f32x4(pub f32, pub f32, pub f32, pub f32); +pub struct f32x4(pub [f32; 4]); #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f32x8(pub f32, pub f32, pub f32, pub f32, - pub f32, pub f32, pub f32, pub f32); +pub struct f32x8(pub [f32; 8]); #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f32x16(pub f32, pub f32, pub f32, pub f32, - pub f32, pub f32, pub f32, pub f32, - pub f32, pub f32, pub f32, pub f32, - pub f32, pub f32, pub f32, pub f32); +pub struct f32x16(pub [f32; 16]); extern "rust-intrinsic" { fn simd_ceil(x: T) -> T; @@ -59,16 +55,15 @@ pub unsafe fn ceil_32x16(a: f32x16) -> f32x16 { #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f64x2(pub f64, pub f64); +pub struct f64x2(pub [f64; 2]); #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f64x4(pub f64, pub f64, pub f64, pub f64); +pub struct f64x4(pub [f64; 4]); #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f64x8(pub f64, pub f64, pub f64, pub f64, - pub f64, pub f64, pub f64, pub f64); +pub struct f64x8(pub [f64; 8]); // CHECK-LABEL: @ceil_64x4 #[no_mangle] diff --git a/tests/codegen/simd-intrinsic/simd-intrinsic-float-cos.rs b/tests/codegen/simd-intrinsic/simd-intrinsic-float-cos.rs index 00f97eef6f0cb..b40fd5365de57 100644 --- a/tests/codegen/simd-intrinsic/simd-intrinsic-float-cos.rs +++ b/tests/codegen/simd-intrinsic/simd-intrinsic-float-cos.rs @@ -7,23 +7,19 @@ #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f32x2(pub f32, pub f32); +pub struct f32x2(pub [f32; 2]); #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f32x4(pub f32, pub f32, pub f32, pub f32); +pub struct f32x4(pub [f32; 4]); #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f32x8(pub f32, pub f32, pub f32, pub f32, - pub f32, pub f32, pub f32, pub f32); +pub struct f32x8(pub [f32; 8]); #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f32x16(pub f32, pub f32, pub f32, pub f32, - pub f32, pub f32, pub f32, pub f32, - pub f32, pub f32, pub f32, pub f32, - pub f32, pub f32, pub f32, pub f32); +pub struct f32x16(pub [f32; 16]); extern "rust-intrinsic" { fn simd_fcos(x: T) -> T; @@ -59,16 +55,15 @@ pub unsafe fn fcos_32x16(a: f32x16) -> f32x16 { #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f64x2(pub f64, pub f64); +pub struct f64x2(pub [f64; 2]); #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f64x4(pub f64, pub f64, pub f64, pub f64); +pub struct f64x4(pub [f64; 4]); #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f64x8(pub f64, pub f64, pub f64, pub f64, - pub f64, pub f64, pub f64, pub f64); +pub struct f64x8(pub [f64; 8]); // CHECK-LABEL: @fcos_64x4 #[no_mangle] diff --git a/tests/codegen/simd-intrinsic/simd-intrinsic-float-exp.rs b/tests/codegen/simd-intrinsic/simd-intrinsic-float-exp.rs index 48c1a8ec489db..fef003dde5bb8 100644 --- a/tests/codegen/simd-intrinsic/simd-intrinsic-float-exp.rs +++ b/tests/codegen/simd-intrinsic/simd-intrinsic-float-exp.rs @@ -7,23 +7,19 @@ #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f32x2(pub f32, pub f32); +pub struct f32x2(pub [f32; 2]); #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f32x4(pub f32, pub f32, pub f32, pub f32); +pub struct f32x4(pub [f32; 4]); #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f32x8(pub f32, pub f32, pub f32, pub f32, - pub f32, pub f32, pub f32, pub f32); +pub struct f32x8(pub [f32; 8]); #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f32x16(pub f32, pub f32, pub f32, pub f32, - pub f32, pub f32, pub f32, pub f32, - pub f32, pub f32, pub f32, pub f32, - pub f32, pub f32, pub f32, pub f32); +pub struct f32x16(pub [f32; 16]); extern "rust-intrinsic" { fn simd_fexp(x: T) -> T; @@ -59,16 +55,15 @@ pub unsafe fn exp_32x16(a: f32x16) -> f32x16 { #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f64x2(pub f64, pub f64); +pub struct f64x2(pub [f64; 2]); #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f64x4(pub f64, pub f64, pub f64, pub f64); +pub struct f64x4(pub [f64; 4]); #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f64x8(pub f64, pub f64, pub f64, pub f64, - pub f64, pub f64, pub f64, pub f64); +pub struct f64x8(pub [f64; 8]); // CHECK-LABEL: @exp_64x4 #[no_mangle] diff --git a/tests/codegen/simd-intrinsic/simd-intrinsic-float-exp2.rs b/tests/codegen/simd-intrinsic/simd-intrinsic-float-exp2.rs index 23c38d8162157..779c0fc403a3d 100644 --- a/tests/codegen/simd-intrinsic/simd-intrinsic-float-exp2.rs +++ b/tests/codegen/simd-intrinsic/simd-intrinsic-float-exp2.rs @@ -7,23 +7,19 @@ #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f32x2(pub f32, pub f32); +pub struct f32x2(pub [f32; 2]); #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f32x4(pub f32, pub f32, pub f32, pub f32); +pub struct f32x4(pub [f32; 4]); #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f32x8(pub f32, pub f32, pub f32, pub f32, - pub f32, pub f32, pub f32, pub f32); +pub struct f32x8(pub [f32; 8]); #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f32x16(pub f32, pub f32, pub f32, pub f32, - pub f32, pub f32, pub f32, pub f32, - pub f32, pub f32, pub f32, pub f32, - pub f32, pub f32, pub f32, pub f32); +pub struct f32x16(pub [f32; 16]); extern "rust-intrinsic" { fn simd_fexp2(x: T) -> T; @@ -59,16 +55,15 @@ pub unsafe fn exp2_32x16(a: f32x16) -> f32x16 { #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f64x2(pub f64, pub f64); +pub struct f64x2(pub [f64; 2]); #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f64x4(pub f64, pub f64, pub f64, pub f64); +pub struct f64x4(pub [f64; 4]); #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f64x8(pub f64, pub f64, pub f64, pub f64, - pub f64, pub f64, pub f64, pub f64); +pub struct f64x8(pub [f64; 8]); // CHECK-LABEL: @exp2_64x4 #[no_mangle] diff --git a/tests/codegen/simd-intrinsic/simd-intrinsic-float-floor.rs b/tests/codegen/simd-intrinsic/simd-intrinsic-float-floor.rs index 978f263031ac3..b2bd27a5b75c2 100644 --- a/tests/codegen/simd-intrinsic/simd-intrinsic-float-floor.rs +++ b/tests/codegen/simd-intrinsic/simd-intrinsic-float-floor.rs @@ -7,23 +7,19 @@ #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f32x2(pub f32, pub f32); +pub struct f32x2(pub [f32; 2]); #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f32x4(pub f32, pub f32, pub f32, pub f32); +pub struct f32x4(pub [f32; 4]); #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f32x8(pub f32, pub f32, pub f32, pub f32, - pub f32, pub f32, pub f32, pub f32); +pub struct f32x8(pub [f32; 8]); #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f32x16(pub f32, pub f32, pub f32, pub f32, - pub f32, pub f32, pub f32, pub f32, - pub f32, pub f32, pub f32, pub f32, - pub f32, pub f32, pub f32, pub f32); +pub struct f32x16(pub [f32; 16]); extern "rust-intrinsic" { fn simd_floor(x: T) -> T; @@ -59,16 +55,15 @@ pub unsafe fn floor_32x16(a: f32x16) -> f32x16 { #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f64x2(pub f64, pub f64); +pub struct f64x2(pub [f64; 2]); #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f64x4(pub f64, pub f64, pub f64, pub f64); +pub struct f64x4(pub [f64; 4]); #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f64x8(pub f64, pub f64, pub f64, pub f64, - pub f64, pub f64, pub f64, pub f64); +pub struct f64x8(pub [f64; 8]); // CHECK-LABEL: @floor_64x4 #[no_mangle] diff --git a/tests/codegen/simd-intrinsic/simd-intrinsic-float-fma.rs b/tests/codegen/simd-intrinsic/simd-intrinsic-float-fma.rs index 200d67180265a..37f4782626add 100644 --- a/tests/codegen/simd-intrinsic/simd-intrinsic-float-fma.rs +++ b/tests/codegen/simd-intrinsic/simd-intrinsic-float-fma.rs @@ -7,23 +7,19 @@ #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f32x2(pub f32, pub f32); +pub struct f32x2(pub [f32; 2]); #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f32x4(pub f32, pub f32, pub f32, pub f32); +pub struct f32x4(pub [f32; 4]); #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f32x8(pub f32, pub f32, pub f32, pub f32, - pub f32, pub f32, pub f32, pub f32); +pub struct f32x8(pub [f32; 8]); #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f32x16(pub f32, pub f32, pub f32, pub f32, - pub f32, pub f32, pub f32, pub f32, - pub f32, pub f32, pub f32, pub f32, - pub f32, pub f32, pub f32, pub f32); +pub struct f32x16(pub [f32; 16]); extern "rust-intrinsic" { fn simd_fma(x: T, b: T, c: T) -> T; @@ -59,16 +55,15 @@ pub unsafe fn fma_32x16(a: f32x16, b: f32x16, c: f32x16) -> f32x16 { #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f64x2(pub f64, pub f64); +pub struct f64x2(pub [f64; 2]); #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f64x4(pub f64, pub f64, pub f64, pub f64); +pub struct f64x4(pub [f64; 4]); #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f64x8(pub f64, pub f64, pub f64, pub f64, - pub f64, pub f64, pub f64, pub f64); +pub struct f64x8(pub [f64; 8]); // CHECK-LABEL: @fma_64x4 #[no_mangle] diff --git a/tests/codegen/simd-intrinsic/simd-intrinsic-float-fsqrt.rs b/tests/codegen/simd-intrinsic/simd-intrinsic-float-fsqrt.rs index f70de3e27536e..336adf6db73f1 100644 --- a/tests/codegen/simd-intrinsic/simd-intrinsic-float-fsqrt.rs +++ b/tests/codegen/simd-intrinsic/simd-intrinsic-float-fsqrt.rs @@ -7,23 +7,19 @@ #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f32x2(pub f32, pub f32); +pub struct f32x2(pub [f32; 2]); #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f32x4(pub f32, pub f32, pub f32, pub f32); +pub struct f32x4(pub [f32; 4]); #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f32x8(pub f32, pub f32, pub f32, pub f32, - pub f32, pub f32, pub f32, pub f32); +pub struct f32x8(pub [f32; 8]); #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f32x16(pub f32, pub f32, pub f32, pub f32, - pub f32, pub f32, pub f32, pub f32, - pub f32, pub f32, pub f32, pub f32, - pub f32, pub f32, pub f32, pub f32); +pub struct f32x16(pub [f32; 16]); extern "rust-intrinsic" { fn simd_fsqrt(x: T) -> T; @@ -59,16 +55,15 @@ pub unsafe fn fsqrt_32x16(a: f32x16) -> f32x16 { #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f64x2(pub f64, pub f64); +pub struct f64x2(pub [f64; 2]); #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f64x4(pub f64, pub f64, pub f64, pub f64); +pub struct f64x4(pub [f64; 4]); #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f64x8(pub f64, pub f64, pub f64, pub f64, - pub f64, pub f64, pub f64, pub f64); +pub struct f64x8(pub [f64; 8]); // CHECK-LABEL: @fsqrt_64x4 #[no_mangle] diff --git a/tests/codegen/simd-intrinsic/simd-intrinsic-float-log.rs b/tests/codegen/simd-intrinsic/simd-intrinsic-float-log.rs index c0edd3ea48fc9..8e97abc3a6618 100644 --- a/tests/codegen/simd-intrinsic/simd-intrinsic-float-log.rs +++ b/tests/codegen/simd-intrinsic/simd-intrinsic-float-log.rs @@ -7,23 +7,19 @@ #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f32x2(pub f32, pub f32); +pub struct f32x2(pub [f32; 2]); #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f32x4(pub f32, pub f32, pub f32, pub f32); +pub struct f32x4(pub [f32; 4]); #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f32x8(pub f32, pub f32, pub f32, pub f32, - pub f32, pub f32, pub f32, pub f32); +pub struct f32x8(pub [f32; 8]); #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f32x16(pub f32, pub f32, pub f32, pub f32, - pub f32, pub f32, pub f32, pub f32, - pub f32, pub f32, pub f32, pub f32, - pub f32, pub f32, pub f32, pub f32); +pub struct f32x16(pub [f32; 16]); extern "rust-intrinsic" { fn simd_flog(x: T) -> T; @@ -59,16 +55,15 @@ pub unsafe fn log_32x16(a: f32x16) -> f32x16 { #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f64x2(pub f64, pub f64); +pub struct f64x2(pub [f64; 2]); #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f64x4(pub f64, pub f64, pub f64, pub f64); +pub struct f64x4(pub [f64; 4]); #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f64x8(pub f64, pub f64, pub f64, pub f64, - pub f64, pub f64, pub f64, pub f64); +pub struct f64x8(pub [f64; 8]); // CHECK-LABEL: @log_64x4 #[no_mangle] diff --git a/tests/codegen/simd-intrinsic/simd-intrinsic-float-log10.rs b/tests/codegen/simd-intrinsic/simd-intrinsic-float-log10.rs index 766307f47ed35..1d4d4dc24e9ad 100644 --- a/tests/codegen/simd-intrinsic/simd-intrinsic-float-log10.rs +++ b/tests/codegen/simd-intrinsic/simd-intrinsic-float-log10.rs @@ -7,23 +7,19 @@ #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f32x2(pub f32, pub f32); +pub struct f32x2(pub [f32; 2]); #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f32x4(pub f32, pub f32, pub f32, pub f32); +pub struct f32x4(pub [f32; 4]); #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f32x8(pub f32, pub f32, pub f32, pub f32, - pub f32, pub f32, pub f32, pub f32); +pub struct f32x8(pub [f32; 8]); #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f32x16(pub f32, pub f32, pub f32, pub f32, - pub f32, pub f32, pub f32, pub f32, - pub f32, pub f32, pub f32, pub f32, - pub f32, pub f32, pub f32, pub f32); +pub struct f32x16(pub [f32; 16]); extern "rust-intrinsic" { fn simd_flog10(x: T) -> T; @@ -59,16 +55,15 @@ pub unsafe fn log10_32x16(a: f32x16) -> f32x16 { #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f64x2(pub f64, pub f64); +pub struct f64x2(pub [f64; 2]); #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f64x4(pub f64, pub f64, pub f64, pub f64); +pub struct f64x4(pub [f64; 4]); #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f64x8(pub f64, pub f64, pub f64, pub f64, - pub f64, pub f64, pub f64, pub f64); +pub struct f64x8(pub [f64; 8]); // CHECK-LABEL: @log10_64x4 #[no_mangle] diff --git a/tests/codegen/simd-intrinsic/simd-intrinsic-float-log2.rs b/tests/codegen/simd-intrinsic/simd-intrinsic-float-log2.rs index 90c5918c33ea3..28f2f1516175c 100644 --- a/tests/codegen/simd-intrinsic/simd-intrinsic-float-log2.rs +++ b/tests/codegen/simd-intrinsic/simd-intrinsic-float-log2.rs @@ -7,23 +7,19 @@ #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f32x2(pub f32, pub f32); +pub struct f32x2(pub [f32; 2]); #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f32x4(pub f32, pub f32, pub f32, pub f32); +pub struct f32x4(pub [f32; 4]); #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f32x8(pub f32, pub f32, pub f32, pub f32, - pub f32, pub f32, pub f32, pub f32); +pub struct f32x8(pub [f32; 8]); #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f32x16(pub f32, pub f32, pub f32, pub f32, - pub f32, pub f32, pub f32, pub f32, - pub f32, pub f32, pub f32, pub f32, - pub f32, pub f32, pub f32, pub f32); +pub struct f32x16(pub [f32; 16]); extern "rust-intrinsic" { fn simd_flog2(x: T) -> T; @@ -59,16 +55,15 @@ pub unsafe fn log2_32x16(a: f32x16) -> f32x16 { #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f64x2(pub f64, pub f64); +pub struct f64x2(pub [f64; 2]); #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f64x4(pub f64, pub f64, pub f64, pub f64); +pub struct f64x4(pub [f64; 4]); #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f64x8(pub f64, pub f64, pub f64, pub f64, - pub f64, pub f64, pub f64, pub f64); +pub struct f64x8(pub [f64; 8]); // CHECK-LABEL: @log2_64x4 #[no_mangle] diff --git a/tests/codegen/simd-intrinsic/simd-intrinsic-float-minmax.rs b/tests/codegen/simd-intrinsic/simd-intrinsic-float-minmax.rs index d949112bae762..50c51bebe37ee 100644 --- a/tests/codegen/simd-intrinsic/simd-intrinsic-float-minmax.rs +++ b/tests/codegen/simd-intrinsic/simd-intrinsic-float-minmax.rs @@ -7,7 +7,7 @@ #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f32x4(pub f32, pub f32, pub f32, pub f32); +pub struct f32x4(pub [f32; 4]); extern "rust-intrinsic" { fn simd_fmin(x: T, y: T) -> T; diff --git a/tests/codegen/simd-intrinsic/simd-intrinsic-float-pow.rs b/tests/codegen/simd-intrinsic/simd-intrinsic-float-pow.rs index 21641c80d313c..3527f71c00b47 100644 --- a/tests/codegen/simd-intrinsic/simd-intrinsic-float-pow.rs +++ b/tests/codegen/simd-intrinsic/simd-intrinsic-float-pow.rs @@ -7,23 +7,19 @@ #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f32x2(pub f32, pub f32); +pub struct f32x2(pub [f32; 2]); #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f32x4(pub f32, pub f32, pub f32, pub f32); +pub struct f32x4(pub [f32; 4]); #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f32x8(pub f32, pub f32, pub f32, pub f32, - pub f32, pub f32, pub f32, pub f32); +pub struct f32x8(pub [f32; 8]); #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f32x16(pub f32, pub f32, pub f32, pub f32, - pub f32, pub f32, pub f32, pub f32, - pub f32, pub f32, pub f32, pub f32, - pub f32, pub f32, pub f32, pub f32); +pub struct f32x16(pub [f32; 16]); extern "rust-intrinsic" { fn simd_fpow(x: T, b: T) -> T; @@ -59,16 +55,15 @@ pub unsafe fn fpow_32x16(a: f32x16, b: f32x16) -> f32x16 { #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f64x2(pub f64, pub f64); +pub struct f64x2(pub [f64; 2]); #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f64x4(pub f64, pub f64, pub f64, pub f64); +pub struct f64x4(pub [f64; 4]); #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f64x8(pub f64, pub f64, pub f64, pub f64, - pub f64, pub f64, pub f64, pub f64); +pub struct f64x8(pub [f64; 8]); // CHECK-LABEL: @fpow_64x4 #[no_mangle] diff --git a/tests/codegen/simd-intrinsic/simd-intrinsic-float-powi.rs b/tests/codegen/simd-intrinsic/simd-intrinsic-float-powi.rs index 3985bdd50df70..4f0b5e4e01a3e 100644 --- a/tests/codegen/simd-intrinsic/simd-intrinsic-float-powi.rs +++ b/tests/codegen/simd-intrinsic/simd-intrinsic-float-powi.rs @@ -7,23 +7,19 @@ #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f32x2(pub f32, pub f32); +pub struct f32x2(pub [f32; 2]); #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f32x4(pub f32, pub f32, pub f32, pub f32); +pub struct f32x4(pub [f32; 4]); #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f32x8(pub f32, pub f32, pub f32, pub f32, - pub f32, pub f32, pub f32, pub f32); +pub struct f32x8(pub [f32; 8]); #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f32x16(pub f32, pub f32, pub f32, pub f32, - pub f32, pub f32, pub f32, pub f32, - pub f32, pub f32, pub f32, pub f32, - pub f32, pub f32, pub f32, pub f32); +pub struct f32x16(pub [f32; 16]); extern "rust-intrinsic" { fn simd_fpowi(x: T, b: i32) -> T; @@ -59,16 +55,15 @@ pub unsafe fn fpowi_32x16(a: f32x16, b: i32) -> f32x16 { #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f64x2(pub f64, pub f64); +pub struct f64x2(pub [f64; 2]); #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f64x4(pub f64, pub f64, pub f64, pub f64); +pub struct f64x4(pub [f64; 4]); #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f64x8(pub f64, pub f64, pub f64, pub f64, - pub f64, pub f64, pub f64, pub f64); +pub struct f64x8(pub [f64; 8]); // CHECK-LABEL: @fpowi_64x4 #[no_mangle] diff --git a/tests/codegen/simd-intrinsic/simd-intrinsic-float-sin.rs b/tests/codegen/simd-intrinsic/simd-intrinsic-float-sin.rs index f6978e32df724..4173809e3a9b3 100644 --- a/tests/codegen/simd-intrinsic/simd-intrinsic-float-sin.rs +++ b/tests/codegen/simd-intrinsic/simd-intrinsic-float-sin.rs @@ -7,23 +7,19 @@ #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f32x2(pub f32, pub f32); +pub struct f32x2(pub [f32; 2]); #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f32x4(pub f32, pub f32, pub f32, pub f32); +pub struct f32x4(pub [f32; 4]); #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f32x8(pub f32, pub f32, pub f32, pub f32, - pub f32, pub f32, pub f32, pub f32); +pub struct f32x8(pub [f32; 8]); #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f32x16(pub f32, pub f32, pub f32, pub f32, - pub f32, pub f32, pub f32, pub f32, - pub f32, pub f32, pub f32, pub f32, - pub f32, pub f32, pub f32, pub f32); +pub struct f32x16(pub [f32; 16]); extern "rust-intrinsic" { fn simd_fsin(x: T) -> T; @@ -59,16 +55,15 @@ pub unsafe fn fsin_32x16(a: f32x16) -> f32x16 { #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f64x2(pub f64, pub f64); +pub struct f64x2(pub [f64; 2]); #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f64x4(pub f64, pub f64, pub f64, pub f64); +pub struct f64x4(pub [f64; 4]); #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f64x8(pub f64, pub f64, pub f64, pub f64, - pub f64, pub f64, pub f64, pub f64); +pub struct f64x8(pub [f64; 8]); // CHECK-LABEL: @fsin_64x4 #[no_mangle] diff --git a/tests/codegen/simd-intrinsic/simd-intrinsic-generic-arithmetic-saturating.rs b/tests/codegen/simd-intrinsic/simd-intrinsic-generic-arithmetic-saturating.rs index 809f9a32226f4..a5afa27876a0f 100644 --- a/tests/codegen/simd-intrinsic/simd-intrinsic-generic-arithmetic-saturating.rs +++ b/tests/codegen/simd-intrinsic/simd-intrinsic-generic-arithmetic-saturating.rs @@ -9,107 +9,57 @@ // signed integer types -#[repr(simd)] #[derive(Copy, Clone)] pub struct i8x2(i8, i8); -#[repr(simd)] #[derive(Copy, Clone)] pub struct i8x4(i8, i8, i8, i8); -#[repr(simd)] #[derive(Copy, Clone)] pub struct i8x8( - i8, i8, i8, i8, i8, i8, i8, i8, -); -#[repr(simd)] #[derive(Copy, Clone)] pub struct i8x16( - i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, -); -#[repr(simd)] #[derive(Copy, Clone)] pub struct i8x32( - i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, - i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, -); -#[repr(simd)] #[derive(Copy, Clone)] pub struct i8x64( - i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, - i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, - i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, - i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, -); - -#[repr(simd)] #[derive(Copy, Clone)] pub struct i16x2(i16, i16); -#[repr(simd)] #[derive(Copy, Clone)] pub struct i16x4(i16, i16, i16, i16); -#[repr(simd)] #[derive(Copy, Clone)] pub struct i16x8( - i16, i16, i16, i16, i16, i16, i16, i16, -); -#[repr(simd)] #[derive(Copy, Clone)] pub struct i16x16( - i16, i16, i16, i16, i16, i16, i16, i16, i16, i16, i16, i16, i16, i16, i16, i16, -); -#[repr(simd)] #[derive(Copy, Clone)] pub struct i16x32( - i16, i16, i16, i16, i16, i16, i16, i16, i16, i16, i16, i16, i16, i16, i16, i16, - i16, i16, i16, i16, i16, i16, i16, i16, i16, i16, i16, i16, i16, i16, i16, i16, -); - -#[repr(simd)] #[derive(Copy, Clone)] pub struct i32x2(i32, i32); -#[repr(simd)] #[derive(Copy, Clone)] pub struct i32x4(i32, i32, i32, i32); -#[repr(simd)] #[derive(Copy, Clone)] pub struct i32x8( - i32, i32, i32, i32, i32, i32, i32, i32, -); -#[repr(simd)] #[derive(Copy, Clone)] pub struct i32x16( - i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, -); - -#[repr(simd)] #[derive(Copy, Clone)] pub struct i64x2(i64, i64); -#[repr(simd)] #[derive(Copy, Clone)] pub struct i64x4(i64, i64, i64, i64); -#[repr(simd)] #[derive(Copy, Clone)] pub struct i64x8( - i64, i64, i64, i64, i64, i64, i64, i64, -); - -#[repr(simd)] #[derive(Copy, Clone)] pub struct i128x2(i128, i128); -#[repr(simd)] #[derive(Copy, Clone)] pub struct i128x4(i128, i128, i128, i128); +#[repr(simd)] #[derive(Copy, Clone)] pub struct i8x2([i8; 2]); +#[repr(simd)] #[derive(Copy, Clone)] pub struct i8x4([i8; 4]); +#[repr(simd)] #[derive(Copy, Clone)] pub struct i8x8([i8; 8]); +#[repr(simd)] #[derive(Copy, Clone)] pub struct i8x16([i8; 16]); +#[repr(simd)] #[derive(Copy, Clone)] pub struct i8x32([i8; 32]); +#[repr(simd)] #[derive(Copy, Clone)] pub struct i8x64([i8; 64]); + +#[repr(simd)] #[derive(Copy, Clone)] pub struct i16x2([i16; 2]); +#[repr(simd)] #[derive(Copy, Clone)] pub struct i16x4([i16; 4]); +#[repr(simd)] #[derive(Copy, Clone)] pub struct i16x8([i16; 8]); +#[repr(simd)] #[derive(Copy, Clone)] pub struct i16x16([i16; 16]); +#[repr(simd)] #[derive(Copy, Clone)] pub struct i16x32([i16; 32]); + +#[repr(simd)] #[derive(Copy, Clone)] pub struct i32x2([i32; 2]); +#[repr(simd)] #[derive(Copy, Clone)] pub struct i32x4([i32; 4]); +#[repr(simd)] #[derive(Copy, Clone)] pub struct i32x8([i32; 8]); +#[repr(simd)] #[derive(Copy, Clone)] pub struct i32x16([i32; 16]); + +#[repr(simd)] #[derive(Copy, Clone)] pub struct i64x2([i64; 2]); +#[repr(simd)] #[derive(Copy, Clone)] pub struct i64x4([i64; 4]); +#[repr(simd)] #[derive(Copy, Clone)] pub struct i64x8([i64; 8]); + +#[repr(simd)] #[derive(Copy, Clone)] pub struct i128x2([i128; 2]); +#[repr(simd)] #[derive(Copy, Clone)] pub struct i128x4([i128; 4]); // unsigned integer types -#[repr(simd)] #[derive(Copy, Clone)] pub struct u8x2(u8, u8); -#[repr(simd)] #[derive(Copy, Clone)] pub struct u8x4(u8, u8, u8, u8); -#[repr(simd)] #[derive(Copy, Clone)] pub struct u8x8( - u8, u8, u8, u8, u8, u8, u8, u8, -); -#[repr(simd)] #[derive(Copy, Clone)] pub struct u8x16( - u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, -); -#[repr(simd)] #[derive(Copy, Clone)] pub struct u8x32( - u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, - u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, -); -#[repr(simd)] #[derive(Copy, Clone)] pub struct u8x64( - u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, - u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, - u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, - u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, -); - -#[repr(simd)] #[derive(Copy, Clone)] pub struct u16x2(u16, u16); -#[repr(simd)] #[derive(Copy, Clone)] pub struct u16x4(u16, u16, u16, u16); -#[repr(simd)] #[derive(Copy, Clone)] pub struct u16x8( - u16, u16, u16, u16, u16, u16, u16, u16, -); -#[repr(simd)] #[derive(Copy, Clone)] pub struct u16x16( - u16, u16, u16, u16, u16, u16, u16, u16, u16, u16, u16, u16, u16, u16, u16, u16, -); -#[repr(simd)] #[derive(Copy, Clone)] pub struct u16x32( - u16, u16, u16, u16, u16, u16, u16, u16, u16, u16, u16, u16, u16, u16, u16, u16, - u16, u16, u16, u16, u16, u16, u16, u16, u16, u16, u16, u16, u16, u16, u16, u16, -); - -#[repr(simd)] #[derive(Copy, Clone)] pub struct u32x2(u32, u32); -#[repr(simd)] #[derive(Copy, Clone)] pub struct u32x4(u32, u32, u32, u32); -#[repr(simd)] #[derive(Copy, Clone)] pub struct u32x8( - u32, u32, u32, u32, u32, u32, u32, u32, -); -#[repr(simd)] #[derive(Copy, Clone)] pub struct u32x16( - u32, u32, u32, u32, u32, u32, u32, u32, u32, u32, u32, u32, u32, u32, u32, u32, -); - -#[repr(simd)] #[derive(Copy, Clone)] pub struct u64x2(u64, u64); -#[repr(simd)] #[derive(Copy, Clone)] pub struct u64x4(u64, u64, u64, u64); -#[repr(simd)] #[derive(Copy, Clone)] pub struct u64x8( - u64, u64, u64, u64, u64, u64, u64, u64, -); - -#[repr(simd)] #[derive(Copy, Clone)] pub struct u128x2(u128, u128); -#[repr(simd)] #[derive(Copy, Clone)] pub struct u128x4(u128, u128, u128, u128); +#[repr(simd)] #[derive(Copy, Clone)] pub struct u8x2([u8; 2]); +#[repr(simd)] #[derive(Copy, Clone)] pub struct u8x4([u8; 4]); +#[repr(simd)] #[derive(Copy, Clone)] pub struct u8x8([u8; 8]); +#[repr(simd)] #[derive(Copy, Clone)] pub struct u8x16([u8; 16]); +#[repr(simd)] #[derive(Copy, Clone)] pub struct u8x32([u8; 32]); +#[repr(simd)] #[derive(Copy, Clone)] pub struct u8x64([u8; 64]); + +#[repr(simd)] #[derive(Copy, Clone)] pub struct u16x2([u16; 2]); +#[repr(simd)] #[derive(Copy, Clone)] pub struct u16x4([u16; 4]); +#[repr(simd)] #[derive(Copy, Clone)] pub struct u16x8([u16; 8]); +#[repr(simd)] #[derive(Copy, Clone)] pub struct u16x16([u16; 16]); +#[repr(simd)] #[derive(Copy, Clone)] pub struct u16x32([u16; 32]); + +#[repr(simd)] #[derive(Copy, Clone)] pub struct u32x2([u32; 2]); +#[repr(simd)] #[derive(Copy, Clone)] pub struct u32x4([u32; 4]); +#[repr(simd)] #[derive(Copy, Clone)] pub struct u32x8([u32; 8]); +#[repr(simd)] #[derive(Copy, Clone)] pub struct u32x16([u32; 16]); + +#[repr(simd)] #[derive(Copy, Clone)] pub struct u64x2([u64; 2]); +#[repr(simd)] #[derive(Copy, Clone)] pub struct u64x4([u64; 4]); +#[repr(simd)] #[derive(Copy, Clone)] pub struct u64x8([u64; 8]); + +#[repr(simd)] #[derive(Copy, Clone)] pub struct u128x2([u128; 2]); +#[repr(simd)] #[derive(Copy, Clone)] pub struct u128x4([u128; 4]); extern "rust-intrinsic" { fn simd_saturating_add(x: T, y: T) -> T; diff --git a/tests/codegen/simd-intrinsic/simd-intrinsic-generic-bitmask.rs b/tests/codegen/simd-intrinsic/simd-intrinsic-generic-bitmask.rs index 44a4c52d64a87..81ac90269b7df 100644 --- a/tests/codegen/simd-intrinsic/simd-intrinsic-generic-bitmask.rs +++ b/tests/codegen/simd-intrinsic/simd-intrinsic-generic-bitmask.rs @@ -8,19 +8,15 @@ #[repr(simd)] #[derive(Copy, Clone)] -pub struct u32x2(u32, u32); +pub struct u32x2([u32; 2]); #[repr(simd)] #[derive(Copy, Clone)] -pub struct i32x2(i32, i32); +pub struct i32x2([i32; 2]); #[repr(simd)] #[derive(Copy, Clone)] -pub struct i8x16( - i8, i8, i8, i8, i8, i8, i8, i8, - i8, i8, i8, i8, i8, i8, i8, i8, -); - +pub struct i8x16([i8; 16]); extern "rust-intrinsic" { fn simd_bitmask(x: T) -> U; diff --git a/tests/codegen/simd-intrinsic/simd-intrinsic-generic-gather.rs b/tests/codegen/simd-intrinsic/simd-intrinsic-generic-gather.rs index 863a9606c7e99..10ceeecf9007e 100644 --- a/tests/codegen/simd-intrinsic/simd-intrinsic-generic-gather.rs +++ b/tests/codegen/simd-intrinsic/simd-intrinsic-generic-gather.rs @@ -9,11 +9,11 @@ #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct Vec2(pub T, pub T); +pub struct Vec2(pub [T; 2]); #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct Vec4(pub T, pub T, pub T, pub T); +pub struct Vec4(pub [T; 4]); extern "rust-intrinsic" { fn simd_gather(value: T, pointers: P, mask: M) -> T; diff --git a/tests/codegen/simd-intrinsic/simd-intrinsic-generic-masked-load.rs b/tests/codegen/simd-intrinsic/simd-intrinsic-generic-masked-load.rs index b41c42810aafd..073dc0ac94d9e 100644 --- a/tests/codegen/simd-intrinsic/simd-intrinsic-generic-masked-load.rs +++ b/tests/codegen/simd-intrinsic/simd-intrinsic-generic-masked-load.rs @@ -7,11 +7,11 @@ #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct Vec2(pub T, pub T); +pub struct Vec2(pub [T; 2]); #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct Vec4(pub T, pub T, pub T, pub T); +pub struct Vec4(pub [T; 4]); extern "rust-intrinsic" { fn simd_masked_load(mask: M, pointer: P, values: T) -> T; diff --git a/tests/codegen/simd-intrinsic/simd-intrinsic-generic-masked-store.rs b/tests/codegen/simd-intrinsic/simd-intrinsic-generic-masked-store.rs index 066392bcde682..7c3393e6f2e7b 100644 --- a/tests/codegen/simd-intrinsic/simd-intrinsic-generic-masked-store.rs +++ b/tests/codegen/simd-intrinsic/simd-intrinsic-generic-masked-store.rs @@ -7,11 +7,11 @@ #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct Vec2(pub T, pub T); +pub struct Vec2(pub [T; 2]); #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct Vec4(pub T, pub T, pub T, pub T); +pub struct Vec4(pub [T; 4]); extern "rust-intrinsic" { fn simd_masked_store(mask: M, pointer: P, values: T) -> (); diff --git a/tests/codegen/simd-intrinsic/simd-intrinsic-generic-scatter.rs b/tests/codegen/simd-intrinsic/simd-intrinsic-generic-scatter.rs index e85bd61c7f83b..3c75ef5be40be 100644 --- a/tests/codegen/simd-intrinsic/simd-intrinsic-generic-scatter.rs +++ b/tests/codegen/simd-intrinsic/simd-intrinsic-generic-scatter.rs @@ -9,11 +9,11 @@ #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct Vec2(pub T, pub T); +pub struct Vec2(pub [T; 2]); #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct Vec4(pub T, pub T, pub T, pub T); +pub struct Vec4(pub [T; 4]); extern "rust-intrinsic" { fn simd_scatter(value: T, pointers: P, mask: M); diff --git a/tests/codegen/simd-intrinsic/simd-intrinsic-generic-select.rs b/tests/codegen/simd-intrinsic/simd-intrinsic-generic-select.rs index 05d2bf627ef12..c12fefa413b24 100644 --- a/tests/codegen/simd-intrinsic/simd-intrinsic-generic-select.rs +++ b/tests/codegen/simd-intrinsic/simd-intrinsic-generic-select.rs @@ -7,15 +7,15 @@ #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f32x4(pub f32, pub f32, pub f32, pub f32); +pub struct f32x4(pub [f32; 4]); #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f32x8(f32, f32, f32, f32, f32, f32, f32, f32); +pub struct f32x8([f32; 8]); #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct b8x4(pub i8, pub i8, pub i8, pub i8); +pub struct b8x4(pub [i8; 4]); extern "rust-intrinsic" { fn simd_select(x: T, a: U, b: U) -> U; diff --git a/tests/codegen/simd-intrinsic/simd-intrinsic-transmute-array.rs b/tests/codegen/simd-intrinsic/simd-intrinsic-transmute-array.rs index c416f4d28bb53..75f989d6e12c4 100644 --- a/tests/codegen/simd-intrinsic/simd-intrinsic-transmute-array.rs +++ b/tests/codegen/simd-intrinsic/simd-intrinsic-transmute-array.rs @@ -13,10 +13,6 @@ pub struct S([f32; N]); #[derive(Copy, Clone)] pub struct T([f32; 4]); -#[repr(simd)] -#[derive(Copy, Clone)] -pub struct U(f32, f32, f32, f32); - // CHECK-LABEL: @array_align( #[no_mangle] pub fn array_align() -> usize { @@ -28,7 +24,7 @@ pub fn array_align() -> usize { #[no_mangle] pub fn vector_align() -> usize { // CHECK: ret [[USIZE]] [[VECTOR_ALIGN:[0-9]+]] - const { std::mem::align_of::() } + const { std::mem::align_of::() } } // CHECK-LABEL: @build_array_s @@ -60,22 +56,3 @@ pub fn build_array_transmute_t(x: [f32; 4]) -> T { // CHECK: store <4 x float> %[[VAL:.+]], ptr %_0, align [[VECTOR_ALIGN]] unsafe { std::mem::transmute(x) } } - -// CHECK-LABEL: @build_array_u -#[no_mangle] -pub fn build_array_u(x: [f32; 4]) -> U { - // CHECK: store float %a, {{.+}}, align [[VECTOR_ALIGN]] - // CHECK: store float %b, {{.+}}, align [[ARRAY_ALIGN]] - // CHECK: store float %c, {{.+}}, align - // CHECK: store float %d, {{.+}}, align [[ARRAY_ALIGN]] - let [a, b, c, d] = x; - U(a, b, c, d) -} - -// CHECK-LABEL: @build_array_transmute_u -#[no_mangle] -pub fn build_array_transmute_u(x: [f32; 4]) -> U { - // CHECK: %[[VAL:.+]] = load <4 x float>, ptr %x, align [[ARRAY_ALIGN]] - // CHECK: store <4 x float> %[[VAL:.+]], ptr %_0, align [[VECTOR_ALIGN]] - unsafe { std::mem::transmute(x) } -} diff --git a/tests/codegen/simd/unpadded-simd.rs b/tests/codegen/simd/unpadded-simd.rs index 66d9298c0068c..ef067a15702c3 100644 --- a/tests/codegen/simd/unpadded-simd.rs +++ b/tests/codegen/simd/unpadded-simd.rs @@ -7,7 +7,7 @@ #[derive(Copy, Clone)] #[repr(simd)] -pub struct int16x4_t(pub i16, pub i16, pub i16, pub i16); +pub struct int16x4_t(pub [i16; 4]); #[derive(Copy, Clone)] pub struct int16x4x2_t(pub int16x4_t, pub int16x4_t); diff --git a/tests/codegen/union-abi.rs b/tests/codegen/union-abi.rs index 08015014456ce..a1c081d7d61c2 100644 --- a/tests/codegen/union-abi.rs +++ b/tests/codegen/union-abi.rs @@ -16,7 +16,7 @@ pub enum Unhab {} #[repr(simd)] #[derive(Copy, Clone)] -pub struct i64x4(i64, i64, i64, i64); +pub struct i64x4([i64; 4]); #[derive(Copy, Clone)] pub union UnionI64x4 { diff --git a/tests/codegen/zst-offset.rs b/tests/codegen/zst-offset.rs index 14e97fd26ddf7..475394a881561 100644 --- a/tests/codegen/zst-offset.rs +++ b/tests/codegen/zst-offset.rs @@ -27,7 +27,7 @@ pub fn scalarpair_layout(s: &(u64, u32, ())) { } #[repr(simd)] -pub struct U64x4(u64, u64, u64, u64); +pub struct U64x4([u64; 4]); // Check that we correctly generate a GEP for a ZST that is not included in Vector layout // CHECK-LABEL: @vector_layout diff --git a/tests/debuginfo/simd.rs b/tests/debuginfo/simd.rs index e4fe262235bae..12675a71a5708 100644 --- a/tests/debuginfo/simd.rs +++ b/tests/debuginfo/simd.rs @@ -10,27 +10,27 @@ // gdb-command:run // gdb-command:print vi8x16 -// gdb-check:$1 = simd::i8x16 (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15) +// gdb-check:$1 = simd::i8x16 ([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]) // gdb-command:print vi16x8 -// gdb-check:$2 = simd::i16x8 (16, 17, 18, 19, 20, 21, 22, 23) +// gdb-check:$2 = simd::i16x8 ([16, 17, 18, 19, 20, 21, 22, 23]) // gdb-command:print vi32x4 -// gdb-check:$3 = simd::i32x4 (24, 25, 26, 27) +// gdb-check:$3 = simd::i32x4 ([24, 25, 26, 27]) // gdb-command:print vi64x2 -// gdb-check:$4 = simd::i64x2 (28, 29) +// gdb-check:$4 = simd::i64x2 ([28, 29]) // gdb-command:print vu8x16 -// gdb-check:$5 = simd::u8x16 (30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45) +// gdb-check:$5 = simd::u8x16 ([30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45]) // gdb-command:print vu16x8 -// gdb-check:$6 = simd::u16x8 (46, 47, 48, 49, 50, 51, 52, 53) +// gdb-check:$6 = simd::u16x8 ([46, 47, 48, 49, 50, 51, 52, 53]) // gdb-command:print vu32x4 -// gdb-check:$7 = simd::u32x4 (54, 55, 56, 57) +// gdb-check:$7 = simd::u32x4 ([54, 55, 56, 57]) // gdb-command:print vu64x2 -// gdb-check:$8 = simd::u64x2 (58, 59) +// gdb-check:$8 = simd::u64x2 ([58, 59]) // gdb-command:print vf32x4 -// gdb-check:$9 = simd::f32x4 (60.5, 61.5, 62.5, 63.5) +// gdb-check:$9 = simd::f32x4 ([60.5, 61.5, 62.5, 63.5]) // gdb-command:print vf64x2 -// gdb-check:$10 = simd::f64x2 (64.5, 65.5) +// gdb-check:$10 = simd::f64x2 ([64.5, 65.5]) // gdb-command:continue @@ -40,43 +40,43 @@ #![feature(repr_simd)] #[repr(simd)] -struct i8x16(i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8); +struct i8x16([i8; 16]); #[repr(simd)] -struct i16x8(i16, i16, i16, i16, i16, i16, i16, i16); +struct i16x8([i16; 8]); #[repr(simd)] -struct i32x4(i32, i32, i32, i32); +struct i32x4([i32; 4]); #[repr(simd)] -struct i64x2(i64, i64); +struct i64x2([i64; 2]); #[repr(simd)] -struct u8x16(u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8); +struct u8x16([u8; 16]); #[repr(simd)] -struct u16x8(u16, u16, u16, u16, u16, u16, u16, u16); +struct u16x8([u16; 8]); #[repr(simd)] -struct u32x4(u32, u32, u32, u32); +struct u32x4([u32; 4]); #[repr(simd)] -struct u64x2(u64, u64); +struct u64x2([u64; 2]); #[repr(simd)] -struct f32x4(f32, f32, f32, f32); +struct f32x4([f32; 4]); #[repr(simd)] -struct f64x2(f64, f64); +struct f64x2([f64; 2]); fn main() { - let vi8x16 = i8x16(0, 1, 2, 3, 4, 5, 6, 7, - 8, 9, 10, 11, 12, 13, 14, 15); + let vi8x16 = i8x16([0, 1, 2, 3, 4, 5, 6, 7, + 8, 9, 10, 11, 12, 13, 14, 15]); - let vi16x8 = i16x8(16, 17, 18, 19, 20, 21, 22, 23); - let vi32x4 = i32x4(24, 25, 26, 27); - let vi64x2 = i64x2(28, 29); + let vi16x8 = i16x8([16, 17, 18, 19, 20, 21, 22, 23]); + let vi32x4 = i32x4([24, 25, 26, 27]); + let vi64x2 = i64x2([28, 29]); - let vu8x16 = u8x16(30, 31, 32, 33, 34, 35, 36, 37, - 38, 39, 40, 41, 42, 43, 44, 45); - let vu16x8 = u16x8(46, 47, 48, 49, 50, 51, 52, 53); - let vu32x4 = u32x4(54, 55, 56, 57); - let vu64x2 = u64x2(58, 59); + let vu8x16 = u8x16([30, 31, 32, 33, 34, 35, 36, 37, + 38, 39, 40, 41, 42, 43, 44, 45]); + let vu16x8 = u16x8([46, 47, 48, 49, 50, 51, 52, 53]); + let vu32x4 = u32x4([54, 55, 56, 57]); + let vu64x2 = u64x2([58, 59]); - let vf32x4 = f32x4(60.5f32, 61.5f32, 62.5f32, 63.5f32); - let vf64x2 = f64x2(64.5f64, 65.5f64); + let vf32x4 = f32x4([60.5f32, 61.5f32, 62.5f32, 63.5f32]); + let vf64x2 = f64x2([64.5f64, 65.5f64]); zzz(); // #break } diff --git a/tests/incremental/issue-61530.rs b/tests/incremental/issue-61530.rs index e4ee8ccbc4bd2..b4914dda11ae1 100644 --- a/tests/incremental/issue-61530.rs +++ b/tests/incremental/issue-61530.rs @@ -3,7 +3,7 @@ //@ revisions:rpass1 rpass2 #[repr(simd)] -struct I32x2(i32, i32); +struct I32x2([i32; 2]); extern "rust-intrinsic" { fn simd_shuffle(x: T, y: T, idx: I) -> U; @@ -12,7 +12,7 @@ extern "rust-intrinsic" { fn main() { unsafe { const IDX: [u32; 2] = [0, 0]; - let _: I32x2 = simd_shuffle(I32x2(1, 2), I32x2(3, 4), IDX); - let _: I32x2 = simd_shuffle(I32x2(1, 2), I32x2(3, 4), IDX); + let _: I32x2 = simd_shuffle(I32x2([1, 2]), I32x2([3, 4]), IDX); + let _: I32x2 = simd_shuffle(I32x2([1, 2]), I32x2([3, 4]), IDX); } } diff --git a/tests/run-make/simd-ffi/simd.rs b/tests/run-make/simd-ffi/simd.rs index d11cfd77c5bf9..b72078faafa26 100644 --- a/tests/run-make/simd-ffi/simd.rs +++ b/tests/run-make/simd-ffi/simd.rs @@ -8,7 +8,7 @@ #[derive(Copy)] #[repr(simd)] -pub struct f32x4(f32, f32, f32, f32); +pub struct f32x4([f32; 4]); extern "C" { #[link_name = "llvm.sqrt.v4f32"] @@ -21,7 +21,7 @@ pub fn foo(x: f32x4) -> f32x4 { #[derive(Copy)] #[repr(simd)] -pub struct i32x4(i32, i32, i32, i32); +pub struct i32x4([i32; 4]); extern "C" { // _mm_sll_epi32 @@ -62,6 +62,8 @@ pub trait Copy {} impl Copy for f32 {} impl Copy for i32 {} +impl Copy for [f32; 4] {} +impl Copy for [i32; 4] {} pub mod marker { pub use Copy; diff --git a/tests/rustdoc/inline_cross/auxiliary/repr.rs b/tests/rustdoc/inline_cross/auxiliary/repr.rs index 35f08c11b7b3a..0211e1a86588f 100644 --- a/tests/rustdoc/inline_cross/auxiliary/repr.rs +++ b/tests/rustdoc/inline_cross/auxiliary/repr.rs @@ -6,7 +6,7 @@ pub struct ReprC { } #[repr(simd, packed(2))] pub struct ReprSimd { - field: u8, + field: [u8; 1], } #[repr(transparent)] pub struct ReprTransparent { diff --git a/tests/ui/abi/arm-unadjusted-intrinsic.rs b/tests/ui/abi/arm-unadjusted-intrinsic.rs index 7a728d4b241d9..533cd40b30a5c 100644 --- a/tests/ui/abi/arm-unadjusted-intrinsic.rs +++ b/tests/ui/abi/arm-unadjusted-intrinsic.rs @@ -25,16 +25,13 @@ impl Copy for i8 {} impl Copy for *const T {} impl Copy for *mut T {} +// I hate no_core tests! +impl Copy for [T; N] {} // Regression test for https://github.com/rust-lang/rust/issues/118124. #[repr(simd)] -pub struct int8x16_t( - pub(crate) i8, pub(crate) i8, pub(crate) i8, pub(crate) i8, - pub(crate) i8, pub(crate) i8, pub(crate) i8, pub(crate) i8, - pub(crate) i8, pub(crate) i8, pub(crate) i8, pub(crate) i8, - pub(crate) i8, pub(crate) i8, pub(crate) i8, pub(crate) i8, -); +pub struct int8x16_t(pub(crate) [i8; 16]); impl Copy for int8x16_t {} #[repr(C)] diff --git a/tests/ui/abi/homogenous-floats-target-feature-mixup.rs b/tests/ui/abi/homogenous-floats-target-feature-mixup.rs index 3a8540a825ca2..4afb710b193eb 100644 --- a/tests/ui/abi/homogenous-floats-target-feature-mixup.rs +++ b/tests/ui/abi/homogenous-floats-target-feature-mixup.rs @@ -65,13 +65,13 @@ fn is_sigill(status: ExitStatus) -> bool { #[allow(nonstandard_style)] mod test { #[derive(PartialEq, Debug, Clone, Copy)] - struct f32x2(f32, f32); + struct f32x2([f32; 2]); #[derive(PartialEq, Debug, Clone, Copy)] - struct f32x4(f32, f32, f32, f32); + struct f32x4([f32; 4]); #[derive(PartialEq, Debug, Clone, Copy)] - struct f32x8(f32, f32, f32, f32, f32, f32, f32, f32); + struct f32x8([f32; 8]); pub fn main(level: &str) { unsafe { @@ -97,9 +97,9 @@ mod test { )*) => ($( $(#[$attr])* unsafe fn $main(level: &str) { - let m128 = f32x2(1., 2.); - let m256 = f32x4(3., 4., 5., 6.); - let m512 = f32x8(7., 8., 9., 10., 11., 12., 13., 14.); + let m128 = f32x2([1., 2.]); + let m256 = f32x4([3., 4., 5., 6.]); + let m512 = f32x8([7., 8., 9., 10., 11., 12., 13., 14.]); assert_eq!(id_sse_128(m128), m128); assert_eq!(id_sse_256(m256), m256); assert_eq!(id_sse_512(m512), m512); @@ -133,55 +133,55 @@ mod test { #[target_feature(enable = "sse2")] unsafe fn id_sse_128(a: f32x2) -> f32x2 { - assert_eq!(a, f32x2(1., 2.)); + assert_eq!(a, f32x2([1., 2.])); a.clone() } #[target_feature(enable = "sse2")] unsafe fn id_sse_256(a: f32x4) -> f32x4 { - assert_eq!(a, f32x4(3., 4., 5., 6.)); + assert_eq!(a, f32x4([3., 4., 5., 6.])); a.clone() } #[target_feature(enable = "sse2")] unsafe fn id_sse_512(a: f32x8) -> f32x8 { - assert_eq!(a, f32x8(7., 8., 9., 10., 11., 12., 13., 14.)); + assert_eq!(a, f32x8([7., 8., 9., 10., 11., 12., 13., 14.])); a.clone() } #[target_feature(enable = "avx")] unsafe fn id_avx_128(a: f32x2) -> f32x2 { - assert_eq!(a, f32x2(1., 2.)); + assert_eq!(a, f32x2([1., 2.])); a.clone() } #[target_feature(enable = "avx")] unsafe fn id_avx_256(a: f32x4) -> f32x4 { - assert_eq!(a, f32x4(3., 4., 5., 6.)); + assert_eq!(a, f32x4([3., 4., 5., 6.])); a.clone() } #[target_feature(enable = "avx")] unsafe fn id_avx_512(a: f32x8) -> f32x8 { - assert_eq!(a, f32x8(7., 8., 9., 10., 11., 12., 13., 14.)); + assert_eq!(a, f32x8([7., 8., 9., 10., 11., 12., 13., 14.])); a.clone() } #[target_feature(enable = "avx512bw")] unsafe fn id_avx512_128(a: f32x2) -> f32x2 { - assert_eq!(a, f32x2(1., 2.)); + assert_eq!(a, f32x2([1., 2.])); a.clone() } #[target_feature(enable = "avx512bw")] unsafe fn id_avx512_256(a: f32x4) -> f32x4 { - assert_eq!(a, f32x4(3., 4., 5., 6.)); + assert_eq!(a, f32x4([3., 4., 5., 6.])); a.clone() } #[target_feature(enable = "avx512bw")] unsafe fn id_avx512_512(a: f32x8) -> f32x8 { - assert_eq!(a, f32x8(7., 8., 9., 10., 11., 12., 13., 14.)); + assert_eq!(a, f32x8([7., 8., 9., 10., 11., 12., 13., 14.])); a.clone() } } diff --git a/tests/ui/asm/aarch64/type-check-2-2.rs b/tests/ui/asm/aarch64/type-check-2-2.rs index f442ce81476ed..4b8ee1d922986 100644 --- a/tests/ui/asm/aarch64/type-check-2-2.rs +++ b/tests/ui/asm/aarch64/type-check-2-2.rs @@ -6,10 +6,10 @@ use std::arch::{asm, global_asm}; #[repr(simd)] #[derive(Clone, Copy)] -struct SimdType(f32, f32, f32, f32); +struct SimdType([f32; 4]); #[repr(simd)] -struct SimdNonCopy(f32, f32, f32, f32); +struct SimdNonCopy([f32; 4]); fn main() { unsafe { diff --git a/tests/ui/asm/aarch64/type-check-2.rs b/tests/ui/asm/aarch64/type-check-2.rs index 46667ae3a6565..ad223b799b786 100644 --- a/tests/ui/asm/aarch64/type-check-2.rs +++ b/tests/ui/asm/aarch64/type-check-2.rs @@ -6,10 +6,10 @@ use std::arch::{asm, global_asm}; #[repr(simd)] #[derive(Clone, Copy)] -struct SimdType(f32, f32, f32, f32); +struct SimdType([f32; 4]); #[repr(simd)] -struct SimdNonCopy(f32, f32, f32, f32); +struct SimdNonCopy([f32; 4]); fn main() { unsafe { @@ -17,7 +17,7 @@ fn main() { // Register operands must be Copy - asm!("{:v}", in(vreg) SimdNonCopy(0.0, 0.0, 0.0, 0.0)); + asm!("{:v}", in(vreg) SimdNonCopy([0.0, 0.0, 0.0, 0.0])); //~^ ERROR arguments for inline assembly must be copyable // Register operands must be integers, floats, SIMD vectors, pointers or @@ -25,7 +25,7 @@ fn main() { asm!("{}", in(reg) 0i64); asm!("{}", in(reg) 0f64); - asm!("{:v}", in(vreg) SimdType(0.0, 0.0, 0.0, 0.0)); + asm!("{:v}", in(vreg) SimdType([0.0, 0.0, 0.0, 0.0])); asm!("{}", in(reg) 0 as *const u8); asm!("{}", in(reg) 0 as *mut u8); asm!("{}", in(reg) main as fn()); diff --git a/tests/ui/asm/aarch64/type-check-2.stderr b/tests/ui/asm/aarch64/type-check-2.stderr index b7723fc74d4b6..84bc5f08b4ed1 100644 --- a/tests/ui/asm/aarch64/type-check-2.stderr +++ b/tests/ui/asm/aarch64/type-check-2.stderr @@ -1,8 +1,8 @@ error: arguments for inline assembly must be copyable --> $DIR/type-check-2.rs:20:31 | -LL | asm!("{:v}", in(vreg) SimdNonCopy(0.0, 0.0, 0.0, 0.0)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | asm!("{:v}", in(vreg) SimdNonCopy([0.0, 0.0, 0.0, 0.0])); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `SimdNonCopy` does not implement the Copy trait diff --git a/tests/ui/asm/aarch64/type-check-3.rs b/tests/ui/asm/aarch64/type-check-3.rs index b64473f98c090..2f8439d0a0f9e 100644 --- a/tests/ui/asm/aarch64/type-check-3.rs +++ b/tests/ui/asm/aarch64/type-check-3.rs @@ -8,11 +8,11 @@ use std::arch::{asm, global_asm}; #[repr(simd)] #[derive(Copy, Clone)] -struct Simd256bit(f64, f64, f64, f64); +struct Simd256bit([f64; 4]); fn main() { let f64x2: float64x2_t = unsafe { std::mem::transmute(0i128) }; - let f64x4 = Simd256bit(0.0, 0.0, 0.0, 0.0); + let f64x4 = Simd256bit([0.0, 0.0, 0.0, 0.0]); unsafe { // Types must be listed in the register class. diff --git a/tests/ui/asm/aarch64/type-check-4.rs b/tests/ui/asm/aarch64/type-check-4.rs index 41eb9de5669f6..1169c3dcfa843 100644 --- a/tests/ui/asm/aarch64/type-check-4.rs +++ b/tests/ui/asm/aarch64/type-check-4.rs @@ -8,7 +8,7 @@ use std::arch::{asm, global_asm}; #[repr(simd)] #[derive(Copy, Clone)] -struct Simd256bit(f64, f64, f64, f64); +struct Simd256bit([f64; 4]); fn main() {} diff --git a/tests/ui/asm/x86_64/type-check-2.rs b/tests/ui/asm/x86_64/type-check-2.rs index ff811961462df..1650c595faebb 100644 --- a/tests/ui/asm/x86_64/type-check-2.rs +++ b/tests/ui/asm/x86_64/type-check-2.rs @@ -5,7 +5,7 @@ use std::arch::{asm, global_asm}; #[repr(simd)] -struct SimdNonCopy(f32, f32, f32, f32); +struct SimdNonCopy([f32; 4]); fn main() { unsafe { @@ -29,7 +29,7 @@ fn main() { // Register operands must be Copy - asm!("{}", in(xmm_reg) SimdNonCopy(0.0, 0.0, 0.0, 0.0)); + asm!("{}", in(xmm_reg) SimdNonCopy([0.0, 0.0, 0.0, 0.0])); //~^ ERROR arguments for inline assembly must be copyable // Register operands must be integers, floats, SIMD vectors, pointers or diff --git a/tests/ui/asm/x86_64/type-check-2.stderr b/tests/ui/asm/x86_64/type-check-2.stderr index c72e695aefb83..8b1bfa85fa2c4 100644 --- a/tests/ui/asm/x86_64/type-check-2.stderr +++ b/tests/ui/asm/x86_64/type-check-2.stderr @@ -1,8 +1,8 @@ error: arguments for inline assembly must be copyable --> $DIR/type-check-2.rs:32:32 | -LL | asm!("{}", in(xmm_reg) SimdNonCopy(0.0, 0.0, 0.0, 0.0)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | asm!("{}", in(xmm_reg) SimdNonCopy([0.0, 0.0, 0.0, 0.0])); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `SimdNonCopy` does not implement the Copy trait diff --git a/tests/ui/asm/x86_64/type-check-5.rs b/tests/ui/asm/x86_64/type-check-5.rs index b5b51f6116890..81e096a72300a 100644 --- a/tests/ui/asm/x86_64/type-check-5.rs +++ b/tests/ui/asm/x86_64/type-check-5.rs @@ -1,12 +1,9 @@ //@ only-x86_64 -#![feature(repr_simd, never_type)] +#![feature(never_type)] use std::arch::asm; -#[repr(simd)] -struct SimdNonCopy(f32, f32, f32, f32); - fn main() { unsafe { // Inputs must be initialized diff --git a/tests/ui/asm/x86_64/type-check-5.stderr b/tests/ui/asm/x86_64/type-check-5.stderr index 4fb759934636d..377e1d19f6c5c 100644 --- a/tests/ui/asm/x86_64/type-check-5.stderr +++ b/tests/ui/asm/x86_64/type-check-5.stderr @@ -1,5 +1,5 @@ error[E0381]: used binding `x` isn't initialized - --> $DIR/type-check-5.rs:15:28 + --> $DIR/type-check-5.rs:12:28 | LL | let x: u64; | - binding declared here but left uninitialized @@ -12,7 +12,7 @@ LL | let x: u64 = 42; | ++++ error[E0381]: used binding `y` isn't initialized - --> $DIR/type-check-5.rs:18:9 + --> $DIR/type-check-5.rs:15:9 | LL | let mut y: u64; | ----- binding declared here but left uninitialized @@ -25,7 +25,7 @@ LL | let mut y: u64 = 42; | ++++ error[E0596]: cannot borrow `v` as mutable, as it is not declared as mutable - --> $DIR/type-check-5.rs:24:13 + --> $DIR/type-check-5.rs:21:13 | LL | let v: Vec = vec![0, 1, 2]; | ^ not mutable diff --git a/tests/ui/consts/const-eval/simd/insert_extract.rs b/tests/ui/consts/const-eval/simd/insert_extract.rs index fc7dbd5a41c34..f4f25327aaf11 100644 --- a/tests/ui/consts/const-eval/simd/insert_extract.rs +++ b/tests/ui/consts/const-eval/simd/insert_extract.rs @@ -5,10 +5,9 @@ #![stable(feature = "foo", since = "1.3.37")] #![allow(non_camel_case_types)] -#[repr(simd)] struct i8x1(i8); -#[repr(simd)] struct u16x2(u16, u16); -// Make some of them array types to ensure those also work. -#[repr(simd)] struct i8x1_arr([i8; 1]); +// repr(simd) now only supports array types +#[repr(simd)] struct i8x1([i8; 1]); +#[repr(simd)] struct u16x2([u16; 2]); #[repr(simd)] struct f32x4([f32; 4]); extern "rust-intrinsic" { @@ -20,26 +19,18 @@ extern "rust-intrinsic" { fn main() { { - const U: i8x1 = i8x1(13); + const U: i8x1 = i8x1([13]); const V: i8x1 = unsafe { simd_insert(U, 0_u32, 42_i8) }; - const X0: i8 = V.0; - const Y0: i8 = unsafe { simd_extract(V, 0) }; - assert_eq!(X0, 42); - assert_eq!(Y0, 42); - } - { - const U: i8x1_arr = i8x1_arr([13]); - const V: i8x1_arr = unsafe { simd_insert(U, 0_u32, 42_i8) }; const X0: i8 = V.0[0]; const Y0: i8 = unsafe { simd_extract(V, 0) }; assert_eq!(X0, 42); assert_eq!(Y0, 42); } { - const U: u16x2 = u16x2(13, 14); + const U: u16x2 = u16x2([13, 14]); const V: u16x2 = unsafe { simd_insert(U, 1_u32, 42_u16) }; - const X0: u16 = V.0; - const X1: u16 = V.1; + const X0: u16 = V.0[0]; + const X1: u16 = V.0[1]; const Y0: u16 = unsafe { simd_extract(V, 0) }; const Y1: u16 = unsafe { simd_extract(V, 1) }; assert_eq!(X0, 13); diff --git a/tests/ui/error-codes/E0075.rs b/tests/ui/error-codes/E0075.rs index 7feab0a8bd7a2..2c610d9186b64 100644 --- a/tests/ui/error-codes/E0075.rs +++ b/tests/ui/error-codes/E0075.rs @@ -3,5 +3,8 @@ #[repr(simd)] struct Bad; //~ ERROR E0075 +#[repr(simd)] +struct AlsoBad([i32; 1], [i32; 1]); //~ ERROR E0075 + fn main() { } diff --git a/tests/ui/error-codes/E0075.stderr b/tests/ui/error-codes/E0075.stderr index 43e9971e3095d..0a44a2eadebd1 100644 --- a/tests/ui/error-codes/E0075.stderr +++ b/tests/ui/error-codes/E0075.stderr @@ -4,6 +4,12 @@ error[E0075]: SIMD vector cannot be empty LL | struct Bad; | ^^^^^^^^^^ -error: aborting due to 1 previous error +error[E0075]: SIMD vector cannot have multiple fields + --> $DIR/E0075.rs:7:1 + | +LL | struct AlsoBad([i32; 1], [i32; 1]); + | ^^^^^^^^^^^^^^ -------- excess field + +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0075`. diff --git a/tests/ui/error-codes/E0076.rs b/tests/ui/error-codes/E0076.rs index a27072eb71e68..2c0376fe7e0bd 100644 --- a/tests/ui/error-codes/E0076.rs +++ b/tests/ui/error-codes/E0076.rs @@ -1,7 +1,7 @@ #![feature(repr_simd)] #[repr(simd)] -struct Bad(u16, u32, u32); +struct Bad(u32); //~^ ERROR E0076 fn main() { diff --git a/tests/ui/error-codes/E0076.stderr b/tests/ui/error-codes/E0076.stderr index ea3bbf094976f..8bf46cf38e338 100644 --- a/tests/ui/error-codes/E0076.stderr +++ b/tests/ui/error-codes/E0076.stderr @@ -1,8 +1,8 @@ -error[E0076]: SIMD vector should be homogeneous +error[E0076]: SIMD vector's only field must be an array --> $DIR/E0076.rs:4:1 | -LL | struct Bad(u16, u32, u32); - | ^^^^^^^^^^ SIMD elements must have the same type +LL | struct Bad(u32); + | ^^^^^^^^^^ --- not an array error: aborting due to 1 previous error diff --git a/tests/ui/error-codes/E0077.rs b/tests/ui/error-codes/E0077.rs index fa2d5e24fa3ca..2704bbeb4ea17 100644 --- a/tests/ui/error-codes/E0077.rs +++ b/tests/ui/error-codes/E0077.rs @@ -1,7 +1,7 @@ #![feature(repr_simd)] #[repr(simd)] -struct Bad(String); //~ ERROR E0077 +struct Bad([String; 2]); //~ ERROR E0077 fn main() { } diff --git a/tests/ui/error-codes/E0077.stderr b/tests/ui/error-codes/E0077.stderr index aae4b3f2c2927..063b40a147c57 100644 --- a/tests/ui/error-codes/E0077.stderr +++ b/tests/ui/error-codes/E0077.stderr @@ -1,7 +1,7 @@ error[E0077]: SIMD vector element type should be a primitive scalar (integer/float/pointer) type --> $DIR/E0077.rs:4:1 | -LL | struct Bad(String); +LL | struct Bad([String; 2]); | ^^^^^^^^^^ error: aborting due to 1 previous error diff --git a/tests/ui/feature-gates/feature-gate-repr-simd.rs b/tests/ui/feature-gates/feature-gate-repr-simd.rs index c527404f57270..65ade97c7e1c3 100644 --- a/tests/ui/feature-gates/feature-gate-repr-simd.rs +++ b/tests/ui/feature-gates/feature-gate-repr-simd.rs @@ -1,9 +1,9 @@ #[repr(simd)] //~ error: SIMD types are experimental -struct Foo(u64, u64); +struct Foo([u64; 2]); #[repr(C)] //~ ERROR conflicting representation hints //~^ WARN this was previously accepted #[repr(simd)] //~ error: SIMD types are experimental -struct Bar(u64, u64); +struct Bar([u64; 2]); fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-simd-ffi.rs b/tests/ui/feature-gates/feature-gate-simd-ffi.rs index abffa4a10010d..2ee935e07ffa4 100644 --- a/tests/ui/feature-gates/feature-gate-simd-ffi.rs +++ b/tests/ui/feature-gates/feature-gate-simd-ffi.rs @@ -3,7 +3,7 @@ #[repr(simd)] #[derive(Copy, Clone)] -struct LocalSimd(u8, u8); +struct LocalSimd([u8; 2]); extern "C" { fn baz() -> LocalSimd; //~ ERROR use of SIMD type diff --git a/tests/ui/feature-gates/feature-gate-simd.rs b/tests/ui/feature-gates/feature-gate-simd.rs index de5f645e6fd0b..e7aef5a97f2ee 100644 --- a/tests/ui/feature-gates/feature-gate-simd.rs +++ b/tests/ui/feature-gates/feature-gate-simd.rs @@ -2,10 +2,7 @@ #[repr(simd)] //~ ERROR SIMD types are experimental struct RGBA { - r: f32, - g: f32, - b: f32, - a: f32 + rgba: [f32; 4], } pub fn main() {} diff --git a/tests/ui/layout/debug.rs b/tests/ui/layout/debug.rs index aeacbc784462d..91e96d78ff556 100644 --- a/tests/ui/layout/debug.rs +++ b/tests/ui/layout/debug.rs @@ -49,7 +49,7 @@ union P2 { x: (u32, u32) } //~ ERROR: layout_of #[repr(simd)] #[derive(Copy, Clone)] -struct F32x4(f32, f32, f32, f32); +struct F32x4([f32; 4]); #[rustc_layout(debug)] #[repr(packed(1))] diff --git a/tests/ui/repr/attr-usage-repr.rs b/tests/ui/repr/attr-usage-repr.rs index 8965decc37989..dc0d4f5be2e30 100644 --- a/tests/ui/repr/attr-usage-repr.rs +++ b/tests/ui/repr/attr-usage-repr.rs @@ -10,7 +10,7 @@ struct SExtern(f64, f64); struct SPacked(f64, f64); #[repr(simd)] -struct SSimd(f64, f64); +struct SSimd([f64; 2]); #[repr(i8)] //~ ERROR: attribute should be applied to an enum struct SInt(f64, f64); diff --git a/tests/ui/repr/explicit-rust-repr-conflicts.rs b/tests/ui/repr/explicit-rust-repr-conflicts.rs index 22dd12d316ac5..5278f5e6ae0cc 100644 --- a/tests/ui/repr/explicit-rust-repr-conflicts.rs +++ b/tests/ui/repr/explicit-rust-repr-conflicts.rs @@ -18,6 +18,6 @@ enum U { #[repr(Rust, simd)] //~^ ERROR conflicting representation hints //~| ERROR SIMD types are experimental and possibly buggy -struct F32x4(f32, f32, f32, f32); +struct F32x4([f32; 4]); fn main() {} diff --git a/tests/ui/simd/const-err-trumps-simd-err.rs b/tests/ui/simd/const-err-trumps-simd-err.rs index fda044344517d..fb87fe1cbca83 100644 --- a/tests/ui/simd/const-err-trumps-simd-err.rs +++ b/tests/ui/simd/const-err-trumps-simd-err.rs @@ -10,7 +10,7 @@ use std::intrinsics::simd::*; #[repr(simd)] #[allow(non_camel_case_types)] -struct int8x4_t(u8,u8,u8,u8); +struct int8x4_t([u8; 4]); fn get_elem(a: int8x4_t) -> u8 { const { assert!(LANE < 4); } // the error should be here... @@ -20,5 +20,5 @@ fn get_elem(a: int8x4_t) -> u8 { } fn main() { - get_elem::<4>(int8x4_t(0,0,0,0)); + get_elem::<4>(int8x4_t([0, 0, 0, 0])); } diff --git a/tests/ui/simd/const-err-trumps-simd-err.stderr b/tests/ui/simd/const-err-trumps-simd-err.stderr index 1e46667cf4e2a..11cbcad227ff8 100644 --- a/tests/ui/simd/const-err-trumps-simd-err.stderr +++ b/tests/ui/simd/const-err-trumps-simd-err.stderr @@ -15,8 +15,8 @@ LL | const { assert!(LANE < 4); } // the error should be here... note: the above error was encountered while instantiating `fn get_elem::<4>` --> $DIR/const-err-trumps-simd-err.rs:23:5 | -LL | get_elem::<4>(int8x4_t(0,0,0,0)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | get_elem::<4>(int8x4_t([0, 0, 0, 0])); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 1 previous error diff --git a/tests/ui/simd/generics.rs b/tests/ui/simd/generics.rs index bd048b19ca886..f96a7cd75e933 100644 --- a/tests/ui/simd/generics.rs +++ b/tests/ui/simd/generics.rs @@ -6,7 +6,7 @@ use std::ops; #[repr(simd)] #[derive(Copy, Clone)] -struct f32x4(f32, f32, f32, f32); +struct f32x4([f32; 4]); #[repr(simd)] #[derive(Copy, Clone)] @@ -67,8 +67,8 @@ pub fn main() { let y = [2.0f32, 4.0f32, 6.0f32, 8.0f32]; // lame-o - let a = f32x4(1.0f32, 2.0f32, 3.0f32, 4.0f32); - let f32x4(a0, a1, a2, a3) = add(a, a); + let a = f32x4([1.0f32, 2.0f32, 3.0f32, 4.0f32]); + let f32x4([a0, a1, a2, a3]) = add(a, a); assert_eq!(a0, 2.0f32); assert_eq!(a1, 4.0f32); assert_eq!(a2, 6.0f32); diff --git a/tests/ui/simd/intrinsic/float-math-pass.rs b/tests/ui/simd/intrinsic/float-math-pass.rs index ea31e2a7c570e..9b14d410acbe3 100644 --- a/tests/ui/simd/intrinsic/float-math-pass.rs +++ b/tests/ui/simd/intrinsic/float-math-pass.rs @@ -13,7 +13,7 @@ #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -struct f32x4(pub f32, pub f32, pub f32, pub f32); +struct f32x4(pub [f32; 4]); extern "rust-intrinsic" { fn simd_fsqrt(x: T) -> T; @@ -47,19 +47,19 @@ macro_rules! assert_approx_eq { ($a:expr, $b:expr) => ({ let a = $a; let b = $b; - assert_approx_eq_f32!(a.0, b.0); - assert_approx_eq_f32!(a.1, b.1); - assert_approx_eq_f32!(a.2, b.2); - assert_approx_eq_f32!(a.3, b.3); + assert_approx_eq_f32!(a.0[0], b.0[0]); + assert_approx_eq_f32!(a.0[1], b.0[1]); + assert_approx_eq_f32!(a.0[2], b.0[2]); + assert_approx_eq_f32!(a.0[3], b.0[3]); }) } fn main() { - let x = f32x4(1.0, 1.0, 1.0, 1.0); - let y = f32x4(-1.0, -1.0, -1.0, -1.0); - let z = f32x4(0.0, 0.0, 0.0, 0.0); + let x = f32x4([1.0, 1.0, 1.0, 1.0]); + let y = f32x4([-1.0, -1.0, -1.0, -1.0]); + let z = f32x4([0.0, 0.0, 0.0, 0.0]); - let h = f32x4(0.5, 0.5, 0.5, 0.5); + let h = f32x4([0.5, 0.5, 0.5, 0.5]); unsafe { let r = simd_fabs(y); diff --git a/tests/ui/simd/intrinsic/float-minmax-pass.rs b/tests/ui/simd/intrinsic/float-minmax-pass.rs index d6cbcd4e05a63..00c0d8cea3fa5 100644 --- a/tests/ui/simd/intrinsic/float-minmax-pass.rs +++ b/tests/ui/simd/intrinsic/float-minmax-pass.rs @@ -8,13 +8,13 @@ #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -struct f32x4(pub f32, pub f32, pub f32, pub f32); +struct f32x4(pub [f32; 4]); use std::intrinsics::simd::*; fn main() { - let x = f32x4(1.0, 2.0, 3.0, 4.0); - let y = f32x4(2.0, 1.0, 4.0, 3.0); + let x = f32x4([1.0, 2.0, 3.0, 4.0]); + let y = f32x4([2.0, 1.0, 4.0, 3.0]); #[cfg(not(any(target_arch = "mips", target_arch = "mips64")))] let nan = f32::NAN; @@ -23,13 +23,13 @@ fn main() { #[cfg(any(target_arch = "mips", target_arch = "mips64"))] let nan = f32::from_bits(f32::NAN.to_bits() - 1); - let n = f32x4(nan, nan, nan, nan); + let n = f32x4([nan, nan, nan, nan]); unsafe { let min0 = simd_fmin(x, y); let min1 = simd_fmin(y, x); assert_eq!(min0, min1); - let e = f32x4(1.0, 1.0, 3.0, 3.0); + let e = f32x4([1.0, 1.0, 3.0, 3.0]); assert_eq!(min0, e); let minn = simd_fmin(x, n); assert_eq!(minn, x); @@ -39,7 +39,7 @@ fn main() { let max0 = simd_fmax(x, y); let max1 = simd_fmax(y, x); assert_eq!(max0, max1); - let e = f32x4(2.0, 2.0, 4.0, 4.0); + let e = f32x4([2.0, 2.0, 4.0, 4.0]); assert_eq!(max0, e); let maxn = simd_fmax(x, n); assert_eq!(maxn, x); diff --git a/tests/ui/simd/intrinsic/generic-arithmetic-2.rs b/tests/ui/simd/intrinsic/generic-arithmetic-2.rs index fc3087cbf7542..663bcdf198193 100644 --- a/tests/ui/simd/intrinsic/generic-arithmetic-2.rs +++ b/tests/ui/simd/intrinsic/generic-arithmetic-2.rs @@ -4,15 +4,15 @@ #![allow(non_camel_case_types)] #[repr(simd)] #[derive(Copy, Clone)] -pub struct i32x4(pub i32, pub i32, pub i32, pub i32); +pub struct i32x4(pub [i32; 4]); #[repr(simd)] #[derive(Copy, Clone)] -pub struct u32x4(pub u32, pub u32, pub u32, pub u32); +pub struct u32x4(pub [u32; 4]); #[repr(simd)] #[derive(Copy, Clone)] -pub struct f32x4(pub f32, pub f32, pub f32, pub f32); +pub struct f32x4(pub [f32; 4]); extern "rust-intrinsic" { fn simd_add(x: T, y: T) -> T; @@ -35,9 +35,9 @@ extern "rust-intrinsic" { } fn main() { - let x = i32x4(0, 0, 0, 0); - let y = u32x4(0, 0, 0, 0); - let z = f32x4(0.0, 0.0, 0.0, 0.0); + let x = i32x4([0, 0, 0, 0]); + let y = u32x4([0, 0, 0, 0]); + let z = f32x4([0.0, 0.0, 0.0, 0.0]); unsafe { simd_add(x, x); diff --git a/tests/ui/simd/intrinsic/generic-arithmetic-pass.rs b/tests/ui/simd/intrinsic/generic-arithmetic-pass.rs index 60dfa62741488..e4eb2a9da2718 100644 --- a/tests/ui/simd/intrinsic/generic-arithmetic-pass.rs +++ b/tests/ui/simd/intrinsic/generic-arithmetic-pass.rs @@ -5,7 +5,7 @@ #[repr(simd)] #[derive(Copy, Clone)] -struct i32x4(pub i32, pub i32, pub i32, pub i32); +struct i32x4(pub [i32; 4]); #[repr(simd)] #[derive(Copy, Clone)] @@ -13,17 +13,9 @@ struct U32([u32; N]); #[repr(simd)] #[derive(Copy, Clone)] -struct f32x4(pub f32, pub f32, pub f32, pub f32); +struct f32x4(pub [f32; 4]); macro_rules! all_eq { - ($a: expr, $b: expr) => {{ - let a = $a; - let b = $b; - assert!(a.0 == b.0 && a.1 == b.1 && a.2 == b.2 && a.3 == b.3); - }}; -} - -macro_rules! all_eq_ { ($a: expr, $b: expr) => {{ let a = $a; let b = $b; @@ -52,112 +44,112 @@ extern "rust-intrinsic" { } fn main() { - let x1 = i32x4(1, 2, 3, 4); + let x1 = i32x4([1, 2, 3, 4]); let y1 = U32::<4>([1, 2, 3, 4]); - let z1 = f32x4(1.0, 2.0, 3.0, 4.0); - let x2 = i32x4(2, 3, 4, 5); + let z1 = f32x4([1.0, 2.0, 3.0, 4.0]); + let x2 = i32x4([2, 3, 4, 5]); let y2 = U32::<4>([2, 3, 4, 5]); - let z2 = f32x4(2.0, 3.0, 4.0, 5.0); - let x3 = i32x4(0, i32::MAX, i32::MIN, -1_i32); + let z2 = f32x4([2.0, 3.0, 4.0, 5.0]); + let x3 = i32x4([0, i32::MAX, i32::MIN, -1_i32]); let y3 = U32::<4>([0, i32::MAX as _, i32::MIN as _, -1_i32 as _]); unsafe { - all_eq!(simd_add(x1, x2), i32x4(3, 5, 7, 9)); - all_eq!(simd_add(x2, x1), i32x4(3, 5, 7, 9)); - all_eq_!(simd_add(y1, y2), U32::<4>([3, 5, 7, 9])); - all_eq_!(simd_add(y2, y1), U32::<4>([3, 5, 7, 9])); - all_eq!(simd_add(z1, z2), f32x4(3.0, 5.0, 7.0, 9.0)); - all_eq!(simd_add(z2, z1), f32x4(3.0, 5.0, 7.0, 9.0)); - - all_eq!(simd_mul(x1, x2), i32x4(2, 6, 12, 20)); - all_eq!(simd_mul(x2, x1), i32x4(2, 6, 12, 20)); - all_eq_!(simd_mul(y1, y2), U32::<4>([2, 6, 12, 20])); - all_eq_!(simd_mul(y2, y1), U32::<4>([2, 6, 12, 20])); - all_eq!(simd_mul(z1, z2), f32x4(2.0, 6.0, 12.0, 20.0)); - all_eq!(simd_mul(z2, z1), f32x4(2.0, 6.0, 12.0, 20.0)); - - all_eq!(simd_sub(x2, x1), i32x4(1, 1, 1, 1)); - all_eq!(simd_sub(x1, x2), i32x4(-1, -1, -1, -1)); - all_eq_!(simd_sub(y2, y1), U32::<4>([1, 1, 1, 1])); - all_eq_!(simd_sub(y1, y2), U32::<4>([!0, !0, !0, !0])); - all_eq!(simd_sub(z2, z1), f32x4(1.0, 1.0, 1.0, 1.0)); - all_eq!(simd_sub(z1, z2), f32x4(-1.0, -1.0, -1.0, -1.0)); - - all_eq!(simd_div(x1, x1), i32x4(1, 1, 1, 1)); - all_eq!(simd_div(i32x4(2, 4, 6, 8), i32x4(2, 2, 2, 2)), x1); - all_eq_!(simd_div(y1, y1), U32::<4>([1, 1, 1, 1])); - all_eq_!(simd_div(U32::<4>([2, 4, 6, 8]), U32::<4>([2, 2, 2, 2])), y1); - all_eq!(simd_div(z1, z1), f32x4(1.0, 1.0, 1.0, 1.0)); - all_eq!(simd_div(z1, z2), f32x4(1.0 / 2.0, 2.0 / 3.0, 3.0 / 4.0, 4.0 / 5.0)); - all_eq!(simd_div(z2, z1), f32x4(2.0 / 1.0, 3.0 / 2.0, 4.0 / 3.0, 5.0 / 4.0)); - - all_eq!(simd_rem(x1, x1), i32x4(0, 0, 0, 0)); - all_eq!(simd_rem(x2, x1), i32x4(0, 1, 1, 1)); - all_eq_!(simd_rem(y1, y1), U32::<4>([0, 0, 0, 0])); - all_eq_!(simd_rem(y2, y1), U32::<4>([0, 1, 1, 1])); - all_eq!(simd_rem(z1, z1), f32x4(0.0, 0.0, 0.0, 0.0)); + all_eq!(simd_add(x1, x2), i32x4([3, 5, 7, 9])); + all_eq!(simd_add(x2, x1), i32x4([3, 5, 7, 9])); + all_eq!(simd_add(y1, y2), U32::<4>([3, 5, 7, 9])); + all_eq!(simd_add(y2, y1), U32::<4>([3, 5, 7, 9])); + all_eq!(simd_add(z1, z2), f32x4([3.0, 5.0, 7.0, 9.0])); + all_eq!(simd_add(z2, z1), f32x4([3.0, 5.0, 7.0, 9.0])); + + all_eq!(simd_mul(x1, x2), i32x4([2, 6, 12, 20])); + all_eq!(simd_mul(x2, x1), i32x4([2, 6, 12, 20])); + all_eq!(simd_mul(y1, y2), U32::<4>([2, 6, 12, 20])); + all_eq!(simd_mul(y2, y1), U32::<4>([2, 6, 12, 20])); + all_eq!(simd_mul(z1, z2), f32x4([2.0, 6.0, 12.0, 20.0])); + all_eq!(simd_mul(z2, z1), f32x4([2.0, 6.0, 12.0, 20.0])); + + all_eq!(simd_sub(x2, x1), i32x4([1, 1, 1, 1])); + all_eq!(simd_sub(x1, x2), i32x4([-1, -1, -1, -1])); + all_eq!(simd_sub(y2, y1), U32::<4>([1, 1, 1, 1])); + all_eq!(simd_sub(y1, y2), U32::<4>([!0, !0, !0, !0])); + all_eq!(simd_sub(z2, z1), f32x4([1.0, 1.0, 1.0, 1.0])); + all_eq!(simd_sub(z1, z2), f32x4([-1.0, -1.0, -1.0, -1.0])); + + all_eq!(simd_div(x1, x1), i32x4([1, 1, 1, 1])); + all_eq!(simd_div(i32x4([2, 4, 6, 8]), i32x4([2, 2, 2, 2])), x1); + all_eq!(simd_div(y1, y1), U32::<4>([1, 1, 1, 1])); + all_eq!(simd_div(U32::<4>([2, 4, 6, 8]), U32::<4>([2, 2, 2, 2])), y1); + all_eq!(simd_div(z1, z1), f32x4([1.0, 1.0, 1.0, 1.0])); + all_eq!(simd_div(z1, z2), f32x4([1.0 / 2.0, 2.0 / 3.0, 3.0 / 4.0, 4.0 / 5.0])); + all_eq!(simd_div(z2, z1), f32x4([2.0 / 1.0, 3.0 / 2.0, 4.0 / 3.0, 5.0 / 4.0])); + + all_eq!(simd_rem(x1, x1), i32x4([0, 0, 0, 0])); + all_eq!(simd_rem(x2, x1), i32x4([0, 1, 1, 1])); + all_eq!(simd_rem(y1, y1), U32::<4>([0, 0, 0, 0])); + all_eq!(simd_rem(y2, y1), U32::<4>([0, 1, 1, 1])); + all_eq!(simd_rem(z1, z1), f32x4([0.0, 0.0, 0.0, 0.0])); all_eq!(simd_rem(z1, z2), z1); - all_eq!(simd_rem(z2, z1), f32x4(0.0, 1.0, 1.0, 1.0)); + all_eq!(simd_rem(z2, z1), f32x4([0.0, 1.0, 1.0, 1.0])); - all_eq!(simd_shl(x1, x2), i32x4(1 << 2, 2 << 3, 3 << 4, 4 << 5)); - all_eq!(simd_shl(x2, x1), i32x4(2 << 1, 3 << 2, 4 << 3, 5 << 4)); - all_eq_!(simd_shl(y1, y2), U32::<4>([1 << 2, 2 << 3, 3 << 4, 4 << 5])); - all_eq_!(simd_shl(y2, y1), U32::<4>([2 << 1, 3 << 2, 4 << 3, 5 << 4])); + all_eq!(simd_shl(x1, x2), i32x4([1 << 2, 2 << 3, 3 << 4, 4 << 5])); + all_eq!(simd_shl(x2, x1), i32x4([2 << 1, 3 << 2, 4 << 3, 5 << 4])); + all_eq!(simd_shl(y1, y2), U32::<4>([1 << 2, 2 << 3, 3 << 4, 4 << 5])); + all_eq!(simd_shl(y2, y1), U32::<4>([2 << 1, 3 << 2, 4 << 3, 5 << 4])); // test right-shift by assuming left-shift is correct all_eq!(simd_shr(simd_shl(x1, x2), x2), x1); all_eq!(simd_shr(simd_shl(x2, x1), x1), x2); - all_eq_!(simd_shr(simd_shl(y1, y2), y2), y1); - all_eq_!(simd_shr(simd_shl(y2, y1), y1), y2); + all_eq!(simd_shr(simd_shl(y1, y2), y2), y1); + all_eq!(simd_shr(simd_shl(y2, y1), y1), y2); // ensure we get logical vs. arithmetic shifts correct let (a, b, c, d) = (-12, -123, -1234, -12345); - all_eq!(simd_shr(i32x4(a, b, c, d), x1), i32x4(a >> 1, b >> 2, c >> 3, d >> 4)); - all_eq_!( + all_eq!(simd_shr(i32x4([a, b, c, d]), x1), i32x4([a >> 1, b >> 2, c >> 3, d >> 4])); + all_eq!( simd_shr(U32::<4>([a as u32, b as u32, c as u32, d as u32]), y1), U32::<4>([(a as u32) >> 1, (b as u32) >> 2, (c as u32) >> 3, (d as u32) >> 4]) ); - all_eq!(simd_and(x1, x2), i32x4(0, 2, 0, 4)); - all_eq!(simd_and(x2, x1), i32x4(0, 2, 0, 4)); - all_eq_!(simd_and(y1, y2), U32::<4>([0, 2, 0, 4])); - all_eq_!(simd_and(y2, y1), U32::<4>([0, 2, 0, 4])); + all_eq!(simd_and(x1, x2), i32x4([0, 2, 0, 4])); + all_eq!(simd_and(x2, x1), i32x4([0, 2, 0, 4])); + all_eq!(simd_and(y1, y2), U32::<4>([0, 2, 0, 4])); + all_eq!(simd_and(y2, y1), U32::<4>([0, 2, 0, 4])); - all_eq!(simd_or(x1, x2), i32x4(3, 3, 7, 5)); - all_eq!(simd_or(x2, x1), i32x4(3, 3, 7, 5)); - all_eq_!(simd_or(y1, y2), U32::<4>([3, 3, 7, 5])); - all_eq_!(simd_or(y2, y1), U32::<4>([3, 3, 7, 5])); + all_eq!(simd_or(x1, x2), i32x4([3, 3, 7, 5])); + all_eq!(simd_or(x2, x1), i32x4([3, 3, 7, 5])); + all_eq!(simd_or(y1, y2), U32::<4>([3, 3, 7, 5])); + all_eq!(simd_or(y2, y1), U32::<4>([3, 3, 7, 5])); - all_eq!(simd_xor(x1, x2), i32x4(3, 1, 7, 1)); - all_eq!(simd_xor(x2, x1), i32x4(3, 1, 7, 1)); - all_eq_!(simd_xor(y1, y2), U32::<4>([3, 1, 7, 1])); - all_eq_!(simd_xor(y2, y1), U32::<4>([3, 1, 7, 1])); + all_eq!(simd_xor(x1, x2), i32x4([3, 1, 7, 1])); + all_eq!(simd_xor(x2, x1), i32x4([3, 1, 7, 1])); + all_eq!(simd_xor(y1, y2), U32::<4>([3, 1, 7, 1])); + all_eq!(simd_xor(y2, y1), U32::<4>([3, 1, 7, 1])); - all_eq!(simd_neg(x1), i32x4(-1, -2, -3, -4)); - all_eq!(simd_neg(x2), i32x4(-2, -3, -4, -5)); - all_eq!(simd_neg(z1), f32x4(-1.0, -2.0, -3.0, -4.0)); - all_eq!(simd_neg(z2), f32x4(-2.0, -3.0, -4.0, -5.0)); + all_eq!(simd_neg(x1), i32x4([-1, -2, -3, -4])); + all_eq!(simd_neg(x2), i32x4([-2, -3, -4, -5])); + all_eq!(simd_neg(z1), f32x4([-1.0, -2.0, -3.0, -4.0])); + all_eq!(simd_neg(z2), f32x4([-2.0, -3.0, -4.0, -5.0])); - all_eq!(simd_bswap(x1), i32x4(0x01000000, 0x02000000, 0x03000000, 0x04000000)); - all_eq_!(simd_bswap(y1), U32::<4>([0x01000000, 0x02000000, 0x03000000, 0x04000000])); + all_eq!(simd_bswap(x1), i32x4([0x01000000, 0x02000000, 0x03000000, 0x04000000])); + all_eq!(simd_bswap(y1), U32::<4>([0x01000000, 0x02000000, 0x03000000, 0x04000000])); all_eq!( simd_bitreverse(x1), - i32x4(0x80000000u32 as i32, 0x40000000, 0xc0000000u32 as i32, 0x20000000) + i32x4([0x80000000u32 as i32, 0x40000000, 0xc0000000u32 as i32, 0x20000000]) ); - all_eq_!(simd_bitreverse(y1), U32::<4>([0x80000000, 0x40000000, 0xc0000000, 0x20000000])); + all_eq!(simd_bitreverse(y1), U32::<4>([0x80000000, 0x40000000, 0xc0000000, 0x20000000])); - all_eq!(simd_ctlz(x1), i32x4(31, 30, 30, 29)); - all_eq_!(simd_ctlz(y1), U32::<4>([31, 30, 30, 29])); + all_eq!(simd_ctlz(x1), i32x4([31, 30, 30, 29])); + all_eq!(simd_ctlz(y1), U32::<4>([31, 30, 30, 29])); - all_eq!(simd_ctpop(x1), i32x4(1, 1, 2, 1)); - all_eq_!(simd_ctpop(y1), U32::<4>([1, 1, 2, 1])); - all_eq!(simd_ctpop(x2), i32x4(1, 2, 1, 2)); - all_eq_!(simd_ctpop(y2), U32::<4>([1, 2, 1, 2])); - all_eq!(simd_ctpop(x3), i32x4(0, 31, 1, 32)); - all_eq_!(simd_ctpop(y3), U32::<4>([0, 31, 1, 32])); + all_eq!(simd_ctpop(x1), i32x4([1, 1, 2, 1])); + all_eq!(simd_ctpop(y1), U32::<4>([1, 1, 2, 1])); + all_eq!(simd_ctpop(x2), i32x4([1, 2, 1, 2])); + all_eq!(simd_ctpop(y2), U32::<4>([1, 2, 1, 2])); + all_eq!(simd_ctpop(x3), i32x4([0, 31, 1, 32])); + all_eq!(simd_ctpop(y3), U32::<4>([0, 31, 1, 32])); - all_eq!(simd_cttz(x1), i32x4(0, 1, 0, 2)); - all_eq_!(simd_cttz(y1), U32::<4>([0, 1, 0, 2])); + all_eq!(simd_cttz(x1), i32x4([0, 1, 0, 2])); + all_eq!(simd_cttz(y1), U32::<4>([0, 1, 0, 2])); } } diff --git a/tests/ui/simd/intrinsic/generic-arithmetic-saturating-2.rs b/tests/ui/simd/intrinsic/generic-arithmetic-saturating-2.rs index 36be8cc62a8c8..ec6ac78df1a7a 100644 --- a/tests/ui/simd/intrinsic/generic-arithmetic-saturating-2.rs +++ b/tests/ui/simd/intrinsic/generic-arithmetic-saturating-2.rs @@ -4,15 +4,15 @@ #![allow(non_camel_case_types)] #[repr(simd)] #[derive(Copy, Clone)] -pub struct i32x4(pub i32, pub i32, pub i32, pub i32); +pub struct i32x4(pub [i32; 4]); #[repr(simd)] #[derive(Copy, Clone)] -pub struct x4(pub T, pub T, pub T, pub T); +pub struct x4(pub [T; 4]); #[repr(simd)] #[derive(Copy, Clone)] -pub struct f32x4(pub f32, pub f32, pub f32, pub f32); +pub struct f32x4(pub [f32; 4]); extern "rust-intrinsic" { fn simd_saturating_add(x: T, y: T) -> T; @@ -20,9 +20,9 @@ extern "rust-intrinsic" { } fn main() { - let x = i32x4(0, 0, 0, 0); - let y = x4(0_usize, 0, 0, 0); - let z = f32x4(0.0, 0.0, 0.0, 0.0); + let x = i32x4([0, 0, 0, 0]); + let y = x4([0_usize, 0, 0, 0]); + let z = f32x4([0.0, 0.0, 0.0, 0.0]); unsafe { simd_saturating_add(x, x); diff --git a/tests/ui/simd/intrinsic/generic-arithmetic-saturating-pass.rs b/tests/ui/simd/intrinsic/generic-arithmetic-saturating-pass.rs index deee9c2ac41e6..57bda5c2d624e 100644 --- a/tests/ui/simd/intrinsic/generic-arithmetic-saturating-pass.rs +++ b/tests/ui/simd/intrinsic/generic-arithmetic-saturating-pass.rs @@ -6,7 +6,7 @@ #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -struct u32x4(pub u32, pub u32, pub u32, pub u32); +struct u32x4(pub [u32; 4]); #[repr(simd)] #[derive(Copy, Clone)] @@ -22,11 +22,11 @@ fn main() { { const M: u32 = u32::MAX; - let a = u32x4(1, 2, 3, 4); - let b = u32x4(2, 4, 6, 8); - let m = u32x4(M, M, M, M); - let m1 = u32x4(M - 1, M - 1, M - 1, M - 1); - let z = u32x4(0, 0, 0, 0); + let a = u32x4([1, 2, 3, 4]); + let b = u32x4([2, 4, 6, 8]); + let m = u32x4([M, M, M, M]); + let m1 = u32x4([M - 1, M - 1, M - 1, M - 1]); + let z = u32x4([0, 0, 0, 0]); unsafe { assert_eq!(simd_saturating_add(z, z), z); diff --git a/tests/ui/simd/intrinsic/generic-bitmask-pass.rs b/tests/ui/simd/intrinsic/generic-bitmask-pass.rs index 5c6a07876e35e..db10020bd469b 100644 --- a/tests/ui/simd/intrinsic/generic-bitmask-pass.rs +++ b/tests/ui/simd/intrinsic/generic-bitmask-pass.rs @@ -11,36 +11,36 @@ #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -struct u32x4(pub u32, pub u32, pub u32, pub u32); +struct u32x4(pub [u32; 4]); #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -struct u8x4(pub u8, pub u8, pub u8, pub u8); +struct u8x4(pub [u8; 4]); #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -struct Tx4(pub T, pub T, pub T, pub T); +struct Tx4(pub [T; 4]); extern "rust-intrinsic" { fn simd_bitmask(x: T) -> U; } fn main() { - let z = u32x4(0, 0, 0, 0); + let z = u32x4([0, 0, 0, 0]); let ez = 0_u8; - let o = u32x4(!0, !0, !0, !0); + let o = u32x4([!0, !0, !0, !0]); let eo = 0b_1111_u8; - let m0 = u32x4(!0, 0, !0, 0); + let m0 = u32x4([!0, 0, !0, 0]); let e0 = 0b_0000_0101_u8; // Check that the MSB is extracted: - let m = u8x4(0b_1000_0000, 0b_0100_0001, 0b_1100_0001, 0b_1111_1111); + let m = u8x4([0b_1000_0000, 0b_0100_0001, 0b_1100_0001, 0b_1111_1111]); let e = 0b_1101; // Check usize / isize - let msize: Tx4 = Tx4(usize::MAX, 0, usize::MAX, usize::MAX); + let msize: Tx4 = Tx4([usize::MAX, 0, usize::MAX, usize::MAX]); unsafe { let r: u8 = simd_bitmask(z); diff --git a/tests/ui/simd/intrinsic/generic-cast.rs b/tests/ui/simd/intrinsic/generic-cast.rs index f3fdbe3403f79..33978a2f7395d 100644 --- a/tests/ui/simd/intrinsic/generic-cast.rs +++ b/tests/ui/simd/intrinsic/generic-cast.rs @@ -5,22 +5,20 @@ #[repr(simd)] #[derive(Copy, Clone)] #[allow(non_camel_case_types)] -struct i32x4(i32, i32, i32, i32); +struct i32x4([i32; 4]); #[repr(simd)] #[derive(Copy, Clone)] #[allow(non_camel_case_types)] -struct i32x8(i32, i32, i32, i32, - i32, i32, i32, i32); +struct i32x8([i32; 8]); #[repr(simd)] #[derive(Copy, Clone)] #[allow(non_camel_case_types)] -struct f32x4(f32, f32, f32, f32); +struct f32x4([f32; 4]); #[repr(simd)] #[derive(Copy, Clone)] #[allow(non_camel_case_types)] -struct f32x8(f32, f32, f32, f32, - f32, f32, f32, f32); +struct f32x8([f32; 8]); extern "rust-intrinsic" { @@ -28,7 +26,7 @@ extern "rust-intrinsic" { } fn main() { - let x = i32x4(0, 0, 0, 0); + let x = i32x4([0, 0, 0, 0]); unsafe { simd_cast::(0); diff --git a/tests/ui/simd/intrinsic/generic-cast.stderr b/tests/ui/simd/intrinsic/generic-cast.stderr index 2226bbbe1bd55..2f9d44037afb5 100644 --- a/tests/ui/simd/intrinsic/generic-cast.stderr +++ b/tests/ui/simd/intrinsic/generic-cast.stderr @@ -1,23 +1,23 @@ error[E0511]: invalid monomorphization of `simd_cast` intrinsic: expected SIMD input type, found non-SIMD `i32` - --> $DIR/generic-cast.rs:34:9 + --> $DIR/generic-cast.rs:32:9 | LL | simd_cast::(0); | ^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_cast` intrinsic: expected SIMD input type, found non-SIMD `i32` - --> $DIR/generic-cast.rs:36:9 + --> $DIR/generic-cast.rs:34:9 | LL | simd_cast::(0); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_cast` intrinsic: expected SIMD return type, found non-SIMD `i32` - --> $DIR/generic-cast.rs:38:9 + --> $DIR/generic-cast.rs:36:9 | LL | simd_cast::(x); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_cast` intrinsic: expected return type with length 4 (same as input type `i32x4`), found `i32x8` with length 8 - --> $DIR/generic-cast.rs:40:9 + --> $DIR/generic-cast.rs:38:9 | LL | simd_cast::<_, i32x8>(x); | ^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/simd/intrinsic/generic-comparison-pass.rs b/tests/ui/simd/intrinsic/generic-comparison-pass.rs index a4df836b6f82a..a4d84a4c53482 100644 --- a/tests/ui/simd/intrinsic/generic-comparison-pass.rs +++ b/tests/ui/simd/intrinsic/generic-comparison-pass.rs @@ -6,13 +6,13 @@ #[repr(simd)] #[derive(Copy, Clone)] -struct i32x4(i32, i32, i32, i32); +struct i32x4([i32; 4]); #[repr(simd)] #[derive(Copy, Clone)] -struct u32x4(pub u32, pub u32, pub u32, pub u32); +struct u32x4(pub [u32; 4]); #[repr(simd)] #[derive(Copy, Clone)] -struct f32x4(pub f32, pub f32, pub f32, pub f32); +struct f32x4(pub [f32; 4]); extern "rust-intrinsic" { fn simd_eq(x: T, y: T) -> U; @@ -29,10 +29,10 @@ macro_rules! cmp { let rhs = $rhs; let e: u32x4 = concat_idents!(simd_, $method)($lhs, $rhs); // assume the scalar version is correct/the behaviour we want. - assert!((e.0 != 0) == lhs.0 .$method(&rhs.0)); - assert!((e.1 != 0) == lhs.1 .$method(&rhs.1)); - assert!((e.2 != 0) == lhs.2 .$method(&rhs.2)); - assert!((e.3 != 0) == lhs.3 .$method(&rhs.3)); + assert!((e.0[0] != 0) == lhs.0[0] .$method(&rhs.0[0])); + assert!((e.0[1] != 0) == lhs.0[1] .$method(&rhs.0[1])); + assert!((e.0[2] != 0) == lhs.0[2] .$method(&rhs.0[2])); + assert!((e.0[3] != 0) == lhs.0[3] .$method(&rhs.0[3])); }} } macro_rules! tests { @@ -61,17 +61,17 @@ macro_rules! tests { fn main() { // 13 vs. -100 tests that we get signed vs. unsigned comparisons // correct (i32: 13 > -100, u32: 13 < -100). let i1 = i32x4(10, -11, 12, 13); - let i1 = i32x4(10, -11, 12, 13); - let i2 = i32x4(5, -5, 20, -100); - let i3 = i32x4(10, -11, 20, -100); + let i1 = i32x4([10, -11, 12, 13]); + let i2 = i32x4([5, -5, 20, -100]); + let i3 = i32x4([10, -11, 20, -100]); - let u1 = u32x4(10, !11+1, 12, 13); - let u2 = u32x4(5, !5+1, 20, !100+1); - let u3 = u32x4(10, !11+1, 20, !100+1); + let u1 = u32x4([10, !11+1, 12, 13]); + let u2 = u32x4([5, !5+1, 20, !100+1]); + let u3 = u32x4([10, !11+1, 20, !100+1]); - let f1 = f32x4(10.0, -11.0, 12.0, 13.0); - let f2 = f32x4(5.0, -5.0, 20.0, -100.0); - let f3 = f32x4(10.0, -11.0, 20.0, -100.0); + let f1 = f32x4([10.0, -11.0, 12.0, 13.0]); + let f2 = f32x4([5.0, -5.0, 20.0, -100.0]); + let f3 = f32x4([10.0, -11.0, 20.0, -100.0]); unsafe { tests! { @@ -92,7 +92,7 @@ fn main() { // NAN comparisons are special: // -11 (*) 13 // -5 -100 (*) - let f4 = f32x4(f32::NAN, f1.1, f32::NAN, f2.3); + let f4 = f32x4([f32::NAN, f1.0[1], f32::NAN, f2.0[3]]); unsafe { tests! { diff --git a/tests/ui/simd/intrinsic/generic-comparison.rs b/tests/ui/simd/intrinsic/generic-comparison.rs index bb2720f615fef..f7f0655f3d244 100644 --- a/tests/ui/simd/intrinsic/generic-comparison.rs +++ b/tests/ui/simd/intrinsic/generic-comparison.rs @@ -5,12 +5,11 @@ #[repr(simd)] #[derive(Copy, Clone)] #[allow(non_camel_case_types)] -struct i32x4(i32, i32, i32, i32); +struct i32x4([i32; 4]); #[repr(simd)] #[derive(Copy, Clone)] #[allow(non_camel_case_types)] -struct i16x8(i16, i16, i16, i16, - i16, i16, i16, i16); +struct i16x8([i16; 8]); extern "rust-intrinsic" { fn simd_eq(x: T, y: T) -> U; @@ -22,7 +21,7 @@ extern "rust-intrinsic" { } fn main() { - let x = i32x4(0, 0, 0, 0); + let x = i32x4([0, 0, 0, 0]); unsafe { simd_eq::(0, 0); diff --git a/tests/ui/simd/intrinsic/generic-comparison.stderr b/tests/ui/simd/intrinsic/generic-comparison.stderr index 0eae2688bced0..ac4d491882742 100644 --- a/tests/ui/simd/intrinsic/generic-comparison.stderr +++ b/tests/ui/simd/intrinsic/generic-comparison.stderr @@ -1,107 +1,107 @@ error[E0511]: invalid monomorphization of `simd_eq` intrinsic: expected SIMD input type, found non-SIMD `i32` - --> $DIR/generic-comparison.rs:28:9 + --> $DIR/generic-comparison.rs:27:9 | LL | simd_eq::(0, 0); | ^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_ne` intrinsic: expected SIMD input type, found non-SIMD `i32` - --> $DIR/generic-comparison.rs:30:9 + --> $DIR/generic-comparison.rs:29:9 | LL | simd_ne::(0, 0); | ^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_lt` intrinsic: expected SIMD input type, found non-SIMD `i32` - --> $DIR/generic-comparison.rs:32:9 + --> $DIR/generic-comparison.rs:31:9 | LL | simd_lt::(0, 0); | ^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_le` intrinsic: expected SIMD input type, found non-SIMD `i32` - --> $DIR/generic-comparison.rs:34:9 + --> $DIR/generic-comparison.rs:33:9 | LL | simd_le::(0, 0); | ^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_gt` intrinsic: expected SIMD input type, found non-SIMD `i32` - --> $DIR/generic-comparison.rs:36:9 + --> $DIR/generic-comparison.rs:35:9 | LL | simd_gt::(0, 0); | ^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_ge` intrinsic: expected SIMD input type, found non-SIMD `i32` - --> $DIR/generic-comparison.rs:38:9 + --> $DIR/generic-comparison.rs:37:9 | LL | simd_ge::(0, 0); | ^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_eq` intrinsic: expected SIMD return type, found non-SIMD `i32` - --> $DIR/generic-comparison.rs:41:9 + --> $DIR/generic-comparison.rs:40:9 | LL | simd_eq::<_, i32>(x, x); | ^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_ne` intrinsic: expected SIMD return type, found non-SIMD `i32` - --> $DIR/generic-comparison.rs:43:9 + --> $DIR/generic-comparison.rs:42:9 | LL | simd_ne::<_, i32>(x, x); | ^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_lt` intrinsic: expected SIMD return type, found non-SIMD `i32` - --> $DIR/generic-comparison.rs:45:9 + --> $DIR/generic-comparison.rs:44:9 | LL | simd_lt::<_, i32>(x, x); | ^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_le` intrinsic: expected SIMD return type, found non-SIMD `i32` - --> $DIR/generic-comparison.rs:47:9 + --> $DIR/generic-comparison.rs:46:9 | LL | simd_le::<_, i32>(x, x); | ^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_gt` intrinsic: expected SIMD return type, found non-SIMD `i32` - --> $DIR/generic-comparison.rs:49:9 + --> $DIR/generic-comparison.rs:48:9 | LL | simd_gt::<_, i32>(x, x); | ^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_ge` intrinsic: expected SIMD return type, found non-SIMD `i32` - --> $DIR/generic-comparison.rs:51:9 + --> $DIR/generic-comparison.rs:50:9 | LL | simd_ge::<_, i32>(x, x); | ^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_eq` intrinsic: expected return type with length 4 (same as input type `i32x4`), found `i16x8` with length 8 - --> $DIR/generic-comparison.rs:54:9 + --> $DIR/generic-comparison.rs:53:9 | LL | simd_eq::<_, i16x8>(x, x); | ^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_ne` intrinsic: expected return type with length 4 (same as input type `i32x4`), found `i16x8` with length 8 - --> $DIR/generic-comparison.rs:56:9 + --> $DIR/generic-comparison.rs:55:9 | LL | simd_ne::<_, i16x8>(x, x); | ^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_lt` intrinsic: expected return type with length 4 (same as input type `i32x4`), found `i16x8` with length 8 - --> $DIR/generic-comparison.rs:58:9 + --> $DIR/generic-comparison.rs:57:9 | LL | simd_lt::<_, i16x8>(x, x); | ^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_le` intrinsic: expected return type with length 4 (same as input type `i32x4`), found `i16x8` with length 8 - --> $DIR/generic-comparison.rs:60:9 + --> $DIR/generic-comparison.rs:59:9 | LL | simd_le::<_, i16x8>(x, x); | ^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_gt` intrinsic: expected return type with length 4 (same as input type `i32x4`), found `i16x8` with length 8 - --> $DIR/generic-comparison.rs:62:9 + --> $DIR/generic-comparison.rs:61:9 | LL | simd_gt::<_, i16x8>(x, x); | ^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_ge` intrinsic: expected return type with length 4 (same as input type `i32x4`), found `i16x8` with length 8 - --> $DIR/generic-comparison.rs:64:9 + --> $DIR/generic-comparison.rs:63:9 | LL | simd_ge::<_, i16x8>(x, x); | ^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/simd/intrinsic/generic-elements-pass.rs b/tests/ui/simd/intrinsic/generic-elements-pass.rs index a81d8ebdf50c2..b159387ab62cc 100644 --- a/tests/ui/simd/intrinsic/generic-elements-pass.rs +++ b/tests/ui/simd/intrinsic/generic-elements-pass.rs @@ -6,16 +6,15 @@ #[repr(simd)] #[derive(Copy, Clone, Debug, PartialEq)] #[allow(non_camel_case_types)] -struct i32x2(i32, i32); +struct i32x2([i32; 2]); #[repr(simd)] #[derive(Copy, Clone, Debug, PartialEq)] #[allow(non_camel_case_types)] -struct i32x4(i32, i32, i32, i32); +struct i32x4([i32; 4]); #[repr(simd)] #[derive(Copy, Clone, Debug, PartialEq)] #[allow(non_camel_case_types)] -struct i32x8(i32, i32, i32, i32, - i32, i32, i32, i32); +struct i32x8([i32; 8]); extern "rust-intrinsic" { fn simd_insert(x: T, idx: u32, y: E) -> T; @@ -37,26 +36,26 @@ macro_rules! all_eq { } fn main() { - let x2 = i32x2(20, 21); - let x4 = i32x4(40, 41, 42, 43); - let x8 = i32x8(80, 81, 82, 83, 84, 85, 86, 87); + let x2 = i32x2([20, 21]); + let x4 = i32x4([40, 41, 42, 43]); + let x8 = i32x8([80, 81, 82, 83, 84, 85, 86, 87]); unsafe { - all_eq!(simd_insert(x2, 0, 100), i32x2(100, 21)); - all_eq!(simd_insert(x2, 1, 100), i32x2(20, 100)); + all_eq!(simd_insert(x2, 0, 100), i32x2([100, 21])); + all_eq!(simd_insert(x2, 1, 100), i32x2([20, 100])); - all_eq!(simd_insert(x4, 0, 100), i32x4(100, 41, 42, 43)); - all_eq!(simd_insert(x4, 1, 100), i32x4(40, 100, 42, 43)); - all_eq!(simd_insert(x4, 2, 100), i32x4(40, 41, 100, 43)); - all_eq!(simd_insert(x4, 3, 100), i32x4(40, 41, 42, 100)); + all_eq!(simd_insert(x4, 0, 100), i32x4([100, 41, 42, 43])); + all_eq!(simd_insert(x4, 1, 100), i32x4([40, 100, 42, 43])); + all_eq!(simd_insert(x4, 2, 100), i32x4([40, 41, 100, 43])); + all_eq!(simd_insert(x4, 3, 100), i32x4([40, 41, 42, 100])); - all_eq!(simd_insert(x8, 0, 100), i32x8(100, 81, 82, 83, 84, 85, 86, 87)); - all_eq!(simd_insert(x8, 1, 100), i32x8(80, 100, 82, 83, 84, 85, 86, 87)); - all_eq!(simd_insert(x8, 2, 100), i32x8(80, 81, 100, 83, 84, 85, 86, 87)); - all_eq!(simd_insert(x8, 3, 100), i32x8(80, 81, 82, 100, 84, 85, 86, 87)); - all_eq!(simd_insert(x8, 4, 100), i32x8(80, 81, 82, 83, 100, 85, 86, 87)); - all_eq!(simd_insert(x8, 5, 100), i32x8(80, 81, 82, 83, 84, 100, 86, 87)); - all_eq!(simd_insert(x8, 6, 100), i32x8(80, 81, 82, 83, 84, 85, 100, 87)); - all_eq!(simd_insert(x8, 7, 100), i32x8(80, 81, 82, 83, 84, 85, 86, 100)); + all_eq!(simd_insert(x8, 0, 100), i32x8([100, 81, 82, 83, 84, 85, 86, 87])); + all_eq!(simd_insert(x8, 1, 100), i32x8([80, 100, 82, 83, 84, 85, 86, 87])); + all_eq!(simd_insert(x8, 2, 100), i32x8([80, 81, 100, 83, 84, 85, 86, 87])); + all_eq!(simd_insert(x8, 3, 100), i32x8([80, 81, 82, 100, 84, 85, 86, 87])); + all_eq!(simd_insert(x8, 4, 100), i32x8([80, 81, 82, 83, 100, 85, 86, 87])); + all_eq!(simd_insert(x8, 5, 100), i32x8([80, 81, 82, 83, 84, 100, 86, 87])); + all_eq!(simd_insert(x8, 6, 100), i32x8([80, 81, 82, 83, 84, 85, 100, 87])); + all_eq!(simd_insert(x8, 7, 100), i32x8([80, 81, 82, 83, 84, 85, 86, 100])); all_eq!(simd_extract(x2, 0), 20); all_eq!(simd_extract(x2, 1), 21); @@ -76,24 +75,24 @@ fn main() { all_eq!(simd_extract(x8, 7), 87); } - let y2 = i32x2(120, 121); - let y4 = i32x4(140, 141, 142, 143); - let y8 = i32x8(180, 181, 182, 183, 184, 185, 186, 187); + let y2 = i32x2([120, 121]); + let y4 = i32x4([140, 141, 142, 143]); + let y8 = i32x8([180, 181, 182, 183, 184, 185, 186, 187]); unsafe { - all_eq!(simd_shuffle(x2, y2, const { [3u32, 0] }), i32x2(121, 20)); - all_eq!(simd_shuffle(x2, y2, const { [3u32, 0, 1, 2] }), i32x4(121, 20, 21, 120)); + all_eq!(simd_shuffle(x2, y2, const { [3u32, 0] }), i32x2([121, 20])); + all_eq!(simd_shuffle(x2, y2, const { [3u32, 0, 1, 2] }), i32x4([121, 20, 21, 120])); all_eq!(simd_shuffle(x2, y2, const { [3u32, 0, 1, 2, 1, 2, 3, 0] }), - i32x8(121, 20, 21, 120, 21, 120, 121, 20)); + i32x8([121, 20, 21, 120, 21, 120, 121, 20])); - all_eq!(simd_shuffle(x4, y4, const { [7u32, 2] }), i32x2(143, 42)); - all_eq!(simd_shuffle(x4, y4, const { [7u32, 2, 5, 0] }), i32x4(143, 42, 141, 40)); + all_eq!(simd_shuffle(x4, y4, const { [7u32, 2] }), i32x2([143, 42])); + all_eq!(simd_shuffle(x4, y4, const { [7u32, 2, 5, 0] }), i32x4([143, 42, 141, 40])); all_eq!(simd_shuffle(x4, y4, const { [7u32, 2, 5, 0, 3, 6, 4, 1] }), - i32x8(143, 42, 141, 40, 43, 142, 140, 41)); + i32x8([143, 42, 141, 40, 43, 142, 140, 41])); - all_eq!(simd_shuffle(x8, y8, const { [11u32, 5] }), i32x2(183, 85)); - all_eq!(simd_shuffle(x8, y8, const { [11u32, 5, 15, 0] }), i32x4(183, 85, 187, 80)); + all_eq!(simd_shuffle(x8, y8, const { [11u32, 5] }), i32x2([183, 85])); + all_eq!(simd_shuffle(x8, y8, const { [11u32, 5, 15, 0] }), i32x4([183, 85, 187, 80])); all_eq!(simd_shuffle(x8, y8, const { [11u32, 5, 15, 0, 3, 8, 12, 1] }), - i32x8(183, 85, 187, 80, 83, 180, 184, 81)); + i32x8([183, 85, 187, 80, 83, 180, 184, 81])); } } diff --git a/tests/ui/simd/intrinsic/generic-elements.rs b/tests/ui/simd/intrinsic/generic-elements.rs index aec75a673067e..4848fd1b803af 100644 --- a/tests/ui/simd/intrinsic/generic-elements.rs +++ b/tests/ui/simd/intrinsic/generic-elements.rs @@ -6,28 +6,28 @@ #[repr(simd)] #[derive(Copy, Clone)] #[allow(non_camel_case_types)] -struct i32x2(i32, i32); +struct i32x2([i32; 2]); #[repr(simd)] #[derive(Copy, Clone)] #[allow(non_camel_case_types)] -struct i32x4(i32, i32, i32, i32); +struct i32x4([i32; 4]); #[repr(simd)] #[derive(Copy, Clone)] #[allow(non_camel_case_types)] -struct i32x8(i32, i32, i32, i32, i32, i32, i32, i32); +struct i32x8([i32; 8]); #[repr(simd)] #[derive(Copy, Clone)] #[allow(non_camel_case_types)] -struct f32x2(f32, f32); +struct f32x2([f32; 2]); #[repr(simd)] #[derive(Copy, Clone)] #[allow(non_camel_case_types)] -struct f32x4(f32, f32, f32, f32); +struct f32x4([f32; 4]); #[repr(simd)] #[derive(Copy, Clone)] #[allow(non_camel_case_types)] -struct f32x8(f32, f32, f32, f32, f32, f32, f32, f32); +struct f32x8([f32; 8]); extern "rust-intrinsic" { fn simd_insert(x: T, idx: u32, y: E) -> T; @@ -38,7 +38,7 @@ extern "rust-intrinsic" { } fn main() { - let x = i32x4(0, 0, 0, 0); + let x = i32x4([0, 0, 0, 0]); unsafe { simd_insert(0, 0, 0); diff --git a/tests/ui/simd/intrinsic/generic-gather-pass.rs b/tests/ui/simd/intrinsic/generic-gather-pass.rs index a00bc67e73bd4..3315d1cdaa22d 100644 --- a/tests/ui/simd/intrinsic/generic-gather-pass.rs +++ b/tests/ui/simd/intrinsic/generic-gather-pass.rs @@ -8,7 +8,7 @@ #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -struct x4(pub T, pub T, pub T, pub T); +struct x4(pub [T; 4]); extern "rust-intrinsic" { fn simd_gather(x: T, y: U, z: V) -> T; @@ -18,19 +18,19 @@ extern "rust-intrinsic" { fn main() { let mut x = [0_f32, 1., 2., 3., 4., 5., 6., 7.]; - let default = x4(-3_f32, -3., -3., -3.); - let s_strided = x4(0_f32, 2., -3., 6.); - let mask = x4(-1_i32, -1, 0, -1); + let default = x4([-3_f32, -3., -3., -3.]); + let s_strided = x4([0_f32, 2., -3., 6.]); + let mask = x4([-1_i32, -1, 0, -1]); // reading from *const unsafe { let pointer = x.as_ptr(); - let pointers = x4( + let pointers = x4([ pointer.offset(0), pointer.offset(2), pointer.offset(4), pointer.offset(6) - ); + ]); let r_strided = simd_gather(default, pointers, mask); @@ -40,12 +40,12 @@ fn main() { // reading from *mut unsafe { let pointer = x.as_mut_ptr(); - let pointers = x4( + let pointers = x4([ pointer.offset(0), pointer.offset(2), pointer.offset(4), pointer.offset(6) - ); + ]); let r_strided = simd_gather(default, pointers, mask); @@ -55,14 +55,14 @@ fn main() { // writing to *mut unsafe { let pointer = x.as_mut_ptr(); - let pointers = x4( + let pointers = x4([ pointer.offset(0), pointer.offset(2), pointer.offset(4), pointer.offset(6) - ); + ]); - let values = x4(42_f32, 43_f32, 44_f32, 45_f32); + let values = x4([42_f32, 43_f32, 44_f32, 45_f32]); simd_scatter(values, pointers, mask); assert_eq!(x, [42., 1., 43., 3., 4., 5., 45., 7.]); @@ -80,18 +80,18 @@ fn main() { &x[7] as *const f32 ]; - let default = x4(y[0], y[0], y[0], y[0]); - let s_strided = x4(y[0], y[2], y[0], y[6]); + let default = x4([y[0], y[0], y[0], y[0]]); + let s_strided = x4([y[0], y[2], y[0], y[6]]); // reading from *const unsafe { let pointer = y.as_ptr(); - let pointers = x4( + let pointers = x4([ pointer.offset(0), pointer.offset(2), pointer.offset(4), pointer.offset(6) - ); + ]); let r_strided = simd_gather(default, pointers, mask); @@ -101,12 +101,12 @@ fn main() { // reading from *mut unsafe { let pointer = y.as_mut_ptr(); - let pointers = x4( + let pointers = x4([ pointer.offset(0), pointer.offset(2), pointer.offset(4), pointer.offset(6) - ); + ]); let r_strided = simd_gather(default, pointers, mask); @@ -116,14 +116,14 @@ fn main() { // writing to *mut unsafe { let pointer = y.as_mut_ptr(); - let pointers = x4( + let pointers = x4([ pointer.offset(0), pointer.offset(2), pointer.offset(4), pointer.offset(6) - ); + ]); - let values = x4(y[7], y[6], y[5], y[1]); + let values = x4([y[7], y[6], y[5], y[1]]); simd_scatter(values, pointers, mask); let s = [ diff --git a/tests/ui/simd/intrinsic/generic-reduction-pass.rs b/tests/ui/simd/intrinsic/generic-reduction-pass.rs index 64902788709eb..699fb396259dc 100644 --- a/tests/ui/simd/intrinsic/generic-reduction-pass.rs +++ b/tests/ui/simd/intrinsic/generic-reduction-pass.rs @@ -10,19 +10,19 @@ #[repr(simd)] #[derive(Copy, Clone)] -struct i32x4(pub i32, pub i32, pub i32, pub i32); +struct i32x4(pub [i32; 4]); #[repr(simd)] #[derive(Copy, Clone)] -struct u32x4(pub u32, pub u32, pub u32, pub u32); +struct u32x4(pub [u32; 4]); #[repr(simd)] #[derive(Copy, Clone)] -struct f32x4(pub f32, pub f32, pub f32, pub f32); +struct f32x4(pub [f32; 4]); #[repr(simd)] #[derive(Copy, Clone)] -struct b8x4(pub i8, pub i8, pub i8, pub i8); +struct b8x4(pub [i8; 4]); extern "rust-intrinsic" { fn simd_reduce_add_unordered(x: T) -> U; @@ -40,7 +40,7 @@ extern "rust-intrinsic" { fn main() { unsafe { - let x = i32x4(1, -2, 3, 4); + let x = i32x4([1, -2, 3, 4]); let r: i32 = simd_reduce_add_unordered(x); assert_eq!(r, 6_i32); let r: i32 = simd_reduce_mul_unordered(x); @@ -55,7 +55,7 @@ fn main() { let r: i32 = simd_reduce_max(x); assert_eq!(r, 4_i32); - let x = i32x4(-1, -1, -1, -1); + let x = i32x4([-1, -1, -1, -1]); let r: i32 = simd_reduce_and(x); assert_eq!(r, -1_i32); let r: i32 = simd_reduce_or(x); @@ -63,7 +63,7 @@ fn main() { let r: i32 = simd_reduce_xor(x); assert_eq!(r, 0_i32); - let x = i32x4(-1, -1, 0, -1); + let x = i32x4([-1, -1, 0, -1]); let r: i32 = simd_reduce_and(x); assert_eq!(r, 0_i32); let r: i32 = simd_reduce_or(x); @@ -73,7 +73,7 @@ fn main() { } unsafe { - let x = u32x4(1, 2, 3, 4); + let x = u32x4([1, 2, 3, 4]); let r: u32 = simd_reduce_add_unordered(x); assert_eq!(r, 10_u32); let r: u32 = simd_reduce_mul_unordered(x); @@ -89,7 +89,7 @@ fn main() { assert_eq!(r, 4_u32); let t = u32::MAX; - let x = u32x4(t, t, t, t); + let x = u32x4([t, t, t, t]); let r: u32 = simd_reduce_and(x); assert_eq!(r, t); let r: u32 = simd_reduce_or(x); @@ -97,7 +97,7 @@ fn main() { let r: u32 = simd_reduce_xor(x); assert_eq!(r, 0_u32); - let x = u32x4(t, t, 0, t); + let x = u32x4([t, t, 0, t]); let r: u32 = simd_reduce_and(x); assert_eq!(r, 0_u32); let r: u32 = simd_reduce_or(x); @@ -107,7 +107,7 @@ fn main() { } unsafe { - let x = f32x4(1., -2., 3., 4.); + let x = f32x4([1., -2., 3., 4.]); let r: f32 = simd_reduce_add_unordered(x); assert_eq!(r, 6_f32); let r: f32 = simd_reduce_mul_unordered(x); @@ -128,19 +128,19 @@ fn main() { } unsafe { - let x = b8x4(!0, !0, !0, !0); + let x = b8x4([!0, !0, !0, !0]); let r: bool = simd_reduce_all(x); assert_eq!(r, true); let r: bool = simd_reduce_any(x); assert_eq!(r, true); - let x = b8x4(!0, !0, 0, !0); + let x = b8x4([!0, !0, 0, !0]); let r: bool = simd_reduce_all(x); assert_eq!(r, false); let r: bool = simd_reduce_any(x); assert_eq!(r, true); - let x = b8x4(0, 0, 0, 0); + let x = b8x4([0, 0, 0, 0]); let r: bool = simd_reduce_all(x); assert_eq!(r, false); let r: bool = simd_reduce_any(x); diff --git a/tests/ui/simd/intrinsic/generic-reduction.rs b/tests/ui/simd/intrinsic/generic-reduction.rs index 96df73591693f..1986deafb6ab5 100644 --- a/tests/ui/simd/intrinsic/generic-reduction.rs +++ b/tests/ui/simd/intrinsic/generic-reduction.rs @@ -9,11 +9,11 @@ #[repr(simd)] #[derive(Copy, Clone)] -pub struct f32x4(pub f32, pub f32, pub f32, pub f32); +pub struct f32x4(pub [f32; 4]); #[repr(simd)] #[derive(Copy, Clone)] -pub struct u32x4(pub u32, pub u32, pub u32, pub u32); +pub struct u32x4(pub [u32; 4]); extern "rust-intrinsic" { @@ -27,8 +27,8 @@ extern "rust-intrinsic" { } fn main() { - let x = u32x4(0, 0, 0, 0); - let z = f32x4(0.0, 0.0, 0.0, 0.0); + let x = u32x4([0, 0, 0, 0]); + let z = f32x4([0.0, 0.0, 0.0, 0.0]); unsafe { simd_reduce_add_ordered(z, 0); diff --git a/tests/ui/simd/intrinsic/generic-select-pass.rs b/tests/ui/simd/intrinsic/generic-select-pass.rs index 98e1534e6e622..5690bad504844 100644 --- a/tests/ui/simd/intrinsic/generic-select-pass.rs +++ b/tests/ui/simd/intrinsic/generic-select-pass.rs @@ -11,23 +11,23 @@ #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -struct i32x4(pub i32, pub i32, pub i32, pub i32); +struct i32x4(pub [i32; 4]); #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -struct u32x4(pub u32, pub u32, pub u32, pub u32); +struct u32x4(pub [u32; 4]); #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -struct u32x8(u32, u32, u32, u32, u32, u32, u32, u32); +struct u32x8([u32; 8]); #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -struct f32x4(pub f32, pub f32, pub f32, pub f32); +struct f32x4(pub [f32; 4]); #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -struct b8x4(pub i8, pub i8, pub i8, pub i8); +struct b8x4(pub [i8; 4]); extern "rust-intrinsic" { fn simd_select(x: T, a: U, b: U) -> U; @@ -35,15 +35,15 @@ extern "rust-intrinsic" { } fn main() { - let m0 = b8x4(!0, !0, !0, !0); - let m1 = b8x4(0, 0, 0, 0); - let m2 = b8x4(!0, !0, 0, 0); - let m3 = b8x4(0, 0, !0, !0); - let m4 = b8x4(!0, 0, !0, 0); + let m0 = b8x4([!0, !0, !0, !0]); + let m1 = b8x4([0, 0, 0, 0]); + let m2 = b8x4([!0, !0, 0, 0]); + let m3 = b8x4([0, 0, !0, !0]); + let m4 = b8x4([!0, 0, !0, 0]); unsafe { - let a = i32x4(1, -2, 3, 4); - let b = i32x4(5, 6, -7, 8); + let a = i32x4([1, -2, 3, 4]); + let b = i32x4([5, 6, -7, 8]); let r: i32x4 = simd_select(m0, a, b); let e = a; @@ -54,21 +54,21 @@ fn main() { assert_eq!(r, e); let r: i32x4 = simd_select(m2, a, b); - let e = i32x4(1, -2, -7, 8); + let e = i32x4([1, -2, -7, 8]); assert_eq!(r, e); let r: i32x4 = simd_select(m3, a, b); - let e = i32x4(5, 6, 3, 4); + let e = i32x4([5, 6, 3, 4]); assert_eq!(r, e); let r: i32x4 = simd_select(m4, a, b); - let e = i32x4(1, 6, 3, 8); + let e = i32x4([1, 6, 3, 8]); assert_eq!(r, e); } unsafe { - let a = u32x4(1, 2, 3, 4); - let b = u32x4(5, 6, 7, 8); + let a = u32x4([1, 2, 3, 4]); + let b = u32x4([5, 6, 7, 8]); let r: u32x4 = simd_select(m0, a, b); let e = a; @@ -79,21 +79,21 @@ fn main() { assert_eq!(r, e); let r: u32x4 = simd_select(m2, a, b); - let e = u32x4(1, 2, 7, 8); + let e = u32x4([1, 2, 7, 8]); assert_eq!(r, e); let r: u32x4 = simd_select(m3, a, b); - let e = u32x4(5, 6, 3, 4); + let e = u32x4([5, 6, 3, 4]); assert_eq!(r, e); let r: u32x4 = simd_select(m4, a, b); - let e = u32x4(1, 6, 3, 8); + let e = u32x4([1, 6, 3, 8]); assert_eq!(r, e); } unsafe { - let a = f32x4(1., 2., 3., 4.); - let b = f32x4(5., 6., 7., 8.); + let a = f32x4([1., 2., 3., 4.]); + let b = f32x4([5., 6., 7., 8.]); let r: f32x4 = simd_select(m0, a, b); let e = a; @@ -104,23 +104,23 @@ fn main() { assert_eq!(r, e); let r: f32x4 = simd_select(m2, a, b); - let e = f32x4(1., 2., 7., 8.); + let e = f32x4([1., 2., 7., 8.]); assert_eq!(r, e); let r: f32x4 = simd_select(m3, a, b); - let e = f32x4(5., 6., 3., 4.); + let e = f32x4([5., 6., 3., 4.]); assert_eq!(r, e); let r: f32x4 = simd_select(m4, a, b); - let e = f32x4(1., 6., 3., 8.); + let e = f32x4([1., 6., 3., 8.]); assert_eq!(r, e); } unsafe { let t = !0 as i8; let f = 0 as i8; - let a = b8x4(t, f, t, f); - let b = b8x4(f, f, f, t); + let a = b8x4([t, f, t, f]); + let b = b8x4([f, f, f, t]); let r: b8x4 = simd_select(m0, a, b); let e = a; @@ -131,21 +131,21 @@ fn main() { assert_eq!(r, e); let r: b8x4 = simd_select(m2, a, b); - let e = b8x4(t, f, f, t); + let e = b8x4([t, f, f, t]); assert_eq!(r, e); let r: b8x4 = simd_select(m3, a, b); - let e = b8x4(f, f, t, f); + let e = b8x4([f, f, t, f]); assert_eq!(r, e); let r: b8x4 = simd_select(m4, a, b); - let e = b8x4(t, f, t, t); + let e = b8x4([t, f, t, t]); assert_eq!(r, e); } unsafe { - let a = u32x8(0, 1, 2, 3, 4, 5, 6, 7); - let b = u32x8(8, 9, 10, 11, 12, 13, 14, 15); + let a = u32x8([0, 1, 2, 3, 4, 5, 6, 7]); + let b = u32x8([8, 9, 10, 11, 12, 13, 14, 15]); let r: u32x8 = simd_select_bitmask(0u8, a, b); let e = b; @@ -156,21 +156,21 @@ fn main() { assert_eq!(r, e); let r: u32x8 = simd_select_bitmask(0b01010101u8, a, b); - let e = u32x8(0, 9, 2, 11, 4, 13, 6, 15); + let e = u32x8([0, 9, 2, 11, 4, 13, 6, 15]); assert_eq!(r, e); let r: u32x8 = simd_select_bitmask(0b10101010u8, a, b); - let e = u32x8(8, 1, 10, 3, 12, 5, 14, 7); + let e = u32x8([8, 1, 10, 3, 12, 5, 14, 7]); assert_eq!(r, e); let r: u32x8 = simd_select_bitmask(0b11110000u8, a, b); - let e = u32x8(8, 9, 10, 11, 4, 5, 6, 7); + let e = u32x8([8, 9, 10, 11, 4, 5, 6, 7]); assert_eq!(r, e); } unsafe { - let a = u32x4(0, 1, 2, 3); - let b = u32x4(4, 5, 6, 7); + let a = u32x4([0, 1, 2, 3]); + let b = u32x4([4, 5, 6, 7]); let r: u32x4 = simd_select_bitmask(0u8, a, b); let e = b; @@ -181,15 +181,15 @@ fn main() { assert_eq!(r, e); let r: u32x4 = simd_select_bitmask(0b0101u8, a, b); - let e = u32x4(0, 5, 2, 7); + let e = u32x4([0, 5, 2, 7]); assert_eq!(r, e); let r: u32x4 = simd_select_bitmask(0b1010u8, a, b); - let e = u32x4(4, 1, 6, 3); + let e = u32x4([4, 1, 6, 3]); assert_eq!(r, e); let r: u32x4 = simd_select_bitmask(0b1100u8, a, b); - let e = u32x4(4, 5, 2, 3); + let e = u32x4([4, 5, 2, 3]); assert_eq!(r, e); } } diff --git a/tests/ui/simd/intrinsic/generic-select.rs b/tests/ui/simd/intrinsic/generic-select.rs index 215ae405c37e2..52e02649590ab 100644 --- a/tests/ui/simd/intrinsic/generic-select.rs +++ b/tests/ui/simd/intrinsic/generic-select.rs @@ -8,19 +8,19 @@ #[repr(simd)] #[derive(Copy, Clone)] -pub struct f32x4(pub f32, pub f32, pub f32, pub f32); +pub struct f32x4(pub [f32; 4]); #[repr(simd)] #[derive(Copy, Clone)] -pub struct u32x4(pub u32, pub u32, pub u32, pub u32); +pub struct u32x4(pub [u32; 4]); #[repr(simd)] #[derive(Copy, Clone, PartialEq)] -struct b8x4(pub i8, pub i8, pub i8, pub i8); +struct b8x4(pub [i8; 4]); #[repr(simd)] #[derive(Copy, Clone, PartialEq)] -struct b8x8(pub i8, pub i8, pub i8, pub i8, pub i8, pub i8, pub i8, pub i8); +struct b8x8(pub [i8; 8]); extern "rust-intrinsic" { fn simd_select(x: T, a: U, b: U) -> U; @@ -28,10 +28,10 @@ extern "rust-intrinsic" { } fn main() { - let m4 = b8x4(0, 0, 0, 0); - let m8 = b8x8(0, 0, 0, 0, 0, 0, 0, 0); - let x = u32x4(0, 0, 0, 0); - let z = f32x4(0.0, 0.0, 0.0, 0.0); + let m4 = b8x4([0, 0, 0, 0]); + let m8 = b8x8([0, 0, 0, 0, 0, 0, 0, 0]); + let x = u32x4([0, 0, 0, 0]); + let z = f32x4([0.0, 0.0, 0.0, 0.0]); unsafe { simd_select(m4, x, x); diff --git a/tests/ui/simd/intrinsic/inlining-issue67557-ice.rs b/tests/ui/simd/intrinsic/inlining-issue67557-ice.rs index 928d3824703e7..a64a7c0b48a1e 100644 --- a/tests/ui/simd/intrinsic/inlining-issue67557-ice.rs +++ b/tests/ui/simd/intrinsic/inlining-issue67557-ice.rs @@ -11,7 +11,7 @@ extern "rust-intrinsic" { #[repr(simd)] #[derive(Debug, PartialEq)] -struct Simd2(u8, u8); +struct Simd2([u8; 2]); fn main() { unsafe { @@ -22,5 +22,5 @@ fn main() { #[inline(always)] unsafe fn inline_me() -> Simd2 { const IDX: [u32; 2] = [0, 3]; - simd_shuffle(Simd2(10, 11), Simd2(12, 13), IDX) + simd_shuffle(Simd2([10, 11]), Simd2([12, 13]), IDX) } diff --git a/tests/ui/simd/intrinsic/inlining-issue67557.rs b/tests/ui/simd/intrinsic/inlining-issue67557.rs index b8b8dbba547d1..cb80d65d46838 100644 --- a/tests/ui/simd/intrinsic/inlining-issue67557.rs +++ b/tests/ui/simd/intrinsic/inlining-issue67557.rs @@ -11,12 +11,12 @@ extern "rust-intrinsic" { #[repr(simd)] #[derive(Debug, PartialEq)] -struct Simd2(u8, u8); +struct Simd2([u8; 2]); fn main() { unsafe { const IDX: [u32; 2] = [0, 1]; - let p_res: Simd2 = simd_shuffle(Simd2(10, 11), Simd2(12, 13), IDX); + let p_res: Simd2 = simd_shuffle(Simd2([10, 11]), Simd2([12, 13]), IDX); let a_res: Simd2 = inline_me(); assert_10_11(p_res); @@ -26,17 +26,17 @@ fn main() { #[inline(never)] fn assert_10_11(x: Simd2) { - assert_eq!(x, Simd2(10, 11)); + assert_eq!(x, Simd2([10, 11])); } #[inline(never)] fn assert_10_13(x: Simd2) { - assert_eq!(x, Simd2(10, 13)); + assert_eq!(x, Simd2([10, 13])); } #[inline(always)] unsafe fn inline_me() -> Simd2 { const IDX: [u32; 2] = [0, 3]; - simd_shuffle(Simd2(10, 11), Simd2(12, 13), IDX) + simd_shuffle(Simd2([10, 11]), Simd2([12, 13]), IDX) } diff --git a/tests/ui/simd/issue-17170.rs b/tests/ui/simd/issue-17170.rs index abfc1c25ffb78..2d13962843c44 100644 --- a/tests/ui/simd/issue-17170.rs +++ b/tests/ui/simd/issue-17170.rs @@ -2,9 +2,9 @@ #![feature(repr_simd)] #[repr(simd)] -struct T(f64, f64, f64); +struct T([f64; 3]); -static X: T = T(0.0, 0.0, 0.0); +static X: T = T([0.0, 0.0, 0.0]); fn main() { let _ = X; diff --git a/tests/ui/simd/issue-32947.rs b/tests/ui/simd/issue-32947.rs index bccca25c52b1d..dc5e7a4ec9153 100644 --- a/tests/ui/simd/issue-32947.rs +++ b/tests/ui/simd/issue-32947.rs @@ -6,7 +6,7 @@ extern crate test; #[repr(simd)] -pub struct Mu64(pub u64, pub u64, pub u64, pub u64); +pub struct Mu64(pub [u64; 4]); fn main() { // This ensures an unaligned pointer even in optimized builds, though LLVM @@ -18,7 +18,7 @@ fn main() { let misaligned_ptr: &mut [u8; 32] = { std::mem::transmute(memory.offset(1)) }; - *misaligned_ptr = std::mem::transmute(Mu64(1, 1, 1, 1)); + *misaligned_ptr = std::mem::transmute(Mu64([1, 1, 1, 1])); test::black_box(memory); } } diff --git a/tests/ui/simd/issue-39720.rs b/tests/ui/simd/issue-39720.rs index 4610b1d50044b..2b51c0224c633 100644 --- a/tests/ui/simd/issue-39720.rs +++ b/tests/ui/simd/issue-39720.rs @@ -5,18 +5,18 @@ #[repr(simd)] #[derive(Copy, Clone, Debug)] -pub struct Char3(pub i8, pub i8, pub i8); +pub struct Char3(pub [i8; 3]); #[repr(simd)] #[derive(Copy, Clone, Debug)] -pub struct Short3(pub i16, pub i16, pub i16); +pub struct Short3(pub [i16; 3]); extern "rust-intrinsic" { fn simd_cast(x: T) -> U; } fn main() { - let cast: Short3 = unsafe { simd_cast(Char3(10, -3, -9)) }; + let cast: Short3 = unsafe { simd_cast(Char3([10, -3, -9])) }; println!("{:?}", cast); } diff --git a/tests/ui/simd/issue-89193.rs b/tests/ui/simd/issue-89193.rs index a4ed9be9962fb..9530124a7cc81 100644 --- a/tests/ui/simd/issue-89193.rs +++ b/tests/ui/simd/issue-89193.rs @@ -8,7 +8,7 @@ #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -struct x4(pub T, pub T, pub T, pub T); +struct x4(pub [T; 4]); extern "rust-intrinsic" { fn simd_gather(x: T, y: U, z: V) -> T; @@ -16,36 +16,36 @@ extern "rust-intrinsic" { fn main() { let x: [usize; 4] = [10, 11, 12, 13]; - let default = x4(0_usize, 1, 2, 3); + let default = x4([0_usize, 1, 2, 3]); let all_set = u8::MAX as i8; // aka -1 - let mask = x4(all_set, all_set, all_set, all_set); - let expected = x4(10_usize, 11, 12, 13); + let mask = x4([all_set, all_set, all_set, all_set]); + let expected = x4([10_usize, 11, 12, 13]); unsafe { let pointer = x.as_ptr(); - let pointers = x4( + let pointers = x4([ pointer.offset(0), pointer.offset(1), pointer.offset(2), pointer.offset(3) - ); + ]); let result = simd_gather(default, pointers, mask); assert_eq!(result, expected); } // and again for isize let x: [isize; 4] = [10, 11, 12, 13]; - let default = x4(0_isize, 1, 2, 3); - let expected = x4(10_isize, 11, 12, 13); + let default = x4([0_isize, 1, 2, 3]); + let expected = x4([10_isize, 11, 12, 13]); unsafe { let pointer = x.as_ptr(); - let pointers = x4( + let pointers = x4([ pointer.offset(0), pointer.offset(1), pointer.offset(2), pointer.offset(3) - ); + ]); let result = simd_gather(default, pointers, mask); assert_eq!(result, expected); } diff --git a/tests/ui/simd/monomorphize-heterogeneous.rs b/tests/ui/simd/monomorphize-heterogeneous.rs index 42e380dbb779b..326e52acc34d1 100644 --- a/tests/ui/simd/monomorphize-heterogeneous.rs +++ b/tests/ui/simd/monomorphize-heterogeneous.rs @@ -2,7 +2,11 @@ #[repr(simd)] struct I64F64(i64, f64); -//~^ ERROR SIMD vector should be homogeneous +//~^ ERROR SIMD vector's only field must be an array + +#[repr(simd)] +struct I64x4F64x0([i64; 4], [f64; 0]); +//~^ ERROR SIMD vector cannot have multiple fields static X: I64F64 = I64F64(1, 2.0); diff --git a/tests/ui/simd/monomorphize-heterogeneous.stderr b/tests/ui/simd/monomorphize-heterogeneous.stderr index 58e2b7c834766..610a1a49038aa 100644 --- a/tests/ui/simd/monomorphize-heterogeneous.stderr +++ b/tests/ui/simd/monomorphize-heterogeneous.stderr @@ -1,9 +1,16 @@ -error[E0076]: SIMD vector should be homogeneous +error[E0076]: SIMD vector's only field must be an array --> $DIR/monomorphize-heterogeneous.rs:4:1 | LL | struct I64F64(i64, f64); - | ^^^^^^^^^^^^^ SIMD elements must have the same type + | ^^^^^^^^^^^^^ --- not an array -error: aborting due to 1 previous error +error[E0075]: SIMD vector cannot have multiple fields + --> $DIR/monomorphize-heterogeneous.rs:8:1 + | +LL | struct I64x4F64x0([i64; 4], [f64; 0]); + | ^^^^^^^^^^^^^^^^^ -------- excess field + +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0076`. +Some errors have detailed explanations: E0075, E0076. +For more information about an error, try `rustc --explain E0075`. diff --git a/tests/ui/simd/monomorphize-too-long.rs b/tests/ui/simd/monomorphize-too-long.rs new file mode 100644 index 0000000000000..4bcde782292d6 --- /dev/null +++ b/tests/ui/simd/monomorphize-too-long.rs @@ -0,0 +1,11 @@ +//@ build-fail +//@ error-pattern: monomorphising SIMD type `Simd` of length greater than 32768 + +#![feature(repr_simd)] + +#[repr(simd)] +struct Simd([T; N]); + +fn main() { + let _too_big = Simd([1_u16; 54321]); +} diff --git a/tests/ui/simd/monomorphize-too-long.stderr b/tests/ui/simd/monomorphize-too-long.stderr new file mode 100644 index 0000000000000..978eef307abd1 --- /dev/null +++ b/tests/ui/simd/monomorphize-too-long.stderr @@ -0,0 +1,4 @@ +error: monomorphising SIMD type `Simd` of length greater than 32768 + +error: aborting due to 1 previous error + diff --git a/tests/ui/simd/monomorphize-zero-length.rs b/tests/ui/simd/monomorphize-zero-length.rs new file mode 100644 index 0000000000000..44b4cfc0bcfab --- /dev/null +++ b/tests/ui/simd/monomorphize-zero-length.rs @@ -0,0 +1,11 @@ +//@ build-fail +//@ error-pattern: monomorphising SIMD type `Simd` of zero length + +#![feature(repr_simd)] + +#[repr(simd)] +struct Simd([T; N]); + +fn main() { + let _empty = Simd([1.0; 0]); +} diff --git a/tests/ui/simd/monomorphize-zero-length.stderr b/tests/ui/simd/monomorphize-zero-length.stderr new file mode 100644 index 0000000000000..738c20fe51a46 --- /dev/null +++ b/tests/ui/simd/monomorphize-zero-length.stderr @@ -0,0 +1,4 @@ +error: monomorphising SIMD type `Simd` of zero length + +error: aborting due to 1 previous error + diff --git a/tests/ui/simd/target-feature-mixup.rs b/tests/ui/simd/target-feature-mixup.rs index 034cb867c95fc..62d87c3a6dc6c 100644 --- a/tests/ui/simd/target-feature-mixup.rs +++ b/tests/ui/simd/target-feature-mixup.rs @@ -54,17 +54,17 @@ mod test { // An SSE type #[repr(simd)] #[derive(PartialEq, Debug, Clone, Copy)] - struct __m128i(u64, u64); + struct __m128i([u64; 2]); // An AVX type #[repr(simd)] #[derive(PartialEq, Debug, Clone, Copy)] - struct __m256i(u64, u64, u64, u64); + struct __m256i([u64; 4]); // An AVX-512 type #[repr(simd)] #[derive(PartialEq, Debug, Clone, Copy)] - struct __m512i(u64, u64, u64, u64, u64, u64, u64, u64); + struct __m512i([u64; 8]); pub fn main(level: &str) { unsafe { @@ -90,9 +90,9 @@ mod test { )*) => ($( $(#[$attr])* unsafe fn $main(level: &str) { - let m128 = __m128i(1, 2); - let m256 = __m256i(3, 4, 5, 6); - let m512 = __m512i(7, 8, 9, 10, 11, 12, 13, 14); + let m128 = __m128i([1, 2]); + let m256 = __m256i([3, 4, 5, 6]); + let m512 = __m512i([7, 8, 9, 10, 11, 12, 13, 14]); assert_eq!(id_sse_128(m128), m128); assert_eq!(id_sse_256(m256), m256); assert_eq!(id_sse_512(m512), m512); @@ -127,55 +127,55 @@ mod test { #[target_feature(enable = "sse2")] unsafe fn id_sse_128(a: __m128i) -> __m128i { - assert_eq!(a, __m128i(1, 2)); + assert_eq!(a, __m128i([1, 2])); a.clone() } #[target_feature(enable = "sse2")] unsafe fn id_sse_256(a: __m256i) -> __m256i { - assert_eq!(a, __m256i(3, 4, 5, 6)); + assert_eq!(a, __m256i([3, 4, 5, 6])); a.clone() } #[target_feature(enable = "sse2")] unsafe fn id_sse_512(a: __m512i) -> __m512i { - assert_eq!(a, __m512i(7, 8, 9, 10, 11, 12, 13, 14)); + assert_eq!(a, __m512i([7, 8, 9, 10, 11, 12, 13, 14])); a.clone() } #[target_feature(enable = "avx")] unsafe fn id_avx_128(a: __m128i) -> __m128i { - assert_eq!(a, __m128i(1, 2)); + assert_eq!(a, __m128i([1, 2])); a.clone() } #[target_feature(enable = "avx")] unsafe fn id_avx_256(a: __m256i) -> __m256i { - assert_eq!(a, __m256i(3, 4, 5, 6)); + assert_eq!(a, __m256i([3, 4, 5, 6])); a.clone() } #[target_feature(enable = "avx")] unsafe fn id_avx_512(a: __m512i) -> __m512i { - assert_eq!(a, __m512i(7, 8, 9, 10, 11, 12, 13, 14)); + assert_eq!(a, __m512i([7, 8, 9, 10, 11, 12, 13, 14])); a.clone() } #[target_feature(enable = "avx512bw")] unsafe fn id_avx512_128(a: __m128i) -> __m128i { - assert_eq!(a, __m128i(1, 2)); + assert_eq!(a, __m128i([1, 2])); a.clone() } #[target_feature(enable = "avx512bw")] unsafe fn id_avx512_256(a: __m256i) -> __m256i { - assert_eq!(a, __m256i(3, 4, 5, 6)); + assert_eq!(a, __m256i([3, 4, 5, 6])); a.clone() } #[target_feature(enable = "avx512bw")] unsafe fn id_avx512_512(a: __m512i) -> __m512i { - assert_eq!(a, __m512i(7, 8, 9, 10, 11, 12, 13, 14)); + assert_eq!(a, __m512i([7, 8, 9, 10, 11, 12, 13, 14])); a.clone() } } diff --git a/tests/ui/simd/type-generic-monomorphisation-extern-nonnull-ptr.rs b/tests/ui/simd/type-generic-monomorphisation-extern-nonnull-ptr.rs index dbe2d9ddd54a7..a969295c9f9cd 100644 --- a/tests/ui/simd/type-generic-monomorphisation-extern-nonnull-ptr.rs +++ b/tests/ui/simd/type-generic-monomorphisation-extern-nonnull-ptr.rs @@ -11,7 +11,7 @@ extern { } #[repr(simd)] -struct S(T); +struct S([T; 4]); #[inline(never)] fn identity(v: T) -> T { @@ -19,5 +19,5 @@ fn identity(v: T) -> T { } fn main() { - let _v: S<[Option>; 4]> = identity(S([None; 4])); + let _v: S>> = identity(S([None; 4])); } diff --git a/tests/ui/simd/type-generic-monomorphisation-wide-ptr.rs b/tests/ui/simd/type-generic-monomorphisation-wide-ptr.rs index 564118e9b1343..18fc075343069 100644 --- a/tests/ui/simd/type-generic-monomorphisation-wide-ptr.rs +++ b/tests/ui/simd/type-generic-monomorphisation-wide-ptr.rs @@ -2,11 +2,11 @@ #![feature(repr_simd)] -//@ error-pattern:monomorphising SIMD type `S<[*mut [u8]; 4]>` with a non-primitive-scalar (integer/float/pointer) element type `*mut [u8]` +//@ error-pattern:monomorphising SIMD type `S<*mut [u8]>` with a non-primitive-scalar (integer/float/pointer) element type `*mut [u8]` #[repr(simd)] -struct S(T); +struct S([T; 4]); fn main() { - let _v: Option> = None; + let _v: Option> = None; } diff --git a/tests/ui/simd/type-generic-monomorphisation-wide-ptr.stderr b/tests/ui/simd/type-generic-monomorphisation-wide-ptr.stderr index 7ac8d71536034..13b8b0315ba75 100644 --- a/tests/ui/simd/type-generic-monomorphisation-wide-ptr.stderr +++ b/tests/ui/simd/type-generic-monomorphisation-wide-ptr.stderr @@ -1,4 +1,4 @@ -error: monomorphising SIMD type `S<[*mut [u8]; 4]>` with a non-primitive-scalar (integer/float/pointer) element type `*mut [u8]` +error: monomorphising SIMD type `S<*mut [u8]>` with a non-primitive-scalar (integer/float/pointer) element type `*mut [u8]` error: aborting due to 1 previous error diff --git a/tests/ui/simd/type-generic-monomorphisation.rs b/tests/ui/simd/type-generic-monomorphisation.rs index 2eeba55ef913a..8b8d645a2649b 100644 --- a/tests/ui/simd/type-generic-monomorphisation.rs +++ b/tests/ui/simd/type-generic-monomorphisation.rs @@ -7,8 +7,8 @@ struct X(Vec); #[repr(simd)] -struct Simd2(T, T); +struct Simd2([T; 2]); fn main() { - let _ = Simd2(X(vec![]), X(vec![])); + let _ = Simd2([X(vec![]), X(vec![])]); } diff --git a/tests/ui/simd/type-len.rs b/tests/ui/simd/type-len.rs index d82c70b8d8268..a971177e1543a 100644 --- a/tests/ui/simd/type-len.rs +++ b/tests/ui/simd/type-len.rs @@ -1,7 +1,6 @@ #![feature(repr_simd)] #![allow(non_camel_case_types)] - #[repr(simd)] struct empty; //~ ERROR SIMD vector cannot be empty @@ -12,12 +11,12 @@ struct empty2([f32; 0]); //~ ERROR SIMD vector cannot be empty struct pow2([f32; 7]); #[repr(simd)] -struct i64f64(i64, f64); //~ ERROR SIMD vector should be homogeneous +struct i64f64(i64, f64); //~ ERROR SIMD vector's only field must be an array struct Foo; #[repr(simd)] -struct FooV(Foo, Foo); //~ ERROR SIMD vector element type should be a primitive scalar (integer/float/pointer) type +struct FooV(Foo, Foo); //~ ERROR SIMD vector's only field must be an array #[repr(simd)] struct FooV2([Foo; 2]); //~ ERROR SIMD vector element type should be a primitive scalar (integer/float/pointer) type @@ -29,11 +28,11 @@ struct TooBig([f32; 65536]); //~ ERROR SIMD vector cannot have more than 32768 e struct JustRight([u128; 32768]); #[repr(simd)] -struct RGBA { +struct RGBA { //~ ERROR SIMD vector's only field must be an array r: f32, g: f32, b: f32, - a: f32 + a: f32, } fn main() {} diff --git a/tests/ui/simd/type-len.stderr b/tests/ui/simd/type-len.stderr index 2a6bd1b0fd58a..04c4ca7677cfc 100644 --- a/tests/ui/simd/type-len.stderr +++ b/tests/ui/simd/type-len.stderr @@ -1,40 +1,48 @@ error[E0075]: SIMD vector cannot be empty - --> $DIR/type-len.rs:6:1 + --> $DIR/type-len.rs:5:1 | LL | struct empty; | ^^^^^^^^^^^^ error[E0075]: SIMD vector cannot be empty - --> $DIR/type-len.rs:9:1 + --> $DIR/type-len.rs:8:1 | LL | struct empty2([f32; 0]); | ^^^^^^^^^^^^^ -error[E0076]: SIMD vector should be homogeneous - --> $DIR/type-len.rs:15:1 +error[E0076]: SIMD vector's only field must be an array + --> $DIR/type-len.rs:14:1 | LL | struct i64f64(i64, f64); - | ^^^^^^^^^^^^^ SIMD elements must have the same type + | ^^^^^^^^^^^^^ --- not an array -error[E0077]: SIMD vector element type should be a primitive scalar (integer/float/pointer) type - --> $DIR/type-len.rs:20:1 +error[E0076]: SIMD vector's only field must be an array + --> $DIR/type-len.rs:19:1 | LL | struct FooV(Foo, Foo); - | ^^^^^^^^^^^ + | ^^^^^^^^^^^ --- not an array error[E0077]: SIMD vector element type should be a primitive scalar (integer/float/pointer) type - --> $DIR/type-len.rs:23:1 + --> $DIR/type-len.rs:22:1 | LL | struct FooV2([Foo; 2]); | ^^^^^^^^^^^^ error[E0075]: SIMD vector cannot have more than 32768 elements - --> $DIR/type-len.rs:26:1 + --> $DIR/type-len.rs:25:1 | LL | struct TooBig([f32; 65536]); | ^^^^^^^^^^^^^ -error: aborting due to 6 previous errors +error[E0076]: SIMD vector's only field must be an array + --> $DIR/type-len.rs:31:1 + | +LL | struct RGBA { + | ^^^^^^^^^^^ +LL | r: f32, + | ------ not an array + +error: aborting due to 7 previous errors Some errors have detailed explanations: E0075, E0076, E0077. For more information about an error, try `rustc --explain E0075`. diff --git a/tests/ui/span/gated-features-attr-spans.rs b/tests/ui/span/gated-features-attr-spans.rs index 69511ab8e1fc7..55527fa8add01 100644 --- a/tests/ui/span/gated-features-attr-spans.rs +++ b/tests/ui/span/gated-features-attr-spans.rs @@ -1,7 +1,6 @@ #[repr(simd)] //~ ERROR are experimental struct Coord { - x: u32, - y: u32, + v: [u32; 2], } fn main() {} From 24c505070c710dea13c02e965cf0b227e856ade1 Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Fri, 23 Aug 2024 01:59:26 -0700 Subject: [PATCH 0777/2194] Fix the examples in cg_clif --- .../example/float-minmax-pass.rs | 12 ++++++------ .../rustc_codegen_cranelift/example/std_example.rs | 4 ++-- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/compiler/rustc_codegen_cranelift/example/float-minmax-pass.rs b/compiler/rustc_codegen_cranelift/example/float-minmax-pass.rs index c54574d801d3a..ad46e18c11c0d 100644 --- a/compiler/rustc_codegen_cranelift/example/float-minmax-pass.rs +++ b/compiler/rustc_codegen_cranelift/example/float-minmax-pass.rs @@ -9,13 +9,13 @@ #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -struct f32x4(pub f32, pub f32, pub f32, pub f32); +struct f32x4(pub [f32; 4]); use std::intrinsics::simd::*; fn main() { - let x = f32x4(1.0, 2.0, 3.0, 4.0); - let y = f32x4(2.0, 1.0, 4.0, 3.0); + let x = f32x4([1.0, 2.0, 3.0, 4.0]); + let y = f32x4([2.0, 1.0, 4.0, 3.0]); #[cfg(not(any(target_arch = "mips", target_arch = "mips64")))] let nan = f32::NAN; @@ -24,13 +24,13 @@ fn main() { #[cfg(any(target_arch = "mips", target_arch = "mips64"))] let nan = f32::from_bits(f32::NAN.to_bits() - 1); - let n = f32x4(nan, nan, nan, nan); + let n = f32x4([nan, nan, nan, nan]); unsafe { let min0 = simd_fmin(x, y); let min1 = simd_fmin(y, x); assert_eq!(min0, min1); - let e = f32x4(1.0, 1.0, 3.0, 3.0); + let e = f32x4([1.0, 1.0, 3.0, 3.0]); assert_eq!(min0, e); let minn = simd_fmin(x, n); assert_eq!(minn, x); @@ -40,7 +40,7 @@ fn main() { let max0 = simd_fmax(x, y); let max1 = simd_fmax(y, x); assert_eq!(max0, max1); - let e = f32x4(2.0, 2.0, 4.0, 4.0); + let e = f32x4([2.0, 2.0, 4.0, 4.0]); assert_eq!(max0, e); let maxn = simd_fmax(x, n); assert_eq!(maxn, x); diff --git a/compiler/rustc_codegen_cranelift/example/std_example.rs b/compiler/rustc_codegen_cranelift/example/std_example.rs index e99763e272233..f27d4ef57e0c0 100644 --- a/compiler/rustc_codegen_cranelift/example/std_example.rs +++ b/compiler/rustc_codegen_cranelift/example/std_example.rs @@ -166,7 +166,7 @@ fn main() { enum Never {} } - foo(I64X2(0, 0)); + foo(I64X2([0, 0])); transmute_fat_pointer(); @@ -204,7 +204,7 @@ fn rust_call_abi() { } #[repr(simd)] -struct I64X2(i64, i64); +struct I64X2([i64; 2]); #[allow(improper_ctypes_definitions)] extern "C" fn foo(_a: I64X2) {} From 51d0f68b781a9fde6cf7712b89d01991420ed70f Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Fri, 23 Aug 2024 12:21:20 -0700 Subject: [PATCH 0778/2194] Update the MIRI tests --- .../tests/fail/intrinsics/simd-div-by-zero.rs | 6 +++--- .../tests/fail/intrinsics/simd-div-overflow.rs | 6 +++--- .../intrinsics/simd-reduce-invalid-bool.rs | 4 ++-- .../tests/fail/intrinsics/simd-rem-by-zero.rs | 6 +++--- .../intrinsics/simd-select-bitmask-invalid.rs | 4 ++-- .../intrinsics/simd-select-invalid-bool.rs | 4 ++-- .../tests/fail/intrinsics/simd-shl-too-far.rs | 6 +++--- .../tests/fail/intrinsics/simd-shr-too-far.rs | 6 +++--- .../pass/simd-intrinsic-generic-elements.rs | 18 +++++++++--------- 9 files changed, 30 insertions(+), 30 deletions(-) diff --git a/src/tools/miri/tests/fail/intrinsics/simd-div-by-zero.rs b/src/tools/miri/tests/fail/intrinsics/simd-div-by-zero.rs index ba474332b811c..57a9b66d8ecde 100644 --- a/src/tools/miri/tests/fail/intrinsics/simd-div-by-zero.rs +++ b/src/tools/miri/tests/fail/intrinsics/simd-div-by-zero.rs @@ -4,12 +4,12 @@ use std::intrinsics::simd::simd_div; #[repr(simd)] #[allow(non_camel_case_types)] -struct i32x2(i32, i32); +struct i32x2([i32; 2]); fn main() { unsafe { - let x = i32x2(1, 1); - let y = i32x2(1, 0); + let x = i32x2([1, 1]); + let y = i32x2([1, 0]); simd_div(x, y); //~ERROR: Undefined Behavior: dividing by zero } } diff --git a/src/tools/miri/tests/fail/intrinsics/simd-div-overflow.rs b/src/tools/miri/tests/fail/intrinsics/simd-div-overflow.rs index d01e41de0e4be..8ffc2669828c4 100644 --- a/src/tools/miri/tests/fail/intrinsics/simd-div-overflow.rs +++ b/src/tools/miri/tests/fail/intrinsics/simd-div-overflow.rs @@ -4,12 +4,12 @@ use std::intrinsics::simd::simd_div; #[repr(simd)] #[allow(non_camel_case_types)] -struct i32x2(i32, i32); +struct i32x2([i32; 2]); fn main() { unsafe { - let x = i32x2(1, i32::MIN); - let y = i32x2(1, -1); + let x = i32x2([1, i32::MIN]); + let y = i32x2([1, -1]); simd_div(x, y); //~ERROR: Undefined Behavior: overflow in signed division } } diff --git a/src/tools/miri/tests/fail/intrinsics/simd-reduce-invalid-bool.rs b/src/tools/miri/tests/fail/intrinsics/simd-reduce-invalid-bool.rs index a194f0dd18aa8..ea0f908d996ff 100644 --- a/src/tools/miri/tests/fail/intrinsics/simd-reduce-invalid-bool.rs +++ b/src/tools/miri/tests/fail/intrinsics/simd-reduce-invalid-bool.rs @@ -4,11 +4,11 @@ use std::intrinsics::simd::simd_reduce_any; #[repr(simd)] #[allow(non_camel_case_types)] -struct i32x2(i32, i32); +struct i32x2([i32; 2]); fn main() { unsafe { - let x = i32x2(0, 1); + let x = i32x2([0, 1]); simd_reduce_any(x); //~ERROR: must be all-0-bits or all-1-bits } } diff --git a/src/tools/miri/tests/fail/intrinsics/simd-rem-by-zero.rs b/src/tools/miri/tests/fail/intrinsics/simd-rem-by-zero.rs index cd1e4b8162b36..21c9520efc48a 100644 --- a/src/tools/miri/tests/fail/intrinsics/simd-rem-by-zero.rs +++ b/src/tools/miri/tests/fail/intrinsics/simd-rem-by-zero.rs @@ -4,12 +4,12 @@ use std::intrinsics::simd::simd_rem; #[repr(simd)] #[allow(non_camel_case_types)] -struct i32x2(i32, i32); +struct i32x2([i32; 2]); fn main() { unsafe { - let x = i32x2(1, 1); - let y = i32x2(1, 0); + let x = i32x2([1, 1]); + let y = i32x2([1, 0]); simd_rem(x, y); //~ERROR: Undefined Behavior: calculating the remainder with a divisor of zero } } diff --git a/src/tools/miri/tests/fail/intrinsics/simd-select-bitmask-invalid.rs b/src/tools/miri/tests/fail/intrinsics/simd-select-bitmask-invalid.rs index 96802fae49c23..409098ac3b5df 100644 --- a/src/tools/miri/tests/fail/intrinsics/simd-select-bitmask-invalid.rs +++ b/src/tools/miri/tests/fail/intrinsics/simd-select-bitmask-invalid.rs @@ -5,11 +5,11 @@ use std::intrinsics::simd::simd_select_bitmask; #[repr(simd)] #[allow(non_camel_case_types)] #[derive(Copy, Clone)] -struct i32x2(i32, i32); +struct i32x2([i32; 2]); fn main() { unsafe { - let x = i32x2(0, 1); + let x = i32x2([0, 1]); simd_select_bitmask(0b11111111u8, x, x); //~ERROR: bitmask less than 8 bits long must be filled with 0s for the remaining bits } } diff --git a/src/tools/miri/tests/fail/intrinsics/simd-select-invalid-bool.rs b/src/tools/miri/tests/fail/intrinsics/simd-select-invalid-bool.rs index 388fb2e2a84ae..a81ce95ada62f 100644 --- a/src/tools/miri/tests/fail/intrinsics/simd-select-invalid-bool.rs +++ b/src/tools/miri/tests/fail/intrinsics/simd-select-invalid-bool.rs @@ -5,11 +5,11 @@ use std::intrinsics::simd::simd_select; #[repr(simd)] #[allow(non_camel_case_types)] #[derive(Copy, Clone)] -struct i32x2(i32, i32); +struct i32x2([i32; 2]); fn main() { unsafe { - let x = i32x2(0, 1); + let x = i32x2([0, 1]); simd_select(x, x, x); //~ERROR: must be all-0-bits or all-1-bits } } diff --git a/src/tools/miri/tests/fail/intrinsics/simd-shl-too-far.rs b/src/tools/miri/tests/fail/intrinsics/simd-shl-too-far.rs index 12aa7c10af4e4..ed317254ee66c 100644 --- a/src/tools/miri/tests/fail/intrinsics/simd-shl-too-far.rs +++ b/src/tools/miri/tests/fail/intrinsics/simd-shl-too-far.rs @@ -4,12 +4,12 @@ use std::intrinsics::simd::simd_shl; #[repr(simd)] #[allow(non_camel_case_types)] -struct i32x2(i32, i32); +struct i32x2([i32; 2]); fn main() { unsafe { - let x = i32x2(1, 1); - let y = i32x2(100, 0); + let x = i32x2([1, 1]); + let y = i32x2([100, 0]); simd_shl(x, y); //~ERROR: overflowing shift by 100 in `simd_shl` in lane 0 } } diff --git a/src/tools/miri/tests/fail/intrinsics/simd-shr-too-far.rs b/src/tools/miri/tests/fail/intrinsics/simd-shr-too-far.rs index ada7cf408c4ed..5d2ff1b82ed06 100644 --- a/src/tools/miri/tests/fail/intrinsics/simd-shr-too-far.rs +++ b/src/tools/miri/tests/fail/intrinsics/simd-shr-too-far.rs @@ -4,12 +4,12 @@ use std::intrinsics::simd::simd_shr; #[repr(simd)] #[allow(non_camel_case_types)] -struct i32x2(i32, i32); +struct i32x2([i32; 2]); fn main() { unsafe { - let x = i32x2(1, 1); - let y = i32x2(20, 40); + let x = i32x2([1, 1]); + let y = i32x2([20, 40]); simd_shr(x, y); //~ERROR: overflowing shift by 40 in `simd_shr` in lane 1 } } diff --git a/src/tools/miri/tests/pass/simd-intrinsic-generic-elements.rs b/src/tools/miri/tests/pass/simd-intrinsic-generic-elements.rs index 4a87f8c3ca720..9cf0c2ddef333 100644 --- a/src/tools/miri/tests/pass/simd-intrinsic-generic-elements.rs +++ b/src/tools/miri/tests/pass/simd-intrinsic-generic-elements.rs @@ -3,22 +3,22 @@ #[repr(simd)] #[derive(Copy, Clone, Debug, PartialEq)] #[allow(non_camel_case_types)] -struct i32x2(i32, i32); +struct i32x2([i32; 2]); #[repr(simd)] #[derive(Copy, Clone, Debug, PartialEq)] #[allow(non_camel_case_types)] -struct i32x4(i32, i32, i32, i32); +struct i32x4([i32; 4]); #[repr(simd)] #[derive(Copy, Clone, Debug, PartialEq)] #[allow(non_camel_case_types)] -struct i32x8(i32, i32, i32, i32, i32, i32, i32, i32); +struct i32x8([i32; 8]); fn main() { - let _x2 = i32x2(20, 21); - let _x4 = i32x4(40, 41, 42, 43); - let _x8 = i32x8(80, 81, 82, 83, 84, 85, 86, 87); + let _x2 = i32x2([20, 21]); + let _x4 = i32x4([40, 41, 42, 43]); + let _x8 = i32x8([80, 81, 82, 83, 84, 85, 86, 87]); - let _y2 = i32x2(120, 121); - let _y4 = i32x4(140, 141, 142, 143); - let _y8 = i32x8(180, 181, 182, 183, 184, 185, 186, 187); + let _y2 = i32x2([120, 121]); + let _y4 = i32x4([140, 141, 142, 143]); + let _y8 = i32x8([180, 181, 182, 183, 184, 185, 186, 187]); } From fe5183e627731f076e1aee9133f71190b5b67c1a Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Fri, 23 Aug 2024 01:59:26 -0700 Subject: [PATCH 0779/2194] Fix the examples in cg_clif --- example/float-minmax-pass.rs | 12 ++++++------ example/std_example.rs | 4 ++-- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/example/float-minmax-pass.rs b/example/float-minmax-pass.rs index c54574d801d3a..ad46e18c11c0d 100644 --- a/example/float-minmax-pass.rs +++ b/example/float-minmax-pass.rs @@ -9,13 +9,13 @@ #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -struct f32x4(pub f32, pub f32, pub f32, pub f32); +struct f32x4(pub [f32; 4]); use std::intrinsics::simd::*; fn main() { - let x = f32x4(1.0, 2.0, 3.0, 4.0); - let y = f32x4(2.0, 1.0, 4.0, 3.0); + let x = f32x4([1.0, 2.0, 3.0, 4.0]); + let y = f32x4([2.0, 1.0, 4.0, 3.0]); #[cfg(not(any(target_arch = "mips", target_arch = "mips64")))] let nan = f32::NAN; @@ -24,13 +24,13 @@ fn main() { #[cfg(any(target_arch = "mips", target_arch = "mips64"))] let nan = f32::from_bits(f32::NAN.to_bits() - 1); - let n = f32x4(nan, nan, nan, nan); + let n = f32x4([nan, nan, nan, nan]); unsafe { let min0 = simd_fmin(x, y); let min1 = simd_fmin(y, x); assert_eq!(min0, min1); - let e = f32x4(1.0, 1.0, 3.0, 3.0); + let e = f32x4([1.0, 1.0, 3.0, 3.0]); assert_eq!(min0, e); let minn = simd_fmin(x, n); assert_eq!(minn, x); @@ -40,7 +40,7 @@ fn main() { let max0 = simd_fmax(x, y); let max1 = simd_fmax(y, x); assert_eq!(max0, max1); - let e = f32x4(2.0, 2.0, 4.0, 4.0); + let e = f32x4([2.0, 2.0, 4.0, 4.0]); assert_eq!(max0, e); let maxn = simd_fmax(x, n); assert_eq!(maxn, x); diff --git a/example/std_example.rs b/example/std_example.rs index e99763e272233..f27d4ef57e0c0 100644 --- a/example/std_example.rs +++ b/example/std_example.rs @@ -166,7 +166,7 @@ fn main() { enum Never {} } - foo(I64X2(0, 0)); + foo(I64X2([0, 0])); transmute_fat_pointer(); @@ -204,7 +204,7 @@ fn rust_call_abi() { } #[repr(simd)] -struct I64X2(i64, i64); +struct I64X2([i64; 2]); #[allow(improper_ctypes_definitions)] extern "C" fn foo(_a: I64X2) {} From bd5873ae1206127011d7d4918d51ffeab5ce4ac0 Mon Sep 17 00:00:00 2001 From: Yacin Tmimi Date: Tue, 10 Sep 2024 01:16:16 -0400 Subject: [PATCH 0780/2194] bump toolchain to nightly-2024-09-10 --- rust-toolchain | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust-toolchain b/rust-toolchain index 7b7081bfe815b..80723123274a0 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1,3 +1,3 @@ [toolchain] -channel = "nightly-2024-08-17" +channel = "nightly-2024-09-10" components = ["llvm-tools", "rustc-dev"] From a21f39522c8d5776f5baa6ead22c1dbb13e56820 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Mon, 9 Sep 2024 17:40:25 +1000 Subject: [PATCH 0781/2194] bootstrap: Print more debug info when `find_initial_libdir` fails --- src/bootstrap/src/lib.rs | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/bootstrap/src/lib.rs b/src/bootstrap/src/lib.rs index 780024e307edc..fa295dea1f6dd 100644 --- a/src/bootstrap/src/lib.rs +++ b/src/bootstrap/src/lib.rs @@ -347,10 +347,14 @@ impl Build { }; let Some(initial_libdir) = find_initial_libdir() else { panic!( - "couldn't determine `initial_libdir` \ - from target dir {initial_target_dir:?} \ - and sysroot {initial_sysroot:?}" - ) + "couldn't determine `initial_libdir`: +- config.initial_rustc: {rustc:?} +- initial_target_libdir_str: {initial_target_libdir_str:?} +- initial_target_dir: {initial_target_dir:?} +- initial_sysroot: {initial_sysroot:?} +", + rustc = config.initial_rustc, + ); }; let version = std::fs::read_to_string(src.join("src").join("version")) From e96b4e479a3835d43d3c0bfd1028b5ac9d99cfec Mon Sep 17 00:00:00 2001 From: Zalathar Date: Fri, 6 Sep 2024 15:41:10 +1000 Subject: [PATCH 0782/2194] coverage: Extract `executor::block_on` from several async coverage tests By moving `block_on` to an auxiliary crate, we avoid having to keep a separate copy of it in every async test. (This also incorporates some small tweaks to the headers in `await_ready.rs`.) --- tests/coverage/async.cov-map | 100 ++++++++++---------- tests/coverage/async.coverage | 21 +--- tests/coverage/async.rs | 21 +--- tests/coverage/async2.cov-map | 24 ++--- tests/coverage/async2.coverage | 21 +--- tests/coverage/async2.rs | 21 +--- tests/coverage/async_block.cov-map | 8 +- tests/coverage/async_block.coverage | 21 +--- tests/coverage/async_block.rs | 21 +--- tests/coverage/auxiliary/executor.rs | 19 ++++ tests/coverage/await_ready.cov-map | 16 +--- tests/coverage/await_ready.coverage | 37 +++----- tests/coverage/await_ready.rs | 31 ++---- tests/coverage/closure_macro_async.cov-map | 16 ++-- tests/coverage/closure_macro_async.coverage | 21 +--- tests/coverage/closure_macro_async.rs | 21 +--- 16 files changed, 142 insertions(+), 277 deletions(-) create mode 100644 tests/coverage/auxiliary/executor.rs diff --git a/tests/coverage/async.cov-map b/tests/coverage/async.cov-map index 1ba165f1e4991..43b497a1d3fe9 100644 --- a/tests/coverage/async.cov-map +++ b/tests/coverage/async.cov-map @@ -1,103 +1,103 @@ Function name: async::c -Raw bytes (9): 0x[01, 01, 00, 01, 01, 09, 01, 00, 19] +Raw bytes (9): 0x[01, 01, 00, 01, 01, 0c, 01, 00, 19] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 9, 1) to (start + 0, 25) +- Code(Counter(0)) at (prev + 12, 1) to (start + 0, 25) Function name: async::c::{closure#0} -Raw bytes (26): 0x[01, 01, 01, 01, 05, 04, 01, 09, 19, 01, 0e, 05, 02, 09, 00, 0a, 02, 02, 09, 00, 0a, 01, 02, 01, 00, 02] +Raw bytes (26): 0x[01, 01, 01, 01, 05, 04, 01, 0c, 19, 01, 0e, 05, 02, 09, 00, 0a, 02, 02, 09, 00, 0a, 01, 02, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 1 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) Number of file 0 mappings: 4 -- Code(Counter(0)) at (prev + 9, 25) to (start + 1, 14) +- Code(Counter(0)) at (prev + 12, 25) to (start + 1, 14) - Code(Counter(1)) at (prev + 2, 9) to (start + 0, 10) - Code(Expression(0, Sub)) at (prev + 2, 9) to (start + 0, 10) = (c0 - c1) - Code(Counter(0)) at (prev + 2, 1) to (start + 0, 2) Function name: async::d -Raw bytes (9): 0x[01, 01, 00, 01, 01, 11, 01, 00, 14] +Raw bytes (9): 0x[01, 01, 00, 01, 01, 14, 01, 00, 14] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 17, 1) to (start + 0, 20) +- Code(Counter(0)) at (prev + 20, 1) to (start + 0, 20) Function name: async::d::{closure#0} -Raw bytes (9): 0x[01, 01, 00, 01, 01, 11, 14, 00, 19] +Raw bytes (9): 0x[01, 01, 00, 01, 01, 14, 14, 00, 19] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 17, 20) to (start + 0, 25) +- Code(Counter(0)) at (prev + 20, 20) to (start + 0, 25) Function name: async::e (unused) -Raw bytes (9): 0x[01, 01, 00, 01, 00, 13, 01, 00, 14] +Raw bytes (9): 0x[01, 01, 00, 01, 00, 16, 01, 00, 14] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Zero) at (prev + 19, 1) to (start + 0, 20) +- Code(Zero) at (prev + 22, 1) to (start + 0, 20) Function name: async::e::{closure#0} (unused) -Raw bytes (9): 0x[01, 01, 00, 01, 00, 13, 14, 00, 19] +Raw bytes (9): 0x[01, 01, 00, 01, 00, 16, 14, 00, 19] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Zero) at (prev + 19, 20) to (start + 0, 25) +- Code(Zero) at (prev + 22, 20) to (start + 0, 25) Function name: async::f -Raw bytes (9): 0x[01, 01, 00, 01, 01, 15, 01, 00, 14] +Raw bytes (9): 0x[01, 01, 00, 01, 01, 18, 01, 00, 14] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 21, 1) to (start + 0, 20) +- Code(Counter(0)) at (prev + 24, 1) to (start + 0, 20) Function name: async::f::{closure#0} -Raw bytes (9): 0x[01, 01, 00, 01, 01, 15, 14, 00, 19] +Raw bytes (9): 0x[01, 01, 00, 01, 01, 18, 14, 00, 19] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 21, 20) to (start + 0, 25) +- Code(Counter(0)) at (prev + 24, 20) to (start + 0, 25) Function name: async::foo (unused) -Raw bytes (9): 0x[01, 01, 00, 01, 00, 17, 01, 00, 1e] +Raw bytes (9): 0x[01, 01, 00, 01, 00, 1a, 01, 00, 1e] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Zero) at (prev + 23, 1) to (start + 0, 30) +- Code(Zero) at (prev + 26, 1) to (start + 0, 30) Function name: async::foo::{closure#0} (unused) -Raw bytes (9): 0x[01, 01, 00, 01, 00, 17, 1e, 00, 2d] +Raw bytes (9): 0x[01, 01, 00, 01, 00, 1a, 1e, 00, 2d] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Zero) at (prev + 23, 30) to (start + 0, 45) +- Code(Zero) at (prev + 26, 30) to (start + 0, 45) Function name: async::g -Raw bytes (9): 0x[01, 01, 00, 01, 01, 19, 01, 00, 17] +Raw bytes (9): 0x[01, 01, 00, 01, 01, 1c, 01, 00, 17] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 25, 1) to (start + 0, 23) +- Code(Counter(0)) at (prev + 28, 1) to (start + 0, 23) Function name: async::g::{closure#0} (unused) -Raw bytes (59): 0x[01, 01, 00, 0b, 00, 19, 17, 01, 0c, 00, 02, 09, 00, 0a, 00, 00, 0e, 00, 17, 00, 00, 1b, 00, 1c, 00, 00, 20, 00, 22, 00, 01, 09, 00, 0a, 00, 00, 0e, 00, 17, 00, 00, 1b, 00, 1c, 00, 00, 20, 00, 22, 00, 01, 0e, 00, 10, 00, 02, 01, 00, 02] +Raw bytes (59): 0x[01, 01, 00, 0b, 00, 1c, 17, 01, 0c, 00, 02, 09, 00, 0a, 00, 00, 0e, 00, 17, 00, 00, 1b, 00, 1c, 00, 00, 20, 00, 22, 00, 01, 09, 00, 0a, 00, 00, 0e, 00, 17, 00, 00, 1b, 00, 1c, 00, 00, 20, 00, 22, 00, 01, 0e, 00, 10, 00, 02, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 11 -- Code(Zero) at (prev + 25, 23) to (start + 1, 12) +- Code(Zero) at (prev + 28, 23) to (start + 1, 12) - Code(Zero) at (prev + 2, 9) to (start + 0, 10) - Code(Zero) at (prev + 0, 14) to (start + 0, 23) - Code(Zero) at (prev + 0, 27) to (start + 0, 28) @@ -110,20 +110,20 @@ Number of file 0 mappings: 11 - Code(Zero) at (prev + 2, 1) to (start + 0, 2) Function name: async::h -Raw bytes (9): 0x[01, 01, 00, 01, 01, 21, 01, 00, 16] +Raw bytes (9): 0x[01, 01, 00, 01, 01, 24, 01, 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 + 33, 1) to (start + 0, 22) +- Code(Counter(0)) at (prev + 36, 1) to (start + 0, 22) Function name: async::h::{closure#0} (unused) -Raw bytes (39): 0x[01, 01, 00, 07, 00, 21, 16, 03, 0c, 00, 04, 09, 00, 0a, 00, 00, 0e, 00, 19, 00, 00, 1a, 00, 1b, 00, 00, 20, 00, 22, 00, 01, 0e, 00, 10, 00, 02, 01, 00, 02] +Raw bytes (39): 0x[01, 01, 00, 07, 00, 24, 16, 03, 0c, 00, 04, 09, 00, 0a, 00, 00, 0e, 00, 19, 00, 00, 1a, 00, 1b, 00, 00, 20, 00, 22, 00, 01, 0e, 00, 10, 00, 02, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 7 -- Code(Zero) at (prev + 33, 22) to (start + 3, 12) +- Code(Zero) at (prev + 36, 22) to (start + 3, 12) - Code(Zero) at (prev + 4, 9) to (start + 0, 10) - Code(Zero) at (prev + 0, 14) to (start + 0, 25) - Code(Zero) at (prev + 0, 26) to (start + 0, 27) @@ -132,22 +132,22 @@ Number of file 0 mappings: 7 - Code(Zero) at (prev + 2, 1) to (start + 0, 2) Function name: async::i -Raw bytes (9): 0x[01, 01, 00, 01, 01, 2a, 01, 00, 13] +Raw bytes (9): 0x[01, 01, 00, 01, 01, 2d, 01, 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 + 42, 1) to (start + 0, 19) +- Code(Counter(0)) at (prev + 45, 1) to (start + 0, 19) Function name: async::i::{closure#0} -Raw bytes (63): 0x[01, 01, 02, 07, 19, 11, 15, 0b, 01, 2a, 13, 04, 0c, 09, 05, 09, 00, 0a, 01, 00, 0e, 00, 18, 05, 00, 1c, 00, 21, 09, 00, 27, 00, 30, 15, 01, 09, 00, 0a, 0d, 00, 0e, 00, 17, 1d, 00, 1b, 00, 20, 15, 00, 24, 00, 26, 19, 01, 0e, 00, 10, 03, 02, 01, 00, 02] +Raw bytes (63): 0x[01, 01, 02, 07, 19, 11, 15, 0b, 01, 2d, 13, 04, 0c, 09, 05, 09, 00, 0a, 01, 00, 0e, 00, 18, 05, 00, 1c, 00, 21, 09, 00, 27, 00, 30, 15, 01, 09, 00, 0a, 0d, 00, 0e, 00, 17, 1d, 00, 1b, 00, 20, 15, 00, 24, 00, 26, 19, 01, 0e, 00, 10, 03, 02, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 2 - expression 0 operands: lhs = Expression(1, Add), rhs = Counter(6) - expression 1 operands: lhs = Counter(4), rhs = Counter(5) Number of file 0 mappings: 11 -- Code(Counter(0)) at (prev + 42, 19) to (start + 4, 12) +- Code(Counter(0)) at (prev + 45, 19) to (start + 4, 12) - Code(Counter(2)) at (prev + 5, 9) to (start + 0, 10) - Code(Counter(0)) at (prev + 0, 14) to (start + 0, 24) - Code(Counter(1)) at (prev + 0, 28) to (start + 0, 33) @@ -161,14 +161,14 @@ Number of file 0 mappings: 11 = ((c4 + c5) + c6) Function name: async::j -Raw bytes (58): 0x[01, 01, 02, 07, 0d, 05, 09, 0a, 01, 35, 01, 00, 0d, 01, 0b, 0b, 00, 0c, 05, 01, 09, 00, 0a, 01, 00, 0e, 00, 1b, 05, 00, 1f, 00, 27, 09, 01, 09, 00, 0a, 11, 00, 0e, 00, 1a, 09, 00, 1e, 00, 20, 0d, 01, 0e, 00, 10, 03, 02, 01, 00, 02] +Raw bytes (58): 0x[01, 01, 02, 07, 0d, 05, 09, 0a, 01, 38, 01, 00, 0d, 01, 0b, 0b, 00, 0c, 05, 01, 09, 00, 0a, 01, 00, 0e, 00, 1b, 05, 00, 1f, 00, 27, 09, 01, 09, 00, 0a, 11, 00, 0e, 00, 1a, 09, 00, 1e, 00, 20, 0d, 01, 0e, 00, 10, 03, 02, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 2 - expression 0 operands: lhs = Expression(1, Add), rhs = Counter(3) - expression 1 operands: lhs = Counter(1), rhs = Counter(2) Number of file 0 mappings: 10 -- Code(Counter(0)) at (prev + 53, 1) to (start + 0, 13) +- Code(Counter(0)) at (prev + 56, 1) to (start + 0, 13) - Code(Counter(0)) at (prev + 11, 11) to (start + 0, 12) - Code(Counter(1)) at (prev + 1, 9) to (start + 0, 10) - Code(Counter(0)) at (prev + 0, 14) to (start + 0, 27) @@ -181,48 +181,48 @@ Number of file 0 mappings: 10 = ((c1 + c2) + c3) Function name: async::j::c -Raw bytes (26): 0x[01, 01, 01, 01, 05, 04, 01, 37, 05, 01, 12, 05, 02, 0d, 00, 0e, 02, 02, 0d, 00, 0e, 01, 02, 05, 00, 06] +Raw bytes (26): 0x[01, 01, 01, 01, 05, 04, 01, 3a, 05, 01, 12, 05, 02, 0d, 00, 0e, 02, 02, 0d, 00, 0e, 01, 02, 05, 00, 06] Number of files: 1 - file 0 => global file 1 Number of expressions: 1 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) Number of file 0 mappings: 4 -- Code(Counter(0)) at (prev + 55, 5) to (start + 1, 18) +- Code(Counter(0)) at (prev + 58, 5) to (start + 1, 18) - Code(Counter(1)) at (prev + 2, 13) to (start + 0, 14) - Code(Expression(0, Sub)) at (prev + 2, 13) to (start + 0, 14) = (c0 - c1) - Code(Counter(0)) at (prev + 2, 5) to (start + 0, 6) Function name: async::j::d -Raw bytes (9): 0x[01, 01, 00, 01, 01, 3e, 05, 00, 17] +Raw bytes (9): 0x[01, 01, 00, 01, 01, 41, 05, 00, 17] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 62, 5) to (start + 0, 23) +- Code(Counter(0)) at (prev + 65, 5) to (start + 0, 23) Function name: async::j::f -Raw bytes (9): 0x[01, 01, 00, 01, 01, 3f, 05, 00, 17] +Raw bytes (9): 0x[01, 01, 00, 01, 01, 42, 05, 00, 17] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 63, 5) to (start + 0, 23) +- Code(Counter(0)) at (prev + 66, 5) to (start + 0, 23) Function name: async::k (unused) -Raw bytes (29): 0x[01, 01, 00, 05, 00, 47, 01, 01, 0c, 00, 02, 0e, 00, 10, 00, 01, 0e, 00, 10, 00, 01, 0e, 00, 10, 00, 02, 01, 00, 02] +Raw bytes (29): 0x[01, 01, 00, 05, 00, 4a, 01, 01, 0c, 00, 02, 0e, 00, 10, 00, 01, 0e, 00, 10, 00, 01, 0e, 00, 10, 00, 02, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 5 -- Code(Zero) at (prev + 71, 1) to (start + 1, 12) +- Code(Zero) at (prev + 74, 1) to (start + 1, 12) - Code(Zero) at (prev + 2, 14) to (start + 0, 16) - Code(Zero) at (prev + 1, 14) to (start + 0, 16) - Code(Zero) at (prev + 1, 14) to (start + 0, 16) - Code(Zero) at (prev + 2, 1) to (start + 0, 2) Function name: async::l -Raw bytes (37): 0x[01, 01, 04, 01, 07, 05, 09, 0f, 02, 09, 05, 05, 01, 4f, 01, 01, 0c, 02, 02, 0e, 00, 10, 05, 01, 0e, 00, 10, 09, 01, 0e, 00, 10, 0b, 02, 01, 00, 02] +Raw bytes (37): 0x[01, 01, 04, 01, 07, 05, 09, 0f, 02, 09, 05, 05, 01, 52, 01, 01, 0c, 02, 02, 0e, 00, 10, 05, 01, 0e, 00, 10, 09, 01, 0e, 00, 10, 0b, 02, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 4 @@ -231,7 +231,7 @@ Number of expressions: 4 - expression 2 operands: lhs = Expression(3, Add), rhs = Expression(0, Sub) - expression 3 operands: lhs = Counter(2), rhs = Counter(1) Number of file 0 mappings: 5 -- Code(Counter(0)) at (prev + 79, 1) to (start + 1, 12) +- Code(Counter(0)) at (prev + 82, 1) to (start + 1, 12) - Code(Expression(0, Sub)) at (prev + 2, 14) to (start + 0, 16) = (c0 - (c1 + c2)) - Code(Counter(1)) at (prev + 1, 14) to (start + 0, 16) @@ -240,26 +240,26 @@ Number of file 0 mappings: 5 = ((c2 + c1) + (c0 - (c1 + c2))) Function name: async::m -Raw bytes (9): 0x[01, 01, 00, 01, 01, 57, 01, 00, 19] +Raw bytes (9): 0x[01, 01, 00, 01, 01, 5a, 01, 00, 19] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 87, 1) to (start + 0, 25) +- Code(Counter(0)) at (prev + 90, 1) to (start + 0, 25) Function name: async::m::{closure#0} (unused) -Raw bytes (9): 0x[01, 01, 00, 01, 00, 57, 19, 00, 22] +Raw bytes (9): 0x[01, 01, 00, 01, 00, 5a, 19, 00, 22] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Zero) at (prev + 87, 25) to (start + 0, 34) +- Code(Zero) at (prev + 90, 25) to (start + 0, 34) Function name: async::main -Raw bytes (9): 0x[01, 01, 00, 01, 01, 59, 01, 08, 02] +Raw bytes (9): 0x[01, 01, 00, 01, 01, 5c, 01, 08, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 89, 1) to (start + 8, 2) +- Code(Counter(0)) at (prev + 92, 1) to (start + 8, 2) diff --git a/tests/coverage/async.coverage b/tests/coverage/async.coverage index 995674257c4af..429fb112f3383 100644 --- a/tests/coverage/async.coverage +++ b/tests/coverage/async.coverage @@ -6,6 +6,9 @@ LL| |//@ edition: 2018 LL| |//@ compile-flags: -Copt-level=1 LL| | + LL| |//@ aux-build: executor.rs + LL| |extern crate executor; + LL| | LL| 1|async fn c(x: u8) -> u8 { LL| 1| if x == 8 { LL| 1| 1 @@ -100,22 +103,4 @@ LL| 1| let _ = m(5); LL| 1| executor::block_on(future.as_mut()); LL| 1|} - LL| | - LL| |mod executor { - LL| | use core::future::Future; - LL| | use core::pin::pin; - LL| | use core::task::{Context, Poll, Waker}; - LL| | - LL| | #[coverage(off)] - LL| | pub fn block_on(mut future: F) -> F::Output { - LL| | let mut future = pin!(future); - LL| | let mut context = Context::from_waker(Waker::noop()); - LL| | - LL| | loop { - LL| | if let Poll::Ready(val) = future.as_mut().poll(&mut context) { - LL| | break val; - LL| | } - LL| | } - LL| | } - LL| |} diff --git a/tests/coverage/async.rs b/tests/coverage/async.rs index 7e6ad761ecd34..a7f3c7cec4191 100644 --- a/tests/coverage/async.rs +++ b/tests/coverage/async.rs @@ -6,6 +6,9 @@ //@ edition: 2018 //@ compile-flags: -Copt-level=1 +//@ aux-build: executor.rs +extern crate executor; + async fn c(x: u8) -> u8 { if x == 8 { 1 @@ -95,21 +98,3 @@ fn main() { let _ = m(5); executor::block_on(future.as_mut()); } - -mod executor { - use core::future::Future; - use core::pin::pin; - use core::task::{Context, Poll, Waker}; - - #[coverage(off)] - pub fn block_on(mut future: F) -> F::Output { - let mut future = pin!(future); - let mut context = Context::from_waker(Waker::noop()); - - loop { - if let Poll::Ready(val) = future.as_mut().poll(&mut context) { - break val; - } - } - } -} diff --git a/tests/coverage/async2.cov-map b/tests/coverage/async2.cov-map index e39a1d7dd2f92..3816401ac6346 100644 --- a/tests/coverage/async2.cov-map +++ b/tests/coverage/async2.cov-map @@ -1,53 +1,53 @@ Function name: async2::async_func -Raw bytes (9): 0x[01, 01, 00, 01, 01, 0d, 01, 00, 17] +Raw bytes (9): 0x[01, 01, 00, 01, 01, 10, 01, 00, 17] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 13, 1) to (start + 0, 23) +- Code(Counter(0)) at (prev + 16, 1) to (start + 0, 23) Function name: async2::async_func::{closure#0} -Raw bytes (24): 0x[01, 01, 00, 04, 01, 0d, 17, 03, 09, 05, 03, 0a, 02, 06, 00, 02, 06, 00, 07, 01, 01, 01, 00, 02] +Raw bytes (24): 0x[01, 01, 00, 04, 01, 10, 17, 03, 09, 05, 03, 0a, 02, 06, 00, 02, 06, 00, 07, 01, 01, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 4 -- Code(Counter(0)) at (prev + 13, 23) to (start + 3, 9) +- Code(Counter(0)) at (prev + 16, 23) to (start + 3, 9) - Code(Counter(1)) at (prev + 3, 10) to (start + 2, 6) - Code(Zero) at (prev + 2, 6) to (start + 0, 7) - Code(Counter(0)) at (prev + 1, 1) to (start + 0, 2) Function name: async2::async_func_just_println -Raw bytes (9): 0x[01, 01, 00, 01, 01, 15, 01, 00, 24] +Raw bytes (9): 0x[01, 01, 00, 01, 01, 18, 01, 00, 24] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 21, 1) to (start + 0, 36) +- Code(Counter(0)) at (prev + 24, 1) to (start + 0, 36) Function name: async2::async_func_just_println::{closure#0} -Raw bytes (9): 0x[01, 01, 00, 01, 01, 15, 24, 02, 02] +Raw bytes (9): 0x[01, 01, 00, 01, 01, 18, 24, 02, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 21, 36) to (start + 2, 2) +- Code(Counter(0)) at (prev + 24, 36) to (start + 2, 2) Function name: async2::main -Raw bytes (9): 0x[01, 01, 00, 01, 01, 19, 01, 07, 02] +Raw bytes (9): 0x[01, 01, 00, 01, 01, 1c, 01, 07, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 25, 1) to (start + 7, 2) +- Code(Counter(0)) at (prev + 28, 1) to (start + 7, 2) Function name: async2::non_async_func -Raw bytes (24): 0x[01, 01, 00, 04, 01, 05, 01, 03, 09, 05, 03, 0a, 02, 06, 00, 02, 06, 00, 07, 01, 01, 01, 00, 02] +Raw bytes (24): 0x[01, 01, 00, 04, 01, 08, 01, 03, 09, 05, 03, 0a, 02, 06, 00, 02, 06, 00, 07, 01, 01, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 4 -- Code(Counter(0)) at (prev + 5, 1) to (start + 3, 9) +- Code(Counter(0)) at (prev + 8, 1) to (start + 3, 9) - Code(Counter(1)) at (prev + 3, 10) to (start + 2, 6) - Code(Zero) at (prev + 2, 6) to (start + 0, 7) - Code(Counter(0)) at (prev + 1, 1) to (start + 0, 2) diff --git a/tests/coverage/async2.coverage b/tests/coverage/async2.coverage index bd5b701491b5f..ed9bc4c239d98 100644 --- a/tests/coverage/async2.coverage +++ b/tests/coverage/async2.coverage @@ -2,6 +2,9 @@ LL| |#![feature(noop_waker)] LL| |//@ edition: 2018 LL| | + LL| |//@ aux-build: executor.rs + LL| |extern crate executor; + LL| | LL| 1|fn non_async_func() { LL| 1| println!("non_async_func was covered"); LL| 1| let b = true; @@ -32,22 +35,4 @@ LL| 1| executor::block_on(async_func()); LL| 1| executor::block_on(async_func_just_println()); LL| 1|} - LL| | - LL| |mod executor { - LL| | use core::future::Future; - LL| | use core::pin::pin; - LL| | use core::task::{Context, Poll, Waker}; - LL| | - LL| | #[coverage(off)] - LL| | pub fn block_on(mut future: F) -> F::Output { - LL| | let mut future = pin!(future); - LL| | let mut context = Context::from_waker(Waker::noop()); - LL| | - LL| | loop { - LL| | if let Poll::Ready(val) = future.as_mut().poll(&mut context) { - LL| | break val; - LL| | } - LL| | } - LL| | } - LL| |} diff --git a/tests/coverage/async2.rs b/tests/coverage/async2.rs index 713c70d277a76..f52c848f6f241 100644 --- a/tests/coverage/async2.rs +++ b/tests/coverage/async2.rs @@ -2,6 +2,9 @@ #![feature(noop_waker)] //@ edition: 2018 +//@ aux-build: executor.rs +extern crate executor; + fn non_async_func() { println!("non_async_func was covered"); let b = true; @@ -30,21 +33,3 @@ fn main() { executor::block_on(async_func()); executor::block_on(async_func_just_println()); } - -mod executor { - use core::future::Future; - use core::pin::pin; - use core::task::{Context, Poll, Waker}; - - #[coverage(off)] - pub fn block_on(mut future: F) -> F::Output { - let mut future = pin!(future); - let mut context = Context::from_waker(Waker::noop()); - - loop { - if let Poll::Ready(val) = future.as_mut().poll(&mut context) { - break val; - } - } - } -} diff --git a/tests/coverage/async_block.cov-map b/tests/coverage/async_block.cov-map index e54c15c04362b..65f3d821f6e46 100644 --- a/tests/coverage/async_block.cov-map +++ b/tests/coverage/async_block.cov-map @@ -1,11 +1,11 @@ Function name: async_block::main -Raw bytes (36): 0x[01, 01, 01, 01, 05, 06, 01, 05, 01, 00, 0b, 05, 01, 09, 00, 0a, 03, 00, 0e, 00, 13, 05, 00, 14, 01, 16, 05, 07, 0a, 02, 06, 01, 03, 01, 00, 02] +Raw bytes (36): 0x[01, 01, 01, 01, 05, 06, 01, 08, 01, 00, 0b, 05, 01, 09, 00, 0a, 03, 00, 0e, 00, 13, 05, 00, 14, 01, 16, 05, 07, 0a, 02, 06, 01, 03, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 1 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) Number of file 0 mappings: 6 -- Code(Counter(0)) at (prev + 5, 1) to (start + 0, 11) +- Code(Counter(0)) at (prev + 8, 1) to (start + 0, 11) - Code(Counter(1)) at (prev + 1, 9) to (start + 0, 10) - Code(Expression(0, Add)) at (prev + 0, 14) to (start + 0, 19) = (c0 + c1) @@ -14,13 +14,13 @@ Number of file 0 mappings: 6 - Code(Counter(0)) at (prev + 3, 1) to (start + 0, 2) Function name: async_block::main::{closure#0} -Raw bytes (26): 0x[01, 01, 01, 01, 05, 04, 01, 07, 1c, 01, 17, 05, 01, 18, 02, 0e, 02, 02, 14, 02, 0e, 01, 03, 09, 00, 0a] +Raw bytes (26): 0x[01, 01, 01, 01, 05, 04, 01, 0a, 1c, 01, 17, 05, 01, 18, 02, 0e, 02, 02, 14, 02, 0e, 01, 03, 09, 00, 0a] Number of files: 1 - file 0 => global file 1 Number of expressions: 1 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) Number of file 0 mappings: 4 -- Code(Counter(0)) at (prev + 7, 28) to (start + 1, 23) +- Code(Counter(0)) at (prev + 10, 28) to (start + 1, 23) - Code(Counter(1)) at (prev + 1, 24) to (start + 2, 14) - Code(Expression(0, Sub)) at (prev + 2, 20) to (start + 2, 14) = (c0 - c1) diff --git a/tests/coverage/async_block.coverage b/tests/coverage/async_block.coverage index 7fd17bc51c3e2..d9be8480d801d 100644 --- a/tests/coverage/async_block.coverage +++ b/tests/coverage/async_block.coverage @@ -2,6 +2,9 @@ LL| |#![feature(noop_waker)] LL| |//@ edition: 2021 LL| | + LL| |//@ aux-build: executor.rs + LL| |extern crate executor; + LL| | LL| 1|fn main() { LL| 17| for i in 0..16 { ^16 @@ -15,22 +18,4 @@ LL| 16| executor::block_on(future); LL| 16| } LL| 1|} - LL| | - LL| |mod executor { - LL| | use core::future::Future; - LL| | use core::pin::pin; - LL| | use core::task::{Context, Poll, Waker}; - LL| | - LL| | #[coverage(off)] - LL| | pub fn block_on(mut future: F) -> F::Output { - LL| | let mut future = pin!(future); - LL| | let mut context = Context::from_waker(Waker::noop()); - LL| | - LL| | loop { - LL| | if let Poll::Ready(val) = future.as_mut().poll(&mut context) { - LL| | break val; - LL| | } - LL| | } - LL| | } - LL| |} diff --git a/tests/coverage/async_block.rs b/tests/coverage/async_block.rs index a70dd74703270..7ae8241aa7712 100644 --- a/tests/coverage/async_block.rs +++ b/tests/coverage/async_block.rs @@ -2,6 +2,9 @@ #![feature(noop_waker)] //@ edition: 2021 +//@ aux-build: executor.rs +extern crate executor; + fn main() { for i in 0..16 { let future = async { @@ -14,21 +17,3 @@ fn main() { executor::block_on(future); } } - -mod executor { - use core::future::Future; - use core::pin::pin; - use core::task::{Context, Poll, Waker}; - - #[coverage(off)] - pub fn block_on(mut future: F) -> F::Output { - let mut future = pin!(future); - let mut context = Context::from_waker(Waker::noop()); - - loop { - if let Poll::Ready(val) = future.as_mut().poll(&mut context) { - break val; - } - } - } -} diff --git a/tests/coverage/auxiliary/executor.rs b/tests/coverage/auxiliary/executor.rs new file mode 100644 index 0000000000000..fb07c8ce304b8 --- /dev/null +++ b/tests/coverage/auxiliary/executor.rs @@ -0,0 +1,19 @@ +#![feature(coverage_attribute, noop_waker)] +//@ edition: 2021 + +use core::future::Future; +use core::pin::pin; +use core::task::{Context, Poll, Waker}; + +/// Dummy "executor" that just repeatedly polls a future until it's ready. +#[coverage(off)] +pub fn block_on(mut future: F) -> F::Output { + let mut future = pin!(future); + let mut context = Context::from_waker(Waker::noop()); + + loop { + if let Poll::Ready(val) = future.as_mut().poll(&mut context) { + break val; + } + } +} diff --git a/tests/coverage/await_ready.cov-map b/tests/coverage/await_ready.cov-map index 0c9f2ae29a8cf..38c2cf7b2d36c 100644 --- a/tests/coverage/await_ready.cov-map +++ b/tests/coverage/await_ready.cov-map @@ -1,25 +1,17 @@ Function name: await_ready::await_ready -Raw bytes (9): 0x[01, 01, 00, 01, 01, 0a, 01, 00, 1e] +Raw bytes (9): 0x[01, 01, 00, 01, 01, 0f, 01, 00, 1e] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 10, 1) to (start + 0, 30) +- Code(Counter(0)) at (prev + 15, 1) to (start + 0, 30) Function name: await_ready::await_ready::{closure#0} -Raw bytes (14): 0x[01, 01, 00, 02, 01, 0a, 1e, 03, 0f, 05, 04, 01, 00, 02] +Raw bytes (14): 0x[01, 01, 00, 02, 01, 0f, 1e, 03, 0f, 05, 04, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 2 -- Code(Counter(0)) at (prev + 10, 30) to (start + 3, 15) +- Code(Counter(0)) at (prev + 15, 30) to (start + 3, 15) - Code(Counter(1)) at (prev + 4, 1) to (start + 0, 2) -Function name: await_ready::main -Raw bytes (9): 0x[01, 01, 00, 01, 01, 10, 01, 03, 02] -Number of files: 1 -- file 0 => global file 1 -Number of expressions: 0 -Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 16, 1) to (start + 3, 2) - diff --git a/tests/coverage/await_ready.coverage b/tests/coverage/await_ready.coverage index 0075f09426e05..7ab03e6d3de0a 100644 --- a/tests/coverage/await_ready.coverage +++ b/tests/coverage/await_ready.coverage @@ -1,38 +1,25 @@ LL| |#![feature(coverage_attribute)] - LL| |#![feature(custom_inner_attributes)] // for #![rustfmt::skip] LL| |#![feature(noop_waker)] - LL| |#![rustfmt::skip] + LL| |#![coverage(off)] LL| |//@ edition: 2021 LL| | - LL| |#[coverage(off)] - LL| |async fn ready() -> u8 { 1 } + LL| |//@ aux-build: executor.rs + LL| |extern crate executor; LL| | + LL| |async fn ready() -> u8 { + LL| | 1 + LL| |} + LL| | + LL| |#[coverage(on)] + LL| |#[rustfmt::skip] LL| 1|async fn await_ready() -> u8 { LL| 1| // await should be covered even if the function never yields LL| 1| ready() LL| 1| .await LL| 1|} LL| | - LL| 1|fn main() { - LL| 1| let mut future = Box::pin(await_ready()); - LL| 1| executor::block_on(future.as_mut()); - LL| 1|} - LL| | - LL| |mod executor { - LL| | use core::future::Future; - LL| | use core::pin::pin; - LL| | use core::task::{Context, Poll, Waker}; - LL| | - LL| | #[coverage(off)] - LL| | pub fn block_on(mut future: F) -> F::Output { - LL| | let mut future = pin!(future); - LL| | let mut context = Context::from_waker(Waker::noop()); - LL| | - LL| | loop { - LL| | if let Poll::Ready(val) = future.as_mut().poll(&mut context) { - LL| | break val; - LL| | } - LL| | } - LL| | } + LL| |fn main() { + LL| | let mut future = Box::pin(await_ready()); + LL| | executor::block_on(future.as_mut()); LL| |} diff --git a/tests/coverage/await_ready.rs b/tests/coverage/await_ready.rs index 9212a4ba705a8..27ee99d39890e 100644 --- a/tests/coverage/await_ready.rs +++ b/tests/coverage/await_ready.rs @@ -1,12 +1,17 @@ #![feature(coverage_attribute)] -#![feature(custom_inner_attributes)] // for #![rustfmt::skip] #![feature(noop_waker)] -#![rustfmt::skip] +#![coverage(off)] //@ edition: 2021 -#[coverage(off)] -async fn ready() -> u8 { 1 } +//@ aux-build: executor.rs +extern crate executor; +async fn ready() -> u8 { + 1 +} + +#[coverage(on)] +#[rustfmt::skip] async fn await_ready() -> u8 { // await should be covered even if the function never yields ready() @@ -17,21 +22,3 @@ fn main() { let mut future = Box::pin(await_ready()); executor::block_on(future.as_mut()); } - -mod executor { - use core::future::Future; - use core::pin::pin; - use core::task::{Context, Poll, Waker}; - - #[coverage(off)] - pub fn block_on(mut future: F) -> F::Output { - let mut future = pin!(future); - let mut context = Context::from_waker(Waker::noop()); - - loop { - if let Poll::Ready(val) = future.as_mut().poll(&mut context) { - break val; - } - } - } -} diff --git a/tests/coverage/closure_macro_async.cov-map b/tests/coverage/closure_macro_async.cov-map index 1286d663bd4de..4d0597f58bf1d 100644 --- a/tests/coverage/closure_macro_async.cov-map +++ b/tests/coverage/closure_macro_async.cov-map @@ -1,27 +1,27 @@ Function name: closure_macro_async::load_configuration_files -Raw bytes (9): 0x[01, 01, 00, 01, 01, 1f, 01, 02, 02] +Raw bytes (9): 0x[01, 01, 00, 01, 01, 22, 01, 02, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 31, 1) to (start + 2, 2) +- Code(Counter(0)) at (prev + 34, 1) to (start + 2, 2) Function name: closure_macro_async::test -Raw bytes (9): 0x[01, 01, 00, 01, 01, 23, 01, 00, 2b] +Raw bytes (9): 0x[01, 01, 00, 01, 01, 26, 01, 00, 2b] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 35, 1) to (start + 0, 43) +- Code(Counter(0)) at (prev + 38, 1) to (start + 0, 43) Function name: closure_macro_async::test::{closure#0} -Raw bytes (36): 0x[01, 01, 01, 01, 05, 06, 01, 23, 2b, 01, 21, 02, 02, 09, 00, 0f, 01, 00, 12, 00, 54, 05, 00, 54, 00, 55, 02, 02, 09, 02, 0b, 01, 03, 01, 00, 02] +Raw bytes (36): 0x[01, 01, 01, 01, 05, 06, 01, 26, 2b, 01, 21, 02, 02, 09, 00, 0f, 01, 00, 12, 00, 54, 05, 00, 54, 00, 55, 02, 02, 09, 02, 0b, 01, 03, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 1 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) Number of file 0 mappings: 6 -- Code(Counter(0)) at (prev + 35, 43) to (start + 1, 33) +- Code(Counter(0)) at (prev + 38, 43) to (start + 1, 33) - Code(Expression(0, Sub)) at (prev + 2, 9) to (start + 0, 15) = (c0 - c1) - Code(Counter(0)) at (prev + 0, 18) to (start + 0, 84) @@ -31,7 +31,7 @@ Number of file 0 mappings: 6 - Code(Counter(0)) at (prev + 3, 1) to (start + 0, 2) Function name: closure_macro_async::test::{closure#0}::{closure#0} -Raw bytes (35): 0x[01, 01, 03, 01, 05, 05, 0b, 09, 00, 05, 01, 12, 1c, 03, 21, 05, 04, 11, 01, 27, 02, 03, 11, 00, 16, 00, 00, 17, 00, 1e, 07, 02, 09, 00, 0a] +Raw bytes (35): 0x[01, 01, 03, 01, 05, 05, 0b, 09, 00, 05, 01, 15, 1c, 03, 21, 05, 04, 11, 01, 27, 02, 03, 11, 00, 16, 00, 00, 17, 00, 1e, 07, 02, 09, 00, 0a] Number of files: 1 - file 0 => global file 1 Number of expressions: 3 @@ -39,7 +39,7 @@ Number of expressions: 3 - expression 1 operands: lhs = Counter(1), rhs = Expression(2, Add) - expression 2 operands: lhs = Counter(2), rhs = Zero Number of file 0 mappings: 5 -- Code(Counter(0)) at (prev + 18, 28) to (start + 3, 33) +- Code(Counter(0)) at (prev + 21, 28) to (start + 3, 33) - Code(Counter(1)) at (prev + 4, 17) to (start + 1, 39) - Code(Expression(0, Sub)) at (prev + 3, 17) to (start + 0, 22) = (c0 - c1) diff --git a/tests/coverage/closure_macro_async.coverage b/tests/coverage/closure_macro_async.coverage index 0557ce47d6873..a8c72efac6664 100644 --- a/tests/coverage/closure_macro_async.coverage +++ b/tests/coverage/closure_macro_async.coverage @@ -2,6 +2,9 @@ LL| |#![feature(noop_waker)] LL| |//@ edition: 2018 LL| | + LL| |//@ aux-build: executor.rs + LL| |extern crate executor; + LL| | LL| |macro_rules! bail { LL| | ($msg:literal $(,)?) => { LL| | if $msg.len() > 0 { @@ -46,22 +49,4 @@ LL| |fn main() { LL| | executor::block_on(test()).unwrap(); LL| |} - LL| | - LL| |mod executor { - LL| | use core::future::Future; - LL| | use core::pin::pin; - LL| | use core::task::{Context, Poll, Waker}; - LL| | - LL| | #[coverage(off)] - LL| | pub fn block_on(mut future: F) -> F::Output { - LL| | let mut future = pin!(future); - LL| | let mut context = Context::from_waker(Waker::noop()); - LL| | - LL| | loop { - LL| | if let Poll::Ready(val) = future.as_mut().poll(&mut context) { - LL| | break val; - LL| | } - LL| | } - LL| | } - LL| |} diff --git a/tests/coverage/closure_macro_async.rs b/tests/coverage/closure_macro_async.rs index 735214629b6f2..defd1b6d632c8 100644 --- a/tests/coverage/closure_macro_async.rs +++ b/tests/coverage/closure_macro_async.rs @@ -2,6 +2,9 @@ #![feature(noop_waker)] //@ edition: 2018 +//@ aux-build: executor.rs +extern crate executor; + macro_rules! bail { ($msg:literal $(,)?) => { if $msg.len() > 0 { @@ -45,21 +48,3 @@ pub async fn test() -> Result<(), String> { fn main() { executor::block_on(test()).unwrap(); } - -mod executor { - use core::future::Future; - use core::pin::pin; - use core::task::{Context, Poll, Waker}; - - #[coverage(off)] - pub fn block_on(mut future: F) -> F::Output { - let mut future = pin!(future); - let mut context = Context::from_waker(Waker::noop()); - - loop { - if let Poll::Ready(val) = future.as_mut().poll(&mut context) { - break val; - } - } - } -} From 0d12c5809f10fa6dea73af038677949a9b0286b1 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 10 Sep 2024 09:57:58 +0200 Subject: [PATCH 0783/2194] Preparing for merge from rustc --- src/tools/miri/rust-version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/miri/rust-version b/src/tools/miri/rust-version index 3fdad2a91e9fc..48cc89b109d73 100644 --- a/src/tools/miri/rust-version +++ b/src/tools/miri/rust-version @@ -1 +1 @@ -54fdef7799d9ff9470bb5cabd29fde9471a99eaa +304b7f801bab31233680879ca4fb6eb294706a59 From 6e70bd4d07deb838af1471258742cf1564bce632 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 10 Sep 2024 10:04:09 +0200 Subject: [PATCH 0784/2194] fmt --- .../provenance/int_copy_looses_provenance3.rs | 2 +- .../miri/tests/fail/uninit/padding-enum.rs | 29 ++++++++++--------- .../tests/fail/uninit/padding-enum.stderr | 4 +-- .../miri/tests/fail/uninit/padding-struct.rs | 15 ++++++---- .../tests/fail/uninit/padding-struct.stderr | 4 +-- .../miri/tests/fail/uninit/padding-union.rs | 15 ++++++---- .../tests/fail/uninit/padding-union.stderr | 4 +-- .../tests/fail/uninit/padding-wide-ptr.rs | 27 +++++++++-------- .../tests/fail/uninit/padding-wide-ptr.stderr | 4 +-- src/tools/miri/tests/pass/arrays.rs | 4 ++- .../miri/tests/pass/async-niche-aliasing.rs | 2 +- 11 files changed, 62 insertions(+), 48 deletions(-) diff --git a/src/tools/miri/tests/fail/provenance/int_copy_looses_provenance3.rs b/src/tools/miri/tests/fail/provenance/int_copy_looses_provenance3.rs index 48a48ce4587ee..d6bbfd7d94c76 100644 --- a/src/tools/miri/tests/fail/provenance/int_copy_looses_provenance3.rs +++ b/src/tools/miri/tests/fail/provenance/int_copy_looses_provenance3.rs @@ -11,7 +11,7 @@ enum E { // Doing a copy at integer type should lose provenance. // This tests the case where provenacne is hiding in the discriminant of an enum. fn main() { - assert_eq!(mem::size_of::(), 2*mem::size_of::()); + assert_eq!(mem::size_of::(), 2 * mem::size_of::()); // We want to store provenance in the enum discriminant, but the value still needs to // be valid atfor the type. So we split provenance and data. diff --git a/src/tools/miri/tests/fail/uninit/padding-enum.rs b/src/tools/miri/tests/fail/uninit/padding-enum.rs index 3852ac5c477d5..a9628799b7d30 100644 --- a/src/tools/miri/tests/fail/uninit/padding-enum.rs +++ b/src/tools/miri/tests/fail/uninit/padding-enum.rs @@ -7,17 +7,20 @@ enum E { Some(&'static (), &'static (), usize), } -fn main() { unsafe { - let mut p: mem::MaybeUninit = mem::MaybeUninit::zeroed(); - // The copy when `E` is returned from `transmute` should destroy padding - // (even when we use `write_unaligned`, which under the hood uses an untyped copy). - p.as_mut_ptr().write_unaligned(mem::transmute((0usize, 0usize, 0usize))); - // This is a `None`, so everything but the discriminant is padding. - assert!(matches!(*p.as_ptr(), E::None)); +fn main() { + unsafe { + let mut p: mem::MaybeUninit = mem::MaybeUninit::zeroed(); + // The copy when `E` is returned from `transmute` should destroy padding + // (even when we use `write_unaligned`, which under the hood uses an untyped copy). + p.as_mut_ptr().write_unaligned(mem::transmute((0usize, 0usize, 0usize))); + // This is a `None`, so everything but the discriminant is padding. + assert!(matches!(*p.as_ptr(), E::None)); - // Turns out the discriminant is (currently) stored - // in the 2nd pointer, so the first half is padding. - let c = &p as *const _ as *const u8; - let _val = *c.add(0); // Get a padding byte. - //~^ERROR: uninitialized -} } + // Turns out the discriminant is (currently) stored + // in the 2nd pointer, so the first half is padding. + let c = &p as *const _ as *const u8; + // Read a padding byte. + let _val = *c.add(0); + //~^ERROR: uninitialized + } +} diff --git a/src/tools/miri/tests/fail/uninit/padding-enum.stderr b/src/tools/miri/tests/fail/uninit/padding-enum.stderr index c571f18874076..312cf6d20fadd 100644 --- a/src/tools/miri/tests/fail/uninit/padding-enum.stderr +++ b/src/tools/miri/tests/fail/uninit/padding-enum.stderr @@ -1,8 +1,8 @@ error: Undefined Behavior: using uninitialized data, but this operation requires initialized memory --> $DIR/padding-enum.rs:LL:CC | -LL | let _val = *c.add(0); // Get a padding byte. - | ^^^^^^^^^ using uninitialized data, but this operation requires initialized memory +LL | let _val = *c.add(0); + | ^^^^^^^^^ using uninitialized data, but this operation requires initialized memory | = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information diff --git a/src/tools/miri/tests/fail/uninit/padding-struct.rs b/src/tools/miri/tests/fail/uninit/padding-struct.rs index dd3be50343902..4cdc6f3a10450 100644 --- a/src/tools/miri/tests/fail/uninit/padding-struct.rs +++ b/src/tools/miri/tests/fail/uninit/padding-struct.rs @@ -3,9 +3,12 @@ use std::mem; #[repr(C)] struct Pair(u8, u16); -fn main() { unsafe { - let p: Pair = mem::transmute(0u32); // The copy when `Pair` is returned from `transmute` should destroy padding. - let c = &p as *const _ as *const u8; - let _val = *c.add(1); // Get the padding byte. - //~^ERROR: uninitialized -} } +fn main() { + unsafe { + let p: Pair = mem::transmute(0u32); // The copy when `Pair` is returned from `transmute` should destroy padding. + let c = &p as *const _ as *const u8; + // Read the padding byte. + let _val = *c.add(1); + //~^ERROR: uninitialized + } +} diff --git a/src/tools/miri/tests/fail/uninit/padding-struct.stderr b/src/tools/miri/tests/fail/uninit/padding-struct.stderr index 8dc40a482ac52..19e3969279bde 100644 --- a/src/tools/miri/tests/fail/uninit/padding-struct.stderr +++ b/src/tools/miri/tests/fail/uninit/padding-struct.stderr @@ -1,8 +1,8 @@ error: Undefined Behavior: using uninitialized data, but this operation requires initialized memory --> $DIR/padding-struct.rs:LL:CC | -LL | let _val = *c.add(1); // Get the padding byte. - | ^^^^^^^^^ using uninitialized data, but this operation requires initialized memory +LL | let _val = *c.add(1); + | ^^^^^^^^^ using uninitialized data, but this operation requires initialized memory | = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information diff --git a/src/tools/miri/tests/fail/uninit/padding-union.rs b/src/tools/miri/tests/fail/uninit/padding-union.rs index 2e9e0a40d6c68..294578607b37d 100644 --- a/src/tools/miri/tests/fail/uninit/padding-union.rs +++ b/src/tools/miri/tests/fail/uninit/padding-union.rs @@ -6,9 +6,12 @@ union U { field: (u8, u16), } -fn main() { unsafe { - let p: U = mem::transmute(0u32); // The copy when `U` is returned from `transmute` should destroy padding. - let c = &p as *const _ as *const [u8; 4]; - let _val = *c; // Read the entire thing, definitely contains the padding byte. - //~^ERROR: uninitialized -} } +fn main() { + unsafe { + let p: U = mem::transmute(0u32); // The copy when `U` is returned from `transmute` should destroy padding. + let c = &p as *const _ as *const [u8; 4]; + // Read the entire thing, definitely contains the padding byte. + let _val = *c; + //~^ERROR: uninitialized + } +} diff --git a/src/tools/miri/tests/fail/uninit/padding-union.stderr b/src/tools/miri/tests/fail/uninit/padding-union.stderr index 04002da4f195c..61a8d1c6ba642 100644 --- a/src/tools/miri/tests/fail/uninit/padding-union.stderr +++ b/src/tools/miri/tests/fail/uninit/padding-union.stderr @@ -1,8 +1,8 @@ error: Undefined Behavior: constructing invalid value at [1]: encountered uninitialized memory, but expected an integer --> $DIR/padding-union.rs:LL:CC | -LL | let _val = *c; // Read the entire thing, definitely contains the padding byte. - | ^^ constructing invalid value at [1]: encountered uninitialized memory, but expected an integer +LL | let _val = *c; + | ^^ constructing invalid value at [1]: encountered uninitialized memory, but expected an integer | = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information diff --git a/src/tools/miri/tests/fail/uninit/padding-wide-ptr.rs b/src/tools/miri/tests/fail/uninit/padding-wide-ptr.rs index 0403a9caba66d..4e363dbf81e08 100644 --- a/src/tools/miri/tests/fail/uninit/padding-wide-ptr.rs +++ b/src/tools/miri/tests/fail/uninit/padding-wide-ptr.rs @@ -3,16 +3,19 @@ use std::mem; // If this is `None`, the metadata becomes padding. type T = Option<&'static str>; -fn main() { unsafe { - let mut p: mem::MaybeUninit = mem::MaybeUninit::zeroed(); - // The copy when `T` is returned from `transmute` should destroy padding - // (even when we use `write_unaligned`, which under the hood uses an untyped copy). - p.as_mut_ptr().write_unaligned(mem::transmute((0usize, 0usize))); - // Null epresents `None`. - assert!(matches!(*p.as_ptr(), None)); +fn main() { + unsafe { + let mut p: mem::MaybeUninit = mem::MaybeUninit::zeroed(); + // The copy when `T` is returned from `transmute` should destroy padding + // (even when we use `write_unaligned`, which under the hood uses an untyped copy). + p.as_mut_ptr().write_unaligned(mem::transmute((0usize, 0usize))); + // Null epresents `None`. + assert!(matches!(*p.as_ptr(), None)); - // The second part, with the length, becomes padding. - let c = &p as *const _ as *const u8; - let _val = *c.add(mem::size_of::<*const u8>()); // Get a padding byte. - //~^ERROR: uninitialized -} } + // The second part, with the length, becomes padding. + let c = &p as *const _ as *const u8; + // Read a padding byte. + let _val = *c.add(mem::size_of::<*const u8>()); + //~^ERROR: uninitialized + } +} diff --git a/src/tools/miri/tests/fail/uninit/padding-wide-ptr.stderr b/src/tools/miri/tests/fail/uninit/padding-wide-ptr.stderr index 0da72550b2e08..24194c4b02a95 100644 --- a/src/tools/miri/tests/fail/uninit/padding-wide-ptr.stderr +++ b/src/tools/miri/tests/fail/uninit/padding-wide-ptr.stderr @@ -1,8 +1,8 @@ error: Undefined Behavior: using uninitialized data, but this operation requires initialized memory --> $DIR/padding-wide-ptr.rs:LL:CC | -LL | let _val = *c.add(mem::size_of::<*const u8>()); // Get a padding byte. - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using uninitialized data, but this operation requires initialized memory +LL | let _val = *c.add(mem::size_of::<*const u8>()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using uninitialized data, but this operation requires initialized memory | = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information diff --git a/src/tools/miri/tests/pass/arrays.rs b/src/tools/miri/tests/pass/arrays.rs index b0c6f54cab87c..5cb04d0f8be19 100644 --- a/src/tools/miri/tests/pass/arrays.rs +++ b/src/tools/miri/tests/pass/arrays.rs @@ -62,7 +62,9 @@ fn debug() { } fn huge_zst() { - fn id(x: T) -> T { x } + fn id(x: T) -> T { + x + } // A "huge" zero-sized array. Make sure we don't loop over it in any part of Miri. let val = [(); usize::MAX]; diff --git a/src/tools/miri/tests/pass/async-niche-aliasing.rs b/src/tools/miri/tests/pass/async-niche-aliasing.rs index 7f19afb33e43b..ab82c929a94c2 100644 --- a/src/tools/miri/tests/pass/async-niche-aliasing.rs +++ b/src/tools/miri/tests/pass/async-niche-aliasing.rs @@ -3,10 +3,10 @@ use std::{ future::Future, + mem::MaybeUninit, pin::Pin, sync::Arc, task::{Context, Poll, Wake}, - mem::MaybeUninit, }; struct ThingAdder<'a> { From a8889052261e23444cfde46b7aba16115625a7d6 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 31 Aug 2024 17:03:03 +0200 Subject: [PATCH 0785/2194] miri: treat non-memory local variables properly for data race detection --- .../rustc_const_eval/src/interpret/machine.rs | 21 +++- .../rustc_const_eval/src/interpret/memory.rs | 4 + .../rustc_const_eval/src/interpret/operand.rs | 1 + .../rustc_const_eval/src/interpret/place.rs | 31 ++++-- .../rustc_const_eval/src/interpret/stack.rs | 5 +- src/tools/miri/src/concurrency/data_race.rs | 98 +++++++++++++++++++ src/tools/miri/src/concurrency/thread.rs | 4 +- .../miri/src/concurrency/vector_clock.rs | 6 ++ src/tools/miri/src/machine.rs | 55 ++++++++++- .../data_race/local_variable_alloc_race.rs | 57 +++++++++++ .../local_variable_alloc_race.stderr | 20 ++++ .../data_race/local_variable_read_race.rs | 38 +++++++ .../data_race/local_variable_read_race.stderr | 20 ++++ .../data_race/local_variable_write_race.rs | 37 +++++++ .../local_variable_write_race.stderr | 20 ++++ .../miri/tests/pass/concurrency/data_race.rs | 34 ++++++- 16 files changed, 433 insertions(+), 18 deletions(-) create mode 100644 src/tools/miri/tests/fail/data_race/local_variable_alloc_race.rs create mode 100644 src/tools/miri/tests/fail/data_race/local_variable_alloc_race.stderr create mode 100644 src/tools/miri/tests/fail/data_race/local_variable_read_race.rs create mode 100644 src/tools/miri/tests/fail/data_race/local_variable_read_race.stderr create mode 100644 src/tools/miri/tests/fail/data_race/local_variable_write_race.rs create mode 100644 src/tools/miri/tests/fail/data_race/local_variable_write_race.stderr diff --git a/compiler/rustc_const_eval/src/interpret/machine.rs b/compiler/rustc_const_eval/src/interpret/machine.rs index 8cab3c34eedfb..67c9993405979 100644 --- a/compiler/rustc_const_eval/src/interpret/machine.rs +++ b/compiler/rustc_const_eval/src/interpret/machine.rs @@ -540,10 +540,29 @@ pub trait Machine<'tcx>: Sized { Ok(ReturnAction::Normal) } + /// Called immediately after an "immediate" local variable is read + /// (i.e., this is called for reads that do not end up accessing addressable memory). + #[inline(always)] + fn after_local_read(_ecx: &InterpCx<'tcx, Self>, _local: mir::Local) -> InterpResult<'tcx> { + Ok(()) + } + + /// Called immediately after an "immediate" local variable is assigned a new value + /// (i.e., this is called for writes that do not end up in memory). + /// `storage_live` indicates whether this is the initial write upon `StorageLive`. + #[inline(always)] + fn after_local_write( + _ecx: &mut InterpCx<'tcx, Self>, + _local: mir::Local, + _storage_live: bool, + ) -> InterpResult<'tcx> { + Ok(()) + } + /// Called immediately after actual memory was allocated for a local /// but before the local's stack frame is updated to point to that memory. #[inline(always)] - fn after_local_allocated( + fn after_local_moved_to_memory( _ecx: &mut InterpCx<'tcx, Self>, _local: mir::Local, _mplace: &MPlaceTy<'tcx, Self::Provenance>, diff --git a/compiler/rustc_const_eval/src/interpret/memory.rs b/compiler/rustc_const_eval/src/interpret/memory.rs index d87588496c0bd..a65637f497837 100644 --- a/compiler/rustc_const_eval/src/interpret/memory.rs +++ b/compiler/rustc_const_eval/src/interpret/memory.rs @@ -1030,6 +1030,10 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { ); res } + + pub(super) fn validation_in_progress(&self) -> bool { + self.memory.validation_in_progress + } } #[doc(hidden)] diff --git a/compiler/rustc_const_eval/src/interpret/operand.rs b/compiler/rustc_const_eval/src/interpret/operand.rs index b906e3422dba5..bdbacfd20c2d5 100644 --- a/compiler/rustc_const_eval/src/interpret/operand.rs +++ b/compiler/rustc_const_eval/src/interpret/operand.rs @@ -719,6 +719,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { if matches!(op, Operand::Immediate(_)) { assert!(!layout.is_unsized()); } + M::after_local_read(self, local)?; Ok(OpTy { op, layout }) } diff --git a/compiler/rustc_const_eval/src/interpret/place.rs b/compiler/rustc_const_eval/src/interpret/place.rs index 3b14142da02ed..ee8e5419495d8 100644 --- a/compiler/rustc_const_eval/src/interpret/place.rs +++ b/compiler/rustc_const_eval/src/interpret/place.rs @@ -504,15 +504,13 @@ where &self, local: mir::Local, ) -> InterpResult<'tcx, PlaceTy<'tcx, M::Provenance>> { - // Other parts of the system rely on `Place::Local` never being unsized. - // So we eagerly check here if this local has an MPlace, and if yes we use it. let frame = self.frame(); let layout = self.layout_of_local(frame, local, None)?; let place = if layout.is_sized() { // We can just always use the `Local` for sized values. Place::Local { local, offset: None, locals_addr: frame.locals_addr() } } else { - // Unsized `Local` isn't okay (we cannot store the metadata). + // Other parts of the system rely on `Place::Local` never being unsized. match frame.locals[local].access()? { Operand::Immediate(_) => bug!(), Operand::Indirect(mplace) => Place::Ptr(*mplace), @@ -565,7 +563,10 @@ where place: &PlaceTy<'tcx, M::Provenance>, ) -> InterpResult< 'tcx, - Either, (&mut Immediate, TyAndLayout<'tcx>)>, + Either< + MPlaceTy<'tcx, M::Provenance>, + (&mut Immediate, TyAndLayout<'tcx>, mir::Local), + >, > { Ok(match place.to_place().as_mplace_or_local() { Left(mplace) => Left(mplace), @@ -584,7 +585,7 @@ where } Operand::Immediate(local_val) => { // The local still has the optimized representation. - Right((local_val, layout)) + Right((local_val, layout, local)) } } } @@ -646,9 +647,13 @@ where assert!(dest.layout().is_sized(), "Cannot write unsized immediate data"); match self.as_mplace_or_mutable_local(&dest.to_place())? { - Right((local_val, local_layout)) => { + Right((local_val, local_layout, local)) => { // Local can be updated in-place. *local_val = src; + // Call the machine hook (the data race detector needs to know about this write). + if !self.validation_in_progress() { + M::after_local_write(self, local, /*storage_live*/ false)?; + } // Double-check that the value we are storing and the local fit to each other. if cfg!(debug_assertions) { src.assert_matches_abi(local_layout.abi, self); @@ -717,8 +722,12 @@ where dest: &impl Writeable<'tcx, M::Provenance>, ) -> InterpResult<'tcx> { match self.as_mplace_or_mutable_local(&dest.to_place())? { - Right((local_val, _local_layout)) => { + Right((local_val, _local_layout, local)) => { *local_val = Immediate::Uninit; + // Call the machine hook (the data race detector needs to know about this write). + if !self.validation_in_progress() { + M::after_local_write(self, local, /*storage_live*/ false)?; + } } Left(mplace) => { let Some(mut alloc) = self.get_place_alloc_mut(&mplace)? else { @@ -737,8 +746,12 @@ where dest: &impl Writeable<'tcx, M::Provenance>, ) -> InterpResult<'tcx> { match self.as_mplace_or_mutable_local(&dest.to_place())? { - Right((local_val, _local_layout)) => { + Right((local_val, _local_layout, local)) => { local_val.clear_provenance()?; + // Call the machine hook (the data race detector needs to know about this write). + if !self.validation_in_progress() { + M::after_local_write(self, local, /*storage_live*/ false)?; + } } Left(mplace) => { let Some(mut alloc) = self.get_place_alloc_mut(&mplace)? else { @@ -944,7 +957,7 @@ where mplace.mplace, )?; } - M::after_local_allocated(self, local, &mplace)?; + M::after_local_moved_to_memory(self, local, &mplace)?; // Now we can call `access_mut` again, asserting it goes well, and actually // overwrite things. This points to the entire allocation, not just the part // the place refers to, i.e. we do this before we apply `offset`. diff --git a/compiler/rustc_const_eval/src/interpret/stack.rs b/compiler/rustc_const_eval/src/interpret/stack.rs index b6e83715e3989..db418c82f663f 100644 --- a/compiler/rustc_const_eval/src/interpret/stack.rs +++ b/compiler/rustc_const_eval/src/interpret/stack.rs @@ -534,8 +534,11 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { let dest_place = self.allocate_dyn(layout, MemoryKind::Stack, meta)?; Operand::Indirect(*dest_place.mplace()) } else { - assert!(!meta.has_meta()); // we're dropping the metadata // Just make this an efficient immediate. + assert!(!meta.has_meta()); // we're dropping the metadata + // Make sure the machine knows this "write" is happening. (This is important so that + // races involving local variable allocation can be detected by Miri.) + M::after_local_write(self, local, /*storage_live*/ true)?; // Note that not calling `layout_of` here does have one real consequence: // if the type is too big, we'll only notice this when the local is actually initialized, // which is a bit too late -- we should ideally notice this already here, when the memory diff --git a/src/tools/miri/src/concurrency/data_race.rs b/src/tools/miri/src/concurrency/data_race.rs index b604fd868a02a..d420301400e43 100644 --- a/src/tools/miri/src/concurrency/data_race.rs +++ b/src/tools/miri/src/concurrency/data_race.rs @@ -47,6 +47,7 @@ use std::{ }; use rustc_ast::Mutability; +use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::fx::FxHashSet; use rustc_index::{Idx, IndexVec}; use rustc_middle::{mir, ty::Ty}; @@ -1121,6 +1122,103 @@ impl VClockAlloc { } } +/// Vector clock state for a stack frame (tracking the local variables +/// that do not have an allocation yet). +#[derive(Debug, Default)] +pub struct FrameState { + local_clocks: RefCell>, +} + +/// Stripped-down version of [`MemoryCellClocks`] for the clocks we need to keep track +/// of in a local that does not yet have addressable memory -- and hence can only +/// be accessed from the thread its stack frame belongs to, and cannot be access atomically. +#[derive(Debug)] +struct LocalClocks { + write: VTimestamp, + write_type: NaWriteType, + read: VTimestamp, +} + +impl Default for LocalClocks { + fn default() -> Self { + Self { write: VTimestamp::ZERO, write_type: NaWriteType::Allocate, read: VTimestamp::ZERO } + } +} + +impl FrameState { + pub fn local_write(&self, local: mir::Local, storage_live: bool, machine: &MiriMachine<'_>) { + let current_span = machine.current_span(); + let global = machine.data_race.as_ref().unwrap(); + if global.race_detecting() { + let (index, mut thread_clocks) = global.active_thread_state_mut(&machine.threads); + // This should do the same things as `MemoryCellClocks::write_race_detect`. + if !current_span.is_dummy() { + thread_clocks.clock.index_mut(index).span = current_span; + } + let mut clocks = self.local_clocks.borrow_mut(); + if storage_live { + let new_clocks = LocalClocks { + write: thread_clocks.clock[index], + write_type: NaWriteType::Allocate, + read: VTimestamp::ZERO, + }; + // There might already be an entry in the map for this, if the local was previously + // live already. + clocks.insert(local, new_clocks); + } else { + // This can fail to exist if `race_detecting` was false when the allocation + // occurred, in which case we can backdate this to the beginning of time. + let clocks = clocks.entry(local).or_insert_with(Default::default); + clocks.write = thread_clocks.clock[index]; + clocks.write_type = NaWriteType::Write; + } + } + } + + pub fn local_read(&self, local: mir::Local, machine: &MiriMachine<'_>) { + let current_span = machine.current_span(); + let global = machine.data_race.as_ref().unwrap(); + if global.race_detecting() { + let (index, mut thread_clocks) = global.active_thread_state_mut(&machine.threads); + // This should do the same things as `MemoryCellClocks::read_race_detect`. + if !current_span.is_dummy() { + thread_clocks.clock.index_mut(index).span = current_span; + } + thread_clocks.clock.index_mut(index).set_read_type(NaReadType::Read); + // This can fail to exist if `race_detecting` was false when the allocation + // occurred, in which case we can backdate this to the beginning of time. + let mut clocks = self.local_clocks.borrow_mut(); + let clocks = clocks.entry(local).or_insert_with(Default::default); + clocks.read = thread_clocks.clock[index]; + } + } + + pub fn local_moved_to_memory( + &self, + local: mir::Local, + alloc: &mut VClockAlloc, + machine: &MiriMachine<'_>, + ) { + let global = machine.data_race.as_ref().unwrap(); + if global.race_detecting() { + let (index, _thread_clocks) = global.active_thread_state_mut(&machine.threads); + // Get the time the last write actually happened. This can fail to exist if + // `race_detecting` was false when the write occurred, in that case we can backdate this + // to the beginning of time. + let local_clocks = self.local_clocks.borrow_mut().remove(&local).unwrap_or_default(); + for (_mem_clocks_range, mem_clocks) in alloc.alloc_ranges.get_mut().iter_mut_all() { + // The initialization write for this already happened, just at the wrong timestamp. + // Check that the thread index matches what we expect. + assert_eq!(mem_clocks.write.0, index); + // Convert the local's clocks into memory clocks. + mem_clocks.write = (index, local_clocks.write); + mem_clocks.write_type = local_clocks.write_type; + mem_clocks.read = VClock::new_with_index(index, local_clocks.read); + } + } + } +} + impl<'tcx> EvalContextPrivExt<'tcx> for MiriInterpCx<'tcx> {} trait EvalContextPrivExt<'tcx>: MiriInterpCxExt<'tcx> { /// Temporarily allow data-races to occur. This should only be used in diff --git a/src/tools/miri/src/concurrency/thread.rs b/src/tools/miri/src/concurrency/thread.rs index 306245a843bf4..8c3bee83e46cb 100644 --- a/src/tools/miri/src/concurrency/thread.rs +++ b/src/tools/miri/src/concurrency/thread.rs @@ -530,7 +530,9 @@ impl<'tcx> ThreadManager<'tcx> { } /// Mutably borrow the stack of the active thread. - fn active_thread_stack_mut(&mut self) -> &mut Vec>> { + pub fn active_thread_stack_mut( + &mut self, + ) -> &mut Vec>> { &mut self.threads[self.active_thread].stack } pub fn all_stacks( diff --git a/src/tools/miri/src/concurrency/vector_clock.rs b/src/tools/miri/src/concurrency/vector_clock.rs index c3496bc1a0c8a..0968e10bbee0b 100644 --- a/src/tools/miri/src/concurrency/vector_clock.rs +++ b/src/tools/miri/src/concurrency/vector_clock.rs @@ -130,6 +130,9 @@ impl Ord for VTimestamp { /// also this means that there is only one unique valid length /// for each set of vector clock values and hence the PartialEq /// and Eq derivations are correct. +/// +/// This means we cannot represent a clock where the last entry is a timestamp-0 read that occurs +/// because of a retag. That's fine, all it does is risk wrong diagnostics in a extreme corner case. #[derive(PartialEq, Eq, Default, Debug)] pub struct VClock(SmallVec<[VTimestamp; SMALL_VECTOR]>); @@ -137,6 +140,9 @@ impl VClock { /// Create a new vector-clock containing all zeros except /// for a value at the given index pub(super) fn new_with_index(index: VectorIdx, timestamp: VTimestamp) -> VClock { + if timestamp.time() == 0 { + return VClock::default(); + } let len = index.index() + 1; let mut vec = smallvec::smallvec![VTimestamp::ZERO; len]; vec[index.index()] = timestamp; diff --git a/src/tools/miri/src/machine.rs b/src/tools/miri/src/machine.rs index 76b4366476d52..df55902decdc8 100644 --- a/src/tools/miri/src/machine.rs +++ b/src/tools/miri/src/machine.rs @@ -81,24 +81,42 @@ pub struct FrameExtra<'tcx> { /// an additional bit of "salt" into the cache key. This salt is fixed per-frame /// so that within a call, a const will have a stable address. salt: usize, + + /// Data race detector per-frame data. + pub data_race: Option, } impl<'tcx> std::fmt::Debug for FrameExtra<'tcx> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { // Omitting `timing`, it does not support `Debug`. - let FrameExtra { borrow_tracker, catch_unwind, timing: _, is_user_relevant: _, salt: _ } = - self; + let FrameExtra { + borrow_tracker, + catch_unwind, + timing: _, + is_user_relevant, + salt, + data_race, + } = self; f.debug_struct("FrameData") .field("borrow_tracker", borrow_tracker) .field("catch_unwind", catch_unwind) + .field("is_user_relevant", is_user_relevant) + .field("salt", salt) + .field("data_race", data_race) .finish() } } impl VisitProvenance for FrameExtra<'_> { fn visit_provenance(&self, visit: &mut VisitWith<'_>) { - let FrameExtra { catch_unwind, borrow_tracker, timing: _, is_user_relevant: _, salt: _ } = - self; + let FrameExtra { + catch_unwind, + borrow_tracker, + timing: _, + is_user_relevant: _, + salt: _, + data_race: _, + } = self; catch_unwind.visit_provenance(visit); borrow_tracker.visit_provenance(visit); @@ -1446,6 +1464,7 @@ impl<'tcx> Machine<'tcx> for MiriMachine<'tcx> { timing, is_user_relevant: ecx.machine.is_user_relevant(&frame), salt: ecx.machine.rng.borrow_mut().gen::() % ADDRS_PER_ANON_GLOBAL, + data_race: ecx.machine.data_race.as_ref().map(|_| data_race::FrameState::default()), }; Ok(frame.with_extra(extra)) @@ -1551,7 +1570,25 @@ impl<'tcx> Machine<'tcx> for MiriMachine<'tcx> { res } - fn after_local_allocated( + fn after_local_read(ecx: &InterpCx<'tcx, Self>, local: mir::Local) -> InterpResult<'tcx> { + if let Some(data_race) = &ecx.frame().extra.data_race { + data_race.local_read(local, &ecx.machine); + } + Ok(()) + } + + fn after_local_write( + ecx: &mut InterpCx<'tcx, Self>, + local: mir::Local, + storage_live: bool, + ) -> InterpResult<'tcx> { + if let Some(data_race) = &ecx.frame().extra.data_race { + data_race.local_write(local, storage_live, &ecx.machine); + } + Ok(()) + } + + fn after_local_moved_to_memory( ecx: &mut InterpCx<'tcx, Self>, local: mir::Local, mplace: &MPlaceTy<'tcx>, @@ -1559,9 +1596,17 @@ impl<'tcx> Machine<'tcx> for MiriMachine<'tcx> { let Some(Provenance::Concrete { alloc_id, .. }) = mplace.ptr().provenance else { panic!("after_local_allocated should only be called on fresh allocations"); }; + // Record the span where this was allocated: the declaration of the local. let local_decl = &ecx.frame().body().local_decls[local]; let span = local_decl.source_info.span; ecx.machine.allocation_spans.borrow_mut().insert(alloc_id, (span, None)); + // The data race system has to fix the clocks used for this write. + let (alloc_info, machine) = ecx.get_alloc_extra_mut(alloc_id)?; + if let Some(data_race) = + &machine.threads.active_thread_stack().last().unwrap().extra.data_race + { + data_race.local_moved_to_memory(local, alloc_info.data_race.as_mut().unwrap(), machine); + } Ok(()) } diff --git a/src/tools/miri/tests/fail/data_race/local_variable_alloc_race.rs b/src/tools/miri/tests/fail/data_race/local_variable_alloc_race.rs new file mode 100644 index 0000000000000..751a308a39998 --- /dev/null +++ b/src/tools/miri/tests/fail/data_race/local_variable_alloc_race.rs @@ -0,0 +1,57 @@ +//@compile-flags: -Zmiri-preemption-rate=0.0 -Zmiri-disable-weak-memory-emulation +#![feature(core_intrinsics)] +#![feature(custom_mir)] + +use std::intrinsics::mir::*; +use std::sync::atomic::Ordering::*; +use std::sync::atomic::*; +use std::thread::JoinHandle; + +static P: AtomicPtr = AtomicPtr::new(core::ptr::null_mut()); + +fn spawn_thread() -> JoinHandle<()> { + std::thread::spawn(|| { + while P.load(Relaxed).is_null() { + std::hint::spin_loop(); + } + unsafe { + // Initialize `*P`. + let ptr = P.load(Relaxed); + *ptr = 127; + //~^ ERROR: Data race detected between (1) creating a new allocation on thread `main` and (2) non-atomic write on thread `unnamed-1` + } + }) +} + +fn finish(t: JoinHandle<()>, val_ptr: *mut u8) { + P.store(val_ptr, Relaxed); + + // Wait for the thread to be done. + t.join().unwrap(); + + // Read initialized value. + assert_eq!(unsafe { *val_ptr }, 127); +} + +#[custom_mir(dialect = "runtime", phase = "optimized")] +fn main() { + mir! { + let t; + let val; + let val_ptr; + let _ret; + { + Call(t = spawn_thread(), ReturnTo(after_spawn), UnwindContinue()) + } + after_spawn = { + // This races with the write in the other thread. + StorageLive(val); + + val_ptr = &raw mut val; + Call(_ret = finish(t, val_ptr), ReturnTo(done), UnwindContinue()) + } + done = { + Return() + } + } +} diff --git a/src/tools/miri/tests/fail/data_race/local_variable_alloc_race.stderr b/src/tools/miri/tests/fail/data_race/local_variable_alloc_race.stderr new file mode 100644 index 0000000000000..f46eb078a5189 --- /dev/null +++ b/src/tools/miri/tests/fail/data_race/local_variable_alloc_race.stderr @@ -0,0 +1,20 @@ +error: Undefined Behavior: Data race detected between (1) creating a new allocation on thread `main` and (2) non-atomic write on thread `unnamed-ID` at ALLOC. (2) just happened here + --> $DIR/local_variable_alloc_race.rs:LL:CC + | +LL | *ptr = 127; + | ^^^^^^^^^^ Data race detected between (1) creating a new allocation on thread `main` and (2) non-atomic write on thread `unnamed-ID` at ALLOC. (2) just happened here + | +help: and (1) occurred earlier here + --> $DIR/local_variable_alloc_race.rs:LL:CC + | +LL | StorageLive(val); + | ^^^^^^^^^^^^^^^^ + = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior + = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information + = note: BACKTRACE (of the first span) on thread `unnamed-ID`: + = note: inside closure at $DIR/local_variable_alloc_race.rs:LL:CC + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to 1 previous error + diff --git a/src/tools/miri/tests/fail/data_race/local_variable_read_race.rs b/src/tools/miri/tests/fail/data_race/local_variable_read_race.rs new file mode 100644 index 0000000000000..80d2b7b7c12bd --- /dev/null +++ b/src/tools/miri/tests/fail/data_race/local_variable_read_race.rs @@ -0,0 +1,38 @@ +//@compile-flags: -Zmiri-preemption-rate=0.0 -Zmiri-disable-weak-memory-emulation +use std::sync::atomic::Ordering::*; +use std::sync::atomic::*; + +static P: AtomicPtr = AtomicPtr::new(core::ptr::null_mut()); + +fn main() { + // Create the local variable, and initialize it. + let mut val: u8 = 0; + + let t1 = std::thread::spawn(|| { + while P.load(Relaxed).is_null() { + std::hint::spin_loop(); + } + unsafe { + // Initialize `*P`. + let ptr = P.load(Relaxed); + *ptr = 127; + //~^ ERROR: Data race detected between (1) non-atomic read on thread `main` and (2) non-atomic write on thread `unnamed-1` + } + }); + + // This read is not ordered with the store above, and thus should be reported as a race. + let _val = val; + + // Actually generate memory for the local variable. + // This is the time its value is actually written to memory. + // If we just "pre-date" the write to the beginning of time (since we don't know + // when it actually happened), we'd miss the UB in this test. + // Also, the UB error should point at the write above, not the addr-of here. + P.store(std::ptr::addr_of_mut!(val), Relaxed); + + // Wait for the thread to be done. + t1.join().unwrap(); + + // Read initialized value. + assert_eq!(val, 127); +} diff --git a/src/tools/miri/tests/fail/data_race/local_variable_read_race.stderr b/src/tools/miri/tests/fail/data_race/local_variable_read_race.stderr new file mode 100644 index 0000000000000..d14c2fb47ffc8 --- /dev/null +++ b/src/tools/miri/tests/fail/data_race/local_variable_read_race.stderr @@ -0,0 +1,20 @@ +error: Undefined Behavior: Data race detected between (1) non-atomic read on thread `main` and (2) non-atomic write on thread `unnamed-ID` at ALLOC. (2) just happened here + --> $DIR/local_variable_read_race.rs:LL:CC + | +LL | *ptr = 127; + | ^^^^^^^^^^ Data race detected between (1) non-atomic read on thread `main` and (2) non-atomic write on thread `unnamed-ID` at ALLOC. (2) just happened here + | +help: and (1) occurred earlier here + --> $DIR/local_variable_read_race.rs:LL:CC + | +LL | let _val = val; + | ^^^ + = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior + = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information + = note: BACKTRACE (of the first span) on thread `unnamed-ID`: + = note: inside closure at $DIR/local_variable_read_race.rs:LL:CC + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to 1 previous error + diff --git a/src/tools/miri/tests/fail/data_race/local_variable_write_race.rs b/src/tools/miri/tests/fail/data_race/local_variable_write_race.rs new file mode 100644 index 0000000000000..eabbe4403c676 --- /dev/null +++ b/src/tools/miri/tests/fail/data_race/local_variable_write_race.rs @@ -0,0 +1,37 @@ +//@compile-flags: -Zmiri-preemption-rate=0.0 -Zmiri-disable-weak-memory-emulation +use std::sync::atomic::Ordering::*; +use std::sync::atomic::*; + +static P: AtomicPtr = AtomicPtr::new(core::ptr::null_mut()); + +fn main() { + let t1 = std::thread::spawn(|| { + while P.load(Relaxed).is_null() { + std::hint::spin_loop(); + } + unsafe { + // Initialize `*P`. + let ptr = P.load(Relaxed); + *ptr = 127; + //~^ ERROR: Data race detected between (1) non-atomic write on thread `main` and (2) non-atomic write on thread `unnamed-1` + } + }); + + // Create the local variable, and initialize it. + // This is not ordered with the store above, so it's definitely UB + // for that thread to access this variable. + let mut val: u8 = 0; + + // Actually generate memory for the local variable. + // This is the time its value is actually written to memory. + // If we just "pre-date" the write to the beginning of time (since we don't know + // when it actually happened), we'd miss the UB in this test. + // Also, the UB error should point at the write above, not the addr-of here. + P.store(std::ptr::addr_of_mut!(val), Relaxed); + + // Wait for the thread to be done. + t1.join().unwrap(); + + // Read initialized value. + assert_eq!(val, 127); +} diff --git a/src/tools/miri/tests/fail/data_race/local_variable_write_race.stderr b/src/tools/miri/tests/fail/data_race/local_variable_write_race.stderr new file mode 100644 index 0000000000000..d84db955a3d78 --- /dev/null +++ b/src/tools/miri/tests/fail/data_race/local_variable_write_race.stderr @@ -0,0 +1,20 @@ +error: Undefined Behavior: Data race detected between (1) non-atomic write on thread `main` and (2) non-atomic write on thread `unnamed-ID` at ALLOC. (2) just happened here + --> $DIR/local_variable_write_race.rs:LL:CC + | +LL | *ptr = 127; + | ^^^^^^^^^^ Data race detected between (1) non-atomic write on thread `main` and (2) non-atomic write on thread `unnamed-ID` at ALLOC. (2) just happened here + | +help: and (1) occurred earlier here + --> $DIR/local_variable_write_race.rs:LL:CC + | +LL | let mut val: u8 = 0; + | ^ + = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior + = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information + = note: BACKTRACE (of the first span) on thread `unnamed-ID`: + = note: inside closure at $DIR/local_variable_write_race.rs:LL:CC + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to 1 previous error + diff --git a/src/tools/miri/tests/pass/concurrency/data_race.rs b/src/tools/miri/tests/pass/concurrency/data_race.rs index d31420380a565..34380dfa504d5 100644 --- a/src/tools/miri/tests/pass/concurrency/data_race.rs +++ b/src/tools/miri/tests/pass/concurrency/data_race.rs @@ -1,6 +1,6 @@ //@compile-flags: -Zmiri-disable-weak-memory-emulation -Zmiri-preemption-rate=0 -use std::sync::atomic::{fence, AtomicUsize, Ordering}; +use std::sync::atomic::*; use std::thread::spawn; #[derive(Copy, Clone)] @@ -112,9 +112,41 @@ pub fn test_simple_release() { } } +fn test_local_variable_lazy_write() { + static P: AtomicPtr = AtomicPtr::new(core::ptr::null_mut()); + + // Create the local variable, and initialize it. + // This write happens before the thread is spanwed, so there is no data race. + let mut val: u8 = 0; + + let t1 = std::thread::spawn(|| { + while P.load(Ordering::Relaxed).is_null() { + std::hint::spin_loop(); + } + unsafe { + // Initialize `*P`. + let ptr = P.load(Ordering::Relaxed); + *ptr = 127; + } + }); + + // Actually generate memory for the local variable. + // This is the time its value is actually written to memory: + // that's *after* the thread above was spawned! + // This may hence look like a data race wrt the access in the thread above. + P.store(std::ptr::addr_of_mut!(val), Ordering::Relaxed); + + // Wait for the thread to be done. + t1.join().unwrap(); + + // Read initialized value. + assert_eq!(val, 127); +} + pub fn main() { test_fence_sync(); test_multiple_reads(); test_rmw_no_block(); test_simple_release(); + test_local_variable_lazy_write(); } From f76f128dc9dea86f52a40d465430a7feddca271a Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Fri, 2 Aug 2024 15:34:59 +0200 Subject: [PATCH 0786/2194] const-eval interning: accpt interior mutable pointers in final value (but keep rejecting mutable references) --- .../src/check_consts/check.rs | 5 +- .../src/const_eval/eval_queries.rs | 26 +- .../src/const_eval/machine.rs | 23 +- compiler/rustc_const_eval/src/errors.rs | 7 +- .../rustc_const_eval/src/interpret/intern.rs | 18 +- compiler/rustc_lint/src/lib.rs | 4 + compiler/rustc_lint_defs/src/builtin.rs | 46 ---- .../rustc_middle/src/mir/interpret/pointer.rs | 47 +++- compiler/rustc_middle/src/ty/codec.rs | 9 +- compiler/rustc_middle/src/ty/impls_ty.rs | 4 +- .../heap/alloc_intrinsic_untyped.rs | 2 - .../heap/alloc_intrinsic_untyped.stderr | 25 +- ...pat-mutable-in-final-value-issue-121610.rs | 18 -- ...mutable-in-final-value-issue-121610.stderr | 23 -- .../miri_unleashed/mutable_references.rs | 21 +- .../miri_unleashed/mutable_references.stderr | 237 +++--------------- .../static-no-inner-mut.32bit.stderr | 91 +------ .../static-no-inner-mut.64bit.stderr | 91 +------ .../miri_unleashed/static-no-inner-mut.rs | 12 +- tests/ui/consts/refs-to-cell-in-final.rs | 8 +- tests/ui/consts/refs-to-cell-in-final.stderr | 23 +- 21 files changed, 177 insertions(+), 563 deletions(-) delete mode 100644 tests/ui/consts/future-incompat-mutable-in-final-value-issue-121610.rs delete mode 100644 tests/ui/consts/future-incompat-mutable-in-final-value-issue-121610.stderr diff --git a/compiler/rustc_const_eval/src/check_consts/check.rs b/compiler/rustc_const_eval/src/check_consts/check.rs index 8be327a8b5647..828d8354c63c2 100644 --- a/compiler/rustc_const_eval/src/check_consts/check.rs +++ b/compiler/rustc_const_eval/src/check_consts/check.rs @@ -538,8 +538,9 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> { // final value. // Note: This is only sound if every local that has a `StorageDead` has a // `StorageDead` in every control flow path leading to a `return` terminator. - // The good news is that interning will detect if any unexpected mutable - // pointer slips through. + // If anything slips through, there's no safety net -- safe code can create + // references to variants of `!Freeze` enums as long as that variant is `Freeze`, + // so interning can't protect us here. if self.local_is_transient(place.local) { self.check_op(ops::TransientCellBorrow); } else { diff --git a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs index 7ccebd83f24f7..594b98f34ef4a 100644 --- a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs +++ b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs @@ -10,7 +10,6 @@ use rustc_middle::traits::Reveal; use rustc_middle::ty::layout::LayoutOf; use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_middle::ty::{self, Ty, TyCtxt}; -use rustc_session::lint; use rustc_span::def_id::LocalDefId; use rustc_span::{Span, DUMMY_SP}; use rustc_target::abi::{self, Abi}; @@ -18,13 +17,12 @@ use tracing::{debug, instrument, trace}; use super::{CanAccessMutGlobal, CompileTimeInterpCx, CompileTimeMachine}; use crate::const_eval::CheckAlignment; -use crate::errors::{self, ConstEvalError, DanglingPtrInFinal}; use crate::interpret::{ create_static_alloc, eval_nullary_intrinsic, intern_const_alloc_recursive, throw_exhaust, CtfeValidationMode, GlobalId, Immediate, InternKind, InternResult, InterpCx, InterpError, InterpResult, MPlaceTy, MemoryKind, OpTy, RefTracking, StackPopCleanup, }; -use crate::CTRL_C_RECEIVED; +use crate::{errors, CTRL_C_RECEIVED}; // Returns a pointer to where the result lives #[instrument(level = "trace", skip(ecx, body))] @@ -105,18 +103,15 @@ fn eval_body_using_ecx<'tcx, R: InterpretationResult<'tcx>>( return Err(ecx .tcx .dcx() - .emit_err(DanglingPtrInFinal { span: ecx.tcx.span, kind: intern_kind }) + .emit_err(errors::DanglingPtrInFinal { span: ecx.tcx.span, kind: intern_kind }) .into()); } Err(InternResult::FoundBadMutablePointer) => { - // only report mutable pointers if there were no dangling pointers - let err_diag = errors::MutablePtrInFinal { span: ecx.tcx.span, kind: intern_kind }; - ecx.tcx.emit_node_span_lint( - lint::builtin::CONST_EVAL_MUTABLE_PTR_IN_FINAL_VALUE, - ecx.machine.best_lint_scope(*ecx.tcx), - err_diag.span, - err_diag, - ) + return Err(ecx + .tcx + .dcx() + .emit_err(errors::MutablePtrInFinal { span: ecx.tcx.span, kind: intern_kind }) + .into()); } } @@ -448,7 +443,12 @@ fn report_eval_error<'tcx>( error, DUMMY_SP, || super::get_span_and_frames(ecx.tcx, ecx.stack()), - |span, frames| ConstEvalError { span, error_kind: kind, instance, frame_notes: frames }, + |span, frames| errors::ConstEvalError { + span, + error_kind: kind, + instance, + frame_notes: frames, + }, ) } diff --git a/compiler/rustc_const_eval/src/const_eval/machine.rs b/compiler/rustc_const_eval/src/const_eval/machine.rs index 7405ca09342da..6a691abae026d 100644 --- a/compiler/rustc_const_eval/src/const_eval/machine.rs +++ b/compiler/rustc_const_eval/src/const_eval/machine.rs @@ -718,16 +718,29 @@ impl<'tcx> interpret::Machine<'tcx> for CompileTimeMachine<'tcx> { _kind: mir::RetagKind, val: &ImmTy<'tcx, CtfeProvenance>, ) -> InterpResult<'tcx, ImmTy<'tcx, CtfeProvenance>> { - // If it's a frozen shared reference that's not already immutable, make it immutable. + // If it's a frozen shared reference that's not already immutable, potentially make it immutable. // (Do nothing on `None` provenance, that cannot store immutability anyway.) if let ty::Ref(_, ty, mutbl) = val.layout.ty.kind() && *mutbl == Mutability::Not - && val.to_scalar_and_meta().0.to_pointer(ecx)?.provenance.is_some_and(|p| !p.immutable()) - // That next check is expensive, that's why we have all the guards above. - && ty.is_freeze(*ecx.tcx, ecx.param_env) + && val + .to_scalar_and_meta() + .0 + .to_pointer(ecx)? + .provenance + .is_some_and(|p| !p.immutable()) { + // That next check is expensive, that's why we have all the guards above. + let is_immutable = ty.is_freeze(*ecx.tcx, ecx.param_env); let place = ecx.ref_to_mplace(val)?; - let new_place = place.map_provenance(CtfeProvenance::as_immutable); + let new_place = if is_immutable { + place.map_provenance(CtfeProvenance::as_immutable) + } else { + // Even if it is not immutable, remember that it is a shared reference. + // This allows it to become part of the final value of the constant. + // (See for why we allow this + // even when there is interior mutability.) + place.map_provenance(CtfeProvenance::as_shared_ref) + }; Ok(ImmTy::from_immediate(new_place.to_ref(ecx), val.layout)) } else { Ok(val.clone()) diff --git a/compiler/rustc_const_eval/src/errors.rs b/compiler/rustc_const_eval/src/errors.rs index 0b366b43f95f6..57e5225475725 100644 --- a/compiler/rustc_const_eval/src/errors.rs +++ b/compiler/rustc_const_eval/src/errors.rs @@ -35,13 +35,10 @@ pub(crate) struct NestedStaticInThreadLocal { pub span: Span, } -#[derive(LintDiagnostic)] +#[derive(Diagnostic)] #[diag(const_eval_mutable_ptr_in_final)] pub(crate) struct MutablePtrInFinal { - // rust-lang/rust#122153: This was marked as `#[primary_span]` under - // `derive(Diagnostic)`. Since we expect we may hard-error in future, we are - // keeping the field (and skipping it under `derive(LintDiagnostic)`). - #[skip_arg] + #[primary_span] pub span: Span, pub kind: InternKind, } diff --git a/compiler/rustc_const_eval/src/interpret/intern.rs b/compiler/rustc_const_eval/src/interpret/intern.rs index 8b0a2afa4d669..e81431b45fb59 100644 --- a/compiler/rustc_const_eval/src/interpret/intern.rs +++ b/compiler/rustc_const_eval/src/interpret/intern.rs @@ -223,16 +223,20 @@ pub fn intern_const_alloc_recursive<'tcx, M: CompileTimeMachine<'tcx, const_eval continue; } - // Crucially, we check this *before* checking whether the `alloc_id` - // has already been interned. The point of this check is to ensure that when - // there are multiple pointers to the same allocation, they are *all* immutable. - // Therefore it would be bad if we only checked the first pointer to any given - // allocation. + // Ensure that this is is derived from a shared reference. Crucially, we check this *before* + // checking whether the `alloc_id` has already been interned. The point of this check is to + // ensure that when there are multiple pointers to the same allocation, they are *all* + // derived from a shared reference. Therefore it would be bad if we only checked the first + // pointer to any given allocation. // (It is likely not possible to actually have multiple pointers to the same allocation, // so alternatively we could also check that and ICE if there are multiple such pointers.) + // See for why we are checking for + // "shared reference" and not "immutable", i.e., for why we are allowed interior-mutable + // shared references: they can actually be created in safe code while pointing to apparently + // "immutable" values, via promotion of `&None::>`. if intern_kind != InternKind::Promoted && inner_mutability == Mutability::Not - && !prov.immutable() + && !prov.shared_ref() { if ecx.tcx.try_get_global_alloc(alloc_id).is_some() && !just_interned.contains(&alloc_id) @@ -245,7 +249,7 @@ pub fn intern_const_alloc_recursive<'tcx, M: CompileTimeMachine<'tcx, const_eval // this to the todo list, since after all it is already interned. continue; } - // Found a mutable pointer inside a const where inner allocations should be + // Found a mutable reference inside a const where inner allocations should be // immutable. We exclude promoteds from this, since things like `&mut []` and // `&None::>` lead to promotion that can produce mutable pointers. We rely // on the promotion analysis not screwing up to ensure that it is sound to intern diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs index a9627e9b78907..4139ac4e3e9c9 100644 --- a/compiler/rustc_lint/src/lib.rs +++ b/compiler/rustc_lint/src/lib.rs @@ -576,6 +576,10 @@ fn register_builtins(store: &mut LintStore) { for more information", ); store.register_removed("writes_through_immutable_pointer", "converted into hard error"); + store.register_removed( + "const_eval_mutable_ptr_in_final_value", + "partially allowed now, otherwise turned into a hard error", + ); } fn register_internals(store: &mut LintStore) { diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index 25d33126754af..f42f35c594b1a 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs @@ -29,7 +29,6 @@ declare_lint_pass! { CENUM_IMPL_DROP_CAST, COHERENCE_LEAK_CHECK, CONFLICTING_REPR_HINTS, - CONST_EVAL_MUTABLE_PTR_IN_FINAL_VALUE, CONST_EVALUATABLE_UNCHECKED, CONST_ITEM_MUTATION, DEAD_CODE, @@ -2804,51 +2803,6 @@ declare_lint! { @feature_gate = strict_provenance; } -declare_lint! { - /// The `const_eval_mutable_ptr_in_final_value` lint detects if a mutable pointer - /// has leaked into the final value of a const expression. - /// - /// ### Example - /// - /// ```rust - /// pub enum JsValue { - /// Undefined, - /// Object(std::cell::Cell), - /// } - /// - /// impl ::std::ops::Drop for JsValue { - /// fn drop(&mut self) {} - /// } - /// - /// const UNDEFINED: &JsValue = &JsValue::Undefined; - /// - /// fn main() { - /// } - /// ``` - /// - /// {{produces}} - /// - /// ### Explanation - /// - /// In the 1.77 release, the const evaluation machinery adopted some - /// stricter rules to reject expressions with values that could - /// end up holding mutable references to state stored in static memory - /// (which is inherently immutable). - /// - /// This is a [future-incompatible] lint to ease the transition to an error. - /// See [issue #122153] for more details. - /// - /// [issue #122153]: https://github.com/rust-lang/rust/issues/122153 - /// [future-incompatible]: ../index.md#future-incompatible-lints - pub CONST_EVAL_MUTABLE_PTR_IN_FINAL_VALUE, - Warn, - "detects a mutable pointer that has leaked into final value of a const expression", - @future_incompatible = FutureIncompatibleInfo { - reason: FutureIncompatibilityReason::FutureReleaseErrorReportInDeps, - reference: "issue #122153 ", - }; -} - declare_lint! { /// The `const_evaluatable_unchecked` lint detects a generic constant used /// in a type. diff --git a/compiler/rustc_middle/src/mir/interpret/pointer.rs b/compiler/rustc_middle/src/mir/interpret/pointer.rs index 6cfd07d699c3e..1700b0f02ecc8 100644 --- a/compiler/rustc_middle/src/mir/interpret/pointer.rs +++ b/compiler/rustc_middle/src/mir/interpret/pointer.rs @@ -80,14 +80,23 @@ pub trait Provenance: Copy + fmt::Debug + 'static { } /// The type of provenance in the compile-time interpreter. -/// This is a packed representation of an `AllocId` and an `immutable: bool`. +/// This is a packed representation of: +/// - an `AllocId` (non-zero) +/// - an `immutable: bool` +/// - a `shared_ref: bool` +/// +/// with the extra invariant that if `immutable` is `true`, then so +/// is `shared_ref`. #[derive(Copy, Clone, Eq, Hash, Ord, PartialEq, PartialOrd)] pub struct CtfeProvenance(NonZero); impl From for CtfeProvenance { fn from(value: AllocId) -> Self { let prov = CtfeProvenance(value.0); - assert!(!prov.immutable(), "`AllocId` with the highest bit set cannot be used in CTFE"); + assert!( + prov.alloc_id() == value, + "`AllocId` with the highest bits set cannot be used in CTFE" + ); prov } } @@ -103,12 +112,14 @@ impl fmt::Debug for CtfeProvenance { } const IMMUTABLE_MASK: u64 = 1 << 63; // the highest bit +const SHARED_REF_MASK: u64 = 1 << 62; +const ALLOC_ID_MASK: u64 = u64::MAX & !IMMUTABLE_MASK & !SHARED_REF_MASK; impl CtfeProvenance { /// Returns the `AllocId` of this provenance. #[inline(always)] pub fn alloc_id(self) -> AllocId { - AllocId(NonZero::new(self.0.get() & !IMMUTABLE_MASK).unwrap()) + AllocId(NonZero::new(self.0.get() & ALLOC_ID_MASK).unwrap()) } /// Returns whether this provenance is immutable. @@ -117,10 +128,38 @@ impl CtfeProvenance { self.0.get() & IMMUTABLE_MASK != 0 } + /// Returns whether this provenance is derived from a shared reference. + #[inline] + pub fn shared_ref(self) -> bool { + self.0.get() & SHARED_REF_MASK != 0 + } + + pub fn into_parts(self) -> (AllocId, bool, bool) { + (self.alloc_id(), self.immutable(), self.shared_ref()) + } + + pub fn from_parts((alloc_id, immutable, shared_ref): (AllocId, bool, bool)) -> Self { + let prov = CtfeProvenance::from(alloc_id); + if immutable { + // This sets both flags, so we don't even have to check `shared_ref`. + prov.as_immutable() + } else if shared_ref { + prov.as_shared_ref() + } else { + prov + } + } + /// Returns an immutable version of this provenance. #[inline] pub fn as_immutable(self) -> Self { - CtfeProvenance(self.0 | IMMUTABLE_MASK) + CtfeProvenance(self.0 | IMMUTABLE_MASK | SHARED_REF_MASK) + } + + /// Returns a "shared reference" (but not necessarily immutable!) version of this provenance. + #[inline] + pub fn as_shared_ref(self) -> Self { + CtfeProvenance(self.0 | SHARED_REF_MASK) } } diff --git a/compiler/rustc_middle/src/ty/codec.rs b/compiler/rustc_middle/src/ty/codec.rs index 46203ee150f64..7e533bc4291a1 100644 --- a/compiler/rustc_middle/src/ty/codec.rs +++ b/compiler/rustc_middle/src/ty/codec.rs @@ -165,8 +165,7 @@ impl<'tcx, E: TyEncoder>> Encodable for AllocId { impl<'tcx, E: TyEncoder>> Encodable for CtfeProvenance { fn encode(&self, e: &mut E) { - self.alloc_id().encode(e); - self.immutable().encode(e); + self.into_parts().encode(e); } } @@ -295,10 +294,8 @@ impl<'tcx, D: TyDecoder>> Decodable for AllocId { impl<'tcx, D: TyDecoder>> Decodable for CtfeProvenance { fn decode(decoder: &mut D) -> Self { - let alloc_id: AllocId = Decodable::decode(decoder); - let prov = CtfeProvenance::from(alloc_id); - let immutable: bool = Decodable::decode(decoder); - if immutable { prov.as_immutable() } else { prov } + let parts = Decodable::decode(decoder); + CtfeProvenance::from_parts(parts) } } diff --git a/compiler/rustc_middle/src/ty/impls_ty.rs b/compiler/rustc_middle/src/ty/impls_ty.rs index b5b7b8bcfef00..5f6305bb48ad4 100644 --- a/compiler/rustc_middle/src/ty/impls_ty.rs +++ b/compiler/rustc_middle/src/ty/impls_ty.rs @@ -75,11 +75,9 @@ impl<'a> HashStable> for mir::interpret::AllocId { } } -// CtfeProvenance is an AllocId and a bool. impl<'a> HashStable> for mir::interpret::CtfeProvenance { fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { - self.alloc_id().hash_stable(hcx, hasher); - self.immutable().hash_stable(hcx, hasher); + self.into_parts().hash_stable(hcx, hasher); } } diff --git a/tests/ui/consts/const-eval/heap/alloc_intrinsic_untyped.rs b/tests/ui/consts/const-eval/heap/alloc_intrinsic_untyped.rs index b8fed212c97f9..105e8e38d84eb 100644 --- a/tests/ui/consts/const-eval/heap/alloc_intrinsic_untyped.rs +++ b/tests/ui/consts/const-eval/heap/alloc_intrinsic_untyped.rs @@ -1,11 +1,9 @@ #![feature(core_intrinsics)] #![feature(const_heap)] #![feature(const_mut_refs)] -#![deny(const_eval_mutable_ptr_in_final_value)] use std::intrinsics; const BAR: *mut i32 = unsafe { intrinsics::const_allocate(4, 4) as *mut i32 }; //~^ error: mutable pointer in final value of constant -//~| WARNING this was previously accepted by the compiler fn main() {} diff --git a/tests/ui/consts/const-eval/heap/alloc_intrinsic_untyped.stderr b/tests/ui/consts/const-eval/heap/alloc_intrinsic_untyped.stderr index bb47adacb9f95..bd82e6781be1e 100644 --- a/tests/ui/consts/const-eval/heap/alloc_intrinsic_untyped.stderr +++ b/tests/ui/consts/const-eval/heap/alloc_intrinsic_untyped.stderr @@ -1,31 +1,8 @@ error: encountered mutable pointer in final value of constant - --> $DIR/alloc_intrinsic_untyped.rs:7:1 + --> $DIR/alloc_intrinsic_untyped.rs:6:1 | LL | const BAR: *mut i32 = unsafe { intrinsics::const_allocate(4, 4) as *mut i32 }; | ^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #122153 -note: the lint level is defined here - --> $DIR/alloc_intrinsic_untyped.rs:4:9 - | -LL | #![deny(const_eval_mutable_ptr_in_final_value)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 1 previous error -Future incompatibility report: Future breakage diagnostic: -error: encountered mutable pointer in final value of constant - --> $DIR/alloc_intrinsic_untyped.rs:7:1 - | -LL | const BAR: *mut i32 = unsafe { intrinsics::const_allocate(4, 4) as *mut i32 }; - | ^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #122153 -note: the lint level is defined here - --> $DIR/alloc_intrinsic_untyped.rs:4:9 - | -LL | #![deny(const_eval_mutable_ptr_in_final_value)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - diff --git a/tests/ui/consts/future-incompat-mutable-in-final-value-issue-121610.rs b/tests/ui/consts/future-incompat-mutable-in-final-value-issue-121610.rs deleted file mode 100644 index ca119f831b145..0000000000000 --- a/tests/ui/consts/future-incompat-mutable-in-final-value-issue-121610.rs +++ /dev/null @@ -1,18 +0,0 @@ -//@ check-pass -use std::cell::Cell; - -pub enum JsValue { - Undefined, - Object(Cell), -} - -impl ::std::ops::Drop for JsValue { - fn drop(&mut self) {} -} - -const UNDEFINED: &JsValue = &JsValue::Undefined; - //~^ WARN encountered mutable pointer in final value of constant - //~| WARN this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - -fn main() { -} diff --git a/tests/ui/consts/future-incompat-mutable-in-final-value-issue-121610.stderr b/tests/ui/consts/future-incompat-mutable-in-final-value-issue-121610.stderr deleted file mode 100644 index 85de4e7ff32e1..0000000000000 --- a/tests/ui/consts/future-incompat-mutable-in-final-value-issue-121610.stderr +++ /dev/null @@ -1,23 +0,0 @@ -warning: encountered mutable pointer in final value of constant - --> $DIR/future-incompat-mutable-in-final-value-issue-121610.rs:13:1 - | -LL | const UNDEFINED: &JsValue = &JsValue::Undefined; - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #122153 - = note: `#[warn(const_eval_mutable_ptr_in_final_value)]` on by default - -warning: 1 warning emitted - -Future incompatibility report: Future breakage diagnostic: -warning: encountered mutable pointer in final value of constant - --> $DIR/future-incompat-mutable-in-final-value-issue-121610.rs:13:1 - | -LL | const UNDEFINED: &JsValue = &JsValue::Undefined; - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #122153 - = note: `#[warn(const_eval_mutable_ptr_in_final_value)]` on by default - diff --git a/tests/ui/consts/miri_unleashed/mutable_references.rs b/tests/ui/consts/miri_unleashed/mutable_references.rs index 7e759a1a1e42e..6ac61e6700160 100644 --- a/tests/ui/consts/miri_unleashed/mutable_references.rs +++ b/tests/ui/consts/miri_unleashed/mutable_references.rs @@ -3,7 +3,6 @@ //@ normalize-stderr-test: "([0-9a-f][0-9a-f] |╾─*ALLOC[0-9]+(\+[a-z0-9]+)?()?─*╼ )+ *│.*" -> "HEX_DUMP" #![allow(static_mut_refs)] -#![deny(const_eval_mutable_ptr_in_final_value)] use std::cell::UnsafeCell; use std::sync::atomic::*; @@ -18,13 +17,11 @@ static OH_YES: &mut i32 = &mut 42; //~| pointing to read-only memory static BAR: &mut () = &mut (); //~^ ERROR encountered mutable pointer in final value of static -//~| WARNING this was previously accepted by the compiler struct Foo(T); static BOO: &mut Foo<()> = &mut Foo(()); //~^ ERROR encountered mutable pointer in final value of static -//~| WARNING this was previously accepted by the compiler const BLUNT: &mut i32 = &mut 42; //~^ ERROR: it is undefined behavior to use this value @@ -81,36 +78,32 @@ const POINTS_TO_MUTABLE2: &i32 = unsafe { &*MUTABLE_REF }; const POINTS_TO_MUTABLE_INNER: *const i32 = &mut 42 as *mut _ as *const _; //~^ ERROR: mutable pointer in final value -//~| WARNING this was previously accepted by the compiler const POINTS_TO_MUTABLE_INNER2: *const i32 = &mut 42 as *const _; //~^ ERROR: mutable pointer in final value -//~| WARNING this was previously accepted by the compiler +// This does *not* error since it uses a shared reference, and we have to ignore +// those. See . const INTERIOR_MUTABLE_BEHIND_RAW: *mut i32 = &UnsafeCell::new(42) as *const _ as *mut _; -//~^ ERROR: mutable pointer in final value -//~| WARNING this was previously accepted by the compiler struct SyncPtr { x: *const T, } unsafe impl Sync for SyncPtr {} -// These pass the lifetime checks because of the "tail expression" / "outer scope" rule. -// (This relies on `SyncPtr` being a curly brace struct.) -// However, we intern the inner memory as read-only, so this must be rejected. +// These pass the lifetime checks because of the "tail expression" / "outer scope" rule. (This +// relies on `SyncPtr` being a curly brace struct.) However, we intern the inner memory as +// read-only, so ideally this should be rejected. Unfortunately, as explained in +// , we have to accept it. // (Also see `static-no-inner-mut` for similar tests on `static`.) const RAW_SYNC: SyncPtr = SyncPtr { x: &AtomicI32::new(42) }; -//~^ ERROR mutable pointer in final value -//~| WARNING this was previously accepted by the compiler +// With mutable references at least, we can detect this and error. const RAW_MUT_CAST: SyncPtr = SyncPtr { x: &mut 42 as *mut _ as *const _ }; //~^ ERROR mutable pointer in final value -//~| WARNING this was previously accepted by the compiler const RAW_MUT_COERCE: SyncPtr = SyncPtr { x: &mut 0 }; //~^ ERROR mutable pointer in final value -//~| WARNING this was previously accepted by the compiler fn main() { diff --git a/tests/ui/consts/miri_unleashed/mutable_references.stderr b/tests/ui/consts/miri_unleashed/mutable_references.stderr index 620953ffa3e2e..793cbac687915 100644 --- a/tests/ui/consts/miri_unleashed/mutable_references.stderr +++ b/tests/ui/consts/miri_unleashed/mutable_references.stderr @@ -1,5 +1,5 @@ error[E0080]: it is undefined behavior to use this value - --> $DIR/mutable_references.rs:13:1 + --> $DIR/mutable_references.rs:12:1 | LL | static FOO: &&mut u32 = &&mut 42; | ^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .: encountered mutable reference or box pointing to read-only memory @@ -10,7 +10,7 @@ LL | static FOO: &&mut u32 = &&mut 42; } error[E0080]: it is undefined behavior to use this value - --> $DIR/mutable_references.rs:16:1 + --> $DIR/mutable_references.rs:15:1 | LL | static OH_YES: &mut i32 = &mut 42; | ^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered mutable reference or box pointing to read-only memory @@ -21,30 +21,19 @@ LL | static OH_YES: &mut i32 = &mut 42; } error: encountered mutable pointer in final value of static - --> $DIR/mutable_references.rs:19:1 + --> $DIR/mutable_references.rs:18:1 | LL | static BAR: &mut () = &mut (); | ^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #122153 -note: the lint level is defined here - --> $DIR/mutable_references.rs:6:9 - | -LL | #![deny(const_eval_mutable_ptr_in_final_value)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: encountered mutable pointer in final value of static - --> $DIR/mutable_references.rs:25:1 + --> $DIR/mutable_references.rs:23:1 | LL | static BOO: &mut Foo<()> = &mut Foo(()); | ^^^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #122153 error[E0080]: it is undefined behavior to use this value - --> $DIR/mutable_references.rs:29:1 + --> $DIR/mutable_references.rs:26:1 | LL | const BLUNT: &mut i32 = &mut 42; | ^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered mutable reference or box pointing to read-only memory @@ -55,7 +44,7 @@ LL | const BLUNT: &mut i32 = &mut 42; } error[E0080]: it is undefined behavior to use this value - --> $DIR/mutable_references.rs:33:1 + --> $DIR/mutable_references.rs:30:1 | LL | const SUBTLE: &mut i32 = unsafe { static mut STATIC: i32 = 0; &mut STATIC }; | ^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered reference to mutable memory in `const` @@ -66,7 +55,7 @@ LL | const SUBTLE: &mut i32 = unsafe { static mut STATIC: i32 = 0; &mut STATIC } } error[E0080]: it is undefined behavior to use this value - --> $DIR/mutable_references.rs:43:1 + --> $DIR/mutable_references.rs:40:1 | LL | static MEH: Meh = Meh { x: &UnsafeCell::new(42) }; | ^^^^^^^^^^^^^^^ constructing invalid value at .x.: encountered `UnsafeCell` in read-only memory @@ -77,7 +66,7 @@ LL | static MEH: Meh = Meh { x: &UnsafeCell::new(42) }; } error[E0080]: it is undefined behavior to use this value - --> $DIR/mutable_references.rs:49:1 + --> $DIR/mutable_references.rs:46:1 | LL | const MUH: Meh = Meh { | ^^^^^^^^^^^^^^ constructing invalid value at .x.: encountered `UnsafeCell` in read-only memory @@ -88,7 +77,7 @@ LL | const MUH: Meh = Meh { } error[E0080]: it is undefined behavior to use this value - --> $DIR/mutable_references.rs:61:1 + --> $DIR/mutable_references.rs:58:1 | LL | const SNEAKY: &dyn Sync = &Synced { x: UnsafeCell::new(42) }; | ^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at ...x: encountered `UnsafeCell` in read-only memory @@ -99,7 +88,7 @@ LL | const SNEAKY: &dyn Sync = &Synced { x: UnsafeCell::new(42) }; } error[E0080]: it is undefined behavior to use this value - --> $DIR/mutable_references.rs:68:1 + --> $DIR/mutable_references.rs:65:1 | LL | static mut MUT_TO_READONLY: &mut i32 = unsafe { &mut *(&READONLY as *const _ as *mut _) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered mutable reference or box pointing to read-only memory @@ -110,7 +99,7 @@ LL | static mut MUT_TO_READONLY: &mut i32 = unsafe { &mut *(&READONLY as *const } error[E0080]: it is undefined behavior to use this value - --> $DIR/mutable_references.rs:75:1 + --> $DIR/mutable_references.rs:72:1 | LL | const POINTS_TO_MUTABLE: &i32 = unsafe { &MUTABLE }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered reference to mutable memory in `const` @@ -121,67 +110,37 @@ LL | const POINTS_TO_MUTABLE: &i32 = unsafe { &MUTABLE }; } error[E0080]: evaluation of constant value failed - --> $DIR/mutable_references.rs:78:43 + --> $DIR/mutable_references.rs:75:43 | LL | const POINTS_TO_MUTABLE2: &i32 = unsafe { &*MUTABLE_REF }; | ^^^^^^^^^^^^^ constant accesses mutable global memory error: encountered mutable pointer in final value of constant - --> $DIR/mutable_references.rs:82:1 + --> $DIR/mutable_references.rs:79:1 | LL | const POINTS_TO_MUTABLE_INNER: *const i32 = &mut 42 as *mut _ as *const _; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #122153 error: encountered mutable pointer in final value of constant - --> $DIR/mutable_references.rs:86:1 + --> $DIR/mutable_references.rs:82:1 | LL | const POINTS_TO_MUTABLE_INNER2: *const i32 = &mut 42 as *const _; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #122153 - -error: encountered mutable pointer in final value of constant - --> $DIR/mutable_references.rs:90:1 - | -LL | const INTERIOR_MUTABLE_BEHIND_RAW: *mut i32 = &UnsafeCell::new(42) as *const _ as *mut _; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #122153 - -error: encountered mutable pointer in final value of constant - --> $DIR/mutable_references.rs:103:1 - | -LL | const RAW_SYNC: SyncPtr = SyncPtr { x: &AtomicI32::new(42) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #122153 error: encountered mutable pointer in final value of constant - --> $DIR/mutable_references.rs:107:1 + --> $DIR/mutable_references.rs:102:1 | LL | const RAW_MUT_CAST: SyncPtr = SyncPtr { x: &mut 42 as *mut _ as *const _ }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #122153 error: encountered mutable pointer in final value of constant - --> $DIR/mutable_references.rs:111:1 + --> $DIR/mutable_references.rs:105:1 | LL | const RAW_MUT_COERCE: SyncPtr = SyncPtr { x: &mut 0 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #122153 error[E0594]: cannot assign to `*OH_YES`, as `OH_YES` is an immutable static item - --> $DIR/mutable_references.rs:120:5 + --> $DIR/mutable_references.rs:113:5 | LL | *OH_YES = 99; | ^^^^^^^^^^^^ cannot assign @@ -189,227 +148,107 @@ LL | *OH_YES = 99; warning: skipping const checks | help: skipping check that does not even have a feature gate - --> $DIR/mutable_references.rs:13:26 + --> $DIR/mutable_references.rs:12:26 | LL | static FOO: &&mut u32 = &&mut 42; | ^^^^^^^ help: skipping check that does not even have a feature gate - --> $DIR/mutable_references.rs:16:27 + --> $DIR/mutable_references.rs:15:27 | LL | static OH_YES: &mut i32 = &mut 42; | ^^^^^^^ help: skipping check that does not even have a feature gate - --> $DIR/mutable_references.rs:19:23 + --> $DIR/mutable_references.rs:18:23 | LL | static BAR: &mut () = &mut (); | ^^^^^^^ help: skipping check that does not even have a feature gate - --> $DIR/mutable_references.rs:25:28 + --> $DIR/mutable_references.rs:23:28 | LL | static BOO: &mut Foo<()> = &mut Foo(()); | ^^^^^^^^^^^^ help: skipping check that does not even have a feature gate - --> $DIR/mutable_references.rs:29:25 + --> $DIR/mutable_references.rs:26:25 | LL | const BLUNT: &mut i32 = &mut 42; | ^^^^^^^ help: skipping check for `const_refs_to_static` feature - --> $DIR/mutable_references.rs:33:68 + --> $DIR/mutable_references.rs:30:68 | LL | const SUBTLE: &mut i32 = unsafe { static mut STATIC: i32 = 0; &mut STATIC }; | ^^^^^^ help: skipping check for `const_mut_refs` feature - --> $DIR/mutable_references.rs:33:63 + --> $DIR/mutable_references.rs:30:63 | LL | const SUBTLE: &mut i32 = unsafe { static mut STATIC: i32 = 0; &mut STATIC }; | ^^^^^^^^^^^ help: skipping check that does not even have a feature gate - --> $DIR/mutable_references.rs:43:28 + --> $DIR/mutable_references.rs:40:28 | LL | static MEH: Meh = Meh { x: &UnsafeCell::new(42) }; | ^^^^^^^^^^^^^^^^^^^^ help: skipping check that does not even have a feature gate - --> $DIR/mutable_references.rs:52:8 + --> $DIR/mutable_references.rs:49:8 | LL | x: &UnsafeCell::new(42), | ^^^^^^^^^^^^^^^^^^^^ help: skipping check that does not even have a feature gate - --> $DIR/mutable_references.rs:61:27 + --> $DIR/mutable_references.rs:58:27 | LL | const SNEAKY: &dyn Sync = &Synced { x: UnsafeCell::new(42) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: skipping check for `const_mut_refs` feature - --> $DIR/mutable_references.rs:68:49 + --> $DIR/mutable_references.rs:65:49 | LL | static mut MUT_TO_READONLY: &mut i32 = unsafe { &mut *(&READONLY as *const _ as *mut _) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: skipping check for `const_mut_refs` feature - --> $DIR/mutable_references.rs:68:49 + --> $DIR/mutable_references.rs:65:49 | LL | static mut MUT_TO_READONLY: &mut i32 = unsafe { &mut *(&READONLY as *const _ as *mut _) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: skipping check for `const_refs_to_static` feature - --> $DIR/mutable_references.rs:75:43 + --> $DIR/mutable_references.rs:72:43 | LL | const POINTS_TO_MUTABLE: &i32 = unsafe { &MUTABLE }; | ^^^^^^^ help: skipping check for `const_refs_to_static` feature - --> $DIR/mutable_references.rs:78:45 + --> $DIR/mutable_references.rs:75:45 | LL | const POINTS_TO_MUTABLE2: &i32 = unsafe { &*MUTABLE_REF }; | ^^^^^^^^^^^ help: skipping check that does not even have a feature gate - --> $DIR/mutable_references.rs:82:45 + --> $DIR/mutable_references.rs:79:45 | LL | const POINTS_TO_MUTABLE_INNER: *const i32 = &mut 42 as *mut _ as *const _; | ^^^^^^^ help: skipping check that does not even have a feature gate - --> $DIR/mutable_references.rs:86:46 + --> $DIR/mutable_references.rs:82:46 | LL | const POINTS_TO_MUTABLE_INNER2: *const i32 = &mut 42 as *const _; | ^^^^^^^ help: skipping check that does not even have a feature gate - --> $DIR/mutable_references.rs:90:47 + --> $DIR/mutable_references.rs:87:47 | LL | const INTERIOR_MUTABLE_BEHIND_RAW: *mut i32 = &UnsafeCell::new(42) as *const _ as *mut _; | ^^^^^^^^^^^^^^^^^^^^ help: skipping check that does not even have a feature gate - --> $DIR/mutable_references.rs:103:51 + --> $DIR/mutable_references.rs:99:51 | LL | const RAW_SYNC: SyncPtr = SyncPtr { x: &AtomicI32::new(42) }; | ^^^^^^^^^^^^^^^^^^^ help: skipping check that does not even have a feature gate - --> $DIR/mutable_references.rs:107:49 + --> $DIR/mutable_references.rs:102:49 | LL | const RAW_MUT_CAST: SyncPtr = SyncPtr { x: &mut 42 as *mut _ as *const _ }; | ^^^^^^^ help: skipping check that does not even have a feature gate - --> $DIR/mutable_references.rs:111:51 + --> $DIR/mutable_references.rs:105:51 | LL | const RAW_MUT_COERCE: SyncPtr = SyncPtr { x: &mut 0 }; | ^^^^^^ -error: aborting due to 19 previous errors; 1 warning emitted +error: aborting due to 17 previous errors; 1 warning emitted Some errors have detailed explanations: E0080, E0594. For more information about an error, try `rustc --explain E0080`. -Future incompatibility report: Future breakage diagnostic: -error: encountered mutable pointer in final value of static - --> $DIR/mutable_references.rs:19:1 - | -LL | static BAR: &mut () = &mut (); - | ^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #122153 -note: the lint level is defined here - --> $DIR/mutable_references.rs:6:9 - | -LL | #![deny(const_eval_mutable_ptr_in_final_value)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -Future breakage diagnostic: -error: encountered mutable pointer in final value of static - --> $DIR/mutable_references.rs:25:1 - | -LL | static BOO: &mut Foo<()> = &mut Foo(()); - | ^^^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #122153 -note: the lint level is defined here - --> $DIR/mutable_references.rs:6:9 - | -LL | #![deny(const_eval_mutable_ptr_in_final_value)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -Future breakage diagnostic: -error: encountered mutable pointer in final value of constant - --> $DIR/mutable_references.rs:82:1 - | -LL | const POINTS_TO_MUTABLE_INNER: *const i32 = &mut 42 as *mut _ as *const _; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #122153 -note: the lint level is defined here - --> $DIR/mutable_references.rs:6:9 - | -LL | #![deny(const_eval_mutable_ptr_in_final_value)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -Future breakage diagnostic: -error: encountered mutable pointer in final value of constant - --> $DIR/mutable_references.rs:86:1 - | -LL | const POINTS_TO_MUTABLE_INNER2: *const i32 = &mut 42 as *const _; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #122153 -note: the lint level is defined here - --> $DIR/mutable_references.rs:6:9 - | -LL | #![deny(const_eval_mutable_ptr_in_final_value)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -Future breakage diagnostic: -error: encountered mutable pointer in final value of constant - --> $DIR/mutable_references.rs:90:1 - | -LL | const INTERIOR_MUTABLE_BEHIND_RAW: *mut i32 = &UnsafeCell::new(42) as *const _ as *mut _; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #122153 -note: the lint level is defined here - --> $DIR/mutable_references.rs:6:9 - | -LL | #![deny(const_eval_mutable_ptr_in_final_value)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -Future breakage diagnostic: -error: encountered mutable pointer in final value of constant - --> $DIR/mutable_references.rs:103:1 - | -LL | const RAW_SYNC: SyncPtr = SyncPtr { x: &AtomicI32::new(42) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #122153 -note: the lint level is defined here - --> $DIR/mutable_references.rs:6:9 - | -LL | #![deny(const_eval_mutable_ptr_in_final_value)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -Future breakage diagnostic: -error: encountered mutable pointer in final value of constant - --> $DIR/mutable_references.rs:107:1 - | -LL | const RAW_MUT_CAST: SyncPtr = SyncPtr { x: &mut 42 as *mut _ as *const _ }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #122153 -note: the lint level is defined here - --> $DIR/mutable_references.rs:6:9 - | -LL | #![deny(const_eval_mutable_ptr_in_final_value)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -Future breakage diagnostic: -error: encountered mutable pointer in final value of constant - --> $DIR/mutable_references.rs:111:1 - | -LL | const RAW_MUT_COERCE: SyncPtr = SyncPtr { x: &mut 0 }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #122153 -note: the lint level is defined here - --> $DIR/mutable_references.rs:6:9 - | -LL | #![deny(const_eval_mutable_ptr_in_final_value)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - diff --git a/tests/ui/consts/miri_unleashed/static-no-inner-mut.32bit.stderr b/tests/ui/consts/miri_unleashed/static-no-inner-mut.32bit.stderr index 1e554f6bac375..88a734bc241eb 100644 --- a/tests/ui/consts/miri_unleashed/static-no-inner-mut.32bit.stderr +++ b/tests/ui/consts/miri_unleashed/static-no-inner-mut.32bit.stderr @@ -1,5 +1,5 @@ error[E0080]: it is undefined behavior to use this value - --> $DIR/static-no-inner-mut.rs:9:1 + --> $DIR/static-no-inner-mut.rs:8:1 | LL | static REF: &AtomicI32 = &AtomicI32::new(42); | ^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at ..v: encountered `UnsafeCell` in read-only memory @@ -10,7 +10,7 @@ LL | static REF: &AtomicI32 = &AtomicI32::new(42); } error[E0080]: it is undefined behavior to use this value - --> $DIR/static-no-inner-mut.rs:12:1 + --> $DIR/static-no-inner-mut.rs:11:1 | LL | static REFMUT: &mut i32 = &mut 0; | ^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered mutable reference or box pointing to read-only memory @@ -21,7 +21,7 @@ LL | static REFMUT: &mut i32 = &mut 0; } error[E0080]: it is undefined behavior to use this value - --> $DIR/static-no-inner-mut.rs:16:1 + --> $DIR/static-no-inner-mut.rs:15:1 | LL | static REF2: &AtomicI32 = {let x = AtomicI32::new(42); &{x}}; | ^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at ..v: encountered `UnsafeCell` in read-only memory @@ -32,7 +32,7 @@ LL | static REF2: &AtomicI32 = {let x = AtomicI32::new(42); &{x}}; } error[E0080]: it is undefined behavior to use this value - --> $DIR/static-no-inner-mut.rs:18:1 + --> $DIR/static-no-inner-mut.rs:17:1 | LL | static REFMUT2: &mut i32 = {let mut x = 0; &mut {x}}; | ^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered mutable reference or box pointing to read-only memory @@ -45,118 +45,53 @@ LL | static REFMUT2: &mut i32 = {let mut x = 0; &mut {x}}; error: encountered mutable pointer in final value of static --> $DIR/static-no-inner-mut.rs:34:1 | -LL | static RAW_SYNC: SyncPtr = SyncPtr { x: &AtomicI32::new(42) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #122153 -note: the lint level is defined here - --> $DIR/static-no-inner-mut.rs:6:9 - | -LL | #![deny(const_eval_mutable_ptr_in_final_value)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: encountered mutable pointer in final value of static - --> $DIR/static-no-inner-mut.rs:38:1 - | LL | static RAW_MUT_CAST: SyncPtr = SyncPtr { x : &mut 42 as *mut _ as *const _ }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #122153 error: encountered mutable pointer in final value of static - --> $DIR/static-no-inner-mut.rs:42:1 + --> $DIR/static-no-inner-mut.rs:37:1 | LL | static RAW_MUT_COERCE: SyncPtr = SyncPtr { x: &mut 0 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #122153 warning: skipping const checks | help: skipping check that does not even have a feature gate - --> $DIR/static-no-inner-mut.rs:9:26 + --> $DIR/static-no-inner-mut.rs:8:26 | LL | static REF: &AtomicI32 = &AtomicI32::new(42); | ^^^^^^^^^^^^^^^^^^^ help: skipping check that does not even have a feature gate - --> $DIR/static-no-inner-mut.rs:12:27 + --> $DIR/static-no-inner-mut.rs:11:27 | LL | static REFMUT: &mut i32 = &mut 0; | ^^^^^^ help: skipping check that does not even have a feature gate - --> $DIR/static-no-inner-mut.rs:16:56 + --> $DIR/static-no-inner-mut.rs:15:56 | LL | static REF2: &AtomicI32 = {let x = AtomicI32::new(42); &{x}}; | ^^^^ help: skipping check that does not even have a feature gate - --> $DIR/static-no-inner-mut.rs:18:44 + --> $DIR/static-no-inner-mut.rs:17:44 | LL | static REFMUT2: &mut i32 = {let mut x = 0; &mut {x}}; | ^^^^^^^^ help: skipping check that does not even have a feature gate - --> $DIR/static-no-inner-mut.rs:34:52 + --> $DIR/static-no-inner-mut.rs:31:52 | LL | static RAW_SYNC: SyncPtr = SyncPtr { x: &AtomicI32::new(42) }; | ^^^^^^^^^^^^^^^^^^^ help: skipping check that does not even have a feature gate - --> $DIR/static-no-inner-mut.rs:38:51 + --> $DIR/static-no-inner-mut.rs:34:51 | LL | static RAW_MUT_CAST: SyncPtr = SyncPtr { x : &mut 42 as *mut _ as *const _ }; | ^^^^^^^ help: skipping check that does not even have a feature gate - --> $DIR/static-no-inner-mut.rs:42:52 + --> $DIR/static-no-inner-mut.rs:37:52 | LL | static RAW_MUT_COERCE: SyncPtr = SyncPtr { x: &mut 0 }; | ^^^^^^ -error: aborting due to 7 previous errors; 1 warning emitted +error: aborting due to 6 previous errors; 1 warning emitted For more information about this error, try `rustc --explain E0080`. -Future incompatibility report: Future breakage diagnostic: -error: encountered mutable pointer in final value of static - --> $DIR/static-no-inner-mut.rs:34:1 - | -LL | static RAW_SYNC: SyncPtr = SyncPtr { x: &AtomicI32::new(42) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #122153 -note: the lint level is defined here - --> $DIR/static-no-inner-mut.rs:6:9 - | -LL | #![deny(const_eval_mutable_ptr_in_final_value)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -Future breakage diagnostic: -error: encountered mutable pointer in final value of static - --> $DIR/static-no-inner-mut.rs:38:1 - | -LL | static RAW_MUT_CAST: SyncPtr = SyncPtr { x : &mut 42 as *mut _ as *const _ }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #122153 -note: the lint level is defined here - --> $DIR/static-no-inner-mut.rs:6:9 - | -LL | #![deny(const_eval_mutable_ptr_in_final_value)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -Future breakage diagnostic: -error: encountered mutable pointer in final value of static - --> $DIR/static-no-inner-mut.rs:42:1 - | -LL | static RAW_MUT_COERCE: SyncPtr = SyncPtr { x: &mut 0 }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #122153 -note: the lint level is defined here - --> $DIR/static-no-inner-mut.rs:6:9 - | -LL | #![deny(const_eval_mutable_ptr_in_final_value)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - diff --git a/tests/ui/consts/miri_unleashed/static-no-inner-mut.64bit.stderr b/tests/ui/consts/miri_unleashed/static-no-inner-mut.64bit.stderr index 84ed631fcdab3..c4f3903e14331 100644 --- a/tests/ui/consts/miri_unleashed/static-no-inner-mut.64bit.stderr +++ b/tests/ui/consts/miri_unleashed/static-no-inner-mut.64bit.stderr @@ -1,5 +1,5 @@ error[E0080]: it is undefined behavior to use this value - --> $DIR/static-no-inner-mut.rs:9:1 + --> $DIR/static-no-inner-mut.rs:8:1 | LL | static REF: &AtomicI32 = &AtomicI32::new(42); | ^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at ..v: encountered `UnsafeCell` in read-only memory @@ -10,7 +10,7 @@ LL | static REF: &AtomicI32 = &AtomicI32::new(42); } error[E0080]: it is undefined behavior to use this value - --> $DIR/static-no-inner-mut.rs:12:1 + --> $DIR/static-no-inner-mut.rs:11:1 | LL | static REFMUT: &mut i32 = &mut 0; | ^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered mutable reference or box pointing to read-only memory @@ -21,7 +21,7 @@ LL | static REFMUT: &mut i32 = &mut 0; } error[E0080]: it is undefined behavior to use this value - --> $DIR/static-no-inner-mut.rs:16:1 + --> $DIR/static-no-inner-mut.rs:15:1 | LL | static REF2: &AtomicI32 = {let x = AtomicI32::new(42); &{x}}; | ^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at ..v: encountered `UnsafeCell` in read-only memory @@ -32,7 +32,7 @@ LL | static REF2: &AtomicI32 = {let x = AtomicI32::new(42); &{x}}; } error[E0080]: it is undefined behavior to use this value - --> $DIR/static-no-inner-mut.rs:18:1 + --> $DIR/static-no-inner-mut.rs:17:1 | LL | static REFMUT2: &mut i32 = {let mut x = 0; &mut {x}}; | ^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered mutable reference or box pointing to read-only memory @@ -45,118 +45,53 @@ LL | static REFMUT2: &mut i32 = {let mut x = 0; &mut {x}}; error: encountered mutable pointer in final value of static --> $DIR/static-no-inner-mut.rs:34:1 | -LL | static RAW_SYNC: SyncPtr = SyncPtr { x: &AtomicI32::new(42) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #122153 -note: the lint level is defined here - --> $DIR/static-no-inner-mut.rs:6:9 - | -LL | #![deny(const_eval_mutable_ptr_in_final_value)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: encountered mutable pointer in final value of static - --> $DIR/static-no-inner-mut.rs:38:1 - | LL | static RAW_MUT_CAST: SyncPtr = SyncPtr { x : &mut 42 as *mut _ as *const _ }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #122153 error: encountered mutable pointer in final value of static - --> $DIR/static-no-inner-mut.rs:42:1 + --> $DIR/static-no-inner-mut.rs:37:1 | LL | static RAW_MUT_COERCE: SyncPtr = SyncPtr { x: &mut 0 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #122153 warning: skipping const checks | help: skipping check that does not even have a feature gate - --> $DIR/static-no-inner-mut.rs:9:26 + --> $DIR/static-no-inner-mut.rs:8:26 | LL | static REF: &AtomicI32 = &AtomicI32::new(42); | ^^^^^^^^^^^^^^^^^^^ help: skipping check that does not even have a feature gate - --> $DIR/static-no-inner-mut.rs:12:27 + --> $DIR/static-no-inner-mut.rs:11:27 | LL | static REFMUT: &mut i32 = &mut 0; | ^^^^^^ help: skipping check that does not even have a feature gate - --> $DIR/static-no-inner-mut.rs:16:56 + --> $DIR/static-no-inner-mut.rs:15:56 | LL | static REF2: &AtomicI32 = {let x = AtomicI32::new(42); &{x}}; | ^^^^ help: skipping check that does not even have a feature gate - --> $DIR/static-no-inner-mut.rs:18:44 + --> $DIR/static-no-inner-mut.rs:17:44 | LL | static REFMUT2: &mut i32 = {let mut x = 0; &mut {x}}; | ^^^^^^^^ help: skipping check that does not even have a feature gate - --> $DIR/static-no-inner-mut.rs:34:52 + --> $DIR/static-no-inner-mut.rs:31:52 | LL | static RAW_SYNC: SyncPtr = SyncPtr { x: &AtomicI32::new(42) }; | ^^^^^^^^^^^^^^^^^^^ help: skipping check that does not even have a feature gate - --> $DIR/static-no-inner-mut.rs:38:51 + --> $DIR/static-no-inner-mut.rs:34:51 | LL | static RAW_MUT_CAST: SyncPtr = SyncPtr { x : &mut 42 as *mut _ as *const _ }; | ^^^^^^^ help: skipping check that does not even have a feature gate - --> $DIR/static-no-inner-mut.rs:42:52 + --> $DIR/static-no-inner-mut.rs:37:52 | LL | static RAW_MUT_COERCE: SyncPtr = SyncPtr { x: &mut 0 }; | ^^^^^^ -error: aborting due to 7 previous errors; 1 warning emitted +error: aborting due to 6 previous errors; 1 warning emitted For more information about this error, try `rustc --explain E0080`. -Future incompatibility report: Future breakage diagnostic: -error: encountered mutable pointer in final value of static - --> $DIR/static-no-inner-mut.rs:34:1 - | -LL | static RAW_SYNC: SyncPtr = SyncPtr { x: &AtomicI32::new(42) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #122153 -note: the lint level is defined here - --> $DIR/static-no-inner-mut.rs:6:9 - | -LL | #![deny(const_eval_mutable_ptr_in_final_value)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -Future breakage diagnostic: -error: encountered mutable pointer in final value of static - --> $DIR/static-no-inner-mut.rs:38:1 - | -LL | static RAW_MUT_CAST: SyncPtr = SyncPtr { x : &mut 42 as *mut _ as *const _ }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #122153 -note: the lint level is defined here - --> $DIR/static-no-inner-mut.rs:6:9 - | -LL | #![deny(const_eval_mutable_ptr_in_final_value)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -Future breakage diagnostic: -error: encountered mutable pointer in final value of static - --> $DIR/static-no-inner-mut.rs:42:1 - | -LL | static RAW_MUT_COERCE: SyncPtr = SyncPtr { x: &mut 0 }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #122153 -note: the lint level is defined here - --> $DIR/static-no-inner-mut.rs:6:9 - | -LL | #![deny(const_eval_mutable_ptr_in_final_value)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - diff --git a/tests/ui/consts/miri_unleashed/static-no-inner-mut.rs b/tests/ui/consts/miri_unleashed/static-no-inner-mut.rs index 810760319c1bc..2b8f32deda7d7 100644 --- a/tests/ui/consts/miri_unleashed/static-no-inner-mut.rs +++ b/tests/ui/consts/miri_unleashed/static-no-inner-mut.rs @@ -3,7 +3,6 @@ #![feature(const_refs_to_cell, const_mut_refs)] // All "inner" allocations that come with a `static` are interned immutably. This means it is // crucial that we do not accept any form of (interior) mutability there. -#![deny(const_eval_mutable_ptr_in_final_value)] use std::sync::atomic::*; static REF: &AtomicI32 = &AtomicI32::new(42); @@ -27,20 +26,15 @@ unsafe impl Sync for SyncPtr {} // All of these pass the lifetime checks because of the "tail expression" / "outer scope" rule. // (This relies on `SyncPtr` being a curly brace struct.) -// Then they get interned immutably, which is not great. -// `mut_ref_in_final.rs` and `std/cell.rs` ensure that we don't accept this even with the feature -// fate, but for unleashed Miri there's not really any way we can reject them: it's just -// non-dangling raw pointers. +// Then they get interned immutably, which is not great. See +// for why we accept such code. static RAW_SYNC: SyncPtr = SyncPtr { x: &AtomicI32::new(42) }; -//~^ ERROR mutable pointer in final value -//~| WARNING this was previously accepted by the compiler +// With mutable references at least, we can detect this and error. static RAW_MUT_CAST: SyncPtr = SyncPtr { x : &mut 42 as *mut _ as *const _ }; //~^ ERROR mutable pointer in final value -//~| WARNING this was previously accepted by the compiler static RAW_MUT_COERCE: SyncPtr = SyncPtr { x: &mut 0 }; //~^ ERROR mutable pointer in final value -//~| WARNING this was previously accepted by the compiler fn main() {} diff --git a/tests/ui/consts/refs-to-cell-in-final.rs b/tests/ui/consts/refs-to-cell-in-final.rs index c7ccd25fc4cb7..cfb458e7ace22 100644 --- a/tests/ui/consts/refs-to-cell-in-final.rs +++ b/tests/ui/consts/refs-to-cell-in-final.rs @@ -18,8 +18,8 @@ const RAW_SYNC_C: SyncPtr> = SyncPtr { x: &Cell::new(42) }; // This one does not get promoted because of `Drop`, and then enters interesting codepaths because // as a value it has no interior mutability, but as a type it does. See // . Value-based reasoning for interior mutability -// is questionable (https://github.com/rust-lang/unsafe-code-guidelines/issues/493) so for now we -// reject this, though not with a great error message. +// is questionable (https://github.com/rust-lang/unsafe-code-guidelines/issues/493) but we've +// done it since Rust 1.0 so we can't stop now. pub enum JsValue { Undefined, Object(Cell), @@ -28,10 +28,8 @@ impl Drop for JsValue { fn drop(&mut self) {} } const UNDEFINED: &JsValue = &JsValue::Undefined; -//~^ WARNING: mutable pointer in final value of constant -//~| WARNING: this was previously accepted by the compiler but is being phased out -// In contrast, this one works since it is being promoted. +// Here's a variant of the above that uses promotion instead of the "outer scope" rule. const NONE: &'static Option> = &None; // Making it clear that this is promotion, not "outer scope". const NONE_EXPLICIT_PROMOTED: &'static Option> = { diff --git a/tests/ui/consts/refs-to-cell-in-final.stderr b/tests/ui/consts/refs-to-cell-in-final.stderr index 2a7a858ebc9bf..fae16fa01251c 100644 --- a/tests/ui/consts/refs-to-cell-in-final.stderr +++ b/tests/ui/consts/refs-to-cell-in-final.stderr @@ -12,27 +12,6 @@ error[E0492]: constants cannot refer to interior mutable data LL | const RAW_SYNC_C: SyncPtr> = SyncPtr { x: &Cell::new(42) }; | ^^^^^^^^^^^^^^ this borrow of an interior mutable value may end up in the final value -warning: encountered mutable pointer in final value of constant - --> $DIR/refs-to-cell-in-final.rs:30:1 - | -LL | const UNDEFINED: &JsValue = &JsValue::Undefined; - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #122153 - = note: `#[warn(const_eval_mutable_ptr_in_final_value)]` on by default - -error: aborting due to 2 previous errors; 1 warning emitted +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0492`. -Future incompatibility report: Future breakage diagnostic: -warning: encountered mutable pointer in final value of constant - --> $DIR/refs-to-cell-in-final.rs:30:1 - | -LL | const UNDEFINED: &JsValue = &JsValue::Undefined; - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #122153 - = note: `#[warn(const_eval_mutable_ptr_in_final_value)]` on by default - From 123757ae07c05d8adafbe00d10b7119608ee13d9 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 18 Aug 2024 13:01:36 +0200 Subject: [PATCH 0787/2194] turn errors that should be impossible due to our static checks into ICEs --- .../rustc_const_eval/src/interpret/intern.rs | 52 ++++++++++++------- .../src/interpret/validity.rs | 9 +++- tests/crashes/const_mut_ref_check_bypass.rs | 11 ++++ .../heap/alloc_intrinsic_untyped.rs | 3 ++ .../heap/alloc_intrinsic_untyped.stderr | 2 +- 5 files changed, 55 insertions(+), 22 deletions(-) create mode 100644 tests/crashes/const_mut_ref_check_bypass.rs diff --git a/compiler/rustc_const_eval/src/interpret/intern.rs b/compiler/rustc_const_eval/src/interpret/intern.rs index e81431b45fb59..5df989b4c1d1e 100644 --- a/compiler/rustc_const_eval/src/interpret/intern.rs +++ b/compiler/rustc_const_eval/src/interpret/intern.rs @@ -20,6 +20,7 @@ use rustc_hir as hir; use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrs; use rustc_middle::mir::interpret::{ConstAllocation, CtfeProvenance, InterpResult}; use rustc_middle::query::TyCtxtAt; +use rustc_middle::span_bug; use rustc_middle::ty::layout::TyAndLayout; use rustc_span::def_id::LocalDefId; use rustc_span::sym; @@ -223,41 +224,52 @@ pub fn intern_const_alloc_recursive<'tcx, M: CompileTimeMachine<'tcx, const_eval continue; } - // Ensure that this is is derived from a shared reference. Crucially, we check this *before* + // Ensure that this is derived from a shared reference. Crucially, we check this *before* // checking whether the `alloc_id` has already been interned. The point of this check is to // ensure that when there are multiple pointers to the same allocation, they are *all* // derived from a shared reference. Therefore it would be bad if we only checked the first // pointer to any given allocation. // (It is likely not possible to actually have multiple pointers to the same allocation, // so alternatively we could also check that and ICE if there are multiple such pointers.) - // See for why we are checking for - // "shared reference" and not "immutable", i.e., for why we are allowed interior-mutable - // shared references: they can actually be created in safe code while pointing to apparently - // "immutable" values, via promotion of `&None::>`. + // See for why we are checking for "shared + // reference" and not "immutable", i.e., for why we are allowing interior-mutable shared + // references: they can actually be created in safe code while pointing to apparently + // "immutable" values, via promotion or tail expression lifetime extension of + // `&None::>`. + // We also exclude promoteds from this as `&mut []` can be promoted, which is a mutable + // reference pointing to an immutable (zero-sized) allocation. We rely on the promotion + // analysis not screwing up to ensure that it is sound to intern promoteds as immutable. if intern_kind != InternKind::Promoted && inner_mutability == Mutability::Not && !prov.shared_ref() { - if ecx.tcx.try_get_global_alloc(alloc_id).is_some() - && !just_interned.contains(&alloc_id) - { + let is_already_global = ecx.tcx.try_get_global_alloc(alloc_id).is_some(); + if is_already_global && !just_interned.contains(&alloc_id) { // This is a pointer to some memory from another constant. We encounter mutable // pointers to such memory since we do not always track immutability through // these "global" pointers. Allowing them is harmless; the point of these checks // during interning is to justify why we intern the *new* allocations immutably, - // so we can completely ignore existing allocations. We also don't need to add - // this to the todo list, since after all it is already interned. + // so we can completely ignore existing allocations. + // We can also skip the rest of this loop iteration, since after all it is already + // interned. continue; } - // Found a mutable reference inside a const where inner allocations should be - // immutable. We exclude promoteds from this, since things like `&mut []` and - // `&None::>` lead to promotion that can produce mutable pointers. We rely - // on the promotion analysis not screwing up to ensure that it is sound to intern - // promoteds as immutable. - trace!("found bad mutable pointer"); - // Prefer dangling pointer errors over mutable pointer errors - if result.is_ok() { - result = Err(InternResult::FoundBadMutablePointer); + // If this is a dangling pointer, that's actually fine -- the problematic case is + // when there is memory there that someone might expect to be mutable, but we make it immutable. + let dangling = !is_already_global && !ecx.memory.alloc_map.contains_key(&alloc_id); + if !dangling { + // Found a mutable reference inside a const where inner allocations should be + // immutable. + if !ecx.tcx.sess.opts.unstable_opts.unleash_the_miri_inside_of_you { + span_bug!( + ecx.tcx.span, + "the static const safety checks accepted mutable references they should not have accepted" + ); + } + // Prefer dangling pointer errors over mutable pointer errors + if result.is_ok() { + result = Err(InternResult::FoundBadMutablePointer); + } } } if ecx.tcx.try_get_global_alloc(alloc_id).is_some() { @@ -265,7 +277,6 @@ pub fn intern_const_alloc_recursive<'tcx, M: CompileTimeMachine<'tcx, const_eval debug_assert!(!ecx.memory.alloc_map.contains_key(&alloc_id)); continue; } - just_interned.insert(alloc_id); // We always intern with `inner_mutability`, and furthermore we ensured above that if // that is "immutable", then there are *no* mutable pointers anywhere in the newly // interned memory -- justifying that we can indeed intern immutably. However this also @@ -276,6 +287,7 @@ pub fn intern_const_alloc_recursive<'tcx, M: CompileTimeMachine<'tcx, const_eval // pointers before deciding which allocations can be made immutable; but for now we are // okay with losing some potential for immutability here. This can anyway only affect // `static mut`. + just_interned.insert(alloc_id); match intern_shallow(ecx, alloc_id, inner_mutability) { Ok(nested) => todo.extend(nested), Err(()) => { diff --git a/compiler/rustc_const_eval/src/interpret/validity.rs b/compiler/rustc_const_eval/src/interpret/validity.rs index fb24f983ca9c3..469af35ec1bd2 100644 --- a/compiler/rustc_const_eval/src/interpret/validity.rs +++ b/compiler/rustc_const_eval/src/interpret/validity.rs @@ -14,7 +14,6 @@ use hir::def::DefKind; use rustc_ast::Mutability; use rustc_data_structures::fx::FxHashSet; use rustc_hir as hir; -use rustc_middle::bug; use rustc_middle::mir::interpret::ValidationErrorKind::{self, *}; use rustc_middle::mir::interpret::{ alloc_range, ExpectedKind, InterpError, InvalidMetaKind, Misalignment, PointerKind, Provenance, @@ -22,6 +21,7 @@ use rustc_middle::mir::interpret::{ }; use rustc_middle::ty::layout::{LayoutCx, LayoutOf, TyAndLayout}; use rustc_middle::ty::{self, Ty, TyCtxt}; +use rustc_middle::{bug, span_bug}; use rustc_span::symbol::{sym, Symbol}; use rustc_target::abi::{ Abi, FieldIdx, FieldsShape, Scalar as ScalarAbi, Size, VariantIdx, Variants, WrappingRange, @@ -617,6 +617,13 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> { if ptr_expected_mutbl == Mutability::Mut && alloc_actual_mutbl == Mutability::Not { + if !self.ecx.tcx.sess.opts.unstable_opts.unleash_the_miri_inside_of_you + { + span_bug!( + self.ecx.tcx.span, + "the static const safety checks accepted mutable references they should not have accepted" + ); + } throw_validation_failure!(self.path, MutableRefToImmutable); } // In a const, everything must be completely immutable. diff --git a/tests/crashes/const_mut_ref_check_bypass.rs b/tests/crashes/const_mut_ref_check_bypass.rs new file mode 100644 index 0000000000000..6234536c72beb --- /dev/null +++ b/tests/crashes/const_mut_ref_check_bypass.rs @@ -0,0 +1,11 @@ +// Version of `tests/ui/consts/const-eval/heap/alloc_intrinsic_untyped.rs` without the flag that +// suppresses the ICE. +//@ known-bug: #129233 +#![feature(core_intrinsics)] +#![feature(const_heap)] +#![feature(const_mut_refs)] +use std::intrinsics; + +const BAR: *mut i32 = unsafe { intrinsics::const_allocate(4, 4) as *mut i32 }; + +fn main() {} diff --git a/tests/ui/consts/const-eval/heap/alloc_intrinsic_untyped.rs b/tests/ui/consts/const-eval/heap/alloc_intrinsic_untyped.rs index 105e8e38d84eb..7be14e3cff72b 100644 --- a/tests/ui/consts/const-eval/heap/alloc_intrinsic_untyped.rs +++ b/tests/ui/consts/const-eval/heap/alloc_intrinsic_untyped.rs @@ -1,3 +1,6 @@ +// We unleash Miri here since this test demonstrates code that bypasses the checks against interning +// mutable pointers, which currently ICEs. Unleashing Miri silence the ICE. +//@ compile-flags: -Zunleash-the-miri-inside-of-you #![feature(core_intrinsics)] #![feature(const_heap)] #![feature(const_mut_refs)] diff --git a/tests/ui/consts/const-eval/heap/alloc_intrinsic_untyped.stderr b/tests/ui/consts/const-eval/heap/alloc_intrinsic_untyped.stderr index bd82e6781be1e..119198bd3476a 100644 --- a/tests/ui/consts/const-eval/heap/alloc_intrinsic_untyped.stderr +++ b/tests/ui/consts/const-eval/heap/alloc_intrinsic_untyped.stderr @@ -1,5 +1,5 @@ error: encountered mutable pointer in final value of constant - --> $DIR/alloc_intrinsic_untyped.rs:6:1 + --> $DIR/alloc_intrinsic_untyped.rs:9:1 | LL | const BAR: *mut i32 = unsafe { intrinsics::const_allocate(4, 4) as *mut i32 }; | ^^^^^^^^^^^^^^^^^^^ From bdda4ec2f5d764134e568421206b29bdeeb7c647 Mon Sep 17 00:00:00 2001 From: Marcondiro <46560192+Marcondiro@users.noreply.github.com> Date: Tue, 10 Sep 2024 10:50:20 +0200 Subject: [PATCH 0788/2194] Bump unicode_data to version 16.0.0 --- library/core/src/unicode/unicode_data.rs | 1321 +++++++++++----------- 1 file changed, 670 insertions(+), 651 deletions(-) diff --git a/library/core/src/unicode/unicode_data.rs b/library/core/src/unicode/unicode_data.rs index 1b3d6729663b5..143beb3770680 100644 --- a/library/core/src/unicode/unicode_data.rs +++ b/library/core/src/unicode/unicode_data.rs @@ -99,75 +99,77 @@ fn skip_search( offset_idx % 2 == 1 } -pub const UNICODE_VERSION: (u8, u8, u8) = (15, 1, 0); +pub const UNICODE_VERSION: (u8, u8, u8) = (16, 0, 0); #[rustfmt::skip] pub mod alphabetic { - static SHORT_OFFSET_RUNS: [u32; 54] = [ - 706, 33559113, 872420973, 952114966, 1161831606, 1310731264, 1314926597, 1394619392, - 1444957632, 1447077005, 1451271693, 1459672996, 1648425216, 1658911342, 1661009214, - 1707147904, 1793132343, 1887506048, 2040601600, 2392923872, 2481005466, 2504077200, - 2514564144, 2520859648, 2527151687, 2529257472, 2531355193, 2533453376, 2564917240, - 2596375766, 2600579056, 2606870819, 2621551356, 2642525184, 2644628480, 2665600678, - 2743197440, 2791432848, 2841765072, 2850154464, 2854350336, 2887905584, 3026321408, - 3038947040, 3041048378, 3045248674, 3053644769, 3057839710, 3062036480, 3064134174, - 3066232832, 3068334923, 3070436272, 3075744688, + static SHORT_OFFSET_RUNS: [u32; 53] = [ + 706, 33559113, 876615277, 956309270, 1166025910, 1314925568, 1319120901, 1398813696, + 1449151936, 1451271309, 1455465997, 1463867300, 1652619520, 1663105646, 1665203518, + 1711342208, 1797326647, 1895898848, 2560697242, 2583768976, 2594255920, 2600551419, + 2608940615, 2613141760, 2615240704, 2619435577, 2621533504, 2652997624, 2688650454, + 2692853744, 2699145507, 2713826044, 2734799872, 2736903168, 2757875366, 2835472128, + 2883707536, 2934039760, 2942429152, 2955013632, 2988568880, 3126984704, 3139610336, + 3141711674, 3145911970, 3154308065, 3158503006, 3162699776, 3164797470, 3166896128, + 3168998219, 3171099568, 3176407984, ]; - static OFFSETS: [u8; 1467] = [ - 65, 26, 6, 26, 47, 1, 10, 1, 4, 1, 5, 23, 1, 31, 1, 0, 4, 12, 14, 5, 7, 1, 1, 1, 86, 1, 42, - 5, 1, 2, 2, 4, 1, 1, 6, 1, 1, 3, 1, 1, 1, 20, 1, 83, 1, 139, 8, 166, 1, 38, 2, 1, 6, 41, 39, - 14, 1, 1, 1, 2, 1, 2, 1, 1, 8, 27, 4, 4, 29, 11, 5, 56, 1, 7, 14, 102, 1, 8, 4, 8, 4, 3, 10, - 3, 2, 1, 16, 48, 13, 101, 24, 33, 9, 2, 4, 1, 5, 24, 2, 19, 19, 25, 7, 11, 5, 24, 1, 6, 17, - 42, 10, 12, 3, 7, 6, 76, 1, 16, 1, 3, 4, 15, 13, 19, 1, 8, 2, 2, 2, 22, 1, 7, 1, 1, 3, 4, 3, - 8, 2, 2, 2, 2, 1, 1, 8, 1, 4, 2, 1, 5, 12, 2, 10, 1, 4, 3, 1, 6, 4, 2, 2, 22, 1, 7, 1, 2, 1, - 2, 1, 2, 4, 5, 4, 2, 2, 2, 4, 1, 7, 4, 1, 1, 17, 6, 11, 3, 1, 9, 1, 3, 1, 22, 1, 7, 1, 2, 1, - 5, 3, 9, 1, 3, 1, 2, 3, 1, 15, 4, 21, 4, 4, 3, 1, 8, 2, 2, 2, 22, 1, 7, 1, 2, 1, 5, 3, 8, 2, - 2, 2, 2, 9, 2, 4, 2, 1, 5, 13, 1, 16, 2, 1, 6, 3, 3, 1, 4, 3, 2, 1, 1, 1, 2, 3, 2, 3, 3, 3, - 12, 4, 5, 3, 3, 1, 3, 3, 1, 6, 1, 40, 13, 1, 3, 1, 23, 1, 16, 3, 8, 1, 3, 1, 3, 8, 2, 1, 3, - 2, 1, 2, 4, 28, 4, 1, 8, 1, 3, 1, 23, 1, 10, 1, 5, 3, 8, 1, 3, 1, 3, 8, 2, 6, 2, 1, 4, 13, - 3, 12, 13, 1, 3, 1, 41, 2, 8, 1, 3, 1, 3, 1, 1, 5, 4, 7, 5, 22, 6, 1, 3, 1, 18, 3, 24, 1, 9, - 1, 1, 2, 7, 8, 6, 1, 1, 1, 8, 18, 2, 13, 58, 5, 7, 6, 1, 51, 2, 1, 1, 1, 5, 1, 24, 1, 1, 1, - 19, 1, 3, 2, 5, 1, 1, 6, 1, 14, 4, 32, 1, 63, 8, 1, 36, 4, 19, 4, 16, 1, 36, 67, 55, 1, 1, - 2, 5, 16, 64, 10, 4, 2, 38, 1, 1, 5, 1, 2, 43, 1, 0, 1, 4, 2, 7, 1, 1, 1, 4, 2, 41, 1, 4, 2, - 33, 1, 4, 2, 7, 1, 1, 1, 4, 2, 15, 1, 57, 1, 4, 2, 67, 37, 16, 16, 86, 2, 6, 3, 0, 2, 17, 1, - 26, 5, 75, 3, 11, 7, 20, 11, 21, 12, 20, 12, 13, 1, 3, 1, 2, 12, 52, 2, 19, 14, 1, 4, 1, 67, - 89, 7, 43, 5, 70, 10, 31, 1, 12, 4, 9, 23, 30, 2, 5, 11, 44, 4, 26, 54, 28, 4, 63, 2, 20, - 50, 1, 23, 2, 11, 3, 49, 52, 1, 15, 1, 8, 51, 42, 2, 4, 10, 44, 1, 11, 14, 55, 22, 3, 10, - 36, 2, 9, 7, 43, 2, 3, 41, 4, 1, 6, 1, 2, 3, 1, 5, 192, 39, 14, 11, 0, 2, 6, 2, 38, 2, 6, 2, - 8, 1, 1, 1, 1, 1, 1, 1, 31, 2, 53, 1, 7, 1, 1, 3, 3, 1, 7, 3, 4, 2, 6, 4, 13, 5, 3, 1, 7, - 116, 1, 13, 1, 16, 13, 101, 1, 4, 1, 2, 10, 1, 1, 3, 5, 6, 1, 1, 1, 1, 1, 1, 4, 1, 11, 2, 4, - 5, 5, 4, 1, 17, 41, 0, 52, 0, 229, 6, 4, 3, 2, 12, 38, 1, 1, 5, 1, 2, 56, 7, 1, 16, 23, 9, - 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 32, 47, 1, 0, 3, 25, 9, 7, 5, 2, 5, 4, 86, - 6, 3, 1, 90, 1, 4, 5, 43, 1, 94, 17, 32, 48, 16, 0, 0, 64, 0, 67, 46, 2, 0, 3, 16, 10, 2, - 20, 47, 5, 8, 3, 113, 39, 9, 2, 103, 2, 64, 5, 2, 1, 1, 1, 5, 24, 20, 1, 33, 24, 52, 12, 68, - 1, 1, 44, 6, 3, 1, 1, 3, 10, 33, 5, 35, 13, 29, 3, 51, 1, 12, 15, 1, 16, 16, 10, 5, 1, 55, - 9, 14, 18, 23, 3, 69, 1, 1, 1, 1, 24, 3, 2, 16, 2, 4, 11, 6, 2, 6, 2, 6, 9, 7, 1, 7, 1, 43, - 1, 14, 6, 123, 21, 0, 12, 23, 4, 49, 0, 0, 2, 106, 38, 7, 12, 5, 5, 12, 1, 13, 1, 5, 1, 1, - 1, 2, 1, 2, 1, 108, 33, 0, 18, 64, 2, 54, 40, 12, 116, 5, 1, 135, 36, 26, 6, 26, 11, 89, 3, - 6, 2, 6, 2, 6, 2, 3, 35, 12, 1, 26, 1, 19, 1, 2, 1, 15, 2, 14, 34, 123, 69, 53, 0, 29, 3, - 49, 47, 32, 13, 30, 5, 43, 5, 30, 2, 36, 4, 8, 1, 5, 42, 158, 18, 36, 4, 36, 4, 40, 8, 52, - 12, 11, 1, 15, 1, 7, 1, 2, 1, 11, 1, 15, 1, 7, 1, 2, 67, 0, 9, 22, 10, 8, 24, 6, 1, 42, 1, - 9, 69, 6, 2, 1, 1, 44, 1, 2, 3, 1, 2, 23, 10, 23, 9, 31, 65, 19, 1, 2, 10, 22, 10, 26, 70, - 56, 6, 2, 64, 4, 1, 2, 5, 8, 1, 3, 1, 29, 42, 29, 3, 29, 35, 8, 1, 28, 27, 54, 10, 22, 10, - 19, 13, 18, 110, 73, 55, 51, 13, 51, 13, 40, 0, 42, 1, 2, 3, 2, 78, 29, 10, 1, 8, 22, 42, - 18, 46, 21, 27, 23, 9, 70, 43, 5, 10, 57, 9, 1, 13, 25, 23, 51, 17, 4, 8, 35, 3, 1, 9, 64, - 1, 4, 9, 2, 10, 1, 1, 1, 35, 18, 1, 34, 2, 1, 6, 4, 62, 7, 1, 1, 1, 4, 1, 15, 1, 10, 7, 57, - 23, 4, 1, 8, 2, 2, 2, 22, 1, 7, 1, 2, 1, 5, 3, 8, 2, 2, 2, 2, 3, 1, 6, 1, 5, 7, 156, 66, 1, - 3, 1, 4, 20, 3, 30, 66, 2, 2, 1, 1, 184, 54, 2, 7, 25, 6, 34, 63, 1, 1, 3, 1, 59, 54, 2, 1, - 71, 27, 2, 14, 21, 7, 185, 57, 103, 64, 31, 8, 2, 1, 2, 8, 1, 2, 1, 30, 1, 2, 2, 2, 2, 4, - 93, 8, 2, 46, 2, 6, 1, 1, 1, 2, 27, 51, 2, 10, 17, 72, 5, 1, 18, 73, 0, 9, 1, 45, 1, 7, 1, - 1, 49, 30, 2, 22, 1, 14, 73, 7, 1, 2, 1, 44, 3, 1, 1, 2, 1, 3, 1, 1, 2, 2, 24, 6, 1, 2, 1, - 37, 1, 2, 1, 4, 1, 1, 0, 23, 9, 17, 1, 41, 3, 3, 111, 1, 79, 0, 102, 111, 17, 196, 0, 97, - 15, 0, 17, 6, 0, 0, 0, 0, 7, 31, 17, 79, 17, 30, 18, 48, 16, 4, 31, 21, 5, 19, 0, 64, 128, - 75, 4, 57, 7, 17, 64, 2, 1, 1, 12, 2, 14, 0, 8, 0, 42, 9, 0, 4, 1, 7, 1, 2, 1, 0, 15, 1, 29, - 3, 2, 1, 14, 4, 8, 0, 0, 107, 5, 13, 3, 9, 7, 10, 4, 1, 0, 85, 1, 71, 1, 2, 2, 1, 2, 2, 2, - 4, 1, 12, 1, 1, 1, 7, 1, 65, 1, 4, 2, 8, 1, 7, 1, 28, 1, 4, 1, 5, 1, 1, 3, 7, 1, 0, 2, 25, - 1, 25, 1, 31, 1, 25, 1, 31, 1, 25, 1, 31, 1, 25, 1, 31, 1, 25, 1, 8, 0, 31, 6, 6, 213, 7, 1, - 17, 2, 7, 1, 2, 1, 5, 5, 62, 33, 1, 112, 45, 10, 7, 16, 1, 0, 30, 18, 44, 0, 28, 0, 7, 1, 4, - 1, 2, 1, 15, 1, 197, 59, 68, 3, 1, 3, 1, 0, 4, 1, 27, 1, 2, 1, 1, 2, 1, 1, 10, 1, 4, 1, 1, - 1, 1, 6, 1, 4, 1, 1, 1, 1, 1, 1, 3, 1, 2, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 2, - 4, 1, 7, 1, 4, 1, 4, 1, 1, 1, 10, 1, 17, 5, 3, 1, 5, 1, 17, 0, 26, 6, 26, 6, 26, 0, 0, 32, - 0, 6, 222, 2, 0, 14, 0, 15, 0, 0, 0, 0, 0, 5, 0, 0, + static OFFSETS: [u8; 1515] = [ + 65, 26, 6, 26, 47, 1, 10, 1, 4, 1, 5, 23, 1, 31, 1, 0, 4, 12, 14, 5, 7, 1, 1, 1, 86, 1, 29, + 18, 1, 2, 2, 4, 1, 1, 6, 1, 1, 3, 1, 1, 1, 20, 1, 83, 1, 139, 8, 166, 1, 38, 2, 1, 6, 41, + 39, 14, 1, 1, 1, 2, 1, 2, 1, 1, 8, 27, 4, 4, 29, 11, 5, 56, 1, 7, 14, 102, 1, 8, 4, 8, 4, 3, + 10, 3, 2, 1, 16, 48, 13, 101, 24, 33, 9, 2, 4, 1, 5, 24, 2, 19, 19, 25, 7, 11, 5, 24, 1, 6, + 8, 1, 8, 42, 10, 12, 3, 7, 6, 76, 1, 16, 1, 3, 4, 15, 13, 19, 1, 8, 2, 2, 2, 22, 1, 7, 1, 1, + 3, 4, 3, 8, 2, 2, 2, 2, 1, 1, 8, 1, 4, 2, 1, 5, 12, 2, 10, 1, 4, 3, 1, 6, 4, 2, 2, 22, 1, 7, + 1, 2, 1, 2, 1, 2, 4, 5, 4, 2, 2, 2, 4, 1, 7, 4, 1, 1, 17, 6, 11, 3, 1, 9, 1, 3, 1, 22, 1, 7, + 1, 2, 1, 5, 3, 9, 1, 3, 1, 2, 3, 1, 15, 4, 21, 4, 4, 3, 1, 8, 2, 2, 2, 22, 1, 7, 1, 2, 1, 5, + 3, 8, 2, 2, 2, 2, 9, 2, 4, 2, 1, 5, 13, 1, 16, 2, 1, 6, 3, 3, 1, 4, 3, 2, 1, 1, 1, 2, 3, 2, + 3, 3, 3, 12, 4, 5, 3, 3, 1, 3, 3, 1, 6, 1, 40, 13, 1, 3, 1, 23, 1, 16, 3, 8, 1, 3, 1, 3, 8, + 2, 1, 3, 2, 1, 2, 4, 28, 4, 1, 8, 1, 3, 1, 23, 1, 10, 1, 5, 3, 8, 1, 3, 1, 3, 8, 2, 6, 2, 1, + 4, 13, 3, 12, 13, 1, 3, 1, 41, 2, 8, 1, 3, 1, 3, 1, 1, 5, 4, 7, 5, 22, 6, 1, 3, 1, 18, 3, + 24, 1, 9, 1, 1, 2, 7, 8, 6, 1, 1, 1, 8, 18, 2, 13, 58, 5, 7, 6, 1, 51, 2, 1, 1, 1, 5, 1, 24, + 1, 1, 1, 19, 1, 3, 2, 5, 1, 1, 6, 1, 14, 4, 32, 1, 63, 8, 1, 36, 4, 19, 4, 16, 1, 36, 67, + 55, 1, 1, 2, 5, 16, 64, 10, 4, 2, 38, 1, 1, 5, 1, 2, 43, 1, 0, 1, 4, 2, 7, 1, 1, 1, 4, 2, + 41, 1, 4, 2, 33, 1, 4, 2, 7, 1, 1, 1, 4, 2, 15, 1, 57, 1, 4, 2, 67, 37, 16, 16, 86, 2, 6, 3, + 0, 2, 17, 1, 26, 5, 75, 3, 11, 7, 20, 11, 21, 12, 20, 12, 13, 1, 3, 1, 2, 12, 52, 2, 19, 14, + 1, 4, 1, 67, 89, 7, 43, 5, 70, 10, 31, 1, 12, 4, 9, 23, 30, 2, 5, 11, 44, 4, 26, 54, 28, 4, + 63, 2, 20, 50, 1, 23, 2, 11, 3, 49, 52, 1, 15, 1, 8, 51, 42, 2, 4, 10, 44, 1, 11, 14, 55, + 22, 3, 10, 36, 2, 11, 5, 43, 2, 3, 41, 4, 1, 6, 1, 2, 3, 1, 5, 192, 19, 34, 11, 0, 2, 6, 2, + 38, 2, 6, 2, 8, 1, 1, 1, 1, 1, 1, 1, 31, 2, 53, 1, 7, 1, 1, 3, 3, 1, 7, 3, 4, 2, 6, 4, 13, + 5, 3, 1, 7, 116, 1, 13, 1, 16, 13, 101, 1, 4, 1, 2, 10, 1, 1, 3, 5, 6, 1, 1, 1, 1, 1, 1, 4, + 1, 11, 2, 4, 5, 5, 4, 1, 17, 41, 0, 52, 0, 229, 6, 4, 3, 2, 12, 38, 1, 1, 5, 1, 2, 56, 7, 1, + 16, 23, 9, 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 32, 47, 1, 0, 3, 25, 9, 7, 5, 2, + 5, 4, 86, 6, 3, 1, 90, 1, 4, 5, 43, 1, 94, 17, 32, 48, 16, 0, 0, 64, 0, 67, 46, 2, 0, 3, 16, + 10, 2, 20, 47, 5, 8, 3, 113, 39, 9, 2, 103, 2, 67, 2, 2, 1, 1, 1, 8, 21, 20, 1, 33, 24, 52, + 12, 68, 1, 1, 44, 6, 3, 1, 1, 3, 10, 33, 5, 35, 13, 29, 3, 51, 1, 12, 15, 1, 16, 16, 10, 5, + 1, 55, 9, 14, 18, 23, 3, 69, 1, 1, 1, 1, 24, 3, 2, 16, 2, 4, 11, 6, 2, 6, 2, 6, 9, 7, 1, 7, + 1, 43, 1, 14, 6, 123, 21, 0, 12, 23, 4, 49, 0, 0, 2, 106, 38, 7, 12, 5, 5, 12, 1, 13, 1, 5, + 1, 1, 1, 2, 1, 2, 1, 108, 33, 0, 18, 64, 2, 54, 40, 12, 116, 5, 1, 135, 36, 26, 6, 26, 11, + 89, 3, 6, 2, 6, 2, 6, 2, 3, 35, 12, 1, 26, 1, 19, 1, 2, 1, 15, 2, 14, 34, 123, 69, 53, 0, + 29, 3, 49, 47, 32, 13, 30, 5, 43, 5, 30, 2, 36, 4, 8, 1, 5, 42, 158, 18, 36, 4, 36, 4, 40, + 8, 52, 12, 11, 1, 15, 1, 7, 1, 2, 1, 11, 1, 15, 1, 7, 1, 2, 3, 52, 12, 0, 9, 22, 10, 8, 24, + 6, 1, 42, 1, 9, 69, 6, 2, 1, 1, 44, 1, 2, 3, 1, 2, 23, 10, 23, 9, 31, 65, 19, 1, 2, 10, 22, + 10, 26, 70, 56, 6, 2, 64, 4, 1, 2, 5, 8, 1, 3, 1, 29, 42, 29, 3, 29, 35, 8, 1, 28, 27, 54, + 10, 22, 10, 19, 13, 18, 110, 73, 55, 51, 13, 51, 13, 40, 34, 28, 3, 1, 5, 23, 250, 42, 1, 2, + 3, 2, 16, 3, 55, 1, 3, 29, 10, 1, 8, 22, 42, 18, 46, 21, 27, 23, 9, 70, 43, 5, 10, 57, 9, 1, + 13, 25, 23, 51, 17, 4, 8, 35, 3, 1, 9, 64, 1, 4, 9, 2, 10, 1, 1, 1, 35, 18, 1, 34, 2, 1, 6, + 4, 62, 7, 1, 1, 1, 4, 1, 15, 1, 10, 7, 57, 23, 4, 1, 8, 2, 2, 2, 22, 1, 7, 1, 2, 1, 5, 3, 8, + 2, 2, 2, 2, 3, 1, 6, 1, 5, 7, 28, 10, 1, 1, 2, 1, 1, 38, 1, 10, 1, 1, 2, 1, 1, 4, 1, 2, 3, + 1, 1, 1, 44, 66, 1, 3, 1, 4, 20, 3, 30, 66, 2, 2, 1, 1, 184, 54, 2, 7, 25, 6, 34, 63, 1, 1, + 3, 1, 59, 54, 2, 1, 71, 27, 2, 14, 21, 7, 185, 57, 103, 64, 31, 8, 2, 1, 2, 8, 1, 2, 1, 30, + 1, 2, 2, 2, 2, 4, 93, 8, 2, 46, 2, 6, 1, 1, 1, 2, 27, 51, 2, 10, 17, 72, 5, 1, 18, 73, 199, + 33, 31, 9, 1, 45, 1, 7, 1, 1, 49, 30, 2, 22, 1, 14, 73, 7, 1, 2, 1, 44, 3, 1, 1, 2, 1, 3, 1, + 1, 2, 2, 24, 6, 1, 2, 1, 37, 1, 2, 1, 4, 1, 1, 0, 23, 9, 17, 1, 41, 3, 3, 111, 1, 79, 0, + 102, 111, 17, 196, 0, 97, 15, 0, 17, 6, 25, 0, 5, 0, 0, 47, 0, 0, 7, 31, 17, 79, 17, 30, 18, + 48, 16, 4, 31, 21, 5, 19, 0, 45, 211, 64, 128, 75, 4, 57, 7, 17, 64, 2, 1, 1, 12, 2, 14, 0, + 8, 0, 41, 10, 0, 4, 1, 7, 1, 2, 1, 0, 15, 1, 29, 3, 2, 1, 14, 4, 8, 0, 0, 107, 5, 13, 3, 9, + 7, 10, 4, 1, 0, 85, 1, 71, 1, 2, 2, 1, 2, 2, 2, 4, 1, 12, 1, 1, 1, 7, 1, 65, 1, 4, 2, 8, 1, + 7, 1, 28, 1, 4, 1, 5, 1, 1, 3, 7, 1, 0, 2, 25, 1, 25, 1, 31, 1, 25, 1, 31, 1, 25, 1, 31, 1, + 25, 1, 31, 1, 25, 1, 8, 0, 31, 6, 6, 213, 7, 1, 17, 2, 7, 1, 2, 1, 5, 5, 62, 33, 1, 112, 45, + 10, 7, 16, 1, 0, 30, 18, 44, 0, 28, 228, 30, 2, 1, 0, 7, 1, 4, 1, 2, 1, 15, 1, 197, 59, 68, + 3, 1, 3, 1, 0, 4, 1, 27, 1, 2, 1, 1, 2, 1, 1, 10, 1, 4, 1, 1, 1, 1, 6, 1, 4, 1, 1, 1, 1, 1, + 1, 3, 1, 2, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 2, 4, 1, 7, 1, 4, 1, 4, 1, 1, 1, + 10, 1, 17, 5, 3, 1, 5, 1, 17, 0, 26, 6, 26, 6, 26, 0, 0, 32, 0, 6, 222, 2, 0, 14, 0, 15, 0, + 0, 0, 0, 0, 5, 0, 0, ]; pub fn lookup(c: char) -> bool { super::skip_search( @@ -180,18 +182,18 @@ pub mod alphabetic { #[rustfmt::skip] pub mod case_ignorable { - static SHORT_OFFSET_RUNS: [u32; 35] = [ + static SHORT_OFFSET_RUNS: [u32; 37] = [ 688, 44045149, 572528402, 576724925, 807414908, 878718981, 903913493, 929080568, 933275148, 937491230, 1138818560, 1147208189, 1210124160, 1222707713, 1235291428, 1260457643, - 1264654383, 1499535675, 1507925040, 1566646003, 1629566000, 1650551536, 1658941263, - 1671540720, 1688321181, 1700908800, 1709298023, 1717688832, 1738661888, 1763828398, - 1797383403, 1805773008, 1809970171, 1819148289, 1824457200, + 1277237295, 1537284411, 1545673776, 1604394739, 1667314736, 1692492062, 1700883184, + 1709272384, 1721855823, 1730260976, 1747041437, 1759629056, 1768018279, 1776409088, + 1797382144, 1822548654, 1856103659, 1864493264, 1872884731, 1882062849, 1887371760, ]; - static OFFSETS: [u8; 875] = [ + static OFFSETS: [u8; 905] = [ 39, 1, 6, 1, 11, 1, 35, 1, 1, 1, 71, 1, 4, 1, 1, 1, 4, 1, 2, 2, 0, 192, 4, 2, 4, 1, 9, 2, 1, 1, 251, 7, 207, 1, 5, 1, 49, 45, 1, 1, 1, 2, 1, 2, 1, 1, 44, 1, 11, 6, 10, 11, 1, 1, 35, 1, 10, 21, 16, 1, 101, 8, 1, 10, 1, 4, 33, 1, 1, 1, 30, 27, 91, 11, 58, 11, 4, 1, 2, 1, 24, - 24, 43, 3, 44, 1, 7, 2, 6, 8, 41, 58, 55, 1, 1, 1, 4, 8, 4, 1, 3, 7, 10, 2, 13, 1, 15, 1, + 24, 43, 3, 44, 1, 7, 2, 5, 9, 41, 58, 55, 1, 1, 1, 4, 8, 4, 1, 3, 7, 10, 2, 13, 1, 15, 1, 58, 1, 4, 4, 8, 1, 20, 2, 26, 1, 2, 2, 57, 1, 4, 2, 4, 2, 2, 3, 3, 1, 30, 2, 3, 1, 11, 2, 57, 1, 4, 5, 1, 2, 4, 1, 20, 2, 22, 6, 1, 1, 58, 1, 2, 1, 1, 4, 8, 1, 7, 2, 11, 2, 30, 1, 61, 1, 12, 1, 50, 1, 3, 1, 55, 1, 1, 3, 5, 3, 1, 4, 7, 2, 11, 2, 29, 1, 58, 1, 2, 1, 6, 1, @@ -209,17 +211,18 @@ pub mod case_ignorable { 2, 2, 17, 1, 21, 2, 66, 6, 2, 2, 2, 2, 12, 1, 8, 1, 35, 1, 11, 1, 51, 1, 1, 3, 2, 2, 5, 2, 1, 1, 27, 1, 14, 2, 5, 2, 1, 1, 100, 5, 9, 3, 121, 1, 2, 1, 4, 1, 0, 1, 147, 17, 0, 16, 3, 1, 12, 16, 34, 1, 2, 1, 169, 1, 7, 1, 6, 1, 11, 1, 35, 1, 1, 1, 47, 1, 45, 2, 67, 1, 21, 3, - 0, 1, 226, 1, 149, 5, 0, 6, 1, 42, 1, 9, 0, 3, 1, 2, 5, 4, 40, 3, 4, 1, 165, 2, 0, 4, 0, 2, - 80, 3, 70, 11, 49, 4, 123, 1, 54, 15, 41, 1, 2, 2, 10, 3, 49, 4, 2, 2, 2, 1, 4, 1, 10, 1, - 50, 3, 36, 5, 1, 8, 62, 1, 12, 2, 52, 9, 10, 4, 2, 1, 95, 3, 2, 1, 1, 2, 6, 1, 2, 1, 157, 1, - 3, 8, 21, 2, 57, 2, 3, 1, 37, 7, 3, 5, 195, 8, 2, 3, 1, 1, 23, 1, 84, 6, 1, 1, 4, 2, 1, 2, - 238, 4, 6, 2, 1, 2, 27, 2, 85, 8, 2, 1, 1, 2, 106, 1, 1, 1, 2, 6, 1, 1, 101, 3, 2, 4, 1, 5, - 0, 9, 1, 2, 0, 2, 1, 1, 4, 1, 144, 4, 2, 2, 4, 1, 32, 10, 40, 6, 2, 4, 8, 1, 9, 6, 2, 3, 46, - 13, 1, 2, 0, 7, 1, 6, 1, 1, 82, 22, 2, 7, 1, 2, 1, 2, 122, 6, 3, 1, 1, 2, 1, 7, 1, 1, 72, 2, - 3, 1, 1, 1, 0, 2, 11, 2, 52, 5, 5, 1, 1, 1, 0, 17, 6, 15, 0, 5, 59, 7, 9, 4, 0, 1, 63, 17, - 64, 2, 1, 2, 0, 4, 1, 7, 1, 2, 0, 2, 1, 4, 0, 46, 2, 23, 0, 3, 9, 16, 2, 7, 30, 4, 148, 3, - 0, 55, 4, 50, 8, 1, 14, 1, 22, 5, 1, 15, 0, 7, 1, 17, 2, 7, 1, 2, 1, 5, 5, 62, 33, 1, 160, - 14, 0, 1, 61, 4, 0, 5, 0, 7, 109, 8, 0, 5, 0, 1, 30, 96, 128, 240, 0, + 0, 1, 226, 1, 149, 5, 0, 6, 1, 42, 1, 9, 0, 3, 1, 2, 5, 4, 40, 3, 4, 1, 165, 2, 0, 4, 38, 1, + 26, 5, 1, 1, 0, 2, 79, 4, 70, 11, 49, 4, 123, 1, 54, 15, 41, 1, 2, 2, 10, 3, 49, 4, 2, 2, 2, + 1, 4, 1, 10, 1, 50, 3, 36, 5, 1, 8, 62, 1, 12, 2, 52, 9, 10, 4, 2, 1, 95, 3, 2, 1, 1, 2, 6, + 1, 2, 1, 157, 1, 3, 8, 21, 2, 57, 2, 3, 1, 37, 7, 3, 5, 70, 6, 13, 1, 1, 1, 1, 1, 14, 2, 85, + 8, 2, 3, 1, 1, 23, 1, 84, 6, 1, 1, 4, 2, 1, 2, 238, 4, 6, 2, 1, 2, 27, 2, 85, 8, 2, 1, 1, 2, + 106, 1, 1, 1, 2, 6, 1, 1, 101, 1, 1, 1, 2, 4, 1, 5, 0, 9, 1, 2, 0, 2, 1, 1, 4, 1, 144, 4, 2, + 2, 4, 1, 32, 10, 40, 6, 2, 4, 8, 1, 9, 6, 2, 3, 46, 13, 1, 2, 0, 7, 1, 6, 1, 1, 82, 22, 2, + 7, 1, 2, 1, 2, 122, 6, 3, 1, 1, 2, 1, 7, 1, 1, 72, 2, 3, 1, 1, 1, 0, 2, 11, 2, 52, 5, 5, 1, + 1, 1, 23, 1, 0, 17, 6, 15, 0, 12, 3, 3, 0, 5, 59, 7, 9, 4, 0, 3, 40, 2, 0, 1, 63, 17, 64, 2, + 1, 2, 0, 4, 1, 7, 1, 2, 0, 2, 1, 4, 0, 46, 2, 23, 0, 3, 9, 16, 2, 7, 30, 4, 148, 3, 0, 55, + 4, 50, 8, 1, 14, 1, 22, 5, 1, 15, 0, 7, 1, 17, 2, 7, 1, 2, 1, 5, 5, 62, 33, 1, 160, 14, 0, + 1, 61, 4, 0, 5, 254, 2, 0, 7, 109, 8, 0, 5, 0, 1, 30, 96, 128, 240, 0, ]; pub fn lookup(c: char) -> bool { super::skip_search( @@ -234,22 +237,22 @@ pub mod case_ignorable { pub mod cased { static SHORT_OFFSET_RUNS: [u32; 22] = [ 4256, 115348384, 136322176, 144711446, 163587254, 320875520, 325101120, 350268208, - 392231680, 404815649, 413205504, 421595008, 467733632, 484513952, 492924480, 497144832, - 501339814, 578936576, 627171376, 639756544, 643952944, 649261450, + 392231680, 404815649, 413205504, 421595008, 467733632, 484513952, 501313088, 505533440, + 509728422, 587325184, 635559984, 648145152, 652341552, 657650058, ]; - static OFFSETS: [u8; 315] = [ + static OFFSETS: [u8; 319] = [ 65, 26, 6, 26, 47, 1, 10, 1, 4, 1, 5, 23, 1, 31, 1, 195, 1, 4, 4, 208, 1, 36, 7, 2, 30, 5, 96, 1, 42, 4, 2, 2, 2, 4, 1, 1, 6, 1, 1, 3, 1, 1, 1, 20, 1, 83, 1, 139, 8, 166, 1, 38, 9, - 41, 0, 38, 1, 1, 5, 1, 2, 43, 1, 4, 0, 86, 2, 6, 0, 9, 7, 43, 2, 3, 64, 192, 64, 0, 2, 6, 2, - 38, 2, 6, 2, 8, 1, 1, 1, 1, 1, 1, 1, 31, 2, 53, 1, 7, 1, 1, 3, 3, 1, 7, 3, 4, 2, 6, 4, 13, - 5, 3, 1, 7, 116, 1, 13, 1, 16, 13, 101, 1, 4, 1, 2, 10, 1, 1, 3, 5, 6, 1, 1, 1, 1, 1, 1, 4, - 1, 6, 4, 1, 2, 4, 5, 5, 4, 1, 17, 32, 3, 2, 0, 52, 0, 229, 6, 4, 3, 2, 12, 38, 1, 1, 5, 1, - 0, 46, 18, 30, 132, 102, 3, 4, 1, 59, 5, 2, 1, 1, 1, 5, 24, 5, 1, 3, 0, 43, 1, 14, 6, 80, 0, - 7, 12, 5, 0, 26, 6, 26, 0, 80, 96, 36, 4, 36, 116, 11, 1, 15, 1, 7, 1, 2, 1, 11, 1, 15, 1, - 7, 1, 2, 0, 1, 2, 3, 1, 42, 1, 9, 0, 51, 13, 51, 0, 64, 0, 64, 0, 85, 1, 71, 1, 2, 2, 1, 2, - 2, 2, 4, 1, 12, 1, 1, 1, 7, 1, 65, 1, 4, 2, 8, 1, 7, 1, 28, 1, 4, 1, 5, 1, 1, 3, 7, 1, 0, 2, - 25, 1, 25, 1, 31, 1, 25, 1, 31, 1, 25, 1, 31, 1, 25, 1, 31, 1, 25, 1, 8, 0, 10, 1, 20, 6, 6, - 0, 62, 0, 68, 0, 26, 6, 26, 6, 26, 0, + 41, 0, 38, 1, 1, 5, 1, 2, 43, 1, 4, 0, 86, 2, 6, 0, 11, 5, 43, 2, 3, 64, 192, 64, 0, 2, 6, + 2, 38, 2, 6, 2, 8, 1, 1, 1, 1, 1, 1, 1, 31, 2, 53, 1, 7, 1, 1, 3, 3, 1, 7, 3, 4, 2, 6, 4, + 13, 5, 3, 1, 7, 116, 1, 13, 1, 16, 13, 101, 1, 4, 1, 2, 10, 1, 1, 3, 5, 6, 1, 1, 1, 1, 1, 1, + 4, 1, 6, 4, 1, 2, 4, 5, 5, 4, 1, 17, 32, 3, 2, 0, 52, 0, 229, 6, 4, 3, 2, 12, 38, 1, 1, 5, + 1, 0, 46, 18, 30, 132, 102, 3, 4, 1, 62, 2, 2, 1, 1, 1, 8, 21, 5, 1, 3, 0, 43, 1, 14, 6, 80, + 0, 7, 12, 5, 0, 26, 6, 26, 0, 80, 96, 36, 4, 36, 116, 11, 1, 15, 1, 7, 1, 2, 1, 11, 1, 15, + 1, 7, 1, 2, 0, 1, 2, 3, 1, 42, 1, 9, 0, 51, 13, 51, 93, 22, 10, 22, 0, 64, 0, 64, 0, 85, 1, + 71, 1, 2, 2, 1, 2, 2, 2, 4, 1, 12, 1, 1, 1, 7, 1, 65, 1, 4, 2, 8, 1, 7, 1, 28, 1, 4, 1, 5, + 1, 1, 3, 7, 1, 0, 2, 25, 1, 25, 1, 31, 1, 25, 1, 31, 1, 25, 1, 31, 1, 25, 1, 31, 1, 25, 1, + 8, 0, 10, 1, 20, 6, 6, 0, 62, 0, 68, 0, 26, 6, 26, 6, 26, 0, ]; pub fn lookup(c: char) -> bool { super::skip_search( @@ -279,41 +282,41 @@ pub mod cc { #[rustfmt::skip] pub mod grapheme_extend { - static SHORT_OFFSET_RUNS: [u32; 33] = [ - 768, 2098307, 6292881, 10490717, 522196754, 526393356, 731917551, 740306986, 752920175, - 761309186, 778107678, 908131840, 912326558, 920715773, 924912129, 937495844, 962662059, - 966858799, 1214323760, 1285627635, 1348547648, 1369533168, 1377922895, 1386331293, - 1398918912, 1403113829, 1411504640, 1440866304, 1466032814, 1495393516, 1503783120, - 1508769824, 1518273008, + static SHORT_OFFSET_RUNS: [u32; 34] = [ + 768, 2098307, 6292881, 10490717, 522196754, 526393356, 723528943, 731918378, 744531567, + 752920578, 769719070, 908131840, 912326558, 920715773, 924912129, 937495844, 962662059, + 971053103, 1256266800, 1323376371, 1386296384, 1407279390, 1415670512, 1424060239, + 1432468637, 1449250560, 1453445477, 1461836288, 1487003648, 1512170158, 1541530860, + 1549920464, 1559101472, 1568604656, ]; - static OFFSETS: [u8; 727] = [ + static OFFSETS: [u8; 751] = [ 0, 112, 0, 7, 0, 45, 1, 1, 1, 2, 1, 2, 1, 1, 72, 11, 48, 21, 16, 1, 101, 7, 2, 6, 2, 2, 1, - 4, 35, 1, 30, 27, 91, 11, 58, 9, 9, 1, 24, 4, 1, 9, 1, 3, 1, 5, 43, 3, 60, 8, 42, 24, 1, 32, + 4, 35, 1, 30, 27, 91, 11, 58, 9, 9, 1, 24, 4, 1, 9, 1, 3, 1, 5, 43, 3, 59, 9, 42, 24, 1, 32, 55, 1, 1, 1, 4, 8, 4, 1, 3, 7, 10, 2, 29, 1, 58, 1, 1, 1, 2, 4, 8, 1, 9, 1, 10, 2, 26, 1, 2, 2, 57, 1, 4, 2, 4, 2, 2, 3, 3, 1, 30, 2, 3, 1, 11, 2, 57, 1, 4, 5, 1, 2, 4, 1, 20, 2, 22, 6, 1, 1, 58, 1, 1, 2, 1, 4, 8, 1, 7, 3, 10, 2, 30, 1, 59, 1, 1, 1, 12, 1, 9, 1, 40, 1, 3, 1, - 55, 1, 1, 3, 5, 3, 1, 4, 7, 2, 11, 2, 29, 1, 58, 1, 2, 1, 2, 1, 3, 1, 5, 2, 7, 2, 11, 2, 28, + 55, 1, 1, 3, 5, 3, 1, 4, 7, 2, 11, 2, 29, 1, 58, 1, 2, 2, 1, 1, 3, 3, 1, 4, 7, 2, 11, 2, 28, 2, 57, 2, 1, 1, 2, 4, 8, 1, 9, 1, 10, 2, 29, 1, 72, 1, 4, 1, 2, 3, 1, 1, 8, 1, 81, 1, 2, 7, 12, 8, 98, 1, 2, 9, 11, 7, 73, 2, 27, 1, 1, 1, 1, 1, 55, 14, 1, 5, 1, 2, 5, 11, 1, 36, 9, 1, - 102, 4, 1, 6, 1, 2, 2, 2, 25, 2, 4, 3, 16, 4, 13, 1, 2, 2, 6, 1, 15, 1, 0, 3, 0, 3, 29, 2, - 30, 2, 30, 2, 64, 2, 1, 7, 8, 1, 2, 11, 9, 1, 45, 3, 1, 1, 117, 2, 34, 1, 118, 3, 4, 2, 9, - 1, 6, 3, 219, 2, 2, 1, 58, 1, 1, 7, 1, 1, 1, 1, 2, 8, 6, 10, 2, 1, 48, 31, 49, 4, 48, 7, 1, - 1, 5, 1, 40, 9, 12, 2, 32, 4, 2, 2, 1, 3, 56, 1, 1, 2, 3, 1, 1, 3, 58, 8, 2, 2, 152, 3, 1, - 13, 1, 7, 4, 1, 6, 1, 3, 2, 198, 64, 0, 1, 195, 33, 0, 3, 141, 1, 96, 32, 0, 6, 105, 2, 0, - 4, 1, 10, 32, 2, 80, 2, 0, 1, 3, 1, 4, 1, 25, 2, 5, 1, 151, 2, 26, 18, 13, 1, 38, 8, 25, 11, - 46, 3, 48, 1, 2, 4, 2, 2, 39, 1, 67, 6, 2, 2, 2, 2, 12, 1, 8, 1, 47, 1, 51, 1, 1, 3, 2, 2, - 5, 2, 1, 1, 42, 2, 8, 1, 238, 1, 2, 1, 4, 1, 0, 1, 0, 16, 16, 16, 0, 2, 0, 1, 226, 1, 149, - 5, 0, 3, 1, 2, 5, 4, 40, 3, 4, 1, 165, 2, 0, 4, 0, 2, 80, 3, 70, 11, 49, 4, 123, 1, 54, 15, - 41, 1, 2, 2, 10, 3, 49, 4, 2, 2, 7, 1, 61, 3, 36, 5, 1, 8, 62, 1, 12, 2, 52, 9, 10, 4, 2, 1, - 95, 3, 2, 1, 1, 2, 6, 1, 2, 1, 157, 1, 3, 8, 21, 2, 57, 2, 1, 1, 1, 1, 22, 1, 14, 7, 3, 5, - 195, 8, 2, 3, 1, 1, 23, 1, 81, 1, 2, 6, 1, 1, 2, 1, 1, 2, 1, 2, 235, 1, 2, 4, 6, 2, 1, 2, - 27, 2, 85, 8, 2, 1, 1, 2, 106, 1, 1, 1, 2, 6, 1, 1, 101, 3, 2, 4, 1, 5, 0, 9, 1, 2, 245, 1, - 10, 2, 1, 1, 4, 1, 144, 4, 2, 2, 4, 1, 32, 10, 40, 6, 2, 4, 8, 1, 9, 6, 2, 3, 46, 13, 1, 2, - 0, 7, 1, 6, 1, 1, 82, 22, 2, 7, 1, 2, 1, 2, 122, 6, 3, 1, 1, 2, 1, 7, 1, 1, 72, 2, 3, 1, 1, - 1, 0, 2, 11, 2, 52, 5, 5, 1, 1, 1, 0, 1, 6, 15, 0, 5, 59, 7, 0, 1, 63, 4, 81, 1, 0, 2, 0, - 46, 2, 23, 0, 1, 1, 3, 4, 5, 8, 8, 2, 7, 30, 4, 148, 3, 0, 55, 4, 50, 8, 1, 14, 1, 22, 5, 1, - 15, 0, 7, 1, 17, 2, 7, 1, 2, 1, 5, 100, 1, 160, 7, 0, 1, 61, 4, 0, 4, 0, 7, 109, 7, 0, 96, - 128, 240, 0, + 102, 4, 1, 6, 1, 2, 2, 2, 25, 2, 4, 3, 16, 4, 13, 1, 2, 2, 6, 1, 15, 1, 0, 3, 0, 4, 28, 3, + 29, 2, 30, 2, 64, 2, 1, 7, 8, 1, 2, 11, 9, 1, 45, 3, 1, 1, 117, 2, 34, 1, 118, 3, 4, 2, 9, + 1, 6, 3, 219, 2, 2, 1, 58, 1, 1, 7, 1, 1, 1, 1, 2, 8, 6, 10, 2, 1, 48, 31, 49, 4, 48, 10, 4, + 3, 38, 9, 12, 2, 32, 4, 2, 6, 56, 1, 1, 2, 3, 1, 1, 5, 56, 8, 2, 2, 152, 3, 1, 13, 1, 7, 4, + 1, 6, 1, 3, 2, 198, 64, 0, 1, 195, 33, 0, 3, 141, 1, 96, 32, 0, 6, 105, 2, 0, 4, 1, 10, 32, + 2, 80, 2, 0, 1, 3, 1, 4, 1, 25, 2, 5, 1, 151, 2, 26, 18, 13, 1, 38, 8, 25, 11, 1, 1, 44, 3, + 48, 1, 2, 4, 2, 2, 2, 1, 36, 1, 67, 6, 2, 2, 2, 2, 12, 1, 8, 1, 47, 1, 51, 1, 1, 3, 2, 2, 5, + 2, 1, 1, 42, 2, 8, 1, 238, 1, 2, 1, 4, 1, 0, 1, 0, 16, 16, 16, 0, 2, 0, 1, 226, 1, 149, 5, + 0, 3, 1, 2, 5, 4, 40, 3, 4, 1, 165, 2, 0, 4, 65, 5, 0, 2, 79, 4, 70, 11, 49, 4, 123, 1, 54, + 15, 41, 1, 2, 2, 10, 3, 49, 4, 2, 2, 7, 1, 61, 3, 36, 5, 1, 8, 62, 1, 12, 2, 52, 9, 1, 1, 8, + 4, 2, 1, 95, 3, 2, 4, 6, 1, 2, 1, 157, 1, 3, 8, 21, 2, 57, 2, 1, 1, 1, 1, 12, 1, 9, 1, 14, + 7, 3, 5, 67, 1, 2, 6, 1, 1, 2, 1, 1, 3, 4, 3, 1, 1, 14, 2, 85, 8, 2, 3, 1, 1, 23, 1, 81, 1, + 2, 6, 1, 1, 2, 1, 1, 2, 1, 2, 235, 1, 2, 4, 6, 2, 1, 2, 27, 2, 85, 8, 2, 1, 1, 2, 106, 1, 1, + 1, 2, 8, 101, 1, 1, 1, 2, 4, 1, 5, 0, 9, 1, 2, 245, 1, 10, 4, 4, 1, 144, 4, 2, 2, 4, 1, 32, + 10, 40, 6, 2, 4, 8, 1, 9, 6, 2, 3, 46, 13, 1, 2, 0, 7, 1, 6, 1, 1, 82, 22, 2, 7, 1, 2, 1, 2, + 122, 6, 3, 1, 1, 2, 1, 7, 1, 1, 72, 2, 3, 1, 1, 1, 0, 2, 11, 2, 52, 5, 5, 3, 23, 1, 0, 1, 6, + 15, 0, 12, 3, 3, 0, 5, 59, 7, 0, 1, 63, 4, 81, 1, 11, 2, 0, 2, 0, 46, 2, 23, 0, 5, 3, 6, 8, + 8, 2, 7, 30, 4, 148, 3, 0, 55, 4, 50, 8, 1, 14, 1, 22, 5, 1, 15, 0, 7, 1, 17, 2, 7, 1, 2, 1, + 5, 100, 1, 160, 7, 0, 1, 61, 4, 0, 4, 254, 2, 0, 7, 109, 7, 0, 96, 128, 240, 0, ]; #[inline] pub fn lookup(c: char) -> bool { @@ -339,27 +342,27 @@ pub mod lowercase { ]; const BITSET_INDEX_CHUNKS: &'static [[u8; 16]; 20] = &[ [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], - [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 59, 0, 0], - [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 14, 55, 0], + [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 61, 0, 0], + [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 14, 56, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 40, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 44, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0], - [0, 0, 0, 0, 0, 0, 0, 0, 0, 65, 43, 0, 51, 47, 49, 33], - [0, 0, 0, 0, 10, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], - [0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0, 0, 0, 67, 43, 0, 52, 48, 50, 33], + [0, 0, 0, 0, 10, 57, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 3, 0, 16, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 27], - [0, 0, 0, 60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], - [0, 0, 0, 69, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], - [0, 0, 57, 0, 55, 55, 55, 0, 22, 22, 67, 22, 36, 25, 24, 37], - [0, 5, 68, 0, 29, 15, 73, 0, 0, 0, 0, 0, 0, 0, 0, 0], - [0, 64, 34, 17, 23, 52, 53, 48, 46, 8, 35, 42, 0, 28, 13, 31], - [11, 58, 0, 6, 0, 0, 30, 0, 0, 0, 0, 0, 0, 0, 32, 0], + [0, 0, 0, 62, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 71, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + [0, 0, 46, 0, 56, 56, 56, 0, 22, 22, 69, 22, 36, 25, 24, 37], + [0, 5, 70, 0, 29, 15, 75, 0, 0, 0, 0, 0, 0, 0, 0, 0], + [0, 66, 34, 17, 23, 53, 54, 49, 47, 8, 35, 42, 0, 28, 13, 31], + [11, 60, 0, 6, 0, 0, 30, 0, 0, 0, 0, 0, 0, 0, 32, 0], [16, 26, 22, 38, 39, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], - [16, 50, 2, 21, 66, 9, 57, 0, 0, 0, 0, 0, 0, 0, 0, 0], - [16, 70, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], - [63, 41, 54, 12, 75, 61, 18, 1, 7, 62, 74, 20, 71, 72, 4, 45], + [16, 51, 2, 21, 68, 9, 59, 0, 0, 0, 0, 0, 0, 0, 0, 0], + [16, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + [65, 41, 55, 12, 77, 63, 18, 1, 7, 64, 76, 20, 73, 74, 4, 45], ]; - const BITSET_CANONICAL: &'static [u64; 55] = &[ + const BITSET_CANONICAL: &'static [u64; 56] = &[ 0b0000000000000000000000000000000000000000000000000000000000000000, 0b1111111111111111110000000000000000000000000011111111111111111111, 0b1010101010101010101010101010101010101010101010101010100000000010, @@ -393,7 +396,7 @@ pub mod lowercase { 0b0001101111111011111111111111101111111111100000000000000000000000, 0b0001100100101111101010101010101010101010111000110111111111111111, 0b0000011111111101111111111111111111111111111111111111111110111001, - 0b0000011101011100000000000000000000000010101010100000010100001010, + 0b0000011101011100000000000000000000001010101010100010010100001010, 0b0000010000100000000001000000000000000000000000000000000000000000, 0b0000000111111111111111111111111111111111111011111111111111111111, 0b0000000011111111000000001111111100000000001111110000000011111111, @@ -406,6 +409,7 @@ pub mod lowercase { 0b0000000000000000000000000000000000111010101010101010101010101010, 0b0000000000000000000000000000000000000000111110000000000001111111, 0b0000000000000000000000000000000000000000000000000000101111110111, + 0b0000000000000000000000000000000000000000000000000000010111111111, 0b1001001111111010101010101010101010101010101010101010101010101010, 0b1001010111111111101010101010101010101010101010101010101010101010, 0b1010101000101001101010101010101010110101010101010101001001000000, @@ -416,9 +420,9 @@ pub mod lowercase { 0b1110011001010001001011010010101001001110001001000011000100101001, 0b1110101111000000000000000000000000001111111111111111111111111100, ]; - const BITSET_MAPPING: &'static [(u8, u8); 21] = &[ - (0, 64), (1, 188), (1, 183), (1, 176), (1, 109), (1, 124), (1, 126), (1, 66), (1, 70), - (1, 77), (2, 146), (2, 144), (2, 83), (3, 93), (3, 147), (3, 133), (4, 12), (4, 6), + const BITSET_MAPPING: &'static [(u8, u8); 22] = &[ + (0, 64), (1, 188), (1, 186), (1, 183), (1, 176), (1, 109), (1, 124), (1, 126), (1, 66), + (1, 70), (1, 77), (2, 146), (2, 144), (2, 83), (3, 93), (3, 147), (3, 133), (4, 12), (4, 6), (5, 187), (6, 78), (7, 132), ]; @@ -436,14 +440,15 @@ pub mod lowercase { #[rustfmt::skip] pub mod n { - static SHORT_OFFSET_RUNS: [u32; 39] = [ + static SHORT_OFFSET_RUNS: [u32; 42] = [ 1632, 18876774, 31461440, 102765417, 111154926, 115349830, 132128880, 165684320, 186656630, 195046653, 199241735, 203436434, 216049184, 241215536, 249605104, 274792208, 278987015, - 283181793, 295766104, 320933114, 383848032, 392238160, 434181712, 442570976, 455154768, - 463544144, 476128256, 484534880, 488730240, 505533120, 509728718, 522314048, 526508784, - 530703600, 534898887, 539094129, 547483904, 568458224, 573766650, + 283181793, 295766104, 320933114, 383848032, 396432464, 438376016, 446765280, 463543280, + 471932752, 488711168, 497115440, 501312096, 505507184, 522284672, 526503152, 530698944, + 534894542, 547479872, 551674608, 555869424, 560064711, 568454257, 576844032, 597818352, + 603126778, ]; - static OFFSETS: [u8; 275] = [ + static OFFSETS: [u8; 289] = [ 48, 10, 120, 2, 5, 1, 2, 3, 0, 10, 134, 10, 198, 10, 0, 10, 118, 10, 4, 6, 108, 10, 118, 10, 118, 10, 2, 6, 110, 13, 115, 10, 8, 7, 103, 10, 104, 7, 7, 19, 109, 10, 96, 10, 118, 10, 70, 20, 0, 10, 70, 10, 0, 20, 0, 3, 239, 10, 6, 10, 22, 10, 0, 10, 128, 11, 165, 10, 6, 10, @@ -451,11 +456,11 @@ pub mod n { 1, 0, 1, 25, 9, 14, 3, 0, 4, 138, 10, 30, 8, 1, 15, 32, 10, 39, 15, 0, 10, 188, 10, 0, 6, 154, 10, 38, 10, 198, 10, 22, 10, 86, 10, 0, 10, 0, 10, 0, 45, 12, 57, 17, 2, 0, 27, 36, 4, 29, 1, 8, 1, 134, 5, 202, 10, 0, 8, 25, 7, 39, 9, 75, 5, 22, 6, 160, 2, 2, 16, 2, 46, 64, 9, - 52, 2, 30, 3, 75, 5, 104, 8, 24, 8, 41, 7, 0, 6, 48, 10, 0, 31, 158, 10, 42, 4, 112, 7, 134, - 30, 128, 10, 60, 10, 144, 10, 7, 20, 251, 10, 0, 10, 118, 10, 0, 10, 102, 10, 102, 12, 0, - 19, 93, 10, 0, 29, 227, 10, 70, 10, 0, 10, 102, 21, 0, 111, 0, 10, 86, 10, 134, 10, 1, 7, 0, - 23, 0, 20, 12, 20, 108, 25, 0, 50, 0, 10, 0, 10, 0, 10, 0, 9, 128, 10, 0, 59, 1, 3, 1, 4, - 76, 45, 1, 15, 0, 13, 0, 10, 0, + 52, 2, 30, 3, 75, 5, 104, 8, 24, 8, 41, 7, 0, 6, 48, 10, 6, 10, 0, 31, 158, 10, 42, 4, 112, + 7, 134, 30, 128, 10, 60, 10, 144, 10, 7, 20, 251, 10, 0, 10, 118, 10, 0, 10, 102, 10, 6, 20, + 76, 12, 0, 19, 93, 10, 0, 10, 86, 29, 227, 10, 70, 10, 0, 10, 102, 21, 0, 111, 0, 10, 0, 10, + 86, 10, 134, 10, 1, 7, 0, 10, 0, 23, 0, 10, 0, 20, 12, 20, 108, 25, 0, 50, 0, 10, 0, 10, 0, + 10, 247, 10, 0, 9, 128, 10, 0, 59, 1, 3, 1, 4, 76, 45, 1, 15, 0, 13, 0, 10, 0, ]; pub fn lookup(c: char) -> bool { super::skip_search( @@ -476,30 +481,30 @@ pub mod uppercase { 6, 6, 9, 6, 3, ]; const BITSET_INDEX_CHUNKS: &'static [[u8; 16]; 17] = &[ - [43, 43, 5, 34, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 5, 1], - [43, 43, 5, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43], - [43, 43, 39, 43, 43, 43, 43, 43, 17, 17, 62, 17, 42, 29, 24, 23], - [43, 43, 43, 43, 9, 8, 44, 43, 43, 43, 43, 43, 43, 43, 43, 43], - [43, 43, 43, 43, 36, 28, 66, 43, 43, 43, 43, 43, 43, 43, 43, 43], - [43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 0, 43, 43, 43], - [43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43], - [43, 43, 43, 43, 43, 43, 43, 43, 43, 54, 43, 43, 43, 43, 43, 43], - [43, 43, 43, 43, 43, 43, 43, 43, 43, 61, 60, 43, 20, 14, 16, 4], - [43, 43, 43, 43, 55, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43], - [43, 43, 58, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43], - [43, 43, 59, 45, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43], - [43, 48, 43, 31, 35, 21, 22, 15, 13, 33, 43, 43, 43, 11, 30, 38], - [51, 53, 26, 49, 12, 7, 25, 50, 40, 52, 6, 3, 65, 64, 63, 67], - [56, 43, 9, 46, 43, 41, 32, 43, 43, 43, 43, 43, 43, 43, 43, 43], - [57, 19, 2, 18, 10, 47, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43], - [57, 37, 17, 27, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43], + [44, 44, 5, 35, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 5, 1], + [44, 44, 5, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44], + [44, 44, 40, 44, 44, 44, 44, 44, 17, 17, 63, 17, 43, 29, 24, 23], + [44, 44, 44, 44, 9, 8, 45, 44, 44, 44, 44, 44, 44, 44, 44, 44], + [44, 44, 44, 44, 37, 28, 67, 44, 44, 44, 44, 44, 44, 44, 44, 44], + [44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 0, 44, 44, 44], + [44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44], + [44, 44, 44, 44, 44, 44, 44, 44, 44, 55, 44, 44, 44, 44, 44, 44], + [44, 44, 44, 44, 44, 44, 44, 44, 44, 62, 61, 44, 20, 14, 16, 4], + [44, 44, 44, 44, 56, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44], + [44, 44, 59, 44, 44, 31, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44], + [44, 44, 60, 46, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44], + [44, 49, 44, 32, 36, 21, 22, 15, 13, 34, 44, 44, 44, 11, 30, 39], + [52, 54, 26, 50, 12, 7, 25, 51, 41, 53, 6, 3, 66, 65, 64, 68], + [57, 44, 9, 47, 44, 42, 33, 44, 44, 44, 44, 44, 44, 44, 44, 44], + [58, 19, 2, 18, 10, 48, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44], + [58, 38, 17, 27, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44], ]; - const BITSET_CANONICAL: &'static [u64; 43] = &[ + const BITSET_CANONICAL: &'static [u64; 44] = &[ 0b0000011111111111111111111111111000000000000000000000000000000000, 0b0000000000111111111111111111111111111111111111111111111111111111, 0b0101010101010101010101010101010101010101010101010101010000000001, 0b0000011111111111111111111111110000000000000000000000000000000001, - 0b0000000000100000000000000000000000000001010000010000001011110101, + 0b0000000000100000000000000000000000010101010000010001101011110101, 0b1111111111111111111111111111111100000000000000000000000000000000, 0b1111111111111111111111110000000000000000000000000000001111111111, 0b1111111111111111111100000000000000000000000000011111110001011111, @@ -526,6 +531,7 @@ pub mod uppercase { 0b0000000000000000111111111111111100000000000000000000000000100000, 0b0000000000000000111111110000000010101010000000000011111100000000, 0b0000000000000000000011111111101111111111111111101101011101000000, + 0b0000000000000000000000000011111111111111111111110000000000000000, 0b0000000000000000000000000000000001111111011111111111111111111111, 0b0000000000000000000000000000000000000000001101111111011111111111, 0b0000000000000000000000000000000000000000000000000101010101111010, @@ -534,7 +540,7 @@ pub mod uppercase { 0b1100000000001111001111010101000000111110001001110011100010000100, 0b1100000000100101111010101001110100000000000000000000000000000000, 0b1110011010010000010101010101010101010101000111001000000000000000, - 0b1110011111111111111111111111111111111111111111110000000000000000, + 0b1110011111111111111111111111111111111111111111110000001000000000, 0b1111000000000000000000000000001111111111111111111111111100000000, 0b1111011111111111000000000000000000000000000000000000000000000000, 0b1111111100000000111111110000000000111111000000001111111100000000, @@ -751,216 +757,223 @@ pub mod conversions { ('\u{13ea}', 43962), ('\u{13eb}', 43963), ('\u{13ec}', 43964), ('\u{13ed}', 43965), ('\u{13ee}', 43966), ('\u{13ef}', 43967), ('\u{13f0}', 5112), ('\u{13f1}', 5113), ('\u{13f2}', 5114), ('\u{13f3}', 5115), ('\u{13f4}', 5116), ('\u{13f5}', 5117), - ('\u{1c90}', 4304), ('\u{1c91}', 4305), ('\u{1c92}', 4306), ('\u{1c93}', 4307), - ('\u{1c94}', 4308), ('\u{1c95}', 4309), ('\u{1c96}', 4310), ('\u{1c97}', 4311), - ('\u{1c98}', 4312), ('\u{1c99}', 4313), ('\u{1c9a}', 4314), ('\u{1c9b}', 4315), - ('\u{1c9c}', 4316), ('\u{1c9d}', 4317), ('\u{1c9e}', 4318), ('\u{1c9f}', 4319), - ('\u{1ca0}', 4320), ('\u{1ca1}', 4321), ('\u{1ca2}', 4322), ('\u{1ca3}', 4323), - ('\u{1ca4}', 4324), ('\u{1ca5}', 4325), ('\u{1ca6}', 4326), ('\u{1ca7}', 4327), - ('\u{1ca8}', 4328), ('\u{1ca9}', 4329), ('\u{1caa}', 4330), ('\u{1cab}', 4331), - ('\u{1cac}', 4332), ('\u{1cad}', 4333), ('\u{1cae}', 4334), ('\u{1caf}', 4335), - ('\u{1cb0}', 4336), ('\u{1cb1}', 4337), ('\u{1cb2}', 4338), ('\u{1cb3}', 4339), - ('\u{1cb4}', 4340), ('\u{1cb5}', 4341), ('\u{1cb6}', 4342), ('\u{1cb7}', 4343), - ('\u{1cb8}', 4344), ('\u{1cb9}', 4345), ('\u{1cba}', 4346), ('\u{1cbd}', 4349), - ('\u{1cbe}', 4350), ('\u{1cbf}', 4351), ('\u{1e00}', 7681), ('\u{1e02}', 7683), - ('\u{1e04}', 7685), ('\u{1e06}', 7687), ('\u{1e08}', 7689), ('\u{1e0a}', 7691), - ('\u{1e0c}', 7693), ('\u{1e0e}', 7695), ('\u{1e10}', 7697), ('\u{1e12}', 7699), - ('\u{1e14}', 7701), ('\u{1e16}', 7703), ('\u{1e18}', 7705), ('\u{1e1a}', 7707), - ('\u{1e1c}', 7709), ('\u{1e1e}', 7711), ('\u{1e20}', 7713), ('\u{1e22}', 7715), - ('\u{1e24}', 7717), ('\u{1e26}', 7719), ('\u{1e28}', 7721), ('\u{1e2a}', 7723), - ('\u{1e2c}', 7725), ('\u{1e2e}', 7727), ('\u{1e30}', 7729), ('\u{1e32}', 7731), - ('\u{1e34}', 7733), ('\u{1e36}', 7735), ('\u{1e38}', 7737), ('\u{1e3a}', 7739), - ('\u{1e3c}', 7741), ('\u{1e3e}', 7743), ('\u{1e40}', 7745), ('\u{1e42}', 7747), - ('\u{1e44}', 7749), ('\u{1e46}', 7751), ('\u{1e48}', 7753), ('\u{1e4a}', 7755), - ('\u{1e4c}', 7757), ('\u{1e4e}', 7759), ('\u{1e50}', 7761), ('\u{1e52}', 7763), - ('\u{1e54}', 7765), ('\u{1e56}', 7767), ('\u{1e58}', 7769), ('\u{1e5a}', 7771), - ('\u{1e5c}', 7773), ('\u{1e5e}', 7775), ('\u{1e60}', 7777), ('\u{1e62}', 7779), - ('\u{1e64}', 7781), ('\u{1e66}', 7783), ('\u{1e68}', 7785), ('\u{1e6a}', 7787), - ('\u{1e6c}', 7789), ('\u{1e6e}', 7791), ('\u{1e70}', 7793), ('\u{1e72}', 7795), - ('\u{1e74}', 7797), ('\u{1e76}', 7799), ('\u{1e78}', 7801), ('\u{1e7a}', 7803), - ('\u{1e7c}', 7805), ('\u{1e7e}', 7807), ('\u{1e80}', 7809), ('\u{1e82}', 7811), - ('\u{1e84}', 7813), ('\u{1e86}', 7815), ('\u{1e88}', 7817), ('\u{1e8a}', 7819), - ('\u{1e8c}', 7821), ('\u{1e8e}', 7823), ('\u{1e90}', 7825), ('\u{1e92}', 7827), - ('\u{1e94}', 7829), ('\u{1e9e}', 223), ('\u{1ea0}', 7841), ('\u{1ea2}', 7843), - ('\u{1ea4}', 7845), ('\u{1ea6}', 7847), ('\u{1ea8}', 7849), ('\u{1eaa}', 7851), - ('\u{1eac}', 7853), ('\u{1eae}', 7855), ('\u{1eb0}', 7857), ('\u{1eb2}', 7859), - ('\u{1eb4}', 7861), ('\u{1eb6}', 7863), ('\u{1eb8}', 7865), ('\u{1eba}', 7867), - ('\u{1ebc}', 7869), ('\u{1ebe}', 7871), ('\u{1ec0}', 7873), ('\u{1ec2}', 7875), - ('\u{1ec4}', 7877), ('\u{1ec6}', 7879), ('\u{1ec8}', 7881), ('\u{1eca}', 7883), - ('\u{1ecc}', 7885), ('\u{1ece}', 7887), ('\u{1ed0}', 7889), ('\u{1ed2}', 7891), - ('\u{1ed4}', 7893), ('\u{1ed6}', 7895), ('\u{1ed8}', 7897), ('\u{1eda}', 7899), - ('\u{1edc}', 7901), ('\u{1ede}', 7903), ('\u{1ee0}', 7905), ('\u{1ee2}', 7907), - ('\u{1ee4}', 7909), ('\u{1ee6}', 7911), ('\u{1ee8}', 7913), ('\u{1eea}', 7915), - ('\u{1eec}', 7917), ('\u{1eee}', 7919), ('\u{1ef0}', 7921), ('\u{1ef2}', 7923), - ('\u{1ef4}', 7925), ('\u{1ef6}', 7927), ('\u{1ef8}', 7929), ('\u{1efa}', 7931), - ('\u{1efc}', 7933), ('\u{1efe}', 7935), ('\u{1f08}', 7936), ('\u{1f09}', 7937), - ('\u{1f0a}', 7938), ('\u{1f0b}', 7939), ('\u{1f0c}', 7940), ('\u{1f0d}', 7941), - ('\u{1f0e}', 7942), ('\u{1f0f}', 7943), ('\u{1f18}', 7952), ('\u{1f19}', 7953), - ('\u{1f1a}', 7954), ('\u{1f1b}', 7955), ('\u{1f1c}', 7956), ('\u{1f1d}', 7957), - ('\u{1f28}', 7968), ('\u{1f29}', 7969), ('\u{1f2a}', 7970), ('\u{1f2b}', 7971), - ('\u{1f2c}', 7972), ('\u{1f2d}', 7973), ('\u{1f2e}', 7974), ('\u{1f2f}', 7975), - ('\u{1f38}', 7984), ('\u{1f39}', 7985), ('\u{1f3a}', 7986), ('\u{1f3b}', 7987), - ('\u{1f3c}', 7988), ('\u{1f3d}', 7989), ('\u{1f3e}', 7990), ('\u{1f3f}', 7991), - ('\u{1f48}', 8000), ('\u{1f49}', 8001), ('\u{1f4a}', 8002), ('\u{1f4b}', 8003), - ('\u{1f4c}', 8004), ('\u{1f4d}', 8005), ('\u{1f59}', 8017), ('\u{1f5b}', 8019), - ('\u{1f5d}', 8021), ('\u{1f5f}', 8023), ('\u{1f68}', 8032), ('\u{1f69}', 8033), - ('\u{1f6a}', 8034), ('\u{1f6b}', 8035), ('\u{1f6c}', 8036), ('\u{1f6d}', 8037), - ('\u{1f6e}', 8038), ('\u{1f6f}', 8039), ('\u{1f88}', 8064), ('\u{1f89}', 8065), - ('\u{1f8a}', 8066), ('\u{1f8b}', 8067), ('\u{1f8c}', 8068), ('\u{1f8d}', 8069), - ('\u{1f8e}', 8070), ('\u{1f8f}', 8071), ('\u{1f98}', 8080), ('\u{1f99}', 8081), - ('\u{1f9a}', 8082), ('\u{1f9b}', 8083), ('\u{1f9c}', 8084), ('\u{1f9d}', 8085), - ('\u{1f9e}', 8086), ('\u{1f9f}', 8087), ('\u{1fa8}', 8096), ('\u{1fa9}', 8097), - ('\u{1faa}', 8098), ('\u{1fab}', 8099), ('\u{1fac}', 8100), ('\u{1fad}', 8101), - ('\u{1fae}', 8102), ('\u{1faf}', 8103), ('\u{1fb8}', 8112), ('\u{1fb9}', 8113), - ('\u{1fba}', 8048), ('\u{1fbb}', 8049), ('\u{1fbc}', 8115), ('\u{1fc8}', 8050), - ('\u{1fc9}', 8051), ('\u{1fca}', 8052), ('\u{1fcb}', 8053), ('\u{1fcc}', 8131), - ('\u{1fd8}', 8144), ('\u{1fd9}', 8145), ('\u{1fda}', 8054), ('\u{1fdb}', 8055), - ('\u{1fe8}', 8160), ('\u{1fe9}', 8161), ('\u{1fea}', 8058), ('\u{1feb}', 8059), - ('\u{1fec}', 8165), ('\u{1ff8}', 8056), ('\u{1ff9}', 8057), ('\u{1ffa}', 8060), - ('\u{1ffb}', 8061), ('\u{1ffc}', 8179), ('\u{2126}', 969), ('\u{212a}', 107), - ('\u{212b}', 229), ('\u{2132}', 8526), ('\u{2160}', 8560), ('\u{2161}', 8561), - ('\u{2162}', 8562), ('\u{2163}', 8563), ('\u{2164}', 8564), ('\u{2165}', 8565), - ('\u{2166}', 8566), ('\u{2167}', 8567), ('\u{2168}', 8568), ('\u{2169}', 8569), - ('\u{216a}', 8570), ('\u{216b}', 8571), ('\u{216c}', 8572), ('\u{216d}', 8573), - ('\u{216e}', 8574), ('\u{216f}', 8575), ('\u{2183}', 8580), ('\u{24b6}', 9424), - ('\u{24b7}', 9425), ('\u{24b8}', 9426), ('\u{24b9}', 9427), ('\u{24ba}', 9428), - ('\u{24bb}', 9429), ('\u{24bc}', 9430), ('\u{24bd}', 9431), ('\u{24be}', 9432), - ('\u{24bf}', 9433), ('\u{24c0}', 9434), ('\u{24c1}', 9435), ('\u{24c2}', 9436), - ('\u{24c3}', 9437), ('\u{24c4}', 9438), ('\u{24c5}', 9439), ('\u{24c6}', 9440), - ('\u{24c7}', 9441), ('\u{24c8}', 9442), ('\u{24c9}', 9443), ('\u{24ca}', 9444), - ('\u{24cb}', 9445), ('\u{24cc}', 9446), ('\u{24cd}', 9447), ('\u{24ce}', 9448), - ('\u{24cf}', 9449), ('\u{2c00}', 11312), ('\u{2c01}', 11313), ('\u{2c02}', 11314), - ('\u{2c03}', 11315), ('\u{2c04}', 11316), ('\u{2c05}', 11317), ('\u{2c06}', 11318), - ('\u{2c07}', 11319), ('\u{2c08}', 11320), ('\u{2c09}', 11321), ('\u{2c0a}', 11322), - ('\u{2c0b}', 11323), ('\u{2c0c}', 11324), ('\u{2c0d}', 11325), ('\u{2c0e}', 11326), - ('\u{2c0f}', 11327), ('\u{2c10}', 11328), ('\u{2c11}', 11329), ('\u{2c12}', 11330), - ('\u{2c13}', 11331), ('\u{2c14}', 11332), ('\u{2c15}', 11333), ('\u{2c16}', 11334), - ('\u{2c17}', 11335), ('\u{2c18}', 11336), ('\u{2c19}', 11337), ('\u{2c1a}', 11338), - ('\u{2c1b}', 11339), ('\u{2c1c}', 11340), ('\u{2c1d}', 11341), ('\u{2c1e}', 11342), - ('\u{2c1f}', 11343), ('\u{2c20}', 11344), ('\u{2c21}', 11345), ('\u{2c22}', 11346), - ('\u{2c23}', 11347), ('\u{2c24}', 11348), ('\u{2c25}', 11349), ('\u{2c26}', 11350), - ('\u{2c27}', 11351), ('\u{2c28}', 11352), ('\u{2c29}', 11353), ('\u{2c2a}', 11354), - ('\u{2c2b}', 11355), ('\u{2c2c}', 11356), ('\u{2c2d}', 11357), ('\u{2c2e}', 11358), - ('\u{2c2f}', 11359), ('\u{2c60}', 11361), ('\u{2c62}', 619), ('\u{2c63}', 7549), - ('\u{2c64}', 637), ('\u{2c67}', 11368), ('\u{2c69}', 11370), ('\u{2c6b}', 11372), - ('\u{2c6d}', 593), ('\u{2c6e}', 625), ('\u{2c6f}', 592), ('\u{2c70}', 594), - ('\u{2c72}', 11379), ('\u{2c75}', 11382), ('\u{2c7e}', 575), ('\u{2c7f}', 576), - ('\u{2c80}', 11393), ('\u{2c82}', 11395), ('\u{2c84}', 11397), ('\u{2c86}', 11399), - ('\u{2c88}', 11401), ('\u{2c8a}', 11403), ('\u{2c8c}', 11405), ('\u{2c8e}', 11407), - ('\u{2c90}', 11409), ('\u{2c92}', 11411), ('\u{2c94}', 11413), ('\u{2c96}', 11415), - ('\u{2c98}', 11417), ('\u{2c9a}', 11419), ('\u{2c9c}', 11421), ('\u{2c9e}', 11423), - ('\u{2ca0}', 11425), ('\u{2ca2}', 11427), ('\u{2ca4}', 11429), ('\u{2ca6}', 11431), - ('\u{2ca8}', 11433), ('\u{2caa}', 11435), ('\u{2cac}', 11437), ('\u{2cae}', 11439), - ('\u{2cb0}', 11441), ('\u{2cb2}', 11443), ('\u{2cb4}', 11445), ('\u{2cb6}', 11447), - ('\u{2cb8}', 11449), ('\u{2cba}', 11451), ('\u{2cbc}', 11453), ('\u{2cbe}', 11455), - ('\u{2cc0}', 11457), ('\u{2cc2}', 11459), ('\u{2cc4}', 11461), ('\u{2cc6}', 11463), - ('\u{2cc8}', 11465), ('\u{2cca}', 11467), ('\u{2ccc}', 11469), ('\u{2cce}', 11471), - ('\u{2cd0}', 11473), ('\u{2cd2}', 11475), ('\u{2cd4}', 11477), ('\u{2cd6}', 11479), - ('\u{2cd8}', 11481), ('\u{2cda}', 11483), ('\u{2cdc}', 11485), ('\u{2cde}', 11487), - ('\u{2ce0}', 11489), ('\u{2ce2}', 11491), ('\u{2ceb}', 11500), ('\u{2ced}', 11502), - ('\u{2cf2}', 11507), ('\u{a640}', 42561), ('\u{a642}', 42563), ('\u{a644}', 42565), - ('\u{a646}', 42567), ('\u{a648}', 42569), ('\u{a64a}', 42571), ('\u{a64c}', 42573), - ('\u{a64e}', 42575), ('\u{a650}', 42577), ('\u{a652}', 42579), ('\u{a654}', 42581), - ('\u{a656}', 42583), ('\u{a658}', 42585), ('\u{a65a}', 42587), ('\u{a65c}', 42589), - ('\u{a65e}', 42591), ('\u{a660}', 42593), ('\u{a662}', 42595), ('\u{a664}', 42597), - ('\u{a666}', 42599), ('\u{a668}', 42601), ('\u{a66a}', 42603), ('\u{a66c}', 42605), - ('\u{a680}', 42625), ('\u{a682}', 42627), ('\u{a684}', 42629), ('\u{a686}', 42631), - ('\u{a688}', 42633), ('\u{a68a}', 42635), ('\u{a68c}', 42637), ('\u{a68e}', 42639), - ('\u{a690}', 42641), ('\u{a692}', 42643), ('\u{a694}', 42645), ('\u{a696}', 42647), - ('\u{a698}', 42649), ('\u{a69a}', 42651), ('\u{a722}', 42787), ('\u{a724}', 42789), - ('\u{a726}', 42791), ('\u{a728}', 42793), ('\u{a72a}', 42795), ('\u{a72c}', 42797), - ('\u{a72e}', 42799), ('\u{a732}', 42803), ('\u{a734}', 42805), ('\u{a736}', 42807), - ('\u{a738}', 42809), ('\u{a73a}', 42811), ('\u{a73c}', 42813), ('\u{a73e}', 42815), - ('\u{a740}', 42817), ('\u{a742}', 42819), ('\u{a744}', 42821), ('\u{a746}', 42823), - ('\u{a748}', 42825), ('\u{a74a}', 42827), ('\u{a74c}', 42829), ('\u{a74e}', 42831), - ('\u{a750}', 42833), ('\u{a752}', 42835), ('\u{a754}', 42837), ('\u{a756}', 42839), - ('\u{a758}', 42841), ('\u{a75a}', 42843), ('\u{a75c}', 42845), ('\u{a75e}', 42847), - ('\u{a760}', 42849), ('\u{a762}', 42851), ('\u{a764}', 42853), ('\u{a766}', 42855), - ('\u{a768}', 42857), ('\u{a76a}', 42859), ('\u{a76c}', 42861), ('\u{a76e}', 42863), - ('\u{a779}', 42874), ('\u{a77b}', 42876), ('\u{a77d}', 7545), ('\u{a77e}', 42879), - ('\u{a780}', 42881), ('\u{a782}', 42883), ('\u{a784}', 42885), ('\u{a786}', 42887), - ('\u{a78b}', 42892), ('\u{a78d}', 613), ('\u{a790}', 42897), ('\u{a792}', 42899), - ('\u{a796}', 42903), ('\u{a798}', 42905), ('\u{a79a}', 42907), ('\u{a79c}', 42909), - ('\u{a79e}', 42911), ('\u{a7a0}', 42913), ('\u{a7a2}', 42915), ('\u{a7a4}', 42917), - ('\u{a7a6}', 42919), ('\u{a7a8}', 42921), ('\u{a7aa}', 614), ('\u{a7ab}', 604), - ('\u{a7ac}', 609), ('\u{a7ad}', 620), ('\u{a7ae}', 618), ('\u{a7b0}', 670), - ('\u{a7b1}', 647), ('\u{a7b2}', 669), ('\u{a7b3}', 43859), ('\u{a7b4}', 42933), - ('\u{a7b6}', 42935), ('\u{a7b8}', 42937), ('\u{a7ba}', 42939), ('\u{a7bc}', 42941), - ('\u{a7be}', 42943), ('\u{a7c0}', 42945), ('\u{a7c2}', 42947), ('\u{a7c4}', 42900), - ('\u{a7c5}', 642), ('\u{a7c6}', 7566), ('\u{a7c7}', 42952), ('\u{a7c9}', 42954), - ('\u{a7d0}', 42961), ('\u{a7d6}', 42967), ('\u{a7d8}', 42969), ('\u{a7f5}', 42998), - ('\u{ff21}', 65345), ('\u{ff22}', 65346), ('\u{ff23}', 65347), ('\u{ff24}', 65348), - ('\u{ff25}', 65349), ('\u{ff26}', 65350), ('\u{ff27}', 65351), ('\u{ff28}', 65352), - ('\u{ff29}', 65353), ('\u{ff2a}', 65354), ('\u{ff2b}', 65355), ('\u{ff2c}', 65356), - ('\u{ff2d}', 65357), ('\u{ff2e}', 65358), ('\u{ff2f}', 65359), ('\u{ff30}', 65360), - ('\u{ff31}', 65361), ('\u{ff32}', 65362), ('\u{ff33}', 65363), ('\u{ff34}', 65364), - ('\u{ff35}', 65365), ('\u{ff36}', 65366), ('\u{ff37}', 65367), ('\u{ff38}', 65368), - ('\u{ff39}', 65369), ('\u{ff3a}', 65370), ('\u{10400}', 66600), ('\u{10401}', 66601), - ('\u{10402}', 66602), ('\u{10403}', 66603), ('\u{10404}', 66604), ('\u{10405}', 66605), - ('\u{10406}', 66606), ('\u{10407}', 66607), ('\u{10408}', 66608), ('\u{10409}', 66609), - ('\u{1040a}', 66610), ('\u{1040b}', 66611), ('\u{1040c}', 66612), ('\u{1040d}', 66613), - ('\u{1040e}', 66614), ('\u{1040f}', 66615), ('\u{10410}', 66616), ('\u{10411}', 66617), - ('\u{10412}', 66618), ('\u{10413}', 66619), ('\u{10414}', 66620), ('\u{10415}', 66621), - ('\u{10416}', 66622), ('\u{10417}', 66623), ('\u{10418}', 66624), ('\u{10419}', 66625), - ('\u{1041a}', 66626), ('\u{1041b}', 66627), ('\u{1041c}', 66628), ('\u{1041d}', 66629), - ('\u{1041e}', 66630), ('\u{1041f}', 66631), ('\u{10420}', 66632), ('\u{10421}', 66633), - ('\u{10422}', 66634), ('\u{10423}', 66635), ('\u{10424}', 66636), ('\u{10425}', 66637), - ('\u{10426}', 66638), ('\u{10427}', 66639), ('\u{104b0}', 66776), ('\u{104b1}', 66777), - ('\u{104b2}', 66778), ('\u{104b3}', 66779), ('\u{104b4}', 66780), ('\u{104b5}', 66781), - ('\u{104b6}', 66782), ('\u{104b7}', 66783), ('\u{104b8}', 66784), ('\u{104b9}', 66785), - ('\u{104ba}', 66786), ('\u{104bb}', 66787), ('\u{104bc}', 66788), ('\u{104bd}', 66789), - ('\u{104be}', 66790), ('\u{104bf}', 66791), ('\u{104c0}', 66792), ('\u{104c1}', 66793), - ('\u{104c2}', 66794), ('\u{104c3}', 66795), ('\u{104c4}', 66796), ('\u{104c5}', 66797), - ('\u{104c6}', 66798), ('\u{104c7}', 66799), ('\u{104c8}', 66800), ('\u{104c9}', 66801), - ('\u{104ca}', 66802), ('\u{104cb}', 66803), ('\u{104cc}', 66804), ('\u{104cd}', 66805), - ('\u{104ce}', 66806), ('\u{104cf}', 66807), ('\u{104d0}', 66808), ('\u{104d1}', 66809), - ('\u{104d2}', 66810), ('\u{104d3}', 66811), ('\u{10570}', 66967), ('\u{10571}', 66968), - ('\u{10572}', 66969), ('\u{10573}', 66970), ('\u{10574}', 66971), ('\u{10575}', 66972), - ('\u{10576}', 66973), ('\u{10577}', 66974), ('\u{10578}', 66975), ('\u{10579}', 66976), - ('\u{1057a}', 66977), ('\u{1057c}', 66979), ('\u{1057d}', 66980), ('\u{1057e}', 66981), - ('\u{1057f}', 66982), ('\u{10580}', 66983), ('\u{10581}', 66984), ('\u{10582}', 66985), - ('\u{10583}', 66986), ('\u{10584}', 66987), ('\u{10585}', 66988), ('\u{10586}', 66989), - ('\u{10587}', 66990), ('\u{10588}', 66991), ('\u{10589}', 66992), ('\u{1058a}', 66993), - ('\u{1058c}', 66995), ('\u{1058d}', 66996), ('\u{1058e}', 66997), ('\u{1058f}', 66998), - ('\u{10590}', 66999), ('\u{10591}', 67000), ('\u{10592}', 67001), ('\u{10594}', 67003), - ('\u{10595}', 67004), ('\u{10c80}', 68800), ('\u{10c81}', 68801), ('\u{10c82}', 68802), - ('\u{10c83}', 68803), ('\u{10c84}', 68804), ('\u{10c85}', 68805), ('\u{10c86}', 68806), - ('\u{10c87}', 68807), ('\u{10c88}', 68808), ('\u{10c89}', 68809), ('\u{10c8a}', 68810), - ('\u{10c8b}', 68811), ('\u{10c8c}', 68812), ('\u{10c8d}', 68813), ('\u{10c8e}', 68814), - ('\u{10c8f}', 68815), ('\u{10c90}', 68816), ('\u{10c91}', 68817), ('\u{10c92}', 68818), - ('\u{10c93}', 68819), ('\u{10c94}', 68820), ('\u{10c95}', 68821), ('\u{10c96}', 68822), - ('\u{10c97}', 68823), ('\u{10c98}', 68824), ('\u{10c99}', 68825), ('\u{10c9a}', 68826), - ('\u{10c9b}', 68827), ('\u{10c9c}', 68828), ('\u{10c9d}', 68829), ('\u{10c9e}', 68830), - ('\u{10c9f}', 68831), ('\u{10ca0}', 68832), ('\u{10ca1}', 68833), ('\u{10ca2}', 68834), - ('\u{10ca3}', 68835), ('\u{10ca4}', 68836), ('\u{10ca5}', 68837), ('\u{10ca6}', 68838), - ('\u{10ca7}', 68839), ('\u{10ca8}', 68840), ('\u{10ca9}', 68841), ('\u{10caa}', 68842), - ('\u{10cab}', 68843), ('\u{10cac}', 68844), ('\u{10cad}', 68845), ('\u{10cae}', 68846), - ('\u{10caf}', 68847), ('\u{10cb0}', 68848), ('\u{10cb1}', 68849), ('\u{10cb2}', 68850), - ('\u{118a0}', 71872), ('\u{118a1}', 71873), ('\u{118a2}', 71874), ('\u{118a3}', 71875), - ('\u{118a4}', 71876), ('\u{118a5}', 71877), ('\u{118a6}', 71878), ('\u{118a7}', 71879), - ('\u{118a8}', 71880), ('\u{118a9}', 71881), ('\u{118aa}', 71882), ('\u{118ab}', 71883), - ('\u{118ac}', 71884), ('\u{118ad}', 71885), ('\u{118ae}', 71886), ('\u{118af}', 71887), - ('\u{118b0}', 71888), ('\u{118b1}', 71889), ('\u{118b2}', 71890), ('\u{118b3}', 71891), - ('\u{118b4}', 71892), ('\u{118b5}', 71893), ('\u{118b6}', 71894), ('\u{118b7}', 71895), - ('\u{118b8}', 71896), ('\u{118b9}', 71897), ('\u{118ba}', 71898), ('\u{118bb}', 71899), - ('\u{118bc}', 71900), ('\u{118bd}', 71901), ('\u{118be}', 71902), ('\u{118bf}', 71903), - ('\u{16e40}', 93792), ('\u{16e41}', 93793), ('\u{16e42}', 93794), ('\u{16e43}', 93795), - ('\u{16e44}', 93796), ('\u{16e45}', 93797), ('\u{16e46}', 93798), ('\u{16e47}', 93799), - ('\u{16e48}', 93800), ('\u{16e49}', 93801), ('\u{16e4a}', 93802), ('\u{16e4b}', 93803), - ('\u{16e4c}', 93804), ('\u{16e4d}', 93805), ('\u{16e4e}', 93806), ('\u{16e4f}', 93807), - ('\u{16e50}', 93808), ('\u{16e51}', 93809), ('\u{16e52}', 93810), ('\u{16e53}', 93811), - ('\u{16e54}', 93812), ('\u{16e55}', 93813), ('\u{16e56}', 93814), ('\u{16e57}', 93815), - ('\u{16e58}', 93816), ('\u{16e59}', 93817), ('\u{16e5a}', 93818), ('\u{16e5b}', 93819), - ('\u{16e5c}', 93820), ('\u{16e5d}', 93821), ('\u{16e5e}', 93822), ('\u{16e5f}', 93823), - ('\u{1e900}', 125218), ('\u{1e901}', 125219), ('\u{1e902}', 125220), ('\u{1e903}', 125221), - ('\u{1e904}', 125222), ('\u{1e905}', 125223), ('\u{1e906}', 125224), ('\u{1e907}', 125225), - ('\u{1e908}', 125226), ('\u{1e909}', 125227), ('\u{1e90a}', 125228), ('\u{1e90b}', 125229), - ('\u{1e90c}', 125230), ('\u{1e90d}', 125231), ('\u{1e90e}', 125232), ('\u{1e90f}', 125233), - ('\u{1e910}', 125234), ('\u{1e911}', 125235), ('\u{1e912}', 125236), ('\u{1e913}', 125237), - ('\u{1e914}', 125238), ('\u{1e915}', 125239), ('\u{1e916}', 125240), ('\u{1e917}', 125241), - ('\u{1e918}', 125242), ('\u{1e919}', 125243), ('\u{1e91a}', 125244), ('\u{1e91b}', 125245), - ('\u{1e91c}', 125246), ('\u{1e91d}', 125247), ('\u{1e91e}', 125248), ('\u{1e91f}', 125249), - ('\u{1e920}', 125250), ('\u{1e921}', 125251), + ('\u{1c89}', 7306), ('\u{1c90}', 4304), ('\u{1c91}', 4305), ('\u{1c92}', 4306), + ('\u{1c93}', 4307), ('\u{1c94}', 4308), ('\u{1c95}', 4309), ('\u{1c96}', 4310), + ('\u{1c97}', 4311), ('\u{1c98}', 4312), ('\u{1c99}', 4313), ('\u{1c9a}', 4314), + ('\u{1c9b}', 4315), ('\u{1c9c}', 4316), ('\u{1c9d}', 4317), ('\u{1c9e}', 4318), + ('\u{1c9f}', 4319), ('\u{1ca0}', 4320), ('\u{1ca1}', 4321), ('\u{1ca2}', 4322), + ('\u{1ca3}', 4323), ('\u{1ca4}', 4324), ('\u{1ca5}', 4325), ('\u{1ca6}', 4326), + ('\u{1ca7}', 4327), ('\u{1ca8}', 4328), ('\u{1ca9}', 4329), ('\u{1caa}', 4330), + ('\u{1cab}', 4331), ('\u{1cac}', 4332), ('\u{1cad}', 4333), ('\u{1cae}', 4334), + ('\u{1caf}', 4335), ('\u{1cb0}', 4336), ('\u{1cb1}', 4337), ('\u{1cb2}', 4338), + ('\u{1cb3}', 4339), ('\u{1cb4}', 4340), ('\u{1cb5}', 4341), ('\u{1cb6}', 4342), + ('\u{1cb7}', 4343), ('\u{1cb8}', 4344), ('\u{1cb9}', 4345), ('\u{1cba}', 4346), + ('\u{1cbd}', 4349), ('\u{1cbe}', 4350), ('\u{1cbf}', 4351), ('\u{1e00}', 7681), + ('\u{1e02}', 7683), ('\u{1e04}', 7685), ('\u{1e06}', 7687), ('\u{1e08}', 7689), + ('\u{1e0a}', 7691), ('\u{1e0c}', 7693), ('\u{1e0e}', 7695), ('\u{1e10}', 7697), + ('\u{1e12}', 7699), ('\u{1e14}', 7701), ('\u{1e16}', 7703), ('\u{1e18}', 7705), + ('\u{1e1a}', 7707), ('\u{1e1c}', 7709), ('\u{1e1e}', 7711), ('\u{1e20}', 7713), + ('\u{1e22}', 7715), ('\u{1e24}', 7717), ('\u{1e26}', 7719), ('\u{1e28}', 7721), + ('\u{1e2a}', 7723), ('\u{1e2c}', 7725), ('\u{1e2e}', 7727), ('\u{1e30}', 7729), + ('\u{1e32}', 7731), ('\u{1e34}', 7733), ('\u{1e36}', 7735), ('\u{1e38}', 7737), + ('\u{1e3a}', 7739), ('\u{1e3c}', 7741), ('\u{1e3e}', 7743), ('\u{1e40}', 7745), + ('\u{1e42}', 7747), ('\u{1e44}', 7749), ('\u{1e46}', 7751), ('\u{1e48}', 7753), + ('\u{1e4a}', 7755), ('\u{1e4c}', 7757), ('\u{1e4e}', 7759), ('\u{1e50}', 7761), + ('\u{1e52}', 7763), ('\u{1e54}', 7765), ('\u{1e56}', 7767), ('\u{1e58}', 7769), + ('\u{1e5a}', 7771), ('\u{1e5c}', 7773), ('\u{1e5e}', 7775), ('\u{1e60}', 7777), + ('\u{1e62}', 7779), ('\u{1e64}', 7781), ('\u{1e66}', 7783), ('\u{1e68}', 7785), + ('\u{1e6a}', 7787), ('\u{1e6c}', 7789), ('\u{1e6e}', 7791), ('\u{1e70}', 7793), + ('\u{1e72}', 7795), ('\u{1e74}', 7797), ('\u{1e76}', 7799), ('\u{1e78}', 7801), + ('\u{1e7a}', 7803), ('\u{1e7c}', 7805), ('\u{1e7e}', 7807), ('\u{1e80}', 7809), + ('\u{1e82}', 7811), ('\u{1e84}', 7813), ('\u{1e86}', 7815), ('\u{1e88}', 7817), + ('\u{1e8a}', 7819), ('\u{1e8c}', 7821), ('\u{1e8e}', 7823), ('\u{1e90}', 7825), + ('\u{1e92}', 7827), ('\u{1e94}', 7829), ('\u{1e9e}', 223), ('\u{1ea0}', 7841), + ('\u{1ea2}', 7843), ('\u{1ea4}', 7845), ('\u{1ea6}', 7847), ('\u{1ea8}', 7849), + ('\u{1eaa}', 7851), ('\u{1eac}', 7853), ('\u{1eae}', 7855), ('\u{1eb0}', 7857), + ('\u{1eb2}', 7859), ('\u{1eb4}', 7861), ('\u{1eb6}', 7863), ('\u{1eb8}', 7865), + ('\u{1eba}', 7867), ('\u{1ebc}', 7869), ('\u{1ebe}', 7871), ('\u{1ec0}', 7873), + ('\u{1ec2}', 7875), ('\u{1ec4}', 7877), ('\u{1ec6}', 7879), ('\u{1ec8}', 7881), + ('\u{1eca}', 7883), ('\u{1ecc}', 7885), ('\u{1ece}', 7887), ('\u{1ed0}', 7889), + ('\u{1ed2}', 7891), ('\u{1ed4}', 7893), ('\u{1ed6}', 7895), ('\u{1ed8}', 7897), + ('\u{1eda}', 7899), ('\u{1edc}', 7901), ('\u{1ede}', 7903), ('\u{1ee0}', 7905), + ('\u{1ee2}', 7907), ('\u{1ee4}', 7909), ('\u{1ee6}', 7911), ('\u{1ee8}', 7913), + ('\u{1eea}', 7915), ('\u{1eec}', 7917), ('\u{1eee}', 7919), ('\u{1ef0}', 7921), + ('\u{1ef2}', 7923), ('\u{1ef4}', 7925), ('\u{1ef6}', 7927), ('\u{1ef8}', 7929), + ('\u{1efa}', 7931), ('\u{1efc}', 7933), ('\u{1efe}', 7935), ('\u{1f08}', 7936), + ('\u{1f09}', 7937), ('\u{1f0a}', 7938), ('\u{1f0b}', 7939), ('\u{1f0c}', 7940), + ('\u{1f0d}', 7941), ('\u{1f0e}', 7942), ('\u{1f0f}', 7943), ('\u{1f18}', 7952), + ('\u{1f19}', 7953), ('\u{1f1a}', 7954), ('\u{1f1b}', 7955), ('\u{1f1c}', 7956), + ('\u{1f1d}', 7957), ('\u{1f28}', 7968), ('\u{1f29}', 7969), ('\u{1f2a}', 7970), + ('\u{1f2b}', 7971), ('\u{1f2c}', 7972), ('\u{1f2d}', 7973), ('\u{1f2e}', 7974), + ('\u{1f2f}', 7975), ('\u{1f38}', 7984), ('\u{1f39}', 7985), ('\u{1f3a}', 7986), + ('\u{1f3b}', 7987), ('\u{1f3c}', 7988), ('\u{1f3d}', 7989), ('\u{1f3e}', 7990), + ('\u{1f3f}', 7991), ('\u{1f48}', 8000), ('\u{1f49}', 8001), ('\u{1f4a}', 8002), + ('\u{1f4b}', 8003), ('\u{1f4c}', 8004), ('\u{1f4d}', 8005), ('\u{1f59}', 8017), + ('\u{1f5b}', 8019), ('\u{1f5d}', 8021), ('\u{1f5f}', 8023), ('\u{1f68}', 8032), + ('\u{1f69}', 8033), ('\u{1f6a}', 8034), ('\u{1f6b}', 8035), ('\u{1f6c}', 8036), + ('\u{1f6d}', 8037), ('\u{1f6e}', 8038), ('\u{1f6f}', 8039), ('\u{1f88}', 8064), + ('\u{1f89}', 8065), ('\u{1f8a}', 8066), ('\u{1f8b}', 8067), ('\u{1f8c}', 8068), + ('\u{1f8d}', 8069), ('\u{1f8e}', 8070), ('\u{1f8f}', 8071), ('\u{1f98}', 8080), + ('\u{1f99}', 8081), ('\u{1f9a}', 8082), ('\u{1f9b}', 8083), ('\u{1f9c}', 8084), + ('\u{1f9d}', 8085), ('\u{1f9e}', 8086), ('\u{1f9f}', 8087), ('\u{1fa8}', 8096), + ('\u{1fa9}', 8097), ('\u{1faa}', 8098), ('\u{1fab}', 8099), ('\u{1fac}', 8100), + ('\u{1fad}', 8101), ('\u{1fae}', 8102), ('\u{1faf}', 8103), ('\u{1fb8}', 8112), + ('\u{1fb9}', 8113), ('\u{1fba}', 8048), ('\u{1fbb}', 8049), ('\u{1fbc}', 8115), + ('\u{1fc8}', 8050), ('\u{1fc9}', 8051), ('\u{1fca}', 8052), ('\u{1fcb}', 8053), + ('\u{1fcc}', 8131), ('\u{1fd8}', 8144), ('\u{1fd9}', 8145), ('\u{1fda}', 8054), + ('\u{1fdb}', 8055), ('\u{1fe8}', 8160), ('\u{1fe9}', 8161), ('\u{1fea}', 8058), + ('\u{1feb}', 8059), ('\u{1fec}', 8165), ('\u{1ff8}', 8056), ('\u{1ff9}', 8057), + ('\u{1ffa}', 8060), ('\u{1ffb}', 8061), ('\u{1ffc}', 8179), ('\u{2126}', 969), + ('\u{212a}', 107), ('\u{212b}', 229), ('\u{2132}', 8526), ('\u{2160}', 8560), + ('\u{2161}', 8561), ('\u{2162}', 8562), ('\u{2163}', 8563), ('\u{2164}', 8564), + ('\u{2165}', 8565), ('\u{2166}', 8566), ('\u{2167}', 8567), ('\u{2168}', 8568), + ('\u{2169}', 8569), ('\u{216a}', 8570), ('\u{216b}', 8571), ('\u{216c}', 8572), + ('\u{216d}', 8573), ('\u{216e}', 8574), ('\u{216f}', 8575), ('\u{2183}', 8580), + ('\u{24b6}', 9424), ('\u{24b7}', 9425), ('\u{24b8}', 9426), ('\u{24b9}', 9427), + ('\u{24ba}', 9428), ('\u{24bb}', 9429), ('\u{24bc}', 9430), ('\u{24bd}', 9431), + ('\u{24be}', 9432), ('\u{24bf}', 9433), ('\u{24c0}', 9434), ('\u{24c1}', 9435), + ('\u{24c2}', 9436), ('\u{24c3}', 9437), ('\u{24c4}', 9438), ('\u{24c5}', 9439), + ('\u{24c6}', 9440), ('\u{24c7}', 9441), ('\u{24c8}', 9442), ('\u{24c9}', 9443), + ('\u{24ca}', 9444), ('\u{24cb}', 9445), ('\u{24cc}', 9446), ('\u{24cd}', 9447), + ('\u{24ce}', 9448), ('\u{24cf}', 9449), ('\u{2c00}', 11312), ('\u{2c01}', 11313), + ('\u{2c02}', 11314), ('\u{2c03}', 11315), ('\u{2c04}', 11316), ('\u{2c05}', 11317), + ('\u{2c06}', 11318), ('\u{2c07}', 11319), ('\u{2c08}', 11320), ('\u{2c09}', 11321), + ('\u{2c0a}', 11322), ('\u{2c0b}', 11323), ('\u{2c0c}', 11324), ('\u{2c0d}', 11325), + ('\u{2c0e}', 11326), ('\u{2c0f}', 11327), ('\u{2c10}', 11328), ('\u{2c11}', 11329), + ('\u{2c12}', 11330), ('\u{2c13}', 11331), ('\u{2c14}', 11332), ('\u{2c15}', 11333), + ('\u{2c16}', 11334), ('\u{2c17}', 11335), ('\u{2c18}', 11336), ('\u{2c19}', 11337), + ('\u{2c1a}', 11338), ('\u{2c1b}', 11339), ('\u{2c1c}', 11340), ('\u{2c1d}', 11341), + ('\u{2c1e}', 11342), ('\u{2c1f}', 11343), ('\u{2c20}', 11344), ('\u{2c21}', 11345), + ('\u{2c22}', 11346), ('\u{2c23}', 11347), ('\u{2c24}', 11348), ('\u{2c25}', 11349), + ('\u{2c26}', 11350), ('\u{2c27}', 11351), ('\u{2c28}', 11352), ('\u{2c29}', 11353), + ('\u{2c2a}', 11354), ('\u{2c2b}', 11355), ('\u{2c2c}', 11356), ('\u{2c2d}', 11357), + ('\u{2c2e}', 11358), ('\u{2c2f}', 11359), ('\u{2c60}', 11361), ('\u{2c62}', 619), + ('\u{2c63}', 7549), ('\u{2c64}', 637), ('\u{2c67}', 11368), ('\u{2c69}', 11370), + ('\u{2c6b}', 11372), ('\u{2c6d}', 593), ('\u{2c6e}', 625), ('\u{2c6f}', 592), + ('\u{2c70}', 594), ('\u{2c72}', 11379), ('\u{2c75}', 11382), ('\u{2c7e}', 575), + ('\u{2c7f}', 576), ('\u{2c80}', 11393), ('\u{2c82}', 11395), ('\u{2c84}', 11397), + ('\u{2c86}', 11399), ('\u{2c88}', 11401), ('\u{2c8a}', 11403), ('\u{2c8c}', 11405), + ('\u{2c8e}', 11407), ('\u{2c90}', 11409), ('\u{2c92}', 11411), ('\u{2c94}', 11413), + ('\u{2c96}', 11415), ('\u{2c98}', 11417), ('\u{2c9a}', 11419), ('\u{2c9c}', 11421), + ('\u{2c9e}', 11423), ('\u{2ca0}', 11425), ('\u{2ca2}', 11427), ('\u{2ca4}', 11429), + ('\u{2ca6}', 11431), ('\u{2ca8}', 11433), ('\u{2caa}', 11435), ('\u{2cac}', 11437), + ('\u{2cae}', 11439), ('\u{2cb0}', 11441), ('\u{2cb2}', 11443), ('\u{2cb4}', 11445), + ('\u{2cb6}', 11447), ('\u{2cb8}', 11449), ('\u{2cba}', 11451), ('\u{2cbc}', 11453), + ('\u{2cbe}', 11455), ('\u{2cc0}', 11457), ('\u{2cc2}', 11459), ('\u{2cc4}', 11461), + ('\u{2cc6}', 11463), ('\u{2cc8}', 11465), ('\u{2cca}', 11467), ('\u{2ccc}', 11469), + ('\u{2cce}', 11471), ('\u{2cd0}', 11473), ('\u{2cd2}', 11475), ('\u{2cd4}', 11477), + ('\u{2cd6}', 11479), ('\u{2cd8}', 11481), ('\u{2cda}', 11483), ('\u{2cdc}', 11485), + ('\u{2cde}', 11487), ('\u{2ce0}', 11489), ('\u{2ce2}', 11491), ('\u{2ceb}', 11500), + ('\u{2ced}', 11502), ('\u{2cf2}', 11507), ('\u{a640}', 42561), ('\u{a642}', 42563), + ('\u{a644}', 42565), ('\u{a646}', 42567), ('\u{a648}', 42569), ('\u{a64a}', 42571), + ('\u{a64c}', 42573), ('\u{a64e}', 42575), ('\u{a650}', 42577), ('\u{a652}', 42579), + ('\u{a654}', 42581), ('\u{a656}', 42583), ('\u{a658}', 42585), ('\u{a65a}', 42587), + ('\u{a65c}', 42589), ('\u{a65e}', 42591), ('\u{a660}', 42593), ('\u{a662}', 42595), + ('\u{a664}', 42597), ('\u{a666}', 42599), ('\u{a668}', 42601), ('\u{a66a}', 42603), + ('\u{a66c}', 42605), ('\u{a680}', 42625), ('\u{a682}', 42627), ('\u{a684}', 42629), + ('\u{a686}', 42631), ('\u{a688}', 42633), ('\u{a68a}', 42635), ('\u{a68c}', 42637), + ('\u{a68e}', 42639), ('\u{a690}', 42641), ('\u{a692}', 42643), ('\u{a694}', 42645), + ('\u{a696}', 42647), ('\u{a698}', 42649), ('\u{a69a}', 42651), ('\u{a722}', 42787), + ('\u{a724}', 42789), ('\u{a726}', 42791), ('\u{a728}', 42793), ('\u{a72a}', 42795), + ('\u{a72c}', 42797), ('\u{a72e}', 42799), ('\u{a732}', 42803), ('\u{a734}', 42805), + ('\u{a736}', 42807), ('\u{a738}', 42809), ('\u{a73a}', 42811), ('\u{a73c}', 42813), + ('\u{a73e}', 42815), ('\u{a740}', 42817), ('\u{a742}', 42819), ('\u{a744}', 42821), + ('\u{a746}', 42823), ('\u{a748}', 42825), ('\u{a74a}', 42827), ('\u{a74c}', 42829), + ('\u{a74e}', 42831), ('\u{a750}', 42833), ('\u{a752}', 42835), ('\u{a754}', 42837), + ('\u{a756}', 42839), ('\u{a758}', 42841), ('\u{a75a}', 42843), ('\u{a75c}', 42845), + ('\u{a75e}', 42847), ('\u{a760}', 42849), ('\u{a762}', 42851), ('\u{a764}', 42853), + ('\u{a766}', 42855), ('\u{a768}', 42857), ('\u{a76a}', 42859), ('\u{a76c}', 42861), + ('\u{a76e}', 42863), ('\u{a779}', 42874), ('\u{a77b}', 42876), ('\u{a77d}', 7545), + ('\u{a77e}', 42879), ('\u{a780}', 42881), ('\u{a782}', 42883), ('\u{a784}', 42885), + ('\u{a786}', 42887), ('\u{a78b}', 42892), ('\u{a78d}', 613), ('\u{a790}', 42897), + ('\u{a792}', 42899), ('\u{a796}', 42903), ('\u{a798}', 42905), ('\u{a79a}', 42907), + ('\u{a79c}', 42909), ('\u{a79e}', 42911), ('\u{a7a0}', 42913), ('\u{a7a2}', 42915), + ('\u{a7a4}', 42917), ('\u{a7a6}', 42919), ('\u{a7a8}', 42921), ('\u{a7aa}', 614), + ('\u{a7ab}', 604), ('\u{a7ac}', 609), ('\u{a7ad}', 620), ('\u{a7ae}', 618), + ('\u{a7b0}', 670), ('\u{a7b1}', 647), ('\u{a7b2}', 669), ('\u{a7b3}', 43859), + ('\u{a7b4}', 42933), ('\u{a7b6}', 42935), ('\u{a7b8}', 42937), ('\u{a7ba}', 42939), + ('\u{a7bc}', 42941), ('\u{a7be}', 42943), ('\u{a7c0}', 42945), ('\u{a7c2}', 42947), + ('\u{a7c4}', 42900), ('\u{a7c5}', 642), ('\u{a7c6}', 7566), ('\u{a7c7}', 42952), + ('\u{a7c9}', 42954), ('\u{a7cb}', 612), ('\u{a7cc}', 42957), ('\u{a7d0}', 42961), + ('\u{a7d6}', 42967), ('\u{a7d8}', 42969), ('\u{a7da}', 42971), ('\u{a7dc}', 411), + ('\u{a7f5}', 42998), ('\u{ff21}', 65345), ('\u{ff22}', 65346), ('\u{ff23}', 65347), + ('\u{ff24}', 65348), ('\u{ff25}', 65349), ('\u{ff26}', 65350), ('\u{ff27}', 65351), + ('\u{ff28}', 65352), ('\u{ff29}', 65353), ('\u{ff2a}', 65354), ('\u{ff2b}', 65355), + ('\u{ff2c}', 65356), ('\u{ff2d}', 65357), ('\u{ff2e}', 65358), ('\u{ff2f}', 65359), + ('\u{ff30}', 65360), ('\u{ff31}', 65361), ('\u{ff32}', 65362), ('\u{ff33}', 65363), + ('\u{ff34}', 65364), ('\u{ff35}', 65365), ('\u{ff36}', 65366), ('\u{ff37}', 65367), + ('\u{ff38}', 65368), ('\u{ff39}', 65369), ('\u{ff3a}', 65370), ('\u{10400}', 66600), + ('\u{10401}', 66601), ('\u{10402}', 66602), ('\u{10403}', 66603), ('\u{10404}', 66604), + ('\u{10405}', 66605), ('\u{10406}', 66606), ('\u{10407}', 66607), ('\u{10408}', 66608), + ('\u{10409}', 66609), ('\u{1040a}', 66610), ('\u{1040b}', 66611), ('\u{1040c}', 66612), + ('\u{1040d}', 66613), ('\u{1040e}', 66614), ('\u{1040f}', 66615), ('\u{10410}', 66616), + ('\u{10411}', 66617), ('\u{10412}', 66618), ('\u{10413}', 66619), ('\u{10414}', 66620), + ('\u{10415}', 66621), ('\u{10416}', 66622), ('\u{10417}', 66623), ('\u{10418}', 66624), + ('\u{10419}', 66625), ('\u{1041a}', 66626), ('\u{1041b}', 66627), ('\u{1041c}', 66628), + ('\u{1041d}', 66629), ('\u{1041e}', 66630), ('\u{1041f}', 66631), ('\u{10420}', 66632), + ('\u{10421}', 66633), ('\u{10422}', 66634), ('\u{10423}', 66635), ('\u{10424}', 66636), + ('\u{10425}', 66637), ('\u{10426}', 66638), ('\u{10427}', 66639), ('\u{104b0}', 66776), + ('\u{104b1}', 66777), ('\u{104b2}', 66778), ('\u{104b3}', 66779), ('\u{104b4}', 66780), + ('\u{104b5}', 66781), ('\u{104b6}', 66782), ('\u{104b7}', 66783), ('\u{104b8}', 66784), + ('\u{104b9}', 66785), ('\u{104ba}', 66786), ('\u{104bb}', 66787), ('\u{104bc}', 66788), + ('\u{104bd}', 66789), ('\u{104be}', 66790), ('\u{104bf}', 66791), ('\u{104c0}', 66792), + ('\u{104c1}', 66793), ('\u{104c2}', 66794), ('\u{104c3}', 66795), ('\u{104c4}', 66796), + ('\u{104c5}', 66797), ('\u{104c6}', 66798), ('\u{104c7}', 66799), ('\u{104c8}', 66800), + ('\u{104c9}', 66801), ('\u{104ca}', 66802), ('\u{104cb}', 66803), ('\u{104cc}', 66804), + ('\u{104cd}', 66805), ('\u{104ce}', 66806), ('\u{104cf}', 66807), ('\u{104d0}', 66808), + ('\u{104d1}', 66809), ('\u{104d2}', 66810), ('\u{104d3}', 66811), ('\u{10570}', 66967), + ('\u{10571}', 66968), ('\u{10572}', 66969), ('\u{10573}', 66970), ('\u{10574}', 66971), + ('\u{10575}', 66972), ('\u{10576}', 66973), ('\u{10577}', 66974), ('\u{10578}', 66975), + ('\u{10579}', 66976), ('\u{1057a}', 66977), ('\u{1057c}', 66979), ('\u{1057d}', 66980), + ('\u{1057e}', 66981), ('\u{1057f}', 66982), ('\u{10580}', 66983), ('\u{10581}', 66984), + ('\u{10582}', 66985), ('\u{10583}', 66986), ('\u{10584}', 66987), ('\u{10585}', 66988), + ('\u{10586}', 66989), ('\u{10587}', 66990), ('\u{10588}', 66991), ('\u{10589}', 66992), + ('\u{1058a}', 66993), ('\u{1058c}', 66995), ('\u{1058d}', 66996), ('\u{1058e}', 66997), + ('\u{1058f}', 66998), ('\u{10590}', 66999), ('\u{10591}', 67000), ('\u{10592}', 67001), + ('\u{10594}', 67003), ('\u{10595}', 67004), ('\u{10c80}', 68800), ('\u{10c81}', 68801), + ('\u{10c82}', 68802), ('\u{10c83}', 68803), ('\u{10c84}', 68804), ('\u{10c85}', 68805), + ('\u{10c86}', 68806), ('\u{10c87}', 68807), ('\u{10c88}', 68808), ('\u{10c89}', 68809), + ('\u{10c8a}', 68810), ('\u{10c8b}', 68811), ('\u{10c8c}', 68812), ('\u{10c8d}', 68813), + ('\u{10c8e}', 68814), ('\u{10c8f}', 68815), ('\u{10c90}', 68816), ('\u{10c91}', 68817), + ('\u{10c92}', 68818), ('\u{10c93}', 68819), ('\u{10c94}', 68820), ('\u{10c95}', 68821), + ('\u{10c96}', 68822), ('\u{10c97}', 68823), ('\u{10c98}', 68824), ('\u{10c99}', 68825), + ('\u{10c9a}', 68826), ('\u{10c9b}', 68827), ('\u{10c9c}', 68828), ('\u{10c9d}', 68829), + ('\u{10c9e}', 68830), ('\u{10c9f}', 68831), ('\u{10ca0}', 68832), ('\u{10ca1}', 68833), + ('\u{10ca2}', 68834), ('\u{10ca3}', 68835), ('\u{10ca4}', 68836), ('\u{10ca5}', 68837), + ('\u{10ca6}', 68838), ('\u{10ca7}', 68839), ('\u{10ca8}', 68840), ('\u{10ca9}', 68841), + ('\u{10caa}', 68842), ('\u{10cab}', 68843), ('\u{10cac}', 68844), ('\u{10cad}', 68845), + ('\u{10cae}', 68846), ('\u{10caf}', 68847), ('\u{10cb0}', 68848), ('\u{10cb1}', 68849), + ('\u{10cb2}', 68850), ('\u{10d50}', 68976), ('\u{10d51}', 68977), ('\u{10d52}', 68978), + ('\u{10d53}', 68979), ('\u{10d54}', 68980), ('\u{10d55}', 68981), ('\u{10d56}', 68982), + ('\u{10d57}', 68983), ('\u{10d58}', 68984), ('\u{10d59}', 68985), ('\u{10d5a}', 68986), + ('\u{10d5b}', 68987), ('\u{10d5c}', 68988), ('\u{10d5d}', 68989), ('\u{10d5e}', 68990), + ('\u{10d5f}', 68991), ('\u{10d60}', 68992), ('\u{10d61}', 68993), ('\u{10d62}', 68994), + ('\u{10d63}', 68995), ('\u{10d64}', 68996), ('\u{10d65}', 68997), ('\u{118a0}', 71872), + ('\u{118a1}', 71873), ('\u{118a2}', 71874), ('\u{118a3}', 71875), ('\u{118a4}', 71876), + ('\u{118a5}', 71877), ('\u{118a6}', 71878), ('\u{118a7}', 71879), ('\u{118a8}', 71880), + ('\u{118a9}', 71881), ('\u{118aa}', 71882), ('\u{118ab}', 71883), ('\u{118ac}', 71884), + ('\u{118ad}', 71885), ('\u{118ae}', 71886), ('\u{118af}', 71887), ('\u{118b0}', 71888), + ('\u{118b1}', 71889), ('\u{118b2}', 71890), ('\u{118b3}', 71891), ('\u{118b4}', 71892), + ('\u{118b5}', 71893), ('\u{118b6}', 71894), ('\u{118b7}', 71895), ('\u{118b8}', 71896), + ('\u{118b9}', 71897), ('\u{118ba}', 71898), ('\u{118bb}', 71899), ('\u{118bc}', 71900), + ('\u{118bd}', 71901), ('\u{118be}', 71902), ('\u{118bf}', 71903), ('\u{16e40}', 93792), + ('\u{16e41}', 93793), ('\u{16e42}', 93794), ('\u{16e43}', 93795), ('\u{16e44}', 93796), + ('\u{16e45}', 93797), ('\u{16e46}', 93798), ('\u{16e47}', 93799), ('\u{16e48}', 93800), + ('\u{16e49}', 93801), ('\u{16e4a}', 93802), ('\u{16e4b}', 93803), ('\u{16e4c}', 93804), + ('\u{16e4d}', 93805), ('\u{16e4e}', 93806), ('\u{16e4f}', 93807), ('\u{16e50}', 93808), + ('\u{16e51}', 93809), ('\u{16e52}', 93810), ('\u{16e53}', 93811), ('\u{16e54}', 93812), + ('\u{16e55}', 93813), ('\u{16e56}', 93814), ('\u{16e57}', 93815), ('\u{16e58}', 93816), + ('\u{16e59}', 93817), ('\u{16e5a}', 93818), ('\u{16e5b}', 93819), ('\u{16e5c}', 93820), + ('\u{16e5d}', 93821), ('\u{16e5e}', 93822), ('\u{16e5f}', 93823), ('\u{1e900}', 125218), + ('\u{1e901}', 125219), ('\u{1e902}', 125220), ('\u{1e903}', 125221), ('\u{1e904}', 125222), + ('\u{1e905}', 125223), ('\u{1e906}', 125224), ('\u{1e907}', 125225), ('\u{1e908}', 125226), + ('\u{1e909}', 125227), ('\u{1e90a}', 125228), ('\u{1e90b}', 125229), ('\u{1e90c}', 125230), + ('\u{1e90d}', 125231), ('\u{1e90e}', 125232), ('\u{1e90f}', 125233), ('\u{1e910}', 125234), + ('\u{1e911}', 125235), ('\u{1e912}', 125236), ('\u{1e913}', 125237), ('\u{1e914}', 125238), + ('\u{1e915}', 125239), ('\u{1e916}', 125240), ('\u{1e917}', 125241), ('\u{1e918}', 125242), + ('\u{1e919}', 125243), ('\u{1e91a}', 125244), ('\u{1e91b}', 125245), ('\u{1e91c}', 125246), + ('\u{1e91d}', 125247), ('\u{1e91e}', 125248), ('\u{1e91f}', 125249), ('\u{1e920}', 125250), + ('\u{1e921}', 125251), ]; static LOWERCASE_TABLE_MULTI: &[[char; 3]] = &[ @@ -989,14 +1002,14 @@ pub mod conversions { ('\u{16f}', 366), ('\u{171}', 368), ('\u{173}', 370), ('\u{175}', 372), ('\u{177}', 374), ('\u{17a}', 377), ('\u{17c}', 379), ('\u{17e}', 381), ('\u{17f}', 83), ('\u{180}', 579), ('\u{183}', 386), ('\u{185}', 388), ('\u{188}', 391), ('\u{18c}', 395), ('\u{192}', 401), - ('\u{195}', 502), ('\u{199}', 408), ('\u{19a}', 573), ('\u{19e}', 544), ('\u{1a1}', 416), - ('\u{1a3}', 418), ('\u{1a5}', 420), ('\u{1a8}', 423), ('\u{1ad}', 428), ('\u{1b0}', 431), - ('\u{1b4}', 435), ('\u{1b6}', 437), ('\u{1b9}', 440), ('\u{1bd}', 444), ('\u{1bf}', 503), - ('\u{1c5}', 452), ('\u{1c6}', 452), ('\u{1c8}', 455), ('\u{1c9}', 455), ('\u{1cb}', 458), - ('\u{1cc}', 458), ('\u{1ce}', 461), ('\u{1d0}', 463), ('\u{1d2}', 465), ('\u{1d4}', 467), - ('\u{1d6}', 469), ('\u{1d8}', 471), ('\u{1da}', 473), ('\u{1dc}', 475), ('\u{1dd}', 398), - ('\u{1df}', 478), ('\u{1e1}', 480), ('\u{1e3}', 482), ('\u{1e5}', 484), ('\u{1e7}', 486), - ('\u{1e9}', 488), ('\u{1eb}', 490), ('\u{1ed}', 492), ('\u{1ef}', 494), + ('\u{195}', 502), ('\u{199}', 408), ('\u{19a}', 573), ('\u{19b}', 42972), ('\u{19e}', 544), + ('\u{1a1}', 416), ('\u{1a3}', 418), ('\u{1a5}', 420), ('\u{1a8}', 423), ('\u{1ad}', 428), + ('\u{1b0}', 431), ('\u{1b4}', 435), ('\u{1b6}', 437), ('\u{1b9}', 440), ('\u{1bd}', 444), + ('\u{1bf}', 503), ('\u{1c5}', 452), ('\u{1c6}', 452), ('\u{1c8}', 455), ('\u{1c9}', 455), + ('\u{1cb}', 458), ('\u{1cc}', 458), ('\u{1ce}', 461), ('\u{1d0}', 463), ('\u{1d2}', 465), + ('\u{1d4}', 467), ('\u{1d6}', 469), ('\u{1d8}', 471), ('\u{1da}', 473), ('\u{1dc}', 475), + ('\u{1dd}', 398), ('\u{1df}', 478), ('\u{1e1}', 480), ('\u{1e3}', 482), ('\u{1e5}', 484), + ('\u{1e7}', 486), ('\u{1e9}', 488), ('\u{1eb}', 490), ('\u{1ed}', 492), ('\u{1ef}', 494), ('\u{1f0}', 4194306), ('\u{1f2}', 497), ('\u{1f3}', 497), ('\u{1f5}', 500), ('\u{1f9}', 504), ('\u{1fb}', 506), ('\u{1fd}', 508), ('\u{1ff}', 510), ('\u{201}', 512), ('\u{203}', 514), ('\u{205}', 516), ('\u{207}', 518), ('\u{209}', 520), ('\u{20b}', 522), @@ -1008,25 +1021,25 @@ pub mod conversions { ('\u{249}', 584), ('\u{24b}', 586), ('\u{24d}', 588), ('\u{24f}', 590), ('\u{250}', 11375), ('\u{251}', 11373), ('\u{252}', 11376), ('\u{253}', 385), ('\u{254}', 390), ('\u{256}', 393), ('\u{257}', 394), ('\u{259}', 399), ('\u{25b}', 400), ('\u{25c}', 42923), - ('\u{260}', 403), ('\u{261}', 42924), ('\u{263}', 404), ('\u{265}', 42893), - ('\u{266}', 42922), ('\u{268}', 407), ('\u{269}', 406), ('\u{26a}', 42926), - ('\u{26b}', 11362), ('\u{26c}', 42925), ('\u{26f}', 412), ('\u{271}', 11374), - ('\u{272}', 413), ('\u{275}', 415), ('\u{27d}', 11364), ('\u{280}', 422), - ('\u{282}', 42949), ('\u{283}', 425), ('\u{287}', 42929), ('\u{288}', 430), - ('\u{289}', 580), ('\u{28a}', 433), ('\u{28b}', 434), ('\u{28c}', 581), ('\u{292}', 439), - ('\u{29d}', 42930), ('\u{29e}', 42928), ('\u{345}', 921), ('\u{371}', 880), - ('\u{373}', 882), ('\u{377}', 886), ('\u{37b}', 1021), ('\u{37c}', 1022), ('\u{37d}', 1023), - ('\u{390}', 4194307), ('\u{3ac}', 902), ('\u{3ad}', 904), ('\u{3ae}', 905), - ('\u{3af}', 906), ('\u{3b0}', 4194308), ('\u{3b1}', 913), ('\u{3b2}', 914), - ('\u{3b3}', 915), ('\u{3b4}', 916), ('\u{3b5}', 917), ('\u{3b6}', 918), ('\u{3b7}', 919), - ('\u{3b8}', 920), ('\u{3b9}', 921), ('\u{3ba}', 922), ('\u{3bb}', 923), ('\u{3bc}', 924), - ('\u{3bd}', 925), ('\u{3be}', 926), ('\u{3bf}', 927), ('\u{3c0}', 928), ('\u{3c1}', 929), - ('\u{3c2}', 931), ('\u{3c3}', 931), ('\u{3c4}', 932), ('\u{3c5}', 933), ('\u{3c6}', 934), - ('\u{3c7}', 935), ('\u{3c8}', 936), ('\u{3c9}', 937), ('\u{3ca}', 938), ('\u{3cb}', 939), - ('\u{3cc}', 908), ('\u{3cd}', 910), ('\u{3ce}', 911), ('\u{3d0}', 914), ('\u{3d1}', 920), - ('\u{3d5}', 934), ('\u{3d6}', 928), ('\u{3d7}', 975), ('\u{3d9}', 984), ('\u{3db}', 986), - ('\u{3dd}', 988), ('\u{3df}', 990), ('\u{3e1}', 992), ('\u{3e3}', 994), ('\u{3e5}', 996), - ('\u{3e7}', 998), ('\u{3e9}', 1000), ('\u{3eb}', 1002), ('\u{3ed}', 1004), + ('\u{260}', 403), ('\u{261}', 42924), ('\u{263}', 404), ('\u{264}', 42955), + ('\u{265}', 42893), ('\u{266}', 42922), ('\u{268}', 407), ('\u{269}', 406), + ('\u{26a}', 42926), ('\u{26b}', 11362), ('\u{26c}', 42925), ('\u{26f}', 412), + ('\u{271}', 11374), ('\u{272}', 413), ('\u{275}', 415), ('\u{27d}', 11364), + ('\u{280}', 422), ('\u{282}', 42949), ('\u{283}', 425), ('\u{287}', 42929), + ('\u{288}', 430), ('\u{289}', 580), ('\u{28a}', 433), ('\u{28b}', 434), ('\u{28c}', 581), + ('\u{292}', 439), ('\u{29d}', 42930), ('\u{29e}', 42928), ('\u{345}', 921), + ('\u{371}', 880), ('\u{373}', 882), ('\u{377}', 886), ('\u{37b}', 1021), ('\u{37c}', 1022), + ('\u{37d}', 1023), ('\u{390}', 4194307), ('\u{3ac}', 902), ('\u{3ad}', 904), + ('\u{3ae}', 905), ('\u{3af}', 906), ('\u{3b0}', 4194308), ('\u{3b1}', 913), + ('\u{3b2}', 914), ('\u{3b3}', 915), ('\u{3b4}', 916), ('\u{3b5}', 917), ('\u{3b6}', 918), + ('\u{3b7}', 919), ('\u{3b8}', 920), ('\u{3b9}', 921), ('\u{3ba}', 922), ('\u{3bb}', 923), + ('\u{3bc}', 924), ('\u{3bd}', 925), ('\u{3be}', 926), ('\u{3bf}', 927), ('\u{3c0}', 928), + ('\u{3c1}', 929), ('\u{3c2}', 931), ('\u{3c3}', 931), ('\u{3c4}', 932), ('\u{3c5}', 933), + ('\u{3c6}', 934), ('\u{3c7}', 935), ('\u{3c8}', 936), ('\u{3c9}', 937), ('\u{3ca}', 938), + ('\u{3cb}', 939), ('\u{3cc}', 908), ('\u{3cd}', 910), ('\u{3ce}', 911), ('\u{3d0}', 914), + ('\u{3d1}', 920), ('\u{3d5}', 934), ('\u{3d6}', 928), ('\u{3d7}', 975), ('\u{3d9}', 984), + ('\u{3db}', 986), ('\u{3dd}', 988), ('\u{3df}', 990), ('\u{3e1}', 992), ('\u{3e3}', 994), + ('\u{3e5}', 996), ('\u{3e7}', 998), ('\u{3e9}', 1000), ('\u{3eb}', 1002), ('\u{3ed}', 1004), ('\u{3ef}', 1006), ('\u{3f0}', 922), ('\u{3f1}', 929), ('\u{3f2}', 1017), ('\u{3f3}', 895), ('\u{3f5}', 917), ('\u{3f8}', 1015), ('\u{3fb}', 1018), ('\u{430}', 1040), ('\u{431}', 1041), ('\u{432}', 1042), ('\u{433}', 1043), ('\u{434}', 1044), @@ -1090,248 +1103,254 @@ pub mod conversions { ('\u{13f8}', 5104), ('\u{13f9}', 5105), ('\u{13fa}', 5106), ('\u{13fb}', 5107), ('\u{13fc}', 5108), ('\u{13fd}', 5109), ('\u{1c80}', 1042), ('\u{1c81}', 1044), ('\u{1c82}', 1054), ('\u{1c83}', 1057), ('\u{1c84}', 1058), ('\u{1c85}', 1058), - ('\u{1c86}', 1066), ('\u{1c87}', 1122), ('\u{1c88}', 42570), ('\u{1d79}', 42877), - ('\u{1d7d}', 11363), ('\u{1d8e}', 42950), ('\u{1e01}', 7680), ('\u{1e03}', 7682), - ('\u{1e05}', 7684), ('\u{1e07}', 7686), ('\u{1e09}', 7688), ('\u{1e0b}', 7690), - ('\u{1e0d}', 7692), ('\u{1e0f}', 7694), ('\u{1e11}', 7696), ('\u{1e13}', 7698), - ('\u{1e15}', 7700), ('\u{1e17}', 7702), ('\u{1e19}', 7704), ('\u{1e1b}', 7706), - ('\u{1e1d}', 7708), ('\u{1e1f}', 7710), ('\u{1e21}', 7712), ('\u{1e23}', 7714), - ('\u{1e25}', 7716), ('\u{1e27}', 7718), ('\u{1e29}', 7720), ('\u{1e2b}', 7722), - ('\u{1e2d}', 7724), ('\u{1e2f}', 7726), ('\u{1e31}', 7728), ('\u{1e33}', 7730), - ('\u{1e35}', 7732), ('\u{1e37}', 7734), ('\u{1e39}', 7736), ('\u{1e3b}', 7738), - ('\u{1e3d}', 7740), ('\u{1e3f}', 7742), ('\u{1e41}', 7744), ('\u{1e43}', 7746), - ('\u{1e45}', 7748), ('\u{1e47}', 7750), ('\u{1e49}', 7752), ('\u{1e4b}', 7754), - ('\u{1e4d}', 7756), ('\u{1e4f}', 7758), ('\u{1e51}', 7760), ('\u{1e53}', 7762), - ('\u{1e55}', 7764), ('\u{1e57}', 7766), ('\u{1e59}', 7768), ('\u{1e5b}', 7770), - ('\u{1e5d}', 7772), ('\u{1e5f}', 7774), ('\u{1e61}', 7776), ('\u{1e63}', 7778), - ('\u{1e65}', 7780), ('\u{1e67}', 7782), ('\u{1e69}', 7784), ('\u{1e6b}', 7786), - ('\u{1e6d}', 7788), ('\u{1e6f}', 7790), ('\u{1e71}', 7792), ('\u{1e73}', 7794), - ('\u{1e75}', 7796), ('\u{1e77}', 7798), ('\u{1e79}', 7800), ('\u{1e7b}', 7802), - ('\u{1e7d}', 7804), ('\u{1e7f}', 7806), ('\u{1e81}', 7808), ('\u{1e83}', 7810), - ('\u{1e85}', 7812), ('\u{1e87}', 7814), ('\u{1e89}', 7816), ('\u{1e8b}', 7818), - ('\u{1e8d}', 7820), ('\u{1e8f}', 7822), ('\u{1e91}', 7824), ('\u{1e93}', 7826), - ('\u{1e95}', 7828), ('\u{1e96}', 4194310), ('\u{1e97}', 4194311), ('\u{1e98}', 4194312), - ('\u{1e99}', 4194313), ('\u{1e9a}', 4194314), ('\u{1e9b}', 7776), ('\u{1ea1}', 7840), - ('\u{1ea3}', 7842), ('\u{1ea5}', 7844), ('\u{1ea7}', 7846), ('\u{1ea9}', 7848), - ('\u{1eab}', 7850), ('\u{1ead}', 7852), ('\u{1eaf}', 7854), ('\u{1eb1}', 7856), - ('\u{1eb3}', 7858), ('\u{1eb5}', 7860), ('\u{1eb7}', 7862), ('\u{1eb9}', 7864), - ('\u{1ebb}', 7866), ('\u{1ebd}', 7868), ('\u{1ebf}', 7870), ('\u{1ec1}', 7872), - ('\u{1ec3}', 7874), ('\u{1ec5}', 7876), ('\u{1ec7}', 7878), ('\u{1ec9}', 7880), - ('\u{1ecb}', 7882), ('\u{1ecd}', 7884), ('\u{1ecf}', 7886), ('\u{1ed1}', 7888), - ('\u{1ed3}', 7890), ('\u{1ed5}', 7892), ('\u{1ed7}', 7894), ('\u{1ed9}', 7896), - ('\u{1edb}', 7898), ('\u{1edd}', 7900), ('\u{1edf}', 7902), ('\u{1ee1}', 7904), - ('\u{1ee3}', 7906), ('\u{1ee5}', 7908), ('\u{1ee7}', 7910), ('\u{1ee9}', 7912), - ('\u{1eeb}', 7914), ('\u{1eed}', 7916), ('\u{1eef}', 7918), ('\u{1ef1}', 7920), - ('\u{1ef3}', 7922), ('\u{1ef5}', 7924), ('\u{1ef7}', 7926), ('\u{1ef9}', 7928), - ('\u{1efb}', 7930), ('\u{1efd}', 7932), ('\u{1eff}', 7934), ('\u{1f00}', 7944), - ('\u{1f01}', 7945), ('\u{1f02}', 7946), ('\u{1f03}', 7947), ('\u{1f04}', 7948), - ('\u{1f05}', 7949), ('\u{1f06}', 7950), ('\u{1f07}', 7951), ('\u{1f10}', 7960), - ('\u{1f11}', 7961), ('\u{1f12}', 7962), ('\u{1f13}', 7963), ('\u{1f14}', 7964), - ('\u{1f15}', 7965), ('\u{1f20}', 7976), ('\u{1f21}', 7977), ('\u{1f22}', 7978), - ('\u{1f23}', 7979), ('\u{1f24}', 7980), ('\u{1f25}', 7981), ('\u{1f26}', 7982), - ('\u{1f27}', 7983), ('\u{1f30}', 7992), ('\u{1f31}', 7993), ('\u{1f32}', 7994), - ('\u{1f33}', 7995), ('\u{1f34}', 7996), ('\u{1f35}', 7997), ('\u{1f36}', 7998), - ('\u{1f37}', 7999), ('\u{1f40}', 8008), ('\u{1f41}', 8009), ('\u{1f42}', 8010), - ('\u{1f43}', 8011), ('\u{1f44}', 8012), ('\u{1f45}', 8013), ('\u{1f50}', 4194315), - ('\u{1f51}', 8025), ('\u{1f52}', 4194316), ('\u{1f53}', 8027), ('\u{1f54}', 4194317), - ('\u{1f55}', 8029), ('\u{1f56}', 4194318), ('\u{1f57}', 8031), ('\u{1f60}', 8040), - ('\u{1f61}', 8041), ('\u{1f62}', 8042), ('\u{1f63}', 8043), ('\u{1f64}', 8044), - ('\u{1f65}', 8045), ('\u{1f66}', 8046), ('\u{1f67}', 8047), ('\u{1f70}', 8122), - ('\u{1f71}', 8123), ('\u{1f72}', 8136), ('\u{1f73}', 8137), ('\u{1f74}', 8138), - ('\u{1f75}', 8139), ('\u{1f76}', 8154), ('\u{1f77}', 8155), ('\u{1f78}', 8184), - ('\u{1f79}', 8185), ('\u{1f7a}', 8170), ('\u{1f7b}', 8171), ('\u{1f7c}', 8186), - ('\u{1f7d}', 8187), ('\u{1f80}', 4194319), ('\u{1f81}', 4194320), ('\u{1f82}', 4194321), - ('\u{1f83}', 4194322), ('\u{1f84}', 4194323), ('\u{1f85}', 4194324), ('\u{1f86}', 4194325), - ('\u{1f87}', 4194326), ('\u{1f88}', 4194327), ('\u{1f89}', 4194328), ('\u{1f8a}', 4194329), - ('\u{1f8b}', 4194330), ('\u{1f8c}', 4194331), ('\u{1f8d}', 4194332), ('\u{1f8e}', 4194333), - ('\u{1f8f}', 4194334), ('\u{1f90}', 4194335), ('\u{1f91}', 4194336), ('\u{1f92}', 4194337), - ('\u{1f93}', 4194338), ('\u{1f94}', 4194339), ('\u{1f95}', 4194340), ('\u{1f96}', 4194341), - ('\u{1f97}', 4194342), ('\u{1f98}', 4194343), ('\u{1f99}', 4194344), ('\u{1f9a}', 4194345), - ('\u{1f9b}', 4194346), ('\u{1f9c}', 4194347), ('\u{1f9d}', 4194348), ('\u{1f9e}', 4194349), - ('\u{1f9f}', 4194350), ('\u{1fa0}', 4194351), ('\u{1fa1}', 4194352), ('\u{1fa2}', 4194353), - ('\u{1fa3}', 4194354), ('\u{1fa4}', 4194355), ('\u{1fa5}', 4194356), ('\u{1fa6}', 4194357), - ('\u{1fa7}', 4194358), ('\u{1fa8}', 4194359), ('\u{1fa9}', 4194360), ('\u{1faa}', 4194361), - ('\u{1fab}', 4194362), ('\u{1fac}', 4194363), ('\u{1fad}', 4194364), ('\u{1fae}', 4194365), - ('\u{1faf}', 4194366), ('\u{1fb0}', 8120), ('\u{1fb1}', 8121), ('\u{1fb2}', 4194367), - ('\u{1fb3}', 4194368), ('\u{1fb4}', 4194369), ('\u{1fb6}', 4194370), ('\u{1fb7}', 4194371), - ('\u{1fbc}', 4194372), ('\u{1fbe}', 921), ('\u{1fc2}', 4194373), ('\u{1fc3}', 4194374), - ('\u{1fc4}', 4194375), ('\u{1fc6}', 4194376), ('\u{1fc7}', 4194377), ('\u{1fcc}', 4194378), - ('\u{1fd0}', 8152), ('\u{1fd1}', 8153), ('\u{1fd2}', 4194379), ('\u{1fd3}', 4194380), - ('\u{1fd6}', 4194381), ('\u{1fd7}', 4194382), ('\u{1fe0}', 8168), ('\u{1fe1}', 8169), - ('\u{1fe2}', 4194383), ('\u{1fe3}', 4194384), ('\u{1fe4}', 4194385), ('\u{1fe5}', 8172), - ('\u{1fe6}', 4194386), ('\u{1fe7}', 4194387), ('\u{1ff2}', 4194388), ('\u{1ff3}', 4194389), - ('\u{1ff4}', 4194390), ('\u{1ff6}', 4194391), ('\u{1ff7}', 4194392), ('\u{1ffc}', 4194393), - ('\u{214e}', 8498), ('\u{2170}', 8544), ('\u{2171}', 8545), ('\u{2172}', 8546), - ('\u{2173}', 8547), ('\u{2174}', 8548), ('\u{2175}', 8549), ('\u{2176}', 8550), - ('\u{2177}', 8551), ('\u{2178}', 8552), ('\u{2179}', 8553), ('\u{217a}', 8554), - ('\u{217b}', 8555), ('\u{217c}', 8556), ('\u{217d}', 8557), ('\u{217e}', 8558), - ('\u{217f}', 8559), ('\u{2184}', 8579), ('\u{24d0}', 9398), ('\u{24d1}', 9399), - ('\u{24d2}', 9400), ('\u{24d3}', 9401), ('\u{24d4}', 9402), ('\u{24d5}', 9403), - ('\u{24d6}', 9404), ('\u{24d7}', 9405), ('\u{24d8}', 9406), ('\u{24d9}', 9407), - ('\u{24da}', 9408), ('\u{24db}', 9409), ('\u{24dc}', 9410), ('\u{24dd}', 9411), - ('\u{24de}', 9412), ('\u{24df}', 9413), ('\u{24e0}', 9414), ('\u{24e1}', 9415), - ('\u{24e2}', 9416), ('\u{24e3}', 9417), ('\u{24e4}', 9418), ('\u{24e5}', 9419), - ('\u{24e6}', 9420), ('\u{24e7}', 9421), ('\u{24e8}', 9422), ('\u{24e9}', 9423), - ('\u{2c30}', 11264), ('\u{2c31}', 11265), ('\u{2c32}', 11266), ('\u{2c33}', 11267), - ('\u{2c34}', 11268), ('\u{2c35}', 11269), ('\u{2c36}', 11270), ('\u{2c37}', 11271), - ('\u{2c38}', 11272), ('\u{2c39}', 11273), ('\u{2c3a}', 11274), ('\u{2c3b}', 11275), - ('\u{2c3c}', 11276), ('\u{2c3d}', 11277), ('\u{2c3e}', 11278), ('\u{2c3f}', 11279), - ('\u{2c40}', 11280), ('\u{2c41}', 11281), ('\u{2c42}', 11282), ('\u{2c43}', 11283), - ('\u{2c44}', 11284), ('\u{2c45}', 11285), ('\u{2c46}', 11286), ('\u{2c47}', 11287), - ('\u{2c48}', 11288), ('\u{2c49}', 11289), ('\u{2c4a}', 11290), ('\u{2c4b}', 11291), - ('\u{2c4c}', 11292), ('\u{2c4d}', 11293), ('\u{2c4e}', 11294), ('\u{2c4f}', 11295), - ('\u{2c50}', 11296), ('\u{2c51}', 11297), ('\u{2c52}', 11298), ('\u{2c53}', 11299), - ('\u{2c54}', 11300), ('\u{2c55}', 11301), ('\u{2c56}', 11302), ('\u{2c57}', 11303), - ('\u{2c58}', 11304), ('\u{2c59}', 11305), ('\u{2c5a}', 11306), ('\u{2c5b}', 11307), - ('\u{2c5c}', 11308), ('\u{2c5d}', 11309), ('\u{2c5e}', 11310), ('\u{2c5f}', 11311), - ('\u{2c61}', 11360), ('\u{2c65}', 570), ('\u{2c66}', 574), ('\u{2c68}', 11367), - ('\u{2c6a}', 11369), ('\u{2c6c}', 11371), ('\u{2c73}', 11378), ('\u{2c76}', 11381), - ('\u{2c81}', 11392), ('\u{2c83}', 11394), ('\u{2c85}', 11396), ('\u{2c87}', 11398), - ('\u{2c89}', 11400), ('\u{2c8b}', 11402), ('\u{2c8d}', 11404), ('\u{2c8f}', 11406), - ('\u{2c91}', 11408), ('\u{2c93}', 11410), ('\u{2c95}', 11412), ('\u{2c97}', 11414), - ('\u{2c99}', 11416), ('\u{2c9b}', 11418), ('\u{2c9d}', 11420), ('\u{2c9f}', 11422), - ('\u{2ca1}', 11424), ('\u{2ca3}', 11426), ('\u{2ca5}', 11428), ('\u{2ca7}', 11430), - ('\u{2ca9}', 11432), ('\u{2cab}', 11434), ('\u{2cad}', 11436), ('\u{2caf}', 11438), - ('\u{2cb1}', 11440), ('\u{2cb3}', 11442), ('\u{2cb5}', 11444), ('\u{2cb7}', 11446), - ('\u{2cb9}', 11448), ('\u{2cbb}', 11450), ('\u{2cbd}', 11452), ('\u{2cbf}', 11454), - ('\u{2cc1}', 11456), ('\u{2cc3}', 11458), ('\u{2cc5}', 11460), ('\u{2cc7}', 11462), - ('\u{2cc9}', 11464), ('\u{2ccb}', 11466), ('\u{2ccd}', 11468), ('\u{2ccf}', 11470), - ('\u{2cd1}', 11472), ('\u{2cd3}', 11474), ('\u{2cd5}', 11476), ('\u{2cd7}', 11478), - ('\u{2cd9}', 11480), ('\u{2cdb}', 11482), ('\u{2cdd}', 11484), ('\u{2cdf}', 11486), - ('\u{2ce1}', 11488), ('\u{2ce3}', 11490), ('\u{2cec}', 11499), ('\u{2cee}', 11501), - ('\u{2cf3}', 11506), ('\u{2d00}', 4256), ('\u{2d01}', 4257), ('\u{2d02}', 4258), - ('\u{2d03}', 4259), ('\u{2d04}', 4260), ('\u{2d05}', 4261), ('\u{2d06}', 4262), - ('\u{2d07}', 4263), ('\u{2d08}', 4264), ('\u{2d09}', 4265), ('\u{2d0a}', 4266), - ('\u{2d0b}', 4267), ('\u{2d0c}', 4268), ('\u{2d0d}', 4269), ('\u{2d0e}', 4270), - ('\u{2d0f}', 4271), ('\u{2d10}', 4272), ('\u{2d11}', 4273), ('\u{2d12}', 4274), - ('\u{2d13}', 4275), ('\u{2d14}', 4276), ('\u{2d15}', 4277), ('\u{2d16}', 4278), - ('\u{2d17}', 4279), ('\u{2d18}', 4280), ('\u{2d19}', 4281), ('\u{2d1a}', 4282), - ('\u{2d1b}', 4283), ('\u{2d1c}', 4284), ('\u{2d1d}', 4285), ('\u{2d1e}', 4286), - ('\u{2d1f}', 4287), ('\u{2d20}', 4288), ('\u{2d21}', 4289), ('\u{2d22}', 4290), - ('\u{2d23}', 4291), ('\u{2d24}', 4292), ('\u{2d25}', 4293), ('\u{2d27}', 4295), - ('\u{2d2d}', 4301), ('\u{a641}', 42560), ('\u{a643}', 42562), ('\u{a645}', 42564), - ('\u{a647}', 42566), ('\u{a649}', 42568), ('\u{a64b}', 42570), ('\u{a64d}', 42572), - ('\u{a64f}', 42574), ('\u{a651}', 42576), ('\u{a653}', 42578), ('\u{a655}', 42580), - ('\u{a657}', 42582), ('\u{a659}', 42584), ('\u{a65b}', 42586), ('\u{a65d}', 42588), - ('\u{a65f}', 42590), ('\u{a661}', 42592), ('\u{a663}', 42594), ('\u{a665}', 42596), - ('\u{a667}', 42598), ('\u{a669}', 42600), ('\u{a66b}', 42602), ('\u{a66d}', 42604), - ('\u{a681}', 42624), ('\u{a683}', 42626), ('\u{a685}', 42628), ('\u{a687}', 42630), - ('\u{a689}', 42632), ('\u{a68b}', 42634), ('\u{a68d}', 42636), ('\u{a68f}', 42638), - ('\u{a691}', 42640), ('\u{a693}', 42642), ('\u{a695}', 42644), ('\u{a697}', 42646), - ('\u{a699}', 42648), ('\u{a69b}', 42650), ('\u{a723}', 42786), ('\u{a725}', 42788), - ('\u{a727}', 42790), ('\u{a729}', 42792), ('\u{a72b}', 42794), ('\u{a72d}', 42796), - ('\u{a72f}', 42798), ('\u{a733}', 42802), ('\u{a735}', 42804), ('\u{a737}', 42806), - ('\u{a739}', 42808), ('\u{a73b}', 42810), ('\u{a73d}', 42812), ('\u{a73f}', 42814), - ('\u{a741}', 42816), ('\u{a743}', 42818), ('\u{a745}', 42820), ('\u{a747}', 42822), - ('\u{a749}', 42824), ('\u{a74b}', 42826), ('\u{a74d}', 42828), ('\u{a74f}', 42830), - ('\u{a751}', 42832), ('\u{a753}', 42834), ('\u{a755}', 42836), ('\u{a757}', 42838), - ('\u{a759}', 42840), ('\u{a75b}', 42842), ('\u{a75d}', 42844), ('\u{a75f}', 42846), - ('\u{a761}', 42848), ('\u{a763}', 42850), ('\u{a765}', 42852), ('\u{a767}', 42854), - ('\u{a769}', 42856), ('\u{a76b}', 42858), ('\u{a76d}', 42860), ('\u{a76f}', 42862), - ('\u{a77a}', 42873), ('\u{a77c}', 42875), ('\u{a77f}', 42878), ('\u{a781}', 42880), - ('\u{a783}', 42882), ('\u{a785}', 42884), ('\u{a787}', 42886), ('\u{a78c}', 42891), - ('\u{a791}', 42896), ('\u{a793}', 42898), ('\u{a794}', 42948), ('\u{a797}', 42902), - ('\u{a799}', 42904), ('\u{a79b}', 42906), ('\u{a79d}', 42908), ('\u{a79f}', 42910), - ('\u{a7a1}', 42912), ('\u{a7a3}', 42914), ('\u{a7a5}', 42916), ('\u{a7a7}', 42918), - ('\u{a7a9}', 42920), ('\u{a7b5}', 42932), ('\u{a7b7}', 42934), ('\u{a7b9}', 42936), - ('\u{a7bb}', 42938), ('\u{a7bd}', 42940), ('\u{a7bf}', 42942), ('\u{a7c1}', 42944), - ('\u{a7c3}', 42946), ('\u{a7c8}', 42951), ('\u{a7ca}', 42953), ('\u{a7d1}', 42960), - ('\u{a7d7}', 42966), ('\u{a7d9}', 42968), ('\u{a7f6}', 42997), ('\u{ab53}', 42931), - ('\u{ab70}', 5024), ('\u{ab71}', 5025), ('\u{ab72}', 5026), ('\u{ab73}', 5027), - ('\u{ab74}', 5028), ('\u{ab75}', 5029), ('\u{ab76}', 5030), ('\u{ab77}', 5031), - ('\u{ab78}', 5032), ('\u{ab79}', 5033), ('\u{ab7a}', 5034), ('\u{ab7b}', 5035), - ('\u{ab7c}', 5036), ('\u{ab7d}', 5037), ('\u{ab7e}', 5038), ('\u{ab7f}', 5039), - ('\u{ab80}', 5040), ('\u{ab81}', 5041), ('\u{ab82}', 5042), ('\u{ab83}', 5043), - ('\u{ab84}', 5044), ('\u{ab85}', 5045), ('\u{ab86}', 5046), ('\u{ab87}', 5047), - ('\u{ab88}', 5048), ('\u{ab89}', 5049), ('\u{ab8a}', 5050), ('\u{ab8b}', 5051), - ('\u{ab8c}', 5052), ('\u{ab8d}', 5053), ('\u{ab8e}', 5054), ('\u{ab8f}', 5055), - ('\u{ab90}', 5056), ('\u{ab91}', 5057), ('\u{ab92}', 5058), ('\u{ab93}', 5059), - ('\u{ab94}', 5060), ('\u{ab95}', 5061), ('\u{ab96}', 5062), ('\u{ab97}', 5063), - ('\u{ab98}', 5064), ('\u{ab99}', 5065), ('\u{ab9a}', 5066), ('\u{ab9b}', 5067), - ('\u{ab9c}', 5068), ('\u{ab9d}', 5069), ('\u{ab9e}', 5070), ('\u{ab9f}', 5071), - ('\u{aba0}', 5072), ('\u{aba1}', 5073), ('\u{aba2}', 5074), ('\u{aba3}', 5075), - ('\u{aba4}', 5076), ('\u{aba5}', 5077), ('\u{aba6}', 5078), ('\u{aba7}', 5079), - ('\u{aba8}', 5080), ('\u{aba9}', 5081), ('\u{abaa}', 5082), ('\u{abab}', 5083), - ('\u{abac}', 5084), ('\u{abad}', 5085), ('\u{abae}', 5086), ('\u{abaf}', 5087), - ('\u{abb0}', 5088), ('\u{abb1}', 5089), ('\u{abb2}', 5090), ('\u{abb3}', 5091), - ('\u{abb4}', 5092), ('\u{abb5}', 5093), ('\u{abb6}', 5094), ('\u{abb7}', 5095), - ('\u{abb8}', 5096), ('\u{abb9}', 5097), ('\u{abba}', 5098), ('\u{abbb}', 5099), - ('\u{abbc}', 5100), ('\u{abbd}', 5101), ('\u{abbe}', 5102), ('\u{abbf}', 5103), - ('\u{fb00}', 4194394), ('\u{fb01}', 4194395), ('\u{fb02}', 4194396), ('\u{fb03}', 4194397), - ('\u{fb04}', 4194398), ('\u{fb05}', 4194399), ('\u{fb06}', 4194400), ('\u{fb13}', 4194401), - ('\u{fb14}', 4194402), ('\u{fb15}', 4194403), ('\u{fb16}', 4194404), ('\u{fb17}', 4194405), - ('\u{ff41}', 65313), ('\u{ff42}', 65314), ('\u{ff43}', 65315), ('\u{ff44}', 65316), - ('\u{ff45}', 65317), ('\u{ff46}', 65318), ('\u{ff47}', 65319), ('\u{ff48}', 65320), - ('\u{ff49}', 65321), ('\u{ff4a}', 65322), ('\u{ff4b}', 65323), ('\u{ff4c}', 65324), - ('\u{ff4d}', 65325), ('\u{ff4e}', 65326), ('\u{ff4f}', 65327), ('\u{ff50}', 65328), - ('\u{ff51}', 65329), ('\u{ff52}', 65330), ('\u{ff53}', 65331), ('\u{ff54}', 65332), - ('\u{ff55}', 65333), ('\u{ff56}', 65334), ('\u{ff57}', 65335), ('\u{ff58}', 65336), - ('\u{ff59}', 65337), ('\u{ff5a}', 65338), ('\u{10428}', 66560), ('\u{10429}', 66561), - ('\u{1042a}', 66562), ('\u{1042b}', 66563), ('\u{1042c}', 66564), ('\u{1042d}', 66565), - ('\u{1042e}', 66566), ('\u{1042f}', 66567), ('\u{10430}', 66568), ('\u{10431}', 66569), - ('\u{10432}', 66570), ('\u{10433}', 66571), ('\u{10434}', 66572), ('\u{10435}', 66573), - ('\u{10436}', 66574), ('\u{10437}', 66575), ('\u{10438}', 66576), ('\u{10439}', 66577), - ('\u{1043a}', 66578), ('\u{1043b}', 66579), ('\u{1043c}', 66580), ('\u{1043d}', 66581), - ('\u{1043e}', 66582), ('\u{1043f}', 66583), ('\u{10440}', 66584), ('\u{10441}', 66585), - ('\u{10442}', 66586), ('\u{10443}', 66587), ('\u{10444}', 66588), ('\u{10445}', 66589), - ('\u{10446}', 66590), ('\u{10447}', 66591), ('\u{10448}', 66592), ('\u{10449}', 66593), - ('\u{1044a}', 66594), ('\u{1044b}', 66595), ('\u{1044c}', 66596), ('\u{1044d}', 66597), - ('\u{1044e}', 66598), ('\u{1044f}', 66599), ('\u{104d8}', 66736), ('\u{104d9}', 66737), - ('\u{104da}', 66738), ('\u{104db}', 66739), ('\u{104dc}', 66740), ('\u{104dd}', 66741), - ('\u{104de}', 66742), ('\u{104df}', 66743), ('\u{104e0}', 66744), ('\u{104e1}', 66745), - ('\u{104e2}', 66746), ('\u{104e3}', 66747), ('\u{104e4}', 66748), ('\u{104e5}', 66749), - ('\u{104e6}', 66750), ('\u{104e7}', 66751), ('\u{104e8}', 66752), ('\u{104e9}', 66753), - ('\u{104ea}', 66754), ('\u{104eb}', 66755), ('\u{104ec}', 66756), ('\u{104ed}', 66757), - ('\u{104ee}', 66758), ('\u{104ef}', 66759), ('\u{104f0}', 66760), ('\u{104f1}', 66761), - ('\u{104f2}', 66762), ('\u{104f3}', 66763), ('\u{104f4}', 66764), ('\u{104f5}', 66765), - ('\u{104f6}', 66766), ('\u{104f7}', 66767), ('\u{104f8}', 66768), ('\u{104f9}', 66769), - ('\u{104fa}', 66770), ('\u{104fb}', 66771), ('\u{10597}', 66928), ('\u{10598}', 66929), - ('\u{10599}', 66930), ('\u{1059a}', 66931), ('\u{1059b}', 66932), ('\u{1059c}', 66933), - ('\u{1059d}', 66934), ('\u{1059e}', 66935), ('\u{1059f}', 66936), ('\u{105a0}', 66937), - ('\u{105a1}', 66938), ('\u{105a3}', 66940), ('\u{105a4}', 66941), ('\u{105a5}', 66942), - ('\u{105a6}', 66943), ('\u{105a7}', 66944), ('\u{105a8}', 66945), ('\u{105a9}', 66946), - ('\u{105aa}', 66947), ('\u{105ab}', 66948), ('\u{105ac}', 66949), ('\u{105ad}', 66950), - ('\u{105ae}', 66951), ('\u{105af}', 66952), ('\u{105b0}', 66953), ('\u{105b1}', 66954), - ('\u{105b3}', 66956), ('\u{105b4}', 66957), ('\u{105b5}', 66958), ('\u{105b6}', 66959), - ('\u{105b7}', 66960), ('\u{105b8}', 66961), ('\u{105b9}', 66962), ('\u{105bb}', 66964), - ('\u{105bc}', 66965), ('\u{10cc0}', 68736), ('\u{10cc1}', 68737), ('\u{10cc2}', 68738), - ('\u{10cc3}', 68739), ('\u{10cc4}', 68740), ('\u{10cc5}', 68741), ('\u{10cc6}', 68742), - ('\u{10cc7}', 68743), ('\u{10cc8}', 68744), ('\u{10cc9}', 68745), ('\u{10cca}', 68746), - ('\u{10ccb}', 68747), ('\u{10ccc}', 68748), ('\u{10ccd}', 68749), ('\u{10cce}', 68750), - ('\u{10ccf}', 68751), ('\u{10cd0}', 68752), ('\u{10cd1}', 68753), ('\u{10cd2}', 68754), - ('\u{10cd3}', 68755), ('\u{10cd4}', 68756), ('\u{10cd5}', 68757), ('\u{10cd6}', 68758), - ('\u{10cd7}', 68759), ('\u{10cd8}', 68760), ('\u{10cd9}', 68761), ('\u{10cda}', 68762), - ('\u{10cdb}', 68763), ('\u{10cdc}', 68764), ('\u{10cdd}', 68765), ('\u{10cde}', 68766), - ('\u{10cdf}', 68767), ('\u{10ce0}', 68768), ('\u{10ce1}', 68769), ('\u{10ce2}', 68770), - ('\u{10ce3}', 68771), ('\u{10ce4}', 68772), ('\u{10ce5}', 68773), ('\u{10ce6}', 68774), - ('\u{10ce7}', 68775), ('\u{10ce8}', 68776), ('\u{10ce9}', 68777), ('\u{10cea}', 68778), - ('\u{10ceb}', 68779), ('\u{10cec}', 68780), ('\u{10ced}', 68781), ('\u{10cee}', 68782), - ('\u{10cef}', 68783), ('\u{10cf0}', 68784), ('\u{10cf1}', 68785), ('\u{10cf2}', 68786), - ('\u{118c0}', 71840), ('\u{118c1}', 71841), ('\u{118c2}', 71842), ('\u{118c3}', 71843), - ('\u{118c4}', 71844), ('\u{118c5}', 71845), ('\u{118c6}', 71846), ('\u{118c7}', 71847), - ('\u{118c8}', 71848), ('\u{118c9}', 71849), ('\u{118ca}', 71850), ('\u{118cb}', 71851), - ('\u{118cc}', 71852), ('\u{118cd}', 71853), ('\u{118ce}', 71854), ('\u{118cf}', 71855), - ('\u{118d0}', 71856), ('\u{118d1}', 71857), ('\u{118d2}', 71858), ('\u{118d3}', 71859), - ('\u{118d4}', 71860), ('\u{118d5}', 71861), ('\u{118d6}', 71862), ('\u{118d7}', 71863), - ('\u{118d8}', 71864), ('\u{118d9}', 71865), ('\u{118da}', 71866), ('\u{118db}', 71867), - ('\u{118dc}', 71868), ('\u{118dd}', 71869), ('\u{118de}', 71870), ('\u{118df}', 71871), - ('\u{16e60}', 93760), ('\u{16e61}', 93761), ('\u{16e62}', 93762), ('\u{16e63}', 93763), - ('\u{16e64}', 93764), ('\u{16e65}', 93765), ('\u{16e66}', 93766), ('\u{16e67}', 93767), - ('\u{16e68}', 93768), ('\u{16e69}', 93769), ('\u{16e6a}', 93770), ('\u{16e6b}', 93771), - ('\u{16e6c}', 93772), ('\u{16e6d}', 93773), ('\u{16e6e}', 93774), ('\u{16e6f}', 93775), - ('\u{16e70}', 93776), ('\u{16e71}', 93777), ('\u{16e72}', 93778), ('\u{16e73}', 93779), - ('\u{16e74}', 93780), ('\u{16e75}', 93781), ('\u{16e76}', 93782), ('\u{16e77}', 93783), - ('\u{16e78}', 93784), ('\u{16e79}', 93785), ('\u{16e7a}', 93786), ('\u{16e7b}', 93787), - ('\u{16e7c}', 93788), ('\u{16e7d}', 93789), ('\u{16e7e}', 93790), ('\u{16e7f}', 93791), - ('\u{1e922}', 125184), ('\u{1e923}', 125185), ('\u{1e924}', 125186), ('\u{1e925}', 125187), - ('\u{1e926}', 125188), ('\u{1e927}', 125189), ('\u{1e928}', 125190), ('\u{1e929}', 125191), - ('\u{1e92a}', 125192), ('\u{1e92b}', 125193), ('\u{1e92c}', 125194), ('\u{1e92d}', 125195), - ('\u{1e92e}', 125196), ('\u{1e92f}', 125197), ('\u{1e930}', 125198), ('\u{1e931}', 125199), - ('\u{1e932}', 125200), ('\u{1e933}', 125201), ('\u{1e934}', 125202), ('\u{1e935}', 125203), - ('\u{1e936}', 125204), ('\u{1e937}', 125205), ('\u{1e938}', 125206), ('\u{1e939}', 125207), - ('\u{1e93a}', 125208), ('\u{1e93b}', 125209), ('\u{1e93c}', 125210), ('\u{1e93d}', 125211), - ('\u{1e93e}', 125212), ('\u{1e93f}', 125213), ('\u{1e940}', 125214), ('\u{1e941}', 125215), - ('\u{1e942}', 125216), ('\u{1e943}', 125217), + ('\u{1c86}', 1066), ('\u{1c87}', 1122), ('\u{1c88}', 42570), ('\u{1c8a}', 7305), + ('\u{1d79}', 42877), ('\u{1d7d}', 11363), ('\u{1d8e}', 42950), ('\u{1e01}', 7680), + ('\u{1e03}', 7682), ('\u{1e05}', 7684), ('\u{1e07}', 7686), ('\u{1e09}', 7688), + ('\u{1e0b}', 7690), ('\u{1e0d}', 7692), ('\u{1e0f}', 7694), ('\u{1e11}', 7696), + ('\u{1e13}', 7698), ('\u{1e15}', 7700), ('\u{1e17}', 7702), ('\u{1e19}', 7704), + ('\u{1e1b}', 7706), ('\u{1e1d}', 7708), ('\u{1e1f}', 7710), ('\u{1e21}', 7712), + ('\u{1e23}', 7714), ('\u{1e25}', 7716), ('\u{1e27}', 7718), ('\u{1e29}', 7720), + ('\u{1e2b}', 7722), ('\u{1e2d}', 7724), ('\u{1e2f}', 7726), ('\u{1e31}', 7728), + ('\u{1e33}', 7730), ('\u{1e35}', 7732), ('\u{1e37}', 7734), ('\u{1e39}', 7736), + ('\u{1e3b}', 7738), ('\u{1e3d}', 7740), ('\u{1e3f}', 7742), ('\u{1e41}', 7744), + ('\u{1e43}', 7746), ('\u{1e45}', 7748), ('\u{1e47}', 7750), ('\u{1e49}', 7752), + ('\u{1e4b}', 7754), ('\u{1e4d}', 7756), ('\u{1e4f}', 7758), ('\u{1e51}', 7760), + ('\u{1e53}', 7762), ('\u{1e55}', 7764), ('\u{1e57}', 7766), ('\u{1e59}', 7768), + ('\u{1e5b}', 7770), ('\u{1e5d}', 7772), ('\u{1e5f}', 7774), ('\u{1e61}', 7776), + ('\u{1e63}', 7778), ('\u{1e65}', 7780), ('\u{1e67}', 7782), ('\u{1e69}', 7784), + ('\u{1e6b}', 7786), ('\u{1e6d}', 7788), ('\u{1e6f}', 7790), ('\u{1e71}', 7792), + ('\u{1e73}', 7794), ('\u{1e75}', 7796), ('\u{1e77}', 7798), ('\u{1e79}', 7800), + ('\u{1e7b}', 7802), ('\u{1e7d}', 7804), ('\u{1e7f}', 7806), ('\u{1e81}', 7808), + ('\u{1e83}', 7810), ('\u{1e85}', 7812), ('\u{1e87}', 7814), ('\u{1e89}', 7816), + ('\u{1e8b}', 7818), ('\u{1e8d}', 7820), ('\u{1e8f}', 7822), ('\u{1e91}', 7824), + ('\u{1e93}', 7826), ('\u{1e95}', 7828), ('\u{1e96}', 4194310), ('\u{1e97}', 4194311), + ('\u{1e98}', 4194312), ('\u{1e99}', 4194313), ('\u{1e9a}', 4194314), ('\u{1e9b}', 7776), + ('\u{1ea1}', 7840), ('\u{1ea3}', 7842), ('\u{1ea5}', 7844), ('\u{1ea7}', 7846), + ('\u{1ea9}', 7848), ('\u{1eab}', 7850), ('\u{1ead}', 7852), ('\u{1eaf}', 7854), + ('\u{1eb1}', 7856), ('\u{1eb3}', 7858), ('\u{1eb5}', 7860), ('\u{1eb7}', 7862), + ('\u{1eb9}', 7864), ('\u{1ebb}', 7866), ('\u{1ebd}', 7868), ('\u{1ebf}', 7870), + ('\u{1ec1}', 7872), ('\u{1ec3}', 7874), ('\u{1ec5}', 7876), ('\u{1ec7}', 7878), + ('\u{1ec9}', 7880), ('\u{1ecb}', 7882), ('\u{1ecd}', 7884), ('\u{1ecf}', 7886), + ('\u{1ed1}', 7888), ('\u{1ed3}', 7890), ('\u{1ed5}', 7892), ('\u{1ed7}', 7894), + ('\u{1ed9}', 7896), ('\u{1edb}', 7898), ('\u{1edd}', 7900), ('\u{1edf}', 7902), + ('\u{1ee1}', 7904), ('\u{1ee3}', 7906), ('\u{1ee5}', 7908), ('\u{1ee7}', 7910), + ('\u{1ee9}', 7912), ('\u{1eeb}', 7914), ('\u{1eed}', 7916), ('\u{1eef}', 7918), + ('\u{1ef1}', 7920), ('\u{1ef3}', 7922), ('\u{1ef5}', 7924), ('\u{1ef7}', 7926), + ('\u{1ef9}', 7928), ('\u{1efb}', 7930), ('\u{1efd}', 7932), ('\u{1eff}', 7934), + ('\u{1f00}', 7944), ('\u{1f01}', 7945), ('\u{1f02}', 7946), ('\u{1f03}', 7947), + ('\u{1f04}', 7948), ('\u{1f05}', 7949), ('\u{1f06}', 7950), ('\u{1f07}', 7951), + ('\u{1f10}', 7960), ('\u{1f11}', 7961), ('\u{1f12}', 7962), ('\u{1f13}', 7963), + ('\u{1f14}', 7964), ('\u{1f15}', 7965), ('\u{1f20}', 7976), ('\u{1f21}', 7977), + ('\u{1f22}', 7978), ('\u{1f23}', 7979), ('\u{1f24}', 7980), ('\u{1f25}', 7981), + ('\u{1f26}', 7982), ('\u{1f27}', 7983), ('\u{1f30}', 7992), ('\u{1f31}', 7993), + ('\u{1f32}', 7994), ('\u{1f33}', 7995), ('\u{1f34}', 7996), ('\u{1f35}', 7997), + ('\u{1f36}', 7998), ('\u{1f37}', 7999), ('\u{1f40}', 8008), ('\u{1f41}', 8009), + ('\u{1f42}', 8010), ('\u{1f43}', 8011), ('\u{1f44}', 8012), ('\u{1f45}', 8013), + ('\u{1f50}', 4194315), ('\u{1f51}', 8025), ('\u{1f52}', 4194316), ('\u{1f53}', 8027), + ('\u{1f54}', 4194317), ('\u{1f55}', 8029), ('\u{1f56}', 4194318), ('\u{1f57}', 8031), + ('\u{1f60}', 8040), ('\u{1f61}', 8041), ('\u{1f62}', 8042), ('\u{1f63}', 8043), + ('\u{1f64}', 8044), ('\u{1f65}', 8045), ('\u{1f66}', 8046), ('\u{1f67}', 8047), + ('\u{1f70}', 8122), ('\u{1f71}', 8123), ('\u{1f72}', 8136), ('\u{1f73}', 8137), + ('\u{1f74}', 8138), ('\u{1f75}', 8139), ('\u{1f76}', 8154), ('\u{1f77}', 8155), + ('\u{1f78}', 8184), ('\u{1f79}', 8185), ('\u{1f7a}', 8170), ('\u{1f7b}', 8171), + ('\u{1f7c}', 8186), ('\u{1f7d}', 8187), ('\u{1f80}', 4194319), ('\u{1f81}', 4194320), + ('\u{1f82}', 4194321), ('\u{1f83}', 4194322), ('\u{1f84}', 4194323), ('\u{1f85}', 4194324), + ('\u{1f86}', 4194325), ('\u{1f87}', 4194326), ('\u{1f88}', 4194327), ('\u{1f89}', 4194328), + ('\u{1f8a}', 4194329), ('\u{1f8b}', 4194330), ('\u{1f8c}', 4194331), ('\u{1f8d}', 4194332), + ('\u{1f8e}', 4194333), ('\u{1f8f}', 4194334), ('\u{1f90}', 4194335), ('\u{1f91}', 4194336), + ('\u{1f92}', 4194337), ('\u{1f93}', 4194338), ('\u{1f94}', 4194339), ('\u{1f95}', 4194340), + ('\u{1f96}', 4194341), ('\u{1f97}', 4194342), ('\u{1f98}', 4194343), ('\u{1f99}', 4194344), + ('\u{1f9a}', 4194345), ('\u{1f9b}', 4194346), ('\u{1f9c}', 4194347), ('\u{1f9d}', 4194348), + ('\u{1f9e}', 4194349), ('\u{1f9f}', 4194350), ('\u{1fa0}', 4194351), ('\u{1fa1}', 4194352), + ('\u{1fa2}', 4194353), ('\u{1fa3}', 4194354), ('\u{1fa4}', 4194355), ('\u{1fa5}', 4194356), + ('\u{1fa6}', 4194357), ('\u{1fa7}', 4194358), ('\u{1fa8}', 4194359), ('\u{1fa9}', 4194360), + ('\u{1faa}', 4194361), ('\u{1fab}', 4194362), ('\u{1fac}', 4194363), ('\u{1fad}', 4194364), + ('\u{1fae}', 4194365), ('\u{1faf}', 4194366), ('\u{1fb0}', 8120), ('\u{1fb1}', 8121), + ('\u{1fb2}', 4194367), ('\u{1fb3}', 4194368), ('\u{1fb4}', 4194369), ('\u{1fb6}', 4194370), + ('\u{1fb7}', 4194371), ('\u{1fbc}', 4194372), ('\u{1fbe}', 921), ('\u{1fc2}', 4194373), + ('\u{1fc3}', 4194374), ('\u{1fc4}', 4194375), ('\u{1fc6}', 4194376), ('\u{1fc7}', 4194377), + ('\u{1fcc}', 4194378), ('\u{1fd0}', 8152), ('\u{1fd1}', 8153), ('\u{1fd2}', 4194379), + ('\u{1fd3}', 4194380), ('\u{1fd6}', 4194381), ('\u{1fd7}', 4194382), ('\u{1fe0}', 8168), + ('\u{1fe1}', 8169), ('\u{1fe2}', 4194383), ('\u{1fe3}', 4194384), ('\u{1fe4}', 4194385), + ('\u{1fe5}', 8172), ('\u{1fe6}', 4194386), ('\u{1fe7}', 4194387), ('\u{1ff2}', 4194388), + ('\u{1ff3}', 4194389), ('\u{1ff4}', 4194390), ('\u{1ff6}', 4194391), ('\u{1ff7}', 4194392), + ('\u{1ffc}', 4194393), ('\u{214e}', 8498), ('\u{2170}', 8544), ('\u{2171}', 8545), + ('\u{2172}', 8546), ('\u{2173}', 8547), ('\u{2174}', 8548), ('\u{2175}', 8549), + ('\u{2176}', 8550), ('\u{2177}', 8551), ('\u{2178}', 8552), ('\u{2179}', 8553), + ('\u{217a}', 8554), ('\u{217b}', 8555), ('\u{217c}', 8556), ('\u{217d}', 8557), + ('\u{217e}', 8558), ('\u{217f}', 8559), ('\u{2184}', 8579), ('\u{24d0}', 9398), + ('\u{24d1}', 9399), ('\u{24d2}', 9400), ('\u{24d3}', 9401), ('\u{24d4}', 9402), + ('\u{24d5}', 9403), ('\u{24d6}', 9404), ('\u{24d7}', 9405), ('\u{24d8}', 9406), + ('\u{24d9}', 9407), ('\u{24da}', 9408), ('\u{24db}', 9409), ('\u{24dc}', 9410), + ('\u{24dd}', 9411), ('\u{24de}', 9412), ('\u{24df}', 9413), ('\u{24e0}', 9414), + ('\u{24e1}', 9415), ('\u{24e2}', 9416), ('\u{24e3}', 9417), ('\u{24e4}', 9418), + ('\u{24e5}', 9419), ('\u{24e6}', 9420), ('\u{24e7}', 9421), ('\u{24e8}', 9422), + ('\u{24e9}', 9423), ('\u{2c30}', 11264), ('\u{2c31}', 11265), ('\u{2c32}', 11266), + ('\u{2c33}', 11267), ('\u{2c34}', 11268), ('\u{2c35}', 11269), ('\u{2c36}', 11270), + ('\u{2c37}', 11271), ('\u{2c38}', 11272), ('\u{2c39}', 11273), ('\u{2c3a}', 11274), + ('\u{2c3b}', 11275), ('\u{2c3c}', 11276), ('\u{2c3d}', 11277), ('\u{2c3e}', 11278), + ('\u{2c3f}', 11279), ('\u{2c40}', 11280), ('\u{2c41}', 11281), ('\u{2c42}', 11282), + ('\u{2c43}', 11283), ('\u{2c44}', 11284), ('\u{2c45}', 11285), ('\u{2c46}', 11286), + ('\u{2c47}', 11287), ('\u{2c48}', 11288), ('\u{2c49}', 11289), ('\u{2c4a}', 11290), + ('\u{2c4b}', 11291), ('\u{2c4c}', 11292), ('\u{2c4d}', 11293), ('\u{2c4e}', 11294), + ('\u{2c4f}', 11295), ('\u{2c50}', 11296), ('\u{2c51}', 11297), ('\u{2c52}', 11298), + ('\u{2c53}', 11299), ('\u{2c54}', 11300), ('\u{2c55}', 11301), ('\u{2c56}', 11302), + ('\u{2c57}', 11303), ('\u{2c58}', 11304), ('\u{2c59}', 11305), ('\u{2c5a}', 11306), + ('\u{2c5b}', 11307), ('\u{2c5c}', 11308), ('\u{2c5d}', 11309), ('\u{2c5e}', 11310), + ('\u{2c5f}', 11311), ('\u{2c61}', 11360), ('\u{2c65}', 570), ('\u{2c66}', 574), + ('\u{2c68}', 11367), ('\u{2c6a}', 11369), ('\u{2c6c}', 11371), ('\u{2c73}', 11378), + ('\u{2c76}', 11381), ('\u{2c81}', 11392), ('\u{2c83}', 11394), ('\u{2c85}', 11396), + ('\u{2c87}', 11398), ('\u{2c89}', 11400), ('\u{2c8b}', 11402), ('\u{2c8d}', 11404), + ('\u{2c8f}', 11406), ('\u{2c91}', 11408), ('\u{2c93}', 11410), ('\u{2c95}', 11412), + ('\u{2c97}', 11414), ('\u{2c99}', 11416), ('\u{2c9b}', 11418), ('\u{2c9d}', 11420), + ('\u{2c9f}', 11422), ('\u{2ca1}', 11424), ('\u{2ca3}', 11426), ('\u{2ca5}', 11428), + ('\u{2ca7}', 11430), ('\u{2ca9}', 11432), ('\u{2cab}', 11434), ('\u{2cad}', 11436), + ('\u{2caf}', 11438), ('\u{2cb1}', 11440), ('\u{2cb3}', 11442), ('\u{2cb5}', 11444), + ('\u{2cb7}', 11446), ('\u{2cb9}', 11448), ('\u{2cbb}', 11450), ('\u{2cbd}', 11452), + ('\u{2cbf}', 11454), ('\u{2cc1}', 11456), ('\u{2cc3}', 11458), ('\u{2cc5}', 11460), + ('\u{2cc7}', 11462), ('\u{2cc9}', 11464), ('\u{2ccb}', 11466), ('\u{2ccd}', 11468), + ('\u{2ccf}', 11470), ('\u{2cd1}', 11472), ('\u{2cd3}', 11474), ('\u{2cd5}', 11476), + ('\u{2cd7}', 11478), ('\u{2cd9}', 11480), ('\u{2cdb}', 11482), ('\u{2cdd}', 11484), + ('\u{2cdf}', 11486), ('\u{2ce1}', 11488), ('\u{2ce3}', 11490), ('\u{2cec}', 11499), + ('\u{2cee}', 11501), ('\u{2cf3}', 11506), ('\u{2d00}', 4256), ('\u{2d01}', 4257), + ('\u{2d02}', 4258), ('\u{2d03}', 4259), ('\u{2d04}', 4260), ('\u{2d05}', 4261), + ('\u{2d06}', 4262), ('\u{2d07}', 4263), ('\u{2d08}', 4264), ('\u{2d09}', 4265), + ('\u{2d0a}', 4266), ('\u{2d0b}', 4267), ('\u{2d0c}', 4268), ('\u{2d0d}', 4269), + ('\u{2d0e}', 4270), ('\u{2d0f}', 4271), ('\u{2d10}', 4272), ('\u{2d11}', 4273), + ('\u{2d12}', 4274), ('\u{2d13}', 4275), ('\u{2d14}', 4276), ('\u{2d15}', 4277), + ('\u{2d16}', 4278), ('\u{2d17}', 4279), ('\u{2d18}', 4280), ('\u{2d19}', 4281), + ('\u{2d1a}', 4282), ('\u{2d1b}', 4283), ('\u{2d1c}', 4284), ('\u{2d1d}', 4285), + ('\u{2d1e}', 4286), ('\u{2d1f}', 4287), ('\u{2d20}', 4288), ('\u{2d21}', 4289), + ('\u{2d22}', 4290), ('\u{2d23}', 4291), ('\u{2d24}', 4292), ('\u{2d25}', 4293), + ('\u{2d27}', 4295), ('\u{2d2d}', 4301), ('\u{a641}', 42560), ('\u{a643}', 42562), + ('\u{a645}', 42564), ('\u{a647}', 42566), ('\u{a649}', 42568), ('\u{a64b}', 42570), + ('\u{a64d}', 42572), ('\u{a64f}', 42574), ('\u{a651}', 42576), ('\u{a653}', 42578), + ('\u{a655}', 42580), ('\u{a657}', 42582), ('\u{a659}', 42584), ('\u{a65b}', 42586), + ('\u{a65d}', 42588), ('\u{a65f}', 42590), ('\u{a661}', 42592), ('\u{a663}', 42594), + ('\u{a665}', 42596), ('\u{a667}', 42598), ('\u{a669}', 42600), ('\u{a66b}', 42602), + ('\u{a66d}', 42604), ('\u{a681}', 42624), ('\u{a683}', 42626), ('\u{a685}', 42628), + ('\u{a687}', 42630), ('\u{a689}', 42632), ('\u{a68b}', 42634), ('\u{a68d}', 42636), + ('\u{a68f}', 42638), ('\u{a691}', 42640), ('\u{a693}', 42642), ('\u{a695}', 42644), + ('\u{a697}', 42646), ('\u{a699}', 42648), ('\u{a69b}', 42650), ('\u{a723}', 42786), + ('\u{a725}', 42788), ('\u{a727}', 42790), ('\u{a729}', 42792), ('\u{a72b}', 42794), + ('\u{a72d}', 42796), ('\u{a72f}', 42798), ('\u{a733}', 42802), ('\u{a735}', 42804), + ('\u{a737}', 42806), ('\u{a739}', 42808), ('\u{a73b}', 42810), ('\u{a73d}', 42812), + ('\u{a73f}', 42814), ('\u{a741}', 42816), ('\u{a743}', 42818), ('\u{a745}', 42820), + ('\u{a747}', 42822), ('\u{a749}', 42824), ('\u{a74b}', 42826), ('\u{a74d}', 42828), + ('\u{a74f}', 42830), ('\u{a751}', 42832), ('\u{a753}', 42834), ('\u{a755}', 42836), + ('\u{a757}', 42838), ('\u{a759}', 42840), ('\u{a75b}', 42842), ('\u{a75d}', 42844), + ('\u{a75f}', 42846), ('\u{a761}', 42848), ('\u{a763}', 42850), ('\u{a765}', 42852), + ('\u{a767}', 42854), ('\u{a769}', 42856), ('\u{a76b}', 42858), ('\u{a76d}', 42860), + ('\u{a76f}', 42862), ('\u{a77a}', 42873), ('\u{a77c}', 42875), ('\u{a77f}', 42878), + ('\u{a781}', 42880), ('\u{a783}', 42882), ('\u{a785}', 42884), ('\u{a787}', 42886), + ('\u{a78c}', 42891), ('\u{a791}', 42896), ('\u{a793}', 42898), ('\u{a794}', 42948), + ('\u{a797}', 42902), ('\u{a799}', 42904), ('\u{a79b}', 42906), ('\u{a79d}', 42908), + ('\u{a79f}', 42910), ('\u{a7a1}', 42912), ('\u{a7a3}', 42914), ('\u{a7a5}', 42916), + ('\u{a7a7}', 42918), ('\u{a7a9}', 42920), ('\u{a7b5}', 42932), ('\u{a7b7}', 42934), + ('\u{a7b9}', 42936), ('\u{a7bb}', 42938), ('\u{a7bd}', 42940), ('\u{a7bf}', 42942), + ('\u{a7c1}', 42944), ('\u{a7c3}', 42946), ('\u{a7c8}', 42951), ('\u{a7ca}', 42953), + ('\u{a7cd}', 42956), ('\u{a7d1}', 42960), ('\u{a7d7}', 42966), ('\u{a7d9}', 42968), + ('\u{a7db}', 42970), ('\u{a7f6}', 42997), ('\u{ab53}', 42931), ('\u{ab70}', 5024), + ('\u{ab71}', 5025), ('\u{ab72}', 5026), ('\u{ab73}', 5027), ('\u{ab74}', 5028), + ('\u{ab75}', 5029), ('\u{ab76}', 5030), ('\u{ab77}', 5031), ('\u{ab78}', 5032), + ('\u{ab79}', 5033), ('\u{ab7a}', 5034), ('\u{ab7b}', 5035), ('\u{ab7c}', 5036), + ('\u{ab7d}', 5037), ('\u{ab7e}', 5038), ('\u{ab7f}', 5039), ('\u{ab80}', 5040), + ('\u{ab81}', 5041), ('\u{ab82}', 5042), ('\u{ab83}', 5043), ('\u{ab84}', 5044), + ('\u{ab85}', 5045), ('\u{ab86}', 5046), ('\u{ab87}', 5047), ('\u{ab88}', 5048), + ('\u{ab89}', 5049), ('\u{ab8a}', 5050), ('\u{ab8b}', 5051), ('\u{ab8c}', 5052), + ('\u{ab8d}', 5053), ('\u{ab8e}', 5054), ('\u{ab8f}', 5055), ('\u{ab90}', 5056), + ('\u{ab91}', 5057), ('\u{ab92}', 5058), ('\u{ab93}', 5059), ('\u{ab94}', 5060), + ('\u{ab95}', 5061), ('\u{ab96}', 5062), ('\u{ab97}', 5063), ('\u{ab98}', 5064), + ('\u{ab99}', 5065), ('\u{ab9a}', 5066), ('\u{ab9b}', 5067), ('\u{ab9c}', 5068), + ('\u{ab9d}', 5069), ('\u{ab9e}', 5070), ('\u{ab9f}', 5071), ('\u{aba0}', 5072), + ('\u{aba1}', 5073), ('\u{aba2}', 5074), ('\u{aba3}', 5075), ('\u{aba4}', 5076), + ('\u{aba5}', 5077), ('\u{aba6}', 5078), ('\u{aba7}', 5079), ('\u{aba8}', 5080), + ('\u{aba9}', 5081), ('\u{abaa}', 5082), ('\u{abab}', 5083), ('\u{abac}', 5084), + ('\u{abad}', 5085), ('\u{abae}', 5086), ('\u{abaf}', 5087), ('\u{abb0}', 5088), + ('\u{abb1}', 5089), ('\u{abb2}', 5090), ('\u{abb3}', 5091), ('\u{abb4}', 5092), + ('\u{abb5}', 5093), ('\u{abb6}', 5094), ('\u{abb7}', 5095), ('\u{abb8}', 5096), + ('\u{abb9}', 5097), ('\u{abba}', 5098), ('\u{abbb}', 5099), ('\u{abbc}', 5100), + ('\u{abbd}', 5101), ('\u{abbe}', 5102), ('\u{abbf}', 5103), ('\u{fb00}', 4194394), + ('\u{fb01}', 4194395), ('\u{fb02}', 4194396), ('\u{fb03}', 4194397), ('\u{fb04}', 4194398), + ('\u{fb05}', 4194399), ('\u{fb06}', 4194400), ('\u{fb13}', 4194401), ('\u{fb14}', 4194402), + ('\u{fb15}', 4194403), ('\u{fb16}', 4194404), ('\u{fb17}', 4194405), ('\u{ff41}', 65313), + ('\u{ff42}', 65314), ('\u{ff43}', 65315), ('\u{ff44}', 65316), ('\u{ff45}', 65317), + ('\u{ff46}', 65318), ('\u{ff47}', 65319), ('\u{ff48}', 65320), ('\u{ff49}', 65321), + ('\u{ff4a}', 65322), ('\u{ff4b}', 65323), ('\u{ff4c}', 65324), ('\u{ff4d}', 65325), + ('\u{ff4e}', 65326), ('\u{ff4f}', 65327), ('\u{ff50}', 65328), ('\u{ff51}', 65329), + ('\u{ff52}', 65330), ('\u{ff53}', 65331), ('\u{ff54}', 65332), ('\u{ff55}', 65333), + ('\u{ff56}', 65334), ('\u{ff57}', 65335), ('\u{ff58}', 65336), ('\u{ff59}', 65337), + ('\u{ff5a}', 65338), ('\u{10428}', 66560), ('\u{10429}', 66561), ('\u{1042a}', 66562), + ('\u{1042b}', 66563), ('\u{1042c}', 66564), ('\u{1042d}', 66565), ('\u{1042e}', 66566), + ('\u{1042f}', 66567), ('\u{10430}', 66568), ('\u{10431}', 66569), ('\u{10432}', 66570), + ('\u{10433}', 66571), ('\u{10434}', 66572), ('\u{10435}', 66573), ('\u{10436}', 66574), + ('\u{10437}', 66575), ('\u{10438}', 66576), ('\u{10439}', 66577), ('\u{1043a}', 66578), + ('\u{1043b}', 66579), ('\u{1043c}', 66580), ('\u{1043d}', 66581), ('\u{1043e}', 66582), + ('\u{1043f}', 66583), ('\u{10440}', 66584), ('\u{10441}', 66585), ('\u{10442}', 66586), + ('\u{10443}', 66587), ('\u{10444}', 66588), ('\u{10445}', 66589), ('\u{10446}', 66590), + ('\u{10447}', 66591), ('\u{10448}', 66592), ('\u{10449}', 66593), ('\u{1044a}', 66594), + ('\u{1044b}', 66595), ('\u{1044c}', 66596), ('\u{1044d}', 66597), ('\u{1044e}', 66598), + ('\u{1044f}', 66599), ('\u{104d8}', 66736), ('\u{104d9}', 66737), ('\u{104da}', 66738), + ('\u{104db}', 66739), ('\u{104dc}', 66740), ('\u{104dd}', 66741), ('\u{104de}', 66742), + ('\u{104df}', 66743), ('\u{104e0}', 66744), ('\u{104e1}', 66745), ('\u{104e2}', 66746), + ('\u{104e3}', 66747), ('\u{104e4}', 66748), ('\u{104e5}', 66749), ('\u{104e6}', 66750), + ('\u{104e7}', 66751), ('\u{104e8}', 66752), ('\u{104e9}', 66753), ('\u{104ea}', 66754), + ('\u{104eb}', 66755), ('\u{104ec}', 66756), ('\u{104ed}', 66757), ('\u{104ee}', 66758), + ('\u{104ef}', 66759), ('\u{104f0}', 66760), ('\u{104f1}', 66761), ('\u{104f2}', 66762), + ('\u{104f3}', 66763), ('\u{104f4}', 66764), ('\u{104f5}', 66765), ('\u{104f6}', 66766), + ('\u{104f7}', 66767), ('\u{104f8}', 66768), ('\u{104f9}', 66769), ('\u{104fa}', 66770), + ('\u{104fb}', 66771), ('\u{10597}', 66928), ('\u{10598}', 66929), ('\u{10599}', 66930), + ('\u{1059a}', 66931), ('\u{1059b}', 66932), ('\u{1059c}', 66933), ('\u{1059d}', 66934), + ('\u{1059e}', 66935), ('\u{1059f}', 66936), ('\u{105a0}', 66937), ('\u{105a1}', 66938), + ('\u{105a3}', 66940), ('\u{105a4}', 66941), ('\u{105a5}', 66942), ('\u{105a6}', 66943), + ('\u{105a7}', 66944), ('\u{105a8}', 66945), ('\u{105a9}', 66946), ('\u{105aa}', 66947), + ('\u{105ab}', 66948), ('\u{105ac}', 66949), ('\u{105ad}', 66950), ('\u{105ae}', 66951), + ('\u{105af}', 66952), ('\u{105b0}', 66953), ('\u{105b1}', 66954), ('\u{105b3}', 66956), + ('\u{105b4}', 66957), ('\u{105b5}', 66958), ('\u{105b6}', 66959), ('\u{105b7}', 66960), + ('\u{105b8}', 66961), ('\u{105b9}', 66962), ('\u{105bb}', 66964), ('\u{105bc}', 66965), + ('\u{10cc0}', 68736), ('\u{10cc1}', 68737), ('\u{10cc2}', 68738), ('\u{10cc3}', 68739), + ('\u{10cc4}', 68740), ('\u{10cc5}', 68741), ('\u{10cc6}', 68742), ('\u{10cc7}', 68743), + ('\u{10cc8}', 68744), ('\u{10cc9}', 68745), ('\u{10cca}', 68746), ('\u{10ccb}', 68747), + ('\u{10ccc}', 68748), ('\u{10ccd}', 68749), ('\u{10cce}', 68750), ('\u{10ccf}', 68751), + ('\u{10cd0}', 68752), ('\u{10cd1}', 68753), ('\u{10cd2}', 68754), ('\u{10cd3}', 68755), + ('\u{10cd4}', 68756), ('\u{10cd5}', 68757), ('\u{10cd6}', 68758), ('\u{10cd7}', 68759), + ('\u{10cd8}', 68760), ('\u{10cd9}', 68761), ('\u{10cda}', 68762), ('\u{10cdb}', 68763), + ('\u{10cdc}', 68764), ('\u{10cdd}', 68765), ('\u{10cde}', 68766), ('\u{10cdf}', 68767), + ('\u{10ce0}', 68768), ('\u{10ce1}', 68769), ('\u{10ce2}', 68770), ('\u{10ce3}', 68771), + ('\u{10ce4}', 68772), ('\u{10ce5}', 68773), ('\u{10ce6}', 68774), ('\u{10ce7}', 68775), + ('\u{10ce8}', 68776), ('\u{10ce9}', 68777), ('\u{10cea}', 68778), ('\u{10ceb}', 68779), + ('\u{10cec}', 68780), ('\u{10ced}', 68781), ('\u{10cee}', 68782), ('\u{10cef}', 68783), + ('\u{10cf0}', 68784), ('\u{10cf1}', 68785), ('\u{10cf2}', 68786), ('\u{10d70}', 68944), + ('\u{10d71}', 68945), ('\u{10d72}', 68946), ('\u{10d73}', 68947), ('\u{10d74}', 68948), + ('\u{10d75}', 68949), ('\u{10d76}', 68950), ('\u{10d77}', 68951), ('\u{10d78}', 68952), + ('\u{10d79}', 68953), ('\u{10d7a}', 68954), ('\u{10d7b}', 68955), ('\u{10d7c}', 68956), + ('\u{10d7d}', 68957), ('\u{10d7e}', 68958), ('\u{10d7f}', 68959), ('\u{10d80}', 68960), + ('\u{10d81}', 68961), ('\u{10d82}', 68962), ('\u{10d83}', 68963), ('\u{10d84}', 68964), + ('\u{10d85}', 68965), ('\u{118c0}', 71840), ('\u{118c1}', 71841), ('\u{118c2}', 71842), + ('\u{118c3}', 71843), ('\u{118c4}', 71844), ('\u{118c5}', 71845), ('\u{118c6}', 71846), + ('\u{118c7}', 71847), ('\u{118c8}', 71848), ('\u{118c9}', 71849), ('\u{118ca}', 71850), + ('\u{118cb}', 71851), ('\u{118cc}', 71852), ('\u{118cd}', 71853), ('\u{118ce}', 71854), + ('\u{118cf}', 71855), ('\u{118d0}', 71856), ('\u{118d1}', 71857), ('\u{118d2}', 71858), + ('\u{118d3}', 71859), ('\u{118d4}', 71860), ('\u{118d5}', 71861), ('\u{118d6}', 71862), + ('\u{118d7}', 71863), ('\u{118d8}', 71864), ('\u{118d9}', 71865), ('\u{118da}', 71866), + ('\u{118db}', 71867), ('\u{118dc}', 71868), ('\u{118dd}', 71869), ('\u{118de}', 71870), + ('\u{118df}', 71871), ('\u{16e60}', 93760), ('\u{16e61}', 93761), ('\u{16e62}', 93762), + ('\u{16e63}', 93763), ('\u{16e64}', 93764), ('\u{16e65}', 93765), ('\u{16e66}', 93766), + ('\u{16e67}', 93767), ('\u{16e68}', 93768), ('\u{16e69}', 93769), ('\u{16e6a}', 93770), + ('\u{16e6b}', 93771), ('\u{16e6c}', 93772), ('\u{16e6d}', 93773), ('\u{16e6e}', 93774), + ('\u{16e6f}', 93775), ('\u{16e70}', 93776), ('\u{16e71}', 93777), ('\u{16e72}', 93778), + ('\u{16e73}', 93779), ('\u{16e74}', 93780), ('\u{16e75}', 93781), ('\u{16e76}', 93782), + ('\u{16e77}', 93783), ('\u{16e78}', 93784), ('\u{16e79}', 93785), ('\u{16e7a}', 93786), + ('\u{16e7b}', 93787), ('\u{16e7c}', 93788), ('\u{16e7d}', 93789), ('\u{16e7e}', 93790), + ('\u{16e7f}', 93791), ('\u{1e922}', 125184), ('\u{1e923}', 125185), ('\u{1e924}', 125186), + ('\u{1e925}', 125187), ('\u{1e926}', 125188), ('\u{1e927}', 125189), ('\u{1e928}', 125190), + ('\u{1e929}', 125191), ('\u{1e92a}', 125192), ('\u{1e92b}', 125193), ('\u{1e92c}', 125194), + ('\u{1e92d}', 125195), ('\u{1e92e}', 125196), ('\u{1e92f}', 125197), ('\u{1e930}', 125198), + ('\u{1e931}', 125199), ('\u{1e932}', 125200), ('\u{1e933}', 125201), ('\u{1e934}', 125202), + ('\u{1e935}', 125203), ('\u{1e936}', 125204), ('\u{1e937}', 125205), ('\u{1e938}', 125206), + ('\u{1e939}', 125207), ('\u{1e93a}', 125208), ('\u{1e93b}', 125209), ('\u{1e93c}', 125210), + ('\u{1e93d}', 125211), ('\u{1e93e}', 125212), ('\u{1e93f}', 125213), ('\u{1e940}', 125214), + ('\u{1e941}', 125215), ('\u{1e942}', 125216), ('\u{1e943}', 125217), ]; static UPPERCASE_TABLE_MULTI: &[[char; 3]] = &[ From c8d9bd488a17e71c78f1e982ad1a3a3d921cd76e Mon Sep 17 00:00:00 2001 From: Marcondiro <46560192+Marcondiro@users.noreply.github.com> Date: Tue, 10 Sep 2024 11:13:35 +0200 Subject: [PATCH 0789/2194] Bump unicode printable to version 16.0.0 --- library/core/src/unicode/printable.rs | 130 +++++++++++++++----------- 1 file changed, 73 insertions(+), 57 deletions(-) diff --git a/library/core/src/unicode/printable.rs b/library/core/src/unicode/printable.rs index 33c3ef8083de5..d8fb50e4ed296 100644 --- a/library/core/src/unicode/printable.rs +++ b/library/core/src/unicode/printable.rs @@ -118,7 +118,7 @@ const SINGLETONS0U: &[(u8, u8)] = &[ (0x30, 4), (0x31, 2), (0x32, 1), - (0xa7, 2), + (0xa7, 4), (0xa9, 2), (0xaa, 4), (0xab, 8), @@ -155,17 +155,18 @@ const SINGLETONS0L: &[u8] = &[ 0x11, 0x16, 0x17, 0x5b, 0x5c, 0xf6, 0xf7, 0xfe, 0xff, 0x80, 0x6d, 0x71, 0xde, 0xdf, 0x0e, 0x1f, 0x6e, 0x6f, 0x1c, 0x1d, 0x5f, 0x7d, 0x7e, 0xae, - 0xaf, 0x7f, 0xbb, 0xbc, 0x16, 0x17, 0x1e, 0x1f, + 0xaf, 0x4d, 0xbb, 0xbc, 0x16, 0x17, 0x1e, 0x1f, 0x46, 0x47, 0x4e, 0x4f, 0x58, 0x5a, 0x5c, 0x5e, 0x7e, 0x7f, 0xb5, 0xc5, 0xd4, 0xd5, 0xdc, 0xf0, 0xf1, 0xf5, 0x72, 0x73, 0x8f, 0x74, 0x75, 0x96, 0x26, 0x2e, 0x2f, 0xa7, 0xaf, 0xb7, 0xbf, 0xc7, 0xcf, 0xd7, 0xdf, 0x9a, 0x00, 0x40, 0x97, 0x98, - 0x30, 0x8f, 0x1f, 0xd2, 0xd4, 0xce, 0xff, 0x4e, - 0x4f, 0x5a, 0x5b, 0x07, 0x08, 0x0f, 0x10, 0x27, - 0x2f, 0xee, 0xef, 0x6e, 0x6f, 0x37, 0x3d, 0x3f, - 0x42, 0x45, 0x90, 0x91, 0x53, 0x67, 0x75, 0xc8, - 0xc9, 0xd0, 0xd1, 0xd8, 0xd9, 0xe7, 0xfe, 0xff, + 0x30, 0x8f, 0x1f, 0xce, 0xcf, 0xd2, 0xd4, 0xce, + 0xff, 0x4e, 0x4f, 0x5a, 0x5b, 0x07, 0x08, 0x0f, + 0x10, 0x27, 0x2f, 0xee, 0xef, 0x6e, 0x6f, 0x37, + 0x3d, 0x3f, 0x42, 0x45, 0x90, 0x91, 0x53, 0x67, + 0x75, 0xc8, 0xc9, 0xd0, 0xd1, 0xd8, 0xd9, 0xe7, + 0xfe, 0xff, ]; #[rustfmt::skip] const SINGLETONS1U: &[(u8, u8)] = &[ @@ -183,7 +184,7 @@ const SINGLETONS1U: &[(u8, u8)] = &[ (0x10, 1), (0x11, 2), (0x12, 5), - (0x13, 17), + (0x13, 28), (0x14, 1), (0x15, 2), (0x17, 2), @@ -211,7 +212,7 @@ const SINGLETONS1U: &[(u8, u8)] = &[ (0xee, 32), (0xf0, 4), (0xf8, 2), - (0xfa, 3), + (0xfa, 4), (0xfb, 1), ]; #[rustfmt::skip] @@ -224,23 +225,24 @@ const SINGLETONS1L: &[u8] = &[ 0xbd, 0x35, 0xe0, 0x12, 0x87, 0x89, 0x8e, 0x9e, 0x04, 0x0d, 0x0e, 0x11, 0x12, 0x29, 0x31, 0x34, 0x3a, 0x45, 0x46, 0x49, 0x4a, 0x4e, 0x4f, 0x64, - 0x65, 0x5c, 0xb6, 0xb7, 0x1b, 0x1c, 0x07, 0x08, - 0x0a, 0x0b, 0x14, 0x17, 0x36, 0x39, 0x3a, 0xa8, - 0xa9, 0xd8, 0xd9, 0x09, 0x37, 0x90, 0x91, 0xa8, - 0x07, 0x0a, 0x3b, 0x3e, 0x66, 0x69, 0x8f, 0x92, - 0x11, 0x6f, 0x5f, 0xbf, 0xee, 0xef, 0x5a, 0x62, - 0xf4, 0xfc, 0xff, 0x53, 0x54, 0x9a, 0x9b, 0x2e, - 0x2f, 0x27, 0x28, 0x55, 0x9d, 0xa0, 0xa1, 0xa3, - 0xa4, 0xa7, 0xa8, 0xad, 0xba, 0xbc, 0xc4, 0x06, - 0x0b, 0x0c, 0x15, 0x1d, 0x3a, 0x3f, 0x45, 0x51, - 0xa6, 0xa7, 0xcc, 0xcd, 0xa0, 0x07, 0x19, 0x1a, - 0x22, 0x25, 0x3e, 0x3f, 0xe7, 0xec, 0xef, 0xff, - 0xc5, 0xc6, 0x04, 0x20, 0x23, 0x25, 0x26, 0x28, - 0x33, 0x38, 0x3a, 0x48, 0x4a, 0x4c, 0x50, 0x53, - 0x55, 0x56, 0x58, 0x5a, 0x5c, 0x5e, 0x60, 0x63, - 0x65, 0x66, 0x6b, 0x73, 0x78, 0x7d, 0x7f, 0x8a, - 0xa4, 0xaa, 0xaf, 0xb0, 0xc0, 0xd0, 0xae, 0xaf, - 0x6e, 0x6f, 0xbe, 0x93, + 0x65, 0x8a, 0x8c, 0x8d, 0x8f, 0xb6, 0xc1, 0xc3, + 0xc4, 0xc6, 0xcb, 0xd6, 0x5c, 0xb6, 0xb7, 0x1b, + 0x1c, 0x07, 0x08, 0x0a, 0x0b, 0x14, 0x17, 0x36, + 0x39, 0x3a, 0xa8, 0xa9, 0xd8, 0xd9, 0x09, 0x37, + 0x90, 0x91, 0xa8, 0x07, 0x0a, 0x3b, 0x3e, 0x66, + 0x69, 0x8f, 0x92, 0x11, 0x6f, 0x5f, 0xbf, 0xee, + 0xef, 0x5a, 0x62, 0xf4, 0xfc, 0xff, 0x53, 0x54, + 0x9a, 0x9b, 0x2e, 0x2f, 0x27, 0x28, 0x55, 0x9d, + 0xa0, 0xa1, 0xa3, 0xa4, 0xa7, 0xa8, 0xad, 0xba, + 0xbc, 0xc4, 0x06, 0x0b, 0x0c, 0x15, 0x1d, 0x3a, + 0x3f, 0x45, 0x51, 0xa6, 0xa7, 0xcc, 0xcd, 0xa0, + 0x07, 0x19, 0x1a, 0x22, 0x25, 0x3e, 0x3f, 0xe7, + 0xec, 0xef, 0xff, 0xc5, 0xc6, 0x04, 0x20, 0x23, + 0x25, 0x26, 0x28, 0x33, 0x38, 0x3a, 0x48, 0x4a, + 0x4c, 0x50, 0x53, 0x55, 0x56, 0x58, 0x5a, 0x5c, + 0x5e, 0x60, 0x63, 0x65, 0x66, 0x6b, 0x73, 0x78, + 0x7d, 0x7f, 0x8a, 0xa4, 0xaa, 0xaf, 0xb0, 0xc0, + 0xd0, 0xae, 0xaf, 0x6e, 0x6f, 0xdd, 0xde, 0x93, ]; #[rustfmt::skip] const NORMAL0: &[u8] = &[ @@ -252,8 +254,8 @@ const NORMAL0: &[u8] = &[ 0x06, 0x11, 0x81, 0xac, 0x0e, 0x80, 0xab, 0x05, - 0x1f, 0x09, - 0x81, 0x1b, 0x03, + 0x1f, 0x08, + 0x81, 0x1c, 0x03, 0x19, 0x08, 0x01, 0x04, 0x2f, 0x04, @@ -318,11 +320,10 @@ const NORMAL0: &[u8] = &[ 0x80, 0xac, 0x06, 0x0a, 0x06, 0x2f, 0x31, - 0x4d, 0x03, - 0x80, 0xa4, 0x08, + 0x80, 0xf4, 0x08, 0x3c, 0x03, 0x0f, 0x03, - 0x3c, 0x07, + 0x3e, 0x05, 0x38, 0x08, 0x2b, 0x05, 0x82, 0xff, 0x11, @@ -332,7 +333,7 @@ const NORMAL0: &[u8] = &[ 0x21, 0x0f, 0x21, 0x0f, 0x80, 0x8c, 0x04, - 0x82, 0x97, 0x19, + 0x82, 0x9a, 0x16, 0x0b, 0x15, 0x88, 0x94, 0x05, 0x2f, 0x05, @@ -343,13 +344,12 @@ const NORMAL0: &[u8] = &[ 0x74, 0x0c, 0x80, 0xd6, 0x1a, 0x81, 0x10, 0x05, - 0x80, 0xdf, 0x0b, + 0x80, 0xe1, 0x09, 0xf2, 0x9e, 0x03, 0x37, 0x09, 0x81, 0x5c, 0x14, 0x80, 0xb8, 0x08, - 0x80, 0xcb, 0x05, - 0x0a, 0x18, + 0x80, 0xdd, 0x15, 0x3b, 0x03, 0x0a, 0x06, 0x38, 0x08, @@ -402,7 +402,8 @@ const NORMAL1: &[u8] = &[ 0x24, 0x04, 0x28, 0x08, 0x34, 0x0b, - 0x4e, 0x43, + 0x4e, 0x03, + 0x34, 0x0c, 0x81, 0x37, 0x09, 0x16, 0x0a, 0x08, 0x18, @@ -431,9 +432,13 @@ const NORMAL1: &[u8] = &[ 0x33, 0x0d, 0x33, 0x07, 0x2e, 0x08, - 0x0a, 0x81, 0x26, - 0x52, 0x4b, - 0x2b, 0x08, + 0x0a, 0x06, + 0x26, 0x03, + 0x1d, 0x08, + 0x02, 0x80, 0xd0, + 0x52, 0x10, + 0x03, 0x37, + 0x2c, 0x08, 0x2a, 0x16, 0x1a, 0x26, 0x1c, 0x14, @@ -453,7 +458,9 @@ const NORMAL1: &[u8] = &[ 0x51, 0x06, 0x01, 0x05, 0x10, 0x03, - 0x05, 0x80, 0x8b, + 0x05, 0x0b, + 0x59, 0x08, + 0x02, 0x1d, 0x62, 0x1e, 0x48, 0x08, 0x0a, 0x80, 0xa6, @@ -462,7 +469,8 @@ const NORMAL1: &[u8] = &[ 0x0a, 0x06, 0x0d, 0x13, 0x3a, 0x06, - 0x0a, 0x36, + 0x0a, 0x06, + 0x14, 0x1c, 0x2c, 0x04, 0x17, 0x80, 0xb9, 0x3c, 0x64, @@ -473,7 +481,9 @@ const NORMAL1: &[u8] = &[ 0x48, 0x08, 0x53, 0x0d, 0x49, 0x07, - 0x0a, 0x80, 0xf6, + 0x0a, 0x80, 0xb6, + 0x22, 0x0e, + 0x0a, 0x06, 0x46, 0x0a, 0x1d, 0x03, 0x47, 0x49, @@ -484,7 +494,7 @@ const NORMAL1: &[u8] = &[ 0x0a, 0x81, 0x36, 0x19, 0x07, 0x3b, 0x03, - 0x1c, 0x56, + 0x1d, 0x55, 0x01, 0x0f, 0x32, 0x0d, 0x83, 0x9b, 0x66, @@ -492,15 +502,18 @@ const NORMAL1: &[u8] = &[ 0x80, 0xc4, 0x8a, 0x4c, 0x63, 0x0d, 0x84, 0x30, 0x10, - 0x16, 0x8f, 0xaa, - 0x82, 0x47, 0xa1, 0xb9, + 0x16, 0x0a, + 0x8f, 0x9b, 0x05, + 0x82, 0x47, 0x9a, 0xb9, + 0x3a, 0x86, 0xc6, 0x82, 0x39, 0x07, 0x2a, 0x04, 0x5c, 0x06, 0x26, 0x0a, 0x46, 0x0a, 0x28, 0x05, - 0x13, 0x82, 0xb0, + 0x13, 0x81, 0xb0, + 0x3a, 0x80, 0xc6, 0x5b, 0x65, 0x4b, 0x04, 0x39, 0x07, @@ -508,8 +521,8 @@ const NORMAL1: &[u8] = &[ 0x05, 0x0b, 0x02, 0x0e, 0x97, 0xf8, 0x08, - 0x84, 0xd6, 0x2a, - 0x09, 0xa2, 0xe7, + 0x84, 0xd6, 0x29, + 0x0a, 0xa2, 0xe7, 0x81, 0x33, 0x0f, 0x01, 0x1d, 0x06, 0x0e, @@ -518,7 +531,9 @@ const NORMAL1: &[u8] = &[ 0x6b, 0x05, 0x0d, 0x03, 0x09, 0x07, - 0x10, 0x92, 0x60, + 0x10, 0x8f, 0x60, + 0x80, 0xfa, 0x06, + 0x81, 0xb4, 0x4c, 0x47, 0x09, 0x74, 0x3c, 0x80, 0xf6, 0x0a, @@ -543,7 +558,9 @@ const NORMAL1: &[u8] = &[ 0x1f, 0x11, 0x3a, 0x05, 0x01, 0x81, 0xd0, - 0x2a, 0x82, 0xe6, + 0x2a, 0x80, 0xd6, + 0x2b, 0x04, + 0x01, 0x81, 0xe0, 0x80, 0xf7, 0x29, 0x4c, 0x04, 0x0a, 0x04, @@ -575,14 +592,13 @@ const NORMAL1: &[u8] = &[ 0x38, 0x08, 0x0a, 0x06, 0x28, 0x08, - 0x22, 0x4e, + 0x2c, 0x04, + 0x02, 0x3e, 0x81, 0x54, 0x0c, 0x1d, 0x03, + 0x0a, 0x05, + 0x38, 0x07, + 0x1c, 0x06, 0x09, 0x07, - 0x36, 0x08, - 0x0e, 0x04, - 0x09, 0x07, - 0x09, 0x07, - 0x80, 0xcb, 0x25, - 0x0a, 0x84, 0x06, + 0x80, 0xfa, 0x84, 0x06, ]; From 96d545a33bb6dc4ed3c1c80b997cce2035c571a6 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Tue, 10 Sep 2024 20:16:43 +1000 Subject: [PATCH 0790/2194] coverage: Avoid referring to "coverage spans" in counter creation The counter-creation code needs to know which BCB nodes require counters, but isn't interested in why, so treat that as an opaque detail. --- .../src/coverage/counters.rs | 43 +++++++------------ 1 file changed, 15 insertions(+), 28 deletions(-) diff --git a/compiler/rustc_mir_transform/src/coverage/counters.rs b/compiler/rustc_mir_transform/src/coverage/counters.rs index ea1c0d2df4517..c9eceff9b507b 100644 --- a/compiler/rustc_mir_transform/src/coverage/counters.rs +++ b/compiler/rustc_mir_transform/src/coverage/counters.rs @@ -74,12 +74,11 @@ pub(super) struct CoverageCounters { } impl CoverageCounters { - /// Makes [`BcbCounter`] `Counter`s and `Expressions` for the `BasicCoverageBlock`s directly or - /// indirectly associated with coverage spans, and accumulates additional `Expression`s - /// representing intermediate values. + /// Ensures that each BCB node needing a counter has one, by creating physical + /// counters or counter expressions for nodes and edges as required. pub(super) fn make_bcb_counters( basic_coverage_blocks: &CoverageGraph, - bcb_has_coverage_spans: impl Fn(BasicCoverageBlock) -> bool, + bcb_needs_counter: impl Fn(BasicCoverageBlock) -> bool, ) -> Self { let num_bcbs = basic_coverage_blocks.num_nodes(); @@ -91,8 +90,7 @@ impl CoverageCounters { expressions_memo: FxHashMap::default(), }; - MakeBcbCounters::new(&mut this, basic_coverage_blocks) - .make_bcb_counters(bcb_has_coverage_spans); + MakeBcbCounters::new(&mut this, basic_coverage_blocks).make_bcb_counters(bcb_needs_counter); this } @@ -241,10 +239,7 @@ impl CoverageCounters { } } -/// Traverse the `CoverageGraph` and add either a `Counter` or `Expression` to every BCB, to be -/// injected with coverage spans. `Expressions` have no runtime overhead, so if a viable expression -/// (adding or subtracting two other counters or expressions) can compute the same result as an -/// embedded counter, an `Expression` should be used. +/// Helper struct that allows counter creation to inspect the BCB graph. struct MakeBcbCounters<'a> { coverage_counters: &'a mut CoverageCounters, basic_coverage_blocks: &'a CoverageGraph, @@ -264,30 +259,21 @@ impl<'a> MakeBcbCounters<'a> { /// One way to predict which branch executes the least is by considering loops. A loop is exited /// at a branch, so the branch that jumps to a `BasicCoverageBlock` outside the loop is almost /// always executed less than the branch that does not exit the loop. - fn make_bcb_counters(&mut self, bcb_has_coverage_spans: impl Fn(BasicCoverageBlock) -> bool) { + fn make_bcb_counters(&mut self, bcb_needs_counter: impl Fn(BasicCoverageBlock) -> bool) { debug!("make_bcb_counters(): adding a counter or expression to each BasicCoverageBlock"); - // Walk the `CoverageGraph`. For each `BasicCoverageBlock` node with an associated - // coverage span, add a counter. If the `BasicCoverageBlock` branches, add a counter or - // expression to each branch `BasicCoverageBlock` (if the branch BCB has only one incoming - // edge) or edge from the branching BCB to the branch BCB (if the branch BCB has multiple - // incoming edges). + // Traverse the coverage graph, ensuring that every node that needs a + // coverage counter has one. // - // The `TraverseCoverageGraphWithLoops` traversal ensures that, when a loop is encountered, - // all `BasicCoverageBlock` nodes in the loop are visited before visiting any node outside - // the loop. The `traversal` state includes a `context_stack`, providing a way to know if - // the current BCB is in one or more nested loops or not. + // The traversal tries to ensure that, when a loop is encountered, all + // nodes within the loop are visited before visiting any nodes outside + // the loop. It also keeps track of which loop(s) the traversal is + // currently inside. let mut traversal = TraverseCoverageGraphWithLoops::new(self.basic_coverage_blocks); while let Some(bcb) = traversal.next() { - if bcb_has_coverage_spans(bcb) { - debug!("{:?} has at least one coverage span. Get or make its counter", bcb); + let _span = debug_span!("traversal", ?bcb).entered(); + if bcb_needs_counter(bcb) { self.make_node_and_branch_counters(&traversal, bcb); - } else { - debug!( - "{:?} does not have any coverage spans. A counter will only be added if \ - and when a covered BCB has an expression dependency.", - bcb, - ); } } @@ -298,6 +284,7 @@ impl<'a> MakeBcbCounters<'a> { ); } + #[instrument(level = "debug", skip(self, traversal))] fn make_node_and_branch_counters( &mut self, traversal: &TraverseCoverageGraphWithLoops<'_>, From 8be70c7b2c88be04e07adcf0c2dafbd0e8a6d70f Mon Sep 17 00:00:00 2001 From: Zalathar Date: Tue, 10 Sep 2024 20:44:15 +1000 Subject: [PATCH 0791/2194] coverage: Avoid referring to out-edges as "branches" This makes the graph terminology a bit more consistent, and avoids potential confusion with branch coverage. --- .../src/coverage/counters.rs | 177 ++++++++---------- 1 file changed, 80 insertions(+), 97 deletions(-) diff --git a/compiler/rustc_mir_transform/src/coverage/counters.rs b/compiler/rustc_mir_transform/src/coverage/counters.rs index c9eceff9b507b..f55d6cf8efc71 100644 --- a/compiler/rustc_mir_transform/src/coverage/counters.rs +++ b/compiler/rustc_mir_transform/src/coverage/counters.rs @@ -253,12 +253,6 @@ impl<'a> MakeBcbCounters<'a> { Self { coverage_counters, basic_coverage_blocks } } - /// If two `BasicCoverageBlock`s branch from another `BasicCoverageBlock`, one of the branches - /// can be counted by `Expression` by subtracting the other branch from the branching - /// block. Otherwise, the `BasicCoverageBlock` executed the least should have the `Counter`. - /// One way to predict which branch executes the least is by considering loops. A loop is exited - /// at a branch, so the branch that jumps to a `BasicCoverageBlock` outside the loop is almost - /// always executed less than the branch that does not exit the loop. fn make_bcb_counters(&mut self, bcb_needs_counter: impl Fn(BasicCoverageBlock) -> bool) { debug!("make_bcb_counters(): adding a counter or expression to each BasicCoverageBlock"); @@ -273,7 +267,7 @@ impl<'a> MakeBcbCounters<'a> { while let Some(bcb) = traversal.next() { let _span = debug_span!("traversal", ?bcb).entered(); if bcb_needs_counter(bcb) { - self.make_node_and_branch_counters(&traversal, bcb); + self.make_node_counter_and_out_edge_counters(&traversal, bcb); } } @@ -284,74 +278,66 @@ impl<'a> MakeBcbCounters<'a> { ); } + /// Make sure the given node has a node counter, and then make sure each of + /// its out-edges has an edge counter (if appropriate). #[instrument(level = "debug", skip(self, traversal))] - fn make_node_and_branch_counters( + fn make_node_counter_and_out_edge_counters( &mut self, traversal: &TraverseCoverageGraphWithLoops<'_>, from_bcb: BasicCoverageBlock, ) { // First, ensure that this node has a counter of some kind. - // We might also use its term later to compute one of the branch counters. + // We might also use that counter to compute one of the out-edge counters. let from_bcb_operand = self.get_or_make_counter_operand(from_bcb); - let branch_target_bcbs = self.basic_coverage_blocks.successors[from_bcb].as_slice(); + let successors = self.basic_coverage_blocks.successors[from_bcb].as_slice(); // If this node doesn't have multiple out-edges, or all of its out-edges // already have counters, then we don't need to create edge counters. - let needs_branch_counters = branch_target_bcbs.len() > 1 - && branch_target_bcbs - .iter() - .any(|&to_bcb| self.branch_has_no_counter(from_bcb, to_bcb)); - if !needs_branch_counters { + let needs_out_edge_counters = successors.len() > 1 + && successors.iter().any(|&to_bcb| self.edge_has_no_counter(from_bcb, to_bcb)); + if !needs_out_edge_counters { return; } - debug!( - "{from_bcb:?} has some branch(es) without counters:\n {}", - branch_target_bcbs - .iter() - .map(|&to_bcb| { - format!("{from_bcb:?}->{to_bcb:?}: {:?}", self.branch_counter(from_bcb, to_bcb)) - }) - .collect::>() - .join("\n "), - ); + if tracing::enabled!(tracing::Level::DEBUG) { + let _span = + debug_span!("node has some out-edges without counters", ?from_bcb).entered(); + for &to_bcb in successors { + debug!(?to_bcb, counter=?self.edge_counter(from_bcb, to_bcb)); + } + } - // Of the branch edges that don't have counters yet, one can be given an expression - // (computed from the other edges) instead of a dedicated counter. - let expression_to_bcb = self.choose_preferred_expression_branch(traversal, from_bcb); + // Of the out-edges that don't have counters yet, one can be given an expression + // (computed from the other out-edges) instead of a dedicated counter. + let expression_to_bcb = self.choose_out_edge_for_expression(traversal, from_bcb); - // For each branch arm other than the one that was chosen to get an expression, + // For each out-edge other than the one that was chosen to get an expression, // ensure that it has a counter (existing counter/expression or a new counter), - // and accumulate the corresponding terms into a single sum term. - let sum_of_all_other_branches: BcbCounter = { - let _span = debug_span!("sum_of_all_other_branches", ?expression_to_bcb).entered(); - branch_target_bcbs + // and accumulate the corresponding counters into a single sum expression. + let sum_of_all_other_out_edges: BcbCounter = { + let _span = debug_span!("sum_of_all_other_out_edges", ?expression_to_bcb).entered(); + successors .iter() .copied() - // Skip the chosen branch, since we'll calculate it from the other branches. + // Skip the chosen edge, since we'll calculate its count from this sum. .filter(|&to_bcb| to_bcb != expression_to_bcb) .fold(None, |accum, to_bcb| { let _span = debug_span!("to_bcb", ?accum, ?to_bcb).entered(); - let branch_counter = self.get_or_make_edge_counter_operand(from_bcb, to_bcb); - Some(self.coverage_counters.make_sum_expression(accum, branch_counter)) + let edge_counter = self.get_or_make_edge_counter_operand(from_bcb, to_bcb); + Some(self.coverage_counters.make_sum_expression(accum, edge_counter)) }) - .expect("there must be at least one other branch") + .expect("there must be at least one other out-edge") }; - // For the branch that was chosen to get an expression, create that expression - // by taking the count of the node we're branching from, and subtracting the - // sum of all the other branches. - debug!( - "Making an expression for the selected expression_branch: \ - {expression_to_bcb:?} (expression_branch predecessors: {:?})", - self.bcb_predecessors(expression_to_bcb), - ); + // Now create an expression for the chosen edge, by taking the counter + // for its source node and subtracting the sum of its sibling out-edges. let expression = self.coverage_counters.make_expression( from_bcb_operand, Op::Subtract, - sum_of_all_other_branches, + sum_of_all_other_out_edges, ); + debug!("{expression_to_bcb:?} gets an expression: {expression:?}"); if self.basic_coverage_blocks.bcb_has_multiple_in_edges(expression_to_bcb) { self.coverage_counters.set_bcb_edge_counter(from_bcb, expression_to_bcb, expression); @@ -442,82 +428,79 @@ impl<'a> MakeBcbCounters<'a> { self.coverage_counters.set_bcb_edge_counter(from_bcb, to_bcb, counter_kind) } - /// Select a branch for the expression, either the recommended `reloop_branch`, or if none was - /// found, select any branch. - fn choose_preferred_expression_branch( + /// Choose one of the out-edges of `from_bcb` to receive an expression + /// instead of a physical counter, and returns that edge's target node. + /// + /// - Precondition: The node must have at least one out-edge without a counter. + /// - Postcondition: The selected edge does not have an edge counter. + fn choose_out_edge_for_expression( &self, traversal: &TraverseCoverageGraphWithLoops<'_>, from_bcb: BasicCoverageBlock, ) -> BasicCoverageBlock { - let good_reloop_branch = self.find_good_reloop_branch(traversal, from_bcb); - if let Some(reloop_target) = good_reloop_branch { - assert!(self.branch_has_no_counter(from_bcb, reloop_target)); + if let Some(reloop_target) = self.find_good_reloop_edge(traversal, from_bcb) { + assert!(self.edge_has_no_counter(from_bcb, reloop_target)); debug!("Selecting reloop target {reloop_target:?} to get an expression"); - reloop_target - } else { - let &branch_without_counter = self - .bcb_successors(from_bcb) - .iter() - .find(|&&to_bcb| self.branch_has_no_counter(from_bcb, to_bcb)) - .expect( - "needs_branch_counters was `true` so there should be at least one \ - branch", - ); - debug!( - "Selecting any branch={:?} that still needs a counter, to get the \ - `Expression` because there was no `reloop_branch`, or it already had a \ - counter", - branch_without_counter - ); - branch_without_counter + return reloop_target; } + + // We couldn't identify a "good" edge, so just choose any edge that + // doesn't already have a counter. + let arbitrary_target = self + .bcb_successors(from_bcb) + .iter() + .copied() + .find(|&to_bcb| self.edge_has_no_counter(from_bcb, to_bcb)) + .expect("precondition: at least one out-edge without a counter"); + debug!(?arbitrary_target, "selecting arbitrary out-edge to get an expression"); + arbitrary_target } - /// Tries to find a branch that leads back to the top of a loop, and that - /// doesn't already have a counter. Such branches are good candidates to + /// Tries to find an edge that leads back to the top of a loop, and that + /// doesn't already have a counter. Such edges are good candidates to /// be given an expression (instead of a physical counter), because they - /// will tend to be executed more times than a loop-exit branch. - fn find_good_reloop_branch( + /// will tend to be executed more times than a loop-exit edge. + fn find_good_reloop_edge( &self, traversal: &TraverseCoverageGraphWithLoops<'_>, from_bcb: BasicCoverageBlock, ) -> Option { - let branch_target_bcbs = self.bcb_successors(from_bcb); + let successors = self.bcb_successors(from_bcb); // Consider each loop on the current traversal context stack, top-down. for reloop_bcbs in traversal.reloop_bcbs_per_loop() { - let mut all_branches_exit_this_loop = true; + let mut all_edges_exit_this_loop = true; - // Try to find a branch that doesn't exit this loop and doesn't + // Try to find an out-edge that doesn't exit this loop and doesn't // already have a counter. - for &branch_target_bcb in branch_target_bcbs { - // A branch is a reloop branch if it dominates any BCB that has - // an edge back to the loop header. (Other branches are exits.) - let is_reloop_branch = reloop_bcbs.iter().any(|&reloop_bcb| { - self.basic_coverage_blocks.dominates(branch_target_bcb, reloop_bcb) + for &target_bcb in successors { + // An edge is a reloop edge if its target dominates any BCB that has + // an edge back to the loop header. (Otherwise it's an exit edge.) + let is_reloop_edge = reloop_bcbs.iter().any(|&reloop_bcb| { + self.basic_coverage_blocks.dominates(target_bcb, reloop_bcb) }); - if is_reloop_branch { - all_branches_exit_this_loop = false; - if self.branch_has_no_counter(from_bcb, branch_target_bcb) { - // We found a good branch to be given an expression. - return Some(branch_target_bcb); + if is_reloop_edge { + all_edges_exit_this_loop = false; + if self.edge_has_no_counter(from_bcb, target_bcb) { + // We found a good out-edge to be given an expression. + return Some(target_bcb); } - // Keep looking for another reloop branch without a counter. + // Keep looking for another reloop edge without a counter. } else { - // This branch exits the loop. + // This edge exits the loop. } } - if !all_branches_exit_this_loop { - // We found one or more reloop branches, but all of them already - // have counters. Let the caller choose one of the exit branches. - debug!("All reloop branches had counters; skip checking the other loops"); + if !all_edges_exit_this_loop { + // We found one or more reloop edges, but all of them already + // have counters. Let the caller choose one of the other edges. + debug!("All reloop edges had counters; skipping the other loops"); return None; } - // All of the branches exit this loop, so keep looking for a good - // reloop branch for one of the outer loops. + // All of the out-edges exit this loop, so keep looking for a good + // reloop edge for one of the outer loops. } None @@ -534,15 +517,15 @@ impl<'a> MakeBcbCounters<'a> { } #[inline] - fn branch_has_no_counter( + fn edge_has_no_counter( &self, from_bcb: BasicCoverageBlock, to_bcb: BasicCoverageBlock, ) -> bool { - self.branch_counter(from_bcb, to_bcb).is_none() + self.edge_counter(from_bcb, to_bcb).is_none() } - fn branch_counter( + fn edge_counter( &self, from_bcb: BasicCoverageBlock, to_bcb: BasicCoverageBlock, From 10cd5e8386a1ed20dc7fe07b481d3965e51e592f Mon Sep 17 00:00:00 2001 From: Zalathar Date: Tue, 10 Sep 2024 20:48:28 +1000 Subject: [PATCH 0792/2194] coverage: Avoid referring to "operands" in counter creation --- .../rustc_mir_transform/src/coverage/counters.rs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/compiler/rustc_mir_transform/src/coverage/counters.rs b/compiler/rustc_mir_transform/src/coverage/counters.rs index f55d6cf8efc71..1c240366afa2e 100644 --- a/compiler/rustc_mir_transform/src/coverage/counters.rs +++ b/compiler/rustc_mir_transform/src/coverage/counters.rs @@ -288,7 +288,7 @@ impl<'a> MakeBcbCounters<'a> { ) { // First, ensure that this node has a counter of some kind. // We might also use that counter to compute one of the out-edge counters. - let from_bcb_operand = self.get_or_make_counter_operand(from_bcb); + let node_counter = self.get_or_make_node_counter(from_bcb); let successors = self.basic_coverage_blocks.successors[from_bcb].as_slice(); @@ -324,7 +324,7 @@ impl<'a> MakeBcbCounters<'a> { .filter(|&to_bcb| to_bcb != expression_to_bcb) .fold(None, |accum, to_bcb| { let _span = debug_span!("to_bcb", ?accum, ?to_bcb).entered(); - let edge_counter = self.get_or_make_edge_counter_operand(from_bcb, to_bcb); + let edge_counter = self.get_or_make_edge_counter(from_bcb, to_bcb); Some(self.coverage_counters.make_sum_expression(accum, edge_counter)) }) .expect("there must be at least one other out-edge") @@ -333,7 +333,7 @@ impl<'a> MakeBcbCounters<'a> { // Now create an expression for the chosen edge, by taking the counter // for its source node and subtracting the sum of its sibling out-edges. let expression = self.coverage_counters.make_expression( - from_bcb_operand, + node_counter, Op::Subtract, sum_of_all_other_out_edges, ); @@ -347,7 +347,7 @@ impl<'a> MakeBcbCounters<'a> { } #[instrument(level = "debug", skip(self))] - fn get_or_make_counter_operand(&mut self, bcb: BasicCoverageBlock) -> BcbCounter { + fn get_or_make_node_counter(&mut self, bcb: BasicCoverageBlock) -> BcbCounter { // If the BCB already has a counter, return it. if let Some(counter_kind) = self.coverage_counters.bcb_counters[bcb] { debug!("{bcb:?} already has a counter: {counter_kind:?}"); @@ -384,7 +384,7 @@ impl<'a> MakeBcbCounters<'a> { .copied() .fold(None, |accum, from_bcb| { let _span = debug_span!("from_bcb", ?accum, ?from_bcb).entered(); - let edge_counter = self.get_or_make_edge_counter_operand(from_bcb, bcb); + let edge_counter = self.get_or_make_edge_counter(from_bcb, bcb); Some(self.coverage_counters.make_sum_expression(accum, edge_counter)) }) .expect("there must be at least one in-edge") @@ -395,7 +395,7 @@ impl<'a> MakeBcbCounters<'a> { } #[instrument(level = "debug", skip(self))] - fn get_or_make_edge_counter_operand( + fn get_or_make_edge_counter( &mut self, from_bcb: BasicCoverageBlock, to_bcb: BasicCoverageBlock, @@ -404,13 +404,13 @@ impl<'a> MakeBcbCounters<'a> { // a node counter instead, since it will have the same value. if !self.basic_coverage_blocks.bcb_has_multiple_in_edges(to_bcb) { assert_eq!([from_bcb].as_slice(), self.basic_coverage_blocks.predecessors[to_bcb]); - return self.get_or_make_counter_operand(to_bcb); + return self.get_or_make_node_counter(to_bcb); } // If the source BCB has only one successor (assumed to be the given target), an edge // counter is unnecessary. Just get or make a counter for the source BCB. if self.bcb_successors(from_bcb).len() == 1 { - return self.get_or_make_counter_operand(from_bcb); + return self.get_or_make_node_counter(from_bcb); } // If the edge already has a counter, return it. From 86075759cc96748e56d70f6e25bbf319141ea82f Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 10 Sep 2024 13:18:20 +0200 Subject: [PATCH 0793/2194] abi/compatibility test: remove tests inside repr(C) wrappers --- tests/ui/abi/compatibility.rs | 52 ++++++++--------------------------- 1 file changed, 11 insertions(+), 41 deletions(-) diff --git a/tests/ui/abi/compatibility.rs b/tests/ui/abi/compatibility.rs index d37e793d9892d..9600c8dff67b1 100644 --- a/tests/ui/abi/compatibility.rs +++ b/tests/ui/abi/compatibility.rs @@ -189,7 +189,7 @@ mod prelude { #[cfg(not(host))] use prelude::*; -macro_rules! assert_abi_compatible { +macro_rules! test_abi_compatible { ($name:ident, $t1:ty, $t2:ty) => { mod $name { use super::*; @@ -212,16 +212,6 @@ impl Clone for Zst { } } -#[repr(C)] -struct ReprC1(T); -#[repr(C)] -struct ReprC2Int(i32, T); -#[repr(C)] -struct ReprC2Float(f32, T); -#[repr(C)] -struct ReprC4(T, Vec, Zst, T); -#[repr(C)] -struct ReprC4Mixed(T, f32, i32, T); #[repr(C)] enum ReprCEnum { Variant1, @@ -233,23 +223,6 @@ union ReprCUnion { something: ManuallyDrop, } -macro_rules! test_abi_compatible { - ($name:ident, $t1:ty, $t2:ty) => { - mod $name { - use super::*; - assert_abi_compatible!(plain, $t1, $t2); - // We also do some tests with differences in fields of `repr(C)` types. - assert_abi_compatible!(repr_c_1, ReprC1<$t1>, ReprC1<$t2>); - assert_abi_compatible!(repr_c_2_int, ReprC2Int<$t1>, ReprC2Int<$t2>); - assert_abi_compatible!(repr_c_2_float, ReprC2Float<$t1>, ReprC2Float<$t2>); - assert_abi_compatible!(repr_c_4, ReprC4<$t1>, ReprC4<$t2>); - assert_abi_compatible!(repr_c_4mixed, ReprC4Mixed<$t1>, ReprC4Mixed<$t2>); - assert_abi_compatible!(repr_c_enum, ReprCEnum<$t1>, ReprCEnum<$t2>); - assert_abi_compatible!(repr_c_union, ReprCUnion<$t1>, ReprCUnion<$t2>); - } - }; -} - // Compatibility of pointers. test_abi_compatible!(ptr_mut, *const i32, *mut i32); test_abi_compatible!(ptr_pointee, *const i32, *const Vec); @@ -268,7 +241,6 @@ test_abi_compatible!(isize_int, isize, i64); // Compatibility of 1-ZST. test_abi_compatible!(zst_unit, Zst, ()); -#[cfg(not(any(target_arch = "sparc64")))] test_abi_compatible!(zst_array, Zst, [u8; 0]); test_abi_compatible!(nonzero_int, NonZero, i32); @@ -285,13 +257,13 @@ test_abi_compatible!(arc, Arc, *mut i32); // `repr(transparent)` compatibility. #[repr(transparent)] -struct Wrapper1(T); +struct TransparentWrapper1(T); #[repr(transparent)] -struct Wrapper2((), Zst, T); +struct TransparentWrapper2((), Zst, T); #[repr(transparent)] -struct Wrapper3(T, [u8; 0], PhantomData); +struct TransparentWrapper3(T, [u8; 0], PhantomData); #[repr(transparent)] -union WrapperUnion { +union TransparentWrapperUnion { nothing: (), something: ManuallyDrop, } @@ -300,10 +272,10 @@ macro_rules! test_transparent { ($name:ident, $t:ty) => { mod $name { use super::*; - test_abi_compatible!(wrap1, $t, Wrapper1<$t>); - test_abi_compatible!(wrap2, $t, Wrapper2<$t>); - test_abi_compatible!(wrap3, $t, Wrapper3<$t>); - test_abi_compatible!(wrap4, $t, WrapperUnion<$t>); + test_abi_compatible!(wrap1, $t, TransparentWrapper1<$t>); + test_abi_compatible!(wrap2, $t, TransparentWrapper2<$t>); + test_abi_compatible!(wrap3, $t, TransparentWrapper3<$t>); + test_abi_compatible!(wrap4, $t, TransparentWrapperUnion<$t>); } }; } @@ -342,10 +314,8 @@ macro_rules! test_transparent_unsized { ($name:ident, $t:ty) => { mod $name { use super::*; - assert_abi_compatible!(wrap1, $t, Wrapper1<$t>); - assert_abi_compatible!(wrap1_reprc, ReprC1<$t>, ReprC1>); - assert_abi_compatible!(wrap2, $t, Wrapper2<$t>); - assert_abi_compatible!(wrap2_reprc, ReprC1<$t>, ReprC1>); + test_abi_compatible!(wrap1, $t, TransparentWrapper1<$t>); + test_abi_compatible!(wrap2, $t, TransparentWrapper2<$t>); } }; } From 6ca5ec7b4ef0466a1cdf3fbce9212cabc171d21a Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Tue, 10 Sep 2024 14:42:17 +0200 Subject: [PATCH 0794/2194] disallow `naked_asm!` outside of `#[naked]` functions --- compiler/rustc_ast/src/ast.rs | 11 +++++ compiler/rustc_ast/src/mut_visit.rs | 1 + compiler/rustc_ast/src/visit.rs | 1 + compiler/rustc_ast_lowering/src/asm.rs | 10 +++- compiler/rustc_builtin_macros/src/asm.rs | 11 +++-- compiler/rustc_hir/src/hir.rs | 1 + compiler/rustc_passes/messages.ftl | 3 ++ compiler/rustc_passes/src/errors.rs | 7 +++ compiler/rustc_passes/src/naked_functions.rs | 48 ++++++++++++++----- tests/ui/asm/naked-asm-outside-naked-fn.rs | 35 ++++++++++++++ .../ui/asm/naked-asm-outside-naked-fn.stderr | 20 ++++++++ 11 files changed, 132 insertions(+), 16 deletions(-) create mode 100644 tests/ui/asm/naked-asm-outside-naked-fn.rs create mode 100644 tests/ui/asm/naked-asm-outside-naked-fn.stderr diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index 85d38a0e28b0f..42741bdca2295 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -2418,11 +2418,22 @@ impl InlineAsmOperand { } } +#[derive(Clone, Copy, Encodable, Decodable, Debug, HashStable_Generic)] +pub enum AsmMacro { + /// The `asm!` macro + Asm, + /// The `global_asm!` macro + GlobalAsm, + /// The `naked_asm!` macro + NakedAsm, +} + /// Inline assembly. /// /// E.g., `asm!("NOP");`. #[derive(Clone, Encodable, Decodable, Debug)] pub struct InlineAsm { + pub asm_macro: AsmMacro, pub template: Vec, pub template_strs: Box<[(Symbol, Option, Span)]>, pub operands: Vec<(InlineAsmOperand, Span)>, diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs index 7c8af6c4a5564..1bef51aa73f7b 100644 --- a/compiler/rustc_ast/src/mut_visit.rs +++ b/compiler/rustc_ast/src/mut_visit.rs @@ -1388,6 +1388,7 @@ fn walk_anon_const(vis: &mut T, AnonConst { id, value }: &mut Ano fn walk_inline_asm(vis: &mut T, asm: &mut InlineAsm) { // FIXME: Visit spans inside all this currently ignored stuff. let InlineAsm { + asm_macro: _, template: _, template_strs: _, operands, diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs index 7b041768983e6..bae7ad93f90fa 100644 --- a/compiler/rustc_ast/src/visit.rs +++ b/compiler/rustc_ast/src/visit.rs @@ -976,6 +976,7 @@ pub fn walk_anon_const<'a, V: Visitor<'a>>(visitor: &mut V, constant: &'a AnonCo pub fn walk_inline_asm<'a, V: Visitor<'a>>(visitor: &mut V, asm: &'a InlineAsm) -> V::Result { let InlineAsm { + asm_macro: _, template: _, template_strs: _, operands, diff --git a/compiler/rustc_ast_lowering/src/asm.rs b/compiler/rustc_ast_lowering/src/asm.rs index e077c54496586..4413c259efbf3 100644 --- a/compiler/rustc_ast_lowering/src/asm.rs +++ b/compiler/rustc_ast_lowering/src/asm.rs @@ -474,8 +474,14 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { ); let line_spans = self.arena.alloc_from_iter(asm.line_spans.iter().map(|span| self.lower_span(*span))); - let hir_asm = - hir::InlineAsm { template, template_strs, operands, options: asm.options, line_spans }; + let hir_asm = hir::InlineAsm { + asm_macro: asm.asm_macro, + template, + template_strs, + operands, + options: asm.options, + line_spans, + }; self.arena.alloc(hir_asm) } } diff --git a/compiler/rustc_builtin_macros/src/asm.rs b/compiler/rustc_builtin_macros/src/asm.rs index e313016e3d863..d6248899655dc 100644 --- a/compiler/rustc_builtin_macros/src/asm.rs +++ b/compiler/rustc_builtin_macros/src/asm.rs @@ -3,6 +3,7 @@ use lint::BuiltinLintDiag; use rustc_ast::ptr::P; use rustc_ast::token::{self, Delimiter}; use rustc_ast::tokenstream::TokenStream; +use rustc_ast::AsmMacro; use rustc_data_structures::fx::{FxHashMap, FxIndexMap}; use rustc_errors::PResult; use rustc_expand::base::*; @@ -484,6 +485,7 @@ fn parse_reg<'a>( fn expand_preparsed_asm( ecx: &mut ExtCtxt<'_>, + asm_macro: ast::AsmMacro, args: AsmArgs, ) -> ExpandResult, ()> { let mut template = vec![]; @@ -774,6 +776,7 @@ fn expand_preparsed_asm( } ExpandResult::Ready(Ok(ast::InlineAsm { + asm_macro, template, template_strs: template_strs.into_boxed_slice(), operands: args.operands, @@ -790,7 +793,7 @@ pub(super) fn expand_asm<'cx>( ) -> MacroExpanderResult<'cx> { ExpandResult::Ready(match parse_args(ecx, sp, tts, false) { Ok(args) => { - let ExpandResult::Ready(mac) = expand_preparsed_asm(ecx, args) else { + let ExpandResult::Ready(mac) = expand_preparsed_asm(ecx, AsmMacro::Asm, args) else { return ExpandResult::Retry(()); }; let expr = match mac { @@ -819,7 +822,8 @@ pub(super) fn expand_naked_asm<'cx>( ) -> MacroExpanderResult<'cx> { ExpandResult::Ready(match parse_args(ecx, sp, tts, false) { Ok(args) => { - let ExpandResult::Ready(mac) = expand_preparsed_asm(ecx, args) else { + let ExpandResult::Ready(mac) = expand_preparsed_asm(ecx, AsmMacro::NakedAsm, args) + else { return ExpandResult::Retry(()); }; let expr = match mac { @@ -857,7 +861,8 @@ pub(super) fn expand_global_asm<'cx>( ) -> MacroExpanderResult<'cx> { ExpandResult::Ready(match parse_args(ecx, sp, tts, true) { Ok(args) => { - let ExpandResult::Ready(mac) = expand_preparsed_asm(ecx, args) else { + let ExpandResult::Ready(mac) = expand_preparsed_asm(ecx, AsmMacro::GlobalAsm, args) + else { return ExpandResult::Retry(()); }; match mac { diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index b01c24cf3053e..ee03f780e16f5 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -2927,6 +2927,7 @@ impl<'hir> InlineAsmOperand<'hir> { #[derive(Debug, Clone, Copy, HashStable_Generic)] pub struct InlineAsm<'hir> { + pub asm_macro: ast::AsmMacro, pub template: &'hir [InlineAsmTemplatePiece], pub template_strs: &'hir [(Symbol, Option, Span)], pub operands: &'hir [(InlineAsmOperand<'hir>, Span)], diff --git a/compiler/rustc_passes/messages.ftl b/compiler/rustc_passes/messages.ftl index e7f208d5ad544..5369f54afb908 100644 --- a/compiler/rustc_passes/messages.ftl +++ b/compiler/rustc_passes/messages.ftl @@ -484,6 +484,9 @@ passes_must_not_suspend = passes_must_use_no_effect = `#[must_use]` has no effect when applied to {$article} {$target} +passes_naked_asm_outside_naked_fn = + the `naked_asm!` macro can only be used in functions marked with `#[naked]` + passes_naked_functions_asm_block = naked functions must contain a single asm block .label_multiple_asm = multiple asm blocks are unsupported in naked functions diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs index f5d982e1a5cd1..a985ecb019a19 100644 --- a/compiler/rustc_passes/src/errors.rs +++ b/compiler/rustc_passes/src/errors.rs @@ -1221,6 +1221,13 @@ pub(crate) struct NakedFunctionIncompatibleAttribute { pub attr: Symbol, } +#[derive(Diagnostic)] +#[diag(passes_naked_asm_outside_naked_fn)] +pub(crate) struct NakedAsmOutsideNakedFn { + #[primary_span] + pub span: Span, +} + #[derive(Diagnostic)] #[diag(passes_attr_only_in_functions)] pub(crate) struct AttrOnlyInFunctions { diff --git a/compiler/rustc_passes/src/naked_functions.rs b/compiler/rustc_passes/src/naked_functions.rs index b72ce239c4a96..ab6385dd7d738 100644 --- a/compiler/rustc_passes/src/naked_functions.rs +++ b/compiler/rustc_passes/src/naked_functions.rs @@ -6,6 +6,7 @@ use rustc_hir::def::DefKind; use rustc_hir::def_id::{LocalDefId, LocalModDefId}; use rustc_hir::intravisit::Visitor; use rustc_hir::{ExprKind, HirIdSet, InlineAsmOperand, StmtKind}; +use rustc_middle::hir::nested_filter::OnlyBodies; use rustc_middle::query::Providers; use rustc_middle::ty::TyCtxt; use rustc_session::lint::builtin::UNDEFINED_NAKED_FUNCTION_ABI; @@ -14,8 +15,9 @@ use rustc_span::Span; use rustc_target::spec::abi::Abi; use crate::errors::{ - NakedFunctionsAsmBlock, NakedFunctionsAsmOptions, NakedFunctionsMustUseNoreturn, - NakedFunctionsOperands, NoPatterns, ParamsNotAllowed, UndefinedNakedFunctionAbi, + NakedAsmOutsideNakedFn, NakedFunctionsAsmBlock, NakedFunctionsAsmOptions, + NakedFunctionsMustUseNoreturn, NakedFunctionsOperands, NoPatterns, ParamsNotAllowed, + UndefinedNakedFunctionAbi, }; pub(crate) fn provide(providers: &mut Providers) { @@ -29,11 +31,6 @@ fn check_mod_naked_functions(tcx: TyCtxt<'_>, module_def_id: LocalModDefId) { continue; } - let naked = tcx.has_attr(def_id, sym::naked); - if !naked { - continue; - } - let (fn_header, body_id) = match tcx.hir_node_by_def_id(def_id) { hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(sig, _, body_id), .. }) | hir::Node::TraitItem(hir::TraitItem { @@ -48,10 +45,17 @@ fn check_mod_naked_functions(tcx: TyCtxt<'_>, module_def_id: LocalModDefId) { }; let body = tcx.hir().body(body_id); - check_abi(tcx, def_id, fn_header.abi); - check_no_patterns(tcx, body.params); - check_no_parameters_use(tcx, body); - check_asm(tcx, def_id, body); + + if tcx.has_attr(def_id, sym::naked) { + check_abi(tcx, def_id, fn_header.abi); + check_no_patterns(tcx, body.params); + check_no_parameters_use(tcx, body); + check_asm(tcx, def_id, body); + } else { + // `naked_asm!` is not allowed outside of functions marked as `#[naked]` + let mut visitor = CheckNakedAsmInNakedFn { tcx }; + visitor.visit_body(body); + } } } @@ -276,3 +280,25 @@ impl<'tcx> Visitor<'tcx> for CheckInlineAssembly<'tcx> { self.check_expr(expr, expr.span); } } + +struct CheckNakedAsmInNakedFn<'tcx> { + tcx: TyCtxt<'tcx>, +} + +impl<'tcx> Visitor<'tcx> for CheckNakedAsmInNakedFn<'tcx> { + type NestedFilter = OnlyBodies; + + fn nested_visit_map(&mut self) -> Self::Map { + self.tcx.hir() + } + + fn visit_expr(&mut self, expr: &'tcx hir::Expr<'tcx>) { + if let ExprKind::InlineAsm(inline_asm) = expr.kind { + if let rustc_ast::AsmMacro::NakedAsm = inline_asm.asm_macro { + self.tcx.dcx().emit_err(NakedAsmOutsideNakedFn { span: expr.span }); + } + } + + hir::intravisit::walk_expr(self, expr); + } +} diff --git a/tests/ui/asm/naked-asm-outside-naked-fn.rs b/tests/ui/asm/naked-asm-outside-naked-fn.rs new file mode 100644 index 0000000000000..1696008f3397d --- /dev/null +++ b/tests/ui/asm/naked-asm-outside-naked-fn.rs @@ -0,0 +1,35 @@ +//@ edition: 2021 +//@ needs-asm-support +//@ ignore-nvptx64 +//@ ignore-spirv + +#![feature(naked_functions)] +#![crate_type = "lib"] + +use std::arch::naked_asm; + +fn main() { + test1(); +} + +#[naked] +extern "C" fn test1() { + unsafe { naked_asm!("") } +} + +extern "C" fn test2() { + unsafe { naked_asm!("") } + //~^ ERROR the `naked_asm!` macro can only be used in functions marked with `#[naked]` +} + +extern "C" fn test3() { + unsafe { (|| naked_asm!(""))() } + //~^ ERROR the `naked_asm!` macro can only be used in functions marked with `#[naked]` +} + +fn test4() { + async move { + unsafe { naked_asm!("") } ; + //~^ ERROR the `naked_asm!` macro can only be used in functions marked with `#[naked]` + }; +} diff --git a/tests/ui/asm/naked-asm-outside-naked-fn.stderr b/tests/ui/asm/naked-asm-outside-naked-fn.stderr new file mode 100644 index 0000000000000..6e91359669ca2 --- /dev/null +++ b/tests/ui/asm/naked-asm-outside-naked-fn.stderr @@ -0,0 +1,20 @@ +error: the `naked_asm!` macro can only be used in functions marked with `#[naked]` + --> $DIR/naked-asm-outside-naked-fn.rs:21:14 + | +LL | unsafe { naked_asm!("") } + | ^^^^^^^^^^^^^^ + +error: the `naked_asm!` macro can only be used in functions marked with `#[naked]` + --> $DIR/naked-asm-outside-naked-fn.rs:26:18 + | +LL | unsafe { (|| naked_asm!(""))() } + | ^^^^^^^^^^^^^^ + +error: the `naked_asm!` macro can only be used in functions marked with `#[naked]` + --> $DIR/naked-asm-outside-naked-fn.rs:32:19 + | +LL | unsafe { naked_asm!("") } ; + | ^^^^^^^^^^^^^^ + +error: aborting due to 3 previous errors + From 7a57a74bf52306d18d265fa4b498064634c91652 Mon Sep 17 00:00:00 2001 From: lcnr Date: Tue, 10 Sep 2024 15:21:57 +0200 Subject: [PATCH 0795/2194] generalize: track relevant info in cache key --- .../rustc_infer/src/infer/relate/generalize.rs | 18 +++++++++--------- .../occurs-check/unused-substs-3.rs | 6 ++++-- .../occurs-check/unused-substs-3.stderr | 8 +++----- 3 files changed, 16 insertions(+), 16 deletions(-) diff --git a/compiler/rustc_infer/src/infer/relate/generalize.rs b/compiler/rustc_infer/src/infer/relate/generalize.rs index f2a511d7a886b..fbe64f47741ba 100644 --- a/compiler/rustc_infer/src/infer/relate/generalize.rs +++ b/compiler/rustc_infer/src/infer/relate/generalize.rs @@ -259,11 +259,11 @@ impl<'tcx> InferCtxt<'tcx> { structurally_relate_aliases, root_vid, for_universe, - ambient_variance, root_term: source_term.into(), + ambient_variance, in_alias: false, - has_unconstrained_ty_var: false, cache: Default::default(), + has_unconstrained_ty_var: false, }; let value_may_be_infer = generalizer.relate(source_term, source_term)?; @@ -304,14 +304,12 @@ struct Generalizer<'me, 'tcx> { /// we reject the relation. for_universe: ty::UniverseIndex, - /// After we generalize this type, we are going to relate it to - /// some other type. What will be the variance at this point? - ambient_variance: ty::Variance, - /// The root term (const or type) we're generalizing. Used for cycle errors. root_term: Term<'tcx>, - cache: SsoHashMap, Ty<'tcx>>, + /// After we generalize this type, we are going to relate it to + /// some other type. What will be the variance at this point? + ambient_variance: ty::Variance, /// This is set once we're generalizing the arguments of an alias. /// @@ -320,6 +318,8 @@ struct Generalizer<'me, 'tcx> { /// hold by either normalizing the outer or the inner associated type. in_alias: bool, + cache: SsoHashMap<(Ty<'tcx>, ty::Variance, bool), Ty<'tcx>>, + /// See the field `has_unconstrained_ty_var` in `Generalization`. has_unconstrained_ty_var: bool, } @@ -451,7 +451,7 @@ impl<'tcx> TypeRelation> for Generalizer<'_, 'tcx> { fn tys(&mut self, t: Ty<'tcx>, t2: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> { assert_eq!(t, t2); // we are misusing TypeRelation here; both LHS and RHS ought to be == - if let Some(&result) = self.cache.get(&t) { + if let Some(&result) = self.cache.get(&(t, self.ambient_variance, self.in_alias)) { return Ok(result); } @@ -557,7 +557,7 @@ impl<'tcx> TypeRelation> for Generalizer<'_, 'tcx> { _ => relate::structurally_relate_tys(self, t, t), }?; - self.cache.insert(t, g); + self.cache.insert((t, self.ambient_variance, self.in_alias), g); Ok(g) } diff --git a/tests/ui/const-generics/occurs-check/unused-substs-3.rs b/tests/ui/const-generics/occurs-check/unused-substs-3.rs index 6db18d587d3e2..dfb051192e2f3 100644 --- a/tests/ui/const-generics/occurs-check/unused-substs-3.rs +++ b/tests/ui/const-generics/occurs-check/unused-substs-3.rs @@ -11,9 +11,11 @@ fn bind() -> (T, [u8; 6 + 1]) { fn main() { let (mut t, foo) = bind(); + //~^ ERROR mismatched types + //~| NOTE cyclic type + // `t` is `ty::Infer(TyVar(?1t))` // `foo` contains `ty::Infer(TyVar(?1t))` in its substs t = foo; - //~^ ERROR mismatched types - //~| NOTE cyclic type + } diff --git a/tests/ui/const-generics/occurs-check/unused-substs-3.stderr b/tests/ui/const-generics/occurs-check/unused-substs-3.stderr index bcb59705c6b2f..30a2a7901bdf5 100644 --- a/tests/ui/const-generics/occurs-check/unused-substs-3.stderr +++ b/tests/ui/const-generics/occurs-check/unused-substs-3.stderr @@ -1,10 +1,8 @@ error[E0308]: mismatched types - --> $DIR/unused-substs-3.rs:16:9 + --> $DIR/unused-substs-3.rs:13:24 | -LL | t = foo; - | ^^^- help: try using a conversion method: `.to_vec()` - | | - | cyclic type of infinite size +LL | let (mut t, foo) = bind(); + | ^^^^^^ cyclic type of infinite size error: aborting due to 1 previous error From 5cf117ed0514af068a6e0e42f732dd93ff5e90dc Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 10 Sep 2024 10:54:59 -0400 Subject: [PATCH 0796/2194] Don't call closure_by_move_body_def_id on FnOnce async closures in MIR validation --- compiler/rustc_interface/src/passes.rs | 2 +- compiler/rustc_middle/src/ty/context.rs | 2 +- compiler/rustc_mir_transform/src/lib.rs | 2 +- compiler/rustc_mir_transform/src/validate.rs | 6 +----- .../async-closures/body-check-on-non-fnmut.rs | 20 +++++++++++++++++++ 5 files changed, 24 insertions(+), 8 deletions(-) create mode 100644 tests/ui/async-await/async-closures/body-check-on-non-fnmut.rs diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index c4a38047b5e3b..b93bc3ed84f54 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -788,7 +788,7 @@ fn run_required_analyses(tcx: TyCtxt<'_>) { rustc_hir_analysis::check_crate(tcx); sess.time("MIR_coroutine_by_move_body", || { tcx.hir().par_body_owners(|def_id| { - if tcx.needs_coroutine_by_move_body_def_id(def_id) { + if tcx.needs_coroutine_by_move_body_def_id(def_id.to_def_id()) { tcx.ensure_with_value().coroutine_by_move_body_def_id(def_id); } }); diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 56fcfe8e798b1..fe162fe830322 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -3173,7 +3173,7 @@ impl<'tcx> TyCtxt<'tcx> { self.impl_trait_header(def_id).map_or(ty::ImplPolarity::Positive, |h| h.polarity) } - pub fn needs_coroutine_by_move_body_def_id(self, def_id: LocalDefId) -> bool { + pub fn needs_coroutine_by_move_body_def_id(self, def_id: DefId) -> bool { if let Some(hir::CoroutineKind::Desugared(_, hir::CoroutineSource::Closure)) = self.coroutine_kind(def_id) && let ty::Coroutine(_, args) = self.type_of(def_id).instantiate_identity().kind() diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs index 0bbbf047f634c..c83b9139801ca 100644 --- a/compiler/rustc_mir_transform/src/lib.rs +++ b/compiler/rustc_mir_transform/src/lib.rs @@ -326,7 +326,7 @@ fn mir_promoted( tcx.ensure_with_value().has_ffi_unwind_calls(def); // the `by_move_body` query uses the raw mir, so make sure it is run. - if tcx.needs_coroutine_by_move_body_def_id(def) { + if tcx.needs_coroutine_by_move_body_def_id(def.to_def_id()) { tcx.ensure_with_value().coroutine_by_move_body_def_id(def); } diff --git a/compiler/rustc_mir_transform/src/validate.rs b/compiler/rustc_mir_transform/src/validate.rs index 18865c73f75b1..da36ddd1e9b7a 100644 --- a/compiler/rustc_mir_transform/src/validate.rs +++ b/compiler/rustc_mir_transform/src/validate.rs @@ -1,7 +1,6 @@ //! Validates the MIR to ensure that invariants are upheld. use rustc_data_structures::fx::{FxHashMap, FxHashSet}; -use rustc_hir as hir; use rustc_hir::LangItem; use rustc_index::bit_set::BitSet; use rustc_index::IndexVec; @@ -716,10 +715,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { // first place. let layout = if def_id == self.caller_body.source.def_id() { self.caller_body.coroutine_layout_raw() - } else if let Some(hir::CoroutineKind::Desugared( - _, - hir::CoroutineSource::Closure, - )) = self.tcx.coroutine_kind(def_id) + } else if self.tcx.needs_coroutine_by_move_body_def_id(def_id) && let ty::ClosureKind::FnOnce = args.as_coroutine().kind_ty().to_opt_closure_kind().unwrap() && self.caller_body.source.def_id() diff --git a/tests/ui/async-await/async-closures/body-check-on-non-fnmut.rs b/tests/ui/async-await/async-closures/body-check-on-non-fnmut.rs new file mode 100644 index 0000000000000..4382a689e7564 --- /dev/null +++ b/tests/ui/async-await/async-closures/body-check-on-non-fnmut.rs @@ -0,0 +1,20 @@ +//@ aux-build:block-on.rs +//@ edition:2021 +//@ build-pass + +#![feature(async_closure)] + +extern crate block_on; + +// Make sure that we don't call `coroutine_by_move_body_def_id` query +// on async closures that are `FnOnce`. See issue: #130167. + +async fn empty() {} + +pub async fn call_once(f: F) { + f().await; +} + +fn main() { + block_on::block_on(call_once(async || empty().await)); +} From 713828d4f430e1393535f588e73dd5d8bb5d793a Mon Sep 17 00:00:00 2001 From: Florian Schmiderer Date: Fri, 6 Sep 2024 23:41:16 +0200 Subject: [PATCH 0797/2194] Add test for S_OBJNAME and update test for LF_BUILDINFO cl and cmd for pdb files. --- .../src/external_deps/llvm.rs | 6 +++++ .../pdb-buildinfo-cl-cmd/filecheck.txt | 4 ++++ tests/run-make/pdb-buildinfo-cl-cmd/rmake.rs | 24 ++++--------------- tests/run-make/pdb-sobjname/main.rs | 1 + tests/run-make/pdb-sobjname/rmake.rs | 20 ++++++++++++++++ 5 files changed, 36 insertions(+), 19 deletions(-) create mode 100644 tests/run-make/pdb-buildinfo-cl-cmd/filecheck.txt create mode 100644 tests/run-make/pdb-sobjname/main.rs create mode 100644 tests/run-make/pdb-sobjname/rmake.rs diff --git a/src/tools/run-make-support/src/external_deps/llvm.rs b/src/tools/run-make-support/src/external_deps/llvm.rs index 16c4251998fb2..38a9ac923b4dc 100644 --- a/src/tools/run-make-support/src/external_deps/llvm.rs +++ b/src/tools/run-make-support/src/external_deps/llvm.rs @@ -54,6 +54,12 @@ pub fn llvm_dwarfdump() -> LlvmDwarfdump { LlvmDwarfdump::new() } +/// Construct a new `llvm-pdbutil` invocation. This assumes that `llvm-pdbutil` is available +/// at `$LLVM_BIN_DIR/llvm-pdbutil`. +pub fn llvm_pdbutil() -> LlvmPdbutil { + LlvmPdbutil::new() +} + /// A `llvm-readobj` invocation builder. #[derive(Debug)] #[must_use] diff --git a/tests/run-make/pdb-buildinfo-cl-cmd/filecheck.txt b/tests/run-make/pdb-buildinfo-cl-cmd/filecheck.txt new file mode 100644 index 0000000000000..a01999d5bdf76 --- /dev/null +++ b/tests/run-make/pdb-buildinfo-cl-cmd/filecheck.txt @@ -0,0 +1,4 @@ +CHECK: LF_BUILDINFO +CHECK: rustc.exe +CHECK: main.rs +CHECK: "-g" "--crate-name" "my_crate_name" "--crate-type" "bin" "-Cmetadata=dc9ef878b0a48666" diff --git a/tests/run-make/pdb-buildinfo-cl-cmd/rmake.rs b/tests/run-make/pdb-buildinfo-cl-cmd/rmake.rs index 2ab9057b24c1b..9418f4f8d84d3 100644 --- a/tests/run-make/pdb-buildinfo-cl-cmd/rmake.rs +++ b/tests/run-make/pdb-buildinfo-cl-cmd/rmake.rs @@ -7,7 +7,7 @@ //@ only-windows-msvc // Reason: pdb files are unique to this architecture -use run_make_support::{assert_contains, bstr, env_var, rfs, rustc}; +use run_make_support::{llvm, rustc}; fn main() { rustc() @@ -17,23 +17,9 @@ fn main() { .crate_type("bin") .metadata("dc9ef878b0a48666") .run(); - let tests = [ - &env_var("RUSTC"), - r#""main.rs""#, - r#""-g""#, - r#""--crate-name""#, - r#""my_crate_name""#, - r#""--crate-type""#, - r#""bin""#, - r#""-Cmetadata=dc9ef878b0a48666""#, - ]; - for test in tests { - assert_pdb_contains(test); - } -} -fn assert_pdb_contains(needle: &str) { - let needle = needle.as_bytes(); - use bstr::ByteSlice; - assert!(&rfs::read("my_crate_name.pdb").find(needle).is_some()); + let pdbutil_result = + llvm::llvm_pdbutil().arg("dump").arg("-ids").input("my_crate_name.pdb").run(); + + llvm::llvm_filecheck().patterns("filecheck.txt").stdin_buf(pdbutil_result.stdout_utf8()).run(); } diff --git a/tests/run-make/pdb-sobjname/main.rs b/tests/run-make/pdb-sobjname/main.rs new file mode 100644 index 0000000000000..f328e4d9d04c3 --- /dev/null +++ b/tests/run-make/pdb-sobjname/main.rs @@ -0,0 +1 @@ +fn main() {} diff --git a/tests/run-make/pdb-sobjname/rmake.rs b/tests/run-make/pdb-sobjname/rmake.rs new file mode 100644 index 0000000000000..83c39fdccd3c7 --- /dev/null +++ b/tests/run-make/pdb-sobjname/rmake.rs @@ -0,0 +1,20 @@ +// Check if the pdb file contains an S_OBJNAME entry with the name of the .o file + +// This is because it used to be missing in #96475. +// See https://github.com/rust-lang/rust/pull/115704 + +//@ only-windows-msvc +// Reason: pdb files are unique to this architecture + +use run_make_support::{llvm, rustc}; + +fn main() { + rustc().input("main.rs").arg("-g").crate_name("my_great_crate_name").crate_type("bin").run(); + + let pdbutil_result = llvm::llvm_pdbutil() + .arg("dump") + .arg("-symbols") + .input("my_great_crate_name.pdb") + .run() + .assert_stdout_contains_regex("S_OBJNAME.+my_great_crate_name.*\\.o"); +} From 16f3eb969f319b5846e96b38c46a4933c24e03d8 Mon Sep 17 00:00:00 2001 From: Chayim Refael Friedman Date: Tue, 10 Sep 2024 18:48:54 +0300 Subject: [PATCH 0798/2194] Correctly escape strings in our quote macro MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is a small change, but it was the cause of 90% of the errors in `rust-analyzer diagnostics .` 🫢 With this change and #18085 together, all remaining errors are type errors. This may mean we can enable more errors, but this is out of scope for this PR. --- .../macro_expansion_tests/builtin_fn_macro.rs | 18 ++++++++++++++++++ .../crates/hir-expand/src/builtin/fn_macro.rs | 8 ++++---- .../crates/hir-expand/src/builtin/quote.rs | 5 +++-- 3 files changed, 25 insertions(+), 6 deletions(-) diff --git a/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/builtin_fn_macro.rs b/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/builtin_fn_macro.rs index 37ae1ab39b494..a3b48831a0b0f 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/builtin_fn_macro.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/builtin_fn_macro.rs @@ -528,3 +528,21 @@ fn main() { foobar; } "##]], ); } + +#[test] +fn test_quote_string() { + check( + r##" +#[rustc_builtin_macro] +macro_rules! stringify {} + +fn main() { stringify!("hello"); } +"##, + expect![[r##" +#[rustc_builtin_macro] +macro_rules! stringify {} + +fn main() { "\"hello\""; } +"##]], + ); +} diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/builtin/fn_macro.rs b/src/tools/rust-analyzer/crates/hir-expand/src/builtin/fn_macro.rs index 15fed45caf02f..d04225b87227b 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/builtin/fn_macro.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/builtin/fn_macro.rs @@ -483,7 +483,7 @@ fn concat_expand( match it.kind { tt::LitKind::Char => { if let Ok(c) = unescape_char(it.symbol.as_str()) { - text.extend(c.escape_default()); + text.push(c); } record_span(it.span); } @@ -491,11 +491,11 @@ fn concat_expand( format_to!(text, "{}", it.symbol.as_str()) } tt::LitKind::Str => { - text.push_str(it.symbol.as_str()); + text.push_str(unescape_str(&it.symbol).as_str()); record_span(it.span); } tt::LitKind::StrRaw(_) => { - format_to!(text, "{}", it.symbol.as_str().escape_debug()); + format_to!(text, "{}", it.symbol.as_str()); record_span(it.span); } tt::LitKind::Byte @@ -813,7 +813,7 @@ fn include_str_expand( fn get_env_inner(db: &dyn ExpandDatabase, arg_id: MacroCallId, key: &Symbol) -> Option { let krate = db.lookup_intern_macro_call(arg_id).krate; - db.crate_graph()[krate].env.get(key.as_str()).map(|it| it.escape_debug().to_string()) + db.crate_graph()[krate].env.get(key.as_str()) } fn env_expand( diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/builtin/quote.rs b/src/tools/rust-analyzer/crates/hir-expand/src/builtin/quote.rs index 5c33f817f9e44..fc248c906dac4 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/builtin/quote.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/builtin/quote.rs @@ -3,6 +3,7 @@ use intern::{sym, Symbol}; use span::Span; +use syntax::ToSmolStr; use tt::IdentIsRaw; use crate::name::Name; @@ -211,8 +212,8 @@ impl_to_to_tokentrees! { _span: crate::tt::Literal => self { self }; _span: crate::tt::Ident => self { self }; _span: crate::tt::Punct => self { self }; - span: &str => self { crate::tt::Literal{symbol: Symbol::intern(self), span, kind: tt::LitKind::Str, suffix: None }}; - span: String => self { crate::tt::Literal{symbol: Symbol::intern(&self), span, kind: tt::LitKind::Str, suffix: None }}; + span: &str => self { crate::tt::Literal{symbol: Symbol::intern(&self.escape_default().to_smolstr()), span, kind: tt::LitKind::Str, suffix: None }}; + span: String => self { crate::tt::Literal{symbol: Symbol::intern(&self.escape_default().to_smolstr()), span, kind: tt::LitKind::Str, suffix: None }}; span: Name => self { let (is_raw, s) = IdentIsRaw::split_from_symbol(self.as_str()); crate::tt::Ident{sym: Symbol::intern(s), span, is_raw } From ed89d9b7a29124e2757a8cfba93046f44992e07b Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Tue, 10 Sep 2024 19:00:54 +0300 Subject: [PATCH 0799/2194] force ci-llvm by default on library and tools profiles It's very rare for developers to need to modify LLVM, so "if-unchanged" isn't a good default since it fetches the LLVM submodule to track changes. Signed-off-by: onur-ozkan --- src/bootstrap/defaults/config.library.toml | 3 ++- src/bootstrap/defaults/config.tools.toml | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/bootstrap/defaults/config.library.toml b/src/bootstrap/defaults/config.library.toml index 087544397f5ea..5447565a4b04c 100644 --- a/src/bootstrap/defaults/config.library.toml +++ b/src/bootstrap/defaults/config.library.toml @@ -13,4 +13,5 @@ lto = "off" [llvm] # Will download LLVM from CI if available on your platform. -download-ci-llvm = "if-unchanged" +# If you intend to modify `src/llvm-project`, use `"if-unchanged"` or `false` instead. +download-ci-llvm = true diff --git a/src/bootstrap/defaults/config.tools.toml b/src/bootstrap/defaults/config.tools.toml index 75ad37ce33549..efb56996bcd45 100644 --- a/src/bootstrap/defaults/config.tools.toml +++ b/src/bootstrap/defaults/config.tools.toml @@ -17,4 +17,5 @@ compiler-docs = true [llvm] # Will download LLVM from CI if available on your platform. -download-ci-llvm = "if-unchanged" +# If you intend to modify `src/llvm-project`, use `"if-unchanged"` or `false` instead. +download-ci-llvm = true From b5d69ba9fb77ee2fa0bedc137660faf1d3d06f9b Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Tue, 10 Sep 2024 19:07:50 +0300 Subject: [PATCH 0800/2194] add change entry for "tools" and "library" profile update Signed-off-by: onur-ozkan --- src/bootstrap/src/utils/change_tracker.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/bootstrap/src/utils/change_tracker.rs b/src/bootstrap/src/utils/change_tracker.rs index 99bcc6e0787ff..bedaa15ccb9c5 100644 --- a/src/bootstrap/src/utils/change_tracker.rs +++ b/src/bootstrap/src/utils/change_tracker.rs @@ -255,4 +255,9 @@ pub const CONFIG_CHANGE_HISTORY: &[ChangeInfo] = &[ severity: ChangeSeverity::Warning, summary: "`download-ci-llvm = true` now checks if CI llvm is available and has become the default for the compiler profile", }, + ChangeInfo { + change_id: 130202, + severity: ChangeSeverity::Info, + summary: "'tools' and 'library' profiles switched `download-ci-llvm` option from `if-unchanged` to `true`.", + }, ]; From a169a5bec870c72ff4c99fb2d56d6cb5bc3ce874 Mon Sep 17 00:00:00 2001 From: Shoyu Vanilla Date: Wed, 11 Sep 2024 01:40:13 +0900 Subject: [PATCH 0801/2194] Skip checks for cast to dyn traits --- .../crates/hir-ty/src/infer/cast.rs | 39 ++++++++ .../crates/hir-ty/src/infer/unify.rs | 4 + .../src/handlers/invalid_cast.rs | 96 +++++++++++++++++++ 3 files changed, 139 insertions(+) diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer/cast.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer/cast.rs index ae914044368ca..caa3960a227cf 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/infer/cast.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer/cast.rs @@ -120,6 +120,13 @@ impl CastCheck { }); } + // Chalk doesn't support trait upcasting and fails to solve some obvious goals + // when the trait environment contains some recursive traits (See issue #18047) + // We skip cast checks for such cases for now, until the next-gen solver. + if contains_dyn_trait(&self.cast_ty) { + return Ok(()); + } + if let Ok((adj, _)) = table.coerce(&self.expr_ty, &self.cast_ty) { apply_adjustments(self.source_expr, adj); set_coercion_cast(self.source_expr); @@ -410,3 +417,35 @@ fn pointer_kind(ty: &Ty, table: &mut InferenceTable<'_>) -> Result bool { + use std::ops::ControlFlow; + + use chalk_ir::{ + visit::{TypeSuperVisitable, TypeVisitable, TypeVisitor}, + DebruijnIndex, + }; + + struct DynTraitVisitor; + + impl TypeVisitor for DynTraitVisitor { + type BreakTy = (); + + fn as_dyn(&mut self) -> &mut dyn TypeVisitor { + self + } + + fn interner(&self) -> Interner { + Interner + } + + fn visit_ty(&mut self, ty: &Ty, outer_binder: DebruijnIndex) -> ControlFlow { + match ty.kind(Interner) { + TyKind::Dyn(_) => ControlFlow::Break(()), + _ => ty.super_visit_with(self.as_dyn(), outer_binder), + } + } + } + + ty.visit_with(DynTraitVisitor.as_dyn(), DebruijnIndex::INNERMOST).is_break() +} diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer/unify.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer/unify.rs index 99ad678980987..d38380e4a3af5 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/infer/unify.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer/unify.rs @@ -902,6 +902,10 @@ impl<'a> InferenceTable<'a> { /// Check if given type is `Sized` or not pub(crate) fn is_sized(&mut self, ty: &Ty) -> bool { + // Early return for some obvious types + if matches!(ty.kind(Interner), TyKind::Scalar(..) | TyKind::Ref(..) | TyKind::Raw(..)) { + return true; + } if let Some((AdtId::StructId(id), subst)) = ty.as_adt() { let struct_data = self.db.struct_data(id); if let Some((last_field, _)) = struct_data.variant_data.fields().iter().last() { diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/invalid_cast.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/invalid_cast.rs index 9eb4e618c01e9..90527c578e413 100644 --- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/invalid_cast.rs +++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/invalid_cast.rs @@ -556,6 +556,7 @@ fn unprincipled<'a, 'b>(x: *mut (dyn Send + 'a)) -> *mut (dyn Sync + 'b) { ); } + #[ignore = "issue #18047"] #[test] fn ptr_to_trait_obj_wrap_upcast() { check_diagnostics( @@ -1004,4 +1005,99 @@ fn _slice(bar: &[i32]) -> bool { &["E0308"], ); } + + #[test] + fn trait_upcasting() { + check_diagnostics( + r#" +//- minicore: coerce_unsized, dispatch_from_dyn +#![feature(trait_upcasting)] +trait Foo {} +trait Bar: Foo {} + +impl dyn Bar { + fn bar(&self) { + _ = self as &dyn Foo; + } +} +"#, + ); + } + + #[test] + fn issue_18047() { + check_diagnostics( + r#" +//- minicore: coerce_unsized, dispatch_from_dyn +trait LocalFrom { + fn from(_: T) -> Self; +} +trait LocalInto { + fn into(self) -> T; +} + +impl LocalInto for T +where + U: LocalFrom, +{ + fn into(self) -> U { + U::from(self) + } +} + +impl LocalFrom for T { + fn from(t: T) -> T { + t + } +} + +trait Foo { + type ErrorType; + type Assoc; +} + +trait Bar { + type ErrorType; +} + +struct ErrorLike; + +impl LocalFrom for ErrorLike +where + E: Trait + 'static, +{ + fn from(_: E) -> Self { + loop {} + } +} + +trait Baz { + type Assoc: Bar; + type Error: LocalInto; +} + +impl Baz for T +where + T: Foo, + T::ErrorType: LocalInto, + U: Bar, + ::ErrorType: LocalInto, +{ + type Assoc = U; + type Error = T::ErrorType; +} +struct S; +trait Trait {} +impl Trait for S {} + +fn test() +where + T: Baz, + T::Assoc: 'static, +{ + let _ = &S as &dyn Trait; +} +"#, + ); + } } From 35ce85e0fd6ae70ffb61139c1fcdb739e0ca1d95 Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Mon, 9 Sep 2024 21:09:30 +0300 Subject: [PATCH 0802/2194] handle `GitConfig` for `tools/compiletest` Signed-off-by: onur-ozkan --- src/bootstrap/src/core/build_steps/test.rs | 1 + src/tools/compiletest/src/common.rs | 7 ++++++- src/tools/compiletest/src/header/tests.rs | 1 + src/tools/compiletest/src/lib.rs | 4 +++- 4 files changed, 11 insertions(+), 2 deletions(-) diff --git a/src/bootstrap/src/core/build_steps/test.rs b/src/bootstrap/src/core/build_steps/test.rs index 83f65615c8ded..a7e9352bb1c4c 100644 --- a/src/bootstrap/src/core/build_steps/test.rs +++ b/src/bootstrap/src/core/build_steps/test.rs @@ -2098,6 +2098,7 @@ NOTE: if you're sure you want to do this, please open an issue as to why. In the let git_config = builder.config.git_config(); cmd.arg("--git-repository").arg(git_config.git_repository); cmd.arg("--nightly-branch").arg(git_config.nightly_branch); + cmd.arg("--git-merge-commit-email").arg(git_config.git_merge_commit_email); cmd.force_coloring_in_ci(); #[cfg(feature = "build-metrics")] diff --git a/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs index 773d795f75a72..5c18179b6fe2f 100644 --- a/src/tools/compiletest/src/common.rs +++ b/src/tools/compiletest/src/common.rs @@ -384,6 +384,7 @@ pub struct Config { // Needed both to construct build_helper::git::GitConfig pub git_repository: String, pub nightly_branch: String, + pub git_merge_commit_email: String, /// True if the profiler runtime is enabled for this target. /// Used by the "needs-profiler-support" header in test files. @@ -461,7 +462,11 @@ impl Config { } pub fn git_config(&self) -> GitConfig<'_> { - GitConfig { git_repository: &self.git_repository, nightly_branch: &self.nightly_branch } + GitConfig { + git_repository: &self.git_repository, + nightly_branch: &self.nightly_branch, + git_merge_commit_email: &self.git_merge_commit_email, + } } } diff --git a/src/tools/compiletest/src/header/tests.rs b/src/tools/compiletest/src/header/tests.rs index 29e11e77f1ce1..3a9a7eb911889 100644 --- a/src/tools/compiletest/src/header/tests.rs +++ b/src/tools/compiletest/src/header/tests.rs @@ -148,6 +148,7 @@ impl ConfigBuilder { self.target.as_deref().unwrap_or("x86_64-unknown-linux-gnu"), "--git-repository=", "--nightly-branch=", + "--git-merge-commit-email=", ]; let mut args: Vec = args.iter().map(ToString::to_string).collect(); diff --git a/src/tools/compiletest/src/lib.rs b/src/tools/compiletest/src/lib.rs index 5402e69bc664e..624111d48adfa 100644 --- a/src/tools/compiletest/src/lib.rs +++ b/src/tools/compiletest/src/lib.rs @@ -163,7 +163,8 @@ pub fn parse_config(args: Vec) -> Config { ) .optopt("", "edition", "default Rust edition", "EDITION") .reqopt("", "git-repository", "name of the git repository", "ORG/REPO") - .reqopt("", "nightly-branch", "name of the git branch for nightly", "BRANCH"); + .reqopt("", "nightly-branch", "name of the git branch for nightly", "BRANCH") + .reqopt("", "git-merge-commit-email", "email address used for the merge commits", "EMAIL"); let (argv0, args_) = args.split_first().unwrap(); if args.len() == 1 || args[1] == "-h" || args[1] == "--help" { @@ -346,6 +347,7 @@ pub fn parse_config(args: Vec) -> Config { git_repository: matches.opt_str("git-repository").unwrap(), nightly_branch: matches.opt_str("nightly-branch").unwrap(), + git_merge_commit_email: matches.opt_str("git-merge-commit-email").unwrap(), profiler_support: matches.opt_present("profiler-support"), } From 0a7f9e213448bfbe336bbb6d5f1f9a79961427f9 Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Mon, 9 Sep 2024 21:23:06 +0300 Subject: [PATCH 0803/2194] skip formatting if no files have been modified Signed-off-by: onur-ozkan --- src/bootstrap/src/core/build_steps/format.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/bootstrap/src/core/build_steps/format.rs b/src/bootstrap/src/core/build_steps/format.rs index 91fbc57429a96..bbd81fb570bd5 100644 --- a/src/bootstrap/src/core/build_steps/format.rs +++ b/src/bootstrap/src/core/build_steps/format.rs @@ -200,6 +200,11 @@ pub fn format(build: &Builder<'_>, check: bool, all: bool, paths: &[PathBuf]) { adjective = Some("modified"); match get_modified_rs_files(build) { Ok(Some(files)) => { + if files.is_empty() { + println!("fmt info: No modified files detected for formatting."); + return; + } + for file in files { override_builder.add(&format!("/{file}")).expect(&file); } From 3810386bbe95e989d399a2d46d806bcf7c607c06 Mon Sep 17 00:00:00 2001 From: Paul Menage Date: Tue, 10 Sep 2024 12:19:16 -0700 Subject: [PATCH 0804/2194] Add -Z small-data-threshold This flag allows specifying the threshold size above which LLVM should not consider placing small objects in a .sdata or .sbss section. Support is indicated in the target options via the small-data-threshold-support target option, which can indicate either an LLVM argument or an LLVM module flag. To avoid duplicate specifications in a large number of targets, the default value for support is DefaultForArch, which is translated to a concrete value according to the target's architecture. --- compiler/rustc_codegen_llvm/src/context.rs | 20 +++- compiler/rustc_codegen_llvm/src/llvm_util.rs | 14 ++- compiler/rustc_interface/src/tests.rs | 1 + compiler/rustc_session/messages.ftl | 2 + compiler/rustc_session/src/errors.rs | 6 ++ compiler/rustc_session/src/options.rs | 2 + compiler/rustc_session/src/session.rs | 12 ++- compiler/rustc_target/src/spec/mod.rs | 76 +++++++++++++++ .../compiler-flags/small-data-threshold.md | 20 ++++ tests/assembly/small_data_threshold.rs | 92 +++++++++++++++++++ 10 files changed, 241 insertions(+), 4 deletions(-) create mode 100644 src/doc/unstable-book/src/compiler-flags/small-data-threshold.md create mode 100644 tests/assembly/small_data_threshold.rs diff --git a/compiler/rustc_codegen_llvm/src/context.rs b/compiler/rustc_codegen_llvm/src/context.rs index 01aae24ab56c2..73c2c15717fc1 100644 --- a/compiler/rustc_codegen_llvm/src/context.rs +++ b/compiler/rustc_codegen_llvm/src/context.rs @@ -27,7 +27,7 @@ use rustc_span::source_map::Spanned; use rustc_span::{Span, DUMMY_SP}; use rustc_target::abi::call::FnAbi; use rustc_target::abi::{HasDataLayout, TargetDataLayout, VariantIdx}; -use rustc_target::spec::{HasTargetSpec, RelocModel, Target, TlsModel}; +use rustc_target::spec::{HasTargetSpec, RelocModel, SmallDataThresholdSupport, Target, TlsModel}; use smallvec::SmallVec; use crate::back::write::to_llvm_code_model; @@ -387,6 +387,24 @@ pub(crate) unsafe fn create_module<'ll>( } } + match (sess.opts.unstable_opts.small_data_threshold, sess.target.small_data_threshold_support()) + { + // Set up the small-data optimization limit for architectures that use + // an LLVM module flag to control this. + (Some(threshold), SmallDataThresholdSupport::LlvmModuleFlag(flag)) => { + let flag = SmallCStr::new(flag.as_ref()); + unsafe { + llvm::LLVMRustAddModuleFlagU32( + llmod, + llvm::LLVMModFlagBehavior::Error, + flag.as_c_str().as_ptr(), + threshold as u32, + ) + } + } + _ => (), + }; + // Insert `llvm.ident` metadata. // // On the wasm targets it will get hooked up to the "producer" sections diff --git a/compiler/rustc_codegen_llvm/src/llvm_util.rs b/compiler/rustc_codegen_llvm/src/llvm_util.rs index d55220ba5c3a4..ea0abb1fa53fa 100644 --- a/compiler/rustc_codegen_llvm/src/llvm_util.rs +++ b/compiler/rustc_codegen_llvm/src/llvm_util.rs @@ -14,7 +14,7 @@ use rustc_middle::bug; use rustc_session::config::{PrintKind, PrintRequest}; use rustc_session::Session; use rustc_span::symbol::Symbol; -use rustc_target::spec::{MergeFunctions, PanicStrategy}; +use rustc_target::spec::{MergeFunctions, PanicStrategy, SmallDataThresholdSupport}; use rustc_target::target_features::{RUSTC_SPECIAL_FEATURES, RUSTC_SPECIFIC_FEATURES}; use crate::back::write::create_informational_target_machine; @@ -125,6 +125,18 @@ unsafe fn configure_llvm(sess: &Session) { for arg in sess_args { add(&(*arg), true); } + + match ( + sess.opts.unstable_opts.small_data_threshold, + sess.target.small_data_threshold_support(), + ) { + // Set up the small-data optimization limit for architectures that use + // an LLVM argument to control this. + (Some(threshold), SmallDataThresholdSupport::LlvmArg(arg)) => { + add(&format!("--{arg}={threshold}"), false) + } + _ => (), + }; } if sess.opts.unstable_opts.llvm_time_trace { diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs index 50422df8ee648..baeac6c32f939 100644 --- a/compiler/rustc_interface/src/tests.rs +++ b/compiler/rustc_interface/src/tests.rs @@ -847,6 +847,7 @@ fn test_unstable_options_tracking_hash() { tracked!(share_generics, Some(true)); tracked!(show_span, Some(String::from("abc"))); tracked!(simulate_remapped_rust_src_base, Some(PathBuf::from("/rustc/abc"))); + tracked!(small_data_threshold, Some(16)); tracked!(split_lto_unit, Some(true)); tracked!(src_hash_algorithm, Some(SourceFileHashAlgorithm::Sha1)); tracked!(stack_protector, StackProtector::All); diff --git a/compiler/rustc_session/messages.ftl b/compiler/rustc_session/messages.ftl index 01c371ee49884..a4fbab8477b13 100644 --- a/compiler/rustc_session/messages.ftl +++ b/compiler/rustc_session/messages.ftl @@ -113,6 +113,8 @@ session_split_lto_unit_requires_lto = `-Zsplit-lto-unit` requires `-Clto`, `-Clt session_target_requires_unwind_tables = target requires unwind tables, they cannot be disabled with `-C force-unwind-tables=no` +session_target_small_data_threshold_not_supported = `-Z small-data-threshold` is not supported for target {$target_triple} and will be ignored + session_target_stack_protector_not_supported = `-Z stack-protector={$stack_protector}` is not supported for target {$target_triple} and will be ignored session_unleashed_feature_help_named = skipping check for `{$gate}` feature diff --git a/compiler/rustc_session/src/errors.rs b/compiler/rustc_session/src/errors.rs index 15bbd4ff7bf4b..462e2a97c33da 100644 --- a/compiler/rustc_session/src/errors.rs +++ b/compiler/rustc_session/src/errors.rs @@ -182,6 +182,12 @@ pub(crate) struct StackProtectorNotSupportedForTarget<'a> { pub(crate) target_triple: &'a TargetTriple, } +#[derive(Diagnostic)] +#[diag(session_target_small_data_threshold_not_supported)] +pub(crate) struct SmallDataThresholdNotSupportedForTarget<'a> { + pub(crate) target_triple: &'a TargetTriple, +} + #[derive(Diagnostic)] #[diag(session_branch_protection_requires_aarch64)] pub(crate) struct BranchProtectionRequiresAArch64; diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index a57dc80b3168d..5a6fa25fd3d6a 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -2014,6 +2014,8 @@ written to standard error output)"), simulate_remapped_rust_src_base: Option = (None, parse_opt_pathbuf, [TRACKED], "simulate the effect of remap-debuginfo = true at bootstrapping by remapping path \ to rust's source base directory. only meant for testing purposes"), + small_data_threshold: Option = (None, parse_opt_number, [TRACKED], + "Set the threshold for objects to be stored in a \"small data\" section"), span_debug: bool = (false, parse_bool, [UNTRACKED], "forward proc_macro::Span's `Debug` impl to `Span`"), /// o/w tests have closure@path diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index 70430d82ab55b..387ae1b78c480 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -30,8 +30,8 @@ use rustc_span::source_map::{FilePathMapping, SourceMap}; use rustc_span::{FileNameDisplayPreference, RealFileName, Span, Symbol}; use rustc_target::asm::InlineAsmArch; use rustc_target::spec::{ - CodeModel, DebuginfoKind, PanicStrategy, RelocModel, RelroLevel, SanitizerSet, SplitDebuginfo, - StackProtector, Target, TargetTriple, TlsModel, + CodeModel, DebuginfoKind, PanicStrategy, RelocModel, RelroLevel, SanitizerSet, + SmallDataThresholdSupport, SplitDebuginfo, StackProtector, Target, TargetTriple, TlsModel, }; use crate::code_stats::CodeStats; @@ -1278,6 +1278,14 @@ fn validate_commandline_args_with_session_available(sess: &Session) { } } + if sess.opts.unstable_opts.small_data_threshold.is_some() { + if sess.target.small_data_threshold_support() == SmallDataThresholdSupport::None { + sess.dcx().emit_warn(errors::SmallDataThresholdNotSupportedForTarget { + target_triple: &sess.opts.target_triple, + }) + } + } + if sess.opts.unstable_opts.branch_protection.is_some() && sess.target.arch != "aarch64" { sess.dcx().emit_err(errors::BranchProtectionRequiresAArch64); } diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index c3e7f74c56410..f12e3e595adf6 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -855,6 +855,43 @@ impl ToJson for RelroLevel { } } +#[derive(Clone, Debug, PartialEq, Hash)] +pub enum SmallDataThresholdSupport { + None, + DefaultForArch, + LlvmModuleFlag(StaticCow), + LlvmArg(StaticCow), +} + +impl FromStr for SmallDataThresholdSupport { + type Err = (); + + fn from_str(s: &str) -> Result { + if s == "none" { + Ok(Self::None) + } else if s == "default-for-arch" { + Ok(Self::DefaultForArch) + } else if let Some(flag) = s.strip_prefix("llvm-module-flag=") { + Ok(Self::LlvmModuleFlag(flag.to_string().into())) + } else if let Some(arg) = s.strip_prefix("llvm-arg=") { + Ok(Self::LlvmArg(arg.to_string().into())) + } else { + Err(()) + } + } +} + +impl ToJson for SmallDataThresholdSupport { + fn to_json(&self) -> Value { + match self { + Self::None => "none".to_json(), + Self::DefaultForArch => "default-for-arch".to_json(), + Self::LlvmModuleFlag(flag) => format!("llvm-module-flag={flag}").to_json(), + Self::LlvmArg(arg) => format!("llvm-arg={arg}").to_json(), + } + } +} + #[derive(Clone, Copy, Debug, PartialEq, Hash)] pub enum MergeFunctions { Disabled, @@ -2392,6 +2429,9 @@ pub struct TargetOptions { /// Whether the target supports XRay instrumentation. pub supports_xray: bool, + + /// Whether the targets supports -Z small-data-threshold + small_data_threshold_support: SmallDataThresholdSupport, } /// Add arguments for the given flavor and also for its "twin" flavors @@ -2609,6 +2649,7 @@ impl Default for TargetOptions { entry_name: "main".into(), entry_abi: Conv::C, supports_xray: false, + small_data_threshold_support: SmallDataThresholdSupport::DefaultForArch, } } } @@ -2884,6 +2925,15 @@ impl Target { Some(Ok(())) })).unwrap_or(Ok(())) } ); + ($key_name:ident, SmallDataThresholdSupport) => ( { + obj.remove("small-data-threshold-support").and_then(|o| o.as_str().and_then(|s| { + match s.parse::() { + Ok(support) => base.small_data_threshold_support = support, + _ => return Some(Err(format!("'{s}' is not a valid value for small-data-threshold-support."))), + } + Some(Ok(())) + })).unwrap_or(Ok(())) + } ); ($key_name:ident, PanicStrategy) => ( { let name = (stringify!($key_name)).replace("_", "-"); obj.remove(&name).and_then(|o| o.as_str().and_then(|s| { @@ -3321,6 +3371,7 @@ impl Target { key!(supported_sanitizers, SanitizerSet)?; key!(generate_arange_section, bool); key!(supports_stack_protector, bool); + key!(small_data_threshold_support, SmallDataThresholdSupport)?; key!(entry_name); key!(entry_abi, Conv)?; key!(supports_xray, bool); @@ -3415,6 +3466,30 @@ impl Target { } } } + + /// Return the target's small data threshold support, converting + /// `DefaultForArch` into a concrete value. + pub fn small_data_threshold_support(&self) -> SmallDataThresholdSupport { + match &self.options.small_data_threshold_support { + // Avoid having to duplicate the small data support in every + // target file by supporting a default value for each + // architecture. + SmallDataThresholdSupport::DefaultForArch => match self.arch.as_ref() { + "mips" | "mips64" | "mips32r6" => { + SmallDataThresholdSupport::LlvmArg("mips-ssection-threshold".into()) + } + "hexagon" => { + SmallDataThresholdSupport::LlvmArg("hexagon-small-data-threshold".into()) + } + "m68k" => SmallDataThresholdSupport::LlvmArg("m68k-ssection-threshold".into()), + "riscv32" | "riscv64" => { + SmallDataThresholdSupport::LlvmModuleFlag("SmallDataLimit".into()) + } + _ => SmallDataThresholdSupport::None, + }, + s => s.clone(), + } + } } impl ToJson for Target { @@ -3577,6 +3652,7 @@ impl ToJson for Target { target_option_val!(c_enum_min_bits); target_option_val!(generate_arange_section); target_option_val!(supports_stack_protector); + target_option_val!(small_data_threshold_support); target_option_val!(entry_name); target_option_val!(entry_abi); target_option_val!(supports_xray); diff --git a/src/doc/unstable-book/src/compiler-flags/small-data-threshold.md b/src/doc/unstable-book/src/compiler-flags/small-data-threshold.md new file mode 100644 index 0000000000000..1734433181e38 --- /dev/null +++ b/src/doc/unstable-book/src/compiler-flags/small-data-threshold.md @@ -0,0 +1,20 @@ +# `small-data-threshold` + +----------------------- + +This flag controls the maximum static variable size that may be included in the +"small data sections" (.sdata, .sbss) supported by some architectures (RISCV, +MIPS, M68K, Hexagon). Can be set to `0` to disable the use of small data +sections. + +Target support is indicated by the `small_data_threshold_support` target +option which can be: + +- `none` (`SmallDataThresholdSupport::None`) for no support +- `default-for-arch` (`SmallDataThresholdSupport::DefaultForArch`) which + is automatically translated into an appropriate value for the target. +- `llvm-module-flag=` + (`SmallDataThresholdSupport::LlvmModuleFlag`) for specifying the + threshold via an LLVM module flag +- `llvm-arg=` (`SmallDataThresholdSupport::LlvmArg`) for + specifying the threshold via an LLVM argument. diff --git a/tests/assembly/small_data_threshold.rs b/tests/assembly/small_data_threshold.rs new file mode 100644 index 0000000000000..b0c0a63ca492d --- /dev/null +++ b/tests/assembly/small_data_threshold.rs @@ -0,0 +1,92 @@ +// Test for -Z small_data_threshold=... +//@ revisions: RISCV MIPS HEXAGON M68K +//@ assembly-output: emit-asm +//@ compile-flags: -Z small_data_threshold=4 +//@ [RISCV] compile-flags: --target=riscv32im-unknown-none-elf +//@ [RISCV] needs-llvm-components: riscv +//@ [MIPS] compile-flags: --target=mips-unknown-linux-uclibc -C relocation-model=static +//@ [MIPS] compile-flags: -C llvm-args=-mgpopt -C llvm-args=-mlocal-sdata +//@ [MIPS] compile-flags: -C target-feature=+noabicalls +//@ [MIPS] needs-llvm-components: mips +//@ [HEXAGON] compile-flags: --target=hexagon-unknown-linux-musl -C target-feature=+small-data +//@ [HEXAGON] compile-flags: -C llvm-args=--hexagon-statics-in-small-data +//@ [HEXAGON] needs-llvm-components: hexagon +//@ [M68K] compile-flags: --target=m68k-unknown-linux-gnu +//@ [M68K] needs-llvm-components: m68k + +#![feature(no_core, lang_items)] +#![no_std] +#![no_core] +#![crate_type = "lib"] + +#[lang = "sized"] +trait Sized {} + +#[lang = "drop_in_place"] +fn drop_in_place(_: *mut T) {} + +#[used] +#[no_mangle] +// U is below the threshold, should be in sdata +static mut U: u16 = 123; + +#[used] +#[no_mangle] +// V is below the threshold, should be in sbss +static mut V: u16 = 0; + +#[used] +#[no_mangle] +// W is at the threshold, should be in sdata +static mut W: u32 = 123; + +#[used] +#[no_mangle] +// X is at the threshold, should be in sbss +static mut X: u32 = 0; + +#[used] +#[no_mangle] +// Y is over the threshold, should be in its own .data section +static mut Y: u64 = 123; + +#[used] +#[no_mangle] +// Z is over the threshold, should be in its own .bss section +static mut Z: u64 = 0; + +// Currently, only MIPS and RISCV successfully put any objects in the small data +// sections so the U/V/W/X tests are skipped on Hexagon and M68K + +//@ RISCV: .section .sdata, +//@ RISCV-NOT: .section +//@ RISCV: U: +//@ RISCV: .section .sbss +//@ RISCV-NOT: .section +//@ RISCV: V: +//@ RISCV: .section .sdata +//@ RISCV-NOT: .section +//@ RISCV: W: +//@ RISCV: .section .sbss +//@ RISCV-NOT: .section +//@ RISCV: X: + +//@ MIPS: .section .sdata, +//@ MIPS-NOT: .section +//@ MIPS: U: +//@ MIPS: .section .sbss +//@ MIPS-NOT: .section +//@ MIPS: V: +//@ MIPS: .section .sdata +//@ MIPS-NOT: .section +//@ MIPS: W: +//@ MIPS: .section .sbss +//@ MIPS-NOT: .section +//@ MIPS: X: + +//@ CHECK: .section .data.Y, +//@ CHECK-NOT: .section +//@ CHECK: Y: +//@ CHECK: .section .bss.Z, +//@ CHECK-NOT: .section +//@ CHECK: Z: From f93df1f7dcea3588620b77e2a0eaac12b46a7678 Mon Sep 17 00:00:00 2001 From: Ding Xiang Fei Date: Tue, 24 Jan 2023 16:06:35 +0800 Subject: [PATCH 0805/2194] rescope temp lifetime in let-chain into IfElse apply rules by span edition --- .../src/diagnostics/conflict_errors.rs | 29 +- .../src/diagnostics/explain_borrow.rs | 95 +++++- compiler/rustc_feature/src/unstable.rs | 2 + .../rustc_hir_analysis/src/check/region.rs | 14 +- compiler/rustc_lint/messages.ftl | 5 + compiler/rustc_lint/src/if_let_rescope.rs | 312 ++++++++++++++++++ compiler/rustc_lint/src/lib.rs | 3 + compiler/rustc_middle/src/middle/region.rs | 6 + compiler/rustc_middle/src/mir/mod.rs | 3 + compiler/rustc_middle/src/ty/rvalue_scopes.rs | 10 +- .../rustc_mir_build/src/build/expr/as_temp.rs | 10 + compiler/rustc_mir_build/src/thir/cx/expr.rs | 8 +- compiler/rustc_span/src/symbol.rs | 1 + tests/ui/drop/drop_order.rs | 22 ++ tests/ui/drop/drop_order_if_let_rescope.rs | 122 +++++++ .../if-let-rescope-borrowck-suggestions.fixed | 26 ++ .../if-let-rescope-borrowck-suggestions.rs | 25 ++ ...if-let-rescope-borrowck-suggestions.stderr | 26 ++ tests/ui/drop/lint-if-let-rescope-gated.rs | 31 ++ ...let-rescope-gated.with_feature_gate.stderr | 30 ++ .../ui/drop/lint-if-let-rescope-with-macro.rs | 41 +++ .../lint-if-let-rescope-with-macro.stderr | 39 +++ tests/ui/drop/lint-if-let-rescope.fixed | 48 +++ tests/ui/drop/lint-if-let-rescope.rs | 48 +++ tests/ui/drop/lint-if-let-rescope.stderr | 74 +++++ .../feature-gate-if-let-rescope.rs | 27 ++ .../feature-gate-if-let-rescope.stderr | 18 + tests/ui/mir/mir_let_chains_drop_order.rs | 41 ++- ...=> issue-54556-niconii.edition2021.stderr} | 2 +- tests/ui/nll/issue-54556-niconii.rs | 19 +- 30 files changed, 1102 insertions(+), 35 deletions(-) create mode 100644 compiler/rustc_lint/src/if_let_rescope.rs create mode 100644 tests/ui/drop/drop_order_if_let_rescope.rs create mode 100644 tests/ui/drop/if-let-rescope-borrowck-suggestions.fixed create mode 100644 tests/ui/drop/if-let-rescope-borrowck-suggestions.rs create mode 100644 tests/ui/drop/if-let-rescope-borrowck-suggestions.stderr create mode 100644 tests/ui/drop/lint-if-let-rescope-gated.rs create mode 100644 tests/ui/drop/lint-if-let-rescope-gated.with_feature_gate.stderr create mode 100644 tests/ui/drop/lint-if-let-rescope-with-macro.rs create mode 100644 tests/ui/drop/lint-if-let-rescope-with-macro.stderr create mode 100644 tests/ui/drop/lint-if-let-rescope.fixed create mode 100644 tests/ui/drop/lint-if-let-rescope.rs create mode 100644 tests/ui/drop/lint-if-let-rescope.stderr create mode 100644 tests/ui/feature-gates/feature-gate-if-let-rescope.rs create mode 100644 tests/ui/feature-gates/feature-gate-if-let-rescope.stderr rename tests/ui/nll/{issue-54556-niconii.stderr => issue-54556-niconii.edition2021.stderr} (96%) diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index a47518fca3f9b..215e0476f01f7 100644 --- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs @@ -1999,19 +1999,32 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { ) { let used_in_call = matches!( explanation, - BorrowExplanation::UsedLater(LaterUseKind::Call | LaterUseKind::Other, _call_span, _) + BorrowExplanation::UsedLater( + _, + LaterUseKind::Call | LaterUseKind::Other, + _call_span, + _ + ) ); if !used_in_call { debug!("not later used in call"); return; } + if matches!( + self.body.local_decls[issued_borrow.borrowed_place.local].local_info(), + LocalInfo::IfThenRescopeTemp { .. } + ) { + // A better suggestion will be issued by the `if_let_rescope` lint + return; + } - let use_span = - if let BorrowExplanation::UsedLater(LaterUseKind::Other, use_span, _) = explanation { - Some(use_span) - } else { - None - }; + let use_span = if let BorrowExplanation::UsedLater(_, LaterUseKind::Other, use_span, _) = + explanation + { + Some(use_span) + } else { + None + }; let outer_call_loc = if let TwoPhaseActivation::ActivatedAt(loc) = issued_borrow.activation_location { @@ -2862,7 +2875,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { // and `move` will not help here. ( Some(name), - BorrowExplanation::UsedLater(LaterUseKind::ClosureCapture, var_or_use_span, _), + BorrowExplanation::UsedLater(_, LaterUseKind::ClosureCapture, var_or_use_span, _), ) if borrow_spans.for_coroutine() || borrow_spans.for_closure() => self .report_escaping_closure_capture( borrow_spans, diff --git a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs index 419e72df00b02..22327d2ba0d46 100644 --- a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs +++ b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs @@ -30,7 +30,7 @@ use crate::{MirBorrowckCtxt, WriteKind}; #[derive(Debug)] pub(crate) enum BorrowExplanation<'tcx> { - UsedLater(LaterUseKind, Span, Option), + UsedLater(Local, LaterUseKind, Span, Option), UsedLaterInLoop(LaterUseKind, Span, Option), UsedLaterWhenDropped { drop_loc: Location, @@ -99,7 +99,12 @@ impl<'tcx> BorrowExplanation<'tcx> { } } match *self { - BorrowExplanation::UsedLater(later_use_kind, var_or_use_span, path_span) => { + BorrowExplanation::UsedLater( + dropped_local, + later_use_kind, + var_or_use_span, + path_span, + ) => { let message = match later_use_kind { LaterUseKind::TraitCapture => "captured here by trait object", LaterUseKind::ClosureCapture => "captured here by closure", @@ -107,9 +112,26 @@ impl<'tcx> BorrowExplanation<'tcx> { LaterUseKind::FakeLetRead => "stored here", LaterUseKind::Other => "used here", }; - // We can use `var_or_use_span` if either `path_span` is not present, or both spans are the same - if path_span.map(|path_span| path_span == var_or_use_span).unwrap_or(true) { - if borrow_span.map(|sp| !sp.overlaps(var_or_use_span)).unwrap_or(true) { + let local_decl = &body.local_decls[dropped_local]; + + if let &LocalInfo::IfThenRescopeTemp { if_then } = local_decl.local_info() + && let Some((_, hir::Node::Expr(expr))) = tcx.hir().parent_iter(if_then).next() + && let hir::ExprKind::If(cond, conseq, alt) = expr.kind + && let hir::ExprKind::Let(&hir::LetExpr { + span: _, + pat, + init, + // FIXME(#101728): enable rewrite when type ascription is stabilized again + ty: None, + recovered: _, + }) = cond.kind + && pat.span.can_be_used_for_suggestions() + && let Ok(pat) = tcx.sess.source_map().span_to_snippet(pat.span) + { + suggest_rewrite_if_let(expr, &pat, init, conseq, alt, err); + } else if path_span.map_or(true, |path_span| path_span == var_or_use_span) { + // We can use `var_or_use_span` if either `path_span` is not present, or both spans are the same + if borrow_span.map_or(true, |sp| !sp.overlaps(var_or_use_span)) { err.span_label( var_or_use_span, format!("{borrow_desc}borrow later {message}"), @@ -255,6 +277,22 @@ impl<'tcx> BorrowExplanation<'tcx> { Applicability::MaybeIncorrect, ); }; + } else if let &LocalInfo::IfThenRescopeTemp { if_then } = + local_decl.local_info() + && let hir::Node::Expr(expr) = tcx.hir_node(if_then) + && let hir::ExprKind::If(cond, conseq, alt) = expr.kind + && let hir::ExprKind::Let(&hir::LetExpr { + span: _, + pat, + init, + // FIXME(#101728): enable rewrite when type ascription is stabilized again + ty: None, + recovered: _, + }) = cond.kind + && pat.span.can_be_used_for_suggestions() + && let Ok(pat) = tcx.sess.source_map().span_to_snippet(pat.span) + { + suggest_rewrite_if_let(expr, &pat, init, conseq, alt, err); } } } @@ -390,6 +428,38 @@ impl<'tcx> BorrowExplanation<'tcx> { } } +fn suggest_rewrite_if_let<'tcx>( + expr: &hir::Expr<'tcx>, + pat: &str, + init: &hir::Expr<'tcx>, + conseq: &hir::Expr<'tcx>, + alt: Option<&hir::Expr<'tcx>>, + err: &mut Diag<'_>, +) { + err.span_note( + conseq.span.shrink_to_hi(), + "lifetime for temporaries generated in `if let`s have been shorted in Edition 2024", + ); + if expr.span.can_be_used_for_suggestions() && conseq.span.can_be_used_for_suggestions() { + let mut sugg = vec![ + (expr.span.shrink_to_lo().between(init.span), "match ".into()), + (conseq.span.shrink_to_lo(), format!(" {{ {pat} => ")), + ]; + let expr_end = expr.span.shrink_to_hi(); + if let Some(alt) = alt { + sugg.push((conseq.span.between(alt.span), format!(" _ => "))); + sugg.push((expr_end, "}".into())); + } else { + sugg.push((expr_end, " _ => {} }".into())); + } + err.multipart_suggestion( + "consider rewriting the `if` into `match` which preserves the extended lifetime", + sugg, + Applicability::MachineApplicable, + ); + } +} + impl<'tcx> MirBorrowckCtxt<'_, '_, 'tcx> { fn free_region_constraint_info( &self, @@ -465,14 +535,21 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, 'tcx> { .or_else(|| self.borrow_spans(span, location)); if use_in_later_iteration_of_loop { - let later_use = self.later_use_kind(borrow, spans, use_location); - BorrowExplanation::UsedLaterInLoop(later_use.0, later_use.1, later_use.2) + let (later_use_kind, var_or_use_span, path_span) = + self.later_use_kind(borrow, spans, use_location); + BorrowExplanation::UsedLaterInLoop(later_use_kind, var_or_use_span, path_span) } else { // Check if the location represents a `FakeRead`, and adapt the error // message to the `FakeReadCause` it is from: in particular, // the ones inserted in optimized `let var = ` patterns. - let later_use = self.later_use_kind(borrow, spans, location); - BorrowExplanation::UsedLater(later_use.0, later_use.1, later_use.2) + let (later_use_kind, var_or_use_span, path_span) = + self.later_use_kind(borrow, spans, location); + BorrowExplanation::UsedLater( + borrow.borrowed_place.local, + later_use_kind, + var_or_use_span, + path_span, + ) } } diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index 3254dab9a0344..1359b6248dcb0 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -497,6 +497,8 @@ declare_features! ( (unstable, half_open_range_patterns_in_slices, "1.66.0", Some(67264)), /// Allows `if let` guard in match arms. (unstable, if_let_guard, "1.47.0", Some(51114)), + /// Rescoping temporaries in `if let` to align with Rust 2024. + (unstable, if_let_rescope, "CURRENT_RUSTC_VERSION", Some(124085)), /// Allows `impl Trait` to be used inside associated types (RFC 2515). (unstable, impl_trait_in_assoc_type, "1.70.0", Some(63063)), /// Allows `impl Trait` as output type in `Fn` traits in return position of functions. diff --git a/compiler/rustc_hir_analysis/src/check/region.rs b/compiler/rustc_hir_analysis/src/check/region.rs index 2d6147cff2a5a..33e58a92e3755 100644 --- a/compiler/rustc_hir_analysis/src/check/region.rs +++ b/compiler/rustc_hir_analysis/src/check/region.rs @@ -472,7 +472,12 @@ fn resolve_expr<'tcx>(visitor: &mut RegionResolutionVisitor<'tcx>, expr: &'tcx h hir::ExprKind::If(cond, then, Some(otherwise)) => { let expr_cx = visitor.cx; - visitor.enter_scope(Scope { id: then.hir_id.local_id, data: ScopeData::IfThen }); + let data = if expr.span.at_least_rust_2024() && visitor.tcx.features().if_let_rescope { + ScopeData::IfThenRescope + } else { + ScopeData::IfThen + }; + visitor.enter_scope(Scope { id: then.hir_id.local_id, data }); visitor.cx.var_parent = visitor.cx.parent; visitor.visit_expr(cond); visitor.visit_expr(then); @@ -482,7 +487,12 @@ fn resolve_expr<'tcx>(visitor: &mut RegionResolutionVisitor<'tcx>, expr: &'tcx h hir::ExprKind::If(cond, then, None) => { let expr_cx = visitor.cx; - visitor.enter_scope(Scope { id: then.hir_id.local_id, data: ScopeData::IfThen }); + let data = if expr.span.at_least_rust_2024() && visitor.tcx.features().if_let_rescope { + ScopeData::IfThenRescope + } else { + ScopeData::IfThen + }; + visitor.enter_scope(Scope { id: then.hir_id.local_id, data }); visitor.cx.var_parent = visitor.cx.parent; visitor.visit_expr(cond); visitor.visit_expr(then); diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl index 7d4dee45c261b..1f8dca337fc8e 100644 --- a/compiler/rustc_lint/messages.ftl +++ b/compiler/rustc_lint/messages.ftl @@ -334,6 +334,11 @@ lint_identifier_uncommon_codepoints = identifier contains {$codepoints_len -> *[other] {" "}{$identifier_type} } Unicode general security profile +lint_if_let_rescope = `if let` assigns a shorter lifetime since Edition 2024 + .label = this value has a significant drop implementation which may observe a major change in drop order and requires your discretion + .help = the value is now dropped here in Edition 2024 + .suggestion = rewrite this `if let` into a `match` with a single arm to preserve the drop order up to Edition 2021 + lint_ignored_unless_crate_specified = {$level}({$name}) is ignored unless specified at crate level lint_ill_formed_attribute_input = {$num_suggestions -> diff --git a/compiler/rustc_lint/src/if_let_rescope.rs b/compiler/rustc_lint/src/if_let_rescope.rs new file mode 100644 index 0000000000000..143965ae58f7e --- /dev/null +++ b/compiler/rustc_lint/src/if_let_rescope.rs @@ -0,0 +1,312 @@ +use std::ops::ControlFlow; + +use hir::intravisit::Visitor; +use rustc_ast::Recovered; +use rustc_hir as hir; +use rustc_macros::{LintDiagnostic, Subdiagnostic}; +use rustc_session::lint::FutureIncompatibilityReason; +use rustc_session::{declare_lint, declare_lint_pass}; +use rustc_span::edition::Edition; +use rustc_span::Span; + +use crate::{LateContext, LateLintPass}; + +declare_lint! { + /// The `if_let_rescope` lint detects cases where a temporary value with + /// significant drop is generated on the right hand side of `if let` + /// and suggests a rewrite into `match` when possible. + /// + /// ### Example + /// + /// ```rust,edition2021 + /// #![feature(if_let_rescope)] + /// #![warn(if_let_rescope)] + /// #![allow(unused_variables)] + /// + /// struct Droppy; + /// impl Drop for Droppy { + /// fn drop(&mut self) { + /// // Custom destructor, including this `drop` implementation, is considered + /// // significant. + /// // Rust does not check whether this destructor emits side-effects that can + /// // lead to observable change in program semantics, when the drop order changes. + /// // Rust biases to be on the safe side, so that you can apply discretion whether + /// // this change indeed breaches any contract or specification that your code needs + /// // to honour. + /// println!("dropped"); + /// } + /// } + /// impl Droppy { + /// fn get(&self) -> Option { + /// None + /// } + /// } + /// + /// fn main() { + /// if let Some(value) = Droppy.get() { + /// // do something + /// } else { + /// // do something else + /// } + /// } + /// ``` + /// + /// {{produces}} + /// + /// ### Explanation + /// + /// With Edition 2024, temporaries generated while evaluating `if let`s + /// will be dropped before the `else` block. + /// This lint captures a possible change in runtime behaviour due to + /// a change in sequence of calls to significant `Drop::drop` destructors. + /// + /// A significant [`Drop::drop`](https://doc.rust-lang.org/std/ops/trait.Drop.html) + /// destructor here refers to an explicit, arbitrary implementation of the `Drop` trait on the type + /// with exceptions including `Vec`, `Box`, `Rc`, `BTreeMap` and `HashMap` + /// that are marked by the compiler otherwise so long that the generic types have + /// no significant destructor recursively. + /// In other words, a type has a significant drop destructor when it has a `Drop` implementation + /// or its destructor invokes a significant destructor on a type. + /// Since we cannot completely reason about the change by just inspecting the existence of + /// a significant destructor, this lint remains only a suggestion and is set to `allow` by default. + /// + /// Whenever possible, a rewrite into an equivalent `match` expression that + /// observe the same order of calls to such destructors is proposed by this lint. + /// Authors may take their own discretion whether the rewrite suggestion shall be + /// accepted, or rejected to continue the use of the `if let` expression. + pub IF_LET_RESCOPE, + Allow, + "`if let` assigns a shorter lifetime to temporary values being pattern-matched against in Edition 2024 and \ + rewriting in `match` is an option to preserve the semantics up to Edition 2021", + @future_incompatible = FutureIncompatibleInfo { + reason: FutureIncompatibilityReason::EditionSemanticsChange(Edition::Edition2024), + reference: "issue #124085 ", + }; +} + +declare_lint_pass!( + /// Lint for potential change in program semantics of `if let`s + IfLetRescope => [IF_LET_RESCOPE] +); + +impl<'tcx> LateLintPass<'tcx> for IfLetRescope { + fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'tcx>) { + if !expr.span.edition().at_least_rust_2021() || !cx.tcx.features().if_let_rescope { + return; + } + let hir::ExprKind::If(cond, conseq, alt) = expr.kind else { return }; + let hir::ExprKind::Let(&hir::LetExpr { + span, + pat, + init, + ty: ty_ascription, + recovered: Recovered::No, + }) = cond.kind + else { + return; + }; + let source_map = cx.tcx.sess.source_map(); + let expr_end = expr.span.shrink_to_hi(); + let if_let_pat = expr.span.shrink_to_lo().between(init.span); + let before_conseq = conseq.span.shrink_to_lo(); + let lifetime_end = source_map.end_point(conseq.span); + + if let ControlFlow::Break(significant_dropper) = + (FindSignificantDropper { cx }).visit_expr(init) + { + let lint_without_suggestion = || { + cx.tcx.emit_node_span_lint( + IF_LET_RESCOPE, + expr.hir_id, + span, + IfLetRescopeRewrite { significant_dropper, lifetime_end, sugg: None }, + ) + }; + if ty_ascription.is_some() + || !expr.span.can_be_used_for_suggestions() + || !pat.span.can_be_used_for_suggestions() + { + // Our `match` rewrites does not support type ascription, + // so we just bail. + // Alternatively when the span comes from proc macro expansion, + // we will also bail. + // FIXME(#101728): change this when type ascription syntax is stabilized again + lint_without_suggestion(); + } else { + let Ok(pat) = source_map.span_to_snippet(pat.span) else { + lint_without_suggestion(); + return; + }; + if let Some(alt) = alt { + let alt_start = conseq.span.between(alt.span); + if !alt_start.can_be_used_for_suggestions() { + lint_without_suggestion(); + return; + } + cx.tcx.emit_node_span_lint( + IF_LET_RESCOPE, + expr.hir_id, + span, + IfLetRescopeRewrite { + significant_dropper, + lifetime_end, + sugg: Some(IfLetRescopeRewriteSuggestion::WithElse { + if_let_pat, + before_conseq, + pat, + expr_end, + alt_start, + }), + }, + ); + } else { + cx.tcx.emit_node_span_lint( + IF_LET_RESCOPE, + expr.hir_id, + span, + IfLetRescopeRewrite { + significant_dropper, + lifetime_end, + sugg: Some(IfLetRescopeRewriteSuggestion::WithoutElse { + if_let_pat, + before_conseq, + pat, + expr_end, + }), + }, + ); + } + } + } + } +} + +#[derive(LintDiagnostic)] +#[diag(lint_if_let_rescope)] +struct IfLetRescopeRewrite { + #[label] + significant_dropper: Span, + #[help] + lifetime_end: Span, + #[subdiagnostic] + sugg: Option, +} + +#[derive(Subdiagnostic)] +enum IfLetRescopeRewriteSuggestion { + #[multipart_suggestion(lint_suggestion, applicability = "machine-applicable")] + WithElse { + #[suggestion_part(code = "match ")] + if_let_pat: Span, + #[suggestion_part(code = " {{ {pat} => ")] + before_conseq: Span, + pat: String, + #[suggestion_part(code = "}}")] + expr_end: Span, + #[suggestion_part(code = " _ => ")] + alt_start: Span, + }, + #[multipart_suggestion(lint_suggestion, applicability = "machine-applicable")] + WithoutElse { + #[suggestion_part(code = "match ")] + if_let_pat: Span, + #[suggestion_part(code = " {{ {pat} => ")] + before_conseq: Span, + pat: String, + #[suggestion_part(code = " _ => {{}} }}")] + expr_end: Span, + }, +} + +struct FindSignificantDropper<'tcx, 'a> { + cx: &'a LateContext<'tcx>, +} + +impl<'tcx, 'a> Visitor<'tcx> for FindSignificantDropper<'tcx, 'a> { + type Result = ControlFlow; + + fn visit_expr(&mut self, expr: &'tcx hir::Expr<'tcx>) -> Self::Result { + if self + .cx + .typeck_results() + .expr_ty(expr) + .has_significant_drop(self.cx.tcx, self.cx.param_env) + { + return ControlFlow::Break(expr.span); + } + match expr.kind { + hir::ExprKind::ConstBlock(_) + | hir::ExprKind::Lit(_) + | hir::ExprKind::Path(_) + | hir::ExprKind::Assign(_, _, _) + | hir::ExprKind::AssignOp(_, _, _) + | hir::ExprKind::Break(_, _) + | hir::ExprKind::Continue(_) + | hir::ExprKind::Ret(_) + | hir::ExprKind::Become(_) + | hir::ExprKind::InlineAsm(_) + | hir::ExprKind::OffsetOf(_, _) + | hir::ExprKind::Repeat(_, _) + | hir::ExprKind::Err(_) + | hir::ExprKind::Struct(_, _, _) + | hir::ExprKind::Closure(_) + | hir::ExprKind::Block(_, _) + | hir::ExprKind::DropTemps(_) + | hir::ExprKind::Loop(_, _, _, _) => ControlFlow::Continue(()), + + hir::ExprKind::Tup(exprs) | hir::ExprKind::Array(exprs) => { + for expr in exprs { + self.visit_expr(expr)?; + } + ControlFlow::Continue(()) + } + hir::ExprKind::Call(callee, args) => { + self.visit_expr(callee)?; + for expr in args { + self.visit_expr(expr)?; + } + ControlFlow::Continue(()) + } + hir::ExprKind::MethodCall(_, receiver, args, _) => { + self.visit_expr(receiver)?; + for expr in args { + self.visit_expr(expr)?; + } + ControlFlow::Continue(()) + } + hir::ExprKind::Index(left, right, _) | hir::ExprKind::Binary(_, left, right) => { + self.visit_expr(left)?; + self.visit_expr(right) + } + hir::ExprKind::Unary(_, expr) + | hir::ExprKind::Cast(expr, _) + | hir::ExprKind::Type(expr, _) + | hir::ExprKind::Yield(expr, _) + | hir::ExprKind::AddrOf(_, _, expr) + | hir::ExprKind::Match(expr, _, _) + | hir::ExprKind::Field(expr, _) + | hir::ExprKind::Let(&hir::LetExpr { + init: expr, + span: _, + pat: _, + ty: _, + recovered: Recovered::No, + }) => self.visit_expr(expr), + hir::ExprKind::Let(_) => ControlFlow::Continue(()), + + hir::ExprKind::If(cond, _, _) => { + if let hir::ExprKind::Let(hir::LetExpr { + init, + span: _, + pat: _, + ty: _, + recovered: Recovered::No, + }) = cond.kind + { + self.visit_expr(init)?; + } + ControlFlow::Continue(()) + } + } + } +} diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs index a9627e9b78907..58b51240a9097 100644 --- a/compiler/rustc_lint/src/lib.rs +++ b/compiler/rustc_lint/src/lib.rs @@ -56,6 +56,7 @@ mod expect; mod for_loops_over_fallibles; mod foreign_modules; pub mod hidden_unicode_codepoints; +mod if_let_rescope; mod impl_trait_overcaptures; mod internal; mod invalid_from_utf8; @@ -94,6 +95,7 @@ use drop_forget_useless::*; use enum_intrinsics_non_enums::EnumIntrinsicsNonEnums; use for_loops_over_fallibles::*; use hidden_unicode_codepoints::*; +use if_let_rescope::IfLetRescope; use impl_trait_overcaptures::ImplTraitOvercaptures; use internal::*; use invalid_from_utf8::*; @@ -243,6 +245,7 @@ late_lint_methods!( NonLocalDefinitions: NonLocalDefinitions::default(), ImplTraitOvercaptures: ImplTraitOvercaptures, TailExprDropOrder: TailExprDropOrder, + IfLetRescope: IfLetRescope, ] ] ); diff --git a/compiler/rustc_middle/src/middle/region.rs b/compiler/rustc_middle/src/middle/region.rs index 6ef1801717c81..999743ed73b84 100644 --- a/compiler/rustc_middle/src/middle/region.rs +++ b/compiler/rustc_middle/src/middle/region.rs @@ -96,6 +96,7 @@ impl fmt::Debug for Scope { ScopeData::Arguments => write!(fmt, "Arguments({:?})", self.id), ScopeData::Destruction => write!(fmt, "Destruction({:?})", self.id), ScopeData::IfThen => write!(fmt, "IfThen({:?})", self.id), + ScopeData::IfThenRescope => write!(fmt, "IfThen[edition2024]({:?})", self.id), ScopeData::Remainder(fsi) => write!( fmt, "Remainder {{ block: {:?}, first_statement_index: {}}}", @@ -126,6 +127,11 @@ pub enum ScopeData { /// Used for variables introduced in an if-let expression. IfThen, + /// Scope of the condition and then block of an if expression + /// Used for variables introduced in an if-let expression, + /// whose lifetimes do not cross beyond this scope. + IfThenRescope, + /// Scope following a `let id = expr;` binding in a block. Remainder(FirstStatementIndex), } diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index 081a23b6ff317..557d2b29e75be 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -1084,6 +1084,9 @@ pub enum LocalInfo<'tcx> { /// (with no intervening statement context). // FIXME(matthewjasper) Don't store in this in `Body` BlockTailTemp(BlockTailInfo), + /// A temporary created during evaluating `if` predicate, possibly for pattern matching for `let`s, + /// and subject to Edition 2024 temporary lifetime rules + IfThenRescopeTemp { if_then: HirId }, /// A temporary created during the pass `Derefer` to avoid it's retagging DerefTemp, /// A temporary created for borrow checking. diff --git a/compiler/rustc_middle/src/ty/rvalue_scopes.rs b/compiler/rustc_middle/src/ty/rvalue_scopes.rs index bcab54cf8bad0..37dcf7c0d649f 100644 --- a/compiler/rustc_middle/src/ty/rvalue_scopes.rs +++ b/compiler/rustc_middle/src/ty/rvalue_scopes.rs @@ -41,7 +41,15 @@ impl RvalueScopes { debug!("temporary_scope({expr_id:?}) = {id:?} [enclosing]"); return Some(id); } - _ => id = p, + ScopeData::IfThenRescope => { + debug!("temporary_scope({expr_id:?}) = {p:?} [enclosing]"); + return Some(p); + } + ScopeData::Node + | ScopeData::CallSite + | ScopeData::Arguments + | ScopeData::IfThen + | ScopeData::Remainder(_) => id = p, } } diff --git a/compiler/rustc_mir_build/src/build/expr/as_temp.rs b/compiler/rustc_mir_build/src/build/expr/as_temp.rs index af5940ff50e61..b8b5e4634ed89 100644 --- a/compiler/rustc_mir_build/src/build/expr/as_temp.rs +++ b/compiler/rustc_mir_build/src/build/expr/as_temp.rs @@ -1,7 +1,9 @@ //! See docs in build/expr/mod.rs use rustc_data_structures::stack::ensure_sufficient_stack; +use rustc_hir::HirId; use rustc_middle::middle::region; +use rustc_middle::middle::region::{Scope, ScopeData}; use rustc_middle::mir::*; use rustc_middle::thir::*; use tracing::{debug, instrument}; @@ -73,11 +75,19 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { _ if let Some(tail_info) = this.block_context.currently_in_block_tail() => { LocalInfo::BlockTailTemp(tail_info) } + + _ if let Some(Scope { data: ScopeData::IfThenRescope, id }) = temp_lifetime => { + LocalInfo::IfThenRescopeTemp { + if_then: HirId { owner: this.hir_id.owner, local_id: id }, + } + } + _ => LocalInfo::Boring, }; **local_decl.local_info.as_mut().assert_crate_local() = local_info; this.local_decls.push(local_decl) }; + debug!(?temp); if deduplicate_temps { this.fixed_temps.insert(expr_id, temp); } diff --git a/compiler/rustc_mir_build/src/thir/cx/expr.rs b/compiler/rustc_mir_build/src/thir/cx/expr.rs index 89f98a40201e7..aa8ccc8b7ddd6 100644 --- a/compiler/rustc_mir_build/src/thir/cx/expr.rs +++ b/compiler/rustc_mir_build/src/thir/cx/expr.rs @@ -706,7 +706,13 @@ impl<'tcx> Cx<'tcx> { hir::ExprKind::If(cond, then, else_opt) => ExprKind::If { if_then_scope: region::Scope { id: then.hir_id.local_id, - data: region::ScopeData::IfThen, + data: { + if expr.span.at_least_rust_2024() && tcx.features().if_let_rescope { + region::ScopeData::IfThenRescope + } else { + region::ScopeData::IfThen + } + }, }, cond: self.mirror_expr(cond), then: self.mirror_expr(then), diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index d5240a05310b6..d340b56fbe46b 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1017,6 +1017,7 @@ symbols! { ident, if_let, if_let_guard, + if_let_rescope, if_while_or_patterns, ignore, impl_header_lifetime_elision, diff --git a/tests/ui/drop/drop_order.rs b/tests/ui/drop/drop_order.rs index 54e9e491f7873..cf06253800745 100644 --- a/tests/ui/drop/drop_order.rs +++ b/tests/ui/drop/drop_order.rs @@ -1,6 +1,11 @@ //@ run-pass //@ compile-flags: -Z validate-mir +//@ revisions: edition2021 edition2024 +//@ [edition2021] edition: 2021 +//@ [edition2024] compile-flags: -Z unstable-options +//@ [edition2024] edition: 2024 #![feature(let_chains)] +#![cfg_attr(edition2024, feature(if_let_rescope))] use std::cell::RefCell; use std::convert::TryInto; @@ -55,11 +60,18 @@ impl DropOrderCollector { } fn if_let(&self) { + #[cfg(edition2021)] if let None = self.option_loud_drop(2) { unreachable!(); } else { self.print(1); } + #[cfg(edition2024)] + if let None = self.option_loud_drop(1) { + unreachable!(); + } else { + self.print(2); + } if let Some(_) = self.option_loud_drop(4) { self.print(3); @@ -194,6 +206,7 @@ impl DropOrderCollector { self.print(3); // 3 } + #[cfg(edition2021)] // take the "else" branch if self.option_loud_drop(5).is_some() // 1 && self.option_loud_drop(6).is_some() // 2 @@ -202,6 +215,15 @@ impl DropOrderCollector { } else { self.print(7); // 3 } + #[cfg(edition2024)] + // take the "else" branch + if self.option_loud_drop(5).is_some() // 1 + && self.option_loud_drop(6).is_some() // 2 + && let None = self.option_loud_drop(7) { // 4 + unreachable!(); + } else { + self.print(8); // 3 + } // let exprs interspersed if self.option_loud_drop(9).is_some() // 1 diff --git a/tests/ui/drop/drop_order_if_let_rescope.rs b/tests/ui/drop/drop_order_if_let_rescope.rs new file mode 100644 index 0000000000000..ae9f381820e16 --- /dev/null +++ b/tests/ui/drop/drop_order_if_let_rescope.rs @@ -0,0 +1,122 @@ +//@ run-pass +//@ edition:2024 +//@ compile-flags: -Z validate-mir -Zunstable-options + +#![feature(let_chains)] +#![feature(if_let_rescope)] + +use std::cell::RefCell; +use std::convert::TryInto; + +#[derive(Default)] +struct DropOrderCollector(RefCell>); + +struct LoudDrop<'a>(&'a DropOrderCollector, u32); + +impl Drop for LoudDrop<'_> { + fn drop(&mut self) { + println!("{}", self.1); + self.0.0.borrow_mut().push(self.1); + } +} + +impl DropOrderCollector { + fn option_loud_drop(&self, n: u32) -> Option { + Some(LoudDrop(self, n)) + } + + fn print(&self, n: u32) { + println!("{}", n); + self.0.borrow_mut().push(n) + } + + fn assert_sorted(self) { + assert!( + self.0 + .into_inner() + .into_iter() + .enumerate() + .all(|(idx, item)| idx + 1 == item.try_into().unwrap()) + ); + } + + fn if_let(&self) { + if let None = self.option_loud_drop(1) { + unreachable!(); + } else { + self.print(2); + } + + if let Some(_) = self.option_loud_drop(4) { + self.print(3); + } + + if let Some(_d) = self.option_loud_drop(6) { + self.print(5); + } + } + + fn let_chain(&self) { + // take the "then" branch + if self.option_loud_drop(1).is_some() // 1 + && self.option_loud_drop(2).is_some() // 2 + && let Some(_d) = self.option_loud_drop(4) + // 4 + { + self.print(3); // 3 + } + + // take the "else" branch + if self.option_loud_drop(5).is_some() // 1 + && self.option_loud_drop(6).is_some() // 2 + && let None = self.option_loud_drop(7) + // 3 + { + unreachable!(); + } else { + self.print(8); // 4 + } + + // let exprs interspersed + if self.option_loud_drop(9).is_some() // 1 + && let Some(_d) = self.option_loud_drop(13) // 5 + && self.option_loud_drop(10).is_some() // 2 + && let Some(_e) = self.option_loud_drop(12) + // 4 + { + self.print(11); // 3 + } + + // let exprs first + if let Some(_d) = self.option_loud_drop(18) // 5 + && let Some(_e) = self.option_loud_drop(17) // 4 + && self.option_loud_drop(14).is_some() // 1 + && self.option_loud_drop(15).is_some() + // 2 + { + self.print(16); // 3 + } + + // let exprs last + if self.option_loud_drop(19).is_some() // 1 + && self.option_loud_drop(20).is_some() // 2 + && let Some(_d) = self.option_loud_drop(23) // 5 + && let Some(_e) = self.option_loud_drop(22) + // 4 + { + self.print(21); // 3 + } + } +} + +fn main() { + println!("-- if let --"); + let collector = DropOrderCollector::default(); + collector.if_let(); + collector.assert_sorted(); + + println!("-- let chain --"); + let collector = DropOrderCollector::default(); + collector.let_chain(); + collector.assert_sorted(); +} diff --git a/tests/ui/drop/if-let-rescope-borrowck-suggestions.fixed b/tests/ui/drop/if-let-rescope-borrowck-suggestions.fixed new file mode 100644 index 0000000000000..129e78ea9fe7d --- /dev/null +++ b/tests/ui/drop/if-let-rescope-borrowck-suggestions.fixed @@ -0,0 +1,26 @@ +//@ edition: 2024 +//@ compile-flags: -Z validate-mir -Zunstable-options +//@ run-rustfix + +#![feature(if_let_rescope)] +#![deny(if_let_rescope)] + +struct Droppy; +impl Drop for Droppy { + fn drop(&mut self) { + println!("dropped"); + } +} +impl Droppy { + fn get_ref(&self) -> Option<&u8> { + None + } +} + +fn do_something(_: &T) {} + +fn main() { + let binding = Droppy; + do_something(match binding.get_ref() { Some(value) => { value } _ => { &0 }}); + //~^ ERROR: temporary value dropped while borrowed +} diff --git a/tests/ui/drop/if-let-rescope-borrowck-suggestions.rs b/tests/ui/drop/if-let-rescope-borrowck-suggestions.rs new file mode 100644 index 0000000000000..1970d5c0f7ed2 --- /dev/null +++ b/tests/ui/drop/if-let-rescope-borrowck-suggestions.rs @@ -0,0 +1,25 @@ +//@ edition: 2024 +//@ compile-flags: -Z validate-mir -Zunstable-options +//@ run-rustfix + +#![feature(if_let_rescope)] +#![deny(if_let_rescope)] + +struct Droppy; +impl Drop for Droppy { + fn drop(&mut self) { + println!("dropped"); + } +} +impl Droppy { + fn get_ref(&self) -> Option<&u8> { + None + } +} + +fn do_something(_: &T) {} + +fn main() { + do_something(if let Some(value) = Droppy.get_ref() { value } else { &0 }); + //~^ ERROR: temporary value dropped while borrowed +} diff --git a/tests/ui/drop/if-let-rescope-borrowck-suggestions.stderr b/tests/ui/drop/if-let-rescope-borrowck-suggestions.stderr new file mode 100644 index 0000000000000..fa154f01a12e9 --- /dev/null +++ b/tests/ui/drop/if-let-rescope-borrowck-suggestions.stderr @@ -0,0 +1,26 @@ +error[E0716]: temporary value dropped while borrowed + --> $DIR/if-let-rescope-borrowck-suggestions.rs:23:39 + | +LL | do_something(if let Some(value) = Droppy.get_ref() { value } else { &0 }); + | ^^^^^^ - temporary value is freed at the end of this statement + | | + | creates a temporary value which is freed while still in use + | +note: lifetime for temporaries generated in `if let`s have been shorted in Edition 2024 + --> $DIR/if-let-rescope-borrowck-suggestions.rs:23:65 + | +LL | do_something(if let Some(value) = Droppy.get_ref() { value } else { &0 }); + | ^ +help: consider using a `let` binding to create a longer lived value + | +LL ~ let binding = Droppy; +LL ~ do_something(if let Some(value) = binding.get_ref() { value } else { &0 }); + | +help: consider rewriting the `if` into `match` which preserves the extended lifetime + | +LL | do_something(match Droppy.get_ref() { Some(value) => { value } _ => { &0 }}); + | ~~~~~ ++++++++++++++++ ~~~~ + + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0716`. diff --git a/tests/ui/drop/lint-if-let-rescope-gated.rs b/tests/ui/drop/lint-if-let-rescope-gated.rs new file mode 100644 index 0000000000000..f8844a09f7c50 --- /dev/null +++ b/tests/ui/drop/lint-if-let-rescope-gated.rs @@ -0,0 +1,31 @@ +// This test checks that the lint `if_let_rescope` only actions +// when the feature gate is enabled. +// Edition 2021 is used here because the lint should work especially +// when edition migration towards 2024 is run. + +//@ revisions: with_feature_gate without_feature_gate +//@ [without_feature_gate] check-pass +//@ edition: 2021 + +#![cfg_attr(with_feature_gate, feature(if_let_rescope))] +#![deny(if_let_rescope)] +#![allow(irrefutable_let_patterns)] + +struct Droppy; +impl Drop for Droppy { + fn drop(&mut self) { + println!("dropped"); + } +} +impl Droppy { + fn get(&self) -> Option { + None + } +} + +fn main() { + if let Some(_value) = Droppy.get() { + //[with_feature_gate]~^ ERROR: `if let` assigns a shorter lifetime since Edition 2024 + //[with_feature_gate]~| WARN: this changes meaning in Rust 2024 + }; +} diff --git a/tests/ui/drop/lint-if-let-rescope-gated.with_feature_gate.stderr b/tests/ui/drop/lint-if-let-rescope-gated.with_feature_gate.stderr new file mode 100644 index 0000000000000..7c295b7f9d89f --- /dev/null +++ b/tests/ui/drop/lint-if-let-rescope-gated.with_feature_gate.stderr @@ -0,0 +1,30 @@ +error: `if let` assigns a shorter lifetime since Edition 2024 + --> $DIR/lint-if-let-rescope-gated.rs:27:8 + | +LL | if let Some(_value) = Droppy.get() { + | ^^^^^^^^^^^^^^^^^^^------^^^^^^ + | | + | this value has a significant drop implementation which may observe a major change in drop order and requires your discretion + | + = warning: this changes meaning in Rust 2024 + = note: for more information, see issue #124085 +help: the value is now dropped here in Edition 2024 + --> $DIR/lint-if-let-rescope-gated.rs:30:5 + | +LL | }; + | ^ +note: the lint level is defined here + --> $DIR/lint-if-let-rescope-gated.rs:11:9 + | +LL | #![deny(if_let_rescope)] + | ^^^^^^^^^^^^^^ +help: rewrite this `if let` into a `match` with a single arm to preserve the drop order up to Edition 2021 + | +LL ~ match Droppy.get() { Some(_value) => { +LL | +LL | +LL ~ } _ => {} }; + | + +error: aborting due to 1 previous error + diff --git a/tests/ui/drop/lint-if-let-rescope-with-macro.rs b/tests/ui/drop/lint-if-let-rescope-with-macro.rs new file mode 100644 index 0000000000000..282b3320d3004 --- /dev/null +++ b/tests/ui/drop/lint-if-let-rescope-with-macro.rs @@ -0,0 +1,41 @@ +// This test ensures that no suggestion is emitted if the span originates from +// an expansion that is probably not under a user's control. + +//@ edition:2021 +//@ compile-flags: -Z unstable-options + +#![feature(if_let_rescope)] +#![deny(if_let_rescope)] +#![allow(irrefutable_let_patterns)] + +macro_rules! edition_2021_if_let { + ($p:pat, $e:expr, { $($conseq:tt)* } { $($alt:tt)* }) => { + if let $p = $e { $($conseq)* } else { $($alt)* } + //~^ ERROR `if let` assigns a shorter lifetime since Edition 2024 + //~| WARN this changes meaning in Rust 2024 + } +} + +fn droppy() -> Droppy { + Droppy +} +struct Droppy; +impl Drop for Droppy { + fn drop(&mut self) { + println!("dropped"); + } +} +impl Droppy { + fn get(&self) -> Option { + None + } +} + +fn main() { + edition_2021_if_let! { + Some(_value), + droppy().get(), + {} + {} + }; +} diff --git a/tests/ui/drop/lint-if-let-rescope-with-macro.stderr b/tests/ui/drop/lint-if-let-rescope-with-macro.stderr new file mode 100644 index 0000000000000..5fd0c61d17a57 --- /dev/null +++ b/tests/ui/drop/lint-if-let-rescope-with-macro.stderr @@ -0,0 +1,39 @@ +error: `if let` assigns a shorter lifetime since Edition 2024 + --> $DIR/lint-if-let-rescope-with-macro.rs:13:12 + | +LL | if let $p = $e { $($conseq)* } else { $($alt)* } + | ^^^ +... +LL | / edition_2021_if_let! { +LL | | Some(_value), +LL | | droppy().get(), + | | -------- this value has a significant drop implementation which may observe a major change in drop order and requires your discretion +LL | | {} +LL | | {} +LL | | }; + | |_____- in this macro invocation + | + = warning: this changes meaning in Rust 2024 + = note: for more information, see issue #124085 +help: the value is now dropped here in Edition 2024 + --> $DIR/lint-if-let-rescope-with-macro.rs:13:38 + | +LL | if let $p = $e { $($conseq)* } else { $($alt)* } + | ^ +... +LL | / edition_2021_if_let! { +LL | | Some(_value), +LL | | droppy().get(), +LL | | {} +LL | | {} +LL | | }; + | |_____- in this macro invocation +note: the lint level is defined here + --> $DIR/lint-if-let-rescope-with-macro.rs:8:9 + | +LL | #![deny(if_let_rescope)] + | ^^^^^^^^^^^^^^ + = note: this error originates in the macro `edition_2021_if_let` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 1 previous error + diff --git a/tests/ui/drop/lint-if-let-rescope.fixed b/tests/ui/drop/lint-if-let-rescope.fixed new file mode 100644 index 0000000000000..7ed7e4b279c03 --- /dev/null +++ b/tests/ui/drop/lint-if-let-rescope.fixed @@ -0,0 +1,48 @@ +//@ edition:2024 +//@ compile-flags: -Z validate-mir -Zunstable-options +//@ run-rustfix + +#![feature(if_let_rescope)] +#![deny(if_let_rescope)] +#![allow(irrefutable_let_patterns)] + +fn droppy() -> Droppy { + Droppy +} +struct Droppy; +impl Drop for Droppy { + fn drop(&mut self) { + println!("dropped"); + } +} +impl Droppy { + fn get(&self) -> Option { + None + } +} + +fn main() { + match droppy().get() { Some(_value) => { + //~^ ERROR: `if let` assigns a shorter lifetime since Edition 2024 + //~| WARN: this changes meaning in Rust 2024 + //~| HELP: rewrite this `if let` into a `match` + // do something + } _ => { + //~^ HELP: the value is now dropped here in Edition 2024 + // do something else + }} + + if let Some(1) = { match Droppy.get() { Some(_value) => { Some(1) } _ => { None }} } { + //~^ ERROR: `if let` assigns a shorter lifetime since Edition 2024 + //~| WARN: this changes meaning in Rust 2024 + //~| HELP: rewrite this `if let` into a `match` + //~| HELP: the value is now dropped here in Edition 2024 + } + + if let () = { match Droppy.get() { Some(_value) => {} _ => {} } } { + //~^ ERROR: `if let` assigns a shorter lifetime since Edition 2024 + //~| WARN: this changes meaning in Rust 2024 + //~| HELP: rewrite this `if let` into a `match` + //~| HELP: the value is now dropped here in Edition 2024 + } +} diff --git a/tests/ui/drop/lint-if-let-rescope.rs b/tests/ui/drop/lint-if-let-rescope.rs new file mode 100644 index 0000000000000..d282cd2626b8f --- /dev/null +++ b/tests/ui/drop/lint-if-let-rescope.rs @@ -0,0 +1,48 @@ +//@ edition:2024 +//@ compile-flags: -Z validate-mir -Zunstable-options +//@ run-rustfix + +#![feature(if_let_rescope)] +#![deny(if_let_rescope)] +#![allow(irrefutable_let_patterns)] + +fn droppy() -> Droppy { + Droppy +} +struct Droppy; +impl Drop for Droppy { + fn drop(&mut self) { + println!("dropped"); + } +} +impl Droppy { + fn get(&self) -> Option { + None + } +} + +fn main() { + if let Some(_value) = droppy().get() { + //~^ ERROR: `if let` assigns a shorter lifetime since Edition 2024 + //~| WARN: this changes meaning in Rust 2024 + //~| HELP: rewrite this `if let` into a `match` + // do something + } else { + //~^ HELP: the value is now dropped here in Edition 2024 + // do something else + } + + if let Some(1) = { if let Some(_value) = Droppy.get() { Some(1) } else { None } } { + //~^ ERROR: `if let` assigns a shorter lifetime since Edition 2024 + //~| WARN: this changes meaning in Rust 2024 + //~| HELP: rewrite this `if let` into a `match` + //~| HELP: the value is now dropped here in Edition 2024 + } + + if let () = { if let Some(_value) = Droppy.get() {} } { + //~^ ERROR: `if let` assigns a shorter lifetime since Edition 2024 + //~| WARN: this changes meaning in Rust 2024 + //~| HELP: rewrite this `if let` into a `match` + //~| HELP: the value is now dropped here in Edition 2024 + } +} diff --git a/tests/ui/drop/lint-if-let-rescope.stderr b/tests/ui/drop/lint-if-let-rescope.stderr new file mode 100644 index 0000000000000..832e73b898cbb --- /dev/null +++ b/tests/ui/drop/lint-if-let-rescope.stderr @@ -0,0 +1,74 @@ +error: `if let` assigns a shorter lifetime since Edition 2024 + --> $DIR/lint-if-let-rescope.rs:25:8 + | +LL | if let Some(_value) = droppy().get() { + | ^^^^^^^^^^^^^^^^^^^--------^^^^^^ + | | + | this value has a significant drop implementation which may observe a major change in drop order and requires your discretion + | + = warning: this changes meaning in Rust 2024 + = note: for more information, see issue #124085 +help: the value is now dropped here in Edition 2024 + --> $DIR/lint-if-let-rescope.rs:30:5 + | +LL | } else { + | ^ +note: the lint level is defined here + --> $DIR/lint-if-let-rescope.rs:6:9 + | +LL | #![deny(if_let_rescope)] + | ^^^^^^^^^^^^^^ +help: rewrite this `if let` into a `match` with a single arm to preserve the drop order up to Edition 2021 + | +LL ~ match droppy().get() { Some(_value) => { +LL | +... +LL | // do something +LL ~ } _ => { +LL | +LL | // do something else +LL ~ }} + | + +error: `if let` assigns a shorter lifetime since Edition 2024 + --> $DIR/lint-if-let-rescope.rs:35:27 + | +LL | if let Some(1) = { if let Some(_value) = Droppy.get() { Some(1) } else { None } } { + | ^^^^^^^^^^^^^^^^^^^------^^^^^^ + | | + | this value has a significant drop implementation which may observe a major change in drop order and requires your discretion + | + = warning: this changes meaning in Rust 2024 + = note: for more information, see issue #124085 +help: the value is now dropped here in Edition 2024 + --> $DIR/lint-if-let-rescope.rs:35:69 + | +LL | if let Some(1) = { if let Some(_value) = Droppy.get() { Some(1) } else { None } } { + | ^ +help: rewrite this `if let` into a `match` with a single arm to preserve the drop order up to Edition 2021 + | +LL | if let Some(1) = { match Droppy.get() { Some(_value) => { Some(1) } _ => { None }} } { + | ~~~~~ +++++++++++++++++ ~~~~ + + +error: `if let` assigns a shorter lifetime since Edition 2024 + --> $DIR/lint-if-let-rescope.rs:42:22 + | +LL | if let () = { if let Some(_value) = Droppy.get() {} } { + | ^^^^^^^^^^^^^^^^^^^------^^^^^^ + | | + | this value has a significant drop implementation which may observe a major change in drop order and requires your discretion + | + = warning: this changes meaning in Rust 2024 + = note: for more information, see issue #124085 +help: the value is now dropped here in Edition 2024 + --> $DIR/lint-if-let-rescope.rs:42:55 + | +LL | if let () = { if let Some(_value) = Droppy.get() {} } { + | ^ +help: rewrite this `if let` into a `match` with a single arm to preserve the drop order up to Edition 2021 + | +LL | if let () = { match Droppy.get() { Some(_value) => {} _ => {} } } { + | ~~~~~ +++++++++++++++++ +++++++++ + +error: aborting due to 3 previous errors + diff --git a/tests/ui/feature-gates/feature-gate-if-let-rescope.rs b/tests/ui/feature-gates/feature-gate-if-let-rescope.rs new file mode 100644 index 0000000000000..bd1efd4fb7c1f --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-if-let-rescope.rs @@ -0,0 +1,27 @@ +// This test shows the code that could have been accepted by enabling #![feature(if_let_rescope)] + +struct A; +struct B<'a, T>(&'a mut T); + +impl A { + fn f(&mut self) -> Option> { + Some(B(self)) + } +} + +impl<'a, T> Drop for B<'a, T> { + fn drop(&mut self) { + // this is needed to keep NLL's hands off and to ensure + // the inner mutable borrow stays alive + } +} + +fn main() { + let mut a = A; + if let None = a.f().as_ref() { + unreachable!() + } else { + a.f().unwrap(); + //~^ ERROR cannot borrow `a` as mutable more than once at a time + }; +} diff --git a/tests/ui/feature-gates/feature-gate-if-let-rescope.stderr b/tests/ui/feature-gates/feature-gate-if-let-rescope.stderr new file mode 100644 index 0000000000000..ff1846ae0b1f5 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-if-let-rescope.stderr @@ -0,0 +1,18 @@ +error[E0499]: cannot borrow `a` as mutable more than once at a time + --> $DIR/feature-gate-if-let-rescope.rs:24:9 + | +LL | if let None = a.f().as_ref() { + | ----- + | | + | first mutable borrow occurs here + | a temporary with access to the first borrow is created here ... +... +LL | a.f().unwrap(); + | ^ second mutable borrow occurs here +LL | +LL | }; + | - ... and the first borrow might be used here, when that temporary is dropped and runs the destructor for type `Option>` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0499`. diff --git a/tests/ui/mir/mir_let_chains_drop_order.rs b/tests/ui/mir/mir_let_chains_drop_order.rs index 5cbfdf2e35a74..daf0a62fc85f3 100644 --- a/tests/ui/mir/mir_let_chains_drop_order.rs +++ b/tests/ui/mir/mir_let_chains_drop_order.rs @@ -1,9 +1,14 @@ //@ run-pass //@ needs-unwind +//@ revisions: edition2021 edition2024 +//@ [edition2021] edition: 2021 +//@ [edition2024] compile-flags: -Z unstable-options +//@ [edition2024] edition: 2024 // See `mir_drop_order.rs` for more information #![feature(let_chains)] +#![cfg_attr(edition2024, feature(if_let_rescope))] #![allow(irrefutable_let_patterns)] use std::cell::RefCell; @@ -39,25 +44,32 @@ fn main() { 0, d( 1, - if let Some(_) = d(2, Some(true)).extra && let DropLogger { .. } = d(3, None) { + if let Some(_) = d(2, Some(true)).extra + && let DropLogger { .. } = d(3, None) + { None } else { Some(true) - } - ).extra + }, + ) + .extra, ), d(4, None), &d(5, None), d(6, None), - if let DropLogger { .. } = d(7, None) && let DropLogger { .. } = d(8, None) { + if let DropLogger { .. } = d(7, None) + && let DropLogger { .. } = d(8, None) + { d(9, None) - } - else { + } else { // 10 is not constructed d(10, None) }, ); + #[cfg(edition2021)] assert_eq!(get(), vec![8, 7, 1, 3, 2]); + #[cfg(edition2024)] + assert_eq!(get(), vec![3, 2, 8, 7, 1]); } assert_eq!(get(), vec![0, 4, 6, 9, 5]); @@ -73,21 +85,26 @@ fn main() { None } else { Some(true) - } - ).extra + }, + ) + .extra, ), d(15, None), &d(16, None), d(17, None), - if let DropLogger { .. } = d(18, None) && let DropLogger { .. } = d(19, None) { + if let DropLogger { .. } = d(18, None) + && let DropLogger { .. } = d(19, None) + { d(20, None) - } - else { + } else { // 10 is not constructed d(21, None) }, - panic::panic_any(InjectedFailure) + panic::panic_any(InjectedFailure), ); }); + #[cfg(edition2021)] assert_eq!(get(), vec![20, 17, 15, 11, 19, 18, 16, 12, 14, 13]); + #[cfg(edition2024)] + assert_eq!(get(), vec![14, 13, 19, 18, 20, 17, 15, 11, 16, 12]); } diff --git a/tests/ui/nll/issue-54556-niconii.stderr b/tests/ui/nll/issue-54556-niconii.edition2021.stderr similarity index 96% rename from tests/ui/nll/issue-54556-niconii.stderr rename to tests/ui/nll/issue-54556-niconii.edition2021.stderr index 015d9e1821205..31a03abbc9826 100644 --- a/tests/ui/nll/issue-54556-niconii.stderr +++ b/tests/ui/nll/issue-54556-niconii.edition2021.stderr @@ -1,5 +1,5 @@ error[E0597]: `counter` does not live long enough - --> $DIR/issue-54556-niconii.rs:22:20 + --> $DIR/issue-54556-niconii.rs:30:20 | LL | let counter = Mutex; | ------- binding `counter` declared here diff --git a/tests/ui/nll/issue-54556-niconii.rs b/tests/ui/nll/issue-54556-niconii.rs index cae389e8ccb52..1a7ad17cc84c0 100644 --- a/tests/ui/nll/issue-54556-niconii.rs +++ b/tests/ui/nll/issue-54556-niconii.rs @@ -6,6 +6,14 @@ // of temp drop order, and thus why inserting a semi-colon after the // `if let` expression in `main` works. +//@ revisions: edition2021 edition2024 +//@ [edition2021] edition: 2021 +//@ [edition2024] edition: 2024 +//@ [edition2024] compile-flags: -Z unstable-options +//@ [edition2024] check-pass + +#![cfg_attr(edition2024, feature(if_let_rescope))] + struct Mutex; struct MutexGuard<'a>(&'a Mutex); @@ -19,8 +27,10 @@ impl Mutex { fn main() { let counter = Mutex; - if let Ok(_) = counter.lock() { } //~ ERROR does not live long enough + if let Ok(_) = counter.lock() { } + //[edition2021]~^ ERROR: does not live long enough + // Up until Edition 2021: // With this code as written, the dynamic semantics here implies // that `Mutex::drop` for `counter` runs *before* // `MutexGuard::drop`, which would be unsound since `MutexGuard` @@ -28,4 +38,11 @@ fn main() { // // The goal of #54556 is to explain that within a compiler // diagnostic. + + // From Edition 2024: + // Now `MutexGuard::drop` runs *before* `Mutex::drop` because + // the lifetime of the `MutexGuard` is shortened to cover only + // from `if let` until the end of the consequent block. + // Therefore, Niconii's issue is properly solved thanks to the new + // temporary lifetime rule for `if let`s. } From e2120a7c3853226e486988b40196ff87b5eacb42 Mon Sep 17 00:00:00 2001 From: Ding Xiang Fei Date: Fri, 6 Sep 2024 03:03:10 +0800 Subject: [PATCH 0806/2194] coalesce lint suggestions that can intersect --- compiler/rustc_lint/messages.ftl | 4 +- compiler/rustc_lint/src/if_let_rescope.rs | 319 ++++++++++++------ compiler/rustc_lint/src/lib.rs | 2 +- tests/ui/drop/lint-if-let-rescope-gated.rs | 5 +- ...let-rescope-gated.with_feature_gate.stderr | 40 ++- tests/ui/drop/lint-if-let-rescope.fixed | 69 +++- tests/ui/drop/lint-if-let-rescope.rs | 63 +++- tests/ui/drop/lint-if-let-rescope.stderr | 223 ++++++++++-- 8 files changed, 568 insertions(+), 157 deletions(-) diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl index 1f8dca337fc8e..2d062465bcfba 100644 --- a/compiler/rustc_lint/messages.ftl +++ b/compiler/rustc_lint/messages.ftl @@ -337,7 +337,9 @@ lint_identifier_uncommon_codepoints = identifier contains {$codepoints_len -> lint_if_let_rescope = `if let` assigns a shorter lifetime since Edition 2024 .label = this value has a significant drop implementation which may observe a major change in drop order and requires your discretion .help = the value is now dropped here in Edition 2024 - .suggestion = rewrite this `if let` into a `match` with a single arm to preserve the drop order up to Edition 2021 + +lint_if_let_rescope_suggestion = a `match` with a single arm can preserve the drop order up to Edition 2021 + .suggestion = rewrite this `if let` into `match` lint_ignored_unless_crate_specified = {$level}({$name}) is ignored unless specified at crate level diff --git a/compiler/rustc_lint/src/if_let_rescope.rs b/compiler/rustc_lint/src/if_let_rescope.rs index 143965ae58f7e..e5bf192d23e31 100644 --- a/compiler/rustc_lint/src/if_let_rescope.rs +++ b/compiler/rustc_lint/src/if_let_rescope.rs @@ -1,11 +1,16 @@ +use std::iter::repeat; use std::ops::ControlFlow; use hir::intravisit::Visitor; use rustc_ast::Recovered; -use rustc_hir as hir; +use rustc_errors::{ + Applicability, Diag, EmissionGuarantee, SubdiagMessageOp, Subdiagnostic, SuggestionStyle, +}; +use rustc_hir::{self as hir, HirIdSet}; use rustc_macros::{LintDiagnostic, Subdiagnostic}; -use rustc_session::lint::FutureIncompatibilityReason; -use rustc_session::{declare_lint, declare_lint_pass}; +use rustc_middle::ty::TyCtxt; +use rustc_session::lint::{FutureIncompatibilityReason, Level}; +use rustc_session::{declare_lint, impl_lint_pass}; use rustc_span::edition::Edition; use rustc_span::Span; @@ -84,138 +89,236 @@ declare_lint! { }; } -declare_lint_pass!( - /// Lint for potential change in program semantics of `if let`s - IfLetRescope => [IF_LET_RESCOPE] -); +/// Lint for potential change in program semantics of `if let`s +#[derive(Default)] +pub(crate) struct IfLetRescope { + skip: HirIdSet, +} -impl<'tcx> LateLintPass<'tcx> for IfLetRescope { - fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'tcx>) { - if !expr.span.edition().at_least_rust_2021() || !cx.tcx.features().if_let_rescope { +fn expr_parent_is_else(tcx: TyCtxt<'_>, hir_id: hir::HirId) -> bool { + let Some((_, hir::Node::Expr(expr))) = tcx.hir().parent_iter(hir_id).next() else { + return false; + }; + let hir::ExprKind::If(_cond, _conseq, Some(alt)) = expr.kind else { return false }; + alt.hir_id == hir_id +} + +fn expr_parent_is_stmt(tcx: TyCtxt<'_>, hir_id: hir::HirId) -> bool { + let Some((_, hir::Node::Stmt(stmt))) = tcx.hir().parent_iter(hir_id).next() else { + return false; + }; + let (hir::StmtKind::Semi(expr) | hir::StmtKind::Expr(expr)) = stmt.kind else { return false }; + expr.hir_id == hir_id +} + +fn match_head_needs_bracket(tcx: TyCtxt<'_>, expr: &hir::Expr<'_>) -> bool { + expr_parent_is_else(tcx, expr.hir_id) && matches!(expr.kind, hir::ExprKind::If(..)) +} + +impl IfLetRescope { + fn probe_if_cascade<'tcx>(&mut self, cx: &LateContext<'tcx>, mut expr: &'tcx hir::Expr<'tcx>) { + if self.skip.contains(&expr.hir_id) { return; } - let hir::ExprKind::If(cond, conseq, alt) = expr.kind else { return }; - let hir::ExprKind::Let(&hir::LetExpr { - span, - pat, - init, - ty: ty_ascription, - recovered: Recovered::No, - }) = cond.kind - else { - return; - }; - let source_map = cx.tcx.sess.source_map(); + let tcx = cx.tcx; + let source_map = tcx.sess.source_map(); let expr_end = expr.span.shrink_to_hi(); - let if_let_pat = expr.span.shrink_to_lo().between(init.span); - let before_conseq = conseq.span.shrink_to_lo(); - let lifetime_end = source_map.end_point(conseq.span); + let mut add_bracket_to_match_head = match_head_needs_bracket(tcx, expr); + let mut closing_brackets = 0; + let mut alt_heads = vec![]; + let mut match_heads = vec![]; + let mut consequent_heads = vec![]; + let mut first_if_to_rewrite = None; + let mut empty_alt = false; + while let hir::ExprKind::If(cond, conseq, alt) = expr.kind { + self.skip.insert(expr.hir_id); + let hir::ExprKind::Let(&hir::LetExpr { + span, + pat, + init, + ty: ty_ascription, + recovered: Recovered::No, + }) = cond.kind + else { + if let Some(alt) = alt { + add_bracket_to_match_head = matches!(alt.kind, hir::ExprKind::If(..)); + expr = alt; + continue; + } else { + // finalize and emit span + break; + } + }; + let if_let_pat = expr.span.shrink_to_lo().between(init.span); + // the consequent fragment is always a block + let before_conseq = conseq.span.shrink_to_lo(); + let lifetime_end = source_map.end_point(conseq.span); - if let ControlFlow::Break(significant_dropper) = - (FindSignificantDropper { cx }).visit_expr(init) - { - let lint_without_suggestion = || { - cx.tcx.emit_node_span_lint( + if let ControlFlow::Break(significant_dropper) = + (FindSignificantDropper { cx }).visit_expr(init) + { + tcx.emit_node_span_lint( IF_LET_RESCOPE, expr.hir_id, span, - IfLetRescopeRewrite { significant_dropper, lifetime_end, sugg: None }, - ) - }; - if ty_ascription.is_some() - || !expr.span.can_be_used_for_suggestions() - || !pat.span.can_be_used_for_suggestions() - { - // Our `match` rewrites does not support type ascription, - // so we just bail. - // Alternatively when the span comes from proc macro expansion, - // we will also bail. - // FIXME(#101728): change this when type ascription syntax is stabilized again - lint_without_suggestion(); - } else { - let Ok(pat) = source_map.span_to_snippet(pat.span) else { - lint_without_suggestion(); - return; - }; - if let Some(alt) = alt { - let alt_start = conseq.span.between(alt.span); - if !alt_start.can_be_used_for_suggestions() { - lint_without_suggestion(); - return; + IfLetRescopeLint { significant_dropper, lifetime_end }, + ); + if ty_ascription.is_some() + || !expr.span.can_be_used_for_suggestions() + || !pat.span.can_be_used_for_suggestions() + { + // Our `match` rewrites does not support type ascription, + // so we just bail. + // Alternatively when the span comes from proc macro expansion, + // we will also bail. + // FIXME(#101728): change this when type ascription syntax is stabilized again + } else if let Ok(pat) = source_map.span_to_snippet(pat.span) { + let emit_suggestion = || { + first_if_to_rewrite = + first_if_to_rewrite.or_else(|| Some((expr.span, expr.hir_id))); + if add_bracket_to_match_head { + closing_brackets += 2; + match_heads.push(SingleArmMatchBegin::WithOpenBracket(if_let_pat)); + } else { + // It has to be a block + closing_brackets += 1; + match_heads.push(SingleArmMatchBegin::WithoutOpenBracket(if_let_pat)); + } + consequent_heads.push(ConsequentRewrite { span: before_conseq, pat }); + }; + if let Some(alt) = alt { + let alt_head = conseq.span.between(alt.span); + if alt_head.can_be_used_for_suggestions() { + // lint + emit_suggestion(); + alt_heads.push(AltHead(alt_head)); + } + } else { + emit_suggestion(); + empty_alt = true; + break; } - cx.tcx.emit_node_span_lint( - IF_LET_RESCOPE, - expr.hir_id, - span, - IfLetRescopeRewrite { - significant_dropper, - lifetime_end, - sugg: Some(IfLetRescopeRewriteSuggestion::WithElse { - if_let_pat, - before_conseq, - pat, - expr_end, - alt_start, - }), - }, - ); - } else { - cx.tcx.emit_node_span_lint( - IF_LET_RESCOPE, - expr.hir_id, - span, - IfLetRescopeRewrite { - significant_dropper, - lifetime_end, - sugg: Some(IfLetRescopeRewriteSuggestion::WithoutElse { - if_let_pat, - before_conseq, - pat, - expr_end, - }), - }, - ); } } + if let Some(alt) = alt { + add_bracket_to_match_head = matches!(alt.kind, hir::ExprKind::If(..)); + expr = alt; + } else { + break; + } + } + if let Some((span, hir_id)) = first_if_to_rewrite { + tcx.emit_node_span_lint( + IF_LET_RESCOPE, + hir_id, + span, + IfLetRescopeRewrite { + match_heads, + consequent_heads, + closing_brackets: ClosingBrackets { + span: expr_end, + count: closing_brackets, + empty_alt, + }, + alt_heads, + }, + ); } } } +impl_lint_pass!( + IfLetRescope => [IF_LET_RESCOPE] +); + +impl<'tcx> LateLintPass<'tcx> for IfLetRescope { + fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'tcx>) { + if expr.span.edition().at_least_rust_2024() || !cx.tcx.features().if_let_rescope { + return; + } + if let (Level::Allow, _) = cx.tcx.lint_level_at_node(IF_LET_RESCOPE, expr.hir_id) { + return; + } + if expr_parent_is_stmt(cx.tcx, expr.hir_id) + && matches!(expr.kind, hir::ExprKind::If(_cond, _conseq, None)) + { + // `if let` statement without an `else` branch has no observable change + // so we can skip linting it + return; + } + self.probe_if_cascade(cx, expr); + } +} + #[derive(LintDiagnostic)] #[diag(lint_if_let_rescope)] -struct IfLetRescopeRewrite { +struct IfLetRescopeLint { #[label] significant_dropper: Span, #[help] lifetime_end: Span, +} + +#[derive(LintDiagnostic)] +#[diag(lint_if_let_rescope_suggestion)] +struct IfLetRescopeRewrite { + #[subdiagnostic] + match_heads: Vec, + #[subdiagnostic] + consequent_heads: Vec, #[subdiagnostic] - sugg: Option, + closing_brackets: ClosingBrackets, + #[subdiagnostic] + alt_heads: Vec, +} + +#[derive(Subdiagnostic)] +#[multipart_suggestion(lint_suggestion, applicability = "machine-applicable")] +struct AltHead(#[suggestion_part(code = " _ => ")] Span); + +#[derive(Subdiagnostic)] +#[multipart_suggestion(lint_suggestion, applicability = "machine-applicable")] +struct ConsequentRewrite { + #[suggestion_part(code = "{{ {pat} => ")] + span: Span, + pat: String, +} + +struct ClosingBrackets { + span: Span, + count: usize, + empty_alt: bool, +} + +impl Subdiagnostic for ClosingBrackets { + fn add_to_diag_with>( + self, + diag: &mut Diag<'_, G>, + f: &F, + ) { + let code: String = self + .empty_alt + .then_some(" _ => {}".chars()) + .into_iter() + .flatten() + .chain(repeat('}').take(self.count)) + .collect(); + let msg = f(diag, crate::fluent_generated::lint_suggestion.into()); + diag.multipart_suggestion_with_style( + msg, + vec![(self.span, code)], + Applicability::MachineApplicable, + SuggestionStyle::ShowCode, + ); + } } #[derive(Subdiagnostic)] -enum IfLetRescopeRewriteSuggestion { +enum SingleArmMatchBegin { #[multipart_suggestion(lint_suggestion, applicability = "machine-applicable")] - WithElse { - #[suggestion_part(code = "match ")] - if_let_pat: Span, - #[suggestion_part(code = " {{ {pat} => ")] - before_conseq: Span, - pat: String, - #[suggestion_part(code = "}}")] - expr_end: Span, - #[suggestion_part(code = " _ => ")] - alt_start: Span, - }, + WithOpenBracket(#[suggestion_part(code = "{{ match ")] Span), #[multipart_suggestion(lint_suggestion, applicability = "machine-applicable")] - WithoutElse { - #[suggestion_part(code = "match ")] - if_let_pat: Span, - #[suggestion_part(code = " {{ {pat} => ")] - before_conseq: Span, - pat: String, - #[suggestion_part(code = " _ => {{}} }}")] - expr_end: Span, - }, + WithoutOpenBracket(#[suggestion_part(code = "match ")] Span), } struct FindSignificantDropper<'tcx, 'a> { diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs index 58b51240a9097..0c32157758cdf 100644 --- a/compiler/rustc_lint/src/lib.rs +++ b/compiler/rustc_lint/src/lib.rs @@ -245,7 +245,7 @@ late_lint_methods!( NonLocalDefinitions: NonLocalDefinitions::default(), ImplTraitOvercaptures: ImplTraitOvercaptures, TailExprDropOrder: TailExprDropOrder, - IfLetRescope: IfLetRescope, + IfLetRescope: IfLetRescope::default(), ] ] ); diff --git a/tests/ui/drop/lint-if-let-rescope-gated.rs b/tests/ui/drop/lint-if-let-rescope-gated.rs index f8844a09f7c50..08ded67a51257 100644 --- a/tests/ui/drop/lint-if-let-rescope-gated.rs +++ b/tests/ui/drop/lint-if-let-rescope-gated.rs @@ -26,6 +26,9 @@ impl Droppy { fn main() { if let Some(_value) = Droppy.get() { //[with_feature_gate]~^ ERROR: `if let` assigns a shorter lifetime since Edition 2024 + //[with_feature_gate]~| ERROR: a `match` with a single arm can preserve the drop order up to Edition 2021 //[with_feature_gate]~| WARN: this changes meaning in Rust 2024 - }; + //[with_feature_gate]~| WARN: this changes meaning in Rust 2024 + } else { + } } diff --git a/tests/ui/drop/lint-if-let-rescope-gated.with_feature_gate.stderr b/tests/ui/drop/lint-if-let-rescope-gated.with_feature_gate.stderr index 7c295b7f9d89f..e0f2bebdbf1ed 100644 --- a/tests/ui/drop/lint-if-let-rescope-gated.with_feature_gate.stderr +++ b/tests/ui/drop/lint-if-let-rescope-gated.with_feature_gate.stderr @@ -9,22 +9,46 @@ LL | if let Some(_value) = Droppy.get() { = warning: this changes meaning in Rust 2024 = note: for more information, see issue #124085 help: the value is now dropped here in Edition 2024 - --> $DIR/lint-if-let-rescope-gated.rs:30:5 + --> $DIR/lint-if-let-rescope-gated.rs:32:5 | -LL | }; +LL | } else { | ^ note: the lint level is defined here --> $DIR/lint-if-let-rescope-gated.rs:11:9 | LL | #![deny(if_let_rescope)] | ^^^^^^^^^^^^^^ -help: rewrite this `if let` into a `match` with a single arm to preserve the drop order up to Edition 2021 + +error: a `match` with a single arm can preserve the drop order up to Edition 2021 + --> $DIR/lint-if-let-rescope-gated.rs:27:5 + | +LL | / if let Some(_value) = Droppy.get() { +LL | | +LL | | +LL | | +LL | | +LL | | } else { +LL | | } + | |_____^ + | + = warning: this changes meaning in Rust 2024 + = note: for more information, see issue #124085 +help: rewrite this `if let` into `match` + | +LL | match Droppy.get() { + | ~~~~~ +help: rewrite this `if let` into `match` + | +LL | if let Some(_value) = Droppy.get() { Some(_value) => { + | +++++++++++++++++ +help: rewrite this `if let` into `match` | -LL ~ match Droppy.get() { Some(_value) => { -LL | -LL | -LL ~ } _ => {} }; +LL | }} + | + +help: rewrite this `if let` into `match` | +LL | } _ => { + | ~~~~ -error: aborting due to 1 previous error +error: aborting due to 2 previous errors diff --git a/tests/ui/drop/lint-if-let-rescope.fixed b/tests/ui/drop/lint-if-let-rescope.fixed index 7ed7e4b279c03..85ffa320796ad 100644 --- a/tests/ui/drop/lint-if-let-rescope.fixed +++ b/tests/ui/drop/lint-if-let-rescope.fixed @@ -1,9 +1,7 @@ -//@ edition:2024 -//@ compile-flags: -Z validate-mir -Zunstable-options //@ run-rustfix -#![feature(if_let_rescope)] #![deny(if_let_rescope)] +#![feature(if_let_rescope)] #![allow(irrefutable_let_patterns)] fn droppy() -> Droppy { @@ -22,27 +20,80 @@ impl Droppy { } fn main() { - match droppy().get() { Some(_value) => { + if let Some(_value) = droppy().get() { + // Should not lint + } + + match droppy().get() { Some(_value) => { //~^ ERROR: `if let` assigns a shorter lifetime since Edition 2024 //~| WARN: this changes meaning in Rust 2024 - //~| HELP: rewrite this `if let` into a `match` + //~| WARN: this changes meaning in Rust 2024 + //~| ERROR a `match` with a single arm can preserve the drop order up to Edition 2021 + //~| HELP: rewrite this `if let` into `match` + //~| HELP: rewrite this `if let` into `match` // do something } _ => { //~^ HELP: the value is now dropped here in Edition 2024 + //~| HELP: rewrite this `if let` into `match` // do something else }} + //~^ HELP: rewrite this `if let` into `match` + + match droppy().get() { Some(_value) => { + //~^ ERROR: `if let` assigns a shorter lifetime since Edition 2024 + //~| WARN: this changes meaning in Rust 2024 + //~| WARN: this changes meaning in Rust 2024 + //~| ERROR a `match` with a single arm can preserve the drop order up to Edition 2021 + //~| HELP: rewrite this `if let` into `match` + //~| HELP: rewrite this `if let` into `match` + // do something + } _ => { match droppy().get() { Some(_value) => { + //~^ HELP: the value is now dropped here in Edition 2024 + //~| ERROR: `if let` assigns a shorter lifetime since Edition 2024 + //~| WARN: this changes meaning in Rust 2024 + //~| HELP: rewrite this `if let` into `match` + //~| HELP: rewrite this `if let` into `match` + //~| HELP: rewrite this `if let` into `match` + // do something else + } _ => {}}}} + //~^ HELP: rewrite this `if let` into `match` + //~| HELP: the value is now dropped here in Edition 2024 + + if droppy().get().is_some() { + // Should not lint + } else { match droppy().get() { Some(_value) => { + //~^ ERROR: `if let` assigns a shorter lifetime since Edition 2024 + //~| ERROR a `match` with a single arm can preserve the drop order up to Edition 2021 + //~| WARN: this changes meaning in Rust 2024 + //~| WARN: this changes meaning in Rust 2024 + //~| HELP: rewrite this `if let` into `match` + //~| HELP: rewrite this `if let` into `match` + } _ => if droppy().get().is_none() { + //~^ HELP: the value is now dropped here in Edition 2024 + //~| HELP: rewrite this `if let` into `match` + }}} + //~^ HELP: rewrite this `if let` into `match` - if let Some(1) = { match Droppy.get() { Some(_value) => { Some(1) } _ => { None }} } { + if let Some(1) = { match Droppy.get() { Some(_value) => { Some(1) } _ => { None }} } { //~^ ERROR: `if let` assigns a shorter lifetime since Edition 2024 + //~| ERROR a `match` with a single arm can preserve the drop order up to Edition 2021 //~| WARN: this changes meaning in Rust 2024 - //~| HELP: rewrite this `if let` into a `match` + //~| WARN: this changes meaning in Rust 2024 + //~| HELP: rewrite this `if let` into `match` + //~| HELP: rewrite this `if let` into `match` + //~| HELP: rewrite this `if let` into `match` + //~| HELP: rewrite this `if let` into `match` //~| HELP: the value is now dropped here in Edition 2024 } - if let () = { match Droppy.get() { Some(_value) => {} _ => {} } } { + if let () = { match Droppy.get() { Some(_value) => {} _ => {}} } { //~^ ERROR: `if let` assigns a shorter lifetime since Edition 2024 + //~| ERROR a `match` with a single arm can preserve the drop order up to Edition 2021 + //~| WARN: this changes meaning in Rust 2024 //~| WARN: this changes meaning in Rust 2024 - //~| HELP: rewrite this `if let` into a `match` + //~| HELP: rewrite this `if let` into `match` + //~| HELP: rewrite this `if let` into `match` + //~| HELP: rewrite this `if let` into `match` //~| HELP: the value is now dropped here in Edition 2024 } } diff --git a/tests/ui/drop/lint-if-let-rescope.rs b/tests/ui/drop/lint-if-let-rescope.rs index d282cd2626b8f..776b34fdbeafe 100644 --- a/tests/ui/drop/lint-if-let-rescope.rs +++ b/tests/ui/drop/lint-if-let-rescope.rs @@ -1,9 +1,7 @@ -//@ edition:2024 -//@ compile-flags: -Z validate-mir -Zunstable-options //@ run-rustfix -#![feature(if_let_rescope)] #![deny(if_let_rescope)] +#![feature(if_let_rescope)] #![allow(irrefutable_let_patterns)] fn droppy() -> Droppy { @@ -22,27 +20,80 @@ impl Droppy { } fn main() { + if let Some(_value) = droppy().get() { + // Should not lint + } + if let Some(_value) = droppy().get() { //~^ ERROR: `if let` assigns a shorter lifetime since Edition 2024 //~| WARN: this changes meaning in Rust 2024 - //~| HELP: rewrite this `if let` into a `match` + //~| WARN: this changes meaning in Rust 2024 + //~| ERROR a `match` with a single arm can preserve the drop order up to Edition 2021 + //~| HELP: rewrite this `if let` into `match` + //~| HELP: rewrite this `if let` into `match` // do something } else { //~^ HELP: the value is now dropped here in Edition 2024 + //~| HELP: rewrite this `if let` into `match` + // do something else + } + //~^ HELP: rewrite this `if let` into `match` + + if let Some(_value) = droppy().get() { + //~^ ERROR: `if let` assigns a shorter lifetime since Edition 2024 + //~| WARN: this changes meaning in Rust 2024 + //~| WARN: this changes meaning in Rust 2024 + //~| ERROR a `match` with a single arm can preserve the drop order up to Edition 2021 + //~| HELP: rewrite this `if let` into `match` + //~| HELP: rewrite this `if let` into `match` + // do something + } else if let Some(_value) = droppy().get() { + //~^ HELP: the value is now dropped here in Edition 2024 + //~| ERROR: `if let` assigns a shorter lifetime since Edition 2024 + //~| WARN: this changes meaning in Rust 2024 + //~| HELP: rewrite this `if let` into `match` + //~| HELP: rewrite this `if let` into `match` + //~| HELP: rewrite this `if let` into `match` // do something else } + //~^ HELP: rewrite this `if let` into `match` + //~| HELP: the value is now dropped here in Edition 2024 + + if droppy().get().is_some() { + // Should not lint + } else if let Some(_value) = droppy().get() { + //~^ ERROR: `if let` assigns a shorter lifetime since Edition 2024 + //~| ERROR a `match` with a single arm can preserve the drop order up to Edition 2021 + //~| WARN: this changes meaning in Rust 2024 + //~| WARN: this changes meaning in Rust 2024 + //~| HELP: rewrite this `if let` into `match` + //~| HELP: rewrite this `if let` into `match` + } else if droppy().get().is_none() { + //~^ HELP: the value is now dropped here in Edition 2024 + //~| HELP: rewrite this `if let` into `match` + } + //~^ HELP: rewrite this `if let` into `match` if let Some(1) = { if let Some(_value) = Droppy.get() { Some(1) } else { None } } { //~^ ERROR: `if let` assigns a shorter lifetime since Edition 2024 + //~| ERROR a `match` with a single arm can preserve the drop order up to Edition 2021 + //~| WARN: this changes meaning in Rust 2024 //~| WARN: this changes meaning in Rust 2024 - //~| HELP: rewrite this `if let` into a `match` + //~| HELP: rewrite this `if let` into `match` + //~| HELP: rewrite this `if let` into `match` + //~| HELP: rewrite this `if let` into `match` + //~| HELP: rewrite this `if let` into `match` //~| HELP: the value is now dropped here in Edition 2024 } if let () = { if let Some(_value) = Droppy.get() {} } { //~^ ERROR: `if let` assigns a shorter lifetime since Edition 2024 + //~| ERROR a `match` with a single arm can preserve the drop order up to Edition 2021 + //~| WARN: this changes meaning in Rust 2024 //~| WARN: this changes meaning in Rust 2024 - //~| HELP: rewrite this `if let` into a `match` + //~| HELP: rewrite this `if let` into `match` + //~| HELP: rewrite this `if let` into `match` + //~| HELP: rewrite this `if let` into `match` //~| HELP: the value is now dropped here in Edition 2024 } } diff --git a/tests/ui/drop/lint-if-let-rescope.stderr b/tests/ui/drop/lint-if-let-rescope.stderr index 832e73b898cbb..a08d95e113869 100644 --- a/tests/ui/drop/lint-if-let-rescope.stderr +++ b/tests/ui/drop/lint-if-let-rescope.stderr @@ -1,5 +1,5 @@ error: `if let` assigns a shorter lifetime since Edition 2024 - --> $DIR/lint-if-let-rescope.rs:25:8 + --> $DIR/lint-if-let-rescope.rs:27:8 | LL | if let Some(_value) = droppy().get() { | ^^^^^^^^^^^^^^^^^^^--------^^^^^^ @@ -9,29 +9,168 @@ LL | if let Some(_value) = droppy().get() { = warning: this changes meaning in Rust 2024 = note: for more information, see issue #124085 help: the value is now dropped here in Edition 2024 - --> $DIR/lint-if-let-rescope.rs:30:5 + --> $DIR/lint-if-let-rescope.rs:35:5 | LL | } else { | ^ note: the lint level is defined here - --> $DIR/lint-if-let-rescope.rs:6:9 + --> $DIR/lint-if-let-rescope.rs:3:9 | LL | #![deny(if_let_rescope)] | ^^^^^^^^^^^^^^ -help: rewrite this `if let` into a `match` with a single arm to preserve the drop order up to Edition 2021 + +error: a `match` with a single arm can preserve the drop order up to Edition 2021 + --> $DIR/lint-if-let-rescope.rs:27:5 + | +LL | / if let Some(_value) = droppy().get() { +LL | | +LL | | +LL | | +... | +LL | | // do something else +LL | | } + | |_____^ + | + = warning: this changes meaning in Rust 2024 + = note: for more information, see issue #124085 +help: rewrite this `if let` into `match` | -LL ~ match droppy().get() { Some(_value) => { -LL | -... -LL | // do something -LL ~ } _ => { -LL | -LL | // do something else -LL ~ }} +LL | match droppy().get() { + | ~~~~~ +help: rewrite this `if let` into `match` + | +LL | if let Some(_value) = droppy().get() { Some(_value) => { + | +++++++++++++++++ +help: rewrite this `if let` into `match` + | +LL | }} + | + +help: rewrite this `if let` into `match` + | +LL | } _ => { + | ~~~~ + +error: `if let` assigns a shorter lifetime since Edition 2024 + --> $DIR/lint-if-let-rescope.rs:42:8 + | +LL | if let Some(_value) = droppy().get() { + | ^^^^^^^^^^^^^^^^^^^--------^^^^^^ + | | + | this value has a significant drop implementation which may observe a major change in drop order and requires your discretion + | + = warning: this changes meaning in Rust 2024 + = note: for more information, see issue #124085 +help: the value is now dropped here in Edition 2024 + --> $DIR/lint-if-let-rescope.rs:50:5 | +LL | } else if let Some(_value) = droppy().get() { + | ^ error: `if let` assigns a shorter lifetime since Edition 2024 - --> $DIR/lint-if-let-rescope.rs:35:27 + --> $DIR/lint-if-let-rescope.rs:50:15 + | +LL | } else if let Some(_value) = droppy().get() { + | ^^^^^^^^^^^^^^^^^^^--------^^^^^^ + | | + | this value has a significant drop implementation which may observe a major change in drop order and requires your discretion + | + = warning: this changes meaning in Rust 2024 + = note: for more information, see issue #124085 +help: the value is now dropped here in Edition 2024 + --> $DIR/lint-if-let-rescope.rs:58:5 + | +LL | } + | ^ + +error: a `match` with a single arm can preserve the drop order up to Edition 2021 + --> $DIR/lint-if-let-rescope.rs:42:5 + | +LL | / if let Some(_value) = droppy().get() { +LL | | +LL | | +LL | | +... | +LL | | // do something else +LL | | } + | |_____^ + | + = warning: this changes meaning in Rust 2024 + = note: for more information, see issue #124085 +help: rewrite this `if let` into `match` + | +LL | match droppy().get() { + | ~~~~~ +help: rewrite this `if let` into `match` + | +LL | } else { match droppy().get() { + | ~~~~~~~ +help: rewrite this `if let` into `match` + | +LL | if let Some(_value) = droppy().get() { Some(_value) => { + | +++++++++++++++++ +help: rewrite this `if let` into `match` + | +LL | } else if let Some(_value) = droppy().get() { Some(_value) => { + | +++++++++++++++++ +help: rewrite this `if let` into `match` + | +LL | } _ => {}}}} + | ++++++++++ +help: rewrite this `if let` into `match` + | +LL | } _ => if let Some(_value) = droppy().get() { + | ~~~~ + +error: `if let` assigns a shorter lifetime since Edition 2024 + --> $DIR/lint-if-let-rescope.rs:64:15 + | +LL | } else if let Some(_value) = droppy().get() { + | ^^^^^^^^^^^^^^^^^^^--------^^^^^^ + | | + | this value has a significant drop implementation which may observe a major change in drop order and requires your discretion + | + = warning: this changes meaning in Rust 2024 + = note: for more information, see issue #124085 +help: the value is now dropped here in Edition 2024 + --> $DIR/lint-if-let-rescope.rs:71:5 + | +LL | } else if droppy().get().is_none() { + | ^ + +error: a `match` with a single arm can preserve the drop order up to Edition 2021 + --> $DIR/lint-if-let-rescope.rs:64:12 + | +LL | } else if let Some(_value) = droppy().get() { + | ____________^ +LL | | +LL | | +LL | | +... | +LL | | +LL | | } + | |_____^ + | + = warning: this changes meaning in Rust 2024 + = note: for more information, see issue #124085 +help: rewrite this `if let` into `match` + | +LL | } else { match droppy().get() { + | ~~~~~~~ +help: rewrite this `if let` into `match` + | +LL | } else if let Some(_value) = droppy().get() { Some(_value) => { + | +++++++++++++++++ +help: rewrite this `if let` into `match` + | +LL | }}} + | ++ +help: rewrite this `if let` into `match` + | +LL | } _ => if droppy().get().is_none() { + | ~~~~ + +error: `if let` assigns a shorter lifetime since Edition 2024 + --> $DIR/lint-if-let-rescope.rs:77:27 | LL | if let Some(1) = { if let Some(_value) = Droppy.get() { Some(1) } else { None } } { | ^^^^^^^^^^^^^^^^^^^------^^^^^^ @@ -41,17 +180,38 @@ LL | if let Some(1) = { if let Some(_value) = Droppy.get() { Some(1) } else = warning: this changes meaning in Rust 2024 = note: for more information, see issue #124085 help: the value is now dropped here in Edition 2024 - --> $DIR/lint-if-let-rescope.rs:35:69 + --> $DIR/lint-if-let-rescope.rs:77:69 | LL | if let Some(1) = { if let Some(_value) = Droppy.get() { Some(1) } else { None } } { | ^ -help: rewrite this `if let` into a `match` with a single arm to preserve the drop order up to Edition 2021 + +error: a `match` with a single arm can preserve the drop order up to Edition 2021 + --> $DIR/lint-if-let-rescope.rs:77:24 + | +LL | if let Some(1) = { if let Some(_value) = Droppy.get() { Some(1) } else { None } } { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this changes meaning in Rust 2024 + = note: for more information, see issue #124085 +help: rewrite this `if let` into `match` + | +LL | if let Some(1) = { match Droppy.get() { Some(1) } else { None } } { + | ~~~~~ +help: rewrite this `if let` into `match` + | +LL | if let Some(1) = { if let Some(_value) = Droppy.get() { Some(_value) => { Some(1) } else { None } } { + | +++++++++++++++++ +help: rewrite this `if let` into `match` | -LL | if let Some(1) = { match Droppy.get() { Some(_value) => { Some(1) } _ => { None }} } { - | ~~~~~ +++++++++++++++++ ~~~~ + +LL | if let Some(1) = { if let Some(_value) = Droppy.get() { Some(1) } else { None }} } { + | + +help: rewrite this `if let` into `match` + | +LL | if let Some(1) = { if let Some(_value) = Droppy.get() { Some(1) } _ => { None } } { + | ~~~~ error: `if let` assigns a shorter lifetime since Edition 2024 - --> $DIR/lint-if-let-rescope.rs:42:22 + --> $DIR/lint-if-let-rescope.rs:89:22 | LL | if let () = { if let Some(_value) = Droppy.get() {} } { | ^^^^^^^^^^^^^^^^^^^------^^^^^^ @@ -61,14 +221,31 @@ LL | if let () = { if let Some(_value) = Droppy.get() {} } { = warning: this changes meaning in Rust 2024 = note: for more information, see issue #124085 help: the value is now dropped here in Edition 2024 - --> $DIR/lint-if-let-rescope.rs:42:55 + --> $DIR/lint-if-let-rescope.rs:89:55 | LL | if let () = { if let Some(_value) = Droppy.get() {} } { | ^ -help: rewrite this `if let` into a `match` with a single arm to preserve the drop order up to Edition 2021 + +error: a `match` with a single arm can preserve the drop order up to Edition 2021 + --> $DIR/lint-if-let-rescope.rs:89:19 + | +LL | if let () = { if let Some(_value) = Droppy.get() {} } { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this changes meaning in Rust 2024 + = note: for more information, see issue #124085 +help: rewrite this `if let` into `match` + | +LL | if let () = { match Droppy.get() {} } { + | ~~~~~ +help: rewrite this `if let` into `match` + | +LL | if let () = { if let Some(_value) = Droppy.get() { Some(_value) => {} } { + | +++++++++++++++++ +help: rewrite this `if let` into `match` | -LL | if let () = { match Droppy.get() { Some(_value) => {} _ => {} } } { - | ~~~~~ +++++++++++++++++ +++++++++ +LL | if let () = { if let Some(_value) = Droppy.get() {} _ => {}} } { + | ++++++++ -error: aborting due to 3 previous errors +error: aborting due to 11 previous errors From 89682a53131803c81c8d6c5f013d1bbe410c8ae1 Mon Sep 17 00:00:00 2001 From: Ding Xiang Fei Date: Wed, 11 Sep 2024 04:07:13 +0800 Subject: [PATCH 0807/2194] downgrade borrowck suggestion level due to possible span conflict --- .../src/diagnostics/explain_borrow.rs | 43 +++++++---- .../if-let-rescope-borrowck-suggestions.fixed | 26 ------- .../if-let-rescope-borrowck-suggestions.rs | 10 ++- ...if-let-rescope-borrowck-suggestions.stderr | 77 +++++++++++++++++-- 4 files changed, 108 insertions(+), 48 deletions(-) delete mode 100644 tests/ui/drop/if-let-rescope-borrowck-suggestions.fixed diff --git a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs index 22327d2ba0d46..d9b5fd8b5c182 100644 --- a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs +++ b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs @@ -128,7 +128,7 @@ impl<'tcx> BorrowExplanation<'tcx> { && pat.span.can_be_used_for_suggestions() && let Ok(pat) = tcx.sess.source_map().span_to_snippet(pat.span) { - suggest_rewrite_if_let(expr, &pat, init, conseq, alt, err); + suggest_rewrite_if_let(tcx, expr, &pat, init, conseq, alt, err); } else if path_span.map_or(true, |path_span| path_span == var_or_use_span) { // We can use `var_or_use_span` if either `path_span` is not present, or both spans are the same if borrow_span.map_or(true, |sp| !sp.overlaps(var_or_use_span)) { @@ -292,7 +292,7 @@ impl<'tcx> BorrowExplanation<'tcx> { && pat.span.can_be_used_for_suggestions() && let Ok(pat) = tcx.sess.source_map().span_to_snippet(pat.span) { - suggest_rewrite_if_let(expr, &pat, init, conseq, alt, err); + suggest_rewrite_if_let(tcx, expr, &pat, init, conseq, alt, err); } } } @@ -428,34 +428,49 @@ impl<'tcx> BorrowExplanation<'tcx> { } } -fn suggest_rewrite_if_let<'tcx>( - expr: &hir::Expr<'tcx>, +fn suggest_rewrite_if_let( + tcx: TyCtxt<'_>, + expr: &hir::Expr<'_>, pat: &str, - init: &hir::Expr<'tcx>, - conseq: &hir::Expr<'tcx>, - alt: Option<&hir::Expr<'tcx>>, + init: &hir::Expr<'_>, + conseq: &hir::Expr<'_>, + alt: Option<&hir::Expr<'_>>, err: &mut Diag<'_>, ) { + let source_map = tcx.sess.source_map(); err.span_note( - conseq.span.shrink_to_hi(), - "lifetime for temporaries generated in `if let`s have been shorted in Edition 2024", + source_map.end_point(conseq.span), + "lifetimes for temporaries generated in `if let`s have been shortened in Edition 2024 so that they are dropped here instead", ); if expr.span.can_be_used_for_suggestions() && conseq.span.can_be_used_for_suggestions() { + let needs_block = if let Some(hir::Node::Expr(expr)) = + alt.and_then(|alt| tcx.hir().parent_iter(alt.hir_id).next()).map(|(_, node)| node) + { + matches!(expr.kind, hir::ExprKind::If(..)) + } else { + false + }; let mut sugg = vec![ - (expr.span.shrink_to_lo().between(init.span), "match ".into()), + ( + expr.span.shrink_to_lo().between(init.span), + if needs_block { "{ match ".into() } else { "match ".into() }, + ), (conseq.span.shrink_to_lo(), format!(" {{ {pat} => ")), ]; let expr_end = expr.span.shrink_to_hi(); + let mut expr_end_code; if let Some(alt) = alt { - sugg.push((conseq.span.between(alt.span), format!(" _ => "))); - sugg.push((expr_end, "}".into())); + sugg.push((conseq.span.between(alt.span), " _ => ".into())); + expr_end_code = "}".to_string(); } else { - sugg.push((expr_end, " _ => {} }".into())); + expr_end_code = " _ => {} }".into(); } + expr_end_code.push('}'); + sugg.push((expr_end, expr_end_code)); err.multipart_suggestion( "consider rewriting the `if` into `match` which preserves the extended lifetime", sugg, - Applicability::MachineApplicable, + Applicability::MaybeIncorrect, ); } } diff --git a/tests/ui/drop/if-let-rescope-borrowck-suggestions.fixed b/tests/ui/drop/if-let-rescope-borrowck-suggestions.fixed deleted file mode 100644 index 129e78ea9fe7d..0000000000000 --- a/tests/ui/drop/if-let-rescope-borrowck-suggestions.fixed +++ /dev/null @@ -1,26 +0,0 @@ -//@ edition: 2024 -//@ compile-flags: -Z validate-mir -Zunstable-options -//@ run-rustfix - -#![feature(if_let_rescope)] -#![deny(if_let_rescope)] - -struct Droppy; -impl Drop for Droppy { - fn drop(&mut self) { - println!("dropped"); - } -} -impl Droppy { - fn get_ref(&self) -> Option<&u8> { - None - } -} - -fn do_something(_: &T) {} - -fn main() { - let binding = Droppy; - do_something(match binding.get_ref() { Some(value) => { value } _ => { &0 }}); - //~^ ERROR: temporary value dropped while borrowed -} diff --git a/tests/ui/drop/if-let-rescope-borrowck-suggestions.rs b/tests/ui/drop/if-let-rescope-borrowck-suggestions.rs index 1970d5c0f7ed2..2476f7cf2580a 100644 --- a/tests/ui/drop/if-let-rescope-borrowck-suggestions.rs +++ b/tests/ui/drop/if-let-rescope-borrowck-suggestions.rs @@ -1,6 +1,5 @@ //@ edition: 2024 //@ compile-flags: -Z validate-mir -Zunstable-options -//@ run-rustfix #![feature(if_let_rescope)] #![deny(if_let_rescope)] @@ -22,4 +21,13 @@ fn do_something(_: &T) {} fn main() { do_something(if let Some(value) = Droppy.get_ref() { value } else { &0 }); //~^ ERROR: temporary value dropped while borrowed + do_something(if let Some(value) = Droppy.get_ref() { + //~^ ERROR: temporary value dropped while borrowed + value + } else if let Some(value) = Droppy.get_ref() { + //~^ ERROR: temporary value dropped while borrowed + value + } else { + &0 + }); } diff --git a/tests/ui/drop/if-let-rescope-borrowck-suggestions.stderr b/tests/ui/drop/if-let-rescope-borrowck-suggestions.stderr index fa154f01a12e9..0c6f1ea28d2ae 100644 --- a/tests/ui/drop/if-let-rescope-borrowck-suggestions.stderr +++ b/tests/ui/drop/if-let-rescope-borrowck-suggestions.stderr @@ -1,16 +1,16 @@ error[E0716]: temporary value dropped while borrowed - --> $DIR/if-let-rescope-borrowck-suggestions.rs:23:39 + --> $DIR/if-let-rescope-borrowck-suggestions.rs:22:39 | LL | do_something(if let Some(value) = Droppy.get_ref() { value } else { &0 }); | ^^^^^^ - temporary value is freed at the end of this statement | | | creates a temporary value which is freed while still in use | -note: lifetime for temporaries generated in `if let`s have been shorted in Edition 2024 - --> $DIR/if-let-rescope-borrowck-suggestions.rs:23:65 +note: lifetimes for temporaries generated in `if let`s have been shortened in Edition 2024 so that they are dropped here instead + --> $DIR/if-let-rescope-borrowck-suggestions.rs:22:64 | LL | do_something(if let Some(value) = Droppy.get_ref() { value } else { &0 }); - | ^ + | ^ help: consider using a `let` binding to create a longer lived value | LL ~ let binding = Droppy; @@ -18,9 +18,72 @@ LL ~ do_something(if let Some(value) = binding.get_ref() { value } else { &0 | help: consider rewriting the `if` into `match` which preserves the extended lifetime | -LL | do_something(match Droppy.get_ref() { Some(value) => { value } _ => { &0 }}); - | ~~~~~ ++++++++++++++++ ~~~~ + +LL | do_something({ match Droppy.get_ref() { Some(value) => { value } _ => { &0 }}}); + | ~~~~~~~ ++++++++++++++++ ~~~~ ++ -error: aborting due to 1 previous error +error[E0716]: temporary value dropped while borrowed + --> $DIR/if-let-rescope-borrowck-suggestions.rs:24:39 + | +LL | do_something(if let Some(value) = Droppy.get_ref() { + | ^^^^^^ creates a temporary value which is freed while still in use +... +LL | } else if let Some(value) = Droppy.get_ref() { + | - temporary value is freed at the end of this statement + | +note: lifetimes for temporaries generated in `if let`s have been shortened in Edition 2024 so that they are dropped here instead + --> $DIR/if-let-rescope-borrowck-suggestions.rs:27:5 + | +LL | } else if let Some(value) = Droppy.get_ref() { + | ^ +help: consider using a `let` binding to create a longer lived value + | +LL ~ let binding = Droppy; +LL ~ do_something(if let Some(value) = binding.get_ref() { + | +help: consider rewriting the `if` into `match` which preserves the extended lifetime + | +LL ~ do_something({ match Droppy.get_ref() { Some(value) => { +LL | +LL | value +LL ~ } _ => if let Some(value) = Droppy.get_ref() { +LL | +... +LL | &0 +LL ~ }}}); + | + +error[E0716]: temporary value dropped while borrowed + --> $DIR/if-let-rescope-borrowck-suggestions.rs:27:33 + | +LL | } else if let Some(value) = Droppy.get_ref() { + | ^^^^^^ creates a temporary value which is freed while still in use +... +LL | } else { + | - temporary value is freed at the end of this statement + | +note: lifetimes for temporaries generated in `if let`s have been shortened in Edition 2024 so that they are dropped here instead + --> $DIR/if-let-rescope-borrowck-suggestions.rs:30:5 + | +LL | } else { + | ^ +help: consider using a `let` binding to create a longer lived value + | +LL ~ let binding = Droppy; +LL ~ do_something(if let Some(value) = Droppy.get_ref() { +LL | +LL | value +LL ~ } else if let Some(value) = binding.get_ref() { + | +help: consider rewriting the `if` into `match` which preserves the extended lifetime + | +LL ~ } else { match Droppy.get_ref() { Some(value) => { +LL | +LL | value +LL ~ } _ => { +LL | &0 +LL ~ }}}); + | + +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0716`. From d104dedad97c935aa328c9b3ebdc6ce6a68414ad Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 10 Sep 2024 15:54:47 +0200 Subject: [PATCH 0808/2194] interpret: mark some hot functions inline(always) recovers some of the perf regressions from #129778 --- compiler/rustc_const_eval/src/interpret/operand.rs | 2 ++ compiler/rustc_const_eval/src/interpret/place.rs | 3 +++ 2 files changed, 5 insertions(+) diff --git a/compiler/rustc_const_eval/src/interpret/operand.rs b/compiler/rustc_const_eval/src/interpret/operand.rs index b906e3422dba5..bb7e58b83ac7a 100644 --- a/compiler/rustc_const_eval/src/interpret/operand.rs +++ b/compiler/rustc_const_eval/src/interpret/operand.rs @@ -433,6 +433,7 @@ impl<'tcx, Prov: Provenance> Projectable<'tcx, Prov> for ImmTy<'tcx, Prov> { Ok(self.offset_(offset, layout, ecx)) } + #[inline(always)] fn to_op>( &self, _ecx: &InterpCx<'tcx, M>, @@ -522,6 +523,7 @@ impl<'tcx, Prov: Provenance> Projectable<'tcx, Prov> for OpTy<'tcx, Prov> { } } + #[inline(always)] fn to_op>( &self, _ecx: &InterpCx<'tcx, M>, diff --git a/compiler/rustc_const_eval/src/interpret/place.rs b/compiler/rustc_const_eval/src/interpret/place.rs index 3b14142da02ed..1eca92812dfb4 100644 --- a/compiler/rustc_const_eval/src/interpret/place.rs +++ b/compiler/rustc_const_eval/src/interpret/place.rs @@ -166,6 +166,7 @@ impl<'tcx, Prov: Provenance> Projectable<'tcx, Prov> for MPlaceTy<'tcx, Prov> { Ok(MPlaceTy { mplace: self.mplace.offset_with_meta_(offset, mode, meta, ecx)?, layout }) } + #[inline(always)] fn to_op>( &self, _ecx: &InterpCx<'tcx, M>, @@ -299,6 +300,7 @@ impl<'tcx, Prov: Provenance> Projectable<'tcx, Prov> for PlaceTy<'tcx, Prov> { }) } + #[inline(always)] fn to_op>( &self, ecx: &InterpCx<'tcx, M>, @@ -560,6 +562,7 @@ where /// Given a place, returns either the underlying mplace or a reference to where the value of /// this place is stored. + #[inline(always)] fn as_mplace_or_mutable_local( &mut self, place: &PlaceTy<'tcx, M::Provenance>, From 4cecf429717ceab06007570fd699086a0855a027 Mon Sep 17 00:00:00 2001 From: FedericoBruzzone Date: Mon, 9 Sep 2024 01:17:49 +0200 Subject: [PATCH 0809/2194] Report the `note` when specified in `diagnostic::on_unimplemented` Signed-off-by: FedericoBruzzone --- .../rustc_hir_typeck/src/method/suggest.rs | 14 +++++--- .../methods/suggest-convert-ptr-to-ref.stderr | 2 ++ .../custom-on-unimplemented-diagnostic.rs | 19 +++++++++++ .../custom-on-unimplemented-diagnostic.stderr | 32 +++++++++++++++++++ 4 files changed, 62 insertions(+), 5 deletions(-) create mode 100644 tests/ui/traits/custom-on-unimplemented-diagnostic.rs create mode 100644 tests/ui/traits/custom-on-unimplemented-diagnostic.stderr diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index 14ad5830111b4..178d5dce08643 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -1317,7 +1317,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let actual_prefix = rcvr_ty.prefix_string(self.tcx); info!("unimplemented_traits.len() == {}", unimplemented_traits.len()); let mut long_ty_file = None; - let (primary_message, label) = if unimplemented_traits.len() == 1 + let (primary_message, label, notes) = if unimplemented_traits.len() == 1 && unimplemented_traits_only { unimplemented_traits @@ -1327,16 +1327,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if trait_ref.self_ty().references_error() || rcvr_ty.references_error() { // Avoid crashing. - return (None, None); + return (None, None, Vec::new()); } - let OnUnimplementedNote { message, label, .. } = self + let OnUnimplementedNote { message, label, notes, .. } = self .err_ctxt() .on_unimplemented_note(trait_ref, &obligation, &mut long_ty_file); - (message, label) + (message, label, notes) }) .unwrap() } else { - (None, None) + (None, None, Vec::new()) }; let primary_message = primary_message.unwrap_or_else(|| { format!( @@ -1363,6 +1363,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { "the following trait bounds were not satisfied:\n{bound_list}" )); } + for note in notes { + err.note(note); + } + suggested_derive = self.suggest_derive(&mut err, unsatisfied_predicates); unsatisfied_bounds = true; diff --git a/tests/ui/methods/suggest-convert-ptr-to-ref.stderr b/tests/ui/methods/suggest-convert-ptr-to-ref.stderr index 69b20d57be829..0e1565e251adc 100644 --- a/tests/ui/methods/suggest-convert-ptr-to-ref.stderr +++ b/tests/ui/methods/suggest-convert-ptr-to-ref.stderr @@ -11,6 +11,7 @@ note: the method `to_string` exists on the type `&u8` = note: the following trait bounds were not satisfied: `*const u8: std::fmt::Display` which is required by `*const u8: ToString` + = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead error[E0599]: `*mut u8` doesn't implement `std::fmt::Display` --> $DIR/suggest-convert-ptr-to-ref.rs:8:22 @@ -25,6 +26,7 @@ note: the method `to_string` exists on the type `&&mut u8` = note: the following trait bounds were not satisfied: `*mut u8: std::fmt::Display` which is required by `*mut u8: ToString` + = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead error[E0599]: no method named `make_ascii_lowercase` found for raw pointer `*mut u8` in the current scope --> $DIR/suggest-convert-ptr-to-ref.rs:9:7 diff --git a/tests/ui/traits/custom-on-unimplemented-diagnostic.rs b/tests/ui/traits/custom-on-unimplemented-diagnostic.rs new file mode 100644 index 0000000000000..d7e257ef3bbe3 --- /dev/null +++ b/tests/ui/traits/custom-on-unimplemented-diagnostic.rs @@ -0,0 +1,19 @@ +#[diagnostic::on_unimplemented(message = "my message", label = "my label", note = "my note")] +pub trait ProviderLt {} + +pub trait ProviderExt { + fn request(&self) { + todo!() + } +} + +impl ProviderExt for T {} + +struct B; + +fn main() { + B.request(); + //~^ my message [E0599] + //~| my label + //~| my note +} diff --git a/tests/ui/traits/custom-on-unimplemented-diagnostic.stderr b/tests/ui/traits/custom-on-unimplemented-diagnostic.stderr new file mode 100644 index 0000000000000..f9788360d06ad --- /dev/null +++ b/tests/ui/traits/custom-on-unimplemented-diagnostic.stderr @@ -0,0 +1,32 @@ +error[E0599]: my message + --> $DIR/custom-on-unimplemented-diagnostic.rs:15:7 + | +LL | struct B; + | -------- method `request` not found for this struct because it doesn't satisfy `B: ProviderExt` or `B: ProviderLt` +... +LL | B.request(); + | ^^^^^^^ my label + | +note: trait bound `B: ProviderLt` was not satisfied + --> $DIR/custom-on-unimplemented-diagnostic.rs:10:18 + | +LL | impl ProviderExt for T {} + | ^^^^^^^^^^ ----------- - + | | + | unsatisfied trait bound introduced here + = note: my note +note: the trait `ProviderLt` must be implemented + --> $DIR/custom-on-unimplemented-diagnostic.rs:2:1 + | +LL | pub trait ProviderLt {} + | ^^^^^^^^^^^^^^^^^^^^ + = help: items from traits can only be used if the trait is implemented and in scope +note: `ProviderExt` defines an item `request`, perhaps you need to implement it + --> $DIR/custom-on-unimplemented-diagnostic.rs:4:1 + | +LL | pub trait ProviderExt { + | ^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0599`. From 8f815978b56c908dcfe7c30b4108fa0486921272 Mon Sep 17 00:00:00 2001 From: Pavel Grigorenko Date: Wed, 11 Sep 2024 00:15:43 +0300 Subject: [PATCH 0810/2194] Map `WSAEDQUOT` to `ErrorKind::FilesystemQuotaExceeded` --- library/std/src/sys/pal/windows/mod.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/library/std/src/sys/pal/windows/mod.rs b/library/std/src/sys/pal/windows/mod.rs index 1cc9a2b7ffa98..af98de3276a37 100644 --- a/library/std/src/sys/pal/windows/mod.rs +++ b/library/std/src/sys/pal/windows/mod.rs @@ -139,6 +139,7 @@ pub fn decode_error_kind(errno: i32) -> ErrorKind { c::WSAEHOSTUNREACH => HostUnreachable, c::WSAENETDOWN => NetworkDown, c::WSAENETUNREACH => NetworkUnreachable, + c::WSAEDQUOT => FilesystemQuotaExceeded, _ => Uncategorized, } From 49b3df92452ca5ce15017e69bb3f9c65d1af4139 Mon Sep 17 00:00:00 2001 From: Pavel Grigorenko Date: Wed, 11 Sep 2024 00:18:23 +0300 Subject: [PATCH 0811/2194] Map `ERROR_CANT_RESOLVE_FILENAME` to `ErrorKind::FilesystemLoop` --- library/std/src/sys/pal/windows/mod.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/library/std/src/sys/pal/windows/mod.rs b/library/std/src/sys/pal/windows/mod.rs index 1cc9a2b7ffa98..b19a225fc27d8 100644 --- a/library/std/src/sys/pal/windows/mod.rs +++ b/library/std/src/sys/pal/windows/mod.rs @@ -122,6 +122,7 @@ pub fn decode_error_kind(errno: i32) -> ErrorKind { c::ERROR_NOT_SAME_DEVICE => return CrossesDevices, c::ERROR_TOO_MANY_LINKS => return TooManyLinks, c::ERROR_FILENAME_EXCED_RANGE => return InvalidFilename, + c::ERROR_CANT_RESOLVE_FILENAME => return FilesystemLoop, _ => {} } From 4198594ef2d95de255bc0535900dac182ecfbe08 Mon Sep 17 00:00:00 2001 From: James Liu <777445+root-goblin@users.noreply.github.com> Date: Sun, 1 Sep 2024 15:27:48 -0400 Subject: [PATCH 0812/2194] Clarify docs for std::collections Page affected: https://doc.rust-lang.org/std/collections/index.html#performance Changes: - bulleted conventions - expanded definitions on terms used - more accessible language - merged Sequence and Map performance cost tables --- library/std/src/collections/mod.rs | 62 +++++++++++++++++------------- 1 file changed, 35 insertions(+), 27 deletions(-) diff --git a/library/std/src/collections/mod.rs b/library/std/src/collections/mod.rs index 3b04412e76630..21bebff96b956 100644 --- a/library/std/src/collections/mod.rs +++ b/library/std/src/collections/mod.rs @@ -79,41 +79,49 @@ //! see each type's documentation, and note that the names of actual methods may //! differ from the tables below on certain collections. //! -//! Throughout the documentation, we will follow a few conventions. For all -//! operations, the collection's size is denoted by n. If another collection is -//! involved in the operation, it contains m elements. Operations which have an -//! *amortized* cost are suffixed with a `*`. Operations with an *expected* -//! cost are suffixed with a `~`. +//! Throughout the documentation, we will adhere to the following conventions +//! for operation notation: //! -//! All amortized costs are for the potential need to resize when capacity is -//! exhausted. If a resize occurs it will take *O*(*n*) time. Our collections never -//! automatically shrink, so removal operations aren't amortized. Over a -//! sufficiently large series of operations, the average cost per operation will -//! deterministically equal the given cost. +//! * The collection's size is denoted by `n`. +//! * If a second collection is involved, its size is denoted by `m`. +//! * Item indices are denoted by `i`. +//! * Operations which have an *amortized* cost are suffixed with a `*`. +//! * Operations with an *expected* cost are suffixed with a `~`. //! -//! Only [`HashMap`] has expected costs, due to the probabilistic nature of hashing. -//! It is theoretically possible, though very unlikely, for [`HashMap`] to -//! experience worse performance. +//! Calling operations that add to a collection will occasionally require a +//! collection to be resized - an extra operation that takes *O*(*n*) time. //! -//! ## Sequences +//! *Amortized* costs are calculated to account for the time cost of such resize +//! operations *over a sufficiently large series of operations*. An individual +//! operation may be slower or faster due to the sporadic nature of collection +//! resizing, however the average cost per operation will approach the amortized +//! cost. //! -//! | | get(i) | insert(i) | remove(i) | append | split_off(i) | -//! |----------------|------------------------|-------------------------|------------------------|-----------|------------------------| -//! | [`Vec`] | *O*(1) | *O*(*n*-*i*)* | *O*(*n*-*i*) | *O*(*m*)* | *O*(*n*-*i*) | -//! | [`VecDeque`] | *O*(1) | *O*(min(*i*, *n*-*i*))* | *O*(min(*i*, *n*-*i*)) | *O*(*m*)* | *O*(min(*i*, *n*-*i*)) | -//! | [`LinkedList`] | *O*(min(*i*, *n*-*i*)) | *O*(min(*i*, *n*-*i*)) | *O*(min(*i*, *n*-*i*)) | *O*(1) | *O*(min(*i*, *n*-*i*)) | +//! Rust's collections never automatically shrink, so removal operations aren't +//! amortized. //! -//! Note that where ties occur, [`Vec`] is generally going to be faster than [`VecDeque`], and -//! [`VecDeque`] is generally going to be faster than [`LinkedList`]. +//! [`HashMap`] uses *expected* costs. It is theoretically possible, though very +//! unlikely, for [`HashMap`] to experience significantly worse performance than +//! the expected cost. This is due to the probabilistic nature of hashing - i.e. +//! it is possible to generate a duplicate hash given some input key that will +//! requires extra computation to correct. //! -//! ## Maps +//! ## Cost of Collection Operations //! -//! For Sets, all operations have the cost of the equivalent Map operation. //! -//! | | get | insert | remove | range | append | -//! |--------------|---------------|---------------|---------------|---------------|--------------| -//! | [`HashMap`] | *O*(1)~ | *O*(1)~* | *O*(1)~ | N/A | N/A | -//! | [`BTreeMap`] | *O*(log(*n*)) | *O*(log(*n*)) | *O*(log(*n*)) | *O*(log(*n*)) | *O*(*n*+*m*) | +//! | | get(i) | insert(i) | remove(i) | append(Vec(m)) | split_off(i) | range | append | +//! |----------------|------------------------|-------------------------|------------------------|-------------------|------------------------|-----------------|--------------| +//! | [`Vec`] | *O*(1) | *O*(*n*-*i*)* | *O*(*n*-*i*) | *O*(*m*)* | *O*(*n*-*i*) | N/A | N/A | +//! | [`VecDeque`] | *O*(1) | *O*(min(*i*, *n*-*i*))* | *O*(min(*i*, *n*-*i*)) | *O*(*m*)* | *O*(min(*i*, *n*-*i*)) | N/A | N/A | +//! | [`LinkedList`] | *O*(min(*i*, *n*-*i*)) | *O*(min(*i*, *n*-*i*)) | *O*(min(*i*, *n*-*i*)) | *O*(1) | *O*(min(*i*, *n*-*i*)) | N/A | N/A | +//! | [`HashMap`] | *O*(1)~ | *O*(1)~* | *O*(1)~ | N/A | N/A | N/A | N/A | +//! | [`BTreeMap`] | *O*(log(*n*)) | *O*(log(*n*)) | *O*(log(*n*)) | N/A | N/A | *O*(log(*n*)) | *O*(*n*+*m*) | +//! +//! Note that where ties occur, [`Vec`] is generally going to be faster than +//! [`VecDeque`], and [`VecDeque`] is generally going to be faster than +//! [`LinkedList`]. +//! +//! For Sets, all operations have the cost of the equivalent Map operation. //! //! # Correct and Efficient Usage of Collections //! From 180eacea1c51610f6ddd550dc0dac5e33d313030 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 31 Aug 2024 22:18:30 +0200 Subject: [PATCH 0813/2194] these tests seem to work fine on i586 these days --- library/std/src/f32/tests.rs | 13 ------------- library/std/src/f64/tests.rs | 13 ------------- 2 files changed, 26 deletions(-) diff --git a/library/std/src/f32/tests.rs b/library/std/src/f32/tests.rs index 3a4c1c120a495..99cfcfb231dad 100644 --- a/library/std/src/f32/tests.rs +++ b/library/std/src/f32/tests.rs @@ -2,31 +2,24 @@ use crate::f32::consts; use crate::num::{FpCategory as Fp, *}; /// Smallest number -#[allow(dead_code)] // unused on x86 const TINY_BITS: u32 = 0x1; /// Next smallest number -#[allow(dead_code)] // unused on x86 const TINY_UP_BITS: u32 = 0x2; /// Exponent = 0b11...10, Sifnificand 0b1111..10. Min val > 0 -#[allow(dead_code)] // unused on x86 const MAX_DOWN_BITS: u32 = 0x7f7f_fffe; /// Zeroed exponent, full significant -#[allow(dead_code)] // unused on x86 const LARGEST_SUBNORMAL_BITS: u32 = 0x007f_ffff; /// Exponent = 0b1, zeroed significand -#[allow(dead_code)] // unused on x86 const SMALLEST_NORMAL_BITS: u32 = 0x0080_0000; /// First pattern over the mantissa -#[allow(dead_code)] // unused on x86 const NAN_MASK1: u32 = 0x002a_aaaa; /// Second pattern over the mantissa -#[allow(dead_code)] // unused on x86 const NAN_MASK2: u32 = 0x0055_5555; #[allow(unused_macros)] @@ -353,9 +346,6 @@ fn test_is_sign_negative() { assert!((-f32::NAN).is_sign_negative()); } -// Ignore test on x87 floating point, these platforms do not guarantee NaN -// payloads are preserved and flush denormals to zero, failing the tests. -#[cfg(not(target_arch = "x86"))] #[test] fn test_next_up() { let tiny = f32::from_bits(TINY_BITS); @@ -386,9 +376,6 @@ fn test_next_up() { assert_f32_biteq!(nan2.next_up(), nan2); } -// Ignore test on x87 floating point, these platforms do not guarantee NaN -// payloads are preserved and flush denormals to zero, failing the tests. -#[cfg(not(target_arch = "x86"))] #[test] fn test_next_down() { let tiny = f32::from_bits(TINY_BITS); diff --git a/library/std/src/f64/tests.rs b/library/std/src/f64/tests.rs index bac8405f97361..3fac2efe0d76c 100644 --- a/library/std/src/f64/tests.rs +++ b/library/std/src/f64/tests.rs @@ -2,31 +2,24 @@ use crate::f64::consts; use crate::num::{FpCategory as Fp, *}; /// Smallest number -#[allow(dead_code)] // unused on x86 const TINY_BITS: u64 = 0x1; /// Next smallest number -#[allow(dead_code)] // unused on x86 const TINY_UP_BITS: u64 = 0x2; /// Exponent = 0b11...10, Sifnificand 0b1111..10. Min val > 0 -#[allow(dead_code)] // unused on x86 const MAX_DOWN_BITS: u64 = 0x7fef_ffff_ffff_fffe; /// Zeroed exponent, full significant -#[allow(dead_code)] // unused on x86 const LARGEST_SUBNORMAL_BITS: u64 = 0x000f_ffff_ffff_ffff; /// Exponent = 0b1, zeroed significand -#[allow(dead_code)] // unused on x86 const SMALLEST_NORMAL_BITS: u64 = 0x0010_0000_0000_0000; /// First pattern over the mantissa -#[allow(dead_code)] // unused on x86 const NAN_MASK1: u64 = 0x000a_aaaa_aaaa_aaaa; /// Second pattern over the mantissa -#[allow(dead_code)] // unused on x86 const NAN_MASK2: u64 = 0x0005_5555_5555_5555; #[allow(unused_macros)] @@ -343,9 +336,6 @@ fn test_is_sign_negative() { assert!((-f64::NAN).is_sign_negative()); } -// Ignore test on x87 floating point, these platforms do not guarantee NaN -// payloads are preserved and flush denormals to zero, failing the tests. -#[cfg(not(target_arch = "x86"))] #[test] fn test_next_up() { let tiny = f64::from_bits(TINY_BITS); @@ -375,9 +365,6 @@ fn test_next_up() { assert_f64_biteq!(nan2.next_up(), nan2); } -// Ignore test on x87 floating point, these platforms do not guarantee NaN -// payloads are preserved and flush denormals to zero, failing the tests. -#[cfg(not(target_arch = "x86"))] #[test] fn test_next_down() { let tiny = f64::from_bits(TINY_BITS); From c40ee79b849daee16f3ab07a5e2bae409d40aca1 Mon Sep 17 00:00:00 2001 From: Jubilee Young Date: Tue, 10 Sep 2024 16:05:37 -0700 Subject: [PATCH 0814/2194] move float tests into their own dir --- .../const-float-classify.rs => float/classify-runtime-const.rs} | 0 .../classify-runtime-const.stderr} | 0 .../const-float-bits-conv.rs => float/conv-bits-runtime-const.rs} | 0 3 files changed, 0 insertions(+), 0 deletions(-) rename tests/ui/{consts/const-float-classify.rs => float/classify-runtime-const.rs} (100%) rename tests/ui/{consts/const-float-classify.stderr => float/classify-runtime-const.stderr} (100%) rename tests/ui/{consts/const-float-bits-conv.rs => float/conv-bits-runtime-const.rs} (100%) diff --git a/tests/ui/consts/const-float-classify.rs b/tests/ui/float/classify-runtime-const.rs similarity index 100% rename from tests/ui/consts/const-float-classify.rs rename to tests/ui/float/classify-runtime-const.rs diff --git a/tests/ui/consts/const-float-classify.stderr b/tests/ui/float/classify-runtime-const.stderr similarity index 100% rename from tests/ui/consts/const-float-classify.stderr rename to tests/ui/float/classify-runtime-const.stderr diff --git a/tests/ui/consts/const-float-bits-conv.rs b/tests/ui/float/conv-bits-runtime-const.rs similarity index 100% rename from tests/ui/consts/const-float-bits-conv.rs rename to tests/ui/float/conv-bits-runtime-const.rs From 3daa9518d5234d0768ba8ea81fd19c372ab98445 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 31 Aug 2024 22:23:13 +0200 Subject: [PATCH 0815/2194] enable and extend float-classify test --- tests/ui/float/classify-runtime-const.rs | 74 ++++---- tests/ui/float/classify-runtime-const.stderr | 11 -- tests/ui/float/conv-bits-runtime-const.rs | 169 ++++++++++--------- 3 files changed, 128 insertions(+), 126 deletions(-) delete mode 100644 tests/ui/float/classify-runtime-const.stderr diff --git a/tests/ui/float/classify-runtime-const.rs b/tests/ui/float/classify-runtime-const.rs index 6e5097f7f2b9c..59a232c255e8d 100644 --- a/tests/ui/float/classify-runtime-const.rs +++ b/tests/ui/float/classify-runtime-const.rs @@ -1,40 +1,46 @@ //@ compile-flags: -Zmir-opt-level=0 -Znext-solver -//@ known-bug: #110395 -// FIXME(effects) run-pass +//@ run-pass +// ignore-tidy-linelength +// This tests the float classification functions, for regular runtime code and for const evaluation. + +#![feature(f16_const)] +#![feature(f128_const)] #![feature(const_float_classify)] -#![feature(const_trait_impl, effects)] -#![allow(incomplete_features)] -// Don't promote -const fn nop(x: T) -> T { x } +use std::hint::black_box; +use std::num::FpCategory::*; -impl const PartialEq for bool { - fn eq(&self, _: &NonDet) -> bool { - true - } -} - -macro_rules! const_assert { - ($a:expr, $b:expr) => { +macro_rules! both_assert { + ($a:expr, NonDet) => { { - const _: () = assert!($a == $b); - assert!(nop($a) == nop($b)); + // Compute `a`, but do not compare with anything as the result is non-deterministic. + const _: () = { let _val = $a; }; + // `black_box` prevents promotion, and MIR opts are disabled above, so this is truly + // going through LLVM. + let _val = black_box($a); + } + }; + ($a:expr, $b:ident) => { + { + const _: () = assert!(matches!($a, $b)); + assert!(black_box($a) == black_box($b)); } }; } macro_rules! suite { - ( $( $tt:tt )* ) => { + ( $tyname:ident: $( $tt:tt )* ) => { fn f32() { + type $tyname = f32; suite_inner!(f32 $($tt)*); } fn f64() { + type $tyname = f64; suite_inner!(f64 $($tt)*); } } - } macro_rules! suite_inner { @@ -44,33 +50,33 @@ macro_rules! suite_inner { $( $tail:tt )* ) => { - $( const_assert!($ty::$fn($val), $out); )* + $( both_assert!($ty::$fn($val), $out); )* suite_inner!($ty [$($fn),*] $($tail)*) }; ( $ty:ident [$( $fn:ident ),*]) => {}; } -#[derive(Debug)] -struct NonDet; - -// The result of the `is_sign` methods are not checked for correctness, since LLVM does not +// The result of the `is_sign` methods are not checked for correctness, since we do not // guarantee anything about the signedness of NaNs. See -// https://github.com/rust-lang/rust/issues/55131. +// https://rust-lang.github.io/rfcs/3514-float-semantics.html. -suite! { - [is_nan, is_infinite, is_finite, is_normal, is_sign_positive, is_sign_negative] - -0.0 / 0.0 => [ true, false, false, false, NonDet, NonDet] - 0.0 / 0.0 => [ true, false, false, false, NonDet, NonDet] - 1.0 => [ false, false, true, true, true, false] - -1.0 => [ false, false, true, true, false, true] - 0.0 => [ false, false, true, false, true, false] - -0.0 => [ false, false, true, false, false, true] - 1.0 / 0.0 => [ false, true, false, false, true, false] - -1.0 / 0.0 => [ false, true, false, false, false, true] +suite! { T: // type alias for the type we are testing + [ classify, is_nan, is_infinite, is_finite, is_normal, is_sign_positive, is_sign_negative] + -0.0 / 0.0 => [ Nan, true, false, false, false, NonDet, NonDet] + 0.0 / 0.0 => [ Nan, true, false, false, false, NonDet, NonDet] + 1.0 => [ Normal, false, false, true, true, true, false] + -1.0 => [ Normal, false, false, true, true, false, true] + 0.0 => [ Zero, false, false, true, false, true, false] + -0.0 => [ Zero, false, false, true, false, false, true] + 1.0 / 0.0 => [ Infinite, false, true, false, false, true, false] + -1.0 / 0.0 => [ Infinite, false, true, false, false, false, true] + 1.0 / T::MAX => [Subnormal, false, false, true, false, true, false] + -1.0 / T::MAX => [Subnormal, false, false, true, false, false, true] } fn main() { f32(); f64(); + // FIXME(f16_f128): also test f16 and f128 } diff --git a/tests/ui/float/classify-runtime-const.stderr b/tests/ui/float/classify-runtime-const.stderr deleted file mode 100644 index a35de8ad0eabd..0000000000000 --- a/tests/ui/float/classify-runtime-const.stderr +++ /dev/null @@ -1,11 +0,0 @@ -error: const `impl` for trait `PartialEq` which is not marked with `#[const_trait]` - --> $DIR/const-float-classify.rs:12:12 - | -LL | impl const PartialEq for bool { - | ^^^^^^^^^^^^^^^^^ - | - = note: marking a trait with `#[const_trait]` ensures all default method bodies are `const` - = note: adding a non-const method body in the future would be a breaking change - -error: aborting due to 1 previous error - diff --git a/tests/ui/float/conv-bits-runtime-const.rs b/tests/ui/float/conv-bits-runtime-const.rs index 869498d107612..e85a889d2c240 100644 --- a/tests/ui/float/conv-bits-runtime-const.rs +++ b/tests/ui/float/conv-bits-runtime-const.rs @@ -1,49 +1,55 @@ //@ compile-flags: -Zmir-opt-level=0 //@ run-pass +// This tests the float classification functions, for regular runtime code and for const evaluation. + #![feature(const_float_classify)] -#![feature(f16, f16_const)] -#![feature(f128, f128_const)] +#![feature(f16)] +#![feature(f128)] +#![feature(f16_const)] +#![feature(f128_const)] #![allow(unused_macro_rules)] -// Don't promote -const fn nop(x: T) -> T { x } -macro_rules! const_assert { +use std::hint::black_box; + +macro_rules! both_assert { ($a:expr) => { { const _: () = assert!($a); - assert!(nop($a)); + // `black_box` prevents promotion, and MIR opts are disabled above, so this is truly + // going through LLVM. + assert!(black_box($a)); } }; ($a:expr, $b:expr) => { { const _: () = assert!($a == $b); - assert_eq!(nop($a), nop($b)); + assert_eq!(black_box($a), black_box($b)); } }; } fn has_broken_floats() -> bool { // i586 targets are broken due to . - std::env::var("TARGET").is_ok_and(|v| v.contains("i586")) + cfg!(all(target_arch = "x86", not(target_feature = "sse2"))) } #[cfg(target_arch = "x86_64")] fn f16(){ - const_assert!((1f16).to_bits(), 0x3c00); - const_assert!(u16::from_be_bytes(1f16.to_be_bytes()), 0x3c00); - const_assert!((12.5f16).to_bits(), 0x4a40); - const_assert!(u16::from_le_bytes(12.5f16.to_le_bytes()), 0x4a40); - const_assert!((1337f16).to_bits(), 0x6539); - const_assert!(u16::from_ne_bytes(1337f16.to_ne_bytes()), 0x6539); - const_assert!((-14.25f16).to_bits(), 0xcb20); - const_assert!(f16::from_bits(0x3c00), 1.0); - const_assert!(f16::from_be_bytes(0x3c00u16.to_be_bytes()), 1.0); - const_assert!(f16::from_bits(0x4a40), 12.5); - const_assert!(f16::from_le_bytes(0x4a40u16.to_le_bytes()), 12.5); - const_assert!(f16::from_bits(0x5be0), 252.0); - const_assert!(f16::from_ne_bytes(0x5be0u16.to_ne_bytes()), 252.0); - const_assert!(f16::from_bits(0xcb20), -14.25); + both_assert!((1f16).to_bits(), 0x3c00); + both_assert!(u16::from_be_bytes(1f16.to_be_bytes()), 0x3c00); + both_assert!((12.5f16).to_bits(), 0x4a40); + both_assert!(u16::from_le_bytes(12.5f16.to_le_bytes()), 0x4a40); + both_assert!((1337f16).to_bits(), 0x6539); + both_assert!(u16::from_ne_bytes(1337f16.to_ne_bytes()), 0x6539); + both_assert!((-14.25f16).to_bits(), 0xcb20); + both_assert!(f16::from_bits(0x3c00), 1.0); + both_assert!(f16::from_be_bytes(0x3c00u16.to_be_bytes()), 1.0); + both_assert!(f16::from_bits(0x4a40), 12.5); + both_assert!(f16::from_le_bytes(0x4a40u16.to_le_bytes()), 12.5); + both_assert!(f16::from_bits(0x5be0), 252.0); + both_assert!(f16::from_ne_bytes(0x5be0u16.to_ne_bytes()), 252.0); + both_assert!(f16::from_bits(0xcb20), -14.25); // Check that NaNs roundtrip their bits regardless of signalingness // 0xA is 0b1010; 0x5 is 0b0101 -- so these two together clobbers all the mantissa bits @@ -51,29 +57,29 @@ fn f16(){ const QUIET_NAN: u16 = f16::NAN.to_bits() ^ 0x0155; const SIGNALING_NAN: u16 = f16::NAN.to_bits() ^ 0x02AA; - const_assert!(f16::from_bits(QUIET_NAN).is_nan()); - const_assert!(f16::from_bits(SIGNALING_NAN).is_nan()); - const_assert!(f16::from_bits(QUIET_NAN).to_bits(), QUIET_NAN); + both_assert!(f16::from_bits(QUIET_NAN).is_nan()); + both_assert!(f16::from_bits(SIGNALING_NAN).is_nan()); + both_assert!(f16::from_bits(QUIET_NAN).to_bits(), QUIET_NAN); if !has_broken_floats() { - const_assert!(f16::from_bits(SIGNALING_NAN).to_bits(), SIGNALING_NAN); + both_assert!(f16::from_bits(SIGNALING_NAN).to_bits(), SIGNALING_NAN); } } fn f32() { - const_assert!((1f32).to_bits(), 0x3f800000); - const_assert!(u32::from_be_bytes(1f32.to_be_bytes()), 0x3f800000); - const_assert!((12.5f32).to_bits(), 0x41480000); - const_assert!(u32::from_le_bytes(12.5f32.to_le_bytes()), 0x41480000); - const_assert!((1337f32).to_bits(), 0x44a72000); - const_assert!(u32::from_ne_bytes(1337f32.to_ne_bytes()), 0x44a72000); - const_assert!((-14.25f32).to_bits(), 0xc1640000); - const_assert!(f32::from_bits(0x3f800000), 1.0); - const_assert!(f32::from_be_bytes(0x3f800000u32.to_be_bytes()), 1.0); - const_assert!(f32::from_bits(0x41480000), 12.5); - const_assert!(f32::from_le_bytes(0x41480000u32.to_le_bytes()), 12.5); - const_assert!(f32::from_bits(0x44a72000), 1337.0); - const_assert!(f32::from_ne_bytes(0x44a72000u32.to_ne_bytes()), 1337.0); - const_assert!(f32::from_bits(0xc1640000), -14.25); + both_assert!((1f32).to_bits(), 0x3f800000); + both_assert!(u32::from_be_bytes(1f32.to_be_bytes()), 0x3f800000); + both_assert!((12.5f32).to_bits(), 0x41480000); + both_assert!(u32::from_le_bytes(12.5f32.to_le_bytes()), 0x41480000); + both_assert!((1337f32).to_bits(), 0x44a72000); + both_assert!(u32::from_ne_bytes(1337f32.to_ne_bytes()), 0x44a72000); + both_assert!((-14.25f32).to_bits(), 0xc1640000); + both_assert!(f32::from_bits(0x3f800000), 1.0); + both_assert!(f32::from_be_bytes(0x3f800000u32.to_be_bytes()), 1.0); + both_assert!(f32::from_bits(0x41480000), 12.5); + both_assert!(f32::from_le_bytes(0x41480000u32.to_le_bytes()), 12.5); + both_assert!(f32::from_bits(0x44a72000), 1337.0); + both_assert!(f32::from_ne_bytes(0x44a72000u32.to_ne_bytes()), 1337.0); + both_assert!(f32::from_bits(0xc1640000), -14.25); // Check that NaNs roundtrip their bits regardless of signalingness // 0xA is 0b1010; 0x5 is 0b0101 -- so these two together clobbers all the mantissa bits @@ -81,29 +87,29 @@ fn f32() { const QUIET_NAN: u32 = f32::NAN.to_bits() ^ 0x002A_AAAA; const SIGNALING_NAN: u32 = f32::NAN.to_bits() ^ 0x0055_5555; - const_assert!(f32::from_bits(QUIET_NAN).is_nan()); - const_assert!(f32::from_bits(SIGNALING_NAN).is_nan()); - const_assert!(f32::from_bits(QUIET_NAN).to_bits(), QUIET_NAN); + both_assert!(f32::from_bits(QUIET_NAN).is_nan()); + both_assert!(f32::from_bits(SIGNALING_NAN).is_nan()); + both_assert!(f32::from_bits(QUIET_NAN).to_bits(), QUIET_NAN); if !has_broken_floats() { - const_assert!(f32::from_bits(SIGNALING_NAN).to_bits(), SIGNALING_NAN); + both_assert!(f32::from_bits(SIGNALING_NAN).to_bits(), SIGNALING_NAN); } } fn f64() { - const_assert!((1f64).to_bits(), 0x3ff0000000000000); - const_assert!(u64::from_be_bytes(1f64.to_be_bytes()), 0x3ff0000000000000); - const_assert!((12.5f64).to_bits(), 0x4029000000000000); - const_assert!(u64::from_le_bytes(12.5f64.to_le_bytes()), 0x4029000000000000); - const_assert!((1337f64).to_bits(), 0x4094e40000000000); - const_assert!(u64::from_ne_bytes(1337f64.to_ne_bytes()), 0x4094e40000000000); - const_assert!((-14.25f64).to_bits(), 0xc02c800000000000); - const_assert!(f64::from_bits(0x3ff0000000000000), 1.0); - const_assert!(f64::from_be_bytes(0x3ff0000000000000u64.to_be_bytes()), 1.0); - const_assert!(f64::from_bits(0x4029000000000000), 12.5); - const_assert!(f64::from_le_bytes(0x4029000000000000u64.to_le_bytes()), 12.5); - const_assert!(f64::from_bits(0x4094e40000000000), 1337.0); - const_assert!(f64::from_ne_bytes(0x4094e40000000000u64.to_ne_bytes()), 1337.0); - const_assert!(f64::from_bits(0xc02c800000000000), -14.25); + both_assert!((1f64).to_bits(), 0x3ff0000000000000); + both_assert!(u64::from_be_bytes(1f64.to_be_bytes()), 0x3ff0000000000000); + both_assert!((12.5f64).to_bits(), 0x4029000000000000); + both_assert!(u64::from_le_bytes(12.5f64.to_le_bytes()), 0x4029000000000000); + both_assert!((1337f64).to_bits(), 0x4094e40000000000); + both_assert!(u64::from_ne_bytes(1337f64.to_ne_bytes()), 0x4094e40000000000); + both_assert!((-14.25f64).to_bits(), 0xc02c800000000000); + both_assert!(f64::from_bits(0x3ff0000000000000), 1.0); + both_assert!(f64::from_be_bytes(0x3ff0000000000000u64.to_be_bytes()), 1.0); + both_assert!(f64::from_bits(0x4029000000000000), 12.5); + both_assert!(f64::from_le_bytes(0x4029000000000000u64.to_le_bytes()), 12.5); + both_assert!(f64::from_bits(0x4094e40000000000), 1337.0); + both_assert!(f64::from_ne_bytes(0x4094e40000000000u64.to_ne_bytes()), 1337.0); + both_assert!(f64::from_bits(0xc02c800000000000), -14.25); // Check that NaNs roundtrip their bits regardless of signalingness // 0xA is 0b1010; 0x5 is 0b0101 -- so these two together clobbers all the mantissa bits @@ -111,30 +117,30 @@ fn f64() { const QUIET_NAN: u64 = f64::NAN.to_bits() ^ 0x0005_5555_5555_5555; const SIGNALING_NAN: u64 = f64::NAN.to_bits() ^ 0x000A_AAAA_AAAA_AAAA; - const_assert!(f64::from_bits(QUIET_NAN).is_nan()); - const_assert!(f64::from_bits(SIGNALING_NAN).is_nan()); - const_assert!(f64::from_bits(QUIET_NAN).to_bits(), QUIET_NAN); + both_assert!(f64::from_bits(QUIET_NAN).is_nan()); + both_assert!(f64::from_bits(SIGNALING_NAN).is_nan()); + both_assert!(f64::from_bits(QUIET_NAN).to_bits(), QUIET_NAN); if !has_broken_floats() { - const_assert!(f64::from_bits(SIGNALING_NAN).to_bits(), SIGNALING_NAN); + both_assert!(f64::from_bits(SIGNALING_NAN).to_bits(), SIGNALING_NAN); } } #[cfg(target_arch = "x86_64")] fn f128() { - const_assert!((1f128).to_bits(), 0x3fff0000000000000000000000000000); - const_assert!(u128::from_be_bytes(1f128.to_be_bytes()), 0x3fff0000000000000000000000000000); - const_assert!((12.5f128).to_bits(), 0x40029000000000000000000000000000); - const_assert!(u128::from_le_bytes(12.5f128.to_le_bytes()), 0x40029000000000000000000000000000); - const_assert!((1337f128).to_bits(), 0x40094e40000000000000000000000000); - const_assert!(u128::from_ne_bytes(1337f128.to_ne_bytes()), 0x40094e40000000000000000000000000); - const_assert!((-14.25f128).to_bits(), 0xc002c800000000000000000000000000); - const_assert!(f128::from_bits(0x3fff0000000000000000000000000000), 1.0); - const_assert!(f128::from_be_bytes(0x3fff0000000000000000000000000000u128.to_be_bytes()), 1.0); - const_assert!(f128::from_bits(0x40029000000000000000000000000000), 12.5); - const_assert!(f128::from_le_bytes(0x40029000000000000000000000000000u128.to_le_bytes()), 12.5); - const_assert!(f128::from_bits(0x40094e40000000000000000000000000), 1337.0); + both_assert!((1f128).to_bits(), 0x3fff0000000000000000000000000000); + both_assert!(u128::from_be_bytes(1f128.to_be_bytes()), 0x3fff0000000000000000000000000000); + both_assert!((12.5f128).to_bits(), 0x40029000000000000000000000000000); + both_assert!(u128::from_le_bytes(12.5f128.to_le_bytes()), 0x40029000000000000000000000000000); + both_assert!((1337f128).to_bits(), 0x40094e40000000000000000000000000); + both_assert!(u128::from_ne_bytes(1337f128.to_ne_bytes()), 0x40094e40000000000000000000000000); + both_assert!((-14.25f128).to_bits(), 0xc002c800000000000000000000000000); + both_assert!(f128::from_bits(0x3fff0000000000000000000000000000), 1.0); + both_assert!(f128::from_be_bytes(0x3fff0000000000000000000000000000u128.to_be_bytes()), 1.0); + both_assert!(f128::from_bits(0x40029000000000000000000000000000), 12.5); + both_assert!(f128::from_le_bytes(0x40029000000000000000000000000000u128.to_le_bytes()), 12.5); + both_assert!(f128::from_bits(0x40094e40000000000000000000000000), 1337.0); assert_eq!(f128::from_ne_bytes(0x40094e40000000000000000000000000u128.to_ne_bytes()), 1337.0); - const_assert!(f128::from_bits(0xc002c800000000000000000000000000), -14.25); + both_assert!(f128::from_bits(0xc002c800000000000000000000000000), -14.25); // Check that NaNs roundtrip their bits regardless of signalingness // 0xA is 0b1010; 0x5 is 0b0101 -- so these two together clobbers all the mantissa bits @@ -142,20 +148,21 @@ fn f128() { const QUIET_NAN: u128 = f128::NAN.to_bits() | 0x0000_AAAA_AAAA_AAAA_AAAA_AAAA_AAAA_AAAA; const SIGNALING_NAN: u128 = f128::NAN.to_bits() ^ 0x0000_5555_5555_5555_5555_5555_5555_5555; - const_assert!(f128::from_bits(QUIET_NAN).is_nan()); - const_assert!(f128::from_bits(SIGNALING_NAN).is_nan()); - const_assert!(f128::from_bits(QUIET_NAN).to_bits(), QUIET_NAN); + both_assert!(f128::from_bits(QUIET_NAN).is_nan()); + both_assert!(f128::from_bits(SIGNALING_NAN).is_nan()); + both_assert!(f128::from_bits(QUIET_NAN).to_bits(), QUIET_NAN); if !has_broken_floats() { - const_assert!(f128::from_bits(SIGNALING_NAN).to_bits(), SIGNALING_NAN); + both_assert!(f128::from_bits(SIGNALING_NAN).to_bits(), SIGNALING_NAN); } } fn main() { + f32(); + f64(); + #[cfg(target_arch = "x86_64")] { f16(); f128(); } - f32(); - f64(); } From e556c136f3a4e5ff36afa248a6dd0e2cc9ddaced Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 31 Aug 2024 22:28:17 +0200 Subject: [PATCH 0816/2194] clean up internal comments about float semantics - remove an outdated FIXME - add reference to floating-point semantics issue Co-authored-by: Jubilee --- library/core/src/num/f16.rs | 1 + library/core/src/num/f32.rs | 5 +---- library/core/src/num/f64.rs | 5 +---- tests/ui/numbers-arithmetic/issue-105626.rs | 1 + 4 files changed, 4 insertions(+), 8 deletions(-) diff --git a/library/core/src/num/f16.rs b/library/core/src/num/f16.rs index 9252e8c601558..da92da1086dab 100644 --- a/library/core/src/num/f16.rs +++ b/library/core/src/num/f16.rs @@ -435,6 +435,7 @@ impl f16 { // WASM, see llvm/llvm-project#96437). These are platforms bugs, and Rust will misbehave on // such platforms, but we can at least try to make things seem as sane as possible by being // careful here. + // see also https://github.com/rust-lang/rust/issues/114479 if self.is_infinite() { // Thus, a value may compare unequal to infinity, despite having a "full" exponent mask. FpCategory::Infinite diff --git a/library/core/src/num/f32.rs b/library/core/src/num/f32.rs index 2bc897224970d..885f7608a337e 100644 --- a/library/core/src/num/f32.rs +++ b/library/core/src/num/f32.rs @@ -662,10 +662,7 @@ impl f32 { // hardware flushes subnormals to zero. These are platforms bugs, and Rust will misbehave on // such hardware, but we can at least try to make things seem as sane as possible by being // careful here. - // - // FIXME(jubilee): Using x87 operations is never necessary in order to function - // on x86 processors for Rust-to-Rust calls, so this issue should not happen. - // Code generation should be adjusted to use non-C calling conventions, avoiding this. + // see also https://github.com/rust-lang/rust/issues/114479 if self.is_infinite() { // A value may compare unequal to infinity, despite having a "full" exponent mask. FpCategory::Infinite diff --git a/library/core/src/num/f64.rs b/library/core/src/num/f64.rs index b3f5be9fc8a46..28cc231ccc76d 100644 --- a/library/core/src/num/f64.rs +++ b/library/core/src/num/f64.rs @@ -660,10 +660,7 @@ impl f64 { // float semantics Rust relies on: x87 uses a too-large exponent, and some hardware flushes // subnormals to zero. These are platforms bugs, and Rust will misbehave on such hardware, // but we can at least try to make things seem as sane as possible by being careful here. - // - // FIXME(jubilee): Using x87 operations is never necessary in order to function - // on x86 processors for Rust-to-Rust calls, so this issue should not happen. - // Code generation should be adjusted to use non-C calling conventions, avoiding this. + // see also https://github.com/rust-lang/rust/issues/114479 // // Thus, a value may compare unequal to infinity, despite having a "full" exponent mask. // And it may not be NaN, as it can simply be an "overextended" finite value. diff --git a/tests/ui/numbers-arithmetic/issue-105626.rs b/tests/ui/numbers-arithmetic/issue-105626.rs index f942cf1283d0d..8d4a7c308e7fe 100644 --- a/tests/ui/numbers-arithmetic/issue-105626.rs +++ b/tests/ui/numbers-arithmetic/issue-105626.rs @@ -11,6 +11,7 @@ fn main() { assert_ne!((n as f64) as f32, n as f32); // FIXME: these assertions fail if only x87 is enabled + // see also https://github.com/rust-lang/rust/issues/114479 assert_eq!(n as i64 as f32, r); assert_eq!(n as u64 as f32, r); } From 7c692e13b171c04b6bb6baa4d5aa138beecf8da8 Mon Sep 17 00:00:00 2001 From: DianQK Date: Wed, 11 Sep 2024 07:59:27 +0800 Subject: [PATCH 0817/2194] Update LLVM to 19 327ca6c --- src/llvm-project | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/llvm-project b/src/llvm-project index 2b259b3c201f9..4b8d29c585687 160000 --- a/src/llvm-project +++ b/src/llvm-project @@ -1 +1 @@ -Subproject commit 2b259b3c201f939f2ed8d2fb0a0e9b37dd2d1321 +Subproject commit 4b8d29c585687084bbcf21471e04f279d1eddc0a From d05323c7b4ebeaeaffe3ea8e0d02a8b01db67ddd Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Sat, 24 Aug 2024 23:11:30 -0700 Subject: [PATCH 0818/2194] rustdoc: redesign toolbar and disclosure widgets This adds labels to the icons and moves them away from the search box. These changes are made together, because they work together, but are based on several complaints: * The [+/-] thing are a Reddit-ism. They don't look like buttons, but look like syntax , (some of these are laundry lists with more suggestions, but they all mention [+/-] looking wrong) * The settings, help, and summary buttons are also too hard to recognize , , , ("Not all functionality is self-explanatory, for example the [+] button in the top right corner, the theme picker or the settings button.") The toggle-all and toggle-individual buttons both need done at once, since we want them to look like they go together. This changes them from both being [+/-] to both being arrows. Settings and Help are also migrated, so that the whole group can benefit from being described using actual words. Additionally, the Help button is only shown on SERPs, not all the time. This is done for two major reasons: * Most of what's in there is search-related. The things that aren't are keyboard commands, and the search box tells you about that anyway. Pressing ? will temporarily show the button and its popover. * I'm trading it off by showing the help button, even on mobile. It's useful since you can use the search engine suggestions there. * The three buttons were causing line wrapping on too many desktop layouts. --- src/librustdoc/html/sources.rs | 35 ++- src/librustdoc/html/static/css/noscript.css | 5 +- src/librustdoc/html/static/css/rustdoc.css | 221 +++++++++++++----- src/librustdoc/html/static/js/main.js | 122 +++++----- src/librustdoc/html/static/js/search.js | 6 +- src/librustdoc/html/static/js/settings.js | 19 +- src/librustdoc/html/static/js/storage.js | 29 ++- src/librustdoc/html/templates/print_item.html | 13 +- src/librustdoc/html/templates/source.html | 13 +- src/librustdoc/lib.rs | 1 + src/tools/compiletest/src/runtest.rs | 2 +- src/tools/html-checker/main.rs | 2 +- tests/rustdoc-gui/help-page.goml | 8 +- tests/rustdoc-gui/item-info.goml | 2 +- tests/rustdoc-gui/mobile.goml | 15 -- tests/rustdoc-gui/notable-trait.goml | 5 +- tests/rustdoc-gui/pocket-menu.goml | 3 +- tests/rustdoc-gui/scrape-examples-layout.goml | 4 +- tests/rustdoc-gui/search-form-elements.goml | 40 +--- tests/rustdoc-gui/search-result-display.goml | 13 +- tests/rustdoc-gui/settings-button.goml | 8 +- tests/rustdoc-gui/settings.goml | 2 +- tests/rustdoc-gui/shortcuts.goml | 10 +- .../sidebar-source-code-display.goml | 2 +- tests/rustdoc-gui/sidebar.goml | 6 +- tests/rustdoc-gui/source-anchor-scroll.goml | 8 +- tests/rustdoc-gui/source-code-page.goml | 4 +- .../src/theme_css/custom-theme.css | 1 + tests/rustdoc-gui/toggle-docs.goml | 12 +- .../rustdoc-gui/type-declation-overflow.goml | 17 +- tests/rustdoc/html-no-source.rs | 8 +- tests/rustdoc/source-version-separator.rs | 4 +- .../version-separator-without-source.rs | 8 +- 33 files changed, 392 insertions(+), 256 deletions(-) diff --git a/src/librustdoc/html/sources.rs b/src/librustdoc/html/sources.rs index 551bb56685c99..bbd427bbdd205 100644 --- a/src/librustdoc/html/sources.rs +++ b/src/librustdoc/html/sources.rs @@ -26,8 +26,11 @@ pub(crate) fn render(cx: &mut Context<'_>, krate: &clean::Crate) -> Result<(), E let dst = cx.dst.join("src").join(krate.name(cx.tcx()).as_str()); cx.shared.ensure_dir(&dst)?; + let crate_name = krate.name(cx.tcx()); + let crate_name = crate_name.as_str(); - let mut collector = SourceCollector { dst, cx, emitted_local_sources: FxHashSet::default() }; + let mut collector = + SourceCollector { dst, cx, emitted_local_sources: FxHashSet::default(), crate_name }; collector.visit_crate(krate); Ok(()) } @@ -115,6 +118,8 @@ struct SourceCollector<'a, 'tcx> { /// Root destination to place all HTML output into dst: PathBuf, emitted_local_sources: FxHashSet, + + crate_name: &'a str, } impl DocVisitor for SourceCollector<'_, '_> { @@ -210,6 +215,9 @@ impl SourceCollector<'_, '_> { }, ); + let src_fname = p.file_name().expect("source has no filename").to_os_string(); + let mut fname = src_fname.clone(); + let root_path = PathBuf::from("../../").join(root_path.into_inner()); let mut root_path = root_path.to_string_lossy(); if let Some(c) = root_path.as_bytes().last() @@ -217,12 +225,12 @@ impl SourceCollector<'_, '_> { { root_path += "/"; } + let mut file_path = Path::new(&self.crate_name).join(&*cur.borrow()); + file_path.push(&fname); + fname.push(".html"); let mut cur = self.dst.join(cur.into_inner()); shared.ensure_dir(&cur)?; - let src_fname = p.file_name().expect("source has no filename").to_os_string(); - let mut fname = src_fname.clone(); - fname.push(".html"); cur.push(&fname); let title = format!("{} - source", src_fname.to_string_lossy()); @@ -250,7 +258,7 @@ impl SourceCollector<'_, '_> { cx, &root_path, highlight::DecorationInfo::default(), - SourceContext::Standalone, + SourceContext::Standalone { file_path }, ) }, &shared.style_files, @@ -313,10 +321,11 @@ struct ScrapedSource<'a, Code: std::fmt::Display> { struct Source { lines: RangeInclusive, code_html: Code, + file_path: Option<(String, String)>, } pub(crate) enum SourceContext<'a> { - Standalone, + Standalone { file_path: PathBuf }, Embedded(ScrapedInfo<'a>), } @@ -345,9 +354,19 @@ pub(crate) fn print_src( }); let lines = s.lines().count(); match source_context { - SourceContext::Standalone => { - Source { lines: (1..=lines), code_html: code }.render_into(&mut writer).unwrap() + SourceContext::Standalone { file_path } => Source { + lines: (1..=lines), + code_html: code, + file_path: if let Some(file_name) = file_path.file_name() + && let Some(file_path) = file_path.parent() + { + Some((file_path.display().to_string(), file_name.display().to_string())) + } else { + None + }, } + .render_into(&mut writer) + .unwrap(), SourceContext::Embedded(info) => { let lines = (1 + info.offset)..=(lines + info.offset); ScrapedSource { info, lines, code_html: code }.render_into(&mut writer).unwrap(); diff --git a/src/librustdoc/html/static/css/noscript.css b/src/librustdoc/html/static/css/noscript.css index e62b16267f102..477a79d63e948 100644 --- a/src/librustdoc/html/static/css/noscript.css +++ b/src/librustdoc/html/static/css/noscript.css @@ -61,6 +61,8 @@ nav.sub { --copy-path-img-hover-filter: invert(35%); --code-example-button-color: #7f7f7f; --code-example-button-hover-color: #595959; + --settings-menu-filter: invert(50%); + --settings-menu-hover-filter: invert(35%); --codeblock-error-hover-color: rgb(255, 0, 0); --codeblock-error-color: rgba(255, 0, 0, .5); --codeblock-ignore-hover-color: rgb(255, 142, 0); @@ -87,7 +89,6 @@ nav.sub { --search-tab-button-not-selected-background: #e6e6e6; --search-tab-button-selected-border-top-color: #0089ff; --search-tab-button-selected-background: #fff; - --settings-menu-filter: none; --stab-background-color: #fff5d6; --stab-code-color: #000; --code-highlight-kw-color: #8959a8; @@ -192,6 +193,8 @@ nav.sub { --search-tab-button-not-selected-background: #252525; --search-tab-button-selected-border-top-color: #0089ff; --search-tab-button-selected-background: #353535; + --settings-menu-filter: invert(50%); + --settings-menu-hover-filter: invert(65%); --stab-background-color: #314559; --stab-code-color: #e6e1cf; --code-highlight-kw-color: #ab8ac1; diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css index 38154dee3e287..2a9b4c9588380 100644 --- a/src/librustdoc/html/static/css/rustdoc.css +++ b/src/librustdoc/html/static/css/rustdoc.css @@ -165,7 +165,7 @@ h1, h2, h3, h4 { .main-heading h1 { margin: 0; padding: 0; - flex-grow: 1; + grid-area: main-heading-h1; /* We use overflow-wrap: break-word for Safari, which doesn't recognize `anywhere`: https://developer.mozilla.org/en-US/docs/Web/CSS/overflow-wrap */ overflow-wrap: break-word; @@ -174,8 +174,12 @@ h1, h2, h3, h4 { overflow-wrap: anywhere; } .main-heading { - display: flex; - flex-wrap: wrap; + position: relative; + display: grid; + grid-template-areas: + "main-heading-h1 main-heading-toolbar" + "main-heading-sub-heading main-heading-toolbar"; + grid-template-columns: 1fr max-content; padding-bottom: 6px; margin-bottom: 15px; } @@ -218,9 +222,10 @@ h1, h2, h3, h4, h5, h6, .search-results .result-name, .item-name > a, .out-of-band, +.sub-heading, span.since, a.src, -#help-button > a, +rustdoc-toolbar, summary.hideme, .scraped-example-list, /* This selector is for the items listed in the "all items" page. */ @@ -884,9 +889,19 @@ both the code example and the line numbers, so we need to remove the radius in t overflow-x: auto; } -.out-of-band { +.sub-heading { flex-grow: 0; font-size: 1.125rem; + grid-area: main-heading-sub-heading; +} + +.main-heading rustdoc-toolbar, .main-heading .out-of-band { + grid-area: main-heading-toolbar; +} +rustdoc-toolbar { + display: flex; + flex-direction: row; + flex-wrap: nowrap; } .docblock code, .docblock-short code, @@ -1282,10 +1297,16 @@ so that we can apply CSS-filters to change the arrow color in themes */ border-color: var(--settings-input-color) !important; } +#settings.popover { + --popover-arrow-offset: 118px; + top: 26px; +} + /* use larger max-width for help popover, but not for help.html */ #help.popover { max-width: 600px; - --popover-arrow-offset: 48px; + --popover-arrow-offset: 36px; + top: 26px; } #help dt { @@ -1293,10 +1314,15 @@ so that we can apply CSS-filters to change the arrow color in themes */ clear: left; margin-right: 0.5rem; } +#help dd { + margin-bottom: 0.5rem; +} #help span.top, #help span.bottom { text-align: center; display: block; font-size: 1.125rem; + padding: 0 0.5rem; + text-wrap-style: balance; } #help span.top { margin: 10px 0; @@ -1308,10 +1334,13 @@ so that we can apply CSS-filters to change the arrow color in themes */ clear: both; border-top: 1px solid var(--border-color); } +.side-by-side { + display: flex; + margin-bottom: 20px; +} .side-by-side > div { width: 50%; - float: left; - padding: 0 20px 20px 17px; + padding: 0 20px 0 17px; } .item-info .stab { @@ -1374,7 +1403,9 @@ so that we can apply CSS-filters to change the arrow color in themes */ } .rightside:not(a), -.out-of-band { +.out-of-band, +.sub-heading, +rustdoc-toolbar { color: var(--right-side-color); } @@ -1588,8 +1619,8 @@ instead, we check that it's not a "finger" cursor. display: block; } -.out-of-band > span.since { - font-size: 1.25rem; +.main-heading span.since::before { + content: "Since "; } .sub-variant h4 { @@ -1691,6 +1722,8 @@ a.tooltip:hover::after { } #search-tabs { + grid-area: main-heading-sub-heading; + margin-top: 0.25rem; display: flex; flex-direction: row; gap: 1px; @@ -1752,9 +1785,10 @@ a.tooltip:hover::after { border-bottom: 1px solid var(--border-color); } -#settings-menu, #help-button { +#settings-menu, #help-button, button#toggle-all-docs { margin-left: var(--button-left-margin); display: flex; + line-height: initial; } #sidebar-button { display: none; @@ -1778,33 +1812,35 @@ a.tooltip:hover::after { .hide-sidebar .src #sidebar-button { position: static; } -#settings-menu > a, #help-button > a, #sidebar-button > a { +#settings-menu > a, #help-button > a, #sidebar-button > a, button#toggle-all-docs { display: flex; align-items: center; justify-content: center; - background-color: var(--button-background-color); - border: 1px solid var(--border-color); + flex-direction: column; + border: 1px solid transparent; border-radius: var(--button-border-radius); - color: var(--settings-button-color); - /* Rare exception to specifying font sizes in rem. Since this is acting - as an icon, it's okay to specify their sizes in pixels. */ - font-size: 20px; + color: var(--main-color); +} +#settings-menu > a, #help-button > a, button#toggle-all-docs { + width: 80px; +} +#sidebar-button > a { + background-color: var(--button-background-color); + border-color: var(--border-color); width: 33px; } -#settings-menu > a:hover, #settings-menu > a:focus, -#help-button > a:hover, #help-button > a:focus, -#sidebar-button > a:hover, #sidebar-button > a:focus { +#settings-menu > a:hover, #settings-menu > a:focus-visible, +#help-button > a:hover, #help-button > a:focus-visible, +#sidebar-button > a:hover, #sidebar-button > a:focus-visible, +button#toggle-all-docs:hover, button#toggle-all-docs:focus-visible { border-color: var(--settings-button-border-focus); + text-decoration: none; } -#settings-menu > a { - line-height: 0; - font-size: 0; -} #settings-menu > a:before { /* Wheel */ - content: url('data:image/svg+xml,\ '); - width: 22px; - height: 22px; + width: 18px; + height: 18px; filter: var(--settings-menu-filter); } +button#toggle-all-docs:before { + /* Custom arrow icon */ + content: url('data:image/svg+xml,\ + '); + width: 18px; + height: 18px; + filter: var(--settings-menu-filter); +} + +#help-button > a:before { + /* Question mark with circle */ + content: url('data:image/svg+xml,\ + \ + ?'); + width: 18px; + height: 18px; + filter: var(--settings-menu-filter); +} + +button#toggle-all-docs:before, +#help-button > a:before, +#settings-menu > a:before { + filter: var(--settings-menu-filter); + margin: 8px; +} + +@media not (pointer: coarse) { + button#toggle-all-docs:hover:before, + #help-button > a:hover:before, + #settings-menu > a:hover:before { + filter: var(--settings-menu-hover-filter); + } +} + +rustdoc-toolbar span.label { + font-size: initial; + font-variant-caps: small-caps; + text-transform: lowercase; + flex-grow: 1; +} + #sidebar-button > a:before { /* sidebar resizer image */ content: url('data:image/svg+xml,\ - \ + \ \ '); width: 22px; @@ -1941,10 +2020,10 @@ details.toggle > summary.hideme > span { } details.toggle > summary::before { - /* toggle plus */ - background: url('data:image/svg+xml,') no-repeat top left; + /* arrow pointing left */ + background: url('data:image/svg+xml,\ + '); content: ""; cursor: pointer; width: 16px; @@ -2027,10 +2106,10 @@ details.toggle[open] > summary.hideme > span { } details.toggle[open] > summary::before { - /* toggle minus */ - background: url('data:image/svg+xml,') no-repeat top left; + /* arrow pointing down */ + background: url('data:image/svg+xml,\ + '); } details.toggle[open] > summary::after { @@ -2076,6 +2155,15 @@ However, it's not needed with smaller screen width because the doc/code block is opacity: 0.75; } +/* help button is mostly for search */ +#help-button:not(.help-open), +#alternative-display #toggle-all-docs { + display: none; +} +#alternative-display #help-button { + display: flex; +} + /* Media Queries */ /* Make sure all the buttons line wrap at the same time */ @@ -2083,6 +2171,12 @@ However, it's not needed with smaller screen width because the doc/code block is #search-tabs .count { display: block; } + .side-by-side { + flex-direction: column-reverse; + } + .side-by-side > div { + width: auto; + } } /* @@ -2099,6 +2193,27 @@ in src-script.js and main.js scroll-margin-top: 45px; } + /* We don't display this button on mobile devices. */ + #copy-path { + display: none; + } + + /* Text label takes up too much space at this size. */ + rustdoc-toolbar span.label { + display: none; + } + #settings-menu > a, #help-button > a, button#toggle-all-docs { + width: 33px; + } + #settings.popover { + --popover-arrow-offset: 48px; + top: calc(100% - 8px); + } + #help.popover { + --popover-arrow-offset: 12px; + top: calc(100% - 8px); + } + .rustdoc { /* Sidebar should overlay main content, rather than pushing main content to the right. Turn off `display: flex` on the body element. */ @@ -2110,20 +2225,6 @@ in src-script.js and main.js padding-top: 0px; } - .main-heading { - flex-direction: column; - } - - .out-of-band { - text-align: left; - margin-left: initial; - padding: initial; - } - - .out-of-band .since::before { - content: "Since "; - } - /* Hide the logo and item name from the sidebar. Those are displayed in the mobile-topbar instead. */ .sidebar .logo-container, @@ -2227,16 +2328,11 @@ in src-script.js and main.js left: -11px; } - /* We don't display these buttons on mobile devices. */ - #copy-path, #help-button { - display: none; - } - /* sidebar button becomes topbar button */ #sidebar-button > a:before { content: url('data:image/svg+xml,\ - \ + \ \ '); width: 22px; @@ -2536,6 +2632,8 @@ by default. --copy-path-img-hover-filter: invert(35%); --code-example-button-color: #7f7f7f; --code-example-button-hover-color: #595959; + --settings-menu-filter: invert(50%); + --settings-menu-hover-filter: invert(35%); --codeblock-error-hover-color: rgb(255, 0, 0); --codeblock-error-color: rgba(255, 0, 0, .5); --codeblock-ignore-hover-color: rgb(255, 142, 0); @@ -2562,7 +2660,6 @@ by default. --search-tab-button-not-selected-background: #e6e6e6; --search-tab-button-selected-border-top-color: #0089ff; --search-tab-button-selected-background: #fff; - --settings-menu-filter: none; --stab-background-color: #fff5d6; --stab-code-color: #000; --code-highlight-kw-color: #8959a8; @@ -2666,7 +2763,8 @@ by default. --search-tab-button-not-selected-background: #252525; --search-tab-button-selected-border-top-color: #0089ff; --search-tab-button-selected-background: #353535; - --settings-menu-filter: none; + --settings-menu-filter: invert(50%); + --settings-menu-hover-filter: invert(65%); --stab-background-color: #314559; --stab-code-color: #e6e1cf; --code-highlight-kw-color: #ab8ac1; @@ -2777,7 +2875,8 @@ Original by Dempfi (https://github.com/dempfi/ayu) --search-tab-button-not-selected-background: transparent !important; --search-tab-button-selected-border-top-color: none; --search-tab-button-selected-background: #141920 !important; - --settings-menu-filter: invert(100%); + --settings-menu-filter: invert(70%); + --settings-menu-hover-filter: invert(100%); --stab-background-color: #314559; --stab-code-color: #e6e1cf; --code-highlight-kw-color: #ff7733; diff --git a/src/librustdoc/html/static/js/main.js b/src/librustdoc/html/static/js/main.js index 858753a1917d8..53326f0fcadf1 100644 --- a/src/librustdoc/html/static/js/main.js +++ b/src/librustdoc/html/static/js/main.js @@ -22,14 +22,14 @@ function hideMain() { } function showMain() { - removeClass(document.getElementById(MAIN_ID), "hidden"); -} - -function blurHandler(event, parentElem, hideCallback) { - if (!parentElem.contains(document.activeElement) && - !parentElem.contains(event.relatedTarget) - ) { - hideCallback(); + const main = document.getElementById(MAIN_ID); + removeClass(main, "hidden"); + const mainHeading = main.querySelector(".main-heading"); + if (mainHeading && searchState.rustdocToolbar) { + if (searchState.rustdocToolbar.parentElement) { + searchState.rustdocToolbar.parentElement.removeChild(searchState.rustdocToolbar); + } + mainHeading.appendChild(searchState.rustdocToolbar); } } @@ -167,6 +167,14 @@ function switchDisplayedElement(elemToDisplay) { el.appendChild(elemToDisplay); hideMain(); removeClass(el, "hidden"); + + const mainHeading = elemToDisplay.querySelector(".main-heading"); + if (mainHeading && searchState.rustdocToolbar) { + if (searchState.rustdocToolbar.parentElement) { + searchState.rustdocToolbar.parentElement.removeChild(searchState.rustdocToolbar); + } + mainHeading.appendChild(searchState.rustdocToolbar); + } } function browserSupportsHistoryApi() { @@ -194,33 +202,36 @@ function preLoadCss(cssUrl) { document.head.append(script); } - getSettingsButton().onclick = event => { - if (event.ctrlKey || event.altKey || event.metaKey) { - return; - } - window.hideAllModals(false); - addClass(getSettingsButton(), "rotate"); - event.preventDefault(); - // Sending request for the CSS and the JS files at the same time so it will - // hopefully be loaded when the JS will generate the settings content. - loadScript(getVar("static-root-path") + getVar("settings-js")); - // Pre-load all theme CSS files, so that switching feels seamless. - // - // When loading settings.html as a standalone page, the equivalent HTML is - // generated in context.rs. - setTimeout(() => { - const themes = getVar("themes").split(","); - for (const theme of themes) { - // if there are no themes, do nothing - // "".split(",") == [""] - if (theme !== "") { - preLoadCss(getVar("root-path") + theme + ".css"); - } + if (getSettingsButton()) { + getSettingsButton().onclick = event => { + if (event.ctrlKey || event.altKey || event.metaKey) { + return; } - }, 0); - }; + window.hideAllModals(false); + addClass(getSettingsButton(), "rotate"); + event.preventDefault(); + // Sending request for the CSS and the JS files at the same time so it will + // hopefully be loaded when the JS will generate the settings content. + loadScript(getVar("static-root-path") + getVar("settings-js")); + // Pre-load all theme CSS files, so that switching feels seamless. + // + // When loading settings.html as a standalone page, the equivalent HTML is + // generated in context.rs. + setTimeout(() => { + const themes = getVar("themes").split(","); + for (const theme of themes) { + // if there are no themes, do nothing + // "".split(",") == [""] + if (theme !== "") { + preLoadCss(getVar("root-path") + theme + ".css"); + } + } + }, 0); + }; + } window.searchState = { + rustdocToolbar: document.querySelector("rustdoc-toolbar"), loadingText: "Loading search results...", input: document.getElementsByClassName("search-input")[0], outputElement: () => { @@ -919,8 +930,7 @@ function preLoadCss(cssUrl) { e.open = true; } }); - innerToggle.title = "collapse all docs"; - innerToggle.children[0].innerText = "\u2212"; // "\u2212" is "−" minus sign + innerToggle.children[0].innerText = "Summary"; } function collapseAllDocs() { @@ -934,8 +944,7 @@ function preLoadCss(cssUrl) { e.open = false; } }); - innerToggle.title = "expand all docs"; - innerToggle.children[0].innerText = "+"; + innerToggle.children[0].innerText = "Show all"; } function toggleAllDocs() { @@ -1328,7 +1337,13 @@ function preLoadCss(cssUrl) { } function helpBlurHandler(event) { - blurHandler(event, getHelpButton(), window.hidePopoverMenus); + if (!getHelpButton().contains(document.activeElement) && + !getHelpButton().contains(event.relatedTarget) && + !getSettingsButton().contains(document.activeElement) && + !getSettingsButton().contains(event.relatedTarget) + ) { + window.hidePopoverMenus(); + } } function buildHelpMenu() { @@ -1431,9 +1446,13 @@ href="https://doc.rust-lang.org/${channel}/rustdoc/read-documentation/search.htm * Hide all the popover menus. */ window.hidePopoverMenus = () => { - onEachLazy(document.querySelectorAll(".search-form .popover"), elem => { + onEachLazy(document.querySelectorAll("rustdoc-toolbar .popover"), elem => { elem.style.display = "none"; }); + const button = getHelpButton(); + if (button) { + removeClass(button, "help-open"); + } }; /** @@ -1458,7 +1477,9 @@ href="https://doc.rust-lang.org/${channel}/rustdoc/read-documentation/search.htm function showHelp() { // Prevent `blur` events from being dispatched as a result of closing // other modals. - getHelpButton().querySelector("a").focus(); + const button = getHelpButton(); + addClass(button, "help-open"); + button.querySelector("a").focus(); const menu = getHelpMenu(true); if (menu.style.display === "none") { window.hideAllModals(); @@ -1466,28 +1487,15 @@ href="https://doc.rust-lang.org/${channel}/rustdoc/read-documentation/search.htm } } + const helpLink = document.querySelector(`#${HELP_BUTTON_ID} > a`); if (isHelpPage) { - showHelp(); - document.querySelector(`#${HELP_BUTTON_ID} > a`).addEventListener("click", event => { - // Already on the help page, make help button a no-op. - const target = event.target; - if (target.tagName !== "A" || - target.parentElement.id !== HELP_BUTTON_ID || - event.ctrlKey || - event.altKey || - event.metaKey) { - return; - } - event.preventDefault(); - }); - } else { - document.querySelector(`#${HELP_BUTTON_ID} > a`).addEventListener("click", event => { + buildHelpMenu(); + } else if (helpLink) { + helpLink.addEventListener("click", event => { // By default, have help button open docs in a popover. // If user clicks with a moderator, though, use default browser behavior, // probably opening in a new window or tab. - const target = event.target; - if (target.tagName !== "A" || - target.parentElement.id !== HELP_BUTTON_ID || + if (!helpLink.contains(helpLink) || event.ctrlKey || event.altKey || event.metaKey) { diff --git a/src/librustdoc/html/static/js/search.js b/src/librustdoc/html/static/js/search.js index 4da0bbc787d9e..15b1046a27cdb 100644 --- a/src/librustdoc/html/static/js/search.js +++ b/src/librustdoc/html/static/js/search.js @@ -3605,7 +3605,8 @@ async function showResults(results, go_to_first, filterCrates) { crates += "

"; } - let output = `

Results${crates}

`; + let output = `
\ +

Results${crates}

`; if (results.query.error !== null) { const error = results.query.error; error.forEach((value, index) => { @@ -3662,6 +3663,9 @@ async function showResults(results, go_to_first, filterCrates) { resultsElem.appendChild(ret_returned[0]); search.innerHTML = output; + if (searchState.rustdocToolbar) { + search.querySelector(".main-heading").appendChild(searchState.rustdocToolbar); + } const crateSearch = document.getElementById("crate-search"); if (crateSearch) { crateSearch.addEventListener("input", updateCrate); diff --git a/src/librustdoc/html/static/js/settings.js b/src/librustdoc/html/static/js/settings.js index c52a19ef98738..183663b94fc28 100644 --- a/src/librustdoc/html/static/js/settings.js +++ b/src/librustdoc/html/static/js/settings.js @@ -1,7 +1,7 @@ // Local js definitions: /* global getSettingValue, updateLocalStorage, updateTheme */ -/* global addClass, removeClass, onEach, onEachLazy, blurHandler */ -/* global MAIN_ID, getVar, getSettingsButton */ +/* global addClass, removeClass, onEach, onEachLazy */ +/* global MAIN_ID, getVar, getSettingsButton, getHelpButton */ "use strict"; @@ -267,15 +267,16 @@ } function settingsBlurHandler(event) { - blurHandler(event, getSettingsButton(), window.hidePopoverMenus); + if (!getHelpButton().contains(document.activeElement) && + !getHelpButton().contains(event.relatedTarget) && + !getSettingsButton().contains(document.activeElement) && + !getSettingsButton().contains(event.relatedTarget) + ) { + window.hidePopoverMenus(); + } } - if (isSettingsPage) { - // We replace the existing "onclick" callback to do nothing if clicked. - getSettingsButton().onclick = event => { - event.preventDefault(); - }; - } else { + if (!isSettingsPage) { // We replace the existing "onclick" callback. const settingsButton = getSettingsButton(); const settingsMenu = document.getElementById("settings"); diff --git a/src/librustdoc/html/static/js/storage.js b/src/librustdoc/html/static/js/storage.js index d75fb7a7fb5ab..344743c87edd3 100644 --- a/src/librustdoc/html/static/js/storage.js +++ b/src/librustdoc/html/static/js/storage.js @@ -274,16 +274,29 @@ class RustdocSearchElement extends HTMLElement { spellcheck="false" placeholder="Type ‘S’ or ‘/’ to search, ‘?’ for more options…" type="search"> -
- ? -
- `; } } window.customElements.define("rustdoc-search", RustdocSearchElement); +class RustdocToolbarElement extends HTMLElement { + constructor() { + super(); + } + connectedCallback() { + // Avoid replacing the children after they're already here. + if (this.firstElementChild) { + return; + } + const rootPath = getVar("root-path"); + this.innerHTML = ` +
+ Settings +
+ +
+ Help +
`; + } +} +window.customElements.define("rustdoc-toolbar", RustdocToolbarElement); diff --git a/src/librustdoc/html/templates/print_item.html b/src/librustdoc/html/templates/print_item.html index 76e770453b6ea..1b8c8293088fd 100644 --- a/src/librustdoc/html/templates/print_item.html +++ b/src/librustdoc/html/templates/print_item.html @@ -10,17 +10,16 @@

Copy item path {# #} {# #}

{# #} - + + {% if !stability_since_raw.is_empty() %} - {{ stability_since_raw|safe +}} · {#+ #} + {{ stability_since_raw|safe +}} {% endif %} {% match src_href %} {% when Some with (href) %} - source · {#+ #} + {% if !stability_since_raw.is_empty() +%} · {%+ endif %} + source {#+ #} {% else %} {% endmatch %} - {# #} - {# #} +
{# #} diff --git a/src/librustdoc/html/templates/source.html b/src/librustdoc/html/templates/source.html index 60a47f1b5de7d..9daa0cf8ff688 100644 --- a/src/librustdoc/html/templates/source.html +++ b/src/librustdoc/html/templates/source.html @@ -1,4 +1,15 @@ -
+{% match file_path %} +{% when Some with ((path, name)) %} +
{# #} +

{# #} +
{{path}}/
+ {{name}} +

{# #} + {# #} +
+{% else %} +{% endmatch %} +
{# #} {# https://developers.google.com/search/docs/crawling-indexing/robots-meta-tag#data-nosnippet-attr Do not show "1 2 3 4 5 ..." in web search results. #}
diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs
index 6649e1721a48b..5f303d96c40df 100644
--- a/src/librustdoc/lib.rs
+++ b/src/librustdoc/lib.rs
@@ -10,6 +10,7 @@
 #![feature(iter_intersperse)]
 #![feature(let_chains)]
 #![feature(never_type)]
+#![feature(os_str_display)]
 #![feature(round_char_boundary)]
 #![feature(test)]
 #![feature(type_alias_impl_trait)]
diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs
index c18f569e52867..d24dd334a3438 100644
--- a/src/tools/compiletest/src/runtest.rs
+++ b/src/tools/compiletest/src/runtest.rs
@@ -2739,7 +2739,7 @@ impl<'test> TestCx<'test> {
 
         #[rustfmt::skip]
         let tidy_args = [
-            "--new-blocklevel-tags", "rustdoc-search",
+            "--new-blocklevel-tags", "rustdoc-search,rustdoc-toolbar",
             "--indent", "yes",
             "--indent-spaces", "2",
             "--wrap", "0",
diff --git a/src/tools/html-checker/main.rs b/src/tools/html-checker/main.rs
index ecfbb1955e779..5cdc4d53ab500 100644
--- a/src/tools/html-checker/main.rs
+++ b/src/tools/html-checker/main.rs
@@ -31,7 +31,7 @@ fn check_html_file(file: &Path) -> usize {
         .arg("--mute-id") // this option is useful in case we want to mute more warnings
         .arg("yes")
         .arg("--new-blocklevel-tags")
-        .arg("rustdoc-search") // custom elements
+        .arg("rustdoc-search,rustdoc-toolbar") // custom elements
         .arg("--mute")
         .arg(&to_mute_s)
         .arg(file);
diff --git a/tests/rustdoc-gui/help-page.goml b/tests/rustdoc-gui/help-page.goml
index f1a2675128ce4..6d6e353ae362b 100644
--- a/tests/rustdoc-gui/help-page.goml
+++ b/tests/rustdoc-gui/help-page.goml
@@ -4,7 +4,7 @@ set-window-size: (1000, 1000) // Try desktop size first.
 wait-for: "#help"
 assert-css: ("#help", {"display": "block"})
 assert-css: ("#help dd", {"font-size": "16px"})
-click: "#help-button > a"
+assert-false: "#help-button > a"
 assert-css: ("#help", {"display": "block"})
 compare-elements-property: (".sub", "#help", ["offsetWidth"])
 compare-elements-position: (".sub", "#help", ["x"])
@@ -50,7 +50,8 @@ call-function: ("check-colors", {
 })
 
 // This test ensures that opening the help popover without switching pages works.
-go-to: "file://" + |DOC_PATH| + "/test_docs/index.html"
+go-to: "file://" + |DOC_PATH| + "/test_docs/index.html?search=a"
+wait-for: "#search-tabs" // Waiting for the search.js to load.
 set-window-size: (1000, 1000) // Only supported on desktop.
 assert-false: "#help"
 click: "#help-button > a"
@@ -62,7 +63,8 @@ compare-elements-property-false: (".sub", "#help", ["offsetWidth"])
 compare-elements-position-false: (".sub", "#help", ["x"])
 
 // This test ensures that the "the rustdoc book" anchor link within the help popover works.
-go-to: "file://" + |DOC_PATH| + "/test_docs/index.html"
+go-to: "file://" + |DOC_PATH| + "/test_docs/index.html?search=a"
+wait-for: "#search-tabs" // Waiting for the search.js to load.
 set-window-size: (1000, 1000) // Popover only appears when the screen width is >700px.
 assert-false: "#help"
 click: "#help-button > a"
diff --git a/tests/rustdoc-gui/item-info.goml b/tests/rustdoc-gui/item-info.goml
index 7a0194c6cc1f6..debda8d06c2c7 100644
--- a/tests/rustdoc-gui/item-info.goml
+++ b/tests/rustdoc-gui/item-info.goml
@@ -20,7 +20,7 @@ store-position: (
     {"x": second_line_x, "y": second_line_y},
 )
 assert: |first_line_x| != |second_line_x| && |first_line_x| == 516 && |second_line_x| == 272
-assert: |first_line_y| != |second_line_y| && |first_line_y| == 688 && |second_line_y| == 711
+assert: |first_line_y| != |second_line_y| && |first_line_y| == 715 && |second_line_y| == 738
 
 // Now we ensure that they're not rendered on the same line.
 set-window-size: (1100, 800)
diff --git a/tests/rustdoc-gui/mobile.goml b/tests/rustdoc-gui/mobile.goml
index e576385cd5370..a9eee53dd1d50 100644
--- a/tests/rustdoc-gui/mobile.goml
+++ b/tests/rustdoc-gui/mobile.goml
@@ -5,23 +5,8 @@ set-window-size: (400, 600)
 set-font-size: 18
 wait-for: 100 // wait a bit for the resize and the font-size change to be fully taken into account.
 
-// The out-of-band info (source, stable version, collapse) should be below the
-// h1 when the screen gets narrow enough.
-assert-css: (".main-heading", {
-  "display": "flex",
-  "flex-direction": "column"
-})
-
 assert-property: (".mobile-topbar h2", {"offsetHeight": 33})
 
-// Note: We can't use assert-text here because the 'Since' is set by CSS and
-// is therefore not part of the DOM.
-assert-css: (".content .out-of-band .since::before", { "content": "\"Since \"" })
-
-set-window-size: (1000, 1000)
-wait-for: 100 // wait a bit for the resize to be fully taken into account.
-assert-css-false: (".content .out-of-band .since::before", { "content": "\"Since \"" })
-
 // On the settings page, the theme buttons should not line-wrap. Instead, they should
 // all be placed as a group on a line below the setting name "Theme."
 go-to: "file://" + |DOC_PATH| + "/settings.html"
diff --git a/tests/rustdoc-gui/notable-trait.goml b/tests/rustdoc-gui/notable-trait.goml
index e2a8a43007eb0..b8fa26b17f6b6 100644
--- a/tests/rustdoc-gui/notable-trait.goml
+++ b/tests/rustdoc-gui/notable-trait.goml
@@ -248,12 +248,13 @@ click: "//*[@id='method.create_an_iterator_from_read']//*[@class='tooltip']"
 assert-count: ("//*[@class='tooltip popover']", 1)
 assert-false: "//*[@class='sidebar shown']"
 
-// Also check the focus handling for the help button.
+// Also check the focus handling for the settings button.
 set-window-size: (1100, 600)
 reload:
 assert-count: ("//*[@class='tooltip popover']", 0)
 click: "//*[@id='method.create_an_iterator_from_read']//*[@class='tooltip']"
 assert-count: ("//*[@class='tooltip popover']", 1)
-click: "#help-button a"
+click: "#settings-menu a"
+wait-for: "#settings"
 assert-count: ("//*[@class='tooltip popover']", 0)
 assert-false: "#method\.create_an_iterator_from_read .tooltip:focus"
diff --git a/tests/rustdoc-gui/pocket-menu.goml b/tests/rustdoc-gui/pocket-menu.goml
index ec31f492abe7c..4a062fec7516d 100644
--- a/tests/rustdoc-gui/pocket-menu.goml
+++ b/tests/rustdoc-gui/pocket-menu.goml
@@ -1,6 +1,7 @@
 // This test ensures that the "pocket menus" are working as expected.
 include: "utils.goml"
-go-to: "file://" + |DOC_PATH| + "/test_docs/index.html"
+go-to: "file://" + |DOC_PATH| + "/test_docs/index.html?search=test"
+wait-for: "#crate-search"
 // First we check that the help menu doesn't exist yet.
 assert-false: "#help-button .popover"
 // Then we display the help menu.
diff --git a/tests/rustdoc-gui/scrape-examples-layout.goml b/tests/rustdoc-gui/scrape-examples-layout.goml
index 6bea352bce4bb..55187a3e59647 100644
--- a/tests/rustdoc-gui/scrape-examples-layout.goml
+++ b/tests/rustdoc-gui/scrape-examples-layout.goml
@@ -72,8 +72,8 @@ click: ".scraped-example .button-holder .expand"
 store-value: (offset_y, 4)
 
 // First with desktop
-assert-position: (".scraped-example", {"y": 226})
-assert-position: (".scraped-example .prev", {"y": 226 + |offset_y|})
+assert-position: (".scraped-example", {"y": 253})
+assert-position: (".scraped-example .prev", {"y": 253 + |offset_y|})
 
 // Gradient background should be at the top of the code block.
 assert-css: (".scraped-example .example-wrap::before", {"top": "0px"})
diff --git a/tests/rustdoc-gui/search-form-elements.goml b/tests/rustdoc-gui/search-form-elements.goml
index 63d2ceb3e7c1c..efe39f7a9d1bf 100644
--- a/tests/rustdoc-gui/search-form-elements.goml
+++ b/tests/rustdoc-gui/search-form-elements.goml
@@ -1,13 +1,14 @@
 // This test ensures that the elements in ".search-form" have the expected display.
 include: "utils.goml"
-go-to: "file://" + |DOC_PATH| + "/test_docs/index.html"
+go-to: "file://" + |DOC_PATH| + "/test_docs/index.html?search=test"
+wait-for: "#search-tabs" // Waiting for the search.js to load.
 show-text: true
 
 define-function: (
     "check-search-colors",
     [
         theme, border, background, search_input_color, search_input_border_focus,
-        menu_button_border, menu_button_a_color, menu_button_a_border_hover, menu_a_color,
+        menu_button_a_color, menu_button_a_border_hover, menu_a_color,
     ],
     block {
         call-function: ("switch-theme", {"theme": |theme|})
@@ -29,30 +30,22 @@ define-function: (
                 "color": |search_input_color|,
             },
         )
-        assert-css: (
-            "#help-button",
-            {"border-color": |menu_button_border|},
-        )
         assert-css: (
             "#help-button > a",
             {
                 "color": |menu_button_a_color|,
-                "border-color": |border|,
-                "background-color": |background|,
+                "border-color": "transparent",
+                "background-color": "transparent",
             },
         )
         // Hover help button.
         move-cursor-to: "#help-button"
-        assert-css: (
-            "#help-button:hover",
-            {"border-color": |menu_button_border|},
-        )
         assert-css: (
             "#help-button > a",
             {
                 "color": |menu_button_a_color|,
                 "border-color": |menu_button_a_border_hover|,
-                "background-color": |background|,
+                "background-color": "transparent",
             },
         )
         // Link color inside
@@ -63,30 +56,22 @@ define-function: (
                 "color": |menu_a_color|,
             },
         )
-        assert-css: (
-            "#settings-menu",
-            {"border-color": |menu_button_border|},
-        )
         assert-css: (
             "#settings-menu > a",
             {
                 "color": |menu_button_a_color|,
-                "border-color": |border|,
-                "background-color": |background|,
+                "border-color": "transparent",
+                "background-color": "transparent",
             },
         )
         // Hover settings menu.
         move-cursor-to: "#settings-menu"
-        assert-css: (
-            "#settings-menu:hover",
-            {"border-color": |menu_button_border|},
-        )
         assert-css: (
             "#settings-menu:hover > a",
             {
                 "color": |menu_button_a_color|,
                 "border-color": |menu_button_a_border_hover|,
-                "background-color": |background|,
+                "background-color": "transparent",
             },
         )
     },
@@ -100,8 +85,7 @@ call-function: (
         "background": "#141920",
         "search_input_color": "#fff",
         "search_input_border_focus": "#5c6773",
-        "menu_button_border": "#c5c5c5",
-        "menu_button_a_color": "#fff",
+        "menu_button_a_color": "#c5c5c5",
         "menu_button_a_border_hover": "#e0e0e0",
         "menu_a_color": "#39afd7",
     }
@@ -114,8 +98,7 @@ call-function: (
         "background": "#f0f0f0",
         "search_input_color": "#111",
         "search_input_border_focus": "#008dfd",
-        "menu_button_border": "#ddd",
-        "menu_button_a_color": "#000",
+        "menu_button_a_color": "#ddd",
         "menu_button_a_border_hover": "#ffb900",
         "menu_a_color": "#d2991d",
     }
@@ -128,7 +111,6 @@ call-function: (
         "background": "#fff",
         "search_input_color": "#000",
         "search_input_border_focus": "#66afe9",
-        "menu_button_border": "#000",
         "menu_button_a_color": "#000",
         "menu_button_a_border_hover": "#717171",
         "menu_a_color": "#3873ad",
diff --git a/tests/rustdoc-gui/search-result-display.goml b/tests/rustdoc-gui/search-result-display.goml
index 3ca46f3c56931..c69ca59d44a7c 100644
--- a/tests/rustdoc-gui/search-result-display.goml
+++ b/tests/rustdoc-gui/search-result-display.goml
@@ -51,7 +51,10 @@ set-window-size: (900, 900)
 
 // First we check the current width, height and position.
 assert-css: ("#crate-search", {"width": "223px"})
-assert-css: (".search-results-title", {"height": "50px", "width": "640px"})
+store-size: (".search-results-title", {
+    "height": search_results_title_height,
+    "width": search_results_title_width,
+})
 assert-css: ("#search", {"width": "640px"})
 
 // Then we update the text of one of the `";
+        crates = "
in 
" + + "
"; + crates += "
"; } let output = `
\ -

Results${crates}

`; +

Results

${crates}
`; if (results.query.error !== null) { const error = results.query.error; error.forEach((value, index) => { diff --git a/src/librustdoc/html/static/js/storage.js b/src/librustdoc/html/static/js/storage.js index 344743c87edd3..d77804d045e36 100644 --- a/src/librustdoc/html/static/js/storage.js +++ b/src/librustdoc/html/static/js/storage.js @@ -293,10 +293,10 @@ class RustdocToolbarElement extends HTMLElement { -
Help -
`; +
+ `; } } window.customElements.define("rustdoc-toolbar", RustdocToolbarElement); diff --git a/src/librustdoc/html/templates/print_item.html b/src/librustdoc/html/templates/print_item.html index 1b8c8293088fd..2c9f8dbddf090 100644 --- a/src/librustdoc/html/templates/print_item.html +++ b/src/librustdoc/html/templates/print_item.html @@ -1,11 +1,16 @@
{# #} -

- {{typ}} - {# The breadcrumbs of the item path, like std::string #} + {% if !path_components.is_empty() %} + {% for component in path_components %} {{component.name}}:: {% endfor %} - {{name}} {# #} + + {% endif %} +

+ {{typ}} + + {{name}} + {# #} {# #} diff --git a/tests/rustdoc-gui/anchors.goml b/tests/rustdoc-gui/anchors.goml index 61b2e8880c602..3168c8e17c52f 100644 --- a/tests/rustdoc-gui/anchors.goml +++ b/tests/rustdoc-gui/anchors.goml @@ -12,8 +12,7 @@ define-function: ( call-function: ("switch-theme", {"theme": |theme|}) assert-css: ("#toggle-all-docs", {"color": |main_color|}) - assert-css: (".main-heading h1 a:nth-of-type(1)", {"color": |main_heading_color|}) - assert-css: (".main-heading a:nth-of-type(2)", {"color": |main_heading_type_color|}) + assert-css: (".main-heading h1 span", {"color": |main_heading_type_color|}) assert-css: ( ".rightside a.src", {"color": |src_link_color|, "text-decoration": "none solid " + |src_link_color|}, @@ -55,7 +54,7 @@ define-function: ( assert-css: ("#top-doc-prose-title", {"color": |title_color|}) assert-css: (".sidebar .block a", {"color": |sidebar_link_color|}) - assert-css: (".main-heading h1 a", {"color": |title_color|}) + assert-css: (".main-heading h1", {"color": |title_color|}) // We move the cursor over the "Implementations" title so the anchor is displayed. move-cursor-to: "h2#implementations" diff --git a/tests/rustdoc-gui/item-info.goml b/tests/rustdoc-gui/item-info.goml index debda8d06c2c7..2824a5711405c 100644 --- a/tests/rustdoc-gui/item-info.goml +++ b/tests/rustdoc-gui/item-info.goml @@ -20,7 +20,7 @@ store-position: ( {"x": second_line_x, "y": second_line_y}, ) assert: |first_line_x| != |second_line_x| && |first_line_x| == 516 && |second_line_x| == 272 -assert: |first_line_y| != |second_line_y| && |first_line_y| == 715 && |second_line_y| == 738 +assert: |first_line_y| != |second_line_y| && |first_line_y| == 710 && |second_line_y| == 733 // Now we ensure that they're not rendered on the same line. set-window-size: (1100, 800) diff --git a/tests/rustdoc-gui/scrape-examples-layout.goml b/tests/rustdoc-gui/scrape-examples-layout.goml index 55187a3e59647..803e8e499f476 100644 --- a/tests/rustdoc-gui/scrape-examples-layout.goml +++ b/tests/rustdoc-gui/scrape-examples-layout.goml @@ -72,8 +72,8 @@ click: ".scraped-example .button-holder .expand" store-value: (offset_y, 4) // First with desktop -assert-position: (".scraped-example", {"y": 253}) -assert-position: (".scraped-example .prev", {"y": 253 + |offset_y|}) +assert-position: (".scraped-example", {"y": 248}) +assert-position: (".scraped-example .prev", {"y": 248 + |offset_y|}) // Gradient background should be at the top of the code block. assert-css: (".scraped-example .example-wrap::before", {"top": "0px"}) @@ -82,8 +82,8 @@ assert-css: (".scraped-example .example-wrap::after", {"bottom": "0px"}) // Then with mobile set-window-size: (600, 600) store-size: (".scraped-example .scraped-example-title", {"height": title_height}) -assert-position: (".scraped-example", {"y": 284}) -assert-position: (".scraped-example .prev", {"y": 284 + |offset_y| + |title_height|}) +assert-position: (".scraped-example", {"y": 277}) +assert-position: (".scraped-example .prev", {"y": 277 + |offset_y| + |title_height|}) define-function: ( "check_title_and_code_position", diff --git a/tests/rustdoc-gui/search-filter.goml b/tests/rustdoc-gui/search-filter.goml index d6421599a207b..c5038e0892b04 100644 --- a/tests/rustdoc-gui/search-filter.goml +++ b/tests/rustdoc-gui/search-filter.goml @@ -56,7 +56,8 @@ assert-property: ("#crate-search", {"value": "lib2"}) assert-false: "#results .externcrate" // Checking that the text for the "title" is correct (the "all crates" comes from the "-element "#crate-search") to be shrunk */ - min-width: 5em; + min-width: 0; } #crate-search { - min-width: 115px; padding: 0 23px 0 4px; /* prevents the {} + +fn new_node(_c: Vec Propagate<::Output<'a>>>>) -> T { + todo!() +} + +impl Propagate for T {} +struct Noop; + +impl Transform for Noop { + type Output<'a> = (); +} + +fn main() { + let _node: Noop = new_node(vec![Box::new(Noop)]); +} diff --git a/tests/crashes/130627.rs b/tests/crashes/130627.rs new file mode 100644 index 0000000000000..59d3606592bf1 --- /dev/null +++ b/tests/crashes/130627.rs @@ -0,0 +1,20 @@ +//@ known-bug: #130627 + +#![feature(trait_alias)] + +trait Test {} + +#[diagnostic::on_unimplemented( + message="message", + label="label", + note="note" +)] +trait Alias = Test; + +// Use trait alias as bound on type parameter. +fn foo(v: &T) { +} + +pub fn main() { + foo(&1); +} diff --git a/tests/crashes/130687.rs b/tests/crashes/130687.rs new file mode 100644 index 0000000000000..361be0905dfca --- /dev/null +++ b/tests/crashes/130687.rs @@ -0,0 +1,4 @@ +//@ known-bug: #130687 +//@ only-x86_64 +pub struct Data([u8; usize::MAX >> 16]); +const _: &'static Data = &Data([0; usize::MAX >> 16]); diff --git a/tests/crashes/130779.rs b/tests/crashes/130779.rs new file mode 100644 index 0000000000000..f0fd81fff4449 --- /dev/null +++ b/tests/crashes/130779.rs @@ -0,0 +1,11 @@ +//@ known-bug: #130779 +#![feature(never_patterns)] + +enum E { A } + +fn main() { + match E::A { + ! | + if true => {} + } +} diff --git a/tests/crashes/130921.rs b/tests/crashes/130921.rs new file mode 100644 index 0000000000000..b7cb1303937e6 --- /dev/null +++ b/tests/crashes/130921.rs @@ -0,0 +1,10 @@ +//@ known-bug: #130921 +//@ compile-flags: -Zvalidate-mir -Copt-level=0 --crate-type lib + +pub fn hello() -> [impl Sized; 2] { + if false { + let x = hello(); + let _: &[i32] = &x; + } + todo!() +} diff --git a/tests/crashes/130970.rs b/tests/crashes/130970.rs new file mode 100644 index 0000000000000..e1f59c155a56a --- /dev/null +++ b/tests/crashes/130970.rs @@ -0,0 +1,9 @@ +//@ known-bug: #130970 +//@ compile-flags: -Zmir-opt-level=5 -Zvalidate-mir + +fn main() { + extern "C" { + static symbol: [usize]; + } + println!("{}", symbol[0]); +} From a78fd694d47608eb382478b038ad0e91b6f5150d Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 29 Sep 2024 12:16:35 +0200 Subject: [PATCH 1693/2194] extend comment in global_llvm_features regarding target-cpu=native handling --- compiler/rustc_codegen_llvm/src/llvm_util.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/compiler/rustc_codegen_llvm/src/llvm_util.rs b/compiler/rustc_codegen_llvm/src/llvm_util.rs index a2a5499597c34..201cfbb1918c8 100644 --- a/compiler/rustc_codegen_llvm/src/llvm_util.rs +++ b/compiler/rustc_codegen_llvm/src/llvm_util.rs @@ -536,6 +536,11 @@ pub(crate) fn global_llvm_features( // -Ctarget-cpu=native match sess.opts.cg.target_cpu { Some(ref s) if s == "native" => { + // We have already figured out the actual CPU name with `LLVMRustGetHostCPUName` and set + // that for LLVM, so the features implied by that CPU name will be available everywhere. + // However, that is not sufficient: e.g. `skylake` alone is not sufficient to tell if + // some of the instructions are available or not. So we have to also explicitly ask for + // the exact set of features available on the host, and enable all of them. let features_string = unsafe { let ptr = llvm::LLVMGetHostCPUFeatures(); let features_string = if !ptr.is_null() { From e9635685859626cc4ea252eac65beef0f6066e68 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= Date: Sun, 29 Sep 2024 12:18:11 +0200 Subject: [PATCH 1694/2194] cleanup: don't `.into()` identical types --- compiler/rustc_const_eval/src/interpret/intrinsics.rs | 7 ++----- compiler/rustc_interface/src/interface.rs | 2 +- compiler/rustc_lint/src/if_let_rescope.rs | 2 +- 3 files changed, 4 insertions(+), 7 deletions(-) diff --git a/compiler/rustc_const_eval/src/interpret/intrinsics.rs b/compiler/rustc_const_eval/src/interpret/intrinsics.rs index e1fd8bea1f30c..4c34ffc5d4ec1 100644 --- a/compiler/rustc_const_eval/src/interpret/intrinsics.rs +++ b/compiler/rustc_const_eval/src/interpret/intrinsics.rs @@ -396,11 +396,8 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { for i in 0..dest_len { let place = self.project_index(&dest, i)?; - let value = if i == index { - elem.clone() - } else { - self.project_index(&input, i)?.into() - }; + let value = + if i == index { elem.clone() } else { self.project_index(&input, i)? }; self.copy_op(&value, &place)?; } } diff --git a/compiler/rustc_interface/src/interface.rs b/compiler/rustc_interface/src/interface.rs index c2241773c8ccb..3b8077bb3fcee 100644 --- a/compiler/rustc_interface/src/interface.rs +++ b/compiler/rustc_interface/src/interface.rs @@ -427,7 +427,7 @@ pub fn run_compiler(config: Config, f: impl FnOnce(&Compiler) -> R + Se Err(e) => early_dcx.early_fatal(format!("failed to load fluent bundle: {e}")), }; - let mut locale_resources = Vec::from(config.locale_resources); + let mut locale_resources = config.locale_resources; locale_resources.push(codegen_backend.locale_resource()); let mut sess = rustc_session::build_session( diff --git a/compiler/rustc_lint/src/if_let_rescope.rs b/compiler/rustc_lint/src/if_let_rescope.rs index 229d0c3642174..c6218fe1e74e7 100644 --- a/compiler/rustc_lint/src/if_let_rescope.rs +++ b/compiler/rustc_lint/src/if_let_rescope.rs @@ -304,7 +304,7 @@ impl Subdiagnostic for IfLetRescopeRewrite { .chain(repeat('}').take(closing_brackets.count)) .collect(), )); - let msg = f(diag, crate::fluent_generated::lint_suggestion.into()); + let msg = f(diag, crate::fluent_generated::lint_suggestion); diag.multipart_suggestion_with_style( msg, suggestions, From 1a28599981a02ee865e51470be1009300a720faf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= Date: Sun, 29 Sep 2024 12:51:28 +0200 Subject: [PATCH 1695/2194] cleanup: don't manually `unwrap_or_default()` --- compiler/rustc_expand/src/proc_macro_server.rs | 6 ++---- compiler/rustc_hir_typeck/src/upvar.rs | 10 +++------- 2 files changed, 5 insertions(+), 11 deletions(-) diff --git a/compiler/rustc_expand/src/proc_macro_server.rs b/compiler/rustc_expand/src/proc_macro_server.rs index a7b251ab2527e..0dc35618ff889 100644 --- a/compiler/rustc_expand/src/proc_macro_server.rs +++ b/compiler/rustc_expand/src/proc_macro_server.rs @@ -627,8 +627,7 @@ impl server::TokenStream for Rustc<'_, '_> { base: Option, trees: Vec>, ) -> Self::TokenStream { - let mut stream = - if let Some(base) = base { base } else { tokenstream::TokenStream::default() }; + let mut stream = base.unwrap_or_default(); for tree in trees { for tt in (tree, &mut *self).to_internal() { stream.push_tree(tt); @@ -642,8 +641,7 @@ impl server::TokenStream for Rustc<'_, '_> { base: Option, streams: Vec, ) -> Self::TokenStream { - let mut stream = - if let Some(base) = base { base } else { tokenstream::TokenStream::default() }; + let mut stream = base.unwrap_or_default(); for s in streams { stream.push_stream(s); } diff --git a/compiler/rustc_hir_typeck/src/upvar.rs b/compiler/rustc_hir_typeck/src/upvar.rs index c5843b883a17b..63cf483aa2274 100644 --- a/compiler/rustc_hir_typeck/src/upvar.rs +++ b/compiler/rustc_hir_typeck/src/upvar.rs @@ -1369,13 +1369,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { for (&var_hir_id, _) in upvars.iter() { let mut diagnostics_info = Vec::new(); - let auto_trait_diagnostic = if let Some(diagnostics_info) = - self.compute_2229_migrations_for_trait(min_captures, var_hir_id, closure_clause) - { - diagnostics_info - } else { - FxIndexMap::default() - }; + let auto_trait_diagnostic = self + .compute_2229_migrations_for_trait(min_captures, var_hir_id, closure_clause) + .unwrap_or_default(); let drop_reorder_diagnostic = if let Some(diagnostics_info) = self .compute_2229_migrations_for_drop( From 6f5f21adfc88a914c507ba8c9a0f1f34ae292d44 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sat, 28 Sep 2024 22:37:59 +0200 Subject: [PATCH 1696/2194] Rename doctest attribute `standalone-crate` into `standalone_crate` for coherency --- library/core/src/panic/location.rs | 2 +- .../src/write-documentation/documentation-tests.md | 4 ++-- src/librustdoc/html/markdown.rs | 6 +++--- tests/run-make/doctests-merge/doctest-standalone.rs | 4 ++-- tests/rustdoc-ui/doctest/standalone-warning-2024.rs | 2 +- .../rustdoc-ui/doctest/standalone-warning-2024.stderr | 10 +++++----- tests/rustdoc-ui/doctest/standalone-warning.rs | 2 +- 7 files changed, 15 insertions(+), 15 deletions(-) diff --git a/library/core/src/panic/location.rs b/library/core/src/panic/location.rs index 97408a4ac180e..1ad5c07d15cd0 100644 --- a/library/core/src/panic/location.rs +++ b/library/core/src/panic/location.rs @@ -44,7 +44,7 @@ impl<'a> Location<'a> { /// /// # Examples /// - /// ```standalone-crate + /// ```standalone_crate /// use std::panic::Location; /// /// /// Returns the [`Location`] at which it is called. diff --git a/src/doc/rustdoc/src/write-documentation/documentation-tests.md b/src/doc/rustdoc/src/write-documentation/documentation-tests.md index 94ef34ea5a51a..c93893b5ada84 100644 --- a/src/doc/rustdoc/src/write-documentation/documentation-tests.md +++ b/src/doc/rustdoc/src/write-documentation/documentation-tests.md @@ -414,11 +414,11 @@ In some cases, doctests cannot be merged. For example, if you have: The problem with this code is that, if you change any other doctests, it'll likely break when runing `rustdoc --test`, making it tricky to maintain. -This is where the `standalone-crate` attribute comes in: it tells `rustdoc` that a doctest +This is where the `standalone_crate` attribute comes in: it tells `rustdoc` that a doctest should not be merged with the others. So the previous code should use it: ```rust -//! ```standalone-crate +//! ```standalone_crate //! let location = std::panic::Location::caller(); //! assert_eq!(location.line(), 4); //! ``` diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs index e1a8dc6e50cc3..8ae5484feda7a 100644 --- a/src/librustdoc/html/markdown.rs +++ b/src/librustdoc/html/markdown.rs @@ -1264,7 +1264,7 @@ impl LangString { seen_rust_tags = !seen_other_tags || seen_rust_tags; data.no_run = true; } - LangStringToken::LangToken("standalone-crate") => { + LangStringToken::LangToken("standalone_crate") => { data.standalone_crate = true; seen_rust_tags = !seen_other_tags || seen_rust_tags; } @@ -1315,12 +1315,12 @@ impl LangString { "use `test_harness` to run functions marked `#[test]` instead of a \ potentially-implicit `main` function", ), - "standalone" | "standalone_crate" => { + "standalone" | "standalone_crate" | "standalone-crate" => { if let Some(extra) = extra && extra.sp.at_least_rust_2024() { Some( - "use `standalone-crate` to compile this code block \ + "use `standalone_crate` to compile this code block \ separately", ) } else { diff --git a/tests/run-make/doctests-merge/doctest-standalone.rs b/tests/run-make/doctests-merge/doctest-standalone.rs index 4b6a1c6ab616c..ac9f8f9272aa2 100644 --- a/tests/run-make/doctests-merge/doctest-standalone.rs +++ b/tests/run-make/doctests-merge/doctest-standalone.rs @@ -1,11 +1,11 @@ #![crate_name = "foo"] #![crate_type = "lib"] -//! ```standalone-crate +//! ```standalone_crate //! foo::init(); //! ``` -/// ```standalone-crate +/// ```standalone_crate /// foo::init(); /// ``` pub fn init() { diff --git a/tests/rustdoc-ui/doctest/standalone-warning-2024.rs b/tests/rustdoc-ui/doctest/standalone-warning-2024.rs index 33ed16a87fa38..aac4303154697 100644 --- a/tests/rustdoc-ui/doctest/standalone-warning-2024.rs +++ b/tests/rustdoc-ui/doctest/standalone-warning-2024.rs @@ -11,6 +11,6 @@ //! bla //! ``` //! -//! ```standalone_crate +//! ```standalone-crate //! bla //! ``` diff --git a/tests/rustdoc-ui/doctest/standalone-warning-2024.stderr b/tests/rustdoc-ui/doctest/standalone-warning-2024.stderr index ef2e236431985..d69d03d8657c1 100644 --- a/tests/rustdoc-ui/doctest/standalone-warning-2024.stderr +++ b/tests/rustdoc-ui/doctest/standalone-warning-2024.stderr @@ -5,12 +5,12 @@ error: unknown attribute `standalone` 11 | | //! bla 12 | | //! ``` 13 | | //! -14 | | //! ```standalone_crate +14 | | //! ```standalone-crate 15 | | //! bla 16 | | //! ``` | |_______^ | - = help: use `standalone-crate` to compile this code block separately + = help: use `standalone_crate` to compile this code block separately = help: this code block may be skipped during testing, because unknown attributes are treated as markers for code samples written in other programming languages, unless it is also explicitly marked as `rust` note: the lint level is defined here --> $DIR/standalone-warning-2024.rs:8:9 @@ -19,19 +19,19 @@ note: the lint level is defined here | ^^^^^^^^ = note: `#[deny(rustdoc::invalid_codeblock_attributes)]` implied by `#[deny(warnings)]` -error: unknown attribute `standalone_crate` +error: unknown attribute `standalone-crate` --> $DIR/standalone-warning-2024.rs:10:1 | 10 | / //! ```standalone 11 | | //! bla 12 | | //! ``` 13 | | //! -14 | | //! ```standalone_crate +14 | | //! ```standalone-crate 15 | | //! bla 16 | | //! ``` | |_______^ | - = help: use `standalone-crate` to compile this code block separately + = help: use `standalone_crate` to compile this code block separately = help: this code block may be skipped during testing, because unknown attributes are treated as markers for code samples written in other programming languages, unless it is also explicitly marked as `rust` error: aborting due to 2 previous errors diff --git a/tests/rustdoc-ui/doctest/standalone-warning.rs b/tests/rustdoc-ui/doctest/standalone-warning.rs index 323d8f5f58065..ce081c7641c61 100644 --- a/tests/rustdoc-ui/doctest/standalone-warning.rs +++ b/tests/rustdoc-ui/doctest/standalone-warning.rs @@ -5,6 +5,6 @@ //! bla //! ``` //! -//! ```standalone_crate +//! ```standalone-crate //! bla //! ``` From 7b757b3e17ee950e29beb391c77e1dfebdd19d23 Mon Sep 17 00:00:00 2001 From: Noah Bright Date: Sat, 28 Sep 2024 07:01:32 -0400 Subject: [PATCH 1697/2194] Rename object_safety to dyn_compatibility Up to a trait implemented by another package, linking to $CARGO_HOME/registry/cache/index.crates.io-6f17d22bba15001f/ --- .../crates/hir-ty/src/chalk_db.rs | 3 +- .../rust-analyzer/crates/hir-ty/src/db.rs | 10 +-- ...{object_safety.rs => dyn_compatibility.rs} | 57 +++++++------- .../tests.rs | 78 ++++++++++--------- .../rust-analyzer/crates/hir-ty/src/lib.rs | 2 +- src/tools/rust-analyzer/crates/hir/src/lib.rs | 6 +- .../crates/ide-db/src/generated/lints.rs | 4 +- .../crates/ide/src/hover/render.rs | 38 ++++----- .../crates/ide/src/hover/tests.rs | 12 +-- .../rust-analyzer/crates/syntax/src/ast.rs | 2 +- .../rust-analyzer/crates/vfs/src/loader.rs | 4 +- src/tools/rust-analyzer/docs/dev/syntax.md | 2 +- 12 files changed, 112 insertions(+), 106 deletions(-) rename src/tools/rust-analyzer/crates/hir-ty/src/{object_safety.rs => dyn_compatibility.rs} (92%) rename src/tools/rust-analyzer/crates/hir-ty/src/{object_safety => dyn_compatibility}/tests.rs (78%) diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/chalk_db.rs b/src/tools/rust-analyzer/crates/hir-ty/src/chalk_db.rs index e74e3d789883e..f7bacbd49b335 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/chalk_db.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/chalk_db.rs @@ -382,8 +382,9 @@ impl chalk_solve::RustIrDatabase for ChalkContext<'_> { } fn is_object_safe(&self, trait_id: chalk_ir::TraitId) -> bool { + // FIXME: When cargo is updated, change to dyn_compatibility let trait_ = from_chalk_trait_id(trait_id); - crate::object_safety::object_safety(self.db, trait_).is_none() + crate::dyn_compatibility::dyn_compatibility(self.db, trait_).is_none() } fn closure_kind( diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/db.rs b/src/tools/rust-analyzer/crates/hir-ty/src/db.rs index ce5a821ea2bc4..5620d80adb537 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/db.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/db.rs @@ -20,11 +20,11 @@ use triomphe::Arc; use crate::{ chalk_db, consteval::ConstEvalError, + dyn_compatibility::DynCompatibilityViolation, layout::{Layout, LayoutError}, lower::{GenericDefaults, GenericPredicates}, method_resolution::{InherentImpls, TraitImpls, TyFingerprint}, mir::{BorrowckResult, MirBody, MirLowerError}, - object_safety::ObjectSafetyViolation, Binders, ClosureId, Const, FnDefId, ImplTraitId, ImplTraits, InferenceResult, Interner, PolyFnSig, Substitution, TraitEnvironment, TraitRef, Ty, TyDefId, ValueTyDefId, }; @@ -108,8 +108,8 @@ pub trait HirDatabase: DefDatabase + Upcast { #[salsa::invoke(crate::layout::target_data_layout_query)] fn target_data_layout(&self, krate: CrateId) -> Result, Arc>; - #[salsa::invoke(crate::object_safety::object_safety_of_trait_query)] - fn object_safety_of_trait(&self, trait_: TraitId) -> Option; + #[salsa::invoke(crate::dyn_compatibility::dyn_compatibility_of_trait_query)] + fn dyn_compatibility_of_trait(&self, trait_: TraitId) -> Option; #[salsa::invoke(crate::lower::ty_query)] #[salsa::cycle(crate::lower::ty_recover)] @@ -280,8 +280,8 @@ pub trait HirDatabase: DefDatabase + Upcast { } #[test] -fn hir_database_is_object_safe() { - fn _assert_object_safe(_: &dyn HirDatabase) {} +fn hir_database_is_dyn_compatible() { + fn _assert_dyn_compatible(_: &dyn HirDatabase) {} } #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/object_safety.rs b/src/tools/rust-analyzer/crates/hir-ty/src/dyn_compatibility.rs similarity index 92% rename from src/tools/rust-analyzer/crates/hir-ty/src/object_safety.rs rename to src/tools/rust-analyzer/crates/hir-ty/src/dyn_compatibility.rs index a4c6626855523..e0d1758210ecc 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/object_safety.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/dyn_compatibility.rs @@ -1,4 +1,4 @@ -//! Compute the object-safety of a trait +//! Compute the dyn-compatibility of a trait use std::ops::ControlFlow; @@ -28,14 +28,14 @@ use crate::{ }; #[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub enum ObjectSafetyViolation { +pub enum DynCompatibilityViolation { SizedSelf, SelfReferential, Method(FunctionId, MethodViolationCode), AssocConst(ConstId), GAT(TypeAliasId), // This doesn't exist in rustc, but added for better visualization - HasNonSafeSuperTrait(TraitId), + HasNonCompatibleSuperTrait(TraitId), } #[derive(Debug, Clone, PartialEq, Eq, Hash)] @@ -50,70 +50,73 @@ pub enum MethodViolationCode { UndispatchableReceiver, } -pub fn object_safety(db: &dyn HirDatabase, trait_: TraitId) -> Option { +pub fn dyn_compatibility( + db: &dyn HirDatabase, + trait_: TraitId, +) -> Option { for super_trait in all_super_traits(db.upcast(), trait_).into_iter().skip(1).rev() { - if db.object_safety_of_trait(super_trait).is_some() { - return Some(ObjectSafetyViolation::HasNonSafeSuperTrait(super_trait)); + if db.dyn_compatibility_of_trait(super_trait).is_some() { + return Some(DynCompatibilityViolation::HasNonCompatibleSuperTrait(super_trait)); } } - db.object_safety_of_trait(trait_) + db.dyn_compatibility_of_trait(trait_) } -pub fn object_safety_with_callback( +pub fn dyn_compatibility_with_callback( db: &dyn HirDatabase, trait_: TraitId, cb: &mut F, ) -> ControlFlow<()> where - F: FnMut(ObjectSafetyViolation) -> ControlFlow<()>, + F: FnMut(DynCompatibilityViolation) -> ControlFlow<()>, { for super_trait in all_super_traits(db.upcast(), trait_).into_iter().skip(1).rev() { - if db.object_safety_of_trait(super_trait).is_some() { - cb(ObjectSafetyViolation::HasNonSafeSuperTrait(trait_))?; + if db.dyn_compatibility_of_trait(super_trait).is_some() { + cb(DynCompatibilityViolation::HasNonCompatibleSuperTrait(trait_))?; } } - object_safety_of_trait_with_callback(db, trait_, cb) + dyn_compatibility_of_trait_with_callback(db, trait_, cb) } -pub fn object_safety_of_trait_with_callback( +pub fn dyn_compatibility_of_trait_with_callback( db: &dyn HirDatabase, trait_: TraitId, cb: &mut F, ) -> ControlFlow<()> where - F: FnMut(ObjectSafetyViolation) -> ControlFlow<()>, + F: FnMut(DynCompatibilityViolation) -> ControlFlow<()>, { // Check whether this has a `Sized` bound if generics_require_sized_self(db, trait_.into()) { - cb(ObjectSafetyViolation::SizedSelf)?; + cb(DynCompatibilityViolation::SizedSelf)?; } // Check if there exist bounds that referencing self if predicates_reference_self(db, trait_) { - cb(ObjectSafetyViolation::SelfReferential)?; + cb(DynCompatibilityViolation::SelfReferential)?; } if bounds_reference_self(db, trait_) { - cb(ObjectSafetyViolation::SelfReferential)?; + cb(DynCompatibilityViolation::SelfReferential)?; } // rustc checks for non-lifetime binders here, but we don't support HRTB yet let trait_data = db.trait_data(trait_); for (_, assoc_item) in &trait_data.items { - object_safety_violation_for_assoc_item(db, trait_, *assoc_item, cb)?; + dyn_compatibility_violation_for_assoc_item(db, trait_, *assoc_item, cb)?; } ControlFlow::Continue(()) } -pub fn object_safety_of_trait_query( +pub fn dyn_compatibility_of_trait_query( db: &dyn HirDatabase, trait_: TraitId, -) -> Option { +) -> Option { let mut res = None; - object_safety_of_trait_with_callback(db, trait_, &mut |osv| { + dyn_compatibility_of_trait_with_callback(db, trait_, &mut |osv| { res = Some(osv); ControlFlow::Break(()) }); @@ -321,14 +324,14 @@ fn contains_illegal_self_type_reference>( t.visit_with(visitor.as_dyn(), outer_binder).is_break() } -fn object_safety_violation_for_assoc_item( +fn dyn_compatibility_violation_for_assoc_item( db: &dyn HirDatabase, trait_: TraitId, item: AssocItemId, cb: &mut F, ) -> ControlFlow<()> where - F: FnMut(ObjectSafetyViolation) -> ControlFlow<()>, + F: FnMut(DynCompatibilityViolation) -> ControlFlow<()>, { // Any item that has a `Self : Sized` requisite is otherwise // exempt from the regulations. @@ -337,10 +340,10 @@ where } match item { - AssocItemId::ConstId(it) => cb(ObjectSafetyViolation::AssocConst(it)), + AssocItemId::ConstId(it) => cb(DynCompatibilityViolation::AssocConst(it)), AssocItemId::FunctionId(it) => { virtual_call_violations_for_method(db, trait_, it, &mut |mvc| { - cb(ObjectSafetyViolation::Method(it, mvc)) + cb(DynCompatibilityViolation::Method(it, mvc)) }) } AssocItemId::TypeAliasId(it) => { @@ -350,7 +353,7 @@ where } else { let generic_params = db.generic_params(item.into()); if !generic_params.is_empty() { - cb(ObjectSafetyViolation::GAT(it)) + cb(DynCompatibilityViolation::GAT(it)) } else { ControlFlow::Continue(()) } @@ -469,7 +472,7 @@ fn receiver_is_dispatchable( return false; }; - // `self: Self` can't be dispatched on, but this is already considered object safe. + // `self: Self` can't be dispatched on, but this is already considered dyn compatible // See rustc's comment on https://github.com/rust-lang/rust/blob/3f121b9461cce02a703a0e7e450568849dfaa074/compiler/rustc_trait_selection/src/traits/object_safety.rs#L433-L437 if sig .skip_binders() diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/object_safety/tests.rs b/src/tools/rust-analyzer/crates/hir-ty/src/dyn_compatibility/tests.rs similarity index 78% rename from src/tools/rust-analyzer/crates/hir-ty/src/object_safety/tests.rs rename to src/tools/rust-analyzer/crates/hir-ty/src/dyn_compatibility/tests.rs index c2a9117c5be4f..3f3e68eeb1c28 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/object_safety/tests.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/dyn_compatibility/tests.rs @@ -5,29 +5,29 @@ use rustc_hash::{FxHashMap, FxHashSet}; use syntax::ToSmolStr; use test_fixture::WithFixture; -use crate::{object_safety::object_safety_with_callback, test_db::TestDB}; +use crate::{dyn_compatibility::dyn_compatibility_with_callback, test_db::TestDB}; use super::{ + DynCompatibilityViolation, MethodViolationCode::{self, *}, - ObjectSafetyViolation, }; -use ObjectSafetyViolationKind::*; +use DynCompatibilityViolationKind::*; #[allow(clippy::upper_case_acronyms)] #[derive(Debug, Clone, PartialEq, Eq, Hash)] -enum ObjectSafetyViolationKind { +enum DynCompatibilityViolationKind { SizedSelf, SelfReferential, Method(MethodViolationCode), AssocConst, GAT, - HasNonSafeSuperTrait, + HasNonCompatibleSuperTrait, } -fn check_object_safety<'a>( +fn check_dyn_compatibility<'a>( ra_fixture: &str, - expected: impl IntoIterator)>, + expected: impl IntoIterator)>, ) { let mut expected: FxHashMap<_, _> = expected.into_iter().map(|(id, osvs)| (id, FxHashSet::from_iter(osvs))).collect(); @@ -53,18 +53,20 @@ fn check_object_safety<'a>( continue; }; let mut osvs = FxHashSet::default(); - object_safety_with_callback(&db, trait_id, &mut |osv| { + dyn_compatibility_with_callback(&db, trait_id, &mut |osv| { osvs.insert(match osv { - ObjectSafetyViolation::SizedSelf => SizedSelf, - ObjectSafetyViolation::SelfReferential => SelfReferential, - ObjectSafetyViolation::Method(_, mvc) => Method(mvc), - ObjectSafetyViolation::AssocConst(_) => AssocConst, - ObjectSafetyViolation::GAT(_) => GAT, - ObjectSafetyViolation::HasNonSafeSuperTrait(_) => HasNonSafeSuperTrait, + DynCompatibilityViolation::SizedSelf => SizedSelf, + DynCompatibilityViolation::SelfReferential => SelfReferential, + DynCompatibilityViolation::Method(_, mvc) => Method(mvc), + DynCompatibilityViolation::AssocConst(_) => AssocConst, + DynCompatibilityViolation::GAT(_) => GAT, + DynCompatibilityViolation::HasNonCompatibleSuperTrait(_) => { + HasNonCompatibleSuperTrait + } }); ControlFlow::Continue(()) }); - assert_eq!(osvs, expected, "Object safety violations for `{name}` do not match;"); + assert_eq!(osvs, expected, "Dyn Compatibility violations for `{name}` do not match;"); } let remains: Vec<_> = expected.keys().collect(); @@ -73,7 +75,7 @@ fn check_object_safety<'a>( #[test] fn item_bounds_can_reference_self() { - check_object_safety( + check_dyn_compatibility( r#" //- minicore: eq pub trait Foo { @@ -88,7 +90,7 @@ pub trait Foo { #[test] fn associated_consts() { - check_object_safety( + check_dyn_compatibility( r#" trait Bar { const X: usize; @@ -100,7 +102,7 @@ trait Bar { #[test] fn bounds_reference_self() { - check_object_safety( + check_dyn_compatibility( r#" //- minicore: eq trait X { @@ -113,7 +115,7 @@ trait X { #[test] fn by_value_self() { - check_object_safety( + check_dyn_compatibility( r#" //- minicore: dispatch_from_dyn trait Bar { @@ -135,7 +137,7 @@ trait Quux { #[test] fn generic_methods() { - check_object_safety( + check_dyn_compatibility( r#" //- minicore: dispatch_from_dyn trait Bar { @@ -157,7 +159,7 @@ trait Qax { #[test] fn mentions_self() { - check_object_safety( + check_dyn_compatibility( r#" //- minicore: dispatch_from_dyn trait Bar { @@ -182,7 +184,7 @@ trait Quux { #[test] fn no_static() { - check_object_safety( + check_dyn_compatibility( r#" //- minicore: dispatch_from_dyn trait Foo { @@ -195,7 +197,7 @@ trait Foo { #[test] fn sized_self() { - check_object_safety( + check_dyn_compatibility( r#" //- minicore: dispatch_from_dyn trait Bar: Sized { @@ -205,7 +207,7 @@ trait Bar: Sized { [("Bar", vec![SizedSelf])], ); - check_object_safety( + check_dyn_compatibility( r#" //- minicore: dispatch_from_dyn trait Bar @@ -220,7 +222,7 @@ trait Bar #[test] fn supertrait_gat() { - check_object_safety( + check_dyn_compatibility( r#" //- minicore: dispatch_from_dyn trait GatTrait { @@ -229,13 +231,13 @@ trait GatTrait { trait SuperTrait: GatTrait {} "#, - [("GatTrait", vec![GAT]), ("SuperTrait", vec![HasNonSafeSuperTrait])], + [("GatTrait", vec![GAT]), ("SuperTrait", vec![HasNonCompatibleSuperTrait])], ); } #[test] fn supertrait_mentions_self() { - check_object_safety( + check_dyn_compatibility( r#" //- minicore: dispatch_from_dyn trait Bar { @@ -251,7 +253,7 @@ trait Baz : Bar { #[test] fn rustc_issue_19538() { - check_object_safety( + check_dyn_compatibility( r#" //- minicore: dispatch_from_dyn trait Foo { @@ -260,13 +262,13 @@ trait Foo { trait Bar: Foo {} "#, - [("Foo", vec![Method(Generic)]), ("Bar", vec![HasNonSafeSuperTrait])], + [("Foo", vec![Method(Generic)]), ("Bar", vec![HasNonCompatibleSuperTrait])], ); } #[test] fn rustc_issue_22040() { - check_object_safety( + check_dyn_compatibility( r#" //- minicore: fmt, eq, dispatch_from_dyn use core::fmt::Debug; @@ -281,7 +283,7 @@ trait Expr: Debug + PartialEq { #[test] fn rustc_issue_102762() { - check_object_safety( + check_dyn_compatibility( r#" //- minicore: future, send, sync, dispatch_from_dyn, deref use core::pin::Pin; @@ -313,7 +315,7 @@ pub trait Fetcher: Send + Sync { #[test] fn rustc_issue_102933() { - check_object_safety( + check_dyn_compatibility( r#" //- minicore: future, dispatch_from_dyn, deref use core::future::Future; @@ -351,7 +353,7 @@ pub trait B2: Service + B1 { #[test] fn rustc_issue_106247() { - check_object_safety( + check_dyn_compatibility( r#" //- minicore: sync, dispatch_from_dyn pub trait Trait { @@ -363,8 +365,8 @@ pub trait Trait { } #[test] -fn std_error_is_object_safe() { - check_object_safety( +fn std_error_is_dyn_compatible() { + check_dyn_compatibility( r#" //- minicore: fmt, dispatch_from_dyn trait Erased<'a>: 'a {} @@ -380,14 +382,14 @@ pub trait Error: core::fmt::Debug + core::fmt::Display { } #[test] -fn lifetime_gat_is_object_unsafe() { - check_object_safety( +fn lifetime_gat_is_dyn_incompatible() { + check_dyn_compatibility( r#" //- minicore: dispatch_from_dyn trait Foo { type Bar<'a>; } "#, - [("Foo", vec![ObjectSafetyViolationKind::GAT])], + [("Foo", vec![DynCompatibilityViolationKind::GAT])], ); } diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs b/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs index 5ed41b99ba3e7..ef570a2055661 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs @@ -38,11 +38,11 @@ pub mod consteval; pub mod db; pub mod diagnostics; pub mod display; +pub mod dyn_compatibility; pub mod lang_items; pub mod layout; pub mod method_resolution; pub mod mir; -pub mod object_safety; pub mod primitive; pub mod traits; diff --git a/src/tools/rust-analyzer/crates/hir/src/lib.rs b/src/tools/rust-analyzer/crates/hir/src/lib.rs index 8f5db32f9576e..e2cf5b07897dc 100644 --- a/src/tools/rust-analyzer/crates/hir/src/lib.rs +++ b/src/tools/rust-analyzer/crates/hir/src/lib.rs @@ -144,9 +144,9 @@ pub use { hir_ty::{ consteval::ConstEvalError, display::{ClosureStyle, HirDisplay, HirDisplayError, HirWrite}, + dyn_compatibility::{DynCompatibilityViolation, MethodViolationCode}, layout::LayoutError, mir::{MirEvalError, MirLowerError}, - object_safety::{MethodViolationCode, ObjectSafetyViolation}, CastError, FnAbi, PointerCast, Safety, }, // FIXME: Properly encapsulate mir @@ -2690,8 +2690,8 @@ impl Trait { .count() } - pub fn object_safety(&self, db: &dyn HirDatabase) -> Option { - hir_ty::object_safety::object_safety(db, self.id) + pub fn dyn_compatibility(&self, db: &dyn HirDatabase) -> Option { + hir_ty::dyn_compatibility::dyn_compatibility(db, self.id) } fn all_macro_calls(&self, db: &dyn HirDatabase) -> Box<[(AstId, MacroCallId)]> { diff --git a/src/tools/rust-analyzer/crates/ide-db/src/generated/lints.rs b/src/tools/rust-analyzer/crates/ide-db/src/generated/lints.rs index abf4438a71ff6..266109765ab8c 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/generated/lints.rs +++ b/src/tools/rust-analyzer/crates/ide-db/src/generated/lints.rs @@ -7081,8 +7081,8 @@ This feature has no tracking issue, and is therefore likely internal to the comp "##, }, Lint { - label: "object_safe_for_dispatch", - description: r##"# `object_safe_for_dispatch` + label: "dyn_compatible_for_dispatch", + description: r##"# `dyn_compatible_for_dispatch` The tracking issue for this feature is: [#43561] diff --git a/src/tools/rust-analyzer/crates/ide/src/hover/render.rs b/src/tools/rust-analyzer/crates/ide/src/hover/render.rs index 83adf6548a890..5a8c9a9f11f28 100644 --- a/src/tools/rust-analyzer/crates/ide/src/hover/render.rs +++ b/src/tools/rust-analyzer/crates/ide/src/hover/render.rs @@ -3,9 +3,9 @@ use std::{mem, ops::Not}; use either::Either; use hir::{ - db::ExpandDatabase, Adt, AsAssocItem, AsExternAssocItem, CaptureKind, HasCrate, HasSource, - HirDisplay, Layout, LayoutError, MethodViolationCode, Name, ObjectSafetyViolation, Semantics, - Trait, Type, TypeInfo, + db::ExpandDatabase, Adt, AsAssocItem, AsExternAssocItem, CaptureKind, + DynCompatibilityViolation, HasCrate, HasSource, HirDisplay, Layout, LayoutError, + MethodViolationCode, Name, Semantics, Trait, Type, TypeInfo, }; use ide_db::{ base_db::SourceDatabase, @@ -529,10 +529,10 @@ pub(super) fn definition( _ => None, }; - let object_safety_info = if let Definition::Trait(it) = def { - let mut object_safety_info = String::new(); - render_object_safety(db, &mut object_safety_info, it.object_safety(db)); - Some(object_safety_info) + let dyn_compatibility_info = if let Definition::Trait(it) = def { + let mut dyn_compatibility_info = String::new(); + render_dyn_compatibility(db, &mut dyn_compatibility_info, it.dyn_compatibility(db)); + Some(dyn_compatibility_info) } else { None }; @@ -546,8 +546,8 @@ pub(super) fn definition( desc.push_str(&layout_info); desc.push('\n'); } - if let Some(object_safety_info) = object_safety_info { - desc.push_str(&object_safety_info); + if let Some(dyn_compatibility_info) = dyn_compatibility_info { + desc.push_str(&dyn_compatibility_info); desc.push('\n'); } desc.push_str(&label); @@ -980,24 +980,24 @@ fn keyword_hints( } } -fn render_object_safety( +fn render_dyn_compatibility( db: &RootDatabase, buf: &mut String, - safety: Option, + safety: Option, ) { let Some(osv) = safety else { - buf.push_str("// Object Safety: Yes"); + buf.push_str("// Dyn Compatible: Yes"); return; }; - buf.push_str("// Object Safety: No\n// - Reason: "); + buf.push_str("// Dyn Compatible: No\n// - Reason: "); match osv { - ObjectSafetyViolation::SizedSelf => { + DynCompatibilityViolation::SizedSelf => { buf.push_str("has a `Self: Sized` bound"); } - ObjectSafetyViolation::SelfReferential => { + DynCompatibilityViolation::SelfReferential => { buf.push_str("has a bound that references `Self`"); } - ObjectSafetyViolation::Method(func, mvc) => { + DynCompatibilityViolation::Method(func, mvc) => { let name = hir::Function::from(func).name(db); format_to!( buf, @@ -1020,7 +1020,7 @@ fn render_object_safety( }; buf.push_str(desc); } - ObjectSafetyViolation::AssocConst(const_) => { + DynCompatibilityViolation::AssocConst(const_) => { let name = hir::Const::from(const_).name(db); if let Some(name) = name { format_to!(buf, "has an associated constant `{}`", name.as_str()); @@ -1028,11 +1028,11 @@ fn render_object_safety( buf.push_str("has an associated constant"); } } - ObjectSafetyViolation::GAT(alias) => { + DynCompatibilityViolation::GAT(alias) => { let name = hir::TypeAlias::from(alias).name(db); format_to!(buf, "has a generic associated type `{}`", name.as_str()); } - ObjectSafetyViolation::HasNonSafeSuperTrait(super_trait) => { + DynCompatibilityViolation::HasNonCompatibleSuperTrait(super_trait) => { let name = hir::Trait::from(super_trait).name(db); format_to!(buf, "has a object unsafe supertrait `{}`", name.as_str()); } diff --git a/src/tools/rust-analyzer/crates/ide/src/hover/tests.rs b/src/tools/rust-analyzer/crates/ide/src/hover/tests.rs index cca62d2181f46..db2b98090cf6d 100644 --- a/src/tools/rust-analyzer/crates/ide/src/hover/tests.rs +++ b/src/tools/rust-analyzer/crates/ide/src/hover/tests.rs @@ -7175,7 +7175,7 @@ impl T$0 for () {} ``` ```rust - // Object Safety: Yes + // Dyn Compatible: Yes trait T {} ``` "#]], @@ -7195,7 +7195,7 @@ impl T$0 for () {} ``` ```rust - // Object Safety: Yes + // Dyn Compatible: Yes trait T {} ``` "#]], @@ -7219,7 +7219,7 @@ impl T$0 for () {} ``` ```rust - // Object Safety: No + // Dyn Compatible: No // - Reason: has a method `func` that is non dispatchable because of: // - missing a receiver trait T { /* … */ } @@ -7245,7 +7245,7 @@ impl T$0 for () {} ``` ```rust - // Object Safety: No + // Dyn Compatible: No // - Reason: has a method `func` that is non dispatchable because of: // - missing a receiver trait T { @@ -7275,7 +7275,7 @@ impl T$0 for () {} ``` ```rust - // Object Safety: No + // Dyn Compatible: No // - Reason: has a method `func` that is non dispatchable because of: // - missing a receiver trait T { @@ -7305,7 +7305,7 @@ impl T$0 for () {} ``` ```rust - // Object Safety: No + // Dyn Compatible: No // - Reason: has a method `func` that is non dispatchable because of: // - missing a receiver trait T { diff --git a/src/tools/rust-analyzer/crates/syntax/src/ast.rs b/src/tools/rust-analyzer/crates/syntax/src/ast.rs index 3ce9afa1dec58..32b1f5f754489 100644 --- a/src/tools/rust-analyzer/crates/syntax/src/ast.rs +++ b/src/tools/rust-analyzer/crates/syntax/src/ast.rs @@ -167,7 +167,7 @@ mod support { } #[test] -fn assert_ast_is_object_safe() { +fn assert_ast_is_dyn_compatible() { fn _f(_: &dyn AstNode, _: &dyn HasName) {} } diff --git a/src/tools/rust-analyzer/crates/vfs/src/loader.rs b/src/tools/rust-analyzer/crates/vfs/src/loader.rs index f24354cb493ca..c49e4c4322d43 100644 --- a/src/tools/rust-analyzer/crates/vfs/src/loader.rs +++ b/src/tools/rust-analyzer/crates/vfs/src/loader.rs @@ -1,4 +1,4 @@ -//! Object safe interface for file watching and reading. +//! Dynamically compatible interface for file watching and reading. use std::fmt; use paths::{AbsPath, AbsPathBuf}; @@ -232,6 +232,6 @@ impl fmt::Debug for Message { } #[test] -fn handle_is_object_safe() { +fn handle_is_dyn_compatible() { fn _assert(_: &dyn Handle) {} } diff --git a/src/tools/rust-analyzer/docs/dev/syntax.md b/src/tools/rust-analyzer/docs/dev/syntax.md index 6c4daecc58ff7..3dcd430cea5d5 100644 --- a/src/tools/rust-analyzer/docs/dev/syntax.md +++ b/src/tools/rust-analyzer/docs/dev/syntax.md @@ -378,7 +378,7 @@ impl AstNode for AssocItem { } ``` -Shared AST substructures are modeled via (object safe) traits: +Shared AST substructures are modeled via (dynamically compatible) traits: ```rust trait HasVisibility: AstNode { From 71cd918dc78c84d41bb89c2fc8effcfd000f4e3e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= Date: Sun, 29 Sep 2024 13:31:30 +0200 Subject: [PATCH 1698/2194] cleanup: don't clone types that are Copy --- compiler/rustc_middle/src/middle/stability.rs | 2 +- .../rustc_mir_transform/src/coroutine/by_move_body.rs | 10 +++++----- compiler/rustc_mir_transform/src/single_use_consts.rs | 5 ++--- compiler/rustc_pattern_analysis/src/constructor.rs | 8 ++++---- compiler/rustc_resolve/src/diagnostics.rs | 6 +----- 5 files changed, 13 insertions(+), 18 deletions(-) diff --git a/compiler/rustc_middle/src/middle/stability.rs b/compiler/rustc_middle/src/middle/stability.rs index 54cfd99583215..ee34ccd889f79 100644 --- a/compiler/rustc_middle/src/middle/stability.rs +++ b/compiler/rustc_middle/src/middle/stability.rs @@ -217,7 +217,7 @@ pub fn early_report_macro_deprecation( suggestion_span: span, note: depr.note, path, - since_kind: deprecated_since_kind(is_in_effect, depr.since.clone()), + since_kind: deprecated_since_kind(is_in_effect, depr.since), }; lint_buffer.buffer_lint(deprecation_lint(is_in_effect), node_id, span, diag); } diff --git a/compiler/rustc_mir_transform/src/coroutine/by_move_body.rs b/compiler/rustc_mir_transform/src/coroutine/by_move_body.rs index 65442877d2dd5..cc4b7689d407c 100644 --- a/compiler/rustc_mir_transform/src/coroutine/by_move_body.rs +++ b/compiler/rustc_mir_transform/src/coroutine/by_move_body.rs @@ -223,14 +223,14 @@ pub(crate) fn coroutine_by_move_body_def_id<'tcx>( // Inherited from the by-ref coroutine. body_def.codegen_fn_attrs(tcx.codegen_fn_attrs(coroutine_def_id).clone()); - body_def.constness(tcx.constness(coroutine_def_id).clone()); - body_def.coroutine_kind(tcx.coroutine_kind(coroutine_def_id).clone()); + body_def.constness(tcx.constness(coroutine_def_id)); + body_def.coroutine_kind(tcx.coroutine_kind(coroutine_def_id)); body_def.def_ident_span(tcx.def_ident_span(coroutine_def_id)); body_def.def_span(tcx.def_span(coroutine_def_id)); - body_def.explicit_predicates_of(tcx.explicit_predicates_of(coroutine_def_id).clone()); + body_def.explicit_predicates_of(tcx.explicit_predicates_of(coroutine_def_id)); body_def.generics_of(tcx.generics_of(coroutine_def_id).clone()); - body_def.param_env(tcx.param_env(coroutine_def_id).clone()); - body_def.predicates_of(tcx.predicates_of(coroutine_def_id).clone()); + body_def.param_env(tcx.param_env(coroutine_def_id)); + body_def.predicates_of(tcx.predicates_of(coroutine_def_id)); // The type of the coroutine is the `by_move_coroutine_ty`. body_def.type_of(ty::EarlyBinder::bind(by_move_coroutine_ty)); diff --git a/compiler/rustc_mir_transform/src/single_use_consts.rs b/compiler/rustc_mir_transform/src/single_use_consts.rs index 9884b6dd1c35e..277a33c031152 100644 --- a/compiler/rustc_mir_transform/src/single_use_consts.rs +++ b/compiler/rustc_mir_transform/src/single_use_consts.rs @@ -185,15 +185,14 @@ impl<'tcx> MutVisitor<'tcx> for LocalReplacer<'tcx> { && let Some(local) = place.as_local() && local == self.local { - let const_op = self + let const_op = *self .operand .as_ref() .unwrap_or_else(|| { bug!("the operand was already stolen"); }) .constant() - .unwrap() - .clone(); + .unwrap(); var_debug_info.value = VarDebugInfoContents::Const(const_op); } } diff --git a/compiler/rustc_pattern_analysis/src/constructor.rs b/compiler/rustc_pattern_analysis/src/constructor.rs index 3cb7576154fc1..8fce42663453a 100644 --- a/compiler/rustc_pattern_analysis/src/constructor.rs +++ b/compiler/rustc_pattern_analysis/src/constructor.rs @@ -735,10 +735,10 @@ impl Clone for Constructor { Constructor::UnionField => Constructor::UnionField, Constructor::Bool(b) => Constructor::Bool(*b), Constructor::IntRange(range) => Constructor::IntRange(*range), - Constructor::F16Range(lo, hi, end) => Constructor::F16Range(lo.clone(), *hi, *end), - Constructor::F32Range(lo, hi, end) => Constructor::F32Range(lo.clone(), *hi, *end), - Constructor::F64Range(lo, hi, end) => Constructor::F64Range(lo.clone(), *hi, *end), - Constructor::F128Range(lo, hi, end) => Constructor::F128Range(lo.clone(), *hi, *end), + Constructor::F16Range(lo, hi, end) => Constructor::F16Range(*lo, *hi, *end), + Constructor::F32Range(lo, hi, end) => Constructor::F32Range(*lo, *hi, *end), + Constructor::F64Range(lo, hi, end) => Constructor::F64Range(*lo, *hi, *end), + Constructor::F128Range(lo, hi, end) => Constructor::F128Range(*lo, *hi, *end), Constructor::Str(value) => Constructor::Str(value.clone()), Constructor::Opaque(inner) => Constructor::Opaque(inner.clone()), Constructor::Or => Constructor::Or, diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index 46e30c614ab4d..582db97e1ce87 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -1469,11 +1469,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { } let unused_macro = self.unused_macros.iter().find_map(|(def_id, (_, unused_ident))| { - if unused_ident.name == ident.name { - Some((def_id.clone(), unused_ident.clone())) - } else { - None - } + if unused_ident.name == ident.name { Some((def_id, unused_ident)) } else { None } }); if let Some((def_id, unused_ident)) = unused_macro { From 0bebedd7993117c56fb5b7301c39fdecf9798787 Mon Sep 17 00:00:00 2001 From: Mads Marquart Date: Sun, 29 Sep 2024 14:45:08 +0200 Subject: [PATCH 1699/2194] Document a bit more how the SDK version actually works --- compiler/rustc_codegen_ssa/src/back/link.rs | 48 ++++++++++++++++++--- 1 file changed, 41 insertions(+), 7 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index 80e8111516ee1..8a023fac95685 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -2959,11 +2959,12 @@ pub(crate) fn are_upstream_rust_objects_already_included(sess: &Session) -> bool } } -/// We need to communicate four things to the linker on Apple/Darwin targets: +/// We need to communicate five things to the linker on Apple/Darwin targets: /// - The architecture. /// - The operating system (and that it's an Apple platform). -/// - The deployment target. /// - The environment / ABI. +/// - The deployment target. +/// - The SDK version. fn add_apple_link_args(cmd: &mut dyn Linker, sess: &Session, flavor: LinkerFlavor) { if !sess.target.is_like_osx { return; @@ -3039,7 +3040,38 @@ fn add_apple_link_args(cmd: &mut dyn Linker, sess: &Session, flavor: LinkerFlavo let (major, minor, patch) = current_apple_deployment_target(&sess.target); let min_version = format!("{major}.{minor}.{patch}"); - // Lie about the SDK version, we don't know it here + // The SDK version is used at runtime when compiling with a newer SDK / version of Xcode: + // - By dyld to give extra warnings and errors, see e.g.: + // + // + // - By system frameworks to change certain behaviour. For example, the default value of + // `-[NSView wantsBestResolutionOpenGLSurface]` is `YES` when the SDK version is >= 10.15. + // + // + // We do not currently know the actual SDK version though, so we have a few options: + // 1. Use the minimum version supported by rustc. + // 2. Use the same as the deployment target. + // 3. Use an arbitary recent version. + // 4. Omit the version. + // + // The first option is too low / too conservative, and means that users will not get the + // same behaviour from a binary compiled with rustc as with one compiled by clang. + // + // The second option is similarly conservative, and also wrong since if the user specified a + // higher deployment target than the SDK they're compiling/linking with, the runtime might + // make invalid assumptions about the capabilities of the binary. + // + // The third option requires that `rustc` is periodically kept up to date with Apple's SDK + // version, and is also wrong for similar reasons as above. + // + // The fourth option is bad because while `ld`, `otool`, `vtool` and such understand it to + // mean "absent" or `n/a`, dyld doesn't actually understand it, and will end up interpreting + // it as 0.0, which is again too low/conservative. + // + // Currently, we lie about the SDK version, and choose the second option. + // + // FIXME(madsmtm): Parse the SDK version from the SDK root instead. + // let sdk_version = &*min_version; // From the man page for ld64 (`man ld`): @@ -3053,11 +3085,13 @@ fn add_apple_link_args(cmd: &mut dyn Linker, sess: &Session, flavor: LinkerFlavo cmd.link_args(&["-platform_version", platform_name, &*min_version, sdk_version]); } else { // cc == Cc::Yes + // // We'd _like_ to use `-target` everywhere, since that can uniquely - // communicate all the required details, but that doesn't work on GCC, - // and since we don't know whether the `cc` compiler is Clang, GCC, or - // something else, we fall back to other options that also work on GCC - // when compiling for macOS. + // communicate all the required details except for the SDK version + // (which is read by Clang itself from the SDKROOT), but that doesn't + // work on GCC, and since we don't know whether the `cc` compiler is + // Clang, GCC, or something else, we fall back to other options that + // also work on GCC when compiling for macOS. // // Targets other than macOS are ill-supported by GCC (it doesn't even // support e.g. `-miphoneos-version-min`), so in those cases we can From 8964c487261273eabb6973a4663322e82d82569f Mon Sep 17 00:00:00 2001 From: Mads Marquart Date: Sun, 29 Sep 2024 14:00:34 +0200 Subject: [PATCH 1700/2194] Add run-make test to check the SDK version(s) that rustc produces --- tests/run-make/apple-sdk-version/foo.rs | 1 + tests/run-make/apple-sdk-version/rmake.rs | 86 +++++++++++++++++++++++ 2 files changed, 87 insertions(+) create mode 100644 tests/run-make/apple-sdk-version/foo.rs create mode 100644 tests/run-make/apple-sdk-version/rmake.rs diff --git a/tests/run-make/apple-sdk-version/foo.rs b/tests/run-make/apple-sdk-version/foo.rs new file mode 100644 index 0000000000000..f328e4d9d04c3 --- /dev/null +++ b/tests/run-make/apple-sdk-version/foo.rs @@ -0,0 +1 @@ +fn main() {} diff --git a/tests/run-make/apple-sdk-version/rmake.rs b/tests/run-make/apple-sdk-version/rmake.rs new file mode 100644 index 0000000000000..a16c84ddc597a --- /dev/null +++ b/tests/run-make/apple-sdk-version/rmake.rs @@ -0,0 +1,86 @@ +//! Test codegen when setting SDK version on Apple platforms. +//! +//! This is important since its a compatibility hazard. The linker will +//! generate load commands differently based on what minimum OS it can assume. +//! +//! See https://github.com/rust-lang/rust/issues/129432. + +//@ only-apple + +use run_make_support::{apple_os, cmd, run_in_tmpdir, rustc, target}; + +/// Run vtool to check the `sdk` field in LC_BUILD_VERSION. +/// +/// On lower deployment targets, LC_VERSION_MIN_MACOSX, LC_VERSION_MIN_IPHONEOS and similar +/// are used instead of LC_BUILD_VERSION, but both name the relevant variable `sdk`. +#[track_caller] +fn has_sdk_version(file: &str, version: &str) { + cmd("vtool") + .arg("-show-build") + .arg(file) + .run() + .assert_stdout_contains(format!("sdk {version}")); +} + +fn main() { + // Fetch rustc's inferred deployment target. + let current_deployment_target = + rustc().target(target()).print("deployment-target").run().stdout_utf8(); + let current_deployment_target = + current_deployment_target.strip_prefix("deployment_target=").unwrap().trim(); + + // Fetch current SDK version via. xcrun. + // + // Assumes a standard Xcode distribution, where e.g. the macOS SDK's Mac Catalyst + // and the iPhone Simulator version is the same as for the iPhone SDK. + let sdk_name = match apple_os() { + "macos" => "macosx", + "ios" => "iphoneos", + "watchos" => "watchos", + "tvos" => "appletvos", + "visionos" => "xros", + _ => unreachable!(), + }; + let current_sdk_version = + cmd("xcrun").arg("--show-sdk-version").arg("--sdk").arg(sdk_name).run().stdout_utf8(); + let current_sdk_version = current_sdk_version.trim(); + + // Check the SDK version in the object file produced by the codegen backend. + rustc().target(target()).crate_type("lib").emit("obj").input("foo.rs").output("foo.o").run(); + // Set to 0, which means not set or "n/a". + has_sdk_version("foo.o", "n/a"); + + // Test that version makes it to the linker. + for (crate_type, file_ext) in [("bin", ""), ("dylib", ".dylib")] { + // Non-simulator watchOS targets don't support dynamic linking, + // for simplicity we disable the test on all watchOS targets. + if crate_type == "dylib" && apple_os() == "watchos" { + continue; + } + + // Test with clang + let file_name = format!("foo_cc{file_ext}"); + rustc() + .target(target()) + .crate_type("bin") + .arg("-Clinker-flavor=gcc") + .input("foo.rs") + .output(&file_name) + .run(); + has_sdk_version(&file_name, current_sdk_version); + + // Test with ld64 + let file_name = format!("foo_ld{file_ext}"); + rustc() + .target(target()) + .crate_type("bin") + .arg("-Clinker-flavor=ld") + .input("foo.rs") + .output(&file_name) + .run(); + // FIXME(madsmtm): This uses the current deployment target + // instead of the current SDK version like Clang does. + // https://github.com/rust-lang/rust/issues/129432 + has_sdk_version(&file_name, current_deployment_target); + } +} From 6b06ceb2fd118a7c6ee62675777a1d503348ef0c Mon Sep 17 00:00:00 2001 From: Mads Marquart Date: Sun, 29 Sep 2024 13:58:49 +0200 Subject: [PATCH 1701/2194] Do not specify an SDK version in object files This is unnecessary, since it ends up being overwritten when linking anyhow, and it feels wrong to embed some arbitrary SDK version in here. --- compiler/rustc_codegen_ssa/src/back/metadata.rs | 10 +++++++--- .../rustc_target/src/spec/base/apple/mod.rs | 17 ----------------- compiler/rustc_target/src/spec/mod.rs | 2 +- tests/run-make/apple-sdk-version/rmake.rs | 9 +++++++++ 4 files changed, 17 insertions(+), 21 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/back/metadata.rs b/compiler/rustc_codegen_ssa/src/back/metadata.rs index 06433484ea3cd..8857fda1e9728 100644 --- a/compiler/rustc_codegen_ssa/src/back/metadata.rs +++ b/compiler/rustc_codegen_ssa/src/back/metadata.rs @@ -402,13 +402,17 @@ fn macho_object_build_version_for_target(target: &Target) -> object::write::Mach let platform = rustc_target::spec::current_apple_platform(target).expect("unknown Apple target OS"); let min_os = rustc_target::spec::current_apple_deployment_target(target); - let (sdk_major, sdk_minor) = - rustc_target::spec::current_apple_sdk_version(platform).expect("unknown Apple target OS"); let mut build_version = object::write::MachOBuildVersion::default(); build_version.platform = platform; build_version.minos = pack_version(min_os); - build_version.sdk = pack_version((sdk_major, sdk_minor, 0)); + // The version here does not _really_ matter, since it is only used at runtime, and we specify + // it when linking the final binary, so we will omit the version. This is also what LLVM does, + // and the tooling also allows this (and shows the SDK version as `n/a`). Finally, it is the + // semantically correct choice, as the SDK has not influenced the binary generated by rustc at + // this point in time. + build_version.sdk = 0; + build_version } diff --git a/compiler/rustc_target/src/spec/base/apple/mod.rs b/compiler/rustc_target/src/spec/base/apple/mod.rs index 81b5a936d35ff..73763cf034ca0 100644 --- a/compiler/rustc_target/src/spec/base/apple/mod.rs +++ b/compiler/rustc_target/src/spec/base/apple/mod.rs @@ -158,23 +158,6 @@ pub(crate) fn base( (opts, llvm_target(os, arch, abi), arch.target_arch()) } -pub fn sdk_version(platform: u32) -> Option<(u16, u8)> { - // NOTE: These values are from an arbitrary point in time but shouldn't make it into the final - // binary since the final link command will have the current SDK version passed to it. - match platform { - object::macho::PLATFORM_MACOS => Some((13, 1)), - object::macho::PLATFORM_IOS - | object::macho::PLATFORM_IOSSIMULATOR - | object::macho::PLATFORM_TVOS - | object::macho::PLATFORM_TVOSSIMULATOR - | object::macho::PLATFORM_MACCATALYST => Some((16, 2)), - object::macho::PLATFORM_WATCHOS | object::macho::PLATFORM_WATCHOSSIMULATOR => Some((9, 1)), - // FIXME: Upgrade to `object-rs` 0.33+ implementation with visionOS platform definition - 11 | 12 => Some((1, 0)), - _ => None, - } -} - pub fn platform(target: &Target) -> Option { Some(match (&*target.os, &*target.abi) { ("macos", _) => object::macho::PLATFORM_MACOS, diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index f327c1fd17902..70ef21120e5a5 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -61,7 +61,7 @@ pub mod crt_objects; mod base; pub use base::apple::{ deployment_target_for_target as current_apple_deployment_target, - platform as current_apple_platform, sdk_version as current_apple_sdk_version, + platform as current_apple_platform, }; pub use base::avr_gnu::ef_avr_arch; diff --git a/tests/run-make/apple-sdk-version/rmake.rs b/tests/run-make/apple-sdk-version/rmake.rs index a16c84ddc597a..6463ec0040359 100644 --- a/tests/run-make/apple-sdk-version/rmake.rs +++ b/tests/run-make/apple-sdk-version/rmake.rs @@ -50,6 +50,15 @@ fn main() { // Set to 0, which means not set or "n/a". has_sdk_version("foo.o", "n/a"); + // Check the SDK version in the .rmeta file, as set in `create_object_file`. + // + // This is just to ensure that we don't set some odd version in `create_object_file`, + // if the rmeta file is packed in a different way in the future, this can safely be removed. + rustc().target(target()).crate_type("rlib").input("foo.rs").output("libfoo.rlib").run(); + // Extra .rmeta file (which is encoded as an object file). + cmd("ar").arg("-x").arg("libfoo.rlib").arg("lib.rmeta").run(); + has_sdk_version("lib.rmeta", "n/a"); + // Test that version makes it to the linker. for (crate_type, file_ext) in [("bin", ""), ("dylib", ".dylib")] { // Non-simulator watchOS targets don't support dynamic linking, From 40d413f9fea106a39f1129d3949369ea55a4877c Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sun, 29 Sep 2024 11:56:06 -0400 Subject: [PATCH 1702/2194] Don't give method suggestions when method probe fails due to bad impl of Deref --- compiler/rustc_hir_typeck/src/method/mod.rs | 6 +++++- compiler/rustc_hir_typeck/src/method/probe.rs | 8 +------- compiler/rustc_hir_typeck/src/method/suggest.rs | 2 ++ .../ui/methods/dont-suggest-import-on-deref-err.rs | 13 +++++++++++++ .../methods/dont-suggest-import-on-deref-err.stderr | 12 ++++++++++++ 5 files changed, 33 insertions(+), 8 deletions(-) create mode 100644 tests/ui/methods/dont-suggest-import-on-deref-err.rs create mode 100644 tests/ui/methods/dont-suggest-import-on-deref-err.stderr diff --git a/compiler/rustc_hir_typeck/src/method/mod.rs b/compiler/rustc_hir_typeck/src/method/mod.rs index 586b753f45493..6d6e9f248a465 100644 --- a/compiler/rustc_hir_typeck/src/method/mod.rs +++ b/compiler/rustc_hir_typeck/src/method/mod.rs @@ -18,8 +18,8 @@ use rustc_middle::ty::{ self, GenericArgs, GenericArgsRef, GenericParamDefKind, Ty, TypeVisitableExt, }; use rustc_middle::{bug, span_bug}; -use rustc_span::Span; use rustc_span::symbol::Ident; +use rustc_span::{ErrorGuaranteed, Span}; use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt; use rustc_trait_selection::traits::{self, NormalizeExt}; use tracing::{debug, instrument}; @@ -66,6 +66,9 @@ pub(crate) enum MethodError<'tcx> { // Found a match, but the return type is wrong BadReturnType, + + // Error has already been emitted, no need to emit another one. + ErrorReported(ErrorGuaranteed), } // Contains a list of static methods that may apply, a list of unsatisfied trait predicates which @@ -120,6 +123,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { Err(PrivateMatch(..)) => false, Err(IllegalSizedBound { .. }) => true, Err(BadReturnType) => false, + Err(ErrorReported(_)) => false, } } diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs index 371380e575dbc..3bb7070d61dfa 100644 --- a/compiler/rustc_hir_typeck/src/method/probe.rs +++ b/compiler/rustc_hir_typeck/src/method/probe.rs @@ -446,13 +446,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { _ => bug!("unexpected bad final type in method autoderef"), }; self.demand_eqtype(span, ty, Ty::new_error(self.tcx, guar)); - return Err(MethodError::NoMatch(NoMatchData { - static_candidates: Vec::new(), - unsatisfied_predicates: Vec::new(), - out_of_scope_traits: Vec::new(), - similar_candidate: None, - mode, - })); + return Err(MethodError::ErrorReported(guar)); } } diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index e03be4f43f73d..43564413ffb02 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -386,6 +386,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { return err.emit(); } + MethodError::ErrorReported(guar) => guar, + MethodError::BadReturnType => bug!("no return type expectations but got BadReturnType"), } } diff --git a/tests/ui/methods/dont-suggest-import-on-deref-err.rs b/tests/ui/methods/dont-suggest-import-on-deref-err.rs new file mode 100644 index 0000000000000..c24ab7919824b --- /dev/null +++ b/tests/ui/methods/dont-suggest-import-on-deref-err.rs @@ -0,0 +1,13 @@ +use std::clone::Clone; +use std::ops::Deref; + +#[derive(Clone)] +pub struct Foo {} + +impl Deref for Foo {} +//~^ ERROR not all trait items implemented + +pub fn main() { + let f = Foo {}; + let _ = f.clone(); +} diff --git a/tests/ui/methods/dont-suggest-import-on-deref-err.stderr b/tests/ui/methods/dont-suggest-import-on-deref-err.stderr new file mode 100644 index 0000000000000..20a63ff375d19 --- /dev/null +++ b/tests/ui/methods/dont-suggest-import-on-deref-err.stderr @@ -0,0 +1,12 @@ +error[E0046]: not all trait items implemented, missing: `Target`, `deref` + --> $DIR/dont-suggest-import-on-deref-err.rs:7:1 + | +LL | impl Deref for Foo {} + | ^^^^^^^^^^^^^^^^^^ missing `Target`, `deref` in implementation + | + = help: implement the missing item: `type Target = /* Type */;` + = help: implement the missing item: `fn deref(&self) -> &::Target { todo!() }` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0046`. From 486440fc7482adf1c57681ffaa34cf9b5fb157eb Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sun, 29 Sep 2024 11:52:25 -0400 Subject: [PATCH 1703/2194] Tweak comments and remove trivial return --- compiler/rustc_hir_typeck/src/method/mod.rs | 14 ++++---- .../rustc_hir_typeck/src/method/suggest.rs | 32 +++++++++---------- 2 files changed, 22 insertions(+), 24 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/method/mod.rs b/compiler/rustc_hir_typeck/src/method/mod.rs index 6d6e9f248a465..3e9cb0ac2c80c 100644 --- a/compiler/rustc_hir_typeck/src/method/mod.rs +++ b/compiler/rustc_hir_typeck/src/method/mod.rs @@ -46,17 +46,17 @@ pub(crate) struct MethodCallee<'tcx> { #[derive(Debug)] pub(crate) enum MethodError<'tcx> { - // Did not find an applicable method, but we did find various near-misses that may work. + /// Did not find an applicable method, but we did find various near-misses that may work. NoMatch(NoMatchData<'tcx>), - // Multiple methods might apply. + /// Multiple methods might apply. Ambiguity(Vec), - // Found an applicable method, but it is not visible. The third argument contains a list of - // not-in-scope traits which may work. + /// Found an applicable method, but it is not visible. The third argument contains a list of + /// not-in-scope traits which may work. PrivateMatch(DefKind, DefId, Vec), - // Found a `Self: Sized` bound where `Self` is a trait object. + /// Found a `Self: Sized` bound where `Self` is a trait object. IllegalSizedBound { candidates: Vec, needs_mut: bool, @@ -64,10 +64,10 @@ pub(crate) enum MethodError<'tcx> { self_expr: &'tcx hir::Expr<'tcx>, }, - // Found a match, but the return type is wrong + /// Found a match, but the return type is wrong BadReturnType, - // Error has already been emitted, no need to emit another one. + /// Error has already been emitted, no need to emit another one. ErrorReported(ErrorGuaranteed), } diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index 43564413ffb02..a37e9744293c3 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -229,20 +229,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } match error { - MethodError::NoMatch(mut no_match_data) => { - return self.report_no_match_method_error( - span, - rcvr_ty, - item_name, - call_id, - source, - args, - sugg_span, - &mut no_match_data, - expected, - trait_missing_method, - ); - } + MethodError::NoMatch(mut no_match_data) => self.report_no_match_method_error( + span, + rcvr_ty, + item_name, + call_id, + source, + args, + sugg_span, + &mut no_match_data, + expected, + trait_missing_method, + ), MethodError::Ambiguity(mut sources) => { let mut err = struct_span_code_err!( @@ -263,7 +261,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { &mut sources, Some(sugg_span), ); - return err.emit(); + err.emit() } MethodError::PrivateMatch(kind, def_id, out_of_scope_traits) => { @@ -284,7 +282,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .unwrap_or_else(|| self.tcx.def_span(def_id)); err.span_label(sp, format!("private {kind} defined here")); self.suggest_valid_traits(&mut err, item_name, out_of_scope_traits, true); - return err.emit(); + err.emit() } MethodError::IllegalSizedBound { candidates, needs_mut, bound_span, self_expr } => { @@ -383,7 +381,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } } - return err.emit(); + err.emit() } MethodError::ErrorReported(guar) => guar, From 490df54bd6983878e975243879f683f02f860c43 Mon Sep 17 00:00:00 2001 From: David Barsky Date: Fri, 27 Sep 2024 16:12:10 -0400 Subject: [PATCH 1704/2194] internal: allow overriding proc macro server in analysis-stats --- .../crates/rust-analyzer/src/cli/analysis_stats.rs | 8 +++++++- .../rust-analyzer/crates/rust-analyzer/src/cli/flags.rs | 7 +++++-- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/analysis_stats.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/analysis_stats.rs index e899e0e8eea5f..2851101659634 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/analysis_stats.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/analysis_stats.rs @@ -81,7 +81,13 @@ impl flags::AnalysisStats { with_proc_macro_server: if self.disable_proc_macros { ProcMacroServerChoice::None } else { - ProcMacroServerChoice::Sysroot + match self.proc_macro_srv { + Some(ref path) => { + let path = vfs::AbsPathBuf::assert_utf8(path.to_owned()); + ProcMacroServerChoice::Explicit(path) + } + None => ProcMacroServerChoice::Sysroot, + } }, prefill_caches: false, }; diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/flags.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/flags.rs index 73e71658d17c5..60d621b214ade 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/flags.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/flags.rs @@ -76,6 +76,8 @@ xflags::xflags! { optional --disable-build-scripts /// Don't use expand proc macros. optional --disable-proc-macros + /// Run the proc-macro-srv binary at the specified path. + optional --proc-macro-srv path: PathBuf /// Skip body lowering. optional --skip-lowering /// Skip type inference. @@ -120,7 +122,7 @@ xflags::xflags! { optional --disable-build-scripts /// Don't use expand proc macros. optional --disable-proc-macros - /// Run a custom proc-macro-srv binary. + /// Run the proc-macro-srv binary at the specified path. optional --proc-macro-srv path: PathBuf } @@ -133,7 +135,7 @@ xflags::xflags! { optional --disable-build-scripts /// Don't use expand proc macros. optional --disable-proc-macros - /// Run a custom proc-macro-srv binary. + /// Run the proc-macro-srv binary at the specified path. optional --proc-macro-srv path: PathBuf } @@ -233,6 +235,7 @@ pub struct AnalysisStats { pub no_sysroot: bool, pub disable_build_scripts: bool, pub disable_proc_macros: bool, + pub proc_macro_srv: Option, pub skip_lowering: bool, pub skip_inference: bool, pub skip_mir_stats: bool, From 7caf2cdc2cc50310f556fe07be63b2b85feabc77 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 29 Sep 2024 08:30:46 +0200 Subject: [PATCH 1705/2194] interpret: always enable write_immediate sanity checks --- compiler/rustc_const_eval/src/interpret/operand.rs | 1 + compiler/rustc_const_eval/src/interpret/place.rs | 8 +++++--- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_const_eval/src/interpret/operand.rs b/compiler/rustc_const_eval/src/interpret/operand.rs index 31ee3e6519afc..b96643ea70f2e 100644 --- a/compiler/rustc_const_eval/src/interpret/operand.rs +++ b/compiler/rustc_const_eval/src/interpret/operand.rs @@ -118,6 +118,7 @@ impl Immediate { (Immediate::Scalar(scalar), Abi::Scalar(s)) => { assert_eq!(scalar.size(), s.size(cx)); if !matches!(s.primitive(), abi::Pointer(..)) { + // This is not a pointer, it should not carry provenance. assert!(matches!(scalar, Scalar::Int(..))); } } diff --git a/compiler/rustc_const_eval/src/interpret/place.rs b/compiler/rustc_const_eval/src/interpret/place.rs index 32f90254a9470..d22d966faeae9 100644 --- a/compiler/rustc_const_eval/src/interpret/place.rs +++ b/compiler/rustc_const_eval/src/interpret/place.rs @@ -652,6 +652,8 @@ where M::after_local_write(self, local, /*storage_live*/ false)?; } // Double-check that the value we are storing and the local fit to each other. + // Things can ge wrong in quite weird ways when this is violated. + // Unfortunately this is too expensive to do in release builds. if cfg!(debug_assertions) { src.assert_matches_abi(local_layout.abi, self); } @@ -672,9 +674,9 @@ where layout: TyAndLayout<'tcx>, dest: MemPlace, ) -> InterpResult<'tcx> { - if cfg!(debug_assertions) { - value.assert_matches_abi(layout.abi, self); - } + // We use the sizes from `value` below. + // Ensure that matches the type of the place it is written to. + value.assert_matches_abi(layout.abi, self); // Note that it is really important that the type here is the right one, and matches the // type things are read at. In case `value` is a `ScalarPair`, we don't do any magic here // to handle padding properly, which is only correct if we never look at this data with the From c27b54ac4ad88bc2aa07260cebec31e886a3c6ad Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Sun, 29 Sep 2024 10:02:06 -0700 Subject: [PATCH 1706/2194] rustdoc-gui: fix test cases --- tests/rustdoc-gui/scrape-examples-layout.goml | 4 ++-- tests/rustdoc-gui/search-result-display.goml | 2 +- tests/rustdoc-gui/sidebar-source-code-display.goml | 2 +- tests/rustdoc-gui/source-anchor-scroll.goml | 8 ++++---- tests/rustdoc-gui/toggle-docs-mobile.goml | 12 ++++++------ 5 files changed, 14 insertions(+), 14 deletions(-) diff --git a/tests/rustdoc-gui/scrape-examples-layout.goml b/tests/rustdoc-gui/scrape-examples-layout.goml index fd0774c91b675..96c78bbfe8b88 100644 --- a/tests/rustdoc-gui/scrape-examples-layout.goml +++ b/tests/rustdoc-gui/scrape-examples-layout.goml @@ -90,8 +90,8 @@ assert-css: (".scraped-example .example-wrap::after", {"bottom": "0px"}) // Then with mobile set-window-size: (600, 600) store-size: (".scraped-example .scraped-example-title", {"height": title_height}) -assert-position: (".scraped-example", {"y": 281}) -assert-position: (".scraped-example .prev", {"y": 281 + |offset_y| + |title_height|}) +assert-position: (".scraped-example", {"y": 287}) +assert-position: (".scraped-example .prev", {"y": 287 + |offset_y| + |title_height|}) define-function: ( "check_title_and_code_position", diff --git a/tests/rustdoc-gui/search-result-display.goml b/tests/rustdoc-gui/search-result-display.goml index 156244f92b4f5..1521267956a88 100644 --- a/tests/rustdoc-gui/search-result-display.goml +++ b/tests/rustdoc-gui/search-result-display.goml @@ -64,7 +64,7 @@ set-text: ( ) // Then we compare again to confirm the height didn't change. -assert-size: ("#crate-search", {"width": 509}) +assert-size: ("#crate-search", {"width": 370}) assert-size: (".search-results-title", { "height": |search_results_title_height|, }) diff --git a/tests/rustdoc-gui/sidebar-source-code-display.goml b/tests/rustdoc-gui/sidebar-source-code-display.goml index c3e02c4e9b409..742453c173b9d 100644 --- a/tests/rustdoc-gui/sidebar-source-code-display.goml +++ b/tests/rustdoc-gui/sidebar-source-code-display.goml @@ -141,7 +141,7 @@ click: "#sidebar-button" wait-for-css: (".src .sidebar > *", {"visibility": "hidden"}) // We scroll to line 117 to change the scroll position. scroll-to: '//*[@id="117"]' -store-value: (y_offset, "2564") +store-value: (y_offset, "2570") assert-window-property: {"pageYOffset": |y_offset|} // Expanding the sidebar... click: "#sidebar-button" diff --git a/tests/rustdoc-gui/source-anchor-scroll.goml b/tests/rustdoc-gui/source-anchor-scroll.goml index 166890abe4b36..f87946457051f 100644 --- a/tests/rustdoc-gui/source-anchor-scroll.goml +++ b/tests/rustdoc-gui/source-anchor-scroll.goml @@ -8,13 +8,13 @@ set-window-size: (600, 800) assert-property: ("html", {"scrollTop": "0"}) click: '//a[text() = "barbar" and @href="#5-7"]' -assert-property: ("html", {"scrollTop": "194"}) +assert-property: ("html", {"scrollTop": "200"}) click: '//a[text() = "bar" and @href="#28-36"]' -assert-property: ("html", {"scrollTop": "225"}) +assert-property: ("html", {"scrollTop": "231"}) click: '//a[normalize-space() = "sub_fn" and @href="#2-4"]' -assert-property: ("html", {"scrollTop": "122"}) +assert-property: ("html", {"scrollTop": "128"}) // We now check that clicking on lines doesn't change the scroll // Extra information: the "sub_fn" function header is on line 1. click: '//*[@id="6"]' -assert-property: ("html", {"scrollTop": "122"}) +assert-property: ("html", {"scrollTop": "128"}) diff --git a/tests/rustdoc-gui/toggle-docs-mobile.goml b/tests/rustdoc-gui/toggle-docs-mobile.goml index 59233d94fcc45..b69aa6e30ca0b 100644 --- a/tests/rustdoc-gui/toggle-docs-mobile.goml +++ b/tests/rustdoc-gui/toggle-docs-mobile.goml @@ -3,12 +3,12 @@ go-to: "file://" + |DOC_PATH| + "/test_docs/struct.Foo.html" set-window-size: (433, 600) assert-attribute: (".top-doc", {"open": ""}) -click: (4, 260) // This is the position of the top doc comment toggle +click: (4, 270) // This is the position of the top doc comment toggle assert-attribute-false: (".top-doc", {"open": ""}) -click: (4, 260) +click: (4, 270) assert-attribute: (".top-doc", {"open": ""}) // To ensure that the toggle isn't over the text, we check that the toggle isn't clicked. -click: (3, 260) +click: (3, 270) assert-attribute: (".top-doc", {"open": ""}) // Assert the position of the toggle on the top doc block. @@ -24,10 +24,10 @@ assert-position: ( // Now we do the same but with a little bigger width set-window-size: (600, 600) assert-attribute: (".top-doc", {"open": ""}) -click: (4, 260) // New Y position since all search elements are back on one line. +click: (4, 270) // New Y position since all search elements are back on one line. assert-attribute-false: (".top-doc", {"open": ""}) -click: (4, 260) +click: (4, 270) assert-attribute: (".top-doc", {"open": ""}) // To ensure that the toggle isn't over the text, we check that the toggle isn't clicked. -click: (3, 260) +click: (3, 270) assert-attribute: (".top-doc", {"open": ""}) From ad8a5ce4cae159b8c9703be969cfe17c877e38f5 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 29 Sep 2024 18:51:03 +0200 Subject: [PATCH 1707/2194] let rustfmt format imports --- .../bench-cargo-miri/backtraces/src/main.rs | 3 +- .../miri/bench-cargo-miri/serde2/src/main.rs | 3 +- src/tools/miri/cargo-miri/src/phases.rs | 3 +- src/tools/miri/miri-script/src/args.rs | 3 +- src/tools/miri/miri-script/src/commands.rs | 7 +--- src/tools/miri/rustfmt.toml | 7 +++- src/tools/miri/src/alloc_addresses/mod.rs | 5 +-- .../miri/src/alloc_addresses/reuse_pool.rs | 4 +- src/tools/miri/src/alloc_bytes.rs | 3 +- src/tools/miri/src/bin/miri.rs | 22 ++++------ src/tools/miri/src/borrow_tracker/mod.rs | 3 +- .../stacked_borrows/diagnostics.rs | 2 +- .../src/borrow_tracker/stacked_borrows/mod.rs | 19 ++++----- .../borrow_tracker/stacked_borrows/stack.rs | 6 +-- .../tree_borrows/diagnostics.rs | 8 ++-- .../src/borrow_tracker/tree_borrows/mod.rs | 13 +++--- .../src/borrow_tracker/tree_borrows/tree.rs | 13 +++--- .../borrow_tracker/tree_borrows/tree/tests.rs | 3 +- .../src/borrow_tracker/tree_borrows/unimap.rs | 3 +- src/tools/miri/src/concurrency/data_race.rs | 21 ++++------ .../miri/src/concurrency/range_object_map.rs | 2 +- src/tools/miri/src/concurrency/sync.rs | 3 +- src/tools/miri/src/concurrency/thread.rs | 1 - .../miri/src/concurrency/vector_clock.rs | 15 +++---- src/tools/miri/src/concurrency/weak_memory.rs | 15 +++---- src/tools/miri/src/eval.rs | 16 +++---- src/tools/miri/src/helpers.rs | 19 +++------ src/tools/miri/src/intrinsics/atomic.rs | 3 +- src/tools/miri/src/intrinsics/mod.rs | 6 +-- src/tools/miri/src/intrinsics/simd.rs | 4 +- src/tools/miri/src/lib.rs | 42 +++++++++---------- src/tools/miri/src/machine.rs | 31 +++++--------- src/tools/miri/src/operator.rs | 3 +- src/tools/miri/src/provenance_gc.rs | 1 - src/tools/miri/src/shims/backtrace.rs | 6 ++- src/tools/miri/src/shims/env.rs | 3 +- src/tools/miri/src/shims/foreign_items.rs | 17 ++++---- src/tools/miri/src/shims/native_lib.rs | 3 +- src/tools/miri/src/shims/os_str.rs | 3 +- src/tools/miri/src/shims/unix/env.rs | 3 +- src/tools/miri/src/shims/unix/fd.rs | 3 +- .../miri/src/shims/unix/foreign_items.rs | 9 ++-- src/tools/miri/src/shims/unix/fs.rs | 15 +++---- .../miri/src/shims/unix/linux/eventfd.rs | 3 +- .../src/shims/unix/linux/foreign_items.rs | 3 +- src/tools/miri/src/shims/unix/linux/mem.rs | 3 +- src/tools/miri/src/shims/unix/mem.rs | 3 +- src/tools/miri/src/shims/unix/mod.rs | 11 ++--- src/tools/miri/src/shims/unix/thread.rs | 3 +- .../miri/src/shims/unix/unnamed_socket.rs | 3 +- .../miri/src/shims/windows/foreign_items.rs | 4 +- src/tools/miri/src/shims/windows/handle.rs | 3 +- src/tools/miri/src/shims/windows/mod.rs | 3 +- src/tools/miri/src/shims/x86/avx.rs | 2 +- src/tools/miri/src/shims/x86/mod.rs | 4 +- src/tools/miri/test-cargo-miri/src/main.rs | 3 +- .../miri/test-cargo-miri/subcrate/test.rs | 1 - .../concurrency/libc_pthread_join_multiple.rs | 3 +- .../miri/tests/fail-dep/libc/affinity.rs | 4 +- .../fail-dep/libc/env-set_var-data-race.rs | 3 +- .../miri/tests/fail/coroutine-pinned-moved.rs | 6 +-- .../data_race/atomic_read_na_write_race2.rs | 3 +- .../data_race/atomic_write_na_read_race1.rs | 3 +- .../data_race/atomic_write_na_write_race2.rs | 3 +- .../fail/tree_borrows/children-can-alias.rs | 3 +- .../tests/pass-dep/concurrency/linux-futex.rs | 3 +- .../concurrency/tls_pthread_drop_order.rs | 3 +- src/tools/miri/tests/pass-dep/libc/gettid.rs | 3 +- .../miri/tests/pass-dep/libc/libc-affinity.rs | 3 +- .../miri/tests/pass-dep/libc/libc-fs-flock.rs | 4 +- src/tools/miri/tests/pass-dep/libc/libc-fs.rs | 3 +- .../miri/tests/pass-dep/tokio/file-io.rs | 1 + .../miri/tests/pass/async-niche-aliasing.rs | 12 +++--- ...atomic-compare-exchange-weak-never-fail.rs | 3 +- src/tools/miri/tests/pass/atomic.rs | 5 +-- .../tests/pass/box-custom-alloc-aliasing.rs | 12 +++--- src/tools/miri/tests/pass/box-custom-alloc.rs | 3 +- .../address_reuse_happens_before.rs | 3 +- .../pass/concurrency/sync_singlethread.rs | 3 +- src/tools/miri/tests/pass/coroutine.rs | 6 +-- .../miri/tests/pass/dyn-arbitrary-self.rs | 10 ++--- .../tests/pass/function_calls/abi_compat.rs | 4 +- .../tests/pass/intrinsics/portable-simd.rs | 3 +- ...iri-3541-dyn-vtable-trait-normalization.rs | 3 +- src/tools/miri/tests/pass/leak-in-static.rs | 6 +-- src/tools/miri/tests/pass/ptr_int_casts.rs | 3 +- src/tools/miri/tests/pass/shims/env/var.rs | 3 +- .../tests/pass/shims/windows-threadname.rs | 3 +- src/tools/miri/tests/pass/slices.rs | 3 +- .../coroutine-self-referential.rs | 6 +-- .../pass/stacked-borrows/stack-printing.rs | 6 +-- .../tests/pass/tree_borrows/tree-borrows.rs | 3 +- src/tools/miri/tests/ui.rs | 3 +- 93 files changed, 255 insertions(+), 319 deletions(-) diff --git a/src/tools/miri/bench-cargo-miri/backtraces/src/main.rs b/src/tools/miri/bench-cargo-miri/backtraces/src/main.rs index eba51c60dbc5b..b1a58712becb6 100644 --- a/src/tools/miri/bench-cargo-miri/backtraces/src/main.rs +++ b/src/tools/miri/bench-cargo-miri/backtraces/src/main.rs @@ -1,8 +1,9 @@ //! Extracted from the backtrace crate's test test_frame_conversion -use backtrace::{Backtrace, BacktraceFrame}; use std::fmt::Write; +use backtrace::{Backtrace, BacktraceFrame}; + fn main() { let mut frames = vec![]; backtrace::trace(|frame| { diff --git a/src/tools/miri/bench-cargo-miri/serde2/src/main.rs b/src/tools/miri/bench-cargo-miri/serde2/src/main.rs index 83c04b9dd5f57..8842d4ce31077 100644 --- a/src/tools/miri/bench-cargo-miri/serde2/src/main.rs +++ b/src/tools/miri/bench-cargo-miri/serde2/src/main.rs @@ -1,9 +1,10 @@ // Like serde1, but in two threads concurrently. And we don't print. static JSON: &str = r#"{"buffer":[-29,-42,-40,-37,-28,-5,-21,1,-24,-8,-20,4,-18,26,-24,44,-26,66,-30,86,-37,88,-41,72,-46,50,-31,28,23,14,64,16,51,26,32,34,39,42,48,35,58,0,72,-36,69,-59,58,-98,54,-124,36,-103,12,-110,5,-173,-19,-146,-59,-4,-42,51,1,-23,-6,-30,-6,45,46,47,70,6,55,19,60,38,62,42,47,61,46,40,42,-19,22,-34,6,-35,-50,-61,-141,-37,-171,17,-163,26,-180,46,-154,80,-63,48,-4,18,20,50,47,58,53,44,61,57,85,37,80,0,86,-8,106,-95,49,-213,-8,-131,47,49,63,40,-39,-69,-74,-37,-20,63,-12,58,-14,-12,25,-31,41,11,45,76,47,167,5,261,-37,277,-83,183,-172,35,-122,-79,138,-70,266,69,124,228,0,391,-29,594,-84,702,-78,627,-8,551,-13,509,13,372,120,352,125,622,127,691,223,362,126,386,-33,915,198,958,457,456,298,500,233,1027,469,1096,426,918,160,1067,141,1220,189,1245,164,1375,297,1378,503,1299,702,1550,929,1799,855,1752,547,1830,602,1928,832,1736,796,1735,933,1961,1385,1935,1562,2105,1485,2716,1449,2948,1305,2768,1205,2716,1346,2531,1450,2470,1653,3117,2111,3370,2176,2696,1947,2925,2305,3846,2658,2425,2184,-877,1981,-2261,2623,-1645,2908,-1876,2732,-2704,2953,-2484,3116,-2120,2954,-2442,3216,-2466,3499,-2192,3234,-2392,3361,-2497,3869,-2078,3772,-1858,3915,-2066,4438,-2285,2934,-2294,-280,-2066,-1762,-1992,-1412,-2298,-1535,-2399,-1789,-2223,-1419,-2244,-1334,-2092,-1476,-1777,-1396,-2014,-1571,-2199,-1574,-1843,-1167,-1910,-1446,-2007,-1818,-1506,-1331,-2526,-2048,-5535,-4573,-7148,-5828,-6422,-5327,-5840,-5488,-5992,-6144,-6014,-6164,-6109,-6234,-6271,-6388,-6288,-6156,-6517,-6249,-6794,-6602,-6822,-6418,-6788,-6245,-6490,-6560,-6394,-6794,-7920,-6937,-10397,-7140,-11428,-6972,-11019,-6610,-11141,-6665,-11913,-7046,-11979,-7235,-11599,-7015,-11854,-6912,-12161,-7441,-12136,-7761,-12861,-7292,-13390,-7254,-12345,-7809,-12490,-7463,-13983,-6969,-10489,-8465,-2382,-11054,1272,-12247,-270,-12060,-323,-12113,502,-12486,-697,-12251,-1086,-12141,-181,-13116,-670,-13509,-1173,-12592,-443,-12811,-449,-13698,-934,-12850,-747,-13083,-873,-15036,-1161,-11478,-1047,-2669,-1407,1006,-1658,-1146,-1195,-1297,-1421,-73,-1946,-977,-1590,-1499,-1577,-1010,-1862,-1256,-1389,-962,-1692,-509,-2613,-1317,-2087,-1359,-1997,-1034,-2891,-2024,-119,-84,5651,5723,8074,8306,7156,6870,6985,7106,7312,8403,7114,8096,7173,7848,7082,7827,6761,7189,6985,7368,7076,7835,6992,7297,7453,7260,7016,7755,6025,7429,8533,7352,14150,7628,17142,7077,16399,6947,15939,7475,16564,7069,16463,6882,16400,7602,17031,7233,16543,6517,15395,7018,15985,7104,16689,6869,15655,7622,16155,7198,17884,6022,14056,8856,5665,14484,1815,16782,3034,15786,3107,15664,2312,16517,2965,16443,3036,16120,2287,16584,2479,16720,2693,16073,2535,16159,2958,16609,3067,16086,2716,16579,3035,17752,3092,13704,2499,5265,2620,1452,2808,3024,2444,3275,2839,2267,3340,2857,2968,3232,3066,2867,3152,3072,2248,2961,2413,2807,3238,3237,2368,2699,2262,2392,3537,3339,827,823,-5020,-5359,-7095,-7857,-5973,-6274,-6208,-6279,-6934,-7181,-6893,-6647,-7146,-6687,-7026,-7328,-6451,-6924,-6763,-6535,-7109,-6639,-6926,-6559,-7188,-6799,-6727,-6955,-5786,-6554,-8543,-6796,-14465,-7190,-17356,-6641,-16372,-6529,-15941,-6898,-16526,-6434,-16219,-6520,-16222,-7449,-17077,-7097,-16665,-6476,-15675,-7026,-16498,-6848,-17147,-6271,-15894,-7069,-16266,-7032,-17817,-5991,-13796,-8594,-5421,-14349,-1649,-17288,-2847,-16525,-2974,-15945,-2324,-16482,-3022,-16593,-3097,-16451,-2420,-16780,-2649,-16641,-2836,-15900,-2660,-16214,-3050,-16827,-3111,-15993,-2741,-16151,-2994,-17537,-2933,-13812,-2314,-5216,-2475,-1125,-2648,-2801,-2290,-3285,-2796,-2243,-3415,-2642,-3109,-3000,-3271,-2839,-3408,-3161,-2497,-2876,-2603,-2570,-3351,-3173,-2416,-2832,-2235,-2408,-3405,-3186,-613,-768,5271,5201,7376,7644,6241,6176,6366,6275,6964,7124,6831,6508,6998,6566,6836,7230,6277,6777,6589,6376,6934,6536,6819,6494,7160,6749,6736,6900,5822,6476,8593,6747,14520,7204,17448,6637,16490,6483,16033,6906,16600,6511,16304,6568,16279,7438,17079,7072,16624,6463,15577,7028,16343,6877,16990,6331,15760,7121,16140,7023,17719,5944,13748,8575,5401,14336,1645,17210,2880,16419,3036,15896,2382,16483,3074,16584,3143,16425,2443,16782,2650,16695,2825,15978,2632,16272,3015,16880,3084,16096,2709,16289,2965,17641,2932,13887,2323,5330,2474,1286,2656,2954,2309,3410,2803,2373,3414,2795,3106,3151,3263,2952,3403,3241,2483,2969,2568,2681,3316,3245,2383,2837,2199,2390,3396,3165,641,706,-5230,-5323,-7307,-7790,-6136,-6317,-6268,-6419,-6884,-7278,-6766,-6666,-6976,-6731,-6853,-7406,-6308,-6958,-6636,-6553,-6978,-6703,-6829,-6647,-7156,-6883,-6737,-7017,-5814,-6581,-8575,-6833,-14490,-7270,-17411,-6699,-16466,-6539,-16016,-6931,-16571,-6504,-16257,-6551,-16202,-7408,-16983,-7021,-16545,-6410,-15512,-6976,-16305,-6803,-17017,-6243,-15820,-7037,-16197,-6923,-17802,-5820,-13840,-8455,-5475,-14227,-1724,-17099,-2923,-16314,-3008,-15801,-2362,-16392,-3088,-16506,-3163,-16356,-2503,-16700,-2717,-16605,-2855,-15904,-2710,-16226,-3108,-16870,-3089,-16101,-2747,-16257,-3087,-17584,-2975,-13868,-2324,-5343,-2548,-1275,-2673,-2917,-2213,-3363,-2694,-2311,-3251,-2744,-2867,-3129,-3034,-2939,-3190,-3234,-2346,-2964,-2639,-2658,-3558,-3241,-2670,-2892,-2453,-2437,-3564,-3175,-771,-779,5105,5171,7308,7655,6265,6204,6397,6288,7024,7172,6903,6586,7002,6627,6777,7308,6190,6889,6537,6465,7011,6613,6985,6631,7393,6934,7073,7072,6112,6615,8751,6859,14672,7282,17448,6652,16146,6448,15565,6899,16151,6547,15860,6591,16048,7446,17065,7064,16661,6368,15774,6857,16524,6677,16825,6071,15577,6900,16119,7040,17490,6118,13495,8696,5432,14446,1678,17366,3036,16488,3624,15834,3012,16382,3575,16465,3685,16301,2815,16708,2982,16679,3356,15952,2934,16049,3290,16352,3964,15605,3612,16222,3647,17764,4272,13865,3977,5384,3592,1580,3794,3243,3627,3670,3622,2758,4007,3130,3835,3294,3964,3065,4468,3408,3933,3234,3789,3118,4634,3643,4211,3174,4155,3176,5512,4400,2792,1730,-3702,-4499,-5940,-6691,-4265,-5094,-4381,-5215,-4918,-5746,-4217,-4871,-4402,-4981,-4479,-5525,-3732,-4968,-4118,-4924,-4300,-5349,-3422,-5021,-3876,-4886,-4087,-4860,-2790,-4254,-5025,-4196,-10898,-4415,-13419,-4007,-12198,-4121,-11995,-4413,-12471,-3808,-11937,-3920,-11792,-4583,-12284,-3776,-12085,-3107,-11421,-3583,-11226,-3081,-11157,-2768,-10580,-3914,-10424,-3197,-11040,-1715,-9822,-5144,-6189,-11154,-4236,-13029,-5134,-11598,-5507,-10949,-4921,-11142,-4999,-11180,-4883,-11184,-4366,-11090,-4548,-10887,-4818,-10708,-4866,-10534,-5253,-10272,-5179,-9894,-4633,-10029,-4773,-10382,-4977,-8674,-4668,-5292,-4651,-3928,-4629,-4465,-4312,-3994,-4459,-3528,-4570,-4400,-4272,-4601,-4482,-4035,-4627,-4334,-4080,-4498,-4045,-3835,-4204,-3526,-3695,-3646,-4045,-4101,-4856,-4628,-3338,-3235,-673,-508,28,147,-453,-639,11,0,8,-2,7,0,7,-3,11,-8,15,-9,17,-6,17,-5,13,-3,7,0,3,0,-2,0,-4,0,-4,-2,-6,0,-14,-2,-17,-4,-8,0,-7,5,-17,7,-18,10,-7,18,-2,25,-3,27,0,31,4,34,4,34,8,36,8,37,2,36,4,34,8,28,3,15,0,11,0,12,-5,8,-4,10,0,23,-4,31,-8,30,-2,30,0,26,-6,22,-6,20,-12,15,-19,10,-10,13,-14,6,-43,-13,-43,-16,-9,-12,-10,-29,-42,-40,-37,-28,-5,-21,1,-24,-8,-20,4,-18,26,-24,44,-26,66,-30,86,-37,88,-41,72,-46,50,-31,28,23,14,64,16,51,26,32,34,39,42,48,35,58,0,72,-36,69,-59,58,-98,54,-124,36,-103,12,-110,5,-173,-19,-146,-59,-4,-42,51,1,-23,-6,-30,-6,45,46,47,70,6,55,19,60,38,62,42,47,61,46,40,42,-19,22,-34,6,-35,-50,-61,-141,-37,-171,17,-163,26,-180,46,-154,80,-63,48,-4,18,20,50,47,58,53,44,61,57,85,37,80,0,86,-8,106,-95,49,-213,-8,-131,47,49,63,40,-39,-69,-74,-37,-20,63,-12,58,-14,-12,25,-31,41,11,45,76,47,167,5,261,-37,277,-83,183,-172,35,-122,-79,138,-70,266,69,124,228,0,391,-29,594,-84,702,-78,627,-8,551,-13,509,13,372,120,352,125,622,127,691,223,362,126,386,-33,915,198,958,457,456,298,500,233,1027,469,1096,426,918,160,1067,141,1220,189,1245,164,1375,297,1378,503,1299,702,1550,929,1799,855,1752,547,1830,602,1928,832,1736,796,1735,933,1961,1385,1935,1562,2105,1485,2716,1449,2948,1305,2768,1205,2716,1346,2531,1450,2470,1653,3117,2111,3370,2176,2696,1947,2925,2305,3846,2658,2425,2184,-877,1981,-2261,2623,-1645,2908,-1876,2732,-2704,2953,-2484,3116,-2120,2954,-2442,3216,-2466,3499,-2192,3234,-2392,3361,-2497,3869,-2078,3772,-1858,3915,-2066,4438,-2285,2934,-2294,-280,-2066,-1762,-1992,-1412,-2298,-1535,-2399,-1789,-2223,-1419,-2244,-1334,-2092,-1476,-1777,-1396,-2014,-1571,-2199,-1574,-1843,-1167,-1910,-1446,-2007,-1818,-1506,-1331,-2526,-2048,-5535,-4573,-7148,-5828,-6422,-5327,-5840,-5488,-5992,-6144,-6014,-6164,-6109,-6234,-6271,-6388,-6288,-6156,-6517,-6249,-6794,-6602,-6822,-6418,-6788,-6245,-6490,-6560,-6394,-6794,-7920,-6937,-10397,-7140,-11428,-6972,-11019,-6610,-11141,-6665,-11913,-7046,-11979,-7235,-11599,-7015,-11854,-6912,-12161,-7441,-12136,-7761,-12861,-7292,-13390,-7254,-12345,-7809,-12490,-7463,-13983,-6969,-10489,-8465,-2382,-11054,1272,-12247,-270,-12060,-323,-12113,502,-12486,-697,-12251,-1086,-12141,-181,-13116,-670,-13509,-1173,-12592,-443,-12811,-449,-13698,-934,-12850,-747,-13083,-873,-15036,-1161,-11478,-1047,-2669,-1407,1006,-1658,-1146,-1195,-1297,-1421,-73,-1946,-977,-1590,-1499,-1577,-1010,-1862,-1256,-1389,-962,-1692,-509,-2613,-1317,-2087,-1359,-1997,-1034,-2891,-2024,-119,-84,5651,5723,8074,8306,7156,6870,6985,7106,7312,8403,7114,8096,7173,7848,7082,7827,6761,7189,6985,7368]}"#; -use serde::Deserialize; use std::thread; +use serde::Deserialize; + #[derive(Deserialize)] #[allow(unused)] struct DeriveStruct { diff --git a/src/tools/miri/cargo-miri/src/phases.rs b/src/tools/miri/cargo-miri/src/phases.rs index e13ecbbe54ba5..52bc8e1a3b6d7 100644 --- a/src/tools/miri/cargo-miri/src/phases.rs +++ b/src/tools/miri/cargo-miri/src/phases.rs @@ -8,7 +8,8 @@ use std::{env, thread}; use rustc_version::VersionMeta; -use crate::{setup::*, util::*}; +use crate::setup::*; +use crate::util::*; const CARGO_MIRI_HELP: &str = r"Runs binary crates and tests in Miri diff --git a/src/tools/miri/miri-script/src/args.rs b/src/tools/miri/miri-script/src/args.rs index c1688ca0fb6b2..55d9de4233d9b 100644 --- a/src/tools/miri/miri-script/src/args.rs +++ b/src/tools/miri/miri-script/src/args.rs @@ -1,5 +1,4 @@ -use std::env; -use std::iter; +use std::{env, iter}; use anyhow::{Result, bail}; diff --git a/src/tools/miri/miri-script/src/commands.rs b/src/tools/miri/miri-script/src/commands.rs index b0e62d5cda6f0..36175c8dd2bd2 100644 --- a/src/tools/miri/miri-script/src/commands.rs +++ b/src/tools/miri/miri-script/src/commands.rs @@ -1,12 +1,9 @@ -use std::env; use std::ffi::{OsStr, OsString}; use std::io::Write; -use std::net; -use std::ops::Not; -use std::ops::Range; +use std::ops::{Not, Range}; use std::path::PathBuf; -use std::process; use std::time::Duration; +use std::{env, net, process}; use anyhow::{Context, Result, anyhow, bail}; use path_macro::path; diff --git a/src/tools/miri/rustfmt.toml b/src/tools/miri/rustfmt.toml index 3f9311d9d1a50..49650d8486c40 100644 --- a/src/tools/miri/rustfmt.toml +++ b/src/tools/miri/rustfmt.toml @@ -1,5 +1,10 @@ +# This matches rustc style_edition = "2024" use_small_heuristics = "Max" +group_imports = "StdExternalCrate" +imports_granularity = "Module" + +# Miri-specific settings +force_multiline_blocks = true match_arm_blocks = false match_arm_leading_pipes = "Preserve" -force_multiline_blocks = true diff --git a/src/tools/miri/src/alloc_addresses/mod.rs b/src/tools/miri/src/alloc_addresses/mod.rs index c19a962e6523e..f71edafb4b2ad 100644 --- a/src/tools/miri/src/alloc_addresses/mod.rs +++ b/src/tools/miri/src/alloc_addresses/mod.rs @@ -7,14 +7,13 @@ use std::cell::RefCell; use std::cmp::max; use rand::Rng; - use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_span::Span; use rustc_target::abi::{Align, Size}; -use crate::{concurrency::VClock, *}; - use self::reuse_pool::ReusePool; +use crate::concurrency::VClock; +use crate::*; #[derive(Copy, Clone, Debug, PartialEq, Eq)] pub enum ProvenanceMode { diff --git a/src/tools/miri/src/alloc_addresses/reuse_pool.rs b/src/tools/miri/src/alloc_addresses/reuse_pool.rs index f6c1675634460..b5366d5ce929c 100644 --- a/src/tools/miri/src/alloc_addresses/reuse_pool.rs +++ b/src/tools/miri/src/alloc_addresses/reuse_pool.rs @@ -1,10 +1,10 @@ //! Manages a pool of addresses that can be reused. use rand::Rng; - use rustc_target::abi::{Align, Size}; -use crate::{MemoryKind, MiriConfig, ThreadId, concurrency::VClock}; +use crate::concurrency::VClock; +use crate::{MemoryKind, MiriConfig, ThreadId}; const MAX_POOL_SIZE: usize = 64; diff --git a/src/tools/miri/src/alloc_bytes.rs b/src/tools/miri/src/alloc_bytes.rs index 84225d83b6aec..6ada8c66fde69 100644 --- a/src/tools/miri/src/alloc_bytes.rs +++ b/src/tools/miri/src/alloc_bytes.rs @@ -1,7 +1,6 @@ -use std::alloc; use std::alloc::Layout; use std::borrow::Cow; -use std::slice; +use std::{alloc, slice}; use rustc_middle::mir::interpret::AllocBytes; use rustc_target::abi::{Align, Size}; diff --git a/src/tools/miri/src/bin/miri.rs b/src/tools/miri/src/bin/miri.rs index 14f43f576d3a4..8d3ae97e0e9fa 100644 --- a/src/tools/miri/src/bin/miri.rs +++ b/src/tools/miri/src/bin/miri.rs @@ -28,31 +28,27 @@ use std::num::NonZero; use std::path::PathBuf; use std::str::FromStr; -use tracing::debug; - +use miri::{BacktraceStyle, BorrowTrackerMethod, ProvenanceMode, RetagFields, ValidationMode}; use rustc_data_structures::sync::Lrc; use rustc_driver::Compilation; use rustc_hir::def_id::LOCAL_CRATE; use rustc_hir::{self as hir, Node}; use rustc_hir_analysis::check::check_function_signature; use rustc_interface::interface::Config; -use rustc_middle::{ - middle::{ - codegen_fn_attrs::CodegenFnAttrFlags, - exported_symbols::{ExportedSymbol, SymbolExportInfo, SymbolExportKind, SymbolExportLevel}, - }, - query::LocalCrate, - traits::{ObligationCause, ObligationCauseCode}, - ty::{self, Ty, TyCtxt}, - util::Providers, +use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; +use rustc_middle::middle::exported_symbols::{ + ExportedSymbol, SymbolExportInfo, SymbolExportKind, SymbolExportLevel, }; +use rustc_middle::query::LocalCrate; +use rustc_middle::traits::{ObligationCause, ObligationCauseCode}; +use rustc_middle::ty::{self, Ty, TyCtxt}; +use rustc_middle::util::Providers; use rustc_session::config::{CrateType, EntryFnType, ErrorOutputType, OptLevel}; use rustc_session::search_paths::PathKind; use rustc_session::{CtfeBacktrace, EarlyDiagCtxt}; use rustc_span::def_id::DefId; use rustc_target::spec::abi::Abi; - -use miri::{BacktraceStyle, BorrowTrackerMethod, ProvenanceMode, RetagFields, ValidationMode}; +use tracing::debug; struct MiriCompilerCalls { miri_config: miri::MiriConfig, diff --git a/src/tools/miri/src/borrow_tracker/mod.rs b/src/tools/miri/src/borrow_tracker/mod.rs index 9e205cd0064aa..89fd8c28af2ae 100644 --- a/src/tools/miri/src/borrow_tracker/mod.rs +++ b/src/tools/miri/src/borrow_tracker/mod.rs @@ -2,11 +2,10 @@ use std::cell::RefCell; use std::fmt; use std::num::NonZero; -use smallvec::SmallVec; - use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_middle::mir::RetagKind; use rustc_target::abi::Size; +use smallvec::SmallVec; use crate::*; pub mod stacked_borrows; diff --git a/src/tools/miri/src/borrow_tracker/stacked_borrows/diagnostics.rs b/src/tools/miri/src/borrow_tracker/stacked_borrows/diagnostics.rs index 12eeaae0eff47..146f9902f6fe0 100644 --- a/src/tools/miri/src/borrow_tracker/stacked_borrows/diagnostics.rs +++ b/src/tools/miri/src/borrow_tracker/stacked_borrows/diagnostics.rs @@ -1,9 +1,9 @@ -use smallvec::SmallVec; use std::fmt; use rustc_data_structures::fx::FxHashSet; use rustc_span::{Span, SpanData}; use rustc_target::abi::Size; +use smallvec::SmallVec; use crate::borrow_tracker::{GlobalStateInner, ProtectorKind}; use crate::*; diff --git a/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs b/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs index 7eb6773038388..b270e484bdba4 100644 --- a/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs +++ b/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs @@ -6,25 +6,24 @@ mod item; mod stack; use std::cell::RefCell; -use std::cmp; use std::fmt::Write; -use std::mem; +use std::{cmp, mem}; use rustc_data_structures::fx::FxHashSet; use rustc_middle::mir::{Mutability, RetagKind}; -use rustc_middle::ty::{self, Ty, layout::HasParamEnv}; +use rustc_middle::ty::layout::HasParamEnv; +use rustc_middle::ty::{self, Ty}; use rustc_target::abi::{Abi, Size}; -use crate::borrow_tracker::{ - GlobalStateInner, ProtectorKind, - stacked_borrows::diagnostics::{AllocHistory, DiagnosticCx, DiagnosticCxBuilder}, -}; -use crate::concurrency::data_race::{NaReadType, NaWriteType}; -use crate::*; - use self::diagnostics::{RetagCause, RetagInfo}; pub use self::item::{Item, Permission}; pub use self::stack::Stack; +use crate::borrow_tracker::stacked_borrows::diagnostics::{ + AllocHistory, DiagnosticCx, DiagnosticCxBuilder, +}; +use crate::borrow_tracker::{GlobalStateInner, ProtectorKind}; +use crate::concurrency::data_race::{NaReadType, NaWriteType}; +use crate::*; pub type AllocState = Stacks; diff --git a/src/tools/miri/src/borrow_tracker/stacked_borrows/stack.rs b/src/tools/miri/src/borrow_tracker/stacked_borrows/stack.rs index 5c040983142f8..6b5ef7d59c554 100644 --- a/src/tools/miri/src/borrow_tracker/stacked_borrows/stack.rs +++ b/src/tools/miri/src/borrow_tracker/stacked_borrows/stack.rs @@ -5,10 +5,8 @@ use rustc_data_structures::fx::FxHashSet; use tracing::trace; use crate::ProvenanceExtra; -use crate::borrow_tracker::{ - AccessKind, BorTag, - stacked_borrows::{Item, Permission}, -}; +use crate::borrow_tracker::stacked_borrows::{Item, Permission}; +use crate::borrow_tracker::{AccessKind, BorTag}; /// Exactly what cache size we should use is a difficult trade-off. There will always be some /// workload which has a `BorTag` working set which exceeds the size of the cache, and ends up diff --git a/src/tools/miri/src/borrow_tracker/tree_borrows/diagnostics.rs b/src/tools/miri/src/borrow_tracker/tree_borrows/diagnostics.rs index 44ea7533b00cb..af9ec129c69f7 100644 --- a/src/tools/miri/src/borrow_tracker/tree_borrows/diagnostics.rs +++ b/src/tools/miri/src/borrow_tracker/tree_borrows/diagnostics.rs @@ -5,11 +5,9 @@ use rustc_data_structures::fx::FxHashMap; use rustc_span::{Span, SpanData}; use crate::borrow_tracker::ProtectorKind; -use crate::borrow_tracker::tree_borrows::{ - perms::{PermTransition, Permission}, - tree::LocationState, - unimap::UniIndex, -}; +use crate::borrow_tracker::tree_borrows::perms::{PermTransition, Permission}; +use crate::borrow_tracker::tree_borrows::tree::LocationState; +use crate::borrow_tracker::tree_borrows::unimap::UniIndex; use crate::*; /// Cause of an access: either a real access or one diff --git a/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs b/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs index 2afe02dc2c7f8..30e940b4439a4 100644 --- a/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs +++ b/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs @@ -1,15 +1,12 @@ -use rustc_middle::{ - mir::{Mutability, RetagKind}, - ty::{self, Ty, layout::HasParamEnv}, -}; +use rustc_middle::mir::{Mutability, RetagKind}; +use rustc_middle::ty::layout::HasParamEnv; +use rustc_middle::ty::{self, Ty}; use rustc_span::def_id::DefId; use rustc_target::abi::{Abi, Size}; +use crate::borrow_tracker::{GlobalState, GlobalStateInner, ProtectorKind}; +use crate::concurrency::data_race::NaReadType; use crate::*; -use crate::{ - borrow_tracker::{GlobalState, GlobalStateInner, ProtectorKind}, - concurrency::data_race::NaReadType, -}; pub mod diagnostics; mod perms; diff --git a/src/tools/miri/src/borrow_tracker/tree_borrows/tree.rs b/src/tools/miri/src/borrow_tracker/tree_borrows/tree.rs index a99c71d96b4b1..9fe134ed34bc9 100644 --- a/src/tools/miri/src/borrow_tracker/tree_borrows/tree.rs +++ b/src/tools/miri/src/borrow_tracker/tree_borrows/tree.rs @@ -12,18 +12,17 @@ use std::{fmt, mem}; -use smallvec::SmallVec; - use rustc_data_structures::fx::FxHashSet; use rustc_span::Span; use rustc_target::abi::Size; +use smallvec::SmallVec; -use crate::borrow_tracker::tree_borrows::{ - Permission, - diagnostics::{self, NodeDebugInfo, TbError, TransitionError}, - perms::PermTransition, - unimap::{UniEntry, UniIndex, UniKeyMap, UniValMap}, +use crate::borrow_tracker::tree_borrows::Permission; +use crate::borrow_tracker::tree_borrows::diagnostics::{ + self, NodeDebugInfo, TbError, TransitionError, }; +use crate::borrow_tracker::tree_borrows::perms::PermTransition; +use crate::borrow_tracker::tree_borrows::unimap::{UniEntry, UniIndex, UniKeyMap, UniValMap}; use crate::borrow_tracker::{GlobalState, ProtectorKind}; use crate::*; diff --git a/src/tools/miri/src/borrow_tracker/tree_borrows/tree/tests.rs b/src/tools/miri/src/borrow_tracker/tree_borrows/tree/tests.rs index 5cd5040f80776..5d51a72852ca9 100644 --- a/src/tools/miri/src/borrow_tracker/tree_borrows/tree/tests.rs +++ b/src/tools/miri/src/borrow_tracker/tree_borrows/tree/tests.rs @@ -1,9 +1,10 @@ //! Tests for the tree #![cfg(test)] +use std::fmt; + use super::*; use crate::borrow_tracker::tree_borrows::exhaustive::{Exhaustive, precondition}; -use std::fmt; impl Exhaustive for LocationState { fn exhaustive() -> Box> { diff --git a/src/tools/miri/src/borrow_tracker/tree_borrows/unimap.rs b/src/tools/miri/src/borrow_tracker/tree_borrows/unimap.rs index cbc25724cb685..7874721c0ac37 100644 --- a/src/tools/miri/src/borrow_tracker/tree_borrows/unimap.rs +++ b/src/tools/miri/src/borrow_tracker/tree_borrows/unimap.rs @@ -12,7 +12,8 @@ #![allow(dead_code)] -use std::{hash::Hash, mem}; +use std::hash::Hash; +use std::mem; use rustc_data_structures::fx::FxHashMap; diff --git a/src/tools/miri/src/concurrency/data_race.rs b/src/tools/miri/src/concurrency/data_race.rs index b5b43f589f699..8ee039b6ddc89 100644 --- a/src/tools/miri/src/concurrency/data_race.rs +++ b/src/tools/miri/src/concurrency/data_race.rs @@ -40,28 +40,23 @@ //! code some atomic operations may increment the timestamp when not necessary but this has no effect //! on the data-race detection code. -use std::{ - cell::{Cell, Ref, RefCell, RefMut}, - fmt::Debug, - mem, -}; +use std::cell::{Cell, Ref, RefCell, RefMut}; +use std::fmt::Debug; +use std::mem; use rustc_ast::Mutability; -use rustc_data_structures::fx::FxHashMap; -use rustc_data_structures::fx::FxHashSet; +use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_index::{Idx, IndexVec}; -use rustc_middle::{mir, ty::Ty}; +use rustc_middle::mir; +use rustc_middle::ty::Ty; use rustc_span::Span; use rustc_target::abi::{Align, HasDataLayout, Size}; +use super::vector_clock::{VClock, VTimestamp, VectorIdx}; +use super::weak_memory::EvalContextExt as _; use crate::diagnostics::RacingOp; use crate::*; -use super::{ - vector_clock::{VClock, VTimestamp, VectorIdx}, - weak_memory::EvalContextExt as _, -}; - pub type AllocState = VClockAlloc; /// Valid atomic read-write orderings, alias of atomic::Ordering (not non-exhaustive). diff --git a/src/tools/miri/src/concurrency/range_object_map.rs b/src/tools/miri/src/concurrency/range_object_map.rs index 859eb4bbb60d2..d36ed36ac1a6c 100644 --- a/src/tools/miri/src/concurrency/range_object_map.rs +++ b/src/tools/miri/src/concurrency/range_object_map.rs @@ -2,10 +2,10 @@ //! ranges and data are discrete and non-splittable -- they represent distinct "objects". An //! allocation in the map will always have the same range until explicitly removed -use rustc_target::abi::Size; use std::ops::{Index, IndexMut, Range}; use rustc_const_eval::interpret::AllocRange; +use rustc_target::abi::Size; #[derive(Clone, Debug)] struct Elem { diff --git a/src/tools/miri/src/concurrency/sync.rs b/src/tools/miri/src/concurrency/sync.rs index 2b34db047f379..7fe67e5c6727e 100644 --- a/src/tools/miri/src/concurrency/sync.rs +++ b/src/tools/miri/src/concurrency/sync.rs @@ -1,5 +1,6 @@ use std::any::Any; -use std::collections::{VecDeque, hash_map::Entry}; +use std::collections::VecDeque; +use std::collections::hash_map::Entry; use std::ops::Not; use std::time::Duration; diff --git a/src/tools/miri/src/concurrency/thread.rs b/src/tools/miri/src/concurrency/thread.rs index 681e9211246dd..f6b453efcbeb7 100644 --- a/src/tools/miri/src/concurrency/thread.rs +++ b/src/tools/miri/src/concurrency/thread.rs @@ -7,7 +7,6 @@ use std::task::Poll; use std::time::{Duration, SystemTime}; use either::Either; - use rustc_const_eval::CTRL_C_RECEIVED; use rustc_data_structures::fx::FxHashMap; use rustc_hir::def_id::DefId; diff --git a/src/tools/miri/src/concurrency/vector_clock.rs b/src/tools/miri/src/concurrency/vector_clock.rs index 901b097c1bd77..f9025e06c684e 100644 --- a/src/tools/miri/src/concurrency/vector_clock.rs +++ b/src/tools/miri/src/concurrency/vector_clock.rs @@ -1,11 +1,10 @@ +use std::cmp::Ordering; +use std::fmt::Debug; +use std::ops::{Index, Shr}; + use rustc_index::Idx; use rustc_span::{DUMMY_SP, Span, SpanData}; use smallvec::SmallVec; -use std::{ - cmp::Ordering, - fmt::Debug, - ops::{Index, Shr}, -}; use super::data_race::NaReadType; @@ -430,10 +429,12 @@ impl Index for VClock { /// test suite #[cfg(test)] mod tests { + use std::cmp::Ordering; + + use rustc_span::DUMMY_SP; + use super::{VClock, VTimestamp, VectorIdx}; use crate::concurrency::data_race::NaReadType; - use rustc_span::DUMMY_SP; - use std::cmp::Ordering; #[test] fn test_equal() { diff --git a/src/tools/miri/src/concurrency/weak_memory.rs b/src/tools/miri/src/concurrency/weak_memory.rs index 0605b744e6afd..307695436c61e 100644 --- a/src/tools/miri/src/concurrency/weak_memory.rs +++ b/src/tools/miri/src/concurrency/weak_memory.rs @@ -76,21 +76,16 @@ // (https://github.com/ChrisLidbury/tsan11/blob/ecbd6b81e9b9454e01cba78eb9d88684168132c7/lib/tsan/rtl/tsan_relaxed.cc#L295) // and here. -use std::{ - cell::{Ref, RefCell}, - collections::VecDeque, -}; +use std::cell::{Ref, RefCell}; +use std::collections::VecDeque; use rustc_data_structures::fx::FxHashMap; +use super::data_race::{GlobalState as DataRaceState, ThreadClockSet}; +use super::range_object_map::{AccessType, RangeObjectMap}; +use super::vector_clock::{VClock, VTimestamp, VectorIdx}; use crate::*; -use super::{ - data_race::{GlobalState as DataRaceState, ThreadClockSet}, - range_object_map::{AccessType, RangeObjectMap}, - vector_clock::{VClock, VTimestamp, VectorIdx}, -}; - pub type AllocState = StoreBufferAlloc; // Each store buffer must be bounded otherwise it will grow indefinitely. diff --git a/src/tools/miri/src/eval.rs b/src/tools/miri/src/eval.rs index 8c8ed9c4ddc3b..3739d46bd60f0 100644 --- a/src/tools/miri/src/eval.rs +++ b/src/tools/miri/src/eval.rs @@ -1,25 +1,21 @@ //! Main evaluator loop and setting up the initial stack frame. use std::ffi::{OsStr, OsString}; -use std::iter; use std::panic::{self, AssertUnwindSafe}; use std::path::PathBuf; use std::task::Poll; -use std::thread; +use std::{iter, thread}; -use crate::concurrency::thread::TlsAllocAction; -use crate::diagnostics::report_leaks; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_hir::def::Namespace; use rustc_hir::def_id::DefId; -use rustc_middle::ty::{ - self, Ty, TyCtxt, - layout::{LayoutCx, LayoutOf}, -}; -use rustc_target::spec::abi::Abi; - +use rustc_middle::ty::layout::{LayoutCx, LayoutOf}; +use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_session::config::EntryFnType; +use rustc_target::spec::abi::Abi; +use crate::concurrency::thread::TlsAllocAction; +use crate::diagnostics::report_leaks; use crate::shims::tls; use crate::*; diff --git a/src/tools/miri/src/helpers.rs b/src/tools/miri/src/helpers.rs index 10e5882b5ba89..0cd6ba69aac9d 100644 --- a/src/tools/miri/src/helpers.rs +++ b/src/tools/miri/src/helpers.rs @@ -1,29 +1,22 @@ -use std::cmp; use std::collections::BTreeSet; -use std::iter; use std::num::NonZero; use std::sync::Mutex; use std::time::Duration; +use std::{cmp, iter}; use rand::RngCore; - use rustc_apfloat::Float; use rustc_apfloat::ieee::{Double, Half, Quad, Single}; -use rustc_hir::{ - Safety, - def::{DefKind, Namespace}, - def_id::{CRATE_DEF_INDEX, CrateNum, DefId, LOCAL_CRATE}, -}; +use rustc_hir::Safety; +use rustc_hir::def::{DefKind, Namespace}; +use rustc_hir::def_id::{CRATE_DEF_INDEX, CrateNum, DefId, LOCAL_CRATE}; use rustc_index::IndexVec; use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; use rustc_middle::middle::dependency_format::Linkage; use rustc_middle::middle::exported_symbols::ExportedSymbol; use rustc_middle::mir; -use rustc_middle::ty::layout::{FnAbiOf, MaybeResult}; -use rustc_middle::ty::{ - self, FloatTy, IntTy, Ty, TyCtxt, UintTy, - layout::{LayoutOf, TyAndLayout}, -}; +use rustc_middle::ty::layout::{FnAbiOf, LayoutOf, MaybeResult, TyAndLayout}; +use rustc_middle::ty::{self, FloatTy, IntTy, Ty, TyCtxt, UintTy}; use rustc_session::config::CrateType; use rustc_span::{Span, Symbol}; use rustc_target::abi::{Align, FieldIdx, FieldsShape, Size, Variants}; diff --git a/src/tools/miri/src/intrinsics/atomic.rs b/src/tools/miri/src/intrinsics/atomic.rs index f38c3b821742a..b6fd9ba1e825c 100644 --- a/src/tools/miri/src/intrinsics/atomic.rs +++ b/src/tools/miri/src/intrinsics/atomic.rs @@ -1,4 +1,5 @@ -use rustc_middle::{mir, mir::BinOp, ty}; +use rustc_middle::mir::BinOp; +use rustc_middle::{mir, ty}; use self::helpers::check_arg_count; use crate::*; diff --git a/src/tools/miri/src/intrinsics/mod.rs b/src/tools/miri/src/intrinsics/mod.rs index d8d267f5ba693..23ce2f8ed1f91 100644 --- a/src/tools/miri/src/intrinsics/mod.rs +++ b/src/tools/miri/src/intrinsics/mod.rs @@ -5,10 +5,8 @@ mod simd; use rand::Rng; use rustc_apfloat::{Float, Round}; -use rustc_middle::{ - mir, - ty::{self, FloatTy}, -}; +use rustc_middle::mir; +use rustc_middle::ty::{self, FloatTy}; use rustc_span::{Symbol, sym}; use rustc_target::abi::Size; diff --git a/src/tools/miri/src/intrinsics/simd.rs b/src/tools/miri/src/intrinsics/simd.rs index 2bc11d63a3951..802a70e5a54aa 100644 --- a/src/tools/miri/src/intrinsics/simd.rs +++ b/src/tools/miri/src/intrinsics/simd.rs @@ -1,8 +1,8 @@ use either::Either; - use rustc_apfloat::{Float, Round}; +use rustc_middle::ty::FloatTy; use rustc_middle::ty::layout::{HasParamEnv, LayoutOf}; -use rustc_middle::{mir, ty, ty::FloatTy}; +use rustc_middle::{mir, ty}; use rustc_span::{Symbol, sym}; use rustc_target::abi::{Endian, HasDataLayout}; diff --git a/src/tools/miri/src/lib.rs b/src/tools/miri/src/lib.rs index 4d0606113f9ea..78e7bf704552d 100644 --- a/src/tools/miri/src/lib.rs +++ b/src/tools/miri/src/lib.rs @@ -92,15 +92,14 @@ mod range_map; mod shims; // Establish a "crate-wide prelude": we often import `crate::*`. -use rustc_middle::{bug, span_bug}; -use tracing::{info, trace}; - // Make all those symbols available in the same place as our own. #[doc(no_inline)] pub use rustc_const_eval::interpret::*; // Resolve ambiguity. #[doc(no_inline)] pub use rustc_const_eval::interpret::{self, AllocMap, Provenance as _}; +use rustc_middle::{bug, span_bug}; +use tracing::{info, trace}; // Type aliases that set the provenance parameter. pub type Pointer = interpret::Pointer>; @@ -111,15 +110,6 @@ pub type OpTy<'tcx> = interpret::OpTy<'tcx, machine::Provenance>; pub type PlaceTy<'tcx> = interpret::PlaceTy<'tcx, machine::Provenance>; pub type MPlaceTy<'tcx> = interpret::MPlaceTy<'tcx, machine::Provenance>; -pub use crate::intrinsics::EvalContextExt as _; -pub use crate::shims::EmulateItemResult; -pub use crate::shims::env::{EnvVars, EvalContextExt as _}; -pub use crate::shims::foreign_items::{DynSym, EvalContextExt as _}; -pub use crate::shims::os_str::EvalContextExt as _; -pub use crate::shims::panic::{CatchUnwindData, EvalContextExt as _}; -pub use crate::shims::time::EvalContextExt as _; -pub use crate::shims::tls::TlsData; - pub use crate::alloc_addresses::{EvalContextExt as _, ProvenanceMode}; pub use crate::alloc_bytes::MiriAllocBytes; pub use crate::borrow_tracker::stacked_borrows::{ @@ -128,15 +118,17 @@ pub use crate::borrow_tracker::stacked_borrows::{ pub use crate::borrow_tracker::tree_borrows::{EvalContextExt as _, Tree}; pub use crate::borrow_tracker::{BorTag, BorrowTrackerMethod, EvalContextExt as _, RetagFields}; pub use crate::clock::{Clock, Instant}; -pub use crate::concurrency::{ - cpu_affinity::MAX_CPUS, - data_race::{AtomicFenceOrd, AtomicReadOrd, AtomicRwOrd, AtomicWriteOrd, EvalContextExt as _}, - init_once::{EvalContextExt as _, InitOnceId}, - sync::{CondvarId, EvalContextExt as _, MutexId, RwLockId, SynchronizationObjects}, - thread::{ - BlockReason, EvalContextExt as _, StackEmptyCallback, ThreadId, ThreadManager, - TimeoutAnchor, TimeoutClock, UnblockCallback, - }, +pub use crate::concurrency::cpu_affinity::MAX_CPUS; +pub use crate::concurrency::data_race::{ + AtomicFenceOrd, AtomicReadOrd, AtomicRwOrd, AtomicWriteOrd, EvalContextExt as _, +}; +pub use crate::concurrency::init_once::{EvalContextExt as _, InitOnceId}; +pub use crate::concurrency::sync::{ + CondvarId, EvalContextExt as _, MutexId, RwLockId, SynchronizationObjects, +}; +pub use crate::concurrency::thread::{ + BlockReason, EvalContextExt as _, StackEmptyCallback, ThreadId, ThreadManager, TimeoutAnchor, + TimeoutClock, UnblockCallback, }; pub use crate::diagnostics::{ EvalContextExt as _, NonHaltingDiagnostic, TerminationInfo, report_error, @@ -146,6 +138,7 @@ pub use crate::eval::{ create_ecx, eval_entry, }; pub use crate::helpers::{AccessKind, EvalContextExt as _}; +pub use crate::intrinsics::EvalContextExt as _; pub use crate::machine::{ AllocExtra, FrameExtra, MemoryKind, MiriInterpCx, MiriInterpCxExt, MiriMachine, MiriMemoryKind, PrimitiveLayouts, Provenance, ProvenanceExtra, @@ -154,6 +147,13 @@ pub use crate::mono_hash_map::MonoHashMap; pub use crate::operator::EvalContextExt as _; pub use crate::provenance_gc::{EvalContextExt as _, LiveAllocs, VisitProvenance, VisitWith}; pub use crate::range_map::RangeMap; +pub use crate::shims::EmulateItemResult; +pub use crate::shims::env::{EnvVars, EvalContextExt as _}; +pub use crate::shims::foreign_items::{DynSym, EvalContextExt as _}; +pub use crate::shims::os_str::EvalContextExt as _; +pub use crate::shims::panic::{CatchUnwindData, EvalContextExt as _}; +pub use crate::shims::time::EvalContextExt as _; +pub use crate::shims::tls::TlsData; /// Insert rustc arguments at the beginning of the argument list that Miri wants to be /// set per default, for maximal validation power. diff --git a/src/tools/miri/src/machine.rs b/src/tools/miri/src/machine.rs index b93feeeee3365..fb5ccbcd4fe22 100644 --- a/src/tools/miri/src/machine.rs +++ b/src/tools/miri/src/machine.rs @@ -4,40 +4,29 @@ use std::borrow::Cow; use std::cell::RefCell; use std::collections::hash_map::Entry; -use std::fmt; use std::path::Path; -use std::process; +use std::{fmt, process}; -use rand::Rng; -use rand::SeedableRng; use rand::rngs::StdRng; - +use rand::{Rng, SeedableRng}; use rustc_attr::InlineAttr; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; #[allow(unused)] use rustc_data_structures::static_assert_size; -use rustc_middle::{ - mir, - query::TyCtxtAt, - ty::{ - self, Instance, Ty, TyCtxt, - layout::{HasTyCtxt, LayoutCx, LayoutError, LayoutOf, TyAndLayout}, - }, -}; +use rustc_middle::mir; +use rustc_middle::query::TyCtxtAt; +use rustc_middle::ty::layout::{HasTyCtxt, LayoutCx, LayoutError, LayoutOf, TyAndLayout}; +use rustc_middle::ty::{self, Instance, Ty, TyCtxt}; use rustc_session::config::InliningThreshold; use rustc_span::def_id::{CrateNum, DefId}; use rustc_span::{Span, SpanData, Symbol}; use rustc_target::abi::{Align, Size}; use rustc_target::spec::abi::Abi; -use crate::{ - concurrency::{ - cpu_affinity::{self, CpuAffinityMask}, - data_race::{self, NaReadType, NaWriteType}, - weak_memory, - }, - *, -}; +use crate::concurrency::cpu_affinity::{self, CpuAffinityMask}; +use crate::concurrency::data_race::{self, NaReadType, NaWriteType}; +use crate::concurrency::weak_memory; +use crate::*; /// First real-time signal. /// `signal(7)` says this must be between 32 and 64 and specifies 34 or 35 diff --git a/src/tools/miri/src/operator.rs b/src/tools/miri/src/operator.rs index 1b6a7255eefbe..6b8c0fe87adb3 100644 --- a/src/tools/miri/src/operator.rs +++ b/src/tools/miri/src/operator.rs @@ -1,6 +1,7 @@ use std::iter; -use rand::{Rng, seq::IteratorRandom}; +use rand::Rng; +use rand::seq::IteratorRandom; use rustc_apfloat::{Float, FloatConvert}; use rustc_middle::mir; use rustc_target::abi::Size; diff --git a/src/tools/miri/src/provenance_gc.rs b/src/tools/miri/src/provenance_gc.rs index d4bed69c6707a..c5a35bc14f591 100644 --- a/src/tools/miri/src/provenance_gc.rs +++ b/src/tools/miri/src/provenance_gc.rs @@ -1,5 +1,4 @@ use either::Either; - use rustc_data_structures::fx::FxHashSet; use crate::*; diff --git a/src/tools/miri/src/shims/backtrace.rs b/src/tools/miri/src/shims/backtrace.rs index edff17c0514ce..1d20189b6fd8f 100644 --- a/src/tools/miri/src/shims/backtrace.rs +++ b/src/tools/miri/src/shims/backtrace.rs @@ -1,9 +1,11 @@ -use crate::*; use rustc_ast::ast::Mutability; use rustc_middle::ty::layout::LayoutOf as _; use rustc_middle::ty::{self, Instance, Ty}; use rustc_span::{BytePos, Loc, Symbol, hygiene}; -use rustc_target::{abi::Size, spec::abi::Abi}; +use rustc_target::abi::Size; +use rustc_target::spec::abi::Abi; + +use crate::*; impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {} pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { diff --git a/src/tools/miri/src/shims/env.rs b/src/tools/miri/src/shims/env.rs index c465ef3d28bc8..557d648682c7c 100644 --- a/src/tools/miri/src/shims/env.rs +++ b/src/tools/miri/src/shims/env.rs @@ -2,7 +2,8 @@ use std::ffi::{OsStr, OsString}; use rustc_data_structures::fx::FxHashMap; -use self::shims::{unix::UnixEnvVars, windows::WindowsEnvVars}; +use self::shims::unix::UnixEnvVars; +use self::shims::windows::WindowsEnvVars; use crate::*; #[derive(Default)] diff --git a/src/tools/miri/src/shims/foreign_items.rs b/src/tools/miri/src/shims/foreign_items.rs index c0484dde59b5b..6a835098e6048 100644 --- a/src/tools/miri/src/shims/foreign_items.rs +++ b/src/tools/miri/src/shims/foreign_items.rs @@ -1,16 +1,17 @@ -use std::{collections::hash_map::Entry, io::Write, iter, path::Path}; +use std::collections::hash_map::Entry; +use std::io::Write; +use std::iter; +use std::path::Path; use rustc_apfloat::Float; use rustc_ast::expand::allocator::alloc_error_handler_name; -use rustc_hir::{def::DefKind, def_id::CrateNum}; +use rustc_hir::def::DefKind; +use rustc_hir::def_id::CrateNum; use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; -use rustc_middle::mir; -use rustc_middle::ty; +use rustc_middle::{mir, ty}; use rustc_span::Symbol; -use rustc_target::{ - abi::{Align, AlignFromBytesError, Size}, - spec::abi::Abi, -}; +use rustc_target::abi::{Align, AlignFromBytesError, Size}; +use rustc_target::spec::abi::Abi; use self::helpers::{ToHost, ToSoft}; use super::alloc::EvalContextExt as _; diff --git a/src/tools/miri/src/shims/native_lib.rs b/src/tools/miri/src/shims/native_lib.rs index e4998c37f3fe6..2b5acee244cba 100644 --- a/src/tools/miri/src/shims/native_lib.rs +++ b/src/tools/miri/src/shims/native_lib.rs @@ -1,7 +1,8 @@ //! Implements calling functions from a native library. -use libffi::{high::call as ffi, low::CodePtr}; use std::ops::Deref; +use libffi::high::call as ffi; +use libffi::low::CodePtr; use rustc_middle::ty::{self as ty, IntTy, UintTy}; use rustc_span::Symbol; use rustc_target::abi::{Abi, HasDataLayout}; diff --git a/src/tools/miri/src/shims/os_str.rs b/src/tools/miri/src/shims/os_str.rs index a1be2ae8b588b..17c451059208f 100644 --- a/src/tools/miri/src/shims/os_str.rs +++ b/src/tools/miri/src/shims/os_str.rs @@ -1,11 +1,10 @@ use std::borrow::Cow; use std::ffi::{OsStr, OsString}; -use std::path::{Path, PathBuf}; - #[cfg(unix)] use std::os::unix::ffi::{OsStrExt, OsStringExt}; #[cfg(windows)] use std::os::windows::ffi::{OsStrExt, OsStringExt}; +use std::path::{Path, PathBuf}; use rustc_middle::ty::Ty; use rustc_middle::ty::layout::LayoutOf; diff --git a/src/tools/miri/src/shims/unix/env.rs b/src/tools/miri/src/shims/unix/env.rs index 324607cc1eda3..184a6c238b392 100644 --- a/src/tools/miri/src/shims/unix/env.rs +++ b/src/tools/miri/src/shims/unix/env.rs @@ -1,7 +1,6 @@ -use std::env; use std::ffi::{OsStr, OsString}; use std::io::ErrorKind; -use std::mem; +use std::{env, mem}; use rustc_data_structures::fx::FxHashMap; use rustc_middle::ty::Ty; diff --git a/src/tools/miri/src/shims/unix/fd.rs b/src/tools/miri/src/shims/unix/fd.rs index 5fae746af2b63..6bd753d0d6bee 100644 --- a/src/tools/miri/src/shims/unix/fd.rs +++ b/src/tools/miri/src/shims/unix/fd.rs @@ -5,8 +5,7 @@ use std::any::Any; use std::collections::BTreeMap; use std::io::{self, ErrorKind, IsTerminal, Read, SeekFrom, Write}; use std::ops::Deref; -use std::rc::Rc; -use std::rc::Weak; +use std::rc::{Rc, Weak}; use rustc_target::abi::Size; diff --git a/src/tools/miri/src/shims/unix/foreign_items.rs b/src/tools/miri/src/shims/unix/foreign_items.rs index 470f13442f92d..528d068ea92c0 100644 --- a/src/tools/miri/src/shims/unix/foreign_items.rs +++ b/src/tools/miri/src/shims/unix/foreign_items.rs @@ -6,16 +6,15 @@ use rustc_span::Symbol; use rustc_target::abi::Size; use rustc_target::spec::abi::Abi; -use crate::concurrency::cpu_affinity::CpuAffinityMask; -use crate::shims::alloc::EvalContextExt as _; -use crate::shims::unix::*; -use crate::*; - use self::shims::unix::android::foreign_items as android; use self::shims::unix::freebsd::foreign_items as freebsd; use self::shims::unix::linux::foreign_items as linux; use self::shims::unix::macos::foreign_items as macos; use self::shims::unix::solarish::foreign_items as solarish; +use crate::concurrency::cpu_affinity::CpuAffinityMask; +use crate::shims::alloc::EvalContextExt as _; +use crate::shims::unix::*; +use crate::*; pub fn is_dyn_sym(name: &str, target_os: &str) -> bool { match name { diff --git a/src/tools/miri/src/shims/unix/fs.rs b/src/tools/miri/src/shims/unix/fs.rs index 1b657db5cccc0..92514b67beab1 100644 --- a/src/tools/miri/src/shims/unix/fs.rs +++ b/src/tools/miri/src/shims/unix/fs.rs @@ -11,14 +11,13 @@ use std::time::SystemTime; use rustc_data_structures::fx::FxHashMap; use rustc_target::abi::Size; +use self::fd::FlockOp; use self::shims::time::system_time_to_duration; use crate::shims::os_str::bytes_to_os_str; use crate::shims::unix::fd::FileDescriptionRef; use crate::shims::unix::*; use crate::*; -use self::fd::FlockOp; - #[derive(Debug)] struct FileHandle { file: File, @@ -186,12 +185,14 @@ impl FileDescription for FileHandle { #[cfg(target_family = "windows")] { use std::os::windows::io::AsRawHandle; - use windows_sys::Win32::{ - Foundation::{ERROR_IO_PENDING, ERROR_LOCK_VIOLATION, FALSE, HANDLE, TRUE}, - Storage::FileSystem::{ - LOCKFILE_EXCLUSIVE_LOCK, LOCKFILE_FAIL_IMMEDIATELY, LockFileEx, UnlockFile, - }, + + use windows_sys::Win32::Foundation::{ + ERROR_IO_PENDING, ERROR_LOCK_VIOLATION, FALSE, HANDLE, TRUE, + }; + use windows_sys::Win32::Storage::FileSystem::{ + LOCKFILE_EXCLUSIVE_LOCK, LOCKFILE_FAIL_IMMEDIATELY, LockFileEx, UnlockFile, }; + let fh = self.file.as_raw_handle() as HANDLE; use FlockOp::*; diff --git a/src/tools/miri/src/shims/unix/linux/eventfd.rs b/src/tools/miri/src/shims/unix/linux/eventfd.rs index 9fbabbd964180..ab7652ca721ca 100644 --- a/src/tools/miri/src/shims/unix/linux/eventfd.rs +++ b/src/tools/miri/src/shims/unix/linux/eventfd.rs @@ -3,10 +3,11 @@ use std::cell::{Cell, RefCell}; use std::io; use std::io::{Error, ErrorKind}; +use crate::concurrency::VClock; use crate::shims::unix::fd::FileDescriptionRef; use crate::shims::unix::linux::epoll::{EpollReadyEvents, EvalContextExt as _}; use crate::shims::unix::*; -use crate::{concurrency::VClock, *}; +use crate::*; /// Maximum value that the eventfd counter can hold. const MAX_COUNTER: u64 = u64::MAX - 1; diff --git a/src/tools/miri/src/shims/unix/linux/foreign_items.rs b/src/tools/miri/src/shims/unix/linux/foreign_items.rs index 07527a9d6e332..e2e76aad7cd6e 100644 --- a/src/tools/miri/src/shims/unix/linux/foreign_items.rs +++ b/src/tools/miri/src/shims/unix/linux/foreign_items.rs @@ -5,8 +5,7 @@ use self::shims::unix::linux::epoll::EvalContextExt as _; use self::shims::unix::linux::eventfd::EvalContextExt as _; use self::shims::unix::linux::mem::EvalContextExt as _; use self::shims::unix::linux::sync::futex; -use crate::machine::SIGRTMAX; -use crate::machine::SIGRTMIN; +use crate::machine::{SIGRTMAX, SIGRTMIN}; use crate::shims::unix::*; use crate::*; diff --git a/src/tools/miri/src/shims/unix/linux/mem.rs b/src/tools/miri/src/shims/unix/linux/mem.rs index 3b32612e8baf0..b11f60048a070 100644 --- a/src/tools/miri/src/shims/unix/linux/mem.rs +++ b/src/tools/miri/src/shims/unix/linux/mem.rs @@ -1,9 +1,10 @@ //! This follows the pattern in src/shims/unix/mem.rs: We only support uses of mremap that would //! correspond to valid uses of realloc. -use crate::*; use rustc_target::abi::Size; +use crate::*; + impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {} pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { fn mremap( diff --git a/src/tools/miri/src/shims/unix/mem.rs b/src/tools/miri/src/shims/unix/mem.rs index 33ed0e2698226..0397ba3b91ad9 100644 --- a/src/tools/miri/src/shims/unix/mem.rs +++ b/src/tools/miri/src/shims/unix/mem.rs @@ -14,9 +14,10 @@ //! munmap shim which would partially unmap a region of address space previously mapped by mmap will //! report UB. -use crate::*; use rustc_target::abi::Size; +use crate::*; + impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {} pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { fn mmap( diff --git a/src/tools/miri/src/shims/unix/mod.rs b/src/tools/miri/src/shims/unix/mod.rs index a95b4d3d30793..9bc310e8d0a5d 100644 --- a/src/tools/miri/src/shims/unix/mod.rs +++ b/src/tools/miri/src/shims/unix/mod.rs @@ -14,14 +14,11 @@ mod linux; mod macos; mod solarish; -pub use self::env::UnixEnvVars; -pub use self::fd::{FdTable, FileDescription}; -pub use self::fs::DirTable; -pub use self::linux::epoll::EpollInterestTable; // All the Unix-specific extension traits -pub use self::env::EvalContextExt as _; -pub use self::fd::EvalContextExt as _; -pub use self::fs::EvalContextExt as _; +pub use self::env::{EvalContextExt as _, UnixEnvVars}; +pub use self::fd::{EvalContextExt as _, FdTable, FileDescription}; +pub use self::fs::{DirTable, EvalContextExt as _}; +pub use self::linux::epoll::EpollInterestTable; pub use self::mem::EvalContextExt as _; pub use self::sync::EvalContextExt as _; pub use self::thread::EvalContextExt as _; diff --git a/src/tools/miri/src/shims/unix/thread.rs b/src/tools/miri/src/shims/unix/thread.rs index 56e8270aa62ac..96af4ae51efaa 100644 --- a/src/tools/miri/src/shims/unix/thread.rs +++ b/src/tools/miri/src/shims/unix/thread.rs @@ -1,6 +1,7 @@ -use crate::*; use rustc_target::spec::abi::Abi; +use crate::*; + impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {} pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { fn pthread_create( diff --git a/src/tools/miri/src/shims/unix/unnamed_socket.rs b/src/tools/miri/src/shims/unix/unnamed_socket.rs index db6872319ea48..d1bfa563387dd 100644 --- a/src/tools/miri/src/shims/unix/unnamed_socket.rs +++ b/src/tools/miri/src/shims/unix/unnamed_socket.rs @@ -9,10 +9,11 @@ use std::io::{Error, ErrorKind, Read}; use rustc_target::abi::Size; +use crate::concurrency::VClock; use crate::shims::unix::fd::{FileDescriptionRef, WeakFileDescriptionRef}; use crate::shims::unix::linux::epoll::{EpollReadyEvents, EvalContextExt as _}; use crate::shims::unix::*; -use crate::{concurrency::VClock, *}; +use crate::*; /// The maximum capacity of the socketpair buffer in bytes. /// This number is arbitrary as the value can always diff --git a/src/tools/miri/src/shims/windows/foreign_items.rs b/src/tools/miri/src/shims/windows/foreign_items.rs index cd8f3e59015a3..22634c509bed0 100644 --- a/src/tools/miri/src/shims/windows/foreign_items.rs +++ b/src/tools/miri/src/shims/windows/foreign_items.rs @@ -1,8 +1,6 @@ use std::ffi::OsStr; -use std::io; -use std::iter; use std::path::{self, Path, PathBuf}; -use std::str; +use std::{io, iter, str}; use rustc_span::Symbol; use rustc_target::abi::{Align, Size}; diff --git a/src/tools/miri/src/shims/windows/handle.rs b/src/tools/miri/src/shims/windows/handle.rs index ec461a4cd3681..0a8e0e8fdfb75 100644 --- a/src/tools/miri/src/shims/windows/handle.rs +++ b/src/tools/miri/src/shims/windows/handle.rs @@ -1,6 +1,7 @@ -use rustc_target::abi::HasDataLayout; use std::mem::variant_count; +use rustc_target::abi::HasDataLayout; + use crate::*; #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] diff --git a/src/tools/miri/src/shims/windows/mod.rs b/src/tools/miri/src/shims/windows/mod.rs index 537c724e52665..892bd6924fc93 100644 --- a/src/tools/miri/src/shims/windows/mod.rs +++ b/src/tools/miri/src/shims/windows/mod.rs @@ -5,9 +5,8 @@ mod handle; mod sync; mod thread; -pub use self::env::WindowsEnvVars; // All the Windows-specific extension traits -pub use self::env::EvalContextExt as _; +pub use self::env::{EvalContextExt as _, WindowsEnvVars}; pub use self::handle::EvalContextExt as _; pub use self::sync::EvalContextExt as _; pub use self::thread::EvalContextExt as _; diff --git a/src/tools/miri/src/shims/x86/avx.rs b/src/tools/miri/src/shims/x86/avx.rs index bdc4fc9446915..169f8f8111adb 100644 --- a/src/tools/miri/src/shims/x86/avx.rs +++ b/src/tools/miri/src/shims/x86/avx.rs @@ -1,4 +1,4 @@ -use rustc_apfloat::{ieee::Double, ieee::Single}; +use rustc_apfloat::ieee::{Double, Single}; use rustc_middle::mir; use rustc_middle::ty::Ty; use rustc_middle::ty::layout::LayoutOf as _; diff --git a/src/tools/miri/src/shims/x86/mod.rs b/src/tools/miri/src/shims/x86/mod.rs index 211bd168af28b..8132de7d64697 100644 --- a/src/tools/miri/src/shims/x86/mod.rs +++ b/src/tools/miri/src/shims/x86/mod.rs @@ -1,6 +1,6 @@ use rand::Rng as _; - -use rustc_apfloat::{Float, ieee::Single}; +use rustc_apfloat::Float; +use rustc_apfloat::ieee::Single; use rustc_middle::ty::Ty; use rustc_middle::ty::layout::LayoutOf as _; use rustc_middle::{mir, ty}; diff --git a/src/tools/miri/test-cargo-miri/src/main.rs b/src/tools/miri/test-cargo-miri/src/main.rs index d171ec1c0d1c4..efe95bf3abab7 100644 --- a/src/tools/miri/test-cargo-miri/src/main.rs +++ b/src/tools/miri/test-cargo-miri/src/main.rs @@ -1,9 +1,10 @@ -use byteorder::{BigEndian, ByteOrder}; use std::env; #[cfg(unix)] use std::io::{self, BufRead}; use std::path::PathBuf; +use byteorder::{BigEndian, ByteOrder}; + fn main() { // Check env var set by `build.rs`. assert_eq!(env!("MIRITESTVAR"), "testval"); diff --git a/src/tools/miri/test-cargo-miri/subcrate/test.rs b/src/tools/miri/test-cargo-miri/subcrate/test.rs index b60cf20339b77..e663643f20b42 100644 --- a/src/tools/miri/test-cargo-miri/subcrate/test.rs +++ b/src/tools/miri/test-cargo-miri/subcrate/test.rs @@ -1,5 +1,4 @@ use std::env; - use std::path::PathBuf; use byteorder::{ByteOrder, LittleEndian}; diff --git a/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_join_multiple.rs b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_join_multiple.rs index 6a49625d75d60..b2a398e0a198e 100644 --- a/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_join_multiple.rs +++ b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_join_multiple.rs @@ -2,8 +2,7 @@ // Joining the same thread from multiple threads is undefined behavior. -use std::thread; -use std::{mem, ptr}; +use std::{mem, ptr, thread}; extern "C" fn thread_start(_null: *mut libc::c_void) -> *mut libc::c_void { // Yield the thread several times so that other threads can join it. diff --git a/src/tools/miri/tests/fail-dep/libc/affinity.rs b/src/tools/miri/tests/fail-dep/libc/affinity.rs index d7d5c59e1bc17..09f096e46f1e6 100644 --- a/src/tools/miri/tests/fail-dep/libc/affinity.rs +++ b/src/tools/miri/tests/fail-dep/libc/affinity.rs @@ -3,10 +3,10 @@ //@compile-flags: -Zmiri-disable-isolation -Zmiri-num-cpus=4 fn main() { - use libc::{cpu_set_t, sched_setaffinity}; - use std::mem::size_of; + use libc::{cpu_set_t, sched_setaffinity}; + // If pid is zero, then the calling thread is used. const PID: i32 = 0; diff --git a/src/tools/miri/tests/fail-dep/libc/env-set_var-data-race.rs b/src/tools/miri/tests/fail-dep/libc/env-set_var-data-race.rs index c7d8bacd37950..3a832bb0ce0c1 100644 --- a/src/tools/miri/tests/fail-dep/libc/env-set_var-data-race.rs +++ b/src/tools/miri/tests/fail-dep/libc/env-set_var-data-race.rs @@ -1,8 +1,7 @@ //@compile-flags: -Zmiri-disable-isolation -Zmiri-preemption-rate=0 //@ignore-target: windows # No libc env support on Windows -use std::env; -use std::thread; +use std::{env, thread}; fn main() { let t = thread::spawn(|| unsafe { diff --git a/src/tools/miri/tests/fail/coroutine-pinned-moved.rs b/src/tools/miri/tests/fail/coroutine-pinned-moved.rs index 46ec58810a62d..abed638e44359 100644 --- a/src/tools/miri/tests/fail/coroutine-pinned-moved.rs +++ b/src/tools/miri/tests/fail/coroutine-pinned-moved.rs @@ -1,10 +1,8 @@ //@compile-flags: -Zmiri-disable-validation -Zmiri-disable-stacked-borrows #![feature(coroutines, coroutine_trait, stmt_expr_attributes)] -use std::{ - ops::{Coroutine, CoroutineState}, - pin::Pin, -}; +use std::ops::{Coroutine, CoroutineState}; +use std::pin::Pin; fn firstn() -> impl Coroutine { #[coroutine] diff --git a/src/tools/miri/tests/fail/data_race/atomic_read_na_write_race2.rs b/src/tools/miri/tests/fail/data_race/atomic_read_na_write_race2.rs index 8bceba9380adf..c67ce65eb3404 100644 --- a/src/tools/miri/tests/fail/data_race/atomic_read_na_write_race2.rs +++ b/src/tools/miri/tests/fail/data_race/atomic_read_na_write_race2.rs @@ -3,8 +3,7 @@ // Avoid accidental synchronization via address reuse inside `thread::spawn`. //@compile-flags: -Zmiri-address-reuse-cross-thread-rate=0 -use std::sync::atomic::AtomicUsize; -use std::sync::atomic::Ordering; +use std::sync::atomic::{AtomicUsize, Ordering}; use std::thread::spawn; #[derive(Copy, Clone)] diff --git a/src/tools/miri/tests/fail/data_race/atomic_write_na_read_race1.rs b/src/tools/miri/tests/fail/data_race/atomic_write_na_read_race1.rs index 1a2746a26f4d8..5e328740e8517 100644 --- a/src/tools/miri/tests/fail/data_race/atomic_write_na_read_race1.rs +++ b/src/tools/miri/tests/fail/data_race/atomic_write_na_read_race1.rs @@ -3,8 +3,7 @@ // Avoid accidental synchronization via address reuse inside `thread::spawn`. //@compile-flags: -Zmiri-address-reuse-cross-thread-rate=0 -use std::sync::atomic::AtomicUsize; -use std::sync::atomic::Ordering; +use std::sync::atomic::{AtomicUsize, Ordering}; use std::thread::spawn; #[derive(Copy, Clone)] diff --git a/src/tools/miri/tests/fail/data_race/atomic_write_na_write_race2.rs b/src/tools/miri/tests/fail/data_race/atomic_write_na_write_race2.rs index b494bd3a003d3..fdc0f9e20f079 100644 --- a/src/tools/miri/tests/fail/data_race/atomic_write_na_write_race2.rs +++ b/src/tools/miri/tests/fail/data_race/atomic_write_na_write_race2.rs @@ -3,8 +3,7 @@ // Avoid accidental synchronization via address reuse inside `thread::spawn`. //@compile-flags: -Zmiri-address-reuse-cross-thread-rate=0 -use std::sync::atomic::AtomicUsize; -use std::sync::atomic::Ordering; +use std::sync::atomic::{AtomicUsize, Ordering}; use std::thread::spawn; #[derive(Copy, Clone)] diff --git a/src/tools/miri/tests/fail/tree_borrows/children-can-alias.rs b/src/tools/miri/tests/fail/tree_borrows/children-can-alias.rs index 036267dc11e9d..d3f272dfbf81d 100644 --- a/src/tools/miri/tests/fail/tree_borrows/children-can-alias.rs +++ b/src/tools/miri/tests/fail/tree_borrows/children-can-alias.rs @@ -8,8 +8,7 @@ #![feature(ptr_internals)] -use core::ptr::Unique; -use core::ptr::addr_of_mut; +use core::ptr::{Unique, addr_of_mut}; fn main() { let mut data = 0u8; diff --git a/src/tools/miri/tests/pass-dep/concurrency/linux-futex.rs b/src/tools/miri/tests/pass-dep/concurrency/linux-futex.rs index 255a93226a958..20e642a0a2952 100644 --- a/src/tools/miri/tests/pass-dep/concurrency/linux-futex.rs +++ b/src/tools/miri/tests/pass-dep/concurrency/linux-futex.rs @@ -6,8 +6,7 @@ use std::mem::MaybeUninit; use std::ptr::{self, addr_of}; -use std::sync::atomic::AtomicI32; -use std::sync::atomic::Ordering; +use std::sync::atomic::{AtomicI32, Ordering}; use std::thread; use std::time::{Duration, Instant}; diff --git a/src/tools/miri/tests/pass-dep/concurrency/tls_pthread_drop_order.rs b/src/tools/miri/tests/pass-dep/concurrency/tls_pthread_drop_order.rs index 2dc09709b8eed..b57386000404f 100644 --- a/src/tools/miri/tests/pass-dep/concurrency/tls_pthread_drop_order.rs +++ b/src/tools/miri/tests/pass-dep/concurrency/tls_pthread_drop_order.rs @@ -8,8 +8,7 @@ // FIXME(static_mut_refs): Do not allow `static_mut_refs` lint #![allow(static_mut_refs)] -use std::mem; -use std::ptr; +use std::{mem, ptr}; pub type Key = libc::pthread_key_t; diff --git a/src/tools/miri/tests/pass-dep/libc/gettid.rs b/src/tools/miri/tests/pass-dep/libc/gettid.rs index ca352e0109a47..51f1a5ed70898 100644 --- a/src/tools/miri/tests/pass-dep/libc/gettid.rs +++ b/src/tools/miri/tests/pass-dep/libc/gettid.rs @@ -2,9 +2,10 @@ //@revisions: with_isolation without_isolation //@[without_isolation] compile-flags: -Zmiri-disable-isolation -use libc::{getpid, gettid}; use std::thread; +use libc::{getpid, gettid}; + fn main() { thread::spawn(|| { // Test that in isolation mode a deterministic value will be returned. diff --git a/src/tools/miri/tests/pass-dep/libc/libc-affinity.rs b/src/tools/miri/tests/pass-dep/libc/libc-affinity.rs index ff152eaea5c50..8aa8c7dcb8e6a 100644 --- a/src/tools/miri/tests/pass-dep/libc/libc-affinity.rs +++ b/src/tools/miri/tests/pass-dep/libc/libc-affinity.rs @@ -5,9 +5,10 @@ #![feature(pointer_is_aligned_to)] #![feature(strict_provenance)] -use libc::{cpu_set_t, sched_getaffinity, sched_setaffinity}; use std::mem::{size_of, size_of_val}; +use libc::{cpu_set_t, sched_getaffinity, sched_setaffinity}; + // If pid is zero, then the calling thread is used. const PID: i32 = 0; diff --git a/src/tools/miri/tests/pass-dep/libc/libc-fs-flock.rs b/src/tools/miri/tests/pass-dep/libc/libc-fs-flock.rs index be11f65a1e081..99d6d2b38f8de 100644 --- a/src/tools/miri/tests/pass-dep/libc/libc-fs-flock.rs +++ b/src/tools/miri/tests/pass-dep/libc/libc-fs-flock.rs @@ -1,7 +1,9 @@ //@ignore-target: windows # File handling is not implemented yet //@compile-flags: -Zmiri-disable-isolation -use std::{fs::File, io::Error, os::fd::AsRawFd}; +use std::fs::File; +use std::io::Error; +use std::os::fd::AsRawFd; #[path = "../../utils/mod.rs"] mod utils; diff --git a/src/tools/miri/tests/pass-dep/libc/libc-fs.rs b/src/tools/miri/tests/pass-dep/libc/libc-fs.rs index 17e6e507c2750..f85abe2cc4377 100644 --- a/src/tools/miri/tests/pass-dep/libc/libc-fs.rs +++ b/src/tools/miri/tests/pass-dep/libc/libc-fs.rs @@ -230,8 +230,7 @@ fn test_posix_mkstemp() { /// Test allocating variant of `realpath`. fn test_posix_realpath_alloc() { - use std::os::unix::ffi::OsStrExt; - use std::os::unix::ffi::OsStringExt; + use std::os::unix::ffi::{OsStrExt, OsStringExt}; let buf; let path = utils::tmp().join("miri_test_libc_posix_realpath_alloc"); diff --git a/src/tools/miri/tests/pass-dep/tokio/file-io.rs b/src/tools/miri/tests/pass-dep/tokio/file-io.rs index 14c27285a6ae5..6e88b907f5dc8 100644 --- a/src/tools/miri/tests/pass-dep/tokio/file-io.rs +++ b/src/tools/miri/tests/pass-dep/tokio/file-io.rs @@ -2,6 +2,7 @@ //@only-target: linux # We only support tokio on Linux use std::fs::remove_file; + use tokio::fs::{File, OpenOptions}; use tokio::io::{self, AsyncReadExt, AsyncWriteExt}; diff --git a/src/tools/miri/tests/pass/async-niche-aliasing.rs b/src/tools/miri/tests/pass/async-niche-aliasing.rs index ab82c929a94c2..fe4ddd9d80088 100644 --- a/src/tools/miri/tests/pass/async-niche-aliasing.rs +++ b/src/tools/miri/tests/pass/async-niche-aliasing.rs @@ -1,13 +1,11 @@ //@revisions: stack tree //@[tree]compile-flags: -Zmiri-tree-borrows -use std::{ - future::Future, - mem::MaybeUninit, - pin::Pin, - sync::Arc, - task::{Context, Poll, Wake}, -}; +use std::future::Future; +use std::mem::MaybeUninit; +use std::pin::Pin; +use std::sync::Arc; +use std::task::{Context, Poll, Wake}; struct ThingAdder<'a> { // Using `MaybeUninit` to ensure there are no niches here. diff --git a/src/tools/miri/tests/pass/atomic-compare-exchange-weak-never-fail.rs b/src/tools/miri/tests/pass/atomic-compare-exchange-weak-never-fail.rs index 8d3d71869f42e..0a236377a9c61 100644 --- a/src/tools/miri/tests/pass/atomic-compare-exchange-weak-never-fail.rs +++ b/src/tools/miri/tests/pass/atomic-compare-exchange-weak-never-fail.rs @@ -1,5 +1,6 @@ //@compile-flags: -Zmiri-compare-exchange-weak-failure-rate=0.0 -use std::sync::atomic::{AtomicBool, Ordering::*}; +use std::sync::atomic::AtomicBool; +use std::sync::atomic::Ordering::*; // Ensure that compare_exchange_weak never fails. fn main() { diff --git a/src/tools/miri/tests/pass/atomic.rs b/src/tools/miri/tests/pass/atomic.rs index 781cc9bd30942..f84fe825d0106 100644 --- a/src/tools/miri/tests/pass/atomic.rs +++ b/src/tools/miri/tests/pass/atomic.rs @@ -6,9 +6,8 @@ // FIXME(static_mut_refs): Do not allow `static_mut_refs` lint #![allow(static_mut_refs)] -use std::sync::atomic::{ - AtomicBool, AtomicIsize, AtomicPtr, AtomicU64, Ordering::*, compiler_fence, fence, -}; +use std::sync::atomic::Ordering::*; +use std::sync::atomic::{AtomicBool, AtomicIsize, AtomicPtr, AtomicU64, compiler_fence, fence}; fn main() { atomic_bool(); diff --git a/src/tools/miri/tests/pass/box-custom-alloc-aliasing.rs b/src/tools/miri/tests/pass/box-custom-alloc-aliasing.rs index a1371242f60d9..0a61db960c1d4 100644 --- a/src/tools/miri/tests/pass/box-custom-alloc-aliasing.rs +++ b/src/tools/miri/tests/pass/box-custom-alloc-aliasing.rs @@ -7,13 +7,11 @@ #![feature(allocator_api)] #![feature(strict_provenance)] -use std::{ - alloc::{AllocError, Allocator, Layout}, - cell::{Cell, UnsafeCell}, - mem, - ptr::{self, NonNull, addr_of}, - thread::{self, ThreadId}, -}; +use std::alloc::{AllocError, Allocator, Layout}; +use std::cell::{Cell, UnsafeCell}; +use std::mem; +use std::ptr::{self, NonNull, addr_of}; +use std::thread::{self, ThreadId}; const BIN_SIZE: usize = 8; diff --git a/src/tools/miri/tests/pass/box-custom-alloc.rs b/src/tools/miri/tests/pass/box-custom-alloc.rs index 8d6da0733fe17..71ce019187c44 100644 --- a/src/tools/miri/tests/pass/box-custom-alloc.rs +++ b/src/tools/miri/tests/pass/box-custom-alloc.rs @@ -3,8 +3,7 @@ #![allow(incomplete_features)] // for trait upcasting #![feature(allocator_api, trait_upcasting)] -use std::alloc::Layout; -use std::alloc::{AllocError, Allocator}; +use std::alloc::{AllocError, Allocator, Layout}; use std::cell::Cell; use std::mem::MaybeUninit; use std::ptr::{self, NonNull}; diff --git a/src/tools/miri/tests/pass/concurrency/address_reuse_happens_before.rs b/src/tools/miri/tests/pass/concurrency/address_reuse_happens_before.rs index cfc1ef7ae455a..255f4061abce7 100644 --- a/src/tools/miri/tests/pass/concurrency/address_reuse_happens_before.rs +++ b/src/tools/miri/tests/pass/concurrency/address_reuse_happens_before.rs @@ -5,7 +5,8 @@ #![feature(sync_unsafe_cell)] use std::cell::SyncUnsafeCell; -use std::sync::atomic::{AtomicUsize, Ordering::Relaxed}; +use std::sync::atomic::AtomicUsize; +use std::sync::atomic::Ordering::Relaxed; use std::thread; static ADDR: AtomicUsize = AtomicUsize::new(0); diff --git a/src/tools/miri/tests/pass/concurrency/sync_singlethread.rs b/src/tools/miri/tests/pass/concurrency/sync_singlethread.rs index 5663e1c1426c9..e52dbd3186e1e 100644 --- a/src/tools/miri/tests/pass/concurrency/sync_singlethread.rs +++ b/src/tools/miri/tests/pass/concurrency/sync_singlethread.rs @@ -1,6 +1,5 @@ use std::hint; -use std::sync::atomic; -use std::sync::{Mutex, TryLockError}; +use std::sync::{Mutex, TryLockError, atomic}; fn main() { test_mutex_stdlib(); diff --git a/src/tools/miri/tests/pass/coroutine.rs b/src/tools/miri/tests/pass/coroutine.rs index 7822c136d91b6..9ec9b1fc5bc48 100644 --- a/src/tools/miri/tests/pass/coroutine.rs +++ b/src/tools/miri/tests/pass/coroutine.rs @@ -4,10 +4,8 @@ use std::fmt::Debug; use std::mem::ManuallyDrop; -use std::ops::{ - Coroutine, - CoroutineState::{self, *}, -}; +use std::ops::Coroutine; +use std::ops::CoroutineState::{self, *}; use std::pin::Pin; use std::ptr; use std::sync::atomic::{AtomicUsize, Ordering}; diff --git a/src/tools/miri/tests/pass/dyn-arbitrary-self.rs b/src/tools/miri/tests/pass/dyn-arbitrary-self.rs index dc2b9e4491b27..d993e5ad68ccc 100644 --- a/src/tools/miri/tests/pass/dyn-arbitrary-self.rs +++ b/src/tools/miri/tests/pass/dyn-arbitrary-self.rs @@ -21,7 +21,9 @@ fn pin_box_dyn() { } fn stdlib_pointers() { - use std::{pin::Pin, rc::Rc, sync::Arc}; + use std::pin::Pin; + use std::rc::Rc; + use std::sync::Arc; trait Trait { fn by_rc(self: Rc) -> i64; @@ -60,10 +62,8 @@ fn stdlib_pointers() { } fn pointers_and_wrappers() { - use std::{ - marker::Unsize, - ops::{CoerceUnsized, Deref, DispatchFromDyn}, - }; + use std::marker::Unsize; + use std::ops::{CoerceUnsized, Deref, DispatchFromDyn}; struct Ptr(Box); diff --git a/src/tools/miri/tests/pass/function_calls/abi_compat.rs b/src/tools/miri/tests/pass/function_calls/abi_compat.rs index 0cfcd532ff4b2..b5feac8c67726 100644 --- a/src/tools/miri/tests/pass/function_calls/abi_compat.rs +++ b/src/tools/miri/tests/pass/function_calls/abi_compat.rs @@ -1,7 +1,5 @@ -use std::mem; -use std::num; -use std::ptr; use std::rc::Rc; +use std::{mem, num, ptr}; #[derive(Copy, Clone, Default)] struct Zst; diff --git a/src/tools/miri/tests/pass/intrinsics/portable-simd.rs b/src/tools/miri/tests/pass/intrinsics/portable-simd.rs index cd606a5282a98..f560669dd6351 100644 --- a/src/tools/miri/tests/pass/intrinsics/portable-simd.rs +++ b/src/tools/miri/tests/pass/intrinsics/portable-simd.rs @@ -11,7 +11,8 @@ #![allow(incomplete_features, internal_features)] use std::intrinsics::simd as intrinsics; use std::ptr; -use std::simd::{StdFloat, prelude::*}; +use std::simd::StdFloat; +use std::simd::prelude::*; extern "rust-intrinsic" { #[rustc_nounwind] diff --git a/src/tools/miri/tests/pass/issues/issue-miri-3541-dyn-vtable-trait-normalization.rs b/src/tools/miri/tests/pass/issues/issue-miri-3541-dyn-vtable-trait-normalization.rs index c46031de2d84f..123fe6ed6425c 100644 --- a/src/tools/miri/tests/pass/issues/issue-miri-3541-dyn-vtable-trait-normalization.rs +++ b/src/tools/miri/tests/pass/issues/issue-miri-3541-dyn-vtable-trait-normalization.rs @@ -2,7 +2,8 @@ // This test is the result of minimizing the `emplacable` crate to reproduce // . -use std::{ops::FnMut, ptr::Pointee}; +use std::ops::FnMut; +use std::ptr::Pointee; pub type EmplacerFn<'a, T> = dyn for<'b> FnMut(::Metadata) + 'a; diff --git a/src/tools/miri/tests/pass/leak-in-static.rs b/src/tools/miri/tests/pass/leak-in-static.rs index 9523394408806..6f08b64ada45f 100644 --- a/src/tools/miri/tests/pass/leak-in-static.rs +++ b/src/tools/miri/tests/pass/leak-in-static.rs @@ -1,7 +1,5 @@ -use std::{ - ptr, - sync::atomic::{AtomicPtr, Ordering}, -}; +use std::ptr; +use std::sync::atomic::{AtomicPtr, Ordering}; static mut LEAKER: Option>> = None; diff --git a/src/tools/miri/tests/pass/ptr_int_casts.rs b/src/tools/miri/tests/pass/ptr_int_casts.rs index 684e8f6ec7bdd..4e274f62981d1 100644 --- a/src/tools/miri/tests/pass/ptr_int_casts.rs +++ b/src/tools/miri/tests/pass/ptr_int_casts.rs @@ -2,8 +2,7 @@ // Tree Borrows doesn't support int2ptr casts, but let's make sure we don't immediately crash either. //@[tree]compile-flags: -Zmiri-tree-borrows //@[stack]compile-flags: -Zmiri-permissive-provenance -use std::mem; -use std::ptr; +use std::{mem, ptr}; fn eq_ref(x: &T, y: &T) -> bool { x as *const _ == y as *const _ diff --git a/src/tools/miri/tests/pass/shims/env/var.rs b/src/tools/miri/tests/pass/shims/env/var.rs index a576c1fc8bb8c..655b29674e340 100644 --- a/src/tools/miri/tests/pass/shims/env/var.rs +++ b/src/tools/miri/tests/pass/shims/env/var.rs @@ -1,6 +1,5 @@ //@compile-flags: -Zmiri-preemption-rate=0 -use std::env; -use std::thread; +use std::{env, thread}; fn main() { // Test that miri environment is isolated when communication is disabled. diff --git a/src/tools/miri/tests/pass/shims/windows-threadname.rs b/src/tools/miri/tests/pass/shims/windows-threadname.rs index 29c3fa5d5f3aa..f1c05fa37905b 100644 --- a/src/tools/miri/tests/pass/shims/windows-threadname.rs +++ b/src/tools/miri/tests/pass/shims/windows-threadname.rs @@ -1,9 +1,8 @@ //@only-target: windows # this directly tests windows-only functions +use core::ffi::c_void; use std::ffi::OsStr; use std::os::windows::ffi::OsStrExt; - -use core::ffi::c_void; type HANDLE = *mut c_void; type PWSTR = *mut u16; type PCWSTR = *const u16; diff --git a/src/tools/miri/tests/pass/slices.rs b/src/tools/miri/tests/pass/slices.rs index 459d04d6761c1..39e1d1cb97f26 100644 --- a/src/tools/miri/tests/pass/slices.rs +++ b/src/tools/miri/tests/pass/slices.rs @@ -6,8 +6,7 @@ #![feature(layout_for_ptr)] #![feature(strict_provenance)] -use std::ptr; -use std::slice; +use std::{ptr, slice}; fn slice_of_zst() { fn foo(v: &[T]) -> Option<&[T]> { diff --git a/src/tools/miri/tests/pass/stacked-borrows/coroutine-self-referential.rs b/src/tools/miri/tests/pass/stacked-borrows/coroutine-self-referential.rs index 259fc72d3929e..72e360fe19a1f 100644 --- a/src/tools/miri/tests/pass/stacked-borrows/coroutine-self-referential.rs +++ b/src/tools/miri/tests/pass/stacked-borrows/coroutine-self-referential.rs @@ -2,10 +2,8 @@ // this fails when Stacked Borrows is strictly applied even to `!Unpin` types. #![feature(coroutines, coroutine_trait, stmt_expr_attributes)] -use std::{ - ops::{Coroutine, CoroutineState}, - pin::Pin, -}; +use std::ops::{Coroutine, CoroutineState}; +use std::pin::Pin; fn firstn() -> impl Coroutine { #[coroutine] diff --git a/src/tools/miri/tests/pass/stacked-borrows/stack-printing.rs b/src/tools/miri/tests/pass/stacked-borrows/stack-printing.rs index 9c9db4d1b3b53..1478b21d6c180 100644 --- a/src/tools/miri/tests/pass/stacked-borrows/stack-printing.rs +++ b/src/tools/miri/tests/pass/stacked-borrows/stack-printing.rs @@ -3,10 +3,8 @@ //@compile-flags: -Zmiri-permissive-provenance -Zmiri-provenance-gc=0 #![feature(strict_provenance)] -use std::{ - alloc::{self, Layout}, - mem::ManuallyDrop, -}; +use std::alloc::{self, Layout}; +use std::mem::ManuallyDrop; extern "Rust" { fn miri_get_alloc_id(ptr: *const u8) -> u64; diff --git a/src/tools/miri/tests/pass/tree_borrows/tree-borrows.rs b/src/tools/miri/tests/pass/tree_borrows/tree-borrows.rs index c741e4de6d5b1..b9d5ca06ed058 100644 --- a/src/tools/miri/tests/pass/tree_borrows/tree-borrows.rs +++ b/src/tools/miri/tests/pass/tree_borrows/tree-borrows.rs @@ -3,8 +3,7 @@ //@[uniq]compile-flags: -Zmiri-unique-is-unique #![feature(allocator_api)] -use std::mem; -use std::ptr; +use std::{mem, ptr}; fn main() { aliasing_read_only_mutable_refs(); diff --git a/src/tools/miri/tests/ui.rs b/src/tools/miri/tests/ui.rs index 2430140eea1d4..9553a37c9a82f 100644 --- a/src/tools/miri/tests/ui.rs +++ b/src/tools/miri/tests/ui.rs @@ -1,8 +1,9 @@ +use std::env; use std::ffi::OsString; use std::num::NonZero; use std::path::{Path, PathBuf}; +use std::process::Command; use std::sync::OnceLock; -use std::{env, process::Command}; use colored::*; use regex::bytes::Regex; From 762a91b40e9f37f1b649f3a879e4639af32da2ed Mon Sep 17 00:00:00 2001 From: Asuna Date: Tue, 24 Sep 2024 01:28:02 +0800 Subject: [PATCH 1708/2194] Simplify negative `Option::{is_some_and,is_none_or}` --- clippy_config/src/msrvs.rs | 1 + clippy_lints/src/booleans.rs | 78 ++++++++++--- clippy_lints/src/lib.rs | 2 +- tests/ui/nonminimal_bool_methods.fixed | 62 ++++++++++ tests/ui/nonminimal_bool_methods.rs | 62 ++++++++++ tests/ui/nonminimal_bool_methods.stderr | 110 +++++++++++++++++- tests/ui/nonminimal_bool_methods_unfixable.rs | 9 ++ .../nonminimal_bool_methods_unfixable.stderr | 17 +++ 8 files changed, 321 insertions(+), 20 deletions(-) create mode 100644 tests/ui/nonminimal_bool_methods_unfixable.rs create mode 100644 tests/ui/nonminimal_bool_methods_unfixable.stderr diff --git a/clippy_config/src/msrvs.rs b/clippy_config/src/msrvs.rs index e30df3d32341a..68a3b11d3848f 100644 --- a/clippy_config/src/msrvs.rs +++ b/clippy_config/src/msrvs.rs @@ -19,6 +19,7 @@ macro_rules! msrv_aliases { msrv_aliases! { 1,83,0 { CONST_EXTERN_FN } 1,83,0 { CONST_FLOAT_BITS_CONV } + 1,82,0 { IS_NONE_OR } 1,81,0 { LINT_REASONS_STABILIZATION } 1,80,0 { BOX_INTO_ITER} 1,77,0 { C_STR_LITERALS } diff --git a/clippy_lints/src/booleans.rs b/clippy_lints/src/booleans.rs index 3c2af72624f60..160f0c6cf100e 100644 --- a/clippy_lints/src/booleans.rs +++ b/clippy_lints/src/booleans.rs @@ -1,3 +1,5 @@ +use clippy_config::Conf; +use clippy_config::msrvs::{self, Msrv}; use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_hir_and_then}; use clippy_utils::eq_expr_value; use clippy_utils::source::SpanRangeExt; @@ -7,7 +9,7 @@ use rustc_errors::Applicability; use rustc_hir::intravisit::{FnKind, Visitor, walk_expr}; use rustc_hir::{BinOpKind, Body, Expr, ExprKind, FnDecl, UnOp}; use rustc_lint::{LateContext, LateLintPass, Level}; -use rustc_session::declare_lint_pass; +use rustc_session::{RustcVersion, impl_lint_pass}; use rustc_span::def_id::LocalDefId; use rustc_span::{Span, sym}; @@ -69,9 +71,25 @@ declare_clippy_lint! { } // For each pairs, both orders are considered. -const METHODS_WITH_NEGATION: [(&str, &str); 2] = [("is_some", "is_none"), ("is_err", "is_ok")]; +const METHODS_WITH_NEGATION: [(Option, &str, &str); 3] = [ + (None, "is_some", "is_none"), + (None, "is_err", "is_ok"), + (Some(msrvs::IS_NONE_OR), "is_some_and", "is_none_or"), +]; + +pub struct NonminimalBool { + msrv: Msrv, +} + +impl NonminimalBool { + pub fn new(conf: &'static Conf) -> Self { + Self { + msrv: conf.msrv.clone(), + } + } +} -declare_lint_pass!(NonminimalBool => [NONMINIMAL_BOOL, OVERLY_COMPLEX_BOOL_EXPR]); +impl_lint_pass!(NonminimalBool => [NONMINIMAL_BOOL, OVERLY_COMPLEX_BOOL_EXPR]); impl<'tcx> LateLintPass<'tcx> for NonminimalBool { fn check_fn( @@ -83,7 +101,7 @@ impl<'tcx> LateLintPass<'tcx> for NonminimalBool { _: Span, _: LocalDefId, ) { - NonminimalBoolVisitor { cx }.visit_body(body); + NonminimalBoolVisitor { cx, msrv: &self.msrv }.visit_body(body); } fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) { @@ -100,6 +118,8 @@ impl<'tcx> LateLintPass<'tcx> for NonminimalBool { _ => {}, } } + + extract_msrv_attr!(LateContext); } fn inverted_bin_op_eq_str(op: BinOpKind) -> Option<&'static str> { @@ -176,11 +196,11 @@ fn check_inverted_bool_in_condition( ); } -fn check_simplify_not(cx: &LateContext<'_>, expr: &Expr<'_>) { +fn check_simplify_not(cx: &LateContext<'_>, msrv: &Msrv, expr: &Expr<'_>) { if let ExprKind::Unary(UnOp::Not, inner) = &expr.kind && !expr.span.from_expansion() && !inner.span.from_expansion() - && let Some(suggestion) = simplify_not(cx, inner) + && let Some(suggestion) = simplify_not(cx, msrv, inner) && cx.tcx.lint_level_at_node(NONMINIMAL_BOOL, expr.hir_id).0 != Level::Allow { span_lint_and_sugg( @@ -197,6 +217,7 @@ fn check_simplify_not(cx: &LateContext<'_>, expr: &Expr<'_>) { struct NonminimalBoolVisitor<'a, 'tcx> { cx: &'a LateContext<'tcx>, + msrv: &'a Msrv, } use quine_mc_cluskey::Bool; @@ -289,6 +310,7 @@ impl<'a, 'tcx, 'v> Hir2Qmm<'a, 'tcx, 'v> { struct SuggestContext<'a, 'tcx, 'v> { terminals: &'v [&'v Expr<'v>], cx: &'a LateContext<'tcx>, + msrv: &'a Msrv, output: String, } @@ -311,7 +333,7 @@ impl<'a, 'tcx, 'v> SuggestContext<'a, 'tcx, 'v> { }, Term(n) => { let terminal = self.terminals[n as usize]; - if let Some(str) = simplify_not(self.cx, terminal) { + if let Some(str) = simplify_not(self.cx, self.msrv, terminal) { self.output.push_str(&str); } else { self.output.push('!'); @@ -358,7 +380,7 @@ impl<'a, 'tcx, 'v> SuggestContext<'a, 'tcx, 'v> { } } -fn simplify_not(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option { +fn simplify_not(cx: &LateContext<'_>, curr_msrv: &Msrv, expr: &Expr<'_>) -> Option { match &expr.kind { ExprKind::Binary(binop, lhs, rhs) => { if !implements_ord(cx, lhs) { @@ -389,7 +411,7 @@ fn simplify_not(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option { Some(format!("{lhs_snippet}{op}{rhs_snippet}")) }) }, - ExprKind::MethodCall(path, receiver, [], _) => { + ExprKind::MethodCall(path, receiver, args, _) => { let type_of_receiver = cx.typeck_results().expr_ty(receiver); if !is_type_diagnostic_item(cx, type_of_receiver, sym::Option) && !is_type_diagnostic_item(cx, type_of_receiver, sym::Result) @@ -399,21 +421,41 @@ fn simplify_not(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option { METHODS_WITH_NEGATION .iter() .copied() - .flat_map(|(a, b)| vec![(a, b), (b, a)]) - .find(|&(a, _)| { - let path: &str = path.ident.name.as_str(); - a == path + .flat_map(|(msrv, a, b)| vec![(msrv, a, b), (msrv, b, a)]) + .find(|&(msrv, a, _)| msrv.is_none_or(|msrv| curr_msrv.meets(msrv)) && a == path.ident.name.as_str()) + .and_then(|(_, _, neg_method)| { + let negated_args = args + .iter() + .map(|arg| simplify_not(cx, curr_msrv, arg)) + .collect::>>()? + .join(", "); + Some(format!( + "{}.{neg_method}({negated_args})", + receiver.span.get_source_text(cx)? + )) }) - .and_then(|(_, neg_method)| Some(format!("{}.{neg_method}()", receiver.span.get_source_text(cx)?))) }, + ExprKind::Closure(closure) => { + let body = cx.tcx.hir().body(closure.body); + let params = body + .params + .iter() + .map(|param| param.span.get_source_text(cx).map(|t| t.to_string())) + .collect::>>()? + .join(", "); + let negated = simplify_not(cx, curr_msrv, body.value)?; + Some(format!("|{params}| {negated}")) + }, + ExprKind::Unary(UnOp::Not, expr) => expr.span.get_source_text(cx).map(|t| t.to_string()), _ => None, } } -fn suggest(cx: &LateContext<'_>, suggestion: &Bool, terminals: &[&Expr<'_>]) -> String { +fn suggest(cx: &LateContext<'_>, msrv: &Msrv, suggestion: &Bool, terminals: &[&Expr<'_>]) -> String { let mut suggest_context = SuggestContext { terminals, cx, + msrv, output: String::new(), }; suggest_context.recurse(suggestion); @@ -526,7 +568,7 @@ impl<'a, 'tcx> NonminimalBoolVisitor<'a, 'tcx> { diag.span_suggestion( e.span, "it would look like the following", - suggest(self.cx, suggestion, &h2q.terminals), + suggest(self.cx, self.msrv, suggestion, &h2q.terminals), // nonminimal_bool can produce minimal but // not human readable expressions (#3141) Applicability::Unspecified, @@ -569,12 +611,12 @@ impl<'a, 'tcx> NonminimalBoolVisitor<'a, 'tcx> { } }; if improvements.is_empty() { - check_simplify_not(self.cx, e); + check_simplify_not(self.cx, self.msrv, e); } else { nonminimal_bool_lint( improvements .into_iter() - .map(|suggestion| suggest(self.cx, suggestion, &h2q.terminals)) + .map(|suggestion| suggest(self.cx, self.msrv, suggestion, &h2q.terminals)) .collect(), ); } diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 1d41f568f3785..2eb6d99b761f7 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -609,7 +609,7 @@ pub fn register_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) { store.register_late_pass(move |tcx| Box::new(await_holding_invalid::AwaitHolding::new(tcx, conf))); store.register_late_pass(|_| Box::new(serde_api::SerdeApi)); store.register_late_pass(move |_| Box::new(types::Types::new(conf))); - store.register_late_pass(|_| Box::new(booleans::NonminimalBool)); + store.register_late_pass(move |_| Box::new(booleans::NonminimalBool::new(conf))); store.register_late_pass(|_| Box::new(enum_clike::UnportableVariant)); store.register_late_pass(|_| Box::new(float_literal::FloatLiteral)); store.register_late_pass(|_| Box::new(ptr::Ptr)); diff --git a/tests/ui/nonminimal_bool_methods.fixed b/tests/ui/nonminimal_bool_methods.fixed index cc91ba6ec66e1..a23310c1ad9fd 100644 --- a/tests/ui/nonminimal_bool_methods.fixed +++ b/tests/ui/nonminimal_bool_methods.fixed @@ -115,4 +115,66 @@ fn issue_12625() { if a as u64 > b {} //~ ERROR: this boolean expression can be simplified } +fn issue_13436() { + fn not_zero(x: i32) -> bool { + x != 0 + } + + let opt = Some(500); + _ = opt.is_some_and(|x| x < 1000); + _ = opt.is_some_and(|x| x <= 1000); + _ = opt.is_some_and(|x| x > 1000); + _ = opt.is_some_and(|x| x >= 1000); + _ = opt.is_some_and(|x| x == 1000); + _ = opt.is_some_and(|x| x != 1000); + _ = opt.is_some_and(not_zero); + _ = opt.is_none_or(|x| x >= 1000); //~ ERROR: this boolean expression can be simplified + _ = opt.is_none_or(|x| x > 1000); //~ ERROR: this boolean expression can be simplified + _ = opt.is_none_or(|x| x <= 1000); //~ ERROR: this boolean expression can be simplified + _ = opt.is_none_or(|x| x < 1000); //~ ERROR: this boolean expression can be simplified + _ = opt.is_none_or(|x| x != 1000); //~ ERROR: this boolean expression can be simplified + _ = opt.is_none_or(|x| x == 1000); //~ ERROR: this boolean expression can be simplified + _ = !opt.is_some_and(not_zero); + _ = opt.is_none_or(|x| x < 1000); + _ = opt.is_none_or(|x| x <= 1000); + _ = opt.is_none_or(|x| x > 1000); + _ = opt.is_none_or(|x| x >= 1000); + _ = opt.is_none_or(|x| x == 1000); + _ = opt.is_none_or(|x| x != 1000); + _ = opt.is_none_or(not_zero); + _ = opt.is_some_and(|x| x >= 1000); //~ ERROR: this boolean expression can be simplified + _ = opt.is_some_and(|x| x > 1000); //~ ERROR: this boolean expression can be simplified + _ = opt.is_some_and(|x| x <= 1000); //~ ERROR: this boolean expression can be simplified + _ = opt.is_some_and(|x| x < 1000); //~ ERROR: this boolean expression can be simplified + _ = opt.is_some_and(|x| x != 1000); //~ ERROR: this boolean expression can be simplified + _ = opt.is_some_and(|x| x == 1000); //~ ERROR: this boolean expression can be simplified + _ = !opt.is_none_or(not_zero); + + let opt = Some(true); + _ = opt.is_some_and(|x| x); + _ = opt.is_some_and(|x| !x); + _ = !opt.is_some_and(|x| x); + _ = opt.is_none_or(|x| x); //~ ERROR: this boolean expression can be simplified + _ = opt.is_none_or(|x| x); + _ = opt.is_none_or(|x| !x); + _ = !opt.is_none_or(|x| x); + _ = opt.is_some_and(|x| x); //~ ERROR: this boolean expression can be simplified + + let opt: Option> = Some(Ok(123)); + _ = opt.is_some_and(|x| x.is_ok()); + _ = opt.is_some_and(|x| x.is_err()); + _ = opt.is_none_or(|x| x.is_ok()); + _ = opt.is_none_or(|x| x.is_err()); + _ = opt.is_none_or(|x| x.is_err()); //~ ERROR: this boolean expression can be simplified + _ = opt.is_none_or(|x| x.is_ok()); //~ ERROR: this boolean expression can be simplified + _ = opt.is_some_and(|x| x.is_err()); //~ ERROR: this boolean expression can be simplified + _ = opt.is_some_and(|x| x.is_ok()); //~ ERROR: this boolean expression can be simplified + + #[clippy::msrv = "1.81"] + fn before_stabilization() { + let opt = Some(500); + _ = !opt.is_some_and(|x| x < 1000); + } +} + fn main() {} diff --git a/tests/ui/nonminimal_bool_methods.rs b/tests/ui/nonminimal_bool_methods.rs index c812f6f0ca4f5..6c844373af709 100644 --- a/tests/ui/nonminimal_bool_methods.rs +++ b/tests/ui/nonminimal_bool_methods.rs @@ -115,4 +115,66 @@ fn issue_12625() { if !(a as u64 <= b) {} //~ ERROR: this boolean expression can be simplified } +fn issue_13436() { + fn not_zero(x: i32) -> bool { + x != 0 + } + + let opt = Some(500); + _ = opt.is_some_and(|x| x < 1000); + _ = opt.is_some_and(|x| x <= 1000); + _ = opt.is_some_and(|x| x > 1000); + _ = opt.is_some_and(|x| x >= 1000); + _ = opt.is_some_and(|x| x == 1000); + _ = opt.is_some_and(|x| x != 1000); + _ = opt.is_some_and(not_zero); + _ = !opt.is_some_and(|x| x < 1000); //~ ERROR: this boolean expression can be simplified + _ = !opt.is_some_and(|x| x <= 1000); //~ ERROR: this boolean expression can be simplified + _ = !opt.is_some_and(|x| x > 1000); //~ ERROR: this boolean expression can be simplified + _ = !opt.is_some_and(|x| x >= 1000); //~ ERROR: this boolean expression can be simplified + _ = !opt.is_some_and(|x| x == 1000); //~ ERROR: this boolean expression can be simplified + _ = !opt.is_some_and(|x| x != 1000); //~ ERROR: this boolean expression can be simplified + _ = !opt.is_some_and(not_zero); + _ = opt.is_none_or(|x| x < 1000); + _ = opt.is_none_or(|x| x <= 1000); + _ = opt.is_none_or(|x| x > 1000); + _ = opt.is_none_or(|x| x >= 1000); + _ = opt.is_none_or(|x| x == 1000); + _ = opt.is_none_or(|x| x != 1000); + _ = opt.is_none_or(not_zero); + _ = !opt.is_none_or(|x| x < 1000); //~ ERROR: this boolean expression can be simplified + _ = !opt.is_none_or(|x| x <= 1000); //~ ERROR: this boolean expression can be simplified + _ = !opt.is_none_or(|x| x > 1000); //~ ERROR: this boolean expression can be simplified + _ = !opt.is_none_or(|x| x >= 1000); //~ ERROR: this boolean expression can be simplified + _ = !opt.is_none_or(|x| x == 1000); //~ ERROR: this boolean expression can be simplified + _ = !opt.is_none_or(|x| x != 1000); //~ ERROR: this boolean expression can be simplified + _ = !opt.is_none_or(not_zero); + + let opt = Some(true); + _ = opt.is_some_and(|x| x); + _ = opt.is_some_and(|x| !x); + _ = !opt.is_some_and(|x| x); + _ = !opt.is_some_and(|x| !x); //~ ERROR: this boolean expression can be simplified + _ = opt.is_none_or(|x| x); + _ = opt.is_none_or(|x| !x); + _ = !opt.is_none_or(|x| x); + _ = !opt.is_none_or(|x| !x); //~ ERROR: this boolean expression can be simplified + + let opt: Option> = Some(Ok(123)); + _ = opt.is_some_and(|x| x.is_ok()); + _ = opt.is_some_and(|x| x.is_err()); + _ = opt.is_none_or(|x| x.is_ok()); + _ = opt.is_none_or(|x| x.is_err()); + _ = !opt.is_some_and(|x| x.is_ok()); //~ ERROR: this boolean expression can be simplified + _ = !opt.is_some_and(|x| x.is_err()); //~ ERROR: this boolean expression can be simplified + _ = !opt.is_none_or(|x| x.is_ok()); //~ ERROR: this boolean expression can be simplified + _ = !opt.is_none_or(|x| x.is_err()); //~ ERROR: this boolean expression can be simplified + + #[clippy::msrv = "1.81"] + fn before_stabilization() { + let opt = Some(500); + _ = !opt.is_some_and(|x| x < 1000); + } +} + fn main() {} diff --git a/tests/ui/nonminimal_bool_methods.stderr b/tests/ui/nonminimal_bool_methods.stderr index d7adc0638b373..52803e828aed0 100644 --- a/tests/ui/nonminimal_bool_methods.stderr +++ b/tests/ui/nonminimal_bool_methods.stderr @@ -97,5 +97,113 @@ error: this boolean expression can be simplified LL | if !(a as u64 <= b) {} | ^^^^^^^^^^^^^^^^ help: try: `a as u64 > b` -error: aborting due to 16 previous errors +error: this boolean expression can be simplified + --> tests/ui/nonminimal_bool_methods.rs:131:9 + | +LL | _ = !opt.is_some_and(|x| x < 1000); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `opt.is_none_or(|x| x >= 1000)` + +error: this boolean expression can be simplified + --> tests/ui/nonminimal_bool_methods.rs:132:9 + | +LL | _ = !opt.is_some_and(|x| x <= 1000); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `opt.is_none_or(|x| x > 1000)` + +error: this boolean expression can be simplified + --> tests/ui/nonminimal_bool_methods.rs:133:9 + | +LL | _ = !opt.is_some_and(|x| x > 1000); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `opt.is_none_or(|x| x <= 1000)` + +error: this boolean expression can be simplified + --> tests/ui/nonminimal_bool_methods.rs:134:9 + | +LL | _ = !opt.is_some_and(|x| x >= 1000); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `opt.is_none_or(|x| x < 1000)` + +error: this boolean expression can be simplified + --> tests/ui/nonminimal_bool_methods.rs:135:9 + | +LL | _ = !opt.is_some_and(|x| x == 1000); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `opt.is_none_or(|x| x != 1000)` + +error: this boolean expression can be simplified + --> tests/ui/nonminimal_bool_methods.rs:136:9 + | +LL | _ = !opt.is_some_and(|x| x != 1000); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `opt.is_none_or(|x| x == 1000)` + +error: this boolean expression can be simplified + --> tests/ui/nonminimal_bool_methods.rs:145:9 + | +LL | _ = !opt.is_none_or(|x| x < 1000); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `opt.is_some_and(|x| x >= 1000)` + +error: this boolean expression can be simplified + --> tests/ui/nonminimal_bool_methods.rs:146:9 + | +LL | _ = !opt.is_none_or(|x| x <= 1000); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `opt.is_some_and(|x| x > 1000)` + +error: this boolean expression can be simplified + --> tests/ui/nonminimal_bool_methods.rs:147:9 + | +LL | _ = !opt.is_none_or(|x| x > 1000); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `opt.is_some_and(|x| x <= 1000)` + +error: this boolean expression can be simplified + --> tests/ui/nonminimal_bool_methods.rs:148:9 + | +LL | _ = !opt.is_none_or(|x| x >= 1000); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `opt.is_some_and(|x| x < 1000)` + +error: this boolean expression can be simplified + --> tests/ui/nonminimal_bool_methods.rs:149:9 + | +LL | _ = !opt.is_none_or(|x| x == 1000); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `opt.is_some_and(|x| x != 1000)` + +error: this boolean expression can be simplified + --> tests/ui/nonminimal_bool_methods.rs:150:9 + | +LL | _ = !opt.is_none_or(|x| x != 1000); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `opt.is_some_and(|x| x == 1000)` + +error: this boolean expression can be simplified + --> tests/ui/nonminimal_bool_methods.rs:157:9 + | +LL | _ = !opt.is_some_and(|x| !x); + | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `opt.is_none_or(|x| x)` + +error: this boolean expression can be simplified + --> tests/ui/nonminimal_bool_methods.rs:161:9 + | +LL | _ = !opt.is_none_or(|x| !x); + | ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `opt.is_some_and(|x| x)` + +error: this boolean expression can be simplified + --> tests/ui/nonminimal_bool_methods.rs:168:9 + | +LL | _ = !opt.is_some_and(|x| x.is_ok()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `opt.is_none_or(|x| x.is_err())` + +error: this boolean expression can be simplified + --> tests/ui/nonminimal_bool_methods.rs:169:9 + | +LL | _ = !opt.is_some_and(|x| x.is_err()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `opt.is_none_or(|x| x.is_ok())` + +error: this boolean expression can be simplified + --> tests/ui/nonminimal_bool_methods.rs:170:9 + | +LL | _ = !opt.is_none_or(|x| x.is_ok()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `opt.is_some_and(|x| x.is_err())` + +error: this boolean expression can be simplified + --> tests/ui/nonminimal_bool_methods.rs:171:9 + | +LL | _ = !opt.is_none_or(|x| x.is_err()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `opt.is_some_and(|x| x.is_ok())` + +error: aborting due to 34 previous errors diff --git a/tests/ui/nonminimal_bool_methods_unfixable.rs b/tests/ui/nonminimal_bool_methods_unfixable.rs new file mode 100644 index 0000000000000..60b8da30a2f13 --- /dev/null +++ b/tests/ui/nonminimal_bool_methods_unfixable.rs @@ -0,0 +1,9 @@ +#![warn(clippy::nonminimal_bool)] +//@no-rustfix + +fn issue_13436() { + let opt_opt = Some(Some(500)); + _ = !opt_opt.is_some_and(|x| !x.is_some_and(|y| y != 1000)); //~ ERROR: this boolean expression can be simplified +} + +fn main() {} diff --git a/tests/ui/nonminimal_bool_methods_unfixable.stderr b/tests/ui/nonminimal_bool_methods_unfixable.stderr new file mode 100644 index 0000000000000..5a90155844cd3 --- /dev/null +++ b/tests/ui/nonminimal_bool_methods_unfixable.stderr @@ -0,0 +1,17 @@ +error: this boolean expression can be simplified + --> tests/ui/nonminimal_bool_methods_unfixable.rs:6:9 + | +LL | _ = !opt_opt.is_some_and(|x| !x.is_some_and(|y| y != 1000)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `opt_opt.is_none_or(|x| x.is_some_and(|y| y != 1000))` + | + = note: `-D clippy::nonminimal-bool` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::nonminimal_bool)]` + +error: this boolean expression can be simplified + --> tests/ui/nonminimal_bool_methods_unfixable.rs:6:34 + | +LL | _ = !opt_opt.is_some_and(|x| !x.is_some_and(|y| y != 1000)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `x.is_none_or(|y| y == 1000)` + +error: aborting due to 2 previous errors + From 5726000b2de7052915e808e42a75d6b60b3db540 Mon Sep 17 00:00:00 2001 From: clubby789 Date: Sun, 29 Sep 2024 15:15:29 +0000 Subject: [PATCH 1709/2194] Copy correct path to clipboard for modules/keywords/primitives --- src/librustdoc/html/static/js/main.js | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/librustdoc/html/static/js/main.js b/src/librustdoc/html/static/js/main.js index 0d556e0a68274..984b0877d8de2 100644 --- a/src/librustdoc/html/static/js/main.js +++ b/src/librustdoc/html/static/js/main.js @@ -1828,11 +1828,15 @@ href="https://doc.rust-lang.org/${channel}/rustdoc/read-documentation/search.htm return; } but.onclick = () => { - const path = []; - onEachLazy(document.querySelectorAll(".rustdoc-breadcrumbs a"), a => { - path.push(a.textContent); - }); - path.push(document.querySelector("title").textContent.split(" ")[0]); + // Most page titles are ' in - Rust', except + // modules (which don't have the first part) and keywords/primitives + // (which don't have a module path) + const title = document.querySelector("title").textContent.replace(" - Rust", ""); + const [item, module] = title.split(" in "); + const path = [item]; + if (module !== undefined) { + path.unshift(module); + } copyContentToClipboard(path.join("::")); copyButtonAnimation(but); From 8e4570ae136e11a4ca8fa4e8ab55d9a82561bac3 Mon Sep 17 00:00:00 2001 From: Chayim Refael Friedman Date: Sun, 29 Sep 2024 22:28:28 +0300 Subject: [PATCH 1710/2194] When glueing together tokens from macros, merge their spans --- .../hir-def/src/macro_expansion_tests/mbe.rs | 2 +- .../crates/syntax-bridge/src/lib.rs | 32 +++++++++++++++++-- 2 files changed, 31 insertions(+), 3 deletions(-) diff --git a/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mbe.rs b/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mbe.rs index 85fb90fdfb69f..d568f6faa7299 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mbe.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mbe.rs @@ -36,7 +36,7 @@ macro_rules! f { } struct#0:1@58..64#1# MyTraitMap2#0:2@31..42#0# {#0:1@72..73#1# - map#0:1@86..89#1#:#0:1@89..90#1# #0:1@89..90#1#::#0:1@91..92#1#std#0:1@93..96#1#::#0:1@96..97#1#collections#0:1@98..109#1#::#0:1@109..110#1#HashSet#0:1@111..118#1#<#0:1@118..119#1#(#0:1@119..120#1#)#0:1@120..121#1#>#0:1@121..122#1#,#0:1@122..123#1# + map#0:1@86..89#1#:#0:1@89..90#1# #0:1@89..90#1#::#0:1@91..93#1#std#0:1@93..96#1#::#0:1@96..98#1#collections#0:1@98..109#1#::#0:1@109..111#1#HashSet#0:1@111..118#1#<#0:1@118..119#1#(#0:1@119..120#1#)#0:1@120..121#1#>#0:1@121..122#1#,#0:1@122..123#1# }#0:1@132..133#1# "#]], ); diff --git a/src/tools/rust-analyzer/crates/syntax-bridge/src/lib.rs b/src/tools/rust-analyzer/crates/syntax-bridge/src/lib.rs index 0ccd08867602c..3a05b83e49703 100644 --- a/src/tools/rust-analyzer/crates/syntax-bridge/src/lib.rs +++ b/src/tools/rust-analyzer/crates/syntax-bridge/src/lib.rs @@ -148,6 +148,7 @@ pub fn token_tree_to_syntax_node( ) -> (Parse, SpanMap) where SpanData: Copy + fmt::Debug, + Ctx: PartialEq, { let buffer = match tt { tt::Subtree { @@ -892,6 +893,7 @@ fn delim_to_str(d: tt::DelimiterKind, closing: bool) -> Option<&'static str> { impl TtTreeSink<'_, Ctx> where SpanData: Copy + fmt::Debug, + Ctx: PartialEq, { /// Parses a float literal as if it was a one to two name ref nodes with a dot inbetween. /// This occurs when a float literal is used as a field access. @@ -949,6 +951,7 @@ where } let mut last = self.cursor; + let mut combined_span = None; 'tokens: for _ in 0..n_tokens { let tmp: u8; if self.cursor.eof() { @@ -982,7 +985,10 @@ where format_to!(self.buf, "{lit}"); debug_assert_ne!(self.buf.len() - buf_l, 0); self.text_pos += TextSize::new((self.buf.len() - buf_l) as u32); - self.token_map.push(self.text_pos, lit.span); + combined_span = match combined_span { + None => Some(lit.span), + Some(prev_span) => Some(Self::merge_spans(prev_span, lit.span)), + }; self.cursor = self.cursor.bump(); continue 'tokens; } @@ -1006,9 +1012,13 @@ where }; self.buf += text; self.text_pos += TextSize::of(text); - self.token_map.push(self.text_pos, span); + combined_span = match combined_span { + None => Some(span), + Some(prev_span) => Some(Self::merge_spans(prev_span, span)), + } } + self.token_map.push(self.text_pos, combined_span.expect("expected at least one token")); self.inner.token(kind, self.buf.as_str()); self.buf.clear(); // FIXME: Emitting whitespace for this is really just a hack, we should get rid of it. @@ -1043,4 +1053,22 @@ where fn error(&mut self, error: String) { self.inner.error(error, self.text_pos) } + + fn merge_spans(a: SpanData, b: SpanData) -> SpanData { + // We don't do what rustc does exactly, rustc does something clever when the spans have different syntax contexts + // but this runs afoul of our separation between `span` and `hir-expand`. + SpanData { + range: if a.ctx == b.ctx { + TextRange::new( + std::cmp::min(a.range.start(), b.range.start()), + std::cmp::max(a.range.end(), b.range.end()), + ) + } else { + // Combining ranges make no sense when they come from different syntax contexts. + a.range + }, + anchor: a.anchor, + ctx: a.ctx, + } + } } From 6d1a25ad7e8ce026a0a2b0c85046afc81ef529ba Mon Sep 17 00:00:00 2001 From: Ding Xiang Fei Date: Mon, 30 Sep 2024 03:40:48 +0800 Subject: [PATCH 1711/2194] preserve brackets around if-lets and skip while-lets --- compiler/rustc_lint/src/if_let_rescope.rs | 29 +++++++++++++++++++++-- tests/ui/drop/lint-if-let-rescope.fixed | 15 +++++++++++- tests/ui/drop/lint-if-let-rescope.rs | 15 +++++++++++- tests/ui/drop/lint-if-let-rescope.stderr | 22 ++++++++++++++++- 4 files changed, 76 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_lint/src/if_let_rescope.rs b/compiler/rustc_lint/src/if_let_rescope.rs index 229d0c3642174..8cb63d5cb0542 100644 --- a/compiler/rustc_lint/src/if_let_rescope.rs +++ b/compiler/rustc_lint/src/if_let_rescope.rs @@ -122,7 +122,11 @@ impl IfLetRescope { } let tcx = cx.tcx; let source_map = tcx.sess.source_map(); - let expr_end = expr.span.shrink_to_hi(); + let expr_end = match expr.kind { + hir::ExprKind::If(_cond, conseq, None) => conseq.span.shrink_to_hi(), + hir::ExprKind::If(_cond, _conseq, Some(alt)) => alt.span.shrink_to_hi(), + _ => return, + }; let mut add_bracket_to_match_head = match_head_needs_bracket(tcx, expr); let mut significant_droppers = vec![]; let mut lifetime_ends = vec![]; @@ -145,7 +149,10 @@ impl IfLetRescope { recovered: Recovered::No, }) = cond.kind { - let if_let_pat = expr.span.shrink_to_lo().between(init.span); + // Peel off round braces + let if_let_pat = source_map + .span_take_while(expr.span, |&ch| ch == '(' || ch.is_whitespace()) + .between(init.span); // The consequent fragment is always a block. let before_conseq = conseq.span.shrink_to_lo(); let lifetime_end = source_map.end_point(conseq.span); @@ -159,6 +166,8 @@ impl IfLetRescope { if ty_ascription.is_some() || !expr.span.can_be_used_for_suggestions() || !pat.span.can_be_used_for_suggestions() + || !if_let_pat.can_be_used_for_suggestions() + || !before_conseq.can_be_used_for_suggestions() { // Our `match` rewrites does not support type ascription, // so we just bail. @@ -240,6 +249,22 @@ impl<'tcx> LateLintPass<'tcx> for IfLetRescope { if let (Level::Allow, _) = cx.tcx.lint_level_at_node(IF_LET_RESCOPE, expr.hir_id) { return; } + if let hir::ExprKind::Loop(block, _label, hir::LoopSource::While, _span) = expr.kind + && let Some(value) = block.expr + && let hir::ExprKind::If(cond, _conseq, _alt) = value.kind + && let hir::ExprKind::Let(..) = cond.kind + { + // Recall that `while let` is lowered into this: + // ``` + // loop { + // if let .. { body } else { break; } + // } + // ``` + // There is no observable from the `{ break; }` block so the edition change + // means nothing substantial to this `while` statement. + self.skip.insert(value.hir_id); + return; + } if expr_parent_is_stmt(cx.tcx, expr.hir_id) && matches!(expr.kind, hir::ExprKind::If(_cond, _conseq, None)) { diff --git a/tests/ui/drop/lint-if-let-rescope.fixed b/tests/ui/drop/lint-if-let-rescope.fixed index f228783f88bc5..d579ce9823691 100644 --- a/tests/ui/drop/lint-if-let-rescope.fixed +++ b/tests/ui/drop/lint-if-let-rescope.fixed @@ -2,7 +2,7 @@ #![deny(if_let_rescope)] #![feature(if_let_rescope)] -#![allow(irrefutable_let_patterns)] +#![allow(irrefutable_let_patterns, unused_parens)] fn droppy() -> Droppy { Droppy @@ -68,4 +68,17 @@ fn main() { //~| HELP: the value is now dropped here in Edition 2024 //~| HELP: a `match` with a single arm can preserve the drop order up to Edition 2021 } + + if (match droppy().get() { Some(_value) => { true } _ => { false }}) { + //~^ ERROR: `if let` assigns a shorter lifetime since Edition 2024 + //~| WARN: this changes meaning in Rust 2024 + //~| HELP: a `match` with a single arm can preserve the drop order up to Edition 2021 + //~| HELP: the value is now dropped here in Edition 2024 + // do something + } + + while let Some(_value) = droppy().get() { + // Should not lint + break; + } } diff --git a/tests/ui/drop/lint-if-let-rescope.rs b/tests/ui/drop/lint-if-let-rescope.rs index 241fb897fce17..aab293cdcfc77 100644 --- a/tests/ui/drop/lint-if-let-rescope.rs +++ b/tests/ui/drop/lint-if-let-rescope.rs @@ -2,7 +2,7 @@ #![deny(if_let_rescope)] #![feature(if_let_rescope)] -#![allow(irrefutable_let_patterns)] +#![allow(irrefutable_let_patterns, unused_parens)] fn droppy() -> Droppy { Droppy @@ -68,4 +68,17 @@ fn main() { //~| HELP: the value is now dropped here in Edition 2024 //~| HELP: a `match` with a single arm can preserve the drop order up to Edition 2021 } + + if (if let Some(_value) = droppy().get() { true } else { false }) { + //~^ ERROR: `if let` assigns a shorter lifetime since Edition 2024 + //~| WARN: this changes meaning in Rust 2024 + //~| HELP: a `match` with a single arm can preserve the drop order up to Edition 2021 + //~| HELP: the value is now dropped here in Edition 2024 + // do something + } + + while let Some(_value) = droppy().get() { + // Should not lint + break; + } } diff --git a/tests/ui/drop/lint-if-let-rescope.stderr b/tests/ui/drop/lint-if-let-rescope.stderr index 25ca3cf1ca873..50801ae166ff0 100644 --- a/tests/ui/drop/lint-if-let-rescope.stderr +++ b/tests/ui/drop/lint-if-let-rescope.stderr @@ -131,5 +131,25 @@ help: a `match` with a single arm can preserve the drop order up to Edition 2021 LL | if let () = { match Droppy.get() { Some(_value) => {} _ => {}} } { | ~~~~~ +++++++++++++++++ ++++++++ -error: aborting due to 5 previous errors +error: `if let` assigns a shorter lifetime since Edition 2024 + --> $DIR/lint-if-let-rescope.rs:72:12 + | +LL | if (if let Some(_value) = droppy().get() { true } else { false }) { + | ^^^^^^^^^^^^^^^^^^^--------^^^^^^ + | | + | this value has a significant drop implementation which may observe a major change in drop order and requires your discretion + | + = warning: this changes meaning in Rust 2024 + = note: for more information, see issue #124085 +help: the value is now dropped here in Edition 2024 + --> $DIR/lint-if-let-rescope.rs:72:53 + | +LL | if (if let Some(_value) = droppy().get() { true } else { false }) { + | ^ +help: a `match` with a single arm can preserve the drop order up to Edition 2021 + | +LL | if (match droppy().get() { Some(_value) => { true } _ => { false }}) { + | ~~~~~ +++++++++++++++++ ~~~~ + + +error: aborting due to 6 previous errors From 8c0adc6716ff1c5b1ef3de0e8972d45cb1053b27 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 29 Sep 2024 23:08:25 +0200 Subject: [PATCH 1712/2194] update lockfile --- Cargo.lock | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 5e9808c806884..7a9701a9cad53 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -432,9 +432,9 @@ dependencies = [ [[package]] name = "chrono-tz" -version = "0.9.0" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93698b29de5e97ad0ae26447b344c482a7284c737d9ddc5f9e52b74a336671bb" +checksum = "cd6dd8046d00723a59a2f8c5f295c515b9bb9a331ee4f8f3d4dd49e428acd3b6" dependencies = [ "chrono", "chrono-tz-build", @@ -443,12 +443,11 @@ dependencies = [ [[package]] name = "chrono-tz-build" -version = "0.3.0" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c088aee841df9c3041febbb73934cfc39708749bf96dc827e3359cd39ef11b1" +checksum = "e94fea34d77a245229e7746bd2beb786cd2a896f306ff491fb8cecb3074b10a7" dependencies = [ "parse-zoneinfo", - "phf", "phf_codegen", ] @@ -3119,9 +3118,9 @@ dependencies = [ [[package]] name = "rustc-build-sysroot" -version = "0.5.3" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2471f8f296262437d7e848e527b4210b44a96e53a3b4435b890227ce3e6da106" +checksum = "d6d984a9db43148467059309bd1e5ad577085162f695d9fe2cf3543aeb25cd38" dependencies = [ "anyhow", "rustc_version", From 1e30b5ae45ddf07fc7b6d233964e8eddebdc4ecd Mon Sep 17 00:00:00 2001 From: schvv31n Date: Mon, 9 Sep 2024 09:23:00 +0100 Subject: [PATCH 1713/2194] rustdoc-json: `Id(String)` -> `Id(u32)` --- src/librustdoc/json/conversions.rs | 590 +++++++++---------- src/librustdoc/json/mod.rs | 23 +- src/rustdoc-json-types/lib.rs | 6 +- src/tools/jsondoclint/src/validator.rs | 2 +- src/tools/jsondoclint/src/validator/tests.rs | 38 +- 5 files changed, 326 insertions(+), 333 deletions(-) diff --git a/src/librustdoc/json/conversions.rs b/src/librustdoc/json/conversions.rs index b411f9a1a52d0..b8791c9918b12 100644 --- a/src/librustdoc/json/conversions.rs +++ b/src/librustdoc/json/conversions.rs @@ -4,20 +4,17 @@ #![allow(rustc::default_hash_types)] -use std::fmt; - use rustc_ast::ast; use rustc_attr::DeprecatedSince; use rustc_hir::def::{CtorKind, DefKind}; use rustc_hir::def_id::DefId; use rustc_metadata::rendered_const; -use rustc_middle::bug; -use rustc_middle::ty::{self, TyCtxt}; -use rustc_span::symbol::sym; -use rustc_span::{Pos, Symbol}; +use rustc_middle::{bug, ty}; +use rustc_span::{Pos, Symbol, sym}; use rustc_target::spec::abi::Abi as RustcAbi; use rustdoc_json_types::*; +use super::FullItemId; use crate::clean::{self, ItemId}; use crate::formats::FormatRenderer; use crate::formats::item_type::ItemType; @@ -40,7 +37,7 @@ impl JsonRenderer<'_> { Some(UrlFragment::UserWritten(_)) | None => *page_id, }; - (String::from(&**link), id_from_item_default(id.into(), self.tcx)) + (String::from(&**link), self.id_from_item_default(id.into())) }) .collect(); let docs = item.opt_doc_value(); @@ -48,7 +45,7 @@ impl JsonRenderer<'_> { let span = item.span(self.tcx); let visibility = item.visibility(self.tcx); let clean::Item { name, item_id, .. } = item; - let id = id_from_item(&item, self.tcx); + let id = self.id_from_item(&item); let inner = match item.kind { clean::KeywordItem => return None, clean::StrippedItem(ref inner) => { @@ -59,12 +56,12 @@ impl JsonRenderer<'_> { clean::ModuleItem(_) if self.imported_items.contains(&item_id.expect_def_id()) => { - from_clean_item(item, self.tcx) + from_clean_item(item, self) } _ => return None, } } - _ => from_clean_item(item, self.tcx), + _ => from_clean_item(item, self), }; Some(Item { id, @@ -105,37 +102,116 @@ impl JsonRenderer<'_> { Some(ty::Visibility::Public) => Visibility::Public, Some(ty::Visibility::Restricted(did)) if did.is_crate_root() => Visibility::Crate, Some(ty::Visibility::Restricted(did)) => Visibility::Restricted { - parent: id_from_item_default(did.into(), self.tcx), + parent: self.id_from_item_default(did.into()), path: self.tcx.def_path(did).to_string_no_crate_verbose(), }, } } + + pub(crate) fn id_from_item_default(&self, item_id: ItemId) -> Id { + self.id_from_item_inner(item_id, None, None) + } + + pub(crate) fn id_from_item_inner( + &self, + item_id: ItemId, + name: Option, + extra: Option, + ) -> Id { + let make_part = |def_id: DefId, name: Option, extra: Option| { + let name = match name { + Some(name) => Some(name), + None => { + // We need this workaround because primitive types' DefId actually refers to + // their parent module, which isn't present in the output JSON items. So + // instead, we directly get the primitive symbol + if matches!(self.tcx.def_kind(def_id), DefKind::Mod) + && let Some(prim) = self + .tcx + .get_attrs(def_id, sym::rustc_doc_primitive) + .find_map(|attr| attr.value_str()) + { + Some(prim) + } else { + self.tcx.opt_item_name(def_id) + } + } + }; + + FullItemId { def_id, name, extra } + }; + + let key = match item_id { + ItemId::DefId(did) => (make_part(did, name, extra), None), + ItemId::Blanket { for_, impl_id } => { + (make_part(impl_id, None, None), Some(make_part(for_, name, extra))) + } + ItemId::Auto { for_, trait_ } => { + (make_part(trait_, None, None), Some(make_part(for_, name, extra))) + } + }; + + let mut interner = self.id_interner.borrow_mut(); + let len = interner.len(); + *interner + .entry(key) + .or_insert_with(|| Id(len.try_into().expect("too many items in a crate"))) + } + + pub(crate) fn id_from_item(&self, item: &clean::Item) -> Id { + match item.kind { + clean::ItemKind::ImportItem(ref import) => { + let extra = + import.source.did.map(ItemId::from).map(|i| self.id_from_item_default(i)); + self.id_from_item_inner(item.item_id, item.name, extra) + } + _ => self.id_from_item_inner(item.item_id, item.name, None), + } + } + + fn ids(&self, items: impl IntoIterator) -> Vec { + items + .into_iter() + .filter(|x| !x.is_stripped() && !x.is_keyword()) + .map(|i| self.id_from_item(&i)) + .collect() + } + + fn ids_keeping_stripped( + &self, + items: impl IntoIterator, + ) -> Vec> { + items + .into_iter() + .map(|i| (!i.is_stripped() && !i.is_keyword()).then(|| self.id_from_item(&i))) + .collect() + } } -pub(crate) trait FromWithTcx { - fn from_tcx(f: T, tcx: TyCtxt<'_>) -> Self; +pub(crate) trait FromClean { + fn from_clean(f: T, renderer: &JsonRenderer<'_>) -> Self; } -pub(crate) trait IntoWithTcx { - fn into_tcx(self, tcx: TyCtxt<'_>) -> T; +pub(crate) trait IntoJson { + fn into_json(self, renderer: &JsonRenderer<'_>) -> T; } -impl IntoWithTcx for T +impl IntoJson for T where - U: FromWithTcx, + U: FromClean, { - fn into_tcx(self, tcx: TyCtxt<'_>) -> U { - U::from_tcx(self, tcx) + fn into_json(self, renderer: &JsonRenderer<'_>) -> U { + U::from_clean(self, renderer) } } -impl FromWithTcx for Vec +impl FromClean for Vec where I: IntoIterator, - U: FromWithTcx, + U: FromClean, { - fn from_tcx(f: I, tcx: TyCtxt<'_>) -> Vec { - f.into_iter().map(|x| x.into_tcx(tcx)).collect() + fn from_clean(f: I, renderer: &JsonRenderer<'_>) -> Vec { + f.into_iter().map(|x| x.into_json(renderer)).collect() } } @@ -150,37 +226,38 @@ pub(crate) fn from_deprecation(deprecation: rustc_attr::Deprecation) -> Deprecat Deprecation { since, note: note.map(|s| s.to_string()) } } -impl FromWithTcx for GenericArgs { - fn from_tcx(args: clean::GenericArgs, tcx: TyCtxt<'_>) -> Self { +impl FromClean for GenericArgs { + fn from_clean(args: clean::GenericArgs, renderer: &JsonRenderer<'_>) -> Self { use clean::GenericArgs::*; match args { AngleBracketed { args, constraints } => GenericArgs::AngleBracketed { - args: args.into_vec().into_tcx(tcx), - constraints: constraints.into_tcx(tcx), + args: args.into_vec().into_json(renderer), + constraints: constraints.into_json(renderer), }, Parenthesized { inputs, output } => GenericArgs::Parenthesized { - inputs: inputs.into_vec().into_tcx(tcx), - output: output.map(|a| (*a).into_tcx(tcx)), + inputs: inputs.into_vec().into_json(renderer), + output: output.map(|a| (*a).into_json(renderer)), }, } } } -impl FromWithTcx for GenericArg { - fn from_tcx(arg: clean::GenericArg, tcx: TyCtxt<'_>) -> Self { +impl FromClean for GenericArg { + fn from_clean(arg: clean::GenericArg, renderer: &JsonRenderer<'_>) -> Self { use clean::GenericArg::*; match arg { Lifetime(l) => GenericArg::Lifetime(convert_lifetime(l)), - Type(t) => GenericArg::Type(t.into_tcx(tcx)), - Const(box c) => GenericArg::Const(c.into_tcx(tcx)), + Type(t) => GenericArg::Type(t.into_json(renderer)), + Const(box c) => GenericArg::Const(c.into_json(renderer)), Infer => GenericArg::Infer, } } } -impl FromWithTcx for Constant { +impl FromClean for Constant { // FIXME(generic_const_items): Add support for generic const items. - fn from_tcx(constant: clean::Constant, tcx: TyCtxt<'_>) -> Self { + fn from_clean(constant: clean::Constant, renderer: &JsonRenderer<'_>) -> Self { + let tcx = renderer.tcx; let expr = constant.expr(tcx); let value = constant.value(tcx); let is_literal = constant.is_literal(tcx); @@ -188,9 +265,10 @@ impl FromWithTcx for Constant { } } -impl FromWithTcx for Constant { +impl FromClean for Constant { // FIXME(generic_const_items): Add support for generic const items. - fn from_tcx(constant: clean::ConstantKind, tcx: TyCtxt<'_>) -> Self { + fn from_clean(constant: clean::ConstantKind, renderer: &JsonRenderer<'_>) -> Self { + let tcx = renderer.tcx; let expr = constant.expr(tcx); let value = constant.value(tcx); let is_literal = constant.is_literal(tcx); @@ -198,147 +276,62 @@ impl FromWithTcx for Constant { } } -impl FromWithTcx for AssocItemConstraint { - fn from_tcx(constraint: clean::AssocItemConstraint, tcx: TyCtxt<'_>) -> Self { +impl FromClean for AssocItemConstraint { + fn from_clean(constraint: clean::AssocItemConstraint, renderer: &JsonRenderer<'_>) -> Self { AssocItemConstraint { name: constraint.assoc.name.to_string(), - args: constraint.assoc.args.into_tcx(tcx), - binding: constraint.kind.into_tcx(tcx), + args: constraint.assoc.args.into_json(renderer), + binding: constraint.kind.into_json(renderer), } } } -impl FromWithTcx for AssocItemConstraintKind { - fn from_tcx(kind: clean::AssocItemConstraintKind, tcx: TyCtxt<'_>) -> Self { +impl FromClean for AssocItemConstraintKind { + fn from_clean(kind: clean::AssocItemConstraintKind, renderer: &JsonRenderer<'_>) -> Self { use clean::AssocItemConstraintKind::*; match kind { - Equality { term } => AssocItemConstraintKind::Equality(term.into_tcx(tcx)), - Bound { bounds } => AssocItemConstraintKind::Constraint(bounds.into_tcx(tcx)), - } - } -} - -#[inline] -pub(crate) fn id_from_item_default(item_id: ItemId, tcx: TyCtxt<'_>) -> Id { - id_from_item_inner(item_id, tcx, None, None) -} - -/// It generates an ID as follows: -/// -/// `CRATE_ID:ITEM_ID[:NAME_ID][-EXTRA]`: -/// * If there is no `name`, `NAME_ID` is not generated. -/// * If there is no `extra`, `EXTRA` is not generated. -/// -/// * `name` is the item's name if available (it's not for impl blocks for example). -/// * `extra` is used for reexports: it contains the ID of the reexported item. It is used to allow -/// to have items with the same name but different types to both appear in the generated JSON. -pub(crate) fn id_from_item_inner( - item_id: ItemId, - tcx: TyCtxt<'_>, - name: Option, - extra: Option<&Id>, -) -> Id { - struct DisplayDefId<'a, 'b>(DefId, TyCtxt<'a>, Option<&'b Id>, Option); - - impl<'a, 'b> fmt::Display for DisplayDefId<'a, 'b> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - let DisplayDefId(def_id, tcx, extra, name) = self; - // We need this workaround because primitive types' DefId actually refers to - // their parent module, which isn't present in the output JSON items. So - // instead, we directly get the primitive symbol and convert it to u32 to - // generate the ID. - let s; - let extra = if let Some(e) = extra { - s = format!("-{}", e.0); - &s - } else { - "" - }; - let name = match name { - Some(name) => format!(":{}", name.as_u32()), - None => { - // We need this workaround because primitive types' DefId actually refers to - // their parent module, which isn't present in the output JSON items. So - // instead, we directly get the primitive symbol and convert it to u32 to - // generate the ID. - if matches!(tcx.def_kind(def_id), DefKind::Mod) - && let Some(prim) = tcx - .get_attrs(*def_id, sym::rustc_doc_primitive) - .find_map(|attr| attr.value_str()) - { - format!(":{}", prim.as_u32()) - } else { - tcx.opt_item_name(*def_id) - .map(|n| format!(":{}", n.as_u32())) - .unwrap_or_default() - } - } - }; - write!(f, "{}:{}{name}{extra}", def_id.krate.as_u32(), u32::from(def_id.index)) - } - } - - match item_id { - ItemId::DefId(did) => Id(format!("{}", DisplayDefId(did, tcx, extra, name))), - ItemId::Blanket { for_, impl_id } => Id(format!( - "b:{}-{}", - DisplayDefId(impl_id, tcx, None, None), - DisplayDefId(for_, tcx, extra, name) - )), - ItemId::Auto { for_, trait_ } => Id(format!( - "a:{}-{}", - DisplayDefId(trait_, tcx, None, None), - DisplayDefId(for_, tcx, extra, name) - )), - } -} - -pub(crate) fn id_from_item(item: &clean::Item, tcx: TyCtxt<'_>) -> Id { - match item.kind { - clean::ItemKind::ImportItem(ref import) => { - let extra = - import.source.did.map(ItemId::from).map(|i| id_from_item_inner(i, tcx, None, None)); - id_from_item_inner(item.item_id, tcx, item.name, extra.as_ref()) + Equality { term } => AssocItemConstraintKind::Equality(term.into_json(renderer)), + Bound { bounds } => AssocItemConstraintKind::Constraint(bounds.into_json(renderer)), } - _ => id_from_item_inner(item.item_id, tcx, item.name, None), } } -fn from_clean_item(item: clean::Item, tcx: TyCtxt<'_>) -> ItemEnum { +fn from_clean_item(item: clean::Item, renderer: &JsonRenderer<'_>) -> ItemEnum { use clean::ItemKind::*; let name = item.name; let is_crate = item.is_crate(); - let header = item.fn_header(tcx); + let header = item.fn_header(renderer.tcx); match item.inner.kind { ModuleItem(m) => { - ItemEnum::Module(Module { is_crate, items: ids(m.items, tcx), is_stripped: false }) - } - ImportItem(i) => ItemEnum::Use(i.into_tcx(tcx)), - StructItem(s) => ItemEnum::Struct(s.into_tcx(tcx)), - UnionItem(u) => ItemEnum::Union(u.into_tcx(tcx)), - StructFieldItem(f) => ItemEnum::StructField(f.into_tcx(tcx)), - EnumItem(e) => ItemEnum::Enum(e.into_tcx(tcx)), - VariantItem(v) => ItemEnum::Variant(v.into_tcx(tcx)), - FunctionItem(f) => ItemEnum::Function(from_function(f, true, header.unwrap(), tcx)), + ItemEnum::Module(Module { is_crate, items: renderer.ids(m.items), is_stripped: false }) + } + ImportItem(i) => ItemEnum::Use(i.into_json(renderer)), + StructItem(s) => ItemEnum::Struct(s.into_json(renderer)), + UnionItem(u) => ItemEnum::Union(u.into_json(renderer)), + StructFieldItem(f) => ItemEnum::StructField(f.into_json(renderer)), + EnumItem(e) => ItemEnum::Enum(e.into_json(renderer)), + VariantItem(v) => ItemEnum::Variant(v.into_json(renderer)), + FunctionItem(f) => ItemEnum::Function(from_function(f, true, header.unwrap(), renderer)), ForeignFunctionItem(f, _) => { - ItemEnum::Function(from_function(f, false, header.unwrap(), tcx)) - } - TraitItem(t) => ItemEnum::Trait((*t).into_tcx(tcx)), - TraitAliasItem(t) => ItemEnum::TraitAlias(t.into_tcx(tcx)), - MethodItem(m, _) => ItemEnum::Function(from_function(m, true, header.unwrap(), tcx)), - TyMethodItem(m) => ItemEnum::Function(from_function(m, false, header.unwrap(), tcx)), - ImplItem(i) => ItemEnum::Impl((*i).into_tcx(tcx)), - StaticItem(s) => ItemEnum::Static(s.into_tcx(tcx)), - ForeignStaticItem(s, _) => ItemEnum::Static(s.into_tcx(tcx)), + ItemEnum::Function(from_function(f, false, header.unwrap(), renderer)) + } + TraitItem(t) => ItemEnum::Trait((*t).into_json(renderer)), + TraitAliasItem(t) => ItemEnum::TraitAlias(t.into_json(renderer)), + MethodItem(m, _) => ItemEnum::Function(from_function(m, true, header.unwrap(), renderer)), + TyMethodItem(m) => ItemEnum::Function(from_function(m, false, header.unwrap(), renderer)), + ImplItem(i) => ItemEnum::Impl((*i).into_json(renderer)), + StaticItem(s) => ItemEnum::Static(s.into_json(renderer)), + ForeignStaticItem(s, _) => ItemEnum::Static(s.into_json(renderer)), ForeignTypeItem => ItemEnum::ExternType, - TypeAliasItem(t) => ItemEnum::TypeAlias(t.into_tcx(tcx)), + TypeAliasItem(t) => ItemEnum::TypeAlias(t.into_json(renderer)), // FIXME(generic_const_items): Add support for generic free consts - ConstantItem(ci) => { - ItemEnum::Constant { type_: ci.type_.into_tcx(tcx), const_: ci.kind.into_tcx(tcx) } - } + ConstantItem(ci) => ItemEnum::Constant { + type_: ci.type_.into_json(renderer), + const_: ci.kind.into_json(renderer), + }, MacroItem(m) => ItemEnum::Macro(m.source), - ProcMacroItem(m) => ItemEnum::ProcMacro(m.into_tcx(tcx)), + ProcMacroItem(m) => ItemEnum::ProcMacro(m.into_json(renderer)), PrimitiveItem(p) => { ItemEnum::Primitive(Primitive { name: p.as_sym().to_string(), @@ -347,19 +340,22 @@ fn from_clean_item(item: clean::Item, tcx: TyCtxt<'_>) -> ItemEnum { } // FIXME(generic_const_items): Add support for generic associated consts. TyAssocConstItem(_generics, ty) => { - ItemEnum::AssocConst { type_: (*ty).into_tcx(tcx), value: None } + ItemEnum::AssocConst { type_: (*ty).into_json(renderer), value: None } } // FIXME(generic_const_items): Add support for generic associated consts. - AssocConstItem(ci) => { - ItemEnum::AssocConst { type_: ci.type_.into_tcx(tcx), value: Some(ci.kind.expr(tcx)) } - } - TyAssocTypeItem(g, b) => { - ItemEnum::AssocType { generics: g.into_tcx(tcx), bounds: b.into_tcx(tcx), type_: None } - } + AssocConstItem(ci) => ItemEnum::AssocConst { + type_: ci.type_.into_json(renderer), + value: Some(ci.kind.expr(renderer.tcx)), + }, + TyAssocTypeItem(g, b) => ItemEnum::AssocType { + generics: g.into_json(renderer), + bounds: b.into_json(renderer), + type_: None, + }, AssocTypeItem(t, b) => ItemEnum::AssocType { - generics: t.generics.into_tcx(tcx), - bounds: b.into_tcx(tcx), - type_: Some(t.item_type.unwrap_or(t.type_).into_tcx(tcx)), + generics: t.generics.into_json(renderer), + bounds: b.into_json(renderer), + type_: Some(t.item_type.unwrap_or(t.type_).into_json(renderer)), }, // `convert_item` early returns `None` for stripped items and keywords. KeywordItem => unreachable!(), @@ -367,7 +363,7 @@ fn from_clean_item(item: clean::Item, tcx: TyCtxt<'_>) -> ItemEnum { match *inner { ModuleItem(m) => ItemEnum::Module(Module { is_crate, - items: ids(m.items, tcx), + items: renderer.ids(m.items), is_stripped: true, }), // `convert_item` early returns `None` for stripped items we're not including @@ -381,36 +377,36 @@ fn from_clean_item(item: clean::Item, tcx: TyCtxt<'_>) -> ItemEnum { } } -impl FromWithTcx for Struct { - fn from_tcx(struct_: clean::Struct, tcx: TyCtxt<'_>) -> Self { +impl FromClean for Struct { + fn from_clean(struct_: clean::Struct, renderer: &JsonRenderer<'_>) -> Self { let has_stripped_fields = struct_.has_stripped_entries(); let clean::Struct { ctor_kind, generics, fields } = struct_; let kind = match ctor_kind { - Some(CtorKind::Fn) => StructKind::Tuple(ids_keeping_stripped(fields, tcx)), + Some(CtorKind::Fn) => StructKind::Tuple(renderer.ids_keeping_stripped(fields)), Some(CtorKind::Const) => { assert!(fields.is_empty()); StructKind::Unit } - None => StructKind::Plain { fields: ids(fields, tcx), has_stripped_fields }, + None => StructKind::Plain { fields: renderer.ids(fields), has_stripped_fields }, }; Struct { kind, - generics: generics.into_tcx(tcx), + generics: generics.into_json(renderer), impls: Vec::new(), // Added in JsonRenderer::item } } } -impl FromWithTcx for Union { - fn from_tcx(union_: clean::Union, tcx: TyCtxt<'_>) -> Self { +impl FromClean for Union { + fn from_clean(union_: clean::Union, renderer: &JsonRenderer<'_>) -> Self { let has_stripped_fields = union_.has_stripped_entries(); let clean::Union { generics, fields } = union_; Union { - generics: generics.into_tcx(tcx), + generics: generics.into_json(renderer), has_stripped_fields, - fields: ids(fields, tcx), + fields: renderer.ids(fields), impls: Vec::new(), // Added in JsonRenderer::item } } @@ -444,51 +440,51 @@ fn convert_lifetime(l: clean::Lifetime) -> String { l.0.to_string() } -impl FromWithTcx for Generics { - fn from_tcx(generics: clean::Generics, tcx: TyCtxt<'_>) -> Self { +impl FromClean for Generics { + fn from_clean(generics: clean::Generics, renderer: &JsonRenderer<'_>) -> Self { Generics { - params: generics.params.into_tcx(tcx), - where_predicates: generics.where_predicates.into_tcx(tcx), + params: generics.params.into_json(renderer), + where_predicates: generics.where_predicates.into_json(renderer), } } } -impl FromWithTcx for GenericParamDef { - fn from_tcx(generic_param: clean::GenericParamDef, tcx: TyCtxt<'_>) -> Self { +impl FromClean for GenericParamDef { + fn from_clean(generic_param: clean::GenericParamDef, renderer: &JsonRenderer<'_>) -> Self { GenericParamDef { name: generic_param.name.to_string(), - kind: generic_param.kind.into_tcx(tcx), + kind: generic_param.kind.into_json(renderer), } } } -impl FromWithTcx for GenericParamDefKind { - fn from_tcx(kind: clean::GenericParamDefKind, tcx: TyCtxt<'_>) -> Self { +impl FromClean for GenericParamDefKind { + fn from_clean(kind: clean::GenericParamDefKind, renderer: &JsonRenderer<'_>) -> Self { use clean::GenericParamDefKind::*; match kind { Lifetime { outlives } => GenericParamDefKind::Lifetime { outlives: outlives.into_iter().map(convert_lifetime).collect(), }, Type { bounds, default, synthetic } => GenericParamDefKind::Type { - bounds: bounds.into_tcx(tcx), - default: default.map(|x| (*x).into_tcx(tcx)), + bounds: bounds.into_json(renderer), + default: default.map(|x| (*x).into_json(renderer)), is_synthetic: synthetic, }, Const { ty, default, synthetic: _ } => GenericParamDefKind::Const { - type_: (*ty).into_tcx(tcx), + type_: (*ty).into_json(renderer), default: default.map(|x| *x), }, } } } -impl FromWithTcx for WherePredicate { - fn from_tcx(predicate: clean::WherePredicate, tcx: TyCtxt<'_>) -> Self { +impl FromClean for WherePredicate { + fn from_clean(predicate: clean::WherePredicate, renderer: &JsonRenderer<'_>) -> Self { use clean::WherePredicate::*; match predicate { BoundPredicate { ty, bounds, bound_params } => WherePredicate::BoundPredicate { - type_: ty.into_tcx(tcx), - bounds: bounds.into_tcx(tcx), + type_: ty.into_json(renderer), + bounds: bounds.into_json(renderer), generic_params: bound_params .into_iter() .map(|x| { @@ -503,15 +499,15 @@ impl FromWithTcx for WherePredicate { GenericParamDefKind::Type { bounds: bounds .into_iter() - .map(|bound| bound.into_tcx(tcx)) + .map(|bound| bound.into_json(renderer)) .collect(), - default: default.map(|ty| (*ty).into_tcx(tcx)), + default: default.map(|ty| (*ty).into_json(renderer)), is_synthetic: synthetic, } } clean::GenericParamDefKind::Const { ty, default, synthetic: _ } => { GenericParamDefKind::Const { - type_: (*ty).into_tcx(tcx), + type_: (*ty).into_json(renderer), default: default.map(|d| *d), } } @@ -530,21 +526,22 @@ impl FromWithTcx for WherePredicate { }) .collect(), }, - EqPredicate { lhs, rhs } => { - WherePredicate::EqPredicate { lhs: lhs.into_tcx(tcx), rhs: rhs.into_tcx(tcx) } - } + EqPredicate { lhs, rhs } => WherePredicate::EqPredicate { + lhs: lhs.into_json(renderer), + rhs: rhs.into_json(renderer), + }, } } } -impl FromWithTcx for GenericBound { - fn from_tcx(bound: clean::GenericBound, tcx: TyCtxt<'_>) -> Self { +impl FromClean for GenericBound { + fn from_clean(bound: clean::GenericBound, renderer: &JsonRenderer<'_>) -> Self { use clean::GenericBound::*; match bound { TraitBound(clean::PolyTrait { trait_, generic_params }, modifier) => { GenericBound::TraitBound { - trait_: trait_.into_tcx(tcx), - generic_params: generic_params.into_tcx(tcx), + trait_: trait_.into_json(renderer), + generic_params: generic_params.into_json(renderer), modifier: from_trait_bound_modifier(modifier), } } @@ -572,73 +569,75 @@ pub(crate) fn from_trait_bound_modifier( } } -impl FromWithTcx for Type { - fn from_tcx(ty: clean::Type, tcx: TyCtxt<'_>) -> Self { +impl FromClean for Type { + fn from_clean(ty: clean::Type, renderer: &JsonRenderer<'_>) -> Self { use clean::Type::{ Array, BareFunction, BorrowedRef, Generic, ImplTrait, Infer, Primitive, QPath, RawPointer, SelfTy, Slice, Tuple, }; match ty { - clean::Type::Path { path } => Type::ResolvedPath(path.into_tcx(tcx)), + clean::Type::Path { path } => Type::ResolvedPath(path.into_json(renderer)), clean::Type::DynTrait(bounds, lt) => Type::DynTrait(DynTrait { lifetime: lt.map(convert_lifetime), - traits: bounds.into_tcx(tcx), + traits: bounds.into_json(renderer), }), Generic(s) => Type::Generic(s.to_string()), // FIXME: add dedicated variant to json Type? SelfTy => Type::Generic("Self".to_owned()), Primitive(p) => Type::Primitive(p.as_sym().to_string()), - BareFunction(f) => Type::FunctionPointer(Box::new((*f).into_tcx(tcx))), - Tuple(t) => Type::Tuple(t.into_tcx(tcx)), - Slice(t) => Type::Slice(Box::new((*t).into_tcx(tcx))), - Array(t, s) => Type::Array { type_: Box::new((*t).into_tcx(tcx)), len: s.to_string() }, + BareFunction(f) => Type::FunctionPointer(Box::new((*f).into_json(renderer))), + Tuple(t) => Type::Tuple(t.into_json(renderer)), + Slice(t) => Type::Slice(Box::new((*t).into_json(renderer))), + Array(t, s) => { + Type::Array { type_: Box::new((*t).into_json(renderer)), len: s.to_string() } + } clean::Type::Pat(t, p) => Type::Pat { - type_: Box::new((*t).into_tcx(tcx)), + type_: Box::new((*t).into_json(renderer)), __pat_unstable_do_not_use: p.to_string(), }, - ImplTrait(g) => Type::ImplTrait(g.into_tcx(tcx)), + ImplTrait(g) => Type::ImplTrait(g.into_json(renderer)), Infer => Type::Infer, RawPointer(mutability, type_) => Type::RawPointer { is_mutable: mutability == ast::Mutability::Mut, - type_: Box::new((*type_).into_tcx(tcx)), + type_: Box::new((*type_).into_json(renderer)), }, BorrowedRef { lifetime, mutability, type_ } => Type::BorrowedRef { lifetime: lifetime.map(convert_lifetime), is_mutable: mutability == ast::Mutability::Mut, - type_: Box::new((*type_).into_tcx(tcx)), + type_: Box::new((*type_).into_json(renderer)), }, QPath(box clean::QPathData { assoc, self_type, trait_, .. }) => Type::QualifiedPath { name: assoc.name.to_string(), - args: Box::new(assoc.args.into_tcx(tcx)), - self_type: Box::new(self_type.into_tcx(tcx)), - trait_: trait_.map(|trait_| trait_.into_tcx(tcx)), + args: Box::new(assoc.args.into_json(renderer)), + self_type: Box::new(self_type.into_json(renderer)), + trait_: trait_.map(|trait_| trait_.into_json(renderer)), }, } } } -impl FromWithTcx for Path { - fn from_tcx(path: clean::Path, tcx: TyCtxt<'_>) -> Path { +impl FromClean for Path { + fn from_clean(path: clean::Path, renderer: &JsonRenderer<'_>) -> Path { Path { name: path.whole_name(), - id: id_from_item_default(path.def_id().into(), tcx), - args: path.segments.last().map(|args| Box::new(args.clone().args.into_tcx(tcx))), + id: renderer.id_from_item_default(path.def_id().into()), + args: path.segments.last().map(|args| Box::new(args.clone().args.into_json(renderer))), } } } -impl FromWithTcx for Term { - fn from_tcx(term: clean::Term, tcx: TyCtxt<'_>) -> Term { +impl FromClean for Term { + fn from_clean(term: clean::Term, renderer: &JsonRenderer<'_>) -> Term { match term { - clean::Term::Type(ty) => Term::Type(FromWithTcx::from_tcx(ty, tcx)), - clean::Term::Constant(c) => Term::Constant(FromWithTcx::from_tcx(c, tcx)), + clean::Term::Type(ty) => Term::Type(ty.into_json(renderer)), + clean::Term::Constant(c) => Term::Constant(c.into_json(renderer)), } } } -impl FromWithTcx for FunctionPointer { - fn from_tcx(bare_decl: clean::BareFunctionDecl, tcx: TyCtxt<'_>) -> Self { +impl FromClean for FunctionPointer { + fn from_clean(bare_decl: clean::BareFunctionDecl, renderer: &JsonRenderer<'_>) -> Self { let clean::BareFunctionDecl { safety, generic_params, decl, abi } = bare_decl; FunctionPointer { header: FunctionHeader { @@ -647,29 +646,30 @@ impl FromWithTcx for FunctionPointer { is_async: false, abi: convert_abi(abi), }, - generic_params: generic_params.into_tcx(tcx), - sig: decl.into_tcx(tcx), + generic_params: generic_params.into_json(renderer), + sig: decl.into_json(renderer), } } } -impl FromWithTcx for FunctionSignature { - fn from_tcx(decl: clean::FnDecl, tcx: TyCtxt<'_>) -> Self { +impl FromClean for FunctionSignature { + fn from_clean(decl: clean::FnDecl, renderer: &JsonRenderer<'_>) -> Self { let clean::FnDecl { inputs, output, c_variadic } = decl; FunctionSignature { inputs: inputs .values .into_iter() - .map(|arg| (arg.name.to_string(), arg.type_.into_tcx(tcx))) + .map(|arg| (arg.name.to_string(), arg.type_.into_json(renderer))) .collect(), - output: if output.is_unit() { None } else { Some(output.into_tcx(tcx)) }, + output: if output.is_unit() { None } else { Some(output.into_json(renderer)) }, is_c_variadic: c_variadic, } } } -impl FromWithTcx for Trait { - fn from_tcx(trait_: clean::Trait, tcx: TyCtxt<'_>) -> Self { +impl FromClean for Trait { + fn from_clean(trait_: clean::Trait, renderer: &JsonRenderer<'_>) -> Self { + let tcx = renderer.tcx; let is_auto = trait_.is_auto(tcx); let is_unsafe = trait_.safety(tcx) == rustc_hir::Safety::Unsafe; let is_object_safe = trait_.is_object_safe(tcx); @@ -678,26 +678,29 @@ impl FromWithTcx for Trait { is_auto, is_unsafe, is_object_safe, - items: ids(items, tcx), - generics: generics.into_tcx(tcx), - bounds: bounds.into_tcx(tcx), + items: renderer.ids(items), + generics: generics.into_json(renderer), + bounds: bounds.into_json(renderer), implementations: Vec::new(), // Added in JsonRenderer::item } } } -impl FromWithTcx for PolyTrait { - fn from_tcx( +impl FromClean for PolyTrait { + fn from_clean( clean::PolyTrait { trait_, generic_params }: clean::PolyTrait, - tcx: TyCtxt<'_>, + renderer: &JsonRenderer<'_>, ) -> Self { - PolyTrait { trait_: trait_.into_tcx(tcx), generic_params: generic_params.into_tcx(tcx) } + PolyTrait { + trait_: trait_.into_json(renderer), + generic_params: generic_params.into_json(renderer), + } } } -impl FromWithTcx for Impl { - fn from_tcx(impl_: clean::Impl, tcx: TyCtxt<'_>) -> Self { - let provided_trait_methods = impl_.provided_trait_methods(tcx); +impl FromClean for Impl { + fn from_clean(impl_: clean::Impl, renderer: &JsonRenderer<'_>) -> Self { + let provided_trait_methods = impl_.provided_trait_methods(renderer.tcx); let clean::Impl { safety, generics, trait_, for_, items, polarity, kind } = impl_; // FIXME: use something like ImplKind in JSON? let (is_synthetic, blanket_impl) = match kind { @@ -711,17 +714,17 @@ impl FromWithTcx for Impl { }; Impl { is_unsafe: safety == rustc_hir::Safety::Unsafe, - generics: generics.into_tcx(tcx), + generics: generics.into_json(renderer), provided_trait_methods: provided_trait_methods .into_iter() .map(|x| x.to_string()) .collect(), - trait_: trait_.map(|path| path.into_tcx(tcx)), - for_: for_.into_tcx(tcx), - items: ids(items, tcx), + trait_: trait_.map(|path| path.into_json(renderer)), + for_: for_.into_json(renderer), + items: renderer.ids(items), is_negative, is_synthetic, - blanket_impl: blanket_impl.map(|x| x.into_tcx(tcx)), + blanket_impl: blanket_impl.map(|x| x.into_json(renderer)), } } } @@ -730,42 +733,42 @@ pub(crate) fn from_function( function: Box, has_body: bool, header: rustc_hir::FnHeader, - tcx: TyCtxt<'_>, + renderer: &JsonRenderer<'_>, ) -> Function { let clean::Function { decl, generics } = *function; Function { - sig: decl.into_tcx(tcx), - generics: generics.into_tcx(tcx), + sig: decl.into_json(renderer), + generics: generics.into_json(renderer), header: from_fn_header(&header), has_body, } } -impl FromWithTcx for Enum { - fn from_tcx(enum_: clean::Enum, tcx: TyCtxt<'_>) -> Self { +impl FromClean for Enum { + fn from_clean(enum_: clean::Enum, renderer: &JsonRenderer<'_>) -> Self { let has_stripped_variants = enum_.has_stripped_entries(); let clean::Enum { variants, generics } = enum_; Enum { - generics: generics.into_tcx(tcx), + generics: generics.into_json(renderer), has_stripped_variants, - variants: ids(variants, tcx), + variants: renderer.ids(variants), impls: Vec::new(), // Added in JsonRenderer::item } } } -impl FromWithTcx for Variant { - fn from_tcx(variant: clean::Variant, tcx: TyCtxt<'_>) -> Self { +impl FromClean for Variant { + fn from_clean(variant: clean::Variant, renderer: &JsonRenderer<'_>) -> Self { use clean::VariantKind::*; - let discriminant = variant.discriminant.map(|d| d.into_tcx(tcx)); + let discriminant = variant.discriminant.map(|d| d.into_json(renderer)); let kind = match variant.kind { CLike => VariantKind::Plain, - Tuple(fields) => VariantKind::Tuple(ids_keeping_stripped(fields, tcx)), + Tuple(fields) => VariantKind::Tuple(renderer.ids_keeping_stripped(fields)), Struct(s) => VariantKind::Struct { has_stripped_fields: s.has_stripped_entries(), - fields: ids(s.fields, tcx), + fields: renderer.ids(s.fields), }, }; @@ -773,8 +776,9 @@ impl FromWithTcx for Variant { } } -impl FromWithTcx for Discriminant { - fn from_tcx(disr: clean::Discriminant, tcx: TyCtxt<'_>) -> Self { +impl FromClean for Discriminant { + fn from_clean(disr: clean::Discriminant, renderer: &JsonRenderer<'_>) -> Self { + let tcx = renderer.tcx; Discriminant { // expr is only none if going through the inlining path, which gets // `rustc_middle` types, not `rustc_hir`, but because JSON never inlines @@ -785,8 +789,8 @@ impl FromWithTcx for Discriminant { } } -impl FromWithTcx for Use { - fn from_tcx(import: clean::Import, tcx: TyCtxt<'_>) -> Self { +impl FromClean for Use { + fn from_clean(import: clean::Import, renderer: &JsonRenderer<'_>) -> Self { use clean::ImportKind::*; let (name, is_glob) = match import.kind { Simple(s) => (s.to_string(), false), @@ -798,14 +802,14 @@ impl FromWithTcx for Use { Use { source: import.source.path.whole_name(), name, - id: import.source.did.map(ItemId::from).map(|i| id_from_item_default(i, tcx)), + id: import.source.did.map(ItemId::from).map(|i| renderer.id_from_item_default(i)), is_glob, } } } -impl FromWithTcx for ProcMacro { - fn from_tcx(mac: clean::ProcMacro, _tcx: TyCtxt<'_>) -> Self { +impl FromClean for ProcMacro { + fn from_clean(mac: clean::ProcMacro, _renderer: &JsonRenderer<'_>) -> Self { ProcMacro { kind: from_macro_kind(mac.kind), helpers: mac.helpers.iter().map(|x| x.to_string()).collect(), @@ -822,17 +826,18 @@ pub(crate) fn from_macro_kind(kind: rustc_span::hygiene::MacroKind) -> MacroKind } } -impl FromWithTcx> for TypeAlias { - fn from_tcx(type_alias: Box, tcx: TyCtxt<'_>) -> Self { +impl FromClean> for TypeAlias { + fn from_clean(type_alias: Box, renderer: &JsonRenderer<'_>) -> Self { let clean::TypeAlias { type_, generics, item_type: _, inner_type: _ } = *type_alias; - TypeAlias { type_: type_.into_tcx(tcx), generics: generics.into_tcx(tcx) } + TypeAlias { type_: type_.into_json(renderer), generics: generics.into_json(renderer) } } } -impl FromWithTcx for Static { - fn from_tcx(stat: clean::Static, tcx: TyCtxt<'_>) -> Self { +impl FromClean for Static { + fn from_clean(stat: clean::Static, renderer: &JsonRenderer<'_>) -> Self { + let tcx = renderer.tcx; Static { - type_: (*stat.type_).into_tcx(tcx), + type_: (*stat.type_).into_json(renderer), is_mutable: stat.mutability == ast::Mutability::Mut, expr: stat .expr @@ -842,14 +847,17 @@ impl FromWithTcx for Static { } } -impl FromWithTcx for TraitAlias { - fn from_tcx(alias: clean::TraitAlias, tcx: TyCtxt<'_>) -> Self { - TraitAlias { generics: alias.generics.into_tcx(tcx), params: alias.bounds.into_tcx(tcx) } +impl FromClean for TraitAlias { + fn from_clean(alias: clean::TraitAlias, renderer: &JsonRenderer<'_>) -> Self { + TraitAlias { + generics: alias.generics.into_json(renderer), + params: alias.bounds.into_json(renderer), + } } } -impl FromWithTcx for ItemKind { - fn from_tcx(kind: ItemType, _tcx: TyCtxt<'_>) -> Self { +impl FromClean for ItemKind { + fn from_clean(kind: ItemType, _renderer: &JsonRenderer<'_>) -> Self { use ItemType::*; match kind { Module => ItemKind::Module, @@ -878,25 +886,3 @@ impl FromWithTcx for ItemKind { } } } - -fn ids(items: impl IntoIterator, tcx: TyCtxt<'_>) -> Vec { - items - .into_iter() - .filter(|x| !x.is_stripped() && !x.is_keyword()) - .map(|i| id_from_item(&i, tcx)) - .collect() -} - -fn ids_keeping_stripped( - items: impl IntoIterator, - tcx: TyCtxt<'_>, -) -> Vec> { - items - .into_iter() - .map( - |i| { - if !i.is_stripped() && !i.is_keyword() { Some(id_from_item(&i, tcx)) } else { None } - }, - ) - .collect() -} diff --git a/src/librustdoc/json/mod.rs b/src/librustdoc/json/mod.rs index b7a683eed1c2f..df97c5ea2634a 100644 --- a/src/librustdoc/json/mod.rs +++ b/src/librustdoc/json/mod.rs @@ -16,6 +16,7 @@ use std::rc::Rc; use rustc_hir::def_id::{DefId, DefIdSet}; use rustc_middle::ty::TyCtxt; use rustc_session::Session; +use rustc_span::Symbol; use rustc_span::def_id::LOCAL_CRATE; use rustdoc_json_types as types; // It's important to use the FxHashMap from rustdoc_json_types here, instead of @@ -31,9 +32,17 @@ use crate::docfs::PathError; use crate::error::Error; use crate::formats::FormatRenderer; use crate::formats::cache::Cache; -use crate::json::conversions::{IntoWithTcx, id_from_item, id_from_item_default}; +use crate::json::conversions::IntoJson; use crate::{clean, try_err}; +#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq)] +struct FullItemId { + def_id: DefId, + name: Option, + /// Used to distinguish imports of different items with the same name + extra: Option, +} + #[derive(Clone)] pub(crate) struct JsonRenderer<'tcx> { tcx: TyCtxt<'tcx>, @@ -46,6 +55,7 @@ pub(crate) struct JsonRenderer<'tcx> { out_dir: Option, cache: Rc, imported_items: DefIdSet, + id_interner: Rc), types::Id>>>, } impl<'tcx> JsonRenderer<'tcx> { @@ -63,7 +73,7 @@ impl<'tcx> JsonRenderer<'tcx> { .map(|i| { let item = &i.impl_item; self.item(item.clone()).unwrap(); - id_from_item(&item, self.tcx) + self.id_from_item(&item) }) .collect() }) @@ -94,7 +104,7 @@ impl<'tcx> JsonRenderer<'tcx> { if item.item_id.is_local() || is_primitive_impl { self.item(item.clone()).unwrap(); - Some(id_from_item(&item, self.tcx)) + Some(self.id_from_item(&item)) } else { None } @@ -145,6 +155,7 @@ impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> { out_dir: if options.output_to_stdout { None } else { Some(options.output) }, cache: Rc::new(cache), imported_items, + id_interner: Default::default(), }, krate, )) @@ -243,7 +254,7 @@ impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> { debug!("Constructing Output"); let output_crate = types::Crate { - root: types::Id(format!("0:0:{}", e.name(self.tcx).as_u32())), + root: self.id_from_item_default(e.def_id().into()), crate_version: self.cache.crate_version.clone(), includes_private: self.cache.document_private, index, @@ -253,10 +264,10 @@ impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> { .iter() .chain(&self.cache.external_paths) .map(|(&k, &(ref path, kind))| { - (id_from_item_default(k.into(), self.tcx), types::ItemSummary { + (self.id_from_item_default(k.into()), types::ItemSummary { crate_id: k.krate.as_u32(), path: path.iter().map(|s| s.to_string()).collect(), - kind: kind.into_tcx(self.tcx), + kind: kind.into_json(self), }) }) .collect(), diff --git a/src/rustdoc-json-types/lib.rs b/src/rustdoc-json-types/lib.rs index b3707cf615714..c94efafd5b79f 100644 --- a/src/rustdoc-json-types/lib.rs +++ b/src/rustdoc-json-types/lib.rs @@ -13,7 +13,7 @@ use serde::{Deserialize, Serialize}; /// This integer is incremented with every breaking change to the API, /// and is returned along with the JSON blob as [`Crate::format_version`]. /// Consuming code should assert that this value matches the format version(s) that it supports. -pub const FORMAT_VERSION: u32 = 34; +pub const FORMAT_VERSION: u32 = 35; /// The root of the emitted JSON blob. /// @@ -296,9 +296,9 @@ pub enum AssocItemConstraintKind { /// Rustdoc makes no guarantees about the inner value of Id's. Applications /// should treat them as opaque keys to lookup items, and avoid attempting /// to parse them, or otherwise depend on any implementation details. -#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] // FIXME(aDotInTheVoid): Consider making this non-public in rustdoc-types. -pub struct Id(pub String); +pub struct Id(pub u32); /// The fundamental kind of an item. Unlike [`ItemEnum`], this does not carry any aditional info. /// diff --git a/src/tools/jsondoclint/src/validator.rs b/src/tools/jsondoclint/src/validator.rs index b04919bdd3edc..f7c752033c59e 100644 --- a/src/tools/jsondoclint/src/validator.rs +++ b/src/tools/jsondoclint/src/validator.rs @@ -418,7 +418,7 @@ impl<'a> Validator<'a> { } else if !self.missing_ids.contains(id) { self.missing_ids.insert(id); - let sels = json_find::find_selector(&self.krate_json, &Value::String(id.0.clone())); + let sels = json_find::find_selector(&self.krate_json, &Value::Number(id.0.into())); assert_ne!(sels.len(), 0); self.fail(id, ErrorKind::NotFound(sels)) diff --git a/src/tools/jsondoclint/src/validator/tests.rs b/src/tools/jsondoclint/src/validator/tests.rs index d15aa7db31571..e842e1318db92 100644 --- a/src/tools/jsondoclint/src/validator/tests.rs +++ b/src/tools/jsondoclint/src/validator/tests.rs @@ -15,24 +15,20 @@ fn check(krate: &Crate, errs: &[Error]) { assert_eq!(errs, &validator.errs[..]); } -fn id(s: &str) -> Id { - Id(s.to_owned()) -} - #[test] fn errors_on_missing_links() { let k = Crate { - root: id("0"), + root: Id(0), crate_version: None, includes_private: false, - index: FxHashMap::from_iter([(id("0"), Item { + index: FxHashMap::from_iter([(Id(0), Item { name: Some("root".to_owned()), - id: id(""), + id: Id(0), crate_id: 0, span: None, visibility: Visibility::Public, docs: None, - links: FxHashMap::from_iter([("Not Found".to_owned(), id("1"))]), + links: FxHashMap::from_iter([("Not Found".to_owned(), Id(1))]), attrs: vec![], deprecation: None, inner: ItemEnum::Module(Module { is_crate: true, items: vec![], is_stripped: false }), @@ -49,7 +45,7 @@ fn errors_on_missing_links() { SelectorPart::Field("links".to_owned()), SelectorPart::Field("Not Found".to_owned()), ]]), - id: id("1"), + id: Id(1), }]); } @@ -58,28 +54,28 @@ fn errors_on_missing_links() { #[test] fn errors_on_local_in_paths_and_not_index() { let krate = Crate { - root: id("0:0:1572"), + root: Id(0), crate_version: None, includes_private: false, index: FxHashMap::from_iter([ - (id("0:0:1572"), Item { - id: id("0:0:1572"), + (Id(0), Item { + id: Id(0), crate_id: 0, name: Some("microcore".to_owned()), span: None, visibility: Visibility::Public, docs: None, - links: FxHashMap::from_iter([(("prim@i32".to_owned(), id("0:1:1571")))]), + links: FxHashMap::from_iter([(("prim@i32".to_owned(), Id(2)))]), attrs: Vec::new(), deprecation: None, inner: ItemEnum::Module(Module { is_crate: true, - items: vec![id("0:1:717")], + items: vec![Id(1)], is_stripped: false, }), }), - (id("0:1:717"), Item { - id: id("0:1:717"), + (Id(1), Item { + id: Id(1), crate_id: 0, name: Some("i32".to_owned()), span: None, @@ -91,7 +87,7 @@ fn errors_on_local_in_paths_and_not_index() { inner: ItemEnum::Primitive(Primitive { name: "i32".to_owned(), impls: vec![] }), }), ]), - paths: FxHashMap::from_iter([(id("0:1:1571"), ItemSummary { + paths: FxHashMap::from_iter([(Id(2), ItemSummary { crate_id: 0, path: vec!["microcore".to_owned(), "i32".to_owned()], kind: ItemKind::Primitive, @@ -101,7 +97,7 @@ fn errors_on_local_in_paths_and_not_index() { }; check(&krate, &[Error { - id: id("0:1:1571"), + id: Id(2), kind: ErrorKind::Custom("Id for local item in `paths` but not in `index`".to_owned()), }]); } @@ -110,11 +106,11 @@ fn errors_on_local_in_paths_and_not_index() { #[should_panic = "LOCAL_CRATE_ID is wrong"] fn checks_local_crate_id_is_correct() { let krate = Crate { - root: id("root"), + root: Id(0), crate_version: None, includes_private: false, - index: FxHashMap::from_iter([(id("root"), Item { - id: id("root"), + index: FxHashMap::from_iter([(Id(0), Item { + id: Id(0), crate_id: LOCAL_CRATE_ID.wrapping_add(1), name: Some("irrelavent".to_owned()), span: None, From 923cb991426a9eb3904f497bce86f33d4a6c935d Mon Sep 17 00:00:00 2001 From: Chayim Refael Friedman Date: Mon, 9 Sep 2024 23:24:34 +0300 Subject: [PATCH 1714/2194] Provide an config option to not set `cfg(test)` --- .../crates/load-cargo/src/lib.rs | 3 +++ .../crates/project-model/src/tests.rs | 2 ++ .../crates/project-model/src/workspace.rs | 26 ++++++++++++++----- .../rust-analyzer/src/cli/analysis_stats.rs | 1 + .../rust-analyzer/src/cli/diagnostics.rs | 2 ++ .../crates/rust-analyzer/src/cli/lsif.rs | 1 + .../crates/rust-analyzer/src/cli/run_tests.rs | 1 + .../rust-analyzer/src/cli/rustc_tests.rs | 1 + .../crates/rust-analyzer/src/cli/scip.rs | 11 ++++---- .../crates/rust-analyzer/src/cli/ssr.rs | 4 ++- .../crates/rust-analyzer/src/config.rs | 4 ++- .../src/integrated_benchmarks.rs | 6 +++++ .../crates/rust-analyzer/src/reload.rs | 10 +++++-- .../docs/user/generated_config.adoc | 5 ++++ .../rust-analyzer/editors/code/package.json | 10 +++++++ .../rust-analyzer/editors/code/src/config.ts | 1 + 16 files changed, 73 insertions(+), 15 deletions(-) diff --git a/src/tools/rust-analyzer/crates/load-cargo/src/lib.rs b/src/tools/rust-analyzer/crates/load-cargo/src/lib.rs index 2ffefa1730503..409f532c3e126 100644 --- a/src/tools/rust-analyzer/crates/load-cargo/src/lib.rs +++ b/src/tools/rust-analyzer/crates/load-cargo/src/lib.rs @@ -30,6 +30,7 @@ pub struct LoadCargoConfig { pub load_out_dirs_from_check: bool, pub with_proc_macro_server: ProcMacroServerChoice, pub prefill_caches: bool, + pub set_test: bool, } #[derive(Debug, Clone, PartialEq, Eq)] @@ -99,6 +100,7 @@ pub fn load_workspace( vfs.file_id(&path) }, extra_env, + load_config.set_test, ); let proc_macros = { let proc_macro_server = match &proc_macro_server { @@ -531,6 +533,7 @@ mod tests { load_out_dirs_from_check: false, with_proc_macro_server: ProcMacroServerChoice::None, prefill_caches: false, + set_test: true, }; let (db, _vfs, _proc_macro) = load_workspace_at(path, &cargo_config, &load_cargo_config, &|_| {}).unwrap(); diff --git a/src/tools/rust-analyzer/crates/project-model/src/tests.rs b/src/tools/rust-analyzer/crates/project-model/src/tests.rs index 30d1ddb636ef1..cccfe3bb51e76 100644 --- a/src/tools/rust-analyzer/crates/project-model/src/tests.rs +++ b/src/tools/rust-analyzer/crates/project-model/src/tests.rs @@ -136,6 +136,7 @@ fn to_crate_graph(project_workspace: ProjectWorkspace) -> (CrateGraph, ProcMacro } }, &Default::default(), + true, ) } @@ -257,5 +258,6 @@ fn smoke_test_real_sysroot_cargo() { } }, &Default::default(), + true, ); } diff --git a/src/tools/rust-analyzer/crates/project-model/src/workspace.rs b/src/tools/rust-analyzer/crates/project-model/src/workspace.rs index c05c03340eb2d..ed1f607309ef6 100644 --- a/src/tools/rust-analyzer/crates/project-model/src/workspace.rs +++ b/src/tools/rust-analyzer/crates/project-model/src/workspace.rs @@ -728,6 +728,7 @@ impl ProjectWorkspace { &self, load: FileLoader<'_>, extra_env: &FxHashMap, + set_test: bool, ) -> (CrateGraph, ProcMacroPaths) { let _p = tracing::info_span!("ProjectWorkspace::to_crate_graph").entered(); @@ -741,6 +742,7 @@ impl ProjectWorkspace { sysroot, extra_env, cfg_overrides, + set_test, ), sysroot, ), @@ -759,6 +761,7 @@ impl ProjectWorkspace { rustc_cfg.clone(), cfg_overrides, build_scripts, + set_test, ), sysroot, ), @@ -772,6 +775,7 @@ impl ProjectWorkspace { rustc_cfg.clone(), cfg_overrides, build_scripts, + set_test, ) } else { detached_file_to_crate_graph( @@ -780,6 +784,7 @@ impl ProjectWorkspace { file, sysroot, cfg_overrides, + set_test, ) }, sysroot, @@ -870,11 +875,12 @@ fn project_json_to_crate_graph( sysroot: &Sysroot, extra_env: &FxHashMap, override_cfg: &CfgOverrides, + set_test: bool, ) -> (CrateGraph, ProcMacroPaths) { let mut res = (CrateGraph::default(), ProcMacroPaths::default()); let (crate_graph, proc_macros) = &mut res; let (public_deps, libproc_macro) = - sysroot_to_crate_graph(crate_graph, sysroot, rustc_cfg.clone(), load); + sysroot_to_crate_graph(crate_graph, sysroot, rustc_cfg.clone(), load, set_test); let r_a_cfg_flag = CfgAtom::Flag(sym::rust_analyzer.clone()); let mut cfg_cache: FxHashMap<&str, Vec> = FxHashMap::default(); @@ -987,13 +993,14 @@ fn cargo_to_crate_graph( rustc_cfg: Vec, override_cfg: &CfgOverrides, build_scripts: &WorkspaceBuildScripts, + set_test: bool, ) -> (CrateGraph, ProcMacroPaths) { let _p = tracing::info_span!("cargo_to_crate_graph").entered(); let mut res = (CrateGraph::default(), ProcMacroPaths::default()); let crate_graph = &mut res.0; let proc_macros = &mut res.1; let (public_deps, libproc_macro) = - sysroot_to_crate_graph(crate_graph, sysroot, rustc_cfg.clone(), load); + sysroot_to_crate_graph(crate_graph, sysroot, rustc_cfg.clone(), load, set_test); let cfg_options = CfgOptions::from_iter(rustc_cfg); @@ -1011,8 +1018,10 @@ fn cargo_to_crate_graph( let mut cfg_options = cfg_options.clone(); if cargo[pkg].is_local { - // Add test cfg for local crates - cfg_options.insert_atom(sym::test.clone()); + if set_test { + // Add test cfg for local crates + cfg_options.insert_atom(sym::test.clone()); + } cfg_options.insert_atom(sym::rust_analyzer.clone()); } @@ -1173,14 +1182,17 @@ fn detached_file_to_crate_graph( detached_file: &ManifestPath, sysroot: &Sysroot, override_cfg: &CfgOverrides, + set_test: bool, ) -> (CrateGraph, ProcMacroPaths) { let _p = tracing::info_span!("detached_file_to_crate_graph").entered(); let mut crate_graph = CrateGraph::default(); let (public_deps, _libproc_macro) = - sysroot_to_crate_graph(&mut crate_graph, sysroot, rustc_cfg.clone(), load); + sysroot_to_crate_graph(&mut crate_graph, sysroot, rustc_cfg.clone(), load, set_test); let mut cfg_options = CfgOptions::from_iter(rustc_cfg); - cfg_options.insert_atom(sym::test.clone()); + if set_test { + cfg_options.insert_atom(sym::test.clone()); + } cfg_options.insert_atom(sym::rust_analyzer.clone()); override_cfg.apply(&mut cfg_options, ""); let cfg_options = Arc::new(cfg_options); @@ -1404,6 +1416,7 @@ fn sysroot_to_crate_graph( sysroot: &Sysroot, rustc_cfg: Vec, load: FileLoader<'_>, + set_test: bool, ) -> (SysrootPublicDeps, Option) { let _p = tracing::info_span!("sysroot_to_crate_graph").entered(); match sysroot.mode() { @@ -1426,6 +1439,7 @@ fn sysroot_to_crate_graph( ..Default::default() }, &WorkspaceBuildScripts::default(), + set_test, ); let mut pub_deps = vec![]; diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/analysis_stats.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/analysis_stats.rs index e899e0e8eea5f..033a7d10d9d25 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/analysis_stats.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/analysis_stats.rs @@ -84,6 +84,7 @@ impl flags::AnalysisStats { ProcMacroServerChoice::Sysroot }, prefill_caches: false, + set_test: true, }; let build_scripts_time = if self.disable_build_scripts { diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/diagnostics.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/diagnostics.rs index 28f25975d64aa..91fa312f33e9d 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/diagnostics.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/diagnostics.rs @@ -39,6 +39,8 @@ impl flags::Diagnostics { load_out_dirs_from_check: !self.disable_build_scripts, with_proc_macro_server, prefill_caches: false, + // We don't pass `--all-targets` so we also set `cfg(test)` to false. + set_test: false, }; let (db, _vfs, _proc_macro) = load_workspace_at(&self.path, &cargo_config, &load_cargo_config, &|_| {})?; diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/lsif.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/lsif.rs index e4263a3f667c3..197dbd86141db 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/lsif.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/lsif.rs @@ -284,6 +284,7 @@ impl flags::Lsif { load_out_dirs_from_check: true, with_proc_macro_server: ProcMacroServerChoice::Sysroot, prefill_caches: false, + set_test: true, }; let path = AbsPathBuf::assert_utf8(env::current_dir()?.join(self.path)); let root = ProjectManifest::discover_single(&path)?; diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/run_tests.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/run_tests.rs index f90ebcfdb2e3e..3afee41580b2b 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/run_tests.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/run_tests.rs @@ -22,6 +22,7 @@ impl flags::RunTests { load_out_dirs_from_check: true, with_proc_macro_server: ProcMacroServerChoice::Sysroot, prefill_caches: false, + set_test: true, }; let (ref db, _vfs, _proc_macro) = load_workspace_at(&self.path, &cargo_config, &load_cargo_config, &|_| {})?; diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/rustc_tests.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/rustc_tests.rs index 730f3c08abb5e..0c148be1da1fc 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/rustc_tests.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/rustc_tests.rs @@ -96,6 +96,7 @@ impl Tester { load_out_dirs_from_check: false, with_proc_macro_server: ProcMacroServerChoice::Sysroot, prefill_caches: false, + set_test: true, }; let (db, _vfs, _proc_macro) = load_workspace(workspace, &cargo_config.extra_env, &load_cargo_config)?; diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/scip.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/scip.rs index e9198977dea50..3d704d6f03ff5 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/scip.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/scip.rs @@ -24,11 +24,6 @@ impl flags::Scip { let now = Instant::now(); let no_progress = &|s| (eprintln!("rust-analyzer: Loading {s}")); - let load_cargo_config = LoadCargoConfig { - load_out_dirs_from_check: true, - with_proc_macro_server: ProcMacroServerChoice::Sysroot, - prefill_caches: true, - }; let root = vfs::AbsPathBuf::assert_utf8(std::env::current_dir()?.join(&self.path)).normalize(); @@ -51,6 +46,12 @@ impl flags::Scip { // FIXME @alibektas : What happens to errors without logging? error!(?error_sink, "Config Error(s)"); } + let load_cargo_config = LoadCargoConfig { + load_out_dirs_from_check: true, + with_proc_macro_server: ProcMacroServerChoice::Sysroot, + prefill_caches: true, + set_test: config.cfg_set_test(None), + }; let cargo_config = config.cargo(None); let (db, vfs, _) = load_workspace_at( root.as_path().as_ref(), diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/ssr.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/ssr.rs index bdca800a0d68a..3a463b822f671 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/ssr.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/ssr.rs @@ -19,6 +19,7 @@ impl flags::Ssr { load_out_dirs_from_check: true, with_proc_macro_server: ProcMacroServerChoice::Sysroot, prefill_caches: false, + set_test: true, }; let (ref db, vfs, _proc_macro) = load_workspace_at( &std::env::current_dir()?, @@ -50,11 +51,12 @@ impl flags::Search { pub fn run(self) -> anyhow::Result<()> { use ide_db::base_db::SourceRootDatabase; use ide_db::symbol_index::SymbolsDatabase; - let cargo_config = CargoConfig::default(); + let cargo_config = CargoConfig { all_targets: true, ..CargoConfig::default() }; let load_cargo_config = LoadCargoConfig { load_out_dirs_from_check: true, with_proc_macro_server: ProcMacroServerChoice::Sysroot, prefill_caches: false, + set_test: true, }; let (ref db, _vfs, _proc_macro) = load_workspace_at( &std::env::current_dir()?, diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs index 4cc60695fe668..97799abb14540 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs @@ -574,6 +574,9 @@ config_data! { /// set to a path relative to the workspace to use that path. cargo_targetDir | rust_analyzerTargetDir: Option = None, + /// Set `cfg(test)` for local crates. Defaults to true. + cfg_setTest: bool = true, + /// Run the check command for diagnostics on save. checkOnSave | checkOnSave_enable: bool = true, @@ -695,7 +698,6 @@ config_data! { workspace_symbol_search_limit: usize = 128, /// Workspace symbol search scope. workspace_symbol_search_scope: WorkspaceSymbolSearchScopeDef = WorkspaceSymbolSearchScopeDef::Workspace, - } } diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/integrated_benchmarks.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/integrated_benchmarks.rs index 118469df730ce..b98da50b420d0 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/integrated_benchmarks.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/integrated_benchmarks.rs @@ -36,12 +36,14 @@ fn integrated_highlighting_benchmark() { let cargo_config = CargoConfig { sysroot: Some(project_model::RustLibSource::Discover), + all_targets: true, ..CargoConfig::default() }; let load_cargo_config = LoadCargoConfig { load_out_dirs_from_check: true, with_proc_macro_server: ProcMacroServerChoice::Sysroot, prefill_caches: false, + set_test: true, }; let (db, vfs, _proc_macro) = { @@ -102,12 +104,14 @@ fn integrated_completion_benchmark() { let cargo_config = CargoConfig { sysroot: Some(project_model::RustLibSource::Discover), + all_targets: true, ..CargoConfig::default() }; let load_cargo_config = LoadCargoConfig { load_out_dirs_from_check: true, with_proc_macro_server: ProcMacroServerChoice::Sysroot, prefill_caches: true, + set_test: true, }; let (db, vfs, _proc_macro) = { @@ -279,12 +283,14 @@ fn integrated_diagnostics_benchmark() { let cargo_config = CargoConfig { sysroot: Some(project_model::RustLibSource::Discover), + all_targets: true, ..CargoConfig::default() }; let load_cargo_config = LoadCargoConfig { load_out_dirs_from_check: true, with_proc_macro_server: ProcMacroServerChoice::Sysroot, prefill_caches: true, + set_test: true, }; let (db, vfs, _proc_macro) = { diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/reload.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/reload.rs index 7a1782e5651bd..830a3d7f3d920 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/reload.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/reload.rs @@ -703,7 +703,12 @@ impl GlobalState { vfs.file_id(&vfs_path) }; - ws_to_crate_graph(&self.workspaces, self.config.extra_env(None), load) + ws_to_crate_graph( + &self.workspaces, + self.config.extra_env(None), + load, + self.config.cfg_set_test(None), + ) }; let mut change = ChangeWithProcMacros::new(); if self.config.expand_proc_macros() { @@ -856,12 +861,13 @@ pub fn ws_to_crate_graph( workspaces: &[ProjectWorkspace], extra_env: &FxHashMap, mut load: impl FnMut(&AbsPath) -> Option, + set_test: bool, ) -> (CrateGraph, Vec, FxHashMap>) { let mut crate_graph = CrateGraph::default(); let mut proc_macro_paths = Vec::default(); let mut ws_data = FxHashMap::default(); for ws in workspaces { - let (other, mut crate_proc_macros) = ws.to_crate_graph(&mut load, extra_env); + let (other, mut crate_proc_macros) = ws.to_crate_graph(&mut load, extra_env, set_test); let ProjectWorkspace { toolchain, target_layout, .. } = ws; let mapping = crate_graph.extend(other, &mut crate_proc_macros); diff --git a/src/tools/rust-analyzer/docs/user/generated_config.adoc b/src/tools/rust-analyzer/docs/user/generated_config.adoc index f37fd7f4ab3c4..708fc2b7891ca 100644 --- a/src/tools/rust-analyzer/docs/user/generated_config.adoc +++ b/src/tools/rust-analyzer/docs/user/generated_config.adoc @@ -158,6 +158,11 @@ building from locking the `Cargo.lock` at the expense of duplicating build artif Set to `true` to use a subdirectory of the existing target directory or set to a path relative to the workspace to use that path. -- +[[rust-analyzer.cfg.setTest]]rust-analyzer.cfg.setTest (default: `true`):: ++ +-- +Set `cfg(test)` for local crates. Defaults to true. +-- [[rust-analyzer.checkOnSave]]rust-analyzer.checkOnSave (default: `true`):: + -- diff --git a/src/tools/rust-analyzer/editors/code/package.json b/src/tools/rust-analyzer/editors/code/package.json index 869bcb65c49c5..a823e5bb96c36 100644 --- a/src/tools/rust-analyzer/editors/code/package.json +++ b/src/tools/rust-analyzer/editors/code/package.json @@ -853,6 +853,16 @@ } } }, + { + "title": "cfg", + "properties": { + "rust-analyzer.cfg.setTest": { + "markdownDescription": "Set `cfg(test)` for local crates. Defaults to true.", + "default": true, + "type": "boolean" + } + } + }, { "title": "general", "properties": { diff --git a/src/tools/rust-analyzer/editors/code/src/config.ts b/src/tools/rust-analyzer/editors/code/src/config.ts index 59ef132b1e46d..abb4099f9f5eb 100644 --- a/src/tools/rust-analyzer/editors/code/src/config.ts +++ b/src/tools/rust-analyzer/editors/code/src/config.ts @@ -24,6 +24,7 @@ export class Config { "serverPath", "server", "files", + "cfg", ].map((opt) => `${this.rootSection}.${opt}`); private readonly requiresWindowReloadOpts = ["testExplorer"].map( From 91834ec7197efeff7dabcea0091937e3ce0f4d2b Mon Sep 17 00:00:00 2001 From: Chayim Refael Friedman Date: Mon, 9 Sep 2024 23:54:22 +0300 Subject: [PATCH 1715/2194] Gate `#[test]` expansion under `cfg(test)`. This will mean users opting to not activate `cfg(test)` will lose IDE experience on them, which is quite unfortunate, but this is unavoidable if we want to avoid false positives on e.g. diagnostics. The real fix is to provide IDE experience even for cfg'ed out code, but this is out of scope for this PR. --- src/tools/rust-analyzer/crates/cfg/src/lib.rs | 4 +++ .../crates/hir-def/src/nameres/collector.rs | 14 ++++++-- .../hir-expand/src/builtin/attr_macro.rs | 21 +++++++++-- .../crates/load-cargo/src/lib.rs | 5 +-- .../project-model/src/cargo_workspace.rs | 1 + .../crates/project-model/src/tests.rs | 4 +-- .../crates/project-model/src/workspace.rs | 35 ++++++++++++------- .../rust-analyzer/src/cli/analysis_stats.rs | 2 +- .../rust-analyzer/src/cli/diagnostics.rs | 2 -- .../crates/rust-analyzer/src/cli/lsif.rs | 2 +- .../crates/rust-analyzer/src/cli/run_tests.rs | 2 +- .../rust-analyzer/src/cli/rustc_tests.rs | 3 +- .../crates/rust-analyzer/src/cli/scip.rs | 1 - .../crates/rust-analyzer/src/cli/ssr.rs | 6 ++-- .../crates/rust-analyzer/src/config.rs | 5 +++ .../src/integrated_benchmarks.rs | 6 ++-- .../crates/rust-analyzer/src/reload.rs | 10 ++---- 17 files changed, 78 insertions(+), 45 deletions(-) diff --git a/src/tools/rust-analyzer/crates/cfg/src/lib.rs b/src/tools/rust-analyzer/crates/cfg/src/lib.rs index e9daaf7de3c3b..c2d4008605618 100644 --- a/src/tools/rust-analyzer/crates/cfg/src/lib.rs +++ b/src/tools/rust-analyzer/crates/cfg/src/lib.rs @@ -49,6 +49,10 @@ impl CfgOptions { cfg.fold(&|atom| self.enabled.contains(atom)) } + pub fn check_atom(&self, cfg: &CfgAtom) -> bool { + self.enabled.contains(cfg) + } + pub fn insert_atom(&mut self, key: Symbol) { self.enabled.insert(CfgAtom::Flag(key)); } diff --git a/src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs b/src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs index e09ef4f205d3c..7f1d19719dab7 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs @@ -6,7 +6,7 @@ use std::{cmp::Ordering, iter, mem, ops::Not}; use base_db::{CrateId, CrateOrigin, Dependency, LangCrateOrigin}; -use cfg::{CfgExpr, CfgOptions}; +use cfg::{CfgAtom, CfgExpr, CfgOptions}; use either::Either; use hir_expand::{ attrs::{Attr, AttrId}, @@ -1324,13 +1324,21 @@ impl DefCollector<'_> { }; // Skip #[test]/#[bench] expansion, which would merely result in more memory usage - // due to duplicating functions into macro expansions + // due to duplicating functions into macro expansions, but only if `cfg(test)` is active, + // otherwise they are expanded to nothing and this can impact e.g. diagnostics (due to things + // being cfg'ed out). + // Ideally we will just expand them to nothing here. But we are only collecting macro calls, + // not expanding them, so we have no way to do that. if matches!( def.kind, MacroDefKind::BuiltInAttr(_, expander) if expander.is_test() || expander.is_bench() ) { - return recollect_without(self); + let test_is_active = + self.cfg_options.check_atom(&CfgAtom::Flag(sym::test.clone())); + if test_is_active { + return recollect_without(self); + } } let call_id = || { diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/builtin/attr_macro.rs b/src/tools/rust-analyzer/crates/hir-expand/src/builtin/attr_macro.rs index b9afc666f7528..2a8691b461c05 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/builtin/attr_macro.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/builtin/attr_macro.rs @@ -4,6 +4,8 @@ use span::{MacroCallId, Span}; use crate::{db::ExpandDatabase, name, tt, ExpandResult, MacroCallKind}; +use super::quote; + macro_rules! register_builtin { ($(($name:ident, $variant:ident) => $expand:ident),* ) => { #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] @@ -52,15 +54,15 @@ impl BuiltinAttrExpander { } register_builtin! { - (bench, Bench) => dummy_attr_expand, + (bench, Bench) => dummy_gate_test_expand, (cfg_accessible, CfgAccessible) => dummy_attr_expand, (cfg_eval, CfgEval) => dummy_attr_expand, (derive, Derive) => derive_expand, // derive const is equivalent to derive for our proposes. (derive_const, DeriveConst) => derive_expand, (global_allocator, GlobalAllocator) => dummy_attr_expand, - (test, Test) => dummy_attr_expand, - (test_case, TestCase) => dummy_attr_expand + (test, Test) => dummy_gate_test_expand, + (test_case, TestCase) => dummy_gate_test_expand } pub fn find_builtin_attr(ident: &name::Name) -> Option { @@ -76,6 +78,19 @@ fn dummy_attr_expand( ExpandResult::ok(tt.clone()) } +fn dummy_gate_test_expand( + _db: &dyn ExpandDatabase, + _id: MacroCallId, + tt: &tt::Subtree, + span: Span, +) -> ExpandResult { + let result = quote::quote! { span=> + #[cfg(test)] + #tt + }; + ExpandResult::ok(result) +} + /// We generate a very specific expansion here, as we do not actually expand the `#[derive]` attribute /// itself in name res, but we do want to expand it to something for the IDE layer, so that the input /// derive attributes can be downmapped, and resolved as proper paths. diff --git a/src/tools/rust-analyzer/crates/load-cargo/src/lib.rs b/src/tools/rust-analyzer/crates/load-cargo/src/lib.rs index 409f532c3e126..0e1606a699110 100644 --- a/src/tools/rust-analyzer/crates/load-cargo/src/lib.rs +++ b/src/tools/rust-analyzer/crates/load-cargo/src/lib.rs @@ -30,7 +30,6 @@ pub struct LoadCargoConfig { pub load_out_dirs_from_check: bool, pub with_proc_macro_server: ProcMacroServerChoice, pub prefill_caches: bool, - pub set_test: bool, } #[derive(Debug, Clone, PartialEq, Eq)] @@ -100,7 +99,6 @@ pub fn load_workspace( vfs.file_id(&path) }, extra_env, - load_config.set_test, ); let proc_macros = { let proc_macro_server = match &proc_macro_server { @@ -528,12 +526,11 @@ mod tests { #[test] fn test_loading_rust_analyzer() { let path = Path::new(env!("CARGO_MANIFEST_DIR")).parent().unwrap().parent().unwrap(); - let cargo_config = CargoConfig::default(); + let cargo_config = CargoConfig { set_test: true, ..CargoConfig::default() }; let load_cargo_config = LoadCargoConfig { load_out_dirs_from_check: false, with_proc_macro_server: ProcMacroServerChoice::None, prefill_caches: false, - set_test: true, }; let (db, _vfs, _proc_macro) = load_workspace_at(path, &cargo_config, &load_cargo_config, &|_| {}).unwrap(); diff --git a/src/tools/rust-analyzer/crates/project-model/src/cargo_workspace.rs b/src/tools/rust-analyzer/crates/project-model/src/cargo_workspace.rs index 7cc21bcf13191..2dc6f0357e3d8 100644 --- a/src/tools/rust-analyzer/crates/project-model/src/cargo_workspace.rs +++ b/src/tools/rust-analyzer/crates/project-model/src/cargo_workspace.rs @@ -100,6 +100,7 @@ pub struct CargoConfig { pub invocation_strategy: InvocationStrategy, /// Optional path to use instead of `target` when building pub target_dir: Option, + pub set_test: bool, } pub type Package = Idx; diff --git a/src/tools/rust-analyzer/crates/project-model/src/tests.rs b/src/tools/rust-analyzer/crates/project-model/src/tests.rs index cccfe3bb51e76..5099697a6963c 100644 --- a/src/tools/rust-analyzer/crates/project-model/src/tests.rs +++ b/src/tools/rust-analyzer/crates/project-model/src/tests.rs @@ -35,6 +35,7 @@ fn load_cargo_with_overrides( rustc: Err(None), cargo_config_extra_env: Default::default(), error: None, + set_test: true, }, cfg_overrides, sysroot: Sysroot::empty(), @@ -136,7 +137,6 @@ fn to_crate_graph(project_workspace: ProjectWorkspace) -> (CrateGraph, ProcMacro } }, &Default::default(), - true, ) } @@ -243,6 +243,7 @@ fn smoke_test_real_sysroot_cargo() { rustc: Err(None), cargo_config_extra_env: Default::default(), error: None, + set_test: true, }, sysroot, rustc_cfg: Vec::new(), @@ -258,6 +259,5 @@ fn smoke_test_real_sysroot_cargo() { } }, &Default::default(), - true, ); } diff --git a/src/tools/rust-analyzer/crates/project-model/src/workspace.rs b/src/tools/rust-analyzer/crates/project-model/src/workspace.rs index ed1f607309ef6..71b9b61e20594 100644 --- a/src/tools/rust-analyzer/crates/project-model/src/workspace.rs +++ b/src/tools/rust-analyzer/crates/project-model/src/workspace.rs @@ -78,6 +78,7 @@ pub enum ProjectWorkspaceKind { rustc: Result, Option>, /// Environment variables set in the `.cargo/config` file. cargo_config_extra_env: FxHashMap, + set_test: bool, }, /// Project workspace was specified using a `rust-project.json` file. Json(ProjectJson), @@ -98,6 +99,7 @@ pub enum ProjectWorkspaceKind { cargo: Option<(CargoWorkspace, WorkspaceBuildScripts, Option>)>, /// Environment variables set in the `.cargo/config` file. cargo_config_extra_env: FxHashMap, + set_test: bool, }, } @@ -112,6 +114,7 @@ impl fmt::Debug for ProjectWorkspace { build_scripts, rustc, cargo_config_extra_env, + set_test, } => f .debug_struct("Cargo") .field("root", &cargo.workspace_root().file_name()) @@ -126,6 +129,7 @@ impl fmt::Debug for ProjectWorkspace { .field("toolchain", &toolchain) .field("data_layout", &target_layout) .field("cargo_config_extra_env", &cargo_config_extra_env) + .field("set_test", set_test) .field("build_scripts", &build_scripts.error().unwrap_or("ok")) .finish(), ProjectWorkspaceKind::Json(project) => { @@ -137,12 +141,14 @@ impl fmt::Debug for ProjectWorkspace { .field("toolchain", &toolchain) .field("data_layout", &target_layout) .field("n_cfg_overrides", &cfg_overrides.len()); + debug_struct.finish() } ProjectWorkspaceKind::DetachedFile { file, cargo: cargo_script, cargo_config_extra_env, + set_test, } => f .debug_struct("DetachedFiles") .field("file", &file) @@ -154,6 +160,7 @@ impl fmt::Debug for ProjectWorkspace { .field("data_layout", &target_layout) .field("n_cfg_overrides", &cfg_overrides.len()) .field("cargo_config_extra_env", &cargo_config_extra_env) + .field("set_test", set_test) .finish(), } } @@ -329,6 +336,7 @@ impl ProjectWorkspace { rustc, cargo_config_extra_env, error: error.map(Arc::new), + set_test: config.set_test, }, sysroot, rustc_cfg, @@ -423,6 +431,7 @@ impl ProjectWorkspace { file: detached_file.to_owned(), cargo: cargo_script, cargo_config_extra_env, + set_test: config.set_test, }, sysroot, rustc_cfg, @@ -609,6 +618,7 @@ impl ProjectWorkspace { build_scripts, cargo_config_extra_env: _, error: _, + set_test: _, } => { cargo .packages() @@ -728,7 +738,6 @@ impl ProjectWorkspace { &self, load: FileLoader<'_>, extra_env: &FxHashMap, - set_test: bool, ) -> (CrateGraph, ProcMacroPaths) { let _p = tracing::info_span!("ProjectWorkspace::to_crate_graph").entered(); @@ -742,7 +751,6 @@ impl ProjectWorkspace { sysroot, extra_env, cfg_overrides, - set_test, ), sysroot, ), @@ -752,6 +760,7 @@ impl ProjectWorkspace { build_scripts, cargo_config_extra_env: _, error: _, + set_test, } => ( cargo_to_crate_graph( load, @@ -761,11 +770,11 @@ impl ProjectWorkspace { rustc_cfg.clone(), cfg_overrides, build_scripts, - set_test, + *set_test, ), sysroot, ), - ProjectWorkspaceKind::DetachedFile { file, cargo: cargo_script, .. } => ( + ProjectWorkspaceKind::DetachedFile { file, cargo: cargo_script, set_test, .. } => ( if let Some((cargo, build_scripts, _)) = cargo_script { cargo_to_crate_graph( &mut |path| load(path), @@ -775,7 +784,7 @@ impl ProjectWorkspace { rustc_cfg.clone(), cfg_overrides, build_scripts, - set_test, + *set_test, ) } else { detached_file_to_crate_graph( @@ -784,7 +793,7 @@ impl ProjectWorkspace { file, sysroot, cfg_overrides, - set_test, + *set_test, ) }, sysroot, @@ -818,6 +827,7 @@ impl ProjectWorkspace { cargo_config_extra_env, build_scripts: _, error: _, + set_test: _, }, ProjectWorkspaceKind::Cargo { cargo: o_cargo, @@ -825,6 +835,7 @@ impl ProjectWorkspace { cargo_config_extra_env: o_cargo_config_extra_env, build_scripts: _, error: _, + set_test: _, }, ) => { cargo == o_cargo @@ -839,11 +850,13 @@ impl ProjectWorkspace { file, cargo: Some((cargo_script, _, _)), cargo_config_extra_env, + set_test: _, }, ProjectWorkspaceKind::DetachedFile { file: o_file, cargo: Some((o_cargo_script, _, _)), cargo_config_extra_env: o_cargo_config_extra_env, + set_test: _, }, ) => { file == o_file @@ -875,12 +888,11 @@ fn project_json_to_crate_graph( sysroot: &Sysroot, extra_env: &FxHashMap, override_cfg: &CfgOverrides, - set_test: bool, ) -> (CrateGraph, ProcMacroPaths) { let mut res = (CrateGraph::default(), ProcMacroPaths::default()); let (crate_graph, proc_macros) = &mut res; let (public_deps, libproc_macro) = - sysroot_to_crate_graph(crate_graph, sysroot, rustc_cfg.clone(), load, set_test); + sysroot_to_crate_graph(crate_graph, sysroot, rustc_cfg.clone(), load); let r_a_cfg_flag = CfgAtom::Flag(sym::rust_analyzer.clone()); let mut cfg_cache: FxHashMap<&str, Vec> = FxHashMap::default(); @@ -1000,7 +1012,7 @@ fn cargo_to_crate_graph( let crate_graph = &mut res.0; let proc_macros = &mut res.1; let (public_deps, libproc_macro) = - sysroot_to_crate_graph(crate_graph, sysroot, rustc_cfg.clone(), load, set_test); + sysroot_to_crate_graph(crate_graph, sysroot, rustc_cfg.clone(), load); let cfg_options = CfgOptions::from_iter(rustc_cfg); @@ -1187,7 +1199,7 @@ fn detached_file_to_crate_graph( let _p = tracing::info_span!("detached_file_to_crate_graph").entered(); let mut crate_graph = CrateGraph::default(); let (public_deps, _libproc_macro) = - sysroot_to_crate_graph(&mut crate_graph, sysroot, rustc_cfg.clone(), load, set_test); + sysroot_to_crate_graph(&mut crate_graph, sysroot, rustc_cfg.clone(), load); let mut cfg_options = CfgOptions::from_iter(rustc_cfg); if set_test { @@ -1416,7 +1428,6 @@ fn sysroot_to_crate_graph( sysroot: &Sysroot, rustc_cfg: Vec, load: FileLoader<'_>, - set_test: bool, ) -> (SysrootPublicDeps, Option) { let _p = tracing::info_span!("sysroot_to_crate_graph").entered(); match sysroot.mode() { @@ -1439,7 +1450,7 @@ fn sysroot_to_crate_graph( ..Default::default() }, &WorkspaceBuildScripts::default(), - set_test, + false, ); let mut pub_deps = vec![]; diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/analysis_stats.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/analysis_stats.rs index 033a7d10d9d25..9a484a5a5b0c9 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/analysis_stats.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/analysis_stats.rs @@ -65,6 +65,7 @@ impl flags::AnalysisStats { false => Some(RustLibSource::Discover), }, all_targets: true, + set_test: true, ..Default::default() }; let no_progress = &|_| (); @@ -84,7 +85,6 @@ impl flags::AnalysisStats { ProcMacroServerChoice::Sysroot }, prefill_caches: false, - set_test: true, }; let build_scripts_time = if self.disable_build_scripts { diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/diagnostics.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/diagnostics.rs index 91fa312f33e9d..28f25975d64aa 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/diagnostics.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/diagnostics.rs @@ -39,8 +39,6 @@ impl flags::Diagnostics { load_out_dirs_from_check: !self.disable_build_scripts, with_proc_macro_server, prefill_caches: false, - // We don't pass `--all-targets` so we also set `cfg(test)` to false. - set_test: false, }; let (db, _vfs, _proc_macro) = load_workspace_at(&self.path, &cargo_config, &load_cargo_config, &|_| {})?; diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/lsif.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/lsif.rs index 197dbd86141db..ca8acf57bff69 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/lsif.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/lsif.rs @@ -277,6 +277,7 @@ impl flags::Lsif { let cargo_config = &CargoConfig { sysroot: Some(RustLibSource::Discover), all_targets: true, + set_test: true, ..Default::default() }; let no_progress = &|_| (); @@ -284,7 +285,6 @@ impl flags::Lsif { load_out_dirs_from_check: true, with_proc_macro_server: ProcMacroServerChoice::Sysroot, prefill_caches: false, - set_test: true, }; let path = AbsPathBuf::assert_utf8(env::current_dir()?.join(self.path)); let root = ProjectManifest::discover_single(&path)?; diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/run_tests.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/run_tests.rs index 3afee41580b2b..11534bbeba9ad 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/run_tests.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/run_tests.rs @@ -16,13 +16,13 @@ impl flags::RunTests { let cargo_config = CargoConfig { sysroot: Some(RustLibSource::Discover), all_targets: true, + set_test: true, ..Default::default() }; let load_cargo_config = LoadCargoConfig { load_out_dirs_from_check: true, with_proc_macro_server: ProcMacroServerChoice::Sysroot, prefill_caches: false, - set_test: true, }; let (ref db, _vfs, _proc_macro) = load_workspace_at(&self.path, &cargo_config, &load_cargo_config, &|_| {})?; diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/rustc_tests.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/rustc_tests.rs index 0c148be1da1fc..30378db0b388b 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/rustc_tests.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/rustc_tests.rs @@ -70,6 +70,7 @@ impl Tester { let cargo_config = CargoConfig { sysroot: Some(RustLibSource::Discover), all_targets: true, + set_test: true, ..Default::default() }; @@ -85,6 +86,7 @@ impl Tester { file: ManifestPath::try_from(tmp_file).unwrap(), cargo: None, cargo_config_extra_env: Default::default(), + set_test: true, }, sysroot, rustc_cfg: vec![], @@ -96,7 +98,6 @@ impl Tester { load_out_dirs_from_check: false, with_proc_macro_server: ProcMacroServerChoice::Sysroot, prefill_caches: false, - set_test: true, }; let (db, _vfs, _proc_macro) = load_workspace(workspace, &cargo_config.extra_env, &load_cargo_config)?; diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/scip.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/scip.rs index 3d704d6f03ff5..ff009e69547a8 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/scip.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/scip.rs @@ -50,7 +50,6 @@ impl flags::Scip { load_out_dirs_from_check: true, with_proc_macro_server: ProcMacroServerChoice::Sysroot, prefill_caches: true, - set_test: config.cfg_set_test(None), }; let cargo_config = config.cargo(None); let (db, vfs, _) = load_workspace_at( diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/ssr.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/ssr.rs index 3a463b822f671..c03688e8009cb 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/ssr.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/ssr.rs @@ -13,13 +13,13 @@ impl flags::Ssr { let cargo_config = CargoConfig { sysroot: Some(RustLibSource::Discover), all_targets: true, + set_test: true, ..Default::default() }; let load_cargo_config = LoadCargoConfig { load_out_dirs_from_check: true, with_proc_macro_server: ProcMacroServerChoice::Sysroot, prefill_caches: false, - set_test: true, }; let (ref db, vfs, _proc_macro) = load_workspace_at( &std::env::current_dir()?, @@ -51,12 +51,12 @@ impl flags::Search { pub fn run(self) -> anyhow::Result<()> { use ide_db::base_db::SourceRootDatabase; use ide_db::symbol_index::SymbolsDatabase; - let cargo_config = CargoConfig { all_targets: true, ..CargoConfig::default() }; + let cargo_config = + CargoConfig { all_targets: true, set_test: true, ..CargoConfig::default() }; let load_cargo_config = LoadCargoConfig { load_out_dirs_from_check: true, with_proc_macro_server: ProcMacroServerChoice::Sysroot, prefill_caches: false, - set_test: true, }; let (ref db, _vfs, _proc_macro) = load_workspace_at( &std::env::current_dir()?, diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs index 97799abb14540..2be71ef92a32c 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs @@ -1861,9 +1861,14 @@ impl Config { extra_args: self.cargo_extraArgs(source_root).clone(), extra_env: self.cargo_extraEnv(source_root).clone(), target_dir: self.target_dir_from_config(source_root), + set_test: *self.cfg_setTest(source_root), } } + pub fn cfg_set_test(&self, source_root: Option) -> bool { + *self.cfg_setTest(source_root) + } + pub(crate) fn completion_snippets_default() -> FxHashMap { serde_json::from_str( r#"{ diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/integrated_benchmarks.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/integrated_benchmarks.rs index b98da50b420d0..8a4f9d49fef93 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/integrated_benchmarks.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/integrated_benchmarks.rs @@ -37,13 +37,13 @@ fn integrated_highlighting_benchmark() { let cargo_config = CargoConfig { sysroot: Some(project_model::RustLibSource::Discover), all_targets: true, + set_test: true, ..CargoConfig::default() }; let load_cargo_config = LoadCargoConfig { load_out_dirs_from_check: true, with_proc_macro_server: ProcMacroServerChoice::Sysroot, prefill_caches: false, - set_test: true, }; let (db, vfs, _proc_macro) = { @@ -105,13 +105,13 @@ fn integrated_completion_benchmark() { let cargo_config = CargoConfig { sysroot: Some(project_model::RustLibSource::Discover), all_targets: true, + set_test: true, ..CargoConfig::default() }; let load_cargo_config = LoadCargoConfig { load_out_dirs_from_check: true, with_proc_macro_server: ProcMacroServerChoice::Sysroot, prefill_caches: true, - set_test: true, }; let (db, vfs, _proc_macro) = { @@ -284,13 +284,13 @@ fn integrated_diagnostics_benchmark() { let cargo_config = CargoConfig { sysroot: Some(project_model::RustLibSource::Discover), all_targets: true, + set_test: true, ..CargoConfig::default() }; let load_cargo_config = LoadCargoConfig { load_out_dirs_from_check: true, with_proc_macro_server: ProcMacroServerChoice::Sysroot, prefill_caches: true, - set_test: true, }; let (db, vfs, _proc_macro) = { diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/reload.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/reload.rs index 830a3d7f3d920..7a1782e5651bd 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/reload.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/reload.rs @@ -703,12 +703,7 @@ impl GlobalState { vfs.file_id(&vfs_path) }; - ws_to_crate_graph( - &self.workspaces, - self.config.extra_env(None), - load, - self.config.cfg_set_test(None), - ) + ws_to_crate_graph(&self.workspaces, self.config.extra_env(None), load) }; let mut change = ChangeWithProcMacros::new(); if self.config.expand_proc_macros() { @@ -861,13 +856,12 @@ pub fn ws_to_crate_graph( workspaces: &[ProjectWorkspace], extra_env: &FxHashMap, mut load: impl FnMut(&AbsPath) -> Option, - set_test: bool, ) -> (CrateGraph, Vec, FxHashMap>) { let mut crate_graph = CrateGraph::default(); let mut proc_macro_paths = Vec::default(); let mut ws_data = FxHashMap::default(); for ws in workspaces { - let (other, mut crate_proc_macros) = ws.to_crate_graph(&mut load, extra_env, set_test); + let (other, mut crate_proc_macros) = ws.to_crate_graph(&mut load, extra_env); let ProjectWorkspace { toolchain, target_layout, .. } = ws; let mapping = crate_graph.extend(other, &mut crate_proc_macros); From 54e4761d0526cd314140f1899c54129270295f5e Mon Sep 17 00:00:00 2001 From: Samuel Moelius Date: Sun, 29 Sep 2024 18:21:47 -0400 Subject: [PATCH 1716/2194] Address review comment https://github.com/rust-lang/rust-clippy/pull/13286#discussion_r1780038602 --- clippy_lints/src/lifetimes.rs | 38 ++++++++++++----------------------- 1 file changed, 13 insertions(+), 25 deletions(-) diff --git a/clippy_lints/src/lifetimes.rs b/clippy_lints/src/lifetimes.rs index 37d244ff53d30..034cab7202523 100644 --- a/clippy_lints/src/lifetimes.rs +++ b/clippy_lints/src/lifetimes.rs @@ -506,8 +506,17 @@ struct LifetimeChecker<'cx, 'tcx, F> { } impl<'cx, 'tcx, F> LifetimeChecker<'cx, 'tcx, F> { - fn new(cx: &'cx LateContext<'tcx>, def_ids: Vec) -> LifetimeChecker<'cx, 'tcx, F> { - let map = def_ids.into_iter().map(|def_id| (def_id, Vec::new())).collect(); + fn new(cx: &'cx LateContext<'tcx>, generics: &'tcx Generics<'_>) -> LifetimeChecker<'cx, 'tcx, F> { + let map = generics + .params + .iter() + .filter_map(|par| match par.kind { + GenericParamKind::Lifetime { + kind: LifetimeParamKind::Explicit, + } => Some((par.def_id, Vec::new())), + _ => None, + }) + .collect(); Self { cx, map, @@ -556,17 +565,7 @@ where } fn report_extra_lifetimes<'tcx>(cx: &LateContext<'tcx>, func: &'tcx FnDecl<'_>, generics: &'tcx Generics<'_>) { - let def_ids = generics - .params - .iter() - .filter_map(|par| match par.kind { - GenericParamKind::Lifetime { - kind: LifetimeParamKind::Explicit, - } => Some(par.def_id), - _ => None, - }) - .collect(); - let mut checker = LifetimeChecker::::new(cx, def_ids); + let mut checker = LifetimeChecker::::new(cx, generics); walk_generics(&mut checker, generics); walk_fn_decl(&mut checker, func); @@ -587,18 +586,7 @@ fn report_extra_lifetimes<'tcx>(cx: &LateContext<'tcx>, func: &'tcx FnDecl<'_>, } fn report_extra_impl_lifetimes<'tcx>(cx: &LateContext<'tcx>, impl_: &'tcx Impl<'_>) { - let def_ids = impl_ - .generics - .params - .iter() - .filter_map(|par| match par.kind { - GenericParamKind::Lifetime { - kind: LifetimeParamKind::Explicit, - } => Some(par.def_id), - _ => None, - }) - .collect(); - let mut checker = LifetimeChecker::::new(cx, def_ids); + let mut checker = LifetimeChecker::::new(cx, impl_.generics); walk_generics(&mut checker, impl_.generics); if let Some(ref trait_ref) = impl_.of_trait { From bc2a913a9bb89b137a43cc761793ae70886dfd14 Mon Sep 17 00:00:00 2001 From: Manuel Drehwald Date: Sun, 29 Sep 2024 18:27:33 -0400 Subject: [PATCH 1717/2194] add has_enzyme/needs-enzyme to the test infra --- src/bootstrap/src/core/build_steps/test.rs | 4 ++++ src/tools/compiletest/src/command-list.rs | 1 + src/tools/compiletest/src/common.rs | 3 +++ src/tools/compiletest/src/header.rs | 3 +++ src/tools/compiletest/src/header/needs.rs | 5 +++++ src/tools/compiletest/src/lib.rs | 3 +++ 6 files changed, 19 insertions(+) diff --git a/src/bootstrap/src/core/build_steps/test.rs b/src/bootstrap/src/core/build_steps/test.rs index 870fe6a9f1658..7283b0e9574c5 100644 --- a/src/bootstrap/src/core/build_steps/test.rs +++ b/src/bootstrap/src/core/build_steps/test.rs @@ -1792,6 +1792,10 @@ NOTE: if you're sure you want to do this, please open an issue as to why. In the cmd.arg("--host").arg(&*compiler.host.triple); cmd.arg("--llvm-filecheck").arg(builder.llvm_filecheck(builder.config.build)); + if builder.build.config.llvm_enzyme { + cmd.arg("--has-enzyme"); + } + if builder.config.cmd.bless() { cmd.arg("--bless"); } diff --git a/src/tools/compiletest/src/command-list.rs b/src/tools/compiletest/src/command-list.rs index 865aa76ddb0c7..a4cedbf66e2ad 100644 --- a/src/tools/compiletest/src/command-list.rs +++ b/src/tools/compiletest/src/command-list.rs @@ -139,6 +139,7 @@ const KNOWN_DIRECTIVE_NAMES: &[&str] = &[ "needs-deterministic-layouts", "needs-dlltool", "needs-dynamic-linking", + "needs-enzyme", "needs-force-clang-based-tests", "needs-git-hash", "needs-llvm-components", diff --git a/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs index 2d8c0c3fa5eb6..adc89cad72f89 100644 --- a/src/tools/compiletest/src/common.rs +++ b/src/tools/compiletest/src/common.rs @@ -349,6 +349,9 @@ pub struct Config { /// whether to run `tidy` when a rustdoc test fails pub has_tidy: bool, + /// whether to run `enzyme` autodiff tests + pub has_enzyme: bool, + /// The current Rust channel pub channel: String, diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs index 6a889d277934b..83a10c5620864 100644 --- a/src/tools/compiletest/src/header.rs +++ b/src/tools/compiletest/src/header.rs @@ -218,6 +218,8 @@ pub struct TestProps { pub filecheck_flags: Vec, /// Don't automatically insert any `--check-cfg` args pub no_auto_check_cfg: bool, + /// Run tests which require enzyme being build + pub has_enzyme: bool, } mod directives { @@ -322,6 +324,7 @@ impl TestProps { llvm_cov_flags: vec![], filecheck_flags: vec![], no_auto_check_cfg: false, + has_enzyme: false, } } diff --git a/src/tools/compiletest/src/header/needs.rs b/src/tools/compiletest/src/header/needs.rs index 99c0e850f1a24..f5dd722ed3711 100644 --- a/src/tools/compiletest/src/header/needs.rs +++ b/src/tools/compiletest/src/header/needs.rs @@ -79,6 +79,11 @@ pub(super) fn handle_needs( condition: cache.sanitizer_safestack, ignore_reason: "ignored on targets without SafeStack support", }, + Need { + name: "needs-enzyme", + condition: config.has_enzyme, + ignore_reason: "ignored when LLVM Enzyme is disabled", + }, Need { name: "needs-run-enabled", condition: config.run_enabled(), diff --git a/src/tools/compiletest/src/lib.rs b/src/tools/compiletest/src/lib.rs index cfc619f934208..a8355ee9590d6 100644 --- a/src/tools/compiletest/src/lib.rs +++ b/src/tools/compiletest/src/lib.rs @@ -83,6 +83,7 @@ pub fn parse_config(args: Vec) -> Config { ) .optopt("", "run", "whether to execute run-* tests", "auto | always | never") .optflag("", "ignored", "run tests marked as ignored") + .optflag("", "has-enzyme", "run tests that require enzyme") .optflag("", "with-debug-assertions", "whether to run tests with `ignore-debug` header") .optmulti( "", @@ -233,6 +234,7 @@ pub fn parse_config(args: Vec) -> Config { // Avoid spawning an external command when we know tidy won't be used. false }; + let has_enzyme = matches.opt_present("has-enzyme"); let filters = if mode == Mode::RunMake { matches .free @@ -331,6 +333,7 @@ pub fn parse_config(args: Vec) -> Config { .map(|s| s.parse().expect("invalid --compare-mode provided")), rustfix_coverage: matches.opt_present("rustfix-coverage"), has_tidy, + has_enzyme, channel: matches.opt_str("channel").unwrap(), git_hash: matches.opt_present("git-hash"), edition: matches.opt_str("edition"), From c5598d6a9e0e8a46775f2c69e1278efee8223425 Mon Sep 17 00:00:00 2001 From: Barrett Ray Date: Sun, 29 Sep 2024 15:28:11 -0500 Subject: [PATCH 1718/2194] fix(hir_analysis/wfcheck): don't leak {type error} avoid `{type error}` being leaked in user-facing messages, particularly when using the `adt_const_params` feature --- .../rustc_hir_analysis/src/check/wfcheck.rs | 17 ++-- .../suggest_feature_only_when_possible.stderr | 18 ++-- .../const-param-elided-lifetime.full.stderr | 8 +- .../const-param-elided-lifetime.min.stderr | 90 ++----------------- .../const-param-elided-lifetime.rs | 5 -- ...ram-type-depends-on-const-param.min.stderr | 4 +- .../const-generics/default-ty-closure.stderr | 2 +- .../float-generic.simple.stderr | 2 +- .../fn-const-param-call.min.stderr | 4 +- .../fn-const-param-infer.min.stderr | 2 +- ...ay-size-in-generic-struct-param.min.stderr | 2 +- .../generic_const_exprs/error_in_ty.stderr | 2 +- .../unevaluated-const-ice-119731.stderr | 2 +- .../ice-118285-fn-ptr-value.stderr | 2 +- ...ics-type_name-as-const-argument.min.stderr | 2 +- .../issues/issue-56445-1.min.stderr | 18 +--- .../ui/const-generics/issues/issue-56445-1.rs | 1 - .../issues/issue-62878.min.stderr | 2 +- .../issues/issue-63322-forbid-dyn.min.stderr | 2 +- .../issues/issue-68366.full.stderr | 2 +- .../issues/issue-68366.min.stderr | 2 +- .../issues/issue-68615-adt.min.stderr | 2 +- .../issues/issue-68615-array.min.stderr | 2 +- .../issues/issue-71169.min.stderr | 2 +- .../issues/issue-71381.min.stderr | 4 +- .../issues/issue-71382.min.stderr | 2 +- .../issues/issue-71611.min.stderr | 2 +- .../issues/issue-72352.min.stderr | 2 +- .../issues/issue-73491.min.stderr | 2 +- ...tic-reference-array-const-param.min.stderr | 2 +- .../issues/issue-74101.min.stderr | 4 +- .../issues/issue-74255.min.stderr | 2 +- .../issues/issue-74950.min.stderr | 8 +- .../issues/issue-75047.min.stderr | 2 +- .../const-generics/lifetime-in-const-param.rs | 1 - .../lifetime-in-const-param.stderr | 14 +-- .../min_const_generics/complex-types.stderr | 14 +-- .../ui/const-generics/nested-type.min.stderr | 2 +- .../const-generics/not_wf_param_in_rpitit.rs | 1 - .../not_wf_param_in_rpitit.stderr | 16 +--- tests/ui/const-generics/opaque_types.stderr | 2 +- .../projection-as-arg-const.stderr | 2 +- .../raw-ptr-const-param-deref.min.stderr | 4 +- .../raw-ptr-const-param.min.stderr | 2 +- .../slice-const-param-mismatch.min.stderr | 4 +- .../std/const-generics-range.min.stderr | 12 +-- ...te-const-param-static-reference.min.stderr | 2 +- .../type-dependent/issue-71348.min.stderr | 4 +- .../type-dependent/issue-71382.stderr | 2 +- tests/ui/consts/issue-103790.rs | 1 - tests/ui/consts/issue-103790.stderr | 16 +--- .../feature-gate-adt_const_params.stderr | 2 +- .../feature-gate-unsized-const-params.stderr | 2 +- .../generic-const-items/elided-lifetimes.rs | 1 - .../elided-lifetimes.stderr | 20 +---- .../wfcheck_err_leak_issue_118179.rs | 7 ++ .../wfcheck_err_leak_issue_118179.stderr | 11 +++ .../ui/lifetimes/unusual-rib-combinations.rs | 2 - .../lifetimes/unusual-rib-combinations.stderr | 32 +------ .../effects/mismatched_generic_args.stderr | 6 +- ...oj-ty-as-type-of-const-issue-125757.stderr | 2 +- ...st-region-infer-to-static-in-binder.stderr | 4 +- .../const_generic_type.infer.stderr | 2 +- .../const_generic_type.no_infer.stderr | 2 +- .../ice-unexpected-region-123863.stderr | 4 +- ...ce-hir-wf-check-anon-const-issue-122199.rs | 2 - ...ir-wf-check-anon-const-issue-122199.stderr | 44 +++------ ...ir-wf-check-anon-const-issue-122989.stderr | 4 +- 68 files changed, 147 insertions(+), 324 deletions(-) create mode 100644 tests/ui/generic-const-items/wfcheck_err_leak_issue_118179.rs create mode 100644 tests/ui/generic-const-items/wfcheck_err_leak_issue_118179.stderr diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index a71e14ce463f6..70b0b3f5788ed 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -961,13 +961,20 @@ fn check_param_wf(tcx: TyCtxt<'_>, param: &hir::GenericParam<'_>) -> Result<(), hir_ty.span, "using raw pointers as const generic parameters is forbidden", ), - _ => tcx.dcx().struct_span_err( - hir_ty.span, - format!("`{}` is forbidden as the type of a const generic parameter", ty), - ), + _ => { + // Avoid showing "{type error}" to users. See #118179. + ty.error_reported()?; + + tcx.dcx().struct_span_err( + hir_ty.span, + format!( + "`{ty}` is forbidden as the type of a const generic parameter", + ), + ) + } }; - diag.note("the only supported types are integers, `bool` and `char`"); + diag.note("the only supported types are integers, `bool`, and `char`"); let cause = ObligationCause::misc(hir_ty.span, param.def_id); let adt_const_params_feature_string = diff --git a/tests/ui/const-generics/adt_const_params/suggest_feature_only_when_possible.stderr b/tests/ui/const-generics/adt_const_params/suggest_feature_only_when_possible.stderr index aafc0640dd2da..8c54aef36cac0 100644 --- a/tests/ui/const-generics/adt_const_params/suggest_feature_only_when_possible.stderr +++ b/tests/ui/const-generics/adt_const_params/suggest_feature_only_when_possible.stderr @@ -4,7 +4,7 @@ error: `&'static mut ()` is forbidden as the type of a const generic parameter LL | fn uwu_0() {} | ^^^^^^^^^^^^^^^ | - = note: the only supported types are integers, `bool` and `char` + = note: the only supported types are integers, `bool`, and `char` error: `&'static u32` is forbidden as the type of a const generic parameter --> $DIR/suggest_feature_only_when_possible.rs:15:19 @@ -12,7 +12,7 @@ error: `&'static u32` is forbidden as the type of a const generic parameter LL | fn owo_0() {} | ^^^^^^^^^^^^ | - = note: the only supported types are integers, `bool` and `char` + = note: the only supported types are integers, `bool`, and `char` help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types | LL + #![feature(adt_const_params)] @@ -28,7 +28,7 @@ error: `Meow` is forbidden as the type of a const generic parameter LL | fn meow_0() {} | ^^^^ | - = note: the only supported types are integers, `bool` and `char` + = note: the only supported types are integers, `bool`, and `char` help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types | LL + #![feature(adt_const_params)] @@ -40,7 +40,7 @@ error: `&'static Meow` is forbidden as the type of a const generic parameter LL | fn meow_1() {} | ^^^^^^^^^^^^^ | - = note: the only supported types are integers, `bool` and `char` + = note: the only supported types are integers, `bool`, and `char` help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types | LL + #![feature(adt_const_params)] @@ -56,7 +56,7 @@ error: `[Meow; 100]` is forbidden as the type of a const generic parameter LL | fn meow_2() {} | ^^^^^^^^^^^ | - = note: the only supported types are integers, `bool` and `char` + = note: the only supported types are integers, `bool`, and `char` error: `(Meow, u8)` is forbidden as the type of a const generic parameter --> $DIR/suggest_feature_only_when_possible.rs:29:20 @@ -64,7 +64,7 @@ error: `(Meow, u8)` is forbidden as the type of a const generic parameter LL | fn meow_3() {} | ^^^^^^^^^^ | - = note: the only supported types are integers, `bool` and `char` + = note: the only supported types are integers, `bool`, and `char` error: `(Meow, String)` is forbidden as the type of a const generic parameter --> $DIR/suggest_feature_only_when_possible.rs:34:20 @@ -72,7 +72,7 @@ error: `(Meow, String)` is forbidden as the type of a const generic parameter LL | fn meow_4() {} | ^^^^^^^^^^^^^^ | - = note: the only supported types are integers, `bool` and `char` + = note: the only supported types are integers, `bool`, and `char` error: `String` is forbidden as the type of a const generic parameter --> $DIR/suggest_feature_only_when_possible.rs:38:19 @@ -80,7 +80,7 @@ error: `String` is forbidden as the type of a const generic parameter LL | fn nya_0() {} | ^^^^^^ | - = note: the only supported types are integers, `bool` and `char` + = note: the only supported types are integers, `bool`, and `char` error: `Vec` is forbidden as the type of a const generic parameter --> $DIR/suggest_feature_only_when_possible.rs:40:19 @@ -88,7 +88,7 @@ error: `Vec` is forbidden as the type of a const generic parameter LL | fn nya_1>() {} | ^^^^^^^^ | - = note: the only supported types are integers, `bool` and `char` + = note: the only supported types are integers, `bool`, and `char` error: aborting due to 9 previous errors diff --git a/tests/ui/const-generics/const-param-elided-lifetime.full.stderr b/tests/ui/const-generics/const-param-elided-lifetime.full.stderr index d6753a74f8574..34510f546c874 100644 --- a/tests/ui/const-generics/const-param-elided-lifetime.full.stderr +++ b/tests/ui/const-generics/const-param-elided-lifetime.full.stderr @@ -5,25 +5,25 @@ LL | struct A; | ^ explicit lifetime name needed here error[E0637]: `&` without an explicit lifetime name cannot be used here - --> $DIR/const-param-elided-lifetime.rs:14:15 + --> $DIR/const-param-elided-lifetime.rs:13:15 | LL | impl A { | ^ explicit lifetime name needed here error[E0637]: `&` without an explicit lifetime name cannot be used here - --> $DIR/const-param-elided-lifetime.rs:17:21 + --> $DIR/const-param-elided-lifetime.rs:15:21 | LL | fn foo(&self) {} | ^ explicit lifetime name needed here error[E0637]: `&` without an explicit lifetime name cannot be used here - --> $DIR/const-param-elided-lifetime.rs:22:15 + --> $DIR/const-param-elided-lifetime.rs:19:15 | LL | impl B for A {} | ^ explicit lifetime name needed here error[E0637]: `&` without an explicit lifetime name cannot be used here - --> $DIR/const-param-elided-lifetime.rs:26:17 + --> $DIR/const-param-elided-lifetime.rs:22:17 | LL | fn bar() {} | ^ explicit lifetime name needed here diff --git a/tests/ui/const-generics/const-param-elided-lifetime.min.stderr b/tests/ui/const-generics/const-param-elided-lifetime.min.stderr index 62267224738d0..34510f546c874 100644 --- a/tests/ui/const-generics/const-param-elided-lifetime.min.stderr +++ b/tests/ui/const-generics/const-param-elided-lifetime.min.stderr @@ -5,109 +5,29 @@ LL | struct A; | ^ explicit lifetime name needed here error[E0637]: `&` without an explicit lifetime name cannot be used here - --> $DIR/const-param-elided-lifetime.rs:14:15 + --> $DIR/const-param-elided-lifetime.rs:13:15 | LL | impl A { | ^ explicit lifetime name needed here error[E0637]: `&` without an explicit lifetime name cannot be used here - --> $DIR/const-param-elided-lifetime.rs:17:21 + --> $DIR/const-param-elided-lifetime.rs:15:21 | LL | fn foo(&self) {} | ^ explicit lifetime name needed here error[E0637]: `&` without an explicit lifetime name cannot be used here - --> $DIR/const-param-elided-lifetime.rs:22:15 + --> $DIR/const-param-elided-lifetime.rs:19:15 | LL | impl B for A {} | ^ explicit lifetime name needed here error[E0637]: `&` without an explicit lifetime name cannot be used here - --> $DIR/const-param-elided-lifetime.rs:26:17 + --> $DIR/const-param-elided-lifetime.rs:22:17 | LL | fn bar() {} | ^ explicit lifetime name needed here -error: `&u8` is forbidden as the type of a const generic parameter - --> $DIR/const-param-elided-lifetime.rs:9:19 - | -LL | struct A; - | ^^^ - | - = note: the only supported types are integers, `bool` and `char` -help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types - | -LL + #![feature(adt_const_params)] - | -help: add `#![feature(unsized_const_params)]` to the crate attributes to enable references to implement the `ConstParamTy` trait - | -LL + #![feature(unsized_const_params)] - | - -error: `&u8` is forbidden as the type of a const generic parameter - --> $DIR/const-param-elided-lifetime.rs:14:15 - | -LL | impl A { - | ^^^ - | - = note: the only supported types are integers, `bool` and `char` -help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types - | -LL + #![feature(adt_const_params)] - | -help: add `#![feature(unsized_const_params)]` to the crate attributes to enable references to implement the `ConstParamTy` trait - | -LL + #![feature(unsized_const_params)] - | - -error: `&u8` is forbidden as the type of a const generic parameter - --> $DIR/const-param-elided-lifetime.rs:22:15 - | -LL | impl B for A {} - | ^^^ - | - = note: the only supported types are integers, `bool` and `char` -help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types - | -LL + #![feature(adt_const_params)] - | -help: add `#![feature(unsized_const_params)]` to the crate attributes to enable references to implement the `ConstParamTy` trait - | -LL + #![feature(unsized_const_params)] - | - -error: `&u8` is forbidden as the type of a const generic parameter - --> $DIR/const-param-elided-lifetime.rs:26:17 - | -LL | fn bar() {} - | ^^^ - | - = note: the only supported types are integers, `bool` and `char` -help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types - | -LL + #![feature(adt_const_params)] - | -help: add `#![feature(unsized_const_params)]` to the crate attributes to enable references to implement the `ConstParamTy` trait - | -LL + #![feature(unsized_const_params)] - | - -error: `&u8` is forbidden as the type of a const generic parameter - --> $DIR/const-param-elided-lifetime.rs:17:21 - | -LL | fn foo(&self) {} - | ^^^ - | - = note: the only supported types are integers, `bool` and `char` -help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types - | -LL + #![feature(adt_const_params)] - | -help: add `#![feature(unsized_const_params)]` to the crate attributes to enable references to implement the `ConstParamTy` trait - | -LL + #![feature(unsized_const_params)] - | - -error: aborting due to 10 previous errors +error: aborting due to 5 previous errors For more information about this error, try `rustc --explain E0637`. diff --git a/tests/ui/const-generics/const-param-elided-lifetime.rs b/tests/ui/const-generics/const-param-elided-lifetime.rs index e75073de98d30..b1cdb6a46c552 100644 --- a/tests/ui/const-generics/const-param-elided-lifetime.rs +++ b/tests/ui/const-generics/const-param-elided-lifetime.rs @@ -8,23 +8,18 @@ struct A; //~^ ERROR `&` without an explicit lifetime name cannot be used here -//[min]~^^ ERROR `&u8` is forbidden trait B {} impl A { //~^ ERROR `&` without an explicit lifetime name cannot be used here - //[min]~^^ ERROR `&u8` is forbidden fn foo(&self) {} //~^ ERROR `&` without an explicit lifetime name cannot be used here - //[min]~^^ ERROR `&u8` is forbidden } impl B for A {} //~^ ERROR `&` without an explicit lifetime name cannot be used here -//[min]~^^ ERROR `&u8` is forbidden fn bar() {} //~^ ERROR `&` without an explicit lifetime name cannot be used here -//[min]~^^ ERROR `&u8` is forbidden fn main() {} diff --git a/tests/ui/const-generics/const-param-type-depends-on-const-param.min.stderr b/tests/ui/const-generics/const-param-type-depends-on-const-param.min.stderr index fcc86b9ac33f2..18b8996326782 100644 --- a/tests/ui/const-generics/const-param-type-depends-on-const-param.min.stderr +++ b/tests/ui/const-generics/const-param-type-depends-on-const-param.min.stderr @@ -20,7 +20,7 @@ error: `[u8; N]` is forbidden as the type of a const generic parameter LL | pub struct Dependent([(); N]); | ^^^^^^^ | - = note: the only supported types are integers, `bool` and `char` + = note: the only supported types are integers, `bool`, and `char` help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types | LL + #![feature(adt_const_params)] @@ -32,7 +32,7 @@ error: `[u8; N]` is forbidden as the type of a const generic parameter LL | pub struct SelfDependent; | ^^^^^^^ | - = note: the only supported types are integers, `bool` and `char` + = note: the only supported types are integers, `bool`, and `char` help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types | LL + #![feature(adt_const_params)] diff --git a/tests/ui/const-generics/default-ty-closure.stderr b/tests/ui/const-generics/default-ty-closure.stderr index 9c737c1a19def..3f6ca9aea4ee8 100644 --- a/tests/ui/const-generics/default-ty-closure.stderr +++ b/tests/ui/const-generics/default-ty-closure.stderr @@ -4,7 +4,7 @@ error: using function pointers as const generic parameters is forbidden LL | struct X; | ^^^^ | - = note: the only supported types are integers, `bool` and `char` + = note: the only supported types are integers, `bool`, and `char` error: aborting due to 1 previous error diff --git a/tests/ui/const-generics/float-generic.simple.stderr b/tests/ui/const-generics/float-generic.simple.stderr index 2999bce32d6ad..abc5e7c5a9926 100644 --- a/tests/ui/const-generics/float-generic.simple.stderr +++ b/tests/ui/const-generics/float-generic.simple.stderr @@ -4,7 +4,7 @@ error: `f32` is forbidden as the type of a const generic parameter LL | fn foo() {} | ^^^ | - = note: the only supported types are integers, `bool` and `char` + = note: the only supported types are integers, `bool`, and `char` error: aborting due to 1 previous error diff --git a/tests/ui/const-generics/fn-const-param-call.min.stderr b/tests/ui/const-generics/fn-const-param-call.min.stderr index d37766b28c9ce..b5b809d278703 100644 --- a/tests/ui/const-generics/fn-const-param-call.min.stderr +++ b/tests/ui/const-generics/fn-const-param-call.min.stderr @@ -4,7 +4,7 @@ error: using function pointers as const generic parameters is forbidden LL | struct Wrapper u32>; | ^^^^^^^^^^^ | - = note: the only supported types are integers, `bool` and `char` + = note: the only supported types are integers, `bool`, and `char` error: using function pointers as const generic parameters is forbidden --> $DIR/fn-const-param-call.rs:15:15 @@ -12,7 +12,7 @@ error: using function pointers as const generic parameters is forbidden LL | impl u32> Wrapper { | ^^^^^^^^^^^ | - = note: the only supported types are integers, `bool` and `char` + = note: the only supported types are integers, `bool`, and `char` error: aborting due to 2 previous errors diff --git a/tests/ui/const-generics/fn-const-param-infer.min.stderr b/tests/ui/const-generics/fn-const-param-infer.min.stderr index 4da503d344a1a..5e08f71a26701 100644 --- a/tests/ui/const-generics/fn-const-param-infer.min.stderr +++ b/tests/ui/const-generics/fn-const-param-infer.min.stderr @@ -4,7 +4,7 @@ error: using function pointers as const generic parameters is forbidden LL | struct Checked bool>; | ^^^^^^^^^^^^^^^^^ | - = note: the only supported types are integers, `bool` and `char` + = note: the only supported types are integers, `bool`, and `char` error[E0308]: mismatched types --> $DIR/fn-const-param-infer.rs:33:25 diff --git a/tests/ui/const-generics/generic_const_exprs/array-size-in-generic-struct-param.min.stderr b/tests/ui/const-generics/generic_const_exprs/array-size-in-generic-struct-param.min.stderr index 1f67a5c09f134..a8b6f06ab1c2f 100644 --- a/tests/ui/const-generics/generic_const_exprs/array-size-in-generic-struct-param.min.stderr +++ b/tests/ui/const-generics/generic_const_exprs/array-size-in-generic-struct-param.min.stderr @@ -22,7 +22,7 @@ error: `Config` is forbidden as the type of a const generic parameter LL | struct B { | ^^^^^^ | - = note: the only supported types are integers, `bool` and `char` + = note: the only supported types are integers, `bool`, and `char` help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types | LL + #![feature(adt_const_params)] diff --git a/tests/ui/const-generics/generic_const_exprs/error_in_ty.stderr b/tests/ui/const-generics/generic_const_exprs/error_in_ty.stderr index 0e40255bcf59b..d822fa5894a5b 100644 --- a/tests/ui/const-generics/generic_const_exprs/error_in_ty.stderr +++ b/tests/ui/const-generics/generic_const_exprs/error_in_ty.stderr @@ -12,7 +12,7 @@ error: `[usize; x]` is forbidden as the type of a const generic parameter LL | pub struct A {} | ^^^^^^^^^^ | - = note: the only supported types are integers, `bool` and `char` + = note: the only supported types are integers, `bool`, and `char` help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types | LL + #![feature(adt_const_params)] diff --git a/tests/ui/const-generics/generic_const_exprs/unevaluated-const-ice-119731.stderr b/tests/ui/const-generics/generic_const_exprs/unevaluated-const-ice-119731.stderr index 15d3c47258525..45be31c7ba35f 100644 --- a/tests/ui/const-generics/generic_const_exprs/unevaluated-const-ice-119731.stderr +++ b/tests/ui/const-generics/generic_const_exprs/unevaluated-const-ice-119731.stderr @@ -66,7 +66,7 @@ error: `[[usize; v4]; v4]` is forbidden as the type of a const generic parameter LL | pub struct v17 { | ^^^ | - = note: the only supported types are integers, `bool` and `char` + = note: the only supported types are integers, `bool`, and `char` help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types | LL + #![feature(adt_const_params)] diff --git a/tests/ui/const-generics/ice-118285-fn-ptr-value.stderr b/tests/ui/const-generics/ice-118285-fn-ptr-value.stderr index 46a8a975d50d7..4ff386c81635a 100644 --- a/tests/ui/const-generics/ice-118285-fn-ptr-value.stderr +++ b/tests/ui/const-generics/ice-118285-fn-ptr-value.stderr @@ -4,7 +4,7 @@ error: using function pointers as const generic parameters is forbidden LL | struct Checked bool>; | ^^^^^^^^^^^^^^^^^ | - = note: the only supported types are integers, `bool` and `char` + = note: the only supported types are integers, `bool`, and `char` error: aborting due to 1 previous error diff --git a/tests/ui/const-generics/intrinsics-type_name-as-const-argument.min.stderr b/tests/ui/const-generics/intrinsics-type_name-as-const-argument.min.stderr index 2a6d9f533174e..506f7d05fa63a 100644 --- a/tests/ui/const-generics/intrinsics-type_name-as-const-argument.min.stderr +++ b/tests/ui/const-generics/intrinsics-type_name-as-const-argument.min.stderr @@ -13,7 +13,7 @@ error: `&'static str` is forbidden as the type of a const generic parameter LL | trait Trait {} | ^^^^^^^^^^^^ | - = note: the only supported types are integers, `bool` and `char` + = note: the only supported types are integers, `bool`, and `char` help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types | LL + #![feature(adt_const_params)] diff --git a/tests/ui/const-generics/issues/issue-56445-1.min.stderr b/tests/ui/const-generics/issues/issue-56445-1.min.stderr index ff0a1bfc0b555..86eb57355bd61 100644 --- a/tests/ui/const-generics/issues/issue-56445-1.min.stderr +++ b/tests/ui/const-generics/issues/issue-56445-1.min.stderr @@ -6,22 +6,6 @@ LL | struct Bug<'a, const S: &'a str>(PhantomData<&'a ()>); | = note: lifetime parameters may not be used in the type of const parameters -error: `&str` is forbidden as the type of a const generic parameter - --> $DIR/issue-56445-1.rs:9:25 - | -LL | struct Bug<'a, const S: &'a str>(PhantomData<&'a ()>); - | ^^^^^^^ - | - = note: the only supported types are integers, `bool` and `char` -help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types - | -LL + #![feature(adt_const_params)] - | -help: add `#![feature(unsized_const_params)]` to the crate attributes to enable references to implement the `ConstParamTy` trait - | -LL + #![feature(unsized_const_params)] - | - -error: aborting due to 2 previous errors +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0770`. diff --git a/tests/ui/const-generics/issues/issue-56445-1.rs b/tests/ui/const-generics/issues/issue-56445-1.rs index 53aab40b0ad4a..681e0e147cfc8 100644 --- a/tests/ui/const-generics/issues/issue-56445-1.rs +++ b/tests/ui/const-generics/issues/issue-56445-1.rs @@ -8,6 +8,5 @@ use std::marker::PhantomData; struct Bug<'a, const S: &'a str>(PhantomData<&'a ()>); //~^ ERROR: the type of const parameters must not depend on other generic parameters -//[min]~| ERROR: `&str` is forbidden as the type of a const generic parameter impl Bug<'_, ""> {} diff --git a/tests/ui/const-generics/issues/issue-62878.min.stderr b/tests/ui/const-generics/issues/issue-62878.min.stderr index 5205726d73845..bd17d70a50ba5 100644 --- a/tests/ui/const-generics/issues/issue-62878.min.stderr +++ b/tests/ui/const-generics/issues/issue-62878.min.stderr @@ -12,7 +12,7 @@ error: `[u8; N]` is forbidden as the type of a const generic parameter LL | fn foo() {} | ^^^^^^^ | - = note: the only supported types are integers, `bool` and `char` + = note: the only supported types are integers, `bool`, and `char` help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types | LL + #![feature(adt_const_params)] diff --git a/tests/ui/const-generics/issues/issue-63322-forbid-dyn.min.stderr b/tests/ui/const-generics/issues/issue-63322-forbid-dyn.min.stderr index 101ca456cd90f..f14485a4976e7 100644 --- a/tests/ui/const-generics/issues/issue-63322-forbid-dyn.min.stderr +++ b/tests/ui/const-generics/issues/issue-63322-forbid-dyn.min.stderr @@ -4,7 +4,7 @@ error: `&'static (dyn A + 'static)` is forbidden as the type of a const generic LL | fn test() { | ^^^^^^^^^^^^^^ | - = note: the only supported types are integers, `bool` and `char` + = note: the only supported types are integers, `bool`, and `char` help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types | LL + #![feature(adt_const_params)] diff --git a/tests/ui/const-generics/issues/issue-68366.full.stderr b/tests/ui/const-generics/issues/issue-68366.full.stderr index 3363a895e4725..caed3c1bf3f7d 100644 --- a/tests/ui/const-generics/issues/issue-68366.full.stderr +++ b/tests/ui/const-generics/issues/issue-68366.full.stderr @@ -4,7 +4,7 @@ error: `Option` is forbidden as the type of a const generic parameter LL | struct Collatz>; | ^^^^^^^^^^^^^ | - = note: the only supported types are integers, `bool` and `char` + = note: the only supported types are integers, `bool`, and `char` help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types | LL + #![feature(adt_const_params)] diff --git a/tests/ui/const-generics/issues/issue-68366.min.stderr b/tests/ui/const-generics/issues/issue-68366.min.stderr index 276f91e76dd42..10b5a06682f53 100644 --- a/tests/ui/const-generics/issues/issue-68366.min.stderr +++ b/tests/ui/const-generics/issues/issue-68366.min.stderr @@ -13,7 +13,7 @@ error: `Option` is forbidden as the type of a const generic parameter LL | struct Collatz>; | ^^^^^^^^^^^^^ | - = note: the only supported types are integers, `bool` and `char` + = note: the only supported types are integers, `bool`, and `char` help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types | LL + #![feature(adt_const_params)] diff --git a/tests/ui/const-generics/issues/issue-68615-adt.min.stderr b/tests/ui/const-generics/issues/issue-68615-adt.min.stderr index 2f95eef98c01e..d25b34435ede8 100644 --- a/tests/ui/const-generics/issues/issue-68615-adt.min.stderr +++ b/tests/ui/const-generics/issues/issue-68615-adt.min.stderr @@ -4,7 +4,7 @@ error: `[usize; 0]` is forbidden as the type of a const generic parameter LL | struct Const {} | ^^^^^^^^^^ | - = note: the only supported types are integers, `bool` and `char` + = note: the only supported types are integers, `bool`, and `char` help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types | LL + #![feature(adt_const_params)] diff --git a/tests/ui/const-generics/issues/issue-68615-array.min.stderr b/tests/ui/const-generics/issues/issue-68615-array.min.stderr index 6d18f8195d242..60cbc9b4eab14 100644 --- a/tests/ui/const-generics/issues/issue-68615-array.min.stderr +++ b/tests/ui/const-generics/issues/issue-68615-array.min.stderr @@ -4,7 +4,7 @@ error: `[usize; 0]` is forbidden as the type of a const generic parameter LL | struct Foo {} | ^^^^^^^^^^ | - = note: the only supported types are integers, `bool` and `char` + = note: the only supported types are integers, `bool`, and `char` help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types | LL + #![feature(adt_const_params)] diff --git a/tests/ui/const-generics/issues/issue-71169.min.stderr b/tests/ui/const-generics/issues/issue-71169.min.stderr index 94d11f969ff8a..2ecbc3379516b 100644 --- a/tests/ui/const-generics/issues/issue-71169.min.stderr +++ b/tests/ui/const-generics/issues/issue-71169.min.stderr @@ -12,7 +12,7 @@ error: `[u8; LEN]` is forbidden as the type of a const generic parameter LL | fn foo() {} | ^^^^^^^^^ | - = note: the only supported types are integers, `bool` and `char` + = note: the only supported types are integers, `bool`, and `char` help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types | LL + #![feature(adt_const_params)] diff --git a/tests/ui/const-generics/issues/issue-71381.min.stderr b/tests/ui/const-generics/issues/issue-71381.min.stderr index e16d3b7a8a469..38d2cbe636831 100644 --- a/tests/ui/const-generics/issues/issue-71381.min.stderr +++ b/tests/ui/const-generics/issues/issue-71381.min.stderr @@ -20,7 +20,7 @@ error: using function pointers as const generic parameters is forbidden LL | pub fn call_me(&self) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: the only supported types are integers, `bool` and `char` + = note: the only supported types are integers, `bool`, and `char` error: using function pointers as const generic parameters is forbidden --> $DIR/issue-71381.rs:23:19 @@ -28,7 +28,7 @@ error: using function pointers as const generic parameters is forbidden LL | const FN: unsafe extern "C" fn(Args), | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: the only supported types are integers, `bool` and `char` + = note: the only supported types are integers, `bool`, and `char` error: aborting due to 4 previous errors diff --git a/tests/ui/const-generics/issues/issue-71382.min.stderr b/tests/ui/const-generics/issues/issue-71382.min.stderr index 0c58b10c0b7c8..f70e1733a9770 100644 --- a/tests/ui/const-generics/issues/issue-71382.min.stderr +++ b/tests/ui/const-generics/issues/issue-71382.min.stderr @@ -4,7 +4,7 @@ error: using function pointers as const generic parameters is forbidden LL | fn test(&self) { | ^^^^ | - = note: the only supported types are integers, `bool` and `char` + = note: the only supported types are integers, `bool`, and `char` error: aborting due to 1 previous error diff --git a/tests/ui/const-generics/issues/issue-71611.min.stderr b/tests/ui/const-generics/issues/issue-71611.min.stderr index b01936f4d2513..7252bfd1d6a72 100644 --- a/tests/ui/const-generics/issues/issue-71611.min.stderr +++ b/tests/ui/const-generics/issues/issue-71611.min.stderr @@ -12,7 +12,7 @@ error: using function pointers as const generic parameters is forbidden LL | fn func(outer: A) { | ^^^^^^^^^^^^ | - = note: the only supported types are integers, `bool` and `char` + = note: the only supported types are integers, `bool`, and `char` error: aborting due to 2 previous errors diff --git a/tests/ui/const-generics/issues/issue-72352.min.stderr b/tests/ui/const-generics/issues/issue-72352.min.stderr index ede0faec7c67c..17ccfa8a0dabb 100644 --- a/tests/ui/const-generics/issues/issue-72352.min.stderr +++ b/tests/ui/const-generics/issues/issue-72352.min.stderr @@ -4,7 +4,7 @@ error: using function pointers as const generic parameters is forbidden LL | unsafe fn unsafely_do_the_thing usize>(ptr: *const c_char) -> usize { | ^^^^^^^^^^^^^^^^^^ | - = note: the only supported types are integers, `bool` and `char` + = note: the only supported types are integers, `bool`, and `char` error: aborting due to 1 previous error diff --git a/tests/ui/const-generics/issues/issue-73491.min.stderr b/tests/ui/const-generics/issues/issue-73491.min.stderr index 8fdd65894ef2b..2cdbeea2fd6e5 100644 --- a/tests/ui/const-generics/issues/issue-73491.min.stderr +++ b/tests/ui/const-generics/issues/issue-73491.min.stderr @@ -4,7 +4,7 @@ error: `[u32; LEN]` is forbidden as the type of a const generic parameter LL | fn hoge() {} | ^^^^^^^^^^ | - = note: the only supported types are integers, `bool` and `char` + = note: the only supported types are integers, `bool`, and `char` help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types | LL + #![feature(adt_const_params)] diff --git a/tests/ui/const-generics/issues/issue-73727-static-reference-array-const-param.min.stderr b/tests/ui/const-generics/issues/issue-73727-static-reference-array-const-param.min.stderr index cba03b1cb1f0f..256636c0628cd 100644 --- a/tests/ui/const-generics/issues/issue-73727-static-reference-array-const-param.min.stderr +++ b/tests/ui/const-generics/issues/issue-73727-static-reference-array-const-param.min.stderr @@ -4,7 +4,7 @@ error: `&'static [u32]` is forbidden as the type of a const generic parameter LL | fn a() {} | ^^^^^^^^^^^^^^ | - = note: the only supported types are integers, `bool` and `char` + = note: the only supported types are integers, `bool`, and `char` help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types | LL + #![feature(adt_const_params)] diff --git a/tests/ui/const-generics/issues/issue-74101.min.stderr b/tests/ui/const-generics/issues/issue-74101.min.stderr index 236556addcefd..65fb51d7df99f 100644 --- a/tests/ui/const-generics/issues/issue-74101.min.stderr +++ b/tests/ui/const-generics/issues/issue-74101.min.stderr @@ -4,7 +4,7 @@ error: `[u8; 1 + 2]` is forbidden as the type of a const generic parameter LL | fn test() {} | ^^^^^^^^^^^ | - = note: the only supported types are integers, `bool` and `char` + = note: the only supported types are integers, `bool`, and `char` help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types | LL + #![feature(adt_const_params)] @@ -16,7 +16,7 @@ error: `[u8; 1 + 2]` is forbidden as the type of a const generic parameter LL | struct Foo; | ^^^^^^^^^^^ | - = note: the only supported types are integers, `bool` and `char` + = note: the only supported types are integers, `bool`, and `char` help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types | LL + #![feature(adt_const_params)] diff --git a/tests/ui/const-generics/issues/issue-74255.min.stderr b/tests/ui/const-generics/issues/issue-74255.min.stderr index 800902860a763..3b30227a9a673 100644 --- a/tests/ui/const-generics/issues/issue-74255.min.stderr +++ b/tests/ui/const-generics/issues/issue-74255.min.stderr @@ -4,7 +4,7 @@ error: `IceEnum` is forbidden as the type of a const generic parameter LL | fn ice_struct_fn() {} | ^^^^^^^ | - = note: the only supported types are integers, `bool` and `char` + = note: the only supported types are integers, `bool`, and `char` help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types | LL + #![feature(adt_const_params)] diff --git a/tests/ui/const-generics/issues/issue-74950.min.stderr b/tests/ui/const-generics/issues/issue-74950.min.stderr index 086176d9959c7..22537af786b14 100644 --- a/tests/ui/const-generics/issues/issue-74950.min.stderr +++ b/tests/ui/const-generics/issues/issue-74950.min.stderr @@ -4,7 +4,7 @@ error: `Inner` is forbidden as the type of a const generic parameter LL | struct Outer; | ^^^^^ | - = note: the only supported types are integers, `bool` and `char` + = note: the only supported types are integers, `bool`, and `char` help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types | LL + #![feature(adt_const_params)] @@ -16,7 +16,7 @@ error: `Inner` is forbidden as the type of a const generic parameter LL | struct Outer; | ^^^^^ | - = note: the only supported types are integers, `bool` and `char` + = note: the only supported types are integers, `bool`, and `char` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types | @@ -29,7 +29,7 @@ error: `Inner` is forbidden as the type of a const generic parameter LL | struct Outer; | ^^^^^ | - = note: the only supported types are integers, `bool` and `char` + = note: the only supported types are integers, `bool`, and `char` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types | @@ -42,7 +42,7 @@ error: `Inner` is forbidden as the type of a const generic parameter LL | struct Outer; | ^^^^^ | - = note: the only supported types are integers, `bool` and `char` + = note: the only supported types are integers, `bool`, and `char` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types | diff --git a/tests/ui/const-generics/issues/issue-75047.min.stderr b/tests/ui/const-generics/issues/issue-75047.min.stderr index f2cc76b9bed03..d78ab6718201a 100644 --- a/tests/ui/const-generics/issues/issue-75047.min.stderr +++ b/tests/ui/const-generics/issues/issue-75047.min.stderr @@ -4,7 +4,7 @@ error: `[u8; Bar::::value()]` is forbidden as the type of a const generic p LL | struct Foo::value()]>; | ^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: the only supported types are integers, `bool` and `char` + = note: the only supported types are integers, `bool`, and `char` help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types | LL + #![feature(adt_const_params)] diff --git a/tests/ui/const-generics/lifetime-in-const-param.rs b/tests/ui/const-generics/lifetime-in-const-param.rs index be90dbb213eef..ce6b52b229f4b 100644 --- a/tests/ui/const-generics/lifetime-in-const-param.rs +++ b/tests/ui/const-generics/lifetime-in-const-param.rs @@ -4,6 +4,5 @@ struct S2<'b>(&'b ()); struct S<'a, const N: S2>(&'a ()); //~^ ERROR missing lifetime specifier [E0106] -//~| ERROR `S2<'_>` is forbidden as the type of a const generic parameter fn main() {} diff --git a/tests/ui/const-generics/lifetime-in-const-param.stderr b/tests/ui/const-generics/lifetime-in-const-param.stderr index 4096725c52a1b..7c9d27c1e284e 100644 --- a/tests/ui/const-generics/lifetime-in-const-param.stderr +++ b/tests/ui/const-generics/lifetime-in-const-param.stderr @@ -4,18 +4,6 @@ error[E0106]: missing lifetime specifier LL | struct S<'a, const N: S2>(&'a ()); | ^^ expected named lifetime parameter -error: `S2<'_>` is forbidden as the type of a const generic parameter - --> $DIR/lifetime-in-const-param.rs:5:23 - | -LL | struct S<'a, const N: S2>(&'a ()); - | ^^ - | - = note: the only supported types are integers, `bool` and `char` -help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types - | -LL + #![feature(adt_const_params)] - | - -error: aborting due to 2 previous errors +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0106`. diff --git a/tests/ui/const-generics/min_const_generics/complex-types.stderr b/tests/ui/const-generics/min_const_generics/complex-types.stderr index 0211770f9e51b..bca68982c399d 100644 --- a/tests/ui/const-generics/min_const_generics/complex-types.stderr +++ b/tests/ui/const-generics/min_const_generics/complex-types.stderr @@ -4,7 +4,7 @@ error: `[u8; 0]` is forbidden as the type of a const generic parameter LL | struct Foo; | ^^^^^^^ | - = note: the only supported types are integers, `bool` and `char` + = note: the only supported types are integers, `bool`, and `char` help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types | LL + #![feature(adt_const_params)] @@ -16,7 +16,7 @@ error: `()` is forbidden as the type of a const generic parameter LL | struct Bar; | ^^ | - = note: the only supported types are integers, `bool` and `char` + = note: the only supported types are integers, `bool`, and `char` help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types | LL + #![feature(adt_const_params)] @@ -28,7 +28,7 @@ error: `No` is forbidden as the type of a const generic parameter LL | struct Fez; | ^^ | - = note: the only supported types are integers, `bool` and `char` + = note: the only supported types are integers, `bool`, and `char` help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types | LL + #![feature(adt_const_params)] @@ -40,7 +40,7 @@ error: `&'static u8` is forbidden as the type of a const generic parameter LL | struct Faz; | ^^^^^^^^^^^ | - = note: the only supported types are integers, `bool` and `char` + = note: the only supported types are integers, `bool`, and `char` help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types | LL + #![feature(adt_const_params)] @@ -56,7 +56,7 @@ error: `!` is forbidden as the type of a const generic parameter LL | struct Fiz; | ^ | - = note: the only supported types are integers, `bool` and `char` + = note: the only supported types are integers, `bool`, and `char` error: `()` is forbidden as the type of a const generic parameter --> $DIR/complex-types.rs:20:19 @@ -64,7 +64,7 @@ error: `()` is forbidden as the type of a const generic parameter LL | enum Goo { A, B } | ^^ | - = note: the only supported types are integers, `bool` and `char` + = note: the only supported types are integers, `bool`, and `char` help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types | LL + #![feature(adt_const_params)] @@ -76,7 +76,7 @@ error: `()` is forbidden as the type of a const generic parameter LL | union Boo { a: () } | ^^ | - = note: the only supported types are integers, `bool` and `char` + = note: the only supported types are integers, `bool`, and `char` help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types | LL + #![feature(adt_const_params)] diff --git a/tests/ui/const-generics/nested-type.min.stderr b/tests/ui/const-generics/nested-type.min.stderr index 0da2b30e3f1a9..8696be3faf37b 100644 --- a/tests/ui/const-generics/nested-type.min.stderr +++ b/tests/ui/const-generics/nested-type.min.stderr @@ -29,7 +29,7 @@ LL | | LL | | }]>; | |__^ | - = note: the only supported types are integers, `bool` and `char` + = note: the only supported types are integers, `bool`, and `char` help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types | LL + #![feature(adt_const_params)] diff --git a/tests/ui/const-generics/not_wf_param_in_rpitit.rs b/tests/ui/const-generics/not_wf_param_in_rpitit.rs index 5471dc9022f90..eb672194340e8 100644 --- a/tests/ui/const-generics/not_wf_param_in_rpitit.rs +++ b/tests/ui/const-generics/not_wf_param_in_rpitit.rs @@ -6,7 +6,6 @@ trait Trait { //~| ERROR: the trait `Trait` cannot be made into an object //~| ERROR: the trait `Trait` cannot be made into an object //~| ERROR: the trait `Trait` cannot be made into an object - //~| ERROR: `(dyn Trait<{const error}> + 'static)` is forbidden as the type of a const generic parameter //~| ERROR: trait objects must include the `dyn` keyword async fn a() {} } diff --git a/tests/ui/const-generics/not_wf_param_in_rpitit.stderr b/tests/ui/const-generics/not_wf_param_in_rpitit.stderr index 82e251f1306c2..ade40550c7389 100644 --- a/tests/ui/const-generics/not_wf_param_in_rpitit.stderr +++ b/tests/ui/const-generics/not_wf_param_in_rpitit.stderr @@ -25,7 +25,7 @@ LL | trait Trait { | ^^^^^ `Trait` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/not_wf_param_in_rpitit.rs:11:14 + --> $DIR/not_wf_param_in_rpitit.rs:10:14 | LL | trait Trait { | ----- this trait cannot be made into an object... @@ -48,7 +48,7 @@ LL | trait Trait { | ^^^^^^^^^^^^^^^^^^^^ `Trait` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/not_wf_param_in_rpitit.rs:11:14 + --> $DIR/not_wf_param_in_rpitit.rs:10:14 | LL | trait Trait { | ----- this trait cannot be made into an object... @@ -64,14 +64,6 @@ help: alternatively, consider constraining `a` so it does not apply to trait obj LL | async fn a() where Self: Sized {} | +++++++++++++++++ -error: `(dyn Trait<{const error}> + 'static)` is forbidden as the type of a const generic parameter - --> $DIR/not_wf_param_in_rpitit.rs:3:22 - | -LL | trait Trait { - | ^^^^^ - | - = note: the only supported types are integers, `bool` and `char` - error[E0038]: the trait `Trait` cannot be made into an object --> $DIR/not_wf_param_in_rpitit.rs:3:13 | @@ -79,7 +71,7 @@ LL | trait Trait { | ^^^^^^^^^^^^^^^^^^^^ `Trait` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/not_wf_param_in_rpitit.rs:11:14 + --> $DIR/not_wf_param_in_rpitit.rs:10:14 | LL | trait Trait { | ----- this trait cannot be made into an object... @@ -107,7 +99,7 @@ help: add `dyn` keyword before this trait LL | trait Trait { | +++ -error: aborting due to 7 previous errors +error: aborting due to 6 previous errors Some errors have detailed explanations: E0038, E0391, E0425, E0782. For more information about an error, try `rustc --explain E0038`. diff --git a/tests/ui/const-generics/opaque_types.stderr b/tests/ui/const-generics/opaque_types.stderr index 3947d645fcbe2..847f1da16f612 100644 --- a/tests/ui/const-generics/opaque_types.stderr +++ b/tests/ui/const-generics/opaque_types.stderr @@ -74,7 +74,7 @@ error: `Foo` is forbidden as the type of a const generic parameter LL | fn foo() {} | ^^^ | - = note: the only supported types are integers, `bool` and `char` + = note: the only supported types are integers, `bool`, and `char` error[E0391]: cycle detected when computing type of opaque `Foo::{opaque#0}` --> $DIR/opaque_types.rs:3:12 diff --git a/tests/ui/const-generics/projection-as-arg-const.stderr b/tests/ui/const-generics/projection-as-arg-const.stderr index 88672bce0a7ee..f6e7620db7d9b 100644 --- a/tests/ui/const-generics/projection-as-arg-const.stderr +++ b/tests/ui/const-generics/projection-as-arg-const.stderr @@ -4,7 +4,7 @@ error: `::Identity` is forbidden as the type of a const generic LL | pub fn foo::Identity>() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: the only supported types are integers, `bool` and `char` + = note: the only supported types are integers, `bool`, and `char` error: aborting due to 1 previous error diff --git a/tests/ui/const-generics/raw-ptr-const-param-deref.min.stderr b/tests/ui/const-generics/raw-ptr-const-param-deref.min.stderr index 6027dbb01cddb..fca2966e3a30a 100644 --- a/tests/ui/const-generics/raw-ptr-const-param-deref.min.stderr +++ b/tests/ui/const-generics/raw-ptr-const-param-deref.min.stderr @@ -4,7 +4,7 @@ error: using raw pointers as const generic parameters is forbidden LL | struct Const; | ^^^^^^^^^^ | - = note: the only supported types are integers, `bool` and `char` + = note: the only supported types are integers, `bool`, and `char` error: using raw pointers as const generic parameters is forbidden --> $DIR/raw-ptr-const-param-deref.rs:13:15 @@ -12,7 +12,7 @@ error: using raw pointers as const generic parameters is forbidden LL | impl Const

{ | ^^^^^^^^^^ | - = note: the only supported types are integers, `bool` and `char` + = note: the only supported types are integers, `bool`, and `char` error: aborting due to 2 previous errors diff --git a/tests/ui/const-generics/raw-ptr-const-param.min.stderr b/tests/ui/const-generics/raw-ptr-const-param.min.stderr index c48eea069e0da..5694b12f2d52a 100644 --- a/tests/ui/const-generics/raw-ptr-const-param.min.stderr +++ b/tests/ui/const-generics/raw-ptr-const-param.min.stderr @@ -4,7 +4,7 @@ error: using raw pointers as const generic parameters is forbidden LL | struct Const; | ^^^^^^^^^^ | - = note: the only supported types are integers, `bool` and `char` + = note: the only supported types are integers, `bool`, and `char` error[E0308]: mismatched types --> $DIR/raw-ptr-const-param.rs:11:40 diff --git a/tests/ui/const-generics/slice-const-param-mismatch.min.stderr b/tests/ui/const-generics/slice-const-param-mismatch.min.stderr index 3b2410c989477..594f8b9b79a33 100644 --- a/tests/ui/const-generics/slice-const-param-mismatch.min.stderr +++ b/tests/ui/const-generics/slice-const-param-mismatch.min.stderr @@ -4,7 +4,7 @@ error: `&'static str` is forbidden as the type of a const generic parameter LL | struct ConstString; | ^^^^^^^^^^^^ | - = note: the only supported types are integers, `bool` and `char` + = note: the only supported types are integers, `bool`, and `char` help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types | LL + #![feature(adt_const_params)] @@ -20,7 +20,7 @@ error: `&'static [u8]` is forbidden as the type of a const generic parameter LL | struct ConstBytes; | ^^^^^^^^^^^^^ | - = note: the only supported types are integers, `bool` and `char` + = note: the only supported types are integers, `bool`, and `char` help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types | LL + #![feature(adt_const_params)] diff --git a/tests/ui/const-generics/std/const-generics-range.min.stderr b/tests/ui/const-generics/std/const-generics-range.min.stderr index 67f137cf1a077..fd23b9b248a06 100644 --- a/tests/ui/const-generics/std/const-generics-range.min.stderr +++ b/tests/ui/const-generics/std/const-generics-range.min.stderr @@ -4,7 +4,7 @@ error: `std::ops::Range` is forbidden as the type of a const generic para LL | struct _Range>; | ^^^^^^^^^^^^^^^^^^^^^^ | - = note: the only supported types are integers, `bool` and `char` + = note: the only supported types are integers, `bool`, and `char` help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types | LL + #![feature(adt_const_params)] @@ -16,7 +16,7 @@ error: `RangeFrom` is forbidden as the type of a const generic parameter LL | struct _RangeFrom>; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: the only supported types are integers, `bool` and `char` + = note: the only supported types are integers, `bool`, and `char` help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types | LL + #![feature(adt_const_params)] @@ -28,7 +28,7 @@ error: `RangeFull` is forbidden as the type of a const generic parameter LL | struct _RangeFull; | ^^^^^^^^^^^^^^^^^^^ | - = note: the only supported types are integers, `bool` and `char` + = note: the only supported types are integers, `bool`, and `char` help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types | LL + #![feature(adt_const_params)] @@ -40,7 +40,7 @@ error: `RangeInclusive` is forbidden as the type of a const generic param LL | struct _RangeInclusive>; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: the only supported types are integers, `bool` and `char` + = note: the only supported types are integers, `bool`, and `char` help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types | LL + #![feature(adt_const_params)] @@ -52,7 +52,7 @@ error: `RangeTo` is forbidden as the type of a const generic parameter LL | struct _RangeTo>; | ^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: the only supported types are integers, `bool` and `char` + = note: the only supported types are integers, `bool`, and `char` help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types | LL + #![feature(adt_const_params)] @@ -64,7 +64,7 @@ error: `RangeToInclusive` is forbidden as the type of a const generic par LL | struct _RangeToInclusive>; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: the only supported types are integers, `bool` and `char` + = note: the only supported types are integers, `bool`, and `char` help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types | LL + #![feature(adt_const_params)] diff --git a/tests/ui/const-generics/transmute-const-param-static-reference.min.stderr b/tests/ui/const-generics/transmute-const-param-static-reference.min.stderr index cf236487cf0ec..911afa3391d16 100644 --- a/tests/ui/const-generics/transmute-const-param-static-reference.min.stderr +++ b/tests/ui/const-generics/transmute-const-param-static-reference.min.stderr @@ -4,7 +4,7 @@ error: `&'static ()` is forbidden as the type of a const generic parameter LL | struct Const; | ^^^^^^^^^^^ | - = note: the only supported types are integers, `bool` and `char` + = note: the only supported types are integers, `bool`, and `char` help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types | LL + #![feature(adt_const_params)] diff --git a/tests/ui/const-generics/type-dependent/issue-71348.min.stderr b/tests/ui/const-generics/type-dependent/issue-71348.min.stderr index 5aee282952aa2..8995c4158635f 100644 --- a/tests/ui/const-generics/type-dependent/issue-71348.min.stderr +++ b/tests/ui/const-generics/type-dependent/issue-71348.min.stderr @@ -12,7 +12,7 @@ error: `&'static str` is forbidden as the type of a const generic parameter LL | trait Get<'a, const N: &'static str> { | ^^^^^^^^^^^^ | - = note: the only supported types are integers, `bool` and `char` + = note: the only supported types are integers, `bool`, and `char` help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types | LL + #![feature(adt_const_params)] @@ -28,7 +28,7 @@ error: `&'static str` is forbidden as the type of a const generic parameter LL | fn ask<'a, const N: &'static str>(&'a self) -> &'a >::Target | ^^^^^^^^^^^^ | - = note: the only supported types are integers, `bool` and `char` + = note: the only supported types are integers, `bool`, and `char` help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types | LL + #![feature(adt_const_params)] diff --git a/tests/ui/const-generics/type-dependent/issue-71382.stderr b/tests/ui/const-generics/type-dependent/issue-71382.stderr index 69fd6f1c7d53e..3830b1527c372 100644 --- a/tests/ui/const-generics/type-dependent/issue-71382.stderr +++ b/tests/ui/const-generics/type-dependent/issue-71382.stderr @@ -4,7 +4,7 @@ error: using function pointers as const generic parameters is forbidden LL | fn test u8>(&self) -> u8 { | ^^^^^^^^^^ | - = note: the only supported types are integers, `bool` and `char` + = note: the only supported types are integers, `bool`, and `char` error: aborting due to 1 previous error diff --git a/tests/ui/consts/issue-103790.rs b/tests/ui/consts/issue-103790.rs index d19115ede74bf..869a43e4018b3 100644 --- a/tests/ui/consts/issue-103790.rs +++ b/tests/ui/consts/issue-103790.rs @@ -6,6 +6,5 @@ struct S; //~| ERROR missing generics for struct `S` //~| ERROR cycle detected when computing type of `S::S` //~| ERROR `()` is forbidden as the type of a const generic parameter -//~| ERROR `S<{const error}, {const error}>` is forbidden as the type of a const generic parameter fn main() {} diff --git a/tests/ui/consts/issue-103790.stderr b/tests/ui/consts/issue-103790.stderr index c671f078cb5c0..1515fa60a5c08 100644 --- a/tests/ui/consts/issue-103790.stderr +++ b/tests/ui/consts/issue-103790.stderr @@ -42,25 +42,13 @@ error: `()` is forbidden as the type of a const generic parameter LL | struct S; | ^^ | - = note: the only supported types are integers, `bool` and `char` + = note: the only supported types are integers, `bool`, and `char` help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types | LL + #![feature(adt_const_params)] | -error: `S<{const error}, {const error}>` is forbidden as the type of a const generic parameter - --> $DIR/issue-103790.rs:4:32 - | -LL | struct S; - | ^ - | - = note: the only supported types are integers, `bool` and `char` -help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types - | -LL + #![feature(adt_const_params)] - | - -error: aborting due to 5 previous errors +error: aborting due to 4 previous errors Some errors have detailed explanations: E0107, E0391, E0403. For more information about an error, try `rustc --explain E0107`. diff --git a/tests/ui/feature-gates/feature-gate-adt_const_params.stderr b/tests/ui/feature-gates/feature-gate-adt_const_params.stderr index 649e936888b22..18d514f8cb5f8 100644 --- a/tests/ui/feature-gates/feature-gate-adt_const_params.stderr +++ b/tests/ui/feature-gates/feature-gate-adt_const_params.stderr @@ -4,7 +4,7 @@ error: `&'static str` is forbidden as the type of a const generic parameter LL | struct Foo; | ^^^^^^^^^^^^ | - = note: the only supported types are integers, `bool` and `char` + = note: the only supported types are integers, `bool`, and `char` help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types | LL + #![feature(adt_const_params)] diff --git a/tests/ui/feature-gates/feature-gate-unsized-const-params.stderr b/tests/ui/feature-gates/feature-gate-unsized-const-params.stderr index 0a87f34f4f51f..85ca2f59cb639 100644 --- a/tests/ui/feature-gates/feature-gate-unsized-const-params.stderr +++ b/tests/ui/feature-gates/feature-gate-unsized-const-params.stderr @@ -4,7 +4,7 @@ error: `[u8]` is forbidden as the type of a const generic parameter LL | struct Foo; | ^^^^ | - = note: the only supported types are integers, `bool` and `char` + = note: the only supported types are integers, `bool`, and `char` help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types | LL + #![feature(adt_const_params)] diff --git a/tests/ui/generic-const-items/elided-lifetimes.rs b/tests/ui/generic-const-items/elided-lifetimes.rs index cca73e2e81e8d..90899de5af618 100644 --- a/tests/ui/generic-const-items/elided-lifetimes.rs +++ b/tests/ui/generic-const-items/elided-lifetimes.rs @@ -9,7 +9,6 @@ where const I: &str = ""; //~^ ERROR `&` without an explicit lifetime name cannot be used here -//~| ERROR `&str` is forbidden as the type of a const generic parameter const B>: () = (); //~ ERROR `'_` cannot be used here diff --git a/tests/ui/generic-const-items/elided-lifetimes.stderr b/tests/ui/generic-const-items/elided-lifetimes.stderr index 85807a1b631a6..2b543d02b5d0f 100644 --- a/tests/ui/generic-const-items/elided-lifetimes.stderr +++ b/tests/ui/generic-const-items/elided-lifetimes.stderr @@ -16,27 +16,11 @@ LL | const I: &str = ""; | ^ explicit lifetime name needed here error[E0637]: `'_` cannot be used here - --> $DIR/elided-lifetimes.rs:14:18 + --> $DIR/elided-lifetimes.rs:13:18 | LL | const B>: () = (); | ^^ `'_` is a reserved lifetime name -error: `&str` is forbidden as the type of a const generic parameter - --> $DIR/elided-lifetimes.rs:10:18 - | -LL | const I: &str = ""; - | ^^^^ - | - = note: the only supported types are integers, `bool` and `char` -help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types - | -LL + #![feature(adt_const_params)] - | -help: add `#![feature(unsized_const_params)]` to the crate attributes to enable references to implement the `ConstParamTy` trait - | -LL + #![feature(unsized_const_params)] - | - -error: aborting due to 4 previous errors +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0637`. diff --git a/tests/ui/generic-const-items/wfcheck_err_leak_issue_118179.rs b/tests/ui/generic-const-items/wfcheck_err_leak_issue_118179.rs new file mode 100644 index 0000000000000..856f7b622d7ef --- /dev/null +++ b/tests/ui/generic-const-items/wfcheck_err_leak_issue_118179.rs @@ -0,0 +1,7 @@ +//! Regression test for #118179: `adt_const_params` feature shouldn't leak +//! `{type error}` in error messages. + +struct G>(T); +//~^ ERROR the type of const parameters must not depend on other generic parameters + +fn main() {} diff --git a/tests/ui/generic-const-items/wfcheck_err_leak_issue_118179.stderr b/tests/ui/generic-const-items/wfcheck_err_leak_issue_118179.stderr new file mode 100644 index 0000000000000..654004571dbbe --- /dev/null +++ b/tests/ui/generic-const-items/wfcheck_err_leak_issue_118179.stderr @@ -0,0 +1,11 @@ +error[E0770]: the type of const parameters must not depend on other generic parameters + --> $DIR/wfcheck_err_leak_issue_118179.rs:4:26 + | +LL | struct G>(T); + | ^ the type must not depend on the parameter `T` + | + = note: type parameters may not be used in the type of const parameters + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0770`. diff --git a/tests/ui/lifetimes/unusual-rib-combinations.rs b/tests/ui/lifetimes/unusual-rib-combinations.rs index 0708a00d37157..0e92b41ae1ee2 100644 --- a/tests/ui/lifetimes/unusual-rib-combinations.rs +++ b/tests/ui/lifetimes/unusual-rib-combinations.rs @@ -20,11 +20,9 @@ fn c() {} // Elided lifetime in path in ConstGeneric fn d() {} //~^ ERROR missing lifetime specifier -//~| ERROR `S<'_>` is forbidden as the type of a const generic parameter trait Foo<'a> {} struct Bar Foo<'a>)>; //~^ ERROR the type of const parameters must not depend on other generic parameters -//~| ERROR `&dyn for<'a> Foo<'a>` is forbidden as the type of a const generic parameter fn main() {} diff --git a/tests/ui/lifetimes/unusual-rib-combinations.stderr b/tests/ui/lifetimes/unusual-rib-combinations.stderr index ebf6f6ca403cb..b7effdc8d61d0 100644 --- a/tests/ui/lifetimes/unusual-rib-combinations.stderr +++ b/tests/ui/lifetimes/unusual-rib-combinations.stderr @@ -5,7 +5,7 @@ LL | fn d() {} | ^ expected named lifetime parameter error[E0770]: the type of const parameters must not depend on other generic parameters - --> $DIR/unusual-rib-combinations.rs:26:22 + --> $DIR/unusual-rib-combinations.rs:25:22 | LL | struct Bar Foo<'a>)>; | ^^ the type must not depend on the parameter `'a` @@ -40,35 +40,7 @@ error[E0308]: mismatched types LL | fn a() -> [u8; foo()] { | ^^^^^ expected `usize`, found `()` -error: `S<'_>` is forbidden as the type of a const generic parameter - --> $DIR/unusual-rib-combinations.rs:21:15 - | -LL | fn d() {} - | ^ - | - = note: the only supported types are integers, `bool` and `char` -help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types - | -LL + #![feature(adt_const_params)] - | - -error: `&dyn for<'a> Foo<'a>` is forbidden as the type of a const generic parameter - --> $DIR/unusual-rib-combinations.rs:26:21 - | -LL | struct Bar Foo<'a>)>; - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: the only supported types are integers, `bool` and `char` -help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types - | -LL + #![feature(adt_const_params)] - | -help: add `#![feature(unsized_const_params)]` to the crate attributes to enable references to implement the `ConstParamTy` trait - | -LL + #![feature(unsized_const_params)] - | - -error: aborting due to 8 previous errors +error: aborting due to 6 previous errors Some errors have detailed explanations: E0106, E0214, E0308, E0770. For more information about an error, try `rustc --explain E0106`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/mismatched_generic_args.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/mismatched_generic_args.stderr index 8c814295de465..8e12b40381fd2 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/mismatched_generic_args.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/mismatched_generic_args.stderr @@ -22,7 +22,7 @@ error: `Dimension` is forbidden as the type of a const generic parameter LL | pub struct Quantity(S); | ^^^^^^^^^ | - = note: the only supported types are integers, `bool` and `char` + = note: the only supported types are integers, `bool`, and `char` help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types | LL + #![feature(adt_const_params)] @@ -40,7 +40,7 @@ error: `Dimension` is forbidden as the type of a const generic parameter LL | impl Add for Quantity {} | ^^^^^^^^^ | - = note: the only supported types are integers, `bool` and `char` + = note: the only supported types are integers, `bool`, and `char` help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types | LL + #![feature(adt_const_params)] @@ -52,7 +52,7 @@ error: `Dimension` is forbidden as the type of a const generic parameter LL | pub fn add(x: Quantity) -> Quantity { | ^^^^^^^^^ | - = note: the only supported types are integers, `bool` and `char` + = note: the only supported types are integers, `bool`, and `char` help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types | LL + #![feature(adt_const_params)] diff --git a/tests/ui/specialization/default-proj-ty-as-type-of-const-issue-125757.stderr b/tests/ui/specialization/default-proj-ty-as-type-of-const-issue-125757.stderr index 7094ee8c67ca0..8df76b296acd6 100644 --- a/tests/ui/specialization/default-proj-ty-as-type-of-const-issue-125757.stderr +++ b/tests/ui/specialization/default-proj-ty-as-type-of-const-issue-125757.stderr @@ -4,7 +4,7 @@ error: `::Type` is forbidden as the type of a const generic parame LL | struct Wrapper::Type> {} | ^^^^^^^^^^^^^^^^^^^^ | - = note: the only supported types are integers, `bool` and `char` + = note: the only supported types are integers, `bool`, and `char` error: the constant `C` is not of type `::Type` --> $DIR/default-proj-ty-as-type-of-const-issue-125757.rs:15:22 diff --git a/tests/ui/traits/next-solver/canonical/const-region-infer-to-static-in-binder.stderr b/tests/ui/traits/next-solver/canonical/const-region-infer-to-static-in-binder.stderr index e0cbee88aa100..377dfc8b52916 100644 --- a/tests/ui/traits/next-solver/canonical/const-region-infer-to-static-in-binder.stderr +++ b/tests/ui/traits/next-solver/canonical/const-region-infer-to-static-in-binder.stderr @@ -10,7 +10,7 @@ error: using function pointers as const generic parameters is forbidden LL | struct X; | ^^^^ | - = note: the only supported types are integers, `bool` and `char` + = note: the only supported types are integers, `bool`, and `char` error: using function pointers as const generic parameters is forbidden --> $DIR/const-region-infer-to-static-in-binder.rs:4:20 @@ -18,7 +18,7 @@ error: using function pointers as const generic parameters is forbidden LL | struct X; | ^^^^ | - = note: the only supported types are integers, `bool` and `char` + = note: the only supported types are integers, `bool`, and `char` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: aborting due to 3 previous errors diff --git a/tests/ui/type-alias-impl-trait/const_generic_type.infer.stderr b/tests/ui/type-alias-impl-trait/const_generic_type.infer.stderr index 3b6999cabc416..b7999a695e7f3 100644 --- a/tests/ui/type-alias-impl-trait/const_generic_type.infer.stderr +++ b/tests/ui/type-alias-impl-trait/const_generic_type.infer.stderr @@ -4,7 +4,7 @@ error: `Bar` is forbidden as the type of a const generic parameter LL | async fn test() { | ^^^^^^^^^^ | - = note: the only supported types are integers, `bool` and `char` + = note: the only supported types are integers, `bool`, and `char` error: aborting due to 1 previous error diff --git a/tests/ui/type-alias-impl-trait/const_generic_type.no_infer.stderr b/tests/ui/type-alias-impl-trait/const_generic_type.no_infer.stderr index 55a5a3d20006b..b526ab49d8d4a 100644 --- a/tests/ui/type-alias-impl-trait/const_generic_type.no_infer.stderr +++ b/tests/ui/type-alias-impl-trait/const_generic_type.no_infer.stderr @@ -45,7 +45,7 @@ error: `Bar` is forbidden as the type of a const generic parameter LL | async fn test() { | ^^^^^^^^^^ | - = note: the only supported types are integers, `bool` and `char` + = note: the only supported types are integers, `bool`, and `char` error: aborting due to 4 previous errors diff --git a/tests/ui/typeck/ice-unexpected-region-123863.stderr b/tests/ui/typeck/ice-unexpected-region-123863.stderr index 0479f134a3897..742096f3861f6 100644 --- a/tests/ui/typeck/ice-unexpected-region-123863.stderr +++ b/tests/ui/typeck/ice-unexpected-region-123863.stderr @@ -4,7 +4,7 @@ error: `&'static str` is forbidden as the type of a const generic parameter LL | const fn concat_strs() -> &'static str { | ^^^^^^^^^^^^ | - = note: the only supported types are integers, `bool` and `char` + = note: the only supported types are integers, `bool`, and `char` help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types | LL + #![feature(adt_const_params)] @@ -20,7 +20,7 @@ error: `&'static str` is forbidden as the type of a const generic parameter LL | struct Inner; | ^^^^^^^^^^^^ | - = note: the only supported types are integers, `bool` and `char` + = note: the only supported types are integers, `bool`, and `char` help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types | LL + #![feature(adt_const_params)] diff --git a/tests/ui/wf/ice-hir-wf-check-anon-const-issue-122199.rs b/tests/ui/wf/ice-hir-wf-check-anon-const-issue-122199.rs index 3f43fbfc0cf41..53363319ba0e6 100644 --- a/tests/ui/wf/ice-hir-wf-check-anon-const-issue-122199.rs +++ b/tests/ui/wf/ice-hir-wf-check-anon-const-issue-122199.rs @@ -4,7 +4,6 @@ trait Trait { //~| ERROR the trait `Trait` cannot be made into an object //~| ERROR the trait `Trait` cannot be made into an object //~| ERROR the trait `Trait` cannot be made into an object - //~| ERROR `(dyn Trait<{const error}> + 'static)` is forbidden as the type of a const generic parameter //~| WARN trait objects without an explicit `dyn` are deprecated [bare_trait_objects] //~| WARN this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! //~| WARN trait objects without an explicit `dyn` are deprecated [bare_trait_objects] @@ -15,7 +14,6 @@ trait Trait { //~| ERROR defaults for const parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions //~| ERROR associated item referring to unboxed trait object for its own trait //~| ERROR the trait `Trait` cannot be made into an object - //~| ERROR `(dyn Trait<{const error}> + 'static)` is forbidden as the type of a const generic parameter //~| WARN trait objects without an explicit `dyn` are deprecated [bare_trait_objects] //~| WARN this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! //~| WARN trait objects without an explicit `dyn` are deprecated [bare_trait_objects] diff --git a/tests/ui/wf/ice-hir-wf-check-anon-const-issue-122199.stderr b/tests/ui/wf/ice-hir-wf-check-anon-const-issue-122199.stderr index 6b309c223afff..fefb788fac79c 100644 --- a/tests/ui/wf/ice-hir-wf-check-anon-const-issue-122199.stderr +++ b/tests/ui/wf/ice-hir-wf-check-anon-const-issue-122199.stderr @@ -1,5 +1,5 @@ error[E0403]: the name `N` is already used for a generic parameter in this item's generic parameters - --> $DIR/ice-hir-wf-check-anon-const-issue-122199.rs:12:18 + --> $DIR/ice-hir-wf-check-anon-const-issue-122199.rs:11:18 | LL | trait Trait { | - first use of `N` @@ -14,13 +14,13 @@ LL | trait Trait { | ^^^ not found in this scope error[E0423]: expected value, found builtin type `u32` - --> $DIR/ice-hir-wf-check-anon-const-issue-122199.rs:12:29 + --> $DIR/ice-hir-wf-check-anon-const-issue-122199.rs:11:29 | LL | fn fnc(&self) -> Trait { | ^^^ not a value error[E0425]: cannot find value `bar` in this scope - --> $DIR/ice-hir-wf-check-anon-const-issue-122199.rs:25:9 + --> $DIR/ice-hir-wf-check-anon-const-issue-122199.rs:23:9 | LL | bar | ^^^ not found in this scope @@ -54,13 +54,13 @@ LL | trait Trait { = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information error: defaults for const parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions - --> $DIR/ice-hir-wf-check-anon-const-issue-122199.rs:12:12 + --> $DIR/ice-hir-wf-check-anon-const-issue-122199.rs:11:12 | LL | fn fnc(&self) -> Trait { | ^^^^^^^^^^^^^^^^^^^^ warning: trait objects without an explicit `dyn` are deprecated - --> $DIR/ice-hir-wf-check-anon-const-issue-122199.rs:12:21 + --> $DIR/ice-hir-wf-check-anon-const-issue-122199.rs:11:21 | LL | fn fnc(&self) -> Trait { | ^^^^^ @@ -73,7 +73,7 @@ LL | fn fnc(&self) -> Trait { | +++ warning: trait objects without an explicit `dyn` are deprecated - --> $DIR/ice-hir-wf-check-anon-const-issue-122199.rs:12:44 + --> $DIR/ice-hir-wf-check-anon-const-issue-122199.rs:11:44 | LL | fn fnc(&self) -> Trait { | ^^^^^ @@ -106,7 +106,7 @@ LL | trait Trait { | ^^^^^ `Trait` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/ice-hir-wf-check-anon-const-issue-122199.rs:12:8 + --> $DIR/ice-hir-wf-check-anon-const-issue-122199.rs:11:8 | LL | trait Trait { | ----- this trait cannot be made into an object... @@ -122,7 +122,7 @@ LL | trait Trait { | ^^^^^^^^^^^^^^^^^^^^ `Trait` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/ice-hir-wf-check-anon-const-issue-122199.rs:12:8 + --> $DIR/ice-hir-wf-check-anon-const-issue-122199.rs:11:8 | LL | trait Trait { | ----- this trait cannot be made into an object... @@ -131,16 +131,8 @@ LL | fn fnc(&self) -> Trait { | ^^^ ...because method `fnc` has generic type parameters = help: consider moving `fnc` to another trait -error: `(dyn Trait<{const error}> + 'static)` is forbidden as the type of a const generic parameter - --> $DIR/ice-hir-wf-check-anon-const-issue-122199.rs:1:22 - | -LL | trait Trait { - | ^^^^^ - | - = note: the only supported types are integers, `bool` and `char` - error: associated item referring to unboxed trait object for its own trait - --> $DIR/ice-hir-wf-check-anon-const-issue-122199.rs:12:44 + --> $DIR/ice-hir-wf-check-anon-const-issue-122199.rs:11:44 | LL | trait Trait { | ----- in this trait @@ -154,7 +146,7 @@ LL | fn fnc(&self) -> Self { | ~~~~ warning: trait objects without an explicit `dyn` are deprecated - --> $DIR/ice-hir-wf-check-anon-const-issue-122199.rs:12:21 + --> $DIR/ice-hir-wf-check-anon-const-issue-122199.rs:11:21 | LL | fn fnc(&self) -> Trait { | ^^^^^ @@ -168,13 +160,13 @@ LL | fn fnc(&self) -> Trait { | +++ error[E0038]: the trait `Trait` cannot be made into an object - --> $DIR/ice-hir-wf-check-anon-const-issue-122199.rs:12:21 + --> $DIR/ice-hir-wf-check-anon-const-issue-122199.rs:11:21 | LL | fn fnc(&self) -> Trait { | ^^^^^ `Trait` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/ice-hir-wf-check-anon-const-issue-122199.rs:12:8 + --> $DIR/ice-hir-wf-check-anon-const-issue-122199.rs:11:8 | LL | trait Trait { | ----- this trait cannot be made into an object... @@ -190,7 +182,7 @@ LL | trait Trait { | ^^^^^^^^^^^^^^^^^^^^ `Trait` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/ice-hir-wf-check-anon-const-issue-122199.rs:12:8 + --> $DIR/ice-hir-wf-check-anon-const-issue-122199.rs:11:8 | LL | trait Trait { | ----- this trait cannot be made into an object... @@ -200,15 +192,7 @@ LL | fn fnc(&self) -> Trait { = help: consider moving `fnc` to another trait = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -error: `(dyn Trait<{const error}> + 'static)` is forbidden as the type of a const generic parameter - --> $DIR/ice-hir-wf-check-anon-const-issue-122199.rs:12:21 - | -LL | fn fnc(&self) -> Trait { - | ^^^^^ - | - = note: the only supported types are integers, `bool` and `char` - -error: aborting due to 13 previous errors; 5 warnings emitted +error: aborting due to 11 previous errors; 5 warnings emitted Some errors have detailed explanations: E0038, E0391, E0403, E0423, E0425. For more information about an error, try `rustc --explain E0038`. diff --git a/tests/ui/wf/ice-hir-wf-check-anon-const-issue-122989.stderr b/tests/ui/wf/ice-hir-wf-check-anon-const-issue-122989.stderr index d2b0e2d92e01f..f8905437c6ea6 100644 --- a/tests/ui/wf/ice-hir-wf-check-anon-const-issue-122989.stderr +++ b/tests/ui/wf/ice-hir-wf-check-anon-const-issue-122989.stderr @@ -73,7 +73,7 @@ error: `(dyn Bar<2> + 'static)` is forbidden as the type of a const generic para LL | trait Foo> { | ^^^^^^ | - = note: the only supported types are integers, `bool` and `char` + = note: the only supported types are integers, `bool`, and `char` error[E0038]: the trait `Foo` cannot be made into an object --> $DIR/ice-hir-wf-check-anon-const-issue-122989.rs:11:11 @@ -104,7 +104,7 @@ error: `(dyn Foo<2> + 'static)` is forbidden as the type of a const generic para LL | trait Bar> {} | ^^^^^^ | - = note: the only supported types are integers, `bool` and `char` + = note: the only supported types are integers, `bool`, and `char` error: aborting due to 5 previous errors; 2 warnings emitted From 4b8a5bd511814ed97640c46ab2232acc0e0ade41 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Thu, 26 Sep 2024 16:48:32 +0200 Subject: [PATCH 1719/2194] panic when an interpreter error gets unintentionally discarded --- .../rustc_const_eval/src/interpret/place.rs | 19 ++- .../src/interpret/validity.rs | 38 +++--- .../src/util/check_validity_requirement.rs | 4 +- .../rustc_middle/src/mir/interpret/error.rs | 61 +++++++++- .../rustc_middle/src/mir/interpret/mod.rs | 12 +- .../src/dataflow_const_prop.rs | 61 ++++++---- compiler/rustc_mir_transform/src/gvn.rs | 115 ++++++++++-------- .../rustc_mir_transform/src/jump_threading.rs | 53 +++++--- .../src/known_panics_lint.rs | 35 +++--- src/tools/miri/src/concurrency/data_race.rs | 2 +- src/tools/miri/src/diagnostics.rs | 6 +- src/tools/miri/src/intrinsics/simd.rs | 3 +- 12 files changed, 262 insertions(+), 147 deletions(-) diff --git a/compiler/rustc_const_eval/src/interpret/place.rs b/compiler/rustc_const_eval/src/interpret/place.rs index 32f90254a9470..05264d32c6ba8 100644 --- a/compiler/rustc_const_eval/src/interpret/place.rs +++ b/compiler/rustc_const_eval/src/interpret/place.rs @@ -13,9 +13,9 @@ use rustc_target::abi::{Abi, Align, HasDataLayout, Size}; use tracing::{instrument, trace}; use super::{ - AllocRef, AllocRefMut, CheckAlignMsg, CtfeProvenance, ImmTy, Immediate, InterpCx, InterpResult, - Machine, MemoryKind, Misalignment, OffsetMode, OpTy, Operand, Pointer, Projectable, Provenance, - Scalar, alloc_range, mir_assign_valid_types, + AllocRef, AllocRefMut, CheckAlignMsg, CtfeProvenance, DiscardInterpError, ImmTy, Immediate, + InterpCx, InterpResult, Machine, MemoryKind, Misalignment, OffsetMode, OpTy, Operand, Pointer, + Projectable, Provenance, Scalar, alloc_range, mir_assign_valid_types, }; #[derive(Copy, Clone, Hash, PartialEq, Eq, Debug)] @@ -490,9 +490,16 @@ where // If an access is both OOB and misaligned, we want to see the bounds error. // However we have to call `check_misalign` first to make the borrow checker happy. let misalign_err = self.check_misalign(mplace.mplace.misaligned, CheckAlignMsg::BasedOn); - let a = self.get_ptr_alloc_mut(mplace.ptr(), size)?; - misalign_err?; - Ok(a) + match self.get_ptr_alloc_mut(mplace.ptr(), size) { + Ok(a) => { + misalign_err?; + Ok(a) + } + Err(e) => { + misalign_err.discard_interp_err(); + Err(e) + } + } } /// Turn a local in the current frame into a place. diff --git a/compiler/rustc_const_eval/src/interpret/validity.rs b/compiler/rustc_const_eval/src/interpret/validity.rs index 203cceccd9d1f..3c9fdd73100c6 100644 --- a/compiler/rustc_const_eval/src/interpret/validity.rs +++ b/compiler/rustc_const_eval/src/interpret/validity.rs @@ -17,8 +17,8 @@ use rustc_hir as hir; use rustc_middle::bug; use rustc_middle::mir::interpret::ValidationErrorKind::{self, *}; use rustc_middle::mir::interpret::{ - ExpectedKind, InterpError, InvalidMetaKind, Misalignment, PointerKind, Provenance, - UnsupportedOpInfo, ValidationErrorInfo, alloc_range, + ExpectedKind, InterpError, InterpErrorInfo, InvalidMetaKind, Misalignment, PointerKind, + Provenance, UnsupportedOpInfo, ValidationErrorInfo, alloc_range, }; use rustc_middle::ty::layout::{LayoutCx, LayoutOf, TyAndLayout}; use rustc_middle::ty::{self, Ty}; @@ -95,16 +95,19 @@ macro_rules! try_validation { Ok(x) => x, // We catch the error and turn it into a validation failure. We are okay with // allocation here as this can only slow down builds that fail anyway. - Err(e) => match e.kind() { - $( - $($p)|+ => - throw_validation_failure!( - $where, - $kind - ) - ),+, - #[allow(unreachable_patterns)] - _ => Err::(e)?, + Err(e) => { + let (kind, backtrace) = e.into_parts(); + match kind { + $( + $($p)|+ => { + throw_validation_failure!( + $where, + $kind + ) + } + ),+, + _ => Err::(InterpErrorInfo::from_parts(kind, backtrace))?, + } } } }}; @@ -510,7 +513,7 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> { Ub(DanglingIntPointer { addr: i, .. }) => DanglingPtrNoProvenance { ptr_kind, // FIXME this says "null pointer" when null but we need translate - pointer: format!("{}", Pointer::>::from_addr_invalid(*i)) + pointer: format!("{}", Pointer::>::from_addr_invalid(i)) }, Ub(PointerOutOfBounds { .. }) => DanglingPtrOutOfBounds { ptr_kind @@ -1231,7 +1234,8 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValueVisitor<'tcx, M> for ValidityVisitor<'rt, Err(err) => { // For some errors we might be able to provide extra information. // (This custom logic does not fit the `try_validation!` macro.) - match err.kind() { + let (kind, backtrace) = err.into_parts(); + match kind { Ub(InvalidUninitBytes(Some((_alloc_id, access)))) | Unsup(ReadPointerAsInt(Some((_alloc_id, access)))) => { // Some byte was uninitialized, determine which // element that byte belongs to so we can @@ -1242,7 +1246,7 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValueVisitor<'tcx, M> for ValidityVisitor<'rt, .unwrap(); self.path.push(PathElem::ArrayElem(i)); - if matches!(err.kind(), Ub(InvalidUninitBytes(_))) { + if matches!(kind, Ub(InvalidUninitBytes(_))) { throw_validation_failure!(self.path, Uninit { expected }) } else { throw_validation_failure!(self.path, PointerAsInt { expected }) @@ -1250,7 +1254,7 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValueVisitor<'tcx, M> for ValidityVisitor<'rt, } // Propagate upwards (that will also check for unexpected errors). - _ => return Err(err), + _ => return Err(InterpErrorInfo::from_parts(kind, backtrace)), } } } @@ -1282,7 +1286,7 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValueVisitor<'tcx, M> for ValidityVisitor<'rt, // It's not great to catch errors here, since we can't give a very good path, // but it's better than ICEing. Ub(InvalidVTableTrait { vtable_dyn_type, expected_dyn_type }) => { - InvalidMetaWrongTrait { vtable_dyn_type, expected_dyn_type: *expected_dyn_type } + InvalidMetaWrongTrait { vtable_dyn_type, expected_dyn_type } }, ); } diff --git a/compiler/rustc_const_eval/src/util/check_validity_requirement.rs b/compiler/rustc_const_eval/src/util/check_validity_requirement.rs index 19393188c9adf..421648d9e7b2a 100644 --- a/compiler/rustc_const_eval/src/util/check_validity_requirement.rs +++ b/compiler/rustc_const_eval/src/util/check_validity_requirement.rs @@ -1,4 +1,5 @@ use rustc_middle::bug; +use rustc_middle::mir::interpret::DiscardInterpError; use rustc_middle::ty::layout::{ HasTyCtxt, LayoutCx, LayoutError, LayoutOf, TyAndLayout, ValidityRequirement, }; @@ -75,7 +76,8 @@ fn check_validity_requirement_strict<'tcx>( /*recursive*/ false, /*reset_provenance_and_padding*/ false, ) - .is_ok()) + .discard_interp_err() + .is_some()) } /// Implements the 'lax' (default) version of the [`check_validity_requirement`] checks; see that diff --git a/compiler/rustc_middle/src/mir/interpret/error.rs b/compiler/rustc_middle/src/mir/interpret/error.rs index 46646e759d59e..06fdb9e1ecdee 100644 --- a/compiler/rustc_middle/src/mir/interpret/error.rs +++ b/compiler/rustc_middle/src/mir/interpret/error.rs @@ -1,7 +1,7 @@ use std::any::Any; use std::backtrace::Backtrace; use std::borrow::Cow; -use std::fmt; +use std::{fmt, mem}; use either::Either; use rustc_ast_ir::Mutability; @@ -104,13 +104,57 @@ rustc_data_structures::static_assert_size!(InterpErrorInfo<'_>, 8); /// These should always be constructed by calling `.into()` on /// an `InterpError`. In `rustc_mir::interpret`, we have `throw_err_*` /// macros for this. +/// +/// Interpreter errors must *not* be silently discarded (that will lead to a panic). Instead, +/// explicitly call `discard_interp_err` if this is really the right thing to do. Note that if +/// this happens during const-eval or in Miri, it could lead to a UB error being lost! #[derive(Debug)] pub struct InterpErrorInfo<'tcx>(Box>); +/// Calling `.ok()` on an `InterpResult` leads to a panic because of the guard. +/// To still let people opt-in to discarding interpreter errors, we have this extension trait. +pub trait DiscardInterpError { + type Output; + + fn discard_interp_err(self) -> Option; +} + +impl<'tcx, T> DiscardInterpError for InterpResult<'tcx, T> { + type Output = T; + + fn discard_interp_err(self) -> Option { + match self { + Ok(v) => Some(v), + Err(e) => { + // Disarm the guard. + mem::forget(e.0.guard); + None + } + } + } +} + +#[derive(Debug)] +struct Guard; + +impl Drop for Guard { + fn drop(&mut self) { + // We silence the guard if we are already panicking, to avoid double-panics. + if !std::thread::panicking() { + panic!( + "an interpreter error got improperly discarded; use `discard_interp_err()` instead of `ok()` if this is intentional" + ); + } + } +} + #[derive(Debug)] struct InterpErrorInfoInner<'tcx> { kind: InterpError<'tcx>, backtrace: InterpErrorBacktrace, + /// This makes us panic on drop. This is used to catch + /// accidentally discarding an interpreter error. + guard: Guard, } #[derive(Debug)] @@ -151,15 +195,25 @@ impl InterpErrorBacktrace { impl<'tcx> InterpErrorInfo<'tcx> { pub fn into_parts(self) -> (InterpError<'tcx>, InterpErrorBacktrace) { - let InterpErrorInfo(box InterpErrorInfoInner { kind, backtrace }) = self; + let InterpErrorInfo(box InterpErrorInfoInner { kind, backtrace, guard }) = self; + mem::forget(guard); // The error got explicitly discarded right here. (kind, backtrace) } pub fn into_kind(self) -> InterpError<'tcx> { - let InterpErrorInfo(box InterpErrorInfoInner { kind, .. }) = self; + let InterpErrorInfo(box InterpErrorInfoInner { kind, guard, .. }) = self; + mem::forget(guard); // The error got explicitly discarded right here. kind } + pub fn discard_interp_err(self) { + mem::forget(self.0.guard); // The error got explicitly discarded right here. + } + + pub fn from_parts(kind: InterpError<'tcx>, backtrace: InterpErrorBacktrace) -> Self { + Self(Box::new(InterpErrorInfoInner { kind, backtrace, guard: Guard })) + } + #[inline] pub fn kind(&self) -> &InterpError<'tcx> { &self.0.kind @@ -191,6 +245,7 @@ impl<'tcx> From> for InterpErrorInfo<'tcx> { InterpErrorInfo(Box::new(InterpErrorInfoInner { kind, backtrace: InterpErrorBacktrace::new(), + guard: Guard, })) } } diff --git a/compiler/rustc_middle/src/mir/interpret/mod.rs b/compiler/rustc_middle/src/mir/interpret/mod.rs index d7809cc4343d2..8ce6f9d230052 100644 --- a/compiler/rustc_middle/src/mir/interpret/mod.rs +++ b/compiler/rustc_middle/src/mir/interpret/mod.rs @@ -34,12 +34,12 @@ pub use self::allocation::{ InitChunkIter, alloc_range, }; pub use self::error::{ - BadBytesAccess, CheckAlignMsg, CheckInAllocMsg, ErrorHandled, EvalStaticInitializerRawResult, - EvalToAllocationRawResult, EvalToConstValueResult, EvalToValTreeResult, ExpectedKind, - InterpError, InterpErrorInfo, InterpResult, InvalidMetaKind, InvalidProgramInfo, - MachineStopType, Misalignment, PointerKind, ReportedErrorInfo, ResourceExhaustionInfo, - ScalarSizeMismatch, UndefinedBehaviorInfo, UnsupportedOpInfo, ValidationErrorInfo, - ValidationErrorKind, + BadBytesAccess, CheckAlignMsg, CheckInAllocMsg, DiscardInterpError, ErrorHandled, + EvalStaticInitializerRawResult, EvalToAllocationRawResult, EvalToConstValueResult, + EvalToValTreeResult, ExpectedKind, InterpError, InterpErrorInfo, InterpResult, InvalidMetaKind, + InvalidProgramInfo, MachineStopType, Misalignment, PointerKind, ReportedErrorInfo, + ResourceExhaustionInfo, ScalarSizeMismatch, UndefinedBehaviorInfo, UnsupportedOpInfo, + ValidationErrorInfo, ValidationErrorKind, }; pub use self::pointer::{CtfeProvenance, Pointer, PointerArithmetic, Provenance}; pub use self::value::Scalar; diff --git a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs index 88dc8e74a8c29..905143b2efbc2 100644 --- a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs +++ b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs @@ -3,7 +3,9 @@ //! Currently, this pass only propagates scalar values. use rustc_const_eval::const_eval::{DummyMachine, throw_machine_stop_str}; -use rustc_const_eval::interpret::{ImmTy, Immediate, InterpCx, OpTy, PlaceTy, Projectable}; +use rustc_const_eval::interpret::{ + DiscardInterpError, ImmTy, Immediate, InterpCx, OpTy, PlaceTy, Projectable, +}; use rustc_data_structures::fx::FxHashMap; use rustc_hir::def::DefKind; use rustc_middle::bug; @@ -364,8 +366,10 @@ impl<'a, 'tcx> ConstAnalysis<'a, 'tcx> { } } Operand::Constant(box constant) => { - if let Ok(constant) = - self.ecx.eval_mir_constant(&constant.const_, constant.span, None) + if let Some(constant) = self + .ecx + .eval_mir_constant(&constant.const_, constant.span, None) + .discard_interp_err() { self.assign_constant(state, place, constant, &[]); } @@ -387,7 +391,7 @@ impl<'a, 'tcx> ConstAnalysis<'a, 'tcx> { for &(mut proj_elem) in projection { if let PlaceElem::Index(index) = proj_elem { if let FlatSet::Elem(index) = state.get(index.into(), &self.map) - && let Ok(offset) = index.to_target_usize(&self.tcx) + && let Some(offset) = index.to_target_usize(&self.tcx).discard_interp_err() && let Some(min_length) = offset.checked_add(1) { proj_elem = PlaceElem::ConstantIndex { offset, min_length, from_end: false }; @@ -395,35 +399,40 @@ impl<'a, 'tcx> ConstAnalysis<'a, 'tcx> { return; } } - operand = if let Ok(operand) = self.ecx.project(&operand, proj_elem) { - operand - } else { - return; - } + operand = + if let Some(operand) = self.ecx.project(&operand, proj_elem).discard_interp_err() { + operand + } else { + return; + } } self.map.for_each_projection_value( place, operand, &mut |elem, op| match elem { - TrackElem::Field(idx) => self.ecx.project_field(op, idx.as_usize()).ok(), - TrackElem::Variant(idx) => self.ecx.project_downcast(op, idx).ok(), + TrackElem::Field(idx) => { + self.ecx.project_field(op, idx.as_usize()).discard_interp_err() + } + TrackElem::Variant(idx) => self.ecx.project_downcast(op, idx).discard_interp_err(), TrackElem::Discriminant => { - let variant = self.ecx.read_discriminant(op).ok()?; - let discr_value = - self.ecx.discriminant_for_variant(op.layout.ty, variant).ok()?; + let variant = self.ecx.read_discriminant(op).discard_interp_err()?; + let discr_value = self + .ecx + .discriminant_for_variant(op.layout.ty, variant) + .discard_interp_err()?; Some(discr_value.into()) } TrackElem::DerefLen => { - let op: OpTy<'_> = self.ecx.deref_pointer(op).ok()?.into(); - let len_usize = op.len(&self.ecx).ok()?; + let op: OpTy<'_> = self.ecx.deref_pointer(op).discard_interp_err()?.into(); + let len_usize = op.len(&self.ecx).discard_interp_err()?; let layout = self.tcx.layout_of(self.param_env.and(self.tcx.types.usize)).unwrap(); Some(ImmTy::from_uint(len_usize, layout).into()) } }, &mut |place, op| { - if let Ok(imm) = self.ecx.read_immediate_raw(op) + if let Some(imm) = self.ecx.read_immediate_raw(op).discard_interp_err() && let Some(imm) = imm.right() { let elem = self.wrap_immediate(*imm); @@ -447,11 +456,11 @@ impl<'a, 'tcx> ConstAnalysis<'a, 'tcx> { (FlatSet::Bottom, _) | (_, FlatSet::Bottom) => (FlatSet::Bottom, FlatSet::Bottom), // Both sides are known, do the actual computation. (FlatSet::Elem(left), FlatSet::Elem(right)) => { - match self.ecx.binary_op(op, &left, &right) { + match self.ecx.binary_op(op, &left, &right).discard_interp_err() { // Ideally this would return an Immediate, since it's sometimes // a pair and sometimes not. But as a hack we always return a pair // and just make the 2nd component `Bottom` when it does not exist. - Ok(val) => { + Some(val) => { if matches!(val.layout.abi, Abi::ScalarPair(..)) { let (val, overflow) = val.to_scalar_pair(); (FlatSet::Elem(val), FlatSet::Elem(overflow)) @@ -470,7 +479,7 @@ impl<'a, 'tcx> ConstAnalysis<'a, 'tcx> { } let arg_scalar = const_arg.to_scalar(); - let Ok(arg_value) = arg_scalar.to_bits(layout.size) else { + let Some(arg_value) = arg_scalar.to_bits(layout.size).discard_interp_err() else { return (FlatSet::Top, FlatSet::Top); }; @@ -518,8 +527,10 @@ impl<'a, 'tcx> ConstAnalysis<'a, 'tcx> { return None; } let enum_ty_layout = self.tcx.layout_of(self.param_env.and(enum_ty)).ok()?; - let discr_value = - self.ecx.discriminant_for_variant(enum_ty_layout.ty, variant_index).ok()?; + let discr_value = self + .ecx + .discriminant_for_variant(enum_ty_layout.ty, variant_index) + .discard_interp_err()?; Some(discr_value.to_scalar()) } @@ -573,7 +584,7 @@ impl<'a, 'tcx> Collector<'a, 'tcx> { map: &Map<'tcx>, ) -> Option> { let ty = place.ty(self.local_decls, self.patch.tcx).ty; - let layout = ecx.layout_of(ty).ok()?; + let layout = ecx.layout_of(ty).discard_interp_err()?; if layout.is_zst() { return Some(Const::zero_sized(ty)); @@ -595,7 +606,7 @@ impl<'a, 'tcx> Collector<'a, 'tcx> { .intern_with_temp_alloc(layout, |ecx, dest| { try_write_constant(ecx, dest, place, ty, state, map) }) - .ok()?; + .discard_interp_err()?; return Some(Const::Val(ConstValue::Indirect { alloc_id, offset: Size::ZERO }, ty)); } @@ -830,7 +841,7 @@ impl<'tcx> MutVisitor<'tcx> for Patch<'tcx> { if let PlaceElem::Index(local) = elem { let offset = self.before_effect.get(&(location, local.into()))?; let offset = offset.try_to_scalar()?; - let offset = offset.to_target_usize(&self.tcx).ok()?; + let offset = offset.to_target_usize(&self.tcx).discard_interp_err()?; let min_length = offset.checked_add(1)?; Some(PlaceElem::ConstantIndex { offset, min_length, from_end: false }) } else { diff --git a/compiler/rustc_mir_transform/src/gvn.rs b/compiler/rustc_mir_transform/src/gvn.rs index f735d08fca573..4dbcc6af9bde4 100644 --- a/compiler/rustc_mir_transform/src/gvn.rs +++ b/compiler/rustc_mir_transform/src/gvn.rs @@ -87,8 +87,8 @@ use std::borrow::Cow; use either::Either; use rustc_const_eval::const_eval::DummyMachine; use rustc_const_eval::interpret::{ - ImmTy, Immediate, InterpCx, MemPlaceMeta, MemoryKind, OpTy, Projectable, Scalar, - intern_const_alloc_for_constprop, + DiscardInterpError, ImmTy, Immediate, InterpCx, MemPlaceMeta, MemoryKind, OpTy, Projectable, + Scalar, intern_const_alloc_for_constprop, }; use rustc_data_structures::fx::FxIndexSet; use rustc_data_structures::graph::dominators::Dominators; @@ -393,7 +393,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { Repeat(..) => return None, Constant { ref value, disambiguator: _ } => { - self.ecx.eval_mir_constant(value, DUMMY_SP, None).ok()? + self.ecx.eval_mir_constant(value, DUMMY_SP, None).discard_interp_err()? } Aggregate(kind, variant, ref fields) => { let fields = fields @@ -414,34 +414,39 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { AggregateTy::RawPtr { output_pointer_ty, .. } => output_pointer_ty, }; let variant = if ty.is_enum() { Some(variant) } else { None }; - let ty = self.ecx.layout_of(ty).ok()?; + let ty = self.ecx.layout_of(ty).discard_interp_err()?; if ty.is_zst() { ImmTy::uninit(ty).into() } else if matches!(kind, AggregateTy::RawPtr { .. }) { // Pointers don't have fields, so don't `project_field` them. - let data = self.ecx.read_pointer(fields[0]).ok()?; + let data = self.ecx.read_pointer(fields[0]).discard_interp_err()?; let meta = if fields[1].layout.is_zst() { MemPlaceMeta::None } else { - MemPlaceMeta::Meta(self.ecx.read_scalar(fields[1]).ok()?) + MemPlaceMeta::Meta(self.ecx.read_scalar(fields[1]).discard_interp_err()?) }; let ptr_imm = Immediate::new_pointer_with_meta(data, meta, &self.ecx); ImmTy::from_immediate(ptr_imm, ty).into() } else if matches!(ty.abi, Abi::Scalar(..) | Abi::ScalarPair(..)) { - let dest = self.ecx.allocate(ty, MemoryKind::Stack).ok()?; + let dest = self.ecx.allocate(ty, MemoryKind::Stack).discard_interp_err()?; let variant_dest = if let Some(variant) = variant { - self.ecx.project_downcast(&dest, variant).ok()? + self.ecx.project_downcast(&dest, variant).discard_interp_err()? } else { dest.clone() }; for (field_index, op) in fields.into_iter().enumerate() { - let field_dest = self.ecx.project_field(&variant_dest, field_index).ok()?; - self.ecx.copy_op(op, &field_dest).ok()?; + let field_dest = self + .ecx + .project_field(&variant_dest, field_index) + .discard_interp_err()?; + self.ecx.copy_op(op, &field_dest).discard_interp_err()?; } - self.ecx.write_discriminant(variant.unwrap_or(FIRST_VARIANT), &dest).ok()?; + self.ecx + .write_discriminant(variant.unwrap_or(FIRST_VARIANT), &dest) + .discard_interp_err()?; self.ecx .alloc_mark_immutable(dest.ptr().provenance.unwrap().alloc_id()) - .ok()?; + .discard_interp_err()?; dest.into() } else { return None; @@ -467,7 +472,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { // This should have been replaced by a `ConstantIndex` earlier. ProjectionElem::Index(_) => return None, }; - self.ecx.project(value, elem).ok()? + self.ecx.project(value, elem).discard_interp_err()? } Address { place, kind, provenance: _ } => { if !place.is_indirect_first_projection() { @@ -475,14 +480,14 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { } let local = self.locals[place.local]?; let pointer = self.evaluated[local].as_ref()?; - let mut mplace = self.ecx.deref_pointer(pointer).ok()?; + let mut mplace = self.ecx.deref_pointer(pointer).discard_interp_err()?; for proj in place.projection.iter().skip(1) { // We have no call stack to associate a local with a value, so we cannot // interpret indexing. if matches!(proj, ProjectionElem::Index(_)) { return None; } - mplace = self.ecx.project(&mplace, proj).ok()?; + mplace = self.ecx.project(&mplace, proj).discard_interp_err()?; } let pointer = mplace.to_ref(&self.ecx); let ty = match kind { @@ -494,26 +499,28 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { ), AddressKind::Address(mutbl) => Ty::new_ptr(self.tcx, mplace.layout.ty, mutbl), }; - let layout = self.ecx.layout_of(ty).ok()?; + let layout = self.ecx.layout_of(ty).discard_interp_err()?; ImmTy::from_immediate(pointer, layout).into() } Discriminant(base) => { let base = self.evaluated[base].as_ref()?; - let variant = self.ecx.read_discriminant(base).ok()?; - let discr_value = - self.ecx.discriminant_for_variant(base.layout.ty, variant).ok()?; + let variant = self.ecx.read_discriminant(base).discard_interp_err()?; + let discr_value = self + .ecx + .discriminant_for_variant(base.layout.ty, variant) + .discard_interp_err()?; discr_value.into() } Len(slice) => { let slice = self.evaluated[slice].as_ref()?; let usize_layout = self.ecx.layout_of(self.tcx.types.usize).unwrap(); - let len = slice.len(&self.ecx).ok()?; + let len = slice.len(&self.ecx).discard_interp_err()?; let imm = ImmTy::from_uint(len, usize_layout); imm.into() } NullaryOp(null_op, ty) => { - let layout = self.ecx.layout_of(ty).ok()?; + let layout = self.ecx.layout_of(ty).discard_interp_err()?; if let NullOp::SizeOf | NullOp::AlignOf = null_op && layout.is_unsized() { @@ -535,36 +542,36 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { } UnaryOp(un_op, operand) => { let operand = self.evaluated[operand].as_ref()?; - let operand = self.ecx.read_immediate(operand).ok()?; - let val = self.ecx.unary_op(un_op, &operand).ok()?; + let operand = self.ecx.read_immediate(operand).discard_interp_err()?; + let val = self.ecx.unary_op(un_op, &operand).discard_interp_err()?; val.into() } BinaryOp(bin_op, lhs, rhs) => { let lhs = self.evaluated[lhs].as_ref()?; - let lhs = self.ecx.read_immediate(lhs).ok()?; + let lhs = self.ecx.read_immediate(lhs).discard_interp_err()?; let rhs = self.evaluated[rhs].as_ref()?; - let rhs = self.ecx.read_immediate(rhs).ok()?; - let val = self.ecx.binary_op(bin_op, &lhs, &rhs).ok()?; + let rhs = self.ecx.read_immediate(rhs).discard_interp_err()?; + let val = self.ecx.binary_op(bin_op, &lhs, &rhs).discard_interp_err()?; val.into() } Cast { kind, value, from: _, to } => match kind { CastKind::IntToInt | CastKind::IntToFloat => { let value = self.evaluated[value].as_ref()?; - let value = self.ecx.read_immediate(value).ok()?; - let to = self.ecx.layout_of(to).ok()?; - let res = self.ecx.int_to_int_or_float(&value, to).ok()?; + let value = self.ecx.read_immediate(value).discard_interp_err()?; + let to = self.ecx.layout_of(to).discard_interp_err()?; + let res = self.ecx.int_to_int_or_float(&value, to).discard_interp_err()?; res.into() } CastKind::FloatToFloat | CastKind::FloatToInt => { let value = self.evaluated[value].as_ref()?; - let value = self.ecx.read_immediate(value).ok()?; - let to = self.ecx.layout_of(to).ok()?; - let res = self.ecx.float_to_float_or_int(&value, to).ok()?; + let value = self.ecx.read_immediate(value).discard_interp_err()?; + let to = self.ecx.layout_of(to).discard_interp_err()?; + let res = self.ecx.float_to_float_or_int(&value, to).discard_interp_err()?; res.into() } CastKind::Transmute => { let value = self.evaluated[value].as_ref()?; - let to = self.ecx.layout_of(to).ok()?; + let to = self.ecx.layout_of(to).discard_interp_err()?; // `offset` for immediates only supports scalar/scalar-pair ABIs, // so bail out if the target is not one. if value.as_mplace_or_imm().is_right() { @@ -574,29 +581,29 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { _ => return None, } } - value.offset(Size::ZERO, to, &self.ecx).ok()? + value.offset(Size::ZERO, to, &self.ecx).discard_interp_err()? } CastKind::PointerCoercion(ty::adjustment::PointerCoercion::Unsize, _) => { let src = self.evaluated[value].as_ref()?; - let to = self.ecx.layout_of(to).ok()?; - let dest = self.ecx.allocate(to, MemoryKind::Stack).ok()?; - self.ecx.unsize_into(src, to, &dest.clone().into()).ok()?; + let to = self.ecx.layout_of(to).discard_interp_err()?; + let dest = self.ecx.allocate(to, MemoryKind::Stack).discard_interp_err()?; + self.ecx.unsize_into(src, to, &dest.clone().into()).discard_interp_err()?; self.ecx .alloc_mark_immutable(dest.ptr().provenance.unwrap().alloc_id()) - .ok()?; + .discard_interp_err()?; dest.into() } CastKind::FnPtrToPtr | CastKind::PtrToPtr => { let src = self.evaluated[value].as_ref()?; - let src = self.ecx.read_immediate(src).ok()?; - let to = self.ecx.layout_of(to).ok()?; - let ret = self.ecx.ptr_to_ptr(&src, to).ok()?; + let src = self.ecx.read_immediate(src).discard_interp_err()?; + let to = self.ecx.layout_of(to).discard_interp_err()?; + let ret = self.ecx.ptr_to_ptr(&src, to).discard_interp_err()?; ret.into() } CastKind::PointerCoercion(ty::adjustment::PointerCoercion::UnsafeFnPointer, _) => { let src = self.evaluated[value].as_ref()?; - let src = self.ecx.read_immediate(src).ok()?; - let to = self.ecx.layout_of(to).ok()?; + let src = self.ecx.read_immediate(src).discard_interp_err()?; + let to = self.ecx.layout_of(to).discard_interp_err()?; ImmTy::from_immediate(*src, to).into() } _ => return None, @@ -708,7 +715,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { && let Some(idx) = self.locals[idx_local] { if let Some(offset) = self.evaluated[idx].as_ref() - && let Ok(offset) = self.ecx.read_target_usize(offset) + && let Some(offset) = self.ecx.read_target_usize(offset).discard_interp_err() && let Some(min_length) = offset.checked_add(1) { projection.to_mut()[i] = @@ -868,7 +875,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { && let DefKind::Enum = self.tcx.def_kind(enum_did) { let enum_ty = self.tcx.type_of(enum_did).instantiate(self.tcx, enum_args); - let discr = self.ecx.discriminant_for_variant(enum_ty, variant).ok()?; + let discr = self.ecx.discriminant_for_variant(enum_ty, variant).discard_interp_err()?; return Some(self.insert_scalar(discr.to_scalar(), discr.layout.ty)); } @@ -1218,13 +1225,13 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { return None; } - let layout = self.ecx.layout_of(lhs_ty).ok()?; + let layout = self.ecx.layout_of(lhs_ty).discard_interp_err()?; let as_bits = |value| { let constant = self.evaluated[value].as_ref()?; if layout.abi.is_scalar() { - let scalar = self.ecx.read_scalar(constant).ok()?; - scalar.to_bits(constant.layout.size).ok() + let scalar = self.ecx.read_scalar(constant).discard_interp_err()?; + scalar.to_bits(constant.layout.size).discard_interp_err() } else { // `constant` is a wide pointer. Do not evaluate to bits. None @@ -1484,7 +1491,7 @@ fn op_to_prop_const<'tcx>( // If this constant has scalar ABI, return it as a `ConstValue::Scalar`. if let Abi::Scalar(abi::Scalar::Initialized { .. }) = op.layout.abi - && let Ok(scalar) = ecx.read_scalar(op) + && let Some(scalar) = ecx.read_scalar(op).discard_interp_err() { if !scalar.try_to_scalar_int().is_ok() { // Check that we do not leak a pointer. @@ -1498,12 +1505,12 @@ fn op_to_prop_const<'tcx>( // If this constant is already represented as an `Allocation`, // try putting it into global memory to return it. if let Either::Left(mplace) = op.as_mplace_or_imm() { - let (size, _align) = ecx.size_and_align_of_mplace(&mplace).ok()??; + let (size, _align) = ecx.size_and_align_of_mplace(&mplace).discard_interp_err()??; // Do not try interning a value that contains provenance. // Due to https://github.com/rust-lang/rust/issues/79738, doing so could lead to bugs. // FIXME: remove this hack once that issue is fixed. - let alloc_ref = ecx.get_ptr_alloc(mplace.ptr(), size).ok()??; + let alloc_ref = ecx.get_ptr_alloc(mplace.ptr(), size).discard_interp_err()??; if alloc_ref.has_provenance() { return None; } @@ -1511,7 +1518,7 @@ fn op_to_prop_const<'tcx>( let pointer = mplace.ptr().into_pointer_or_addr().ok()?; let (prov, offset) = pointer.into_parts(); let alloc_id = prov.alloc_id(); - intern_const_alloc_for_constprop(ecx, alloc_id).ok()?; + intern_const_alloc_for_constprop(ecx, alloc_id).discard_interp_err()?; // `alloc_id` may point to a static. Codegen will choke on an `Indirect` with anything // by `GlobalAlloc::Memory`, so do fall through to copying if needed. @@ -1526,7 +1533,9 @@ fn op_to_prop_const<'tcx>( } // Everything failed: create a new allocation to hold the data. - let alloc_id = ecx.intern_with_temp_alloc(op.layout, |ecx, dest| ecx.copy_op(op, dest)).ok()?; + let alloc_id = ecx + .intern_with_temp_alloc(op.layout, |ecx, dest| ecx.copy_op(op, dest)) + .discard_interp_err()?; let value = ConstValue::Indirect { alloc_id, offset: Size::ZERO }; // Check that we do not leak a pointer. diff --git a/compiler/rustc_mir_transform/src/jump_threading.rs b/compiler/rustc_mir_transform/src/jump_threading.rs index 91fbc91e1e727..e69a7e552f606 100644 --- a/compiler/rustc_mir_transform/src/jump_threading.rs +++ b/compiler/rustc_mir_transform/src/jump_threading.rs @@ -37,7 +37,9 @@ use rustc_arena::DroplessArena; use rustc_const_eval::const_eval::DummyMachine; -use rustc_const_eval::interpret::{ImmTy, Immediate, InterpCx, OpTy, Projectable}; +use rustc_const_eval::interpret::{ + DiscardInterpError, ImmTy, Immediate, InterpCx, OpTy, Projectable, +}; use rustc_data_structures::fx::FxHashSet; use rustc_index::IndexVec; use rustc_index::bit_set::BitSet; @@ -200,7 +202,9 @@ impl<'a, 'tcx> TOFinder<'a, 'tcx> { debug!(?discr, ?bb); let discr_ty = discr.ty(self.body, self.tcx).ty; - let Ok(discr_layout) = self.ecx.layout_of(discr_ty) else { return }; + let Some(discr_layout) = self.ecx.layout_of(discr_ty).discard_interp_err() else { + return; + }; let Some(discr) = self.map.find(discr.as_ref()) else { return }; debug!(?discr); @@ -388,24 +392,28 @@ impl<'a, 'tcx> TOFinder<'a, 'tcx> { lhs, constant, &mut |elem, op| match elem { - TrackElem::Field(idx) => self.ecx.project_field(op, idx.as_usize()).ok(), - TrackElem::Variant(idx) => self.ecx.project_downcast(op, idx).ok(), + TrackElem::Field(idx) => { + self.ecx.project_field(op, idx.as_usize()).discard_interp_err() + } + TrackElem::Variant(idx) => self.ecx.project_downcast(op, idx).discard_interp_err(), TrackElem::Discriminant => { - let variant = self.ecx.read_discriminant(op).ok()?; - let discr_value = - self.ecx.discriminant_for_variant(op.layout.ty, variant).ok()?; + let variant = self.ecx.read_discriminant(op).discard_interp_err()?; + let discr_value = self + .ecx + .discriminant_for_variant(op.layout.ty, variant) + .discard_interp_err()?; Some(discr_value.into()) } TrackElem::DerefLen => { - let op: OpTy<'_> = self.ecx.deref_pointer(op).ok()?.into(); - let len_usize = op.len(&self.ecx).ok()?; + let op: OpTy<'_> = self.ecx.deref_pointer(op).discard_interp_err()?.into(); + let len_usize = op.len(&self.ecx).discard_interp_err()?; let layout = self.ecx.layout_of(self.tcx.types.usize).unwrap(); Some(ImmTy::from_uint(len_usize, layout).into()) } }, &mut |place, op| { if let Some(conditions) = state.try_get_idx(place, &self.map) - && let Ok(imm) = self.ecx.read_immediate_raw(op) + && let Some(imm) = self.ecx.read_immediate_raw(op).discard_interp_err() && let Some(imm) = imm.right() && let Immediate::Scalar(Scalar::Int(int)) = *imm { @@ -429,8 +437,10 @@ impl<'a, 'tcx> TOFinder<'a, 'tcx> { match rhs { // If we expect `lhs ?= A`, we have an opportunity if we assume `constant == A`. Operand::Constant(constant) => { - let Ok(constant) = - self.ecx.eval_mir_constant(&constant.const_, constant.span, None) + let Some(constant) = self + .ecx + .eval_mir_constant(&constant.const_, constant.span, None) + .discard_interp_err() else { return; }; @@ -469,8 +479,10 @@ impl<'a, 'tcx> TOFinder<'a, 'tcx> { AggregateKind::Adt(.., Some(_)) => return, AggregateKind::Adt(_, variant_index, ..) if agg_ty.is_enum() => { if let Some(discr_target) = self.map.apply(lhs, TrackElem::Discriminant) - && let Ok(discr_value) = - self.ecx.discriminant_for_variant(agg_ty, *variant_index) + && let Some(discr_value) = self + .ecx + .discriminant_for_variant(agg_ty, *variant_index) + .discard_interp_err() { self.process_immediate(bb, discr_target, discr_value, state); } @@ -555,7 +567,9 @@ impl<'a, 'tcx> TOFinder<'a, 'tcx> { // `SetDiscriminant` may be a no-op if the assigned variant is the untagged variant // of a niche encoding. If we cannot ensure that we write to the discriminant, do // nothing. - let Ok(enum_layout) = self.ecx.layout_of(enum_ty) else { return }; + let Some(enum_layout) = self.ecx.layout_of(enum_ty).discard_interp_err() else { + return; + }; let writes_discriminant = match enum_layout.variants { Variants::Single { index } => { assert_eq!(index, *variant_index); @@ -568,7 +582,10 @@ impl<'a, 'tcx> TOFinder<'a, 'tcx> { } => *variant_index != untagged_variant, }; if writes_discriminant { - let Ok(discr) = self.ecx.discriminant_for_variant(enum_ty, *variant_index) + let Some(discr) = self + .ecx + .discriminant_for_variant(enum_ty, *variant_index) + .discard_interp_err() else { return; }; @@ -645,7 +662,9 @@ impl<'a, 'tcx> TOFinder<'a, 'tcx> { let Some(discr) = discr.place() else { return }; let discr_ty = discr.ty(self.body, self.tcx).ty; - let Ok(discr_layout) = self.ecx.layout_of(discr_ty) else { return }; + let Some(discr_layout) = self.ecx.layout_of(discr_ty).discard_interp_err() else { + return; + }; let Some(conditions) = state.try_get(discr.as_ref(), &self.map) else { return }; if let Some((value, _)) = targets.iter().find(|&(_, target)| target == target_bb) { diff --git a/compiler/rustc_mir_transform/src/known_panics_lint.rs b/compiler/rustc_mir_transform/src/known_panics_lint.rs index 783e7aabe8543..b165ea53440e0 100644 --- a/compiler/rustc_mir_transform/src/known_panics_lint.rs +++ b/compiler/rustc_mir_transform/src/known_panics_lint.rs @@ -6,7 +6,7 @@ use std::fmt::Debug; use rustc_const_eval::const_eval::DummyMachine; use rustc_const_eval::interpret::{ - ImmTy, InterpCx, InterpResult, Projectable, Scalar, format_interp_error, + DiscardInterpError, ImmTy, InterpCx, InterpResult, Projectable, Scalar, format_interp_error, }; use rustc_data_structures::fx::FxHashSet; use rustc_hir::HirId; @@ -101,7 +101,8 @@ impl<'tcx> Value<'tcx> { } (PlaceElem::Index(idx), Value::Aggregate { fields, .. }) => { let idx = prop.get_const(idx.into())?.immediate()?; - let idx = prop.ecx.read_target_usize(idx).ok()?.try_into().ok()?; + let idx = + prop.ecx.read_target_usize(idx).discard_interp_err()?.try_into().ok()?; if idx <= FieldIdx::MAX_AS_U32 { fields.get(FieldIdx::from_u32(idx)).unwrap_or(&Value::Uninit) } else { @@ -243,6 +244,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { "known panics lint encountered formatting error: {}", format_interp_error(self.ecx.tcx.dcx(), error), ); + error.discard_interp_err(); None } } @@ -347,9 +349,9 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { // We need the type of the LHS. We cannot use `place_layout` as that is the type // of the result, which for checked binops is not the same! let left_ty = left.ty(self.local_decls(), self.tcx); - let left_size = self.ecx.layout_of(left_ty).ok()?.size; + let left_size = self.ecx.layout_of(left_ty).discard_interp_err()?.size; let right_size = r.layout.size; - let r_bits = r.to_scalar().to_bits(right_size).ok(); + let r_bits = r.to_scalar().to_bits(right_size).discard_interp_err(); if r_bits.is_some_and(|b| b >= left_size.bits() as u128) { debug!("check_binary_op: reporting assert for {:?}", location); let panic = AssertKind::Overflow( @@ -496,7 +498,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { // This can be `None` if the lhs wasn't const propagated and we just // triggered the assert on the value of the rhs. self.eval_operand(op) - .and_then(|op| self.ecx.read_immediate(&op).ok()) + .and_then(|op| self.ecx.read_immediate(&op).discard_interp_err()) .map_or(DbgVal::Underscore, |op| DbgVal::Val(op.to_const_int())) }; let msg = match msg { @@ -540,7 +542,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { return None; } use rustc_middle::mir::Rvalue::*; - let layout = self.ecx.layout_of(dest.ty(self.body, self.tcx).ty).ok()?; + let layout = self.ecx.layout_of(dest.ty(self.body, self.tcx).ty).discard_interp_err()?; trace!(?layout); let val: Value<'_> = match *rvalue { @@ -602,7 +604,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { Len(place) => { let len = match self.get_const(place)? { - Value::Immediate(src) => src.len(&self.ecx).ok()?, + Value::Immediate(src) => src.len(&self.ecx).discard_interp_err()?, Value::Aggregate { fields, .. } => fields.len() as u64, Value::Uninit => match place.ty(self.local_decls(), self.tcx).ty.kind() { ty::Array(_, n) => n.try_eval_target_usize(self.tcx, self.param_env)?, @@ -633,21 +635,21 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { Cast(ref kind, ref value, to) => match kind { CastKind::IntToInt | CastKind::IntToFloat => { let value = self.eval_operand(value)?; - let value = self.ecx.read_immediate(&value).ok()?; - let to = self.ecx.layout_of(to).ok()?; - let res = self.ecx.int_to_int_or_float(&value, to).ok()?; + let value = self.ecx.read_immediate(&value).discard_interp_err()?; + let to = self.ecx.layout_of(to).discard_interp_err()?; + let res = self.ecx.int_to_int_or_float(&value, to).discard_interp_err()?; res.into() } CastKind::FloatToFloat | CastKind::FloatToInt => { let value = self.eval_operand(value)?; - let value = self.ecx.read_immediate(&value).ok()?; - let to = self.ecx.layout_of(to).ok()?; - let res = self.ecx.float_to_float_or_int(&value, to).ok()?; + let value = self.ecx.read_immediate(&value).discard_interp_err()?; + let to = self.ecx.layout_of(to).discard_interp_err()?; + let res = self.ecx.float_to_float_or_int(&value, to).discard_interp_err()?; res.into() } CastKind::Transmute => { let value = self.eval_operand(value)?; - let to = self.ecx.layout_of(to).ok()?; + let to = self.ecx.layout_of(to).discard_interp_err()?; // `offset` for immediates only supports scalar/scalar-pair ABIs, // so bail out if the target is not one. match (value.layout.abi, to.abi) { @@ -656,7 +658,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { _ => return None, } - value.offset(Size::ZERO, to, &self.ecx).ok()?.into() + value.offset(Size::ZERO, to, &self.ecx).discard_interp_err()?.into() } _ => return None, }, @@ -781,7 +783,8 @@ impl<'tcx> Visitor<'tcx> for ConstPropagator<'_, 'tcx> { TerminatorKind::SwitchInt { ref discr, ref targets } => { if let Some(ref value) = self.eval_operand(discr) && let Some(value_const) = self.use_ecx(|this| this.ecx.read_scalar(value)) - && let Ok(constant) = value_const.to_bits(value_const.size()) + && let Some(constant) = + value_const.to_bits(value_const.size()).discard_interp_err() { // We managed to evaluate the discriminant, so we know we only need to visit // one target. diff --git a/src/tools/miri/src/concurrency/data_race.rs b/src/tools/miri/src/concurrency/data_race.rs index d1cd15aab3dde..5910be22a690a 100644 --- a/src/tools/miri/src/concurrency/data_race.rs +++ b/src/tools/miri/src/concurrency/data_race.rs @@ -641,7 +641,7 @@ pub trait EvalContextExt<'tcx>: MiriInterpCxExt<'tcx> { // The program didn't actually do a read, so suppress the memory access hooks. // This is also a very special exception where we just ignore an error -- if this read // was UB e.g. because the memory is uninitialized, we don't want to know! - let old_val = this.run_for_validation(|this| this.read_scalar(dest)).ok(); + let old_val = this.run_for_validation(|this| this.read_scalar(dest)).discard_interp_err(); this.allow_data_races_mut(move |this| this.write_scalar(val, dest))?; this.validate_atomic_store(dest, atomic)?; this.buffered_atomic_write(val, dest, atomic, old_val) diff --git a/src/tools/miri/src/diagnostics.rs b/src/tools/miri/src/diagnostics.rs index 4445550512b49..ee087ece9d833 100644 --- a/src/tools/miri/src/diagnostics.rs +++ b/src/tools/miri/src/diagnostics.rs @@ -223,7 +223,10 @@ pub fn report_error<'tcx>( let info = info.downcast_ref::().expect("invalid MachineStop payload"); use TerminationInfo::*; let title = match info { - Exit { code, leak_check } => return Some((*code, *leak_check)), + &Exit { code, leak_check } => { + e.discard_interp_err(); + return Some((code, leak_check)); + } Abort(_) => Some("abnormal termination"), UnsupportedInIsolation(_) | Int2PtrWithStrictProvenance | UnsupportedForeignItem(_) => Some("unsupported operation"), @@ -375,6 +378,7 @@ pub fn report_error<'tcx>( InvalidProgramInfo::AlreadyReported(_) ) => { // This got already reported. No point in reporting it again. + e.discard_interp_err(); return None; } _ => diff --git a/src/tools/miri/src/intrinsics/simd.rs b/src/tools/miri/src/intrinsics/simd.rs index 802a70e5a54aa..7f43c61cd66d8 100644 --- a/src/tools/miri/src/intrinsics/simd.rs +++ b/src/tools/miri/src/intrinsics/simd.rs @@ -247,7 +247,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // This does NaN adjustments. let val = this.binary_op(mir_op, &left, &right).map_err(|err| { match err.kind() { - InterpError::UndefinedBehavior(UndefinedBehaviorInfo::ShiftOverflow { shift_amount, .. }) => { + &InterpError::UndefinedBehavior(UndefinedBehaviorInfo::ShiftOverflow { shift_amount, .. }) => { + err.discard_interp_err(); // This resets the interpreter backtrace, but it's not worth avoiding that. let shift_amount = match shift_amount { Either::Left(v) => v.to_string(), From 15ac6983930a0d49b921c0330dbbb5a4f8f1d34a Mon Sep 17 00:00:00 2001 From: lcnr Date: Mon, 30 Sep 2024 10:18:27 +0200 Subject: [PATCH 1720/2194] canonicalizer: rm region uniquification, add caching --- .../src/canonicalizer.rs | 247 ++++++++++-------- 1 file changed, 138 insertions(+), 109 deletions(-) diff --git a/compiler/rustc_next_trait_solver/src/canonicalizer.rs b/compiler/rustc_next_trait_solver/src/canonicalizer.rs index 196ddeb244302..5c3c35b7b3e46 100644 --- a/compiler/rustc_next_trait_solver/src/canonicalizer.rs +++ b/compiler/rustc_next_trait_solver/src/canonicalizer.rs @@ -1,5 +1,6 @@ use std::cmp::Ordering; +use rustc_type_ir::data_structures::HashMap; use rustc_type_ir::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable}; use rustc_type_ir::inherent::*; use rustc_type_ir::visit::TypeVisitableExt; @@ -44,8 +45,15 @@ pub struct Canonicalizer<'a, D: SolverDelegate, I: Interner> { canonicalize_mode: CanonicalizeMode, variables: &'a mut Vec, + variable_lookup_table: HashMap, + primitive_var_infos: Vec>, binder_index: ty::DebruijnIndex, + + /// We only use the debruijn index during lookup as all other fields + /// should not be impacted by whether a type is folded once or multiple + /// times. + cache: HashMap<(ty::DebruijnIndex, I::Ty), I::Ty>, } impl<'a, D: SolverDelegate, I: Interner> Canonicalizer<'a, D, I> { @@ -60,12 +68,14 @@ impl<'a, D: SolverDelegate, I: Interner> Canonicalizer<'a, D, I> { canonicalize_mode, variables, + variable_lookup_table: Default::default(), primitive_var_infos: Vec::new(), binder_index: ty::INNERMOST, + + cache: Default::default(), }; let value = value.fold_with(&mut canonicalizer); - // FIXME: Restore these assertions. Should we uplift type flags? assert!(!value.has_infer(), "unexpected infer in {value:?}"); assert!(!value.has_placeholders(), "unexpected placeholders in {value:?}"); @@ -75,6 +85,37 @@ impl<'a, D: SolverDelegate, I: Interner> Canonicalizer<'a, D, I> { Canonical { defining_opaque_types, max_universe, variables, value } } + fn get_or_insert_bound_var( + &mut self, + arg: impl Into, + canonical_var_info: CanonicalVarInfo, + ) -> ty::BoundVar { + // FIXME: 16 is made up and arbitrary. We should look at some + // perf data here. + let arg = arg.into(); + let idx = if self.variables.len() > 16 { + if self.variable_lookup_table.is_empty() { + self.variable_lookup_table.extend(self.variables.iter().copied().zip(0..)); + } + + *self.variable_lookup_table.entry(arg).or_insert_with(|| { + let var = self.variables.len(); + self.variables.push(arg); + self.primitive_var_infos.push(canonical_var_info); + var + }) + } else { + self.variables.iter().position(|&v| v == arg).unwrap_or_else(|| { + let var = self.variables.len(); + self.variables.push(arg); + self.primitive_var_infos.push(canonical_var_info); + var + }) + }; + + ty::BoundVar::from(idx) + } + fn finalize(self) -> (ty::UniverseIndex, I::CanonicalVars) { let mut var_infos = self.primitive_var_infos; // See the rustc-dev-guide section about how we deal with universes @@ -124,8 +165,8 @@ impl<'a, D: SolverDelegate, I: Interner> Canonicalizer<'a, D, I> { // - var_infos: [E0, U1, E2, U1, E1, E6, U6], curr_compressed_uv: 2, next_orig_uv: 6 // - var_infos: [E0, U1, E1, U1, E1, E3, U3], curr_compressed_uv: 2, next_orig_uv: - // - // This algorithm runs in `O(n²)` where `n` is the number of different universe - // indices in the input. This should be fine as `n` is expected to be small. + // This algorithm runs in `O(mn)` where `n` is the number of different universes and + // `m` the number of variables. This should be fine as both are expected to be small. let mut curr_compressed_uv = ty::UniverseIndex::ROOT; let mut existential_in_new_uv = None; let mut next_orig_uv = Some(ty::UniverseIndex::ROOT); @@ -185,14 +226,16 @@ impl<'a, D: SolverDelegate, I: Interner> Canonicalizer<'a, D, I> { for var in var_infos.iter_mut() { // We simply put all regions from the input into the highest // compressed universe, so we only deal with them at the end. - if !var.is_region() && is_existential == var.is_existential() { - update_uv(var, orig_uv, is_existential) + if !var.is_region() { + if is_existential == var.is_existential() { + update_uv(var, orig_uv, is_existential) + } } } } } - // We uniquify regions and always put them into their own universe + // We put all regions into a separate universe. let mut first_region = true; for var in var_infos.iter_mut() { if var.is_region() { @@ -208,93 +251,8 @@ impl<'a, D: SolverDelegate, I: Interner> Canonicalizer<'a, D, I> { let var_infos = self.delegate.cx().mk_canonical_var_infos(&var_infos); (curr_compressed_uv, var_infos) } -} - -impl, I: Interner> TypeFolder for Canonicalizer<'_, D, I> { - fn cx(&self) -> I { - self.delegate.cx() - } - - fn fold_binder(&mut self, t: ty::Binder) -> ty::Binder - where - T: TypeFoldable, - { - self.binder_index.shift_in(1); - let t = t.super_fold_with(self); - self.binder_index.shift_out(1); - t - } - - fn fold_region(&mut self, r: I::Region) -> I::Region { - let kind = match r.kind() { - ty::ReBound(..) => return r, - - // We may encounter `ReStatic` in item signatures or the hidden type - // of an opaque. `ReErased` should only be encountered in the hidden - // type of an opaque for regions that are ignored for the purposes of - // captures. - // - // FIXME: We should investigate the perf implications of not uniquifying - // `ReErased`. We may be able to short-circuit registering region - // obligations if we encounter a `ReErased` on one side, for example. - ty::ReStatic | ty::ReErased | ty::ReError(_) => match self.canonicalize_mode { - CanonicalizeMode::Input => CanonicalVarKind::Region(ty::UniverseIndex::ROOT), - CanonicalizeMode::Response { .. } => return r, - }, - - ty::ReEarlyParam(_) | ty::ReLateParam(_) => match self.canonicalize_mode { - CanonicalizeMode::Input => CanonicalVarKind::Region(ty::UniverseIndex::ROOT), - CanonicalizeMode::Response { .. } => { - panic!("unexpected region in response: {r:?}") - } - }, - - ty::RePlaceholder(placeholder) => match self.canonicalize_mode { - // We canonicalize placeholder regions as existentials in query inputs. - CanonicalizeMode::Input => CanonicalVarKind::Region(ty::UniverseIndex::ROOT), - CanonicalizeMode::Response { max_input_universe } => { - // If we have a placeholder region inside of a query, it must be from - // a new universe. - if max_input_universe.can_name(placeholder.universe()) { - panic!("new placeholder in universe {max_input_universe:?}: {r:?}"); - } - CanonicalVarKind::PlaceholderRegion(placeholder) - } - }, - - ty::ReVar(vid) => { - assert_eq!( - self.delegate.opportunistic_resolve_lt_var(vid), - r, - "region vid should have been resolved fully before canonicalization" - ); - match self.canonicalize_mode { - CanonicalizeMode::Input => CanonicalVarKind::Region(ty::UniverseIndex::ROOT), - CanonicalizeMode::Response { .. } => { - CanonicalVarKind::Region(self.delegate.universe_of_lt(vid).unwrap()) - } - } - } - }; - - let existing_bound_var = match self.canonicalize_mode { - CanonicalizeMode::Input => None, - CanonicalizeMode::Response { .. } => { - self.variables.iter().position(|&v| v == r.into()).map(ty::BoundVar::from) - } - }; - - let var = existing_bound_var.unwrap_or_else(|| { - let var = ty::BoundVar::from(self.variables.len()); - self.variables.push(r.into()); - self.primitive_var_infos.push(CanonicalVarInfo { kind }); - var - }); - Region::new_anon_bound(self.cx(), self.binder_index, var) - } - - fn fold_ty(&mut self, t: I::Ty) -> I::Ty { + fn cached_fold_ty(&mut self, t: I::Ty) -> I::Ty { let kind = match t.kind() { ty::Infer(i) => match i { ty::TyVar(vid) => { @@ -368,20 +326,98 @@ impl, I: Interner> TypeFolder for Canonicaliz | ty::Tuple(_) | ty::Alias(_, _) | ty::Bound(_, _) - | ty::Error(_) => return t.super_fold_with(self), + | ty::Error(_) => { + return t.super_fold_with(self); + } }; - let var = ty::BoundVar::from( - self.variables.iter().position(|&v| v == t.into()).unwrap_or_else(|| { - let var = self.variables.len(); - self.variables.push(t.into()); - self.primitive_var_infos.push(CanonicalVarInfo { kind }); - var - }), - ); + let var = self.get_or_insert_bound_var(t, CanonicalVarInfo { kind }); Ty::new_anon_bound(self.cx(), self.binder_index, var) } +} + +impl, I: Interner> TypeFolder for Canonicalizer<'_, D, I> { + fn cx(&self) -> I { + self.delegate.cx() + } + + fn fold_binder(&mut self, t: ty::Binder) -> ty::Binder + where + T: TypeFoldable, + { + self.binder_index.shift_in(1); + let t = t.super_fold_with(self); + self.binder_index.shift_out(1); + t + } + + fn fold_region(&mut self, r: I::Region) -> I::Region { + let kind = match r.kind() { + ty::ReBound(..) => return r, + + // We may encounter `ReStatic` in item signatures or the hidden type + // of an opaque. `ReErased` should only be encountered in the hidden + // type of an opaque for regions that are ignored for the purposes of + // captures. + // + // FIXME: We should investigate the perf implications of not uniquifying + // `ReErased`. We may be able to short-circuit registering region + // obligations if we encounter a `ReErased` on one side, for example. + ty::ReStatic | ty::ReErased | ty::ReError(_) => match self.canonicalize_mode { + CanonicalizeMode::Input => CanonicalVarKind::Region(ty::UniverseIndex::ROOT), + CanonicalizeMode::Response { .. } => return r, + }, + + ty::ReEarlyParam(_) | ty::ReLateParam(_) => match self.canonicalize_mode { + CanonicalizeMode::Input => CanonicalVarKind::Region(ty::UniverseIndex::ROOT), + CanonicalizeMode::Response { .. } => { + panic!("unexpected region in response: {r:?}") + } + }, + + ty::RePlaceholder(placeholder) => match self.canonicalize_mode { + // We canonicalize placeholder regions as existentials in query inputs. + CanonicalizeMode::Input => CanonicalVarKind::Region(ty::UniverseIndex::ROOT), + CanonicalizeMode::Response { max_input_universe } => { + // If we have a placeholder region inside of a query, it must be from + // a new universe. + if max_input_universe.can_name(placeholder.universe()) { + panic!("new placeholder in universe {max_input_universe:?}: {r:?}"); + } + CanonicalVarKind::PlaceholderRegion(placeholder) + } + }, + + ty::ReVar(vid) => { + assert_eq!( + self.delegate.opportunistic_resolve_lt_var(vid), + r, + "region vid should have been resolved fully before canonicalization" + ); + match self.canonicalize_mode { + CanonicalizeMode::Input => CanonicalVarKind::Region(ty::UniverseIndex::ROOT), + CanonicalizeMode::Response { .. } => { + CanonicalVarKind::Region(self.delegate.universe_of_lt(vid).unwrap()) + } + } + } + }; + + let var = self.get_or_insert_bound_var(r, CanonicalVarInfo { kind }); + + Region::new_anon_bound(self.cx(), self.binder_index, var) + } + + fn fold_ty(&mut self, t: I::Ty) -> I::Ty { + if let Some(&ty) = self.cache.get(&(self.binder_index, t)) { + ty + } else { + let res = self.cached_fold_ty(t); + assert!(self.cache.insert((self.binder_index, t), res).is_none()); + res + } + } fn fold_const(&mut self, c: I::Const) -> I::Const { let kind = match c.kind() { @@ -419,14 +455,7 @@ impl, I: Interner> TypeFolder for Canonicaliz | ty::ConstKind::Expr(_) => return c.super_fold_with(self), }; - let var = ty::BoundVar::from( - self.variables.iter().position(|&v| v == c.into()).unwrap_or_else(|| { - let var = self.variables.len(); - self.variables.push(c.into()); - self.primitive_var_infos.push(CanonicalVarInfo { kind }); - var - }), - ); + let var = self.get_or_insert_bound_var(c, CanonicalVarInfo { kind }); Const::new_anon_bound(self.cx(), self.binder_index, var) } From 020bd6d323f20fa3c723320ee5b8484a8bcaa6cb Mon Sep 17 00:00:00 2001 From: Urgau Date: Mon, 30 Sep 2024 11:15:05 +0200 Subject: [PATCH 1721/2194] Improve `--print=check-cfg` documentation --- .../src/compiler-flags/print-check-cfg.md | 27 +++++++++++-------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/src/doc/unstable-book/src/compiler-flags/print-check-cfg.md b/src/doc/unstable-book/src/compiler-flags/print-check-cfg.md index ab63c986e856e..8d314aa62d4cc 100644 --- a/src/doc/unstable-book/src/compiler-flags/print-check-cfg.md +++ b/src/doc/unstable-book/src/compiler-flags/print-check-cfg.md @@ -4,23 +4,28 @@ The tracking issue for this feature is: [#125704](https://github.com/rust-lang/r ------------------------ -This option of the `--print` flag print the list of expected cfgs. +This option of the `--print` flag print the list of all the expected cfgs. -This is related to the `--check-cfg` flag which allows specifying arbitrary expected +This is related to the [`--check-cfg` flag][check-cfg] which allows specifying arbitrary expected names and values. -This print option works similarly to `--print=cfg` (modulo check-cfg specifics): - - *check_cfg syntax*: *output of --print=check-cfg* - - `cfg(windows)`: `windows` - - `cfg(feature, values("foo", "bar"))`: `feature="foo"` and `feature="bar"` - - `cfg(feature, values(none(), ""))`: `feature` and `feature=""` - - `cfg(feature, values(any()))`: `feature=any()` - - `cfg(feature, values())`: `feature=` - - `cfg(any())`: `any()` - - *nothing*: `any()=any()` +This print option works similarly to `--print=cfg` (modulo check-cfg specifics). + +| `--check-cfg` | `--print=check-cfg` | +|-----------------------------------|-----------------------------| +| `cfg(foo)` | `foo` | +| `cfg(foo, values("bar"))` | `foo="bar"` | +| `cfg(foo, values(none(), "bar"))` | `foo` & `foo="bar"` | +| | *check-cfg specific syntax* | +| `cfg(foo, values(any())` | `foo=any()` | +| `cfg(foo, values())` | `foo=` | +| `cfg(any())` | `any()` | +| *none* | `any()=any()` | To be used like this: ```bash rustc --print=check-cfg -Zunstable-options lib.rs ``` + +[check-cfg]: https://doc.rust-lang.org/nightly/rustc/check-cfg.html From 874d55cea8af386d23663dcea1821d9697e028ff Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Mon, 30 Sep 2024 13:05:44 +0300 Subject: [PATCH 1722/2194] enable compiler fingerprint logs in verbose mode Signed-off-by: onur-ozkan --- src/bootstrap/src/core/builder.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/bootstrap/src/core/builder.rs b/src/bootstrap/src/core/builder.rs index 47420f8fe72fb..122eb50dd946e 100644 --- a/src/bootstrap/src/core/builder.rs +++ b/src/bootstrap/src/core/builder.rs @@ -2012,6 +2012,11 @@ impl<'a> Builder<'a> { cargo.env("RUSTC_BACKTRACE_ON_ICE", "1"); } + if self.is_verbose() { + // This provides very useful logs especially when debugging build cache-related stuff. + cargo.env("CARGO_LOG", "cargo::core::compiler::fingerprint=info"); + } + cargo.env("RUSTC_VERBOSE", self.verbosity.to_string()); // Downstream forks of the Rust compiler might want to use a custom libc to add support for From 9cb540a13cb2249754ea3e755cb1472151d061db Mon Sep 17 00:00:00 2001 From: Urgau Date: Mon, 30 Sep 2024 12:13:17 +0200 Subject: [PATCH 1723/2194] Reject leading unsafe in `cfg!(...)` and `--check-cfg`. --- compiler/rustc_builtin_macros/src/cfg.rs | 2 +- compiler/rustc_interface/src/interface.rs | 2 +- .../unsafe/extraneous-unsafe-attributes.rs | 6 +++++- .../extraneous-unsafe-attributes.stderr | 20 ++++++++++++++++++- tests/ui/check-cfg/invalid-arguments.rs | 3 ++- .../invalid-arguments.unsafe_attr.stderr | 5 +++++ 6 files changed, 33 insertions(+), 5 deletions(-) create mode 100644 tests/ui/check-cfg/invalid-arguments.unsafe_attr.stderr diff --git a/compiler/rustc_builtin_macros/src/cfg.rs b/compiler/rustc_builtin_macros/src/cfg.rs index de198115fa00b..cf1d5c68eadd0 100644 --- a/compiler/rustc_builtin_macros/src/cfg.rs +++ b/compiler/rustc_builtin_macros/src/cfg.rs @@ -43,7 +43,7 @@ fn parse_cfg<'a>(cx: &ExtCtxt<'a>, span: Span, tts: TokenStream) -> PResult<'a, return Err(cx.dcx().create_err(errors::RequiresCfgPattern { span })); } - let cfg = p.parse_meta_item(AllowLeadingUnsafe::Yes)?; + let cfg = p.parse_meta_item(AllowLeadingUnsafe::No)?; let _ = p.eat(&token::Comma); diff --git a/compiler/rustc_interface/src/interface.rs b/compiler/rustc_interface/src/interface.rs index c2241773c8ccb..780693f893290 100644 --- a/compiler/rustc_interface/src/interface.rs +++ b/compiler/rustc_interface/src/interface.rs @@ -174,7 +174,7 @@ pub(crate) fn parse_check_cfg(dcx: DiagCtxtHandle<'_>, specs: Vec) -> Ch } }; - let meta_item = match parser.parse_meta_item(AllowLeadingUnsafe::Yes) { + let meta_item = match parser.parse_meta_item(AllowLeadingUnsafe::No) { Ok(meta_item) if parser.token == token::Eof => meta_item, Ok(..) => expected_error(), Err(err) => { diff --git a/tests/ui/attributes/unsafe/extraneous-unsafe-attributes.rs b/tests/ui/attributes/unsafe/extraneous-unsafe-attributes.rs index b561550c19843..273b127bf9cb4 100644 --- a/tests/ui/attributes/unsafe/extraneous-unsafe-attributes.rs +++ b/tests/ui/attributes/unsafe/extraneous-unsafe-attributes.rs @@ -27,4 +27,8 @@ mod inner { #[unsafe(used)] //~ ERROR: is not an unsafe attribute static FOO: usize = 0; -fn main() {} +fn main() { + let _a = cfg!(unsafe(foo)); + //~^ ERROR: expected identifier, found keyword `unsafe` + //~^^ ERROR: invalid predicate `r#unsafe` +} diff --git a/tests/ui/attributes/unsafe/extraneous-unsafe-attributes.stderr b/tests/ui/attributes/unsafe/extraneous-unsafe-attributes.stderr index 9fb7f062b912b..445d239d86729 100644 --- a/tests/ui/attributes/unsafe/extraneous-unsafe-attributes.stderr +++ b/tests/ui/attributes/unsafe/extraneous-unsafe-attributes.stderr @@ -22,6 +22,23 @@ LL | #[unsafe(test)] | = note: extraneous unsafe is not allowed in attributes +error: expected identifier, found keyword `unsafe` + --> $DIR/extraneous-unsafe-attributes.rs:31:19 + | +LL | let _a = cfg!(unsafe(foo)); + | ^^^^^^ expected identifier, found keyword + | +help: escape `unsafe` to use it as an identifier + | +LL | let _a = cfg!(r#unsafe(foo)); + | ++ + +error[E0537]: invalid predicate `r#unsafe` + --> $DIR/extraneous-unsafe-attributes.rs:31:19 + | +LL | let _a = cfg!(unsafe(foo)); + | ^^^^^^^^^^^ + error: `ignore` is not an unsafe attribute --> $DIR/extraneous-unsafe-attributes.rs:13:3 | @@ -62,5 +79,6 @@ LL | #[unsafe(used)] | = note: extraneous unsafe is not allowed in attributes -error: aborting due to 8 previous errors +error: aborting due to 10 previous errors +For more information about this error, try `rustc --explain E0537`. diff --git a/tests/ui/check-cfg/invalid-arguments.rs b/tests/ui/check-cfg/invalid-arguments.rs index b8588ecb4ff68..c6b1218ce27c9 100644 --- a/tests/ui/check-cfg/invalid-arguments.rs +++ b/tests/ui/check-cfg/invalid-arguments.rs @@ -8,7 +8,7 @@ //@ revisions: values_any_missing_values values_any_before_ident ident_in_values_1 //@ revisions: ident_in_values_2 unknown_meta_item_1 unknown_meta_item_2 unknown_meta_item_3 //@ revisions: mixed_values_any mixed_any any_values giberich unterminated -//@ revisions: none_not_empty cfg_none +//@ revisions: none_not_empty cfg_none unsafe_attr // //@ [anything_else]compile-flags: --check-cfg=anything_else(...) //@ [boolean]compile-flags: --check-cfg=cfg(true) @@ -33,5 +33,6 @@ //@ [cfg_none]compile-flags: --check-cfg=cfg(none()) //@ [giberich]compile-flags: --check-cfg=cfg(...) //@ [unterminated]compile-flags: --check-cfg=cfg( +//@ [unsafe_attr]compile-flags: --check-cfg=unsafe(cfg(foo)) fn main() {} diff --git a/tests/ui/check-cfg/invalid-arguments.unsafe_attr.stderr b/tests/ui/check-cfg/invalid-arguments.unsafe_attr.stderr new file mode 100644 index 0000000000000..5236ed6f60547 --- /dev/null +++ b/tests/ui/check-cfg/invalid-arguments.unsafe_attr.stderr @@ -0,0 +1,5 @@ +error: invalid `--check-cfg` argument: `unsafe(cfg(foo))` + | + = note: expected `cfg(name, values("value1", "value2", ... "valueN"))` + = note: visit for more details + From 5a7058c5a542ec42d1fa9b524f7b4f7d6845d1e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=AE=B8=E6=9D=B0=E5=8F=8B=20Jieyou=20Xu=20=28Joe=29?= <39484203+jieyouxu@users.noreply.github.com> Date: Mon, 30 Sep 2024 17:07:24 +0800 Subject: [PATCH 1724/2194] Drop conditionally applied cargo `-Zon-broken-pipe=kill` flags These conditionally applied flags trigger rebuilds because they can invalidate previous cargo build cache. --- src/bootstrap/src/core/build_steps/compile.rs | 4 ---- src/bootstrap/src/core/build_steps/tool.rs | 11 ++++------- 2 files changed, 4 insertions(+), 11 deletions(-) diff --git a/src/bootstrap/src/core/build_steps/compile.rs b/src/bootstrap/src/core/build_steps/compile.rs index eaa982d4e2bbd..bb1d8d279288d 100644 --- a/src/bootstrap/src/core/build_steps/compile.rs +++ b/src/bootstrap/src/core/build_steps/compile.rs @@ -1053,10 +1053,6 @@ pub fn rustc_cargo( cargo.rustdocflag("-Zcrate-attr=warn(rust_2018_idioms)"); - // If the rustc output is piped to e.g. `head -n1` we want the process to be - // killed, rather than having an error bubble up and cause a panic. - cargo.rustflag("-Zon-broken-pipe=kill"); - if builder.config.llvm_enzyme { cargo.rustflag("-l").rustflag("Enzyme-19"); } diff --git a/src/bootstrap/src/core/build_steps/tool.rs b/src/bootstrap/src/core/build_steps/tool.rs index 64dfe054d9c77..fa2c1b8360f4c 100644 --- a/src/bootstrap/src/core/build_steps/tool.rs +++ b/src/bootstrap/src/core/build_steps/tool.rs @@ -200,6 +200,10 @@ pub fn prepare_tool_cargo( cargo.arg("--features").arg(features.join(", ")); } + // Warning: be very careful with RUSTFLAGS or command-line options, as conditionally applied + // RUSTFLAGS or cli flags can lead to hard-to-diagnose rebuilds due to flag differences, causing + // previous tool build artifacts to get invalidated. + // Enable internal lints for clippy and rustdoc // NOTE: this doesn't enable lints for any other tools unless they explicitly add `#![warn(rustc::internal)]` // See https://github.com/rust-lang/rust/pull/80573#issuecomment-754010776 @@ -209,13 +213,6 @@ pub fn prepare_tool_cargo( // See https://github.com/rust-lang/rust/issues/116538 cargo.rustflag("-Zunstable-options"); - // `-Zon-broken-pipe=kill` breaks cargo tests - if !path.ends_with("cargo") { - // If the output is piped to e.g. `head -n1` we want the process to be killed, - // rather than having an error bubble up and cause a panic. - cargo.rustflag("-Zon-broken-pipe=kill"); - } - cargo } From fd1429a56b5c6eadb6205c982f4945b631f55db9 Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Mon, 30 Sep 2024 14:20:12 +0300 Subject: [PATCH 1725/2194] replace manual verbose checks with `Config::is_verbose` Signed-off-by: onur-ozkan --- src/bootstrap/src/core/builder.rs | 4 ++-- src/bootstrap/src/core/config/config.rs | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/bootstrap/src/core/builder.rs b/src/bootstrap/src/core/builder.rs index 47420f8fe72fb..5653b29fda8fa 100644 --- a/src/bootstrap/src/core/builder.rs +++ b/src/bootstrap/src/core/builder.rs @@ -1562,8 +1562,8 @@ impl<'a> Builder<'a> { let libdir = self.rustc_libdir(compiler); let sysroot_str = sysroot.as_os_str().to_str().expect("sysroot should be UTF-8"); - if !matches!(self.config.dry_run, DryRun::SelfCheck) { - self.verbose_than(0, || println!("using sysroot {sysroot_str}")); + if self.is_verbose() && !matches!(self.config.dry_run, DryRun::SelfCheck) { + println!("using sysroot {sysroot_str}"); } let mut rustflags = Rustflags::new(target); diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs index 77e0ece31047f..0689a4caa9a31 100644 --- a/src/bootstrap/src/core/config/config.rs +++ b/src/bootstrap/src/core/config/config.rs @@ -2428,7 +2428,7 @@ impl Config { /// Runs a function if verbosity is greater than 0 pub fn verbose(&self, f: impl Fn()) { - if self.verbose > 0 { + if self.is_verbose() { f() } } @@ -2713,7 +2713,7 @@ impl Config { .success(); if has_changes { if if_unchanged { - if self.verbose > 0 { + if self.is_verbose() { println!( "WARNING: saw changes to compiler/ or library/ since {commit}; \ ignoring `download-rustc`" @@ -2810,7 +2810,7 @@ impl Config { let has_changes = !t!(git.as_command_mut().status()).success(); if has_changes { if if_unchanged { - if self.verbose > 0 { + if self.is_verbose() { println!( "warning: saw changes to one of {modified_paths:?} since {commit}; \ ignoring `{option_name}`" From ac2e3180344bdd6092fe2b845df65c4ff4a5aa10 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Thu, 26 Sep 2024 20:16:40 +0200 Subject: [PATCH 1726/2194] make type-check-4 asm tests about non-const expressions --- tests/ui/asm/aarch64/type-check-4.rs | 27 ------------------------ tests/ui/asm/aarch64/type-check-4.stderr | 21 ------------------ tests/ui/asm/non-const.rs | 11 ++++++++++ tests/ui/asm/non-const.stderr | 11 ++++++++++ tests/ui/asm/x86_64/type-check-4.rs | 27 ------------------------ tests/ui/asm/x86_64/type-check-4.stderr | 21 ------------------ 6 files changed, 22 insertions(+), 96 deletions(-) delete mode 100644 tests/ui/asm/aarch64/type-check-4.rs delete mode 100644 tests/ui/asm/aarch64/type-check-4.stderr create mode 100644 tests/ui/asm/non-const.rs create mode 100644 tests/ui/asm/non-const.stderr delete mode 100644 tests/ui/asm/x86_64/type-check-4.rs delete mode 100644 tests/ui/asm/x86_64/type-check-4.stderr diff --git a/tests/ui/asm/aarch64/type-check-4.rs b/tests/ui/asm/aarch64/type-check-4.rs deleted file mode 100644 index c24567bd5b002..0000000000000 --- a/tests/ui/asm/aarch64/type-check-4.rs +++ /dev/null @@ -1,27 +0,0 @@ -//@ only-aarch64 -//@ build-fail - -use std::arch::global_asm; - -fn main() {} - -// Constants must be... constant - -static mut S: i32 = 1; -const fn const_foo(x: i32) -> i32 { - x -} -const fn const_bar(x: T) -> T { - x -} -global_asm!("{}", const unsafe { S }); -//~^ ERROR: evaluation of constant value failed -//~| mutable global memory -global_asm!("{}", const const_foo(0)); -global_asm!("{}", const const_foo(unsafe { S })); -//~^ ERROR: evaluation of constant value failed -//~| mutable global memory -global_asm!("{}", const const_bar(0)); -global_asm!("{}", const const_bar(unsafe { S })); -//~^ ERROR: evaluation of constant value failed -//~| mutable global memory diff --git a/tests/ui/asm/aarch64/type-check-4.stderr b/tests/ui/asm/aarch64/type-check-4.stderr deleted file mode 100644 index 8c22dfcdb5ed6..0000000000000 --- a/tests/ui/asm/aarch64/type-check-4.stderr +++ /dev/null @@ -1,21 +0,0 @@ -error[E0080]: evaluation of constant value failed - --> $DIR/type-check-4.rs:17:34 - | -LL | global_asm!("{}", const unsafe { S }); - | ^ constant accesses mutable global memory - -error[E0080]: evaluation of constant value failed - --> $DIR/type-check-4.rs:21:44 - | -LL | global_asm!("{}", const const_foo(unsafe { S })); - | ^ constant accesses mutable global memory - -error[E0080]: evaluation of constant value failed - --> $DIR/type-check-4.rs:25:44 - | -LL | global_asm!("{}", const const_bar(unsafe { S })); - | ^ constant accesses mutable global memory - -error: aborting due to 3 previous errors - -For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/asm/non-const.rs b/tests/ui/asm/non-const.rs new file mode 100644 index 0000000000000..63c4656322610 --- /dev/null +++ b/tests/ui/asm/non-const.rs @@ -0,0 +1,11 @@ +//@ needs-asm-support + +use std::arch::global_asm; + +fn main() {} + +// Constants must be... constant +fn non_const_fn(x: i32) -> i32 { x } + +global_asm!("/* {} */", const non_const_fn(0)); +//~^ERROR: cannot call non-const fn diff --git a/tests/ui/asm/non-const.stderr b/tests/ui/asm/non-const.stderr new file mode 100644 index 0000000000000..5fae2ac984378 --- /dev/null +++ b/tests/ui/asm/non-const.stderr @@ -0,0 +1,11 @@ +error[E0015]: cannot call non-const fn `non_const_fn` in constants + --> $DIR/non-const.rs:10:31 + | +LL | global_asm!("/* {} */", const non_const_fn(0)); + | ^^^^^^^^^^^^^^^ + | + = note: calls in constants are limited to constant functions, tuple structs and tuple variants + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/asm/x86_64/type-check-4.rs b/tests/ui/asm/x86_64/type-check-4.rs deleted file mode 100644 index ebc6edc07e4cd..0000000000000 --- a/tests/ui/asm/x86_64/type-check-4.rs +++ /dev/null @@ -1,27 +0,0 @@ -//@ only-x86_64 -//@ build-fail - -use std::arch::global_asm; - -fn main() {} - -// Constants must be... constant - -static mut S: i32 = 1; -const fn const_foo(x: i32) -> i32 { - x -} -const fn const_bar(x: T) -> T { - x -} -global_asm!("{}", const unsafe { S }); -//~^ ERROR evaluation of constant value failed -//~| mutable global memory -global_asm!("{}", const const_foo(0)); -global_asm!("{}", const const_foo(unsafe { S })); -//~^ ERROR evaluation of constant value failed -//~| mutable global memory -global_asm!("{}", const const_bar(0)); -global_asm!("{}", const const_bar(unsafe { S })); -//~^ ERROR evaluation of constant value failed -//~| mutable global memory diff --git a/tests/ui/asm/x86_64/type-check-4.stderr b/tests/ui/asm/x86_64/type-check-4.stderr deleted file mode 100644 index 8c22dfcdb5ed6..0000000000000 --- a/tests/ui/asm/x86_64/type-check-4.stderr +++ /dev/null @@ -1,21 +0,0 @@ -error[E0080]: evaluation of constant value failed - --> $DIR/type-check-4.rs:17:34 - | -LL | global_asm!("{}", const unsafe { S }); - | ^ constant accesses mutable global memory - -error[E0080]: evaluation of constant value failed - --> $DIR/type-check-4.rs:21:44 - | -LL | global_asm!("{}", const const_foo(unsafe { S })); - | ^ constant accesses mutable global memory - -error[E0080]: evaluation of constant value failed - --> $DIR/type-check-4.rs:25:44 - | -LL | global_asm!("{}", const const_bar(unsafe { S })); - | ^ constant accesses mutable global memory - -error: aborting due to 3 previous errors - -For more information about this error, try `rustc --explain E0080`. From d073a852205a0b1a711b36d6dc2d87b67dde60e5 Mon Sep 17 00:00:00 2001 From: Chayim Refael Friedman Date: Sun, 29 Sep 2024 23:00:27 +0300 Subject: [PATCH 1727/2194] When resolving labels in `break` and `continue` for the IDE, do not resolve them textually, instead reuse the results of HIR lowering This fixes a bug where labels inside macros were not resolved, but more importantly this prepares us to a future where we have hygiene, and textual equivalence isn't enough to resolve identifiers. --- .../rust-analyzer/crates/hir/src/semantics.rs | 30 +++++-------------- .../crates/hir/src/semantics/source_to_def.rs | 16 +++++++++- .../crates/ide/src/goto_definition.rs | 18 +++++++++++ 3 files changed, 40 insertions(+), 24 deletions(-) diff --git a/src/tools/rust-analyzer/crates/hir/src/semantics.rs b/src/tools/rust-analyzer/crates/hir/src/semantics.rs index fa14b53dbc3d7..fa18182fbb68d 100644 --- a/src/tools/rust-analyzer/crates/hir/src/semantics.rs +++ b/src/tools/rust-analyzer/crates/hir/src/semantics.rs @@ -36,9 +36,9 @@ use span::{EditionedFileId, FileId, HirFileIdRepr}; use stdx::TupleExt; use syntax::{ algo::skip_trivia_token, - ast::{self, HasAttrs as _, HasGenericParams, HasLoopBody, IsString as _}, - match_ast, AstNode, AstToken, Direction, SyntaxKind, SyntaxNode, SyntaxNodePtr, SyntaxToken, - TextRange, TextSize, + ast::{self, HasAttrs as _, HasGenericParams, IsString as _}, + AstNode, AstToken, Direction, SyntaxKind, SyntaxNode, SyntaxNodePtr, SyntaxToken, TextRange, + TextSize, }; use crate::{ @@ -1221,26 +1221,10 @@ impl<'db> SemanticsImpl<'db> { ToDef::to_def(self, src.as_ref()) } - pub fn resolve_label(&self, lifetime: &ast::Lifetime) -> Option

` (where P is one of the previous types except `Self`) + error[E0038]: the trait `Foo` cannot be made into an object --> $DIR/inference_var_self_argument.rs:5:5 | @@ -13,15 +22,6 @@ LL | async fn foo(self: &dyn Foo) { | ^^^ ...because method `foo` is `async` = help: consider moving `foo` to another trait -error[E0307]: invalid `self` parameter type: `&dyn Foo` - --> $DIR/inference_var_self_argument.rs:5:24 - | -LL | async fn foo(self: &dyn Foo) { - | ^^^^^^^^ - | - = note: type of `self` must be `Self` or a type that dereferences to it - = help: consider changing to `self`, `&self`, `&mut self`, `self: Box`, `self: Rc`, `self: Arc`, or `self: Pin

` (where P is one of the previous types except `Self`) - error: aborting due to 2 previous errors Some errors have detailed explanations: E0038, E0307. diff --git a/tests/ui/async-await/issue-66312.stderr b/tests/ui/async-await/issue-66312.stderr index 702e0b375e577..c95ae1147df36 100644 --- a/tests/ui/async-await/issue-66312.stderr +++ b/tests/ui/async-await/issue-66312.stderr @@ -1,9 +1,3 @@ -error[E0308]: mismatched types - --> $DIR/issue-66312.rs:9:8 - | -LL | if x.is_some() { - | ^^^^^^^^^^^ expected `bool`, found `()` - error[E0307]: invalid `self` parameter type: `T` --> $DIR/issue-66312.rs:4:22 | @@ -13,6 +7,12 @@ LL | fn is_some(self: T); = note: type of `self` must be `Self` or a type that dereferences to it = help: consider changing to `self`, `&self`, `&mut self`, `self: Box`, `self: Rc`, `self: Arc`, or `self: Pin

` (where P is one of the previous types except `Self`) +error[E0308]: mismatched types + --> $DIR/issue-66312.rs:9:8 + | +LL | if x.is_some() { + | ^^^^^^^^^^^ expected `bool`, found `()` + error: aborting due to 2 previous errors Some errors have detailed explanations: E0307, E0308. diff --git a/tests/ui/const-generics/opaque_types.stderr b/tests/ui/const-generics/opaque_types.stderr index 847f1da16f612..a060488b3287e 100644 --- a/tests/ui/const-generics/opaque_types.stderr +++ b/tests/ui/const-generics/opaque_types.stderr @@ -1,3 +1,11 @@ +error: `Foo` is forbidden as the type of a const generic parameter + --> $DIR/opaque_types.rs:7:17 + | +LL | fn foo() {} + | ^^^ + | + = note: the only supported types are integers, `bool`, and `char` + error: item does not constrain `Foo::{opaque#0}`, but has it in its signature --> $DIR/opaque_types.rs:7:4 | @@ -68,14 +76,6 @@ LL | type Foo = impl Sized; | ^^^^^^^^^^ = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information -error: `Foo` is forbidden as the type of a const generic parameter - --> $DIR/opaque_types.rs:7:17 - | -LL | fn foo() {} - | ^^^ - | - = note: the only supported types are integers, `bool`, and `char` - error[E0391]: cycle detected when computing type of opaque `Foo::{opaque#0}` --> $DIR/opaque_types.rs:3:12 | diff --git a/tests/ui/delegation/unsupported.stderr b/tests/ui/delegation/unsupported.stderr index 03ded300bb446..6a627be3b64e7 100644 --- a/tests/ui/delegation/unsupported.stderr +++ b/tests/ui/delegation/unsupported.stderr @@ -3,22 +3,6 @@ error: using `#![feature(effects)]` without enabling next trait solver globally = note: the next trait solver must be enabled globally for the effects feature to work correctly = help: use `-Znext-solver` to enable -warning: this function depends on never type fallback being `()` - --> $DIR/unsupported.rs:20:9 - | -LL | fn opaque_ret() -> impl Trait { unimplemented!() } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #123748 - = help: specify the types explicitly -note: in edition 2024, the requirement `!: opaque::Trait` will fail - --> $DIR/unsupported.rs:20:28 - | -LL | fn opaque_ret() -> impl Trait { unimplemented!() } - | ^^^^^^^^^^ - = note: `#[warn(dependency_on_unit_never_type_fallback)]` on by default - error[E0391]: cycle detected when computing type of `opaque::::{synthetic#0}` --> $DIR/unsupported.rs:27:25 | @@ -52,6 +36,22 @@ note: in edition 2024, the requirement `!: opaque::Trait` will fail | LL | pub fn opaque_ret() -> impl Trait { unimplemented!() } | ^^^^^^^^^^ + = note: `#[warn(dependency_on_unit_never_type_fallback)]` on by default + +warning: this function depends on never type fallback being `()` + --> $DIR/unsupported.rs:20:9 + | +LL | fn opaque_ret() -> impl Trait { unimplemented!() } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #123748 + = help: specify the types explicitly +note: in edition 2024, the requirement `!: opaque::Trait` will fail + --> $DIR/unsupported.rs:20:28 + | +LL | fn opaque_ret() -> impl Trait { unimplemented!() } + | ^^^^^^^^^^ error[E0391]: cycle detected when computing type of `opaque::::{synthetic#0}` --> $DIR/unsupported.rs:30:24 diff --git a/tests/ui/feature-gates/feature-gate-impl_trait_in_assoc_type.stderr b/tests/ui/feature-gates/feature-gate-impl_trait_in_assoc_type.stderr index d8a85c8838d4d..7dfd79c728641 100644 --- a/tests/ui/feature-gates/feature-gate-impl_trait_in_assoc_type.stderr +++ b/tests/ui/feature-gates/feature-gate-impl_trait_in_assoc_type.stderr @@ -18,14 +18,6 @@ LL | type Bop = impl std::fmt::Debug; = help: add `#![feature(impl_trait_in_assoc_type)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error: unconstrained opaque type - --> $DIR/feature-gate-impl_trait_in_assoc_type.rs:6:16 - | -LL | type Bar = impl std::fmt::Debug; - | ^^^^^^^^^^^^^^^^^^^^ - | - = note: `Bar` must be used in combination with a concrete type within the same impl - error[E0658]: inherent associated types are unstable --> $DIR/feature-gate-impl_trait_in_assoc_type.rs:14:5 | @@ -36,6 +28,14 @@ LL | type Bop = impl std::fmt::Debug; = help: add `#![feature(inherent_associated_types)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date +error: unconstrained opaque type + --> $DIR/feature-gate-impl_trait_in_assoc_type.rs:6:16 + | +LL | type Bar = impl std::fmt::Debug; + | ^^^^^^^^^^^^^^^^^^^^ + | + = note: `Bar` must be used in combination with a concrete type within the same impl + error: unconstrained opaque type --> $DIR/feature-gate-impl_trait_in_assoc_type.rs:14:16 | diff --git a/tests/ui/impl-trait/impl-fn-predefined-lifetimes.stderr b/tests/ui/impl-trait/impl-fn-predefined-lifetimes.stderr index 50a9f3ebeabb8..91550f0e284c1 100644 --- a/tests/ui/impl-trait/impl-fn-predefined-lifetimes.stderr +++ b/tests/ui/impl-trait/impl-fn-predefined-lifetimes.stderr @@ -19,7 +19,10 @@ error[E0720]: cannot resolve opaque type --> $DIR/impl-fn-predefined-lifetimes.rs:4:35 | LL | fn a<'a>() -> impl Fn(&'a u8) -> (impl Debug + '_) { - | ^^^^^^^^^^^^^^^ cannot resolve opaque type + | ^^^^^^^^^^^^^^^ recursive opaque type +... +LL | |x| x + | ----- returning here with type `{closure@$DIR/impl-fn-predefined-lifetimes.rs:7:5: 7:8}` error: aborting due to 2 previous errors; 1 warning emitted diff --git a/tests/ui/impl-trait/issues/issue-78722-2.stderr b/tests/ui/impl-trait/issues/issue-78722-2.stderr index dc5579c1c829e..2cf6b94dd9d9b 100644 --- a/tests/ui/impl-trait/issues/issue-78722-2.stderr +++ b/tests/ui/impl-trait/issues/issue-78722-2.stderr @@ -1,9 +1,3 @@ -error[E0271]: expected `{async block@$DIR/issue-78722-2.rs:13:13: 13:18}` to be a future that resolves to `u8`, but it resolves to `()` - --> $DIR/issue-78722-2.rs:11:30 - | -LL | fn concrete_use() -> F { - | ^ expected `()`, found `u8` - error[E0308]: mismatched types --> $DIR/issue-78722-2.rs:16:20 | @@ -18,6 +12,12 @@ LL | let f: F = async { 1 }; = note: expected opaque type `F` found `async` block `{async block@$DIR/issue-78722-2.rs:16:20: 16:25}` +error[E0271]: expected `{async block@$DIR/issue-78722-2.rs:13:13: 13:18}` to be a future that resolves to `u8`, but it resolves to `()` + --> $DIR/issue-78722-2.rs:11:30 + | +LL | fn concrete_use() -> F { + | ^ expected `()`, found `u8` + error: aborting due to 2 previous errors Some errors have detailed explanations: E0271, E0308. diff --git a/tests/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle.stderr b/tests/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle.stderr index 3692cc77b0fb4..6485aa207103c 100644 --- a/tests/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle.stderr +++ b/tests/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle.stderr @@ -1,24 +1,3 @@ -error: item does not constrain `a::Foo::{opaque#0}`, but has it in its signature - --> $DIR/recursive-type-alias-impl-trait-declaration-too-subtle.rs:10:12 - | -LL | fn eq(&self, _other: &(Foo, i32)) -> bool { - | ^^ - | - = note: consider moving the opaque type's declaration and defining uses into a separate module -note: this opaque type is in the signature - --> $DIR/recursive-type-alias-impl-trait-declaration-too-subtle.rs:4:16 - | -LL | type Foo = impl PartialEq<(Foo, i32)>; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: unconstrained opaque type - --> $DIR/recursive-type-alias-impl-trait-declaration-too-subtle.rs:4:16 - | -LL | type Foo = impl PartialEq<(Foo, i32)>; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `Foo` must be used in combination with a concrete type within the same module - error[E0053]: method `eq` has an incompatible type for trait --> $DIR/recursive-type-alias-impl-trait-declaration-too-subtle.rs:10:30 | @@ -35,8 +14,21 @@ help: change the parameter type to match the trait LL | fn eq(&self, _other: &(a::Bar, i32)) -> bool { | ~~~~~~~~~~~~~~ +error: item does not constrain `a::Foo::{opaque#0}`, but has it in its signature + --> $DIR/recursive-type-alias-impl-trait-declaration-too-subtle.rs:10:12 + | +LL | fn eq(&self, _other: &(Foo, i32)) -> bool { + | ^^ + | + = note: consider moving the opaque type's declaration and defining uses into a separate module +note: this opaque type is in the signature + --> $DIR/recursive-type-alias-impl-trait-declaration-too-subtle.rs:4:16 + | +LL | type Foo = impl PartialEq<(Foo, i32)>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + error: unconstrained opaque type - --> $DIR/recursive-type-alias-impl-trait-declaration-too-subtle.rs:19:16 + --> $DIR/recursive-type-alias-impl-trait-declaration-too-subtle.rs:4:16 | LL | type Foo = impl PartialEq<(Foo, i32)>; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -64,6 +56,14 @@ help: change the parameter type to match the trait LL | fn eq(&self, _other: &(b::Foo, i32)) -> bool { | ~~~~~~~~~~~~~~ +error: unconstrained opaque type + --> $DIR/recursive-type-alias-impl-trait-declaration-too-subtle.rs:19:16 + | +LL | type Foo = impl PartialEq<(Foo, i32)>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `Foo` must be used in combination with a concrete type within the same module + error: aborting due to 5 previous errors For more information about this error, try `rustc --explain E0053`. diff --git a/tests/ui/impl-trait/where-allowed.stderr b/tests/ui/impl-trait/where-allowed.stderr index 2770a6cc40e59..13f50fcea7b3f 100644 --- a/tests/ui/impl-trait/where-allowed.stderr +++ b/tests/ui/impl-trait/where-allowed.stderr @@ -342,6 +342,47 @@ LL | let _in_return_in_local_variable = || -> impl Fn() { || {} }; | = note: `impl Trait` is only allowed in arguments and return types of functions and methods +error[E0053]: method `in_trait_impl_return` has an incompatible type for trait + --> $DIR/where-allowed.rs:128:34 + | +LL | type Out = impl Debug; + | ---------- the expected opaque type +... +LL | fn in_trait_impl_return() -> impl Debug { () } + | ^^^^^^^^^^ expected opaque type, found a different opaque type + | +note: type in trait + --> $DIR/where-allowed.rs:118:34 + | +LL | fn in_trait_impl_return() -> Self::Out; + | ^^^^^^^^^ + = note: expected signature `fn() -> <() as DummyTrait>::Out` + found signature `fn() -> impl Debug` + = note: distinct uses of `impl Trait` result in different opaque types +help: change the output type to match the trait + | +LL | fn in_trait_impl_return() -> <() as DummyTrait>::Out { () } + | ~~~~~~~~~~~~~~~~~~~~~~~ + +error: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions + --> $DIR/where-allowed.rs:245:36 + | +LL | fn in_method_generic_param_default(_: T) {} + | ^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #36887 + = note: `#[deny(invalid_type_param_default)]` on by default + +error: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions + --> $DIR/where-allowed.rs:238:7 + | +LL | impl T {} + | ^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #36887 + error[E0283]: type annotations needed --> $DIR/where-allowed.rs:46:57 | @@ -362,16 +403,6 @@ LL | fn in_impl_Fn_return_in_return() -> &'static impl Fn() -> impl Debug { pani - impl Fn for Box where Args: Tuple, F: Fn, A: Allocator, F: ?Sized; -error: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions - --> $DIR/where-allowed.rs:238:7 - | -LL | impl T {} - | ^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #36887 - = note: `#[deny(invalid_type_param_default)]` on by default - error[E0118]: no nominal type found for inherent implementation --> $DIR/where-allowed.rs:238:1 | @@ -380,28 +411,6 @@ LL | impl T {} | = note: either implement a trait on it or create a newtype to wrap it instead -error[E0053]: method `in_trait_impl_return` has an incompatible type for trait - --> $DIR/where-allowed.rs:128:34 - | -LL | type Out = impl Debug; - | ---------- the expected opaque type -... -LL | fn in_trait_impl_return() -> impl Debug { () } - | ^^^^^^^^^^ expected opaque type, found a different opaque type - | -note: type in trait - --> $DIR/where-allowed.rs:118:34 - | -LL | fn in_trait_impl_return() -> Self::Out; - | ^^^^^^^^^ - = note: expected signature `fn() -> <() as DummyTrait>::Out` - found signature `fn() -> impl Debug` - = note: distinct uses of `impl Trait` result in different opaque types -help: change the output type to match the trait - | -LL | fn in_trait_impl_return() -> <() as DummyTrait>::Out { () } - | ~~~~~~~~~~~~~~~~~~~~~~~ - error: unconstrained opaque type --> $DIR/where-allowed.rs:121:16 | @@ -410,25 +419,16 @@ LL | type Out = impl Debug; | = note: `Out` must be used in combination with a concrete type within the same impl -error: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions - --> $DIR/where-allowed.rs:245:36 - | -LL | fn in_method_generic_param_default(_: T) {} - | ^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #36887 - error: aborting due to 49 previous errors Some errors have detailed explanations: E0053, E0118, E0283, E0562, E0658, E0666. For more information about an error, try `rustc --explain E0053`. Future incompatibility report: Future breakage diagnostic: error: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions - --> $DIR/where-allowed.rs:238:7 + --> $DIR/where-allowed.rs:245:36 | -LL | impl T {} - | ^^^^^^^^^^^^^^ +LL | fn in_method_generic_param_default(_: T) {} + | ^^^^^^^^^^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #36887 @@ -436,10 +436,10 @@ LL | impl T {} Future breakage diagnostic: error: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions - --> $DIR/where-allowed.rs:245:36 + --> $DIR/where-allowed.rs:238:7 | -LL | fn in_method_generic_param_default(_: T) {} - | ^^^^^^^^^^^^^^ +LL | impl T {} + | ^^^^^^^^^^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #36887 diff --git a/tests/ui/privacy/private-type-in-interface.rs b/tests/ui/privacy/private-type-in-interface.rs index 2e8be28d76ebf..9eadd09867d41 100644 --- a/tests/ui/privacy/private-type-in-interface.rs +++ b/tests/ui/privacy/private-type-in-interface.rs @@ -26,7 +26,5 @@ 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 091cae42dea3c..03225d84fdb34 100644 --- a/tests/ui/privacy/private-type-in-interface.stderr +++ b/tests/ui/privacy/private-type-in-interface.stderr @@ -46,23 +46,11 @@ 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:11 - | -LL | fn g() -> impl Tr2 { 0 } - | ^^^^^^^^^^^^^^^^^^ private type - -error: type `ext::Priv` is private - --> $DIR/private-type-in-interface.rs:30:15 - | -LL | fn g_ext() -> impl Tr2 { 0 } - | ^^^^^^^^^^^^^^^^^^^^ private type - error: type `ext::Priv` is private - --> $DIR/private-type-in-interface.rs:30:15 + --> $DIR/private-type-in-interface.rs:29:15 | LL | fn g_ext() -> impl Tr2 { 0 } | ^^^^^^^^^^^^^^^^^^^^ private type -error: aborting due to 11 previous errors +error: aborting due to 9 previous errors diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-impl-trait.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-impl-trait.stderr index b59c6d1eed8da..1040af7541c08 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-impl-trait.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-impl-trait.stderr @@ -68,76 +68,76 @@ LL | fn huh() -> impl ~const PartialEq + ~const Destruct + Copy; | ^^^^^^^^ error: `~const` can only be applied to `#[const_trait]` traits - --> $DIR/const-impl-trait.rs:25:29 + --> $DIR/const-impl-trait.rs:29:29 | -LL | fn huh() -> impl ~const PartialEq + ~const Destruct + Copy; +LL | fn huh() -> impl ~const PartialEq + ~const Destruct + Copy { | ^^^^^^^^^ - | - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: `~const` can only be applied to `#[const_trait]` traits - --> $DIR/const-impl-trait.rs:25:48 + --> $DIR/const-impl-trait.rs:29:48 | -LL | fn huh() -> impl ~const PartialEq + ~const Destruct + Copy; +LL | fn huh() -> impl ~const PartialEq + ~const Destruct + Copy { | ^^^^^^^^ - | - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: `~const` can only be applied to `#[const_trait]` traits - --> $DIR/const-impl-trait.rs:25:29 + --> $DIR/const-impl-trait.rs:29:29 | -LL | fn huh() -> impl ~const PartialEq + ~const Destruct + Copy; +LL | fn huh() -> impl ~const PartialEq + ~const Destruct + Copy { | ^^^^^^^^^ | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: `~const` can only be applied to `#[const_trait]` traits - --> $DIR/const-impl-trait.rs:25:48 + --> $DIR/const-impl-trait.rs:29:48 | -LL | fn huh() -> impl ~const PartialEq + ~const Destruct + Copy; +LL | fn huh() -> impl ~const PartialEq + ~const Destruct + Copy { | ^^^^^^^^ | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: `~const` can only be applied to `#[const_trait]` traits - --> $DIR/const-impl-trait.rs:29:29 + --> $DIR/const-impl-trait.rs:50:41 | -LL | fn huh() -> impl ~const PartialEq + ~const Destruct + Copy { - | ^^^^^^^^^ +LL | const fn apit(_: impl ~const T + ~const Destruct) {} + | ^^^^^^^^ error: `~const` can only be applied to `#[const_trait]` traits - --> $DIR/const-impl-trait.rs:29:48 + --> $DIR/const-impl-trait.rs:54:73 | -LL | fn huh() -> impl ~const PartialEq + ~const Destruct + Copy { - | ^^^^^^^^ +LL | const fn apit_assoc_bound(_: impl IntoIterator + ~const Destruct) {} + | ^^^^^^^^ error: `~const` can only be applied to `#[const_trait]` traits - --> $DIR/const-impl-trait.rs:29:29 + --> $DIR/const-impl-trait.rs:25:29 | -LL | fn huh() -> impl ~const PartialEq + ~const Destruct + Copy { +LL | fn huh() -> impl ~const PartialEq + ~const Destruct + Copy; | ^^^^^^^^^ | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: `~const` can only be applied to `#[const_trait]` traits - --> $DIR/const-impl-trait.rs:29:48 + --> $DIR/const-impl-trait.rs:25:48 | -LL | fn huh() -> impl ~const PartialEq + ~const Destruct + Copy { +LL | fn huh() -> impl ~const PartialEq + ~const Destruct + Copy; | ^^^^^^^^ | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: `~const` can only be applied to `#[const_trait]` traits - --> $DIR/const-impl-trait.rs:50:41 + --> $DIR/const-impl-trait.rs:25:29 | -LL | const fn apit(_: impl ~const T + ~const Destruct) {} - | ^^^^^^^^ +LL | fn huh() -> impl ~const PartialEq + ~const Destruct + Copy; + | ^^^^^^^^^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: `~const` can only be applied to `#[const_trait]` traits - --> $DIR/const-impl-trait.rs:54:73 + --> $DIR/const-impl-trait.rs:25:48 | -LL | const fn apit_assoc_bound(_: impl IntoIterator + ~const Destruct) {} - | ^^^^^^^^ +LL | fn huh() -> impl ~const PartialEq + ~const Destruct + Copy; + | ^^^^^^^^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: `~const` can only be applied to `#[const_trait]` traits --> $DIR/const-impl-trait.rs:25:29 diff --git a/tests/ui/self/arbitrary-self-opaque.stderr b/tests/ui/self/arbitrary-self-opaque.stderr index 5ccc076bfaf6c..5634b3d6e64a3 100644 --- a/tests/ui/self/arbitrary-self-opaque.stderr +++ b/tests/ui/self/arbitrary-self-opaque.stderr @@ -1,3 +1,12 @@ +error[E0307]: invalid `self` parameter type: `Bar` + --> $DIR/arbitrary-self-opaque.rs:8:18 + | +LL | fn foo(self: Bar) {} + | ^^^ + | + = note: type of `self` must be `Self` or a type that dereferences to it + = help: consider changing to `self`, `&self`, `&mut self`, `self: Box`, `self: Rc`, `self: Arc`, or `self: Pin

` (where P is one of the previous types except `Self`) + error: item does not constrain `Bar::{opaque#0}`, but has it in its signature --> $DIR/arbitrary-self-opaque.rs:8:8 | @@ -19,15 +28,6 @@ LL | type Bar = impl Sized; | = note: `Bar` must be used in combination with a concrete type within the same module -error[E0307]: invalid `self` parameter type: `Bar` - --> $DIR/arbitrary-self-opaque.rs:8:18 - | -LL | fn foo(self: Bar) {} - | ^^^ - | - = note: type of `self` must be `Self` or a type that dereferences to it - = help: consider changing to `self`, `&self`, `&mut self`, `self: Box`, `self: Rc`, `self: Arc`, or `self: Pin

` (where P is one of the previous types except `Self`) - error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0307`. diff --git a/tests/ui/self/arbitrary_self_types_pin_lifetime_mismatch-async.stderr b/tests/ui/self/arbitrary_self_types_pin_lifetime_mismatch-async.stderr index b00260fa0efa4..f3393830eebb3 100644 --- a/tests/ui/self/arbitrary_self_types_pin_lifetime_mismatch-async.stderr +++ b/tests/ui/self/arbitrary_self_types_pin_lifetime_mismatch-async.stderr @@ -9,8 +9,8 @@ LL | async fn a(self: Pin<&Foo>, f: &Foo) -> &Foo { f } | help: consider introducing a named lifetime parameter and update trait if needed | -LL | async fn a<'a>(self: Pin<&'a Foo>, f: &'a Foo) -> &Foo { f } - | ++++ ++ ++ +LL | async fn a<'a>(self: Pin<&Foo>, f: &'a Foo) -> &'a Foo { f } + | ++++ ++ ++ error: lifetime may not live long enough --> $DIR/arbitrary_self_types_pin_lifetime_mismatch-async.rs:11:75 @@ -23,8 +23,8 @@ LL | async fn c(self: Pin<&Self>, f: &Foo, g: &Foo) -> (Pin<&Foo>, &Foo) { ( | help: consider introducing a named lifetime parameter and update trait if needed | -LL | async fn c<'a>(self: Pin<&'a Self>, f: &'a Foo, g: &Foo) -> (Pin<&Foo>, &Foo) { (self, f) } - | ++++ ++ ++ +LL | async fn c<'a>(self: Pin<&Self>, f: &'a Foo, g: &Foo) -> (Pin<&'a Foo>, &'a Foo) { (self, f) } + | ++++ ++ ++ ++ error: lifetime may not live long enough --> $DIR/arbitrary_self_types_pin_lifetime_mismatch-async.rs:17:64 @@ -37,8 +37,8 @@ LL | async fn bar<'a>(self: Alias<&Self>, arg: &'a ()) -> &() { arg } | help: consider reusing a named lifetime parameter and update trait if needed | -LL | async fn bar<'a>(self: Alias<&'a Self>, arg: &'a ()) -> &() { arg } - | ++ +LL | async fn bar<'a>(self: Alias<&Self>, arg: &'a ()) -> &'a () { arg } + | ++ error: aborting due to 3 previous errors diff --git a/tests/ui/self/elision/lt-ref-self-async.fixed b/tests/ui/self/elision/lt-ref-self-async.fixed index 914511641b894..aae94f7a6ccce 100644 --- a/tests/ui/self/elision/lt-ref-self-async.fixed +++ b/tests/ui/self/elision/lt-ref-self-async.fixed @@ -11,34 +11,34 @@ struct Struct<'a> { impl<'a> Struct<'a> { // Test using `&self` sugar: - async fn ref_self<'b>(&'b self, f: &'b u32) -> &u32 { + async fn ref_self<'b>(&self, f: &'b u32) -> &'b u32 { f //~^ ERROR lifetime may not live long enough } // Test using `&Self` explicitly: - async fn ref_Self<'b>(self: &'b Self, f: &'b u32) -> &u32 { + async fn ref_Self<'b>(self: &Self, f: &'b u32) -> &'b u32 { f //~^ ERROR lifetime may not live long enough } - async fn box_ref_Self<'b>(self: Box<&'b Self>, f: &'b u32) -> &u32 { + async fn box_ref_Self<'b>(self: Box<&Self>, f: &'b u32) -> &'b u32 { f //~^ ERROR lifetime may not live long enough } - async fn pin_ref_Self<'b>(self: Pin<&'b Self>, f: &'b u32) -> &u32 { + async fn pin_ref_Self<'b>(self: Pin<&Self>, f: &'b u32) -> &'b u32 { f //~^ ERROR lifetime may not live long enough } - async fn box_box_ref_Self<'b>(self: Box>, f: &'b u32) -> &u32 { + async fn box_box_ref_Self<'b>(self: Box>, f: &'b u32) -> &'b u32 { f //~^ ERROR lifetime may not live long enough } - async fn box_pin_Self<'b>(self: Box>, f: &'b u32) -> &u32 { + async fn box_pin_Self<'b>(self: Box>, f: &'b u32) -> &'b u32 { f //~^ ERROR lifetime may not live long enough } diff --git a/tests/ui/self/elision/lt-ref-self-async.stderr b/tests/ui/self/elision/lt-ref-self-async.stderr index b84044f754887..c43ff49d5080c 100644 --- a/tests/ui/self/elision/lt-ref-self-async.stderr +++ b/tests/ui/self/elision/lt-ref-self-async.stderr @@ -10,8 +10,8 @@ LL | f | help: consider introducing a named lifetime parameter and update trait if needed | -LL | async fn ref_self<'b>(&'b self, f: &'b u32) -> &u32 { - | ++++ ++ ++ +LL | async fn ref_self<'b>(&self, f: &'b u32) -> &'b u32 { + | ++++ ++ ++ error: lifetime may not live long enough --> $DIR/lt-ref-self-async.rs:22:9 @@ -25,8 +25,8 @@ LL | f | help: consider introducing a named lifetime parameter and update trait if needed | -LL | async fn ref_Self<'b>(self: &'b Self, f: &'b u32) -> &u32 { - | ++++ ++ ++ +LL | async fn ref_Self<'b>(self: &Self, f: &'b u32) -> &'b u32 { + | ++++ ++ ++ error: lifetime may not live long enough --> $DIR/lt-ref-self-async.rs:27:9 @@ -40,8 +40,8 @@ LL | f | help: consider introducing a named lifetime parameter and update trait if needed | -LL | async fn box_ref_Self<'b>(self: Box<&'b Self>, f: &'b u32) -> &u32 { - | ++++ ++ ++ +LL | async fn box_ref_Self<'b>(self: Box<&Self>, f: &'b u32) -> &'b u32 { + | ++++ ++ ++ error: lifetime may not live long enough --> $DIR/lt-ref-self-async.rs:32:9 @@ -55,8 +55,8 @@ LL | f | help: consider introducing a named lifetime parameter and update trait if needed | -LL | async fn pin_ref_Self<'b>(self: Pin<&'b Self>, f: &'b u32) -> &u32 { - | ++++ ++ ++ +LL | async fn pin_ref_Self<'b>(self: Pin<&Self>, f: &'b u32) -> &'b u32 { + | ++++ ++ ++ error: lifetime may not live long enough --> $DIR/lt-ref-self-async.rs:37:9 @@ -70,8 +70,8 @@ LL | f | help: consider introducing a named lifetime parameter and update trait if needed | -LL | async fn box_box_ref_Self<'b>(self: Box>, f: &'b u32) -> &u32 { - | ++++ ++ ++ +LL | async fn box_box_ref_Self<'b>(self: Box>, f: &'b u32) -> &'b u32 { + | ++++ ++ ++ error: lifetime may not live long enough --> $DIR/lt-ref-self-async.rs:42:9 @@ -85,8 +85,8 @@ LL | f | help: consider introducing a named lifetime parameter and update trait if needed | -LL | async fn box_pin_Self<'b>(self: Box>, f: &'b u32) -> &u32 { - | ++++ ++ ++ +LL | async fn box_pin_Self<'b>(self: Box>, f: &'b u32) -> &'b u32 { + | ++++ ++ ++ error: aborting due to 6 previous errors diff --git a/tests/ui/self/elision/ref-assoc-async.stderr b/tests/ui/self/elision/ref-assoc-async.stderr index cf54a86b45f06..9f2768d5e695d 100644 --- a/tests/ui/self/elision/ref-assoc-async.stderr +++ b/tests/ui/self/elision/ref-assoc-async.stderr @@ -10,8 +10,8 @@ LL | f | help: consider introducing a named lifetime parameter and update trait if needed | -LL | async fn ref_AssocType<'a>(self: &'a ::AssocType, f: &'a u32) -> &u32 { - | ++++ ++ ++ +LL | async fn ref_AssocType<'a>(self: &::AssocType, f: &'a u32) -> &'a u32 { + | ++++ ++ ++ error: lifetime may not live long enough --> $DIR/ref-assoc-async.rs:24:9 @@ -25,8 +25,8 @@ LL | f | help: consider introducing a named lifetime parameter and update trait if needed | -LL | async fn box_ref_AssocType<'a>(self: Box<&'a ::AssocType>, f: &'a u32) -> &u32 { - | ++++ ++ ++ +LL | async fn box_ref_AssocType<'a>(self: Box<&::AssocType>, f: &'a u32) -> &'a u32 { + | ++++ ++ ++ error: lifetime may not live long enough --> $DIR/ref-assoc-async.rs:29:9 @@ -40,8 +40,8 @@ LL | f | help: consider introducing a named lifetime parameter and update trait if needed | -LL | async fn pin_ref_AssocType<'a>(self: Pin<&'a ::AssocType>, f: &'a u32) -> &u32 { - | ++++ ++ ++ +LL | async fn pin_ref_AssocType<'a>(self: Pin<&::AssocType>, f: &'a u32) -> &'a u32 { + | ++++ ++ ++ error: lifetime may not live long enough --> $DIR/ref-assoc-async.rs:34:9 @@ -55,8 +55,8 @@ LL | f | help: consider introducing a named lifetime parameter and update trait if needed | -LL | async fn box_box_ref_AssocType<'a>(self: Box::AssocType>>, f: &'a u32) -> &u32 { - | ++++ ++ ++ +LL | async fn box_box_ref_AssocType<'a>(self: Box::AssocType>>, f: &'a u32) -> &'a u32 { + | ++++ ++ ++ error: lifetime may not live long enough --> $DIR/ref-assoc-async.rs:39:9 @@ -70,8 +70,8 @@ LL | f | help: consider introducing a named lifetime parameter and update trait if needed | -LL | async fn box_pin_ref_AssocType<'a>(self: Box::AssocType>>, f: &'a u32) -> &u32 { - | ++++ ++ ++ +LL | async fn box_pin_ref_AssocType<'a>(self: Box::AssocType>>, f: &'a u32) -> &'a u32 { + | ++++ ++ ++ error: aborting due to 5 previous errors diff --git a/tests/ui/self/elision/ref-mut-self-async.stderr b/tests/ui/self/elision/ref-mut-self-async.stderr index 62543ba533955..945fb5e028216 100644 --- a/tests/ui/self/elision/ref-mut-self-async.stderr +++ b/tests/ui/self/elision/ref-mut-self-async.stderr @@ -10,8 +10,8 @@ LL | f | help: consider introducing a named lifetime parameter and update trait if needed | -LL | async fn ref_self<'a>(&'a mut self, f: &'a u32) -> &u32 { - | ++++ ++ ++ +LL | async fn ref_self<'a>(&mut self, f: &'a u32) -> &'a u32 { + | ++++ ++ ++ error: lifetime may not live long enough --> $DIR/ref-mut-self-async.rs:20:9 @@ -25,8 +25,8 @@ LL | f | help: consider introducing a named lifetime parameter and update trait if needed | -LL | async fn ref_Self<'a>(self: &'a mut Self, f: &'a u32) -> &u32 { - | ++++ ++ ++ +LL | async fn ref_Self<'a>(self: &mut Self, f: &'a u32) -> &'a u32 { + | ++++ ++ ++ error: lifetime may not live long enough --> $DIR/ref-mut-self-async.rs:25:9 @@ -40,8 +40,8 @@ LL | f | help: consider introducing a named lifetime parameter and update trait if needed | -LL | async fn box_ref_Self<'a>(self: Box<&'a mut Self>, f: &'a u32) -> &u32 { - | ++++ ++ ++ +LL | async fn box_ref_Self<'a>(self: Box<&mut Self>, f: &'a u32) -> &'a u32 { + | ++++ ++ ++ error: lifetime may not live long enough --> $DIR/ref-mut-self-async.rs:30:9 @@ -55,8 +55,8 @@ LL | f | help: consider introducing a named lifetime parameter and update trait if needed | -LL | async fn pin_ref_Self<'a>(self: Pin<&'a mut Self>, f: &'a u32) -> &u32 { - | ++++ ++ ++ +LL | async fn pin_ref_Self<'a>(self: Pin<&mut Self>, f: &'a u32) -> &'a u32 { + | ++++ ++ ++ error: lifetime may not live long enough --> $DIR/ref-mut-self-async.rs:35:9 @@ -70,8 +70,8 @@ LL | f | help: consider introducing a named lifetime parameter and update trait if needed | -LL | async fn box_box_ref_Self<'a>(self: Box>, f: &'a u32) -> &u32 { - | ++++ ++ ++ +LL | async fn box_box_ref_Self<'a>(self: Box>, f: &'a u32) -> &'a u32 { + | ++++ ++ ++ error: lifetime may not live long enough --> $DIR/ref-mut-self-async.rs:40:9 @@ -85,8 +85,8 @@ LL | f | help: consider introducing a named lifetime parameter and update trait if needed | -LL | async fn box_pin_ref_Self<'a>(self: Box>, f: &'a u32) -> &u32 { - | ++++ ++ ++ +LL | async fn box_pin_ref_Self<'a>(self: Box>, f: &'a u32) -> &'a u32 { + | ++++ ++ ++ error: aborting due to 6 previous errors diff --git a/tests/ui/self/elision/ref-mut-struct-async.stderr b/tests/ui/self/elision/ref-mut-struct-async.stderr index f8fb2e4a1383b..149ab01045c1f 100644 --- a/tests/ui/self/elision/ref-mut-struct-async.stderr +++ b/tests/ui/self/elision/ref-mut-struct-async.stderr @@ -10,8 +10,8 @@ LL | f | help: consider introducing a named lifetime parameter and update trait if needed | -LL | async fn ref_Struct<'a>(self: &'a mut Struct, f: &'a u32) -> &u32 { - | ++++ ++ ++ +LL | async fn ref_Struct<'a>(self: &mut Struct, f: &'a u32) -> &'a u32 { + | ++++ ++ ++ error: lifetime may not live long enough --> $DIR/ref-mut-struct-async.rs:18:9 @@ -25,8 +25,8 @@ LL | f | help: consider introducing a named lifetime parameter and update trait if needed | -LL | async fn box_ref_Struct<'a>(self: Box<&'a mut Struct>, f: &'a u32) -> &u32 { - | ++++ ++ ++ +LL | async fn box_ref_Struct<'a>(self: Box<&mut Struct>, f: &'a u32) -> &'a u32 { + | ++++ ++ ++ error: lifetime may not live long enough --> $DIR/ref-mut-struct-async.rs:23:9 @@ -40,8 +40,8 @@ LL | f | help: consider introducing a named lifetime parameter and update trait if needed | -LL | async fn pin_ref_Struct<'a>(self: Pin<&'a mut Struct>, f: &'a u32) -> &u32 { - | ++++ ++ ++ +LL | async fn pin_ref_Struct<'a>(self: Pin<&mut Struct>, f: &'a u32) -> &'a u32 { + | ++++ ++ ++ error: lifetime may not live long enough --> $DIR/ref-mut-struct-async.rs:28:9 @@ -55,8 +55,8 @@ LL | f | help: consider introducing a named lifetime parameter and update trait if needed | -LL | async fn box_box_ref_Struct<'a>(self: Box>, f: &'a u32) -> &u32 { - | ++++ ++ ++ +LL | async fn box_box_ref_Struct<'a>(self: Box>, f: &'a u32) -> &'a u32 { + | ++++ ++ ++ error: lifetime may not live long enough --> $DIR/ref-mut-struct-async.rs:33:9 @@ -70,8 +70,8 @@ LL | f | help: consider introducing a named lifetime parameter and update trait if needed | -LL | async fn box_pin_ref_Struct<'a>(self: Box>, f: &'a u32) -> &u32 { - | ++++ ++ ++ +LL | async fn box_pin_ref_Struct<'a>(self: Box>, f: &'a u32) -> &'a u32 { + | ++++ ++ ++ error: aborting due to 5 previous errors diff --git a/tests/ui/self/elision/ref-self-async.stderr b/tests/ui/self/elision/ref-self-async.stderr index 010d281b00224..a75ece5f2c768 100644 --- a/tests/ui/self/elision/ref-self-async.stderr +++ b/tests/ui/self/elision/ref-self-async.stderr @@ -10,8 +10,8 @@ LL | f | help: consider introducing a named lifetime parameter and update trait if needed | -LL | async fn ref_self<'a>(&'a self, f: &'a u32) -> &u32 { - | ++++ ++ ++ +LL | async fn ref_self<'a>(&self, f: &'a u32) -> &'a u32 { + | ++++ ++ ++ error: lifetime may not live long enough --> $DIR/ref-self-async.rs:30:9 @@ -25,8 +25,8 @@ LL | f | help: consider introducing a named lifetime parameter and update trait if needed | -LL | async fn ref_Self<'a>(self: &'a Self, f: &'a u32) -> &u32 { - | ++++ ++ ++ +LL | async fn ref_Self<'a>(self: &Self, f: &'a u32) -> &'a u32 { + | ++++ ++ ++ error: lifetime may not live long enough --> $DIR/ref-self-async.rs:35:9 @@ -40,8 +40,8 @@ LL | f | help: consider introducing a named lifetime parameter and update trait if needed | -LL | async fn box_ref_Self<'a>(self: Box<&'a Self>, f: &'a u32) -> &u32 { - | ++++ ++ ++ +LL | async fn box_ref_Self<'a>(self: Box<&Self>, f: &'a u32) -> &'a u32 { + | ++++ ++ ++ error: lifetime may not live long enough --> $DIR/ref-self-async.rs:40:9 @@ -55,8 +55,8 @@ LL | f | help: consider introducing a named lifetime parameter and update trait if needed | -LL | async fn pin_ref_Self<'a>(self: Pin<&'a Self>, f: &'a u32) -> &u32 { - | ++++ ++ ++ +LL | async fn pin_ref_Self<'a>(self: Pin<&Self>, f: &'a u32) -> &'a u32 { + | ++++ ++ ++ error: lifetime may not live long enough --> $DIR/ref-self-async.rs:45:9 @@ -70,8 +70,8 @@ LL | f | help: consider introducing a named lifetime parameter and update trait if needed | -LL | async fn box_box_ref_Self<'a>(self: Box>, f: &'a u32) -> &u32 { - | ++++ ++ ++ +LL | async fn box_box_ref_Self<'a>(self: Box>, f: &'a u32) -> &'a u32 { + | ++++ ++ ++ error: lifetime may not live long enough --> $DIR/ref-self-async.rs:50:9 @@ -85,8 +85,8 @@ LL | f | help: consider introducing a named lifetime parameter and update trait if needed | -LL | async fn box_pin_ref_Self<'a>(self: Box>, f: &'a u32) -> &u32 { - | ++++ ++ ++ +LL | async fn box_pin_ref_Self<'a>(self: Box>, f: &'a u32) -> &'a u32 { + | ++++ ++ ++ error: lifetime may not live long enough --> $DIR/ref-self-async.rs:55:9 @@ -100,8 +100,8 @@ LL | f | help: consider introducing a named lifetime parameter and update trait if needed | -LL | async fn wrap_ref_Self_Self<'a>(self: Wrap<&'a Self, Self>, f: &'a u8) -> &u8 { - | ++++ ++ ++ +LL | async fn wrap_ref_Self_Self<'a>(self: Wrap<&Self, Self>, f: &'a u8) -> &'a u8 { + | ++++ ++ ++ error: aborting due to 7 previous errors diff --git a/tests/ui/self/elision/ref-struct-async.stderr b/tests/ui/self/elision/ref-struct-async.stderr index c9376d58f9096..6bdc145223a68 100644 --- a/tests/ui/self/elision/ref-struct-async.stderr +++ b/tests/ui/self/elision/ref-struct-async.stderr @@ -10,8 +10,8 @@ LL | f | help: consider introducing a named lifetime parameter and update trait if needed | -LL | async fn ref_Struct<'a>(self: &'a Struct, f: &'a u32) -> &u32 { - | ++++ ++ ++ +LL | async fn ref_Struct<'a>(self: &Struct, f: &'a u32) -> &'a u32 { + | ++++ ++ ++ error: lifetime may not live long enough --> $DIR/ref-struct-async.rs:18:9 @@ -25,8 +25,8 @@ LL | f | help: consider introducing a named lifetime parameter and update trait if needed | -LL | async fn box_ref_Struct<'a>(self: Box<&'a Struct>, f: &'a u32) -> &u32 { - | ++++ ++ ++ +LL | async fn box_ref_Struct<'a>(self: Box<&Struct>, f: &'a u32) -> &'a u32 { + | ++++ ++ ++ error: lifetime may not live long enough --> $DIR/ref-struct-async.rs:23:9 @@ -40,8 +40,8 @@ LL | f | help: consider introducing a named lifetime parameter and update trait if needed | -LL | async fn pin_ref_Struct<'a>(self: Pin<&'a Struct>, f: &'a u32) -> &u32 { - | ++++ ++ ++ +LL | async fn pin_ref_Struct<'a>(self: Pin<&Struct>, f: &'a u32) -> &'a u32 { + | ++++ ++ ++ error: lifetime may not live long enough --> $DIR/ref-struct-async.rs:28:9 @@ -55,8 +55,8 @@ LL | f | help: consider introducing a named lifetime parameter and update trait if needed | -LL | async fn box_box_ref_Struct<'a>(self: Box>, f: &'a u32) -> &u32 { - | ++++ ++ ++ +LL | async fn box_box_ref_Struct<'a>(self: Box>, f: &'a u32) -> &'a u32 { + | ++++ ++ ++ error: lifetime may not live long enough --> $DIR/ref-struct-async.rs:33:9 @@ -70,8 +70,8 @@ LL | f | help: consider introducing a named lifetime parameter and update trait if needed | -LL | async fn box_pin_Struct<'a>(self: Box>, f: &'a u32) -> &u32 { - | ++++ ++ ++ +LL | async fn box_pin_Struct<'a>(self: Box>, f: &'a u32) -> &'a u32 { + | ++++ ++ ++ error: aborting due to 5 previous errors diff --git a/tests/ui/type-alias-impl-trait/const_generic_type.no_infer.stderr b/tests/ui/type-alias-impl-trait/const_generic_type.no_infer.stderr index b526ab49d8d4a..ec8a51b08188a 100644 --- a/tests/ui/type-alias-impl-trait/const_generic_type.no_infer.stderr +++ b/tests/ui/type-alias-impl-trait/const_generic_type.no_infer.stderr @@ -1,3 +1,11 @@ +error: `Bar` is forbidden as the type of a const generic parameter + --> $DIR/const_generic_type.rs:8:24 + | +LL | async fn test() { + | ^^^^^^^^^^ + | + = note: the only supported types are integers, `bool`, and `char` + error: item does not constrain `Bar::{opaque#0}`, but has it in its signature --> $DIR/const_generic_type.rs:8:10 | @@ -39,13 +47,5 @@ LL | type Bar = impl std::fmt::Display; | = note: `Bar` must be used in combination with a concrete type within the same module -error: `Bar` is forbidden as the type of a const generic parameter - --> $DIR/const_generic_type.rs:8:24 - | -LL | async fn test() { - | ^^^^^^^^^^ - | - = note: the only supported types are integers, `bool`, and `char` - error: aborting due to 4 previous errors diff --git a/tests/ui/type-alias-impl-trait/constrain_inputs.stderr b/tests/ui/type-alias-impl-trait/constrain_inputs.stderr index 2468fb7480b07..436326e66c386 100644 --- a/tests/ui/type-alias-impl-trait/constrain_inputs.stderr +++ b/tests/ui/type-alias-impl-trait/constrain_inputs.stderr @@ -7,19 +7,6 @@ LL | fn execute(ty: Ty<'_>) -> &str { todo!() } = note: lifetimes appearing in an associated or opaque type are not considered constrained = note: consider introducing a named lifetime parameter -error: item does not constrain `lifetime_params::Ty::{opaque#0}`, but has it in its signature - --> $DIR/constrain_inputs.rs:6:8 - | -LL | fn execute(ty: Ty<'_>) -> &str { todo!() } - | ^^^^^^^ - | - = note: consider moving the opaque type's declaration and defining uses into a separate module -note: this opaque type is in the signature - --> $DIR/constrain_inputs.rs:4:19 - | -LL | type Ty<'a> = impl Sized; - | ^^^^^^^^^^ - error[E0581]: return type references an anonymous lifetime, which is not constrained by the fn input types --> $DIR/constrain_inputs.rs:10:35 | @@ -38,6 +25,19 @@ LL | type BadTraitRef = dyn Fn(Ty<'_>) -> &str; = note: lifetimes appearing in an associated or opaque type are not considered constrained = note: consider introducing a named lifetime parameter +error: item does not constrain `lifetime_params::Ty::{opaque#0}`, but has it in its signature + --> $DIR/constrain_inputs.rs:6:8 + | +LL | fn execute(ty: Ty<'_>) -> &str { todo!() } + | ^^^^^^^ + | + = note: consider moving the opaque type's declaration and defining uses into a separate module +note: this opaque type is in the signature + --> $DIR/constrain_inputs.rs:4:19 + | +LL | type Ty<'a> = impl Sized; + | ^^^^^^^^^^ + error[E0581]: return type references an anonymous lifetime, which is not constrained by the fn input types --> $DIR/constrain_inputs.rs:19:31 | diff --git a/tests/ui/type-alias-impl-trait/generic_underconstrained.stderr b/tests/ui/type-alias-impl-trait/generic_underconstrained.stderr index be9b07823ae0a..88529b370f133 100644 --- a/tests/ui/type-alias-impl-trait/generic_underconstrained.stderr +++ b/tests/ui/type-alias-impl-trait/generic_underconstrained.stderr @@ -1,13 +1,8 @@ error[E0277]: the trait bound `T: Trait` is not satisfied - --> $DIR/generic_underconstrained.rs:9:51 + --> $DIR/generic_underconstrained.rs:9:31 | -LL | fn underconstrain(_: T) -> Underconstrained { - | ___________________________________________________^ -LL | | -LL | | -LL | | unimplemented!() -LL | | } - | |_^ the trait `Trait` is not implemented for `T` +LL | fn underconstrain(_: T) -> Underconstrained { + | ^^^^^^^^^^^^^^^^^^^ the trait `Trait` is not implemented for `T` | note: required by a bound on the type alias `Underconstrained` --> $DIR/generic_underconstrained.rs:6:26 @@ -20,10 +15,15 @@ LL | fn underconstrain(_: T) -> Underconstrained { | +++++++ error[E0277]: the trait bound `T: Trait` is not satisfied - --> $DIR/generic_underconstrained.rs:9:31 + --> $DIR/generic_underconstrained.rs:9:51 | -LL | fn underconstrain(_: T) -> Underconstrained { - | ^^^^^^^^^^^^^^^^^^^ the trait `Trait` is not implemented for `T` +LL | fn underconstrain(_: T) -> Underconstrained { + | ___________________________________________________^ +LL | | +LL | | +LL | | unimplemented!() +LL | | } + | |_^ the trait `Trait` is not implemented for `T` | note: required by a bound on the type alias `Underconstrained` --> $DIR/generic_underconstrained.rs:6:26 diff --git a/tests/ui/type-alias-impl-trait/generic_underconstrained2.stderr b/tests/ui/type-alias-impl-trait/generic_underconstrained2.stderr index 15d96191ba9e2..b3b9cbca96854 100644 --- a/tests/ui/type-alias-impl-trait/generic_underconstrained2.stderr +++ b/tests/ui/type-alias-impl-trait/generic_underconstrained2.stderr @@ -1,13 +1,8 @@ error[E0277]: `U` doesn't implement `Debug` - --> $DIR/generic_underconstrained2.rs:8:53 + --> $DIR/generic_underconstrained2.rs:8:33 | -LL | fn underconstrained(_: U) -> Underconstrained { - | _____________________________________________________^ -LL | | -LL | | -LL | | 5u32 -LL | | } - | |_^ `U` cannot be formatted using `{:?}` because it doesn't implement `Debug` +LL | fn underconstrained(_: U) -> Underconstrained { + | ^^^^^^^^^^^^^^^^^^^ `U` cannot be formatted using `{:?}` because it doesn't implement `Debug` | note: required by a bound on the type alias `Underconstrained` --> $DIR/generic_underconstrained2.rs:5:26 @@ -20,15 +15,10 @@ LL | fn underconstrained(_: U) -> Underconstrained { | +++++++++++++++++ error[E0277]: `V` doesn't implement `Debug` - --> $DIR/generic_underconstrained2.rs:17:64 + --> $DIR/generic_underconstrained2.rs:17:43 | -LL | fn underconstrained2(_: U, _: V) -> Underconstrained2 { - | ________________________________________________________________^ -LL | | -LL | | -LL | | 5u32 -LL | | } - | |_^ `V` cannot be formatted using `{:?}` because it doesn't implement `Debug` +LL | fn underconstrained2(_: U, _: V) -> Underconstrained2 { + | ^^^^^^^^^^^^^^^^^^^^ `V` cannot be formatted using `{:?}` because it doesn't implement `Debug` | note: required by a bound on the type alias `Underconstrained2` --> $DIR/generic_underconstrained2.rs:14:27 @@ -41,10 +31,15 @@ LL | fn underconstrained2(_: U, _: V) -> Underconstrained | +++++++++++++++++ error[E0277]: `U` doesn't implement `Debug` - --> $DIR/generic_underconstrained2.rs:8:33 + --> $DIR/generic_underconstrained2.rs:8:53 | -LL | fn underconstrained(_: U) -> Underconstrained { - | ^^^^^^^^^^^^^^^^^^^ `U` cannot be formatted using `{:?}` because it doesn't implement `Debug` +LL | fn underconstrained(_: U) -> Underconstrained { + | _____________________________________________________^ +LL | | +LL | | +LL | | 5u32 +LL | | } + | |_^ `U` cannot be formatted using `{:?}` because it doesn't implement `Debug` | note: required by a bound on the type alias `Underconstrained` --> $DIR/generic_underconstrained2.rs:5:26 @@ -57,10 +52,15 @@ LL | fn underconstrained(_: U) -> Underconstrained { | +++++++++++++++++ error[E0277]: `V` doesn't implement `Debug` - --> $DIR/generic_underconstrained2.rs:17:43 + --> $DIR/generic_underconstrained2.rs:17:64 | -LL | fn underconstrained2(_: U, _: V) -> Underconstrained2 { - | ^^^^^^^^^^^^^^^^^^^^ `V` cannot be formatted using `{:?}` because it doesn't implement `Debug` +LL | fn underconstrained2(_: U, _: V) -> Underconstrained2 { + | ________________________________________________________________^ +LL | | +LL | | +LL | | 5u32 +LL | | } + | |_^ `V` cannot be formatted using `{:?}` because it doesn't implement `Debug` | note: required by a bound on the type alias `Underconstrained2` --> $DIR/generic_underconstrained2.rs:14:27 diff --git a/tests/ui/type-alias-impl-trait/ice-failed-to-resolve-instance-for-110696.stderr b/tests/ui/type-alias-impl-trait/ice-failed-to-resolve-instance-for-110696.stderr index 22c776e171c2f..eace96317dc1d 100644 --- a/tests/ui/type-alias-impl-trait/ice-failed-to-resolve-instance-for-110696.stderr +++ b/tests/ui/type-alias-impl-trait/ice-failed-to-resolve-instance-for-110696.stderr @@ -1,3 +1,9 @@ +error[E0207]: the type parameter `T` is not constrained by the impl trait, self type, or predicates + --> $DIR/ice-failed-to-resolve-instance-for-110696.rs:41:6 + | +LL | impl>>, U> MyIndex> for Scope { + | ^ unconstrained type parameter + error: item does not constrain `DummyT::{opaque#0}`, but has it in its signature --> $DIR/ice-failed-to-resolve-instance-for-110696.rs:28:8 | @@ -24,12 +30,6 @@ note: this opaque type is in the signature LL | type DummyT = impl F; | ^^^^^^ -error[E0207]: the type parameter `T` is not constrained by the impl trait, self type, or predicates - --> $DIR/ice-failed-to-resolve-instance-for-110696.rs:41:6 - | -LL | impl>>, U> MyIndex> for Scope { - | ^ unconstrained type parameter - error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0207`. diff --git a/tests/ui/type-alias-impl-trait/in-where-clause.stderr b/tests/ui/type-alias-impl-trait/in-where-clause.stderr index f1361b47c56e6..5ac09e20b02c2 100644 --- a/tests/ui/type-alias-impl-trait/in-where-clause.stderr +++ b/tests/ui/type-alias-impl-trait/in-where-clause.stderr @@ -1,14 +1,25 @@ -error[E0391]: cycle detected when computing type of `Bar::{opaque#0}` - --> $DIR/in-where-clause.rs:5:12 +error[E0283]: type annotations needed: cannot satisfy `Bar: Send` + --> $DIR/in-where-clause.rs:12:9 | -LL | type Bar = impl Sized; - | ^^^^^^^^^^ +LL | [0; 1 + 2] + | ^^^^^ | -note: ...which requires computing type of opaque `Bar::{opaque#0}`... + = note: cannot satisfy `Bar: Send` +note: required by a bound in `foo` + --> $DIR/in-where-clause.rs:10:10 + | +LL | fn foo() -> Bar + | --- required by a bound in this function +LL | where +LL | Bar: Send, + | ^^^^ required by this bound in `foo` + +error[E0391]: cycle detected when computing type of opaque `Bar::{opaque#0}` --> $DIR/in-where-clause.rs:5:12 | LL | type Bar = impl Sized; | ^^^^^^^^^^ + | note: ...which requires type-checking `foo`... --> $DIR/in-where-clause.rs:8:1 | @@ -17,30 +28,15 @@ LL | | where LL | | Bar: Send, | |______________^ = note: ...which requires revealing opaque types in `[Binder { value: TraitPredicate(, polarity:Positive), bound_vars: [] }]`... - = note: ...which again requires computing type of `Bar::{opaque#0}`, completing the cycle -note: cycle used when checking that `Bar::{opaque#0}` is well-formed +note: ...which requires computing type of `Bar::{opaque#0}`... --> $DIR/in-where-clause.rs:5:12 | LL | type Bar = impl Sized; | ^^^^^^^^^^ + = note: ...which again requires computing type of opaque `Bar::{opaque#0}`, completing the cycle + = note: cycle used when evaluating trait selection obligation `Bar: core::marker::Send` = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information -error[E0283]: type annotations needed: cannot satisfy `Bar: Send` - --> $DIR/in-where-clause.rs:12:9 - | -LL | [0; 1 + 2] - | ^^^^^ - | - = note: cannot satisfy `Bar: Send` -note: required by a bound in `foo` - --> $DIR/in-where-clause.rs:10:10 - | -LL | fn foo() -> Bar - | --- required by a bound in this function -LL | where -LL | Bar: Send, - | ^^^^ required by this bound in `foo` - error: aborting due to 2 previous errors Some errors have detailed explanations: E0283, E0391. diff --git a/tests/ui/type-alias-impl-trait/issue-53092-2.rs b/tests/ui/type-alias-impl-trait/issue-53092-2.rs index 2adfad4fc5b80..2383008d042f7 100644 --- a/tests/ui/type-alias-impl-trait/issue-53092-2.rs +++ b/tests/ui/type-alias-impl-trait/issue-53092-2.rs @@ -1,15 +1,14 @@ #![feature(type_alias_impl_trait)] #![allow(dead_code)] -type Bug = impl Fn(T) -> U + Copy; //~ ERROR cycle detected +type Bug = impl Fn(T) -> U + Copy; const CONST_BUG: Bug = unsafe { std::mem::transmute(|_: u8| ()) }; -//~^ ERROR: non-defining opaque type use -//~| ERROR: item does not constrain -//~| ERROR: item does not constrain +//~^ ERROR cycle detected +//~| ERROR: non-defining opaque type use fn make_bug>() -> Bug { - |x| x.into() //~ ERROR the trait bound `U: From` is not satisfied + |x| x.into() } fn main() { diff --git a/tests/ui/type-alias-impl-trait/issue-53092-2.stderr b/tests/ui/type-alias-impl-trait/issue-53092-2.stderr index 121f765e66726..ac580866704d7 100644 --- a/tests/ui/type-alias-impl-trait/issue-53092-2.stderr +++ b/tests/ui/type-alias-impl-trait/issue-53092-2.stderr @@ -10,75 +10,33 @@ note: for this opaque type LL | type Bug = impl Fn(T) -> U + Copy; | ^^^^^^^^^^^^^^^^^^^^^^ -error[E0391]: cycle detected when computing type of `Bug::{opaque#0}` - --> $DIR/issue-53092-2.rs:4:18 - | -LL | type Bug = impl Fn(T) -> U + Copy; - | ^^^^^^^^^^^^^^^^^^^^^^ - | -note: ...which requires computing type of opaque `Bug::{opaque#0}`... - --> $DIR/issue-53092-2.rs:4:18 - | -LL | type Bug = impl Fn(T) -> U + Copy; - | ^^^^^^^^^^^^^^^^^^^^^^ -note: ...which requires type-checking `CONST_BUG`... +error[E0391]: cycle detected when type-checking `CONST_BUG` --> $DIR/issue-53092-2.rs:6:1 | LL | const CONST_BUG: Bug = unsafe { std::mem::transmute(|_: u8| ()) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | = note: ...which requires computing layout of `Bug`... = note: ...which requires normalizing `Bug`... - = note: ...which again requires computing type of `Bug::{opaque#0}`, completing the cycle -note: cycle used when checking that `Bug::{opaque#0}` is well-formed +note: ...which requires computing type of `Bug::{opaque#0}`... --> $DIR/issue-53092-2.rs:4:18 | LL | type Bug = impl Fn(T) -> U + Copy; | ^^^^^^^^^^^^^^^^^^^^^^ - = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information - -error: item does not constrain `Bug::{opaque#0}`, but has it in its signature - --> $DIR/issue-53092-2.rs:6:7 - | -LL | const CONST_BUG: Bug = unsafe { std::mem::transmute(|_: u8| ()) }; - | ^^^^^^^^^ - | - = note: consider moving the opaque type's declaration and defining uses into a separate module -note: this opaque type is in the signature +note: ...which requires computing type of opaque `Bug::{opaque#0}`... --> $DIR/issue-53092-2.rs:4:18 | LL | type Bug = impl Fn(T) -> U + Copy; | ^^^^^^^^^^^^^^^^^^^^^^ - -error: item does not constrain `Bug::{opaque#0}`, but has it in its signature - --> $DIR/issue-53092-2.rs:6:61 + = note: ...which again requires type-checking `CONST_BUG`, completing the cycle +note: cycle used when checking that `CONST_BUG` is well-formed + --> $DIR/issue-53092-2.rs:6:1 | LL | const CONST_BUG: Bug = unsafe { std::mem::transmute(|_: u8| ()) }; - | ^^^^^^^ - | - = note: consider moving the opaque type's declaration and defining uses into a separate module -note: this opaque type is in the signature - --> $DIR/issue-53092-2.rs:4:18 - | -LL | type Bug = impl Fn(T) -> U + Copy; - | ^^^^^^^^^^^^^^^^^^^^^^ - -error[E0277]: the trait bound `U: From` is not satisfied - --> $DIR/issue-53092-2.rs:12:5 - | -LL | |x| x.into() - | ^^^^^^^^^^^^ the trait `From` is not implemented for `U` - | -note: required by a bound in `make_bug` - --> $DIR/issue-53092-2.rs:11:19 - | -LL | fn make_bug>() -> Bug { - | ^^^^^^^ required by this bound in `make_bug` -help: consider restricting type parameter `U` - | -LL | type Bug> = impl Fn(T) -> U + Copy; - | +++++++++++++++++++++++ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information -error: aborting due to 5 previous errors +error: aborting due to 2 previous errors -Some errors have detailed explanations: E0277, E0391, E0792. -For more information about an error, try `rustc --explain E0277`. +Some errors have detailed explanations: E0391, E0792. +For more information about an error, try `rustc --explain E0391`. diff --git a/tests/ui/type-alias-impl-trait/issue-84660-unsoundness.current.stderr b/tests/ui/type-alias-impl-trait/issue-84660-unsoundness.current.stderr index 2b064dcfc31a5..ec7b9e0e12b3f 100644 --- a/tests/ui/type-alias-impl-trait/issue-84660-unsoundness.current.stderr +++ b/tests/ui/type-alias-impl-trait/issue-84660-unsoundness.current.stderr @@ -1,3 +1,12 @@ +error[E0119]: conflicting implementations of trait `Trait` + --> $DIR/issue-84660-unsoundness.rs:29:1 + | +LL | impl Trait for Out { + | ------------------------------------ first implementation here +... +LL | impl Trait<(), In> for Out { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation + error: item does not constrain `Bar::{opaque#0}`, but has it in its signature --> $DIR/issue-84660-unsoundness.rs:22:8 | @@ -11,15 +20,6 @@ note: this opaque type is in the signature LL | type Bar = impl Foo; | ^^^^^^^^ -error[E0119]: conflicting implementations of trait `Trait` - --> $DIR/issue-84660-unsoundness.rs:29:1 - | -LL | impl Trait for Out { - | ------------------------------------ first implementation here -... -LL | impl Trait<(), In> for Out { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation - error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/type-alias-impl-trait/issue-84660-unsoundness.next.stderr b/tests/ui/type-alias-impl-trait/issue-84660-unsoundness.next.stderr index 5a728a00138c8..e33102f687c53 100644 --- a/tests/ui/type-alias-impl-trait/issue-84660-unsoundness.next.stderr +++ b/tests/ui/type-alias-impl-trait/issue-84660-unsoundness.next.stderr @@ -1,3 +1,12 @@ +error[E0119]: conflicting implementations of trait `Trait` + --> $DIR/issue-84660-unsoundness.rs:29:1 + | +LL | impl Trait for Out { + | ------------------------------------ first implementation here +... +LL | impl Trait<(), In> for Out { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation + error[E0284]: type annotations needed: cannot satisfy `Bar == _` --> $DIR/issue-84660-unsoundness.rs:22:37 | @@ -9,15 +18,6 @@ LL | | unreachable!(); LL | | } | |_____^ cannot satisfy `Bar == _` -error[E0119]: conflicting implementations of trait `Trait` - --> $DIR/issue-84660-unsoundness.rs:29:1 - | -LL | impl Trait for Out { - | ------------------------------------ first implementation here -... -LL | impl Trait<(), In> for Out { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation - error: aborting due to 2 previous errors Some errors have detailed explanations: E0119, E0284. diff --git a/tests/ui/type-alias-impl-trait/nested-in-anon-const.stderr b/tests/ui/type-alias-impl-trait/nested-in-anon-const.stderr index d0fe920b35f4a..aa0c1076117cc 100644 --- a/tests/ui/type-alias-impl-trait/nested-in-anon-const.stderr +++ b/tests/ui/type-alias-impl-trait/nested-in-anon-const.stderr @@ -1,11 +1,3 @@ -error: unconstrained opaque type - --> $DIR/nested-in-anon-const.rs:13:33 - | -LL | type B = impl Sized; - | ^^^^^^^^^^ - | - = note: `B` must be used in combination with a concrete type within the same item - error[E0308]: mismatched types --> $DIR/nested-in-anon-const.rs:12:17 | @@ -15,6 +7,14 @@ LL | | LL | | }, | |_________________^ expected `usize`, found `()` +error: unconstrained opaque type + --> $DIR/nested-in-anon-const.rs:13:33 + | +LL | type B = impl Sized; + | ^^^^^^^^^^ + | + = note: `B` must be used in combination with a concrete type within the same item + error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-4.stderr b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-4.stderr index aedb78bf5e7a1..99646aa4d1b2c 100644 --- a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-4.stderr +++ b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-4.stderr @@ -10,18 +10,6 @@ note: required by a bound on the type alias `Ty` LL | Ty: Id, | ^^^^^^^^^^^^^^ required by this bound -error[E0275]: overflow evaluating the requirement `Ty: Id` - --> $DIR/type-alias-impl-trait-with-cycle-error-4.rs:15:19 - | -LL | fn define() -> Ty {} - | ^^ - | -note: required by a bound on the type alias `Ty` - --> $DIR/type-alias-impl-trait-with-cycle-error-4.rs:13:9 - | -LL | Ty: Id, - | ^^^^^^^^^^^^^^ required by this bound - error[E0275]: overflow evaluating the requirement `Ty: Id` --> $DIR/type-alias-impl-trait-with-cycle-error-4.rs:15:16 | @@ -34,6 +22,6 @@ note: required by a bound on the type alias `Ty` LL | Ty: Id, | ^^^^^^^^^^^^^^ required by this bound -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0275`. diff --git a/tests/ui/typeck/typeck_type_placeholder_item.rs b/tests/ui/typeck/typeck_type_placeholder_item.rs index 29a21a1f45f56..437a1aed40307 100644 --- a/tests/ui/typeck/typeck_type_placeholder_item.rs +++ b/tests/ui/typeck/typeck_type_placeholder_item.rs @@ -160,7 +160,7 @@ impl BadTrait<_> for BadStruct<_> {} //~^ ERROR the placeholder `_` is not allowed within types on item signatures for implementations fn impl_trait() -> impl BadTrait<_> { -//~^ ERROR the placeholder `_` is not allowed within types on item signatures for opaque types +//~^ ERROR the placeholder `_` is not allowed within types on item signatures for functions unimplemented!() } @@ -180,7 +180,7 @@ struct Struct; trait Trait {} impl Trait for Struct {} type Y = impl Trait<_>; -//~^ ERROR the placeholder `_` is not allowed within types on item signatures for opaque types +//~^ ERROR the placeholder `_` is not allowed within types on item signatures for type aliases fn foo() -> Y { Struct } diff --git a/tests/ui/typeck/typeck_type_placeholder_item.stderr b/tests/ui/typeck/typeck_type_placeholder_item.stderr index 2c064fbb19f71..8a765c21624e6 100644 --- a/tests/ui/typeck/typeck_type_placeholder_item.stderr +++ b/tests/ui/typeck/typeck_type_placeholder_item.stderr @@ -484,11 +484,16 @@ help: use type parameters instead LL | impl BadTrait for BadStruct {} | +++ ~ ~ -error[E0121]: the placeholder `_` is not allowed within types on item signatures for opaque types +error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions --> $DIR/typeck_type_placeholder_item.rs:162:34 | LL | fn impl_trait() -> impl BadTrait<_> { | ^ not allowed in type signatures + | +help: use type parameters instead + | +LL | fn impl_trait() -> impl BadTrait { + | +++ ~ error[E0121]: the placeholder `_` is not allowed within types on item signatures for structs --> $DIR/typeck_type_placeholder_item.rs:167:25 @@ -518,33 +523,17 @@ error[E0121]: the placeholder `_` is not allowed within types on item signatures LL | type X = Box<_>; | ^ not allowed in type signatures -error[E0121]: the placeholder `_` is not allowed within types on item signatures for opaque types +error[E0121]: the placeholder `_` is not allowed within types on item signatures for type aliases --> $DIR/typeck_type_placeholder_item.rs:182:21 | LL | type Y = impl Trait<_>; | ^ not allowed in type signatures -error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions - --> $DIR/typeck_type_placeholder_item.rs:44:27 - | -LL | fn test10(&self, _x : _) { } - | ^ not allowed in type signatures - | -help: use type parameters instead - | -LL | fn test10(&self, _x : T) { } - | +++ ~ - -error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions - --> $DIR/typeck_type_placeholder_item.rs:110:34 - | -LL | fn fn_test10(&self, _x : _) { } - | ^ not allowed in type signatures - | -help: use type parameters instead +error[E0121]: the placeholder `_` is not allowed within types on item signatures for associated constants + --> $DIR/typeck_type_placeholder_item.rs:206:14 | -LL | fn fn_test10(&self, _x : T) { } - | +++ ~ +LL | const C: _; + | ^ not allowed in type signatures error[E0121]: the placeholder `_` is not allowed within types on item signatures for associated constants --> $DIR/typeck_type_placeholder_item.rs:194:14 @@ -555,6 +544,21 @@ LL | const D: _ = 42; | not allowed in type signatures | help: replace with the correct type: `i32` +error[E0121]: the placeholder `_` is not allowed within types on item signatures for associated constants + --> $DIR/typeck_type_placeholder_item.rs:209:14 + | +LL | const D: _ = 42; + | ^ not allowed in type signatures + +error[E0046]: not all trait items implemented, missing: `F` + --> $DIR/typeck_type_placeholder_item.rs:200:1 + | +LL | type F: std::ops::Fn(_); + | ----------------------- `F` from trait +... +LL | impl Qux for Struct { + | ^^^^^^^^^^^^^^^^^^^ missing `F` in implementation + error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types --> $DIR/typeck_type_placeholder_item.rs:217:31 | @@ -573,27 +577,6 @@ LL | const _: Option<_> = map(value); | not allowed in type signatures | help: replace with the correct type: `Option` -error[E0121]: the placeholder `_` is not allowed within types on item signatures for associated constants - --> $DIR/typeck_type_placeholder_item.rs:206:14 - | -LL | const C: _; - | ^ not allowed in type signatures - -error[E0121]: the placeholder `_` is not allowed within types on item signatures for associated constants - --> $DIR/typeck_type_placeholder_item.rs:209:14 - | -LL | const D: _ = 42; - | ^ not allowed in type signatures - -error[E0046]: not all trait items implemented, missing: `F` - --> $DIR/typeck_type_placeholder_item.rs:200:1 - | -LL | type F: std::ops::Fn(_); - | ----------------------- `F` from trait -... -LL | impl Qux for Struct { - | ^^^^^^^^^^^^^^^^^^^ missing `F` in implementation - error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types --> $DIR/typeck_type_placeholder_item.rs:225:31 | @@ -624,6 +607,17 @@ LL | fn test9(&self) -> _ { () } | not allowed in type signatures | help: replace with the correct return type: `()` +error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions + --> $DIR/typeck_type_placeholder_item.rs:44:27 + | +LL | fn test10(&self, _x : _) { } + | ^ not allowed in type signatures + | +help: use type parameters instead + | +LL | fn test10(&self, _x : T) { } + | +++ ~ + error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types --> $DIR/typeck_type_placeholder_item.rs:107:31 | @@ -633,6 +627,17 @@ LL | fn fn_test9(&self) -> _ { () } | not allowed in type signatures | help: replace with the correct return type: `()` +error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions + --> $DIR/typeck_type_placeholder_item.rs:110:34 + | +LL | fn fn_test10(&self, _x : _) { } + | ^ not allowed in type signatures + | +help: use type parameters instead + | +LL | fn fn_test10(&self, _x : T) { } + | +++ ~ + error[E0121]: the placeholder `_` is not allowed within types on item signatures for associated types --> $DIR/typeck_type_placeholder_item.rs:202:14 | From c7cb45a791b0a3191b68a3cfaf5883e1958466ec Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Thu, 22 Aug 2024 00:55:23 +0000 Subject: [PATCH 1886/2194] Remove stray fixmes. --- compiler/rustc_hir_analysis/src/collect.rs | 3 --- 1 file changed, 3 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index 02ad5355d252b..640907c3e4a50 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -260,7 +260,6 @@ fn reject_placeholder_type_signatures_in_item<'tcx>( | hir::ItemKind::Trait(_, _, generics, ..) | hir::ItemKind::Impl(hir::Impl { generics, .. }) | hir::ItemKind::Struct(_, generics) => (generics, true), - // FIXME: how to handle opaque types since no longer items hir::ItemKind::TyAlias(_, generics) => (generics, false), // `static`, `fn` and `const` are handled elsewhere to suggest appropriate type. _ => return, @@ -744,8 +743,6 @@ fn lower_item(tcx: TyCtxt<'_>, item_id: hir::ItemId) { } } - // FIXME: ok to ignore opaque tys in collection? - // hir::ItemKind::TyAlias(..) => { tcx.ensure().generics_of(def_id); tcx.ensure().type_of(def_id); From 6ec58a44e20fa3c0a5c957ab3c31f2d039e9a24a Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Sun, 18 Aug 2024 16:10:54 +0000 Subject: [PATCH 1887/2194] Simplify bound var resolution. --- .../src/collect/resolve_bound_vars.rs | 56 +++++++++---------- .../src/middle/resolve_bound_vars.rs | 10 ++-- compiler/rustc_middle/src/query/mod.rs | 6 +- compiler/rustc_middle/src/ty/context.rs | 11 ++-- 4 files changed, 39 insertions(+), 44 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs index 513d4e9b4a555..c8852a3a3695a 100644 --- a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs +++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs @@ -11,10 +11,13 @@ use std::fmt; use rustc_ast::visit::walk_list; use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet}; +use rustc_data_structures::sorted_map::SortedMap; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; use rustc_hir::intravisit::{self, Visitor}; -use rustc_hir::{GenericArg, GenericParam, GenericParamKind, HirId, HirIdMap, LifetimeName, Node}; +use rustc_hir::{ + GenericArg, GenericParam, GenericParamKind, HirId, ItemLocalMap, LifetimeName, Node, +}; use rustc_macros::extension; use rustc_middle::hir::nested_filter; use rustc_middle::middle::resolve_bound_vars::*; @@ -74,7 +77,7 @@ impl ResolvedArg { struct NamedVarMap { // maps from every use of a named (not anonymous) bound var to a // `ResolvedArg` describing how that variable is bound - defs: HirIdMap, + defs: ItemLocalMap, // Maps relevant hir items to the bound vars on them. These include: // - function defs @@ -82,7 +85,7 @@ struct NamedVarMap { // - closures // - trait refs // - bound types (like `T` in `for<'a> T<'a>: Foo`) - late_bound_vars: HirIdMap>, + late_bound_vars: ItemLocalMap>, } struct BoundVarContext<'a, 'tcx> { @@ -225,10 +228,10 @@ pub(crate) fn provide(providers: &mut Providers) { *providers = Providers { resolve_bound_vars, - named_variable_map: |tcx, id| tcx.resolve_bound_vars(id).defs.get(&id), + named_variable_map: |tcx, id| &tcx.resolve_bound_vars(id).defs, is_late_bound_map, object_lifetime_default, - late_bound_vars_map: |tcx, id| tcx.resolve_bound_vars(id).late_bound_vars.get(&id), + late_bound_vars_map: |tcx, id| &tcx.resolve_bound_vars(id).late_bound_vars, ..*providers }; @@ -265,16 +268,12 @@ fn resolve_bound_vars(tcx: TyCtxt<'_>, local_def_id: hir::OwnerId) -> ResolveBou hir::OwnerNode::Synthetic => unreachable!(), } - let mut rl = ResolveBoundVars::default(); - - for (hir_id, v) in named_variable_map.defs { - let map = rl.defs.entry(hir_id.owner).or_default(); - map.insert(hir_id.local_id, v); - } - for (hir_id, v) in named_variable_map.late_bound_vars { - let map = rl.late_bound_vars.entry(hir_id.owner).or_default(); - map.insert(hir_id.local_id, v); - } + let defs = named_variable_map.defs.into_sorted_stable_ord(); + let late_bound_vars = named_variable_map.late_bound_vars.into_sorted_stable_ord(); + let rl = ResolveBoundVars { + defs: SortedMap::from_presorted_elements(defs), + late_bound_vars: SortedMap::from_presorted_elements(late_bound_vars), + }; debug!(?rl.defs); debug!(?rl.late_bound_vars); @@ -340,7 +339,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> { Scope::Binder { hir_id, .. } => { // Nested poly trait refs have the binders concatenated let mut full_binders = - self.map.late_bound_vars.entry(*hir_id).or_default().clone(); + self.map.late_bound_vars.entry(hir_id.local_id).or_default().clone(); full_binders.extend(supertrait_bound_vars); break (full_binders, BinderScopeType::Concatenating); } @@ -677,7 +676,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> { hir::TyKind::Ref(lifetime_ref, ref mt) => { self.visit_lifetime(lifetime_ref); let scope = Scope::ObjectLifetimeDefault { - lifetime: self.map.defs.get(&lifetime_ref.hir_id).cloned(), + lifetime: self.map.defs.get(&lifetime_ref.hir_id.local_id).cloned(), s: self.scope, }; self.with(scope, |this| this.visit_ty(mt.ty)); @@ -704,7 +703,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> { // and ban them. Type variables instantiated inside binders aren't // well-supported at the moment, so this doesn't work. // In the future, this should be fixed and this error should be removed. - let def = self.map.defs.get(&lifetime.hir_id).copied(); + let def = self.map.defs.get(&lifetime.hir_id.local_id).copied(); let Some(ResolvedArg::LateBound(_, _, lifetime_def_id)) = def else { continue }; let lifetime_hir_id = self.tcx.local_def_id_to_hir_id(lifetime_def_id); @@ -841,7 +840,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> { let bound_vars: Vec<_> = self.tcx.fn_sig(sig_id).skip_binder().bound_vars().iter().collect(); let hir_id = self.tcx.local_def_id_to_hir_id(def_id); - self.map.late_bound_vars.insert(hir_id, bound_vars); + self.map.late_bound_vars.insert(hir_id.local_id, bound_vars); } self.visit_fn_like_elision(fd.inputs, output, matches!(fk, intravisit::FnKind::Closure)); intravisit::walk_fn_kind(self, fk); @@ -1019,10 +1018,10 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> { } fn record_late_bound_vars(&mut self, hir_id: HirId, binder: Vec) { - if let Some(old) = self.map.late_bound_vars.insert(hir_id, binder) { + if let Some(old) = self.map.late_bound_vars.insert(hir_id.local_id, binder) { bug!( "overwrote bound vars for {hir_id:?}:\nold={old:?}\nnew={:?}", - self.map.late_bound_vars[&hir_id] + self.map.late_bound_vars[&hir_id.local_id] ) } } @@ -1381,9 +1380,9 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> { kind.descr(param_def_id.to_def_id()) ), }; - self.map.defs.insert(hir_id, ResolvedArg::Error(guar)); + self.map.defs.insert(hir_id.local_id, ResolvedArg::Error(guar)); } else { - self.map.defs.insert(hir_id, def); + self.map.defs.insert(hir_id.local_id, def); } return; } @@ -1416,7 +1415,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> { bug!("unexpected def-kind: {}", kind.descr(param_def_id.to_def_id())) } }); - self.map.defs.insert(hir_id, ResolvedArg::Error(guar)); + self.map.defs.insert(hir_id.local_id, ResolvedArg::Error(guar)); return; } Scope::Root { .. } => break, @@ -1526,7 +1525,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> { // This index can be used with `generic_args` since `parent_count == 0`. let index = generics.param_def_id_to_index[¶m_def_id] as usize; generic_args.args.get(index).and_then(|arg| match arg { - GenericArg::Lifetime(lt) => map.defs.get(<.hir_id).copied(), + GenericArg::Lifetime(lt) => map.defs.get(<.hir_id.local_id).copied(), _ => None, }) } @@ -1816,7 +1815,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> { #[instrument(level = "debug", skip(self))] fn insert_lifetime(&mut self, lifetime_ref: &'tcx hir::Lifetime, def: ResolvedArg) { debug!(span = ?lifetime_ref.ident.span); - self.map.defs.insert(lifetime_ref.hir_id, def); + self.map.defs.insert(lifetime_ref.hir_id.local_id, def); } /// Sometimes we resolve a lifetime, but later find that it is an @@ -1827,8 +1826,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> { lifetime_ref: &'tcx hir::Lifetime, bad_def: ResolvedArg, ) { - // FIXME(#120456) - is `swap_remove` correct? - let old_value = self.map.defs.swap_remove(&lifetime_ref.hir_id); + let old_value = self.map.defs.remove(&lifetime_ref.hir_id.local_id); assert_eq!(old_value, Some(bad_def)); } @@ -1998,7 +1996,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> { // See where these vars are used in `HirTyLowerer::lower_ty_maybe_return_type_notation`. // And this is exercised in: // `tests/ui/associated-type-bounds/return-type-notation/higher-ranked-bound-works.rs`. - let existing_bound_vars = self.map.late_bound_vars.get_mut(&hir_id).unwrap(); + let existing_bound_vars = self.map.late_bound_vars.get_mut(&hir_id.local_id).unwrap(); let existing_bound_vars_saved = existing_bound_vars.clone(); existing_bound_vars.extend(bound_vars); self.record_late_bound_vars(item_segment.hir_id, existing_bound_vars_saved); diff --git a/compiler/rustc_middle/src/middle/resolve_bound_vars.rs b/compiler/rustc_middle/src/middle/resolve_bound_vars.rs index 32e2f3b4b1685..13e35cd090983 100644 --- a/compiler/rustc_middle/src/middle/resolve_bound_vars.rs +++ b/compiler/rustc_middle/src/middle/resolve_bound_vars.rs @@ -1,9 +1,9 @@ //! Name resolution for lifetimes and late-bound type and const variables: type declarations. -use rustc_data_structures::fx::FxIndexMap; +use rustc_data_structures::sorted_map::SortedMap; use rustc_errors::ErrorGuaranteed; +use rustc_hir::ItemLocalId; use rustc_hir::def_id::{DefId, LocalDefId}; -use rustc_hir::{ItemLocalId, OwnerId}; use rustc_macros::{Decodable, Encodable, HashStable, TyDecodable, TyEncodable}; use crate::ty; @@ -47,11 +47,11 @@ pub enum ObjectLifetimeDefault { /// Maps the id of each lifetime reference to the lifetime decl /// that it corresponds to. -#[derive(Default, HashStable, Debug)] +#[derive(HashStable, Debug)] pub struct ResolveBoundVars { /// Maps from every use of a named (not anonymous) lifetime to a /// `Region` describing how that region is bound - pub defs: FxIndexMap>, + pub defs: SortedMap, - pub late_bound_vars: FxIndexMap>>, + pub late_bound_vars: SortedMap>, } diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index bd6a7578a6864..f0be70e00dfca 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -16,6 +16,7 @@ use rustc_ast::expand::StrippedCfgItem; use rustc_ast::expand::allocator::AllocatorKind; use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::fx::{FxIndexMap, FxIndexSet}; +use rustc_data_structures::sorted_map::SortedMap; use rustc_data_structures::steal::Steal; use rustc_data_structures::svh::Svh; use rustc_data_structures::sync::Lrc; @@ -1742,8 +1743,7 @@ rustc_queries! { arena_cache desc { |tcx| "resolving lifetimes for `{}`", tcx.def_path_str(owner_id) } } - query named_variable_map(owner_id: hir::OwnerId) -> - Option<&'tcx FxIndexMap> { + query named_variable_map(owner_id: hir::OwnerId) -> &'tcx SortedMap { desc { |tcx| "looking up a named region inside `{}`", tcx.def_path_str(owner_id) } } query is_late_bound_map(owner_id: hir::OwnerId) -> Option<&'tcx FxIndexSet> { @@ -1759,7 +1759,7 @@ rustc_queries! { separate_provide_extern } query late_bound_vars_map(owner_id: hir::OwnerId) - -> Option<&'tcx FxIndexMap>> { + -> &'tcx SortedMap> { desc { |tcx| "looking up late bound vars inside `{}`", tcx.def_path_str(owner_id) } } diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index d6547b51186b6..27c1b88f93f74 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -2996,7 +2996,7 @@ impl<'tcx> TyCtxt<'tcx> { pub fn named_bound_var(self, id: HirId) -> Option { debug!(?id, "named_region"); - self.named_variable_map(id.owner).and_then(|map| map.get(&id.local_id).cloned()) + self.named_variable_map(id.owner).get(&id.local_id).cloned() } pub fn is_late_bound(self, id: HirId) -> bool { @@ -3005,12 +3005,9 @@ impl<'tcx> TyCtxt<'tcx> { pub fn late_bound_vars(self, id: HirId) -> &'tcx List { self.mk_bound_variable_kinds( - &self - .late_bound_vars_map(id.owner) - .and_then(|map| map.get(&id.local_id).cloned()) - .unwrap_or_else(|| { - bug!("No bound vars found for {}", self.hir().node_to_string(id)) - }), + &self.late_bound_vars_map(id.owner).get(&id.local_id).cloned().unwrap_or_else(|| { + bug!("No bound vars found for {}", self.hir().node_to_string(id)) + }), ) } From 6278e0f50745bafb8563c5765ef6a1622e3718c4 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Sun, 18 Aug 2024 16:35:03 +0000 Subject: [PATCH 1888/2194] Promote crash tests to ui. --- tests/crashes/119716-2.rs | 4 --- tests/crashes/119716.rs | 4 --- tests/crashes/121422.rs | 8 ----- tests/crashes/125843.rs | 4 --- tests/crashes/129099.rs | 15 ---------- .../bound-lifetime-through-dyn-trait.rs | 18 +++++++++++ .../bound-lifetime-through-dyn-trait.stderr | 28 +++++++++++++++++ .../non-lifetime-binder-in-constraint.rs | 13 ++++++++ .../non-lifetime-binder-in-constraint.stderr | 30 +++++++++++++++++++ .../non-lifetime-binder.rs | 10 +++++++ .../non-lifetime-binder.stderr | 25 ++++++++++++++++ 11 files changed, 124 insertions(+), 35 deletions(-) delete mode 100644 tests/crashes/119716-2.rs delete mode 100644 tests/crashes/119716.rs delete mode 100644 tests/crashes/121422.rs delete mode 100644 tests/crashes/125843.rs delete mode 100644 tests/crashes/129099.rs create mode 100644 tests/ui/type-alias-impl-trait/bound-lifetime-through-dyn-trait.rs create mode 100644 tests/ui/type-alias-impl-trait/bound-lifetime-through-dyn-trait.stderr create mode 100644 tests/ui/type-alias-impl-trait/non-lifetime-binder-in-constraint.rs create mode 100644 tests/ui/type-alias-impl-trait/non-lifetime-binder-in-constraint.stderr create mode 100644 tests/ui/type-alias-impl-trait/non-lifetime-binder.rs create mode 100644 tests/ui/type-alias-impl-trait/non-lifetime-binder.stderr diff --git a/tests/crashes/119716-2.rs b/tests/crashes/119716-2.rs deleted file mode 100644 index 47bffb5c1de0d..0000000000000 --- a/tests/crashes/119716-2.rs +++ /dev/null @@ -1,4 +0,0 @@ -//@ known-bug: #119716 -#![feature(non_lifetime_binders)] -trait Trait {} -fn f() -> impl for Trait> {} diff --git a/tests/crashes/119716.rs b/tests/crashes/119716.rs deleted file mode 100644 index d7cba0f51c4e0..0000000000000 --- a/tests/crashes/119716.rs +++ /dev/null @@ -1,4 +0,0 @@ -//@ known-bug: #119716 -#![feature(non_lifetime_binders)] -trait v0 {} -fn kind :(v3main impl for v0<'_, v2 = impl v0 + '_>) {} diff --git a/tests/crashes/121422.rs b/tests/crashes/121422.rs deleted file mode 100644 index 5d7ef6e8ce991..0000000000000 --- a/tests/crashes/121422.rs +++ /dev/null @@ -1,8 +0,0 @@ -//@ known-bug: #121422 -#![feature(non_lifetime_binders)] - -trait Trait {} - -fn produce() -> impl for Trait<(), Assoc = impl Trait> { - 16 -} diff --git a/tests/crashes/125843.rs b/tests/crashes/125843.rs deleted file mode 100644 index 8b9a3913c7e62..0000000000000 --- a/tests/crashes/125843.rs +++ /dev/null @@ -1,4 +0,0 @@ -//@ known-bug: rust-lang/rust#125843 -#![feature(non_lifetime_binders)] -trait v0<> {} -fn kind :(v3main impl for v0<'_, v2 = impl v0 + '_>) {} diff --git a/tests/crashes/129099.rs b/tests/crashes/129099.rs deleted file mode 100644 index 9aaab756b5b8d..0000000000000 --- a/tests/crashes/129099.rs +++ /dev/null @@ -1,15 +0,0 @@ -//@ known-bug: rust-lang/rust#129099 - -#![feature(type_alias_impl_trait)] - -fn dyn_hoops() -> dyn for<'a> Iterator> { - loop {} -} - -pub fn main() { - type Opaque = impl Sized; - fn define() -> Opaque { - let x: Opaque = dyn_hoops::<()>(0); - x - } -} diff --git a/tests/ui/type-alias-impl-trait/bound-lifetime-through-dyn-trait.rs b/tests/ui/type-alias-impl-trait/bound-lifetime-through-dyn-trait.rs new file mode 100644 index 0000000000000..df589473a8460 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/bound-lifetime-through-dyn-trait.rs @@ -0,0 +1,18 @@ +#![feature(type_alias_impl_trait)] + +trait Captures<'a> {} +impl Captures<'_> for T {} + +fn dyn_hoops() -> dyn for<'a> Iterator> { + //~^ ERROR `impl Trait` cannot capture higher-ranked lifetime from `dyn` type + loop {} +} + +pub fn main() { + //~^ ERROR item does not constrain `Opaque::{opaque#0}`, but has it in its signature + type Opaque = impl Sized; + fn define() -> Opaque { + let x: Opaque = dyn_hoops::<()>(); + x + } +} diff --git a/tests/ui/type-alias-impl-trait/bound-lifetime-through-dyn-trait.stderr b/tests/ui/type-alias-impl-trait/bound-lifetime-through-dyn-trait.stderr new file mode 100644 index 0000000000000..59d9ff86c6e09 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/bound-lifetime-through-dyn-trait.stderr @@ -0,0 +1,28 @@ +error[E0657]: `impl Trait` cannot capture higher-ranked lifetime from `dyn` type + --> $DIR/bound-lifetime-through-dyn-trait.rs:6:71 + | +LL | fn dyn_hoops() -> dyn for<'a> Iterator> { + | ^^ + | +note: lifetime declared here + --> $DIR/bound-lifetime-through-dyn-trait.rs:6:37 + | +LL | fn dyn_hoops() -> dyn for<'a> Iterator> { + | ^^ + +error: item does not constrain `Opaque::{opaque#0}`, but has it in its signature + --> $DIR/bound-lifetime-through-dyn-trait.rs:11:8 + | +LL | pub fn main() { + | ^^^^ + | + = note: consider moving the opaque type's declaration and defining uses into a separate module +note: this opaque type is in the signature + --> $DIR/bound-lifetime-through-dyn-trait.rs:13:19 + | +LL | type Opaque = impl Sized; + | ^^^^^^^^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0657`. diff --git a/tests/ui/type-alias-impl-trait/non-lifetime-binder-in-constraint.rs b/tests/ui/type-alias-impl-trait/non-lifetime-binder-in-constraint.rs new file mode 100644 index 0000000000000..dda42580e0f3a --- /dev/null +++ b/tests/ui/type-alias-impl-trait/non-lifetime-binder-in-constraint.rs @@ -0,0 +1,13 @@ +#![allow(incomplete_features)] +#![feature(non_lifetime_binders)] + +trait Trait {} + +fn produce() -> impl for Trait<(), Assoc = impl Trait> { + //~^ ERROR associated type `Assoc` not found for `Trait` + //~| ERROR associated type `Assoc` not found for `Trait` + //~| the trait bound `{integer}: Trait<()>` is not satisfied + 16 +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/non-lifetime-binder-in-constraint.stderr b/tests/ui/type-alias-impl-trait/non-lifetime-binder-in-constraint.stderr new file mode 100644 index 0000000000000..fa3306ff11fa0 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/non-lifetime-binder-in-constraint.stderr @@ -0,0 +1,30 @@ +error[E0220]: associated type `Assoc` not found for `Trait` + --> $DIR/non-lifetime-binder-in-constraint.rs:6:39 + | +LL | fn produce() -> impl for Trait<(), Assoc = impl Trait> { + | ^^^^^ associated type `Assoc` not found + +error[E0220]: associated type `Assoc` not found for `Trait` + --> $DIR/non-lifetime-binder-in-constraint.rs:6:39 + | +LL | fn produce() -> impl for Trait<(), Assoc = impl Trait> { + | ^^^^^ associated type `Assoc` not found + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error[E0277]: the trait bound `{integer}: Trait<()>` is not satisfied + --> $DIR/non-lifetime-binder-in-constraint.rs:6:17 + | +LL | fn produce() -> impl for Trait<(), Assoc = impl Trait> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Trait<()>` is not implemented for `{integer}` + | +help: this trait has no implementations, consider adding one + --> $DIR/non-lifetime-binder-in-constraint.rs:4:1 + | +LL | trait Trait {} + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0220, E0277. +For more information about an error, try `rustc --explain E0220`. diff --git a/tests/ui/type-alias-impl-trait/non-lifetime-binder.rs b/tests/ui/type-alias-impl-trait/non-lifetime-binder.rs new file mode 100644 index 0000000000000..23951c3427006 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/non-lifetime-binder.rs @@ -0,0 +1,10 @@ +#![allow(incomplete_features)] +#![feature(non_lifetime_binders)] + +trait Trait {} + +fn f() -> impl for Trait> {} +//~^ ERROR nested `impl Trait` is not allowed +//~| ERROR the trait bound `(): Trait>` is not satisfied + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/non-lifetime-binder.stderr b/tests/ui/type-alias-impl-trait/non-lifetime-binder.stderr new file mode 100644 index 0000000000000..5859d952b75c7 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/non-lifetime-binder.stderr @@ -0,0 +1,25 @@ +error[E0666]: nested `impl Trait` is not allowed + --> $DIR/non-lifetime-binder.rs:6:29 + | +LL | fn f() -> impl for Trait> {} + | ------------------^^^^^^^^^^^^^- + | | | + | | nested `impl Trait` here + | outer `impl Trait` + +error[E0277]: the trait bound `(): Trait>` is not satisfied + --> $DIR/non-lifetime-binder.rs:6:11 + | +LL | fn f() -> impl for Trait> {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Trait>` is not implemented for `()` + | +help: this trait has no implementations, consider adding one + --> $DIR/non-lifetime-binder.rs:4:1 + | +LL | trait Trait {} + | ^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0277, E0666. +For more information about an error, try `rustc --explain E0277`. From 98941f76ff5cd166d9c88177cae1e06db08bbe5f Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Sun, 18 Aug 2024 16:54:02 +0000 Subject: [PATCH 1889/2194] Bless incremental tests. --- tests/incremental/hashes/function_interfaces.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/incremental/hashes/function_interfaces.rs b/tests/incremental/hashes/function_interfaces.rs index ab4d578458d40..016a1813babd7 100644 --- a/tests/incremental/hashes/function_interfaces.rs +++ b/tests/incremental/hashes/function_interfaces.rs @@ -318,9 +318,9 @@ pub fn change_return_impl_trait() -> impl Clone { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg = "cfail2")] +#[rustc_clean(cfg = "cfail2", except = "opt_hir_owner_nodes")] #[rustc_clean(cfg = "cfail3")] -#[rustc_clean(cfg = "cfail5", except = "typeck")] +#[rustc_clean(cfg = "cfail5", except = "opt_hir_owner_nodes, typeck")] #[rustc_clean(cfg = "cfail6")] pub fn change_return_impl_trait() -> impl Copy { 0u32 From ef17eb79bbc5c7f5b303e203c1095e2eb216f84b Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Sun, 18 Aug 2024 16:43:39 +0000 Subject: [PATCH 1890/2194] Adapt clippy. --- .../clippy_lints/src/extra_unused_type_parameters.rs | 8 +------- .../clippy/clippy_lints/src/implied_bounds_in_impls.rs | 9 +++------ src/tools/clippy/clippy_lints/src/len_zero.rs | 6 +----- src/tools/clippy/clippy_lints/src/lifetimes.rs | 8 +++----- src/tools/clippy/clippy_lints/src/manual_async_fn.rs | 6 ++---- src/tools/clippy/clippy_lints/src/missing_doc.rs | 3 +-- src/tools/clippy/clippy_lints/src/missing_inline.rs | 1 - src/tools/clippy/clippy_lints/src/use_self.rs | 10 ++-------- 8 files changed, 13 insertions(+), 38 deletions(-) diff --git a/src/tools/clippy/clippy_lints/src/extra_unused_type_parameters.rs b/src/tools/clippy/clippy_lints/src/extra_unused_type_parameters.rs index 796af851bac0a..6ad879b9fe7ae 100644 --- a/src/tools/clippy/clippy_lints/src/extra_unused_type_parameters.rs +++ b/src/tools/clippy/clippy_lints/src/extra_unused_type_parameters.rs @@ -6,7 +6,7 @@ use rustc_errors::Applicability; use rustc_hir::intravisit::{Visitor, walk_impl_item, walk_item, walk_param_bound, walk_ty}; use rustc_hir::{ BodyId, ExprKind, GenericBound, GenericParam, GenericParamKind, Generics, ImplItem, ImplItemKind, Item, ItemKind, - PredicateOrigin, Ty, TyKind, WherePredicate, + PredicateOrigin, Ty, WherePredicate, }; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_middle::hir::nested_filter; @@ -199,12 +199,6 @@ impl<'tcx> Visitor<'tcx> for TypeWalker<'_, 'tcx> { fn visit_ty(&mut self, t: &'tcx Ty<'tcx>) { if let Some((def_id, _)) = t.peel_refs().as_generic_param() { self.ty_params.remove(&def_id); - } else if let TyKind::OpaqueDef(id, _) = t.kind { - // Explicitly walk OpaqueDef. Normally `walk_ty` would do the job, but it calls - // `visit_nested_item`, which checks that `Self::NestedFilter::INTER` is set. We're - // using `OnlyBodies`, so the check ends up failing and the type isn't fully walked. - let item = self.nested_visit_map().item(id); - walk_item(self, item); } else { walk_ty(self, t); } diff --git a/src/tools/clippy/clippy_lints/src/implied_bounds_in_impls.rs b/src/tools/clippy/clippy_lints/src/implied_bounds_in_impls.rs index 6794c6cabfeef..5f349d780537b 100644 --- a/src/tools/clippy/clippy_lints/src/implied_bounds_in_impls.rs +++ b/src/tools/clippy/clippy_lints/src/implied_bounds_in_impls.rs @@ -3,7 +3,7 @@ use clippy_utils::source::snippet; use rustc_errors::{Applicability, SuggestionStyle}; use rustc_hir::def_id::DefId; use rustc_hir::{ - AssocItemConstraint, GenericArg, GenericBound, GenericBounds, ItemKind, PredicateOrigin, TraitBoundModifier, + AssocItemConstraint, GenericArg, GenericBound, GenericBounds, PredicateOrigin, TraitBoundModifier, TyKind, WherePredicate, }; use rustc_hir_analysis::lower_ty; @@ -342,11 +342,8 @@ impl<'tcx> LateLintPass<'tcx> for ImpliedBoundsInImpls { } } - fn check_ty(&mut self, cx: &LateContext<'_>, ty: &rustc_hir::Ty<'_>) { - if let TyKind::OpaqueDef(item_id, ..) = ty.kind - && let item = cx.tcx.hir().item(item_id) - && let ItemKind::OpaqueTy(opaque_ty) = item.kind - { + fn check_ty(&mut self, cx: &LateContext<'tcx>, ty: &rustc_hir::Ty<'tcx>) { + if let TyKind::OpaqueDef(opaque_ty, ..) = ty.kind { check(cx, opaque_ty.bounds); } } diff --git a/src/tools/clippy/clippy_lints/src/len_zero.rs b/src/tools/clippy/clippy_lints/src/len_zero.rs index 45346cd18a61b..311bbce14bd7e 100644 --- a/src/tools/clippy/clippy_lints/src/len_zero.rs +++ b/src/tools/clippy/clippy_lints/src/len_zero.rs @@ -308,11 +308,7 @@ enum LenOutput { fn extract_future_output<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> Option<&'tcx PathSegment<'tcx>> { if let ty::Alias(_, alias_ty) = ty.kind() - && let Some(Node::Item(item)) = cx.tcx.hir().get_if_local(alias_ty.def_id) - && let Item { - kind: ItemKind::OpaqueTy(opaque), - .. - } = item + && let Some(Node::OpaqueTy(opaque)) = cx.tcx.hir().get_if_local(alias_ty.def_id) && let OpaqueTyOrigin::AsyncFn { .. } = opaque.origin && let [GenericBound::Trait(trait_ref, _)] = &opaque.bounds && let Some(segment) = trait_ref.trait_ref.path.segments.last() diff --git a/src/tools/clippy/clippy_lints/src/lifetimes.rs b/src/tools/clippy/clippy_lints/src/lifetimes.rs index 5c37e73544577..7c3ef98fd74f5 100644 --- a/src/tools/clippy/clippy_lints/src/lifetimes.rs +++ b/src/tools/clippy/clippy_lints/src/lifetimes.rs @@ -6,7 +6,7 @@ use rustc_errors::Applicability; use rustc_hir::FnRetTy::Return; use rustc_hir::intravisit::nested_filter::{self as hir_nested_filter, NestedFilter}; use rustc_hir::intravisit::{ - Visitor, walk_fn_decl, walk_generic_args, walk_generics, walk_impl_item_ref, walk_item, walk_param_bound, + Visitor, walk_fn_decl, walk_generic_args, walk_generics, walk_impl_item_ref, walk_param_bound, walk_poly_trait_ref, walk_trait_ref, walk_ty, walk_where_predicate, }; use rustc_hir::{ @@ -420,11 +420,9 @@ impl<'tcx> Visitor<'tcx> for RefVisitor<'_, 'tcx> { fn visit_ty(&mut self, ty: &'tcx Ty<'_>) { match ty.kind { - TyKind::OpaqueDef(item, bounds) => { - let map = self.cx.tcx.hir(); - let item = map.item(item); + TyKind::OpaqueDef(opaque, bounds) => { let len = self.lts.len(); - walk_item(self, item); + self.visit_opaque_ty(opaque); self.lts.truncate(len); self.lts.extend(bounds.iter().filter_map(|bound| match bound { GenericArg::Lifetime(&l) => Some(l), diff --git a/src/tools/clippy/clippy_lints/src/manual_async_fn.rs b/src/tools/clippy/clippy_lints/src/manual_async_fn.rs index 7097c85156c34..81115cffdca88 100644 --- a/src/tools/clippy/clippy_lints/src/manual_async_fn.rs +++ b/src/tools/clippy/clippy_lints/src/manual_async_fn.rs @@ -4,7 +4,7 @@ use rustc_errors::Applicability; use rustc_hir::intravisit::FnKind; use rustc_hir::{ Block, Body, Closure, ClosureKind, CoroutineDesugaring, CoroutineKind, CoroutineSource, Expr, ExprKind, FnDecl, - FnRetTy, GenericArg, GenericBound, ImplItem, Item, ItemKind, LifetimeName, Node, TraitRef, Ty, TyKind, + FnRetTy, GenericArg, GenericBound, ImplItem, Item, LifetimeName, Node, TraitRef, Ty, TyKind, }; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::declare_lint_pass; @@ -105,9 +105,7 @@ fn future_trait_ref<'tcx>( cx: &LateContext<'tcx>, ty: &'tcx Ty<'tcx>, ) -> Option<(&'tcx TraitRef<'tcx>, Vec)> { - if let TyKind::OpaqueDef(item_id, bounds) = ty.kind - && let item = cx.tcx.hir().item(item_id) - && let ItemKind::OpaqueTy(opaque) = &item.kind + if let TyKind::OpaqueDef(opaque, bounds) = ty.kind && let Some(trait_ref) = opaque.bounds.iter().find_map(|bound| { if let GenericBound::Trait(poly, _) = bound { Some(&poly.trait_ref) diff --git a/src/tools/clippy/clippy_lints/src/missing_doc.rs b/src/tools/clippy/clippy_lints/src/missing_doc.rs index 64fc1a8a1a580..007bcebdff650 100644 --- a/src/tools/clippy/clippy_lints/src/missing_doc.rs +++ b/src/tools/clippy/clippy_lints/src/missing_doc.rs @@ -193,8 +193,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingDoc { | hir::ItemKind::Trait(..) | hir::ItemKind::TraitAlias(..) | hir::ItemKind::TyAlias(..) - | hir::ItemKind::Union(..) - | hir::ItemKind::OpaqueTy(..) => {}, + | hir::ItemKind::Union(..) => {} hir::ItemKind::ExternCrate(..) | hir::ItemKind::ForeignMod { .. } | hir::ItemKind::GlobalAsm(..) diff --git a/src/tools/clippy/clippy_lints/src/missing_inline.rs b/src/tools/clippy/clippy_lints/src/missing_inline.rs index d342be4545cea..f95a0f63fab7a 100644 --- a/src/tools/clippy/clippy_lints/src/missing_inline.rs +++ b/src/tools/clippy/clippy_lints/src/missing_inline.rs @@ -130,7 +130,6 @@ impl<'tcx> LateLintPass<'tcx> for MissingInline { | hir::ItemKind::GlobalAsm(..) | hir::ItemKind::TyAlias(..) | hir::ItemKind::Union(..) - | hir::ItemKind::OpaqueTy(..) | hir::ItemKind::ExternCrate(..) | hir::ItemKind::ForeignMod { .. } | hir::ItemKind::Impl { .. } diff --git a/src/tools/clippy/clippy_lints/src/use_self.rs b/src/tools/clippy/clippy_lints/src/use_self.rs index 08449de79b364..f5cf4a586fd29 100644 --- a/src/tools/clippy/clippy_lints/src/use_self.rs +++ b/src/tools/clippy/clippy_lints/src/use_self.rs @@ -85,10 +85,6 @@ const SEGMENTS_MSG: &str = "segments should be composed of at least 1 element"; impl<'tcx> LateLintPass<'tcx> for UseSelf { fn check_item(&mut self, cx: &LateContext<'tcx>, item: &Item<'tcx>) { - if matches!(item.kind, ItemKind::OpaqueTy(_)) { - // skip over `ItemKind::OpaqueTy` in order to lint `foo() -> impl <..>` - return; - } // We push the self types of `impl`s on a stack here. Only the top type on the stack is // relevant for linting, since this is the self type of the `impl` we're currently in. To // avoid linting on nested items, we push `StackItem::NoCheck` on the stack to signal, that @@ -130,10 +126,8 @@ impl<'tcx> LateLintPass<'tcx> for UseSelf { self.stack.push(stack_item); } - fn check_item_post(&mut self, _: &LateContext<'_>, item: &Item<'_>) { - if !matches!(item.kind, ItemKind::OpaqueTy(_)) { - self.stack.pop(); - } + fn check_item_post(&mut self, _: &LateContext<'_>, _: &Item<'_>) { + self.stack.pop(); } fn check_impl_item(&mut self, cx: &LateContext<'_>, impl_item: &hir::ImplItem<'_>) { From 6b67c46a253d453674401fad70c515d8fd439e35 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Sat, 24 Aug 2024 18:19:38 +0000 Subject: [PATCH 1891/2194] Compute array length from type for unconditional panic. --- .../rustc_mir_transform/src/known_panics_lint.rs | 16 +++++++++------- tests/ui/lint/unconditional_panic_promoted.rs | 8 ++++++++ .../ui/lint/unconditional_panic_promoted.stderr | 10 ++++++++++ 3 files changed, 27 insertions(+), 7 deletions(-) create mode 100644 tests/ui/lint/unconditional_panic_promoted.rs create mode 100644 tests/ui/lint/unconditional_panic_promoted.stderr diff --git a/compiler/rustc_mir_transform/src/known_panics_lint.rs b/compiler/rustc_mir_transform/src/known_panics_lint.rs index ccc029b1e281e..8f490094d6030 100644 --- a/compiler/rustc_mir_transform/src/known_panics_lint.rs +++ b/compiler/rustc_mir_transform/src/known_panics_lint.rs @@ -600,13 +600,15 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { } Len(place) => { - let len = match self.get_const(place)? { - Value::Immediate(src) => src.len(&self.ecx).discard_err()?, - Value::Aggregate { fields, .. } => fields.len() as u64, - Value::Uninit => match place.ty(self.local_decls(), self.tcx).ty.kind() { - ty::Array(_, n) => n.try_eval_target_usize(self.tcx, self.param_env)?, - _ => return None, - }, + let len = if let ty::Array(_, n) = place.ty(self.local_decls(), self.tcx).ty.kind() + { + n.try_eval_target_usize(self.tcx, self.param_env)? + } else { + match self.get_const(place)? { + Value::Immediate(src) => src.len(&self.ecx).discard_err()?, + Value::Aggregate { fields, .. } => fields.len() as u64, + Value::Uninit => return None, + } }; ImmTy::from_scalar(Scalar::from_target_usize(len, self), layout).into() } diff --git a/tests/ui/lint/unconditional_panic_promoted.rs b/tests/ui/lint/unconditional_panic_promoted.rs new file mode 100644 index 0000000000000..37bcf04651352 --- /dev/null +++ b/tests/ui/lint/unconditional_panic_promoted.rs @@ -0,0 +1,8 @@ +//@ build-fail + +fn main() { + // MIR encodes this as a reborrow from a promoted constant. + // But the array lenth can still be gotten from the type. + let slice = &[0, 1]; + let _ = slice[2]; //~ ERROR: this operation will panic at runtime [unconditional_panic] +} diff --git a/tests/ui/lint/unconditional_panic_promoted.stderr b/tests/ui/lint/unconditional_panic_promoted.stderr new file mode 100644 index 0000000000000..647a84a55fda5 --- /dev/null +++ b/tests/ui/lint/unconditional_panic_promoted.stderr @@ -0,0 +1,10 @@ +error: this operation will panic at runtime + --> $DIR/unconditional_panic_promoted.rs:7:13 + | +LL | let _ = slice[2]; + | ^^^^^^^^ index out of bounds: the length is 2 but the index is 2 + | + = note: `#[deny(unconditional_panic)]` on by default + +error: aborting due to 1 previous error + From 479779d6a90cc228fc45b5126c558ca52539b2c2 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Sun, 25 Aug 2024 12:13:15 +0000 Subject: [PATCH 1892/2194] Bless clippy. --- .../clippy/tests/ui-toml/unwrap_used/unwrap_used.fixed | 1 + src/tools/clippy/tests/ui-toml/unwrap_used/unwrap_used.rs | 1 + .../clippy/tests/ui-toml/unwrap_used/unwrap_used.stderr | 2 +- src/tools/clippy/tests/ui/get_unwrap.fixed | 1 + src/tools/clippy/tests/ui/get_unwrap.rs | 1 + src/tools/clippy/tests/ui/get_unwrap.stderr | 8 ++++---- 6 files changed, 9 insertions(+), 5 deletions(-) diff --git a/src/tools/clippy/tests/ui-toml/unwrap_used/unwrap_used.fixed b/src/tools/clippy/tests/ui-toml/unwrap_used/unwrap_used.fixed index baf939af24efb..cdb8fa0454cd4 100644 --- a/src/tools/clippy/tests/ui-toml/unwrap_used/unwrap_used.fixed +++ b/src/tools/clippy/tests/ui-toml/unwrap_used/unwrap_used.fixed @@ -86,6 +86,7 @@ mod issue9612 { util(); } + #[allow(unconditional_panic)] fn util() { let _a: u8 = 4.try_into().unwrap(); let _a: u8 = 5.try_into().expect(""); diff --git a/src/tools/clippy/tests/ui-toml/unwrap_used/unwrap_used.rs b/src/tools/clippy/tests/ui-toml/unwrap_used/unwrap_used.rs index e300ba18c3309..e53d53db5f7a4 100644 --- a/src/tools/clippy/tests/ui-toml/unwrap_used/unwrap_used.rs +++ b/src/tools/clippy/tests/ui-toml/unwrap_used/unwrap_used.rs @@ -86,6 +86,7 @@ mod issue9612 { util(); } + #[allow(unconditional_panic)] fn util() { let _a: u8 = 4.try_into().unwrap(); let _a: u8 = 5.try_into().expect(""); diff --git a/src/tools/clippy/tests/ui-toml/unwrap_used/unwrap_used.stderr b/src/tools/clippy/tests/ui-toml/unwrap_used/unwrap_used.stderr index 320578bfabce0..b58ce9b8af3e4 100644 --- a/src/tools/clippy/tests/ui-toml/unwrap_used/unwrap_used.stderr +++ b/src/tools/clippy/tests/ui-toml/unwrap_used/unwrap_used.stderr @@ -274,7 +274,7 @@ LL | let _ = &boxed_slice[1]; | ~~~~~~~~~~~~~~~ error: called `.get().unwrap()` on a slice - --> tests/ui-toml/unwrap_used/unwrap_used.rs:93:17 + --> tests/ui-toml/unwrap_used/unwrap_used.rs:94:17 | LL | let _ = Box::new([0]).get(1).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/tools/clippy/tests/ui/get_unwrap.fixed b/src/tools/clippy/tests/ui/get_unwrap.fixed index 62beb195939c6..2dd3c30a4e29b 100644 --- a/src/tools/clippy/tests/ui/get_unwrap.fixed +++ b/src/tools/clippy/tests/ui/get_unwrap.fixed @@ -70,6 +70,7 @@ fn main() { mod issue9909 { #![allow(clippy::identity_op, clippy::unwrap_used, dead_code)] + #[allow(unconditional_panic)] fn reduced() { let f = &[1, 2, 3]; diff --git a/src/tools/clippy/tests/ui/get_unwrap.rs b/src/tools/clippy/tests/ui/get_unwrap.rs index 1e09ff5c67e51..94226564cacb5 100644 --- a/src/tools/clippy/tests/ui/get_unwrap.rs +++ b/src/tools/clippy/tests/ui/get_unwrap.rs @@ -70,6 +70,7 @@ fn main() { mod issue9909 { #![allow(clippy::identity_op, clippy::unwrap_used, dead_code)] + #[allow(unconditional_panic)] fn reduced() { let f = &[1, 2, 3]; diff --git a/src/tools/clippy/tests/ui/get_unwrap.stderr b/src/tools/clippy/tests/ui/get_unwrap.stderr index 0f8b279da1e7a..8eacb249c60c6 100644 --- a/src/tools/clippy/tests/ui/get_unwrap.stderr +++ b/src/tools/clippy/tests/ui/get_unwrap.stderr @@ -266,7 +266,7 @@ LL | let _ = some_vec.get_mut(0..1).unwrap().to_vec(); = help: consider using `expect()` to provide a better panic message error: called `.get().unwrap()` on a slice - --> tests/ui/get_unwrap.rs:77:24 + --> tests/ui/get_unwrap.rs:78:24 | LL | let _x: &i32 = f.get(1 + 2).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^ @@ -277,7 +277,7 @@ LL | let _x: &i32 = &f[1 + 2]; | ~~~~~~~~~ error: called `.get().unwrap()` on a slice - --> tests/ui/get_unwrap.rs:80:18 + --> tests/ui/get_unwrap.rs:81:18 | LL | let _x = f.get(1 + 2).unwrap().to_string(); | ^^^^^^^^^^^^^^^^^^^^^ @@ -288,7 +288,7 @@ LL | let _x = f[1 + 2].to_string(); | ~~~~~~~~ error: called `.get().unwrap()` on a slice - --> tests/ui/get_unwrap.rs:83:18 + --> tests/ui/get_unwrap.rs:84:18 | LL | let _x = f.get(1 + 2).unwrap().abs(); | ^^^^^^^^^^^^^^^^^^^^^ @@ -299,7 +299,7 @@ LL | let _x = f[1 + 2].abs(); | ~~~~~~~~ error: called `.get_mut().unwrap()` on a slice - --> tests/ui/get_unwrap.rs:100:33 + --> tests/ui/get_unwrap.rs:101:33 | LL | let b = rest.get_mut(linidx(j, k) - linidx(i, k) - 1).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ From 00ed47b8496bacb9da0196127508e07ba5d14bb4 Mon Sep 17 00:00:00 2001 From: est31 Date: Wed, 28 Aug 2024 00:00:08 +0200 Subject: [PATCH 1893/2194] Make deprecated_cfg_attr_crate_type_name a hard error --- compiler/rustc_expand/messages.ftl | 6 +++ compiler/rustc_expand/src/config.rs | 19 +++------ compiler/rustc_expand/src/errors.rs | 14 +++++++ compiler/rustc_lint/messages.ftl | 6 --- .../rustc_lint/src/context/diagnostics.rs | 6 --- compiler/rustc_lint/src/lib.rs | 5 +++ compiler/rustc_lint/src/lints.rs | 8 ---- compiler/rustc_lint_defs/src/builtin.rs | 37 ----------------- compiler/rustc_lint_defs/src/lib.rs | 2 - ....rs => crate-attributes-using-cfg_attr.rs} | 4 -- .../crate-attributes-using-cfg_attr.stderr | 30 ++++++++++++++ ...pat-crate-attributes-using-cfg_attr.stderr | 41 ------------------- 12 files changed, 60 insertions(+), 118 deletions(-) rename tests/ui/cfg/{future-compat-crate-attributes-using-cfg_attr.rs => crate-attributes-using-cfg_attr.rs} (63%) create mode 100644 tests/ui/cfg/crate-attributes-using-cfg_attr.stderr delete mode 100644 tests/ui/cfg/future-compat-crate-attributes-using-cfg_attr.stderr diff --git a/compiler/rustc_expand/messages.ftl b/compiler/rustc_expand/messages.ftl index 766d96e268f04..57bac9d09d5ec 100644 --- a/compiler/rustc_expand/messages.ftl +++ b/compiler/rustc_expand/messages.ftl @@ -27,6 +27,12 @@ expand_collapse_debuginfo_illegal = expand_count_repetition_misplaced = `count` can not be placed inside the inner-most repetition +expand_crate_name_in_cfg_attr = + `crate_name` within an `#![cfg_attr]` attribute is forbidden + +expand_crate_type_in_cfg_attr = + `crate_type` within an `#![cfg_attr]` attribute is forbidden + expand_custom_attribute_panicked = custom attribute panicked .help = message: {$message} diff --git a/compiler/rustc_expand/src/config.rs b/compiler/rustc_expand/src/config.rs index 3208837427736..7bd4372d18645 100644 --- a/compiler/rustc_expand/src/config.rs +++ b/compiler/rustc_expand/src/config.rs @@ -21,8 +21,9 @@ use thin_vec::ThinVec; use tracing::instrument; use crate::errors::{ - FeatureNotAllowed, FeatureRemoved, FeatureRemovedReason, InvalidCfg, MalformedFeatureAttribute, - MalformedFeatureAttributeHelp, RemoveExprNotSupported, + CrateNameInCfgAttr, CrateTypeInCfgAttr, FeatureNotAllowed, FeatureRemoved, + FeatureRemovedReason, InvalidCfg, MalformedFeatureAttribute, MalformedFeatureAttributeHelp, + RemoveExprNotSupported, }; /// A folder that strips out items that do not belong in the current configuration. @@ -358,20 +359,10 @@ impl<'a> StripUnconfigured<'a> { item_span, ); if attr.has_name(sym::crate_type) { - self.sess.psess.buffer_lint( - rustc_lint_defs::builtin::DEPRECATED_CFG_ATTR_CRATE_TYPE_NAME, - attr.span, - ast::CRATE_NODE_ID, - BuiltinLintDiag::CrateTypeInCfgAttr, - ); + self.sess.dcx().emit_err(CrateTypeInCfgAttr { span: attr.span }); } if attr.has_name(sym::crate_name) { - self.sess.psess.buffer_lint( - rustc_lint_defs::builtin::DEPRECATED_CFG_ATTR_CRATE_TYPE_NAME, - attr.span, - ast::CRATE_NODE_ID, - BuiltinLintDiag::CrateNameInCfgAttr, - ); + self.sess.dcx().emit_err(CrateNameInCfgAttr { span: attr.span }); } attr } diff --git a/compiler/rustc_expand/src/errors.rs b/compiler/rustc_expand/src/errors.rs index 0fdccb0891899..5682c574552b4 100644 --- a/compiler/rustc_expand/src/errors.rs +++ b/compiler/rustc_expand/src/errors.rs @@ -467,6 +467,20 @@ pub(crate) struct GlobDelegationOutsideImpls { pub span: Span, } +#[derive(Diagnostic)] +#[diag(expand_crate_name_in_cfg_attr)] +pub(crate) struct CrateNameInCfgAttr { + #[primary_span] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag(expand_crate_type_in_cfg_attr)] +pub(crate) struct CrateTypeInCfgAttr { + #[primary_span] + pub span: Span, +} + #[derive(Diagnostic)] #[diag(expand_glob_delegation_traitless_qpath)] pub(crate) struct GlobDelegationTraitlessQpath { diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl index 375cfccbe9f71..3b360bdef2fa9 100644 --- a/compiler/rustc_lint/messages.ftl +++ b/compiler/rustc_lint/messages.ftl @@ -203,12 +203,6 @@ lint_confusable_identifier_pair = found both `{$existing_sym}` and `{$sym}` as i .current_use = this identifier can be confused with `{$existing_sym}` .other_use = other identifier used here -lint_crate_name_in_cfg_attr_deprecated = - `crate_name` within an `#![cfg_attr]` attribute is deprecated - -lint_crate_type_in_cfg_attr_deprecated = - `crate_type` within an `#![cfg_attr]` attribute is deprecated - lint_cstring_ptr = getting the inner pointer of a temporary `CString` .as_ptr_label = this pointer will be invalid .unwrap_label = this `CString` is deallocated at the end of the statement, bind it to a variable to extend its lifetime diff --git a/compiler/rustc_lint/src/context/diagnostics.rs b/compiler/rustc_lint/src/context/diagnostics.rs index 168e3a8e92c5f..b5ab56912cb2d 100644 --- a/compiler/rustc_lint/src/context/diagnostics.rs +++ b/compiler/rustc_lint/src/context/diagnostics.rs @@ -400,12 +400,6 @@ pub(super) fn decorate_lint(sess: &Session, diagnostic: BuiltinLintDiag, diag: & BuiltinLintDiag::CfgAttrNoAttributes => { lints::CfgAttrNoAttributes.decorate_lint(diag); } - BuiltinLintDiag::CrateTypeInCfgAttr => { - lints::CrateTypeInCfgAttr.decorate_lint(diag); - } - BuiltinLintDiag::CrateNameInCfgAttr => { - lints::CrateNameInCfgAttr.decorate_lint(diag); - } BuiltinLintDiag::MissingFragmentSpecifier => { lints::MissingFragmentSpecifier.decorate_lint(diag); } diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs index c74cb866f21fa..38a9fb8abfc4c 100644 --- a/compiler/rustc_lint/src/lib.rs +++ b/compiler/rustc_lint/src/lib.rs @@ -570,6 +570,11 @@ fn register_builtins(store: &mut LintStore) { "converted into hard error, see RFC #3535 \ for more information", ); + store.register_removed( + "deprecated_cfg_attr_crate_type_name", + "converted into hard error, see issue #91632 \ + for more information", + ); store.register_removed( "pointer_structural_match", "converted into hard error, see RFC #3535 \ diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index 0045cfcaa56ad..5187a13bd41cf 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -2441,14 +2441,6 @@ pub(crate) struct DuplicateMacroAttribute; #[diag(lint_cfg_attr_no_attributes)] pub(crate) struct CfgAttrNoAttributes; -#[derive(LintDiagnostic)] -#[diag(lint_crate_type_in_cfg_attr_deprecated)] -pub(crate) struct CrateTypeInCfgAttr; - -#[derive(LintDiagnostic)] -#[diag(lint_crate_name_in_cfg_attr_deprecated)] -pub(crate) struct CrateNameInCfgAttr; - #[derive(LintDiagnostic)] #[diag(lint_missing_fragment_specifier)] pub(crate) struct MissingFragmentSpecifier; diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index 549dc64a562b2..3cc9cb901a6af 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs @@ -34,7 +34,6 @@ declare_lint_pass! { DEAD_CODE, DEPENDENCY_ON_UNIT_NEVER_TYPE_FALLBACK, DEPRECATED, - DEPRECATED_CFG_ATTR_CRATE_TYPE_NAME, DEPRECATED_IN_FUTURE, DEPRECATED_SAFE_2024, DEPRECATED_WHERE_CLAUSE_LOCATION, @@ -3143,42 +3142,6 @@ declare_lint! { "detects large moves or copies", } -declare_lint! { - /// The `deprecated_cfg_attr_crate_type_name` lint detects uses of the - /// `#![cfg_attr(..., crate_type = "...")]` and - /// `#![cfg_attr(..., crate_name = "...")]` attributes to conditionally - /// specify the crate type and name in the source code. - /// - /// ### Example - /// - /// ```rust,compile_fail - /// #![cfg_attr(debug_assertions, crate_type = "lib")] - /// ``` - /// - /// {{produces}} - /// - /// - /// ### Explanation - /// - /// The `#![crate_type]` and `#![crate_name]` attributes require a hack in - /// the compiler to be able to change the used crate type and crate name - /// after macros have been expanded. Neither attribute works in combination - /// with Cargo as it explicitly passes `--crate-type` and `--crate-name` on - /// the commandline. These values must match the value used in the source - /// code to prevent an error. - /// - /// To fix the warning use `--crate-type` on the commandline when running - /// rustc instead of `#![cfg_attr(..., crate_type = "...")]` and - /// `--crate-name` instead of `#![cfg_attr(..., crate_name = "...")]`. - pub DEPRECATED_CFG_ATTR_CRATE_TYPE_NAME, - Deny, - "detects usage of `#![cfg_attr(..., crate_type/crate_name = \"...\")]`", - @future_incompatible = FutureIncompatibleInfo { - reason: FutureIncompatibilityReason::FutureReleaseErrorDontReportInDeps, - reference: "issue #91632 ", - }; -} - declare_lint! { /// The `unexpected_cfgs` lint detects unexpected conditional compilation conditions. /// diff --git a/compiler/rustc_lint_defs/src/lib.rs b/compiler/rustc_lint_defs/src/lib.rs index 734e7069c9026..386918a5c4157 100644 --- a/compiler/rustc_lint_defs/src/lib.rs +++ b/compiler/rustc_lint_defs/src/lib.rs @@ -720,8 +720,6 @@ pub enum BuiltinLintDiag { UnnameableTestItems, DuplicateMacroAttribute, CfgAttrNoAttributes, - CrateTypeInCfgAttr, - CrateNameInCfgAttr, MissingFragmentSpecifier, MetaVariableStillRepeating(MacroRulesNormalizedIdent), MetaVariableWrongOperator, diff --git a/tests/ui/cfg/future-compat-crate-attributes-using-cfg_attr.rs b/tests/ui/cfg/crate-attributes-using-cfg_attr.rs similarity index 63% rename from tests/ui/cfg/future-compat-crate-attributes-using-cfg_attr.rs rename to tests/ui/cfg/crate-attributes-using-cfg_attr.rs index 3ced3a630e334..f99fad881f284 100644 --- a/tests/ui/cfg/future-compat-crate-attributes-using-cfg_attr.rs +++ b/tests/ui/cfg/crate-attributes-using-cfg_attr.rs @@ -3,13 +3,9 @@ #![cfg_attr(foo, crate_type="bin")] //~^ERROR `crate_type` within -//~| WARN this was previously accepted //~|ERROR `crate_type` within -//~| WARN this was previously accepted #![cfg_attr(foo, crate_name="bar")] //~^ERROR `crate_name` within -//~| WARN this was previously accepted //~|ERROR `crate_name` within -//~| WARN this was previously accepted fn main() {} diff --git a/tests/ui/cfg/crate-attributes-using-cfg_attr.stderr b/tests/ui/cfg/crate-attributes-using-cfg_attr.stderr new file mode 100644 index 0000000000000..1dfca2b88d0e5 --- /dev/null +++ b/tests/ui/cfg/crate-attributes-using-cfg_attr.stderr @@ -0,0 +1,30 @@ +error: `crate_type` within an `#![cfg_attr]` attribute is forbidden + --> $DIR/crate-attributes-using-cfg_attr.rs:4:18 + | +LL | #![cfg_attr(foo, crate_type="bin")] + | ^^^^^^^^^^^^^^^^ + +error: `crate_name` within an `#![cfg_attr]` attribute is forbidden + --> $DIR/crate-attributes-using-cfg_attr.rs:7:18 + | +LL | #![cfg_attr(foo, crate_name="bar")] + | ^^^^^^^^^^^^^^^^ + +error: `crate_type` within an `#![cfg_attr]` attribute is forbidden + --> $DIR/crate-attributes-using-cfg_attr.rs:4:18 + | +LL | #![cfg_attr(foo, crate_type="bin")] + | ^^^^^^^^^^^^^^^^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: `crate_name` within an `#![cfg_attr]` attribute is forbidden + --> $DIR/crate-attributes-using-cfg_attr.rs:7:18 + | +LL | #![cfg_attr(foo, crate_name="bar")] + | ^^^^^^^^^^^^^^^^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: aborting due to 4 previous errors + diff --git a/tests/ui/cfg/future-compat-crate-attributes-using-cfg_attr.stderr b/tests/ui/cfg/future-compat-crate-attributes-using-cfg_attr.stderr deleted file mode 100644 index 82b2d7d1b1da6..0000000000000 --- a/tests/ui/cfg/future-compat-crate-attributes-using-cfg_attr.stderr +++ /dev/null @@ -1,41 +0,0 @@ -error: `crate_type` within an `#![cfg_attr]` attribute is deprecated - --> $DIR/future-compat-crate-attributes-using-cfg_attr.rs:4:18 - | -LL | #![cfg_attr(foo, crate_type="bin")] - | ^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #91632 - = note: `#[deny(deprecated_cfg_attr_crate_type_name)]` on by default - -error: `crate_name` within an `#![cfg_attr]` attribute is deprecated - --> $DIR/future-compat-crate-attributes-using-cfg_attr.rs:9:18 - | -LL | #![cfg_attr(foo, crate_name="bar")] - | ^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #91632 - -error: `crate_type` within an `#![cfg_attr]` attribute is deprecated - --> $DIR/future-compat-crate-attributes-using-cfg_attr.rs:4:18 - | -LL | #![cfg_attr(foo, crate_type="bin")] - | ^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #91632 - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error: `crate_name` within an `#![cfg_attr]` attribute is deprecated - --> $DIR/future-compat-crate-attributes-using-cfg_attr.rs:9:18 - | -LL | #![cfg_attr(foo, crate_name="bar")] - | ^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #91632 - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error: aborting due to 4 previous errors - From 925e7e6baf435e68b463f9e31911d28118de318e Mon Sep 17 00:00:00 2001 From: ismailarilik Date: Sat, 5 Oct 2024 07:34:14 +0300 Subject: [PATCH 1894/2194] Handle `clippy` cases of `rustc::potential_query_instability` lint --- compiler/rustc_data_structures/src/unhash.rs | 1 + compiler/rustc_session/src/parse.rs | 2 +- .../clippy/clippy_lints/src/index_refutable_slice.rs | 4 ++-- src/tools/clippy/clippy_lints/src/lib.rs | 2 -- src/tools/clippy/clippy_lints/src/lifetimes.rs | 8 ++++---- .../clippy_lints/src/loops/needless_range_loop.rs | 6 +++--- .../src/matches/significant_drop_in_scrutinee.rs | 7 ++++--- .../clippy_lints/src/missing_asserts_for_indexing.rs | 10 +++++----- src/tools/clippy/clippy_lints/src/module_style.rs | 6 +++--- .../clippy_lints/src/needless_pass_by_ref_mut.rs | 10 +++++----- src/tools/clippy/clippy_lints/src/swap.rs | 4 ++-- src/tools/clippy/clippy_lints/src/trait_bounds.rs | 9 ++++----- 12 files changed, 34 insertions(+), 35 deletions(-) diff --git a/compiler/rustc_data_structures/src/unhash.rs b/compiler/rustc_data_structures/src/unhash.rs index 48e21a9dab1b6..0617ef83aad9c 100644 --- a/compiler/rustc_data_structures/src/unhash.rs +++ b/compiler/rustc_data_structures/src/unhash.rs @@ -3,6 +3,7 @@ use std::hash::{BuildHasherDefault, Hasher}; pub type UnhashMap = HashMap>; pub type UnhashSet = HashSet>; +pub type UnindexMap = indexmap::IndexMap>; /// This no-op hasher expects only a single `write_u64` call. It's intended for /// map keys that already have hash-like quality, like `Fingerprint`. diff --git a/compiler/rustc_session/src/parse.rs b/compiler/rustc_session/src/parse.rs index 9781c74652081..3d44810e7dd36 100644 --- a/compiler/rustc_session/src/parse.rs +++ b/compiler/rustc_session/src/parse.rs @@ -66,7 +66,7 @@ impl GatedSpans { #[derive(Default)] pub struct SymbolGallery { /// All symbols occurred and their first occurrence span. - pub symbols: Lock>, + pub symbols: Lock>, } impl SymbolGallery { diff --git a/src/tools/clippy/clippy_lints/src/index_refutable_slice.rs b/src/tools/clippy/clippy_lints/src/index_refutable_slice.rs index 73ebe6aec15a0..96550c4d1cb95 100644 --- a/src/tools/clippy/clippy_lints/src/index_refutable_slice.rs +++ b/src/tools/clippy/clippy_lints/src/index_refutable_slice.rs @@ -5,7 +5,7 @@ use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::higher::IfLet; use clippy_utils::ty::is_copy; use clippy_utils::{is_expn_of, is_lint_allowed, path_to_local}; -use rustc_data_structures::fx::{FxHashSet, FxIndexMap}; +use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet}; use rustc_errors::Applicability; use rustc_hir as hir; use rustc_hir::HirId; @@ -133,7 +133,7 @@ fn lint_slice(cx: &LateContext<'_>, slice: &SliceLintInformation) { .index_use .iter() .map(|(index, _)| *index) - .collect::>(); + .collect::>(); let value_name = |index| format!("{}_{index}", slice.ident.name); diff --git a/src/tools/clippy/clippy_lints/src/lib.rs b/src/tools/clippy/clippy_lints/src/lib.rs index 2eb6d99b761f7..1a6d646e0dfb0 100644 --- a/src/tools/clippy/clippy_lints/src/lib.rs +++ b/src/tools/clippy/clippy_lints/src/lib.rs @@ -27,8 +27,6 @@ unused_qualifications, rustc::internal )] -// Disable this rustc lint for now, as it was also done in rustc -#![allow(rustc::potential_query_instability)] // FIXME: switch to something more ergonomic here, once available. // (Currently there is no way to opt into sysroot crates without `extern crate`.) diff --git a/src/tools/clippy/clippy_lints/src/lifetimes.rs b/src/tools/clippy/clippy_lints/src/lifetimes.rs index 5c37e73544577..0d151e299b25b 100644 --- a/src/tools/clippy/clippy_lints/src/lifetimes.rs +++ b/src/tools/clippy/clippy_lints/src/lifetimes.rs @@ -1,7 +1,7 @@ use clippy_utils::diagnostics::{span_lint, span_lint_and_then}; use clippy_utils::trait_ref_of_method; use itertools::Itertools; -use rustc_data_structures::fx::{FxHashMap, FxHashSet}; +use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet}; use rustc_errors::Applicability; use rustc_hir::FnRetTy::Return; use rustc_hir::intravisit::nested_filter::{self as hir_nested_filter, NestedFilter}; @@ -311,7 +311,7 @@ fn could_use_elision<'tcx>( Some((elidable_lts, usages)) } -fn allowed_lts_from(named_generics: &[GenericParam<'_>]) -> FxHashSet { +fn allowed_lts_from(named_generics: &[GenericParam<'_>]) -> FxIndexSet { named_generics .iter() .filter_map(|par| { @@ -499,7 +499,7 @@ struct Usage { struct LifetimeChecker<'cx, 'tcx, F> { cx: &'cx LateContext<'tcx>, - map: FxHashMap>, + map: FxIndexMap>, where_predicate_depth: usize, generic_args_depth: usize, phantom: std::marker::PhantomData, @@ -621,7 +621,7 @@ fn report_extra_impl_lifetimes<'tcx>(cx: &LateContext<'tcx>, impl_: &'tcx Impl<' fn report_elidable_impl_lifetimes<'tcx>( cx: &LateContext<'tcx>, impl_: &'tcx Impl<'_>, - map: &FxHashMap>, + map: &FxIndexMap>, ) { let single_usages = map .iter() diff --git a/src/tools/clippy/clippy_lints/src/loops/needless_range_loop.rs b/src/tools/clippy/clippy_lints/src/loops/needless_range_loop.rs index 745f070a577d5..214b8b0f37922 100644 --- a/src/tools/clippy/clippy_lints/src/loops/needless_range_loop.rs +++ b/src/tools/clippy/clippy_lints/src/loops/needless_range_loop.rs @@ -5,7 +5,7 @@ use clippy_utils::ty::has_iter_method; use clippy_utils::visitors::is_local_used; use clippy_utils::{SpanlessEq, contains_name, higher, is_integer_const, sugg}; use rustc_ast::ast; -use rustc_data_structures::fx::{FxHashMap, FxHashSet}; +use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap}; use rustc_errors::Applicability; use rustc_hir::def::{DefKind, Res}; use rustc_hir::intravisit::{Visitor, walk_expr}; @@ -39,7 +39,7 @@ pub(super) fn check<'tcx>( var: canonical_id, indexed_mut: FxHashSet::default(), indexed_indirectly: FxHashMap::default(), - indexed_directly: FxHashMap::default(), + indexed_directly: FxIndexMap::default(), referenced: FxHashSet::default(), nonindex: false, prefer_mutable: false, @@ -229,7 +229,7 @@ struct VarVisitor<'a, 'tcx> { indexed_indirectly: FxHashMap>, /// subset of `indexed` of vars that are indexed directly: `v[i]` /// this will not contain cases like `v[calc_index(i)]` or `v[(i + 4) % N]` - indexed_directly: FxHashMap, Ty<'tcx>)>, + indexed_directly: FxIndexMap, Ty<'tcx>)>, /// Any names that are used outside an index operation. /// Used to detect things like `&mut vec` used together with `vec[i]` referenced: FxHashSet, diff --git a/src/tools/clippy/clippy_lints/src/matches/significant_drop_in_scrutinee.rs b/src/tools/clippy/clippy_lints/src/matches/significant_drop_in_scrutinee.rs index 7372f52e1e5bd..2ce6a8a85a5eb 100644 --- a/src/tools/clippy/clippy_lints/src/matches/significant_drop_in_scrutinee.rs +++ b/src/tools/clippy/clippy_lints/src/matches/significant_drop_in_scrutinee.rs @@ -7,6 +7,7 @@ use clippy_utils::ty::{for_each_top_level_late_bound_region, is_copy}; use clippy_utils::{get_attr, is_lint_allowed}; use itertools::Itertools; use rustc_ast::Mutability; +use rustc_data_structures::fx::FxIndexSet; use rustc_errors::{Applicability, Diag}; use rustc_hir::intravisit::{Visitor, walk_expr}; use rustc_hir::{Arm, Expr, ExprKind, MatchSource}; @@ -475,19 +476,19 @@ impl<'tcx> Visitor<'tcx> for SigDropHelper<'_, 'tcx> { struct ArmSigDropHelper<'a, 'tcx> { sig_drop_checker: SigDropChecker<'a, 'tcx>, - found_sig_drop_spans: FxHashSet, + found_sig_drop_spans: FxIndexSet, } impl<'a, 'tcx> ArmSigDropHelper<'a, 'tcx> { fn new(cx: &'a LateContext<'tcx>) -> ArmSigDropHelper<'a, 'tcx> { ArmSigDropHelper { sig_drop_checker: SigDropChecker::new(cx), - found_sig_drop_spans: FxHashSet::::default(), + found_sig_drop_spans: FxIndexSet::::default(), } } } -fn has_significant_drop_in_arms<'tcx>(cx: &LateContext<'tcx>, arms: &[&'tcx Expr<'_>]) -> FxHashSet { +fn has_significant_drop_in_arms<'tcx>(cx: &LateContext<'tcx>, arms: &[&'tcx Expr<'_>]) -> FxIndexSet { let mut helper = ArmSigDropHelper::new(cx); for arm in arms { helper.visit_expr(arm); diff --git a/src/tools/clippy/clippy_lints/src/missing_asserts_for_indexing.rs b/src/tools/clippy/clippy_lints/src/missing_asserts_for_indexing.rs index b40d7eba15e5e..c56a4014b3494 100644 --- a/src/tools/clippy/clippy_lints/src/missing_asserts_for_indexing.rs +++ b/src/tools/clippy/clippy_lints/src/missing_asserts_for_indexing.rs @@ -8,7 +8,7 @@ use clippy_utils::visitors::for_each_expr_without_closures; use clippy_utils::{eq_expr_value, hash_expr, higher}; use rustc_ast::{LitKind, RangeLimits}; use rustc_data_structures::packed::Pu128; -use rustc_data_structures::unhash::UnhashMap; +use rustc_data_structures::unhash::UnindexMap; use rustc_errors::{Applicability, Diag}; use rustc_hir::{BinOp, Block, Body, Expr, ExprKind, UnOp}; use rustc_lint::{LateContext, LateLintPass}; @@ -226,7 +226,7 @@ fn upper_index_expr(expr: &Expr<'_>) -> Option { } /// Checks if the expression is an index into a slice and adds it to `indexes` -fn check_index<'hir>(cx: &LateContext<'_>, expr: &'hir Expr<'hir>, map: &mut UnhashMap>>) { +fn check_index<'hir>(cx: &LateContext<'_>, expr: &'hir Expr<'hir>, map: &mut UnindexMap>>) { if let ExprKind::Index(slice, index_lit, _) = expr.kind && cx.typeck_results().expr_ty_adjusted(slice).peel_refs().is_slice() && let Some(index) = upper_index_expr(index_lit) @@ -274,7 +274,7 @@ fn check_index<'hir>(cx: &LateContext<'_>, expr: &'hir Expr<'hir>, map: &mut Unh } /// Checks if the expression is an `assert!` expression and adds it to `asserts` -fn check_assert<'hir>(cx: &LateContext<'_>, expr: &'hir Expr<'hir>, map: &mut UnhashMap>>) { +fn check_assert<'hir>(cx: &LateContext<'_>, expr: &'hir Expr<'hir>, map: &mut UnindexMap>>) { if let Some((comparison, asserted_len, slice)) = assert_len_expr(cx, expr) { let hash = hash_expr(cx, slice); let indexes = map.entry(hash).or_default(); @@ -311,7 +311,7 @@ fn check_assert<'hir>(cx: &LateContext<'_>, expr: &'hir Expr<'hir>, map: &mut Un /// Inspects indexes and reports lints. /// /// Called at the end of this lint after all indexing and `assert!` expressions have been collected. -fn report_indexes(cx: &LateContext<'_>, map: &UnhashMap>>) { +fn report_indexes(cx: &LateContext<'_>, map: &UnindexMap>>) { for bucket in map.values() { for entry in bucket { let Some(full_span) = entry @@ -403,7 +403,7 @@ fn report_indexes(cx: &LateContext<'_>, map: &UnhashMap> impl LateLintPass<'_> for MissingAssertsForIndexing { fn check_body(&mut self, cx: &LateContext<'_>, body: &Body<'_>) { - let mut map = UnhashMap::default(); + let mut map = UnindexMap::default(); for_each_expr_without_closures(body.value, |expr| { check_index(cx, expr, &mut map); diff --git a/src/tools/clippy/clippy_lints/src/module_style.rs b/src/tools/clippy/clippy_lints/src/module_style.rs index e9c5f64a2550d..676d608eb318c 100644 --- a/src/tools/clippy/clippy_lints/src/module_style.rs +++ b/src/tools/clippy/clippy_lints/src/module_style.rs @@ -1,6 +1,6 @@ use clippy_utils::diagnostics::span_lint_and_then; use rustc_ast::ast; -use rustc_data_structures::fx::{FxHashMap, FxHashSet}; +use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet}; use rustc_lint::{EarlyContext, EarlyLintPass, Level, LintContext}; use rustc_session::impl_lint_pass; use rustc_span::def_id::LOCAL_CRATE; @@ -87,7 +87,7 @@ impl EarlyLintPass for ModStyle { // `folder_segments` is all unique folder path segments `path/to/foo.rs` gives // `[path, to]` but not foo - let mut folder_segments = FxHashSet::default(); + let mut folder_segments = FxIndexSet::default(); // `mod_folders` is all the unique folder names that contain a mod.rs file let mut mod_folders = FxHashSet::default(); // `file_map` maps file names to the full path including the file name @@ -144,7 +144,7 @@ impl EarlyLintPass for ModStyle { /// is `mod.rs` we add it's parent folder to `mod_folders`. fn process_paths_for_mod_files<'a>( path: &'a Path, - folder_segments: &mut FxHashSet<&'a OsStr>, + folder_segments: &mut FxIndexSet<&'a OsStr>, mod_folders: &mut FxHashSet<&'a OsStr>, ) { let mut comp = path.components().rev().peekable(); diff --git a/src/tools/clippy/clippy_lints/src/needless_pass_by_ref_mut.rs b/src/tools/clippy/clippy_lints/src/needless_pass_by_ref_mut.rs index c2facb2fcf68c..5c631a176c4af 100644 --- a/src/tools/clippy/clippy_lints/src/needless_pass_by_ref_mut.rs +++ b/src/tools/clippy/clippy_lints/src/needless_pass_by_ref_mut.rs @@ -5,7 +5,7 @@ use clippy_utils::source::snippet; use clippy_utils::visitors::for_each_expr; use clippy_utils::{inherits_cfg, is_from_proc_macro, is_self}; use core::ops::ControlFlow; -use rustc_data_structures::fx::{FxHashSet, FxIndexMap}; +use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet}; use rustc_errors::Applicability; use rustc_hir::intravisit::FnKind; use rustc_hir::{ @@ -101,7 +101,7 @@ fn check_closures<'tcx>( ctx: &mut MutablyUsedVariablesCtxt<'tcx>, cx: &LateContext<'tcx>, checked_closures: &mut FxHashSet, - closures: FxHashSet, + closures: FxIndexSet, ) { let hir = cx.tcx.hir(); for closure in closures { @@ -196,7 +196,7 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByRefMut<'tcx> { prev_bind: None, prev_move_to_closure: HirIdSet::default(), aliases: HirIdMap::default(), - async_closures: FxHashSet::default(), + async_closures: FxIndexSet::default(), tcx: cx.tcx, }; euv::ExprUseVisitor::for_clippy(cx, fn_def_id, &mut ctx) @@ -207,7 +207,7 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByRefMut<'tcx> { // We retrieve all the closures declared in the function because they will not be found // by `euv::Delegate`. - let mut closures: FxHashSet = FxHashSet::default(); + let mut closures: FxIndexSet = FxIndexSet::default(); for_each_expr(cx, body, |expr| { if let ExprKind::Closure(closure) = expr.kind { closures.insert(closure.def_id); @@ -307,7 +307,7 @@ struct MutablyUsedVariablesCtxt<'tcx> { /// use of a variable. prev_move_to_closure: HirIdSet, aliases: HirIdMap, - async_closures: FxHashSet, + async_closures: FxIndexSet, tcx: TyCtxt<'tcx>, } diff --git a/src/tools/clippy/clippy_lints/src/swap.rs b/src/tools/clippy/clippy_lints/src/swap.rs index a3145c4647cab..6cba560393d0d 100644 --- a/src/tools/clippy/clippy_lints/src/swap.rs +++ b/src/tools/clippy/clippy_lints/src/swap.rs @@ -6,9 +6,9 @@ use clippy_utils::ty::is_type_diagnostic_item; use clippy_utils::{can_mut_borrow_both, eq_expr_value, is_in_const_context, std_or_core}; use itertools::Itertools; +use rustc_data_structures::fx::FxIndexSet; use rustc_hir::intravisit::{Visitor, walk_expr}; -use crate::FxHashSet; use rustc_errors::Applicability; use rustc_hir::{BinOpKind, Block, Expr, ExprKind, LetStmt, PatKind, QPath, Stmt, StmtKind}; use rustc_lint::{LateContext, LateLintPass, LintContext}; @@ -334,7 +334,7 @@ struct IndexBinding<'a, 'tcx> { impl<'tcx> IndexBinding<'_, 'tcx> { fn snippet_index_bindings(&mut self, exprs: &[&'tcx Expr<'tcx>]) -> String { - let mut bindings = FxHashSet::default(); + let mut bindings = FxIndexSet::default(); for expr in exprs { bindings.insert(self.snippet_index_binding(expr)); } diff --git a/src/tools/clippy/clippy_lints/src/trait_bounds.rs b/src/tools/clippy/clippy_lints/src/trait_bounds.rs index 00277593622aa..3c3973857e796 100644 --- a/src/tools/clippy/clippy_lints/src/trait_bounds.rs +++ b/src/tools/clippy/clippy_lints/src/trait_bounds.rs @@ -5,7 +5,7 @@ use clippy_utils::source::{SpanRangeExt, snippet, snippet_with_applicability}; use clippy_utils::{SpanlessEq, SpanlessHash, is_from_proc_macro}; use core::hash::{Hash, Hasher}; use itertools::Itertools; -use rustc_data_structures::fx::{FxHashMap, FxHashSet}; +use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap, IndexEntry}; use rustc_data_structures::unhash::UnhashMap; use rustc_errors::Applicability; use rustc_hir::def::Res; @@ -16,7 +16,6 @@ use rustc_hir::{ use rustc_lint::{LateContext, LateLintPass}; use rustc_session::impl_lint_pass; use rustc_span::{BytePos, Span}; -use std::collections::hash_map::Entry; declare_clippy_lint! { /// ### What it does @@ -427,7 +426,7 @@ fn rollup_traits( bounds: &[GenericBound<'_>], msg: &'static str, ) -> Vec<(ComparableTraitRef, Span)> { - let mut map = FxHashMap::default(); + let mut map = FxIndexMap::default(); let mut repeated_res = false; let only_comparable_trait_refs = |bound: &GenericBound<'_>| { @@ -442,8 +441,8 @@ fn rollup_traits( for bound in bounds.iter().filter_map(only_comparable_trait_refs) { let (comparable_bound, span_direct) = bound; match map.entry(comparable_bound) { - Entry::Occupied(_) => repeated_res = true, - Entry::Vacant(e) => { + IndexEntry::Occupied(_) => repeated_res = true, + IndexEntry::Vacant(e) => { e.insert((span_direct, i)); i += 1; }, From 05f7b092a484c1bd0132ab645800e53be3709aef Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Sat, 5 Oct 2024 08:07:26 +0300 Subject: [PATCH 1895/2194] remove outdated contribution direction Signed-off-by: onur-ozkan --- src/bootstrap/README.md | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/bootstrap/README.md b/src/bootstrap/README.md index 0ac58645d2dfc..f036603ee707b 100644 --- a/src/bootstrap/README.md +++ b/src/bootstrap/README.md @@ -182,10 +182,8 @@ Some general areas that you may be interested in modifying are: `Config` struct. * Adding a sanity check? Take a look at `bootstrap/src/core/sanity.rs`. -If you make a major change on bootstrap configuration, please remember to: - -+ Update `CONFIG_CHANGE_HISTORY` in `src/bootstrap/src/utils/change_tracker.rs`. -* Update `change-id = {pull-request-id}` in `config.example.toml`. +If you make a major change on bootstrap configuration, please add a new entry to +`CONFIG_CHANGE_HISTORY` in `src/bootstrap/src/utils/change_tracker.rs`. A 'major change' includes From 2feed6279655d6febce04a0efd167c2aea56facf Mon Sep 17 00:00:00 2001 From: ismailarilik Date: Sat, 5 Oct 2024 10:01:27 +0300 Subject: [PATCH 1896/2194] Handle `rustc_interface` cases of `rustc::potential_query_instability` lint --- compiler/rustc_interface/src/passes.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index 204ae437a3e9a..fd850d2f39a5f 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -470,7 +470,6 @@ fn write_out_deps(tcx: TyCtxt<'_>, outputs: &OutputFilenames, out_filenames: &[P }) } - #[allow(rustc::potential_query_instability)] let extra_tracked_files = hash_iter_files( file_depinfo.iter().map(|path_sym| normalize_path(PathBuf::from(path_sym.as_str()))), checksum_hash_algo, From d0e67586774530fa8fd70e563768067c0b2ca99d Mon Sep 17 00:00:00 2001 From: onestacked Date: Sun, 29 Sep 2024 23:51:18 +0200 Subject: [PATCH 1897/2194] Stabilize `const_slice_split_at_mut` and `const_slice_first_last_chunk` --- library/core/src/lib.rs | 1 - library/core/src/slice/mod.rs | 21 ++++++++++++++------- 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index b1dbcc744ac60..380140601a50a 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -146,7 +146,6 @@ #![feature(const_size_of_val)] #![feature(const_size_of_val_raw)] #![feature(const_slice_from_ref)] -#![feature(const_slice_split_at_mut)] #![feature(const_strict_overflow_ops)] #![feature(const_swap)] #![feature(const_try)] diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs index 754a736b15b3c..90ddc9c1d85d6 100644 --- a/library/core/src/slice/mod.rs +++ b/library/core/src/slice/mod.rs @@ -356,7 +356,8 @@ impl [T] { /// ``` #[inline] #[stable(feature = "slice_first_last_chunk", since = "1.77.0")] - #[rustc_const_unstable(feature = "const_slice_first_last_chunk", issue = "111774")] + #[rustc_const_stable(feature = "const_slice_first_last_chunk", since = "CURRENT_RUSTC_VERSION")] + #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] pub const fn first_chunk_mut(&mut self) -> Option<&mut [T; N]> { if self.len() < N { None @@ -421,7 +422,8 @@ impl [T] { /// ``` #[inline] #[stable(feature = "slice_first_last_chunk", since = "1.77.0")] - #[rustc_const_unstable(feature = "const_slice_first_last_chunk", issue = "111774")] + #[rustc_const_stable(feature = "const_slice_first_last_chunk", since = "CURRENT_RUSTC_VERSION")] + #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] pub const fn split_first_chunk_mut( &mut self, ) -> Option<(&mut [T; N], &mut [T])> { @@ -491,7 +493,8 @@ impl [T] { /// ``` #[inline] #[stable(feature = "slice_first_last_chunk", since = "1.77.0")] - #[rustc_const_unstable(feature = "const_slice_first_last_chunk", issue = "111774")] + #[rustc_const_stable(feature = "const_slice_first_last_chunk", since = "CURRENT_RUSTC_VERSION")] + #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] pub const fn split_last_chunk_mut( &mut self, ) -> Option<(&mut [T], &mut [T; N])> { @@ -560,7 +563,8 @@ impl [T] { /// ``` #[inline] #[stable(feature = "slice_first_last_chunk", since = "1.77.0")] - #[rustc_const_unstable(feature = "const_slice_first_last_chunk", issue = "111774")] + #[rustc_const_stable(feature = "const_slice_first_last_chunk", since = "CURRENT_RUSTC_VERSION")] + #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] pub const fn last_chunk_mut(&mut self) -> Option<&mut [T; N]> { if self.len() < N { None @@ -1903,7 +1907,8 @@ impl [T] { #[inline] #[track_caller] #[must_use] - #[rustc_const_unstable(feature = "const_slice_split_at_mut", issue = "101804")] + #[rustc_const_stable(feature = "const_slice_split_at_mut", since = "CURRENT_RUSTC_VERSION")] + #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] pub const fn split_at_mut(&mut self, mid: usize) -> (&mut [T], &mut [T]) { match self.split_at_mut_checked(mid) { Some(pair) => pair, @@ -2005,7 +2010,8 @@ impl [T] { /// assert_eq!(v, [1, 2, 3, 4, 5, 6]); /// ``` #[stable(feature = "slice_split_at_unchecked", since = "1.79.0")] - #[rustc_const_unstable(feature = "const_slice_split_at_mut", issue = "101804")] + #[rustc_const_stable(feature = "const_slice_split_at_mut", since = "CURRENT_RUSTC_VERSION")] + #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] #[inline] #[must_use] pub const unsafe fn split_at_mut_unchecked(&mut self, mid: usize) -> (&mut [T], &mut [T]) { @@ -2105,7 +2111,8 @@ impl [T] { /// assert_eq!(None, v.split_at_mut_checked(7)); /// ``` #[stable(feature = "split_at_checked", since = "1.80.0")] - #[rustc_const_unstable(feature = "const_slice_split_at_mut", issue = "101804")] + #[rustc_const_stable(feature = "const_slice_split_at_mut", since = "CURRENT_RUSTC_VERSION")] + #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] #[inline] #[must_use] pub const fn split_at_mut_checked(&mut self, mid: usize) -> Option<(&mut [T], &mut [T])> { From 0cd0f7ceef442f2767024df261d3898db23402d8 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Fri, 4 Oct 2024 17:43:27 +0200 Subject: [PATCH 1898/2194] move f16/f128 const fn under f16/f128 feature gate --- library/core/src/lib.rs | 2 -- library/core/src/num/f128.rs | 16 ++++++++-------- library/core/src/num/f16.rs | 16 ++++++++-------- .../clippy/tests/ui/transmute_float_to_int.fixed | 4 ++-- .../clippy/tests/ui/transmute_float_to_int.rs | 4 ++-- tests/ui/float/classify-runtime-const.rs | 4 ++-- tests/ui/float/conv-bits-runtime-const.rs | 2 -- 7 files changed, 22 insertions(+), 26 deletions(-) diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index b1dbcc744ac60..577ce124251af 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -158,8 +158,6 @@ #![feature(coverage_attribute)] #![feature(do_not_recommend)] #![feature(duration_consts_float)] -#![feature(f128_const)] -#![feature(f16_const)] #![feature(internal_impls_macro)] #![feature(ip)] #![feature(is_ascii_octdigit)] diff --git a/library/core/src/num/f128.rs b/library/core/src/num/f128.rs index 133d6e3fc9ae2..764df4fe4b058 100644 --- a/library/core/src/num/f128.rs +++ b/library/core/src/num/f128.rs @@ -910,7 +910,7 @@ impl f128 { /// ``` #[inline] #[unstable(feature = "f128", issue = "116909")] - #[rustc_const_unstable(feature = "f128_const", issue = "116909")] + #[rustc_const_unstable(feature = "f128", issue = "116909")] #[must_use = "this returns the result of the operation, without modifying the original"] pub const fn to_bits(self) -> u128 { // SAFETY: `u128` is a plain old datatype so we can always transmute to it. @@ -959,7 +959,7 @@ impl f128 { #[inline] #[must_use] #[unstable(feature = "f128", issue = "116909")] - #[rustc_const_unstable(feature = "f128_const", issue = "116909")] + #[rustc_const_unstable(feature = "f128", issue = "116909")] pub const fn from_bits(v: u128) -> Self { // It turns out the safety issues with sNaN were overblown! Hooray! // SAFETY: `u128` is a plain old datatype so we can always transmute from it. @@ -986,7 +986,7 @@ impl f128 { /// ``` #[inline] #[unstable(feature = "f128", issue = "116909")] - #[rustc_const_unstable(feature = "f128_const", issue = "116909")] + #[rustc_const_unstable(feature = "f128", issue = "116909")] #[must_use = "this returns the result of the operation, without modifying the original"] pub const fn to_be_bytes(self) -> [u8; 16] { self.to_bits().to_be_bytes() @@ -1012,7 +1012,7 @@ impl f128 { /// ``` #[inline] #[unstable(feature = "f128", issue = "116909")] - #[rustc_const_unstable(feature = "f128_const", issue = "116909")] + #[rustc_const_unstable(feature = "f128", issue = "116909")] #[must_use = "this returns the result of the operation, without modifying the original"] pub const fn to_le_bytes(self) -> [u8; 16] { self.to_bits().to_le_bytes() @@ -1049,7 +1049,7 @@ impl f128 { /// ``` #[inline] #[unstable(feature = "f128", issue = "116909")] - #[rustc_const_unstable(feature = "f128_const", issue = "116909")] + #[rustc_const_unstable(feature = "f128", issue = "116909")] #[must_use = "this returns the result of the operation, without modifying the original"] pub const fn to_ne_bytes(self) -> [u8; 16] { self.to_bits().to_ne_bytes() @@ -1077,7 +1077,7 @@ impl f128 { #[inline] #[must_use] #[unstable(feature = "f128", issue = "116909")] - #[rustc_const_unstable(feature = "f128_const", issue = "116909")] + #[rustc_const_unstable(feature = "f128", issue = "116909")] pub const fn from_be_bytes(bytes: [u8; 16]) -> Self { Self::from_bits(u128::from_be_bytes(bytes)) } @@ -1104,7 +1104,7 @@ impl f128 { #[inline] #[must_use] #[unstable(feature = "f128", issue = "116909")] - #[rustc_const_unstable(feature = "f128_const", issue = "116909")] + #[rustc_const_unstable(feature = "f128", issue = "116909")] pub const fn from_le_bytes(bytes: [u8; 16]) -> Self { Self::from_bits(u128::from_le_bytes(bytes)) } @@ -1141,7 +1141,7 @@ impl f128 { #[inline] #[must_use] #[unstable(feature = "f128", issue = "116909")] - #[rustc_const_unstable(feature = "f128_const", issue = "116909")] + #[rustc_const_unstable(feature = "f128", issue = "116909")] pub const fn from_ne_bytes(bytes: [u8; 16]) -> Self { Self::from_bits(u128::from_ne_bytes(bytes)) } diff --git a/library/core/src/num/f16.rs b/library/core/src/num/f16.rs index e50f5e7e8fbd5..897fc8c105d46 100644 --- a/library/core/src/num/f16.rs +++ b/library/core/src/num/f16.rs @@ -896,7 +896,7 @@ impl f16 { /// ``` #[inline] #[unstable(feature = "f16", issue = "116909")] - #[rustc_const_unstable(feature = "f16_const", issue = "116909")] + #[rustc_const_unstable(feature = "f16", issue = "116909")] #[must_use = "this returns the result of the operation, without modifying the original"] pub const fn to_bits(self) -> u16 { // SAFETY: `u16` is a plain old datatype so we can always transmute to it. @@ -944,7 +944,7 @@ impl f16 { #[inline] #[must_use] #[unstable(feature = "f16", issue = "116909")] - #[rustc_const_unstable(feature = "f16_const", issue = "116909")] + #[rustc_const_unstable(feature = "f16", issue = "116909")] pub const fn from_bits(v: u16) -> Self { // It turns out the safety issues with sNaN were overblown! Hooray! // SAFETY: `u16` is a plain old datatype so we can always transmute from it. @@ -970,7 +970,7 @@ impl f16 { /// ``` #[inline] #[unstable(feature = "f16", issue = "116909")] - #[rustc_const_unstable(feature = "f16_const", issue = "116909")] + #[rustc_const_unstable(feature = "f16", issue = "116909")] #[must_use = "this returns the result of the operation, without modifying the original"] pub const fn to_be_bytes(self) -> [u8; 2] { self.to_bits().to_be_bytes() @@ -995,7 +995,7 @@ impl f16 { /// ``` #[inline] #[unstable(feature = "f16", issue = "116909")] - #[rustc_const_unstable(feature = "f16_const", issue = "116909")] + #[rustc_const_unstable(feature = "f16", issue = "116909")] #[must_use = "this returns the result of the operation, without modifying the original"] pub const fn to_le_bytes(self) -> [u8; 2] { self.to_bits().to_le_bytes() @@ -1033,7 +1033,7 @@ impl f16 { /// ``` #[inline] #[unstable(feature = "f16", issue = "116909")] - #[rustc_const_unstable(feature = "f16_const", issue = "116909")] + #[rustc_const_unstable(feature = "f16", issue = "116909")] #[must_use = "this returns the result of the operation, without modifying the original"] pub const fn to_ne_bytes(self) -> [u8; 2] { self.to_bits().to_ne_bytes() @@ -1057,7 +1057,7 @@ impl f16 { #[inline] #[must_use] #[unstable(feature = "f16", issue = "116909")] - #[rustc_const_unstable(feature = "f16_const", issue = "116909")] + #[rustc_const_unstable(feature = "f16", issue = "116909")] pub const fn from_be_bytes(bytes: [u8; 2]) -> Self { Self::from_bits(u16::from_be_bytes(bytes)) } @@ -1080,7 +1080,7 @@ impl f16 { #[inline] #[must_use] #[unstable(feature = "f16", issue = "116909")] - #[rustc_const_unstable(feature = "f16_const", issue = "116909")] + #[rustc_const_unstable(feature = "f16", issue = "116909")] pub const fn from_le_bytes(bytes: [u8; 2]) -> Self { Self::from_bits(u16::from_le_bytes(bytes)) } @@ -1114,7 +1114,7 @@ impl f16 { #[inline] #[must_use] #[unstable(feature = "f16", issue = "116909")] - #[rustc_const_unstable(feature = "f16_const", issue = "116909")] + #[rustc_const_unstable(feature = "f16", issue = "116909")] pub const fn from_ne_bytes(bytes: [u8; 2]) -> Self { Self::from_bits(u16::from_ne_bytes(bytes)) } diff --git a/src/tools/clippy/tests/ui/transmute_float_to_int.fixed b/src/tools/clippy/tests/ui/transmute_float_to_int.fixed index 83814ca43b96d..075a198918a0d 100644 --- a/src/tools/clippy/tests/ui/transmute_float_to_int.fixed +++ b/src/tools/clippy/tests/ui/transmute_float_to_int.fixed @@ -1,7 +1,7 @@ #![warn(clippy::transmute_float_to_int)] #![allow(clippy::missing_transmute_annotations)] -#![feature(f128, f128_const)] -#![feature(f16, f16_const)] +#![feature(f128)] +#![feature(f16)] fn float_to_int() { let _: u32 = unsafe { 1f32.to_bits() }; diff --git a/src/tools/clippy/tests/ui/transmute_float_to_int.rs b/src/tools/clippy/tests/ui/transmute_float_to_int.rs index 64d6e9172039d..12541b2f7cf32 100644 --- a/src/tools/clippy/tests/ui/transmute_float_to_int.rs +++ b/src/tools/clippy/tests/ui/transmute_float_to_int.rs @@ -1,7 +1,7 @@ #![warn(clippy::transmute_float_to_int)] #![allow(clippy::missing_transmute_annotations)] -#![feature(f128, f128_const)] -#![feature(f16, f16_const)] +#![feature(f128)] +#![feature(f16)] fn float_to_int() { let _: u32 = unsafe { std::mem::transmute(1f32) }; diff --git a/tests/ui/float/classify-runtime-const.rs b/tests/ui/float/classify-runtime-const.rs index 2a24e51cabbc4..ca852ea2468bc 100644 --- a/tests/ui/float/classify-runtime-const.rs +++ b/tests/ui/float/classify-runtime-const.rs @@ -6,8 +6,8 @@ // This tests the float classification functions, for regular runtime code and for const evaluation. -#![feature(f16_const)] -#![feature(f128_const)] +#![feature(f16)] +#![feature(f128)] use std::num::FpCategory::*; diff --git a/tests/ui/float/conv-bits-runtime-const.rs b/tests/ui/float/conv-bits-runtime-const.rs index 60c45cc4cc194..3046728fe66ff 100644 --- a/tests/ui/float/conv-bits-runtime-const.rs +++ b/tests/ui/float/conv-bits-runtime-const.rs @@ -5,8 +5,6 @@ #![feature(f16)] #![feature(f128)] -#![feature(f16_const)] -#![feature(f128_const)] #![allow(unused_macro_rules)] use std::hint::black_box; From 155380523c1fe0381255556d2b0588f9a0fdcacd Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 5 Oct 2024 10:40:38 +0200 Subject: [PATCH 1899/2194] pthread mutex: better error in reentrant-locking-UB, also test PTHREAD_MUTEX_INITIALIZER --- src/tools/miri/src/shims/unix/sync.rs | 4 +++- ...ck.rs => libc_pthread_mutex_NULL_reentrant.rs} | 4 ++-- ...r => libc_pthread_mutex_NULL_reentrant.stderr} | 8 ++++---- ...rs => libc_pthread_mutex_default_reentrant.rs} | 9 +++++++-- ...> libc_pthread_mutex_default_reentrant.stderr} | 8 ++++---- ....rs => libc_pthread_mutex_normal_reentrant.rs} | 2 ++ ...=> libc_pthread_mutex_normal_reentrant.stderr} | 4 ++-- .../libc_pthread_mutex_staticinit_reentrant.rs | 12 ++++++++++++ ...libc_pthread_mutex_staticinit_reentrant.stderr | 15 +++++++++++++++ 9 files changed, 51 insertions(+), 15 deletions(-) rename src/tools/miri/tests/fail-dep/concurrency/{libc_pthread_mutex_NULL_deadlock.rs => libc_pthread_mutex_NULL_reentrant.rs} (72%) rename src/tools/miri/tests/fail-dep/concurrency/{libc_pthread_mutex_NULL_deadlock.stderr => libc_pthread_mutex_NULL_reentrant.stderr} (68%) rename src/tools/miri/tests/fail-dep/concurrency/{libc_pthread_mutex_default_deadlock.rs => libc_pthread_mutex_default_reentrant.rs} (52%) rename src/tools/miri/tests/fail-dep/concurrency/{libc_pthread_mutex_default_deadlock.stderr => libc_pthread_mutex_default_reentrant.stderr} (68%) rename src/tools/miri/tests/fail-dep/concurrency/{libc_pthread_mutex_normal_deadlock.rs => libc_pthread_mutex_normal_reentrant.rs} (81%) rename src/tools/miri/tests/fail-dep/concurrency/{libc_pthread_mutex_normal_deadlock.stderr => libc_pthread_mutex_normal_reentrant.stderr} (79%) create mode 100644 src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutex_staticinit_reentrant.rs create mode 100644 src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutex_staticinit_reentrant.stderr diff --git a/src/tools/miri/src/shims/unix/sync.rs b/src/tools/miri/src/shims/unix/sync.rs index 017291f81a22e..b05f340861e78 100644 --- a/src/tools/miri/src/shims/unix/sync.rs +++ b/src/tools/miri/src/shims/unix/sync.rs @@ -483,7 +483,9 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // Trying to acquire the same mutex again. match kind { MutexKind::Default => - throw_ub_format!("trying to acquire already locked default mutex"), + throw_ub_format!( + "trying to acquire default mutex already locked by the current thread" + ), MutexKind::Normal => throw_machine_stop!(TerminationInfo::Deadlock), MutexKind::ErrorCheck => this.eval_libc_i32("EDEADLK"), MutexKind::Recursive => { diff --git a/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutex_NULL_deadlock.rs b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutex_NULL_reentrant.rs similarity index 72% rename from src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutex_NULL_deadlock.rs rename to src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutex_NULL_reentrant.rs index a79abe65328e0..f2df8bdca12bd 100644 --- a/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutex_NULL_deadlock.rs +++ b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutex_NULL_reentrant.rs @@ -1,12 +1,12 @@ //@ignore-target: windows # No pthreads on Windows // -// Check that if we pass NULL attribute, then we get the default mutex type. +// Check that if we pass NULL attribute, then reentrant locking is UB. fn main() { unsafe { let mut mutex: libc::pthread_mutex_t = std::mem::zeroed(); assert_eq!(libc::pthread_mutex_init(&mut mutex as *mut _, std::ptr::null() as *const _), 0); assert_eq!(libc::pthread_mutex_lock(&mut mutex as *mut _), 0); - libc::pthread_mutex_lock(&mut mutex as *mut _); //~ ERROR: Undefined Behavior: trying to acquire already locked default mutex + libc::pthread_mutex_lock(&mut mutex as *mut _); //~ ERROR: already locked by the current thread } } diff --git a/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutex_NULL_deadlock.stderr b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutex_NULL_reentrant.stderr similarity index 68% rename from src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutex_NULL_deadlock.stderr rename to src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutex_NULL_reentrant.stderr index e9961ed413d0c..9455e70437629 100644 --- a/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutex_NULL_deadlock.stderr +++ b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutex_NULL_reentrant.stderr @@ -1,13 +1,13 @@ -error: Undefined Behavior: trying to acquire already locked default mutex - --> tests/fail-dep/concurrency/libc_pthread_mutex_NULL_deadlock.rs:LL:CC +error: Undefined Behavior: trying to acquire default mutex already locked by the current thread + --> tests/fail-dep/concurrency/libc_pthread_mutex_NULL_reentrant.rs:LL:CC | LL | libc::pthread_mutex_lock(&mut mutex as *mut _); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ trying to acquire already locked default mutex + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ trying to acquire default mutex already locked by the current thread | = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information = note: BACKTRACE: - = note: inside `main` at tests/fail-dep/concurrency/libc_pthread_mutex_NULL_deadlock.rs:LL:CC + = note: inside `main` at tests/fail-dep/concurrency/libc_pthread_mutex_NULL_reentrant.rs:LL:CC note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace diff --git a/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutex_default_deadlock.rs b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutex_default_reentrant.rs similarity index 52% rename from src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutex_default_deadlock.rs rename to src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutex_default_reentrant.rs index d9293f938b6aa..d2d0ffff07a92 100644 --- a/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutex_default_deadlock.rs +++ b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutex_default_reentrant.rs @@ -1,6 +1,11 @@ //@ignore-target: windows # No pthreads on Windows // -// Check that if we do not set the mutex type, it is the default. +// Check that if we do not set the mutex type, it is UB to do reentrant locking. glibc apparently +// actually exploits this, see +// : +// one must actively call pthread_mutexattr_settype to disable lock elision. This means a call to +// pthread_mutexattr_settype(PTHREAD_MUTEX_NORMAL) makes a difference even if +// PTHREAD_MUTEX_NORMAL == PTHREAD_MUTEX_DEFAULT! fn main() { unsafe { @@ -9,6 +14,6 @@ fn main() { let mut mutex: libc::pthread_mutex_t = std::mem::zeroed(); assert_eq!(libc::pthread_mutex_init(&mut mutex as *mut _, &mutexattr as *const _), 0); assert_eq!(libc::pthread_mutex_lock(&mut mutex as *mut _), 0); - libc::pthread_mutex_lock(&mut mutex as *mut _); //~ ERROR: Undefined Behavior: trying to acquire already locked default mutex + libc::pthread_mutex_lock(&mut mutex as *mut _); //~ ERROR: already locked by the current thread } } diff --git a/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutex_default_deadlock.stderr b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutex_default_reentrant.stderr similarity index 68% rename from src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutex_default_deadlock.stderr rename to src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutex_default_reentrant.stderr index a57d10753d90d..a9ffbde1b65cf 100644 --- a/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutex_default_deadlock.stderr +++ b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutex_default_reentrant.stderr @@ -1,13 +1,13 @@ -error: Undefined Behavior: trying to acquire already locked default mutex - --> tests/fail-dep/concurrency/libc_pthread_mutex_default_deadlock.rs:LL:CC +error: Undefined Behavior: trying to acquire default mutex already locked by the current thread + --> tests/fail-dep/concurrency/libc_pthread_mutex_default_reentrant.rs:LL:CC | LL | libc::pthread_mutex_lock(&mut mutex as *mut _); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ trying to acquire already locked default mutex + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ trying to acquire default mutex already locked by the current thread | = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information = note: BACKTRACE: - = note: inside `main` at tests/fail-dep/concurrency/libc_pthread_mutex_default_deadlock.rs:LL:CC + = note: inside `main` at tests/fail-dep/concurrency/libc_pthread_mutex_default_reentrant.rs:LL:CC note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace diff --git a/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutex_normal_deadlock.rs b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutex_normal_reentrant.rs similarity index 81% rename from src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutex_normal_deadlock.rs rename to src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutex_normal_reentrant.rs index b38582482b88b..9a88639edf795 100644 --- a/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutex_normal_deadlock.rs +++ b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutex_normal_reentrant.rs @@ -10,6 +10,8 @@ fn main() { let mut mutex: libc::pthread_mutex_t = std::mem::zeroed(); assert_eq!(libc::pthread_mutex_init(&mut mutex as *mut _, &mutexattr as *const _), 0); assert_eq!(libc::pthread_mutex_lock(&mut mutex as *mut _), 0); + // A "normal" mutex properly tries to acquire the lock even if its is already held + // by the current thread -- and then we deadlock. libc::pthread_mutex_lock(&mut mutex as *mut _); //~ ERROR: deadlock: the evaluated program deadlocked } } diff --git a/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutex_normal_deadlock.stderr b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutex_normal_reentrant.stderr similarity index 79% rename from src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutex_normal_deadlock.stderr rename to src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutex_normal_reentrant.stderr index 4337475963e4a..f20b26297e274 100644 --- a/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutex_normal_deadlock.stderr +++ b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutex_normal_reentrant.stderr @@ -1,11 +1,11 @@ error: deadlock: the evaluated program deadlocked - --> tests/fail-dep/concurrency/libc_pthread_mutex_normal_deadlock.rs:LL:CC + --> tests/fail-dep/concurrency/libc_pthread_mutex_normal_reentrant.rs:LL:CC | LL | libc::pthread_mutex_lock(&mut mutex as *mut _); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the evaluated program deadlocked | = note: BACKTRACE: - = note: inside `main` at tests/fail-dep/concurrency/libc_pthread_mutex_normal_deadlock.rs:LL:CC + = note: inside `main` at tests/fail-dep/concurrency/libc_pthread_mutex_normal_reentrant.rs:LL:CC note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace diff --git a/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutex_staticinit_reentrant.rs b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutex_staticinit_reentrant.rs new file mode 100644 index 0000000000000..bd8aef787e6fb --- /dev/null +++ b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutex_staticinit_reentrant.rs @@ -0,0 +1,12 @@ +//@ignore-target: windows # No pthreads on Windows +// +// Check that if we use PTHREAD_MUTEX_INITIALIZER, then reentrant locking is UB. +// glibc apparently actually exploits this so we better catch it! + +fn main() { + unsafe { + let mut mutex: libc::pthread_mutex_t = libc::PTHREAD_MUTEX_INITIALIZER; + assert_eq!(libc::pthread_mutex_lock(&mut mutex as *mut _), 0); + libc::pthread_mutex_lock(&mut mutex as *mut _); //~ ERROR: already locked by the current thread + } +} diff --git a/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutex_staticinit_reentrant.stderr b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutex_staticinit_reentrant.stderr new file mode 100644 index 0000000000000..984bb07b72895 --- /dev/null +++ b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutex_staticinit_reentrant.stderr @@ -0,0 +1,15 @@ +error: Undefined Behavior: trying to acquire default mutex already locked by the current thread + --> tests/fail-dep/concurrency/libc_pthread_mutex_staticinit_reentrant.rs:LL:CC + | +LL | libc::pthread_mutex_lock(&mut mutex as *mut _); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ trying to acquire default mutex already locked by the current thread + | + = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior + = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information + = note: BACKTRACE: + = note: inside `main` at tests/fail-dep/concurrency/libc_pthread_mutex_staticinit_reentrant.rs:LL:CC + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to 1 previous error + From 98aa3d96e2d93eefa50374f1ea6057377bcec17b Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 5 Oct 2024 11:08:33 +0200 Subject: [PATCH 1900/2194] make Cell unstably const --- library/core/src/cell.rs | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/library/core/src/cell.rs b/library/core/src/cell.rs index 690d439513712..95cf55a923e2a 100644 --- a/library/core/src/cell.rs +++ b/library/core/src/cell.rs @@ -494,8 +494,9 @@ impl Cell { /// ``` #[inline] #[stable(feature = "move_cell", since = "1.17.0")] + #[rustc_const_unstable(feature = "const_cell", issue = "131283")] #[rustc_confusables("swap")] - pub fn replace(&self, val: T) -> T { + pub const fn replace(&self, val: T) -> T { // SAFETY: This can cause data races if called from a separate thread, // but `Cell` is `!Sync` so this won't happen. mem::replace(unsafe { &mut *self.value.get() }, val) @@ -535,7 +536,8 @@ impl Cell { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] - pub fn get(&self) -> T { + #[rustc_const_unstable(feature = "const_cell", issue = "131283")] + pub const fn get(&self) -> T { // SAFETY: This can cause data races if called from a separate thread, // but `Cell` is `!Sync` so this won't happen. unsafe { *self.value.get() } @@ -613,7 +615,8 @@ impl Cell { /// ``` #[inline] #[stable(feature = "cell_get_mut", since = "1.11.0")] - pub fn get_mut(&mut self) -> &mut T { + #[rustc_const_unstable(feature = "const_cell", issue = "131283")] + pub const fn get_mut(&mut self) -> &mut T { self.value.get_mut() } @@ -632,7 +635,8 @@ impl Cell { /// ``` #[inline] #[stable(feature = "as_cell", since = "1.37.0")] - pub fn from_mut(t: &mut T) -> &Cell { + #[rustc_const_unstable(feature = "const_cell", issue = "131283")] + pub const fn from_mut(t: &mut T) -> &Cell { // SAFETY: `&mut` ensures unique access. unsafe { &*(t as *mut T as *const Cell) } } @@ -686,7 +690,8 @@ impl Cell<[T]> { /// assert_eq!(slice_cell.len(), 3); /// ``` #[stable(feature = "as_cell", since = "1.37.0")] - pub fn as_slice_of_cells(&self) -> &[Cell] { + #[rustc_const_unstable(feature = "const_cell", issue = "131283")] + pub const fn as_slice_of_cells(&self) -> &[Cell] { // SAFETY: `Cell` has the same memory layout as `T`. unsafe { &*(self as *const Cell<[T]> as *const [Cell]) } } @@ -706,7 +711,8 @@ impl Cell<[T; N]> { /// let array_cell: &[Cell; 3] = cell_array.as_array_of_cells(); /// ``` #[unstable(feature = "as_array_of_cells", issue = "88248")] - pub fn as_array_of_cells(&self) -> &[Cell; N] { + #[rustc_const_unstable(feature = "as_array_of_cells", issue = "88248")] + pub const fn as_array_of_cells(&self) -> &[Cell; N] { // SAFETY: `Cell` has the same memory layout as `T`. unsafe { &*(self as *const Cell<[T; N]> as *const [Cell; N]) } } From b22b348e0d0334c42521aed90955cb39bd0d278c Mon Sep 17 00:00:00 2001 From: Henri Lunnikivi Date: Thu, 19 Sep 2024 13:14:52 +0300 Subject: [PATCH 1901/2194] Add targets: riscv32{e|em|emc} - Based on riscv32{i|im|imc} - Set data_layout stack alignment: S32 (bits) - Set llvm_abiname = ilp32e --- compiler/rustc_target/src/spec/mod.rs | 4 +++ .../spec/targets/riscv32e_unknown_none_elf.rs | 25 +++++++++++++++++++ .../targets/riscv32em_unknown_none_elf.rs | 25 +++++++++++++++++++ .../targets/riscv32emc_unknown_none_elf.rs | 25 +++++++++++++++++++ 4 files changed, 79 insertions(+) create mode 100644 compiler/rustc_target/src/spec/targets/riscv32e_unknown_none_elf.rs create mode 100644 compiler/rustc_target/src/spec/targets/riscv32em_unknown_none_elf.rs create mode 100644 compiler/rustc_target/src/spec/targets/riscv32emc_unknown_none_elf.rs diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index 18ec8ee9476b4..82e11a3afce32 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -1841,6 +1841,10 @@ supported_targets! { ("riscv32imac-esp-espidf", riscv32imac_esp_espidf), ("riscv32imafc-esp-espidf", riscv32imafc_esp_espidf), + ("riscv32e-unknown-none-elf", riscv32e_unknown_none_elf), + ("riscv32em-unknown-none-elf", riscv32em_unknown_none_elf), + ("riscv32emc-unknown-none-elf", riscv32emc_unknown_none_elf), + ("riscv32imac-unknown-none-elf", riscv32imac_unknown_none_elf), ("riscv32imafc-unknown-none-elf", riscv32imafc_unknown_none_elf), ("riscv32imac-unknown-xous-elf", riscv32imac_unknown_xous_elf), diff --git a/compiler/rustc_target/src/spec/targets/riscv32e_unknown_none_elf.rs b/compiler/rustc_target/src/spec/targets/riscv32e_unknown_none_elf.rs new file mode 100644 index 0000000000000..71a5607f927a4 --- /dev/null +++ b/compiler/rustc_target/src/spec/targets/riscv32e_unknown_none_elf.rs @@ -0,0 +1,25 @@ +use crate::spec::{Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, TargetOptions}; + +pub fn target() -> Target { + Target { + data_layout: "e-m:e-p:32:32-i64:64-n32-S32".into(), + llvm_target: "riscv32".into(), + pointer_width: 32, + arch: "riscv32".into(), + + options: TargetOptions { + linker_flavor: LinkerFlavor::Gnu(Cc::No, Lld::Yes), + linker: Some("rust-lld".into()), + cpu: "generic-rv32".into(), + llvm_abiname: "ilp32e".into(), + max_atomic_width: Some(32), + atomic_cas: false, + features: "+e,+forced-atomics".into(), + panic_strategy: PanicStrategy::Abort, + relocation_model: RelocModel::Static, + emit_debug_gdb_scripts: false, + eh_frame_header: false, + ..Default::default() + }, + } +} diff --git a/compiler/rustc_target/src/spec/targets/riscv32em_unknown_none_elf.rs b/compiler/rustc_target/src/spec/targets/riscv32em_unknown_none_elf.rs new file mode 100644 index 0000000000000..ed7a006963d0d --- /dev/null +++ b/compiler/rustc_target/src/spec/targets/riscv32em_unknown_none_elf.rs @@ -0,0 +1,25 @@ +use crate::spec::{Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, TargetOptions}; + +pub fn target() -> Target { + Target { + data_layout: "e-m:e-p:32:32-i64:64-n32-S32".into(), + llvm_target: "riscv32".into(), + pointer_width: 32, + arch: "riscv32".into(), + + options: TargetOptions { + linker_flavor: LinkerFlavor::Gnu(Cc::No, Lld::Yes), + linker: Some("rust-lld".into()), + cpu: "generic-rv32".into(), + llvm_abiname: "ilp32e".into(), + max_atomic_width: Some(32), + atomic_cas: false, + features: "+e,+m,+forced-atomics".into(), + panic_strategy: PanicStrategy::Abort, + relocation_model: RelocModel::Static, + emit_debug_gdb_scripts: false, + eh_frame_header: false, + ..Default::default() + }, + } +} diff --git a/compiler/rustc_target/src/spec/targets/riscv32emc_unknown_none_elf.rs b/compiler/rustc_target/src/spec/targets/riscv32emc_unknown_none_elf.rs new file mode 100644 index 0000000000000..cba19c28be3b7 --- /dev/null +++ b/compiler/rustc_target/src/spec/targets/riscv32emc_unknown_none_elf.rs @@ -0,0 +1,25 @@ +use crate::spec::{Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, TargetOptions}; + +pub fn target() -> Target { + Target { + data_layout: "e-m:e-p:32:32-i64:64-n32-S32".into(), + llvm_target: "riscv32".into(), + pointer_width: 32, + arch: "riscv32".into(), + + options: TargetOptions { + linker_flavor: LinkerFlavor::Gnu(Cc::No, Lld::Yes), + linker: Some("rust-lld".into()), + cpu: "generic-rv32".into(), + llvm_abiname: "ilp32e".into(), + max_atomic_width: Some(32), + atomic_cas: false, + features: "+e,+m,+c,+forced-atomics".into(), + panic_strategy: PanicStrategy::Abort, + relocation_model: RelocModel::Static, + emit_debug_gdb_scripts: false, + eh_frame_header: false, + ..Default::default() + }, + } +} From 7a0bac49c8bbdd06869aad64d2ea25e41b24cb9d Mon Sep 17 00:00:00 2001 From: Henri Lunnikivi Date: Fri, 4 Oct 2024 19:18:25 +0300 Subject: [PATCH 1902/2194] Add comment: data_layout --- .../rustc_target/src/spec/targets/riscv32e_unknown_none_elf.rs | 3 +++ .../src/spec/targets/riscv32em_unknown_none_elf.rs | 3 +++ .../src/spec/targets/riscv32emc_unknown_none_elf.rs | 3 +++ 3 files changed, 9 insertions(+) diff --git a/compiler/rustc_target/src/spec/targets/riscv32e_unknown_none_elf.rs b/compiler/rustc_target/src/spec/targets/riscv32e_unknown_none_elf.rs index 71a5607f927a4..9aeb591cb5790 100644 --- a/compiler/rustc_target/src/spec/targets/riscv32e_unknown_none_elf.rs +++ b/compiler/rustc_target/src/spec/targets/riscv32e_unknown_none_elf.rs @@ -2,6 +2,8 @@ use crate::spec::{Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, Targ pub fn target() -> Target { Target { + // The below `data_layout` is explicitly specified by the ilp32e ABI in LLVM. See also + // `options.llvm_abiname`. data_layout: "e-m:e-p:32:32-i64:64-n32-S32".into(), llvm_target: "riscv32".into(), pointer_width: 32, @@ -11,6 +13,7 @@ pub fn target() -> Target { linker_flavor: LinkerFlavor::Gnu(Cc::No, Lld::Yes), linker: Some("rust-lld".into()), cpu: "generic-rv32".into(), + // The ilp32e ABI specifies the `data_layout` llvm_abiname: "ilp32e".into(), max_atomic_width: Some(32), atomic_cas: false, diff --git a/compiler/rustc_target/src/spec/targets/riscv32em_unknown_none_elf.rs b/compiler/rustc_target/src/spec/targets/riscv32em_unknown_none_elf.rs index ed7a006963d0d..07b1a0228a2ad 100644 --- a/compiler/rustc_target/src/spec/targets/riscv32em_unknown_none_elf.rs +++ b/compiler/rustc_target/src/spec/targets/riscv32em_unknown_none_elf.rs @@ -2,6 +2,8 @@ use crate::spec::{Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, Targ pub fn target() -> Target { Target { + // The below `data_layout` is explicitly specified by the ilp32e ABI in LLVM. See also + // `options.llvm_abiname`. data_layout: "e-m:e-p:32:32-i64:64-n32-S32".into(), llvm_target: "riscv32".into(), pointer_width: 32, @@ -11,6 +13,7 @@ pub fn target() -> Target { linker_flavor: LinkerFlavor::Gnu(Cc::No, Lld::Yes), linker: Some("rust-lld".into()), cpu: "generic-rv32".into(), + // The ilp32e ABI specifies the `data_layout` llvm_abiname: "ilp32e".into(), max_atomic_width: Some(32), atomic_cas: false, diff --git a/compiler/rustc_target/src/spec/targets/riscv32emc_unknown_none_elf.rs b/compiler/rustc_target/src/spec/targets/riscv32emc_unknown_none_elf.rs index cba19c28be3b7..18da14a00d439 100644 --- a/compiler/rustc_target/src/spec/targets/riscv32emc_unknown_none_elf.rs +++ b/compiler/rustc_target/src/spec/targets/riscv32emc_unknown_none_elf.rs @@ -2,6 +2,8 @@ use crate::spec::{Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, Targ pub fn target() -> Target { Target { + // The below `data_layout` is explicitly specified by the ilp32e ABI in LLVM. See also + // `options.llvm_abiname`. data_layout: "e-m:e-p:32:32-i64:64-n32-S32".into(), llvm_target: "riscv32".into(), pointer_width: 32, @@ -11,6 +13,7 @@ pub fn target() -> Target { linker_flavor: LinkerFlavor::Gnu(Cc::No, Lld::Yes), linker: Some("rust-lld".into()), cpu: "generic-rv32".into(), + // The ilp32e ABI specifies the `data_layout` llvm_abiname: "ilp32e".into(), max_atomic_width: Some(32), atomic_cas: false, From 04099b663c1ee252be058f27147d2e6cfec9ec5f Mon Sep 17 00:00:00 2001 From: Henri Lunnikivi Date: Thu, 19 Sep 2024 13:24:21 +0300 Subject: [PATCH 1903/2194] Update target fns to latest main --- .../src/spec/targets/riscv32e_unknown_none_elf.rs | 8 +++++++- .../src/spec/targets/riscv32em_unknown_none_elf.rs | 8 +++++++- .../src/spec/targets/riscv32emc_unknown_none_elf.rs | 8 +++++++- 3 files changed, 21 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_target/src/spec/targets/riscv32e_unknown_none_elf.rs b/compiler/rustc_target/src/spec/targets/riscv32e_unknown_none_elf.rs index 9aeb591cb5790..b1f52973c107f 100644 --- a/compiler/rustc_target/src/spec/targets/riscv32e_unknown_none_elf.rs +++ b/compiler/rustc_target/src/spec/targets/riscv32e_unknown_none_elf.rs @@ -1,11 +1,17 @@ use crate::spec::{Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, TargetOptions}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { Target { // The below `data_layout` is explicitly specified by the ilp32e ABI in LLVM. See also // `options.llvm_abiname`. data_layout: "e-m:e-p:32:32-i64:64-n32-S32".into(), llvm_target: "riscv32".into(), + metadata: crate::spec::TargetMetadata { + description: Some("Bare RISC-V (RV32E ISA)".into()), + tier: Some(3), + host_tools: Some(false), + std: Some(false), + }, pointer_width: 32, arch: "riscv32".into(), diff --git a/compiler/rustc_target/src/spec/targets/riscv32em_unknown_none_elf.rs b/compiler/rustc_target/src/spec/targets/riscv32em_unknown_none_elf.rs index 07b1a0228a2ad..feeaa48778d43 100644 --- a/compiler/rustc_target/src/spec/targets/riscv32em_unknown_none_elf.rs +++ b/compiler/rustc_target/src/spec/targets/riscv32em_unknown_none_elf.rs @@ -1,11 +1,17 @@ use crate::spec::{Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, TargetOptions}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { Target { // The below `data_layout` is explicitly specified by the ilp32e ABI in LLVM. See also // `options.llvm_abiname`. data_layout: "e-m:e-p:32:32-i64:64-n32-S32".into(), llvm_target: "riscv32".into(), + metadata: crate::spec::TargetMetadata { + description: Some("Bare RISC-V (RV32EM ISA)".into()), + tier: Some(3), + host_tools: Some(false), + std: Some(false), + }, pointer_width: 32, arch: "riscv32".into(), diff --git a/compiler/rustc_target/src/spec/targets/riscv32emc_unknown_none_elf.rs b/compiler/rustc_target/src/spec/targets/riscv32emc_unknown_none_elf.rs index 18da14a00d439..45d73c1323371 100644 --- a/compiler/rustc_target/src/spec/targets/riscv32emc_unknown_none_elf.rs +++ b/compiler/rustc_target/src/spec/targets/riscv32emc_unknown_none_elf.rs @@ -1,11 +1,17 @@ use crate::spec::{Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, TargetOptions}; -pub fn target() -> Target { +pub(crate) fn target() -> Target { Target { // The below `data_layout` is explicitly specified by the ilp32e ABI in LLVM. See also // `options.llvm_abiname`. data_layout: "e-m:e-p:32:32-i64:64-n32-S32".into(), llvm_target: "riscv32".into(), + metadata: crate::spec::TargetMetadata { + description: Some("Bare RISC-V (RV32EMC ISA)".into()), + tier: Some(3), + host_tools: Some(false), + std: Some(false), + }, pointer_width: 32, arch: "riscv32".into(), From f3037823de584ea94cf2b1c275d4c1dd8a769507 Mon Sep 17 00:00:00 2001 From: Henri Lunnikivi Date: Fri, 27 Sep 2024 22:01:44 +0300 Subject: [PATCH 1904/2194] doc: platform-support.md: Document port --- src/doc/rustc/src/platform-support.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md index 9d2efc0f6dee9..0ef95ba64a1f5 100644 --- a/src/doc/rustc/src/platform-support.md +++ b/src/doc/rustc/src/platform-support.md @@ -413,5 +413,8 @@ target | std | host | notes [`riscv32imafc-unknown-nuttx-elf`](platform-support/nuttx.md) | * | | RISC-V 32bit with NuttX [`riscv64imac-unknown-nuttx-elf`](platform-support/nuttx.md) | * | | RISC-V 64bit with NuttX [`riscv64gc-unknown-nuttx-elf`](platform-support/nuttx.md) | * | | RISC-V 64bit with NuttX +[`riscv32e-unknown-none-elf`](platform-support/riscv32-unknown-none-elf.md) | * | | Bare RISC-V (RV32E ISA) +[`riscv32em-unknown-none-elf`](platform-support/riscv32-unknown-none-elf.md) | * | | Bare RISC-V (RV32EM ISA) +[`riscv32emc-unknown-none-elf`](platform-support/riscv32-unknown-none-elf.md) | * | | Bare RISC-V (RV32EMC ISA) [runs on NVIDIA GPUs]: https://github.com/japaric-archived/nvptx#targets From 66b3d0b36ad48400e83ae2692799b42a252ae023 Mon Sep 17 00:00:00 2001 From: Henri Lunnikivi Date: Thu, 19 Sep 2024 13:54:11 +0300 Subject: [PATCH 1905/2194] Work around the stage0 sanity check Add rv32e-targets to 'stage0 missing targets'. This prevents the error "no such target exists in the target list". --- src/bootstrap/src/core/sanity.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/bootstrap/src/core/sanity.rs b/src/bootstrap/src/core/sanity.rs index 888ba8e2a3f75..11260f87d00f0 100644 --- a/src/bootstrap/src/core/sanity.rs +++ b/src/bootstrap/src/core/sanity.rs @@ -37,6 +37,9 @@ pub struct Finder { const STAGE0_MISSING_TARGETS: &[&str] = &[ // just a dummy comment so the list doesn't get onelined "armv7-rtems-eabihf", + "riscv32e-unknown-none-elf", + "riscv32em-unknown-none-elf", + "riscv32emc-unknown-none-elf", ]; /// Minimum version threshold for libstdc++ required when using prebuilt LLVM From fe658e1fe4d44e2eeeffc079acd7481b2d67b7d9 Mon Sep 17 00:00:00 2001 From: Henri Lunnikivi Date: Thu, 19 Sep 2024 16:43:33 +0300 Subject: [PATCH 1906/2194] Add assembly tests to satisfy 'tidy' --- tests/assembly/targets/targets-elf.rs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/tests/assembly/targets/targets-elf.rs b/tests/assembly/targets/targets-elf.rs index e08e6a8b17458..f26d06a0ecb87 100644 --- a/tests/assembly/targets/targets-elf.rs +++ b/tests/assembly/targets/targets-elf.rs @@ -375,6 +375,15 @@ //@ revisions: riscv32_wrs_vxworks //@ [riscv32_wrs_vxworks] compile-flags: --target riscv32-wrs-vxworks //@ [riscv32_wrs_vxworks] needs-llvm-components: riscv +//@ revisions: riscv32e_unknown_none_elf +//@ [riscv32e_unknown_none_elf] compile-flags: --target riscv32e-unknown-none-elf +//@ [riscv32e_unknown_none_elf] needs-llvm-components: riscv +//@ revisions: riscv32em_unknown_none_elf +//@ [riscv32em_unknown_none_elf] compile-flags: --target riscv32em-unknown-none-elf +//@ [riscv32em_unknown_none_elf] needs-llvm-components: riscv +//@ revisions: riscv32emc_unknown_none_elf +//@ [riscv32emc_unknown_none_elf] compile-flags: --target riscv32emc-unknown-none-elf +//@ [riscv32emc_unknown_none_elf] needs-llvm-components: riscv //@ revisions: riscv32gc_unknown_linux_gnu //@ [riscv32gc_unknown_linux_gnu] compile-flags: --target riscv32gc-unknown-linux-gnu //@ [riscv32gc_unknown_linux_gnu] needs-llvm-components: riscv From 346afc7017fc9b4475fbbe8984f41d7467c6065a Mon Sep 17 00:00:00 2001 From: Henri Lunnikivi Date: Fri, 4 Oct 2024 18:20:53 +0300 Subject: [PATCH 1907/2194] Add UI test to verify invalid loads are not generated --- .../ui/abi/riscv32e-registers.riscv32e.stderr | 194 ++++++++++++++++++ .../abi/riscv32e-registers.riscv32em.stderr | 194 ++++++++++++++++++ .../abi/riscv32e-registers.riscv32emc.stderr | 194 ++++++++++++++++++ tests/ui/abi/riscv32e-registers.rs | 91 ++++++++ 4 files changed, 673 insertions(+) create mode 100644 tests/ui/abi/riscv32e-registers.riscv32e.stderr create mode 100644 tests/ui/abi/riscv32e-registers.riscv32em.stderr create mode 100644 tests/ui/abi/riscv32e-registers.riscv32emc.stderr create mode 100644 tests/ui/abi/riscv32e-registers.rs diff --git a/tests/ui/abi/riscv32e-registers.riscv32e.stderr b/tests/ui/abi/riscv32e-registers.riscv32e.stderr new file mode 100644 index 0000000000000..e3894431eb44d --- /dev/null +++ b/tests/ui/abi/riscv32e-registers.riscv32e.stderr @@ -0,0 +1,194 @@ +error: invalid operand for instruction + --> $DIR/riscv32e-registers.rs:43:11 + | +LL | asm!("li x16, 0"); + | ^ + | +note: instantiated into assembly here + --> :1:5 + | +LL | li x16, 0 + | ^ + +error: invalid operand for instruction + --> $DIR/riscv32e-registers.rs:46:11 + | +LL | asm!("li x17, 0"); + | ^ + | +note: instantiated into assembly here + --> :1:5 + | +LL | li x17, 0 + | ^ + +error: invalid operand for instruction + --> $DIR/riscv32e-registers.rs:49:11 + | +LL | asm!("li x18, 0"); + | ^ + | +note: instantiated into assembly here + --> :1:5 + | +LL | li x18, 0 + | ^ + +error: invalid operand for instruction + --> $DIR/riscv32e-registers.rs:52:11 + | +LL | asm!("li x19, 0"); + | ^ + | +note: instantiated into assembly here + --> :1:5 + | +LL | li x19, 0 + | ^ + +error: invalid operand for instruction + --> $DIR/riscv32e-registers.rs:55:11 + | +LL | asm!("li x20, 0"); + | ^ + | +note: instantiated into assembly here + --> :1:5 + | +LL | li x20, 0 + | ^ + +error: invalid operand for instruction + --> $DIR/riscv32e-registers.rs:58:11 + | +LL | asm!("li x21, 0"); + | ^ + | +note: instantiated into assembly here + --> :1:5 + | +LL | li x21, 0 + | ^ + +error: invalid operand for instruction + --> $DIR/riscv32e-registers.rs:61:11 + | +LL | asm!("li x22, 0"); + | ^ + | +note: instantiated into assembly here + --> :1:5 + | +LL | li x22, 0 + | ^ + +error: invalid operand for instruction + --> $DIR/riscv32e-registers.rs:64:11 + | +LL | asm!("li x23, 0"); + | ^ + | +note: instantiated into assembly here + --> :1:5 + | +LL | li x23, 0 + | ^ + +error: invalid operand for instruction + --> $DIR/riscv32e-registers.rs:67:11 + | +LL | asm!("li x24, 0"); + | ^ + | +note: instantiated into assembly here + --> :1:5 + | +LL | li x24, 0 + | ^ + +error: invalid operand for instruction + --> $DIR/riscv32e-registers.rs:70:11 + | +LL | asm!("li x25, 0"); + | ^ + | +note: instantiated into assembly here + --> :1:5 + | +LL | li x25, 0 + | ^ + +error: invalid operand for instruction + --> $DIR/riscv32e-registers.rs:73:11 + | +LL | asm!("li x26, 0"); + | ^ + | +note: instantiated into assembly here + --> :1:5 + | +LL | li x26, 0 + | ^ + +error: invalid operand for instruction + --> $DIR/riscv32e-registers.rs:76:11 + | +LL | asm!("li x27, 0"); + | ^ + | +note: instantiated into assembly here + --> :1:5 + | +LL | li x27, 0 + | ^ + +error: invalid operand for instruction + --> $DIR/riscv32e-registers.rs:79:11 + | +LL | asm!("li x28, 0"); + | ^ + | +note: instantiated into assembly here + --> :1:5 + | +LL | li x28, 0 + | ^ + +error: invalid operand for instruction + --> $DIR/riscv32e-registers.rs:82:11 + | +LL | asm!("li x29, 0"); + | ^ + | +note: instantiated into assembly here + --> :1:5 + | +LL | li x29, 0 + | ^ + +error: invalid operand for instruction + --> $DIR/riscv32e-registers.rs:85:11 + | +LL | asm!("li x30, 0"); + | ^ + | +note: instantiated into assembly here + --> :1:5 + | +LL | li x30, 0 + | ^ + +error: invalid operand for instruction + --> $DIR/riscv32e-registers.rs:88:11 + | +LL | asm!("li x31, 0"); + | ^ + | +note: instantiated into assembly here + --> :1:5 + | +LL | li x31, 0 + | ^ + +error: aborting due to 16 previous errors + diff --git a/tests/ui/abi/riscv32e-registers.riscv32em.stderr b/tests/ui/abi/riscv32e-registers.riscv32em.stderr new file mode 100644 index 0000000000000..e3894431eb44d --- /dev/null +++ b/tests/ui/abi/riscv32e-registers.riscv32em.stderr @@ -0,0 +1,194 @@ +error: invalid operand for instruction + --> $DIR/riscv32e-registers.rs:43:11 + | +LL | asm!("li x16, 0"); + | ^ + | +note: instantiated into assembly here + --> :1:5 + | +LL | li x16, 0 + | ^ + +error: invalid operand for instruction + --> $DIR/riscv32e-registers.rs:46:11 + | +LL | asm!("li x17, 0"); + | ^ + | +note: instantiated into assembly here + --> :1:5 + | +LL | li x17, 0 + | ^ + +error: invalid operand for instruction + --> $DIR/riscv32e-registers.rs:49:11 + | +LL | asm!("li x18, 0"); + | ^ + | +note: instantiated into assembly here + --> :1:5 + | +LL | li x18, 0 + | ^ + +error: invalid operand for instruction + --> $DIR/riscv32e-registers.rs:52:11 + | +LL | asm!("li x19, 0"); + | ^ + | +note: instantiated into assembly here + --> :1:5 + | +LL | li x19, 0 + | ^ + +error: invalid operand for instruction + --> $DIR/riscv32e-registers.rs:55:11 + | +LL | asm!("li x20, 0"); + | ^ + | +note: instantiated into assembly here + --> :1:5 + | +LL | li x20, 0 + | ^ + +error: invalid operand for instruction + --> $DIR/riscv32e-registers.rs:58:11 + | +LL | asm!("li x21, 0"); + | ^ + | +note: instantiated into assembly here + --> :1:5 + | +LL | li x21, 0 + | ^ + +error: invalid operand for instruction + --> $DIR/riscv32e-registers.rs:61:11 + | +LL | asm!("li x22, 0"); + | ^ + | +note: instantiated into assembly here + --> :1:5 + | +LL | li x22, 0 + | ^ + +error: invalid operand for instruction + --> $DIR/riscv32e-registers.rs:64:11 + | +LL | asm!("li x23, 0"); + | ^ + | +note: instantiated into assembly here + --> :1:5 + | +LL | li x23, 0 + | ^ + +error: invalid operand for instruction + --> $DIR/riscv32e-registers.rs:67:11 + | +LL | asm!("li x24, 0"); + | ^ + | +note: instantiated into assembly here + --> :1:5 + | +LL | li x24, 0 + | ^ + +error: invalid operand for instruction + --> $DIR/riscv32e-registers.rs:70:11 + | +LL | asm!("li x25, 0"); + | ^ + | +note: instantiated into assembly here + --> :1:5 + | +LL | li x25, 0 + | ^ + +error: invalid operand for instruction + --> $DIR/riscv32e-registers.rs:73:11 + | +LL | asm!("li x26, 0"); + | ^ + | +note: instantiated into assembly here + --> :1:5 + | +LL | li x26, 0 + | ^ + +error: invalid operand for instruction + --> $DIR/riscv32e-registers.rs:76:11 + | +LL | asm!("li x27, 0"); + | ^ + | +note: instantiated into assembly here + --> :1:5 + | +LL | li x27, 0 + | ^ + +error: invalid operand for instruction + --> $DIR/riscv32e-registers.rs:79:11 + | +LL | asm!("li x28, 0"); + | ^ + | +note: instantiated into assembly here + --> :1:5 + | +LL | li x28, 0 + | ^ + +error: invalid operand for instruction + --> $DIR/riscv32e-registers.rs:82:11 + | +LL | asm!("li x29, 0"); + | ^ + | +note: instantiated into assembly here + --> :1:5 + | +LL | li x29, 0 + | ^ + +error: invalid operand for instruction + --> $DIR/riscv32e-registers.rs:85:11 + | +LL | asm!("li x30, 0"); + | ^ + | +note: instantiated into assembly here + --> :1:5 + | +LL | li x30, 0 + | ^ + +error: invalid operand for instruction + --> $DIR/riscv32e-registers.rs:88:11 + | +LL | asm!("li x31, 0"); + | ^ + | +note: instantiated into assembly here + --> :1:5 + | +LL | li x31, 0 + | ^ + +error: aborting due to 16 previous errors + diff --git a/tests/ui/abi/riscv32e-registers.riscv32emc.stderr b/tests/ui/abi/riscv32e-registers.riscv32emc.stderr new file mode 100644 index 0000000000000..e3894431eb44d --- /dev/null +++ b/tests/ui/abi/riscv32e-registers.riscv32emc.stderr @@ -0,0 +1,194 @@ +error: invalid operand for instruction + --> $DIR/riscv32e-registers.rs:43:11 + | +LL | asm!("li x16, 0"); + | ^ + | +note: instantiated into assembly here + --> :1:5 + | +LL | li x16, 0 + | ^ + +error: invalid operand for instruction + --> $DIR/riscv32e-registers.rs:46:11 + | +LL | asm!("li x17, 0"); + | ^ + | +note: instantiated into assembly here + --> :1:5 + | +LL | li x17, 0 + | ^ + +error: invalid operand for instruction + --> $DIR/riscv32e-registers.rs:49:11 + | +LL | asm!("li x18, 0"); + | ^ + | +note: instantiated into assembly here + --> :1:5 + | +LL | li x18, 0 + | ^ + +error: invalid operand for instruction + --> $DIR/riscv32e-registers.rs:52:11 + | +LL | asm!("li x19, 0"); + | ^ + | +note: instantiated into assembly here + --> :1:5 + | +LL | li x19, 0 + | ^ + +error: invalid operand for instruction + --> $DIR/riscv32e-registers.rs:55:11 + | +LL | asm!("li x20, 0"); + | ^ + | +note: instantiated into assembly here + --> :1:5 + | +LL | li x20, 0 + | ^ + +error: invalid operand for instruction + --> $DIR/riscv32e-registers.rs:58:11 + | +LL | asm!("li x21, 0"); + | ^ + | +note: instantiated into assembly here + --> :1:5 + | +LL | li x21, 0 + | ^ + +error: invalid operand for instruction + --> $DIR/riscv32e-registers.rs:61:11 + | +LL | asm!("li x22, 0"); + | ^ + | +note: instantiated into assembly here + --> :1:5 + | +LL | li x22, 0 + | ^ + +error: invalid operand for instruction + --> $DIR/riscv32e-registers.rs:64:11 + | +LL | asm!("li x23, 0"); + | ^ + | +note: instantiated into assembly here + --> :1:5 + | +LL | li x23, 0 + | ^ + +error: invalid operand for instruction + --> $DIR/riscv32e-registers.rs:67:11 + | +LL | asm!("li x24, 0"); + | ^ + | +note: instantiated into assembly here + --> :1:5 + | +LL | li x24, 0 + | ^ + +error: invalid operand for instruction + --> $DIR/riscv32e-registers.rs:70:11 + | +LL | asm!("li x25, 0"); + | ^ + | +note: instantiated into assembly here + --> :1:5 + | +LL | li x25, 0 + | ^ + +error: invalid operand for instruction + --> $DIR/riscv32e-registers.rs:73:11 + | +LL | asm!("li x26, 0"); + | ^ + | +note: instantiated into assembly here + --> :1:5 + | +LL | li x26, 0 + | ^ + +error: invalid operand for instruction + --> $DIR/riscv32e-registers.rs:76:11 + | +LL | asm!("li x27, 0"); + | ^ + | +note: instantiated into assembly here + --> :1:5 + | +LL | li x27, 0 + | ^ + +error: invalid operand for instruction + --> $DIR/riscv32e-registers.rs:79:11 + | +LL | asm!("li x28, 0"); + | ^ + | +note: instantiated into assembly here + --> :1:5 + | +LL | li x28, 0 + | ^ + +error: invalid operand for instruction + --> $DIR/riscv32e-registers.rs:82:11 + | +LL | asm!("li x29, 0"); + | ^ + | +note: instantiated into assembly here + --> :1:5 + | +LL | li x29, 0 + | ^ + +error: invalid operand for instruction + --> $DIR/riscv32e-registers.rs:85:11 + | +LL | asm!("li x30, 0"); + | ^ + | +note: instantiated into assembly here + --> :1:5 + | +LL | li x30, 0 + | ^ + +error: invalid operand for instruction + --> $DIR/riscv32e-registers.rs:88:11 + | +LL | asm!("li x31, 0"); + | ^ + | +note: instantiated into assembly here + --> :1:5 + | +LL | li x31, 0 + | ^ + +error: aborting due to 16 previous errors + diff --git a/tests/ui/abi/riscv32e-registers.rs b/tests/ui/abi/riscv32e-registers.rs new file mode 100644 index 0000000000000..714b0ee4633c9 --- /dev/null +++ b/tests/ui/abi/riscv32e-registers.rs @@ -0,0 +1,91 @@ +// Test that loads into registers x16..=x31 are never generated for riscv32{e,em,emc} targets +// +//@ build-fail +//@ revisions: riscv32e riscv32em riscv32emc +// +//@ compile-flags: --crate-type=rlib +//@ [riscv32e] needs-llvm-components: riscv +//@ [riscv32e] compile-flags: --target=riscv32e-unknown-none-elf +//@ [riscv32em] needs-llvm-components: riscv +//@ [riscv32em] compile-flags: --target=riscv32em-unknown-none-elf +//@ [riscv32emc] needs-llvm-components: riscv +//@ [riscv32emc] compile-flags: --target=riscv32emc-unknown-none-elf + +#![no_core] +#![feature(no_core, lang_items, rustc_attrs)] + +#[rustc_builtin_macro] +macro_rules! asm { + () => {}; +} + +#[lang = "sized"] +trait Sized {} + +// Verify registers x1..=x15 are addressable on riscv32e, but registers x16..=x31 are not +#[no_mangle] +pub unsafe fn registers() { + asm!("li x1, 0"); + asm!("li x2, 0"); + asm!("li x3, 0"); + asm!("li x4, 0"); + asm!("li x5, 0"); + asm!("li x6, 0"); + asm!("li x7, 0"); + asm!("li x8, 0"); + asm!("li x9, 0"); + asm!("li x10, 0"); + asm!("li x11, 0"); + asm!("li x12, 0"); + asm!("li x13, 0"); + asm!("li x14, 0"); + asm!("li x15, 0"); + asm!("li x16, 0"); + //~^ ERROR invalid operand for instruction + //~| NOTE instantiated into assembly here + asm!("li x17, 0"); + //~^ ERROR invalid operand for instruction + //~| NOTE instantiated into assembly here + asm!("li x18, 0"); + //~^ ERROR invalid operand for instruction + //~| NOTE instantiated into assembly here + asm!("li x19, 0"); + //~^ ERROR invalid operand for instruction + //~| NOTE instantiated into assembly here + asm!("li x20, 0"); + //~^ ERROR invalid operand for instruction + //~| NOTE instantiated into assembly here + asm!("li x21, 0"); + //~^ ERROR invalid operand for instruction + //~| NOTE instantiated into assembly here + asm!("li x22, 0"); + //~^ ERROR invalid operand for instruction + //~| NOTE instantiated into assembly here + asm!("li x23, 0"); + //~^ ERROR invalid operand for instruction + //~| NOTE instantiated into assembly here + asm!("li x24, 0"); + //~^ ERROR invalid operand for instruction + //~| NOTE instantiated into assembly here + asm!("li x25, 0"); + //~^ ERROR invalid operand for instruction + //~| NOTE instantiated into assembly here + asm!("li x26, 0"); + //~^ ERROR invalid operand for instruction + //~| NOTE instantiated into assembly here + asm!("li x27, 0"); + //~^ ERROR invalid operand for instruction + //~| NOTE instantiated into assembly here + asm!("li x28, 0"); + //~^ ERROR invalid operand for instruction + //~| NOTE instantiated into assembly here + asm!("li x29, 0"); + //~^ ERROR invalid operand for instruction + //~| NOTE instantiated into assembly here + asm!("li x30, 0"); + //~^ ERROR invalid operand for instruction + //~| NOTE instantiated into assembly here + asm!("li x31, 0"); + //~^ ERROR invalid operand for instruction + //~| NOTE instantiated into assembly here +} From 6edd0b356fac7585b27b14b4b9e6cd2b29537726 Mon Sep 17 00:00:00 2001 From: Henri Lunnikivi Date: Fri, 4 Oct 2024 20:58:39 +0300 Subject: [PATCH 1908/2194] Add platform support doc for rv32e --- .../riscv32-unknown-none-elf.md | 2 +- .../riscv32e-unknown-none-elf.md | 30 +++++++++++++++++++ 2 files changed, 31 insertions(+), 1 deletion(-) create mode 100644 src/doc/rustc/src/platform-support/riscv32e-unknown-none-elf.md diff --git a/src/doc/rustc/src/platform-support/riscv32-unknown-none-elf.md b/src/doc/rustc/src/platform-support/riscv32-unknown-none-elf.md index 9a27a568b5703..38742143c4ba2 100644 --- a/src/doc/rustc/src/platform-support/riscv32-unknown-none-elf.md +++ b/src/doc/rustc/src/platform-support/riscv32-unknown-none-elf.md @@ -35,4 +35,4 @@ Rust test-suite on this target. ## Cross-compilation toolchains and C code This target supports C code. If interlinking with C or C++, you may need to use -`riscv64-unknown-elf-gcc` as a linker instead of `rust-lld`. +`riscv32-unknown-elf-gcc` as a linker instead of `rust-lld`. diff --git a/src/doc/rustc/src/platform-support/riscv32e-unknown-none-elf.md b/src/doc/rustc/src/platform-support/riscv32e-unknown-none-elf.md new file mode 100644 index 0000000000000..69f08774f8381 --- /dev/null +++ b/src/doc/rustc/src/platform-support/riscv32e-unknown-none-elf.md @@ -0,0 +1,30 @@ +# `riscv32{e,em,emc}-unknown-none-elf` + +**Tier: 3** + +Bare-metal target for RISC-V CPUs with the RV32E, RV32EM and RV32EMC ISAs. + +## Target maintainers + +* Henri Lunnikivi, , [@hegza](https://github.com/hegza) + +## Requirements + +The target is cross-compiled, and uses static linking. No external toolchain is +required and the default `rust-lld` linker works, but you must specify a linker +script. + +## Building the target + +This target is included in Rust and can be installed via `rustup`. + +## Testing + +This is a cross-compiled `no-std` target, which must be run either in a +simulator or by programming them onto suitable hardware. It is not possible to +run the Rust test-suite on this target. + +## Cross-compilation toolchains and C code + +This target supports C code. If interlinking with C or C++, you may need to use +`riscv32-unknown-elf-gcc` as a linker instead of `rust-lld`. From f0ddc7b472a6ea84f2224364e2b71c688b7b285e Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 5 Oct 2024 12:19:14 +0200 Subject: [PATCH 1909/2194] clarify semantics of ConstantIndex MIR projection --- compiler/rustc_middle/src/mir/syntax.rs | 6 ++++-- compiler/stable_mir/src/mir/body.rs | 6 ++++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs index ae75f2d4187ba..1722a7a1f358f 100644 --- a/compiler/rustc_middle/src/mir/syntax.rs +++ b/compiler/rustc_middle/src/mir/syntax.rs @@ -1135,8 +1135,10 @@ pub enum ProjectionElem { ConstantIndex { /// index or -index (in Python terms), depending on from_end offset: u64, - /// The thing being indexed must be at least this long. For arrays this - /// is always the exact length. + /// The thing being indexed must be at least this long -- otherwise, the + /// projection is UB. + /// + /// For arrays this is always the exact length. min_length: u64, /// Counting backwards from end? This is always false when indexing an /// array. diff --git a/compiler/stable_mir/src/mir/body.rs b/compiler/stable_mir/src/mir/body.rs index 9f4db7e483335..742469a1c9325 100644 --- a/compiler/stable_mir/src/mir/body.rs +++ b/compiler/stable_mir/src/mir/body.rs @@ -768,8 +768,10 @@ pub enum ProjectionElem { ConstantIndex { /// index or -index (in Python terms), depending on from_end offset: u64, - /// The thing being indexed must be at least this long. For arrays this - /// is always the exact length. + /// The thing being indexed must be at least this long -- otherwise, the + /// projection is UB. + /// + /// For arrays this is always the exact length. min_length: u64, /// Counting backwards from end? This is always false when indexing an /// array. From ab8673501ce13573c06b5989b179f5cfed85c771 Mon Sep 17 00:00:00 2001 From: Veera Date: Sun, 22 Sep 2024 19:32:56 -0400 Subject: [PATCH 1910/2194] Add a Lint for Pointer to Integer Transmutes in Consts --- compiler/rustc_lint_defs/src/builtin.rs | 35 +++++++++ compiler/rustc_mir_transform/messages.ftl | 5 ++ .../src/check_undefined_transmutes.rs | 77 +++++++++++++++++++ compiler/rustc_mir_transform/src/errors.rs | 7 ++ compiler/rustc_mir_transform/src/lib.rs | 2 + library/core/src/ptr/mod.rs | 1 + .../transmutes_expressible_as_ptr_casts.fixed | 9 ++- .../ui/transmutes_expressible_as_ptr_casts.rs | 9 ++- ...-to-int-transmute-in-consts-issue-87525.rs | 22 +++--- ...int-transmute-in-consts-issue-87525.stderr | 43 ++++++++++- 10 files changed, 192 insertions(+), 18 deletions(-) create mode 100644 compiler/rustc_mir_transform/src/check_undefined_transmutes.rs diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index 25d33126754af..a618bd773011f 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs @@ -82,6 +82,7 @@ declare_lint_pass! { PRIVATE_INTERFACES, PROC_MACRO_DERIVE_RESOLUTION_FALLBACK, PTR_CAST_ADD_AUTO_TO_OBJECT, + PTR_TO_INTEGER_TRANSMUTE_IN_CONSTS, PUB_USE_OF_PRIVATE_EXTERN_CRATE, REDUNDANT_IMPORTS, REDUNDANT_LIFETIMES, @@ -5095,3 +5096,37 @@ declare_lint! { reference: "issue #124535 ", }; } + +declare_lint! { + /// The `ptr_to_integer_transmute_in_consts` lint detects pointer to integer + /// transmute in const functions and associated constants. + /// + /// ### Example + /// + /// ```rust + /// const fn foo(ptr: *const u8) -> usize { + /// unsafe { + /// std::mem::transmute::<*const u8, usize>(ptr) + /// } + /// } + /// ``` + /// + /// {{produces}} + /// + /// ### Explanation + /// + /// Transmuting pointers to integers in a `const` context is undefined behavior. + /// Any attempt to use the resulting integer will abort const-evaluation. + /// + /// But sometimes the compiler might not emit an error for pointer to integer transmutes + /// inside const functions and associated consts because they are evaluated only when referenced. + /// Therefore, this lint serves as an extra layer of defense to prevent any undefined behavior + /// from compiling without any warnings or errors. + /// + /// See [std::mem::transmute] in the reference for more details. + /// + /// [std::mem::transmute]: https://doc.rust-lang.org/std/mem/fn.transmute.html + pub PTR_TO_INTEGER_TRANSMUTE_IN_CONSTS, + Warn, + "detects pointer to integer transmutes in const functions and associated constants", +} diff --git a/compiler/rustc_mir_transform/messages.ftl b/compiler/rustc_mir_transform/messages.ftl index f9b79d72b0504..b81c090673476 100644 --- a/compiler/rustc_mir_transform/messages.ftl +++ b/compiler/rustc_mir_transform/messages.ftl @@ -27,3 +27,8 @@ mir_transform_unaligned_packed_ref = reference to packed field is unaligned .note = packed structs are only aligned by one byte, and many modern architectures penalize unaligned field accesses .note_ub = creating a misaligned reference is undefined behavior (even if that reference is never dereferenced) .help = copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers) + +mir_transform_undefined_transmute = pointers cannot be transmuted to integers during const eval + .note = at compile-time, pointers do not have an integer value + .note2 = avoiding this restriction via `union` or raw pointers leads to compile-time undefined behavior + .help = for more information, see https://doc.rust-lang.org/std/mem/fn.transmute.html diff --git a/compiler/rustc_mir_transform/src/check_undefined_transmutes.rs b/compiler/rustc_mir_transform/src/check_undefined_transmutes.rs new file mode 100644 index 0000000000000..8ba14a1158ef9 --- /dev/null +++ b/compiler/rustc_mir_transform/src/check_undefined_transmutes.rs @@ -0,0 +1,77 @@ +use rustc_middle::mir::visit::Visitor; +use rustc_middle::mir::{Body, Location, Operand, Terminator, TerminatorKind}; +use rustc_middle::ty::{AssocItem, AssocKind, TyCtxt}; +use rustc_session::lint::builtin::PTR_TO_INTEGER_TRANSMUTE_IN_CONSTS; +use rustc_span::sym; + +use crate::errors; + +/// Check for transmutes that exhibit undefined behavior. +/// For example, transmuting pointers to integers in a const context. +pub(super) struct CheckUndefinedTransmutes; + +impl<'tcx> crate::MirLint<'tcx> for CheckUndefinedTransmutes { + fn run_lint(&self, tcx: TyCtxt<'tcx>, body: &Body<'tcx>) { + let mut checker = UndefinedTransmutesChecker { body, tcx }; + checker.visit_body(body); + } +} + +struct UndefinedTransmutesChecker<'a, 'tcx> { + body: &'a Body<'tcx>, + tcx: TyCtxt<'tcx>, +} + +impl<'a, 'tcx> UndefinedTransmutesChecker<'a, 'tcx> { + // This functions checks two things: + // 1. `function` takes a raw pointer as input and returns an integer as output. + // 2. `function` is called from a const function or an associated constant. + // + // Why do we consider const functions and associated constants only? + // + // Generally, undefined behavior in const items are handled by the evaluator. + // But, const functions and associated constants are evaluated only when referenced. + // This can result in undefined behavior in a library going unnoticed until + // the function or constant is actually used. + // + // Therefore, we only consider const functions and associated constants here and leave + // other const items to be handled by the evaluator. + fn is_ptr_to_int_in_const(&self, function: &Operand<'tcx>) -> bool { + let def_id = self.body.source.def_id(); + + if self.tcx.is_const_fn(def_id) + || matches!( + self.tcx.opt_associated_item(def_id), + Some(AssocItem { kind: AssocKind::Const, .. }) + ) + { + let fn_sig = function.ty(self.body, self.tcx).fn_sig(self.tcx).skip_binder(); + if let [input] = fn_sig.inputs() { + return input.is_unsafe_ptr() && fn_sig.output().is_integral(); + } + } + false + } +} + +impl<'tcx> Visitor<'tcx> for UndefinedTransmutesChecker<'_, 'tcx> { + // Check each block's terminator for calls to pointer to integer transmutes + // in const functions or associated constants and emit a lint. + fn visit_terminator(&mut self, terminator: &Terminator<'tcx>, location: Location) { + if let TerminatorKind::Call { func, .. } = &terminator.kind + && let Some((func_def_id, _)) = func.const_fn_def() + && self.tcx.is_intrinsic(func_def_id, sym::transmute) + && self.is_ptr_to_int_in_const(func) + && let Some(call_id) = self.body.source.def_id().as_local() + { + let hir_id = self.tcx.local_def_id_to_hir_id(call_id); + let span = self.body.source_info(location).span; + self.tcx.emit_node_span_lint( + PTR_TO_INTEGER_TRANSMUTE_IN_CONSTS, + hir_id, + span, + errors::UndefinedTransmute, + ); + } + } +} diff --git a/compiler/rustc_mir_transform/src/errors.rs b/compiler/rustc_mir_transform/src/errors.rs index 9a93c3a72b1c9..e480537402da1 100644 --- a/compiler/rustc_mir_transform/src/errors.rs +++ b/compiler/rustc_mir_transform/src/errors.rs @@ -121,3 +121,10 @@ pub(crate) struct MustNotSuspendReason { pub span: Span, pub reason: String, } + +#[derive(LintDiagnostic)] +#[diag(mir_transform_undefined_transmute)] +#[note] +#[note(mir_transform_note2)] +#[help] +pub(crate) struct UndefinedTransmute; diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs index 84d07d3833071..626b4584fb27f 100644 --- a/compiler/rustc_mir_transform/src/lib.rs +++ b/compiler/rustc_mir_transform/src/lib.rs @@ -51,6 +51,7 @@ mod add_subtyping_projections; mod check_alignment; mod check_const_item_mutation; mod check_packed_ref; +mod check_undefined_transmutes; // This pass is public to allow external drivers to perform MIR cleanup pub mod cleanup_post_borrowck; mod copy_prop; @@ -293,6 +294,7 @@ fn mir_built(tcx: TyCtxt<'_>, def: LocalDefId) -> &Steal> { &Lint(check_packed_ref::CheckPackedRef), &Lint(check_const_item_mutation::CheckConstItemMutation), &Lint(function_item_references::FunctionItemReferences), + &Lint(check_undefined_transmutes::CheckUndefinedTransmutes), // What we need to do constant evaluation. &simplify::SimplifyCfg::Initial, &Lint(sanity_check::SanityCheck), diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs index 08d06cad55d06..8d6560111dad0 100644 --- a/library/core/src/ptr/mod.rs +++ b/library/core/src/ptr/mod.rs @@ -1916,6 +1916,7 @@ pub unsafe fn write_volatile(dst: *mut T, src: T) { /// than trying to adapt this to accommodate that change. /// /// Any questions go to @nagisa. +#[cfg_attr(not(bootstrap), allow(ptr_to_integer_transmute_in_consts))] #[lang = "align_offset"] pub(crate) const unsafe fn align_offset(p: *const T, a: usize) -> usize { // FIXME(#75598): Direct use of these intrinsics improves codegen significantly at opt-level <= diff --git a/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.fixed b/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.fixed index e95054a7ccb0e..617d32d1fa793 100644 --- a/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.fixed +++ b/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.fixed @@ -84,8 +84,11 @@ fn issue_10449() { } // Pointers cannot be cast to integers in const contexts +#[allow(ptr_to_integer_transmute_in_consts, reason = "This is tested in the compiler test suite")] const fn issue_12402

(ptr: *const P) { - unsafe { transmute::<*const i32, usize>(&42i32) }; - unsafe { transmute::(issue_12402) }; - let _ = unsafe { transmute::<_, usize>(ptr) }; + // This test exists even though the compiler lints against it + // to test that clippy's transmute lints do not trigger on this. + unsafe { std::mem::transmute::<*const i32, usize>(&42i32) }; + unsafe { std::mem::transmute::(issue_12402) }; + let _ = unsafe { std::mem::transmute::<_, usize>(ptr) }; } diff --git a/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.rs b/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.rs index e5fcdef7a1c39..d68db3c2deb9f 100644 --- a/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.rs +++ b/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.rs @@ -84,8 +84,11 @@ fn issue_10449() { } // Pointers cannot be cast to integers in const contexts +#[allow(ptr_to_integer_transmute_in_consts, reason = "This is tested in the compiler test suite")] const fn issue_12402

(ptr: *const P) { - unsafe { transmute::<*const i32, usize>(&42i32) }; - unsafe { transmute::(issue_12402) }; - let _ = unsafe { transmute::<_, usize>(ptr) }; + // This test exists even though the compiler lints against it + // to test that clippy's transmute lints do not trigger on this. + unsafe { std::mem::transmute::<*const i32, usize>(&42i32) }; + unsafe { std::mem::transmute::(issue_12402) }; + let _ = unsafe { std::mem::transmute::<_, usize>(ptr) }; } diff --git a/tests/ui/consts/const-eval/ptr-to-int-transmute-in-consts-issue-87525.rs b/tests/ui/consts/const-eval/ptr-to-int-transmute-in-consts-issue-87525.rs index f8e97904e9e08..19c78f019aab7 100644 --- a/tests/ui/consts/const-eval/ptr-to-int-transmute-in-consts-issue-87525.rs +++ b/tests/ui/consts/const-eval/ptr-to-int-transmute-in-consts-issue-87525.rs @@ -1,21 +1,21 @@ const fn foo(ptr: *const u8) -> usize { unsafe { std::mem::transmute(ptr) - //~^ ERROR pointers cannot be transmuted to integers + //~^ WARN pointers cannot be transmuted to integers } } trait Human { - const ID: u64 = { + const ID: usize = { let value = 10; - let ptr: *const i32 = &value; + let ptr: *const usize = &value; unsafe { std::mem::transmute(ptr) - //~^ ERROR pointers cannot be transmuted to integers + //~^ WARN pointers cannot be transmuted to integers } }; - fn id_plus_one() -> u64 { + fn id_plus_one() -> usize { Self::ID + 1 } } @@ -23,16 +23,16 @@ trait Human { struct Type(T); impl Type { - const ID: u64 = { + const ID: usize = { let value = 10; - let ptr: *const i32 = &value; + let ptr: *const usize = &value; unsafe { std::mem::transmute(ptr) - //~^ ERROR pointers cannot be transmuted to integers + //~^ WARN pointers cannot be transmuted to integers } }; - fn id_plus_one() -> u64 { + fn id_plus_one() -> usize { Self::ID + 1 } } @@ -59,10 +59,10 @@ impl ControlStruct { const fn zoom(ptr: *const u8) -> usize { unsafe { std::mem::transmute(ptr) - //~^ ERROR pointers cannot be transmuted to integers + //~^ WARN pointers cannot be transmuted to integers } } - + fn main() { const a: u8 = 10; const value: usize = zoom(&a); diff --git a/tests/ui/consts/const-eval/ptr-to-int-transmute-in-consts-issue-87525.stderr b/tests/ui/consts/const-eval/ptr-to-int-transmute-in-consts-issue-87525.stderr index a57bc8e1e70ec..ca6ad9408ab91 100644 --- a/tests/ui/consts/const-eval/ptr-to-int-transmute-in-consts-issue-87525.stderr +++ b/tests/ui/consts/const-eval/ptr-to-int-transmute-in-consts-issue-87525.stderr @@ -1,3 +1,14 @@ +warning: pointers cannot be transmuted to integers during const eval + --> $DIR/ptr-to-int-transmute-in-consts-issue-87525.rs:61:9 + | +LL | std::mem::transmute(ptr) + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: at compile-time, pointers do not have an integer value + = note: avoiding this restriction via `union` or raw pointers leads to compile-time undefined behavior + = help: for more information, see https://doc.rust-lang.org/std/mem/fn.transmute.html + = note: `#[warn(ptr_to_integer_transmute_in_consts)]` on by default + error[E0080]: evaluation of constant value failed --> $DIR/ptr-to-int-transmute-in-consts-issue-87525.rs:68:26 | @@ -7,6 +18,36 @@ LL | const value: usize = zoom(&a); = help: this code performed an operation that depends on the underlying bytes representing a pointer = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported -error: aborting due to 1 previous error +warning: pointers cannot be transmuted to integers during const eval + --> $DIR/ptr-to-int-transmute-in-consts-issue-87525.rs:3:9 + | +LL | std::mem::transmute(ptr) + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: at compile-time, pointers do not have an integer value + = note: avoiding this restriction via `union` or raw pointers leads to compile-time undefined behavior + = help: for more information, see https://doc.rust-lang.org/std/mem/fn.transmute.html + +warning: pointers cannot be transmuted to integers during const eval + --> $DIR/ptr-to-int-transmute-in-consts-issue-87525.rs:13:13 + | +LL | std::mem::transmute(ptr) + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: at compile-time, pointers do not have an integer value + = note: avoiding this restriction via `union` or raw pointers leads to compile-time undefined behavior + = help: for more information, see https://doc.rust-lang.org/std/mem/fn.transmute.html + +warning: pointers cannot be transmuted to integers during const eval + --> $DIR/ptr-to-int-transmute-in-consts-issue-87525.rs:30:13 + | +LL | std::mem::transmute(ptr) + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: at compile-time, pointers do not have an integer value + = note: avoiding this restriction via `union` or raw pointers leads to compile-time undefined behavior + = help: for more information, see https://doc.rust-lang.org/std/mem/fn.transmute.html + +error: aborting due to 1 previous error; 4 warnings emitted For more information about this error, try `rustc --explain E0080`. From 70260dbeca3303e4d62d2ff4c136501ddac7491d Mon Sep 17 00:00:00 2001 From: DianQK Date: Sat, 5 Oct 2024 21:10:04 +0800 Subject: [PATCH 1911/2194] Update to LLVM 19.1.1 --- src/llvm-project | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/llvm-project b/src/llvm-project index 56997739365e8..dd46457da7825 160000 --- a/src/llvm-project +++ b/src/llvm-project @@ -1 +1 @@ -Subproject commit 56997739365e8132cc817e00899480746c09d7d9 +Subproject commit dd46457da782554454106d48ecd4f6b4c2f9af73 From 8faf3722ac963a637265c3fb087fce08f9ceb163 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 5 Oct 2024 17:12:46 +0200 Subject: [PATCH 1912/2194] fix typo in 'lang item with track_caller' message --- compiler/rustc_passes/messages.ftl | 2 +- tests/ui/panic-handler/panic-handler-with-track-caller.stderr | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_passes/messages.ftl b/compiler/rustc_passes/messages.ftl index 5369f54afb908..f2682acf8aa0b 100644 --- a/compiler/rustc_passes/messages.ftl +++ b/compiler/rustc_passes/messages.ftl @@ -391,7 +391,7 @@ passes_lang_item_fn_with_target_feature = passes_lang_item_fn_with_track_caller = {passes_lang_item_fn} is not allowed to have `#[track_caller]` - .label = {passes_lang_item_fn} is not allowed to have `#[target_feature]` + .label = {passes_lang_item_fn} is not allowed to have `#[track_caller]` passes_lang_item_on_incorrect_target = `{$name}` lang item must be applied to a {$expected_target} diff --git a/tests/ui/panic-handler/panic-handler-with-track-caller.stderr b/tests/ui/panic-handler/panic-handler-with-track-caller.stderr index 9ed387fc8d1f4..605567acdb58b 100644 --- a/tests/ui/panic-handler/panic-handler-with-track-caller.stderr +++ b/tests/ui/panic-handler/panic-handler-with-track-caller.stderr @@ -5,7 +5,7 @@ LL | #[track_caller] | ^^^^^^^^^^^^^^^ LL | LL | fn panic(info: &PanicInfo) -> ! { - | ------------------------------- `#[panic_handler]` function is not allowed to have `#[target_feature]` + | ------------------------------- `#[panic_handler]` function is not allowed to have `#[track_caller]` error: aborting due to 1 previous error From 7d63efdb8c2d3b9ea25fa2bbb8703168d21483c8 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 5 Oct 2024 17:05:47 +0200 Subject: [PATCH 1913/2194] fix GVN trying to transmute pointers to integers --- compiler/rustc_mir_transform/src/gvn.rs | 30 +++++++++++++++++----- tests/coverage/closure_macro.cov-map | 8 +++--- tests/coverage/closure_macro_async.cov-map | 8 +++--- 3 files changed, 31 insertions(+), 15 deletions(-) diff --git a/compiler/rustc_mir_transform/src/gvn.rs b/compiler/rustc_mir_transform/src/gvn.rs index 50c9702cb9b02..7707d0d51f1bc 100644 --- a/compiler/rustc_mir_transform/src/gvn.rs +++ b/compiler/rustc_mir_transform/src/gvn.rs @@ -103,7 +103,7 @@ use rustc_middle::ty::layout::{HasParamEnv, LayoutOf}; use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_span::DUMMY_SP; use rustc_span::def_id::DefId; -use rustc_target::abi::{self, Abi, FIRST_VARIANT, FieldIdx, Size, VariantIdx}; +use rustc_target::abi::{self, Abi, FIRST_VARIANT, FieldIdx, Primitive, Size, VariantIdx}; use smallvec::SmallVec; use tracing::{debug, instrument, trace}; @@ -568,13 +568,29 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { CastKind::Transmute => { let value = self.evaluated[value].as_ref()?; let to = self.ecx.layout_of(to).ok()?; - // `offset` for immediates only supports scalar/scalar-pair ABIs, - // so bail out if the target is not one. + // `offset` for immediates generally only supports projections that match the + // type of the immediate. However, as a HACK, we exploit that it can also do + // limited transmutes: it only works between types with the same layout, and + // cannot transmute pointers to integers. if value.as_mplace_or_imm().is_right() { - match (value.layout.abi, to.abi) { - (Abi::Scalar(..), Abi::Scalar(..)) => {} - (Abi::ScalarPair(..), Abi::ScalarPair(..)) => {} - _ => return None, + let can_transmute = match (value.layout.abi, to.abi) { + (Abi::Scalar(s1), Abi::Scalar(s2)) => { + s1.size(&self.ecx) == s2.size(&self.ecx) + && !matches!(s1.primitive(), Primitive::Pointer(..)) + } + (Abi::ScalarPair(a1, b1), Abi::ScalarPair(a2, b2)) => { + a1.size(&self.ecx) == a2.size(&self.ecx) && + b1.size(&self.ecx) == b2.size(&self.ecx) && + // The alignment of the second component determines its offset, so that also needs to match. + b1.align(&self.ecx) == b2.align(&self.ecx) && + // None of the inputs may be a pointer. + !matches!(a1.primitive(), Primitive::Pointer(..)) + && !matches!(b1.primitive(), Primitive::Pointer(..)) + } + _ => false, + }; + if !can_transmute { + return None; } } value.offset(Size::ZERO, to, &self.ecx).discard_err()? diff --git a/tests/coverage/closure_macro.cov-map b/tests/coverage/closure_macro.cov-map index eb5f94d108068..fb4a137d4c8ec 100644 --- a/tests/coverage/closure_macro.cov-map +++ b/tests/coverage/closure_macro.cov-map @@ -23,19 +23,19 @@ Number of file 0 mappings: 6 - Code(Counter(0)) at (prev + 3, 1) to (start + 0, 2) Function name: closure_macro::main::{closure#0} -Raw bytes (35): 0x[01, 01, 03, 01, 05, 05, 0b, 09, 00, 05, 01, 10, 1c, 03, 21, 05, 04, 11, 01, 27, 02, 03, 11, 00, 16, 00, 00, 17, 00, 1e, 07, 02, 09, 00, 0a] +Raw bytes (35): 0x[01, 01, 03, 01, 05, 05, 0b, 09, 0d, 05, 01, 10, 1c, 03, 21, 05, 04, 11, 01, 27, 02, 03, 11, 00, 16, 0d, 00, 17, 00, 1e, 07, 02, 09, 00, 0a] Number of files: 1 - file 0 => global file 1 Number of expressions: 3 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) - expression 1 operands: lhs = Counter(1), rhs = Expression(2, Add) -- expression 2 operands: lhs = Counter(2), rhs = Zero +- expression 2 operands: lhs = Counter(2), rhs = Counter(3) Number of file 0 mappings: 5 - Code(Counter(0)) at (prev + 16, 28) to (start + 3, 33) - Code(Counter(1)) at (prev + 4, 17) to (start + 1, 39) - Code(Expression(0, Sub)) at (prev + 3, 17) to (start + 0, 22) = (c0 - c1) -- Code(Zero) at (prev + 0, 23) to (start + 0, 30) +- Code(Counter(3)) at (prev + 0, 23) to (start + 0, 30) - Code(Expression(1, Add)) at (prev + 2, 9) to (start + 0, 10) - = (c1 + (c2 + Zero)) + = (c1 + (c2 + c3)) diff --git a/tests/coverage/closure_macro_async.cov-map b/tests/coverage/closure_macro_async.cov-map index 4d0597f58bf1d..091e87909f900 100644 --- a/tests/coverage/closure_macro_async.cov-map +++ b/tests/coverage/closure_macro_async.cov-map @@ -31,19 +31,19 @@ Number of file 0 mappings: 6 - Code(Counter(0)) at (prev + 3, 1) to (start + 0, 2) Function name: closure_macro_async::test::{closure#0}::{closure#0} -Raw bytes (35): 0x[01, 01, 03, 01, 05, 05, 0b, 09, 00, 05, 01, 15, 1c, 03, 21, 05, 04, 11, 01, 27, 02, 03, 11, 00, 16, 00, 00, 17, 00, 1e, 07, 02, 09, 00, 0a] +Raw bytes (35): 0x[01, 01, 03, 01, 05, 05, 0b, 09, 0d, 05, 01, 15, 1c, 03, 21, 05, 04, 11, 01, 27, 02, 03, 11, 00, 16, 0d, 00, 17, 00, 1e, 07, 02, 09, 00, 0a] Number of files: 1 - file 0 => global file 1 Number of expressions: 3 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) - expression 1 operands: lhs = Counter(1), rhs = Expression(2, Add) -- expression 2 operands: lhs = Counter(2), rhs = Zero +- expression 2 operands: lhs = Counter(2), rhs = Counter(3) Number of file 0 mappings: 5 - Code(Counter(0)) at (prev + 21, 28) to (start + 3, 33) - Code(Counter(1)) at (prev + 4, 17) to (start + 1, 39) - Code(Expression(0, Sub)) at (prev + 3, 17) to (start + 0, 22) = (c0 - c1) -- Code(Zero) at (prev + 0, 23) to (start + 0, 30) +- Code(Counter(3)) at (prev + 0, 23) to (start + 0, 30) - Code(Expression(1, Add)) at (prev + 2, 9) to (start + 0, 10) - = (c1 + (c2 + Zero)) + = (c1 + (c2 + c3)) From 2223328d166a16cde864a17a5cb96de0853c9981 Mon Sep 17 00:00:00 2001 From: Yoh Deadfall Date: Sat, 5 Oct 2024 21:29:40 +0300 Subject: [PATCH 1914/2194] Android: Debug assertion after setting thread name --- library/std/src/sys/pal/unix/thread.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/library/std/src/sys/pal/unix/thread.rs b/library/std/src/sys/pal/unix/thread.rs index 2f2d6e6add396..040246618360f 100644 --- a/library/std/src/sys/pal/unix/thread.rs +++ b/library/std/src/sys/pal/unix/thread.rs @@ -117,13 +117,15 @@ impl Thread { pub fn set_name(name: &CStr) { const PR_SET_NAME: libc::c_int = 15; unsafe { - libc::prctl( + let res = libc::prctl( PR_SET_NAME, name.as_ptr(), 0 as libc::c_ulong, 0 as libc::c_ulong, 0 as libc::c_ulong, ); + // We have no good way of propagating errors here, but in debug-builds let's check that this actually worked. + debug_assert_eq!(res, 0); } } From 4f50efd1329f430998231f018c2cf61bfe0db449 Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Sat, 5 Oct 2024 22:48:55 +0300 Subject: [PATCH 1915/2194] update "build/host" symlink comment Signed-off-by: onur-ozkan --- src/bootstrap/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bootstrap/src/lib.rs b/src/bootstrap/src/lib.rs index 75659f46431af..bcd6b07f2a25e 100644 --- a/src/bootstrap/src/lib.rs +++ b/src/bootstrap/src/lib.rs @@ -470,7 +470,7 @@ impl Build { crate::core::metadata::build(&mut build); } - // Make a symbolic link so we can use a consistent directory in the documentation. + // Create symbolic link to use host sysroot from a consistent path (e.g., in the rust-analyzer config file). let build_triple = build.out.join(build.build); t!(fs::create_dir_all(&build_triple)); let host = build.out.join("host"); From 9d2495db60312472506939fdde49bb852b75b414 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Miku=C5=82a?= Date: Sun, 29 Sep 2024 22:28:08 +0200 Subject: [PATCH 1916/2194] enable f16 and f128 on windows-gnullvm targets --- library/std/build.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/library/std/build.rs b/library/std/build.rs index 7d37d4e9d7d83..032326556bd5b 100644 --- a/library/std/build.rs +++ b/library/std/build.rs @@ -7,6 +7,7 @@ fn main() { let target_vendor = env::var("CARGO_CFG_TARGET_VENDOR").expect("CARGO_CFG_TARGET_VENDOR was not set"); let target_env = env::var("CARGO_CFG_TARGET_ENV").expect("CARGO_CFG_TARGET_ENV was not set"); + let target_abi = env::var("CARGO_CFG_TARGET_ABI").expect("CARGO_CFG_TARGET_ABI was not set"); let target_pointer_width: u32 = env::var("CARGO_CFG_TARGET_POINTER_WIDTH") .expect("CARGO_CFG_TARGET_POINTER_WIDTH was not set") .parse() @@ -101,7 +102,7 @@ fn main() { // Unsupported ("arm64ec", _) => false, // MinGW ABI bugs - ("x86_64", "windows") if target_env == "gnu" => false, + ("x86_64", "windows") if target_env == "gnu" && target_abi != "llvm" => false, // Infinite recursion ("csky", _) => false, ("hexagon", _) => false, @@ -129,7 +130,7 @@ fn main() { // ABI unsupported ("sparc", _) => false, // MinGW ABI bugs - ("x86_64", "windows") if target_env == "gnu" => false, + ("x86_64", "windows") if target_env == "gnu" && target_abi != "llvm" => false, // 64-bit Linux is about the only platform to have f128 symbols by default (_, "linux") if target_pointer_width == 64 => true, // Almost all OSs are missing symbol. compiler-builtins will have to add them. From 6371ef6e964a72ca3b4c7557312d8808e98f4ff3 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Thu, 5 Sep 2024 07:02:26 -0400 Subject: [PATCH 1917/2194] Evaluating place expr that is never read from does not diverge --- compiler/rustc_hir_typeck/src/expr.rs | 67 ++++++++++++++++++- compiler/rustc_hir_typeck/src/pat.rs | 7 ++ ...ocess_never.SimplifyLocals-final.after.mir | 5 +- tests/mir-opt/uninhabited_enum.rs | 2 - tests/ui/never_type/diverging-place-match.rs | 13 ++++ .../never_type/diverging-place-match.stderr | 20 ++++++ .../raw-ref-op/never-place-isnt-diverging.rs | 13 ++++ .../never-place-isnt-diverging.stderr | 20 ++++++ tests/ui/reachable/expr_assign.stderr | 9 +-- .../reachable/unwarned-match-on-never.stderr | 2 +- 10 files changed, 146 insertions(+), 12 deletions(-) create mode 100644 tests/ui/never_type/diverging-place-match.rs create mode 100644 tests/ui/never_type/diverging-place-match.stderr create mode 100644 tests/ui/raw-ref-op/never-place-isnt-diverging.rs create mode 100644 tests/ui/raw-ref-op/never-place-isnt-diverging.stderr diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index e3c7dded0ca6e..870a260c9fe09 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -238,8 +238,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { _ => self.warn_if_unreachable(expr.hir_id, expr.span, "expression"), } - // Any expression that produces a value of type `!` must have diverged - if ty.is_never() { + // Any expression that produces a value of type `!` must have diverged, + // unless it's a place expression that isn't being read from, in which case + // diverging would be unsound since we may never actually read the `!`. + // e.g. `let _ = *never_ptr;` with `never_ptr: *const !`. + if ty.is_never() && self.expr_constitutes_read(expr) { self.diverges.set(self.diverges.get() | Diverges::always(expr.span)); } @@ -257,6 +260,66 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ty } + pub(super) fn expr_constitutes_read(&self, expr: &'tcx hir::Expr<'tcx>) -> bool { + // We only care about place exprs. Anything else returns an immediate + // which would constitute a read. We don't care about distinguishing + // "syntactic" place exprs since if the base of a field projection is + // not a place then it would've been UB to read from it anyways since + // that constitutes a read. + if !expr.is_syntactic_place_expr() { + return true; + } + + // If this expression has any adjustments applied after the place expression, + // they may constitute reads. + if !self.typeck_results.borrow().expr_adjustments(expr).is_empty() { + return true; + } + + fn pat_does_read(pat: &hir::Pat<'_>) -> bool { + let mut does_read = false; + pat.walk(|pat| { + if matches!( + pat.kind, + hir::PatKind::Wild | hir::PatKind::Never | hir::PatKind::Or(_) + ) { + true + } else { + does_read = true; + // No need to continue. + false + } + }); + does_read + } + + match self.tcx.parent_hir_node(expr.hir_id) { + // Addr-of, field projections, and LHS of assignment don't constitute reads. + // Assignment does call `drop_in_place`, though, but its safety + // requirements are not the same. + hir::Node::Expr(hir::Expr { kind: hir::ExprKind::AddrOf(..), .. }) => false, + hir::Node::Expr(hir::Expr { + kind: hir::ExprKind::Assign(target, _, _) | hir::ExprKind::Field(target, _), + .. + }) if expr.hir_id == target.hir_id => false, + + // If we have a subpattern that performs a read, we want to consider this + // to diverge for compatibility to support something like `let x: () = *never_ptr;`. + hir::Node::LetStmt(hir::LetStmt { init: Some(target), pat, .. }) + | hir::Node::Expr(hir::Expr { + kind: hir::ExprKind::Let(hir::LetExpr { init: target, pat, .. }), + .. + }) if expr.hir_id == target.hir_id && !pat_does_read(*pat) => false, + hir::Node::Expr(hir::Expr { kind: hir::ExprKind::Match(target, arms, _), .. }) + if expr.hir_id == target.hir_id + && !arms.iter().any(|arm| pat_does_read(arm.pat)) => + { + false + } + _ => true, + } + } + #[instrument(skip(self, expr), level = "debug")] fn check_expr_kind( &self, diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs index 49c5a7d8a652d..824918d1fa222 100644 --- a/compiler/rustc_hir_typeck/src/pat.rs +++ b/compiler/rustc_hir_typeck/src/pat.rs @@ -27,6 +27,7 @@ use tracing::{debug, instrument, trace}; use ty::VariantDef; use super::report_unexpected_variant_res; +use crate::diverges::Diverges; use crate::gather_locals::DeclOrigin; use crate::{FnCtxt, LoweredTy, errors}; @@ -276,6 +277,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } }; + // All other patterns constitute a read, which causes us to diverge + // if the type is never. + if ty.is_never() && !matches!(pat.kind, PatKind::Wild | PatKind::Never | PatKind::Or(_)) { + self.diverges.set(self.diverges.get() | Diverges::always(pat.span)); + } + self.write_ty(pat.hir_id, ty); // (note_1): In most of the cases where (note_1) is referenced diff --git a/tests/mir-opt/uninhabited_enum.process_never.SimplifyLocals-final.after.mir b/tests/mir-opt/uninhabited_enum.process_never.SimplifyLocals-final.after.mir index 240f409817d77..64fc81e298946 100644 --- a/tests/mir-opt/uninhabited_enum.process_never.SimplifyLocals-final.after.mir +++ b/tests/mir-opt/uninhabited_enum.process_never.SimplifyLocals-final.after.mir @@ -3,12 +3,11 @@ fn process_never(_1: *const !) -> () { debug input => _1; let mut _0: (); - let _2: &!; scope 1 { - debug _input => _2; + debug _input => _1; } bb0: { - unreachable; + return; } } diff --git a/tests/mir-opt/uninhabited_enum.rs b/tests/mir-opt/uninhabited_enum.rs index 859535852cf0d..9d845e34fbda8 100644 --- a/tests/mir-opt/uninhabited_enum.rs +++ b/tests/mir-opt/uninhabited_enum.rs @@ -13,8 +13,6 @@ pub fn process_never(input: *const !) { #[no_mangle] pub fn process_void(input: *const Void) { let _input = unsafe { &*input }; - // In the future, this should end with `unreachable`, but we currently only do - // unreachability analysis for `!`. } fn main() {} diff --git a/tests/ui/never_type/diverging-place-match.rs b/tests/ui/never_type/diverging-place-match.rs new file mode 100644 index 0000000000000..7bc00773c0ba5 --- /dev/null +++ b/tests/ui/never_type/diverging-place-match.rs @@ -0,0 +1,13 @@ +#![feature(never_type)] + +fn make_up_a_value() -> T { + unsafe { + //~^ ERROR mismatched types + let x: *const ! = 0 as _; + let _: ! = *x; + // Since `*x` "diverges" in HIR, but doesn't count as a read in MIR, this + // is unsound since we act as if it diverges but it doesn't. + } +} + +fn main() {} diff --git a/tests/ui/never_type/diverging-place-match.stderr b/tests/ui/never_type/diverging-place-match.stderr new file mode 100644 index 0000000000000..e86c634d59186 --- /dev/null +++ b/tests/ui/never_type/diverging-place-match.stderr @@ -0,0 +1,20 @@ +error[E0308]: mismatched types + --> $DIR/diverging-place-match.rs:4:5 + | +LL | fn make_up_a_value() -> T { + | - expected this type parameter +LL | / unsafe { +LL | | +LL | | let x: *const ! = 0 as _; +LL | | let _: ! = *x; +LL | | // Since `*x` "diverges" in HIR, but doesn't count as a read in MIR, this +LL | | // is unsound since we act as if it diverges but it doesn't. +LL | | } + | |_____^ expected type parameter `T`, found `()` + | + = note: expected type parameter `T` + found unit type `()` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/raw-ref-op/never-place-isnt-diverging.rs b/tests/ui/raw-ref-op/never-place-isnt-diverging.rs new file mode 100644 index 0000000000000..52f4158dbc988 --- /dev/null +++ b/tests/ui/raw-ref-op/never-place-isnt-diverging.rs @@ -0,0 +1,13 @@ +#![feature(never_type)] + +fn make_up_a_value() -> T { + unsafe { + //~^ ERROR mismatched types + let x: *const ! = 0 as _; + &raw const *x; + // Since `*x` is `!`, HIR typeck used to think that it diverges + // and allowed the block to coerce to any value, leading to UB. + } +} + +fn main() {} diff --git a/tests/ui/raw-ref-op/never-place-isnt-diverging.stderr b/tests/ui/raw-ref-op/never-place-isnt-diverging.stderr new file mode 100644 index 0000000000000..9eba57dde8fa7 --- /dev/null +++ b/tests/ui/raw-ref-op/never-place-isnt-diverging.stderr @@ -0,0 +1,20 @@ +error[E0308]: mismatched types + --> $DIR/never-place-isnt-diverging.rs:4:5 + | +LL | fn make_up_a_value() -> T { + | - expected this type parameter +LL | / unsafe { +LL | | +LL | | let x: *const ! = 0 as _; +LL | | &raw const *x; +LL | | // Since `*x` is `!`, HIR typeck used to think that it diverges +LL | | // and allowed the block to coerce to any value, leading to UB. +LL | | } + | |_____^ expected type parameter `T`, found `()` + | + = note: expected type parameter `T` + found unit type `()` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/reachable/expr_assign.stderr b/tests/ui/reachable/expr_assign.stderr index c51156b3f40cf..cfbbe04db769d 100644 --- a/tests/ui/reachable/expr_assign.stderr +++ b/tests/ui/reachable/expr_assign.stderr @@ -14,12 +14,13 @@ LL | #![deny(unreachable_code)] | ^^^^^^^^^^^^^^^^ error: unreachable expression - --> $DIR/expr_assign.rs:20:14 + --> $DIR/expr_assign.rs:20:9 | LL | *p = return; - | -- ^^^^^^ unreachable expression - | | - | any code following this expression is unreachable + | ^^^^^------ + | | | + | | any code following this expression is unreachable + | unreachable expression error: unreachable expression --> $DIR/expr_assign.rs:26:15 diff --git a/tests/ui/reachable/unwarned-match-on-never.stderr b/tests/ui/reachable/unwarned-match-on-never.stderr index a296d2a055e09..c1ad3511b4e08 100644 --- a/tests/ui/reachable/unwarned-match-on-never.stderr +++ b/tests/ui/reachable/unwarned-match-on-never.stderr @@ -2,7 +2,7 @@ error: unreachable expression --> $DIR/unwarned-match-on-never.rs:10:5 | LL | match x {} - | - any code following this expression is unreachable + | ---------- any code following this expression is unreachable LL | // But matches in unreachable code are warned. LL | match x {} | ^^^^^^^^^^ unreachable expression From 5193c211ea594ad9918372868bdb5d4dfafaea87 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Thu, 5 Sep 2024 07:21:52 -0400 Subject: [PATCH 1918/2194] Do not coerce places if they do not constitute reads --- compiler/rustc_hir_typeck/src/coercion.rs | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs index fb462eec1b9aa..6a1018883c98a 100644 --- a/compiler/rustc_hir_typeck/src/coercion.rs +++ b/compiler/rustc_hir_typeck/src/coercion.rs @@ -82,6 +82,7 @@ struct Coerce<'a, 'tcx> { /// See #47489 and #48598 /// See docs on the "AllowTwoPhase" type for a more detailed discussion allow_two_phase: AllowTwoPhase, + coerce_never: bool, } impl<'a, 'tcx> Deref for Coerce<'a, 'tcx> { @@ -125,8 +126,9 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { fcx: &'f FnCtxt<'f, 'tcx>, cause: ObligationCause<'tcx>, allow_two_phase: AllowTwoPhase, + coerce_never: bool, ) -> Self { - Coerce { fcx, cause, allow_two_phase, use_lub: false } + Coerce { fcx, cause, allow_two_phase, use_lub: false, coerce_never } } fn unify(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> InferResult<'tcx, Ty<'tcx>> { @@ -177,7 +179,11 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { // Coercing from `!` to any type is allowed: if a.is_never() { - return success(simple(Adjust::NeverToAny)(b), b, vec![]); + if self.coerce_never { + return success(simple(Adjust::NeverToAny)(b), b, vec![]); + } else { + return self.unify_and(a, b, identity); + } } // Coercing *from* an unresolved inference variable means that @@ -1038,7 +1044,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// The expressions *must not* have any preexisting adjustments. pub(crate) fn coerce( &self, - expr: &hir::Expr<'_>, + expr: &'tcx hir::Expr<'tcx>, expr_ty: Ty<'tcx>, mut target: Ty<'tcx>, allow_two_phase: AllowTwoPhase, @@ -1055,7 +1061,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let cause = cause.unwrap_or_else(|| self.cause(expr.span, ObligationCauseCode::ExprAssignable)); - let coerce = Coerce::new(self, cause, allow_two_phase); + let coerce = Coerce::new(self, cause, allow_two_phase, self.expr_constitutes_read(expr)); let ok = self.commit_if_ok(|_| coerce.coerce(source, target))?; let (adjustments, _) = self.register_infer_ok_obligations(ok); @@ -1078,7 +1084,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let cause = self.cause(DUMMY_SP, ObligationCauseCode::ExprAssignable); // We don't ever need two-phase here since we throw out the result of the coercion - let coerce = Coerce::new(self, cause, AllowTwoPhase::No); + let coerce = Coerce::new(self, cause, AllowTwoPhase::No, true); self.probe(|_| { let Ok(ok) = coerce.coerce(source, target) else { return false; @@ -1095,7 +1101,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { pub(crate) fn deref_steps(&self, expr_ty: Ty<'tcx>, target: Ty<'tcx>) -> Option { let cause = self.cause(DUMMY_SP, ObligationCauseCode::ExprAssignable); // We don't ever need two-phase here since we throw out the result of the coercion - let coerce = Coerce::new(self, cause, AllowTwoPhase::No); + let coerce = Coerce::new(self, cause, AllowTwoPhase::No, true); coerce .autoderef(DUMMY_SP, expr_ty) .find_map(|(ty, steps)| self.probe(|_| coerce.unify(ty, target)).ok().map(|_| steps)) @@ -1252,7 +1258,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // probably aren't processing function arguments here and even if we were, // they're going to get autorefed again anyway and we can apply 2-phase borrows // at that time. - let mut coerce = Coerce::new(self, cause.clone(), AllowTwoPhase::No); + let mut coerce = Coerce::new(self, cause.clone(), AllowTwoPhase::No, true); coerce.use_lub = true; // First try to coerce the new expression to the type of the previous ones, From 73d49f8c697da34ee1372b51540bfb0f1ae0c712 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Thu, 5 Sep 2024 07:49:38 -0400 Subject: [PATCH 1919/2194] Fix up tests --- compiler/rustc_hir_typeck/src/coercion.rs | 17 ++++- .../src/fn_ctxt/suggestions.rs | 6 +- .../miri/tests/pass/underscore_pattern.rs | 51 ++++++++++++- ...t_read.main.SimplifyLocals-final.after.mir | 49 ++++++++++++ tests/mir-opt/uninhabited_not_read.rs | 27 +++++++ tests/ui/never_type/diverging-place-match.rs | 36 ++++++++- .../never_type/diverging-place-match.stderr | 75 +++++++++++++++++-- 7 files changed, 245 insertions(+), 16 deletions(-) create mode 100644 tests/mir-opt/uninhabited_not_read.main.SimplifyLocals-final.after.mir create mode 100644 tests/mir-opt/uninhabited_not_read.rs diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs index 6a1018883c98a..1705421c2f40e 100644 --- a/compiler/rustc_hir_typeck/src/coercion.rs +++ b/compiler/rustc_hir_typeck/src/coercion.rs @@ -82,6 +82,10 @@ struct Coerce<'a, 'tcx> { /// See #47489 and #48598 /// See docs on the "AllowTwoPhase" type for a more detailed discussion allow_two_phase: AllowTwoPhase, + /// Whether we allow `NeverToAny` coercions. This is unsound if we're + /// coercing a place expression without it counting as a read in the MIR. + /// This is a side-effect of HIR not really having a great distinction + /// between places and values. coerce_never: bool, } @@ -1083,7 +1087,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { debug!("coercion::can_with_predicates({:?} -> {:?})", source, target); let cause = self.cause(DUMMY_SP, ObligationCauseCode::ExprAssignable); - // We don't ever need two-phase here since we throw out the result of the coercion + // We don't ever need two-phase here since we throw out the result of the coercion. + // We also just always set `coerce_never` to true, since this is a heuristic. let coerce = Coerce::new(self, cause, AllowTwoPhase::No, true); self.probe(|_| { let Ok(ok) = coerce.coerce(source, target) else { @@ -1096,11 +1101,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } /// Given a type and a target type, this function will calculate and return - /// how many dereference steps needed to achieve `expr_ty <: target`. If + /// how many dereference steps needed to coerce `expr_ty` to `target`. If /// it's not possible, return `None`. - pub(crate) fn deref_steps(&self, expr_ty: Ty<'tcx>, target: Ty<'tcx>) -> Option { + pub(crate) fn deref_steps_for_suggestion( + &self, + expr_ty: Ty<'tcx>, + target: Ty<'tcx>, + ) -> Option { let cause = self.cause(DUMMY_SP, ObligationCauseCode::ExprAssignable); - // We don't ever need two-phase here since we throw out the result of the coercion + // We don't ever need two-phase here since we throw out the result of the coercion. let coerce = Coerce::new(self, cause, AllowTwoPhase::No, true); coerce .autoderef(DUMMY_SP, expr_ty) diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs index 435b7d0f39a37..1df4d32f3cbac 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs @@ -2608,7 +2608,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } if let hir::ExprKind::Unary(hir::UnOp::Deref, inner) = expr.kind - && let Some(1) = self.deref_steps(expected, checked_ty) + && let Some(1) = self.deref_steps_for_suggestion(expected, checked_ty) { // We have `*&T`, check if what was expected was `&T`. // If so, we may want to suggest removing a `*`. @@ -2738,7 +2738,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } (_, &ty::RawPtr(ty_b, mutbl_b), &ty::Ref(_, ty_a, mutbl_a)) => { - if let Some(steps) = self.deref_steps(ty_a, ty_b) + if let Some(steps) = self.deref_steps_for_suggestion(ty_a, ty_b) // Only suggest valid if dereferencing needed. && steps > 0 // The pointer type implements `Copy` trait so the suggestion is always valid. @@ -2782,7 +2782,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } _ if sp == expr.span => { - if let Some(mut steps) = self.deref_steps(checked_ty, expected) { + if let Some(mut steps) = self.deref_steps_for_suggestion(checked_ty, expected) { let mut expr = expr.peel_blocks(); let mut prefix_span = expr.span.shrink_to_lo(); let mut remove = String::new(); diff --git a/src/tools/miri/tests/pass/underscore_pattern.rs b/src/tools/miri/tests/pass/underscore_pattern.rs index f0afe5589546e..f59bb9f5c82d5 100644 --- a/src/tools/miri/tests/pass/underscore_pattern.rs +++ b/src/tools/miri/tests/pass/underscore_pattern.rs @@ -1,5 +1,7 @@ // Various tests ensuring that underscore patterns really just construct the place, but don't check its contents. #![feature(strict_provenance)] +#![feature(never_type)] + use std::ptr; fn main() { @@ -9,6 +11,7 @@ fn main() { invalid_let(); dangling_let_type_annotation(); invalid_let_type_annotation(); + never(); } fn dangling_match() { @@ -34,6 +37,13 @@ fn invalid_match() { _ => {} } } + + unsafe { + let x: Uninit = Uninit { uninit: () }; + match x.value { + _ => {} + } + } } fn dangling_let() { @@ -41,6 +51,11 @@ fn dangling_let() { let ptr = ptr::without_provenance::(0x40); let _ = *ptr; } + + unsafe { + let ptr = ptr::without_provenance::(0x40); + let _ = *ptr; + } } fn invalid_let() { @@ -49,6 +64,12 @@ fn invalid_let() { let ptr = ptr::addr_of!(val).cast::(); let _ = *ptr; } + + unsafe { + let val = 3u8; + let ptr = ptr::addr_of!(val).cast::(); + let _ = *ptr; + } } // Adding a type annotation used to change how MIR is generated, make sure we cover both cases. @@ -57,6 +78,11 @@ fn dangling_let_type_annotation() { let ptr = ptr::without_provenance::(0x40); let _: bool = *ptr; } + + unsafe { + let ptr = ptr::without_provenance::(0x40); + let _: ! = *ptr; + } } fn invalid_let_type_annotation() { @@ -65,7 +91,28 @@ fn invalid_let_type_annotation() { let ptr = ptr::addr_of!(val).cast::(); let _: bool = *ptr; } + + unsafe { + let val = 3u8; + let ptr = ptr::addr_of!(val).cast::(); + let _: ! = *ptr; + } } -// FIXME: we should also test `!`, not just `bool` -- but that s currently buggy: -// https://github.com/rust-lang/rust/issues/117288 +// Regression test from . +fn never() { + unsafe { + let x = 3u8; + let x: *const ! = &x as *const u8 as *const _; + let _: ! = *x; + } + + // Without a type annotation, make sure we don't implicitly coerce `!` to `()` + // when we do the noop `*x` (as that would require a `!` *value*, creating + // which is UB). + unsafe { + let x = 3u8; + let x: *const ! = &x as *const u8 as *const _; + let _ = *x; + } +} diff --git a/tests/mir-opt/uninhabited_not_read.main.SimplifyLocals-final.after.mir b/tests/mir-opt/uninhabited_not_read.main.SimplifyLocals-final.after.mir new file mode 100644 index 0000000000000..6bf4be652bef3 --- /dev/null +++ b/tests/mir-opt/uninhabited_not_read.main.SimplifyLocals-final.after.mir @@ -0,0 +1,49 @@ +// MIR for `main` after SimplifyLocals-final + +fn main() -> () { + let mut _0: (); + let _1: u8; + let mut _2: *const !; + let mut _3: *const u8; + let _4: u8; + let mut _5: *const !; + let mut _6: *const u8; + scope 1 { + debug x => _1; + scope 2 { + debug x => _2; + scope 3 { + } + } + } + scope 4 { + debug x => _4; + scope 5 { + debug x => _5; + scope 6 { + } + } + } + + bb0: { + StorageLive(_1); + _1 = const 3_u8; + StorageLive(_2); + StorageLive(_3); + _3 = &raw const _1; + _2 = move _3 as *const ! (PtrToPtr); + StorageDead(_3); + StorageDead(_2); + StorageDead(_1); + StorageLive(_4); + _4 = const 3_u8; + StorageLive(_5); + StorageLive(_6); + _6 = &raw const _4; + _5 = move _6 as *const ! (PtrToPtr); + StorageDead(_6); + StorageDead(_5); + StorageDead(_4); + return; + } +} diff --git a/tests/mir-opt/uninhabited_not_read.rs b/tests/mir-opt/uninhabited_not_read.rs new file mode 100644 index 0000000000000..39ffdbdbb3359 --- /dev/null +++ b/tests/mir-opt/uninhabited_not_read.rs @@ -0,0 +1,27 @@ +// skip-filecheck + +//@ edition: 2021 +// In ed 2021 and below, we don't fallback `!` to `()`. +// This would introduce a `! -> ()` coercion which would +// be UB if we didn't disallow this explicitly. + +#![feature(never_type)] + +// EMIT_MIR uninhabited_not_read.main.SimplifyLocals-final.after.mir +fn main() { + // With a type annotation + unsafe { + let x = 3u8; + let x: *const ! = &x as *const u8 as *const _; + let _: ! = *x; + } + + // Without a type annotation, make sure we don't implicitly coerce `!` to `()` + // when we do the noop `*x`. + unsafe { + let x = 3u8; + let x: *const ! = &x as *const u8 as *const _; + let _ = *x; + } +} + diff --git a/tests/ui/never_type/diverging-place-match.rs b/tests/ui/never_type/diverging-place-match.rs index 7bc00773c0ba5..185e17c05a773 100644 --- a/tests/ui/never_type/diverging-place-match.rs +++ b/tests/ui/never_type/diverging-place-match.rs @@ -1,6 +1,6 @@ #![feature(never_type)] -fn make_up_a_value() -> T { +fn not_a_read() -> ! { unsafe { //~^ ERROR mismatched types let x: *const ! = 0 as _; @@ -10,4 +10,38 @@ fn make_up_a_value() -> T { } } +fn not_a_read_implicit() -> ! { + unsafe { + //~^ ERROR mismatched types + let x: *const ! = 0 as _; + let _ = *x; + } +} + +fn not_a_read_guide_coercion() -> ! { + unsafe { + //~^ ERROR mismatched types + let x: *const ! = 0 as _; + let _: () = *x; + //~^ ERROR mismatched types + } +} + +fn empty_match() -> ! { + unsafe { + //~^ ERROR mismatched types + let x: *const ! = 0 as _; + match *x { _ => {} }; + } +} + +fn field_projection() -> ! { + unsafe { + //~^ ERROR mismatched types + let x: *const (!, ()) = 0 as _; + let _ = (*x).0; + // ^ I think this is still UB, but because of the inbounds projection. + } +} + fn main() {} diff --git a/tests/ui/never_type/diverging-place-match.stderr b/tests/ui/never_type/diverging-place-match.stderr index e86c634d59186..14b14f4270131 100644 --- a/tests/ui/never_type/diverging-place-match.stderr +++ b/tests/ui/never_type/diverging-place-match.stderr @@ -1,8 +1,6 @@ error[E0308]: mismatched types --> $DIR/diverging-place-match.rs:4:5 | -LL | fn make_up_a_value() -> T { - | - expected this type parameter LL | / unsafe { LL | | LL | | let x: *const ! = 0 as _; @@ -10,11 +8,76 @@ LL | | let _: ! = *x; LL | | // Since `*x` "diverges" in HIR, but doesn't count as a read in MIR, this LL | | // is unsound since we act as if it diverges but it doesn't. LL | | } - | |_____^ expected type parameter `T`, found `()` + | |_____^ expected `!`, found `()` | - = note: expected type parameter `T` - found unit type `()` + = note: expected type `!` + found unit type `()` -error: aborting due to 1 previous error +error[E0308]: mismatched types + --> $DIR/diverging-place-match.rs:14:5 + | +LL | / unsafe { +LL | | +LL | | let x: *const ! = 0 as _; +LL | | let _ = *x; +LL | | } + | |_____^ expected `!`, found `()` + | + = note: expected type `!` + found unit type `()` + +error[E0308]: mismatched types + --> $DIR/diverging-place-match.rs:25:21 + | +LL | let _: () = *x; + | -- ^^ expected `()`, found `!` + | | + | expected due to this + | + = note: expected unit type `()` + found type `!` + +error[E0308]: mismatched types + --> $DIR/diverging-place-match.rs:22:5 + | +LL | / unsafe { +LL | | +LL | | let x: *const ! = 0 as _; +LL | | let _: () = *x; +LL | | +LL | | } + | |_____^ expected `!`, found `()` + | + = note: expected type `!` + found unit type `()` + +error[E0308]: mismatched types + --> $DIR/diverging-place-match.rs:31:5 + | +LL | / unsafe { +LL | | +LL | | let x: *const ! = 0 as _; +LL | | match *x { _ => {} }; +LL | | } + | |_____^ expected `!`, found `()` + | + = note: expected type `!` + found unit type `()` + +error[E0308]: mismatched types + --> $DIR/diverging-place-match.rs:39:5 + | +LL | / unsafe { +LL | | +LL | | let x: *const (!, ()) = 0 as _; +LL | | let _ = (*x).0; +LL | | // ^ I think this is still UB, but because of the inbounds projection. +LL | | } + | |_____^ expected `!`, found `()` + | + = note: expected type `!` + found unit type `()` + +error: aborting due to 6 previous errors For more information about this error, try `rustc --explain E0308`. From 515b93297ff6b96e6368070f3eb3f3a833112bc0 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Thu, 5 Sep 2024 07:53:49 -0400 Subject: [PATCH 1920/2194] Document things a bit more carefully, also account for coercion in check_expr_has_type_or_error --- compiler/rustc_hir_typeck/src/coercion.rs | 1 + compiler/rustc_hir_typeck/src/expr.rs | 16 +++++++++++++++- tests/mir-opt/uninhabited_not_read.rs | 1 - .../match/pattern-matching-should-fail.stderr | 6 ++---- 4 files changed, 18 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs index 1705421c2f40e..96bff04dbc7cf 100644 --- a/compiler/rustc_hir_typeck/src/coercion.rs +++ b/compiler/rustc_hir_typeck/src/coercion.rs @@ -186,6 +186,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { if self.coerce_never { return success(simple(Adjust::NeverToAny)(b), b, vec![]); } else { + // Otherwise the only coercion we can do is unification. return self.unify_and(a, b, identity); } } diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index 870a260c9fe09..604bec95701d5 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -62,7 +62,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // While we don't allow *arbitrary* coercions here, we *do* allow // coercions from ! to `expected`. - if ty.is_never() { + if ty.is_never() && self.expr_constitutes_read(expr) { if let Some(_) = self.typeck_results.borrow().adjustments().get(expr.hir_id) { let reported = self.dcx().span_delayed_bug( expr.span, @@ -260,6 +260,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ty } + /// Whether this expression constitutes a read of value of the type that + /// it evaluates to. + /// + /// This is used to determine if we should consider the block to diverge + /// if the expression evaluates to `!`, and if we should insert a `NeverToAny` + /// coercion for values of type `!`. + /// + /// This function generally returns `false` if the expression is a place + /// expression and the *parent* expression is the scrutinee of a match or + /// the pointee of an `&` addr-of expression, since both of those parent + /// expressions take a *place* and not a value. + /// + /// This function is unfortunately a bit heuristical, though it is certainly + /// far sounder than the prior status quo: . pub(super) fn expr_constitutes_read(&self, expr: &'tcx hir::Expr<'tcx>) -> bool { // We only care about place exprs. Anything else returns an immediate // which would constitute a read. We don't care about distinguishing diff --git a/tests/mir-opt/uninhabited_not_read.rs b/tests/mir-opt/uninhabited_not_read.rs index 39ffdbdbb3359..15769cdd75b3f 100644 --- a/tests/mir-opt/uninhabited_not_read.rs +++ b/tests/mir-opt/uninhabited_not_read.rs @@ -24,4 +24,3 @@ fn main() { let _ = *x; } } - diff --git a/tests/ui/closures/2229_closure_analysis/match/pattern-matching-should-fail.stderr b/tests/ui/closures/2229_closure_analysis/match/pattern-matching-should-fail.stderr index f8ed792e3c675..e0d900a1eb564 100644 --- a/tests/ui/closures/2229_closure_analysis/match/pattern-matching-should-fail.stderr +++ b/tests/ui/closures/2229_closure_analysis/match/pattern-matching-should-fail.stderr @@ -7,14 +7,12 @@ LL | let c1 = || match x { }; | ^ `x` used here but it isn't initialized error[E0381]: used binding `x` isn't initialized - --> $DIR/pattern-matching-should-fail.rs:15:14 + --> $DIR/pattern-matching-should-fail.rs:15:23 | LL | let x: !; | - binding declared here but left uninitialized LL | let c2 = || match x { _ => () }; - | ^^ - borrow occurs due to use in closure - | | - | `x` used here but it isn't initialized + | ^ `x` used here but it isn't initialized error[E0381]: used binding `variant` isn't initialized --> $DIR/pattern-matching-should-fail.rs:27:13 From d2bd018dadc98442a15f52d962aaf3c5d102f034 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Thu, 5 Sep 2024 09:42:44 -0400 Subject: [PATCH 1921/2194] Be more thorough in expr_constitutes_read --- compiler/rustc_hir_typeck/src/expr.rs | 181 ++++++++++++++++++++------ compiler/rustc_hir_typeck/src/pat.rs | 2 +- 2 files changed, 141 insertions(+), 42 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index 604bec95701d5..cef00cf8ce865 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -1,3 +1,6 @@ +// ignore-tidy-filelength +// FIXME: we should move the field error reporting code somewhere else. + //! Type checking expressions. //! //! See [`rustc_hir_analysis::check`] for more context on type checking in general. @@ -284,54 +287,150 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { return true; } - // If this expression has any adjustments applied after the place expression, - // they may constitute reads. - if !self.typeck_results.borrow().expr_adjustments(expr).is_empty() { - return true; - } + let parent_node = self.tcx.parent_hir_node(expr.hir_id); + match parent_node { + hir::Node::Expr(parent_expr) => { + match parent_expr.kind { + // Addr-of, field projections, and LHS of assignment don't constitute reads. + // Assignment does call `drop_in_place`, though, but its safety + // requirements are not the same. + ExprKind::AddrOf(..) | hir::ExprKind::Field(..) => false, + ExprKind::Assign(lhs, _, _) => { + // Only the LHS does not constitute a read + expr.hir_id != lhs.hir_id + } - fn pat_does_read(pat: &hir::Pat<'_>) -> bool { - let mut does_read = false; - pat.walk(|pat| { - if matches!( - pat.kind, - hir::PatKind::Wild | hir::PatKind::Never | hir::PatKind::Or(_) - ) { - true - } else { - does_read = true; - // No need to continue. - false - } - }); - does_read - } + // If we have a subpattern that performs a read, we want to consider this + // to diverge for compatibility to support something like `let x: () = *never_ptr;`. + ExprKind::Match(scrutinee, arms, _) => { + assert_eq!(scrutinee.hir_id, expr.hir_id); + arms.iter().any(|arm| self.pat_constitutes_read(arm.pat)) + } + ExprKind::Let(hir::LetExpr { init, pat, .. }) => { + assert_eq!(init.hir_id, expr.hir_id); + self.pat_constitutes_read(*pat) + } - match self.tcx.parent_hir_node(expr.hir_id) { - // Addr-of, field projections, and LHS of assignment don't constitute reads. - // Assignment does call `drop_in_place`, though, but its safety - // requirements are not the same. - hir::Node::Expr(hir::Expr { kind: hir::ExprKind::AddrOf(..), .. }) => false, - hir::Node::Expr(hir::Expr { - kind: hir::ExprKind::Assign(target, _, _) | hir::ExprKind::Field(target, _), - .. - }) if expr.hir_id == target.hir_id => false, + // Any expression child of these expressions constitute reads. + ExprKind::Array(_) + | ExprKind::Call(_, _) + | ExprKind::MethodCall(_, _, _, _) + | ExprKind::Tup(_) + | ExprKind::Binary(_, _, _) + | ExprKind::Unary(_, _) + | ExprKind::Cast(_, _) + | ExprKind::Type(_, _) + | ExprKind::DropTemps(_) + | ExprKind::If(_, _, _) + | ExprKind::Closure(_) + | ExprKind::Block(_, _) + | ExprKind::AssignOp(_, _, _) + | ExprKind::Index(_, _, _) + | ExprKind::Break(_, _) + | ExprKind::Ret(_) + | ExprKind::Become(_) + | ExprKind::InlineAsm(_) + | ExprKind::Struct(_, _, _) + | ExprKind::Repeat(_, _) + | ExprKind::Yield(_, _) => true, + + // These expressions have no (direct) sub-exprs. + ExprKind::ConstBlock(_) + | ExprKind::Loop(_, _, _, _) + | ExprKind::Lit(_) + | ExprKind::Path(_) + | ExprKind::Continue(_) + | ExprKind::OffsetOf(_, _) + | ExprKind::Err(_) => unreachable!("no sub-expr expected for {:?}", expr.kind), + } + } // If we have a subpattern that performs a read, we want to consider this // to diverge for compatibility to support something like `let x: () = *never_ptr;`. - hir::Node::LetStmt(hir::LetStmt { init: Some(target), pat, .. }) - | hir::Node::Expr(hir::Expr { - kind: hir::ExprKind::Let(hir::LetExpr { init: target, pat, .. }), + hir::Node::LetStmt(hir::LetStmt { init: Some(target), pat, .. }) => { + assert_eq!(target.hir_id, expr.hir_id); + self.pat_constitutes_read(*pat) + } + + // These nodes (if they have a sub-expr) do constitute a read. + hir::Node::Block(_) + | hir::Node::Arm(_) + | hir::Node::ExprField(_) + | hir::Node::AnonConst(_) + | hir::Node::ConstBlock(_) + | hir::Node::ConstArg(_) + | hir::Node::Stmt(_) + | hir::Node::Item(hir::Item { + kind: hir::ItemKind::Const(..) | hir::ItemKind::Static(..), .. - }) if expr.hir_id == target.hir_id && !pat_does_read(*pat) => false, - hir::Node::Expr(hir::Expr { kind: hir::ExprKind::Match(target, arms, _), .. }) - if expr.hir_id == target.hir_id - && !arms.iter().any(|arm| pat_does_read(arm.pat)) => - { - false + }) + | hir::Node::TraitItem(hir::TraitItem { + kind: hir::TraitItemKind::Const(..), .. + }) + | hir::Node::ImplItem(hir::ImplItem { kind: hir::ImplItemKind::Const(..), .. }) => true, + + // These nodes do not have direct sub-exprs. + hir::Node::Param(_) + | hir::Node::Item(_) + | hir::Node::ForeignItem(_) + | hir::Node::TraitItem(_) + | hir::Node::ImplItem(_) + | hir::Node::Variant(_) + | hir::Node::Field(_) + | hir::Node::PathSegment(_) + | hir::Node::Ty(_) + | hir::Node::AssocItemConstraint(_) + | hir::Node::TraitRef(_) + | hir::Node::Pat(_) + | hir::Node::PatField(_) + | hir::Node::LetStmt(_) + | hir::Node::Synthetic + | hir::Node::Err(_) + | hir::Node::Ctor(_) + | hir::Node::Lifetime(_) + | hir::Node::GenericParam(_) + | hir::Node::Crate(_) + | hir::Node::Infer(_) + | hir::Node::WhereBoundPredicate(_) + | hir::Node::ArrayLenInfer(_) + | hir::Node::PreciseCapturingNonLifetimeArg(_) + | hir::Node::OpaqueTy(_) => { + unreachable!("no sub-expr expected for {parent_node:?}") + } + } + } + + /// Whether this pattern constitutes a read of value of the scrutinee that + /// it is matching against. + /// + /// See above for the nuances of what happens when this returns true. + pub(super) fn pat_constitutes_read(&self, pat: &hir::Pat<'_>) -> bool { + let mut does_read = false; + pat.walk(|pat| { + match pat.kind { + hir::PatKind::Wild | hir::PatKind::Never | hir::PatKind::Or(_) => { + // Recurse + true + } + hir::PatKind::Binding(_, _, _, _) + | hir::PatKind::Struct(_, _, _) + | hir::PatKind::TupleStruct(_, _, _) + | hir::PatKind::Path(_) + | hir::PatKind::Tuple(_, _) + | hir::PatKind::Box(_) + | hir::PatKind::Ref(_, _) + | hir::PatKind::Deref(_) + | hir::PatKind::Lit(_) + | hir::PatKind::Range(_, _, _) + | hir::PatKind::Slice(_, _, _) + | hir::PatKind::Err(_) => { + does_read = true; + // No need to continue. + false + } } - _ => true, - } + }); + does_read } #[instrument(skip(self, expr), level = "debug")] diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs index 824918d1fa222..c2e25d259c582 100644 --- a/compiler/rustc_hir_typeck/src/pat.rs +++ b/compiler/rustc_hir_typeck/src/pat.rs @@ -279,7 +279,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // All other patterns constitute a read, which causes us to diverge // if the type is never. - if ty.is_never() && !matches!(pat.kind, PatKind::Wild | PatKind::Never | PatKind::Or(_)) { + if ty.is_never() && self.pat_constitutes_read(pat) { self.diverges.set(self.diverges.get() | Diverges::always(pat.span)); } From e8d5eb2a2b6cdddd6725501e1b54a33c278d9697 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Fri, 6 Sep 2024 10:19:07 -0400 Subject: [PATCH 1922/2194] Be far more strict about what we consider to be a read of never --- compiler/rustc_hir_typeck/src/coercion.rs | 10 ++- compiler/rustc_hir_typeck/src/expr.rs | 87 ++++++++++--------- compiler/rustc_hir_typeck/src/pat.rs | 7 -- ...ocess_never.SimplifyLocals-final.after.mir | 4 +- ...rocess_void.SimplifyLocals-final.after.mir | 2 +- tests/mir-opt/uninhabited_enum.rs | 7 +- tests/ui/never_type/diverging-place-match.rs | 27 ++++++ .../never_type/diverging-place-match.stderr | 61 ++++++++++++- .../raw-ref-op/never-place-isnt-diverging.rs | 9 ++ .../never-place-isnt-diverging.stderr | 16 +++- .../reachable/unwarned-match-on-never.stderr | 2 +- 11 files changed, 177 insertions(+), 55 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs index 96bff04dbc7cf..642db3f36b586 100644 --- a/compiler/rustc_hir_typeck/src/coercion.rs +++ b/compiler/rustc_hir_typeck/src/coercion.rs @@ -1066,7 +1066,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let cause = cause.unwrap_or_else(|| self.cause(expr.span, ObligationCauseCode::ExprAssignable)); - let coerce = Coerce::new(self, cause, allow_two_phase, self.expr_constitutes_read(expr)); + let coerce = Coerce::new( + self, + cause, + allow_two_phase, + self.expr_guaranteed_to_constitute_read_for_never(expr), + ); let ok = self.commit_if_ok(|_| coerce.coerce(source, target))?; let (adjustments, _) = self.register_infer_ok_obligations(ok); @@ -1268,6 +1273,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // probably aren't processing function arguments here and even if we were, // they're going to get autorefed again anyway and we can apply 2-phase borrows // at that time. + // + // NOTE: we set `coerce_never` to `true` here because coercion LUBs only + // operate on values and not places, so a never coercion is valid. let mut coerce = Coerce::new(self, cause.clone(), AllowTwoPhase::No, true); coerce.use_lub = true; diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index cef00cf8ce865..2d71829537496 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -65,7 +65,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // While we don't allow *arbitrary* coercions here, we *do* allow // coercions from ! to `expected`. - if ty.is_never() && self.expr_constitutes_read(expr) { + if ty.is_never() && self.expr_guaranteed_to_constitute_read_for_never(expr) { if let Some(_) = self.typeck_results.borrow().adjustments().get(expr.hir_id) { let reported = self.dcx().span_delayed_bug( expr.span, @@ -245,7 +245,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // unless it's a place expression that isn't being read from, in which case // diverging would be unsound since we may never actually read the `!`. // e.g. `let _ = *never_ptr;` with `never_ptr: *const !`. - if ty.is_never() && self.expr_constitutes_read(expr) { + if ty.is_never() && self.expr_guaranteed_to_constitute_read_for_never(expr) { self.diverges.set(self.diverges.get() | Diverges::always(expr.span)); } @@ -274,10 +274,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// expression and the *parent* expression is the scrutinee of a match or /// the pointee of an `&` addr-of expression, since both of those parent /// expressions take a *place* and not a value. - /// - /// This function is unfortunately a bit heuristical, though it is certainly - /// far sounder than the prior status quo: . - pub(super) fn expr_constitutes_read(&self, expr: &'tcx hir::Expr<'tcx>) -> bool { + pub(super) fn expr_guaranteed_to_constitute_read_for_never( + &self, + expr: &'tcx hir::Expr<'tcx>, + ) -> bool { // We only care about place exprs. Anything else returns an immediate // which would constitute a read. We don't care about distinguishing // "syntactic" place exprs since if the base of a field projection is @@ -300,15 +300,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { expr.hir_id != lhs.hir_id } - // If we have a subpattern that performs a read, we want to consider this - // to diverge for compatibility to support something like `let x: () = *never_ptr;`. + // See note on `PatKind::Or` below for why this is `all`. ExprKind::Match(scrutinee, arms, _) => { assert_eq!(scrutinee.hir_id, expr.hir_id); - arms.iter().any(|arm| self.pat_constitutes_read(arm.pat)) + arms.iter() + .all(|arm| self.pat_guaranteed_to_constitute_read_for_never(arm.pat)) } ExprKind::Let(hir::LetExpr { init, pat, .. }) => { assert_eq!(init.hir_id, expr.hir_id); - self.pat_constitutes_read(*pat) + self.pat_guaranteed_to_constitute_read_for_never(*pat) } // Any expression child of these expressions constitute reads. @@ -349,7 +349,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // to diverge for compatibility to support something like `let x: () = *never_ptr;`. hir::Node::LetStmt(hir::LetStmt { init: Some(target), pat, .. }) => { assert_eq!(target.hir_id, expr.hir_id); - self.pat_constitutes_read(*pat) + self.pat_guaranteed_to_constitute_read_for_never(*pat) } // These nodes (if they have a sub-expr) do constitute a read. @@ -401,36 +401,45 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } /// Whether this pattern constitutes a read of value of the scrutinee that - /// it is matching against. + /// it is matching against. This is used to determine whether we should + /// perform `NeverToAny` coercions. /// /// See above for the nuances of what happens when this returns true. - pub(super) fn pat_constitutes_read(&self, pat: &hir::Pat<'_>) -> bool { - let mut does_read = false; - pat.walk(|pat| { - match pat.kind { - hir::PatKind::Wild | hir::PatKind::Never | hir::PatKind::Or(_) => { - // Recurse - true - } - hir::PatKind::Binding(_, _, _, _) - | hir::PatKind::Struct(_, _, _) - | hir::PatKind::TupleStruct(_, _, _) - | hir::PatKind::Path(_) - | hir::PatKind::Tuple(_, _) - | hir::PatKind::Box(_) - | hir::PatKind::Ref(_, _) - | hir::PatKind::Deref(_) - | hir::PatKind::Lit(_) - | hir::PatKind::Range(_, _, _) - | hir::PatKind::Slice(_, _, _) - | hir::PatKind::Err(_) => { - does_read = true; - // No need to continue. - false - } - } - }); - does_read + pub(super) fn pat_guaranteed_to_constitute_read_for_never(&self, pat: &hir::Pat<'_>) -> bool { + match pat.kind { + // Does not constitute a read. + hir::PatKind::Wild => false, + + // This is unnecessarily restrictive when the pattern that doesn't + // constitute a read is unreachable. + // + // For example `match *never_ptr { value => {}, _ => {} }` or + // `match *never_ptr { _ if false => {}, value => {} }`. + // + // It is however fine to be restrictive here; only returning `true` + // can lead to unsoundness. + hir::PatKind::Or(subpats) => { + subpats.iter().all(|pat| self.pat_guaranteed_to_constitute_read_for_never(pat)) + } + + // Does constitute a read, since it is equivalent to a discriminant read. + hir::PatKind::Never => true, + + // All of these constitute a read, or match on something that isn't `!`, + // which would require a `NeverToAny` coercion. + hir::PatKind::Binding(_, _, _, _) + | hir::PatKind::Struct(_, _, _) + | hir::PatKind::TupleStruct(_, _, _) + | hir::PatKind::Path(_) + | hir::PatKind::Tuple(_, _) + | hir::PatKind::Box(_) + | hir::PatKind::Ref(_, _) + | hir::PatKind::Deref(_) + | hir::PatKind::Lit(_) + | hir::PatKind::Range(_, _, _) + | hir::PatKind::Slice(_, _, _) + | hir::PatKind::Err(_) => true, + } } #[instrument(skip(self, expr), level = "debug")] diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs index c2e25d259c582..49c5a7d8a652d 100644 --- a/compiler/rustc_hir_typeck/src/pat.rs +++ b/compiler/rustc_hir_typeck/src/pat.rs @@ -27,7 +27,6 @@ use tracing::{debug, instrument, trace}; use ty::VariantDef; use super::report_unexpected_variant_res; -use crate::diverges::Diverges; use crate::gather_locals::DeclOrigin; use crate::{FnCtxt, LoweredTy, errors}; @@ -277,12 +276,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } }; - // All other patterns constitute a read, which causes us to diverge - // if the type is never. - if ty.is_never() && self.pat_constitutes_read(pat) { - self.diverges.set(self.diverges.get() | Diverges::always(pat.span)); - } - self.write_ty(pat.hir_id, ty); // (note_1): In most of the cases where (note_1) is referenced diff --git a/tests/mir-opt/uninhabited_enum.process_never.SimplifyLocals-final.after.mir b/tests/mir-opt/uninhabited_enum.process_never.SimplifyLocals-final.after.mir index 64fc81e298946..02e1f4be15e2e 100644 --- a/tests/mir-opt/uninhabited_enum.process_never.SimplifyLocals-final.after.mir +++ b/tests/mir-opt/uninhabited_enum.process_never.SimplifyLocals-final.after.mir @@ -4,10 +4,10 @@ fn process_never(_1: *const !) -> () { debug input => _1; let mut _0: (); scope 1 { - debug _input => _1; + debug _input => const (); } bb0: { - return; + unreachable; } } diff --git a/tests/mir-opt/uninhabited_enum.process_void.SimplifyLocals-final.after.mir b/tests/mir-opt/uninhabited_enum.process_void.SimplifyLocals-final.after.mir index 51514ba5e5d90..64711755f7394 100644 --- a/tests/mir-opt/uninhabited_enum.process_void.SimplifyLocals-final.after.mir +++ b/tests/mir-opt/uninhabited_enum.process_void.SimplifyLocals-final.after.mir @@ -4,7 +4,7 @@ fn process_void(_1: *const Void) -> () { debug input => _1; let mut _0: (); scope 1 { - debug _input => _1; + debug _input => const ZeroSized: Void; } bb0: { diff --git a/tests/mir-opt/uninhabited_enum.rs b/tests/mir-opt/uninhabited_enum.rs index 9d845e34fbda8..90b5353f29143 100644 --- a/tests/mir-opt/uninhabited_enum.rs +++ b/tests/mir-opt/uninhabited_enum.rs @@ -1,18 +1,21 @@ // skip-filecheck #![feature(never_type)] +#[derive(Copy, Clone)] pub enum Void {} // EMIT_MIR uninhabited_enum.process_never.SimplifyLocals-final.after.mir #[no_mangle] pub fn process_never(input: *const !) { - let _input = unsafe { &*input }; + let _input = unsafe { *input }; } // EMIT_MIR uninhabited_enum.process_void.SimplifyLocals-final.after.mir #[no_mangle] pub fn process_void(input: *const Void) { - let _input = unsafe { &*input }; + let _input = unsafe { *input }; + // In the future, this should end with `unreachable`, but we currently only do + // unreachability analysis for `!`. } fn main() {} diff --git a/tests/ui/never_type/diverging-place-match.rs b/tests/ui/never_type/diverging-place-match.rs index 185e17c05a773..b9bc29a218c4a 100644 --- a/tests/ui/never_type/diverging-place-match.rs +++ b/tests/ui/never_type/diverging-place-match.rs @@ -44,4 +44,31 @@ fn field_projection() -> ! { } } +fn covered_arm() -> ! { + unsafe { + //~^ ERROR mismatched types + let x: *const ! = 0 as _; + let (_ | 1i32) = *x; + //~^ ERROR mismatched types + } +} + +// FIXME: This *could* be considered a read of `!`, but we're not that sophisticated.. +fn uncovered_arm() -> ! { + unsafe { + //~^ ERROR mismatched types + let x: *const ! = 0 as _; + let (1i32 | _) = *x; + //~^ ERROR mismatched types + } +} + +fn coerce_ref_binding() -> ! { + unsafe { + let x: *const ! = 0 as _; + let ref _x: () = *x; + //~^ ERROR mismatched types + } +} + fn main() {} diff --git a/tests/ui/never_type/diverging-place-match.stderr b/tests/ui/never_type/diverging-place-match.stderr index 14b14f4270131..74e1bfa0a6b64 100644 --- a/tests/ui/never_type/diverging-place-match.stderr +++ b/tests/ui/never_type/diverging-place-match.stderr @@ -78,6 +78,65 @@ LL | | } = note: expected type `!` found unit type `()` -error: aborting due to 6 previous errors +error[E0308]: mismatched types + --> $DIR/diverging-place-match.rs:51:18 + | +LL | let (_ | 1i32) = *x; + | ^^^^ -- this expression has type `!` + | | + | expected `!`, found `i32` + | + = note: expected type `!` + found type `i32` + +error[E0308]: mismatched types + --> $DIR/diverging-place-match.rs:48:5 + | +LL | / unsafe { +LL | | +LL | | let x: *const ! = 0 as _; +LL | | let (_ | 1i32) = *x; +LL | | +LL | | } + | |_____^ expected `!`, found `()` + | + = note: expected type `!` + found unit type `()` + +error[E0308]: mismatched types + --> $DIR/diverging-place-match.rs:61:14 + | +LL | let (1i32 | _) = *x; + | ^^^^ -- this expression has type `!` + | | + | expected `!`, found `i32` + | + = note: expected type `!` + found type `i32` + +error[E0308]: mismatched types + --> $DIR/diverging-place-match.rs:58:5 + | +LL | / unsafe { +LL | | +LL | | let x: *const ! = 0 as _; +LL | | let (1i32 | _) = *x; +LL | | +LL | | } + | |_____^ expected `!`, found `()` + | + = note: expected type `!` + found unit type `()` + +error[E0308]: mismatched types + --> $DIR/diverging-place-match.rs:69:26 + | +LL | let ref _x: () = *x; + | ^^ expected `()`, found `!` + | + = note: expected unit type `()` + found type `!` + +error: aborting due to 11 previous errors For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/raw-ref-op/never-place-isnt-diverging.rs b/tests/ui/raw-ref-op/never-place-isnt-diverging.rs index 52f4158dbc988..80d441729f746 100644 --- a/tests/ui/raw-ref-op/never-place-isnt-diverging.rs +++ b/tests/ui/raw-ref-op/never-place-isnt-diverging.rs @@ -10,4 +10,13 @@ fn make_up_a_value() -> T { } } + +fn make_up_a_pointer() -> *const T { + unsafe { + let x: *const ! = 0 as _; + &raw const *x + //~^ ERROR mismatched types + } +} + fn main() {} diff --git a/tests/ui/raw-ref-op/never-place-isnt-diverging.stderr b/tests/ui/raw-ref-op/never-place-isnt-diverging.stderr index 9eba57dde8fa7..af9e788982179 100644 --- a/tests/ui/raw-ref-op/never-place-isnt-diverging.stderr +++ b/tests/ui/raw-ref-op/never-place-isnt-diverging.stderr @@ -15,6 +15,20 @@ LL | | } = note: expected type parameter `T` found unit type `()` -error: aborting due to 1 previous error +error[E0308]: mismatched types + --> $DIR/never-place-isnt-diverging.rs:17:9 + | +LL | fn make_up_a_pointer() -> *const T { + | - -------- expected `*const T` because of return type + | | + | expected this type parameter +... +LL | &raw const *x + | ^^^^^^^^^^^^^ expected `*const T`, found `*const !` + | + = note: expected raw pointer `*const T` + found raw pointer `*const !` + +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/reachable/unwarned-match-on-never.stderr b/tests/ui/reachable/unwarned-match-on-never.stderr index c1ad3511b4e08..a296d2a055e09 100644 --- a/tests/ui/reachable/unwarned-match-on-never.stderr +++ b/tests/ui/reachable/unwarned-match-on-never.stderr @@ -2,7 +2,7 @@ error: unreachable expression --> $DIR/unwarned-match-on-never.rs:10:5 | LL | match x {} - | ---------- any code following this expression is unreachable + | - any code following this expression is unreachable LL | // But matches in unreachable code are warned. LL | match x {} | ^^^^^^^^^^ unreachable expression From 3743618c13d9f4afb06c9778b05b75e879b6919c Mon Sep 17 00:00:00 2001 From: Taiki Endo Date: Sun, 6 Oct 2024 08:14:44 +0900 Subject: [PATCH 1923/2194] Support clobber_abi in MSP430 inline assembly --- compiler/rustc_target/src/asm/mod.rs | 10 ++++++++ tests/codegen/asm-msp430-clobbers.rs | 36 ++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+) create mode 100644 tests/codegen/asm-msp430-clobbers.rs diff --git a/compiler/rustc_target/src/asm/mod.rs b/compiler/rustc_target/src/asm/mod.rs index df13d24cb9e21..73ae1ae96ae23 100644 --- a/compiler/rustc_target/src/asm/mod.rs +++ b/compiler/rustc_target/src/asm/mod.rs @@ -893,6 +893,7 @@ pub enum InlineAsmClobberAbi { RiscV, LoongArch, S390x, + Msp430, } impl InlineAsmClobberAbi { @@ -946,6 +947,10 @@ impl InlineAsmClobberAbi { "C" | "system" => Ok(InlineAsmClobberAbi::S390x), _ => Err(&["C", "system"]), }, + InlineAsmArch::Msp430 => match name { + "C" | "system" => Ok(InlineAsmClobberAbi::Msp430), + _ => Err(&["C", "system"]), + }, _ => Err(&[]), } } @@ -1125,6 +1130,11 @@ impl InlineAsmClobberAbi { a8, a9, a10, a11, a12, a13, a14, a15, } }, + InlineAsmClobberAbi::Msp430 => clobbered_regs! { + Msp430 Msp430InlineAsmReg { + r11, r12, r13, r14, r15, + } + }, } } } diff --git a/tests/codegen/asm-msp430-clobbers.rs b/tests/codegen/asm-msp430-clobbers.rs new file mode 100644 index 0000000000000..c00c04f3088cb --- /dev/null +++ b/tests/codegen/asm-msp430-clobbers.rs @@ -0,0 +1,36 @@ +//@ assembly-output: emit-asm +//@ compile-flags: --target msp430-none-elf +//@ needs-llvm-components: msp430 + +#![crate_type = "rlib"] +#![feature(no_core, rustc_attrs, lang_items, asm_experimental_arch)] +#![no_core] + +#[lang = "sized"] +trait Sized {} + +#[rustc_builtin_macro] +macro_rules! asm { + () => {}; +} + +// CHECK-LABEL: @sr_clobber +// CHECK: call void asm sideeffect "", "~{sr}"() +#[no_mangle] +pub unsafe fn sr_clobber() { + asm!("", options(nostack, nomem)); +} + +// CHECK-LABEL: @no_clobber +// CHECK: call void asm sideeffect "", ""() +#[no_mangle] +pub unsafe fn no_clobber() { + asm!("", options(nostack, nomem, preserves_flags)); +} + +// CHECK-LABEL: @clobber_abi +// CHECK: asm sideeffect "", "={r11},={r12},={r13},={r14},={r15}"() +#[no_mangle] +pub unsafe fn clobber_abi() { + asm!("", clobber_abi("C"), options(nostack, nomem, preserves_flags)); +} From 7f5548fa8b22bccdadb3cbe7cf4d566a970eeb25 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sun, 6 Oct 2024 01:44:59 +0000 Subject: [PATCH 1924/2194] On function and method calls in patterns, link to the book ``` error: expected a pattern, found an expression --> f889.rs:3:13 | 3 | let (x, y.drop()) = (1, 2); //~ ERROR | ^^^^^^^^ not a pattern | = note: arbitrary expressions are not allowed in patterns: error[E0532]: expected a pattern, found a function call --> f889.rs:2:13 | 2 | let (x, drop(y)) = (1, 2); //~ ERROR | ^^^^ not a tuple struct or tuple variant | = note: function calls are not allowed in patterns: ``` Fix #97200. --- compiler/rustc_parse/messages.ftl | 3 +- compiler/rustc_parse/src/errors.rs | 1 + .../rustc_resolve/src/late/diagnostics.rs | 13 +++ .../range_pat_interactions1.stderr | 3 +- .../range_pat_interactions2.stderr | 3 +- tests/ui/parser/bad-name.stderr | 4 +- tests/ui/parser/issues/issue-24197.stderr | 4 +- tests/ui/parser/issues/issue-24375.stderr | 3 +- tests/ui/parser/pat-lt-bracket-5.stderr | 4 +- tests/ui/parser/pat-lt-bracket-6.stderr | 4 +- tests/ui/parser/pat-ranges-3.stderr | 8 +- .../parser/recover/recover-pat-exprs.stderr | 103 ++++++++++++------ .../parser/recover/recover-pat-issues.stderr | 18 ++- .../ui/parser/recover/recover-pat-lets.stderr | 18 ++- .../parser/recover/recover-pat-ranges.stderr | 18 ++- .../recover/recover-pat-wildcards.stderr | 3 +- tests/ui/resolve/issue-10200.rs | 2 +- tests/ui/resolve/issue-10200.stderr | 4 +- ...s-in-pattern-with-ty-err-doesnt-ice.stderr | 4 +- 19 files changed, 156 insertions(+), 64 deletions(-) diff --git a/compiler/rustc_parse/messages.ftl b/compiler/rustc_parse/messages.ftl index 5d1c300b45357..948199fd55c65 100644 --- a/compiler/rustc_parse/messages.ftl +++ b/compiler/rustc_parse/messages.ftl @@ -812,7 +812,8 @@ parse_unexpected_expr_in_pat = *[false] a pattern }, found an expression - .label = arbitrary expressions are not allowed in patterns + .label = not a pattern + .note = arbitrary expressions are not allowed in patterns: parse_unexpected_expr_in_pat_const_sugg = consider extracting the expression into a `const` diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs index 40502158469f0..dade39127515f 100644 --- a/compiler/rustc_parse/src/errors.rs +++ b/compiler/rustc_parse/src/errors.rs @@ -2608,6 +2608,7 @@ pub(crate) struct ExpectedCommaAfterPatternField { #[derive(Diagnostic)] #[diag(parse_unexpected_expr_in_pat)] +#[note] pub(crate) struct UnexpectedExpressionInPattern { /// The unexpected expr's span. #[primary_span] diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index 35d166e8b4ab3..fce5ec36c661b 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -443,6 +443,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { self.suggest_bare_struct_literal(&mut err); self.suggest_changing_type_to_const_param(&mut err, res, source, span); + self.explain_functions_in_pattern(&mut err, res, source); if self.suggest_pattern_match_with_let(&mut err, source, span) { // Fallback label. @@ -1166,6 +1167,18 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { } } + fn explain_functions_in_pattern( + &mut self, + err: &mut Diag<'_>, + res: Option, + source: PathSource<'_>, + ) { + let PathSource::TupleStruct(_, _) = source else { return }; + let Some(Res::Def(DefKind::Fn, _)) = res else { return }; + err.primary_message("expected a pattern, found a function call"); + err.note("function calls are not allowed in patterns: "); + } + fn suggest_changing_type_to_const_param( &mut self, err: &mut Diag<'_>, diff --git a/tests/ui/half-open-range-patterns/range_pat_interactions1.stderr b/tests/ui/half-open-range-patterns/range_pat_interactions1.stderr index 9831348de7569..e2916725fbd90 100644 --- a/tests/ui/half-open-range-patterns/range_pat_interactions1.stderr +++ b/tests/ui/half-open-range-patterns/range_pat_interactions1.stderr @@ -2,8 +2,9 @@ error: expected a pattern range bound, found an expression --> $DIR/range_pat_interactions1.rs:17:16 | LL | 0..5+1 => errors_only.push(x), - | ^^^ arbitrary expressions are not allowed in patterns + | ^^^ not a pattern | + = note: arbitrary expressions are not allowed in patterns: help: consider extracting the expression into a `const` | LL + const VAL: /* Type */ = 5+1; diff --git a/tests/ui/half-open-range-patterns/range_pat_interactions2.stderr b/tests/ui/half-open-range-patterns/range_pat_interactions2.stderr index 1b5e875cccb68..f54e07c3a6370 100644 --- a/tests/ui/half-open-range-patterns/range_pat_interactions2.stderr +++ b/tests/ui/half-open-range-patterns/range_pat_interactions2.stderr @@ -14,8 +14,9 @@ error: expected a pattern range bound, found an expression --> $DIR/range_pat_interactions2.rs:10:18 | LL | 0..=(5+1) => errors_only.push(x), - | ^^^ arbitrary expressions are not allowed in patterns + | ^^^ not a pattern | + = note: arbitrary expressions are not allowed in patterns: help: consider extracting the expression into a `const` | LL + const VAL: /* Type */ = 5+1; diff --git a/tests/ui/parser/bad-name.stderr b/tests/ui/parser/bad-name.stderr index 3fc416dd5311f..5ca248380ee5b 100644 --- a/tests/ui/parser/bad-name.stderr +++ b/tests/ui/parser/bad-name.stderr @@ -8,7 +8,9 @@ error: expected a pattern, found an expression --> $DIR/bad-name.rs:2:7 | LL | let x.y::.z foo; - | ^^^^^^^^^^^^^^ arbitrary expressions are not allowed in patterns + | ^^^^^^^^^^^^^^ not a pattern + | + = note: arbitrary expressions are not allowed in patterns: error: expected one of `(`, `.`, `::`, `:`, `;`, `=`, `?`, `|`, or an operator, found `foo` --> $DIR/bad-name.rs:2:22 diff --git a/tests/ui/parser/issues/issue-24197.stderr b/tests/ui/parser/issues/issue-24197.stderr index 7ebbf4ac370d7..c92e165b23b65 100644 --- a/tests/ui/parser/issues/issue-24197.stderr +++ b/tests/ui/parser/issues/issue-24197.stderr @@ -2,7 +2,9 @@ error: expected a pattern, found an expression --> $DIR/issue-24197.rs:2:9 | LL | let buf[0] = 0; - | ^^^^^^ arbitrary expressions are not allowed in patterns + | ^^^^^^ not a pattern + | + = note: arbitrary expressions are not allowed in patterns: error: aborting due to 1 previous error diff --git a/tests/ui/parser/issues/issue-24375.stderr b/tests/ui/parser/issues/issue-24375.stderr index a25c277d78a5b..fef3fcde7b799 100644 --- a/tests/ui/parser/issues/issue-24375.stderr +++ b/tests/ui/parser/issues/issue-24375.stderr @@ -2,8 +2,9 @@ error: expected a pattern, found an expression --> $DIR/issue-24375.rs:6:9 | LL | tmp[0] => {} - | ^^^^^^ arbitrary expressions are not allowed in patterns + | ^^^^^^ not a pattern | + = note: arbitrary expressions are not allowed in patterns: help: consider moving the expression to a match arm guard | LL | val if val == tmp[0] => {} diff --git a/tests/ui/parser/pat-lt-bracket-5.stderr b/tests/ui/parser/pat-lt-bracket-5.stderr index 18cf2df028216..a2a972652d188 100644 --- a/tests/ui/parser/pat-lt-bracket-5.stderr +++ b/tests/ui/parser/pat-lt-bracket-5.stderr @@ -2,7 +2,9 @@ error: expected a pattern, found an expression --> $DIR/pat-lt-bracket-5.rs:2:9 | LL | let v[0] = v[1]; - | ^^^^ arbitrary expressions are not allowed in patterns + | ^^^^ not a pattern + | + = note: arbitrary expressions are not allowed in patterns: error[E0425]: cannot find value `v` in this scope --> $DIR/pat-lt-bracket-5.rs:2:16 diff --git a/tests/ui/parser/pat-lt-bracket-6.stderr b/tests/ui/parser/pat-lt-bracket-6.stderr index 892883c4aedca..14ae602fedfa1 100644 --- a/tests/ui/parser/pat-lt-bracket-6.stderr +++ b/tests/ui/parser/pat-lt-bracket-6.stderr @@ -2,7 +2,9 @@ error: expected a pattern, found an expression --> $DIR/pat-lt-bracket-6.rs:5:14 | LL | let Test(&desc[..]) = x; - | ^^^^^^^^^ arbitrary expressions are not allowed in patterns + | ^^^^^^^^^ not a pattern + | + = note: arbitrary expressions are not allowed in patterns: error[E0308]: mismatched types --> $DIR/pat-lt-bracket-6.rs:10:30 diff --git a/tests/ui/parser/pat-ranges-3.stderr b/tests/ui/parser/pat-ranges-3.stderr index 5e1f35d1b6f9a..ef080368e19ca 100644 --- a/tests/ui/parser/pat-ranges-3.stderr +++ b/tests/ui/parser/pat-ranges-3.stderr @@ -2,13 +2,17 @@ error: expected a pattern range bound, found an expression --> $DIR/pat-ranges-3.rs:4:16 | LL | let 10 ..= 10 + 3 = 12; - | ^^^^^^ arbitrary expressions are not allowed in patterns + | ^^^^^^ not a pattern + | + = note: arbitrary expressions are not allowed in patterns: error: expected a pattern range bound, found an expression --> $DIR/pat-ranges-3.rs:7:9 | LL | let 10 - 3 ..= 10 = 8; - | ^^^^^^ arbitrary expressions are not allowed in patterns + | ^^^^^^ not a pattern + | + = note: arbitrary expressions are not allowed in patterns: error: aborting due to 2 previous errors diff --git a/tests/ui/parser/recover/recover-pat-exprs.stderr b/tests/ui/parser/recover/recover-pat-exprs.stderr index 63956f35c079f..6cb3753de8d17 100644 --- a/tests/ui/parser/recover/recover-pat-exprs.stderr +++ b/tests/ui/parser/recover/recover-pat-exprs.stderr @@ -2,8 +2,9 @@ error: expected a pattern, found an expression --> $DIR/recover-pat-exprs.rs:5:9 | LL | x.y => (), - | ^^^ arbitrary expressions are not allowed in patterns + | ^^^ not a pattern | + = note: arbitrary expressions are not allowed in patterns: help: consider moving the expression to a match arm guard | LL | val if val == x.y => (), @@ -24,8 +25,9 @@ error: expected a pattern, found an expression --> $DIR/recover-pat-exprs.rs:6:9 | LL | x.0 => (), - | ^^^ arbitrary expressions are not allowed in patterns + | ^^^ not a pattern | + = note: arbitrary expressions are not allowed in patterns: help: consider moving the expression to a match arm guard | LL | val if val == x.0 => (), @@ -47,8 +49,9 @@ error: expected a pattern, found an expression --> $DIR/recover-pat-exprs.rs:7:9 | LL | x._0 => (), - | ^^^^ arbitrary expressions are not allowed in patterns + | ^^^^ not a pattern | + = note: arbitrary expressions are not allowed in patterns: help: consider moving the expression to a match arm guard | LL | val if val == x._0 => (), @@ -71,8 +74,9 @@ error: expected a pattern, found an expression --> $DIR/recover-pat-exprs.rs:8:9 | LL | x.0.1 => (), - | ^^^^^ arbitrary expressions are not allowed in patterns + | ^^^^^ not a pattern | + = note: arbitrary expressions are not allowed in patterns: help: consider moving the expression to a match arm guard | LL | val if val == x.0.1 => (), @@ -95,8 +99,9 @@ error: expected a pattern, found an expression --> $DIR/recover-pat-exprs.rs:9:9 | LL | x.4.y.17.__z => (), - | ^^^^^^^^^^^^ arbitrary expressions are not allowed in patterns + | ^^^^^^^^^^^^ not a pattern | + = note: arbitrary expressions are not allowed in patterns: help: consider moving the expression to a match arm guard | LL | val if val == x.4.y.17.__z => (), @@ -149,8 +154,9 @@ error: expected a pattern, found an expression --> $DIR/recover-pat-exprs.rs:23:9 | LL | x[0] => (), - | ^^^^ arbitrary expressions are not allowed in patterns + | ^^^^ not a pattern | + = note: arbitrary expressions are not allowed in patterns: help: consider moving the expression to a match arm guard | LL | val if val == x[0] => (), @@ -170,8 +176,9 @@ error: expected a pattern, found an expression --> $DIR/recover-pat-exprs.rs:24:9 | LL | x[..] => (), - | ^^^^^ arbitrary expressions are not allowed in patterns + | ^^^^^ not a pattern | + = note: arbitrary expressions are not allowed in patterns: help: consider moving the expression to a match arm guard | LL | val if val == x[..] => (), @@ -219,8 +226,9 @@ error: expected a pattern, found an expression --> $DIR/recover-pat-exprs.rs:37:9 | LL | x.f() => (), - | ^^^^^ arbitrary expressions are not allowed in patterns + | ^^^^^ not a pattern | + = note: arbitrary expressions are not allowed in patterns: help: consider moving the expression to a match arm guard | LL | val if val == x.f() => (), @@ -240,8 +248,9 @@ error: expected a pattern, found an expression --> $DIR/recover-pat-exprs.rs:38:9 | LL | x._f() => (), - | ^^^^^^ arbitrary expressions are not allowed in patterns + | ^^^^^^ not a pattern | + = note: arbitrary expressions are not allowed in patterns: help: consider moving the expression to a match arm guard | LL | val if val == x._f() => (), @@ -262,8 +271,9 @@ error: expected a pattern, found an expression --> $DIR/recover-pat-exprs.rs:39:9 | LL | x? => (), - | ^^ arbitrary expressions are not allowed in patterns + | ^^ not a pattern | + = note: arbitrary expressions are not allowed in patterns: help: consider moving the expression to a match arm guard | LL | val if val == x? => (), @@ -285,8 +295,9 @@ error: expected a pattern, found an expression --> $DIR/recover-pat-exprs.rs:40:9 | LL | ().f() => (), - | ^^^^^^ arbitrary expressions are not allowed in patterns + | ^^^^^^ not a pattern | + = note: arbitrary expressions are not allowed in patterns: help: consider moving the expression to a match arm guard | LL | val if val == ().f() => (), @@ -309,8 +320,9 @@ error: expected a pattern, found an expression --> $DIR/recover-pat-exprs.rs:41:9 | LL | (0, x)?.f() => (), - | ^^^^^^^^^^^ arbitrary expressions are not allowed in patterns + | ^^^^^^^^^^^ not a pattern | + = note: arbitrary expressions are not allowed in patterns: help: consider moving the expression to a match arm guard | LL | val if val == (0, x)?.f() => (), @@ -333,8 +345,9 @@ error: expected a pattern, found an expression --> $DIR/recover-pat-exprs.rs:42:9 | LL | x.f().g() => (), - | ^^^^^^^^^ arbitrary expressions are not allowed in patterns + | ^^^^^^^^^ not a pattern | + = note: arbitrary expressions are not allowed in patterns: help: consider moving the expression to a match arm guard | LL | val if val == x.f().g() => (), @@ -357,8 +370,9 @@ error: expected a pattern, found an expression --> $DIR/recover-pat-exprs.rs:43:9 | LL | 0.f()?.g()?? => (), - | ^^^^^^^^^^^^ arbitrary expressions are not allowed in patterns + | ^^^^^^^^^^^^ not a pattern | + = note: arbitrary expressions are not allowed in patterns: help: consider moving the expression to a match arm guard | LL | val if val == 0.f()?.g()?? => (), @@ -381,8 +395,9 @@ error: expected a pattern, found an expression --> $DIR/recover-pat-exprs.rs:50:9 | LL | x as usize => (), - | ^^^^^^^^^^ arbitrary expressions are not allowed in patterns + | ^^^^^^^^^^ not a pattern | + = note: arbitrary expressions are not allowed in patterns: help: consider moving the expression to a match arm guard | LL | val if val == x as usize => (), @@ -402,8 +417,9 @@ error: expected a pattern, found an expression --> $DIR/recover-pat-exprs.rs:51:9 | LL | 0 as usize => (), - | ^^^^^^^^^^ arbitrary expressions are not allowed in patterns + | ^^^^^^^^^^ not a pattern | + = note: arbitrary expressions are not allowed in patterns: help: consider moving the expression to a match arm guard | LL | val if val == 0 as usize => (), @@ -424,8 +440,9 @@ error: expected a pattern, found an expression --> $DIR/recover-pat-exprs.rs:52:9 | LL | x.f().0.4 as f32 => (), - | ^^^^^^^^^^^^^^^^ arbitrary expressions are not allowed in patterns + | ^^^^^^^^^^^^^^^^ not a pattern | + = note: arbitrary expressions are not allowed in patterns: help: consider moving the expression to a match arm guard | LL | val if val == x.f().0.4 as f32 => (), @@ -447,8 +464,9 @@ error: expected a pattern, found an expression --> $DIR/recover-pat-exprs.rs:59:9 | LL | 1 + 1 => (), - | ^^^^^ arbitrary expressions are not allowed in patterns + | ^^^^^ not a pattern | + = note: arbitrary expressions are not allowed in patterns: help: consider moving the expression to a match arm guard | LL | val if val == 1 + 1 => (), @@ -468,8 +486,9 @@ error: expected a pattern, found an expression --> $DIR/recover-pat-exprs.rs:60:9 | LL | (1 + 2) * 3 => (), - | ^^^^^^^^^^^ arbitrary expressions are not allowed in patterns + | ^^^^^^^^^^^ not a pattern | + = note: arbitrary expressions are not allowed in patterns: help: consider moving the expression to a match arm guard | LL | val if val == (1 + 2) * 3 => (), @@ -490,8 +509,9 @@ error: expected a pattern, found an expression --> $DIR/recover-pat-exprs.rs:63:9 | LL | x.0 > 2 => (), - | ^^^^^^^ arbitrary expressions are not allowed in patterns + | ^^^^^^^ not a pattern | + = note: arbitrary expressions are not allowed in patterns: help: consider moving the expression to a match arm guard | LL | val if val == (x.0 > 2) => (), @@ -514,8 +534,9 @@ error: expected a pattern, found an expression --> $DIR/recover-pat-exprs.rs:64:9 | LL | x.0 == 2 => (), - | ^^^^^^^^ arbitrary expressions are not allowed in patterns + | ^^^^^^^^ not a pattern | + = note: arbitrary expressions are not allowed in patterns: help: consider moving the expression to a match arm guard | LL | val if val == (x.0 == 2) => (), @@ -538,8 +559,9 @@ error: expected a pattern, found an expression --> $DIR/recover-pat-exprs.rs:69:13 | LL | (x, y.0 > 2) if x != 0 => (), - | ^^^^^^^ arbitrary expressions are not allowed in patterns + | ^^^^^^^ not a pattern | + = note: arbitrary expressions are not allowed in patterns: help: consider moving the expression to the match arm guard | LL | (x, val) if x != 0 && val == (y.0 > 2) => (), @@ -559,8 +581,9 @@ error: expected a pattern, found an expression --> $DIR/recover-pat-exprs.rs:70:13 | LL | (x, y.0 > 2) if x != 0 || x != 1 => (), - | ^^^^^^^ arbitrary expressions are not allowed in patterns + | ^^^^^^^ not a pattern | + = note: arbitrary expressions are not allowed in patterns: help: consider moving the expression to the match arm guard | LL | (x, val) if (x != 0 || x != 1) && val == (y.0 > 2) => (), @@ -598,8 +621,9 @@ error: expected a pattern, found an expression --> $DIR/recover-pat-exprs.rs:81:9 | LL | u8::MAX.abs() => (), - | ^^^^^^^^^^^^^ arbitrary expressions are not allowed in patterns + | ^^^^^^^^^^^^^ not a pattern | + = note: arbitrary expressions are not allowed in patterns: help: consider moving the expression to a match arm guard | LL | val if val == u8::MAX.abs() => (), @@ -619,8 +643,9 @@ error: expected a pattern, found an expression --> $DIR/recover-pat-exprs.rs:86:17 | LL | z @ w @ v.u() => (), - | ^^^^^ arbitrary expressions are not allowed in patterns + | ^^^^^ not a pattern | + = note: arbitrary expressions are not allowed in patterns: help: consider moving the expression to a match arm guard | LL | z @ w @ val if val == v.u() => (), @@ -643,8 +668,9 @@ error: expected a pattern, found an expression --> $DIR/recover-pat-exprs.rs:88:9 | LL | y.ilog(3) => (), - | ^^^^^^^^^ arbitrary expressions are not allowed in patterns + | ^^^^^^^^^ not a pattern | + = note: arbitrary expressions are not allowed in patterns: help: consider moving the expression to a match arm guard | LL | val if val == y.ilog(3) => (), @@ -667,8 +693,9 @@ error: expected a pattern, found an expression --> $DIR/recover-pat-exprs.rs:90:9 | LL | n + 1 => (), - | ^^^^^ arbitrary expressions are not allowed in patterns + | ^^^^^ not a pattern | + = note: arbitrary expressions are not allowed in patterns: help: consider moving the expression to a match arm guard | LL | val if val == n + 1 => (), @@ -691,8 +718,9 @@ error: expected a pattern, found an expression --> $DIR/recover-pat-exprs.rs:92:10 | LL | ("".f() + 14 * 8) => (), - | ^^^^^^^^^^^^^^^ arbitrary expressions are not allowed in patterns + | ^^^^^^^^^^^^^^^ not a pattern | + = note: arbitrary expressions are not allowed in patterns: help: consider moving the expression to a match arm guard | LL | (val) if val == "".f() + 14 * 8 => (), @@ -715,8 +743,9 @@ error: expected a pattern, found an expression --> $DIR/recover-pat-exprs.rs:95:9 | LL | f?() => (), - | ^^^^ arbitrary expressions are not allowed in patterns + | ^^^^ not a pattern | + = note: arbitrary expressions are not allowed in patterns: help: consider moving the expression to a match arm guard | LL | val if val == f?() => (), @@ -739,7 +768,9 @@ error: expected a pattern, found an expression --> $DIR/recover-pat-exprs.rs:101:9 | LL | let 1 + 1 = 2; - | ^^^^^ arbitrary expressions are not allowed in patterns + | ^^^^^ not a pattern + | + = note: arbitrary expressions are not allowed in patterns: error: expected one of `)`, `,`, `@`, or `|`, found `*` --> $DIR/recover-pat-exprs.rs:104:28 @@ -754,19 +785,25 @@ error: expected a pattern, found an expression --> $DIR/recover-pat-exprs.rs:60:10 | LL | (1 + 2) * 3 => (), - | ^^^^^ arbitrary expressions are not allowed in patterns + | ^^^^^ not a pattern + | + = note: arbitrary expressions are not allowed in patterns: error: expected a pattern, found an expression --> $DIR/recover-pat-exprs.rs:75:5 | LL | 1 + 2 * PI.cos() => 2, - | ^^^^^^^^^^^^^^^^ arbitrary expressions are not allowed in patterns + | ^^^^^^^^^^^^^^^^ not a pattern + | + = note: arbitrary expressions are not allowed in patterns: error: expected a pattern, found an expression --> $DIR/recover-pat-exprs.rs:83:9 | LL | x.sqrt() @ .. => (), - | ^^^^^^^^ arbitrary expressions are not allowed in patterns + | ^^^^^^^^ not a pattern + | + = note: arbitrary expressions are not allowed in patterns: error: aborting due to 45 previous errors diff --git a/tests/ui/parser/recover/recover-pat-issues.stderr b/tests/ui/parser/recover/recover-pat-issues.stderr index 596bff2139525..17cb7b4aead80 100644 --- a/tests/ui/parser/recover/recover-pat-issues.stderr +++ b/tests/ui/parser/recover/recover-pat-issues.stderr @@ -2,8 +2,9 @@ error: expected a pattern, found an expression --> $DIR/recover-pat-issues.rs:6:13 | LL | Foo("hi".to_owned()) => true, - | ^^^^^^^^^^^^^^^ arbitrary expressions are not allowed in patterns + | ^^^^^^^^^^^^^^^ not a pattern | + = note: arbitrary expressions are not allowed in patterns: help: consider moving the expression to a match arm guard | LL | Foo(val) if val == "hi".to_owned() => true, @@ -23,8 +24,9 @@ error: expected a pattern, found an expression --> $DIR/recover-pat-issues.rs:14:20 | LL | Bar { baz: "hi".to_owned() } => true, - | ^^^^^^^^^^^^^^^ arbitrary expressions are not allowed in patterns + | ^^^^^^^^^^^^^^^ not a pattern | + = note: arbitrary expressions are not allowed in patterns: help: consider moving the expression to a match arm guard | LL | Bar { baz } if baz == "hi".to_owned() => true, @@ -44,8 +46,9 @@ error: expected a pattern, found an expression --> $DIR/recover-pat-issues.rs:25:11 | LL | &["foo".to_string()] => {} - | ^^^^^^^^^^^^^^^^^ arbitrary expressions are not allowed in patterns + | ^^^^^^^^^^^^^^^^^ not a pattern | + = note: arbitrary expressions are not allowed in patterns: help: consider moving the expression to a match arm guard | LL | &[val] if val == "foo".to_string() => {} @@ -65,8 +68,9 @@ error: expected a pattern, found an expression --> $DIR/recover-pat-issues.rs:36:17 | LL | if let Some(MAGIC.0 as usize) = None:: {} - | ^^^^^^^^^^^^^^^^ arbitrary expressions are not allowed in patterns + | ^^^^^^^^^^^^^^^^ not a pattern | + = note: arbitrary expressions are not allowed in patterns: help: consider extracting the expression into a `const` | LL + const VAL: /* Type */ = MAGIC.0 as usize; @@ -81,8 +85,9 @@ error: expected a pattern, found an expression --> $DIR/recover-pat-issues.rs:41:13 | LL | if let (-1.some(4)) = (0, Some(4)) {} - | ^^^^^^^^^^ arbitrary expressions are not allowed in patterns + | ^^^^^^^^^^ not a pattern | + = note: arbitrary expressions are not allowed in patterns: help: consider extracting the expression into a `const` | LL + const VAL: /* Type */ = -1.some(4); @@ -97,8 +102,9 @@ error: expected a pattern, found an expression --> $DIR/recover-pat-issues.rs:44:13 | LL | if let (-1.Some(4)) = (0, Some(4)) {} - | ^^^^^^^^^^ arbitrary expressions are not allowed in patterns + | ^^^^^^^^^^ not a pattern | + = note: arbitrary expressions are not allowed in patterns: help: consider extracting the expression into a `const` | LL + const VAL: /* Type */ = -1.Some(4); diff --git a/tests/ui/parser/recover/recover-pat-lets.stderr b/tests/ui/parser/recover/recover-pat-lets.stderr index e54586b092483..b481813b24621 100644 --- a/tests/ui/parser/recover/recover-pat-lets.stderr +++ b/tests/ui/parser/recover/recover-pat-lets.stderr @@ -2,26 +2,33 @@ error: expected a pattern, found an expression --> $DIR/recover-pat-lets.rs:4:9 | LL | let x.expect("foo"); - | ^^^^^^^^^^^^^^^ arbitrary expressions are not allowed in patterns + | ^^^^^^^^^^^^^^^ not a pattern + | + = note: arbitrary expressions are not allowed in patterns: error: expected a pattern, found an expression --> $DIR/recover-pat-lets.rs:7:9 | LL | let x.unwrap(): u32; - | ^^^^^^^^^^ arbitrary expressions are not allowed in patterns + | ^^^^^^^^^^ not a pattern + | + = note: arbitrary expressions are not allowed in patterns: error: expected a pattern, found an expression --> $DIR/recover-pat-lets.rs:10:9 | LL | let x[0] = 1; - | ^^^^ arbitrary expressions are not allowed in patterns + | ^^^^ not a pattern + | + = note: arbitrary expressions are not allowed in patterns: error: expected a pattern, found an expression --> $DIR/recover-pat-lets.rs:13:14 | LL | let Some(1 + 1) = x else { - | ^^^^^ arbitrary expressions are not allowed in patterns + | ^^^^^ not a pattern | + = note: arbitrary expressions are not allowed in patterns: help: consider extracting the expression into a `const` | LL + const VAL: /* Type */ = 1 + 1; @@ -36,8 +43,9 @@ error: expected a pattern, found an expression --> $DIR/recover-pat-lets.rs:17:17 | LL | if let Some(1 + 1) = x { - | ^^^^^ arbitrary expressions are not allowed in patterns + | ^^^^^ not a pattern | + = note: arbitrary expressions are not allowed in patterns: help: consider extracting the expression into a `const` | LL + const VAL: /* Type */ = 1 + 1; diff --git a/tests/ui/parser/recover/recover-pat-ranges.stderr b/tests/ui/parser/recover/recover-pat-ranges.stderr index 088f83b0ccbac..0a9b54474689a 100644 --- a/tests/ui/parser/recover/recover-pat-ranges.stderr +++ b/tests/ui/parser/recover/recover-pat-ranges.stderr @@ -86,8 +86,9 @@ error: expected a pattern range bound, found an expression --> $DIR/recover-pat-ranges.rs:11:12 | LL | ..=1 + 2 => (), - | ^^^^^ arbitrary expressions are not allowed in patterns + | ^^^^^ not a pattern | + = note: arbitrary expressions are not allowed in patterns: help: consider extracting the expression into a `const` | LL + const VAL: /* Type */ = 1 + 2; @@ -106,8 +107,9 @@ error: expected a pattern range bound, found an expression --> $DIR/recover-pat-ranges.rs:15:10 | LL | (-4 + 0).. => (), - | ^^^^^^ arbitrary expressions are not allowed in patterns + | ^^^^^^ not a pattern | + = note: arbitrary expressions are not allowed in patterns: help: consider extracting the expression into a `const` | LL + const VAL: /* Type */ = -4 + 0; @@ -126,8 +128,9 @@ error: expected a pattern range bound, found an expression --> $DIR/recover-pat-ranges.rs:18:10 | LL | (1 + 4)...1 * 2 => (), - | ^^^^^ arbitrary expressions are not allowed in patterns + | ^^^^^ not a pattern | + = note: arbitrary expressions are not allowed in patterns: help: consider extracting the expression into a `const` | LL + const VAL: /* Type */ = 1 + 4; @@ -146,8 +149,9 @@ error: expected a pattern range bound, found an expression --> $DIR/recover-pat-ranges.rs:18:19 | LL | (1 + 4)...1 * 2 => (), - | ^^^^^ arbitrary expressions are not allowed in patterns + | ^^^^^ not a pattern | + = note: arbitrary expressions are not allowed in patterns: help: consider extracting the expression into a `const` | LL + const VAL: /* Type */ = 1 * 2; @@ -166,8 +170,9 @@ error: expected a pattern range bound, found an expression --> $DIR/recover-pat-ranges.rs:24:9 | LL | 0.x()..="y".z() => (), - | ^^^^^ arbitrary expressions are not allowed in patterns + | ^^^^^ not a pattern | + = note: arbitrary expressions are not allowed in patterns: help: consider extracting the expression into a `const` | LL + const VAL: /* Type */ = 0.x(); @@ -186,8 +191,9 @@ error: expected a pattern range bound, found an expression --> $DIR/recover-pat-ranges.rs:24:17 | LL | 0.x()..="y".z() => (), - | ^^^^^^^ arbitrary expressions are not allowed in patterns + | ^^^^^^^ not a pattern | + = note: arbitrary expressions are not allowed in patterns: help: consider extracting the expression into a `const` | LL + const VAL: /* Type */ = "y".z(); diff --git a/tests/ui/parser/recover/recover-pat-wildcards.stderr b/tests/ui/parser/recover/recover-pat-wildcards.stderr index 30307726a973b..8d4212ed389dd 100644 --- a/tests/ui/parser/recover/recover-pat-wildcards.stderr +++ b/tests/ui/parser/recover/recover-pat-wildcards.stderr @@ -75,8 +75,9 @@ error: expected a pattern range bound, found an expression --> $DIR/recover-pat-wildcards.rs:55:14 | LL | 4..=(2 + _) => () - | ^^^^^ arbitrary expressions are not allowed in patterns + | ^^^^^ not a pattern | + = note: arbitrary expressions are not allowed in patterns: help: consider extracting the expression into a `const` | LL + const VAL: /* Type */ = 2 + _; diff --git a/tests/ui/resolve/issue-10200.rs b/tests/ui/resolve/issue-10200.rs index fe36a7e00bff3..d529536b95256 100644 --- a/tests/ui/resolve/issue-10200.rs +++ b/tests/ui/resolve/issue-10200.rs @@ -3,7 +3,7 @@ fn foo(_: usize) -> Foo { Foo(false) } fn main() { match Foo(true) { - foo(x) //~ ERROR expected tuple struct or tuple variant, found function `foo` + foo(x) //~ ERROR expected a pattern, found a function call => () } } diff --git a/tests/ui/resolve/issue-10200.stderr b/tests/ui/resolve/issue-10200.stderr index 7b218694b269e..172d016c6e6c4 100644 --- a/tests/ui/resolve/issue-10200.stderr +++ b/tests/ui/resolve/issue-10200.stderr @@ -1,4 +1,4 @@ -error[E0532]: expected tuple struct or tuple variant, found function `foo` +error[E0532]: expected a pattern, found a function call --> $DIR/issue-10200.rs:6:9 | LL | struct Foo(bool); @@ -6,6 +6,8 @@ LL | struct Foo(bool); ... LL | foo(x) | ^^^ help: a tuple struct with a similar name exists (notice the capitalization): `Foo` + | + = note: function calls are not allowed in patterns: error: aborting due to 1 previous error diff --git a/tests/ui/sized/ensure-overriding-bindings-in-pattern-with-ty-err-doesnt-ice.stderr b/tests/ui/sized/ensure-overriding-bindings-in-pattern-with-ty-err-doesnt-ice.stderr index fc431eb14127f..d40e98224355b 100644 --- a/tests/ui/sized/ensure-overriding-bindings-in-pattern-with-ty-err-doesnt-ice.stderr +++ b/tests/ui/sized/ensure-overriding-bindings-in-pattern-with-ty-err-doesnt-ice.stderr @@ -2,7 +2,9 @@ error: expected a pattern, found an expression --> $DIR/ensure-overriding-bindings-in-pattern-with-ty-err-doesnt-ice.rs:2:31 | LL | let str::<{fn str() { let str::T>>::as_bytes; }}, T>::as_bytes; - | ^^^^^^^^^^^^^^^^^^ arbitrary expressions are not allowed in patterns + | ^^^^^^^^^^^^^^^^^^ not a pattern + | + = note: arbitrary expressions are not allowed in patterns: error[E0412]: cannot find type `T` in this scope --> $DIR/ensure-overriding-bindings-in-pattern-with-ty-err-doesnt-ice.rs:2:55 From 7c0c51193327fcf7f09d6450bd4dcc744adf6fe3 Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Sat, 5 Oct 2024 21:34:51 -0500 Subject: [PATCH 1925/2194] Update `compiler-builtins` to 0.1.133 This includes [1], which should help resolve an infinite recusion issue on WASM and SPARC (possibly other platforms). See [2] and [3] for further details. [1]: https://github.com/rust-lang/compiler-builtins/pull/708 [2]: https://rust-lang.zulipchat.com/#narrow/stream/131828-t-compiler/topic/sparc-unknown-none-elf.20regresssion.20between.20compiler-built.2E.2E.2E [3]: https://rust-lang.zulipchat.com/#narrow/stream/131828-t-compiler/topic/.5Bwasm32.5D.20Infinite.20recursion.20.60compiler-builtins.60.20.60__multi3.60 --- library/Cargo.lock | 4 ++-- library/alloc/Cargo.toml | 2 +- library/std/Cargo.toml | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/library/Cargo.lock b/library/Cargo.lock index 66ded59ae3661..59b76d8d4427d 100644 --- a/library/Cargo.lock +++ b/library/Cargo.lock @@ -61,9 +61,9 @@ dependencies = [ [[package]] name = "compiler_builtins" -version = "0.1.132" +version = "0.1.133" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88f58330b127df19326d19e9debbb722578589cb1b9c061b5cdc4036d038b54b" +checksum = "ab10bf45b2ed1b4f4c25401527a61684142c042b3c86ace7da7ea6881e26741b" dependencies = [ "cc", "rustc-std-workspace-core", diff --git a/library/alloc/Cargo.toml b/library/alloc/Cargo.toml index fa18c7aec743a..259a3ed2bebde 100644 --- a/library/alloc/Cargo.toml +++ b/library/alloc/Cargo.toml @@ -10,7 +10,7 @@ edition = "2021" [dependencies] core = { path = "../core" } -compiler_builtins = { version = "0.1.132", features = ['rustc-dep-of-std'] } +compiler_builtins = { version = "0.1.133", features = ['rustc-dep-of-std'] } [dev-dependencies] rand = { version = "0.8.5", default-features = false, features = ["alloc"] } diff --git a/library/std/Cargo.toml b/library/std/Cargo.toml index 6bf70e1d82abe..f2669326065d5 100644 --- a/library/std/Cargo.toml +++ b/library/std/Cargo.toml @@ -17,7 +17,7 @@ cfg-if = { version = "1.0", features = ['rustc-dep-of-std'] } panic_unwind = { path = "../panic_unwind", optional = true } panic_abort = { path = "../panic_abort" } core = { path = "../core", public = true } -compiler_builtins = { version = "0.1.132" } +compiler_builtins = { version = "0.1.133" } profiler_builtins = { path = "../profiler_builtins", optional = true } unwind = { path = "../unwind" } hashbrown = { version = "0.15", default-features = false, features = [ From 8a5e03bf438ddc990ab311bc63d7c15b2f21f5a8 Mon Sep 17 00:00:00 2001 From: WANG Rui Date: Fri, 13 Sep 2024 14:30:22 +0800 Subject: [PATCH 1926/2194] Enable sanitizers for loongarch64-unknown-* --- .../src/spec/targets/loongarch64_unknown_linux_gnu.rs | 7 ++++++- .../src/spec/targets/loongarch64_unknown_linux_musl.rs | 7 ++++++- .../src/spec/targets/loongarch64_unknown_linux_ohos.rs | 7 ++++++- src/bootstrap/src/core/build_steps/llvm.rs | 3 +++ .../docker/host-x86_64/dist-loongarch64-linux/Dockerfile | 1 + src/ci/docker/host-x86_64/dist-loongarch64-musl/Dockerfile | 1 + 6 files changed, 23 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_target/src/spec/targets/loongarch64_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/targets/loongarch64_unknown_linux_gnu.rs index de8d99977b438..e869314d4d8b9 100644 --- a/compiler/rustc_target/src/spec/targets/loongarch64_unknown_linux_gnu.rs +++ b/compiler/rustc_target/src/spec/targets/loongarch64_unknown_linux_gnu.rs @@ -1,4 +1,4 @@ -use crate::spec::{CodeModel, Target, TargetOptions, base}; +use crate::spec::{CodeModel, SanitizerSet, Target, TargetOptions, base}; pub(crate) fn target() -> Target { Target { @@ -18,6 +18,11 @@ pub(crate) fn target() -> Target { features: "+f,+d".into(), llvm_abiname: "lp64d".into(), max_atomic_width: Some(64), + supported_sanitizers: SanitizerSet::ADDRESS + | SanitizerSet::CFI + | SanitizerSet::LEAK + | SanitizerSet::MEMORY + | SanitizerSet::THREAD, direct_access_external_data: Some(false), ..base::linux_gnu::opts() }, diff --git a/compiler/rustc_target/src/spec/targets/loongarch64_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/targets/loongarch64_unknown_linux_musl.rs index a5088bcd5c257..70e8bf633a9a6 100644 --- a/compiler/rustc_target/src/spec/targets/loongarch64_unknown_linux_musl.rs +++ b/compiler/rustc_target/src/spec/targets/loongarch64_unknown_linux_musl.rs @@ -1,4 +1,4 @@ -use crate::spec::{CodeModel, Target, TargetOptions, base}; +use crate::spec::{CodeModel, SanitizerSet, Target, TargetOptions, base}; pub(crate) fn target() -> Target { Target { @@ -19,6 +19,11 @@ pub(crate) fn target() -> Target { llvm_abiname: "lp64d".into(), max_atomic_width: Some(64), crt_static_default: false, + supported_sanitizers: SanitizerSet::ADDRESS + | SanitizerSet::CFI + | SanitizerSet::LEAK + | SanitizerSet::MEMORY + | SanitizerSet::THREAD, ..base::linux_musl::opts() }, } diff --git a/compiler/rustc_target/src/spec/targets/loongarch64_unknown_linux_ohos.rs b/compiler/rustc_target/src/spec/targets/loongarch64_unknown_linux_ohos.rs index 32a856be66907..90bcd9a45cf42 100644 --- a/compiler/rustc_target/src/spec/targets/loongarch64_unknown_linux_ohos.rs +++ b/compiler/rustc_target/src/spec/targets/loongarch64_unknown_linux_ohos.rs @@ -1,4 +1,4 @@ -use crate::spec::{Target, TargetOptions, base}; +use crate::spec::{SanitizerSet, Target, TargetOptions, base}; pub(crate) fn target() -> Target { Target { @@ -17,6 +17,11 @@ pub(crate) fn target() -> Target { features: "+f,+d".into(), llvm_abiname: "lp64d".into(), max_atomic_width: Some(64), + supported_sanitizers: SanitizerSet::ADDRESS + | SanitizerSet::CFI + | SanitizerSet::LEAK + | SanitizerSet::MEMORY + | SanitizerSet::THREAD, ..base::linux_ohos::opts() }, } diff --git a/src/bootstrap/src/core/build_steps/llvm.rs b/src/bootstrap/src/core/build_steps/llvm.rs index 3021358415790..c64ca73069899 100644 --- a/src/bootstrap/src/core/build_steps/llvm.rs +++ b/src/bootstrap/src/core/build_steps/llvm.rs @@ -1215,6 +1215,9 @@ fn supported_sanitizers( "aarch64-unknown-linux-ohos" => { common_libs("linux", "aarch64", &["asan", "lsan", "msan", "tsan", "hwasan"]) } + "loongarch64-unknown-linux-gnu" | "loongarch64-unknown-linux-musl" => { + common_libs("linux", "loongarch64", &["asan", "lsan", "msan", "tsan"]) + } "x86_64-apple-darwin" => darwin_libs("osx", &["asan", "lsan", "tsan"]), "x86_64-unknown-fuchsia" => common_libs("fuchsia", "x86_64", &["asan"]), "x86_64-apple-ios" => darwin_libs("iossim", &["asan", "tsan"]), diff --git a/src/ci/docker/host-x86_64/dist-loongarch64-linux/Dockerfile b/src/ci/docker/host-x86_64/dist-loongarch64-linux/Dockerfile index 865a9e32fa92b..71eb72686b06a 100644 --- a/src/ci/docker/host-x86_64/dist-loongarch64-linux/Dockerfile +++ b/src/ci/docker/host-x86_64/dist-loongarch64-linux/Dockerfile @@ -47,6 +47,7 @@ ENV RUST_CONFIGURE_ARGS \ --enable-extended \ --enable-full-tools \ --enable-profiler \ + --enable-sanitizers \ --disable-docs ENV SCRIPT python3 ../x.py dist --host $HOSTS --target $TARGETS diff --git a/src/ci/docker/host-x86_64/dist-loongarch64-musl/Dockerfile b/src/ci/docker/host-x86_64/dist-loongarch64-musl/Dockerfile index 62dbfaaa67315..5081f25e56743 100644 --- a/src/ci/docker/host-x86_64/dist-loongarch64-musl/Dockerfile +++ b/src/ci/docker/host-x86_64/dist-loongarch64-musl/Dockerfile @@ -29,6 +29,7 @@ ENV RUST_CONFIGURE_ARGS \ --enable-extended \ --enable-full-tools \ --enable-profiler \ + --enable-sanitizers \ --disable-docs \ --set target.loongarch64-unknown-linux-musl.crt-static=false \ --musl-root-loongarch64=/x-tools/loongarch64-unknown-linux-musl/loongarch64-unknown-linux-musl/sysroot/usr From 8b968764f15ea84b389b2af98297b9d30fb9952e Mon Sep 17 00:00:00 2001 From: Shriram Balaji Date: Thu, 12 Sep 2024 00:56:52 +0530 Subject: [PATCH 1927/2194] bootstrap: add `std_features` config MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit bootstrap: add std_features to config.example fix: use BTreeSet for std-features; add unit tests * fix formatting of string in front of std_features * rename `std_features` to `std-features` in config.toml fix: remove space before std-features in config.toml fix: remove explicit .into_iter conversion bootstrap: add details for rust.std-features in config.example.toml Co-authored-by: Onur Özkan fix: remove `Option` from `rust_std_features` fix: move default rust_std_features to config fix: make std_features CI rustc incompatible --- config.example.toml | 10 +++++++++ src/bootstrap/src/core/config/config.rs | 12 ++++++++++- src/bootstrap/src/core/config/tests.rs | 22 ++++++++++++++++++++ src/bootstrap/src/lib.rs | 27 ++++++++++++++----------- 4 files changed, 58 insertions(+), 13 deletions(-) diff --git a/config.example.toml b/config.example.toml index 47ebb20d8fa82..4b591b949b36d 100644 --- a/config.example.toml +++ b/config.example.toml @@ -759,6 +759,16 @@ # Build compiler with the optimization enabled and -Zvalidate-mir, currently only for `std` #validate-mir-opts = 3 +# Configure `std` features used during bootstrap. +# Default features will be expanded in the following cases: +# - If `rust.llvm-libunwind` or `target.llvm-libunwind` is enabled: +# - "llvm-libunwind" will be added for in-tree LLVM builds. +# - "system-llvm-libunwind" will be added for system LLVM builds. +# - If `rust.backtrace` is enabled, "backtrace" will be added. +# - If `rust.profiler` or `target.profiler` is enabled, "profiler" will be added. +# - If building for a zkvm target, "compiler-builtins-mem" will be added. +#std-features = ["panic_unwind"] + # ============================================================================= # Options for specific targets # diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs index 07460b81412ac..7dc3b7b081aea 100644 --- a/src/bootstrap/src/core/config/config.rs +++ b/src/bootstrap/src/core/config/config.rs @@ -4,7 +4,7 @@ //! how the build runs. use std::cell::{Cell, RefCell}; -use std::collections::{HashMap, HashSet}; +use std::collections::{BTreeSet, HashMap, HashSet}; use std::fmt::{self, Display}; use std::io::IsTerminal; use std::path::{Path, PathBuf, absolute}; @@ -287,6 +287,7 @@ pub struct Config { pub rust_profile_generate: Option, pub rust_lto: RustcLto, pub rust_validate_mir_opts: Option, + pub rust_std_features: BTreeSet, pub llvm_profile_use: Option, pub llvm_profile_generate: bool, pub llvm_libunwind_default: Option, @@ -1152,6 +1153,7 @@ define_config! { download_rustc: Option = "download-rustc", lto: Option = "lto", validate_mir_opts: Option = "validate-mir-opts", + std_features: Option> = "std-features", } } @@ -1645,6 +1647,7 @@ impl Config { let mut optimize = None; let mut omit_git_hash = None; let mut lld_enabled = None; + let mut std_features = None; let mut is_user_configured_rust_channel = false; @@ -1703,6 +1706,7 @@ impl Config { stack_protector, strip, lld_mode, + std_features: std_features_toml, } = rust; is_user_configured_rust_channel = channel.is_some(); @@ -1722,6 +1726,7 @@ impl Config { debuginfo_level_tools = debuginfo_level_tools_toml; debuginfo_level_tests = debuginfo_level_tests_toml; lld_enabled = lld_enabled_toml; + std_features = std_features_toml; optimize = optimize_toml; omit_git_hash = omit_git_hash_toml; @@ -2118,6 +2123,9 @@ impl Config { ); } + let default_std_features = BTreeSet::from([String::from("panic-unwind")]); + config.rust_std_features = std_features.unwrap_or(default_std_features); + let default = debug == Some(true); config.rust_debug_assertions = debug_assertions.unwrap_or(default); config.rust_debug_assertions_std = @@ -3016,6 +3024,7 @@ fn check_incompatible_options_for_ci_rustc( description, incremental, default_linker, + std_features, // Rest of the options can simply be ignored. debug: _, @@ -3077,6 +3086,7 @@ fn check_incompatible_options_for_ci_rustc( err!(current_rust_config.default_linker, default_linker); err!(current_rust_config.stack_protector, stack_protector); err!(current_rust_config.lto, lto); + err!(current_rust_config.std_features, std_features); warn!(current_rust_config.channel, channel); warn!(current_rust_config.description, description); diff --git a/src/bootstrap/src/core/config/tests.rs b/src/bootstrap/src/core/config/tests.rs index e38d4eac051d8..278becdcbc77d 100644 --- a/src/bootstrap/src/core/config/tests.rs +++ b/src/bootstrap/src/core/config/tests.rs @@ -1,3 +1,4 @@ +use std::collections::BTreeSet; use std::env; use std::fs::{File, remove_file}; use std::io::Write; @@ -326,3 +327,24 @@ fn verbose_tests_default_value() { let config = Config::parse(Flags::parse(&["build".into(), "compiler".into(), "-v".into()])); assert_eq!(config.verbose_tests, true); } + +#[test] +fn parse_rust_std_features() { + let config = parse("rust.std-features = [\"panic-unwind\", \"backtrace\"]"); + let expected_features: BTreeSet = + ["panic-unwind", "backtrace"].into_iter().map(|s| s.to_string()).collect(); + assert_eq!(config.rust_std_features, expected_features); +} + +#[test] +fn parse_rust_std_features_empty() { + let config = parse("rust.std-features = []"); + let expected_features: BTreeSet = BTreeSet::new(); + assert_eq!(config.rust_std_features, expected_features); +} + +#[test] +#[should_panic] +fn parse_rust_std_features_invalid() { + parse("rust.std-features = \"backtrace\""); +} diff --git a/src/bootstrap/src/lib.rs b/src/bootstrap/src/lib.rs index 75659f46431af..313b49346bc56 100644 --- a/src/bootstrap/src/lib.rs +++ b/src/bootstrap/src/lib.rs @@ -17,7 +17,7 @@ //! also check out the `src/bootstrap/README.md` file for more information. use std::cell::{Cell, RefCell}; -use std::collections::{HashMap, HashSet}; +use std::collections::{BTreeSet, HashMap, HashSet}; use std::fmt::Display; use std::fs::{self, File}; use std::path::{Path, PathBuf}; @@ -645,28 +645,31 @@ impl Build { &self.config.rust_info } - /// Gets the space-separated set of activated features for the standard - /// library. + /// Gets the space-separated set of activated features for the standard library. + /// This can be configured with the `std-features` key in config.toml. fn std_features(&self, target: TargetSelection) -> String { - let mut features = " panic-unwind".to_string(); + let mut features: BTreeSet<&str> = + self.config.rust_std_features.iter().map(|s| s.as_str()).collect(); match self.config.llvm_libunwind(target) { - LlvmLibunwind::InTree => features.push_str(" llvm-libunwind"), - LlvmLibunwind::System => features.push_str(" system-llvm-libunwind"), - LlvmLibunwind::No => {} - } + LlvmLibunwind::InTree => features.insert("llvm-libunwind"), + LlvmLibunwind::System => features.insert("system-llvm-libunwind"), + LlvmLibunwind::No => false, + }; + if self.config.backtrace { - features.push_str(" backtrace"); + features.insert("backtrace"); } if self.config.profiler_enabled(target) { - features.push_str(" profiler"); + features.insert("profiler"); } // Generate memcpy, etc. FIXME: Remove this once compiler-builtins // automatically detects this target. if target.contains("zkvm") { - features.push_str(" compiler-builtins-mem"); + features.insert("compiler-builtins-mem"); } - features + + features.into_iter().collect::>().join(" ") } /// Gets the space-separated set of activated features for the compiler. From 002afd1ae9c646d4120cc8e078bb329de8b3ecac Mon Sep 17 00:00:00 2001 From: Jacob Lifshay Date: Sat, 5 Oct 2024 22:01:02 -0700 Subject: [PATCH 1928/2194] Fix typo in primitive_docs.rs --- library/core/src/primitive_docs.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/core/src/primitive_docs.rs b/library/core/src/primitive_docs.rs index 962da6643ddb1..c25501f12001a 100644 --- a/library/core/src/primitive_docs.rs +++ b/library/core/src/primitive_docs.rs @@ -1251,7 +1251,7 @@ mod prim_f16 {} /// - **Unchanged NaN propagation**: The quiet bit and payload are copied from any input operand /// that is a NaN. If the inputs and outputs do not have the same size (i.e., for `as` casts), the /// same rules as for "quieting NaN propagation" apply, with one caveat: if the output is smaller -/// than the input, droppig the low-order bits may result in a payload of 0; a payload of 0 is not +/// than the input, dropping the low-order bits may result in a payload of 0; a payload of 0 is not /// possible with a signaling NaN (the all-0 significand encodes an infinity) so unchanged NaN /// propagation cannot occur with some inputs. /// - **Target-specific NaN**: The quiet bit is set and the payload is picked from a target-specific From e0a20b484d0b88183ddd46b82aa47d7bbfe48468 Mon Sep 17 00:00:00 2001 From: ismailarilik Date: Sun, 6 Oct 2024 10:39:03 +0300 Subject: [PATCH 1929/2194] Handle `librustdoc` cases of `rustc::potential_query_instability` lint --- compiler/rustc_resolve/src/rustdoc.rs | 6 +-- src/librustdoc/clean/types.rs | 16 ++++---- src/librustdoc/config.rs | 4 +- src/librustdoc/core.rs | 4 +- src/librustdoc/doctest.rs | 15 ++++---- src/librustdoc/doctest/runner.rs | 6 +-- src/librustdoc/formats/cache.rs | 16 ++++---- src/librustdoc/html/highlight.rs | 4 +- src/librustdoc/html/highlight/tests.rs | 4 +- src/librustdoc/html/layout.rs | 4 +- src/librustdoc/html/markdown.rs | 8 ++-- src/librustdoc/html/render/context.rs | 14 +++---- src/librustdoc/html/render/mod.rs | 38 +++++++++---------- src/librustdoc/html/render/print_item.rs | 4 +- src/librustdoc/html/render/search_index.rs | 10 ++--- src/librustdoc/html/render/span_map.rs | 4 +- src/librustdoc/html/render/write_shared.rs | 10 ++--- src/librustdoc/html/sources.rs | 8 ++-- src/librustdoc/lib.rs | 3 +- .../passes/collect_intra_doc_links.rs | 6 +-- src/librustdoc/passes/collect_trait_impls.rs | 2 +- src/librustdoc/scrape_examples.rs | 10 ++--- src/librustdoc/theme.rs | 33 ++++++++-------- 23 files changed, 114 insertions(+), 115 deletions(-) diff --git a/compiler/rustc_resolve/src/rustdoc.rs b/compiler/rustc_resolve/src/rustdoc.rs index d1c1b6c882eaa..02e255d7726d1 100644 --- a/compiler/rustc_resolve/src/rustdoc.rs +++ b/compiler/rustc_resolve/src/rustdoc.rs @@ -6,7 +6,7 @@ use pulldown_cmark::{ }; use rustc_ast as ast; use rustc_ast::util::comments::beautify_doc_string; -use rustc_data_structures::fx::FxHashMap; +use rustc_data_structures::fx::FxIndexMap; use rustc_middle::ty::TyCtxt; use rustc_span::def_id::DefId; use rustc_span::symbol::{Symbol, kw, sym}; @@ -235,8 +235,8 @@ fn span_for_value(attr: &ast::Attribute) -> Span { /// early and late doc link resolution regardless of their position. pub fn prepare_to_doc_link_resolution( doc_fragments: &[DocFragment], -) -> FxHashMap, String> { - let mut res = FxHashMap::default(); +) -> FxIndexMap, String> { + let mut res = FxIndexMap::default(); for fragment in doc_fragments { let out_str = res.entry(fragment.item_id).or_default(); add_doc_fragment(out_str, fragment); diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index ec31a51a81e2d..ea4388b305b36 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -9,7 +9,7 @@ use rustc_ast::NestedMetaItem; use rustc_ast_pretty::pprust; use rustc_attr::{ConstStability, Deprecation, Stability, StableSince}; use rustc_const_eval::const_eval::is_unstable_const_fn; -use rustc_data_structures::fx::{FxHashMap, FxHashSet}; +use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet}; use rustc_hir::def::{CtorKind, DefKind, Res}; use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE, LocalDefId}; use rustc_hir::lang_items::LangItem; @@ -114,7 +114,7 @@ impl From for ItemId { pub(crate) struct Crate { pub(crate) module: Item, /// Only here so that they can be filtered through the rustdoc passes. - pub(crate) external_traits: Box>, + pub(crate) external_traits: Box>, } impl Crate { @@ -1223,7 +1223,7 @@ impl Attributes { } pub(crate) fn get_doc_aliases(&self) -> Box<[Symbol]> { - let mut aliases = FxHashSet::default(); + let mut aliases = FxIndexSet::default(); for attr in self.other_attrs.lists(sym::doc).filter(|a| a.has_name(sym::alias)) { if let Some(values) = attr.meta_item_list() { @@ -1759,7 +1759,7 @@ pub(crate) enum PrimitiveType { Never, } -type SimplifiedTypes = FxHashMap>; +type SimplifiedTypes = FxIndexMap>; impl PrimitiveType { pub(crate) fn from_hir(prim: hir::PrimTy) -> PrimitiveType { use ast::{FloatTy, IntTy, UintTy}; @@ -1927,10 +1927,10 @@ impl PrimitiveType { /// In particular, if a crate depends on both `std` and another crate that also defines /// `rustc_doc_primitive`, then it's entirely random whether `std` or the other crate is picked. /// (no_std crates are usually fine unless multiple dependencies define a primitive.) - pub(crate) fn primitive_locations(tcx: TyCtxt<'_>) -> &FxHashMap { - static PRIMITIVE_LOCATIONS: OnceCell> = OnceCell::new(); + pub(crate) fn primitive_locations(tcx: TyCtxt<'_>) -> &FxIndexMap { + static PRIMITIVE_LOCATIONS: OnceCell> = OnceCell::new(); PRIMITIVE_LOCATIONS.get_or_init(|| { - let mut primitive_locations = FxHashMap::default(); + let mut primitive_locations = FxIndexMap::default(); // NOTE: technically this misses crates that are only passed with `--extern` and not loaded when checking the crate. // This is a degenerate case that I don't plan to support. for &crate_num in tcx.crates(()) { @@ -2460,7 +2460,7 @@ pub(crate) struct Impl { } impl Impl { - pub(crate) fn provided_trait_methods(&self, tcx: TyCtxt<'_>) -> FxHashSet { + pub(crate) fn provided_trait_methods(&self, tcx: TyCtxt<'_>) -> FxIndexSet { self.trait_ .as_ref() .map(|t| t.def_id()) diff --git a/src/librustdoc/config.rs b/src/librustdoc/config.rs index 7a37f5c70a592..2cd69474b1cf0 100644 --- a/src/librustdoc/config.rs +++ b/src/librustdoc/config.rs @@ -5,7 +5,7 @@ use std::path::{Path, PathBuf}; use std::str::FromStr; use std::{fmt, io}; -use rustc_data_structures::fx::FxHashMap; +use rustc_data_structures::fx::FxIndexMap; use rustc_errors::DiagCtxtHandle; use rustc_session::config::{ self, CodegenOptions, CrateType, ErrorOutputType, Externs, Input, JsonUnusedExterns, @@ -249,7 +249,7 @@ pub(crate) struct RenderOptions { pub(crate) extern_html_root_takes_precedence: bool, /// A map of the default settings (values are as for DOM storage API). Keys should lack the /// `rustdoc-` prefix. - pub(crate) default_settings: FxHashMap, + pub(crate) default_settings: FxIndexMap, /// If present, suffix added to CSS/JavaScript files when referencing them in generated pages. pub(crate) resource_suffix: String, /// Whether to create an index page in the root of the output directory. If this is true but diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index 4c48c075a944d..aaf4c80f99763 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -2,7 +2,7 @@ use std::sync::atomic::AtomicBool; use std::sync::{Arc, LazyLock}; use std::{io, mem}; -use rustc_data_structures::fx::{FxHashMap, FxHashSet}; +use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap}; use rustc_data_structures::sync::Lrc; use rustc_data_structures::unord::UnordSet; use rustc_errors::codes::*; @@ -39,7 +39,7 @@ pub(crate) struct DocContext<'tcx> { /// Most of this logic is copied from rustc_lint::late. pub(crate) param_env: ParamEnv<'tcx>, /// Later on moved through `clean::Crate` into `cache` - pub(crate) external_traits: FxHashMap, + pub(crate) external_traits: FxIndexMap, /// Used while populating `external_traits` to ensure we don't process the same trait twice at /// the same time. pub(crate) active_extern_traits: DefIdSet, diff --git a/src/librustdoc/doctest.rs b/src/librustdoc/doctest.rs index 4e7571a480380..d5bc2a93fa807 100644 --- a/src/librustdoc/doctest.rs +++ b/src/librustdoc/doctest.rs @@ -14,7 +14,7 @@ use std::{panic, str}; pub(crate) use make::DocTestBuilder; pub(crate) use markdown::test as test_markdown; use rustc_ast as ast; -use rustc_data_structures::fx::{FxHashMap, FxHashSet}; +use rustc_data_structures::fx::{FxHashMap, FxIndexMap, FxIndexSet}; use rustc_errors::{ColorConfig, DiagCtxtHandle, ErrorGuaranteed, FatalError}; use rustc_hir::CRATE_HIR_ID; use rustc_hir::def_id::LOCAL_CRATE; @@ -213,12 +213,13 @@ pub(crate) fn run( let unused_extern_reports: Vec<_> = std::mem::take(&mut unused_extern_reports.lock().unwrap()); if unused_extern_reports.len() == compiling_test_count { - let extern_names = externs.iter().map(|(name, _)| name).collect::>(); + let extern_names = + externs.iter().map(|(name, _)| name).collect::>(); let mut unused_extern_names = unused_extern_reports .iter() - .map(|uexts| uexts.unused_extern_names.iter().collect::>()) + .map(|uexts| uexts.unused_extern_names.iter().collect::>()) .fold(extern_names, |uextsa, uextsb| { - uextsa.intersection(&uextsb).copied().collect::>() + uextsa.intersection(&uextsb).copied().collect::>() }) .iter() .map(|v| (*v).clone()) @@ -253,7 +254,7 @@ pub(crate) fn run_tests( rustdoc_options: &Arc, unused_extern_reports: &Arc>>, mut standalone_tests: Vec, - mergeable_tests: FxHashMap>, + mergeable_tests: FxIndexMap>, ) { let mut test_args = Vec::with_capacity(rustdoc_options.test_args.len() + 1); test_args.insert(0, "rustdoctest".to_string()); @@ -775,7 +776,7 @@ pub(crate) trait DocTestVisitor { struct CreateRunnableDocTests { standalone_tests: Vec, - mergeable_tests: FxHashMap>, + mergeable_tests: FxIndexMap>, rustdoc_options: Arc, opts: GlobalTestOptions, @@ -790,7 +791,7 @@ impl CreateRunnableDocTests { let can_merge_doctests = rustdoc_options.edition >= Edition::Edition2024; CreateRunnableDocTests { standalone_tests: Vec::new(), - mergeable_tests: FxHashMap::default(), + mergeable_tests: FxIndexMap::default(), rustdoc_options: Arc::new(rustdoc_options), opts, visited_tests: FxHashMap::default(), diff --git a/src/librustdoc/doctest/runner.rs b/src/librustdoc/doctest/runner.rs index 326ca4ee1e68f..942ec8d9936cf 100644 --- a/src/librustdoc/doctest/runner.rs +++ b/src/librustdoc/doctest/runner.rs @@ -1,6 +1,6 @@ use std::fmt::Write; -use rustc_data_structures::fx::FxHashSet; +use rustc_data_structures::fx::FxIndexSet; use rustc_span::edition::Edition; use crate::doctest::{ @@ -11,7 +11,7 @@ use crate::html::markdown::{Ignore, LangString}; /// Convenient type to merge compatible doctests into one. pub(crate) struct DocTestRunner { - crate_attrs: FxHashSet, + crate_attrs: FxIndexSet, ids: String, output: String, supports_color: bool, @@ -21,7 +21,7 @@ pub(crate) struct DocTestRunner { impl DocTestRunner { pub(crate) fn new() -> Self { Self { - crate_attrs: FxHashSet::default(), + crate_attrs: FxIndexSet::default(), ids: String::new(), output: String::new(), supports_color: true, diff --git a/src/librustdoc/formats/cache.rs b/src/librustdoc/formats/cache.rs index db1a0bd0af938..ff0d537b19f75 100644 --- a/src/librustdoc/formats/cache.rs +++ b/src/librustdoc/formats/cache.rs @@ -1,6 +1,6 @@ use std::mem; -use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet}; +use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap, FxIndexSet}; use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, DefIdSet}; use rustc_middle::ty::{self, TyCtxt}; use rustc_span::Symbol; @@ -42,7 +42,7 @@ pub(crate) struct Cache { /// URLs when a type is being linked to. External paths are not located in /// this map because the `External` type itself has all the information /// necessary. - pub(crate) paths: FxHashMap, ItemType)>, + pub(crate) paths: FxIndexMap, ItemType)>, /// Similar to `paths`, but only holds external paths. This is only used for /// generating explicit hyperlinks to other crates. @@ -64,18 +64,18 @@ pub(crate) struct Cache { /// Implementations of a crate should inherit the documentation of the /// parent trait if no extra documentation is specified, and default methods /// should show up in documentation about trait implementations. - pub(crate) traits: FxHashMap, + pub(crate) traits: FxIndexMap, /// When rendering traits, it's often useful to be able to list all /// implementors of the trait, and this mapping is exactly, that: a mapping /// of trait ids to the list of known implementors of the trait - pub(crate) implementors: FxHashMap>, + pub(crate) implementors: FxIndexMap>, /// Cache of where external crate documentation can be found. - pub(crate) extern_locations: FxHashMap, + pub(crate) extern_locations: FxIndexMap, /// Cache of where documentation for primitives can be found. - pub(crate) primitive_locations: FxHashMap, + pub(crate) primitive_locations: FxIndexMap, // Note that external items for which `doc(hidden)` applies to are shown as // non-reachable while local items aren't. This is because we're reusing @@ -118,7 +118,7 @@ pub(crate) struct Cache { // crawl. In order to prevent crashes when looking for notable traits or // when gathering trait documentation on a type, hold impls here while // folding and add them to the cache later on if we find the trait. - orphan_trait_impls: Vec<(DefId, FxHashSet, Impl)>, + orphan_trait_impls: Vec<(DefId, FxIndexSet, Impl)>, /// All intra-doc links resolved so far. /// @@ -376,7 +376,7 @@ impl<'a, 'tcx> DocFolder for CacheBuilder<'a, 'tcx> { // Figure out the id of this impl. This may map to a // primitive rather than always to a struct/enum. // Note: matching twice to restrict the lifetime of the `i` borrow. - let mut dids = FxHashSet::default(); + let mut dids = FxIndexSet::default(); match i.for_ { clean::Type::Path { ref path } | clean::BorrowedRef { type_: box clean::Type::Path { ref path }, .. } => { diff --git a/src/librustdoc/html/highlight.rs b/src/librustdoc/html/highlight.rs index 69b3421f8881f..e7ddd4b73b47b 100644 --- a/src/librustdoc/html/highlight.rs +++ b/src/librustdoc/html/highlight.rs @@ -8,7 +8,7 @@ use std::collections::VecDeque; use std::fmt::{Display, Write}; -use rustc_data_structures::fx::FxHashMap; +use rustc_data_structures::fx::FxIndexMap; use rustc_lexer::{Cursor, LiteralKind, TokenKind}; use rustc_span::edition::Edition; use rustc_span::symbol::Symbol; @@ -34,7 +34,7 @@ pub(crate) struct HrefContext<'a, 'tcx> { /// Decorations are represented as a map from CSS class to vector of character ranges. /// Each range will be wrapped in a span with that class. #[derive(Default)] -pub(crate) struct DecorationInfo(pub(crate) FxHashMap<&'static str, Vec<(u32, u32)>>); +pub(crate) struct DecorationInfo(pub(crate) FxIndexMap<&'static str, Vec<(u32, u32)>>); #[derive(Eq, PartialEq, Clone, Copy)] pub(crate) enum Tooltip { diff --git a/src/librustdoc/html/highlight/tests.rs b/src/librustdoc/html/highlight/tests.rs index 75328e724fea8..fd5275189d661 100644 --- a/src/librustdoc/html/highlight/tests.rs +++ b/src/librustdoc/html/highlight/tests.rs @@ -1,5 +1,5 @@ use expect_test::expect_file; -use rustc_data_structures::fx::FxHashMap; +use rustc_data_structures::fx::FxIndexMap; use rustc_span::create_default_session_globals_then; use super::{DecorationInfo, write_code}; @@ -73,7 +73,7 @@ fn test_decorations() { let y = 2; let z = 3; let a = 4;"; - let mut decorations = FxHashMap::default(); + let mut decorations = FxIndexMap::default(); decorations.insert("example", vec![(0, 10), (11, 21)]); decorations.insert("example2", vec![(22, 32)]); diff --git a/src/librustdoc/html/layout.rs b/src/librustdoc/html/layout.rs index 3684dc42ac73c..31ccfeb38738c 100644 --- a/src/librustdoc/html/layout.rs +++ b/src/librustdoc/html/layout.rs @@ -1,7 +1,7 @@ use std::path::PathBuf; use rinja::Template; -use rustc_data_structures::fx::FxHashMap; +use rustc_data_structures::fx::FxIndexMap; use super::static_files::{STATIC_FILES, StaticFiles}; use crate::externalfiles::ExternalHtml; @@ -13,7 +13,7 @@ pub(crate) struct Layout { pub(crate) logo: String, pub(crate) favicon: String, pub(crate) external_html: ExternalHtml, - pub(crate) default_settings: FxHashMap, + pub(crate) default_settings: FxIndexMap, pub(crate) krate: String, pub(crate) krate_version: String, /// The given user css file which allow to customize the generated diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs index 8ae5484feda7a..6c5c58754a88f 100644 --- a/src/librustdoc/html/markdown.rs +++ b/src/librustdoc/html/markdown.rs @@ -38,7 +38,7 @@ use pulldown_cmark::{ BrokenLink, BrokenLinkCallback, CodeBlockKind, CowStr, Event, LinkType, OffsetIter, Options, Parser, Tag, TagEnd, html, }; -use rustc_data_structures::fx::FxHashMap; +use rustc_data_structures::fx::{FxHashMap, FxIndexMap}; use rustc_errors::{Diag, DiagMessage}; use rustc_hir::def_id::LocalDefId; use rustc_middle::ty::TyCtxt; @@ -651,12 +651,12 @@ impl<'a, I: Iterator>> Iterator for SummaryLine<'a, I> { /// references. struct Footnotes<'a, I> { inner: I, - footnotes: FxHashMap>, u16)>, + footnotes: FxIndexMap>, u16)>, } impl<'a, I> Footnotes<'a, I> { fn new(iter: I) -> Self { - Footnotes { inner: iter, footnotes: FxHashMap::default() } + Footnotes { inner: iter, footnotes: FxIndexMap::default() } } fn get_entry(&mut self, key: &str) -> &mut (Vec>, u16) { @@ -694,7 +694,7 @@ impl<'a, I: Iterator>> Iterator for Footnotes<'a, I> { Some(e) => return Some(e), None => { if !self.footnotes.is_empty() { - let mut v: Vec<_> = self.footnotes.drain().map(|(_, x)| x).collect(); + let mut v: Vec<_> = self.footnotes.drain(..).map(|(_, x)| x).collect(); v.sort_by(|a, b| a.1.cmp(&b.1)); let mut ret = String::from("


    "); for (mut content, id) in v { diff --git a/src/librustdoc/html/render/context.rs b/src/librustdoc/html/render/context.rs index bce3f21890857..dc4d45e592eb7 100644 --- a/src/librustdoc/html/render/context.rs +++ b/src/librustdoc/html/render/context.rs @@ -6,7 +6,7 @@ use std::rc::Rc; use std::sync::mpsc::{Receiver, channel}; use rinja::Template; -use rustc_data_structures::fx::{FxHashMap, FxHashSet}; +use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap, FxIndexSet}; use rustc_hir::def_id::{DefIdMap, LOCAL_CRATE}; use rustc_middle::ty::TyCtxt; use rustc_session::Session; @@ -69,16 +69,16 @@ pub(crate) struct Context<'tcx> { /// `true`. pub(crate) include_sources: bool, /// Collection of all types with notable traits referenced in the current module. - pub(crate) types_with_notable_traits: FxHashSet, + pub(crate) types_with_notable_traits: FxIndexSet, /// Field used during rendering, to know if we're inside an inlined item. pub(crate) is_inside_inlined_module: bool, } // `Context` is cloned a lot, so we don't want the size to grow unexpectedly. #[cfg(all(not(windows), target_pointer_width = "64"))] -rustc_data_structures::static_assert_size!(Context<'_>, 160); +rustc_data_structures::static_assert_size!(Context<'_>, 184); #[cfg(all(windows, target_pointer_width = "64"))] -rustc_data_structures::static_assert_size!(Context<'_>, 168); +rustc_data_structures::static_assert_size!(Context<'_>, 192); /// Shared mutable state used in [`Context`] and elsewhere. pub(crate) struct SharedContext<'tcx> { @@ -90,7 +90,7 @@ pub(crate) struct SharedContext<'tcx> { /// creation of the context (contains info like the favicon and added html). pub(crate) layout: layout::Layout, /// The local file sources we've emitted and their respective url-paths. - pub(crate) local_sources: FxHashMap, + pub(crate) local_sources: FxIndexMap, /// Show the memory layout of types in the docs. pub(super) show_type_layout: bool, /// The base-URL of the issue tracker for when an item has been tagged with @@ -567,7 +567,7 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> { deref_id_map: Default::default(), shared: Rc::new(scx), include_sources, - types_with_notable_traits: FxHashSet::default(), + types_with_notable_traits: FxIndexSet::default(), is_inside_inlined_module: false, }; @@ -591,7 +591,7 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> { id_map: IdMap::new(), shared: Rc::clone(&self.shared), include_sources: self.include_sources, - types_with_notable_traits: FxHashSet::default(), + types_with_notable_traits: FxIndexSet::default(), is_inside_inlined_module: self.is_inside_inlined_module, } } diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index 227df0c5f3930..399730a01c82f 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -47,7 +47,7 @@ use std::{fs, str}; use rinja::Template; use rustc_attr::{ConstStability, DeprecatedSince, Deprecation, StabilityLevel, StableSince}; use rustc_data_structures::captures::Captures; -use rustc_data_structures::fx::{FxHashMap, FxHashSet}; +use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet}; use rustc_hir::Mutability; use rustc_hir::def_id::{DefId, DefIdSet}; use rustc_middle::ty::print::PrintTraitRefExt; @@ -328,24 +328,24 @@ impl Ord for ItemEntry { #[derive(Debug)] struct AllTypes { - structs: FxHashSet, - enums: FxHashSet, - unions: FxHashSet, - primitives: FxHashSet, - traits: FxHashSet, - macros: FxHashSet, - functions: FxHashSet, - type_aliases: FxHashSet, - statics: FxHashSet, - constants: FxHashSet, - attribute_macros: FxHashSet, - derive_macros: FxHashSet, - trait_aliases: FxHashSet, + structs: FxIndexSet, + enums: FxIndexSet, + unions: FxIndexSet, + primitives: FxIndexSet, + traits: FxIndexSet, + macros: FxIndexSet, + functions: FxIndexSet, + type_aliases: FxIndexSet, + statics: FxIndexSet, + constants: FxIndexSet, + attribute_macros: FxIndexSet, + derive_macros: FxIndexSet, + trait_aliases: FxIndexSet, } impl AllTypes { fn new() -> AllTypes { - let new_set = |cap| FxHashSet::with_capacity_and_hasher(cap, Default::default()); + let new_set = |cap| FxIndexSet::with_capacity_and_hasher(cap, Default::default()); AllTypes { structs: new_set(100), enums: new_set(100), @@ -437,7 +437,7 @@ impl AllTypes { } fn print(self, f: &mut Buffer) { - fn print_entries(f: &mut Buffer, e: &FxHashSet, kind: ItemSection) { + fn print_entries(f: &mut Buffer, e: &FxIndexSet, kind: ItemSection) { if !e.is_empty() { let mut e: Vec<&ItemEntry> = e.iter().collect(); e.sort(); @@ -1151,7 +1151,7 @@ fn render_attributes_in_code(w: &mut impl fmt::Write, it: &clean::Item, cx: &Con #[derive(Copy, Clone)] enum AssocItemLink<'a> { Anchor(Option<&'a str>), - GotoSource(ItemId, &'a FxHashSet), + GotoSource(ItemId, &'a FxIndexSet), } impl<'a> AssocItemLink<'a> { @@ -1494,7 +1494,7 @@ fn notable_traits_decl(ty: &clean::Type, cx: &Context<'_>) -> (String, String) { for it in &impl_.items { if let clean::AssocTypeItem(ref tydef, ref _bounds) = it.kind { out.push_str("
    "); - let empty_set = FxHashSet::default(); + let empty_set = FxIndexSet::default(); let src_link = AssocItemLink::GotoSource(trait_did.into(), &empty_set); assoc_type( &mut out, @@ -2526,7 +2526,7 @@ fn render_call_locations(mut w: W, cx: &mut Context<'_>, item: &c })() .unwrap_or(DUMMY_SP); - let mut decoration_info = FxHashMap::default(); + let mut decoration_info = FxIndexMap::default(); decoration_info.insert("highlight focus", vec![byte_ranges.remove(0)]); decoration_info.insert("highlight", byte_ranges); diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs index 38276e4d20c26..3c96f8736814e 100644 --- a/src/librustdoc/html/render/print_item.rs +++ b/src/librustdoc/html/render/print_item.rs @@ -6,7 +6,7 @@ use std::rc::Rc; use itertools::Itertools; use rinja::Template; use rustc_data_structures::captures::Captures; -use rustc_data_structures::fx::{FxHashMap, FxHashSet}; +use rustc_data_structures::fx::{FxHashMap, FxIndexSet}; use rustc_hir as hir; use rustc_hir::def::CtorKind; use rustc_hir::def_id::DefId; @@ -932,7 +932,7 @@ fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean: let cloned_shared = Rc::clone(&cx.shared); let cache = &cloned_shared.cache; - let mut extern_crates = FxHashSet::default(); + let mut extern_crates = FxIndexSet::default(); if !t.is_object_safe(cx.tcx()) { write_section_heading( diff --git a/src/librustdoc/html/render/search_index.rs b/src/librustdoc/html/render/search_index.rs index 660ca3b2594cc..c958458b662c2 100644 --- a/src/librustdoc/html/render/search_index.rs +++ b/src/librustdoc/html/render/search_index.rs @@ -774,7 +774,7 @@ pub(crate) fn get_function_type_for_search<'tcx>( fn get_index_type( clean_type: &clean::Type, generics: Vec, - rgen: &mut FxHashMap)>, + rgen: &mut FxIndexMap)>, ) -> RenderType { RenderType { id: get_index_type_id(clean_type, rgen), @@ -785,7 +785,7 @@ fn get_index_type( fn get_index_type_id( clean_type: &clean::Type, - rgen: &mut FxHashMap)>, + rgen: &mut FxIndexMap)>, ) -> Option { use rustc_hir::def::{DefKind, Res}; match *clean_type { @@ -854,7 +854,7 @@ fn simplify_fn_type<'a, 'tcx>( tcx: TyCtxt<'tcx>, recurse: usize, res: &mut Vec, - rgen: &mut FxHashMap)>, + rgen: &mut FxIndexMap)>, is_return: bool, cache: &Cache, ) { @@ -1198,7 +1198,7 @@ fn simplify_fn_constraint<'a, 'tcx>( tcx: TyCtxt<'tcx>, recurse: usize, res: &mut Vec<(RenderTypeId, Vec)>, - rgen: &mut FxHashMap)>, + rgen: &mut FxIndexMap)>, is_return: bool, cache: &Cache, ) { @@ -1285,7 +1285,7 @@ fn get_fn_inputs_and_outputs<'tcx>( ) -> (Vec, Vec, Vec>) { let decl = &func.decl; - let mut rgen: FxHashMap)> = Default::default(); + let mut rgen: FxIndexMap)> = Default::default(); let combined_generics; let (self_, generics) = if let Some((impl_self, impl_generics)) = impl_or_trait_generics { diff --git a/src/librustdoc/html/render/span_map.rs b/src/librustdoc/html/render/span_map.rs index 7e1ea5cde8320..b314b060368aa 100644 --- a/src/librustdoc/html/render/span_map.rs +++ b/src/librustdoc/html/render/span_map.rs @@ -1,6 +1,6 @@ use std::path::{Path, PathBuf}; -use rustc_data_structures::fx::FxHashMap; +use rustc_data_structures::fx::{FxHashMap, FxIndexMap}; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::{DefId, LOCAL_CRATE}; use rustc_hir::intravisit::{self, Visitor}; @@ -44,7 +44,7 @@ pub(crate) fn collect_spans_and_sources( src_root: &Path, include_sources: bool, generate_link_to_definition: bool, -) -> (FxHashMap, FxHashMap) { +) -> (FxIndexMap, FxHashMap) { let mut visitor = SpanMapVisitor { tcx, matches: FxHashMap::default() }; if include_sources { diff --git a/src/librustdoc/html/render/write_shared.rs b/src/librustdoc/html/render/write_shared.rs index af94b1042c05c..12b6346005697 100644 --- a/src/librustdoc/html/render/write_shared.rs +++ b/src/librustdoc/html/render/write_shared.rs @@ -28,7 +28,7 @@ use indexmap::IndexMap; use itertools::Itertools; use regex::Regex; use rustc_data_structures::flock; -use rustc_data_structures::fx::{FxHashMap, FxHashSet}; +use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet}; use rustc_middle::ty::TyCtxt; use rustc_middle::ty::fast_reject::DeepRejectCtxt; use rustc_span::Symbol; @@ -505,8 +505,8 @@ createSrcSidebar();", struct Hierarchy { parent: Weak, elem: OsString, - children: RefCell>>, - elems: RefCell>, + children: RefCell>>, + elems: RefCell>, } impl Hierarchy { @@ -961,8 +961,8 @@ impl Serialize for AliasSerializableImpl { fn get_path_parts( dst: &Path, crates_info: &[CrateInfo], -) -> FxHashMap> { - let mut templates: FxHashMap> = FxHashMap::default(); +) -> FxIndexMap> { + let mut templates: FxIndexMap> = FxIndexMap::default(); crates_info .iter() .map(|crate_info| T::from_crate_info(crate_info).parts.iter()) diff --git a/src/librustdoc/html/sources.rs b/src/librustdoc/html/sources.rs index 7be9cc0b8858e..f4a0ef01c253b 100644 --- a/src/librustdoc/html/sources.rs +++ b/src/librustdoc/html/sources.rs @@ -6,7 +6,7 @@ use std::rc::Rc; use std::{fmt, fs}; use rinja::Template; -use rustc_data_structures::fx::{FxHashMap, FxHashSet}; +use rustc_data_structures::fx::{FxHashSet, FxIndexMap}; use rustc_hir::def_id::LOCAL_CRATE; use rustc_middle::ty::TyCtxt; use rustc_session::Session; @@ -39,15 +39,15 @@ pub(crate) fn collect_local_sources<'tcx>( tcx: TyCtxt<'tcx>, src_root: &Path, krate: &clean::Crate, -) -> FxHashMap { - let mut lsc = LocalSourcesCollector { tcx, local_sources: FxHashMap::default(), src_root }; +) -> FxIndexMap { + let mut lsc = LocalSourcesCollector { tcx, local_sources: FxIndexMap::default(), src_root }; lsc.visit_crate(krate); lsc.local_sources } struct LocalSourcesCollector<'a, 'tcx> { tcx: TyCtxt<'tcx>, - local_sources: FxHashMap, + local_sources: FxIndexMap, src_root: &'a Path, } diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index 2be415e2e0ef3..10fc0ea999015 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -20,7 +20,6 @@ #![warn(rustc::internal)] #![allow(clippy::collapsible_if, clippy::collapsible_else_if)] #![allow(rustc::diagnostic_outside_of_impl)] -#![allow(rustc::potential_query_instability)] #![allow(rustc::untranslatable_diagnostic)] extern crate thin_vec; @@ -99,7 +98,7 @@ use crate::clean::utils::DOC_RUST_LANG_ORG_CHANNEL; /// Commas between elements are required (even if the expression is a block). macro_rules! map { ($( $key: expr => $val: expr ),* $(,)*) => {{ - let mut map = ::rustc_data_structures::fx::FxHashMap::default(); + let mut map = ::rustc_data_structures::fx::FxIndexMap::default(); $( map.insert($key, $val); )* map }} diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs index def9ac3ce4b5a..2eb0e32b83173 100644 --- a/src/librustdoc/passes/collect_intra_doc_links.rs +++ b/src/librustdoc/passes/collect_intra_doc_links.rs @@ -9,7 +9,7 @@ use std::ops::Range; use pulldown_cmark::LinkType; use rustc_ast::util::comments::may_have_doc_links; -use rustc_data_structures::fx::{FxHashMap, FxHashSet}; +use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet}; use rustc_data_structures::intern::Interned; use rustc_errors::{Applicability, Diag, DiagMessage}; use rustc_hir::def::Namespace::*; @@ -778,9 +778,9 @@ fn trait_impls_for<'a>( cx: &mut DocContext<'a>, ty: Ty<'a>, module: DefId, -) -> FxHashSet<(DefId, DefId)> { +) -> FxIndexSet<(DefId, DefId)> { let tcx = cx.tcx; - let mut impls = FxHashSet::default(); + let mut impls = FxIndexSet::default(); for &trait_ in tcx.doc_link_traits_in_scope(module) { tcx.for_each_relevant_impl(trait_, ty, |impl_| { diff --git a/src/librustdoc/passes/collect_trait_impls.rs b/src/librustdoc/passes/collect_trait_impls.rs index b307e84e42ec2..d1a1f0df3e7ed 100644 --- a/src/librustdoc/passes/collect_trait_impls.rs +++ b/src/librustdoc/passes/collect_trait_impls.rs @@ -219,7 +219,7 @@ pub(crate) fn collect_trait_impls(mut krate: Crate, cx: &mut DocContext<'_>) -> panic!("collect-trait-impls can't run"); }; - krate.external_traits.extend(cx.external_traits.drain()); + krate.external_traits.extend(cx.external_traits.drain(..)); krate } diff --git a/src/librustdoc/scrape_examples.rs b/src/librustdoc/scrape_examples.rs index 9d4d203562cb4..a59c43bfbf904 100644 --- a/src/librustdoc/scrape_examples.rs +++ b/src/librustdoc/scrape_examples.rs @@ -3,7 +3,7 @@ use std::fs; use std::path::PathBuf; -use rustc_data_structures::fx::FxHashMap; +use rustc_data_structures::fx::FxIndexMap; use rustc_errors::DiagCtxtHandle; use rustc_hir::intravisit::{self, Visitor}; use rustc_hir::{self as hir}; @@ -102,8 +102,8 @@ pub(crate) struct CallData { pub(crate) is_bin: bool, } -pub(crate) type FnCallLocations = FxHashMap; -pub(crate) type AllCallLocations = FxHashMap; +pub(crate) type FnCallLocations = FxIndexMap; +pub(crate) type AllCallLocations = FxIndexMap; /// Visitor for traversing a crate and finding instances of function calls. struct FindCalls<'a, 'tcx> { @@ -293,7 +293,7 @@ pub(crate) fn run( debug!("Scrape examples target_crates: {target_crates:?}"); // Run call-finder on all items - let mut calls = FxHashMap::default(); + let mut calls = FxIndexMap::default(); let mut finder = FindCalls { calls: &mut calls, tcx, map: tcx.hir(), cx, target_crates, bin_crate }; tcx.hir().visit_all_item_likes_in_crate(&mut finder); @@ -332,7 +332,7 @@ pub(crate) fn load_call_locations( with_examples: Vec, dcx: DiagCtxtHandle<'_>, ) -> AllCallLocations { - let mut all_calls: AllCallLocations = FxHashMap::default(); + let mut all_calls: AllCallLocations = FxIndexMap::default(); for path in with_examples { let bytes = match fs::read(&path) { Ok(bytes) => bytes, diff --git a/src/librustdoc/theme.rs b/src/librustdoc/theme.rs index 409728a8e867c..2c00bb7e13295 100644 --- a/src/librustdoc/theme.rs +++ b/src/librustdoc/theme.rs @@ -1,10 +1,9 @@ -use std::collections::hash_map::Entry; use std::fs; use std::iter::Peekable; use std::path::Path; use std::str::Chars; -use rustc_data_structures::fx::FxHashMap; +use rustc_data_structures::fx::{FxIndexMap, IndexEntry}; use rustc_errors::DiagCtxtHandle; #[cfg(test)] @@ -12,8 +11,8 @@ mod tests; #[derive(Debug)] pub(crate) struct CssPath { - pub(crate) rules: FxHashMap, - pub(crate) children: FxHashMap, + pub(crate) rules: FxIndexMap, + pub(crate) children: FxIndexMap, } /// When encountering a `"` or a `'`, returns the whole string, including the quote characters. @@ -120,10 +119,10 @@ fn parse_rules( content: &str, selector: String, iter: &mut Peekable>, - paths: &mut FxHashMap, + paths: &mut FxIndexMap, ) -> Result<(), String> { - let mut rules = FxHashMap::default(); - let mut children = FxHashMap::default(); + let mut rules = FxIndexMap::default(); + let mut children = FxIndexMap::default(); loop { // If the parent isn't a "normal" CSS selector, we only expect sub-selectors and not CSS @@ -146,10 +145,10 @@ fn parse_rules( return Err(format!("Found empty value for rule `{rule}` in selector `{selector}`")); } match rules.entry(rule) { - Entry::Occupied(mut o) => { + IndexEntry::Occupied(mut o) => { *o.get_mut() = value; } - Entry::Vacant(v) => { + IndexEntry::Vacant(v) => { v.insert(value); } } @@ -159,7 +158,7 @@ fn parse_rules( } match paths.entry(selector) { - Entry::Occupied(mut o) => { + IndexEntry::Occupied(mut o) => { let v = o.get_mut(); for (key, value) in rules.into_iter() { v.rules.insert(key, value); @@ -168,7 +167,7 @@ fn parse_rules( v.children.insert(sel, child); } } - Entry::Vacant(v) => { + IndexEntry::Vacant(v) => { v.insert(CssPath { rules, children }); } } @@ -178,7 +177,7 @@ fn parse_rules( pub(crate) fn parse_selectors( content: &str, iter: &mut Peekable>, - paths: &mut FxHashMap, + paths: &mut FxIndexMap, ) -> Result<(), String> { let mut selector = String::new(); @@ -202,17 +201,17 @@ pub(crate) fn parse_selectors( /// The entry point to parse the CSS rules. Every time we encounter a `{`, we then parse the rules /// inside it. -pub(crate) fn load_css_paths(content: &str) -> Result, String> { +pub(crate) fn load_css_paths(content: &str) -> Result, String> { let mut iter = content.chars().peekable(); - let mut paths = FxHashMap::default(); + let mut paths = FxIndexMap::default(); parse_selectors(content, &mut iter, &mut paths)?; Ok(paths) } pub(crate) fn get_differences( - origin: &FxHashMap, - against: &FxHashMap, + origin: &FxIndexMap, + against: &FxIndexMap, v: &mut Vec, ) { for (selector, entry) in origin.iter() { @@ -235,7 +234,7 @@ pub(crate) fn get_differences( pub(crate) fn test_theme_against>( f: &P, - origin: &FxHashMap, + origin: &FxIndexMap, dcx: DiagCtxtHandle<'_>, ) -> (bool, Vec) { let against = match fs::read_to_string(f) From aa75b5f686945b0d2c4927ae3f277cd2216a1350 Mon Sep 17 00:00:00 2001 From: mu001999 Date: Sun, 6 Oct 2024 18:08:28 +0800 Subject: [PATCH 1930/2194] Update out-dated link --- compiler/rustc_driver_impl/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_driver_impl/README.md b/compiler/rustc_driver_impl/README.md index 6d7fba36fb3d0..9fa4242de3c82 100644 --- a/compiler/rustc_driver_impl/README.md +++ b/compiler/rustc_driver_impl/README.md @@ -7,4 +7,4 @@ options). For more information about how the driver works, see the [rustc dev guide]. -[rustc dev guide]: https://rustc-dev-guide.rust-lang.org/rustc-driver.html +[rustc dev guide]: https://rustc-dev-guide.rust-lang.org/rustc-driver/intro.html From 3f90bb15ed1672984c826b38d93e6d771c320701 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Sun, 6 Oct 2024 20:59:24 +1100 Subject: [PATCH 1931/2194] coverage: Make `BcbCounter` module-private --- compiler/rustc_mir_transform/src/coverage/counters.rs | 8 ++++---- compiler/rustc_mir_transform/src/coverage/mod.rs | 8 ++------ 2 files changed, 6 insertions(+), 10 deletions(-) diff --git a/compiler/rustc_mir_transform/src/coverage/counters.rs b/compiler/rustc_mir_transform/src/coverage/counters.rs index ef4031c5c034f..a954ca359857d 100644 --- a/compiler/rustc_mir_transform/src/coverage/counters.rs +++ b/compiler/rustc_mir_transform/src/coverage/counters.rs @@ -13,13 +13,13 @@ use crate::coverage::graph::{BasicCoverageBlock, CoverageGraph, TraverseCoverage /// The coverage counter or counter expression associated with a particular /// BCB node or BCB edge. #[derive(Clone, Copy, PartialEq, Eq, Hash)] -pub(super) enum BcbCounter { +enum BcbCounter { Counter { id: CounterId }, Expression { id: ExpressionId }, } impl BcbCounter { - pub(super) fn as_term(&self) -> CovTerm { + fn as_term(&self) -> CovTerm { match *self { BcbCounter::Counter { id, .. } => CovTerm::Counter(id), BcbCounter::Expression { id, .. } => CovTerm::Expression(id), @@ -218,8 +218,8 @@ impl CoverageCounters { } } - pub(super) fn bcb_counter(&self, bcb: BasicCoverageBlock) -> Option { - self.bcb_counters[bcb] + pub(super) fn term_for_bcb(&self, bcb: BasicCoverageBlock) -> Option { + self.bcb_counters[bcb].map(|counter| counter.as_term()) } /// Returns an iterator over all the nodes/edges in the coverage graph that diff --git a/compiler/rustc_mir_transform/src/coverage/mod.rs b/compiler/rustc_mir_transform/src/coverage/mod.rs index 104f340c8d63f..97684d796b726 100644 --- a/compiler/rustc_mir_transform/src/coverage/mod.rs +++ b/compiler/rustc_mir_transform/src/coverage/mod.rs @@ -153,12 +153,8 @@ fn create_mappings<'tcx>( &source_file.name.for_scope(tcx.sess, RemapPathScopeComponents::MACRO).to_string_lossy(), ); - let term_for_bcb = |bcb| { - coverage_counters - .bcb_counter(bcb) - .expect("all BCBs with spans were given counters") - .as_term() - }; + let term_for_bcb = + |bcb| coverage_counters.term_for_bcb(bcb).expect("all BCBs with spans were given counters"); let region_for_span = |span: Span| make_source_region(source_map, file_name, span, body_span); // Fully destructure the mappings struct to make sure we don't miss any kinds. From c6e4fcd4faaa57fa059165a5c24b119d1e8f0f7f Mon Sep 17 00:00:00 2001 From: Zalathar Date: Sat, 5 Oct 2024 17:08:07 +1000 Subject: [PATCH 1932/2194] coverage: Have MakeBcbCounters own its CoverageCounters --- .../src/coverage/counters.rs | 27 ++++++++++--------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/compiler/rustc_mir_transform/src/coverage/counters.rs b/compiler/rustc_mir_transform/src/coverage/counters.rs index a954ca359857d..95c4d9f88fbe9 100644 --- a/compiler/rustc_mir_transform/src/coverage/counters.rs +++ b/compiler/rustc_mir_transform/src/coverage/counters.rs @@ -80,19 +80,20 @@ impl CoverageCounters { basic_coverage_blocks: &CoverageGraph, bcb_needs_counter: impl Fn(BasicCoverageBlock) -> bool, ) -> Self { - let num_bcbs = basic_coverage_blocks.num_nodes(); + let mut counters = MakeBcbCounters::new(basic_coverage_blocks); + counters.make_bcb_counters(bcb_needs_counter); - let mut this = Self { + counters.coverage_counters + } + + fn with_num_bcbs(num_bcbs: usize) -> Self { + Self { counter_increment_sites: IndexVec::new(), bcb_counters: IndexVec::from_elem_n(None, num_bcbs), bcb_edge_counters: FxHashMap::default(), expressions: IndexVec::new(), expressions_memo: FxHashMap::default(), - }; - - MakeBcbCounters::new(&mut this, basic_coverage_blocks).make_bcb_counters(bcb_needs_counter); - - this + } } /// Shared helper used by [`Self::make_phys_node_counter`] and @@ -265,16 +266,16 @@ impl CoverageCounters { /// Helper struct that allows counter creation to inspect the BCB graph. struct MakeBcbCounters<'a> { - coverage_counters: &'a mut CoverageCounters, + coverage_counters: CoverageCounters, basic_coverage_blocks: &'a CoverageGraph, } impl<'a> MakeBcbCounters<'a> { - fn new( - coverage_counters: &'a mut CoverageCounters, - basic_coverage_blocks: &'a CoverageGraph, - ) -> Self { - Self { coverage_counters, basic_coverage_blocks } + fn new(basic_coverage_blocks: &'a CoverageGraph) -> Self { + Self { + coverage_counters: CoverageCounters::with_num_bcbs(basic_coverage_blocks.num_nodes()), + basic_coverage_blocks, + } } fn make_bcb_counters(&mut self, bcb_needs_counter: impl Fn(BasicCoverageBlock) -> bool) { From ab154e69993f15c4f37842dd2c2dfc6750af6a8a Mon Sep 17 00:00:00 2001 From: Zalathar Date: Sun, 6 Oct 2024 22:44:14 +1100 Subject: [PATCH 1933/2194] coverage: Store `bcb_needs_counter` in a field as a bitset This makes it possible for other parts of counter-assignment to check whether a node is guaranteed to end up with some kind of counter. Switching from `impl Fn` to a concrete `&BitSet` just avoids the hassle of trying to store a closure in a struct field, and currently there's no foreseeable need for this information to not be a bitset. --- .../src/coverage/counters.rs | 19 +++++++++++++------ .../rustc_mir_transform/src/coverage/mod.rs | 3 +-- 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/compiler/rustc_mir_transform/src/coverage/counters.rs b/compiler/rustc_mir_transform/src/coverage/counters.rs index 95c4d9f88fbe9..9408815675692 100644 --- a/compiler/rustc_mir_transform/src/coverage/counters.rs +++ b/compiler/rustc_mir_transform/src/coverage/counters.rs @@ -4,6 +4,7 @@ use rustc_data_structures::captures::Captures; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::graph::DirectedGraph; use rustc_index::IndexVec; +use rustc_index::bit_set::BitSet; use rustc_middle::bug; use rustc_middle::mir::coverage::{CounterId, CovTerm, Expression, ExpressionId, Op}; use tracing::{debug, debug_span, instrument}; @@ -78,10 +79,10 @@ impl CoverageCounters { /// counters or counter expressions for nodes and edges as required. pub(super) fn make_bcb_counters( basic_coverage_blocks: &CoverageGraph, - bcb_needs_counter: impl Fn(BasicCoverageBlock) -> bool, + bcb_needs_counter: &BitSet, ) -> Self { - let mut counters = MakeBcbCounters::new(basic_coverage_blocks); - counters.make_bcb_counters(bcb_needs_counter); + let mut counters = MakeBcbCounters::new(basic_coverage_blocks, bcb_needs_counter); + counters.make_bcb_counters(); counters.coverage_counters } @@ -268,17 +269,23 @@ impl CoverageCounters { struct MakeBcbCounters<'a> { coverage_counters: CoverageCounters, basic_coverage_blocks: &'a CoverageGraph, + bcb_needs_counter: &'a BitSet, } impl<'a> MakeBcbCounters<'a> { - fn new(basic_coverage_blocks: &'a CoverageGraph) -> Self { + fn new( + basic_coverage_blocks: &'a CoverageGraph, + bcb_needs_counter: &'a BitSet, + ) -> Self { + assert_eq!(basic_coverage_blocks.num_nodes(), bcb_needs_counter.domain_size()); Self { coverage_counters: CoverageCounters::with_num_bcbs(basic_coverage_blocks.num_nodes()), basic_coverage_blocks, + bcb_needs_counter, } } - fn make_bcb_counters(&mut self, bcb_needs_counter: impl Fn(BasicCoverageBlock) -> bool) { + fn make_bcb_counters(&mut self) { debug!("make_bcb_counters(): adding a counter or expression to each BasicCoverageBlock"); // Traverse the coverage graph, ensuring that every node that needs a @@ -291,7 +298,7 @@ impl<'a> MakeBcbCounters<'a> { let mut traversal = TraverseCoverageGraphWithLoops::new(self.basic_coverage_blocks); while let Some(bcb) = traversal.next() { let _span = debug_span!("traversal", ?bcb).entered(); - if bcb_needs_counter(bcb) { + if self.bcb_needs_counter.contains(bcb) { self.make_node_counter_and_out_edge_counters(&traversal, bcb); } } diff --git a/compiler/rustc_mir_transform/src/coverage/mod.rs b/compiler/rustc_mir_transform/src/coverage/mod.rs index 97684d796b726..79482ba39198e 100644 --- a/compiler/rustc_mir_transform/src/coverage/mod.rs +++ b/compiler/rustc_mir_transform/src/coverage/mod.rs @@ -94,9 +94,8 @@ fn instrument_function_for_coverage<'tcx>(tcx: TyCtxt<'tcx>, mir_body: &mut mir: return; } - let bcb_has_counter_mappings = |bcb| bcbs_with_counter_mappings.contains(bcb); let coverage_counters = - CoverageCounters::make_bcb_counters(&basic_coverage_blocks, bcb_has_counter_mappings); + CoverageCounters::make_bcb_counters(&basic_coverage_blocks, &bcbs_with_counter_mappings); let mappings = create_mappings(tcx, &hir_info, &extracted_mappings, &coverage_counters); if mappings.is_empty() { From 0df736c2a9a7b5ceddd90bfdd6aa991801145a54 Mon Sep 17 00:00:00 2001 From: "Naveen R. Iyer" Date: Sat, 28 Sep 2024 20:27:51 -0500 Subject: [PATCH 1934/2194] add clarity for custom path installation install.sysconfdir is another value, in addition to install.prefix, that could be set for custom path installation. Signed-off-by: Naveen R. Iyer --- INSTALL.md | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/INSTALL.md b/INSTALL.md index ded0b59fc6cd3..74fcc58348b43 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -79,9 +79,23 @@ See [the rustc-dev-guide for more info][sysllvm]. ./configure ``` - If you plan to use `x.py install` to create an installation, it is - recommended that you set the `prefix` value in the `[install]` section to a - directory: `./configure --set install.prefix=` + If you plan to use `x.py install` to create an installation, you can either + set `DESTDIR` environment variable to your custom directory path: + + ```bash + export DESTDIR= + ``` + + or set `prefix` and `sysconfdir` in the `[install]` section to your custom + directory path: + + ```sh + ./configure --set install.prefix= --set install.sysconfdir= + ``` + + When the `DESTDIR` environment variable is present, the `prefix` and + `sysconfdir` values are combined with the path from the `DESTDIR` + environment variable. 3. Build and install: From 6dfc4a0473ed0901b9c0d09f5189c41f3882d5fc Mon Sep 17 00:00:00 2001 From: codemountains <4kz12zz@gmail.com> Date: Fri, 4 Oct 2024 21:59:04 +0900 Subject: [PATCH 1935/2194] Rename NestedMetaItem to MetaItemInner --- compiler/rustc_ast/src/ast.rs | 4 +- compiler/rustc_ast/src/attr/mod.rs | 48 +++++++++---------- compiler/rustc_ast/src/mut_visit.rs | 8 ++-- compiler/rustc_ast_pretty/src/pprust/mod.rs | 2 +- compiler/rustc_ast_pretty/src/pprust/state.rs | 8 ++-- compiler/rustc_attr/src/builtin.rs | 24 +++++----- compiler/rustc_builtin_macros/src/cfg.rs | 2 +- compiler/rustc_builtin_macros/src/derive.rs | 6 +-- .../rustc_codegen_ssa/src/codegen_attrs.rs | 4 +- compiler/rustc_codegen_ssa/src/lib.rs | 2 +- compiler/rustc_expand/src/base.rs | 4 +- compiler/rustc_expand/src/config.rs | 6 +-- compiler/rustc_expand/src/expand.rs | 4 +- .../src/persist/dirty_clean.rs | 6 +-- compiler/rustc_lint/src/levels.rs | 2 +- compiler/rustc_middle/src/ty/context.rs | 5 +- .../src/framework/engine.rs | 2 +- compiler/rustc_parse/src/lib.rs | 4 +- compiler/rustc_parse/src/parser/attr.rs | 10 ++-- compiler/rustc_parse/src/validate_attr.rs | 6 +-- compiler/rustc_passes/src/check_attr.rs | 29 ++++++----- compiler/rustc_resolve/src/diagnostics.rs | 5 +- compiler/rustc_session/src/cstore.rs | 2 +- .../traits/on_unimplemented.rs | 6 +-- src/librustdoc/clean/cfg.rs | 14 +++--- src/librustdoc/clean/cfg/tests.rs | 18 +++---- src/librustdoc/clean/types.rs | 18 +++---- .../attrs/allow_attributes_without_reason.rs | 6 +-- .../attrs/blanket_clippy_restriction_lints.rs | 4 +- .../clippy/clippy_lints/src/attrs/mod.rs | 4 +- .../clippy_lints/src/attrs/non_minimal_cfg.rs | 6 +-- .../src/attrs/useless_attribute.rs | 4 +- .../clippy/clippy_lints/src/attrs/utils.rs | 8 ++-- .../clippy/clippy_lints/src/cfg_not_test.rs | 4 +- src/tools/clippy/clippy_lints/src/returns.rs | 4 +- src/tools/rustfmt/src/attr.rs | 16 +++---- src/tools/rustfmt/src/overflow.rs | 25 +++++----- src/tools/rustfmt/src/spanned.rs | 2 +- src/tools/rustfmt/src/utils.rs | 8 ++-- 39 files changed, 167 insertions(+), 173 deletions(-) diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index 37f429cce44d7..18d27167ec982 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -511,7 +511,7 @@ pub enum MetaItemKind { /// List meta item. /// /// E.g., `#[derive(..)]`, where the field represents the `..`. - List(ThinVec), + List(ThinVec), /// Name value meta item. /// @@ -523,7 +523,7 @@ pub enum MetaItemKind { /// /// E.g., each of `Clone`, `Copy` in `#[derive(Clone, Copy)]`. #[derive(Clone, Encodable, Decodable, Debug, HashStable_Generic)] -pub enum NestedMetaItem { +pub enum MetaItemInner { /// A full MetaItem, for recursive meta items. MetaItem(MetaItem), diff --git a/compiler/rustc_ast/src/attr/mod.rs b/compiler/rustc_ast/src/attr/mod.rs index 338d50cb39424..b73412a4b1de9 100644 --- a/compiler/rustc_ast/src/attr/mod.rs +++ b/compiler/rustc_ast/src/attr/mod.rs @@ -11,7 +11,7 @@ use thin_vec::{ThinVec, thin_vec}; use crate::ast::{ AttrArgs, AttrArgsEq, AttrId, AttrItem, AttrKind, AttrStyle, AttrVec, Attribute, DUMMY_NODE_ID, - DelimArgs, Expr, ExprKind, LitKind, MetaItem, MetaItemKind, MetaItemLit, NestedMetaItem, + DelimArgs, Expr, ExprKind, LitKind, MetaItem, MetaItemInner, MetaItemKind, MetaItemLit, NormalAttr, Path, PathSegment, Safety, }; use crate::ptr::P; @@ -136,7 +136,7 @@ impl Attribute { } } - pub fn meta_item_list(&self) -> Option> { + pub fn meta_item_list(&self) -> Option> { match &self.kind { AttrKind::Normal(normal) => normal.item.meta_item_list(), AttrKind::DocComment(..) => None, @@ -223,7 +223,7 @@ impl AttrItem { self.args.span().map_or(self.path.span, |args_span| self.path.span.to(args_span)) } - fn meta_item_list(&self) -> Option> { + fn meta_item_list(&self) -> Option> { match &self.args { AttrArgs::Delimited(args) if args.delim == Delimiter::Parenthesis => { MetaItemKind::list_from_tokens(args.tokens.clone()) @@ -285,7 +285,7 @@ impl MetaItem { matches!(self.kind, MetaItemKind::Word) } - pub fn meta_item_list(&self) -> Option<&[NestedMetaItem]> { + pub fn meta_item_list(&self) -> Option<&[MetaItemInner]> { match &self.kind { MetaItemKind::List(l) => Some(&**l), _ => None, @@ -393,11 +393,11 @@ impl MetaItem { } impl MetaItemKind { - fn list_from_tokens(tokens: TokenStream) -> Option> { + fn list_from_tokens(tokens: TokenStream) -> Option> { let mut tokens = tokens.trees().peekable(); let mut result = ThinVec::new(); while tokens.peek().is_some() { - let item = NestedMetaItem::from_tokens(&mut tokens)?; + let item = MetaItemInner::from_tokens(&mut tokens)?; result.push(item); match tokens.next() { None | Some(TokenTree::Token(Token { kind: token::Comma, .. }, _)) => {} @@ -460,11 +460,11 @@ impl MetaItemKind { } } -impl NestedMetaItem { +impl MetaItemInner { pub fn span(&self) -> Span { match self { - NestedMetaItem::MetaItem(item) => item.span, - NestedMetaItem::Lit(lit) => lit.span, + MetaItemInner::MetaItem(item) => item.span, + MetaItemInner::Lit(lit) => lit.span, } } @@ -488,7 +488,7 @@ impl NestedMetaItem { } /// Gets a list of inner meta items from a list `MetaItem` type. - pub fn meta_item_list(&self) -> Option<&[NestedMetaItem]> { + pub fn meta_item_list(&self) -> Option<&[MetaItemInner]> { self.meta_item().and_then(|meta_item| meta_item.meta_item_list()) } @@ -519,28 +519,28 @@ impl NestedMetaItem { self.meta_item().and_then(|meta_item| meta_item.value_str()) } - /// Returns the `MetaItemLit` if `self` is a `NestedMetaItem::Literal`s. + /// Returns the `MetaItemLit` if `self` is a `MetaItemInner::Literal`s. pub fn lit(&self) -> Option<&MetaItemLit> { match self { - NestedMetaItem::Lit(lit) => Some(lit), + MetaItemInner::Lit(lit) => Some(lit), _ => None, } } - /// Returns the `MetaItem` if `self` is a `NestedMetaItem::MetaItem` or if it's - /// `NestedMetaItem::Lit(MetaItemLit { kind: LitKind::Bool(_), .. })`. - pub fn meta_item_or_bool(&self) -> Option<&NestedMetaItem> { + /// Returns the `MetaItem` if `self` is a `MetaItemInner::MetaItem` or if it's + /// `MetaItemInner::Lit(MetaItemLit { kind: LitKind::Bool(_), .. })`. + pub fn meta_item_or_bool(&self) -> Option<&MetaItemInner> { match self { - NestedMetaItem::MetaItem(_item) => Some(self), - NestedMetaItem::Lit(MetaItemLit { kind: LitKind::Bool(_), .. }) => Some(self), + MetaItemInner::MetaItem(_item) => Some(self), + MetaItemInner::Lit(MetaItemLit { kind: LitKind::Bool(_), .. }) => Some(self), _ => None, } } - /// Returns the `MetaItem` if `self` is a `NestedMetaItem::MetaItem`. + /// Returns the `MetaItem` if `self` is a `MetaItemInner::MetaItem`. pub fn meta_item(&self) -> Option<&MetaItem> { match self { - NestedMetaItem::MetaItem(item) => Some(item), + MetaItemInner::MetaItem(item) => Some(item), _ => None, } } @@ -550,22 +550,22 @@ impl NestedMetaItem { self.meta_item().is_some() } - fn from_tokens<'a, I>(tokens: &mut iter::Peekable) -> Option + fn from_tokens<'a, I>(tokens: &mut iter::Peekable) -> Option where I: Iterator, { match tokens.peek() { Some(TokenTree::Token(token, _)) if let Some(lit) = MetaItemLit::from_token(token) => { tokens.next(); - return Some(NestedMetaItem::Lit(lit)); + return Some(MetaItemInner::Lit(lit)); } Some(TokenTree::Delimited(.., Delimiter::Invisible, inner_tokens)) => { tokens.next(); - return NestedMetaItem::from_tokens(&mut inner_tokens.trees().peekable()); + return MetaItemInner::from_tokens(&mut inner_tokens.trees().peekable()); } _ => {} } - MetaItem::from_tokens(tokens).map(NestedMetaItem::MetaItem) + MetaItem::from_tokens(tokens).map(MetaItemInner::MetaItem) } } @@ -676,6 +676,6 @@ pub fn contains_name(attrs: &[Attribute], name: Symbol) -> bool { find_by_name(attrs, name).is_some() } -pub fn list_contains_name(items: &[NestedMetaItem], name: Symbol) -> bool { +pub fn list_contains_name(items: &[MetaItemInner], name: Symbol) -> bool { items.iter().any(|item| item.has_name(name)) } diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs index 104f84f26e0af..6ce23a1479d05 100644 --- a/compiler/rustc_ast/src/mut_visit.rs +++ b/compiler/rustc_ast/src/mut_visit.rs @@ -83,7 +83,7 @@ pub trait MutVisitor: Sized { walk_crate(self, c) } - fn visit_meta_list_item(&mut self, list_item: &mut NestedMetaItem) { + fn visit_meta_list_item(&mut self, list_item: &mut MetaItemInner) { walk_meta_list_item(self, list_item); } @@ -659,10 +659,10 @@ fn walk_macro_def(vis: &mut T, macro_def: &mut MacroDef) { visit_delim_args(vis, body); } -fn walk_meta_list_item(vis: &mut T, li: &mut NestedMetaItem) { +fn walk_meta_list_item(vis: &mut T, li: &mut MetaItemInner) { match li { - NestedMetaItem::MetaItem(mi) => vis.visit_meta_item(mi), - NestedMetaItem::Lit(_lit) => {} + MetaItemInner::MetaItem(mi) => vis.visit_meta_item(mi), + MetaItemInner::Lit(_lit) => {} } } diff --git a/compiler/rustc_ast_pretty/src/pprust/mod.rs b/compiler/rustc_ast_pretty/src/pprust/mod.rs index 726ceebe3c524..97cb6e52d5625 100644 --- a/compiler/rustc_ast_pretty/src/pprust/mod.rs +++ b/compiler/rustc_ast_pretty/src/pprust/mod.rs @@ -67,7 +67,7 @@ pub fn vis_to_string(v: &ast::Visibility) -> String { State::new().vis_to_string(v) } -pub fn meta_list_item_to_string(li: &ast::NestedMetaItem) -> String { +pub fn meta_list_item_to_string(li: &ast::MetaItemInner) -> String { State::new().meta_list_item_to_string(li) } diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs index 7e07ccf28a0cb..884cc413bd583 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state.rs @@ -2006,10 +2006,10 @@ impl<'a> State<'a> { self.print_attribute_inline(attr, false) } - fn print_meta_list_item(&mut self, item: &ast::NestedMetaItem) { + fn print_meta_list_item(&mut self, item: &ast::MetaItemInner) { match item { - ast::NestedMetaItem::MetaItem(mi) => self.print_meta_item(mi), - ast::NestedMetaItem::Lit(lit) => self.print_meta_item_lit(lit), + ast::MetaItemInner::MetaItem(mi) => self.print_meta_item(mi), + ast::MetaItemInner::Lit(lit) => self.print_meta_item_lit(lit), } } @@ -2054,7 +2054,7 @@ impl<'a> State<'a> { Self::to_string(|s| s.print_path_segment(p, false)) } - pub(crate) fn meta_list_item_to_string(&self, li: &ast::NestedMetaItem) -> String { + pub(crate) fn meta_list_item_to_string(&self, li: &ast::MetaItemInner) -> String { Self::to_string(|s| s.print_meta_list_item(li)) } diff --git a/compiler/rustc_attr/src/builtin.rs b/compiler/rustc_attr/src/builtin.rs index d6a7dbad12d4a..c1db4d07dfc86 100644 --- a/compiler/rustc_attr/src/builtin.rs +++ b/compiler/rustc_attr/src/builtin.rs @@ -4,7 +4,7 @@ use std::num::NonZero; use rustc_abi::Align; use rustc_ast::{ - self as ast, Attribute, LitKind, MetaItem, MetaItemKind, MetaItemLit, NestedMetaItem, NodeId, + self as ast, Attribute, LitKind, MetaItem, MetaItemInner, MetaItemKind, MetaItemLit, NodeId, attr, }; use rustc_ast_pretty::pprust; @@ -534,7 +534,7 @@ pub struct Condition { /// Tests if a cfg-pattern matches the cfg set pub fn cfg_matches( - cfg: &ast::NestedMetaItem, + cfg: &ast::MetaItemInner, sess: &Session, lint_node_id: NodeId, features: Option<&Features>, @@ -605,7 +605,7 @@ pub fn parse_version(s: Symbol) -> Option { /// Evaluate a cfg-like condition (with `any` and `all`), using `eval` to /// evaluate individual items. pub fn eval_condition( - cfg: &ast::NestedMetaItem, + cfg: &ast::MetaItemInner, sess: &Session, features: Option<&Features>, eval: &mut impl FnMut(Condition) -> bool, @@ -613,8 +613,8 @@ pub fn eval_condition( let dcx = sess.dcx(); let cfg = match cfg { - ast::NestedMetaItem::MetaItem(meta_item) => meta_item, - ast::NestedMetaItem::Lit(MetaItemLit { kind: LitKind::Bool(b), .. }) => { + ast::MetaItemInner::MetaItem(meta_item) => meta_item, + ast::MetaItemInner::Lit(MetaItemLit { kind: LitKind::Bool(b), .. }) => { if let Some(features) = features { // we can't use `try_gate_cfg` as symbols don't differentiate between `r#true` // and `true`, and we want to keep the former working without feature gate @@ -646,12 +646,12 @@ pub fn eval_condition( ast::MetaItemKind::List(mis) if cfg.name_or_empty() == sym::version => { try_gate_cfg(sym::version, cfg.span, sess, features); let (min_version, span) = match &mis[..] { - [NestedMetaItem::Lit(MetaItemLit { kind: LitKind::Str(sym, ..), span, .. })] => { + [MetaItemInner::Lit(MetaItemLit { kind: LitKind::Str(sym, ..), span, .. })] => { (sym, span) } [ - NestedMetaItem::Lit(MetaItemLit { span, .. }) - | NestedMetaItem::MetaItem(MetaItem { span, .. }), + MetaItemInner::Lit(MetaItemLit { span, .. }) + | MetaItemInner::MetaItem(MetaItem { span, .. }), ] => { dcx.emit_err(session_diagnostics::ExpectedVersionLiteral { span: *span }); return false; @@ -729,7 +729,7 @@ pub fn eval_condition( } res & eval_condition( - &ast::NestedMetaItem::MetaItem(mi), + &ast::MetaItemInner::MetaItem(mi), sess, features, eval, @@ -873,7 +873,7 @@ pub fn find_deprecation( for meta in list { match meta { - NestedMetaItem::MetaItem(mi) => match mi.name_or_empty() { + MetaItemInner::MetaItem(mi) => match mi.name_or_empty() { sym::since => { if !get(mi, &mut since) { continue 'outer; @@ -912,7 +912,7 @@ pub fn find_deprecation( continue 'outer; } }, - NestedMetaItem::Lit(lit) => { + MetaItemInner::Lit(lit) => { sess.dcx().emit_err(session_diagnostics::UnsupportedLiteral { span: lit.span, reason: UnsupportedLiteralReason::DeprecatedKvPair, @@ -1277,7 +1277,7 @@ pub fn parse_confusables(attr: &Attribute) -> Option> { let mut candidates = Vec::new(); for meta in metas { - let NestedMetaItem::Lit(meta_lit) = meta else { + let MetaItemInner::Lit(meta_lit) = meta else { return None; }; candidates.push(meta_lit.symbol); diff --git a/compiler/rustc_builtin_macros/src/cfg.rs b/compiler/rustc_builtin_macros/src/cfg.rs index 940c94b1cfc89..15993dbf5ecc3 100644 --- a/compiler/rustc_builtin_macros/src/cfg.rs +++ b/compiler/rustc_builtin_macros/src/cfg.rs @@ -39,7 +39,7 @@ fn parse_cfg<'a>( cx: &ExtCtxt<'a>, span: Span, tts: TokenStream, -) -> PResult<'a, ast::NestedMetaItem> { +) -> PResult<'a, ast::MetaItemInner> { let mut p = cx.new_parser_from_tts(tts); if p.token == token::Eof { diff --git a/compiler/rustc_builtin_macros/src/derive.rs b/compiler/rustc_builtin_macros/src/derive.rs index 4be2d209ae785..361fcaa8534f2 100644 --- a/compiler/rustc_builtin_macros/src/derive.rs +++ b/compiler/rustc_builtin_macros/src/derive.rs @@ -1,5 +1,5 @@ use rustc_ast as ast; -use rustc_ast::{GenericParamKind, ItemKind, MetaItemKind, NestedMetaItem, StmtKind}; +use rustc_ast::{GenericParamKind, ItemKind, MetaItemInner, MetaItemKind, StmtKind}; use rustc_expand::base::{ Annotatable, DeriveResolution, ExpandResult, ExtCtxt, Indeterminate, MultiItemModifier, }; @@ -50,8 +50,8 @@ impl MultiItemModifier for Expander { MetaItemKind::List(list) => { list.iter() .filter_map(|nested_meta| match nested_meta { - NestedMetaItem::MetaItem(meta) => Some(meta), - NestedMetaItem::Lit(lit) => { + MetaItemInner::MetaItem(meta) => Some(meta), + MetaItemInner::Lit(lit) => { // Reject `#[derive("Debug")]`. report_unexpected_meta_item_lit(sess, lit); None diff --git a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs index e99c3a462711c..8d634ca465535 100644 --- a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs +++ b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs @@ -1,4 +1,4 @@ -use rustc_ast::{MetaItemKind, NestedMetaItem, ast, attr}; +use rustc_ast::{MetaItemInner, MetaItemKind, ast, attr}; use rustc_attr::{InlineAttr, InstructionSetAttr, OptimizeAttr, list_contains_name}; use rustc_errors::codes::*; use rustc_errors::{DiagMessage, SubdiagMessage, struct_span_code_err}; @@ -357,7 +357,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs { sym::instruction_set => { codegen_fn_attrs.instruction_set = attr.meta_item_list().and_then(|l| match &l[..] { - [NestedMetaItem::MetaItem(set)] => { + [MetaItemInner::MetaItem(set)] => { let segments = set.path.segments.iter().map(|x| x.ident.name).collect::>(); match segments.as_slice() { diff --git a/compiler/rustc_codegen_ssa/src/lib.rs b/compiler/rustc_codegen_ssa/src/lib.rs index 3129b9ac20344..cbd95146294f5 100644 --- a/compiler/rustc_codegen_ssa/src/lib.rs +++ b/compiler/rustc_codegen_ssa/src/lib.rs @@ -156,7 +156,7 @@ pub struct NativeLib { pub kind: NativeLibKind, pub name: Symbol, pub filename: Option, - pub cfg: Option, + pub cfg: Option, pub verbatim: bool, pub dll_imports: Vec, } diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs index d0552a754feb0..f0cfe133a4955 100644 --- a/compiler/rustc_expand/src/base.rs +++ b/compiler/rustc_expand/src/base.rs @@ -29,7 +29,7 @@ use rustc_span::{DUMMY_SP, FileName, Span}; use smallvec::{SmallVec, smallvec}; use thin_vec::ThinVec; -use crate::base::ast::NestedMetaItem; +use crate::base::ast::MetaItemInner; use crate::errors; use crate::expand::{self, AstFragment, Invocation}; use crate::module::DirOwnership; @@ -783,7 +783,7 @@ impl SyntaxExtension { fn collapse_debuginfo_by_name(attr: &Attribute) -> Result { let list = attr.meta_item_list(); - let Some([NestedMetaItem::MetaItem(item)]) = list.as_deref() else { + let Some([MetaItemInner::MetaItem(item)]) = list.as_deref() else { return Err(attr.span); }; if !item.is_word() { diff --git a/compiler/rustc_expand/src/config.rs b/compiler/rustc_expand/src/config.rs index af56169fd60c9..db5a98878e801 100644 --- a/compiler/rustc_expand/src/config.rs +++ b/compiler/rustc_expand/src/config.rs @@ -6,7 +6,7 @@ use rustc_ast::tokenstream::{ AttrTokenStream, AttrTokenTree, LazyAttrTokenStream, Spacing, TokenTree, }; use rustc_ast::{ - self as ast, AttrStyle, Attribute, HasAttrs, HasTokens, MetaItem, NestedMetaItem, NodeId, + self as ast, AttrStyle, Attribute, HasAttrs, HasTokens, MetaItem, MetaItemInner, NodeId, }; use rustc_attr as attr; use rustc_data_structures::flat_map_in_place::FlatMapInPlace; @@ -39,7 +39,7 @@ pub struct StripUnconfigured<'a> { } pub fn features(sess: &Session, krate_attrs: &[Attribute], crate_name: Symbol) -> Features { - fn feature_list(attr: &Attribute) -> ThinVec { + fn feature_list(attr: &Attribute) -> ThinVec { if attr.has_name(sym::feature) && let Some(list) = attr.meta_item_list() { @@ -451,7 +451,7 @@ impl<'a> StripUnconfigured<'a> { } } -pub fn parse_cfg<'a>(meta_item: &'a MetaItem, sess: &Session) -> Option<&'a NestedMetaItem> { +pub fn parse_cfg<'a>(meta_item: &'a MetaItem, sess: &Session) -> Option<&'a MetaItemInner> { let span = meta_item.span; match meta_item.meta_item_list() { None => { diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs index 079dcee99d3f4..5347381c3c3de 100644 --- a/compiler/rustc_expand/src/expand.rs +++ b/compiler/rustc_expand/src/expand.rs @@ -11,7 +11,7 @@ use rustc_ast::tokenstream::TokenStream; use rustc_ast::visit::{self, AssocCtxt, Visitor, VisitorResult, try_visit, walk_list}; use rustc_ast::{ AssocItemKind, AstNodeWrapper, AttrArgs, AttrStyle, AttrVec, ExprKind, ForeignItemKind, - HasAttrs, HasNodeId, Inline, ItemKind, MacStmtStyle, MetaItemKind, ModKind, NestedMetaItem, + HasAttrs, HasNodeId, Inline, ItemKind, MacStmtStyle, MetaItemInner, MetaItemKind, ModKind, NodeId, PatKind, StmtKind, TyKind, }; use rustc_ast_pretty::pprust; @@ -1864,7 +1864,7 @@ impl<'a, 'b> InvocationCollector<'a, 'b> { .filter(|a| a.has_name(sym::derive)) .flat_map(|a| a.meta_item_list().unwrap_or_default()) .filter_map(|nested_meta| match nested_meta { - NestedMetaItem::MetaItem(ast::MetaItem { + MetaItemInner::MetaItem(ast::MetaItem { kind: MetaItemKind::Word, path, .. diff --git a/compiler/rustc_incremental/src/persist/dirty_clean.rs b/compiler/rustc_incremental/src/persist/dirty_clean.rs index 9dc5cbaafce19..d25fe4219b587 100644 --- a/compiler/rustc_incremental/src/persist/dirty_clean.rs +++ b/compiler/rustc_incremental/src/persist/dirty_clean.rs @@ -19,7 +19,7 @@ //! Errors are reported if we are in the suitable configuration but //! the required condition is not met. -use rustc_ast::{self as ast, Attribute, NestedMetaItem}; +use rustc_ast::{self as ast, Attribute, MetaItemInner}; use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::unord::UnordSet; use rustc_hir::def_id::LocalDefId; @@ -307,7 +307,7 @@ impl<'tcx> DirtyCleanVisitor<'tcx> { (name, labels) } - fn resolve_labels(&self, item: &NestedMetaItem, value: Symbol) -> Labels { + fn resolve_labels(&self, item: &MetaItemInner, value: Symbol) -> Labels { let mut out = Labels::default(); for label in value.as_str().split(',') { let label = label.trim(); @@ -415,7 +415,7 @@ fn check_config(tcx: TyCtxt<'_>, attr: &Attribute) -> bool { } } -fn expect_associated_value(tcx: TyCtxt<'_>, item: &NestedMetaItem) -> Symbol { +fn expect_associated_value(tcx: TyCtxt<'_>, item: &MetaItemInner) -> Symbol { if let Some(value) = item.value_str() { value } else if let Some(ident) = item.ident() { diff --git a/compiler/rustc_lint/src/levels.rs b/compiler/rustc_lint/src/levels.rs index 007e86ae0d2b2..89a67fc0d8988 100644 --- a/compiler/rustc_lint/src/levels.rs +++ b/compiler/rustc_lint/src/levels.rs @@ -669,7 +669,7 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> { let sp = li.span(); let meta_item = match li { - ast::NestedMetaItem::MetaItem(meta_item) if meta_item.is_word() => meta_item, + ast::MetaItemInner::MetaItem(meta_item) if meta_item.is_word() => meta_item, _ => { let sub = if let Some(item) = li.meta_item() && let ast::MetaItemKind::NameValue(_) = item.kind diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 27c1b88f93f74..4a02fce5e7d03 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -1451,9 +1451,8 @@ impl<'tcx> TyCtxt<'tcx> { debug!("layout_scalar_valid_range: attr={:?}", attr); if let Some( &[ - ast::NestedMetaItem::Lit(ast::MetaItemLit { - kind: ast::LitKind::Int(a, _), - .. + ast::MetaItemInner::Lit(ast::MetaItemLit { + kind: ast::LitKind::Int(a, _), .. }), ], ) = attr.meta_item_list().as_deref() diff --git a/compiler/rustc_mir_dataflow/src/framework/engine.rs b/compiler/rustc_mir_dataflow/src/framework/engine.rs index faf5c610a0c47..9d50e57d66868 100644 --- a/compiler/rustc_mir_dataflow/src/framework/engine.rs +++ b/compiler/rustc_mir_dataflow/src/framework/engine.rs @@ -367,7 +367,7 @@ impl RustcMirAttrs { fn set_field( field: &mut Option, tcx: TyCtxt<'_>, - attr: &ast::NestedMetaItem, + attr: &ast::MetaItemInner, mapper: impl FnOnce(Symbol) -> Result, ) -> Result<(), ()> { if field.is_some() { diff --git a/compiler/rustc_parse/src/lib.rs b/compiler/rustc_parse/src/lib.rs index da02f98d0e5bd..2792050a0b39d 100644 --- a/compiler/rustc_parse/src/lib.rs +++ b/compiler/rustc_parse/src/lib.rs @@ -18,7 +18,7 @@ use std::path::Path; use rustc_ast as ast; use rustc_ast::tokenstream::TokenStream; -use rustc_ast::{AttrItem, Attribute, NestedMetaItem, token}; +use rustc_ast::{AttrItem, Attribute, MetaItemInner, token}; use rustc_ast_pretty::pprust; use rustc_data_structures::sync::Lrc; use rustc_errors::{Diag, FatalError, PResult}; @@ -160,7 +160,7 @@ pub fn fake_token_stream_for_crate(psess: &ParseSess, krate: &ast::Crate) -> Tok pub fn parse_cfg_attr( cfg_attr: &Attribute, psess: &ParseSess, -) -> Option<(NestedMetaItem, Vec<(AttrItem, Span)>)> { +) -> Option<(MetaItemInner, Vec<(AttrItem, Span)>)> { const CFG_ATTR_GRAMMAR_HELP: &str = "#[cfg_attr(condition, attribute, other_attribute, ...)]"; const CFG_ATTR_NOTE_REF: &str = "for more information, visit \ "; diff --git a/compiler/rustc_parse/src/parser/attr.rs b/compiler/rustc_parse/src/parser/attr.rs index 4aa56cb7624a6..b6fa209958831 100644 --- a/compiler/rustc_parse/src/parser/attr.rs +++ b/compiler/rustc_parse/src/parser/attr.rs @@ -358,7 +358,7 @@ impl<'a> Parser<'a> { /// Parses `cfg_attr(pred, attr_item_list)` where `attr_item_list` is comma-delimited. pub fn parse_cfg_attr( &mut self, - ) -> PResult<'a, (ast::NestedMetaItem, Vec<(ast::AttrItem, Span)>)> { + ) -> PResult<'a, (ast::MetaItemInner, Vec<(ast::AttrItem, Span)>)> { let cfg_predicate = self.parse_meta_item_inner()?; self.expect(&token::Comma)?; @@ -377,7 +377,7 @@ impl<'a> Parser<'a> { } /// Matches `COMMASEP(meta_item_inner)`. - pub(crate) fn parse_meta_seq_top(&mut self) -> PResult<'a, ThinVec> { + pub(crate) fn parse_meta_seq_top(&mut self) -> PResult<'a, ThinVec> { // Presumably, the majority of the time there will only be one attr. let mut nmis = ThinVec::with_capacity(1); while self.token != token::Eof { @@ -454,14 +454,14 @@ impl<'a> Parser<'a> { /// ```ebnf /// MetaItemInner = UNSUFFIXED_LIT | MetaItem ; /// ``` - pub fn parse_meta_item_inner(&mut self) -> PResult<'a, ast::NestedMetaItem> { + pub fn parse_meta_item_inner(&mut self) -> PResult<'a, ast::MetaItemInner> { match self.parse_unsuffixed_meta_item_lit() { - Ok(lit) => return Ok(ast::NestedMetaItem::Lit(lit)), + Ok(lit) => return Ok(ast::MetaItemInner::Lit(lit)), Err(err) => err.cancel(), // we provide a better error below } match self.parse_meta_item(AllowLeadingUnsafe::No) { - Ok(mi) => return Ok(ast::NestedMetaItem::MetaItem(mi)), + Ok(mi) => return Ok(ast::MetaItemInner::MetaItem(mi)), Err(err) => err.cancel(), // we provide a better error below } diff --git a/compiler/rustc_parse/src/validate_attr.rs b/compiler/rustc_parse/src/validate_attr.rs index b15d1edf79cda..f3174e7dea2d8 100644 --- a/compiler/rustc_parse/src/validate_attr.rs +++ b/compiler/rustc_parse/src/validate_attr.rs @@ -3,8 +3,8 @@ use rustc_ast::token::Delimiter; use rustc_ast::tokenstream::DelimSpan; use rustc_ast::{ - self as ast, AttrArgs, AttrArgsEq, Attribute, DelimArgs, MetaItem, MetaItemKind, - NestedMetaItem, Safety, + self as ast, AttrArgs, AttrArgsEq, Attribute, DelimArgs, MetaItem, MetaItemInner, MetaItemKind, + Safety, }; use rustc_errors::{Applicability, FatalError, PResult}; use rustc_feature::{AttributeSafety, AttributeTemplate, BUILTIN_ATTRIBUTE_MAP, BuiltinAttribute}; @@ -143,7 +143,7 @@ pub(super) fn check_cfg_attr_bad_delim(psess: &ParseSess, span: DelimSpan, delim /// Checks that the given meta-item is compatible with this `AttributeTemplate`. fn is_attr_template_compatible(template: &AttributeTemplate, meta: &ast::MetaItemKind) -> bool { - let is_one_allowed_subword = |items: &[NestedMetaItem]| match items { + let is_one_allowed_subword = |items: &[MetaItemInner]| match items { [item] => item.is_word() && template.one_of.iter().any(|&word| item.has_name(word)), _ => false, }; diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index b3334bb70aa8d..44a62383e6eed 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -8,7 +8,7 @@ use std::cell::Cell; use std::collections::hash_map::Entry; use rustc_ast::{ - AttrKind, AttrStyle, Attribute, LitKind, MetaItemKind, MetaItemLit, NestedMetaItem, ast, + AttrKind, AttrStyle, Attribute, LitKind, MetaItemInner, MetaItemKind, MetaItemLit, ast, }; use rustc_data_structures::fx::FxHashMap; use rustc_errors::{Applicability, DiagCtxtHandle, IntoDiagArg, MultiSpan, StashKey}; @@ -742,13 +742,13 @@ impl<'tcx> CheckAttrVisitor<'tcx> { } } - fn doc_attr_str_error(&self, meta: &NestedMetaItem, attr_name: &str) { + fn doc_attr_str_error(&self, meta: &MetaItemInner, attr_name: &str) { self.dcx().emit_err(errors::DocExpectStr { attr_span: meta.span(), attr_name }); } fn check_doc_alias_value( &self, - meta: &NestedMetaItem, + meta: &MetaItemInner, doc_alias: Symbol, hir_id: HirId, target: Target, @@ -850,7 +850,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { fn check_doc_alias( &self, - meta: &NestedMetaItem, + meta: &MetaItemInner, hir_id: HirId, target: Target, aliases: &mut FxHashMap, @@ -882,7 +882,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { } } - fn check_doc_keyword(&self, meta: &NestedMetaItem, hir_id: HirId) { + fn check_doc_keyword(&self, meta: &MetaItemInner, hir_id: HirId) { let doc_keyword = meta.value_str().unwrap_or(kw::Empty); if doc_keyword == kw::Empty { self.doc_attr_str_error(meta, "keyword"); @@ -912,7 +912,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { } } - fn check_doc_fake_variadic(&self, meta: &NestedMetaItem, hir_id: HirId) { + fn check_doc_fake_variadic(&self, meta: &MetaItemInner, hir_id: HirId) { let item_kind = match self.tcx.hir_node(hir_id) { hir::Node::Item(item) => Some(&item.kind), _ => None, @@ -957,7 +957,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { fn check_doc_inline( &self, attr: &Attribute, - meta: &NestedMetaItem, + meta: &MetaItemInner, hir_id: HirId, target: Target, specified_inline: &mut Option<(bool, Span)>, @@ -997,7 +997,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { fn check_doc_masked( &self, attr: &Attribute, - meta: &NestedMetaItem, + meta: &MetaItemInner, hir_id: HirId, target: Target, ) { @@ -1032,7 +1032,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { /// Checks that an attribute is *not* used at the crate level. Returns `true` if valid. fn check_attr_not_crate_level( &self, - meta: &NestedMetaItem, + meta: &MetaItemInner, hir_id: HirId, attr_name: &str, ) -> bool { @@ -1047,7 +1047,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { fn check_attr_crate_level( &self, attr: &Attribute, - meta: &NestedMetaItem, + meta: &MetaItemInner, hir_id: HirId, ) -> bool { if hir_id != CRATE_HIR_ID { @@ -1071,7 +1071,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { /// Checks that `doc(test(...))` attribute contains only valid attributes. Returns `true` if /// valid. - fn check_test_attr(&self, meta: &NestedMetaItem, hir_id: HirId) { + fn check_test_attr(&self, meta: &MetaItemInner, hir_id: HirId) { if let Some(metas) = meta.meta_item_list() { for i_meta in metas { match (i_meta.name_or_empty(), i_meta.meta_item()) { @@ -1108,7 +1108,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { /// Check that the `#![doc(cfg_hide(...))]` attribute only contains a list of attributes. /// - fn check_doc_cfg_hide(&self, meta: &NestedMetaItem, hir_id: HirId) { + fn check_doc_cfg_hide(&self, meta: &MetaItemInner, hir_id: HirId) { if meta.meta_item_list().is_none() { self.tcx.emit_node_span_lint( INVALID_DOC_ATTRIBUTES, @@ -1499,8 +1499,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { return; }; - if !matches!(&list[..], &[NestedMetaItem::Lit(MetaItemLit { kind: LitKind::Int(..), .. })]) - { + if !matches!(&list[..], &[MetaItemInner::Lit(MetaItemLit { kind: LitKind::Int(..), .. })]) { self.tcx .dcx() .emit_err(errors::RustcLayoutScalarValidRangeArg { attr_span: attr.span }); @@ -2073,7 +2072,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { let mut candidates = Vec::new(); for meta in metas { - let NestedMetaItem::Lit(meta_lit) = meta else { + let MetaItemInner::Lit(meta_lit) = meta else { self.dcx().emit_err(errors::IncorrectMetaItem { span: meta.span(), suggestion: errors::IncorrectMetaItemSuggestion { diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index 582db97e1ce87..5437ca65935f8 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -2,8 +2,7 @@ use rustc_ast::expand::StrippedCfgItem; use rustc_ast::ptr::P; use rustc_ast::visit::{self, Visitor}; use rustc_ast::{ - self as ast, CRATE_NODE_ID, Crate, ItemKind, MetaItemKind, ModKind, NestedMetaItem, NodeId, - Path, + self as ast, CRATE_NODE_ID, Crate, ItemKind, MetaItemInner, MetaItemKind, ModKind, NodeId, Path, }; use rustc_ast_pretty::pprust; use rustc_data_structures::fx::FxHashSet; @@ -2541,7 +2540,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { err.subdiagnostic(note); if let MetaItemKind::List(nested) = &cfg.kind - && let NestedMetaItem::MetaItem(meta_item) = &nested[0] + && let MetaItemInner::MetaItem(meta_item) = &nested[0] && let MetaItemKind::NameValue(feature_name) = &meta_item.kind { let note = errors::ItemWasBehindFeature { diff --git a/compiler/rustc_session/src/cstore.rs b/compiler/rustc_session/src/cstore.rs index b936a299b0973..041a10475eaad 100644 --- a/compiler/rustc_session/src/cstore.rs +++ b/compiler/rustc_session/src/cstore.rs @@ -72,7 +72,7 @@ pub struct NativeLib { pub name: Symbol, /// If packed_bundled_libs enabled, actual filename of library is stored. pub filename: Option, - pub cfg: Option, + pub cfg: Option, pub foreign_module: Option, pub verbatim: Option, pub dll_imports: Vec, diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented.rs index e9a2c5b8d8e06..c3100c48b0aa2 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented.rs @@ -1,7 +1,7 @@ use std::iter; use std::path::PathBuf; -use rustc_ast::{AttrArgs, AttrArgsEq, AttrKind, Attribute, NestedMetaItem}; +use rustc_ast::{AttrArgs, AttrArgsEq, AttrKind, Attribute, MetaItemInner}; use rustc_data_structures::fx::FxHashMap; use rustc_errors::codes::*; use rustc_errors::{ErrorGuaranteed, struct_span_code_err}; @@ -282,7 +282,7 @@ pub struct OnUnimplementedFormatString { #[derive(Debug)] pub struct OnUnimplementedDirective { - pub condition: Option, + pub condition: Option, pub subcommands: Vec, pub message: Option, pub label: Option, @@ -389,7 +389,7 @@ impl<'tcx> OnUnimplementedDirective { fn parse( tcx: TyCtxt<'tcx>, item_def_id: DefId, - items: &[NestedMetaItem], + items: &[MetaItemInner], span: Span, is_root: bool, is_diagnostic_namespace_variant: bool, diff --git a/src/librustdoc/clean/cfg.rs b/src/librustdoc/clean/cfg.rs index 53830016a80bb..9255242611afc 100644 --- a/src/librustdoc/clean/cfg.rs +++ b/src/librustdoc/clean/cfg.rs @@ -6,7 +6,7 @@ use std::fmt::{self, Write}; use std::{mem, ops}; -use rustc_ast::{LitKind, MetaItem, MetaItemKind, MetaItemLit, NestedMetaItem}; +use rustc_ast::{LitKind, MetaItem, MetaItemInner, MetaItemKind, MetaItemLit}; use rustc_data_structures::fx::FxHashSet; use rustc_feature::Features; use rustc_session::parse::ParseSess; @@ -41,18 +41,18 @@ pub(crate) struct InvalidCfgError { } impl Cfg { - /// Parses a `NestedMetaItem` into a `Cfg`. + /// Parses a `MetaItemInner` into a `Cfg`. fn parse_nested( - nested_cfg: &NestedMetaItem, + nested_cfg: &MetaItemInner, exclude: &FxHashSet, ) -> Result, InvalidCfgError> { match nested_cfg { - NestedMetaItem::MetaItem(ref cfg) => Cfg::parse_without(cfg, exclude), - NestedMetaItem::Lit(MetaItemLit { kind: LitKind::Bool(b), .. }) => match *b { + MetaItemInner::MetaItem(ref cfg) => Cfg::parse_without(cfg, exclude), + MetaItemInner::Lit(MetaItemLit { kind: LitKind::Bool(b), .. }) => match *b { true => Ok(Some(Cfg::True)), false => Ok(Some(Cfg::False)), }, - NestedMetaItem::Lit(ref lit) => { + MetaItemInner::Lit(ref lit) => { Err(InvalidCfgError { msg: "unexpected literal", span: lit.span }) } } @@ -124,7 +124,7 @@ impl Cfg { /// /// If the content is not properly formatted, it will return an error indicating what and where /// the error is. - pub(crate) fn parse(cfg: &NestedMetaItem) -> Result { + pub(crate) fn parse(cfg: &MetaItemInner) -> Result { Self::parse_nested(cfg, &FxHashSet::default()).map(|ret| ret.unwrap()) } diff --git a/src/librustdoc/clean/cfg/tests.rs b/src/librustdoc/clean/cfg/tests.rs index d4b11451c8941..2c62e12c96dc1 100644 --- a/src/librustdoc/clean/cfg/tests.rs +++ b/src/librustdoc/clean/cfg/tests.rs @@ -1,5 +1,5 @@ use rustc_ast::ast::LitIntType; -use rustc_ast::{MetaItemLit, NestedMetaItem, Path, Safety, StrStyle}; +use rustc_ast::{MetaItemInner, MetaItemLit, Path, Safety, StrStyle}; use rustc_span::symbol::{Ident, kw}; use rustc_span::{DUMMY_SP, create_default_session_globals_then}; use thin_vec::thin_vec; @@ -14,12 +14,12 @@ fn name_value_cfg(name: &str, value: &str) -> Cfg { Cfg::Cfg(Symbol::intern(name), Some(Symbol::intern(value))) } -fn dummy_lit(symbol: Symbol, kind: LitKind) -> NestedMetaItem { - NestedMetaItem::Lit(MetaItemLit { symbol, suffix: None, kind, span: DUMMY_SP }) +fn dummy_lit(symbol: Symbol, kind: LitKind) -> MetaItemInner { + MetaItemInner::Lit(MetaItemLit { symbol, suffix: None, kind, span: DUMMY_SP }) } -fn dummy_meta_item_word(name: &str) -> NestedMetaItem { - NestedMetaItem::MetaItem(MetaItem { +fn dummy_meta_item_word(name: &str) -> MetaItemInner { + MetaItemInner::MetaItem(MetaItem { unsafety: Safety::Default, path: Path::from_ident(Ident::from_str(name)), kind: MetaItemKind::Word, @@ -27,9 +27,9 @@ fn dummy_meta_item_word(name: &str) -> NestedMetaItem { }) } -fn dummy_meta_item_name_value(name: &str, symbol: Symbol, kind: LitKind) -> NestedMetaItem { +fn dummy_meta_item_name_value(name: &str, symbol: Symbol, kind: LitKind) -> MetaItemInner { let lit = MetaItemLit { symbol, suffix: None, kind, span: DUMMY_SP }; - NestedMetaItem::MetaItem(MetaItem { + MetaItemInner::MetaItem(MetaItem { unsafety: Safety::Default, path: Path::from_ident(Ident::from_str(name)), kind: MetaItemKind::NameValue(lit), @@ -39,7 +39,7 @@ fn dummy_meta_item_name_value(name: &str, symbol: Symbol, kind: LitKind) -> Nest macro_rules! dummy_meta_item_list { ($name:ident, [$($list:ident),* $(,)?]) => { - NestedMetaItem::MetaItem(MetaItem { + MetaItemInner::MetaItem(MetaItem { unsafety: Safety::Default, path: Path::from_ident(Ident::from_str(stringify!($name))), kind: MetaItemKind::List(thin_vec![ @@ -52,7 +52,7 @@ macro_rules! dummy_meta_item_list { }; ($name:ident, [$($list:expr),* $(,)?]) => { - NestedMetaItem::MetaItem(MetaItem { + MetaItemInner::MetaItem(MetaItem { unsafety: Safety::Default, path: Path::from_ident(Ident::from_str(stringify!($name))), kind: MetaItemKind::List(thin_vec![ diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index ec31a51a81e2d..5e43dfc7bcc3e 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -5,7 +5,7 @@ use std::sync::{Arc, OnceLock as OnceCell}; use std::{fmt, iter}; use arrayvec::ArrayVec; -use rustc_ast::NestedMetaItem; +use rustc_ast::MetaItemInner; use rustc_ast_pretty::pprust; use rustc_attr::{ConstStability, Deprecation, Stability, StableSince}; use rustc_const_eval::const_eval::is_unstable_const_fn; @@ -953,7 +953,7 @@ pub(crate) struct Module { } pub(crate) trait AttributesExt { - type AttributeIterator<'a>: Iterator + type AttributeIterator<'a>: Iterator where Self: 'a; type Attributes<'a>: Iterator @@ -1043,7 +1043,7 @@ pub(crate) trait AttributesExt { let mut meta = attr.meta_item().unwrap().clone(); meta.path = ast::Path::from_ident(Ident::with_dummy_span(sym::target_feature)); - if let Ok(feat_cfg) = Cfg::parse(&NestedMetaItem::MetaItem(meta)) { + if let Ok(feat_cfg) = Cfg::parse(&MetaItemInner::MetaItem(meta)) { cfg &= feat_cfg; } } @@ -1055,7 +1055,7 @@ pub(crate) trait AttributesExt { } impl AttributesExt for [ast::Attribute] { - type AttributeIterator<'a> = impl Iterator + 'a; + type AttributeIterator<'a> = impl Iterator + 'a; type Attributes<'a> = impl Iterator + 'a; fn lists(&self, name: Symbol) -> Self::AttributeIterator<'_> { @@ -1072,7 +1072,7 @@ impl AttributesExt for [ast::Attribute] { impl AttributesExt for [(Cow<'_, ast::Attribute>, Option)] { type AttributeIterator<'a> - = impl Iterator + 'a + = impl Iterator + 'a where Self: 'a; type Attributes<'a> @@ -1106,11 +1106,11 @@ pub(crate) trait NestedAttributesExt { /// Returns `Some(attr)` if the attribute list contains 'attr' /// corresponding to a specific `word` - fn get_word_attr(self, word: Symbol) -> Option; + fn get_word_attr(self, word: Symbol) -> Option; } -impl> NestedAttributesExt for I { - fn get_word_attr(mut self, word: Symbol) -> Option { +impl> NestedAttributesExt for I { + fn get_word_attr(mut self, word: Symbol) -> Option { self.find(|attr| attr.is_word() && attr.has_name(word)) } } @@ -1157,7 +1157,7 @@ pub(crate) struct Attributes { } impl Attributes { - pub(crate) fn lists(&self, name: Symbol) -> impl Iterator + '_ { + pub(crate) fn lists(&self, name: Symbol) -> impl Iterator + '_ { self.other_attrs.lists(name) } diff --git a/src/tools/clippy/clippy_lints/src/attrs/allow_attributes_without_reason.rs b/src/tools/clippy/clippy_lints/src/attrs/allow_attributes_without_reason.rs index 40959eccd3a9f..5d4e864b9b0b5 100644 --- a/src/tools/clippy/clippy_lints/src/attrs/allow_attributes_without_reason.rs +++ b/src/tools/clippy/clippy_lints/src/attrs/allow_attributes_without_reason.rs @@ -1,15 +1,15 @@ use super::{ALLOW_ATTRIBUTES_WITHOUT_REASON, Attribute}; use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::is_from_proc_macro; -use rustc_ast::{MetaItemKind, NestedMetaItem}; +use rustc_ast::{MetaItemInner, MetaItemKind}; use rustc_lint::{LateContext, LintContext}; use rustc_middle::lint::in_external_macro; use rustc_span::sym; use rustc_span::symbol::Symbol; -pub(super) fn check<'cx>(cx: &LateContext<'cx>, name: Symbol, items: &[NestedMetaItem], attr: &'cx Attribute) { +pub(super) fn check<'cx>(cx: &LateContext<'cx>, name: Symbol, items: &[MetaItemInner], attr: &'cx Attribute) { // Check if the reason is present - if let Some(item) = items.last().and_then(NestedMetaItem::meta_item) + if let Some(item) = items.last().and_then(MetaItemInner::meta_item) && let MetaItemKind::NameValue(_) = &item.kind && item.path == sym::reason { diff --git a/src/tools/clippy/clippy_lints/src/attrs/blanket_clippy_restriction_lints.rs b/src/tools/clippy/clippy_lints/src/attrs/blanket_clippy_restriction_lints.rs index 508963a20ea71..0baf889faa076 100644 --- a/src/tools/clippy/clippy_lints/src/attrs/blanket_clippy_restriction_lints.rs +++ b/src/tools/clippy/clippy_lints/src/attrs/blanket_clippy_restriction_lints.rs @@ -1,12 +1,12 @@ use super::BLANKET_CLIPPY_RESTRICTION_LINTS; use super::utils::extract_clippy_lint; use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_then}; -use rustc_ast::NestedMetaItem; +use rustc_ast::MetaItemInner; use rustc_lint::{LateContext, Level, LintContext}; use rustc_span::symbol::Symbol; use rustc_span::{DUMMY_SP, sym}; -pub(super) fn check(cx: &LateContext<'_>, name: Symbol, items: &[NestedMetaItem]) { +pub(super) fn check(cx: &LateContext<'_>, name: Symbol, items: &[MetaItemInner]) { for lint in items { if let Some(lint_name) = extract_clippy_lint(lint) { if lint_name.as_str() == "restriction" && name != sym::allow { diff --git a/src/tools/clippy/clippy_lints/src/attrs/mod.rs b/src/tools/clippy/clippy_lints/src/attrs/mod.rs index 888f28fa2258c..1a34ca99fc2b9 100644 --- a/src/tools/clippy/clippy_lints/src/attrs/mod.rs +++ b/src/tools/clippy/clippy_lints/src/attrs/mod.rs @@ -14,7 +14,7 @@ mod utils; use clippy_config::Conf; use clippy_config::msrvs::{self, Msrv}; -use rustc_ast::{Attribute, MetaItemKind, NestedMetaItem}; +use rustc_ast::{Attribute, MetaItemInner, MetaItemKind}; use rustc_hir::{ImplItem, Item, ItemKind, TraitItem}; use rustc_lint::{EarlyContext, EarlyLintPass, LateContext, LateLintPass}; use rustc_session::impl_lint_pass; @@ -456,7 +456,7 @@ impl<'tcx> LateLintPass<'tcx> for Attributes { return; } for item in items { - if let NestedMetaItem::MetaItem(mi) = &item + if let MetaItemInner::MetaItem(mi) = &item && let MetaItemKind::NameValue(lit) = &mi.kind && mi.has_name(sym::since) { diff --git a/src/tools/clippy/clippy_lints/src/attrs/non_minimal_cfg.rs b/src/tools/clippy/clippy_lints/src/attrs/non_minimal_cfg.rs index 877025cce4c2b..7eff5eccfa138 100644 --- a/src/tools/clippy/clippy_lints/src/attrs/non_minimal_cfg.rs +++ b/src/tools/clippy/clippy_lints/src/attrs/non_minimal_cfg.rs @@ -1,7 +1,7 @@ use super::{Attribute, NON_MINIMAL_CFG}; use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::source::SpanRangeExt; -use rustc_ast::{MetaItemKind, NestedMetaItem}; +use rustc_ast::{MetaItemInner, MetaItemKind}; use rustc_errors::Applicability; use rustc_lint::EarlyContext; use rustc_span::sym; @@ -14,9 +14,9 @@ pub(super) fn check(cx: &EarlyContext<'_>, attr: &Attribute) { } } -fn check_nested_cfg(cx: &EarlyContext<'_>, items: &[NestedMetaItem]) { +fn check_nested_cfg(cx: &EarlyContext<'_>, items: &[MetaItemInner]) { for item in items { - if let NestedMetaItem::MetaItem(meta) = item { + if let MetaItemInner::MetaItem(meta) = item { if !meta.has_name(sym::any) && !meta.has_name(sym::all) { continue; } diff --git a/src/tools/clippy/clippy_lints/src/attrs/useless_attribute.rs b/src/tools/clippy/clippy_lints/src/attrs/useless_attribute.rs index 12668c616c13e..72e6ce59d5980 100644 --- a/src/tools/clippy/clippy_lints/src/attrs/useless_attribute.rs +++ b/src/tools/clippy/clippy_lints/src/attrs/useless_attribute.rs @@ -2,7 +2,7 @@ use super::utils::{extract_clippy_lint, is_lint_level, is_word}; use super::{Attribute, USELESS_ATTRIBUTE}; use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::source::{SpanRangeExt, first_line_of_span}; -use rustc_ast::NestedMetaItem; +use rustc_ast::MetaItemInner; use rustc_errors::Applicability; use rustc_hir::{Item, ItemKind}; use rustc_lint::{LateContext, LintContext}; @@ -21,7 +21,7 @@ pub(super) fn check(cx: &LateContext<'_>, item: &Item<'_>, attrs: &[Attribute]) for lint in lint_list { match item.kind { ItemKind::Use(..) => { - if let NestedMetaItem::MetaItem(meta_item) = lint + if let MetaItemInner::MetaItem(meta_item) = lint && meta_item.is_word() && let Some(ident) = meta_item.ident() && matches!( diff --git a/src/tools/clippy/clippy_lints/src/attrs/utils.rs b/src/tools/clippy/clippy_lints/src/attrs/utils.rs index 91ae19acbf7f6..9b10ae8365149 100644 --- a/src/tools/clippy/clippy_lints/src/attrs/utils.rs +++ b/src/tools/clippy/clippy_lints/src/attrs/utils.rs @@ -1,5 +1,5 @@ use clippy_utils::macros::{is_panic, macro_backtrace}; -use rustc_ast::{AttrId, NestedMetaItem}; +use rustc_ast::{AttrId, MetaItemInner}; use rustc_hir::{ Block, Expr, ExprKind, ImplItem, ImplItemKind, Item, ItemKind, StmtKind, TraitFn, TraitItem, TraitItemKind, }; @@ -8,8 +8,8 @@ use rustc_middle::ty; use rustc_span::sym; use rustc_span::symbol::Symbol; -pub(super) fn is_word(nmi: &NestedMetaItem, expected: Symbol) -> bool { - if let NestedMetaItem::MetaItem(mi) = &nmi { +pub(super) fn is_word(nmi: &MetaItemInner, expected: Symbol) -> bool { + if let MetaItemInner::MetaItem(mi) = &nmi { mi.is_word() && mi.has_name(expected) } else { false @@ -74,7 +74,7 @@ fn is_relevant_expr(cx: &LateContext<'_>, typeck_results: &ty::TypeckResults<'_> } /// Returns the lint name if it is clippy lint. -pub(super) fn extract_clippy_lint(lint: &NestedMetaItem) -> Option { +pub(super) fn extract_clippy_lint(lint: &MetaItemInner) -> Option { if let Some(meta_item) = lint.meta_item() && meta_item.path.segments.len() > 1 && let tool_name = meta_item.path.segments[0].ident diff --git a/src/tools/clippy/clippy_lints/src/cfg_not_test.rs b/src/tools/clippy/clippy_lints/src/cfg_not_test.rs index 884d15cabffcb..84136a2e6c28f 100644 --- a/src/tools/clippy/clippy_lints/src/cfg_not_test.rs +++ b/src/tools/clippy/clippy_lints/src/cfg_not_test.rs @@ -1,5 +1,5 @@ use clippy_utils::diagnostics::span_lint_and_then; -use rustc_ast::NestedMetaItem; +use rustc_ast::MetaItemInner; use rustc_lint::{EarlyContext, EarlyLintPass}; use rustc_session::declare_lint_pass; @@ -47,7 +47,7 @@ impl EarlyLintPass for CfgNotTest { } } -fn contains_not_test(list: Option<&[NestedMetaItem]>, not: bool) -> bool { +fn contains_not_test(list: Option<&[MetaItemInner]>, not: bool) -> bool { list.is_some_and(|list| { list.iter().any(|item| { item.ident().is_some_and(|ident| match ident.name { diff --git a/src/tools/clippy/clippy_lints/src/returns.rs b/src/tools/clippy/clippy_lints/src/returns.rs index 1f223048ce5ce..f6f75d8c798a6 100644 --- a/src/tools/clippy/clippy_lints/src/returns.rs +++ b/src/tools/clippy/clippy_lints/src/returns.rs @@ -7,7 +7,7 @@ use clippy_utils::{ path_to_local_id, span_contains_cfg, span_find_starting_semi, }; use core::ops::ControlFlow; -use rustc_ast::NestedMetaItem; +use rustc_ast::MetaItemInner; use rustc_errors::Applicability; use rustc_hir::LangItem::ResultErr; use rustc_hir::intravisit::FnKind; @@ -421,7 +421,7 @@ fn check_final_expr<'tcx>( if matches!(Level::from_attr(attr), Some(Level::Expect(_))) && let metas = attr.meta_item_list() && let Some(lst) = metas - && let [NestedMetaItem::MetaItem(meta_item), ..] = lst.as_slice() + && let [MetaItemInner::MetaItem(meta_item), ..] = lst.as_slice() && let [tool, lint_name] = meta_item.path.segments.as_slice() && tool.ident.name == sym::clippy && matches!( diff --git a/src/tools/rustfmt/src/attr.rs b/src/tools/rustfmt/src/attr.rs index 5c2068b6a22a1..ad425d0bff7f0 100644 --- a/src/tools/rustfmt/src/attr.rs +++ b/src/tools/rustfmt/src/attr.rs @@ -243,17 +243,15 @@ fn rewrite_initial_doc_comments( Ok((0, None)) } -impl Rewrite for ast::NestedMetaItem { +impl Rewrite for ast::MetaItemInner { fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option { self.rewrite_result(context, shape).ok() } fn rewrite_result(&self, context: &RewriteContext<'_>, shape: Shape) -> RewriteResult { match self { - ast::NestedMetaItem::MetaItem(ref meta_item) => { - meta_item.rewrite_result(context, shape) - } - ast::NestedMetaItem::Lit(ref l) => { + ast::MetaItemInner::MetaItem(ref meta_item) => meta_item.rewrite_result(context, shape), + ast::MetaItemInner::Lit(ref l) => { rewrite_literal(context, l.as_token_lit(), l.span, shape) } } @@ -535,7 +533,7 @@ pub(crate) trait MetaVisitor<'ast> { fn visit_meta_list( &mut self, _meta_item: &'ast ast::MetaItem, - list: &'ast [ast::NestedMetaItem], + list: &'ast [ast::MetaItemInner], ) { for nm in list { self.visit_nested_meta_item(nm); @@ -551,10 +549,10 @@ pub(crate) trait MetaVisitor<'ast> { ) { } - fn visit_nested_meta_item(&mut self, nm: &'ast ast::NestedMetaItem) { + fn visit_nested_meta_item(&mut self, nm: &'ast ast::MetaItemInner) { match nm { - ast::NestedMetaItem::MetaItem(ref meta_item) => self.visit_meta_item(meta_item), - ast::NestedMetaItem::Lit(ref lit) => self.visit_meta_item_lit(lit), + ast::MetaItemInner::MetaItem(ref meta_item) => self.visit_meta_item(meta_item), + ast::MetaItemInner::Lit(ref lit) => self.visit_meta_item_lit(lit), } } diff --git a/src/tools/rustfmt/src/overflow.rs b/src/tools/rustfmt/src/overflow.rs index fdc8e23e72b38..3f44789bafd16 100644 --- a/src/tools/rustfmt/src/overflow.rs +++ b/src/tools/rustfmt/src/overflow.rs @@ -78,7 +78,7 @@ pub(crate) enum OverflowableItem<'a> { Expr(&'a ast::Expr), GenericParam(&'a ast::GenericParam), MacroArg(&'a MacroArg), - NestedMetaItem(&'a ast::NestedMetaItem), + MetaItemInner(&'a ast::MetaItemInner), SegmentParam(&'a SegmentParam<'a>), FieldDef(&'a ast::FieldDef), TuplePatField(&'a TuplePatField<'a>), @@ -123,7 +123,7 @@ impl<'a> OverflowableItem<'a> { OverflowableItem::Expr(expr) => f(*expr), OverflowableItem::GenericParam(gp) => f(*gp), OverflowableItem::MacroArg(macro_arg) => f(*macro_arg), - OverflowableItem::NestedMetaItem(nmi) => f(*nmi), + OverflowableItem::MetaItemInner(nmi) => f(*nmi), OverflowableItem::SegmentParam(sp) => f(*sp), OverflowableItem::FieldDef(sf) => f(*sf), OverflowableItem::TuplePatField(pat) => f(*pat), @@ -138,9 +138,9 @@ impl<'a> OverflowableItem<'a> { OverflowableItem::Expr(expr) => is_simple_expr(expr), OverflowableItem::MacroArg(MacroArg::Keyword(..)) => true, OverflowableItem::MacroArg(MacroArg::Expr(expr)) => is_simple_expr(expr), - OverflowableItem::NestedMetaItem(nested_meta_item) => match nested_meta_item { - ast::NestedMetaItem::Lit(..) => true, - ast::NestedMetaItem::MetaItem(ref meta_item) => { + OverflowableItem::MetaItemInner(nested_meta_item) => match nested_meta_item { + ast::MetaItemInner::Lit(..) => true, + ast::MetaItemInner::MetaItem(ref meta_item) => { matches!(meta_item.kind, ast::MetaItemKind::Word) } }, @@ -184,12 +184,11 @@ impl<'a> OverflowableItem<'a> { MacroArg::Item(..) => len == 1, MacroArg::Keyword(..) => false, }, - OverflowableItem::NestedMetaItem(nested_meta_item) if len == 1 => { - match nested_meta_item { - ast::NestedMetaItem::Lit(..) => false, - ast::NestedMetaItem::MetaItem(..) => true, - } - } + OverflowableItem::MetaItemInner(nested_meta_item) if len == 1 => match nested_meta_item + { + ast::MetaItemInner::Lit(..) => false, + ast::MetaItemInner::MetaItem(..) => true, + }, OverflowableItem::SegmentParam(SegmentParam::Type(ty)) => { can_be_overflowed_type(context, ty, len) } @@ -202,7 +201,7 @@ impl<'a> OverflowableItem<'a> { fn special_cases(&self, config: &Config) -> impl Iterator { let base_cases = match self { OverflowableItem::MacroArg(..) => SPECIAL_CASE_MACROS, - OverflowableItem::NestedMetaItem(..) => SPECIAL_CASE_ATTR, + OverflowableItem::MetaItemInner(..) => SPECIAL_CASE_ATTR, _ => &[], }; let additional_cases = match self { @@ -261,7 +260,7 @@ macro_rules! impl_into_overflowable_item_for_rustfmt_types { impl_into_overflowable_item_for_ast_node!( Expr, GenericParam, - NestedMetaItem, + MetaItemInner, FieldDef, Ty, Pat, diff --git a/src/tools/rustfmt/src/spanned.rs b/src/tools/rustfmt/src/spanned.rs index b4424e476ee6b..555a924079879 100644 --- a/src/tools/rustfmt/src/spanned.rs +++ b/src/tools/rustfmt/src/spanned.rs @@ -199,7 +199,7 @@ impl Spanned for MacroArg { } } -impl Spanned for ast::NestedMetaItem { +impl Spanned for ast::MetaItemInner { fn span(&self) -> Span { self.span() } diff --git a/src/tools/rustfmt/src/utils.rs b/src/tools/rustfmt/src/utils.rs index d1cfc6acc49bc..0ca34a7949174 100644 --- a/src/tools/rustfmt/src/utils.rs +++ b/src/tools/rustfmt/src/utils.rs @@ -1,7 +1,7 @@ use std::borrow::Cow; use rustc_ast::ast::{ - self, Attribute, MetaItem, MetaItemKind, NestedMetaItem, NodeId, Path, Visibility, + self, Attribute, MetaItem, MetaItemInner, MetaItemKind, NodeId, Path, Visibility, VisibilityKind, }; use rustc_ast::ptr; @@ -257,10 +257,10 @@ fn is_skip(meta_item: &MetaItem) -> bool { } #[inline] -fn is_skip_nested(meta_item: &NestedMetaItem) -> bool { +fn is_skip_nested(meta_item: &MetaItemInner) -> bool { match meta_item { - NestedMetaItem::MetaItem(ref mi) => is_skip(mi), - NestedMetaItem::Lit(_) => false, + MetaItemInner::MetaItem(ref mi) => is_skip(mi), + MetaItemInner::Lit(_) => false, } } From dd0bcf5185c540508b318079cde03aa67e205f32 Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Sun, 6 Oct 2024 18:59:40 +0300 Subject: [PATCH 1936/2194] Revert "Auto merge of #130121 - lolbinarycat:bootstrap-warn-old-upstream-worktree, r=albertlarsan68" This reverts commit 507c05bead4026ed8841512095b4218119eb479f, reversing changes made to 0609062a91c8f445c3e9a0de57e402f9b1b8b0a7. --- src/bootstrap/src/core/sanity.rs | 10 ++++- src/tools/build_helper/src/git.rs | 62 ++++++++----------------------- 2 files changed, 25 insertions(+), 47 deletions(-) diff --git a/src/bootstrap/src/core/sanity.rs b/src/bootstrap/src/core/sanity.rs index 11260f87d00f0..e9f03352ff307 100644 --- a/src/bootstrap/src/core/sanity.rs +++ b/src/bootstrap/src/core/sanity.rs @@ -383,5 +383,13 @@ $ pacman -R cmake && pacman -S mingw-w64-x86_64-cmake cmd_finder.must_have(s); } - warn_old_master_branch(&build.config.git_config(), &build.config.src); + // this warning is useless in CI, + // and CI probably won't have the right branches anyway. + if !build_helper::ci::CiEnv::is_ci() { + if let Err(e) = warn_old_master_branch(&build.config.git_config(), &build.config.src) + .map_err(|e| e.to_string()) + { + eprintln!("unable to check if upstream branch is old: {e}"); + } + } } diff --git a/src/tools/build_helper/src/git.rs b/src/tools/build_helper/src/git.rs index 10c5476cd8f3b..15d863caf0c5f 100644 --- a/src/tools/build_helper/src/git.rs +++ b/src/tools/build_helper/src/git.rs @@ -204,20 +204,21 @@ pub fn get_git_untracked_files( /// /// This can result in formatting thousands of files instead of a dozen, /// so we should warn the user something is wrong. -pub fn warn_old_master_branch(config: &GitConfig<'_>, git_dir: &Path) { - if crate::ci::CiEnv::is_ci() { - // this warning is useless in CI, - // and CI probably won't have the right branches anyway. - return; - } - // this will be overwritten by the actual name, if possible - let mut updated_master = "the upstream master branch".to_string(); - match warn_old_master_branch_(config, git_dir, &mut updated_master) { - Ok(branch_is_old) => { - if !branch_is_old { - return; +pub fn warn_old_master_branch( + config: &GitConfig<'_>, + git_dir: &Path, +) -> Result<(), Box> { + use std::time::Duration; + const WARN_AFTER: Duration = Duration::from_secs(60 * 60 * 24 * 10); + let updated_master = updated_master_branch(config, Some(git_dir))?; + let branch_path = git_dir.join(".git/refs/remotes").join(&updated_master); + match std::fs::metadata(branch_path) { + Ok(meta) => { + if meta.modified()?.elapsed()? > WARN_AFTER { + eprintln!("warning: {updated_master} has not been updated in 10 days"); + } else { + return Ok(()); } - // otherwise fall through and print the rest of the warning } Err(err) => { eprintln!("warning: unable to check if {updated_master} is old due to error: {err}") @@ -225,38 +226,7 @@ pub fn warn_old_master_branch(config: &GitConfig<'_>, git_dir: &Path) { } eprintln!( "warning: {updated_master} is used to determine if files have been modified\n\ - warning: if it is not updated, this may cause files to be needlessly reformatted" + warning: if it is not updated, this may cause files to be needlessly reformatted" ); -} - -pub fn warn_old_master_branch_( - config: &GitConfig<'_>, - git_dir: &Path, - updated_master: &mut String, -) -> Result> { - use std::time::Duration; - *updated_master = updated_master_branch(config, Some(git_dir))?; - let branch_path = git_dir.join(".git/refs/remotes").join(&updated_master); - const WARN_AFTER: Duration = Duration::from_secs(60 * 60 * 24 * 10); - let meta = match std::fs::metadata(&branch_path) { - Ok(meta) => meta, - Err(err) => { - let gcd = git_common_dir(&git_dir)?; - if branch_path.starts_with(&gcd) { - return Err(Box::new(err)); - } - std::fs::metadata(Path::new(&gcd).join("refs/remotes").join(&updated_master))? - } - }; - if meta.modified()?.elapsed()? > WARN_AFTER { - eprintln!("warning: {updated_master} has not been updated in 10 days"); - Ok(true) - } else { - Ok(false) - } -} - -fn git_common_dir(dir: &Path) -> Result { - output_result(Command::new("git").arg("-C").arg(dir).arg("rev-parse").arg("--git-common-dir")) - .map(|x| x.trim().to_string()) + Ok(()) } From 1e5c4cb0a2a4ef588598eb63f7d56b6dfe9296d4 Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Sun, 6 Oct 2024 19:01:12 +0300 Subject: [PATCH 1937/2194] Revert "Rollup merge of #129584 - lolbinarycat:old-upstream-warning, r=albertlarsan68" This reverts commit 776187d2c9a42dc07452ae36a8b765d66bd8e2ca, reversing changes made to 7d015575ada1de8a4627fcdea416194a57a175c2. --- src/bootstrap/src/core/build_steps/format.rs | 1 + src/bootstrap/src/core/sanity.rs | 12 ------- src/tools/build_helper/src/git.rs | 34 -------------------- 3 files changed, 1 insertion(+), 46 deletions(-) diff --git a/src/bootstrap/src/core/build_steps/format.rs b/src/bootstrap/src/core/build_steps/format.rs index 952d8d73328fb..5ca4321d85555 100644 --- a/src/bootstrap/src/core/build_steps/format.rs +++ b/src/bootstrap/src/core/build_steps/format.rs @@ -93,6 +93,7 @@ fn get_modified_rs_files(build: &Builder<'_>) -> Result>, Str if !verify_rustfmt_version(build) { return Ok(None); } + get_git_modified_files(&build.config.git_config(), Some(&build.config.src), &["rs"]) } diff --git a/src/bootstrap/src/core/sanity.rs b/src/bootstrap/src/core/sanity.rs index e9f03352ff307..6fbdd76ed5b6c 100644 --- a/src/bootstrap/src/core/sanity.rs +++ b/src/bootstrap/src/core/sanity.rs @@ -13,8 +13,6 @@ use std::ffi::{OsStr, OsString}; use std::path::PathBuf; use std::{env, fs}; -use build_helper::git::warn_old_master_branch; - use crate::Build; #[cfg(not(feature = "bootstrap-self-test"))] use crate::builder::Builder; @@ -382,14 +380,4 @@ $ pacman -R cmake && pacman -S mingw-w64-x86_64-cmake if let Some(ref s) = build.config.ccache { cmd_finder.must_have(s); } - - // this warning is useless in CI, - // and CI probably won't have the right branches anyway. - if !build_helper::ci::CiEnv::is_ci() { - if let Err(e) = warn_old_master_branch(&build.config.git_config(), &build.config.src) - .map_err(|e| e.to_string()) - { - eprintln!("unable to check if upstream branch is old: {e}"); - } - } } diff --git a/src/tools/build_helper/src/git.rs b/src/tools/build_helper/src/git.rs index 15d863caf0c5f..1e28d552fe66c 100644 --- a/src/tools/build_helper/src/git.rs +++ b/src/tools/build_helper/src/git.rs @@ -196,37 +196,3 @@ pub fn get_git_untracked_files( .collect(); Ok(Some(files)) } - -/// Print a warning if the branch returned from `updated_master_branch` is old -/// -/// For certain configurations of git repository, this remote will not be -/// updated when running `git pull`. -/// -/// This can result in formatting thousands of files instead of a dozen, -/// so we should warn the user something is wrong. -pub fn warn_old_master_branch( - config: &GitConfig<'_>, - git_dir: &Path, -) -> Result<(), Box> { - use std::time::Duration; - const WARN_AFTER: Duration = Duration::from_secs(60 * 60 * 24 * 10); - let updated_master = updated_master_branch(config, Some(git_dir))?; - let branch_path = git_dir.join(".git/refs/remotes").join(&updated_master); - match std::fs::metadata(branch_path) { - Ok(meta) => { - if meta.modified()?.elapsed()? > WARN_AFTER { - eprintln!("warning: {updated_master} has not been updated in 10 days"); - } else { - return Ok(()); - } - } - Err(err) => { - eprintln!("warning: unable to check if {updated_master} is old due to error: {err}") - } - } - eprintln!( - "warning: {updated_master} is used to determine if files have been modified\n\ - warning: if it is not updated, this may cause files to be needlessly reformatted" - ); - Ok(()) -} From aa5bbf05f424ae7bfb2bd859141c7e8553120d87 Mon Sep 17 00:00:00 2001 From: Folkert Date: Sun, 4 Aug 2024 16:42:37 +0200 Subject: [PATCH 1938/2194] implement `naked_asm` macro --- compiler/rustc_builtin_macros/messages.ftl | 24 +-- compiler/rustc_builtin_macros/src/asm.rs | 159 ++++++++++++++------ compiler/rustc_builtin_macros/src/errors.rs | 27 ++-- library/core/src/arch.rs | 14 ++ src/tools/rustfmt/src/parse/macros/asm.rs | 4 +- 5 files changed, 160 insertions(+), 68 deletions(-) diff --git a/compiler/rustc_builtin_macros/messages.ftl b/compiler/rustc_builtin_macros/messages.ftl index 9695df9c87e8a..b25892242b54b 100644 --- a/compiler/rustc_builtin_macros/messages.ftl +++ b/compiler/rustc_builtin_macros/messages.ftl @@ -12,9 +12,9 @@ builtin_macros_asm_duplicate_arg = duplicate argument named `{$name}` builtin_macros_asm_expected_comma = expected token: `,` .label = expected `,` -builtin_macros_asm_expected_other = expected operand, {$is_global_asm -> - [true] options - *[false] clobber_abi, options +builtin_macros_asm_expected_other = expected operand, {$is_inline_asm -> + [false] options + *[true] clobber_abi, options }, or additional template string builtin_macros_asm_expected_string_literal = expected string literal @@ -51,6 +51,15 @@ builtin_macros_asm_sym_no_path = expected a path for argument to `sym` builtin_macros_asm_underscore_input = _ cannot be used for input operands +builtin_macros_asm_unsupported_clobber_abi = `clobber_abi` cannot be used with `{$macro_name}!` + +builtin_macros_asm_unsupported_operand = the `{$symbol}` operand cannot be used with `{$macro_name}!` + .label = the `{$symbol}` operand is not meaningful for global-scoped inline assembly, remove it + +builtin_macros_asm_unsupported_option = the `{$symbol}` option cannot be used with `{$macro_name}!` + .label = the `{$symbol}` option is not meaningful for global-scoped inline assembly + .suggestion = remove this option + builtin_macros_assert_missing_comma = unexpected string literal .suggestion = try adding a comma @@ -194,15 +203,6 @@ builtin_macros_format_unused_args = multiple unused formatting arguments builtin_macros_format_use_positional = consider using a positional formatting argument instead -builtin_macros_global_asm_clobber_abi = `clobber_abi` cannot be used with `global_asm!` - -builtin_macros_global_asm_unsupported_operand = the `{$symbol}` operand cannot be used with `global_asm!` - .label = the `{$symbol}` operand is not meaningful for global-scoped inline assembly, remove it - -builtin_macros_global_asm_unsupported_option = the `{$symbol}` option cannot be used with `global_asm!` - .label = the `{$symbol}` option is not meaningful for global-scoped inline assembly - .suggestion = remove this option - builtin_macros_invalid_crate_attribute = invalid crate attribute builtin_macros_multiple_default_attrs = multiple `#[default]` attributes diff --git a/compiler/rustc_builtin_macros/src/asm.rs b/compiler/rustc_builtin_macros/src/asm.rs index 75dbb3d8e6abb..2019c42e296f5 100644 --- a/compiler/rustc_builtin_macros/src/asm.rs +++ b/compiler/rustc_builtin_macros/src/asm.rs @@ -37,29 +37,66 @@ pub struct AsmArgs { /// - `Ok(true)` if the current token matches the keyword, and was expected /// - `Ok(false)` if the current token does not match the keyword /// - `Err(_)` if the current token matches the keyword, but was not expected -fn eat_operand_keyword<'a>(p: &mut Parser<'a>, symbol: Symbol, expect: bool) -> PResult<'a, bool> { - if expect { +fn eat_operand_keyword<'a>( + p: &mut Parser<'a>, + symbol: Symbol, + asm_macro: AsmMacro, +) -> PResult<'a, bool> { + if matches!(asm_macro, AsmMacro::Asm) { Ok(p.eat_keyword(symbol)) } else { let span = p.token.span; if p.eat_keyword_noexpect(symbol) { // in gets printed as `r#in` otherwise let symbol = if symbol == kw::In { "in" } else { symbol.as_str() }; - Err(p.dcx().create_err(errors::GlobalAsmUnsupportedOperand { span, symbol })) + Err(p.dcx().create_err(errors::AsmUnsupportedOperand { + span, + symbol, + macro_name: asm_macro.macro_name(), + })) } else { Ok(false) } } } +// Public for rustfmt consumption. +#[derive(Copy, Clone)] +pub enum AsmMacro { + /// The `asm!` macro + Asm, + /// The `global_asm!` macro + GlobalAsm, + /// The `naked_asm!` macro + NakedAsm, +} + +impl AsmMacro { + const fn macro_name(&self) -> &'static str { + match self { + AsmMacro::Asm => "asm", + AsmMacro::GlobalAsm => "global_asm", + AsmMacro::NakedAsm => "naked_asm", + } + } + + const fn is_supported_option(&self, option: ast::InlineAsmOptions) -> bool { + match self { + AsmMacro::Asm => true, + AsmMacro::GlobalAsm => ast::InlineAsmOptions::GLOBAL_OPTIONS.contains(option), + AsmMacro::NakedAsm => ast::InlineAsmOptions::NAKED_OPTIONS.contains(option), + } + } +} + fn parse_args<'a>( ecx: &ExtCtxt<'a>, sp: Span, tts: TokenStream, - is_global_asm: bool, + asm_macro: AsmMacro, ) -> PResult<'a, AsmArgs> { let mut p = ecx.new_parser_from_tts(tts); - parse_asm_args(&mut p, sp, is_global_asm) + parse_asm_args(&mut p, sp, asm_macro) } // Primarily public for rustfmt consumption. @@ -67,7 +104,7 @@ fn parse_args<'a>( pub fn parse_asm_args<'a>( p: &mut Parser<'a>, sp: Span, - is_global_asm: bool, + asm_macro: AsmMacro, ) -> PResult<'a, AsmArgs> { let dcx = p.dcx(); @@ -110,7 +147,7 @@ pub fn parse_asm_args<'a>( // Parse options if p.eat_keyword(sym::options) { - parse_options(p, &mut args, is_global_asm)?; + parse_options(p, &mut args, asm_macro)?; allow_templates = false; continue; } @@ -129,7 +166,7 @@ pub fn parse_asm_args<'a>( }; let mut explicit_reg = false; - let op = if eat_operand_keyword(p, kw::In, !is_global_asm)? { + let op = if eat_operand_keyword(p, kw::In, asm_macro)? { let reg = parse_reg(p, &mut explicit_reg)?; if p.eat_keyword(kw::Underscore) { let err = dcx.create_err(errors::AsmUnderscoreInput { span: p.token.span }); @@ -137,15 +174,15 @@ pub fn parse_asm_args<'a>( } let expr = p.parse_expr()?; ast::InlineAsmOperand::In { reg, expr } - } else if eat_operand_keyword(p, sym::out, !is_global_asm)? { + } else if eat_operand_keyword(p, sym::out, asm_macro)? { let reg = parse_reg(p, &mut explicit_reg)?; let expr = if p.eat_keyword(kw::Underscore) { None } else { Some(p.parse_expr()?) }; ast::InlineAsmOperand::Out { reg, expr, late: false } - } else if eat_operand_keyword(p, sym::lateout, !is_global_asm)? { + } else if eat_operand_keyword(p, sym::lateout, asm_macro)? { let reg = parse_reg(p, &mut explicit_reg)?; let expr = if p.eat_keyword(kw::Underscore) { None } else { Some(p.parse_expr()?) }; ast::InlineAsmOperand::Out { reg, expr, late: true } - } else if eat_operand_keyword(p, sym::inout, !is_global_asm)? { + } else if eat_operand_keyword(p, sym::inout, asm_macro)? { let reg = parse_reg(p, &mut explicit_reg)?; if p.eat_keyword(kw::Underscore) { let err = dcx.create_err(errors::AsmUnderscoreInput { span: p.token.span }); @@ -159,7 +196,7 @@ pub fn parse_asm_args<'a>( } else { ast::InlineAsmOperand::InOut { reg, expr, late: false } } - } else if eat_operand_keyword(p, sym::inlateout, !is_global_asm)? { + } else if eat_operand_keyword(p, sym::inlateout, asm_macro)? { let reg = parse_reg(p, &mut explicit_reg)?; if p.eat_keyword(kw::Underscore) { let err = dcx.create_err(errors::AsmUnderscoreInput { span: p.token.span }); @@ -173,7 +210,7 @@ pub fn parse_asm_args<'a>( } else { ast::InlineAsmOperand::InOut { reg, expr, late: true } } - } else if eat_operand_keyword(p, sym::label, !is_global_asm)? { + } else if eat_operand_keyword(p, sym::label, asm_macro)? { let block = p.parse_block()?; ast::InlineAsmOperand::Label { block } } else if p.eat_keyword(kw::Const) { @@ -205,7 +242,7 @@ pub fn parse_asm_args<'a>( _ => { let err = dcx.create_err(errors::AsmExpectedOther { span: template.span, - is_global_asm, + is_inline_asm: matches!(asm_macro, AsmMacro::Asm), }); return Err(err); } @@ -301,20 +338,25 @@ pub fn parse_asm_args<'a>( dcx.emit_err(errors::AsmMayUnwind { labels_sp }); } - if args.clobber_abis.len() > 0 { - if is_global_asm { - let err = dcx.create_err(errors::GlobalAsmClobberAbi { - spans: args.clobber_abis.iter().map(|(_, span)| *span).collect(), - }); + if !args.clobber_abis.is_empty() { + match asm_macro { + AsmMacro::GlobalAsm | AsmMacro::NakedAsm => { + let err = dcx.create_err(errors::AsmUnsupportedClobberAbi { + spans: args.clobber_abis.iter().map(|(_, span)| *span).collect(), + macro_name: asm_macro.macro_name(), + }); - // Bail out now since this is likely to confuse later stages - return Err(err); - } - if !regclass_outputs.is_empty() { - dcx.emit_err(errors::AsmClobberNoReg { - spans: regclass_outputs, - clobbers: args.clobber_abis.iter().map(|(_, span)| *span).collect(), - }); + // Bail out now since this is likely to confuse later stages + return Err(err); + } + AsmMacro::Asm => { + if !regclass_outputs.is_empty() { + dcx.emit_err(errors::AsmClobberNoReg { + spans: regclass_outputs, + clobbers: args.clobber_abis.iter().map(|(_, span)| *span).collect(), + }); + } + } } } @@ -335,10 +377,15 @@ fn err_duplicate_option(p: &Parser<'_>, symbol: Symbol, span: Span) { /// /// This function must be called immediately after the option token is parsed. /// Otherwise, the suggestion will be incorrect. -fn err_unsupported_option(p: &Parser<'_>, symbol: Symbol, span: Span) { +fn err_unsupported_option(p: &Parser<'_>, asm_macro: AsmMacro, symbol: Symbol, span: Span) { // Tool-only output let full_span = if p.token == token::Comma { span.to(p.token.span) } else { span }; - p.dcx().emit_err(errors::GlobalAsmUnsupportedOption { span, symbol, full_span }); + p.dcx().emit_err(errors::AsmUnsupportedOption { + span, + symbol, + full_span, + macro_name: asm_macro.macro_name(), + }); } /// Try to set the provided option in the provided `AsmArgs`. @@ -349,12 +396,12 @@ fn err_unsupported_option(p: &Parser<'_>, symbol: Symbol, span: Span) { fn try_set_option<'a>( p: &Parser<'a>, args: &mut AsmArgs, - is_global_asm: bool, + asm_macro: AsmMacro, symbol: Symbol, option: ast::InlineAsmOptions, ) { - if is_global_asm && !ast::InlineAsmOptions::GLOBAL_OPTIONS.contains(option) { - err_unsupported_option(p, symbol, p.prev_token.span); + if !asm_macro.is_supported_option(option) { + err_unsupported_option(p, asm_macro, symbol, p.prev_token.span); } else if args.options.contains(option) { err_duplicate_option(p, symbol, p.prev_token.span); } else { @@ -365,7 +412,7 @@ fn try_set_option<'a>( fn parse_options<'a>( p: &mut Parser<'a>, args: &mut AsmArgs, - is_global_asm: bool, + asm_macro: AsmMacro, ) -> PResult<'a, ()> { let span_start = p.prev_token.span; @@ -386,15 +433,14 @@ fn parse_options<'a>( 'blk: { for (symbol, option) in OPTIONS { - let kw_matched = - if !is_global_asm || ast::InlineAsmOptions::GLOBAL_OPTIONS.contains(option) { - p.eat_keyword(symbol) - } else { - p.eat_keyword_noexpect(symbol) - }; + let kw_matched = if asm_macro.is_supported_option(option) { + p.eat_keyword(symbol) + } else { + p.eat_keyword_noexpect(symbol) + }; if kw_matched { - try_set_option(p, args, is_global_asm, symbol, option); + try_set_option(p, args, asm_macro, symbol, option); break 'blk; } } @@ -797,7 +843,7 @@ pub(super) fn expand_asm<'cx>( sp: Span, tts: TokenStream, ) -> MacroExpanderResult<'cx> { - ExpandResult::Ready(match parse_args(ecx, sp, tts, false) { + ExpandResult::Ready(match parse_args(ecx, sp, tts, AsmMacro::Asm) { Ok(args) => { let ExpandResult::Ready(mac) = expand_preparsed_asm(ecx, AsmMacro::Asm, args) else { return ExpandResult::Retry(()); @@ -865,7 +911,7 @@ pub(super) fn expand_global_asm<'cx>( sp: Span, tts: TokenStream, ) -> MacroExpanderResult<'cx> { - ExpandResult::Ready(match parse_args(ecx, sp, tts, true) { + ExpandResult::Ready(match parse_args(ecx, sp, tts, AsmMacro::GlobalAsm) { Ok(args) => { let ExpandResult::Ready(mac) = expand_preparsed_asm(ecx, AsmMacro::GlobalAsm, args) else { @@ -894,3 +940,32 @@ pub(super) fn expand_global_asm<'cx>( } }) } + +pub(super) fn expand_naked_asm<'cx>( + ecx: &'cx mut ExtCtxt<'_>, + sp: Span, + tts: TokenStream, +) -> MacroExpanderResult<'cx> { + ExpandResult::Ready(match parse_args(ecx, sp, tts, AsmMacro::NakedAsm) { + Ok(args) => { + let ExpandResult::Ready(mac) = expand_preparsed_asm(ecx, args) else { + return ExpandResult::Retry(()); + }; + let expr = match mac { + Ok(inline_asm) => P(ast::Expr { + id: ast::DUMMY_NODE_ID, + kind: ast::ExprKind::InlineAsm(P(inline_asm)), + span: sp, + attrs: ast::AttrVec::new(), + tokens: None, + }), + Err(guar) => DummyResult::raw_expr(sp, Some(guar)), + }; + MacEager::expr(expr) + } + Err(err) => { + let guar = err.emit(); + DummyResult::any(sp, guar) + } + }) +} diff --git a/compiler/rustc_builtin_macros/src/errors.rs b/compiler/rustc_builtin_macros/src/errors.rs index 4fffffb91c8b4..f13ca224a45d4 100644 --- a/compiler/rustc_builtin_macros/src/errors.rs +++ b/compiler/rustc_builtin_macros/src/errors.rs @@ -751,7 +751,7 @@ pub(crate) struct AsmExpectedOther { #[primary_span] #[label(builtin_macros_asm_expected_other)] pub(crate) span: Span, - pub(crate) is_global_asm: bool, + pub(crate) is_inline_asm: bool, } #[derive(Diagnostic)] @@ -799,13 +799,6 @@ pub(crate) struct AsmMayUnwind { pub(crate) labels_sp: Vec, } -#[derive(Diagnostic)] -#[diag(builtin_macros_global_asm_clobber_abi)] -pub(crate) struct GlobalAsmClobberAbi { - #[primary_span] - pub(crate) spans: Vec, -} - pub(crate) struct AsmClobberNoReg { pub(crate) spans: Vec, pub(crate) clobbers: Vec, @@ -841,23 +834,33 @@ pub(crate) struct AsmOptAlreadyprovided { } #[derive(Diagnostic)] -#[diag(builtin_macros_global_asm_unsupported_option)] -pub(crate) struct GlobalAsmUnsupportedOption { +#[diag(builtin_macros_asm_unsupported_option)] +pub(crate) struct AsmUnsupportedOption { #[primary_span] #[label] pub(crate) span: Span, pub(crate) symbol: Symbol, #[suggestion(code = "", applicability = "machine-applicable", style = "tool-only")] pub(crate) full_span: Span, + pub(crate) macro_name: &'static str, } #[derive(Diagnostic)] -#[diag(builtin_macros_global_asm_unsupported_operand)] -pub(crate) struct GlobalAsmUnsupportedOperand<'a> { +#[diag(builtin_macros_asm_unsupported_operand)] +pub(crate) struct AsmUnsupportedOperand<'a> { #[primary_span] #[label] pub(crate) span: Span, pub(crate) symbol: &'a str, + pub(crate) macro_name: &'static str, +} + +#[derive(Diagnostic)] +#[diag(builtin_macros_asm_unsupported_clobber_abi)] +pub(crate) struct AsmUnsupportedClobberAbi { + #[primary_span] + pub(crate) spans: Vec, + pub(crate) macro_name: &'static str, } #[derive(Diagnostic)] diff --git a/library/core/src/arch.rs b/library/core/src/arch.rs index 4945c045bc635..f1a0739128cdb 100644 --- a/library/core/src/arch.rs +++ b/library/core/src/arch.rs @@ -77,3 +77,17 @@ pub macro naked_asm("assembly template", $(operands,)* $(options($(option),*))?) pub macro global_asm("assembly template", $(operands,)* $(options($(option),*))?) { /* compiler built-in */ } + +/// Inline assembly used in combination with `#[naked]` functions. +/// +/// Refer to [Rust By Example] for a usage guide and the [reference] for +/// detailed information about the syntax and available options. +/// +/// [Rust By Example]: https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html +/// [reference]: https://doc.rust-lang.org/nightly/reference/inline-assembly.html +#[unstable(feature = "naked_functions", issue = "90957")] +#[rustc_builtin_macro] +#[cfg(not(bootstrap))] +pub macro naked_asm("assembly template", $(operands,)* $(options($(option),*))?) { + /* compiler built-in */ +} diff --git a/src/tools/rustfmt/src/parse/macros/asm.rs b/src/tools/rustfmt/src/parse/macros/asm.rs index 5ee083da5399d..5d30171e29543 100644 --- a/src/tools/rustfmt/src/parse/macros/asm.rs +++ b/src/tools/rustfmt/src/parse/macros/asm.rs @@ -1,5 +1,5 @@ use rustc_ast::ast; -use rustc_builtin_macros::asm::{AsmArgs, parse_asm_args}; +use rustc_builtin_macros::asm::{parse_asm_args, AsmArgs, AsmMacro}; use crate::rewrite::RewriteContext; @@ -7,5 +7,5 @@ use crate::rewrite::RewriteContext; pub(crate) fn parse_asm(context: &RewriteContext<'_>, mac: &ast::MacCall) -> Option { let ts = mac.args.tokens.clone(); let mut parser = super::build_parser(context, ts); - parse_asm_args(&mut parser, mac.span(), false).ok() + parse_asm_args(&mut parser, mac.span(), AsmMacro::Asm).ok() } From 0aec55504cf188d99b2047e49aad9027604df89e Mon Sep 17 00:00:00 2001 From: Folkert Date: Sun, 4 Aug 2024 16:43:12 +0200 Subject: [PATCH 1939/2194] use `naked_asm!` in `tests/ui/asm/naked-functions.rs` --- tests/ui/asm/naked-functions.rs | 72 +++++------ tests/ui/asm/naked-functions.stderr | 184 ++++++++++++---------------- 2 files changed, 117 insertions(+), 139 deletions(-) diff --git a/tests/ui/asm/naked-functions.rs b/tests/ui/asm/naked-functions.rs index 116a84506c570..86c89ea1262fd 100644 --- a/tests/ui/asm/naked-functions.rs +++ b/tests/ui/asm/naked-functions.rs @@ -6,7 +6,7 @@ #![feature(asm_unwind, linkage)] #![crate_type = "lib"] -use std::arch::asm; +use std::arch::naked_asm; #[repr(C)] pub struct P { @@ -25,7 +25,7 @@ pub unsafe extern "C" fn patterns( P { x, y }: P, //~^ ERROR patterns not allowed in naked function parameters ) { - asm!("", options(noreturn)) + naked_asm!("", options(noreturn)) } #[naked] @@ -38,9 +38,8 @@ pub unsafe extern "C" fn inc(a: u32) -> u32 { #[naked] #[allow(asm_sub_register)] pub unsafe extern "C" fn inc_asm(a: u32) -> u32 { - asm!("/* {0} */", in(reg) a, options(noreturn)); - //~^ ERROR referencing function parameters is not allowed in naked functions - //~| ERROR only `const` and `sym` operands are supported in naked functions + naked_asm!("/* {0} */", in(reg) a, options(noreturn)) + //~^ ERROR the `in` operand cannot be used with `naked_asm!` } #[naked] @@ -59,10 +58,9 @@ pub unsafe extern "C" fn unsupported_operands() { let mut e = 0usize; const F: usize = 0usize; static G: usize = 0usize; - asm!("/* {0} {1} {2} {3} {4} {5} {6} */", - //~^ ERROR asm in naked functions must use `noreturn` option + naked_asm!("/* {0} {1} {2} {3} {4} {5} {6} */", in(reg) a, - //~^ ERROR only `const` and `sym` operands are supported in naked functions + //~^ ERROR the `in` operand cannot be used with `naked_asm!` inlateout(reg) b, inout(reg) c, lateout(reg) d, @@ -81,13 +79,13 @@ pub extern "C" fn missing_assembly() { pub extern "C" fn too_many_asm_blocks() { //~^ ERROR naked functions must contain a single asm block unsafe { - asm!(""); + naked_asm!(""); //~^ ERROR asm in naked functions must use `noreturn` option - asm!(""); + naked_asm!(""); //~^ ERROR asm in naked functions must use `noreturn` option - asm!(""); + naked_asm!(""); //~^ ERROR asm in naked functions must use `noreturn` option - asm!("", options(noreturn)); + naked_asm!("", options(noreturn)); } } @@ -103,40 +101,42 @@ pub fn outer(x: u32) -> extern "C" fn(usize) -> usize { #[naked] unsafe extern "C" fn invalid_options() { - asm!("", options(nomem, preserves_flags, noreturn)); - //~^ ERROR asm options unsupported in naked functions: `nomem`, `preserves_flags` + naked_asm!("", options(nomem, preserves_flags, noreturn)); + //~^ ERROR the `nomem` option cannot be used with `naked_asm!` + //~| ERROR the `preserves_flags` option cannot be used with `naked_asm!` } #[naked] unsafe extern "C" fn invalid_options_continued() { - asm!("", options(readonly, nostack), options(pure)); - //~^ ERROR asm with the `pure` option must have at least one output - //~| ERROR asm options unsupported in naked functions: `pure`, `readonly`, `nostack` + naked_asm!("", options(readonly, nostack), options(pure)); + //~^ ERROR the `readonly` option cannot be used with `naked_asm!` + //~| ERROR the `nostack` option cannot be used with `naked_asm!` + //~| ERROR the `pure` option cannot be used with `naked_asm!` //~| ERROR asm in naked functions must use `noreturn` option } #[naked] unsafe extern "C" fn invalid_may_unwind() { - asm!("", options(noreturn, may_unwind)); - //~^ ERROR asm options unsupported in naked functions: `may_unwind` + naked_asm!("", options(noreturn, may_unwind)); + //~^ ERROR the `may_unwind` option cannot be used with `naked_asm!` } #[naked] pub unsafe fn default_abi() { //~^ WARN Rust ABI is unsupported in naked functions - asm!("", options(noreturn)); + naked_asm!("", options(noreturn)); } #[naked] pub unsafe fn rust_abi() { //~^ WARN Rust ABI is unsupported in naked functions - asm!("", options(noreturn)); + naked_asm!("", options(noreturn)); } #[naked] pub extern "C" fn valid_a() -> T { unsafe { - asm!("", options(noreturn)); + naked_asm!("", options(noreturn)); } } @@ -145,7 +145,7 @@ pub extern "C" fn valid_b() { unsafe { { { - asm!("", options(noreturn)); + naked_asm!("", options(noreturn)); }; }; } @@ -153,13 +153,13 @@ pub extern "C" fn valid_b() { #[naked] pub unsafe extern "C" fn valid_c() { - asm!("", options(noreturn)); + naked_asm!("", options(noreturn)); } #[cfg(target_arch = "x86_64")] #[naked] pub unsafe extern "C" fn valid_att_syntax() { - asm!("", options(noreturn, att_syntax)); + naked_asm!("", options(noreturn, att_syntax)); } #[naked] @@ -173,12 +173,12 @@ pub unsafe extern "C" fn allow_compile_error(a: u32) -> u32 { pub unsafe extern "C" fn allow_compile_error_and_asm(a: u32) -> u32 { compile_error!("this is a user specified error"); //~^ ERROR this is a user specified error - asm!("", options(noreturn)) + naked_asm!("", options(noreturn)) } #[naked] pub unsafe extern "C" fn invalid_asm_syntax(a: u32) -> u32 { - asm!(invalid_syntax) + naked_asm!(invalid_syntax) //~^ ERROR asm template must be a string literal } @@ -186,7 +186,7 @@ pub unsafe extern "C" fn invalid_asm_syntax(a: u32) -> u32 { #[cfg_attr(target_pointer_width = "64", no_mangle)] #[naked] pub unsafe extern "C" fn compatible_cfg_attributes() { - asm!("", options(noreturn, att_syntax)); + naked_asm!("", options(noreturn, att_syntax)); } #[allow(dead_code)] @@ -195,20 +195,20 @@ pub unsafe extern "C" fn compatible_cfg_attributes() { #[forbid(dead_code)] #[naked] pub unsafe extern "C" fn compatible_diagnostic_attributes() { - asm!("", options(noreturn, raw)); + naked_asm!("", options(noreturn, raw)); } #[deprecated = "test"] #[naked] pub unsafe extern "C" fn compatible_deprecated_attributes() { - asm!("", options(noreturn, raw)); + naked_asm!("", options(noreturn, raw)); } #[cfg(target_arch = "x86_64")] #[must_use] #[naked] pub unsafe extern "C" fn compatible_must_use_attributes() -> u64 { - asm!( + naked_asm!( " mov rax, 42 ret @@ -222,20 +222,20 @@ pub unsafe extern "C" fn compatible_must_use_attributes() -> u64 { #[no_mangle] #[naked] pub unsafe extern "C" fn compatible_ffi_attributes_1() { - asm!("", options(noreturn, raw)); + naked_asm!("", options(noreturn, raw)); } #[cold] #[naked] pub unsafe extern "C" fn compatible_codegen_attributes() { - asm!("", options(noreturn, raw)); + naked_asm!("", options(noreturn, raw)); } #[cfg(target_arch = "x86_64")] #[target_feature(enable = "sse2")] #[naked] pub unsafe extern "C" fn compatible_target_feature() { - asm!("", options(noreturn)); + naked_asm!("", options(noreturn)); } #[doc = "foo bar baz"] @@ -244,11 +244,11 @@ pub unsafe extern "C" fn compatible_target_feature() { #[doc(alias = "ADocAlias")] #[naked] pub unsafe extern "C" fn compatible_doc_attributes() { - asm!("", options(noreturn, raw)); + naked_asm!("", options(noreturn, raw)); } #[linkage = "external"] #[naked] pub unsafe extern "C" fn compatible_linkage() { - asm!("", options(noreturn, raw)); + naked_asm!("", options(noreturn, raw)); } diff --git a/tests/ui/asm/naked-functions.stderr b/tests/ui/asm/naked-functions.stderr index 93c02e2fbef82..22c1946a960c1 100644 --- a/tests/ui/asm/naked-functions.stderr +++ b/tests/ui/asm/naked-functions.stderr @@ -1,8 +1,50 @@ -error: asm with the `pure` option must have at least one output - --> $DIR/naked-functions.rs:112:14 +error: the `in` operand cannot be used with `naked_asm!` + --> $DIR/naked-functions.rs:41:29 | -LL | asm!("", options(readonly, nostack), options(pure)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^ +LL | naked_asm!("/* {0} */", in(reg) a, options(noreturn)) + | ^^ the `in` operand is not meaningful for global-scoped inline assembly, remove it + +error: the `in` operand cannot be used with `naked_asm!` + --> $DIR/naked-functions.rs:62:10 + | +LL | in(reg) a, + | ^^ the `in` operand is not meaningful for global-scoped inline assembly, remove it + +error: the `nomem` option cannot be used with `naked_asm!` + --> $DIR/naked-functions.rs:104:28 + | +LL | naked_asm!("", options(nomem, preserves_flags, noreturn)); + | ^^^^^ the `nomem` option is not meaningful for global-scoped inline assembly + +error: the `preserves_flags` option cannot be used with `naked_asm!` + --> $DIR/naked-functions.rs:104:35 + | +LL | naked_asm!("", options(nomem, preserves_flags, noreturn)); + | ^^^^^^^^^^^^^^^ the `preserves_flags` option is not meaningful for global-scoped inline assembly + +error: the `readonly` option cannot be used with `naked_asm!` + --> $DIR/naked-functions.rs:111:28 + | +LL | naked_asm!("", options(readonly, nostack), options(pure)); + | ^^^^^^^^ the `readonly` option is not meaningful for global-scoped inline assembly + +error: the `nostack` option cannot be used with `naked_asm!` + --> $DIR/naked-functions.rs:111:38 + | +LL | naked_asm!("", options(readonly, nostack), options(pure)); + | ^^^^^^^ the `nostack` option is not meaningful for global-scoped inline assembly + +error: the `pure` option cannot be used with `naked_asm!` + --> $DIR/naked-functions.rs:111:56 + | +LL | naked_asm!("", options(readonly, nostack), options(pure)); + | ^^^^ the `pure` option is not meaningful for global-scoped inline assembly + +error: the `may_unwind` option cannot be used with `naked_asm!` + --> $DIR/naked-functions.rs:120:38 + | +LL | naked_asm!("", options(noreturn, may_unwind)); + | ^^^^^^^^^^ the `may_unwind` option is not meaningful for global-scoped inline assembly error: this is a user specified error --> $DIR/naked-functions.rs:168:5 @@ -17,10 +59,10 @@ LL | compile_error!("this is a user specified error"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: asm template must be a string literal - --> $DIR/naked-functions.rs:181:10 + --> $DIR/naked-functions.rs:181:16 | -LL | asm!(invalid_syntax) - | ^^^^^^^^^^^^^^ +LL | naked_asm!(invalid_syntax) + | ^^^^^^^^^^^^^^ error: patterns not allowed in naked function parameters --> $DIR/naked-functions.rs:19:5 @@ -63,22 +105,8 @@ LL | LL | a + 1 | ----- non-asm is unsupported in naked functions -error: referencing function parameters is not allowed in naked functions - --> $DIR/naked-functions.rs:41:31 - | -LL | asm!("/* {0} */", in(reg) a, options(noreturn)); - | ^ - | - = help: follow the calling convention in asm block to use parameters - -error[E0787]: only `const` and `sym` operands are supported in naked functions - --> $DIR/naked-functions.rs:41:23 - | -LL | asm!("/* {0} */", in(reg) a, options(noreturn)); - | ^^^^^^^^^ - error[E0787]: naked functions must contain a single asm block - --> $DIR/naked-functions.rs:47:1 + --> $DIR/naked-functions.rs:46:1 | LL | pub unsafe extern "C" fn inc_closure(a: u32) -> u32 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -86,40 +114,8 @@ LL | LL | (|| a + 1)() | ------------ non-asm is unsupported in naked functions -error[E0787]: only `const` and `sym` operands are supported in naked functions - --> $DIR/naked-functions.rs:64:10 - | -LL | in(reg) a, - | ^^^^^^^^^ -LL | -LL | inlateout(reg) b, - | ^^^^^^^^^^^^^^^^ -LL | inout(reg) c, - | ^^^^^^^^^^^^ -LL | lateout(reg) d, - | ^^^^^^^^^^^^^^ -LL | out(reg) e, - | ^^^^^^^^^^ - -error[E0787]: asm in naked functions must use `noreturn` option - --> $DIR/naked-functions.rs:62:5 - | -LL | / asm!("/* {0} {1} {2} {3} {4} {5} {6} */", -LL | | -LL | | in(reg) a, -LL | | -... | -LL | | sym G, -LL | | ); - | |_____^ - | -help: consider specifying that the asm block is responsible for returning from the function - | -LL | sym G, options(noreturn), - | +++++++++++++++++++ - error[E0787]: naked functions must contain a single asm block - --> $DIR/naked-functions.rs:53:1 + --> $DIR/naked-functions.rs:52:1 | LL | pub unsafe extern "C" fn unsupported_operands() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -136,61 +132,61 @@ LL | let mut e = 0usize; | ------------------- non-asm is unsupported in naked functions error[E0787]: naked functions must contain a single asm block - --> $DIR/naked-functions.rs:76:1 + --> $DIR/naked-functions.rs:74:1 | LL | pub extern "C" fn missing_assembly() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0787]: asm in naked functions must use `noreturn` option - --> $DIR/naked-functions.rs:84:9 + --> $DIR/naked-functions.rs:82:9 | -LL | asm!(""); - | ^^^^^^^^ +LL | naked_asm!(""); + | ^^^^^^^^^^^^^^ | help: consider specifying that the asm block is responsible for returning from the function | -LL | asm!("", options(noreturn)); - | +++++++++++++++++++ +LL | naked_asm!("", options(noreturn)); + | +++++++++++++++++++ error[E0787]: asm in naked functions must use `noreturn` option - --> $DIR/naked-functions.rs:86:9 + --> $DIR/naked-functions.rs:84:9 | -LL | asm!(""); - | ^^^^^^^^ +LL | naked_asm!(""); + | ^^^^^^^^^^^^^^ | help: consider specifying that the asm block is responsible for returning from the function | -LL | asm!("", options(noreturn)); - | +++++++++++++++++++ +LL | naked_asm!("", options(noreturn)); + | +++++++++++++++++++ error[E0787]: asm in naked functions must use `noreturn` option - --> $DIR/naked-functions.rs:88:9 + --> $DIR/naked-functions.rs:86:9 | -LL | asm!(""); - | ^^^^^^^^ +LL | naked_asm!(""); + | ^^^^^^^^^^^^^^ | help: consider specifying that the asm block is responsible for returning from the function | -LL | asm!("", options(noreturn)); - | +++++++++++++++++++ +LL | naked_asm!("", options(noreturn)); + | +++++++++++++++++++ error[E0787]: naked functions must contain a single asm block - --> $DIR/naked-functions.rs:81:1 + --> $DIR/naked-functions.rs:79:1 | LL | pub extern "C" fn too_many_asm_blocks() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ... -LL | asm!(""); - | -------- multiple asm blocks are unsupported in naked functions +LL | naked_asm!(""); + | -------------- multiple asm blocks are unsupported in naked functions LL | -LL | asm!(""); - | -------- multiple asm blocks are unsupported in naked functions +LL | naked_asm!(""); + | -------------- multiple asm blocks are unsupported in naked functions LL | -LL | asm!("", options(noreturn)); - | --------------------------- multiple asm blocks are unsupported in naked functions +LL | naked_asm!("", options(noreturn)); + | --------------------------------- multiple asm blocks are unsupported in naked functions error: referencing function parameters is not allowed in naked functions - --> $DIR/naked-functions.rs:98:11 + --> $DIR/naked-functions.rs:96:11 | LL | *&y | ^ @@ -198,7 +194,7 @@ LL | *&y = help: follow the calling convention in asm block to use parameters error[E0787]: naked functions must contain a single asm block - --> $DIR/naked-functions.rs:96:5 + --> $DIR/naked-functions.rs:94:5 | LL | pub extern "C" fn inner(y: usize) -> usize { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -206,34 +202,16 @@ LL | LL | *&y | --- non-asm is unsupported in naked functions -error[E0787]: asm options unsupported in naked functions: `nomem`, `preserves_flags` - --> $DIR/naked-functions.rs:106:5 - | -LL | asm!("", options(nomem, preserves_flags, noreturn)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error[E0787]: asm options unsupported in naked functions: `pure`, `readonly`, `nostack` - --> $DIR/naked-functions.rs:112:5 - | -LL | asm!("", options(readonly, nostack), options(pure)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - error[E0787]: asm in naked functions must use `noreturn` option - --> $DIR/naked-functions.rs:112:5 + --> $DIR/naked-functions.rs:111:5 | -LL | asm!("", options(readonly, nostack), options(pure)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | naked_asm!("", options(readonly, nostack), options(pure)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | help: consider specifying that the asm block is responsible for returning from the function | -LL | asm!("", options(noreturn), options(readonly, nostack), options(pure)); - | +++++++++++++++++++ - -error[E0787]: asm options unsupported in naked functions: `may_unwind` - --> $DIR/naked-functions.rs:120:5 - | -LL | asm!("", options(noreturn, may_unwind)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | naked_asm!("", options(noreturn), options(readonly, nostack), options(pure)); + | +++++++++++++++++++ warning: Rust ABI is unsupported in naked functions --> $DIR/naked-functions.rs:125:1 From 47b42bef3226bb71506988572c73ec1b6f99a730 Mon Sep 17 00:00:00 2001 From: Folkert Date: Sun, 4 Aug 2024 16:45:48 +0200 Subject: [PATCH 1940/2194] use `naked_asm!` in naked-function tests --- tests/codegen/naked-fn/naked-functions.rs | 6 +-- tests/ui/asm/naked-functions-ffi.rs | 4 +- tests/ui/asm/naked-functions-inline.rs | 2 +- .../ui/asm/naked-functions-instruction-set.rs | 6 +-- tests/ui/asm/naked-functions-testattrs.rs | 10 ++--- .../asm/naked-functions-unused.aarch64.stderr | 16 +++---- tests/ui/asm/naked-functions-unused.rs | 42 ++++++++++++++----- .../asm/naked-functions-unused.x86_64.stderr | 16 +++---- .../feature-gate-naked_functions.rs | 4 +- 9 files changed, 63 insertions(+), 43 deletions(-) diff --git a/tests/codegen/naked-fn/naked-functions.rs b/tests/codegen/naked-fn/naked-functions.rs index 307745a921cf6..2b2625429f8e0 100644 --- a/tests/codegen/naked-fn/naked-functions.rs +++ b/tests/codegen/naked-fn/naked-functions.rs @@ -4,7 +4,7 @@ #![crate_type = "lib"] #![feature(naked_functions)] -use std::arch::asm; +use std::arch::naked_asm; // CHECK: Function Attrs: naked // CHECK-NEXT: define{{.*}}void @naked_empty() @@ -14,7 +14,7 @@ pub unsafe extern "C" fn naked_empty() { // CHECK-NEXT: {{.+}}: // CHECK-NEXT: call void asm // CHECK-NEXT: unreachable - asm!("ret", options(noreturn)); + naked_asm!("ret", options(noreturn)); } // CHECK: Function Attrs: naked @@ -25,5 +25,5 @@ pub unsafe extern "C" fn naked_with_args_and_return(a: isize, b: isize) -> isize // CHECK-NEXT: {{.+}}: // CHECK-NEXT: call void asm // CHECK-NEXT: unreachable - asm!("lea rax, [rdi + rsi]", "ret", options(noreturn)); + naked_asm!("lea rax, [rdi + rsi]", "ret", options(noreturn)); } diff --git a/tests/ui/asm/naked-functions-ffi.rs b/tests/ui/asm/naked-functions-ffi.rs index 93d23885b1353..6b32290905d49 100644 --- a/tests/ui/asm/naked-functions-ffi.rs +++ b/tests/ui/asm/naked-functions-ffi.rs @@ -3,13 +3,13 @@ #![feature(naked_functions)] #![crate_type = "lib"] -use std::arch::asm; +use std::arch::naked_asm; #[naked] pub extern "C" fn naked(p: char) -> u128 { //~^ WARN uses type `char` //~| WARN uses type `u128` unsafe { - asm!("", options(noreturn)); + naked_asm!("", options(noreturn)); } } diff --git a/tests/ui/asm/naked-functions-inline.rs b/tests/ui/asm/naked-functions-inline.rs index 74049e8ecbc7c..a4df38e3347c6 100644 --- a/tests/ui/asm/naked-functions-inline.rs +++ b/tests/ui/asm/naked-functions-inline.rs @@ -19,7 +19,7 @@ pub unsafe extern "C" fn inline_hint() { #[naked] #[inline(always)] //~^ ERROR [E0736] -pub unsafe extern "C" fn inline_always() { +<<<<<<< HEAD naked_asm!(""); } diff --git a/tests/ui/asm/naked-functions-instruction-set.rs b/tests/ui/asm/naked-functions-instruction-set.rs index b81b65cff74fc..6c6dcdf008779 100644 --- a/tests/ui/asm/naked-functions-instruction-set.rs +++ b/tests/ui/asm/naked-functions-instruction-set.rs @@ -8,7 +8,7 @@ #![no_core] #[rustc_builtin_macro] -macro_rules! asm { +macro_rules! naked_asm { () => {}; } @@ -19,12 +19,12 @@ trait Sized {} #[naked] #[instruction_set(arm::t32)] unsafe extern "C" fn test_thumb() { - asm!("bx lr", options(noreturn)); + naked_asm!("bx lr", options(noreturn)); } #[no_mangle] #[naked] #[instruction_set(arm::t32)] unsafe extern "C" fn test_arm() { - asm!("bx lr", options(noreturn)); + naked_asm!("bx lr", options(noreturn)); } diff --git a/tests/ui/asm/naked-functions-testattrs.rs b/tests/ui/asm/naked-functions-testattrs.rs index 12943ac0378b7..2532e6e86d63a 100644 --- a/tests/ui/asm/naked-functions-testattrs.rs +++ b/tests/ui/asm/naked-functions-testattrs.rs @@ -6,13 +6,13 @@ #![feature(test)] #![crate_type = "lib"] -use std::arch::asm; +use std::arch::naked_asm; #[test] #[naked] //~^ ERROR [E0736] fn test_naked() { - unsafe { asm!("", options(noreturn)) }; + unsafe { naked_asm!("", options(noreturn)) }; } #[should_panic] @@ -20,7 +20,7 @@ fn test_naked() { #[naked] //~^ ERROR [E0736] fn test_naked_should_panic() { - unsafe { asm!("", options(noreturn)) }; + unsafe { naked_asm!("", options(noreturn)) }; } #[ignore] @@ -28,12 +28,12 @@ fn test_naked_should_panic() { #[naked] //~^ ERROR [E0736] fn test_naked_ignore() { - unsafe { asm!("", options(noreturn)) }; + unsafe { naked_asm!("", options(noreturn)) }; } #[bench] #[naked] //~^ ERROR [E0736] fn bench_naked() { - unsafe { asm!("", options(noreturn)) }; + unsafe { naked_asm!("", options(noreturn)) }; } diff --git a/tests/ui/asm/naked-functions-unused.aarch64.stderr b/tests/ui/asm/naked-functions-unused.aarch64.stderr index 8d3c300e0586c..ea63ced1aab04 100644 --- a/tests/ui/asm/naked-functions-unused.aarch64.stderr +++ b/tests/ui/asm/naked-functions-unused.aarch64.stderr @@ -18,49 +18,49 @@ LL | pub extern "C" fn function(a: usize, b: usize) -> usize { | ^ help: if this is intentional, prefix it with an underscore: `_b` error: unused variable: `a` - --> $DIR/naked-functions-unused.rs:26:38 + --> $DIR/naked-functions-unused.rs:28:38 | LL | pub extern "C" fn associated(a: usize, b: usize) -> usize { | ^ help: if this is intentional, prefix it with an underscore: `_a` error: unused variable: `b` - --> $DIR/naked-functions-unused.rs:26:48 + --> $DIR/naked-functions-unused.rs:28:48 | LL | pub extern "C" fn associated(a: usize, b: usize) -> usize { | ^ help: if this is intentional, prefix it with an underscore: `_b` error: unused variable: `a` - --> $DIR/naked-functions-unused.rs:32:41 + --> $DIR/naked-functions-unused.rs:36:41 | LL | pub extern "C" fn method(&self, a: usize, b: usize) -> usize { | ^ help: if this is intentional, prefix it with an underscore: `_a` error: unused variable: `b` - --> $DIR/naked-functions-unused.rs:32:51 + --> $DIR/naked-functions-unused.rs:36:51 | LL | pub extern "C" fn method(&self, a: usize, b: usize) -> usize { | ^ help: if this is intentional, prefix it with an underscore: `_b` error: unused variable: `a` - --> $DIR/naked-functions-unused.rs:40:40 + --> $DIR/naked-functions-unused.rs:46:40 | LL | extern "C" fn trait_associated(a: usize, b: usize) -> usize { | ^ help: if this is intentional, prefix it with an underscore: `_a` error: unused variable: `b` - --> $DIR/naked-functions-unused.rs:40:50 + --> $DIR/naked-functions-unused.rs:46:50 | LL | extern "C" fn trait_associated(a: usize, b: usize) -> usize { | ^ help: if this is intentional, prefix it with an underscore: `_b` error: unused variable: `a` - --> $DIR/naked-functions-unused.rs:46:43 + --> $DIR/naked-functions-unused.rs:54:43 | LL | extern "C" fn trait_method(&self, a: usize, b: usize) -> usize { | ^ help: if this is intentional, prefix it with an underscore: `_a` error: unused variable: `b` - --> $DIR/naked-functions-unused.rs:46:53 + --> $DIR/naked-functions-unused.rs:54:53 | LL | extern "C" fn trait_method(&self, a: usize, b: usize) -> usize { | ^ help: if this is intentional, prefix it with an underscore: `_b` diff --git a/tests/ui/asm/naked-functions-unused.rs b/tests/ui/asm/naked-functions-unused.rs index 745d30e6a84a9..6d3cc0afed836 100644 --- a/tests/ui/asm/naked-functions-unused.rs +++ b/tests/ui/asm/naked-functions-unused.rs @@ -17,7 +17,9 @@ pub mod normal { pub extern "C" fn function(a: usize, b: usize) -> usize { //~^ ERROR unused variable: `a` //~| ERROR unused variable: `b` - unsafe { asm!("", options(noreturn)); } + unsafe { + asm!("", options(noreturn)); + } } pub struct Normal; @@ -26,13 +28,17 @@ pub mod normal { pub extern "C" fn associated(a: usize, b: usize) -> usize { //~^ ERROR unused variable: `a` //~| ERROR unused variable: `b` - unsafe { asm!("", options(noreturn)); } + unsafe { + asm!("", options(noreturn)); + } } pub extern "C" fn method(&self, a: usize, b: usize) -> usize { //~^ ERROR unused variable: `a` //~| ERROR unused variable: `b` - unsafe { asm!("", options(noreturn)); } + unsafe { + asm!("", options(noreturn)); + } } } @@ -40,23 +46,29 @@ pub mod normal { extern "C" fn trait_associated(a: usize, b: usize) -> usize { //~^ ERROR unused variable: `a` //~| ERROR unused variable: `b` - unsafe { asm!("", options(noreturn)); } + unsafe { + asm!("", options(noreturn)); + } } extern "C" fn trait_method(&self, a: usize, b: usize) -> usize { //~^ ERROR unused variable: `a` //~| ERROR unused variable: `b` - unsafe { asm!("", options(noreturn)); } + unsafe { + asm!("", options(noreturn)); + } } } } pub mod naked { - use std::arch::asm; + use std::arch::naked_asm; #[naked] pub extern "C" fn function(a: usize, b: usize) -> usize { - unsafe { asm!("", options(noreturn)); } + unsafe { + naked_asm!("", options(noreturn)); + } } pub struct Naked; @@ -64,24 +76,32 @@ pub mod naked { impl Naked { #[naked] pub extern "C" fn associated(a: usize, b: usize) -> usize { - unsafe { asm!("", options(noreturn)); } + unsafe { + naked_asm!("", options(noreturn)); + } } #[naked] pub extern "C" fn method(&self, a: usize, b: usize) -> usize { - unsafe { asm!("", options(noreturn)); } + unsafe { + naked_asm!("", options(noreturn)); + } } } impl super::Trait for Naked { #[naked] extern "C" fn trait_associated(a: usize, b: usize) -> usize { - unsafe { asm!("", options(noreturn)); } + unsafe { + naked_asm!("", options(noreturn)); + } } #[naked] extern "C" fn trait_method(&self, a: usize, b: usize) -> usize { - unsafe { asm!("", options(noreturn)); } + unsafe { + naked_asm!("", options(noreturn)); + } } } } diff --git a/tests/ui/asm/naked-functions-unused.x86_64.stderr b/tests/ui/asm/naked-functions-unused.x86_64.stderr index 8d3c300e0586c..ea63ced1aab04 100644 --- a/tests/ui/asm/naked-functions-unused.x86_64.stderr +++ b/tests/ui/asm/naked-functions-unused.x86_64.stderr @@ -18,49 +18,49 @@ LL | pub extern "C" fn function(a: usize, b: usize) -> usize { | ^ help: if this is intentional, prefix it with an underscore: `_b` error: unused variable: `a` - --> $DIR/naked-functions-unused.rs:26:38 + --> $DIR/naked-functions-unused.rs:28:38 | LL | pub extern "C" fn associated(a: usize, b: usize) -> usize { | ^ help: if this is intentional, prefix it with an underscore: `_a` error: unused variable: `b` - --> $DIR/naked-functions-unused.rs:26:48 + --> $DIR/naked-functions-unused.rs:28:48 | LL | pub extern "C" fn associated(a: usize, b: usize) -> usize { | ^ help: if this is intentional, prefix it with an underscore: `_b` error: unused variable: `a` - --> $DIR/naked-functions-unused.rs:32:41 + --> $DIR/naked-functions-unused.rs:36:41 | LL | pub extern "C" fn method(&self, a: usize, b: usize) -> usize { | ^ help: if this is intentional, prefix it with an underscore: `_a` error: unused variable: `b` - --> $DIR/naked-functions-unused.rs:32:51 + --> $DIR/naked-functions-unused.rs:36:51 | LL | pub extern "C" fn method(&self, a: usize, b: usize) -> usize { | ^ help: if this is intentional, prefix it with an underscore: `_b` error: unused variable: `a` - --> $DIR/naked-functions-unused.rs:40:40 + --> $DIR/naked-functions-unused.rs:46:40 | LL | extern "C" fn trait_associated(a: usize, b: usize) -> usize { | ^ help: if this is intentional, prefix it with an underscore: `_a` error: unused variable: `b` - --> $DIR/naked-functions-unused.rs:40:50 + --> $DIR/naked-functions-unused.rs:46:50 | LL | extern "C" fn trait_associated(a: usize, b: usize) -> usize { | ^ help: if this is intentional, prefix it with an underscore: `_b` error: unused variable: `a` - --> $DIR/naked-functions-unused.rs:46:43 + --> $DIR/naked-functions-unused.rs:54:43 | LL | extern "C" fn trait_method(&self, a: usize, b: usize) -> usize { | ^ help: if this is intentional, prefix it with an underscore: `_a` error: unused variable: `b` - --> $DIR/naked-functions-unused.rs:46:53 + --> $DIR/naked-functions-unused.rs:54:53 | LL | extern "C" fn trait_method(&self, a: usize, b: usize) -> usize { | ^ help: if this is intentional, prefix it with an underscore: `_b` diff --git a/tests/ui/feature-gates/feature-gate-naked_functions.rs b/tests/ui/feature-gates/feature-gate-naked_functions.rs index 36980fd74c264..298b687e4f2fd 100644 --- a/tests/ui/feature-gates/feature-gate-naked_functions.rs +++ b/tests/ui/feature-gates/feature-gate-naked_functions.rs @@ -5,14 +5,14 @@ use std::arch::asm; #[naked] //~^ the `#[naked]` attribute is an experimental feature extern "C" fn naked() { - asm!("", options(noreturn)) + naked_asm!("", options(noreturn)) //~^ ERROR: requires unsafe } #[naked] //~^ the `#[naked]` attribute is an experimental feature extern "C" fn naked_2() -> isize { - asm!("", options(noreturn)) + naked_asm!("", options(noreturn)) //~^ ERROR: requires unsafe } From 1a9c1cbf367fb2b6f04a0a81d7fae56485e29e7f Mon Sep 17 00:00:00 2001 From: Folkert Date: Sun, 4 Aug 2024 17:19:08 +0200 Subject: [PATCH 1941/2194] use `naked_asm!` in feature-gate-naked_functions test --- .../feature-gate-naked_functions.rs | 9 ++-- .../feature-gate-naked_functions.stderr | 48 +++++++++++++++---- 2 files changed, 45 insertions(+), 12 deletions(-) diff --git a/tests/ui/feature-gates/feature-gate-naked_functions.rs b/tests/ui/feature-gates/feature-gate-naked_functions.rs index 298b687e4f2fd..c8802ea4c31f2 100644 --- a/tests/ui/feature-gates/feature-gate-naked_functions.rs +++ b/tests/ui/feature-gates/feature-gate-naked_functions.rs @@ -1,19 +1,22 @@ //@ needs-asm-support -use std::arch::asm; +use std::arch::naked_asm; +//~^ ERROR use of unstable library feature 'naked_functions' #[naked] //~^ the `#[naked]` attribute is an experimental feature extern "C" fn naked() { naked_asm!("", options(noreturn)) - //~^ ERROR: requires unsafe + //~^ ERROR use of unstable library feature 'naked_functions' + //~| ERROR: requires unsafe } #[naked] //~^ the `#[naked]` attribute is an experimental feature extern "C" fn naked_2() -> isize { naked_asm!("", options(noreturn)) - //~^ ERROR: requires unsafe + //~^ ERROR use of unstable library feature 'naked_functions' + //~| ERROR: requires unsafe } fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-naked_functions.stderr b/tests/ui/feature-gates/feature-gate-naked_functions.stderr index ffdf31e147aed..5fecc218a1622 100644 --- a/tests/ui/feature-gates/feature-gate-naked_functions.stderr +++ b/tests/ui/feature-gates/feature-gate-naked_functions.stderr @@ -1,5 +1,25 @@ +error[E0658]: use of unstable library feature 'naked_functions' + --> $DIR/feature-gate-naked_functions.rs:9:5 + | +LL | naked_asm!("", options(noreturn)) + | ^^^^^^^^^ + | + = note: see issue #90957 for more information + = help: add `#![feature(naked_functions)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: use of unstable library feature 'naked_functions' + --> $DIR/feature-gate-naked_functions.rs:17:5 + | +LL | naked_asm!("", options(noreturn)) + | ^^^^^^^^^ + | + = note: see issue #90957 for more information + = help: add `#![feature(naked_functions)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + error[E0658]: the `#[naked]` attribute is an experimental feature - --> $DIR/feature-gate-naked_functions.rs:5:1 + --> $DIR/feature-gate-naked_functions.rs:6:1 | LL | #[naked] | ^^^^^^^^ @@ -9,7 +29,7 @@ LL | #[naked] = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: the `#[naked]` attribute is an experimental feature - --> $DIR/feature-gate-naked_functions.rs:12:1 + --> $DIR/feature-gate-naked_functions.rs:14:1 | LL | #[naked] | ^^^^^^^^ @@ -18,23 +38,33 @@ LL | #[naked] = help: add `#![feature(naked_functions)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date +error[E0658]: use of unstable library feature 'naked_functions' + --> $DIR/feature-gate-naked_functions.rs:3:5 + | +LL | use std::arch::naked_asm; + | ^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #90957 for more information + = help: add `#![feature(naked_functions)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + error[E0133]: use of inline assembly is unsafe and requires unsafe function or block - --> $DIR/feature-gate-naked_functions.rs:8:5 + --> $DIR/feature-gate-naked_functions.rs:9:5 | -LL | asm!("", options(noreturn)) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ use of inline assembly +LL | naked_asm!("", options(noreturn)) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ use of inline assembly | = note: inline assembly is entirely unchecked and can cause undefined behavior error[E0133]: use of inline assembly is unsafe and requires unsafe function or block - --> $DIR/feature-gate-naked_functions.rs:15:5 + --> $DIR/feature-gate-naked_functions.rs:17:5 | -LL | asm!("", options(noreturn)) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ use of inline assembly +LL | naked_asm!("", options(noreturn)) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ use of inline assembly | = note: inline assembly is entirely unchecked and can cause undefined behavior -error: aborting due to 4 previous errors +error: aborting due to 7 previous errors Some errors have detailed explanations: E0133, E0658. For more information about an error, try `rustc --explain E0133`. From 562ec5a6fb469a360b72aa8ba0ce149598cc7975 Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Thu, 5 Sep 2024 13:45:26 +0200 Subject: [PATCH 1942/2194] disallow `asm!` in `#[naked]` functions also disallow the `noreturn` option, and infer `naked_asm!` as `!` --- compiler/rustc_ast/src/ast.rs | 20 ++- compiler/rustc_builtin_macros/src/asm.rs | 62 +------ .../src/error_codes/E0787.md | 5 +- compiler/rustc_hir_typeck/src/expr.rs | 6 +- compiler/rustc_passes/messages.ftl | 12 +- compiler/rustc_passes/src/errors.rs | 8 +- compiler/rustc_passes/src/naked_functions.rs | 47 +++--- library/core/src/arch.rs | 14 -- src/tools/rustfmt/src/parse/macros/asm.rs | 4 +- tests/codegen/naked-fn/aligned.rs | 4 +- tests/codegen/naked-fn/naked-functions.rs | 4 +- tests/codegen/naked-fn/naked-nocoverage.rs | 4 +- tests/codegen/naked-fn/naked-noinline.rs | 4 +- tests/ui/asm/naked-functions-ffi.rs | 2 +- tests/ui/asm/naked-functions-inline.rs | 2 +- .../ui/asm/naked-functions-instruction-set.rs | 4 +- tests/ui/asm/naked-functions-testattrs.rs | 8 +- tests/ui/asm/naked-functions-unused.rs | 10 +- tests/ui/asm/naked-functions.rs | 68 ++++---- tests/ui/asm/naked-functions.stderr | 156 +++++++----------- tests/ui/asm/naked-invalid-attr.rs | 13 +- tests/ui/asm/naked-invalid-attr.stderr | 6 +- tests/ui/asm/naked-with-invalid-repr-attr.rs | 12 +- .../asm/naked-with-invalid-repr-attr.stderr | 12 +- tests/ui/asm/named-asm-labels.rs | 10 +- tests/ui/asm/named-asm-labels.stderr | 18 +- .../feature-gate-naked_functions.rs | 4 +- 27 files changed, 222 insertions(+), 297 deletions(-) diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index 37f429cce44d7..cb71521317637 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -2278,7 +2278,7 @@ impl InlineAsmOptions { pub const COUNT: usize = Self::all().bits().count_ones() as usize; pub const GLOBAL_OPTIONS: Self = Self::ATT_SYNTAX.union(Self::RAW); - pub const NAKED_OPTIONS: Self = Self::ATT_SYNTAX.union(Self::RAW).union(Self::NORETURN); + pub const NAKED_OPTIONS: Self = Self::ATT_SYNTAX.union(Self::RAW); pub fn human_readable_names(&self) -> Vec<&'static str> { let mut options = vec![]; @@ -2434,6 +2434,24 @@ pub enum AsmMacro { NakedAsm, } +impl AsmMacro { + pub const fn macro_name(&self) -> &'static str { + match self { + AsmMacro::Asm => "asm", + AsmMacro::GlobalAsm => "global_asm", + AsmMacro::NakedAsm => "naked_asm", + } + } + + pub const fn is_supported_option(&self, option: InlineAsmOptions) -> bool { + match self { + AsmMacro::Asm => true, + AsmMacro::GlobalAsm => InlineAsmOptions::GLOBAL_OPTIONS.contains(option), + AsmMacro::NakedAsm => InlineAsmOptions::NAKED_OPTIONS.contains(option), + } + } +} + /// Inline assembly. /// /// E.g., `asm!("NOP");`. diff --git a/compiler/rustc_builtin_macros/src/asm.rs b/compiler/rustc_builtin_macros/src/asm.rs index 2019c42e296f5..515ac17f70a14 100644 --- a/compiler/rustc_builtin_macros/src/asm.rs +++ b/compiler/rustc_builtin_macros/src/asm.rs @@ -60,35 +60,6 @@ fn eat_operand_keyword<'a>( } } -// Public for rustfmt consumption. -#[derive(Copy, Clone)] -pub enum AsmMacro { - /// The `asm!` macro - Asm, - /// The `global_asm!` macro - GlobalAsm, - /// The `naked_asm!` macro - NakedAsm, -} - -impl AsmMacro { - const fn macro_name(&self) -> &'static str { - match self { - AsmMacro::Asm => "asm", - AsmMacro::GlobalAsm => "global_asm", - AsmMacro::NakedAsm => "naked_asm", - } - } - - const fn is_supported_option(&self, option: ast::InlineAsmOptions) -> bool { - match self { - AsmMacro::Asm => true, - AsmMacro::GlobalAsm => ast::InlineAsmOptions::GLOBAL_OPTIONS.contains(option), - AsmMacro::NakedAsm => ast::InlineAsmOptions::NAKED_OPTIONS.contains(option), - } - } -} - fn parse_args<'a>( ecx: &ExtCtxt<'a>, sp: Span, @@ -529,7 +500,7 @@ fn parse_reg<'a>( fn expand_preparsed_asm( ecx: &mut ExtCtxt<'_>, - asm_macro: ast::AsmMacro, + asm_macro: AsmMacro, args: AsmArgs, ) -> ExpandResult, ()> { let mut template = vec![]; @@ -872,7 +843,7 @@ pub(super) fn expand_naked_asm<'cx>( sp: Span, tts: TokenStream, ) -> MacroExpanderResult<'cx> { - ExpandResult::Ready(match parse_args(ecx, sp, tts, false) { + ExpandResult::Ready(match parse_args(ecx, sp, tts, AsmMacro::NakedAsm) { Ok(args) => { let ExpandResult::Ready(mac) = expand_preparsed_asm(ecx, AsmMacro::NakedAsm, args) else { @@ -940,32 +911,3 @@ pub(super) fn expand_global_asm<'cx>( } }) } - -pub(super) fn expand_naked_asm<'cx>( - ecx: &'cx mut ExtCtxt<'_>, - sp: Span, - tts: TokenStream, -) -> MacroExpanderResult<'cx> { - ExpandResult::Ready(match parse_args(ecx, sp, tts, AsmMacro::NakedAsm) { - Ok(args) => { - let ExpandResult::Ready(mac) = expand_preparsed_asm(ecx, args) else { - return ExpandResult::Retry(()); - }; - let expr = match mac { - Ok(inline_asm) => P(ast::Expr { - id: ast::DUMMY_NODE_ID, - kind: ast::ExprKind::InlineAsm(P(inline_asm)), - span: sp, - attrs: ast::AttrVec::new(), - tokens: None, - }), - Err(guar) => DummyResult::raw_expr(sp, Some(guar)), - }; - MacEager::expr(expr) - } - Err(err) => { - let guar = err.emit(); - DummyResult::any(sp, guar) - } - }) -} diff --git a/compiler/rustc_error_codes/src/error_codes/E0787.md b/compiler/rustc_error_codes/src/error_codes/E0787.md index cee5082927026..f5c5faa066b6b 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0787.md +++ b/compiler/rustc_error_codes/src/error_codes/E0787.md @@ -11,11 +11,10 @@ pub extern "C" fn f() -> u32 { } ``` -The naked functions must be defined using a single inline assembly -block. +The naked function must be defined using a single `naked_asm!` assembly block. The execution must never fall through past the end of the assembly -code so the block must use `noreturn` option. The asm block can also +code, so it must either return or diverge. The asm block can also use `att_syntax` and `raw` options, but others options are not allowed. The asm block must not contain any operands other than `const` and diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index 2d71829537496..5c2f39f879c4c 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -3507,7 +3507,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } fn check_expr_asm(&self, asm: &'tcx hir::InlineAsm<'tcx>) -> Ty<'tcx> { - let mut diverge = asm.options.contains(ast::InlineAsmOptions::NORETURN); + let mut diverge = match asm.asm_macro { + rustc_ast::AsmMacro::Asm => asm.options.contains(ast::InlineAsmOptions::NORETURN), + rustc_ast::AsmMacro::GlobalAsm => true, + rustc_ast::AsmMacro::NakedAsm => true, + }; for (op, _op_sp) in asm.operands { match op { diff --git a/compiler/rustc_passes/messages.ftl b/compiler/rustc_passes/messages.ftl index f2682acf8aa0b..1b1d1b1fb72ed 100644 --- a/compiler/rustc_passes/messages.ftl +++ b/compiler/rustc_passes/messages.ftl @@ -488,9 +488,9 @@ passes_naked_asm_outside_naked_fn = the `naked_asm!` macro can only be used in functions marked with `#[naked]` passes_naked_functions_asm_block = - naked functions must contain a single asm block - .label_multiple_asm = multiple asm blocks are unsupported in naked functions - .label_non_asm = non-asm is unsupported in naked functions + naked functions must contain a single `naked_asm!` invocation + .label_multiple_asm = multiple `naked_asm!` invocations are not allowed in naked functions + .label_non_asm = not allowed in naked functions passes_naked_functions_asm_options = asm options unsupported in naked functions: {$unsupported_options} @@ -500,9 +500,9 @@ passes_naked_functions_incompatible_attribute = .label = the `{$attr}` attribute is incompatible with `#[naked]` .naked_attribute = function marked with `#[naked]` here -passes_naked_functions_must_use_noreturn = - asm in naked functions must use `noreturn` option - .suggestion = consider specifying that the asm block is responsible for returning from the function +passes_naked_functions_must_naked_asm = + the `asm!` macro is not allowed in naked functions + .suggestion = consider using the `naked_asm!` macro instead passes_naked_functions_operands = only `const` and `sym` operands are supported in naked functions diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs index 29a087bf75975..c46768ace53ab 100644 --- a/compiler/rustc_passes/src/errors.rs +++ b/compiler/rustc_passes/src/errors.rs @@ -1202,12 +1202,12 @@ pub(crate) struct NakedFunctionsAsmOptions { } #[derive(Diagnostic)] -#[diag(passes_naked_functions_must_use_noreturn, code = E0787)] -pub(crate) struct NakedFunctionsMustUseNoreturn { +#[diag(passes_naked_functions_must_naked_asm, code = E0787)] +pub(crate) struct NakedFunctionsMustNakedAsm { #[primary_span] pub span: Span, - #[suggestion(code = ", options(noreturn)", applicability = "machine-applicable")] - pub last_span: Span, + #[suggestion(code = "naked_asm!", applicability = "machine-applicable")] + pub macro_span: Span, } #[derive(Diagnostic)] diff --git a/compiler/rustc_passes/src/naked_functions.rs b/compiler/rustc_passes/src/naked_functions.rs index 8d3f7e0231f78..6046c7284304e 100644 --- a/compiler/rustc_passes/src/naked_functions.rs +++ b/compiler/rustc_passes/src/naked_functions.rs @@ -10,13 +10,13 @@ use rustc_middle::hir::nested_filter::OnlyBodies; use rustc_middle::query::Providers; use rustc_middle::ty::TyCtxt; use rustc_session::lint::builtin::UNDEFINED_NAKED_FUNCTION_ABI; -use rustc_span::Span; use rustc_span::symbol::sym; +use rustc_span::{BytePos, Span}; use rustc_target::spec::abi::Abi; use crate::errors::{ NakedAsmOutsideNakedFn, NakedFunctionsAsmBlock, NakedFunctionsAsmOptions, - NakedFunctionsMustUseNoreturn, NakedFunctionsOperands, NoPatterns, ParamsNotAllowed, + NakedFunctionsMustNakedAsm, NakedFunctionsOperands, NoPatterns, ParamsNotAllowed, UndefinedNakedFunctionAbi, }; @@ -121,21 +121,29 @@ impl<'tcx> Visitor<'tcx> for CheckParameters<'tcx> { fn check_asm<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId, body: &'tcx hir::Body<'tcx>) { let mut this = CheckInlineAssembly { tcx, items: Vec::new() }; this.visit_body(body); - if let [(ItemKind::Asm | ItemKind::Err, _)] = this.items[..] { + if let [(ItemKind::NakedAsm | ItemKind::Err, _)] = this.items[..] { // Ok. } else { let mut must_show_error = false; - let mut has_asm = false; + let mut has_naked_asm = false; let mut has_err = false; let mut multiple_asms = vec![]; let mut non_asms = vec![]; for &(kind, span) in &this.items { match kind { - ItemKind::Asm if has_asm => { + ItemKind::NakedAsm if has_naked_asm => { must_show_error = true; multiple_asms.push(span); } - ItemKind::Asm => has_asm = true, + ItemKind::NakedAsm => has_naked_asm = true, + ItemKind::InlineAsm => { + has_err = true; + + // the span that contains the `asm!` call, + // so tooling can replace it with `naked_asm!` + let macro_span = span.with_hi(span.lo() + BytePos("asm!".len() as u32)); + tcx.dcx().emit_err(NakedFunctionsMustNakedAsm { span, macro_span }); + } ItemKind::NonAsm => { must_show_error = true; non_asms.push(span); @@ -164,7 +172,8 @@ struct CheckInlineAssembly<'tcx> { #[derive(Copy, Clone)] enum ItemKind { - Asm, + NakedAsm, + InlineAsm, NonAsm, Err, } @@ -205,8 +214,18 @@ impl<'tcx> CheckInlineAssembly<'tcx> { } ExprKind::InlineAsm(asm) => { - self.items.push((ItemKind::Asm, span)); - self.check_inline_asm(asm, span); + match asm.asm_macro { + rustc_ast::AsmMacro::Asm => { + self.items.push((ItemKind::InlineAsm, span)); + } + rustc_ast::AsmMacro::NakedAsm => { + self.items.push((ItemKind::NakedAsm, span)); + self.check_inline_asm(asm, span); + } + rustc_ast::AsmMacro::GlobalAsm => { + // not allowed in this position + } + } } ExprKind::DropTemps(..) | ExprKind::Block(..) => { @@ -250,16 +269,6 @@ impl<'tcx> CheckInlineAssembly<'tcx> { .join(", "), }); } - - if !asm.options.contains(InlineAsmOptions::NORETURN) { - let last_span = asm - .operands - .last() - .map_or_else(|| asm.template_strs.last().unwrap().2, |op| op.1) - .shrink_to_hi(); - - self.tcx.dcx().emit_err(NakedFunctionsMustUseNoreturn { span, last_span }); - } } } diff --git a/library/core/src/arch.rs b/library/core/src/arch.rs index f1a0739128cdb..4945c045bc635 100644 --- a/library/core/src/arch.rs +++ b/library/core/src/arch.rs @@ -77,17 +77,3 @@ pub macro naked_asm("assembly template", $(operands,)* $(options($(option),*))?) pub macro global_asm("assembly template", $(operands,)* $(options($(option),*))?) { /* compiler built-in */ } - -/// Inline assembly used in combination with `#[naked]` functions. -/// -/// Refer to [Rust By Example] for a usage guide and the [reference] for -/// detailed information about the syntax and available options. -/// -/// [Rust By Example]: https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html -/// [reference]: https://doc.rust-lang.org/nightly/reference/inline-assembly.html -#[unstable(feature = "naked_functions", issue = "90957")] -#[rustc_builtin_macro] -#[cfg(not(bootstrap))] -pub macro naked_asm("assembly template", $(operands,)* $(options($(option),*))?) { - /* compiler built-in */ -} diff --git a/src/tools/rustfmt/src/parse/macros/asm.rs b/src/tools/rustfmt/src/parse/macros/asm.rs index 5d30171e29543..0c37d12490e2f 100644 --- a/src/tools/rustfmt/src/parse/macros/asm.rs +++ b/src/tools/rustfmt/src/parse/macros/asm.rs @@ -1,5 +1,5 @@ use rustc_ast::ast; -use rustc_builtin_macros::asm::{parse_asm_args, AsmArgs, AsmMacro}; +use rustc_builtin_macros::asm::{parse_asm_args, AsmArgs}; use crate::rewrite::RewriteContext; @@ -7,5 +7,5 @@ use crate::rewrite::RewriteContext; pub(crate) fn parse_asm(context: &RewriteContext<'_>, mac: &ast::MacCall) -> Option { let ts = mac.args.tokens.clone(); let mut parser = super::build_parser(context, ts); - parse_asm_args(&mut parser, mac.span(), AsmMacro::Asm).ok() + parse_asm_args(&mut parser, mac.span(), ast::AsmMacro::Asm).ok() } diff --git a/tests/codegen/naked-fn/aligned.rs b/tests/codegen/naked-fn/aligned.rs index d5faac44836fe..3bbd67981e5bf 100644 --- a/tests/codegen/naked-fn/aligned.rs +++ b/tests/codegen/naked-fn/aligned.rs @@ -4,7 +4,7 @@ #![crate_type = "lib"] #![feature(naked_functions, fn_align)] -use std::arch::asm; +use std::arch::naked_asm; // CHECK: Function Attrs: naked // CHECK-NEXT: define{{.*}}void @naked_empty() @@ -16,5 +16,5 @@ pub unsafe extern "C" fn naked_empty() { // CHECK-NEXT: start: // CHECK-NEXT: call void asm // CHECK-NEXT: unreachable - asm!("ret", options(noreturn)); + naked_asm!("ret"); } diff --git a/tests/codegen/naked-fn/naked-functions.rs b/tests/codegen/naked-fn/naked-functions.rs index 2b2625429f8e0..3f7447af599ab 100644 --- a/tests/codegen/naked-fn/naked-functions.rs +++ b/tests/codegen/naked-fn/naked-functions.rs @@ -14,7 +14,7 @@ pub unsafe extern "C" fn naked_empty() { // CHECK-NEXT: {{.+}}: // CHECK-NEXT: call void asm // CHECK-NEXT: unreachable - naked_asm!("ret", options(noreturn)); + naked_asm!("ret"); } // CHECK: Function Attrs: naked @@ -25,5 +25,5 @@ pub unsafe extern "C" fn naked_with_args_and_return(a: isize, b: isize) -> isize // CHECK-NEXT: {{.+}}: // CHECK-NEXT: call void asm // CHECK-NEXT: unreachable - naked_asm!("lea rax, [rdi + rsi]", "ret", options(noreturn)); + naked_asm!("lea rax, [rdi + rsi]", "ret"); } diff --git a/tests/codegen/naked-fn/naked-nocoverage.rs b/tests/codegen/naked-fn/naked-nocoverage.rs index d73c5b7fd26d1..f63661bcd3a7a 100644 --- a/tests/codegen/naked-fn/naked-nocoverage.rs +++ b/tests/codegen/naked-fn/naked-nocoverage.rs @@ -6,7 +6,7 @@ //@ compile-flags: -Cinstrument-coverage #![crate_type = "lib"] #![feature(naked_functions)] -use std::arch::asm; +use std::arch::naked_asm; #[naked] #[no_mangle] @@ -15,5 +15,5 @@ pub unsafe extern "C" fn f() { // CHECK-NEXT: start: // CHECK-NEXT: call void asm // CHECK-NEXT: unreachable - asm!("", options(noreturn)); + naked_asm!(""); } diff --git a/tests/codegen/naked-fn/naked-noinline.rs b/tests/codegen/naked-fn/naked-noinline.rs index c1e8f368249fd..6ea36d9678315 100644 --- a/tests/codegen/naked-fn/naked-noinline.rs +++ b/tests/codegen/naked-fn/naked-noinline.rs @@ -5,7 +5,7 @@ #![crate_type = "lib"] #![feature(naked_functions)] -use std::arch::asm; +use std::arch::naked_asm; #[naked] #[no_mangle] @@ -15,7 +15,7 @@ pub unsafe extern "C" fn f() { // CHECK: define {{(dso_local )?}}void @f() unnamed_addr [[ATTR:#[0-9]+]] // CHECK-NEXT: start: // CHECK-NEXT: call void asm - asm!("", options(noreturn)); + naked_asm!(""); } #[no_mangle] diff --git a/tests/ui/asm/naked-functions-ffi.rs b/tests/ui/asm/naked-functions-ffi.rs index 6b32290905d49..b78d1e6a0d1c6 100644 --- a/tests/ui/asm/naked-functions-ffi.rs +++ b/tests/ui/asm/naked-functions-ffi.rs @@ -10,6 +10,6 @@ pub extern "C" fn naked(p: char) -> u128 { //~^ WARN uses type `char` //~| WARN uses type `u128` unsafe { - naked_asm!("", options(noreturn)); + naked_asm!(""); } } diff --git a/tests/ui/asm/naked-functions-inline.rs b/tests/ui/asm/naked-functions-inline.rs index a4df38e3347c6..74049e8ecbc7c 100644 --- a/tests/ui/asm/naked-functions-inline.rs +++ b/tests/ui/asm/naked-functions-inline.rs @@ -19,7 +19,7 @@ pub unsafe extern "C" fn inline_hint() { #[naked] #[inline(always)] //~^ ERROR [E0736] -<<<<<<< HEAD +pub unsafe extern "C" fn inline_always() { naked_asm!(""); } diff --git a/tests/ui/asm/naked-functions-instruction-set.rs b/tests/ui/asm/naked-functions-instruction-set.rs index 6c6dcdf008779..37c7b52c191cd 100644 --- a/tests/ui/asm/naked-functions-instruction-set.rs +++ b/tests/ui/asm/naked-functions-instruction-set.rs @@ -19,12 +19,12 @@ trait Sized {} #[naked] #[instruction_set(arm::t32)] unsafe extern "C" fn test_thumb() { - naked_asm!("bx lr", options(noreturn)); + naked_asm!("bx lr"); } #[no_mangle] #[naked] #[instruction_set(arm::t32)] unsafe extern "C" fn test_arm() { - naked_asm!("bx lr", options(noreturn)); + naked_asm!("bx lr"); } diff --git a/tests/ui/asm/naked-functions-testattrs.rs b/tests/ui/asm/naked-functions-testattrs.rs index 2532e6e86d63a..7e373270e9fc6 100644 --- a/tests/ui/asm/naked-functions-testattrs.rs +++ b/tests/ui/asm/naked-functions-testattrs.rs @@ -12,7 +12,7 @@ use std::arch::naked_asm; #[naked] //~^ ERROR [E0736] fn test_naked() { - unsafe { naked_asm!("", options(noreturn)) }; + unsafe { naked_asm!("") }; } #[should_panic] @@ -20,7 +20,7 @@ fn test_naked() { #[naked] //~^ ERROR [E0736] fn test_naked_should_panic() { - unsafe { naked_asm!("", options(noreturn)) }; + unsafe { naked_asm!("") }; } #[ignore] @@ -28,12 +28,12 @@ fn test_naked_should_panic() { #[naked] //~^ ERROR [E0736] fn test_naked_ignore() { - unsafe { naked_asm!("", options(noreturn)) }; + unsafe { naked_asm!("") }; } #[bench] #[naked] //~^ ERROR [E0736] fn bench_naked() { - unsafe { naked_asm!("", options(noreturn)) }; + unsafe { naked_asm!("") }; } diff --git a/tests/ui/asm/naked-functions-unused.rs b/tests/ui/asm/naked-functions-unused.rs index 6d3cc0afed836..c27037819a44f 100644 --- a/tests/ui/asm/naked-functions-unused.rs +++ b/tests/ui/asm/naked-functions-unused.rs @@ -67,7 +67,7 @@ pub mod naked { #[naked] pub extern "C" fn function(a: usize, b: usize) -> usize { unsafe { - naked_asm!("", options(noreturn)); + naked_asm!(""); } } @@ -77,14 +77,14 @@ pub mod naked { #[naked] pub extern "C" fn associated(a: usize, b: usize) -> usize { unsafe { - naked_asm!("", options(noreturn)); + naked_asm!(""); } } #[naked] pub extern "C" fn method(&self, a: usize, b: usize) -> usize { unsafe { - naked_asm!("", options(noreturn)); + naked_asm!(""); } } } @@ -93,14 +93,14 @@ pub mod naked { #[naked] extern "C" fn trait_associated(a: usize, b: usize) -> usize { unsafe { - naked_asm!("", options(noreturn)); + naked_asm!(""); } } #[naked] extern "C" fn trait_method(&self, a: usize, b: usize) -> usize { unsafe { - naked_asm!("", options(noreturn)); + naked_asm!(""); } } } diff --git a/tests/ui/asm/naked-functions.rs b/tests/ui/asm/naked-functions.rs index 86c89ea1262fd..5c58f1498cc97 100644 --- a/tests/ui/asm/naked-functions.rs +++ b/tests/ui/asm/naked-functions.rs @@ -6,7 +6,13 @@ #![feature(asm_unwind, linkage)] #![crate_type = "lib"] -use std::arch::naked_asm; +use std::arch::{asm, naked_asm}; + +#[naked] +pub unsafe extern "C" fn inline_asm_macro() { + asm!("", options(raw)); + //~^ERROR the `asm!` macro is not allowed in naked functions +} #[repr(C)] pub struct P { @@ -25,12 +31,12 @@ pub unsafe extern "C" fn patterns( P { x, y }: P, //~^ ERROR patterns not allowed in naked function parameters ) { - naked_asm!("", options(noreturn)) + naked_asm!("") } #[naked] pub unsafe extern "C" fn inc(a: u32) -> u32 { - //~^ ERROR naked functions must contain a single asm block + //~^ ERROR naked functions must contain a single `naked_asm!` invocation a + 1 //~^ ERROR referencing function parameters is not allowed in naked functions } @@ -38,19 +44,19 @@ pub unsafe extern "C" fn inc(a: u32) -> u32 { #[naked] #[allow(asm_sub_register)] pub unsafe extern "C" fn inc_asm(a: u32) -> u32 { - naked_asm!("/* {0} */", in(reg) a, options(noreturn)) + naked_asm!("/* {0} */", in(reg) a) //~^ ERROR the `in` operand cannot be used with `naked_asm!` } #[naked] pub unsafe extern "C" fn inc_closure(a: u32) -> u32 { - //~^ ERROR naked functions must contain a single asm block + //~^ ERROR naked functions must contain a single `naked_asm!` invocation (|| a + 1)() } #[naked] pub unsafe extern "C" fn unsupported_operands() { - //~^ ERROR naked functions must contain a single asm block + //~^ ERROR naked functions must contain a single `naked_asm!` invocation let mut a = 0usize; let mut b = 0usize; let mut c = 0usize; @@ -72,27 +78,23 @@ pub unsafe extern "C" fn unsupported_operands() { #[naked] pub extern "C" fn missing_assembly() { - //~^ ERROR naked functions must contain a single asm block + //~^ ERROR naked functions must contain a single `naked_asm!` invocation } #[naked] pub extern "C" fn too_many_asm_blocks() { - //~^ ERROR naked functions must contain a single asm block + //~^ ERROR naked functions must contain a single `naked_asm!` invocation unsafe { - naked_asm!(""); - //~^ ERROR asm in naked functions must use `noreturn` option - naked_asm!(""); - //~^ ERROR asm in naked functions must use `noreturn` option - naked_asm!(""); - //~^ ERROR asm in naked functions must use `noreturn` option naked_asm!("", options(noreturn)); + //~^ ERROR the `noreturn` option cannot be used with `naked_asm!` + naked_asm!(""); } } pub fn outer(x: u32) -> extern "C" fn(usize) -> usize { #[naked] pub extern "C" fn inner(y: usize) -> usize { - //~^ ERROR naked functions must contain a single asm block + //~^ ERROR naked functions must contain a single `naked_asm!` invocation *&y //~^ ERROR referencing function parameters is not allowed in naked functions } @@ -101,7 +103,7 @@ pub fn outer(x: u32) -> extern "C" fn(usize) -> usize { #[naked] unsafe extern "C" fn invalid_options() { - naked_asm!("", options(nomem, preserves_flags, noreturn)); + naked_asm!("", options(nomem, preserves_flags)); //~^ ERROR the `nomem` option cannot be used with `naked_asm!` //~| ERROR the `preserves_flags` option cannot be used with `naked_asm!` } @@ -112,31 +114,30 @@ unsafe extern "C" fn invalid_options_continued() { //~^ ERROR the `readonly` option cannot be used with `naked_asm!` //~| ERROR the `nostack` option cannot be used with `naked_asm!` //~| ERROR the `pure` option cannot be used with `naked_asm!` - //~| ERROR asm in naked functions must use `noreturn` option } #[naked] unsafe extern "C" fn invalid_may_unwind() { - naked_asm!("", options(noreturn, may_unwind)); + naked_asm!("", options(may_unwind)); //~^ ERROR the `may_unwind` option cannot be used with `naked_asm!` } #[naked] pub unsafe fn default_abi() { //~^ WARN Rust ABI is unsupported in naked functions - naked_asm!("", options(noreturn)); + naked_asm!(""); } #[naked] pub unsafe fn rust_abi() { //~^ WARN Rust ABI is unsupported in naked functions - naked_asm!("", options(noreturn)); + naked_asm!(""); } #[naked] pub extern "C" fn valid_a() -> T { unsafe { - naked_asm!("", options(noreturn)); + naked_asm!(""); } } @@ -145,7 +146,7 @@ pub extern "C" fn valid_b() { unsafe { { { - naked_asm!("", options(noreturn)); + naked_asm!(""); }; }; } @@ -153,13 +154,13 @@ pub extern "C" fn valid_b() { #[naked] pub unsafe extern "C" fn valid_c() { - naked_asm!("", options(noreturn)); + naked_asm!(""); } #[cfg(target_arch = "x86_64")] #[naked] pub unsafe extern "C" fn valid_att_syntax() { - naked_asm!("", options(noreturn, att_syntax)); + naked_asm!("", options(att_syntax)); } #[naked] @@ -173,7 +174,7 @@ pub unsafe extern "C" fn allow_compile_error(a: u32) -> u32 { pub unsafe extern "C" fn allow_compile_error_and_asm(a: u32) -> u32 { compile_error!("this is a user specified error"); //~^ ERROR this is a user specified error - naked_asm!("", options(noreturn)) + naked_asm!("") } #[naked] @@ -186,7 +187,7 @@ pub unsafe extern "C" fn invalid_asm_syntax(a: u32) -> u32 { #[cfg_attr(target_pointer_width = "64", no_mangle)] #[naked] pub unsafe extern "C" fn compatible_cfg_attributes() { - naked_asm!("", options(noreturn, att_syntax)); + naked_asm!("", options(att_syntax)); } #[allow(dead_code)] @@ -195,13 +196,13 @@ pub unsafe extern "C" fn compatible_cfg_attributes() { #[forbid(dead_code)] #[naked] pub unsafe extern "C" fn compatible_diagnostic_attributes() { - naked_asm!("", options(noreturn, raw)); + naked_asm!("", options(raw)); } #[deprecated = "test"] #[naked] pub unsafe extern "C" fn compatible_deprecated_attributes() { - naked_asm!("", options(noreturn, raw)); + naked_asm!("", options(raw)); } #[cfg(target_arch = "x86_64")] @@ -213,7 +214,6 @@ pub unsafe extern "C" fn compatible_must_use_attributes() -> u64 { mov rax, 42 ret ", - options(noreturn) ) } @@ -222,20 +222,20 @@ pub unsafe extern "C" fn compatible_must_use_attributes() -> u64 { #[no_mangle] #[naked] pub unsafe extern "C" fn compatible_ffi_attributes_1() { - naked_asm!("", options(noreturn, raw)); + naked_asm!("", options(raw)); } #[cold] #[naked] pub unsafe extern "C" fn compatible_codegen_attributes() { - naked_asm!("", options(noreturn, raw)); + naked_asm!("", options(raw)); } #[cfg(target_arch = "x86_64")] #[target_feature(enable = "sse2")] #[naked] pub unsafe extern "C" fn compatible_target_feature() { - naked_asm!("", options(noreturn)); + naked_asm!(""); } #[doc = "foo bar baz"] @@ -244,11 +244,11 @@ pub unsafe extern "C" fn compatible_target_feature() { #[doc(alias = "ADocAlias")] #[naked] pub unsafe extern "C" fn compatible_doc_attributes() { - naked_asm!("", options(noreturn, raw)); + naked_asm!("", options(raw)); } #[linkage = "external"] #[naked] pub unsafe extern "C" fn compatible_linkage() { - naked_asm!("", options(noreturn, raw)); + naked_asm!("", options(raw)); } diff --git a/tests/ui/asm/naked-functions.stderr b/tests/ui/asm/naked-functions.stderr index 22c1946a960c1..1ceeafffd9091 100644 --- a/tests/ui/asm/naked-functions.stderr +++ b/tests/ui/asm/naked-functions.stderr @@ -1,220 +1,184 @@ error: the `in` operand cannot be used with `naked_asm!` - --> $DIR/naked-functions.rs:41:29 + --> $DIR/naked-functions.rs:47:29 | -LL | naked_asm!("/* {0} */", in(reg) a, options(noreturn)) +LL | naked_asm!("/* {0} */", in(reg) a) | ^^ the `in` operand is not meaningful for global-scoped inline assembly, remove it error: the `in` operand cannot be used with `naked_asm!` - --> $DIR/naked-functions.rs:62:10 + --> $DIR/naked-functions.rs:68:10 | LL | in(reg) a, | ^^ the `in` operand is not meaningful for global-scoped inline assembly, remove it +error: the `noreturn` option cannot be used with `naked_asm!` + --> $DIR/naked-functions.rs:88:32 + | +LL | naked_asm!("", options(noreturn)); + | ^^^^^^^^ the `noreturn` option is not meaningful for global-scoped inline assembly + error: the `nomem` option cannot be used with `naked_asm!` - --> $DIR/naked-functions.rs:104:28 + --> $DIR/naked-functions.rs:106:28 | -LL | naked_asm!("", options(nomem, preserves_flags, noreturn)); +LL | naked_asm!("", options(nomem, preserves_flags)); | ^^^^^ the `nomem` option is not meaningful for global-scoped inline assembly error: the `preserves_flags` option cannot be used with `naked_asm!` - --> $DIR/naked-functions.rs:104:35 + --> $DIR/naked-functions.rs:106:35 | -LL | naked_asm!("", options(nomem, preserves_flags, noreturn)); +LL | naked_asm!("", options(nomem, preserves_flags)); | ^^^^^^^^^^^^^^^ the `preserves_flags` option is not meaningful for global-scoped inline assembly error: the `readonly` option cannot be used with `naked_asm!` - --> $DIR/naked-functions.rs:111:28 + --> $DIR/naked-functions.rs:113:28 | LL | naked_asm!("", options(readonly, nostack), options(pure)); | ^^^^^^^^ the `readonly` option is not meaningful for global-scoped inline assembly error: the `nostack` option cannot be used with `naked_asm!` - --> $DIR/naked-functions.rs:111:38 + --> $DIR/naked-functions.rs:113:38 | LL | naked_asm!("", options(readonly, nostack), options(pure)); | ^^^^^^^ the `nostack` option is not meaningful for global-scoped inline assembly error: the `pure` option cannot be used with `naked_asm!` - --> $DIR/naked-functions.rs:111:56 + --> $DIR/naked-functions.rs:113:56 | LL | naked_asm!("", options(readonly, nostack), options(pure)); | ^^^^ the `pure` option is not meaningful for global-scoped inline assembly error: the `may_unwind` option cannot be used with `naked_asm!` - --> $DIR/naked-functions.rs:120:38 + --> $DIR/naked-functions.rs:121:28 | -LL | naked_asm!("", options(noreturn, may_unwind)); - | ^^^^^^^^^^ the `may_unwind` option is not meaningful for global-scoped inline assembly +LL | naked_asm!("", options(may_unwind)); + | ^^^^^^^^^^ the `may_unwind` option is not meaningful for global-scoped inline assembly error: this is a user specified error - --> $DIR/naked-functions.rs:168:5 + --> $DIR/naked-functions.rs:169:5 | LL | compile_error!("this is a user specified error") | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: this is a user specified error - --> $DIR/naked-functions.rs:174:5 + --> $DIR/naked-functions.rs:175:5 | LL | compile_error!("this is a user specified error"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: asm template must be a string literal - --> $DIR/naked-functions.rs:181:16 + --> $DIR/naked-functions.rs:182:16 | LL | naked_asm!(invalid_syntax) | ^^^^^^^^^^^^^^ +error[E0787]: the `asm!` macro is not allowed in naked functions + --> $DIR/naked-functions.rs:13:5 + | +LL | asm!("", options(raw)); + | ----^^^^^^^^^^^^^^^^^^ + | | + | help: consider using the `naked_asm!` macro instead: `naked_asm!` + error: patterns not allowed in naked function parameters - --> $DIR/naked-functions.rs:19:5 + --> $DIR/naked-functions.rs:25:5 | LL | mut a: u32, | ^^^^^ error: patterns not allowed in naked function parameters - --> $DIR/naked-functions.rs:21:5 + --> $DIR/naked-functions.rs:27:5 | LL | &b: &i32, | ^^ error: patterns not allowed in naked function parameters - --> $DIR/naked-functions.rs:23:6 + --> $DIR/naked-functions.rs:29:6 | LL | (None | Some(_)): Option>, | ^^^^^^^^^^^^^^ error: patterns not allowed in naked function parameters - --> $DIR/naked-functions.rs:25:5 + --> $DIR/naked-functions.rs:31:5 | LL | P { x, y }: P, | ^^^^^^^^^^ error: referencing function parameters is not allowed in naked functions - --> $DIR/naked-functions.rs:34:5 + --> $DIR/naked-functions.rs:40:5 | LL | a + 1 | ^ | = help: follow the calling convention in asm block to use parameters -error[E0787]: naked functions must contain a single asm block - --> $DIR/naked-functions.rs:32:1 +error[E0787]: naked functions must contain a single `naked_asm!` invocation + --> $DIR/naked-functions.rs:38:1 | LL | pub unsafe extern "C" fn inc(a: u32) -> u32 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ LL | LL | a + 1 - | ----- non-asm is unsupported in naked functions + | ----- not allowed in naked functions -error[E0787]: naked functions must contain a single asm block - --> $DIR/naked-functions.rs:46:1 +error[E0787]: naked functions must contain a single `naked_asm!` invocation + --> $DIR/naked-functions.rs:52:1 | LL | pub unsafe extern "C" fn inc_closure(a: u32) -> u32 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ LL | LL | (|| a + 1)() - | ------------ non-asm is unsupported in naked functions + | ------------ not allowed in naked functions -error[E0787]: naked functions must contain a single asm block - --> $DIR/naked-functions.rs:52:1 +error[E0787]: naked functions must contain a single `naked_asm!` invocation + --> $DIR/naked-functions.rs:58:1 | LL | pub unsafe extern "C" fn unsupported_operands() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ LL | LL | let mut a = 0usize; - | ------------------- non-asm is unsupported in naked functions + | ------------------- not allowed in naked functions LL | let mut b = 0usize; - | ------------------- non-asm is unsupported in naked functions + | ------------------- not allowed in naked functions LL | let mut c = 0usize; - | ------------------- non-asm is unsupported in naked functions + | ------------------- not allowed in naked functions LL | let mut d = 0usize; - | ------------------- non-asm is unsupported in naked functions + | ------------------- not allowed in naked functions LL | let mut e = 0usize; - | ------------------- non-asm is unsupported in naked functions + | ------------------- not allowed in naked functions -error[E0787]: naked functions must contain a single asm block - --> $DIR/naked-functions.rs:74:1 +error[E0787]: naked functions must contain a single `naked_asm!` invocation + --> $DIR/naked-functions.rs:80:1 | LL | pub extern "C" fn missing_assembly() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error[E0787]: asm in naked functions must use `noreturn` option - --> $DIR/naked-functions.rs:82:9 - | -LL | naked_asm!(""); - | ^^^^^^^^^^^^^^ - | -help: consider specifying that the asm block is responsible for returning from the function - | -LL | naked_asm!("", options(noreturn)); - | +++++++++++++++++++ - -error[E0787]: asm in naked functions must use `noreturn` option - --> $DIR/naked-functions.rs:84:9 - | -LL | naked_asm!(""); - | ^^^^^^^^^^^^^^ - | -help: consider specifying that the asm block is responsible for returning from the function - | -LL | naked_asm!("", options(noreturn)); - | +++++++++++++++++++ - -error[E0787]: asm in naked functions must use `noreturn` option - --> $DIR/naked-functions.rs:86:9 - | -LL | naked_asm!(""); - | ^^^^^^^^^^^^^^ - | -help: consider specifying that the asm block is responsible for returning from the function - | -LL | naked_asm!("", options(noreturn)); - | +++++++++++++++++++ - -error[E0787]: naked functions must contain a single asm block - --> $DIR/naked-functions.rs:79:1 +error[E0787]: naked functions must contain a single `naked_asm!` invocation + --> $DIR/naked-functions.rs:85:1 | LL | pub extern "C" fn too_many_asm_blocks() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ... LL | naked_asm!(""); - | -------------- multiple asm blocks are unsupported in naked functions -LL | -LL | naked_asm!(""); - | -------------- multiple asm blocks are unsupported in naked functions -LL | -LL | naked_asm!("", options(noreturn)); - | --------------------------------- multiple asm blocks are unsupported in naked functions + | -------------- multiple `naked_asm!` invocations are not allowed in naked functions error: referencing function parameters is not allowed in naked functions - --> $DIR/naked-functions.rs:96:11 + --> $DIR/naked-functions.rs:98:11 | LL | *&y | ^ | = help: follow the calling convention in asm block to use parameters -error[E0787]: naked functions must contain a single asm block - --> $DIR/naked-functions.rs:94:5 +error[E0787]: naked functions must contain a single `naked_asm!` invocation + --> $DIR/naked-functions.rs:96:5 | LL | pub extern "C" fn inner(y: usize) -> usize { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ LL | LL | *&y - | --- non-asm is unsupported in naked functions - -error[E0787]: asm in naked functions must use `noreturn` option - --> $DIR/naked-functions.rs:111:5 - | -LL | naked_asm!("", options(readonly, nostack), options(pure)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | -help: consider specifying that the asm block is responsible for returning from the function - | -LL | naked_asm!("", options(noreturn), options(readonly, nostack), options(pure)); - | +++++++++++++++++++ + | --- not allowed in naked functions warning: Rust ABI is unsupported in naked functions - --> $DIR/naked-functions.rs:125:1 + --> $DIR/naked-functions.rs:126:1 | LL | pub unsafe fn default_abi() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -222,11 +186,11 @@ LL | pub unsafe fn default_abi() { = note: `#[warn(undefined_naked_function_abi)]` on by default warning: Rust ABI is unsupported in naked functions - --> $DIR/naked-functions.rs:131:1 + --> $DIR/naked-functions.rs:132:1 | LL | pub unsafe fn rust_abi() { | ^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 27 previous errors; 2 warnings emitted +error: aborting due to 25 previous errors; 2 warnings emitted For more information about this error, try `rustc --explain E0787`. diff --git a/tests/ui/asm/naked-invalid-attr.rs b/tests/ui/asm/naked-invalid-attr.rs index 57edd57de998e..4053c58fb5136 100644 --- a/tests/ui/asm/naked-invalid-attr.rs +++ b/tests/ui/asm/naked-invalid-attr.rs @@ -4,7 +4,7 @@ #![feature(naked_functions)] #![naked] //~ ERROR should be applied to a function definition -use std::arch::asm; +use std::arch::naked_asm; extern "C" { #[naked] //~ ERROR should be applied to a function definition @@ -26,27 +26,28 @@ trait Invoke { impl Invoke for S { #[naked] extern "C" fn invoke(&self) { - unsafe { asm!("", options(noreturn)) } + unsafe { naked_asm!("") } } } #[naked] extern "C" fn ok() { - unsafe { asm!("", options(noreturn)) } + unsafe { naked_asm!("") } } impl S { #[naked] extern "C" fn g() { - unsafe { asm!("", options(noreturn)) } + unsafe { naked_asm!("") } } #[naked] extern "C" fn h(&self) { - unsafe { asm!("", options(noreturn)) } + unsafe { naked_asm!("") } } } fn main() { - #[naked] || {}; //~ ERROR should be applied to a function definition + #[naked] //~ ERROR should be applied to a function definition + || {}; } diff --git a/tests/ui/asm/naked-invalid-attr.stderr b/tests/ui/asm/naked-invalid-attr.stderr index e8ddccc854abe..640f9d9510d15 100644 --- a/tests/ui/asm/naked-invalid-attr.stderr +++ b/tests/ui/asm/naked-invalid-attr.stderr @@ -13,8 +13,10 @@ LL | | } error: attribute should be applied to a function definition --> $DIR/naked-invalid-attr.rs:51:5 | -LL | #[naked] || {}; - | ^^^^^^^^ ----- not a function definition +LL | #[naked] + | ^^^^^^^^ +LL | || {}; + | ----- not a function definition error: attribute should be applied to a function definition --> $DIR/naked-invalid-attr.rs:22:5 diff --git a/tests/ui/asm/naked-with-invalid-repr-attr.rs b/tests/ui/asm/naked-with-invalid-repr-attr.rs index 687fe1ad73db1..18b9c1014c3fa 100644 --- a/tests/ui/asm/naked-with-invalid-repr-attr.rs +++ b/tests/ui/asm/naked-with-invalid-repr-attr.rs @@ -2,14 +2,14 @@ #![feature(naked_functions)] #![feature(fn_align)] #![crate_type = "lib"] -use std::arch::asm; +use std::arch::naked_asm; #[repr(C)] //~^ ERROR attribute should be applied to a struct, enum, or union [E0517] #[naked] extern "C" fn example1() { //~^ NOTE not a struct, enum, or union - unsafe { asm!("", options(noreturn)) } + unsafe { naked_asm!("") } } #[repr(transparent)] @@ -17,7 +17,7 @@ extern "C" fn example1() { #[naked] extern "C" fn example2() { //~^ NOTE not a struct, enum, or union - unsafe { asm!("", options(noreturn)) } + unsafe { naked_asm!("") } } #[repr(align(16), C)] @@ -25,7 +25,7 @@ extern "C" fn example2() { #[naked] extern "C" fn example3() { //~^ NOTE not a struct, enum, or union - unsafe { asm!("", options(noreturn)) } + unsafe { naked_asm!("") } } // note: two errors because of packed and C @@ -36,7 +36,7 @@ extern "C" fn example3() { extern "C" fn example4() { //~^ NOTE not a struct, enum, or union //~| NOTE not a struct or union - unsafe { asm!("", options(noreturn)) } + unsafe { naked_asm!("") } } #[repr(u8)] @@ -44,5 +44,5 @@ extern "C" fn example4() { #[naked] extern "C" fn example5() { //~^ NOTE not an enum - unsafe { asm!("", options(noreturn)) } + unsafe { naked_asm!("") } } diff --git a/tests/ui/asm/naked-with-invalid-repr-attr.stderr b/tests/ui/asm/naked-with-invalid-repr-attr.stderr index 3740f17a9dc32..8248a8c165791 100644 --- a/tests/ui/asm/naked-with-invalid-repr-attr.stderr +++ b/tests/ui/asm/naked-with-invalid-repr-attr.stderr @@ -6,7 +6,7 @@ LL | #[repr(C)] ... LL | / extern "C" fn example1() { LL | | -LL | | unsafe { asm!("", options(noreturn)) } +LL | | unsafe { naked_asm!("") } LL | | } | |_- not a struct, enum, or union @@ -18,7 +18,7 @@ LL | #[repr(transparent)] ... LL | / extern "C" fn example2() { LL | | -LL | | unsafe { asm!("", options(noreturn)) } +LL | | unsafe { naked_asm!("") } LL | | } | |_- not a struct, enum, or union @@ -30,7 +30,7 @@ LL | #[repr(align(16), C)] ... LL | / extern "C" fn example3() { LL | | -LL | | unsafe { asm!("", options(noreturn)) } +LL | | unsafe { naked_asm!("") } LL | | } | |_- not a struct, enum, or union @@ -43,7 +43,7 @@ LL | #[repr(C, packed)] LL | / extern "C" fn example4() { LL | | LL | | -LL | | unsafe { asm!("", options(noreturn)) } +LL | | unsafe { naked_asm!("") } LL | | } | |_- not a struct, enum, or union @@ -56,7 +56,7 @@ LL | #[repr(C, packed)] LL | / extern "C" fn example4() { LL | | LL | | -LL | | unsafe { asm!("", options(noreturn)) } +LL | | unsafe { naked_asm!("") } LL | | } | |_- not a struct or union @@ -68,7 +68,7 @@ LL | #[repr(u8)] ... LL | / extern "C" fn example5() { LL | | -LL | | unsafe { asm!("", options(noreturn)) } +LL | | unsafe { naked_asm!("") } LL | | } | |_- not an enum diff --git a/tests/ui/asm/named-asm-labels.rs b/tests/ui/asm/named-asm-labels.rs index 043aab9029d7d..77831e679ed42 100644 --- a/tests/ui/asm/named-asm-labels.rs +++ b/tests/ui/asm/named-asm-labels.rs @@ -12,7 +12,7 @@ #![feature(naked_functions)] -use std::arch::{asm, global_asm}; +use std::arch::{asm, global_asm, naked_asm}; #[no_mangle] pub static FOO: usize = 42; @@ -177,7 +177,7 @@ fn main() { // label or LTO can cause labels to break #[naked] pub extern "C" fn foo() -> i32 { - unsafe { asm!(".Lfoo: mov rax, {}; ret;", "nop", const 1, options(noreturn)) } + unsafe { naked_asm!(".Lfoo: mov rax, {}; ret;", "nop", const 1) } //~^ ERROR avoid using named labels } @@ -192,7 +192,7 @@ pub extern "C" fn bar() { pub extern "C" fn aaa() { fn _local() {} - unsafe { asm!(".Laaa: nop; ret;", options(noreturn)) } //~ ERROR avoid using named labels + unsafe { naked_asm!(".Laaa: nop; ret;") } //~ ERROR avoid using named labels } pub fn normal() { @@ -202,7 +202,7 @@ pub fn normal() { pub extern "C" fn bbb() { fn _very_local() {} - unsafe { asm!(".Lbbb: nop; ret;", options(noreturn)) } //~ ERROR avoid using named labels + unsafe { naked_asm!(".Lbbb: nop; ret;") } //~ ERROR avoid using named labels } fn _local2() {} @@ -221,7 +221,7 @@ fn closures() { || { #[naked] unsafe extern "C" fn _nested() { - asm!("ret;", options(noreturn)); + naked_asm!("ret;"); } unsafe { diff --git a/tests/ui/asm/named-asm-labels.stderr b/tests/ui/asm/named-asm-labels.stderr index e5e177fb8b83e..44ce358c62bdb 100644 --- a/tests/ui/asm/named-asm-labels.stderr +++ b/tests/ui/asm/named-asm-labels.stderr @@ -475,10 +475,10 @@ LL | #[warn(named_asm_labels)] | ^^^^^^^^^^^^^^^^ error: avoid using named labels in inline assembly - --> $DIR/named-asm-labels.rs:180:20 + --> $DIR/named-asm-labels.rs:180:26 | -LL | unsafe { asm!(".Lfoo: mov rax, {}; ret;", "nop", const 1, options(noreturn)) } - | ^^^^^ +LL | unsafe { naked_asm!(".Lfoo: mov rax, {}; ret;", "nop", const 1) } + | ^^^^^ | = help: only local labels of the form `:` should be used in inline asm = note: see the asm section of Rust By Example for more information @@ -493,19 +493,19 @@ LL | unsafe { asm!(".Lbar: mov rax, {}; ret;", "nop", const 1, options(noret = note: see the asm section of Rust By Example for more information error: avoid using named labels in inline assembly - --> $DIR/named-asm-labels.rs:195:20 + --> $DIR/named-asm-labels.rs:195:26 | -LL | unsafe { asm!(".Laaa: nop; ret;", options(noreturn)) } - | ^^^^^ +LL | unsafe { naked_asm!(".Laaa: nop; ret;") } + | ^^^^^ | = help: only local labels of the form `:` should be used in inline asm = note: see the asm section of Rust By Example for more information error: avoid using named labels in inline assembly - --> $DIR/named-asm-labels.rs:205:24 + --> $DIR/named-asm-labels.rs:205:30 | -LL | unsafe { asm!(".Lbbb: nop; ret;", options(noreturn)) } - | ^^^^^ +LL | unsafe { naked_asm!(".Lbbb: nop; ret;") } + | ^^^^^ | = help: only local labels of the form `:` should be used in inline asm = note: see the asm section of Rust By Example for more information diff --git a/tests/ui/feature-gates/feature-gate-naked_functions.rs b/tests/ui/feature-gates/feature-gate-naked_functions.rs index c8802ea4c31f2..5fe0bbdc77435 100644 --- a/tests/ui/feature-gates/feature-gate-naked_functions.rs +++ b/tests/ui/feature-gates/feature-gate-naked_functions.rs @@ -6,7 +6,7 @@ use std::arch::naked_asm; #[naked] //~^ the `#[naked]` attribute is an experimental feature extern "C" fn naked() { - naked_asm!("", options(noreturn)) + naked_asm!("") //~^ ERROR use of unstable library feature 'naked_functions' //~| ERROR: requires unsafe } @@ -14,7 +14,7 @@ extern "C" fn naked() { #[naked] //~^ the `#[naked]` attribute is an experimental feature extern "C" fn naked_2() -> isize { - naked_asm!("", options(noreturn)) + naked_asm!("") //~^ ERROR use of unstable library feature 'naked_functions' //~| ERROR: requires unsafe } From bc0a9543a3e8843a908d3e256e70b75441ef2743 Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Thu, 5 Sep 2024 17:48:13 +0200 Subject: [PATCH 1943/2194] more `asm!` -> `naked_asm!` in tests --- tests/assembly/aarch64-naked-fn-no-bti-prolog.rs | 4 ++-- tests/assembly/x86_64-naked-fn-no-cet-prolog.rs | 4 ++-- tests/codegen/cffi/c-variadic-naked.rs | 3 +-- tests/crashes/124375.rs | 4 ++-- .../run-make/naked-symbol-visibility/a_rust_dylib.rs | 12 ++++++------ .../feature-gate-naked_functions.stderr | 12 ++++++------ .../rfcs/rfc-2091-track-caller/error-with-naked.rs | 6 +++--- 7 files changed, 22 insertions(+), 23 deletions(-) diff --git a/tests/assembly/aarch64-naked-fn-no-bti-prolog.rs b/tests/assembly/aarch64-naked-fn-no-bti-prolog.rs index 8ee6f6792e943..46e627eaa00bd 100644 --- a/tests/assembly/aarch64-naked-fn-no-bti-prolog.rs +++ b/tests/assembly/aarch64-naked-fn-no-bti-prolog.rs @@ -5,7 +5,7 @@ #![crate_type = "lib"] #![feature(naked_functions)] -use std::arch::asm; +use std::arch::naked_asm; // The problem at hand: Rust has adopted a fairly strict meaning for "naked functions", // meaning "no prologue whatsoever, no, really, not one instruction." @@ -17,5 +17,5 @@ use std::arch::asm; pub unsafe extern "C" fn _hlt() -> ! { // CHECK-NOT: hint #34 // CHECK: hlt #0x1 - asm!("hlt #1", options(noreturn)) + naked_asm!("hlt #1") } diff --git a/tests/assembly/x86_64-naked-fn-no-cet-prolog.rs b/tests/assembly/x86_64-naked-fn-no-cet-prolog.rs index a568387418211..54e1d93c68bd6 100644 --- a/tests/assembly/x86_64-naked-fn-no-cet-prolog.rs +++ b/tests/assembly/x86_64-naked-fn-no-cet-prolog.rs @@ -5,7 +5,7 @@ #![crate_type = "lib"] #![feature(naked_functions)] -use std::arch::asm; +use std::arch::naked_asm; // The problem at hand: Rust has adopted a fairly strict meaning for "naked functions", // meaning "no prologue whatsoever, no, really, not one instruction." @@ -17,7 +17,7 @@ use std::arch::asm; pub unsafe extern "sysv64" fn will_halt() -> ! { // CHECK-NOT: endbr{{32|64}} // CHECK: hlt - asm!("hlt", options(noreturn)) + naked_asm!("hlt") } // what about aarch64? diff --git a/tests/codegen/cffi/c-variadic-naked.rs b/tests/codegen/cffi/c-variadic-naked.rs index 807873ea3689f..24b69c5f59e21 100644 --- a/tests/codegen/cffi/c-variadic-naked.rs +++ b/tests/codegen/cffi/c-variadic-naked.rs @@ -12,8 +12,7 @@ pub unsafe extern "C" fn c_variadic(_: usize, _: ...) { // CHECK-NOT: va_start // CHECK-NOT: alloca - core::arch::asm! { + core::arch::naked_asm! { "ret", - options(noreturn), } } diff --git a/tests/crashes/124375.rs b/tests/crashes/124375.rs index 7165655178d7d..1d877caeb8bc1 100644 --- a/tests/crashes/124375.rs +++ b/tests/crashes/124375.rs @@ -3,9 +3,9 @@ //@ only-x86_64 #![crate_type = "lib"] #![feature(naked_functions)] -use std::arch::asm; +use std::arch::naked_asm; #[naked] pub unsafe extern "C" fn naked_with_args_and_return(a: isize, b: isize) -> isize { - asm!("lea rax, [rdi + rsi]", "ret", options(noreturn)); + naked_asm!("lea rax, [rdi + rsi]", "ret"); } diff --git a/tests/run-make/naked-symbol-visibility/a_rust_dylib.rs b/tests/run-make/naked-symbol-visibility/a_rust_dylib.rs index f00123f006b24..517c8da656ad0 100644 --- a/tests/run-make/naked-symbol-visibility/a_rust_dylib.rs +++ b/tests/run-make/naked-symbol-visibility/a_rust_dylib.rs @@ -1,7 +1,7 @@ #![feature(naked_functions, asm_const, linkage)] #![crate_type = "dylib"] -use std::arch::asm; +use std::arch::naked_asm; pub trait TraitWithConst { const COUNT: u32; @@ -28,7 +28,7 @@ extern "C" fn private_vanilla() -> u32 { #[naked] extern "C" fn private_naked() -> u32 { - unsafe { asm!("mov rax, 42", "ret", options(noreturn)) } + unsafe { naked_asm!("mov rax, 42", "ret") } } #[no_mangle] @@ -39,7 +39,7 @@ pub extern "C" fn public_vanilla() -> u32 { #[naked] #[no_mangle] pub extern "C" fn public_naked() -> u32 { - unsafe { asm!("mov rax, 42", "ret", options(noreturn)) } + unsafe { naked_asm!("mov rax, 42", "ret") } } pub extern "C" fn public_vanilla_generic() -> u32 { @@ -48,7 +48,7 @@ pub extern "C" fn public_vanilla_generic() -> u32 { #[naked] pub extern "C" fn public_naked_generic() -> u32 { - unsafe { asm!("mov rax, {}", "ret", const T::COUNT, options(noreturn)) } + unsafe { naked_asm!("mov rax, {}", "ret", const T::COUNT) } } #[linkage = "external"] @@ -59,7 +59,7 @@ extern "C" fn vanilla_external_linkage() -> u32 { #[naked] #[linkage = "external"] extern "C" fn naked_external_linkage() -> u32 { - unsafe { asm!("mov rax, 42", "ret", options(noreturn)) } + unsafe { naked_asm!("mov rax, 42", "ret") } } #[cfg(not(windows))] @@ -72,7 +72,7 @@ extern "C" fn vanilla_weak_linkage() -> u32 { #[cfg(not(windows))] #[linkage = "weak"] extern "C" fn naked_weak_linkage() -> u32 { - unsafe { asm!("mov rax, 42", "ret", options(noreturn)) } + unsafe { naked_asm!("mov rax, 42", "ret", options(noreturn)) } } // functions that are declared in an `extern "C"` block are currently not exported diff --git a/tests/ui/feature-gates/feature-gate-naked_functions.stderr b/tests/ui/feature-gates/feature-gate-naked_functions.stderr index 5fecc218a1622..709234eb02372 100644 --- a/tests/ui/feature-gates/feature-gate-naked_functions.stderr +++ b/tests/ui/feature-gates/feature-gate-naked_functions.stderr @@ -1,7 +1,7 @@ error[E0658]: use of unstable library feature 'naked_functions' --> $DIR/feature-gate-naked_functions.rs:9:5 | -LL | naked_asm!("", options(noreturn)) +LL | naked_asm!("") | ^^^^^^^^^ | = note: see issue #90957 for more information @@ -11,7 +11,7 @@ LL | naked_asm!("", options(noreturn)) error[E0658]: use of unstable library feature 'naked_functions' --> $DIR/feature-gate-naked_functions.rs:17:5 | -LL | naked_asm!("", options(noreturn)) +LL | naked_asm!("") | ^^^^^^^^^ | = note: see issue #90957 for more information @@ -51,16 +51,16 @@ LL | use std::arch::naked_asm; error[E0133]: use of inline assembly is unsafe and requires unsafe function or block --> $DIR/feature-gate-naked_functions.rs:9:5 | -LL | naked_asm!("", options(noreturn)) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ use of inline assembly +LL | naked_asm!("") + | ^^^^^^^^^^^^^^ use of inline assembly | = note: inline assembly is entirely unchecked and can cause undefined behavior error[E0133]: use of inline assembly is unsafe and requires unsafe function or block --> $DIR/feature-gate-naked_functions.rs:17:5 | -LL | naked_asm!("", options(noreturn)) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ use of inline assembly +LL | naked_asm!("") + | ^^^^^^^^^^^^^^ use of inline assembly | = note: inline assembly is entirely unchecked and can cause undefined behavior diff --git a/tests/ui/rfcs/rfc-2091-track-caller/error-with-naked.rs b/tests/ui/rfcs/rfc-2091-track-caller/error-with-naked.rs index 0c73b9abf351d..0e85515fd104a 100644 --- a/tests/ui/rfcs/rfc-2091-track-caller/error-with-naked.rs +++ b/tests/ui/rfcs/rfc-2091-track-caller/error-with-naked.rs @@ -1,14 +1,14 @@ //@ needs-asm-support #![feature(naked_functions)] -use std::arch::asm; +use std::arch::naked_asm; #[track_caller] //~ ERROR [E0736] //~^ ERROR `#[track_caller]` requires Rust ABI #[naked] extern "C" fn f() { unsafe { - asm!("", options(noreturn)); + naked_asm!(""); } } @@ -20,7 +20,7 @@ impl S { #[naked] extern "C" fn g() { unsafe { - asm!("", options(noreturn)); + naked_asm!(""); } } } From 10fa482906ab1f2fba07b32b70457ad9444e8f63 Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Thu, 5 Sep 2024 18:56:38 +0200 Subject: [PATCH 1944/2194] remove checks that are now performed during macro expansion of `naked_asm!` --- compiler/rustc_passes/messages.ftl | 6 --- compiler/rustc_passes/src/errors.rs | 15 ------ compiler/rustc_passes/src/naked_functions.rs | 53 +++----------------- 3 files changed, 8 insertions(+), 66 deletions(-) diff --git a/compiler/rustc_passes/messages.ftl b/compiler/rustc_passes/messages.ftl index 1b1d1b1fb72ed..414a9c6e3b964 100644 --- a/compiler/rustc_passes/messages.ftl +++ b/compiler/rustc_passes/messages.ftl @@ -492,9 +492,6 @@ passes_naked_functions_asm_block = .label_multiple_asm = multiple `naked_asm!` invocations are not allowed in naked functions .label_non_asm = not allowed in naked functions -passes_naked_functions_asm_options = - asm options unsupported in naked functions: {$unsupported_options} - passes_naked_functions_incompatible_attribute = attribute incompatible with `#[naked]` .label = the `{$attr}` attribute is incompatible with `#[naked]` @@ -504,9 +501,6 @@ passes_naked_functions_must_naked_asm = the `asm!` macro is not allowed in naked functions .suggestion = consider using the `naked_asm!` macro instead -passes_naked_functions_operands = - only `const` and `sym` operands are supported in naked functions - passes_no_link = attribute should be applied to an `extern crate` item .label = not an `extern crate` item diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs index c46768ace53ab..fb47137702252 100644 --- a/compiler/rustc_passes/src/errors.rs +++ b/compiler/rustc_passes/src/errors.rs @@ -1186,21 +1186,6 @@ impl Diagnostic<'_, G> for NakedFunctionsAsmBlock { } } -#[derive(Diagnostic)] -#[diag(passes_naked_functions_operands, code = E0787)] -pub(crate) struct NakedFunctionsOperands { - #[primary_span] - pub unsupported_operands: Vec, -} - -#[derive(Diagnostic)] -#[diag(passes_naked_functions_asm_options, code = E0787)] -pub(crate) struct NakedFunctionsAsmOptions { - #[primary_span] - pub span: Span, - pub unsupported_options: String, -} - #[derive(Diagnostic)] #[diag(passes_naked_functions_must_naked_asm, code = E0787)] pub(crate) struct NakedFunctionsMustNakedAsm { diff --git a/compiler/rustc_passes/src/naked_functions.rs b/compiler/rustc_passes/src/naked_functions.rs index 6046c7284304e..fa4971cd2cc7f 100644 --- a/compiler/rustc_passes/src/naked_functions.rs +++ b/compiler/rustc_passes/src/naked_functions.rs @@ -1,11 +1,10 @@ //! Checks validity of naked functions. -use rustc_ast::InlineAsmOptions; use rustc_hir as hir; use rustc_hir::def::DefKind; use rustc_hir::def_id::{LocalDefId, LocalModDefId}; use rustc_hir::intravisit::Visitor; -use rustc_hir::{ExprKind, HirIdSet, InlineAsmOperand, StmtKind}; +use rustc_hir::{ExprKind, HirIdSet, StmtKind}; use rustc_middle::hir::nested_filter::OnlyBodies; use rustc_middle::query::Providers; use rustc_middle::ty::TyCtxt; @@ -15,9 +14,8 @@ use rustc_span::{BytePos, Span}; use rustc_target::spec::abi::Abi; use crate::errors::{ - NakedAsmOutsideNakedFn, NakedFunctionsAsmBlock, NakedFunctionsAsmOptions, - NakedFunctionsMustNakedAsm, NakedFunctionsOperands, NoPatterns, ParamsNotAllowed, - UndefinedNakedFunctionAbi, + NakedAsmOutsideNakedFn, NakedFunctionsAsmBlock, NakedFunctionsMustNakedAsm, NoPatterns, + ParamsNotAllowed, UndefinedNakedFunctionAbi, }; pub(crate) fn provide(providers: &mut Providers) { @@ -119,7 +117,7 @@ impl<'tcx> Visitor<'tcx> for CheckParameters<'tcx> { /// Checks that function body contains a single inline assembly block. fn check_asm<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId, body: &'tcx hir::Body<'tcx>) { - let mut this = CheckInlineAssembly { tcx, items: Vec::new() }; + let mut this = CheckInlineAssembly { items: Vec::new() }; this.visit_body(body); if let [(ItemKind::NakedAsm | ItemKind::Err, _)] = this.items[..] { // Ok. @@ -165,8 +163,7 @@ fn check_asm<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId, body: &'tcx hir::Body< } } -struct CheckInlineAssembly<'tcx> { - tcx: TyCtxt<'tcx>, +struct CheckInlineAssembly { items: Vec<(ItemKind, Span)>, } @@ -178,8 +175,8 @@ enum ItemKind { Err, } -impl<'tcx> CheckInlineAssembly<'tcx> { - fn check_expr(&mut self, expr: &'tcx hir::Expr<'tcx>, span: Span) { +impl CheckInlineAssembly { + fn check_expr<'tcx>(&mut self, expr: &'tcx hir::Expr<'tcx>, span: Span) { match expr.kind { ExprKind::ConstBlock(..) | ExprKind::Array(..) @@ -220,7 +217,6 @@ impl<'tcx> CheckInlineAssembly<'tcx> { } rustc_ast::AsmMacro::NakedAsm => { self.items.push((ItemKind::NakedAsm, span)); - self.check_inline_asm(asm, span); } rustc_ast::AsmMacro::GlobalAsm => { // not allowed in this position @@ -237,42 +233,9 @@ impl<'tcx> CheckInlineAssembly<'tcx> { } } } - - fn check_inline_asm(&self, asm: &'tcx hir::InlineAsm<'tcx>, span: Span) { - let unsupported_operands: Vec = asm - .operands - .iter() - .filter_map(|&(ref op, op_sp)| match op { - InlineAsmOperand::Const { .. } - | InlineAsmOperand::SymFn { .. } - | InlineAsmOperand::SymStatic { .. } => None, - InlineAsmOperand::In { .. } - | InlineAsmOperand::Out { .. } - | InlineAsmOperand::InOut { .. } - | InlineAsmOperand::SplitInOut { .. } - | InlineAsmOperand::Label { .. } => Some(op_sp), - }) - .collect(); - if !unsupported_operands.is_empty() { - self.tcx.dcx().emit_err(NakedFunctionsOperands { unsupported_operands }); - } - - let unsupported_options = asm.options.difference(InlineAsmOptions::NAKED_OPTIONS); - if !unsupported_options.is_empty() { - self.tcx.dcx().emit_err(NakedFunctionsAsmOptions { - span, - unsupported_options: unsupported_options - .human_readable_names() - .into_iter() - .map(|name| format!("`{name}`")) - .collect::>() - .join(", "), - }); - } - } } -impl<'tcx> Visitor<'tcx> for CheckInlineAssembly<'tcx> { +impl<'tcx> Visitor<'tcx> for CheckInlineAssembly { fn visit_stmt(&mut self, stmt: &'tcx hir::Stmt<'tcx>) { match stmt.kind { StmtKind::Item(..) => {} From 5fc60d1e52ea12f53d2c8d22fee94592860739ad Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Thu, 5 Sep 2024 19:45:40 +0200 Subject: [PATCH 1945/2194] various fixes for `naked_asm!` implementation - fix for divergence - fix error message - fix another cranelift test - fix some cranelift things - don't set the NORETURN option for naked asm - fix use of naked_asm! in doc comment - fix use of naked_asm! in run-make test - use `span_bug` in unreachable branch --- compiler/rustc_ast/src/ast.rs | 12 ++++++-- compiler/rustc_borrowck/src/lib.rs | 1 + .../src/polonius/loan_invalidations.rs | 1 + compiler/rustc_builtin_macros/src/asm.rs | 23 +++++--------- .../example/mini_core.rs | 6 ++++ .../example/mini_core_hello_world.rs | 2 +- compiler/rustc_codegen_cranelift/src/base.rs | 3 ++ compiler/rustc_codegen_ssa/src/mir/block.rs | 13 ++++---- .../rustc_const_eval/src/interpret/machine.rs | 2 +- compiler/rustc_hir_typeck/src/expr.rs | 6 +--- compiler/rustc_lint_defs/src/builtin.rs | 6 ++-- compiler/rustc_middle/src/mir/pretty.rs | 6 ++-- compiler/rustc_middle/src/mir/syntax.rs | 24 ++++++++++++++- compiler/rustc_middle/src/mir/terminator.rs | 1 + compiler/rustc_middle/src/mir/visit.rs | 1 + compiler/rustc_middle/src/thir.rs | 3 +- compiler/rustc_middle/src/thir/visit.rs | 8 ++++- .../rustc_mir_build/src/build/expr/into.rs | 19 ++++++++---- compiler/rustc_mir_build/src/thir/cx/expr.rs | 1 + compiler/rustc_mir_build/src/thir/print.rs | 4 ++- .../src/move_paths/builder.rs | 1 + compiler/rustc_passes/messages.ftl | 2 +- compiler/rustc_passes/src/errors.rs | 3 +- compiler/rustc_passes/src/naked_functions.rs | 30 ++++++++----------- .../rustc_smir/src/rustc_smir/convert/mir.rs | 1 + src/tools/rustfmt/src/parse/macros/asm.rs | 2 +- tests/codegen/naked-asan.rs | 2 +- .../naked-symbol-visibility/a_rust_dylib.rs | 2 +- tests/ui/asm/naked-functions.stderr | 4 +-- 29 files changed, 116 insertions(+), 73 deletions(-) diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index cb71521317637..733c2d931144d 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -2435,7 +2435,7 @@ pub enum AsmMacro { } impl AsmMacro { - pub const fn macro_name(&self) -> &'static str { + pub const fn macro_name(self) -> &'static str { match self { AsmMacro::Asm => "asm", AsmMacro::GlobalAsm => "global_asm", @@ -2443,13 +2443,21 @@ impl AsmMacro { } } - pub const fn is_supported_option(&self, option: InlineAsmOptions) -> bool { + pub const fn is_supported_option(self, option: InlineAsmOptions) -> bool { match self { AsmMacro::Asm => true, AsmMacro::GlobalAsm => InlineAsmOptions::GLOBAL_OPTIONS.contains(option), AsmMacro::NakedAsm => InlineAsmOptions::NAKED_OPTIONS.contains(option), } } + + pub const fn diverges(self, options: InlineAsmOptions) -> bool { + match self { + AsmMacro::Asm => options.contains(InlineAsmOptions::NORETURN), + AsmMacro::GlobalAsm => true, + AsmMacro::NakedAsm => true, + } + } } /// Inline assembly. diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs index 3b0b3ee1a745a..fad4d790be4a8 100644 --- a/compiler/rustc_borrowck/src/lib.rs +++ b/compiler/rustc_borrowck/src/lib.rs @@ -742,6 +742,7 @@ impl<'a, 'tcx, R> rustc_mir_dataflow::ResultsVisitor<'a, 'tcx, R> } TerminatorKind::InlineAsm { + asm_macro: _, template: _, operands, options: _, diff --git a/compiler/rustc_borrowck/src/polonius/loan_invalidations.rs b/compiler/rustc_borrowck/src/polonius/loan_invalidations.rs index afd811a0efb43..d1b65943199c4 100644 --- a/compiler/rustc_borrowck/src/polonius/loan_invalidations.rs +++ b/compiler/rustc_borrowck/src/polonius/loan_invalidations.rs @@ -169,6 +169,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LoanInvalidationsGenerator<'a, 'tcx> { } } TerminatorKind::InlineAsm { + asm_macro: _, template: _, operands, options: _, diff --git a/compiler/rustc_builtin_macros/src/asm.rs b/compiler/rustc_builtin_macros/src/asm.rs index 515ac17f70a14..9ae48024f445b 100644 --- a/compiler/rustc_builtin_macros/src/asm.rs +++ b/compiler/rustc_builtin_macros/src/asm.rs @@ -850,22 +850,13 @@ pub(super) fn expand_naked_asm<'cx>( return ExpandResult::Retry(()); }; let expr = match mac { - Ok(mut inline_asm) => { - // for future compatibility, we always set the NORETURN option. - // - // When we turn `asm!` into `naked_asm!` with this implementation, we can drop - // the `options(noreturn)`, which makes the upgrade smooth when `naked_asm!` - // starts disallowing the `noreturn` option in the future - inline_asm.options |= ast::InlineAsmOptions::NORETURN; - - P(ast::Expr { - id: ast::DUMMY_NODE_ID, - kind: ast::ExprKind::InlineAsm(P(inline_asm)), - span: sp, - attrs: ast::AttrVec::new(), - tokens: None, - }) - } + Ok(inline_asm) => P(ast::Expr { + id: ast::DUMMY_NODE_ID, + kind: ast::ExprKind::InlineAsm(P(inline_asm)), + span: sp, + attrs: ast::AttrVec::new(), + tokens: None, + }), Err(guar) => DummyResult::raw_expr(sp, Some(guar)), }; MacEager::expr(expr) diff --git a/compiler/rustc_codegen_cranelift/example/mini_core.rs b/compiler/rustc_codegen_cranelift/example/mini_core.rs index 5e535ff62e173..9fc0318df5dc0 100644 --- a/compiler/rustc_codegen_cranelift/example/mini_core.rs +++ b/compiler/rustc_codegen_cranelift/example/mini_core.rs @@ -726,6 +726,12 @@ pub macro global_asm() { /* compiler built-in */ } +#[rustc_builtin_macro] +#[rustc_macro_transparency = "semitransparent"] +pub macro naked_asm() { + /* compiler built-in */ +} + pub static A_STATIC: u8 = 42; #[lang = "panic_location"] diff --git a/compiler/rustc_codegen_cranelift/example/mini_core_hello_world.rs b/compiler/rustc_codegen_cranelift/example/mini_core_hello_world.rs index ccbd5a78485d7..e47431e0f873a 100644 --- a/compiler/rustc_codegen_cranelift/example/mini_core_hello_world.rs +++ b/compiler/rustc_codegen_cranelift/example/mini_core_hello_world.rs @@ -390,7 +390,7 @@ global_asm! { #[naked] extern "C" fn naked_test() { unsafe { - asm!("ret", options(noreturn)); + naked_asm!("ret"); } } diff --git a/compiler/rustc_codegen_cranelift/src/base.rs b/compiler/rustc_codegen_cranelift/src/base.rs index 0968062206940..a681e6d9f3cd1 100644 --- a/compiler/rustc_codegen_cranelift/src/base.rs +++ b/compiler/rustc_codegen_cranelift/src/base.rs @@ -8,6 +8,7 @@ use rustc_ast::InlineAsmOptions; use rustc_codegen_ssa::base::is_call_from_compiler_builtins_to_upstream_monomorphization; use rustc_index::IndexVec; use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; +use rustc_middle::mir::InlineAsmMacro; use rustc_middle::ty::TypeVisitableExt; use rustc_middle::ty::adjustment::PointerCoercion; use rustc_middle::ty::layout::FnAbiOf; @@ -57,6 +58,7 @@ pub(crate) fn codegen_fn<'tcx>( match &mir.basic_blocks[START_BLOCK].terminator().kind { TerminatorKind::InlineAsm { + asm_macro: InlineAsmMacro::NakedAsm, template, operands, options, @@ -498,6 +500,7 @@ fn codegen_fn_body(fx: &mut FunctionCx<'_, '_, '_>, start_block: Block) { "tail calls are not yet supported in `rustc_codegen_cranelift` backend" ), TerminatorKind::InlineAsm { + asm_macro: _, template, operands, options, diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs index 125d3b908c733..be9a6d9a90eed 100644 --- a/compiler/rustc_codegen_ssa/src/mir/block.rs +++ b/compiler/rustc_codegen_ssa/src/mir/block.rs @@ -3,7 +3,9 @@ use std::cmp; use rustc_ast as ast; use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece}; use rustc_hir::lang_items::LangItem; -use rustc_middle::mir::{self, AssertKind, BasicBlock, SwitchTargets, UnwindTerminateReason}; +use rustc_middle::mir::{ + self, AssertKind, BasicBlock, InlineAsmMacro, SwitchTargets, UnwindTerminateReason, +}; use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf, ValidityRequirement}; use rustc_middle::ty::print::{with_no_trimmed_paths, with_no_visible_paths}; use rustc_middle::ty::{self, Instance, Ty}; @@ -1133,6 +1135,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { &mut self, helper: TerminatorCodegenHelper<'tcx>, bx: &mut Bx, + asm_macro: InlineAsmMacro, terminator: &mir::Terminator<'tcx>, template: &[ast::InlineAsmTemplatePiece], operands: &[mir::InlineAsmOperand<'tcx>], @@ -1203,11 +1206,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { &operands, options, line_spans, - if options.contains(InlineAsmOptions::NORETURN) { - None - } else { - targets.get(0).copied() - }, + if asm_macro.diverges(options) { None } else { targets.get(0).copied() }, unwind, instance, mergeable_succ, @@ -1381,6 +1380,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { } mir::TerminatorKind::InlineAsm { + asm_macro, template, ref operands, options, @@ -1390,6 +1390,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { } => self.codegen_asm_terminator( helper, bx, + asm_macro, terminator, template, operands, diff --git a/compiler/rustc_const_eval/src/interpret/machine.rs b/compiler/rustc_const_eval/src/interpret/machine.rs index 0f796c3122210..89d49ba046e7d 100644 --- a/compiler/rustc_const_eval/src/interpret/machine.rs +++ b/compiler/rustc_const_eval/src/interpret/machine.rs @@ -395,7 +395,7 @@ pub trait Machine<'tcx>: Sized { /// /// This should take care of jumping to the next block (one of `targets`) when asm goto /// is triggered, `targets[0]` when the assembly falls through, or diverge in case of - /// `InlineAsmOptions::NORETURN` being set. + /// naked_asm! or `InlineAsmOptions::NORETURN` being set. fn eval_inline_asm( _ecx: &mut InterpCx<'tcx, Self>, _template: &'tcx [InlineAsmTemplatePiece], diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index 5c2f39f879c4c..95ca3e6647272 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -3507,11 +3507,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } fn check_expr_asm(&self, asm: &'tcx hir::InlineAsm<'tcx>) -> Ty<'tcx> { - let mut diverge = match asm.asm_macro { - rustc_ast::AsmMacro::Asm => asm.options.contains(ast::InlineAsmOptions::NORETURN), - rustc_ast::AsmMacro::GlobalAsm => true, - rustc_ast::AsmMacro::NakedAsm => true, - }; + let mut diverge = asm.asm_macro.diverges(asm.options); for (op, _op_sp) in asm.operands { match op { diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index bd87019508be9..a439514e16f87 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs @@ -2926,16 +2926,16 @@ declare_lint! { /// ```rust /// #![feature(asm_experimental_arch, naked_functions)] /// - /// use std::arch::asm; + /// use std::arch::naked_asm; /// /// #[naked] /// pub fn default_abi() -> u32 { - /// unsafe { asm!("", options(noreturn)); } + /// unsafe { naked_asm!(""); } /// } /// /// #[naked] /// pub extern "Rust" fn rust_abi() -> u32 { - /// unsafe { asm!("", options(noreturn)); } + /// unsafe { naked_asm!(""); } /// } /// ``` /// diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs index 4878956521831..9cafe804a8ee9 100644 --- a/compiler/rustc_middle/src/mir/pretty.rs +++ b/compiler/rustc_middle/src/mir/pretty.rs @@ -4,7 +4,7 @@ use std::fs; use std::io::{self, Write as _}; use std::path::{Path, PathBuf}; -use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece}; +use rustc_ast::InlineAsmTemplatePiece; use rustc_middle::mir::interpret::{ AllocBytes, AllocId, Allocation, GlobalAlloc, Pointer, Provenance, alloc_range, read_target_uint, @@ -1024,9 +1024,9 @@ impl<'tcx> TerminatorKind<'tcx> { vec!["real".into(), "unwind".into()] } FalseUnwind { unwind: _, .. } => vec!["real".into()], - InlineAsm { options, ref targets, unwind, .. } => { + InlineAsm { asm_macro, options, ref targets, unwind, .. } => { let mut vec = Vec::with_capacity(targets.len() + 1); - if !options.contains(InlineAsmOptions::NORETURN) { + if !asm_macro.diverges(options) { vec.push("return".into()); } vec.resize(targets.len(), "label".into()); diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs index 1722a7a1f358f..c610fac80f68f 100644 --- a/compiler/rustc_middle/src/mir/syntax.rs +++ b/compiler/rustc_middle/src/mir/syntax.rs @@ -605,6 +605,25 @@ impl CallSource { } } +#[derive(Clone, Copy, Debug, TyEncodable, TyDecodable, Hash, HashStable, PartialEq)] +#[derive(TypeFoldable, TypeVisitable)] +/// The macro that an inline assembly block was created by +pub enum InlineAsmMacro { + /// The `asm!` macro + Asm, + /// The `naked_asm!` macro + NakedAsm, +} + +impl InlineAsmMacro { + pub const fn diverges(self, options: InlineAsmOptions) -> bool { + match self { + InlineAsmMacro::Asm => options.contains(InlineAsmOptions::NORETURN), + InlineAsmMacro::NakedAsm => true, + } + } +} + /////////////////////////////////////////////////////////////////////////// // Terminators @@ -859,6 +878,9 @@ pub enum TerminatorKind<'tcx> { /// Block ends with an inline assembly block. This is a terminator since /// inline assembly is allowed to diverge. InlineAsm { + /// Macro used to create this inline asm: one of `asm!` or `naked_asm!` + asm_macro: InlineAsmMacro, + /// The template for the inline assembly, with placeholders. template: &'tcx [InlineAsmTemplatePiece], @@ -874,7 +896,7 @@ pub enum TerminatorKind<'tcx> { /// Valid targets for the inline assembly. /// The first element is the fallthrough destination, unless - /// InlineAsmOptions::NORETURN is set. + /// asm_macro == InlineAsmMacro::NakedAsm or InlineAsmOptions::NORETURN is set. targets: Box<[BasicBlock]>, /// Action to be taken if the inline assembly unwinds. This is present diff --git a/compiler/rustc_middle/src/mir/terminator.rs b/compiler/rustc_middle/src/mir/terminator.rs index 783952fb9cb8a..b919f5726db58 100644 --- a/compiler/rustc_middle/src/mir/terminator.rs +++ b/compiler/rustc_middle/src/mir/terminator.rs @@ -666,6 +666,7 @@ impl<'tcx> TerminatorKind<'tcx> { }, InlineAsm { + asm_macro: _, template: _, ref operands, options: _, diff --git a/compiler/rustc_middle/src/mir/visit.rs b/compiler/rustc_middle/src/mir/visit.rs index 64898a8495e26..9f9ee8497b60b 100644 --- a/compiler/rustc_middle/src/mir/visit.rs +++ b/compiler/rustc_middle/src/mir/visit.rs @@ -576,6 +576,7 @@ macro_rules! make_mir_visitor { } TerminatorKind::InlineAsm { + asm_macro: _, template: _, operands, options: _, diff --git a/compiler/rustc_middle/src/thir.rs b/compiler/rustc_middle/src/thir.rs index e614d41899a0e..fe865b8a51508 100644 --- a/compiler/rustc_middle/src/thir.rs +++ b/compiler/rustc_middle/src/thir.rs @@ -12,7 +12,7 @@ use std::cmp::Ordering; use std::fmt; use std::ops::Index; -use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece}; +use rustc_ast::{AsmMacro, InlineAsmOptions, InlineAsmTemplatePiece}; use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_hir::{BindingMode, ByRef, HirId, MatchSource, RangeEnd}; @@ -173,6 +173,7 @@ pub struct ClosureExpr<'tcx> { #[derive(Clone, Debug, HashStable)] pub struct InlineAsmExpr<'tcx> { + pub asm_macro: AsmMacro, pub template: &'tcx [InlineAsmTemplatePiece], pub operands: Box<[InlineAsmOperand<'tcx>]>, pub options: InlineAsmOptions, diff --git a/compiler/rustc_middle/src/thir/visit.rs b/compiler/rustc_middle/src/thir/visit.rs index 58e2ebaeaf8df..36f0e3d890cfd 100644 --- a/compiler/rustc_middle/src/thir/visit.rs +++ b/compiler/rustc_middle/src/thir/visit.rs @@ -148,7 +148,13 @@ pub fn walk_expr<'thir, 'tcx: 'thir, V: Visitor<'thir, 'tcx>>( NamedConst { def_id: _, args: _, user_ty: _ } => {} ConstParam { param: _, def_id: _ } => {} StaticRef { alloc_id: _, ty: _, def_id: _ } => {} - InlineAsm(box InlineAsmExpr { ref operands, template: _, options: _, line_spans: _ }) => { + InlineAsm(box InlineAsmExpr { + asm_macro: _, + ref operands, + template: _, + options: _, + line_spans: _, + }) => { for op in &**operands { use InlineAsmOperand::*; match op { diff --git a/compiler/rustc_mir_build/src/build/expr/into.rs b/compiler/rustc_mir_build/src/build/expr/into.rs index 86fe447f39973..dc317feb20c4c 100644 --- a/compiler/rustc_mir_build/src/build/expr/into.rs +++ b/compiler/rustc_mir_build/src/build/expr/into.rs @@ -2,7 +2,7 @@ use std::iter; -use rustc_ast::InlineAsmOptions; +use rustc_ast::{AsmMacro, InlineAsmOptions}; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_hir as hir; @@ -384,6 +384,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { block.unit() } ExprKind::InlineAsm(box InlineAsmExpr { + asm_macro, template, ref operands, options, @@ -392,11 +393,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { use rustc_middle::{mir, thir}; let destination_block = this.cfg.start_new_block(); - let mut targets = if options.contains(InlineAsmOptions::NORETURN) { - vec![] - } else { - vec![destination_block] - }; + let mut targets = + if asm_macro.diverges(options) { vec![] } else { vec![destination_block] }; let operands = operands .into_iter() @@ -474,7 +472,16 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { this.cfg.push_assign_unit(block, source_info, destination, this.tcx); } + let asm_macro = match asm_macro { + AsmMacro::Asm => InlineAsmMacro::Asm, + AsmMacro::GlobalAsm => { + span_bug!(expr_span, "unexpected global_asm! in inline asm") + } + AsmMacro::NakedAsm => InlineAsmMacro::NakedAsm, + }; + this.cfg.terminate(block, source_info, TerminatorKind::InlineAsm { + asm_macro, template, operands, options, diff --git a/compiler/rustc_mir_build/src/thir/cx/expr.rs b/compiler/rustc_mir_build/src/thir/cx/expr.rs index 2ffad0b4834a0..abf486af9623e 100644 --- a/compiler/rustc_mir_build/src/thir/cx/expr.rs +++ b/compiler/rustc_mir_build/src/thir/cx/expr.rs @@ -672,6 +672,7 @@ impl<'tcx> Cx<'tcx> { } hir::ExprKind::InlineAsm(asm) => ExprKind::InlineAsm(Box::new(InlineAsmExpr { + asm_macro: asm.asm_macro, template: asm.template, operands: asm .operands diff --git a/compiler/rustc_mir_build/src/thir/print.rs b/compiler/rustc_mir_build/src/thir/print.rs index 61317925d09e5..dae13df4054a4 100644 --- a/compiler/rustc_mir_build/src/thir/print.rs +++ b/compiler/rustc_mir_build/src/thir/print.rs @@ -818,10 +818,12 @@ impl<'a, 'tcx> ThirPrinter<'a, 'tcx> { } fn print_inline_asm_expr(&mut self, expr: &InlineAsmExpr<'tcx>, depth_lvl: usize) { - let InlineAsmExpr { template, operands, options, line_spans } = expr; + let InlineAsmExpr { asm_macro, template, operands, options, line_spans } = expr; print_indented!(self, "InlineAsmExpr {", depth_lvl); + print_indented!(self, format!("asm_macro: {:?}", asm_macro), depth_lvl + 1); + print_indented!(self, "template: [", depth_lvl + 1); for template_piece in template.iter() { print_indented!(self, format!("{:?}", template_piece), depth_lvl + 2); diff --git a/compiler/rustc_mir_dataflow/src/move_paths/builder.rs b/compiler/rustc_mir_dataflow/src/move_paths/builder.rs index 3c8be2f73e14a..162245cb95060 100644 --- a/compiler/rustc_mir_dataflow/src/move_paths/builder.rs +++ b/compiler/rustc_mir_dataflow/src/move_paths/builder.rs @@ -481,6 +481,7 @@ impl<'a, 'tcx, F: Fn(Ty<'tcx>) -> bool> MoveDataBuilder<'a, 'tcx, F> { } } TerminatorKind::InlineAsm { + asm_macro: _, template: _, ref operands, options: _, diff --git a/compiler/rustc_passes/messages.ftl b/compiler/rustc_passes/messages.ftl index 414a9c6e3b964..be76d6cef2b88 100644 --- a/compiler/rustc_passes/messages.ftl +++ b/compiler/rustc_passes/messages.ftl @@ -499,7 +499,7 @@ passes_naked_functions_incompatible_attribute = passes_naked_functions_must_naked_asm = the `asm!` macro is not allowed in naked functions - .suggestion = consider using the `naked_asm!` macro instead + .label = consider using the `naked_asm!` macro instead passes_no_link = attribute should be applied to an `extern crate` item diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs index fb47137702252..4f00c90fa3b0f 100644 --- a/compiler/rustc_passes/src/errors.rs +++ b/compiler/rustc_passes/src/errors.rs @@ -1190,9 +1190,8 @@ impl Diagnostic<'_, G> for NakedFunctionsAsmBlock { #[diag(passes_naked_functions_must_naked_asm, code = E0787)] pub(crate) struct NakedFunctionsMustNakedAsm { #[primary_span] + #[label] pub span: Span, - #[suggestion(code = "naked_asm!", applicability = "machine-applicable")] - pub macro_span: Span, } #[derive(Diagnostic)] diff --git a/compiler/rustc_passes/src/naked_functions.rs b/compiler/rustc_passes/src/naked_functions.rs index fa4971cd2cc7f..b2f8d7dadff37 100644 --- a/compiler/rustc_passes/src/naked_functions.rs +++ b/compiler/rustc_passes/src/naked_functions.rs @@ -7,10 +7,11 @@ use rustc_hir::intravisit::Visitor; use rustc_hir::{ExprKind, HirIdSet, StmtKind}; use rustc_middle::hir::nested_filter::OnlyBodies; use rustc_middle::query::Providers; +use rustc_middle::span_bug; use rustc_middle::ty::TyCtxt; use rustc_session::lint::builtin::UNDEFINED_NAKED_FUNCTION_ABI; +use rustc_span::Span; use rustc_span::symbol::sym; -use rustc_span::{BytePos, Span}; use rustc_target::spec::abi::Abi; use crate::errors::{ @@ -137,10 +138,7 @@ fn check_asm<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId, body: &'tcx hir::Body< ItemKind::InlineAsm => { has_err = true; - // the span that contains the `asm!` call, - // so tooling can replace it with `naked_asm!` - let macro_span = span.with_hi(span.lo() + BytePos("asm!".len() as u32)); - tcx.dcx().emit_err(NakedFunctionsMustNakedAsm { span, macro_span }); + tcx.dcx().emit_err(NakedFunctionsMustNakedAsm { span }); } ItemKind::NonAsm => { must_show_error = true; @@ -210,19 +208,17 @@ impl CheckInlineAssembly { self.items.push((ItemKind::NonAsm, span)); } - ExprKind::InlineAsm(asm) => { - match asm.asm_macro { - rustc_ast::AsmMacro::Asm => { - self.items.push((ItemKind::InlineAsm, span)); - } - rustc_ast::AsmMacro::NakedAsm => { - self.items.push((ItemKind::NakedAsm, span)); - } - rustc_ast::AsmMacro::GlobalAsm => { - // not allowed in this position - } + ExprKind::InlineAsm(asm) => match asm.asm_macro { + rustc_ast::AsmMacro::Asm => { + self.items.push((ItemKind::InlineAsm, span)); } - } + rustc_ast::AsmMacro::NakedAsm => { + self.items.push((ItemKind::NakedAsm, span)); + } + rustc_ast::AsmMacro::GlobalAsm => { + span_bug!(span, "`global_asm!` is not allowed in this position") + } + }, ExprKind::DropTemps(..) | ExprKind::Block(..) => { hir::intravisit::walk_expr(self, expr); diff --git a/compiler/rustc_smir/src/rustc_smir/convert/mir.rs b/compiler/rustc_smir/src/rustc_smir/convert/mir.rs index 0dbbc338e738b..dbae4b7e71919 100644 --- a/compiler/rustc_smir/src/rustc_smir/convert/mir.rs +++ b/compiler/rustc_smir/src/rustc_smir/convert/mir.rs @@ -655,6 +655,7 @@ impl<'tcx> Stable<'tcx> for mir::TerminatorKind<'tcx> { } } mir::TerminatorKind::InlineAsm { + asm_macro: _, template, operands, options, diff --git a/src/tools/rustfmt/src/parse/macros/asm.rs b/src/tools/rustfmt/src/parse/macros/asm.rs index 0c37d12490e2f..58c8d21bd7a4c 100644 --- a/src/tools/rustfmt/src/parse/macros/asm.rs +++ b/src/tools/rustfmt/src/parse/macros/asm.rs @@ -1,5 +1,5 @@ use rustc_ast::ast; -use rustc_builtin_macros::asm::{parse_asm_args, AsmArgs}; +use rustc_builtin_macros::asm::{AsmArgs, parse_asm_args}; use crate::rewrite::RewriteContext; diff --git a/tests/codegen/naked-asan.rs b/tests/codegen/naked-asan.rs index ac36018eed3a1..bcaa60baeffd8 100644 --- a/tests/codegen/naked-asan.rs +++ b/tests/codegen/naked-asan.rs @@ -14,7 +14,7 @@ #[no_mangle] pub extern "x86-interrupt" fn page_fault_handler(_: u64, _: u64) { unsafe { - core::arch::asm!("ud2", options(noreturn)); + core::arch::naked_asm!("ud2"); } } diff --git a/tests/run-make/naked-symbol-visibility/a_rust_dylib.rs b/tests/run-make/naked-symbol-visibility/a_rust_dylib.rs index 517c8da656ad0..8dd19e613bff8 100644 --- a/tests/run-make/naked-symbol-visibility/a_rust_dylib.rs +++ b/tests/run-make/naked-symbol-visibility/a_rust_dylib.rs @@ -72,7 +72,7 @@ extern "C" fn vanilla_weak_linkage() -> u32 { #[cfg(not(windows))] #[linkage = "weak"] extern "C" fn naked_weak_linkage() -> u32 { - unsafe { naked_asm!("mov rax, 42", "ret", options(noreturn)) } + unsafe { naked_asm!("mov rax, 42", "ret") } } // functions that are declared in an `extern "C"` block are currently not exported diff --git a/tests/ui/asm/naked-functions.stderr b/tests/ui/asm/naked-functions.stderr index 1ceeafffd9091..0898f3620f24f 100644 --- a/tests/ui/asm/naked-functions.stderr +++ b/tests/ui/asm/naked-functions.stderr @@ -74,9 +74,7 @@ error[E0787]: the `asm!` macro is not allowed in naked functions --> $DIR/naked-functions.rs:13:5 | LL | asm!("", options(raw)); - | ----^^^^^^^^^^^^^^^^^^ - | | - | help: consider using the `naked_asm!` macro instead: `naked_asm!` + | ^^^^^^^^^^^^^^^^^^^^^^ consider using the `naked_asm!` macro instead error: patterns not allowed in naked function parameters --> $DIR/naked-functions.rs:25:5 From 3b2be4457da8521ab0a8a9cd7e11b1c24b0de191 Mon Sep 17 00:00:00 2001 From: dacian Date: Sun, 6 Oct 2024 20:37:10 +0300 Subject: [PATCH 1946/2194] grammar fix --- library/core/src/intrinsics/mir.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/core/src/intrinsics/mir.rs b/library/core/src/intrinsics/mir.rs index fb0aa5398a55b..a2ab39caade53 100644 --- a/library/core/src/intrinsics/mir.rs +++ b/library/core/src/intrinsics/mir.rs @@ -213,7 +213,7 @@ //! - All other locals need to be declared with `let` somewhere and then can be accessed by name. //! //! #### Places -//! - Locals implicit convert to places. +//! - Locals implicitly convert to places. //! - Field accesses, derefs, and indexing work normally. //! - Fields in variants can be accessed via the [`Variant`] and [`Field`] associated functions, //! see their documentation for details. From 0e96fd02f027a32ae01966ed3ea8270fc49b04bc Mon Sep 17 00:00:00 2001 From: Chayim Refael Friedman Date: Sun, 6 Oct 2024 23:48:16 +0300 Subject: [PATCH 1947/2194] Use external stack in borrowck DFS Because damnit, it can crash r-a. Why do people make this stupid DFSes anyway (I get it, it's easier until it blows). --- .../crates/hir-ty/src/mir/borrowck.rs | 125 ++++++++++-------- 1 file changed, 67 insertions(+), 58 deletions(-) diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir/borrowck.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir/borrowck.rs index 878d584a4efa0..9830fa1ca7b73 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/mir/borrowck.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir/borrowck.rs @@ -386,82 +386,91 @@ fn ever_initialized_map( fn dfs( db: &dyn HirDatabase, body: &MirBody, - b: BasicBlockId, l: LocalId, + stack: &mut Vec, result: &mut ArenaMap>, ) { - let mut is_ever_initialized = result[b][l]; // It must be filled, as we use it as mark for dfs - let block = &body.basic_blocks[b]; - for statement in &block.statements { - match &statement.kind { - StatementKind::Assign(p, _) => { - if p.projection.lookup(&body.projection_store).is_empty() && p.local == l { - is_ever_initialized = true; + while let Some(b) = stack.pop() { + let mut is_ever_initialized = result[b][l]; // It must be filled, as we use it as mark for dfs + let block = &body.basic_blocks[b]; + for statement in &block.statements { + match &statement.kind { + StatementKind::Assign(p, _) => { + if p.projection.lookup(&body.projection_store).is_empty() && p.local == l { + is_ever_initialized = true; + } } - } - StatementKind::StorageDead(p) => { - if *p == l { - is_ever_initialized = false; + StatementKind::StorageDead(p) => { + if *p == l { + is_ever_initialized = false; + } } + StatementKind::Deinit(_) + | StatementKind::FakeRead(_) + | StatementKind::Nop + | StatementKind::StorageLive(_) => (), } - StatementKind::Deinit(_) - | StatementKind::FakeRead(_) - | StatementKind::Nop - | StatementKind::StorageLive(_) => (), - } - } - let Some(terminator) = &block.terminator else { - never!( - "Terminator should be none only in construction.\nThe body:\n{}", - body.pretty_print(db) - ); - return; - }; - let mut process = |target, is_ever_initialized| { - if !result[target].contains_idx(l) || !result[target][l] && is_ever_initialized { - result[target].insert(l, is_ever_initialized); - dfs(db, body, target, l, result); - } - }; - match &terminator.kind { - TerminatorKind::Goto { target } => process(*target, is_ever_initialized), - TerminatorKind::SwitchInt { targets, .. } => { - targets.all_targets().iter().for_each(|&it| process(it, is_ever_initialized)); } - TerminatorKind::UnwindResume - | TerminatorKind::Abort - | TerminatorKind::Return - | TerminatorKind::Unreachable => (), - TerminatorKind::Call { target, cleanup, destination, .. } => { - if destination.projection.lookup(&body.projection_store).is_empty() - && destination.local == l - { - is_ever_initialized = true; + let Some(terminator) = &block.terminator else { + never!( + "Terminator should be none only in construction.\nThe body:\n{}", + body.pretty_print(db) + ); + return; + }; + let mut process = |target, is_ever_initialized| { + if !result[target].contains_idx(l) || !result[target][l] && is_ever_initialized { + result[target].insert(l, is_ever_initialized); + stack.push(target); + } + }; + match &terminator.kind { + TerminatorKind::Goto { target } => process(*target, is_ever_initialized), + TerminatorKind::SwitchInt { targets, .. } => { + targets.all_targets().iter().for_each(|&it| process(it, is_ever_initialized)); + } + TerminatorKind::UnwindResume + | TerminatorKind::Abort + | TerminatorKind::Return + | TerminatorKind::Unreachable => (), + TerminatorKind::Call { target, cleanup, destination, .. } => { + if destination.projection.lookup(&body.projection_store).is_empty() + && destination.local == l + { + is_ever_initialized = true; + } + target.iter().chain(cleanup).for_each(|&it| process(it, is_ever_initialized)); + } + TerminatorKind::Drop { target, unwind, place: _ } => { + iter::once(target) + .chain(unwind) + .for_each(|&it| process(it, is_ever_initialized)); + } + TerminatorKind::DropAndReplace { .. } + | TerminatorKind::Assert { .. } + | TerminatorKind::Yield { .. } + | TerminatorKind::CoroutineDrop + | TerminatorKind::FalseEdge { .. } + | TerminatorKind::FalseUnwind { .. } => { + never!("We don't emit these MIR terminators yet"); } - target.iter().chain(cleanup).for_each(|&it| process(it, is_ever_initialized)); - } - TerminatorKind::Drop { target, unwind, place: _ } => { - iter::once(target).chain(unwind).for_each(|&it| process(it, is_ever_initialized)); - } - TerminatorKind::DropAndReplace { .. } - | TerminatorKind::Assert { .. } - | TerminatorKind::Yield { .. } - | TerminatorKind::CoroutineDrop - | TerminatorKind::FalseEdge { .. } - | TerminatorKind::FalseUnwind { .. } => { - never!("We don't emit these MIR terminators yet"); } } } + let mut stack = Vec::new(); for &l in &body.param_locals { result[body.start_block].insert(l, true); - dfs(db, body, body.start_block, l, &mut result); + stack.clear(); + stack.push(body.start_block); + dfs(db, body, l, &mut stack, &mut result); } for l in body.locals.iter().map(|it| it.0) { db.unwind_if_cancelled(); if !result[body.start_block].contains_idx(l) { result[body.start_block].insert(l, false); - dfs(db, body, body.start_block, l, &mut result); + stack.clear(); + stack.push(body.start_block); + dfs(db, body, l, &mut stack, &mut result); } } result From aa4f16a6e71fa63a366ffa0981a422eec73f66ca Mon Sep 17 00:00:00 2001 From: Brezak Date: Tue, 20 Aug 2024 20:53:49 +0200 Subject: [PATCH 1948/2194] Check that `#[pointee]` is applied only to generic arguments --- compiler/rustc_builtin_macros/messages.ftl | 2 + .../src/deriving/smart_ptr.rs | 64 +++++++++++++++++++ compiler/rustc_builtin_macros/src/errors.rs | 7 ++ .../ui/deriving/deriving-smart-pointer-neg.rs | 33 ++++++++++ .../deriving-smart-pointer-neg.stderr | 26 +++++++- 5 files changed, 131 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_builtin_macros/messages.ftl b/compiler/rustc_builtin_macros/messages.ftl index 9695df9c87e8a..8bd07027da46f 100644 --- a/compiler/rustc_builtin_macros/messages.ftl +++ b/compiler/rustc_builtin_macros/messages.ftl @@ -235,6 +235,8 @@ builtin_macros_non_exhaustive_default = default variant must be exhaustive .label = declared `#[non_exhaustive]` here .help = consider a manual implementation of `Default` +builtin_macros_non_generic_pointee = the `#[pointee]` attribute may only be used on generic parameters + builtin_macros_non_unit_default = the `#[default]` attribute may only be used on unit enum variants .help = consider a manual implementation of `Default` diff --git a/compiler/rustc_builtin_macros/src/deriving/smart_ptr.rs b/compiler/rustc_builtin_macros/src/deriving/smart_ptr.rs index 78028df2aa0ee..fab1906eecd50 100644 --- a/compiler/rustc_builtin_macros/src/deriving/smart_ptr.rs +++ b/compiler/rustc_builtin_macros/src/deriving/smart_ptr.rs @@ -13,6 +13,8 @@ use rustc_span::symbol::{Ident, sym}; use rustc_span::{Span, Symbol}; use thin_vec::{ThinVec, thin_vec}; +use crate::errors; + macro_rules! path { ($span:expr, $($part:ident)::*) => { vec![$(Ident::new(sym::$part, $span),)*] } } @@ -25,6 +27,8 @@ pub(crate) fn expand_deriving_smart_ptr( push: &mut dyn FnMut(Annotatable), _is_const: bool, ) { + item.visit_with(&mut DetectNonGenericPointeeAttr { cx }); + let (name_ident, generics) = if let Annotatable::Item(aitem) = item && let ItemKind::Struct(struct_data, g) = &aitem.kind { @@ -396,3 +400,63 @@ impl<'a> ast::mut_visit::MutVisitor for TypeSubstitution<'a> { } } } + +struct DetectNonGenericPointeeAttr<'a, 'b> { + cx: &'a ExtCtxt<'b>, +} + +impl<'a, 'b> rustc_ast::visit::Visitor<'a> for DetectNonGenericPointeeAttr<'a, 'b> { + fn visit_attribute(&mut self, attr: &'a rustc_ast::Attribute) -> Self::Result { + if attr.has_name(sym::pointee) { + self.cx.dcx().emit_err(errors::NonGenericPointee { span: attr.span }); + } + } + + fn visit_generic_param(&mut self, param: &'a rustc_ast::GenericParam) -> Self::Result { + let mut error_on_pointee = AlwaysErrorOnGenericParam { cx: self.cx }; + + match ¶m.kind { + GenericParamKind::Type { default } => { + // The `default` may end up containing a block expression. + // The problem is block expressions may define structs with generics. + // A user may attach a #[pointee] attribute to one of these generics + // We want to catch that. The simple solution is to just + // always raise a `NonGenericPointee` error when this happens. + // + // This solution does reject valid rust programs but, + // such a code would have to, in order: + // - Define a smart pointer struct. + // - Somewhere in this struct definition use a type with a const generic argument. + // - Calculate this const generic in a expression block. + // - Define a new smart pointer type in this block. + // - Have this smart pointer type have more than 1 generic type. + // In this case, the inner smart pointer derive would be complaining that it + // needs a pointer attribute. Meanwhile, the outer macro would be complaining + // that we attached a #[pointee] to a generic type argument while helpfully + // informing the user that #[pointee] can only be attached to generic pointer arguments + rustc_ast::visit::visit_opt!(error_on_pointee, visit_ty, default); + } + + GenericParamKind::Const { .. } | GenericParamKind::Lifetime => { + rustc_ast::visit::walk_generic_param(&mut error_on_pointee, param); + } + } + } + + fn visit_ty(&mut self, t: &'a rustc_ast::Ty) -> Self::Result { + let mut error_on_pointee = AlwaysErrorOnGenericParam { cx: self.cx }; + error_on_pointee.visit_ty(t) + } +} + +struct AlwaysErrorOnGenericParam<'a, 'b> { + cx: &'a ExtCtxt<'b>, +} + +impl<'a, 'b> rustc_ast::visit::Visitor<'a> for AlwaysErrorOnGenericParam<'a, 'b> { + fn visit_attribute(&mut self, attr: &'a rustc_ast::Attribute) -> Self::Result { + if attr.has_name(sym::pointee) { + self.cx.dcx().emit_err(errors::NonGenericPointee { span: attr.span }); + } + } +} diff --git a/compiler/rustc_builtin_macros/src/errors.rs b/compiler/rustc_builtin_macros/src/errors.rs index 4fffffb91c8b4..625aa4f2b75de 100644 --- a/compiler/rustc_builtin_macros/src/errors.rs +++ b/compiler/rustc_builtin_macros/src/errors.rs @@ -937,3 +937,10 @@ pub(crate) struct NakedFunctionTestingAttribute { #[label] pub testing_span: Span, } + +#[derive(Diagnostic)] +#[diag(builtin_macros_non_generic_pointee)] +pub(crate) struct NonGenericPointee { + #[primary_span] + pub span: Span, +} diff --git a/tests/ui/deriving/deriving-smart-pointer-neg.rs b/tests/ui/deriving/deriving-smart-pointer-neg.rs index f02fb56130fa7..41d3039236f71 100644 --- a/tests/ui/deriving/deriving-smart-pointer-neg.rs +++ b/tests/ui/deriving/deriving-smart-pointer-neg.rs @@ -53,6 +53,39 @@ struct NoMaybeSized<'a, #[pointee] T> { ptr: &'a T, } +#[derive(SmartPointer)] +#[repr(transparent)] +struct PointeeOnField<'a, #[pointee] T: ?Sized> { + #[pointee] + //~^ ERROR: the `#[pointee]` attribute may only be used on generic parameters + ptr: &'a T +} + +#[derive(SmartPointer)] +#[repr(transparent)] +struct PointeeInTypeConstBlock<'a, T: ?Sized = [u32; const { struct UhOh<#[pointee] T>(T); 10 }]> { + //~^ ERROR: the `#[pointee]` attribute may only be used on generic parameters + ptr: &'a T, +} + +#[derive(SmartPointer)] +#[repr(transparent)] +struct PointeeInConstConstBlock< + 'a, + T: ?Sized, + const V: u32 = { struct UhOh<#[pointee] T>(T); 10 }> + //~^ ERROR: the `#[pointee]` attribute may only be used on generic parameters +{ + ptr: &'a T, +} + +#[derive(SmartPointer)] +#[repr(transparent)] +struct PointeeInAnotherTypeConstBlock<'a, #[pointee] T: ?Sized> { + ptr: PointeeInConstConstBlock<'a, T, { struct UhOh<#[pointee] T>(T); 0 }> + //~^ ERROR: the `#[pointee]` attribute may only be used on generic parameters +} + // However, reordering attributes should work nevertheless. #[repr(transparent)] #[derive(SmartPointer)] diff --git a/tests/ui/deriving/deriving-smart-pointer-neg.stderr b/tests/ui/deriving/deriving-smart-pointer-neg.stderr index e7c2afc8b00c7..9ab117698c7a0 100644 --- a/tests/ui/deriving/deriving-smart-pointer-neg.stderr +++ b/tests/ui/deriving/deriving-smart-pointer-neg.stderr @@ -58,6 +58,30 @@ error: `derive(SmartPointer)` requires T to be marked `?Sized` LL | struct NoMaybeSized<'a, #[pointee] T> { | ^ +error: the `#[pointee]` attribute may only be used on generic parameters + --> $DIR/deriving-smart-pointer-neg.rs:59:5 + | +LL | #[pointee] + | ^^^^^^^^^^ + +error: the `#[pointee]` attribute may only be used on generic parameters + --> $DIR/deriving-smart-pointer-neg.rs:66:74 + | +LL | struct PointeeInTypeConstBlock<'a, T: ?Sized = [u32; const { struct UhOh<#[pointee] T>(T); 10 }]> { + | ^^^^^^^^^^ + +error: the `#[pointee]` attribute may only be used on generic parameters + --> $DIR/deriving-smart-pointer-neg.rs:76:34 + | +LL | const V: u32 = { struct UhOh<#[pointee] T>(T); 10 }> + | ^^^^^^^^^^ + +error: the `#[pointee]` attribute may only be used on generic parameters + --> $DIR/deriving-smart-pointer-neg.rs:85:56 + | +LL | ptr: PointeeInConstConstBlock<'a, T, { struct UhOh<#[pointee] T>(T); 0 }> + | ^^^^^^^^^^ + error[E0392]: lifetime parameter `'a` is never used --> $DIR/deriving-smart-pointer-neg.rs:15:16 | @@ -90,6 +114,6 @@ LL | struct NoFieldUnit<'a, #[pointee] T: ?Sized>(); | = help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData` -error: aborting due to 12 previous errors +error: aborting due to 16 previous errors For more information about this error, try `rustc --explain E0392`. From cfeee7bcbf182a6c22083c7dfb56c6034a65d0a0 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 1 Oct 2024 16:08:09 +1000 Subject: [PATCH 1949/2194] Remove unused features. --- compiler/rustc_infer/src/lib.rs | 3 --- 1 file changed, 3 deletions(-) diff --git a/compiler/rustc_infer/src/lib.rs b/compiler/rustc_infer/src/lib.rs index 934484bf9158a..a04b2bb2b08b5 100644 --- a/compiler/rustc_infer/src/lib.rs +++ b/compiler/rustc_infer/src/lib.rs @@ -19,10 +19,7 @@ #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![doc(rust_logo)] #![feature(assert_matches)] -#![feature(box_patterns)] #![feature(extend_one)] -#![feature(if_let_guard)] -#![feature(iter_intersperse)] #![feature(iterator_try_collect)] #![feature(let_chains)] #![feature(rustdoc_internals)] From 7a9bbd05c42f1c6b0d920a4e741ea28452916c99 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 1 Oct 2024 16:11:48 +1000 Subject: [PATCH 1950/2194] Rename `errors/mod.rs` as `errors.rs`. It's simpler, for this tiny module. --- compiler/rustc_infer/src/{errors/mod.rs => errors.rs} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename compiler/rustc_infer/src/{errors/mod.rs => errors.rs} (100%) diff --git a/compiler/rustc_infer/src/errors/mod.rs b/compiler/rustc_infer/src/errors.rs similarity index 100% rename from compiler/rustc_infer/src/errors/mod.rs rename to compiler/rustc_infer/src/errors.rs From 5486d72e7783271f457649e4e865a821becf27a2 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 1 Oct 2024 16:18:34 +1000 Subject: [PATCH 1951/2194] Reduce visibilities. Three of the modules don't need to be `pub`, and then `warn(unreachable_pub)` identifies a bunch more things that also shouldn't be `pub`, plus a couple of things that are unused. --- compiler/rustc_infer/src/infer/mod.rs | 6 +-- .../rustc_infer/src/infer/opaque_types/mod.rs | 24 +++------- .../src/infer/opaque_types/table.rs | 2 +- .../rustc_infer/src/infer/type_variable.rs | 45 +++++++------------ 4 files changed, 25 insertions(+), 52 deletions(-) diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index 5fa1bf51634a3..87dae0c1e0960 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -56,17 +56,17 @@ use crate::traits::{self, ObligationCause, ObligationInspector, PredicateObligat pub mod at; pub mod canonical; mod context; -pub mod free_regions; +mod free_regions; mod freshen; mod lexical_region_resolve; -pub mod opaque_types; +mod opaque_types; pub mod outlives; mod projection; pub mod region_constraints; pub mod relate; pub mod resolve; pub(crate) mod snapshot; -pub mod type_variable; +mod type_variable; #[must_use] #[derive(Debug)] diff --git a/compiler/rustc_infer/src/infer/opaque_types/mod.rs b/compiler/rustc_infer/src/infer/opaque_types/mod.rs index 55c51bc856f8e..0c5eca6ebdfd9 100644 --- a/compiler/rustc_infer/src/infer/opaque_types/mod.rs +++ b/compiler/rustc_infer/src/infer/opaque_types/mod.rs @@ -19,8 +19,8 @@ use crate::traits::{self, Obligation}; mod table; -pub type OpaqueTypeMap<'tcx> = FxIndexMap, OpaqueTypeDecl<'tcx>>; -pub use table::{OpaqueTypeStorage, OpaqueTypeTable}; +pub(crate) type OpaqueTypeMap<'tcx> = FxIndexMap, OpaqueTypeDecl<'tcx>>; +pub(crate) use table::{OpaqueTypeStorage, OpaqueTypeTable}; use super::DefineOpaqueTypes; @@ -377,9 +377,9 @@ impl<'tcx> InferCtxt<'tcx> { /// /// We ignore any type parameters because impl trait values are assumed to /// capture all the in-scope type parameters. -pub struct ConstrainOpaqueTypeRegionVisitor<'tcx, OP: FnMut(ty::Region<'tcx>)> { - pub tcx: TyCtxt<'tcx>, - pub op: OP, +struct ConstrainOpaqueTypeRegionVisitor<'tcx, OP: FnMut(ty::Region<'tcx>)> { + tcx: TyCtxt<'tcx>, + op: OP, } impl<'tcx, OP> TypeVisitor> for ConstrainOpaqueTypeRegionVisitor<'tcx, OP> @@ -455,20 +455,6 @@ where } } -pub enum UseKind { - DefiningUse, - OpaqueUse, -} - -impl UseKind { - pub fn is_defining(self) -> bool { - match self { - UseKind::DefiningUse => true, - UseKind::OpaqueUse => false, - } - } -} - impl<'tcx> InferCtxt<'tcx> { #[instrument(skip(self), level = "debug")] fn register_hidden_type( diff --git a/compiler/rustc_infer/src/infer/opaque_types/table.rs b/compiler/rustc_infer/src/infer/opaque_types/table.rs index 4aa2ccab0e7bb..6e4cc65bec339 100644 --- a/compiler/rustc_infer/src/infer/opaque_types/table.rs +++ b/compiler/rustc_infer/src/infer/opaque_types/table.rs @@ -7,7 +7,7 @@ use super::{OpaqueTypeDecl, OpaqueTypeMap}; use crate::infer::snapshot::undo_log::{InferCtxtUndoLogs, UndoLog}; #[derive(Default, Debug, Clone)] -pub struct OpaqueTypeStorage<'tcx> { +pub(crate) struct OpaqueTypeStorage<'tcx> { /// Opaque types found in explicit return types and their /// associated fresh inference variable. Writeback resolves these /// variables to get the concrete type, which can be used to diff --git a/compiler/rustc_infer/src/infer/type_variable.rs b/compiler/rustc_infer/src/infer/type_variable.rs index 7eb2c20e0d8e7..c50477b2922be 100644 --- a/compiler/rustc_infer/src/infer/type_variable.rs +++ b/compiler/rustc_infer/src/infer/type_variable.rs @@ -20,7 +20,7 @@ impl<'tcx> Rollback>>> for TypeVariabl } #[derive(Clone)] -pub struct TypeVariableStorage<'tcx> { +pub(crate) struct TypeVariableStorage<'tcx> { /// The origins of each type variable. values: IndexVec, /// Two variables are unified in `eq_relations` when we have a @@ -29,7 +29,7 @@ pub struct TypeVariableStorage<'tcx> { eq_relations: ut::UnificationTableStorage>, } -pub struct TypeVariableTable<'a, 'tcx> { +pub(crate) struct TypeVariableTable<'a, 'tcx> { storage: &'a mut TypeVariableStorage<'tcx>, undo_log: &'a mut InferCtxtUndoLogs<'tcx>, @@ -50,7 +50,7 @@ pub(crate) struct TypeVariableData { } #[derive(Copy, Clone, Debug)] -pub enum TypeVariableValue<'tcx> { +pub(crate) enum TypeVariableValue<'tcx> { Known { value: Ty<'tcx> }, Unknown { universe: ty::UniverseIndex }, } @@ -58,14 +58,14 @@ pub enum TypeVariableValue<'tcx> { impl<'tcx> TypeVariableValue<'tcx> { /// If this value is known, returns the type it is known to be. /// Otherwise, `None`. - pub fn known(&self) -> Option> { + pub(crate) fn known(&self) -> Option> { match *self { TypeVariableValue::Unknown { .. } => None, TypeVariableValue::Known { value } => Some(value), } } - pub fn is_unknown(&self) -> bool { + pub(crate) fn is_unknown(&self) -> bool { match *self { TypeVariableValue::Unknown { .. } => true, TypeVariableValue::Known { .. } => false, @@ -74,7 +74,7 @@ impl<'tcx> TypeVariableValue<'tcx> { } impl<'tcx> TypeVariableStorage<'tcx> { - pub fn new() -> TypeVariableStorage<'tcx> { + pub(crate) fn new() -> TypeVariableStorage<'tcx> { TypeVariableStorage { values: Default::default(), eq_relations: ut::UnificationTableStorage::new(), @@ -105,14 +105,14 @@ impl<'tcx> TypeVariableTable<'_, 'tcx> { /// /// Note that this function does not return care whether /// `vid` has been unified with something else or not. - pub fn var_origin(&self, vid: ty::TyVid) -> TypeVariableOrigin { + pub(crate) fn var_origin(&self, vid: ty::TyVid) -> TypeVariableOrigin { self.storage.values[vid].origin } /// Records that `a == b`, depending on `dir`. /// /// Precondition: neither `a` nor `b` are known. - pub fn equate(&mut self, a: ty::TyVid, b: ty::TyVid) { + pub(crate) fn equate(&mut self, a: ty::TyVid, b: ty::TyVid) { debug_assert!(self.probe(a).is_unknown()); debug_assert!(self.probe(b).is_unknown()); self.eq_relations().union(a, b); @@ -121,7 +121,7 @@ impl<'tcx> TypeVariableTable<'_, 'tcx> { /// Instantiates `vid` with the type `ty`. /// /// Precondition: `vid` must not have been previously instantiated. - pub fn instantiate(&mut self, vid: ty::TyVid, ty: Ty<'tcx>) { + pub(crate) fn instantiate(&mut self, vid: ty::TyVid, ty: Ty<'tcx>) { let vid = self.root_var(vid); debug_assert!(!ty.is_ty_var(), "instantiating ty var with var: {vid:?} {ty:?}"); debug_assert!(self.probe(vid).is_unknown()); @@ -143,7 +143,7 @@ impl<'tcx> TypeVariableTable<'_, 'tcx> { /// - `origin`: indicates *why* the type variable was created. /// The code in this module doesn't care, but it can be useful /// for improving error messages. - pub fn new_var( + pub(crate) fn new_var( &mut self, universe: ty::UniverseIndex, origin: TypeVariableOrigin, @@ -158,7 +158,7 @@ impl<'tcx> TypeVariableTable<'_, 'tcx> { } /// Returns the number of type variables created thus far. - pub fn num_vars(&self) -> usize { + pub(crate) fn num_vars(&self) -> usize { self.storage.values.len() } @@ -167,42 +167,29 @@ impl<'tcx> TypeVariableTable<'_, 'tcx> { /// will yield the same root variable (per the union-find /// algorithm), so `root_var(a) == root_var(b)` implies that `a == /// b` (transitively). - pub fn root_var(&mut self, vid: ty::TyVid) -> ty::TyVid { + pub(crate) fn root_var(&mut self, vid: ty::TyVid) -> ty::TyVid { self.eq_relations().find(vid).vid } /// Retrieves the type to which `vid` has been instantiated, if /// any. - pub fn probe(&mut self, vid: ty::TyVid) -> TypeVariableValue<'tcx> { + pub(crate) fn probe(&mut self, vid: ty::TyVid) -> TypeVariableValue<'tcx> { self.inlined_probe(vid) } /// An always-inlined variant of `probe`, for very hot call sites. #[inline(always)] - pub fn inlined_probe(&mut self, vid: ty::TyVid) -> TypeVariableValue<'tcx> { + pub(crate) fn inlined_probe(&mut self, vid: ty::TyVid) -> TypeVariableValue<'tcx> { self.eq_relations().inlined_probe_value(vid) } - /// If `t` is a type-inference variable, and it has been - /// instantiated, then return the with which it was - /// instantiated. Otherwise, returns `t`. - pub fn replace_if_possible(&mut self, t: Ty<'tcx>) -> Ty<'tcx> { - match *t.kind() { - ty::Infer(ty::TyVar(v)) => match self.probe(v) { - TypeVariableValue::Unknown { .. } => t, - TypeVariableValue::Known { value } => value, - }, - _ => t, - } - } - #[inline] fn eq_relations(&mut self) -> super::UnificationTable<'_, 'tcx, TyVidEqKey<'tcx>> { self.storage.eq_relations.with_log(self.undo_log) } /// Returns a range of the type variables created during the snapshot. - pub fn vars_since_snapshot( + pub(crate) fn vars_since_snapshot( &mut self, value_count: usize, ) -> (Range, Vec) { @@ -215,7 +202,7 @@ impl<'tcx> TypeVariableTable<'_, 'tcx> { /// Returns indices of all variables that are not yet /// instantiated. - pub fn unresolved_variables(&mut self) -> Vec { + pub(crate) fn unresolved_variables(&mut self) -> Vec { (0..self.num_vars()) .filter_map(|i| { let vid = ty::TyVid::from_usize(i); From 5c015eed473ff648ed5febc1f8eac4d0553af845 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 1 Oct 2024 16:36:38 +1000 Subject: [PATCH 1952/2194] Remove unused `UnitResult` type. --- compiler/rustc_infer/src/infer/mod.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index 87dae0c1e0960..c98604de83925 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -50,7 +50,6 @@ use snapshot::undo_log::InferCtxtUndoLogs; use tracing::{debug, instrument}; use type_variable::TypeVariableOrigin; -use crate::infer::relate::RelateResult; use crate::traits::{self, ObligationCause, ObligationInspector, PredicateObligation, TraitEngine}; pub mod at; @@ -76,7 +75,6 @@ pub struct InferOk<'tcx, T> { } pub type InferResult<'tcx, T> = Result, TypeError<'tcx>>; -pub type UnitResult<'tcx> = RelateResult<'tcx, ()>; // "unify result" pub type FixupResult = Result; // "fixup result" pub(crate) type UnificationTable<'a, 'tcx, T> = ut::UnificationTable< From 2d2755ff97d4c1909dfcd3e2c1fce806a6550919 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 1 Oct 2024 16:40:22 +1000 Subject: [PATCH 1953/2194] Reduce visibilities some more. It helps people reading the code understand how widely things are used. --- compiler/rustc_infer/src/infer/mod.rs | 9 +++++---- .../rustc_infer/src/infer/opaque_types/table.rs | 2 +- compiler/rustc_infer/src/infer/outlives/mod.rs | 2 +- .../rustc_infer/src/infer/outlives/verify.rs | 12 ++++++------ .../src/infer/region_constraints/mod.rs | 2 +- compiler/rustc_infer/src/infer/relate/combine.rs | 16 ++++++++-------- compiler/rustc_infer/src/infer/relate/mod.rs | 2 +- .../src/infer/relate/type_relating.rs | 4 ++-- compiler/rustc_infer/src/infer/snapshot/mod.rs | 2 +- 9 files changed, 26 insertions(+), 25 deletions(-) diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index c98604de83925..8714e85411493 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -14,7 +14,8 @@ use region_constraints::{ GenericKind, RegionConstraintCollector, RegionConstraintStorage, VarInfos, VerifyBound, }; pub use relate::StructurallyRelateAliases; -pub use relate::combine::{CombineFields, PredicateEmittingRelation}; +use relate::combine::CombineFields; +pub use relate::combine::PredicateEmittingRelation; use rustc_data_structures::captures::Captures; use rustc_data_structures::fx::{FxHashSet, FxIndexMap}; use rustc_data_structures::sync::Lrc; @@ -75,7 +76,7 @@ pub struct InferOk<'tcx, T> { } pub type InferResult<'tcx, T> = Result, TypeError<'tcx>>; -pub type FixupResult = Result; // "fixup result" +pub(crate) type FixupResult = Result; // "fixup result" pub(crate) type UnificationTable<'a, 'tcx, T> = ut::UnificationTable< ut::InPlace, &'a mut InferCtxtUndoLogs<'tcx>>, @@ -200,7 +201,7 @@ impl<'tcx> InferCtxtInner<'tcx> { } #[inline] - pub fn opaque_types(&mut self) -> opaque_types::OpaqueTypeTable<'_, 'tcx> { + fn opaque_types(&mut self) -> opaque_types::OpaqueTypeTable<'_, 'tcx> { self.opaque_type_storage.with_log(&mut self.undo_log) } @@ -1351,7 +1352,7 @@ impl<'tcx> InferCtxt<'tcx> { } /// See the [`region_constraints::RegionConstraintCollector::verify_generic_bound`] method. - pub fn verify_generic_bound( + pub(crate) fn verify_generic_bound( &self, origin: SubregionOrigin<'tcx>, kind: GenericKind<'tcx>, diff --git a/compiler/rustc_infer/src/infer/opaque_types/table.rs b/compiler/rustc_infer/src/infer/opaque_types/table.rs index 6e4cc65bec339..047d8edad3de7 100644 --- a/compiler/rustc_infer/src/infer/opaque_types/table.rs +++ b/compiler/rustc_infer/src/infer/opaque_types/table.rs @@ -46,7 +46,7 @@ impl<'tcx> Drop for OpaqueTypeStorage<'tcx> { } } -pub struct OpaqueTypeTable<'a, 'tcx> { +pub(crate) struct OpaqueTypeTable<'a, 'tcx> { storage: &'a mut OpaqueTypeStorage<'tcx>, undo_log: &'a mut InferCtxtUndoLogs<'tcx>, diff --git a/compiler/rustc_infer/src/infer/outlives/mod.rs b/compiler/rustc_infer/src/infer/outlives/mod.rs index f5c873b037552..a270f9322f39b 100644 --- a/compiler/rustc_infer/src/infer/outlives/mod.rs +++ b/compiler/rustc_infer/src/infer/outlives/mod.rs @@ -14,7 +14,7 @@ pub mod env; pub mod for_liveness; pub mod obligations; pub mod test_type_match; -pub mod verify; +pub(crate) mod verify; #[instrument(level = "debug", skip(param_env), ret)] pub fn explicit_outlives_bounds<'tcx>( diff --git a/compiler/rustc_infer/src/infer/outlives/verify.rs b/compiler/rustc_infer/src/infer/outlives/verify.rs index 74a80a1b9aa7c..247fbc259652e 100644 --- a/compiler/rustc_infer/src/infer/outlives/verify.rs +++ b/compiler/rustc_infer/src/infer/outlives/verify.rs @@ -15,7 +15,7 @@ use crate::infer::{GenericKind, VerifyBound}; /// via a "delegate" of type `D` -- this is usually the `infcx`, which /// accrues them into the `region_obligations` code, but for NLL we /// use something else. -pub struct VerifyBoundCx<'cx, 'tcx> { +pub(crate) struct VerifyBoundCx<'cx, 'tcx> { tcx: TyCtxt<'tcx>, region_bound_pairs: &'cx RegionBoundPairs<'tcx>, /// During borrowck, if there are no outlives bounds on a generic @@ -28,7 +28,7 @@ pub struct VerifyBoundCx<'cx, 'tcx> { } impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> { - pub fn new( + pub(crate) fn new( tcx: TyCtxt<'tcx>, region_bound_pairs: &'cx RegionBoundPairs<'tcx>, implicit_region_bound: Option>, @@ -38,7 +38,7 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> { } #[instrument(level = "debug", skip(self))] - pub fn param_or_placeholder_bound(&self, ty: Ty<'tcx>) -> VerifyBound<'tcx> { + pub(crate) fn param_or_placeholder_bound(&self, ty: Ty<'tcx>) -> VerifyBound<'tcx> { // Start with anything like `T: 'a` we can scrape from the // environment. If the environment contains something like // `for<'a> T: 'a`, then we know that `T` outlives everything. @@ -92,7 +92,7 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> { /// the clause from the environment only applies if `'0 = 'a`, /// which we don't know yet. But we would still include `'b` in /// this list. - pub fn approx_declared_bounds_from_env( + pub(crate) fn approx_declared_bounds_from_env( &self, alias_ty: ty::AliasTy<'tcx>, ) -> Vec> { @@ -101,7 +101,7 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> { } #[instrument(level = "debug", skip(self))] - pub fn alias_bound(&self, alias_ty: ty::AliasTy<'tcx>) -> VerifyBound<'tcx> { + pub(crate) fn alias_bound(&self, alias_ty: ty::AliasTy<'tcx>) -> VerifyBound<'tcx> { let alias_ty_as_ty = alias_ty.to_ty(self.tcx); // Search the env for where clauses like `P: 'a`. @@ -285,7 +285,7 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> { /// /// This is for simplicity, and because we are not really smart /// enough to cope with such bounds anywhere. - pub fn declared_bounds_from_definition( + pub(crate) fn declared_bounds_from_definition( &self, alias_ty: ty::AliasTy<'tcx>, ) -> impl Iterator> { diff --git a/compiler/rustc_infer/src/infer/region_constraints/mod.rs b/compiler/rustc_infer/src/infer/region_constraints/mod.rs index 82f7668b2d2ec..a6d1d05f6e1c8 100644 --- a/compiler/rustc_infer/src/infer/region_constraints/mod.rs +++ b/compiler/rustc_infer/src/infer/region_constraints/mod.rs @@ -304,7 +304,7 @@ pub struct RegionVariableInfo { pub universe: ty::UniverseIndex, } -pub struct RegionSnapshot { +pub(crate) struct RegionSnapshot { any_unifications: bool, } diff --git a/compiler/rustc_infer/src/infer/relate/combine.rs b/compiler/rustc_infer/src/infer/relate/combine.rs index 4a8c7387ddc6c..450437f217647 100644 --- a/compiler/rustc_infer/src/infer/relate/combine.rs +++ b/compiler/rustc_infer/src/infer/relate/combine.rs @@ -33,7 +33,7 @@ use crate::infer::{DefineOpaqueTypes, InferCtxt, TypeTrace, relate}; use crate::traits::{Obligation, PredicateObligation}; #[derive(Clone)] -pub struct CombineFields<'infcx, 'tcx> { +pub(crate) struct CombineFields<'infcx, 'tcx> { pub infcx: &'infcx InferCtxt<'tcx>, // Immutable fields pub trace: TypeTrace<'tcx>, @@ -47,7 +47,7 @@ pub struct CombineFields<'infcx, 'tcx> { } impl<'infcx, 'tcx> CombineFields<'infcx, 'tcx> { - pub fn new( + pub(crate) fn new( infcx: &'infcx InferCtxt<'tcx>, trace: TypeTrace<'tcx>, param_env: ty::ParamEnv<'tcx>, @@ -283,22 +283,22 @@ impl<'tcx> InferCtxt<'tcx> { } impl<'infcx, 'tcx> CombineFields<'infcx, 'tcx> { - pub fn tcx(&self) -> TyCtxt<'tcx> { + pub(crate) fn tcx(&self) -> TyCtxt<'tcx> { self.infcx.tcx } - pub fn equate<'a>( + pub(crate) fn equate<'a>( &'a mut self, structurally_relate_aliases: StructurallyRelateAliases, ) -> TypeRelating<'a, 'infcx, 'tcx> { TypeRelating::new(self, structurally_relate_aliases, ty::Invariant) } - pub fn sub<'a>(&'a mut self) -> TypeRelating<'a, 'infcx, 'tcx> { + pub(crate) fn sub<'a>(&'a mut self) -> TypeRelating<'a, 'infcx, 'tcx> { TypeRelating::new(self, StructurallyRelateAliases::No, ty::Covariant) } - pub fn sup<'a>(&'a mut self) -> TypeRelating<'a, 'infcx, 'tcx> { + pub(crate) fn sup<'a>(&'a mut self) -> TypeRelating<'a, 'infcx, 'tcx> { TypeRelating::new(self, StructurallyRelateAliases::No, ty::Contravariant) } @@ -310,14 +310,14 @@ impl<'infcx, 'tcx> CombineFields<'infcx, 'tcx> { LatticeOp::new(self, LatticeOpKind::Glb) } - pub fn register_obligations( + pub(crate) fn register_obligations( &mut self, obligations: impl IntoIterator>>, ) { self.goals.extend(obligations); } - pub fn register_predicates( + pub(crate) fn register_predicates( &mut self, obligations: impl IntoIterator, ty::Predicate<'tcx>>>, ) { diff --git a/compiler/rustc_infer/src/infer/relate/mod.rs b/compiler/rustc_infer/src/infer/relate/mod.rs index edc0c4f078ab2..85158faa65d13 100644 --- a/compiler/rustc_infer/src/infer/relate/mod.rs +++ b/compiler/rustc_infer/src/infer/relate/mod.rs @@ -5,7 +5,7 @@ pub use rustc_middle::ty::relate::RelateResult; pub use rustc_next_trait_solver::relate::*; -pub use self::combine::{CombineFields, PredicateEmittingRelation}; +pub use self::combine::PredicateEmittingRelation; #[allow(hidden_glob_reexports)] pub(super) mod combine; diff --git a/compiler/rustc_infer/src/infer/relate/type_relating.rs b/compiler/rustc_infer/src/infer/relate/type_relating.rs index 7acfea643dd1e..7537ceec307a3 100644 --- a/compiler/rustc_infer/src/infer/relate/type_relating.rs +++ b/compiler/rustc_infer/src/infer/relate/type_relating.rs @@ -13,7 +13,7 @@ use crate::infer::relate::{PredicateEmittingRelation, StructurallyRelateAliases} use crate::infer::{DefineOpaqueTypes, InferCtxt, SubregionOrigin}; /// Enforce that `a` is equal to or a subtype of `b`. -pub struct TypeRelating<'combine, 'a, 'tcx> { +pub(crate) struct TypeRelating<'combine, 'a, 'tcx> { // Immutable except for the `InferCtxt` and the // resulting nested `goals`. fields: &'combine mut CombineFields<'a, 'tcx>, @@ -49,7 +49,7 @@ pub struct TypeRelating<'combine, 'a, 'tcx> { } impl<'combine, 'infcx, 'tcx> TypeRelating<'combine, 'infcx, 'tcx> { - pub fn new( + pub(crate) fn new( f: &'combine mut CombineFields<'infcx, 'tcx>, structurally_relate_aliases: StructurallyRelateAliases, ambient_variance: ty::Variance, diff --git a/compiler/rustc_infer/src/infer/snapshot/mod.rs b/compiler/rustc_infer/src/infer/snapshot/mod.rs index 964fb1f681955..07a482c2f9ac3 100644 --- a/compiler/rustc_infer/src/infer/snapshot/mod.rs +++ b/compiler/rustc_infer/src/infer/snapshot/mod.rs @@ -5,7 +5,7 @@ use tracing::{debug, instrument}; use super::InferCtxt; use super::region_constraints::RegionSnapshot; -mod fudge; +pub(crate) mod fudge; pub(crate) mod undo_log; use undo_log::{Snapshot, UndoLog}; From 25d1ef199353b395e60fb75937a8b4837cd3a9c4 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 1 Oct 2024 17:10:39 +1000 Subject: [PATCH 1954/2194] Remove `InferCtxt::err_count_on_creation`. It's no longer used meaningfully. This also means `DiagCtxtHandle::err_count_excluding_lint_errs` can be removed. --- compiler/rustc_errors/src/lib.rs | 12 ------------ compiler/rustc_infer/src/infer/at.rs | 1 - compiler/rustc_infer/src/infer/mod.rs | 20 +++----------------- 3 files changed, 3 insertions(+), 30 deletions(-) diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index 39acacfbe59c8..10ec521908e95 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -925,18 +925,6 @@ impl<'a> DiagCtxtHandle<'a> { self.inner.borrow_mut().emit_stashed_diagnostics() } - /// This excludes lint errors, and delayed bugs. - #[inline] - pub fn err_count_excluding_lint_errs(&self) -> usize { - let inner = self.inner.borrow(); - inner.err_guars.len() - + inner - .stashed_diagnostics - .values() - .filter(|(diag, guar)| guar.is_some() && diag.is_lint.is_none()) - .count() - } - /// This excludes delayed bugs. #[inline] pub fn err_count(&self) -> usize { diff --git a/compiler/rustc_infer/src/infer/at.rs b/compiler/rustc_infer/src/infer/at.rs index 6ce47db8b9bd2..f80737d1269c5 100644 --- a/compiler/rustc_infer/src/infer/at.rs +++ b/compiler/rustc_infer/src/infer/at.rs @@ -82,7 +82,6 @@ impl<'tcx> InferCtxt<'tcx> { reported_trait_errors: self.reported_trait_errors.clone(), reported_signature_mismatch: self.reported_signature_mismatch.clone(), tainted_by_errors: self.tainted_by_errors.clone(), - err_count_on_creation: self.err_count_on_creation, universe: self.universe.clone(), intercrate, next_trait_solver: self.next_trait_solver, diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index 8714e85411493..45b28b98c9460 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -279,27 +279,14 @@ pub struct InferCtxt<'tcx> { pub reported_signature_mismatch: RefCell)>>, /// When an error occurs, we want to avoid reporting "derived" - /// errors that are due to this original failure. Normally, we - /// handle this with the `err_count_on_creation` count, which - /// basically just tracks how many errors were reported when we - /// started type-checking a fn and checks to see if any new errors - /// have been reported since then. Not great, but it works. - /// - /// However, when errors originated in other passes -- notably - /// resolve -- this heuristic breaks down. Therefore, we have this - /// auxiliary flag that one can set whenever one creates a - /// type-error that is due to an error in a prior pass. + /// errors that are due to this original failure. We have this + /// flag that one can set whenever one creates a type-error that + /// is due to an error in a prior pass. /// /// Don't read this flag directly, call `is_tainted_by_errors()` /// and `set_tainted_by_errors()`. tainted_by_errors: Cell>, - /// Track how many errors were reported when this infcx is created. - /// If the number of errors increases, that's also a sign (like - /// `tainted_by_errors`) to avoid reporting certain kinds of errors. - // FIXME(matthewjasper) Merge into `tainted_by_errors` - err_count_on_creation: usize, - /// What is the innermost universe we have created? Starts out as /// `UniverseIndex::root()` but grows from there as we enter /// universal quantifiers. @@ -656,7 +643,6 @@ impl<'tcx> InferCtxtBuilder<'tcx> { reported_trait_errors: Default::default(), reported_signature_mismatch: Default::default(), tainted_by_errors: Cell::new(None), - err_count_on_creation: tcx.dcx().err_count_excluding_lint_errs(), universe: Cell::new(ty::UniverseIndex::ROOT), intercrate, next_trait_solver, From 0ca4784c45665a0267314ddd2a12c6710fbbe2c0 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 1 Oct 2024 17:58:49 +1000 Subject: [PATCH 1955/2194] Fix `FIXME` comment on `FixupError`. `FixupError` is isomorphic with `TyOrConstInferVar`, so this commit changes it to just be a wrapper around `TyOrConstInferVar`. Also, move the `Display` impl for `FixupError` next to `FixupError`. --- compiler/rustc_infer/src/infer/mod.rs | 39 ++++++++++------------- compiler/rustc_infer/src/infer/resolve.rs | 12 ++++--- 2 files changed, 24 insertions(+), 27 deletions(-) diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index 45b28b98c9460..dbdcc3e2a8a04 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -495,46 +495,41 @@ pub enum NllRegionVariableOrigin { }, } -// FIXME(eddyb) investigate overlap between this and `TyOrConstInferVar`. #[derive(Copy, Clone, Debug)] -pub enum FixupError { - UnresolvedIntTy(IntVid), - UnresolvedFloatTy(FloatVid), - UnresolvedTy(TyVid), - UnresolvedConst(ConstVid), - UnresolvedEffect(EffectVid), -} - -/// See the `region_obligations` field for more information. -#[derive(Clone, Debug)] -pub struct RegionObligation<'tcx> { - pub sub_region: ty::Region<'tcx>, - pub sup_type: Ty<'tcx>, - pub origin: SubregionOrigin<'tcx>, +pub struct FixupError { + unresolved: TyOrConstInferVar, } impl fmt::Display for FixupError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - use self::FixupError::*; + use TyOrConstInferVar::*; - match *self { - UnresolvedIntTy(_) => write!( + match self.unresolved { + TyInt(_) => write!( f, "cannot determine the type of this integer; \ add a suffix to specify the type explicitly" ), - UnresolvedFloatTy(_) => write!( + TyFloat(_) => write!( f, "cannot determine the type of this number; \ add a suffix to specify the type explicitly" ), - UnresolvedTy(_) => write!(f, "unconstrained type"), - UnresolvedConst(_) => write!(f, "unconstrained const value"), - UnresolvedEffect(_) => write!(f, "unconstrained effect value"), + Ty(_) => write!(f, "unconstrained type"), + Const(_) => write!(f, "unconstrained const value"), + Effect(_) => write!(f, "unconstrained effect value"), } } } +/// See the `region_obligations` field for more information. +#[derive(Clone, Debug)] +pub struct RegionObligation<'tcx> { + pub sub_region: ty::Region<'tcx>, + pub sup_type: Ty<'tcx>, + pub origin: SubregionOrigin<'tcx>, +} + /// Used to configure inference contexts before their creation. pub struct InferCtxtBuilder<'tcx> { tcx: TyCtxt<'tcx>, diff --git a/compiler/rustc_infer/src/infer/resolve.rs b/compiler/rustc_infer/src/infer/resolve.rs index 671a66d504f9d..2c7b35af94760 100644 --- a/compiler/rustc_infer/src/infer/resolve.rs +++ b/compiler/rustc_infer/src/infer/resolve.rs @@ -138,11 +138,13 @@ impl<'a, 'tcx> FallibleTypeFolder> for FullTypeResolver<'a, 'tcx> { if !t.has_infer() { Ok(t) // micro-optimize -- if there is nothing in this type that this fold affects... } else { + use super::TyOrConstInferVar::*; + let t = self.infcx.shallow_resolve(t); match *t.kind() { - ty::Infer(ty::TyVar(vid)) => Err(FixupError::UnresolvedTy(vid)), - ty::Infer(ty::IntVar(vid)) => Err(FixupError::UnresolvedIntTy(vid)), - ty::Infer(ty::FloatVar(vid)) => Err(FixupError::UnresolvedFloatTy(vid)), + ty::Infer(ty::TyVar(vid)) => Err(FixupError { unresolved: Ty(vid) }), + ty::Infer(ty::IntVar(vid)) => Err(FixupError { unresolved: TyInt(vid) }), + ty::Infer(ty::FloatVar(vid)) => Err(FixupError { unresolved: TyFloat(vid) }), ty::Infer(_) => { bug!("Unexpected type in full type resolver: {:?}", t); } @@ -171,13 +173,13 @@ impl<'a, 'tcx> FallibleTypeFolder> for FullTypeResolver<'a, 'tcx> { let c = self.infcx.shallow_resolve_const(c); match c.kind() { ty::ConstKind::Infer(InferConst::Var(vid)) => { - return Err(FixupError::UnresolvedConst(vid)); + return Err(FixupError { unresolved: super::TyOrConstInferVar::Const(vid) }); } ty::ConstKind::Infer(InferConst::Fresh(_)) => { bug!("Unexpected const in full const resolver: {:?}", c); } ty::ConstKind::Infer(InferConst::EffectVar(evid)) => { - return Err(FixupError::UnresolvedEffect(evid)); + return Err(FixupError { unresolved: super::TyOrConstInferVar::Effect(evid) }); } _ => {} } From deeb0c5cf3737d2a681334befee694cc5aa005b8 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 2 Oct 2024 08:41:38 +1000 Subject: [PATCH 1956/2194] Inline and remove `InferCtxtBuilder::with_defining_opaque_types`. It has a single use. --- compiler/rustc_infer/src/infer/mod.rs | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index dbdcc3e2a8a04..7238c670be9c2 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -569,14 +569,6 @@ impl<'tcx> InferCtxtBuilder<'tcx> { self } - pub fn with_defining_opaque_types( - mut self, - defining_opaque_types: &'tcx ty::List, - ) -> Self { - self.defining_opaque_types = defining_opaque_types; - self - } - pub fn with_next_trait_solver(mut self, next_trait_solver: bool) -> Self { self.next_trait_solver = next_trait_solver; self @@ -605,14 +597,15 @@ impl<'tcx> InferCtxtBuilder<'tcx> { /// the bound values in `C` to their instantiated values in `V` /// (in other words, `S(C) = V`). pub fn build_with_canonical( - self, + mut self, span: Span, canonical: &Canonical<'tcx, T>, ) -> (InferCtxt<'tcx>, T, CanonicalVarValues<'tcx>) where T: TypeFoldable>, { - let infcx = self.with_defining_opaque_types(canonical.defining_opaque_types).build(); + self.defining_opaque_types = canonical.defining_opaque_types; + let infcx = self.build(); let (value, args) = infcx.instantiate_canonical(span, canonical); (infcx, value, args) } From 3386530c9166f5b1177f81fb2037dd0e0b5a50f1 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 2 Oct 2024 14:01:07 +1000 Subject: [PATCH 1957/2194] Streamline `next_*_var*` methods. Inline and remove `next_const_var_id`, `next_int_var_id`, `next_float_var_id`, all of which have a single call site. --- compiler/rustc_infer/src/infer/mod.rs | 24 ++++++------------------ 1 file changed, 6 insertions(+), 18 deletions(-) diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index 7238c670be9c2..89dfa01925368 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -892,28 +892,16 @@ impl<'tcx> InferCtxt<'tcx> { ty::Const::new_var(self.tcx, vid) } - pub fn next_const_var_id(&self, origin: ConstVariableOrigin) -> ConstVid { - self.inner - .borrow_mut() - .const_unification_table() - .new_key(ConstVariableValue::Unknown { origin, universe: self.universe() }) - .vid - } - - fn next_int_var_id(&self) -> IntVid { - self.inner.borrow_mut().int_unification_table().new_key(ty::IntVarValue::Unknown) - } - pub fn next_int_var(&self) -> Ty<'tcx> { - Ty::new_int_var(self.tcx, self.next_int_var_id()) - } - - fn next_float_var_id(&self) -> FloatVid { - self.inner.borrow_mut().float_unification_table().new_key(ty::FloatVarValue::Unknown) + let next_int_var_id = + self.inner.borrow_mut().int_unification_table().new_key(ty::IntVarValue::Unknown); + Ty::new_int_var(self.tcx, next_int_var_id) } pub fn next_float_var(&self) -> Ty<'tcx> { - Ty::new_float_var(self.tcx, self.next_float_var_id()) + let next_float_var_id = + self.inner.borrow_mut().float_unification_table().new_key(ty::FloatVarValue::Unknown); + Ty::new_float_var(self.tcx, next_float_var_id) } /// Creates a fresh region variable with the next available index. From e80096747853fc5a0c8a98e8532c2f74ba770aa2 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 2 Oct 2024 14:33:48 +1000 Subject: [PATCH 1958/2194] Simplify two matches. Matches involving `GenericArgKind` pairs typically use a single `_` for the impossible case. This commit shortens two verbose matches in this way. --- compiler/rustc_infer/src/infer/at.rs | 16 +--------------- compiler/rustc_middle/src/ty/relate.rs | 10 +--------- 2 files changed, 2 insertions(+), 24 deletions(-) diff --git a/compiler/rustc_infer/src/infer/at.rs b/compiler/rustc_infer/src/infer/at.rs index f80737d1269c5..183973af4f9f3 100644 --- a/compiler/rustc_infer/src/infer/at.rs +++ b/compiler/rustc_infer/src/infer/at.rs @@ -381,21 +381,7 @@ impl<'tcx> ToTrace<'tcx> for ty::GenericArg<'tcx> { (GenericArgKind::Const(a), GenericArgKind::Const(b)) => { ValuePairs::Terms(ExpectedFound::new(true, a.into(), b.into())) } - - ( - GenericArgKind::Lifetime(_), - GenericArgKind::Type(_) | GenericArgKind::Const(_), - ) - | ( - GenericArgKind::Type(_), - GenericArgKind::Lifetime(_) | GenericArgKind::Const(_), - ) - | ( - GenericArgKind::Const(_), - GenericArgKind::Lifetime(_) | GenericArgKind::Type(_), - ) => { - bug!("relating different kinds: {a:?} {b:?}") - } + _ => bug!("relating different kinds: {a:?} {b:?}"), }, } } diff --git a/compiler/rustc_middle/src/ty/relate.rs b/compiler/rustc_middle/src/ty/relate.rs index 61c03922ac05f..4c7bcb1bf2e88 100644 --- a/compiler/rustc_middle/src/ty/relate.rs +++ b/compiler/rustc_middle/src/ty/relate.rs @@ -212,15 +212,7 @@ impl<'tcx> Relate> for ty::GenericArg<'tcx> { (ty::GenericArgKind::Const(a_ct), ty::GenericArgKind::Const(b_ct)) => { Ok(relation.relate(a_ct, b_ct)?.into()) } - (ty::GenericArgKind::Lifetime(unpacked), x) => { - bug!("impossible case reached: can't relate: {:?} with {:?}", unpacked, x) - } - (ty::GenericArgKind::Type(unpacked), x) => { - bug!("impossible case reached: can't relate: {:?} with {:?}", unpacked, x) - } - (ty::GenericArgKind::Const(unpacked), x) => { - bug!("impossible case reached: can't relate: {:?} with {:?}", unpacked, x) - } + _ => bug!("impossible case reached: can't relate: {a:?} with {b:?}"), } } } From afbff05c84c8c22909be929d20d6075f53d51e12 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 2 Oct 2024 16:52:55 +1000 Subject: [PATCH 1959/2194] Move a `use` statement so it's with the other `use` statements. --- compiler/rustc_infer/src/infer/opaque_types/mod.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/compiler/rustc_infer/src/infer/opaque_types/mod.rs b/compiler/rustc_infer/src/infer/opaque_types/mod.rs index 0c5eca6ebdfd9..d3afabdb7da0e 100644 --- a/compiler/rustc_infer/src/infer/opaque_types/mod.rs +++ b/compiler/rustc_infer/src/infer/opaque_types/mod.rs @@ -13,6 +13,7 @@ use rustc_middle::ty::{ use rustc_span::Span; use tracing::{debug, instrument}; +use super::DefineOpaqueTypes; use crate::errors::OpaqueHiddenTypeDiag; use crate::infer::{InferCtxt, InferOk}; use crate::traits::{self, Obligation}; @@ -22,8 +23,6 @@ mod table; pub(crate) type OpaqueTypeMap<'tcx> = FxIndexMap, OpaqueTypeDecl<'tcx>>; pub(crate) use table::{OpaqueTypeStorage, OpaqueTypeTable}; -use super::DefineOpaqueTypes; - /// Information about the opaque types whose values we /// are inferring in this function (these are the `impl Trait` that /// appear in the return type). From 3fdcde76d9bcbf31e2409aefede4dd8b2f7c315f Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 7 Oct 2024 09:40:52 +1100 Subject: [PATCH 1960/2194] Remove out-of-date comment. --- compiler/rustc_infer/src/infer/resolve.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/compiler/rustc_infer/src/infer/resolve.rs b/compiler/rustc_infer/src/infer/resolve.rs index 2c7b35af94760..025c3a629fabf 100644 --- a/compiler/rustc_infer/src/infer/resolve.rs +++ b/compiler/rustc_infer/src/infer/resolve.rs @@ -121,8 +121,6 @@ where value.try_fold_with(&mut FullTypeResolver { infcx }) } -// N.B. This type is not public because the protocol around checking the -// `err` field is not enforceable otherwise. struct FullTypeResolver<'a, 'tcx> { infcx: &'a InferCtxt<'tcx>, } From d793766a6199d9b7339633ad0296af63c7b4f9b8 Mon Sep 17 00:00:00 2001 From: Nathan Perry Date: Tue, 30 Jul 2024 09:48:36 -0400 Subject: [PATCH 1961/2194] liballoc: introduce String, Vec const-slicing This change `const`-qualifies many methods on Vec and String, notably `as_slice`, `as_str`, `len`. These changes are made behind the unstable feature flag `const_vec_string_slice` with the following tracking issue: https://github.com/rust-lang/rust/issues/129041 --- library/alloc/src/lib.rs | 1 + library/alloc/src/raw_vec.rs | 12 +-- library/alloc/src/string.rs | 38 +++++--- library/alloc/src/vec/mod.rs | 55 ++++++++--- ..._to_slice.PreCodegen.after.panic-abort.mir | 91 +++++++++---------- ...to_slice.PreCodegen.after.panic-unwind.mir | 91 +++++++++---------- tests/ui/consts/issue-94675.rs | 2 +- tests/ui/consts/issue-94675.stderr | 10 +- 8 files changed, 164 insertions(+), 136 deletions(-) diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs index f0597f295b3f0..4a09b5dfd17b5 100644 --- a/library/alloc/src/lib.rs +++ b/library/alloc/src/lib.rs @@ -114,6 +114,7 @@ #![feature(const_option)] #![feature(const_pin)] #![feature(const_size_of_val)] +#![feature(const_vec_string_slice)] #![feature(core_intrinsics)] #![feature(deprecated_suggestion)] #![feature(deref_pure_trait)] diff --git a/library/alloc/src/raw_vec.rs b/library/alloc/src/raw_vec.rs index 436e0596e3d5e..8fdca8c420036 100644 --- a/library/alloc/src/raw_vec.rs +++ b/library/alloc/src/raw_vec.rs @@ -280,7 +280,7 @@ impl RawVec { /// `Unique::dangling()` if `capacity == 0` or `T` is zero-sized. In the former case, you must /// be careful. #[inline] - pub fn ptr(&self) -> *mut T { + pub const fn ptr(&self) -> *mut T { self.inner.ptr() } @@ -293,7 +293,7 @@ impl RawVec { /// /// This will always be `usize::MAX` if `T` is zero-sized. #[inline] - pub fn capacity(&self) -> usize { + pub const fn capacity(&self) -> usize { self.inner.capacity(size_of::()) } @@ -488,17 +488,17 @@ impl RawVecInner { } #[inline] - fn ptr(&self) -> *mut T { + const fn ptr(&self) -> *mut T { self.non_null::().as_ptr() } #[inline] - fn non_null(&self) -> NonNull { - self.ptr.cast().into() + const fn non_null(&self) -> NonNull { + self.ptr.cast().as_non_null_ptr() } #[inline] - fn capacity(&self, elem_size: usize) -> usize { + const fn capacity(&self, elem_size: usize) -> usize { if elem_size == 0 { usize::MAX } else { self.cap.0 } } diff --git a/library/alloc/src/string.rs b/library/alloc/src/string.rs index d58a016b502ca..2815ea4da7fea 100644 --- a/library/alloc/src/string.rs +++ b/library/alloc/src/string.rs @@ -1059,7 +1059,8 @@ impl String { #[inline] #[must_use = "`self` will be dropped if the result is not used"] #[stable(feature = "rust1", since = "1.0.0")] - pub fn into_bytes(self) -> Vec { + #[rustc_const_unstable(feature = "const_vec_string_slice", issue = "129041")] + pub const fn into_bytes(self) -> Vec { self.vec } @@ -1076,8 +1077,11 @@ impl String { #[must_use] #[stable(feature = "string_as_str", since = "1.7.0")] #[cfg_attr(not(test), rustc_diagnostic_item = "string_as_str")] - pub fn as_str(&self) -> &str { - self + #[rustc_const_unstable(feature = "const_vec_string_slice", issue = "129041")] + pub const fn as_str(&self) -> &str { + // SAFETY: String contents are stipulated to be valid UTF-8, invalid contents are an error + // at construction. + unsafe { str::from_utf8_unchecked(self.vec.as_slice()) } } /// Converts a `String` into a mutable string slice. @@ -1096,8 +1100,11 @@ impl String { #[must_use] #[stable(feature = "string_as_str", since = "1.7.0")] #[cfg_attr(not(test), rustc_diagnostic_item = "string_as_mut_str")] - pub fn as_mut_str(&mut self) -> &mut str { - self + #[rustc_const_unstable(feature = "const_vec_string_slice", issue = "129041")] + pub const fn as_mut_str(&mut self) -> &mut str { + // SAFETY: String contents are stipulated to be valid UTF-8, invalid contents are an error + // at construction. + unsafe { str::from_utf8_unchecked_mut(self.vec.as_mut_slice()) } } /// Appends a given string slice onto the end of this `String`. @@ -1168,7 +1175,8 @@ impl String { #[inline] #[must_use] #[stable(feature = "rust1", since = "1.0.0")] - pub fn capacity(&self) -> usize { + #[rustc_const_unstable(feature = "const_vec_string_slice", issue = "129041")] + pub const fn capacity(&self) -> usize { self.vec.capacity() } @@ -1431,8 +1439,9 @@ impl String { #[inline] #[must_use] #[stable(feature = "rust1", since = "1.0.0")] - pub fn as_bytes(&self) -> &[u8] { - &self.vec + #[rustc_const_unstable(feature = "const_vec_string_slice", issue = "129041")] + pub const fn as_bytes(&self) -> &[u8] { + self.vec.as_slice() } /// Shortens this `String` to the specified length. @@ -1784,7 +1793,8 @@ impl String { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] - pub unsafe fn as_mut_vec(&mut self) -> &mut Vec { + #[rustc_const_unstable(feature = "const_vec_string_slice", issue = "129041")] + pub const unsafe fn as_mut_vec(&mut self) -> &mut Vec { &mut self.vec } @@ -1805,8 +1815,9 @@ impl String { #[inline] #[must_use] #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable(feature = "const_vec_string_slice", issue = "129041")] #[rustc_confusables("length", "size")] - pub fn len(&self) -> usize { + pub const fn len(&self) -> usize { self.vec.len() } @@ -1824,7 +1835,8 @@ impl String { #[inline] #[must_use] #[stable(feature = "rust1", since = "1.0.0")] - pub fn is_empty(&self) -> bool { + #[rustc_const_unstable(feature = "const_vec_string_slice", issue = "129041")] + pub const fn is_empty(&self) -> bool { self.len() == 0 } @@ -2565,7 +2577,7 @@ impl ops::Deref for String { #[inline] fn deref(&self) -> &str { - unsafe { str::from_utf8_unchecked(&self.vec) } + self.as_str() } } @@ -2576,7 +2588,7 @@ unsafe impl ops::DerefPure for String {} impl ops::DerefMut for String { #[inline] fn deref_mut(&mut self) -> &mut str { - unsafe { str::from_utf8_unchecked_mut(&mut *self.vec) } + self.as_mut_str() } } diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index 13b06584223ba..cae47393a8140 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -1240,7 +1240,8 @@ impl Vec { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] - pub fn capacity(&self) -> usize { + #[rustc_const_unstable(feature = "const_vec_string_slice", issue = "129041")] + pub const fn capacity(&self) -> usize { self.buf.capacity() } @@ -1548,8 +1549,22 @@ impl Vec { #[inline] #[stable(feature = "vec_as_slice", since = "1.7.0")] #[cfg_attr(not(test), rustc_diagnostic_item = "vec_as_slice")] - pub fn as_slice(&self) -> &[T] { - self + #[rustc_const_unstable(feature = "const_vec_string_slice", issue = "129041")] + pub const fn as_slice(&self) -> &[T] { + // SAFETY: `slice::from_raw_parts` requires pointee is a contiguous, aligned buffer of size + // `len` containing properly-initialized `T`s. Data must not be mutated for the returned + // lifetime. Further, `len * mem::size_of::` <= `ISIZE::MAX`, and allocation does not + // "wrap" through overflowing memory addresses. + // + // * Vec API guarantees that self.buf: + // * contains only properly-initialized items within 0..len + // * is aligned, contiguous, and valid for `len` reads + // * obeys size and address-wrapping constraints + // + // * We only construct `&mut` references to `self.buf` through `&mut self` methods; borrow- + // check ensures that it is not possible to mutably alias `self.buf` within the + // returned lifetime. + unsafe { slice::from_raw_parts(self.as_ptr(), self.len) } } /// Extracts a mutable slice of the entire vector. @@ -1566,8 +1581,22 @@ impl Vec { #[inline] #[stable(feature = "vec_as_slice", since = "1.7.0")] #[cfg_attr(not(test), rustc_diagnostic_item = "vec_as_mut_slice")] - pub fn as_mut_slice(&mut self) -> &mut [T] { - self + #[rustc_const_unstable(feature = "const_vec_string_slice", issue = "129041")] + pub const fn as_mut_slice(&mut self) -> &mut [T] { + // SAFETY: `slice::from_raw_parts_mut` requires pointee is a contiguous, aligned buffer of + // size `len` containing properly-initialized `T`s. Data must not be accessed through any + // other pointer for the returned lifetime. Further, `len * mem::size_of::` <= + // `ISIZE::MAX` and allocation does not "wrap" through overflowing memory addresses. + // + // * Vec API guarantees that self.buf: + // * contains only properly-initialized items within 0..len + // * is aligned, contiguous, and valid for `len` reads + // * obeys size and address-wrapping constraints + // + // * We only construct references to `self.buf` through `&self` and `&mut self` methods; + // borrow-check ensures that it is not possible to construct a reference to `self.buf` + // within the returned lifetime. + unsafe { slice::from_raw_parts_mut(self.as_mut_ptr(), self.len) } } /// Returns a raw pointer to the vector's buffer, or a dangling raw pointer @@ -1622,9 +1651,10 @@ impl Vec { /// [`as_mut_ptr`]: Vec::as_mut_ptr /// [`as_ptr`]: Vec::as_ptr #[stable(feature = "vec_as_ptr", since = "1.37.0")] + #[rustc_const_unstable(feature = "const_vec_string_slice", issue = "129041")] #[rustc_never_returns_null_ptr] #[inline] - pub fn as_ptr(&self) -> *const T { + pub const fn as_ptr(&self) -> *const T { // We shadow the slice method of the same name to avoid going through // `deref`, which creates an intermediate reference. self.buf.ptr() @@ -1681,9 +1711,10 @@ impl Vec { /// [`as_mut_ptr`]: Vec::as_mut_ptr /// [`as_ptr`]: Vec::as_ptr #[stable(feature = "vec_as_ptr", since = "1.37.0")] + #[rustc_const_unstable(feature = "const_vec_string_slice", issue = "129041")] #[rustc_never_returns_null_ptr] #[inline] - pub fn as_mut_ptr(&mut self) -> *mut T { + pub const fn as_mut_ptr(&mut self) -> *mut T { // We shadow the slice method of the same name to avoid going through // `deref_mut`, which creates an intermediate reference. self.buf.ptr() @@ -2561,8 +2592,9 @@ impl Vec { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable(feature = "const_vec_string_slice", issue = "129041")] #[rustc_confusables("length", "size")] - pub fn len(&self) -> usize { + pub const fn len(&self) -> usize { self.len } @@ -2579,7 +2611,8 @@ impl Vec { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[cfg_attr(not(test), rustc_diagnostic_item = "vec_is_empty")] - pub fn is_empty(&self) -> bool { + #[rustc_const_unstable(feature = "const_vec_string_slice", issue = "129041")] + pub const fn is_empty(&self) -> bool { self.len() == 0 } @@ -3130,7 +3163,7 @@ impl ops::Deref for Vec { #[inline] fn deref(&self) -> &[T] { - unsafe { slice::from_raw_parts(self.as_ptr(), self.len) } + self.as_slice() } } @@ -3138,7 +3171,7 @@ impl ops::Deref for Vec { impl ops::DerefMut for Vec { #[inline] fn deref_mut(&mut self) -> &mut [T] { - unsafe { slice::from_raw_parts_mut(self.as_mut_ptr(), self.len) } + self.as_mut_slice() } } diff --git a/tests/mir-opt/pre-codegen/vec_deref.vec_deref_to_slice.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/vec_deref.vec_deref_to_slice.PreCodegen.after.panic-abort.mir index 0ad7f5910a0b3..4d964b0afb78c 100644 --- a/tests/mir-opt/pre-codegen/vec_deref.vec_deref_to_slice.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/vec_deref.vec_deref_to_slice.PreCodegen.after.panic-abort.mir @@ -5,66 +5,61 @@ fn vec_deref_to_slice(_1: &Vec) -> &[u8] { let mut _0: &[u8]; scope 1 (inlined as Deref>::deref) { debug self => _1; - let mut _6: usize; - scope 2 (inlined Vec::::as_ptr) { + scope 2 (inlined Vec::::as_slice) { debug self => _1; - let mut _2: &alloc::raw_vec::RawVec; - scope 3 (inlined alloc::raw_vec::RawVec::::ptr) { - debug self => _2; - let mut _3: &alloc::raw_vec::RawVecInner; - scope 4 (inlined alloc::raw_vec::RawVecInner::ptr::) { - debug self => _3; - scope 5 (inlined alloc::raw_vec::RawVecInner::non_null::) { + let mut _6: usize; + scope 3 (inlined Vec::::as_ptr) { + debug self => _1; + let mut _2: &alloc::raw_vec::RawVec; + scope 4 (inlined alloc::raw_vec::RawVec::::ptr) { + debug self => _2; + let mut _3: &alloc::raw_vec::RawVecInner; + scope 5 (inlined alloc::raw_vec::RawVecInner::ptr::) { debug self => _3; - let mut _4: std::ptr::NonNull; - scope 6 (inlined Unique::::cast::) { - debug ((self: Unique).0: std::ptr::NonNull) => _4; - debug ((self: Unique).1: std::marker::PhantomData) => const PhantomData::; - scope 7 (inlined NonNull::::cast::) { - debug self => _4; - scope 8 (inlined NonNull::::as_ptr) { + scope 6 (inlined alloc::raw_vec::RawVecInner::non_null::) { + debug self => _3; + let mut _4: std::ptr::NonNull; + scope 7 (inlined Unique::::cast::) { + debug ((self: Unique).0: std::ptr::NonNull) => _4; + debug ((self: Unique).1: std::marker::PhantomData) => const PhantomData::; + scope 8 (inlined NonNull::::cast::) { debug self => _4; - let mut _5: *const u8; + scope 9 (inlined NonNull::::as_ptr) { + debug self => _4; + let mut _5: *const u8; + } } } - } - scope 9 (inlined #[track_caller] as Into>>::into) { - debug ((self: Unique).0: std::ptr::NonNull) => _4; - debug ((self: Unique).1: std::marker::PhantomData) => const PhantomData::; - scope 10 (inlined as From>>::from) { - debug ((unique: Unique).0: std::ptr::NonNull) => _4; - debug ((unique: Unique).1: std::marker::PhantomData) => const PhantomData::; - scope 11 (inlined Unique::::as_non_null_ptr) { - debug ((self: Unique).0: std::ptr::NonNull) => _4; - debug ((self: Unique).1: std::marker::PhantomData) => const PhantomData::; - } + scope 10 (inlined Unique::::as_non_null_ptr) { + debug ((self: Unique).0: std::ptr::NonNull) => _4; + debug ((self: Unique).1: std::marker::PhantomData) => const PhantomData::; } } + scope 11 (inlined NonNull::::as_ptr) { + debug self => _4; + } } - scope 12 (inlined NonNull::::as_ptr) { - debug self => _4; - } - } - } - } - scope 13 (inlined std::slice::from_raw_parts::<'_, u8>) { - debug data => _5; - debug len => _6; - let _7: *const [u8]; - scope 14 (inlined core::ub_checks::check_language_ub) { - scope 15 (inlined core::ub_checks::check_language_ub::runtime) { } } - scope 16 (inlined std::mem::size_of::) { - } - scope 17 (inlined align_of::) { - } - scope 18 (inlined slice_from_raw_parts::) { + scope 12 (inlined std::slice::from_raw_parts::<'_, u8>) { debug data => _5; debug len => _6; - scope 19 (inlined std::ptr::from_raw_parts::<[u8], u8>) { - debug data_pointer => _5; - debug metadata => _6; + let _7: *const [u8]; + scope 13 (inlined core::ub_checks::check_language_ub) { + scope 14 (inlined core::ub_checks::check_language_ub::runtime) { + } + } + scope 15 (inlined std::mem::size_of::) { + } + scope 16 (inlined align_of::) { + } + scope 17 (inlined slice_from_raw_parts::) { + debug data => _5; + debug len => _6; + scope 18 (inlined std::ptr::from_raw_parts::<[u8], u8>) { + debug data_pointer => _5; + debug metadata => _6; + } } } } diff --git a/tests/mir-opt/pre-codegen/vec_deref.vec_deref_to_slice.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/vec_deref.vec_deref_to_slice.PreCodegen.after.panic-unwind.mir index 0ad7f5910a0b3..4d964b0afb78c 100644 --- a/tests/mir-opt/pre-codegen/vec_deref.vec_deref_to_slice.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/vec_deref.vec_deref_to_slice.PreCodegen.after.panic-unwind.mir @@ -5,66 +5,61 @@ fn vec_deref_to_slice(_1: &Vec) -> &[u8] { let mut _0: &[u8]; scope 1 (inlined as Deref>::deref) { debug self => _1; - let mut _6: usize; - scope 2 (inlined Vec::::as_ptr) { + scope 2 (inlined Vec::::as_slice) { debug self => _1; - let mut _2: &alloc::raw_vec::RawVec; - scope 3 (inlined alloc::raw_vec::RawVec::::ptr) { - debug self => _2; - let mut _3: &alloc::raw_vec::RawVecInner; - scope 4 (inlined alloc::raw_vec::RawVecInner::ptr::) { - debug self => _3; - scope 5 (inlined alloc::raw_vec::RawVecInner::non_null::) { + let mut _6: usize; + scope 3 (inlined Vec::::as_ptr) { + debug self => _1; + let mut _2: &alloc::raw_vec::RawVec; + scope 4 (inlined alloc::raw_vec::RawVec::::ptr) { + debug self => _2; + let mut _3: &alloc::raw_vec::RawVecInner; + scope 5 (inlined alloc::raw_vec::RawVecInner::ptr::) { debug self => _3; - let mut _4: std::ptr::NonNull; - scope 6 (inlined Unique::::cast::) { - debug ((self: Unique).0: std::ptr::NonNull) => _4; - debug ((self: Unique).1: std::marker::PhantomData) => const PhantomData::; - scope 7 (inlined NonNull::::cast::) { - debug self => _4; - scope 8 (inlined NonNull::::as_ptr) { + scope 6 (inlined alloc::raw_vec::RawVecInner::non_null::) { + debug self => _3; + let mut _4: std::ptr::NonNull; + scope 7 (inlined Unique::::cast::) { + debug ((self: Unique).0: std::ptr::NonNull) => _4; + debug ((self: Unique).1: std::marker::PhantomData) => const PhantomData::; + scope 8 (inlined NonNull::::cast::) { debug self => _4; - let mut _5: *const u8; + scope 9 (inlined NonNull::::as_ptr) { + debug self => _4; + let mut _5: *const u8; + } } } - } - scope 9 (inlined #[track_caller] as Into>>::into) { - debug ((self: Unique).0: std::ptr::NonNull) => _4; - debug ((self: Unique).1: std::marker::PhantomData) => const PhantomData::; - scope 10 (inlined as From>>::from) { - debug ((unique: Unique).0: std::ptr::NonNull) => _4; - debug ((unique: Unique).1: std::marker::PhantomData) => const PhantomData::; - scope 11 (inlined Unique::::as_non_null_ptr) { - debug ((self: Unique).0: std::ptr::NonNull) => _4; - debug ((self: Unique).1: std::marker::PhantomData) => const PhantomData::; - } + scope 10 (inlined Unique::::as_non_null_ptr) { + debug ((self: Unique).0: std::ptr::NonNull) => _4; + debug ((self: Unique).1: std::marker::PhantomData) => const PhantomData::; } } + scope 11 (inlined NonNull::::as_ptr) { + debug self => _4; + } } - scope 12 (inlined NonNull::::as_ptr) { - debug self => _4; - } - } - } - } - scope 13 (inlined std::slice::from_raw_parts::<'_, u8>) { - debug data => _5; - debug len => _6; - let _7: *const [u8]; - scope 14 (inlined core::ub_checks::check_language_ub) { - scope 15 (inlined core::ub_checks::check_language_ub::runtime) { } } - scope 16 (inlined std::mem::size_of::) { - } - scope 17 (inlined align_of::) { - } - scope 18 (inlined slice_from_raw_parts::) { + scope 12 (inlined std::slice::from_raw_parts::<'_, u8>) { debug data => _5; debug len => _6; - scope 19 (inlined std::ptr::from_raw_parts::<[u8], u8>) { - debug data_pointer => _5; - debug metadata => _6; + let _7: *const [u8]; + scope 13 (inlined core::ub_checks::check_language_ub) { + scope 14 (inlined core::ub_checks::check_language_ub::runtime) { + } + } + scope 15 (inlined std::mem::size_of::) { + } + scope 16 (inlined align_of::) { + } + scope 17 (inlined slice_from_raw_parts::) { + debug data => _5; + debug len => _6; + scope 18 (inlined std::ptr::from_raw_parts::<[u8], u8>) { + debug data_pointer => _5; + debug metadata => _6; + } } } } diff --git a/tests/ui/consts/issue-94675.rs b/tests/ui/consts/issue-94675.rs index 56c4b6ea36f6a..2e30eebb07b2e 100644 --- a/tests/ui/consts/issue-94675.rs +++ b/tests/ui/consts/issue-94675.rs @@ -1,6 +1,6 @@ //@ known-bug: #103507 -#![feature(const_trait_impl)] +#![feature(const_trait_impl, const_vec_string_slice)] struct Foo<'a> { bar: &'a mut Vec, diff --git a/tests/ui/consts/issue-94675.stderr b/tests/ui/consts/issue-94675.stderr index ebfa09b2e5d5d..a85c5e10374f8 100644 --- a/tests/ui/consts/issue-94675.stderr +++ b/tests/ui/consts/issue-94675.stderr @@ -1,11 +1,3 @@ -error[E0015]: cannot call non-const fn `Vec::::len` in constant functions - --> $DIR/issue-94675.rs:11:27 - | -LL | self.bar[0] = baz.len(); - | ^^^^^ - | - = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants - error[E0015]: cannot call non-const operator in constant functions --> $DIR/issue-94675.rs:11:17 | @@ -20,6 +12,6 @@ help: add `#![feature(effects)]` to the crate attributes to enable LL + #![feature(effects)] | -error: aborting due to 2 previous errors +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0015`. From 731469fee50133528c1904a07da73e739db6f6c4 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 7 Oct 2024 11:03:52 +1100 Subject: [PATCH 1962/2194] Convert `Option<&Lrc>` return types to `Option<&T>`. It's simpler and more concise. --- compiler/rustc_codegen_ssa/src/back/write.rs | 5 ++--- .../src/annotate_snippet_emitter_writer.rs | 8 ++++---- compiler/rustc_errors/src/emitter.rs | 14 +++++++------- compiler/rustc_errors/src/json.rs | 6 +++--- compiler/rustc_errors/src/lib.rs | 6 +++--- compiler/rustc_errors/src/tests.rs | 4 ++-- compiler/rustc_errors/src/translation.rs | 3 +-- .../passes/lint/check_code_block_syntax.rs | 4 ++-- src/tools/rustfmt/src/parse/session.rs | 8 ++++---- 9 files changed, 28 insertions(+), 30 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs index 4d81ff933dded..e22dd8373bdc4 100644 --- a/compiler/rustc_codegen_ssa/src/back/write.rs +++ b/compiler/rustc_codegen_ssa/src/back/write.rs @@ -11,7 +11,6 @@ use rustc_ast::attr; use rustc_data_structures::fx::{FxHashMap, FxIndexMap}; use rustc_data_structures::memmap::Mmap; use rustc_data_structures::profiling::{SelfProfilerRef, VerboseTimingGuard}; -use rustc_data_structures::sync::Lrc; use rustc_errors::emitter::Emitter; use rustc_errors::translation::Translate; use rustc_errors::{ @@ -1889,7 +1888,7 @@ impl SharedEmitter { } impl Translate for SharedEmitter { - fn fluent_bundle(&self) -> Option<&Lrc> { + fn fluent_bundle(&self) -> Option<&FluentBundle> { None } @@ -1924,7 +1923,7 @@ impl Emitter for SharedEmitter { ); } - fn source_map(&self) -> Option<&Lrc> { + fn source_map(&self) -> Option<&SourceMap> { None } } diff --git a/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs b/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs index f468fbf4497e0..335432c9cfec3 100644 --- a/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs +++ b/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs @@ -34,8 +34,8 @@ pub struct AnnotateSnippetEmitter { } impl Translate for AnnotateSnippetEmitter { - fn fluent_bundle(&self) -> Option<&Lrc> { - self.fluent_bundle.as_ref() + fn fluent_bundle(&self) -> Option<&FluentBundle> { + self.fluent_bundle.as_deref() } fn fallback_fluent_bundle(&self) -> &FluentBundle { @@ -69,8 +69,8 @@ impl Emitter for AnnotateSnippetEmitter { ); } - fn source_map(&self) -> Option<&Lrc> { - self.source_map.as_ref() + fn source_map(&self) -> Option<&SourceMap> { + self.source_map.as_deref() } fn should_show_explain(&self) -> bool { diff --git a/compiler/rustc_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs index 1dc52c4d0a423..1adb6b9dcfee3 100644 --- a/compiler/rustc_errors/src/emitter.rs +++ b/compiler/rustc_errors/src/emitter.rs @@ -205,7 +205,7 @@ pub trait Emitter: Translate { false } - fn source_map(&self) -> Option<&Lrc>; + fn source_map(&self) -> Option<&SourceMap>; /// Formats the substitutions of the primary_span /// @@ -481,8 +481,8 @@ pub trait Emitter: Translate { } impl Translate for HumanEmitter { - fn fluent_bundle(&self) -> Option<&Lrc> { - self.fluent_bundle.as_ref() + fn fluent_bundle(&self) -> Option<&FluentBundle> { + self.fluent_bundle.as_deref() } fn fallback_fluent_bundle(&self) -> &FluentBundle { @@ -491,8 +491,8 @@ impl Translate for HumanEmitter { } impl Emitter for HumanEmitter { - fn source_map(&self) -> Option<&Lrc> { - self.sm.as_ref() + fn source_map(&self) -> Option<&SourceMap> { + self.sm.as_deref() } fn emit_diagnostic(&mut self, mut diag: DiagInner) { @@ -540,7 +540,7 @@ pub struct SilentEmitter { } impl Translate for SilentEmitter { - fn fluent_bundle(&self) -> Option<&Lrc> { + fn fluent_bundle(&self) -> Option<&FluentBundle> { None } @@ -552,7 +552,7 @@ impl Translate for SilentEmitter { } impl Emitter for SilentEmitter { - fn source_map(&self) -> Option<&Lrc> { + fn source_map(&self) -> Option<&SourceMap> { None } diff --git a/compiler/rustc_errors/src/json.rs b/compiler/rustc_errors/src/json.rs index 1972a522e394a..1534e25652077 100644 --- a/compiler/rustc_errors/src/json.rs +++ b/compiler/rustc_errors/src/json.rs @@ -111,8 +111,8 @@ enum EmitTyped<'a> { } impl Translate for JsonEmitter { - fn fluent_bundle(&self) -> Option<&Lrc> { - self.fluent_bundle.as_ref() + fn fluent_bundle(&self) -> Option<&FluentBundle> { + self.fluent_bundle.as_deref() } fn fallback_fluent_bundle(&self) -> &FluentBundle { @@ -172,7 +172,7 @@ impl Emitter for JsonEmitter { } } - fn source_map(&self) -> Option<&Lrc> { + fn source_map(&self) -> Option<&SourceMap> { Some(&self.sm) } diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index 39acacfbe59c8..e5560be453110 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -59,7 +59,7 @@ use registry::Registry; use rustc_data_structures::AtomicRef; use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet}; use rustc_data_structures::stable_hasher::{Hash128, StableHasher}; -use rustc_data_structures::sync::{Lock, Lrc}; +use rustc_data_structures::sync::Lock; pub use rustc_error_messages::{ DiagMessage, FluentBundle, LanguageIdentifier, LazyFallbackBundle, MultiSpan, SpanLabel, SubdiagMessage, fallback_fluent_bundle, fluent_bundle, @@ -685,13 +685,13 @@ impl DiagCtxt { unimplemented!("false emitter must only used during `wrap_emitter`") } - fn source_map(&self) -> Option<&Lrc> { + fn source_map(&self) -> Option<&SourceMap> { unimplemented!("false emitter must only used during `wrap_emitter`") } } impl translation::Translate for FalseEmitter { - fn fluent_bundle(&self) -> Option<&Lrc> { + fn fluent_bundle(&self) -> Option<&FluentBundle> { unimplemented!("false emitter must only used during `wrap_emitter`") } diff --git a/compiler/rustc_errors/src/tests.rs b/compiler/rustc_errors/src/tests.rs index 17a1635bd1143..70179237e5d41 100644 --- a/compiler/rustc_errors/src/tests.rs +++ b/compiler/rustc_errors/src/tests.rs @@ -1,4 +1,4 @@ -use rustc_data_structures::sync::{IntoDynSyncSend, Lrc}; +use rustc_data_structures::sync::IntoDynSyncSend; use rustc_error_messages::fluent_bundle::resolver::errors::{ReferenceKind, ResolverError}; use rustc_error_messages::{DiagMessage, langid}; @@ -12,7 +12,7 @@ struct Dummy { } impl Translate for Dummy { - fn fluent_bundle(&self) -> Option<&Lrc> { + fn fluent_bundle(&self) -> Option<&FluentBundle> { None } diff --git a/compiler/rustc_errors/src/translation.rs b/compiler/rustc_errors/src/translation.rs index e0b64b276ebc6..156f5e5d26e64 100644 --- a/compiler/rustc_errors/src/translation.rs +++ b/compiler/rustc_errors/src/translation.rs @@ -2,7 +2,6 @@ use std::borrow::Cow; use std::env; use std::error::Report; -use rustc_data_structures::sync::Lrc; pub use rustc_error_messages::FluentArgs; use tracing::{debug, trace}; @@ -33,7 +32,7 @@ pub trait Translate { /// Return `FluentBundle` with localized diagnostics for the locale requested by the user. If no /// language was requested by the user then this will be `None` and `fallback_fluent_bundle` /// should be used. - fn fluent_bundle(&self) -> Option<&Lrc>; + fn fluent_bundle(&self) -> Option<&FluentBundle>; /// Return `FluentBundle` with localized diagnostics for the default locale of the compiler. /// Used when the user has not requested a specific language or when a localized diagnostic is diff --git a/src/librustdoc/passes/lint/check_code_block_syntax.rs b/src/librustdoc/passes/lint/check_code_block_syntax.rs index 848e70a7bdbab..e0dc5b4c51333 100644 --- a/src/librustdoc/passes/lint/check_code_block_syntax.rs +++ b/src/librustdoc/passes/lint/check_code_block_syntax.rs @@ -145,7 +145,7 @@ struct BufferEmitter { } impl Translate for BufferEmitter { - fn fluent_bundle(&self) -> Option<&Lrc> { + fn fluent_bundle(&self) -> Option<&rustc_errors::FluentBundle> { None } @@ -169,7 +169,7 @@ impl Emitter for BufferEmitter { } } - fn source_map(&self) -> Option<&Lrc> { + fn source_map(&self) -> Option<&SourceMap> { None } } diff --git a/src/tools/rustfmt/src/parse/session.rs b/src/tools/rustfmt/src/parse/session.rs index 9f27a05939eba..54ad56ed3f35d 100644 --- a/src/tools/rustfmt/src/parse/session.rs +++ b/src/tools/rustfmt/src/parse/session.rs @@ -46,7 +46,7 @@ impl SilentOnIgnoredFilesEmitter { } impl Translate for SilentOnIgnoredFilesEmitter { - fn fluent_bundle(&self) -> Option<&Lrc> { + fn fluent_bundle(&self) -> Option<&rustc_errors::FluentBundle> { self.emitter.fluent_bundle() } @@ -56,7 +56,7 @@ impl Translate for SilentOnIgnoredFilesEmitter { } impl Emitter for SilentOnIgnoredFilesEmitter { - fn source_map(&self) -> Option<&Lrc> { + fn source_map(&self) -> Option<&SourceMap> { None } @@ -344,7 +344,7 @@ mod tests { } impl Translate for TestEmitter { - fn fluent_bundle(&self) -> Option<&Lrc> { + fn fluent_bundle(&self) -> Option<&rustc_errors::FluentBundle> { None } @@ -354,7 +354,7 @@ mod tests { } impl Emitter for TestEmitter { - fn source_map(&self) -> Option<&Lrc> { + fn source_map(&self) -> Option<&SourceMap> { None } From 860cbccad993151ef87ec6c39fd1b2892b18972f Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 7 Oct 2024 13:06:28 +1100 Subject: [PATCH 1963/2194] Convert a `&Lrc` argument to `Lrc`. It's slightly simpler. --- compiler/rustc_infer/src/infer/mod.rs | 2 +- compiler/rustc_infer/src/infer/opaque_types/mod.rs | 10 +++++++++- .../rustc_infer/src/infer/region_constraints/mod.rs | 4 ++-- 3 files changed, 12 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index 5fa1bf51634a3..040264586f644 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -776,7 +776,7 @@ impl<'tcx> InferCtxt<'tcx> { definition_span: Span, hidden_ty: Ty<'tcx>, region: ty::Region<'tcx>, - in_regions: &Lrc>>, + in_regions: Lrc>>, ) { self.inner.borrow_mut().unwrap_region_constraints().member_constraint( key, diff --git a/compiler/rustc_infer/src/infer/opaque_types/mod.rs b/compiler/rustc_infer/src/infer/opaque_types/mod.rs index 55c51bc856f8e..ba0a9b14ccbda 100644 --- a/compiler/rustc_infer/src/infer/opaque_types/mod.rs +++ b/compiler/rustc_infer/src/infer/opaque_types/mod.rs @@ -359,7 +359,15 @@ impl<'tcx> InferCtxt<'tcx> { // not currently sound until we have existential regions. concrete_ty.visit_with(&mut ConstrainOpaqueTypeRegionVisitor { tcx: self.tcx, - op: |r| self.member_constraint(opaque_type_key, span, concrete_ty, r, &choice_regions), + op: |r| { + self.member_constraint( + opaque_type_key, + span, + concrete_ty, + r, + choice_regions.clone(), + ) + }, }); } } diff --git a/compiler/rustc_infer/src/infer/region_constraints/mod.rs b/compiler/rustc_infer/src/infer/region_constraints/mod.rs index 82f7668b2d2ec..f22cfed0b717a 100644 --- a/compiler/rustc_infer/src/infer/region_constraints/mod.rs +++ b/compiler/rustc_infer/src/infer/region_constraints/mod.rs @@ -522,7 +522,7 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> { definition_span: Span, hidden_ty: Ty<'tcx>, member_region: ty::Region<'tcx>, - choice_regions: &Lrc>>, + choice_regions: Lrc>>, ) { debug!("member_constraint({:?} in {:#?})", member_region, choice_regions); @@ -535,7 +535,7 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> { definition_span, hidden_ty, member_region, - choice_regions: choice_regions.clone(), + choice_regions, }); } From 2123509351c970b1c3fdbb21f719862dd0ab9e00 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 7 Oct 2024 13:08:19 +1100 Subject: [PATCH 1964/2194] Remove an unnecessary `&Lrc<_>` local variable. --- compiler/rustc_lint/src/late.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_lint/src/late.rs b/compiler/rustc_lint/src/late.rs index de40139715076..6d5903ac46740 100644 --- a/compiler/rustc_lint/src/late.rs +++ b/compiler/rustc_lint/src/late.rs @@ -18,7 +18,7 @@ use std::any::Any; use std::cell::Cell; use rustc_data_structures::stack::ensure_sufficient_stack; -use rustc_data_structures::sync::{Lrc, join}; +use rustc_data_structures::sync::join; use rustc_hir as hir; use rustc_hir::def_id::{LocalDefId, LocalModDefId}; use rustc_hir::{HirId, intravisit as hir_visit}; @@ -36,8 +36,7 @@ use crate::{LateContext, LateLintPass, LintStore}; /// /// This function exists because [`Session::lint_store`] is type-erased. pub fn unerased_lint_store(sess: &Session) -> &LintStore { - let store: &Lrc<_> = sess.lint_store.as_ref().unwrap(); - let store: &dyn Any = &**store; + let store: &dyn Any = sess.lint_store.as_deref().unwrap(); store.downcast_ref().unwrap() } From 4547c0a990b88700812c4e5d14c383bdc7167c31 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 7 Oct 2024 13:25:38 +1100 Subject: [PATCH 1965/2194] Avoid another `&Lrc<..>` in a return value. --- compiler/rustc_span/src/lib.rs | 2 +- compiler/rustc_span/src/source_map/tests.rs | 2 +- src/tools/clippy/clippy_utils/src/source.rs | 1 + 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs index b55465ddef7f1..5b1be5bca0593 100644 --- a/compiler/rustc_span/src/lib.rs +++ b/compiler/rustc_span/src/lib.rs @@ -1380,7 +1380,7 @@ pub enum ExternalSourceKind { } impl ExternalSource { - pub fn get_source(&self) -> Option<&Lrc> { + pub fn get_source(&self) -> Option<&str> { match self { ExternalSource::Foreign { kind: ExternalSourceKind::Present(ref src), .. } => Some(src), _ => None, diff --git a/compiler/rustc_span/src/source_map/tests.rs b/compiler/rustc_span/src/source_map/tests.rs index 360baec273d9a..5b39706f3ade1 100644 --- a/compiler/rustc_span/src/source_map/tests.rs +++ b/compiler/rustc_span/src/source_map/tests.rs @@ -257,7 +257,7 @@ fn t10() { ); imported_src_file.add_external_src(|| Some(unnormalized.to_string())); assert_eq!( - imported_src_file.external_src.borrow().get_source().unwrap().as_ref(), + imported_src_file.external_src.borrow().get_source().unwrap(), normalized, "imported source file should be normalized" ); diff --git a/src/tools/clippy/clippy_utils/src/source.rs b/src/tools/clippy/clippy_utils/src/source.rs index 4ad7575e7201f..eecbfb3936ac4 100644 --- a/src/tools/clippy/clippy_utils/src/source.rs +++ b/src/tools/clippy/clippy_utils/src/source.rs @@ -287,6 +287,7 @@ impl SourceFileRange { self.sf .src .as_ref() + .map(|src| src.as_str()) .or_else(|| self.sf.external_src.get().and_then(|src| src.get_source())) .and_then(|x| x.get(self.range.clone())) } From 64efbe2b537b5c597587655f53e6227fa682c6ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=AE=B8=E6=9D=B0=E5=8F=8B=20Jieyou=20Xu=20=28Joe=29?= Date: Mon, 7 Oct 2024 05:03:23 +0000 Subject: [PATCH 1966/2194] Prune invalid `ignore-mode-*` directives These are only valid for coverage test modes. --- src/tools/compiletest/src/command-list.rs | 15 --------------- src/tools/compiletest/src/header/cfg.rs | 4 ++-- src/tools/compiletest/src/header/tests.rs | 5 +---- 3 files changed, 3 insertions(+), 21 deletions(-) diff --git a/src/tools/compiletest/src/command-list.rs b/src/tools/compiletest/src/command-list.rs index a4cedbf66e2ad..bcdd4a69b66c3 100644 --- a/src/tools/compiletest/src/command-list.rs +++ b/src/tools/compiletest/src/command-list.rs @@ -64,23 +64,8 @@ const KNOWN_DIRECTIVE_NAMES: &[&str] = &[ "ignore-loongarch64", "ignore-macabi", "ignore-macos", - "ignore-mode-assembly", - "ignore-mode-codegen", - "ignore-mode-codegen-units", "ignore-mode-coverage-map", "ignore-mode-coverage-run", - "ignore-mode-crashes", - "ignore-mode-debuginfo", - "ignore-mode-incremental", - "ignore-mode-js-doc-test", - "ignore-mode-mir-opt", - "ignore-mode-pretty", - "ignore-mode-run-make", - "ignore-mode-run-pass-valgrind", - "ignore-mode-rustdoc", - "ignore-mode-rustdoc-json", - "ignore-mode-ui", - "ignore-mode-ui-fulldeps", "ignore-msp430", "ignore-msvc", "ignore-musl", diff --git a/src/tools/compiletest/src/header/cfg.rs b/src/tools/compiletest/src/header/cfg.rs index 948568e63c2dc..f3835637a1ec2 100644 --- a/src/tools/compiletest/src/header/cfg.rs +++ b/src/tools/compiletest/src/header/cfg.rs @@ -1,6 +1,6 @@ use std::collections::HashSet; -use crate::common::{CompareMode, Config, Debugger, Mode}; +use crate::common::{CompareMode, Config, Debugger}; use crate::header::IgnoreDecision; const EXTRA_ARCHS: &[&str] = &["spirv"]; @@ -222,7 +222,7 @@ pub(super) fn parse_cfg_name_directive<'a>( name: format!("mode-{}", config.mode.to_str()), allowed_names: ContainsPrefixed { prefix: "mode-", - inner: Mode::STR_VARIANTS, + inner: ["coverage-run", "coverage-map"], }, message: "when the test mode is {name}", } diff --git a/src/tools/compiletest/src/header/tests.rs b/src/tools/compiletest/src/header/tests.rs index ae661200c6cfa..76a8b129198dc 100644 --- a/src/tools/compiletest/src/header/tests.rs +++ b/src/tools/compiletest/src/header/tests.rs @@ -1,6 +1,5 @@ use std::io::Read; use std::path::Path; -use std::str::FromStr; use super::iter_header; use crate::common::{Config, Debugger, Mode}; @@ -574,14 +573,12 @@ fn families() { #[test] fn ignore_mode() { - for &mode in Mode::STR_VARIANTS { + for mode in ["coverage-map", "coverage-run"] { // Indicate profiler support so that "coverage-run" tests aren't skipped. let config: Config = cfg().mode(mode).profiler_support(true).build(); let other = if mode == "coverage-run" { "coverage-map" } else { "coverage-run" }; assert_ne!(mode, other); - assert_eq!(config.mode, Mode::from_str(mode).unwrap()); - assert_ne!(config.mode, Mode::from_str(other).unwrap()); assert!(check_ignore(&config, &format!("//@ ignore-mode-{mode}"))); assert!(!check_ignore(&config, &format!("//@ ignore-mode-{other}"))); From fc64ff7ec2aad5261365c0cfc033f65140828eb2 Mon Sep 17 00:00:00 2001 From: codemountains <4kz12zz@gmail.com> Date: Mon, 7 Oct 2024 08:49:47 +0900 Subject: [PATCH 1967/2194] Rename nested_meta to meta_item_inner --- compiler/rustc_ast_passes/src/feature_gate.rs | 4 ++-- compiler/rustc_builtin_macros/src/derive.rs | 2 +- compiler/rustc_expand/src/expand.rs | 2 +- .../rustc_resolve/src/build_reduced_graph.rs | 16 +++++++++------- compiler/rustc_resolve/src/macros.rs | 6 +++--- src/tools/rustfmt/src/attr.rs | 6 +++--- src/tools/rustfmt/src/overflow.rs | 5 ++--- src/tools/rustfmt/src/skip.rs | 4 ++-- 8 files changed, 23 insertions(+), 22 deletions(-) diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs index 83931a8c1a960..42d1ef5c558b0 100644 --- a/compiler/rustc_ast_passes/src/feature_gate.rs +++ b/compiler/rustc_ast_passes/src/feature_gate.rs @@ -186,9 +186,9 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { } // Check unstable flavors of the `#[doc]` attribute. if attr.has_name(sym::doc) { - for nested_meta in attr.meta_item_list().unwrap_or_default() { + for meta_item_inner in attr.meta_item_list().unwrap_or_default() { macro_rules! gate_doc { ($($s:literal { $($name:ident => $feature:ident)* })*) => { - $($(if nested_meta.has_name(sym::$name) { + $($(if meta_item_inner.has_name(sym::$name) { let msg = concat!("`#[doc(", stringify!($name), ")]` is ", $s); gate!(self, $feature, attr.span, msg); })*)* diff --git a/compiler/rustc_builtin_macros/src/derive.rs b/compiler/rustc_builtin_macros/src/derive.rs index 361fcaa8534f2..60450d085f6c0 100644 --- a/compiler/rustc_builtin_macros/src/derive.rs +++ b/compiler/rustc_builtin_macros/src/derive.rs @@ -49,7 +49,7 @@ impl MultiItemModifier for Expander { let mut resolutions = match &meta_item.kind { MetaItemKind::List(list) => { list.iter() - .filter_map(|nested_meta| match nested_meta { + .filter_map(|meta_item_inner| match meta_item_inner { MetaItemInner::MetaItem(meta) => Some(meta), MetaItemInner::Lit(lit) => { // Reject `#[derive("Debug")]`. diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs index 5347381c3c3de..a872b12e744c4 100644 --- a/compiler/rustc_expand/src/expand.rs +++ b/compiler/rustc_expand/src/expand.rs @@ -1863,7 +1863,7 @@ impl<'a, 'b> InvocationCollector<'a, 'b> { .iter() .filter(|a| a.has_name(sym::derive)) .flat_map(|a| a.meta_item_list().unwrap_or_default()) - .filter_map(|nested_meta| match nested_meta { + .filter_map(|meta_item_inner| match meta_item_inner { MetaItemInner::MetaItem(ast::MetaItem { kind: MetaItemKind::Word, path, diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs index a9ea268e51a9d..d836e53566951 100644 --- a/compiler/rustc_resolve/src/build_reduced_graph.rs +++ b/compiler/rustc_resolve/src/build_reduced_graph.rs @@ -1072,13 +1072,13 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> { import_all = Some(meta.span); break; } - MetaItemKind::List(nested_metas) => { - for nested_meta in nested_metas { - match nested_meta.ident() { - Some(ident) if nested_meta.is_word() => { + MetaItemKind::List(meta_item_inners) => { + for meta_item_inner in meta_item_inners { + match meta_item_inner.ident() { + Some(ident) if meta_item_inner.is_word() => { single_imports.push(ident) } - _ => ill_formed(nested_meta.span()), + _ => ill_formed(meta_item_inner.span()), } } } @@ -1198,8 +1198,10 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> { } else if attr::contains_name(&item.attrs, sym::proc_macro_attribute) { return Some((MacroKind::Attr, item.ident, item.span)); } else if let Some(attr) = attr::find_by_name(&item.attrs, sym::proc_macro_derive) { - if let Some(nested_meta) = attr.meta_item_list().and_then(|list| list.get(0).cloned()) { - if let Some(ident) = nested_meta.ident() { + if let Some(meta_item_inner) = + attr.meta_item_list().and_then(|list| list.get(0).cloned()) + { + if let Some(ident) = meta_item_inner.ident() { return Some((MacroKind::Derive, ident, ident.span)); } } diff --git a/compiler/rustc_resolve/src/macros.rs b/compiler/rustc_resolve/src/macros.rs index 21924437a4a46..fa2be8216c73f 100644 --- a/compiler/rustc_resolve/src/macros.rs +++ b/compiler/rustc_resolve/src/macros.rs @@ -129,8 +129,8 @@ pub(crate) fn registered_tools(tcx: TyCtxt<'_>, (): ()) -> RegisteredTools { let mut registered_tools = RegisteredTools::default(); let (_, pre_configured_attrs) = &*tcx.crate_for_resolver(()).borrow(); for attr in attr::filter_by_name(pre_configured_attrs, sym::register_tool) { - for nested_meta in attr.meta_item_list().unwrap_or_default() { - match nested_meta.ident() { + for meta_item_inner in attr.meta_item_list().unwrap_or_default() { + match meta_item_inner.ident() { Some(ident) => { if let Some(old_ident) = registered_tools.replace(ident) { tcx.dcx().emit_err(errors::ToolWasAlreadyRegistered { @@ -142,7 +142,7 @@ pub(crate) fn registered_tools(tcx: TyCtxt<'_>, (): ()) -> RegisteredTools { } None => { tcx.dcx().emit_err(errors::ToolOnlyAcceptsIdentifiers { - span: nested_meta.span(), + span: meta_item_inner.span(), tool: sym::register_tool, }); } diff --git a/src/tools/rustfmt/src/attr.rs b/src/tools/rustfmt/src/attr.rs index ad425d0bff7f0..381c938ae8062 100644 --- a/src/tools/rustfmt/src/attr.rs +++ b/src/tools/rustfmt/src/attr.rs @@ -90,7 +90,7 @@ fn format_derive( let item_spans = attr.meta_item_list().map(|meta_item_list| { meta_item_list .into_iter() - .map(|nested_meta_item| nested_meta_item.span()) + .map(|meta_item_inner| meta_item_inner.span()) })?; let items = itemize_list( @@ -536,7 +536,7 @@ pub(crate) trait MetaVisitor<'ast> { list: &'ast [ast::MetaItemInner], ) { for nm in list { - self.visit_nested_meta_item(nm); + self.visit_meta_item_inner(nm); } } @@ -549,7 +549,7 @@ pub(crate) trait MetaVisitor<'ast> { ) { } - fn visit_nested_meta_item(&mut self, nm: &'ast ast::MetaItemInner) { + fn visit_meta_item_inner(&mut self, nm: &'ast ast::MetaItemInner) { match nm { ast::MetaItemInner::MetaItem(ref meta_item) => self.visit_meta_item(meta_item), ast::MetaItemInner::Lit(ref lit) => self.visit_meta_item_lit(lit), diff --git a/src/tools/rustfmt/src/overflow.rs b/src/tools/rustfmt/src/overflow.rs index 3f44789bafd16..728adff2c7d13 100644 --- a/src/tools/rustfmt/src/overflow.rs +++ b/src/tools/rustfmt/src/overflow.rs @@ -138,7 +138,7 @@ impl<'a> OverflowableItem<'a> { OverflowableItem::Expr(expr) => is_simple_expr(expr), OverflowableItem::MacroArg(MacroArg::Keyword(..)) => true, OverflowableItem::MacroArg(MacroArg::Expr(expr)) => is_simple_expr(expr), - OverflowableItem::MetaItemInner(nested_meta_item) => match nested_meta_item { + OverflowableItem::MetaItemInner(meta_item_inner) => match meta_item_inner { ast::MetaItemInner::Lit(..) => true, ast::MetaItemInner::MetaItem(ref meta_item) => { matches!(meta_item.kind, ast::MetaItemKind::Word) @@ -184,8 +184,7 @@ impl<'a> OverflowableItem<'a> { MacroArg::Item(..) => len == 1, MacroArg::Keyword(..) => false, }, - OverflowableItem::MetaItemInner(nested_meta_item) if len == 1 => match nested_meta_item - { + OverflowableItem::MetaItemInner(meta_item_inner) if len == 1 => match meta_item_inner { ast::MetaItemInner::Lit(..) => false, ast::MetaItemInner::MetaItem(..) => true, }, diff --git a/src/tools/rustfmt/src/skip.rs b/src/tools/rustfmt/src/skip.rs index d733f7068fd8e..cd3860d3d7f0a 100644 --- a/src/tools/rustfmt/src/skip.rs +++ b/src/tools/rustfmt/src/skip.rs @@ -116,8 +116,8 @@ fn get_skip_names(kind: &str, attrs: &[ast::Attribute]) -> Vec { } if let Some(list) = attr.meta_item_list() { - for nested_meta_item in list { - if let Some(name) = nested_meta_item.ident() { + for meta_item_inner in list { + if let Some(name) = meta_item_inner.ident() { skip_names.push(name.to_string()); } } From a961be9f1338d215a356fca01ffd4db1de56279c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=AE=B8=E6=9D=B0=E5=8F=8B=20Jieyou=20Xu=20=28Joe=29?= Date: Mon, 7 Oct 2024 07:51:06 +0000 Subject: [PATCH 1968/2194] Remove valgrind test suite and support from compiletest --- src/tools/compiletest/src/common.rs | 8 ---- src/tools/compiletest/src/lib.rs | 6 +-- src/tools/compiletest/src/main.rs | 4 -- src/tools/compiletest/src/runtest.rs | 38 ++----------------- .../compiletest/src/runtest/incremental.rs | 34 ++++++++++++----- src/tools/compiletest/src/runtest/valgrind.rs | 34 ----------------- 6 files changed, 29 insertions(+), 95 deletions(-) delete mode 100644 src/tools/compiletest/src/runtest/valgrind.rs diff --git a/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs index adc89cad72f89..17ec6ea430169 100644 --- a/src/tools/compiletest/src/common.rs +++ b/src/tools/compiletest/src/common.rs @@ -53,7 +53,6 @@ macro_rules! string_enum { string_enum! { #[derive(Clone, Copy, PartialEq, Debug)] pub enum Mode { - RunPassValgrind => "run-pass-valgrind", Pretty => "pretty", DebugInfo => "debuginfo", Codegen => "codegen", @@ -207,13 +206,6 @@ pub struct Config { /// Path to LLVM's bin directory. pub llvm_bin_dir: Option, - /// The valgrind path. - pub valgrind_path: Option, - - /// Whether to fail if we can't run run-pass-valgrind tests under valgrind - /// (or, alternatively, to silently run them like regular run-pass tests). - pub force_valgrind: bool, - /// The path to the Clang executable to run Clang-based tests with. If /// `None` then these tests will be ignored. pub run_clang_based_tests_with: Option, diff --git a/src/tools/compiletest/src/lib.rs b/src/tools/compiletest/src/lib.rs index a8355ee9590d6..d9f64cddf5d43 100644 --- a/src/tools/compiletest/src/lib.rs +++ b/src/tools/compiletest/src/lib.rs @@ -53,8 +53,6 @@ pub fn parse_config(args: Vec) -> Config { .reqopt("", "python", "path to python to use for doc tests", "PATH") .optopt("", "jsondocck-path", "path to jsondocck to use for doc tests", "PATH") .optopt("", "jsondoclint-path", "path to jsondoclint to use for doc tests", "PATH") - .optopt("", "valgrind-path", "path to Valgrind executable for Valgrind tests", "PROGRAM") - .optflag("", "force-valgrind", "fail if Valgrind tests cannot be run under Valgrind") .optopt("", "run-clang-based-tests-with", "path to Clang executable", "PATH") .optopt("", "llvm-filecheck", "path to LLVM's FileCheck binary", "DIR") .reqopt("", "src-base", "directory to scan for test files", "PATH") @@ -65,7 +63,7 @@ pub fn parse_config(args: Vec) -> Config { "", "mode", "which sort of compile tests to run", - "run-pass-valgrind | pretty | debug-info | codegen | rustdoc \ + "pretty | debug-info | codegen | rustdoc \ | rustdoc-json | codegen-units | incremental | run-make | ui \ | js-doc-test | mir-opt | assembly | crashes", ) @@ -269,8 +267,6 @@ pub fn parse_config(args: Vec) -> Config { python: matches.opt_str("python").unwrap(), jsondocck_path: matches.opt_str("jsondocck-path"), jsondoclint_path: matches.opt_str("jsondoclint-path"), - valgrind_path: matches.opt_str("valgrind-path"), - force_valgrind: matches.opt_present("force-valgrind"), run_clang_based_tests_with: matches.opt_str("run-clang-based-tests-with"), llvm_filecheck: matches.opt_str("llvm-filecheck").map(PathBuf::from), llvm_bin_dir: matches.opt_str("llvm-bin-dir").map(PathBuf::from), diff --git a/src/tools/compiletest/src/main.rs b/src/tools/compiletest/src/main.rs index 7b85e6f80b32a..9f3eef3776d4e 100644 --- a/src/tools/compiletest/src/main.rs +++ b/src/tools/compiletest/src/main.rs @@ -18,10 +18,6 @@ fn main() { let config = Arc::new(parse_config(env::args().collect())); - if config.valgrind_path.is_none() && config.force_valgrind { - panic!("Can't find Valgrind to run Valgrind tests"); - } - if !config.has_tidy && config.mode == Mode::Rustdoc { eprintln!("warning: `tidy` is not installed; diffs will not be generated"); } diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 74d86d2b521dc..ffde06fdd8b3d 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -20,9 +20,9 @@ use tracing::*; use crate::common::{ Assembly, Codegen, CodegenUnits, CompareMode, Config, CoverageMap, CoverageRun, Crashes, DebugInfo, Debugger, FailMode, Incremental, JsDocTest, MirOpt, PassMode, Pretty, RunMake, - RunPassValgrind, Rustdoc, RustdocJson, TestPaths, UI_EXTENSIONS, UI_FIXED, UI_RUN_STDERR, - UI_RUN_STDOUT, UI_STDERR, UI_STDOUT, UI_SVG, UI_WINDOWS_SVG, Ui, expected_output_path, - incremental_dir, output_base_dir, output_base_name, output_testname_unique, + Rustdoc, RustdocJson, TestPaths, UI_EXTENSIONS, UI_FIXED, UI_RUN_STDERR, UI_RUN_STDOUT, + UI_STDERR, UI_STDOUT, UI_SVG, UI_WINDOWS_SVG, Ui, expected_output_path, incremental_dir, + output_base_dir, output_base_name, output_testname_unique, }; use crate::compute_diff::{write_diff, write_filtered_diff}; use crate::errors::{self, Error, ErrorKind}; @@ -49,7 +49,6 @@ mod run_make; mod rustdoc; mod rustdoc_json; mod ui; -mod valgrind; // tidy-alphabet-end #[cfg(test)] @@ -253,7 +252,6 @@ impl<'test> TestCx<'test> { self.fatal("cannot use should-ice in a test that is not cfail"); } match self.config.mode { - RunPassValgrind => self.run_valgrind_test(), Pretty => self.run_pretty_test(), DebugInfo => self.run_debuginfo_test(), Codegen => self.run_codegen_test(), @@ -1500,8 +1498,7 @@ impl<'test> TestCx<'test> { Crashes => { set_mir_dump_dir(&mut rustc); } - RunPassValgrind | Pretty | DebugInfo | Rustdoc | RustdocJson | RunMake - | CodegenUnits | JsDocTest => { + Pretty | DebugInfo | Rustdoc | RustdocJson | RunMake | CodegenUnits | JsDocTest => { // do not use JSON output } } @@ -2651,33 +2648,6 @@ impl<'test> TestCx<'test> { } } - // FIXME(jieyouxu): `run_rpass_test` is hoisted out here and not in incremental because - // apparently valgrind test falls back to `run_rpass_test` if valgrind isn't available, which - // seems highly questionable to me. - fn run_rpass_test(&self) { - let emit_metadata = self.should_emit_metadata(self.pass_mode()); - let should_run = self.run_if_enabled(); - let proc_res = self.compile_test(should_run, emit_metadata); - - if !proc_res.status.success() { - self.fatal_proc_rec("compilation failed!", &proc_res); - } - - // FIXME(#41968): Move this check to tidy? - if !errors::load_errors(&self.testpaths.file, self.revision).is_empty() { - self.fatal("run-pass tests with expected warnings should be moved to ui/"); - } - - if let WillExecute::Disabled = should_run { - return; - } - - let proc_res = self.exec_compiled_test(); - if !proc_res.status.success() { - self.fatal_proc_rec("test run failed!", &proc_res); - } - } - fn aggressive_rm_rf(&self, path: &Path) -> io::Result<()> { for e in path.read_dir()? { let entry = e?; diff --git a/src/tools/compiletest/src/runtest/incremental.rs b/src/tools/compiletest/src/runtest/incremental.rs index 81b006292e492..bf2b71fef4378 100644 --- a/src/tools/compiletest/src/runtest/incremental.rs +++ b/src/tools/compiletest/src/runtest/incremental.rs @@ -1,10 +1,6 @@ use super::{TestCx, WillExecute}; use crate::errors; -// FIXME(jieyouxu): `run_rpass_test` got hoisted out of this because apparently valgrind falls back -// to `run_rpass_test` if valgrind isn't available, which is questionable, but keeping it for -// refactoring changes to preserve current behavior. - impl TestCx<'_> { pub(super) fn run_incremental_test(&self) { // Basic plan for a test incremental/foo/bar.rs: @@ -73,6 +69,30 @@ impl TestCx<'_> { } } + fn run_rpass_test(&self) { + let emit_metadata = self.should_emit_metadata(self.pass_mode()); + let should_run = self.run_if_enabled(); + let proc_res = self.compile_test(should_run, emit_metadata); + + if !proc_res.status.success() { + self.fatal_proc_rec("compilation failed!", &proc_res); + } + + // FIXME(#41968): Move this check to tidy? + if !errors::load_errors(&self.testpaths.file, self.revision).is_empty() { + self.fatal("run-pass tests with expected warnings should be moved to ui/"); + } + + if let WillExecute::Disabled = should_run { + return; + } + + let proc_res = self.exec_compiled_test(); + if !proc_res.status.success() { + self.fatal_proc_rec("test run failed!", &proc_res); + } + } + fn run_cfail_test(&self) { let pm = self.pass_mode(); let proc_res = self.compile_test(WillExecute::No, self.should_emit_metadata(pm)); @@ -115,12 +135,6 @@ impl TestCx<'_> { let proc_res = self.exec_compiled_test(); - // The value our Makefile configures valgrind to return on failure - const VALGRIND_ERR: i32 = 100; - if proc_res.status.code() == Some(VALGRIND_ERR) { - self.fatal_proc_rec("run-fail test isn't valgrind-clean!", &proc_res); - } - let output_to_check = self.get_output(&proc_res); self.check_correct_failure_status(&proc_res); self.check_all_error_patterns(&output_to_check, &proc_res, pm); diff --git a/src/tools/compiletest/src/runtest/valgrind.rs b/src/tools/compiletest/src/runtest/valgrind.rs deleted file mode 100644 index 8d72c4be9ff29..0000000000000 --- a/src/tools/compiletest/src/runtest/valgrind.rs +++ /dev/null @@ -1,34 +0,0 @@ -use super::{Emit, TestCx, WillExecute}; - -impl TestCx<'_> { - pub(super) fn run_valgrind_test(&self) { - assert!(self.revision.is_none(), "revisions not relevant here"); - - // FIXME(jieyouxu): does this really make any sense? If a valgrind test isn't testing - // valgrind, what is it even testing? - if self.config.valgrind_path.is_none() { - assert!(!self.config.force_valgrind); - return self.run_rpass_test(); - } - - let should_run = self.run_if_enabled(); - let mut proc_res = self.compile_test(should_run, Emit::None); - - if !proc_res.status.success() { - self.fatal_proc_rec("compilation failed!", &proc_res); - } - - if let WillExecute::Disabled = should_run { - return; - } - - let mut new_config = self.config.clone(); - new_config.runner = new_config.valgrind_path.clone(); - let new_cx = TestCx { config: &new_config, ..*self }; - proc_res = new_cx.exec_compiled_test(); - - if !proc_res.status.success() { - self.fatal_proc_rec("test run failed!", &proc_res); - } - } -} From de588a6e6069f06aac04e4bd0b6d93e3db2a70e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=AE=B8=E6=9D=B0=E5=8F=8B=20Jieyou=20Xu=20=28Joe=29?= Date: Mon, 7 Oct 2024 07:53:14 +0000 Subject: [PATCH 1969/2194] Remove valgrind test suite support from bootstrap --- src/bootstrap/src/core/build_steps/test.rs | 6 ------ src/bootstrap/src/core/builder.rs | 2 -- 2 files changed, 8 deletions(-) diff --git a/src/bootstrap/src/core/build_steps/test.rs b/src/bootstrap/src/core/build_steps/test.rs index 7283b0e9574c5..7a49b68b91e65 100644 --- a/src/bootstrap/src/core/build_steps/test.rs +++ b/src/bootstrap/src/core/build_steps/test.rs @@ -1394,12 +1394,6 @@ default_test!(Ui { path: "tests/ui", mode: "ui", suite: "ui" }); default_test!(Crashes { path: "tests/crashes", mode: "crashes", suite: "crashes" }); -default_test!(RunPassValgrind { - path: "tests/run-pass-valgrind", - mode: "run-pass-valgrind", - suite: "run-pass-valgrind" -}); - default_test!(Codegen { path: "tests/codegen", mode: "codegen", suite: "codegen" }); default_test!(CodegenUnits { diff --git a/src/bootstrap/src/core/builder.rs b/src/bootstrap/src/core/builder.rs index e7a19d0bcc0df..4ca06e680d3e8 100644 --- a/src/bootstrap/src/core/builder.rs +++ b/src/bootstrap/src/core/builder.rs @@ -327,7 +327,6 @@ const PATH_REMAP: &[(&str, &[&str])] = &[ "tests/mir-opt", "tests/pretty", "tests/run-make", - "tests/run-pass-valgrind", "tests/rustdoc", "tests/rustdoc-gui", "tests/rustdoc-js", @@ -852,7 +851,6 @@ impl<'a> Builder<'a> { test::Tidy, test::Ui, test::Crashes, - test::RunPassValgrind, test::Coverage, test::CoverageMap, test::CoverageRun, From f1e408a8debad9b6dd230cc7b7e914e8d7c2fdd6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=AE=B8=E6=9D=B0=E5=8F=8B=20Jieyou=20Xu=20=28Joe=29?= Date: Mon, 7 Oct 2024 07:54:57 +0000 Subject: [PATCH 1970/2194] Remove valgrind test suite from opt-dist --- src/tools/opt-dist/src/tests.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/tools/opt-dist/src/tests.rs b/src/tools/opt-dist/src/tests.rs index 82c393d34a679..e401554640c49 100644 --- a/src/tools/opt-dist/src/tests.rs +++ b/src/tools/opt-dist/src/tests.rs @@ -96,7 +96,6 @@ llvm-config = "{llvm_config}" "tests/incremental", "tests/mir-opt", "tests/pretty", - "tests/run-pass-valgrind", "tests/ui", "tests/crashes", ]; From fa3c25e1124d4cd45efde79efdd7455e48379eda Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=AE=B8=E6=9D=B0=E5=8F=8B=20Jieyou=20Xu=20=28Joe=29?= Date: Mon, 7 Oct 2024 08:02:30 +0000 Subject: [PATCH 1971/2194] Delete the `run-pass-valgrind` test suite --- .../run-pass-valgrind/cast-enum-with-dtor.rs | 34 --------- .../cleanup-auto-borrow-obj.rs | 28 -------- tests/run-pass-valgrind/cleanup-stdin.rs | 5 -- tests/run-pass-valgrind/coerce-match-calls.rs | 21 ------ tests/run-pass-valgrind/coerce-match.rs | 31 --------- .../down-with-thread-dtors.rs | 43 ------------ tests/run-pass-valgrind/dst-dtor-1.rs | 28 -------- tests/run-pass-valgrind/dst-dtor-2.rs | 23 ------- tests/run-pass-valgrind/dst-dtor-3.rs | 26 ------- tests/run-pass-valgrind/dst-dtor-4.rs | 21 ------ tests/run-pass-valgrind/exit-flushes.rs | 19 ----- tests/run-pass-valgrind/issue-44800.rs | 12 ---- .../by-value-trait-objects-rust-call.rs | 55 --------------- .../by-value-trait-objects-rust-call2.rs | 69 ------------------- .../unsized-locals/by-value-trait-objects.rs | 48 ------------- .../long-live-the-unsized-temporary.rs | 52 -------------- 16 files changed, 515 deletions(-) delete mode 100644 tests/run-pass-valgrind/cast-enum-with-dtor.rs delete mode 100644 tests/run-pass-valgrind/cleanup-auto-borrow-obj.rs delete mode 100644 tests/run-pass-valgrind/cleanup-stdin.rs delete mode 100644 tests/run-pass-valgrind/coerce-match-calls.rs delete mode 100644 tests/run-pass-valgrind/coerce-match.rs delete mode 100644 tests/run-pass-valgrind/down-with-thread-dtors.rs delete mode 100644 tests/run-pass-valgrind/dst-dtor-1.rs delete mode 100644 tests/run-pass-valgrind/dst-dtor-2.rs delete mode 100644 tests/run-pass-valgrind/dst-dtor-3.rs delete mode 100644 tests/run-pass-valgrind/dst-dtor-4.rs delete mode 100644 tests/run-pass-valgrind/exit-flushes.rs delete mode 100644 tests/run-pass-valgrind/issue-44800.rs delete mode 100644 tests/run-pass-valgrind/unsized-locals/by-value-trait-objects-rust-call.rs delete mode 100644 tests/run-pass-valgrind/unsized-locals/by-value-trait-objects-rust-call2.rs delete mode 100644 tests/run-pass-valgrind/unsized-locals/by-value-trait-objects.rs delete mode 100644 tests/run-pass-valgrind/unsized-locals/long-live-the-unsized-temporary.rs diff --git a/tests/run-pass-valgrind/cast-enum-with-dtor.rs b/tests/run-pass-valgrind/cast-enum-with-dtor.rs deleted file mode 100644 index a57dc3734789e..0000000000000 --- a/tests/run-pass-valgrind/cast-enum-with-dtor.rs +++ /dev/null @@ -1,34 +0,0 @@ -#![allow(dead_code, cenum_impl_drop_cast)] - -// check dtor calling order when casting enums. - -use std::mem; -use std::sync::atomic; -use std::sync::atomic::Ordering; - -enum E { - A = 0, - B = 1, - C = 2, -} - -static FLAG: atomic::AtomicUsize = atomic::AtomicUsize::new(0); - -impl Drop for E { - fn drop(&mut self) { - // avoid dtor loop - unsafe { mem::forget(mem::replace(self, E::B)) }; - - FLAG.store(FLAG.load(Ordering::SeqCst) + 1, Ordering::SeqCst); - } -} - -fn main() { - assert_eq!(FLAG.load(Ordering::SeqCst), 0); - { - let e = E::C; - assert_eq!(e as u32, 2); - assert_eq!(FLAG.load(Ordering::SeqCst), 1); - } - assert_eq!(FLAG.load(Ordering::SeqCst), 1); -} diff --git a/tests/run-pass-valgrind/cleanup-auto-borrow-obj.rs b/tests/run-pass-valgrind/cleanup-auto-borrow-obj.rs deleted file mode 100644 index e4ce80b330593..0000000000000 --- a/tests/run-pass-valgrind/cleanup-auto-borrow-obj.rs +++ /dev/null @@ -1,28 +0,0 @@ -// This would previously leak the Box because we wouldn't -// schedule cleanups when auto borrowing trait objects. -// This program should be valgrind clean. - -static mut DROP_RAN: bool = false; - -struct Foo; -impl Drop for Foo { - fn drop(&mut self) { - unsafe { - DROP_RAN = true; - } - } -} - -trait Trait { - fn dummy(&self) {} -} -impl Trait for Foo {} - -pub fn main() { - { - let _x: &Trait = &*(Box::new(Foo) as Box); - } - unsafe { - assert!(DROP_RAN); - } -} diff --git a/tests/run-pass-valgrind/cleanup-stdin.rs b/tests/run-pass-valgrind/cleanup-stdin.rs deleted file mode 100644 index cf8f81cf5aa7c..0000000000000 --- a/tests/run-pass-valgrind/cleanup-stdin.rs +++ /dev/null @@ -1,5 +0,0 @@ -fn main() { - let _ = std::io::stdin(); - let _ = std::io::stdout(); - let _ = std::io::stderr(); -} diff --git a/tests/run-pass-valgrind/coerce-match-calls.rs b/tests/run-pass-valgrind/coerce-match-calls.rs deleted file mode 100644 index 8c7375610dd76..0000000000000 --- a/tests/run-pass-valgrind/coerce-match-calls.rs +++ /dev/null @@ -1,21 +0,0 @@ -// Check that coercions are propagated through match and if expressions. - -//@ pretty-expanded FIXME #23616 - -use std::boxed::Box; - -pub fn main() { - let _: Box<[isize]> = if true { Box::new([1, 2, 3]) } else { Box::new([1]) }; - - let _: Box<[isize]> = match true { - true => Box::new([1, 2, 3]), - false => Box::new([1]), - }; - - // Check we don't get over-keen at propagating coercions in the case of casts. - let x = if true { 42 } else { 42u8 } as u16; - let x = match true { - true => 42, - false => 42u8, - } as u16; -} diff --git a/tests/run-pass-valgrind/coerce-match.rs b/tests/run-pass-valgrind/coerce-match.rs deleted file mode 100644 index 95f16a8cc896e..0000000000000 --- a/tests/run-pass-valgrind/coerce-match.rs +++ /dev/null @@ -1,31 +0,0 @@ -// Check that coercions are propagated through match and if expressions. - -//@ pretty-expanded FIXME #23616 - -pub fn main() { - let _: Box<[isize]> = if true { - let b: Box<_> = Box::new([1, 2, 3]); - b - } else { - let b: Box<_> = Box::new([1]); - b - }; - - let _: Box<[isize]> = match true { - true => { - let b: Box<_> = Box::new([1, 2, 3]); - b - } - false => { - let b: Box<_> = Box::new([1]); - b - } - }; - - // Check we don't get over-keen at propagating coercions in the case of casts. - let x = if true { 42 } else { 42u8 } as u16; - let x = match true { - true => 42, - false => 42u8, - } as u16; -} diff --git a/tests/run-pass-valgrind/down-with-thread-dtors.rs b/tests/run-pass-valgrind/down-with-thread-dtors.rs deleted file mode 100644 index 0d3745bba5ba9..0000000000000 --- a/tests/run-pass-valgrind/down-with-thread-dtors.rs +++ /dev/null @@ -1,43 +0,0 @@ -//@ ignore-emscripten - -thread_local!(static FOO: Foo = Foo); -thread_local!(static BAR: Bar = Bar(1)); -thread_local!(static BAZ: Baz = Baz); - -static mut HIT: bool = false; - -struct Foo; -struct Bar(i32); -struct Baz; - -impl Drop for Foo { - fn drop(&mut self) { - BAR.with(|_| {}); - } -} - -impl Drop for Bar { - fn drop(&mut self) { - assert_eq!(self.0, 1); - self.0 = 2; - BAZ.with(|_| {}); - assert_eq!(self.0, 2); - } -} - -impl Drop for Baz { - fn drop(&mut self) { - unsafe { - HIT = true; - } - } -} - -fn main() { - std::thread::spawn(|| { - FOO.with(|_| {}); - }) - .join() - .unwrap(); - assert!(unsafe { HIT }); -} diff --git a/tests/run-pass-valgrind/dst-dtor-1.rs b/tests/run-pass-valgrind/dst-dtor-1.rs deleted file mode 100644 index 47065151a037b..0000000000000 --- a/tests/run-pass-valgrind/dst-dtor-1.rs +++ /dev/null @@ -1,28 +0,0 @@ -static mut DROP_RAN: bool = false; - -struct Foo; -impl Drop for Foo { - fn drop(&mut self) { - unsafe { - DROP_RAN = true; - } - } -} - -trait Trait { - fn dummy(&self) {} -} -impl Trait for Foo {} - -struct Fat { - f: T, -} - -pub fn main() { - { - let _x: Box> = Box::>::new(Fat { f: Foo }); - } - unsafe { - assert!(DROP_RAN); - } -} diff --git a/tests/run-pass-valgrind/dst-dtor-2.rs b/tests/run-pass-valgrind/dst-dtor-2.rs deleted file mode 100644 index d8abebfb4473c..0000000000000 --- a/tests/run-pass-valgrind/dst-dtor-2.rs +++ /dev/null @@ -1,23 +0,0 @@ -static mut DROP_RAN: isize = 0; - -struct Foo; -impl Drop for Foo { - fn drop(&mut self) { - unsafe { - DROP_RAN += 1; - } - } -} - -struct Fat { - f: T, -} - -pub fn main() { - { - let _x: Box> = Box::>::new(Fat { f: [Foo, Foo, Foo] }); - } - unsafe { - assert_eq!(DROP_RAN, 3); - } -} diff --git a/tests/run-pass-valgrind/dst-dtor-3.rs b/tests/run-pass-valgrind/dst-dtor-3.rs deleted file mode 100644 index 09adaca21c714..0000000000000 --- a/tests/run-pass-valgrind/dst-dtor-3.rs +++ /dev/null @@ -1,26 +0,0 @@ -#![feature(unsized_tuple_coercion)] - -static mut DROP_RAN: bool = false; - -struct Foo; -impl Drop for Foo { - fn drop(&mut self) { - unsafe { - DROP_RAN = true; - } - } -} - -trait Trait { - fn dummy(&self) {} -} -impl Trait for Foo {} - -pub fn main() { - { - let _x: Box<(i32, Trait)> = Box::<(i32, Foo)>::new((42, Foo)); - } - unsafe { - assert!(DROP_RAN); - } -} diff --git a/tests/run-pass-valgrind/dst-dtor-4.rs b/tests/run-pass-valgrind/dst-dtor-4.rs deleted file mode 100644 index a66ac8e3cfca6..0000000000000 --- a/tests/run-pass-valgrind/dst-dtor-4.rs +++ /dev/null @@ -1,21 +0,0 @@ -#![feature(unsized_tuple_coercion)] - -static mut DROP_RAN: isize = 0; - -struct Foo; -impl Drop for Foo { - fn drop(&mut self) { - unsafe { - DROP_RAN += 1; - } - } -} - -pub fn main() { - { - let _x: Box<(i32, [Foo])> = Box::<(i32, [Foo; 3])>::new((42, [Foo, Foo, Foo])); - } - unsafe { - assert_eq!(DROP_RAN, 3); - } -} diff --git a/tests/run-pass-valgrind/exit-flushes.rs b/tests/run-pass-valgrind/exit-flushes.rs deleted file mode 100644 index 4e25ef76d39af..0000000000000 --- a/tests/run-pass-valgrind/exit-flushes.rs +++ /dev/null @@ -1,19 +0,0 @@ -//@ ignore-wasm32 no subprocess support -//@ ignore-sgx no processes -//@ ignore-apple this needs valgrind 3.11 or higher; see -// https://github.com/rust-lang/rust/pull/30365#issuecomment-165763679 - -use std::env; -use std::process::{Command, exit}; - -fn main() { - if env::args().len() > 1 { - print!("hello!"); - exit(0); - } else { - let out = Command::new(env::args().next().unwrap()).arg("foo").output().unwrap(); - assert!(out.status.success()); - assert_eq!(String::from_utf8(out.stdout).unwrap(), "hello!"); - assert_eq!(String::from_utf8(out.stderr).unwrap(), ""); - } -} diff --git a/tests/run-pass-valgrind/issue-44800.rs b/tests/run-pass-valgrind/issue-44800.rs deleted file mode 100644 index f76657ca75207..0000000000000 --- a/tests/run-pass-valgrind/issue-44800.rs +++ /dev/null @@ -1,12 +0,0 @@ -use std::alloc::System; -use std::collections::VecDeque; - -#[global_allocator] -static ALLOCATOR: System = System; - -fn main() { - let mut deque = VecDeque::with_capacity(32); - deque.push_front(0); - deque.reserve(31); - deque.push_back(0); -} diff --git a/tests/run-pass-valgrind/unsized-locals/by-value-trait-objects-rust-call.rs b/tests/run-pass-valgrind/unsized-locals/by-value-trait-objects-rust-call.rs deleted file mode 100644 index 5d3f558a63a97..0000000000000 --- a/tests/run-pass-valgrind/unsized-locals/by-value-trait-objects-rust-call.rs +++ /dev/null @@ -1,55 +0,0 @@ -#![feature(unsized_locals)] -#![feature(unboxed_closures)] -#![feature(tuple_trait)] - -pub trait FnOnce { - type Output; - extern "rust-call" fn call_once(self, args: Args) -> Self::Output; -} - -struct A; - -impl FnOnce<()> for A { - type Output = String; - extern "rust-call" fn call_once(self, (): ()) -> Self::Output { - format!("hello") - } -} - -struct B(i32); - -impl FnOnce<()> for B { - type Output = String; - extern "rust-call" fn call_once(self, (): ()) -> Self::Output { - format!("{}", self.0) - } -} - -struct C(String); - -impl FnOnce<()> for C { - type Output = String; - extern "rust-call" fn call_once(self, (): ()) -> Self::Output { - self.0 - } -} - -struct D(Box); - -impl FnOnce<()> for D { - type Output = String; - extern "rust-call" fn call_once(self, (): ()) -> Self::Output { - *self.0 - } -} - -fn main() { - let x = *(Box::new(A) as Box>); - assert_eq!(x.call_once(()), format!("hello")); - let x = *(Box::new(B(42)) as Box>); - assert_eq!(x.call_once(()), format!("42")); - let x = *(Box::new(C(format!("jumping fox"))) as Box>); - assert_eq!(x.call_once(()), format!("jumping fox")); - let x = *(Box::new(D(Box::new(format!("lazy dog")))) as Box>); - assert_eq!(x.call_once(()), format!("lazy dog")); -} diff --git a/tests/run-pass-valgrind/unsized-locals/by-value-trait-objects-rust-call2.rs b/tests/run-pass-valgrind/unsized-locals/by-value-trait-objects-rust-call2.rs deleted file mode 100644 index 9b6648f2e27a5..0000000000000 --- a/tests/run-pass-valgrind/unsized-locals/by-value-trait-objects-rust-call2.rs +++ /dev/null @@ -1,69 +0,0 @@ -#![feature(unsized_locals)] -#![feature(unboxed_closures)] -#![feature(tuple_trait)] - -pub trait FnOnce { - type Output; - extern "rust-call" fn call_once(self, args: Args) -> Self::Output; -} - -struct A; - -impl FnOnce<(String, Box)> for A { - type Output = String; - extern "rust-call" fn call_once(self, (s1, s2): (String, Box)) -> Self::Output { - assert_eq!(&s1 as &str, "s1"); - assert_eq!(&s2 as &str, "s2"); - format!("hello") - } -} - -struct B(i32); - -impl FnOnce<(String, Box)> for B { - type Output = String; - extern "rust-call" fn call_once(self, (s1, s2): (String, Box)) -> Self::Output { - assert_eq!(&s1 as &str, "s1"); - assert_eq!(&s2 as &str, "s2"); - format!("{}", self.0) - } -} - -struct C(String); - -impl FnOnce<(String, Box)> for C { - type Output = String; - extern "rust-call" fn call_once(self, (s1, s2): (String, Box)) -> Self::Output { - assert_eq!(&s1 as &str, "s1"); - assert_eq!(&s2 as &str, "s2"); - self.0 - } -} - -struct D(Box); - -impl FnOnce<(String, Box)> for D { - type Output = String; - extern "rust-call" fn call_once(self, (s1, s2): (String, Box)) -> Self::Output { - assert_eq!(&s1 as &str, "s1"); - assert_eq!(&s2 as &str, "s2"); - *self.0 - } -} - -fn main() { - let (s1, s2) = (format!("s1"), format!("s2").into_boxed_str()); - let x = *(Box::new(A) as Box), Output = String>>); - assert_eq!(x.call_once((s1, s2)), format!("hello")); - let (s1, s2) = (format!("s1"), format!("s2").into_boxed_str()); - let x = *(Box::new(B(42)) as Box), Output = String>>); - assert_eq!(x.call_once((s1, s2)), format!("42")); - let (s1, s2) = (format!("s1"), format!("s2").into_boxed_str()); - let x = *(Box::new(C(format!("jumping fox"))) - as Box), Output = String>>); - assert_eq!(x.call_once((s1, s2)), format!("jumping fox")); - let (s1, s2) = (format!("s1"), format!("s2").into_boxed_str()); - let x = *(Box::new(D(Box::new(format!("lazy dog")))) - as Box), Output = String>>); - assert_eq!(x.call_once((s1, s2)), format!("lazy dog")); -} diff --git a/tests/run-pass-valgrind/unsized-locals/by-value-trait-objects.rs b/tests/run-pass-valgrind/unsized-locals/by-value-trait-objects.rs deleted file mode 100644 index 3f6b6d262b5dc..0000000000000 --- a/tests/run-pass-valgrind/unsized-locals/by-value-trait-objects.rs +++ /dev/null @@ -1,48 +0,0 @@ -#![feature(unsized_locals)] - -pub trait Foo { - fn foo(self) -> String; -} - -struct A; - -impl Foo for A { - fn foo(self) -> String { - format!("hello") - } -} - -struct B(i32); - -impl Foo for B { - fn foo(self) -> String { - format!("{}", self.0) - } -} - -struct C(String); - -impl Foo for C { - fn foo(self) -> String { - self.0 - } -} - -struct D(Box); - -impl Foo for D { - fn foo(self) -> String { - *self.0 - } -} - -fn main() { - let x = *(Box::new(A) as Box); - assert_eq!(x.foo(), format!("hello")); - let x = *(Box::new(B(42)) as Box); - assert_eq!(x.foo(), format!("42")); - let x = *(Box::new(C(format!("jumping fox"))) as Box); - assert_eq!(x.foo(), format!("jumping fox")); - let x = *(Box::new(D(Box::new(format!("lazy dog")))) as Box); - assert_eq!(x.foo(), format!("lazy dog")); -} diff --git a/tests/run-pass-valgrind/unsized-locals/long-live-the-unsized-temporary.rs b/tests/run-pass-valgrind/unsized-locals/long-live-the-unsized-temporary.rs deleted file mode 100644 index a7b9052617f0c..0000000000000 --- a/tests/run-pass-valgrind/unsized-locals/long-live-the-unsized-temporary.rs +++ /dev/null @@ -1,52 +0,0 @@ -#![allow(incomplete_features)] -#![feature(unsized_locals, unsized_fn_params)] - -use std::fmt; - -fn gen_foo() -> Box { - Box::new(Box::new("foo")) -} - -fn foo(x: fmt::Display) { - assert_eq!(x.to_string(), "foo"); -} - -fn foo_indirect(x: fmt::Display) { - foo(x); -} - -fn main() { - foo(*gen_foo()); - foo_indirect(*gen_foo()); - - { - let x: fmt::Display = *gen_foo(); - foo(x); - } - - { - let x: fmt::Display = *gen_foo(); - let y: fmt::Display = *gen_foo(); - foo(x); - foo(y); - } - - { - let mut cnt: usize = 3; - let x = loop { - let x: fmt::Display = *gen_foo(); - if cnt == 0 { - break x; - } else { - cnt -= 1; - } - }; - foo(x); - } - - { - let x: fmt::Display = *gen_foo(); - let x = if true { x } else { *gen_foo() }; - foo(x); - } -} From da71dfbc516ec6fb7aa18e23c393ba6d1d2fb523 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sun, 6 Oct 2024 22:42:28 -0400 Subject: [PATCH 1972/2194] Inline CombineFields --- compiler/rustc_infer/src/infer/at.rs | 89 +++++++-------- compiler/rustc_infer/src/infer/mod.rs | 1 - .../rustc_infer/src/infer/relate/combine.rs | 96 +--------------- .../rustc_infer/src/infer/relate/lattice.rs | 96 ++++++++++------ compiler/rustc_infer/src/infer/relate/mod.rs | 4 +- .../src/infer/relate/type_relating.rs | 106 ++++++++++-------- 6 files changed, 174 insertions(+), 218 deletions(-) diff --git a/compiler/rustc_infer/src/infer/at.rs b/compiler/rustc_infer/src/infer/at.rs index 183973af4f9f3..ecef90c5ca25d 100644 --- a/compiler/rustc_infer/src/infer/at.rs +++ b/compiler/rustc_infer/src/infer/at.rs @@ -25,12 +25,13 @@ //! sometimes useful when the types of `c` and `d` are not traceable //! things. (That system should probably be refactored.) +use relate::lattice::{LatticeOp, LatticeOpKind}; use rustc_middle::bug; use rustc_middle::ty::{Const, ImplSubject}; use super::*; +use crate::infer::relate::type_relating::TypeRelating; use crate::infer::relate::{Relate, StructurallyRelateAliases, TypeRelation}; -use crate::traits::Obligation; /// Whether we should define opaque types or just treat them opaquely. /// @@ -108,14 +109,16 @@ impl<'a, 'tcx> At<'a, 'tcx> { where T: ToTrace<'tcx>, { - let mut fields = CombineFields::new( + let mut op = TypeRelating::new( self.infcx, ToTrace::to_trace(self.cause, expected, actual), self.param_env, define_opaque_types, + StructurallyRelateAliases::No, + ty::Contravariant, ); - fields.sup().relate(expected, actual)?; - Ok(InferOk { value: (), obligations: fields.into_obligations() }) + op.relate(expected, actual)?; + Ok(InferOk { value: (), obligations: op.into_obligations() }) } /// Makes `expected <: actual`. @@ -128,14 +131,16 @@ impl<'a, 'tcx> At<'a, 'tcx> { where T: ToTrace<'tcx>, { - let mut fields = CombineFields::new( + let mut op = TypeRelating::new( self.infcx, ToTrace::to_trace(self.cause, expected, actual), self.param_env, define_opaque_types, + StructurallyRelateAliases::No, + ty::Covariant, ); - fields.sub().relate(expected, actual)?; - Ok(InferOk { value: (), obligations: fields.into_obligations() }) + op.relate(expected, actual)?; + Ok(InferOk { value: (), obligations: op.into_obligations() }) } /// Makes `expected == actual`. @@ -167,23 +172,16 @@ impl<'a, 'tcx> At<'a, 'tcx> { where T: Relate>, { - let mut fields = CombineFields::new(self.infcx, trace, self.param_env, define_opaque_types); - fields.equate(StructurallyRelateAliases::No).relate(expected, actual)?; - Ok(InferOk { - value: (), - obligations: fields - .goals - .into_iter() - .map(|goal| { - Obligation::new( - self.infcx.tcx, - fields.trace.cause.clone(), - goal.param_env, - goal.predicate, - ) - }) - .collect(), - }) + let mut op = TypeRelating::new( + self.infcx, + trace, + self.param_env, + define_opaque_types, + StructurallyRelateAliases::No, + ty::Invariant, + ); + op.relate(expected, actual)?; + Ok(InferOk { value: (), obligations: op.into_obligations() }) } /// Equates `expected` and `found` while structurally relating aliases. @@ -198,14 +196,16 @@ impl<'a, 'tcx> At<'a, 'tcx> { T: ToTrace<'tcx>, { assert!(self.infcx.next_trait_solver()); - let mut fields = CombineFields::new( + let mut op = TypeRelating::new( self.infcx, ToTrace::to_trace(self.cause, expected, actual), self.param_env, DefineOpaqueTypes::Yes, + StructurallyRelateAliases::Yes, + ty::Invariant, ); - fields.equate(StructurallyRelateAliases::Yes).relate(expected, actual)?; - Ok(InferOk { value: (), obligations: fields.into_obligations() }) + op.relate(expected, actual)?; + Ok(InferOk { value: (), obligations: op.into_obligations() }) } pub fn relate( @@ -242,19 +242,16 @@ impl<'a, 'tcx> At<'a, 'tcx> { where T: Relate>, { - let mut fields = CombineFields::new( + let mut op = TypeRelating::new( self.infcx, TypeTrace::dummy(self.cause), self.param_env, DefineOpaqueTypes::Yes, - ); - fields.sub().relate_with_variance( + StructurallyRelateAliases::No, variance, - ty::VarianceDiagInfo::default(), - expected, - actual, - )?; - Ok(fields.goals) + ); + op.relate(expected, actual)?; + Ok(op.into_obligations().into_iter().map(|o| o.into()).collect()) } /// Used in the new solver since we don't care about tracking an `ObligationCause`. @@ -266,14 +263,16 @@ impl<'a, 'tcx> At<'a, 'tcx> { where T: Relate>, { - let mut fields = CombineFields::new( + let mut op = TypeRelating::new( self.infcx, TypeTrace::dummy(self.cause), self.param_env, DefineOpaqueTypes::Yes, + StructurallyRelateAliases::Yes, + ty::Invariant, ); - fields.equate(StructurallyRelateAliases::Yes).relate(expected, actual)?; - Ok(fields.goals) + op.relate(expected, actual)?; + Ok(op.into_obligations().into_iter().map(|o| o.into()).collect()) } /// Computes the least-upper-bound, or mutual supertype, of two @@ -290,14 +289,15 @@ impl<'a, 'tcx> At<'a, 'tcx> { where T: ToTrace<'tcx>, { - let mut fields = CombineFields::new( + let mut op = LatticeOp::new( self.infcx, ToTrace::to_trace(self.cause, expected, actual), self.param_env, define_opaque_types, + LatticeOpKind::Lub, ); - let value = fields.lub().relate(expected, actual)?; - Ok(InferOk { value, obligations: fields.into_obligations() }) + let value = op.relate(expected, actual)?; + Ok(InferOk { value, obligations: op.into_obligations() }) } /// Computes the greatest-lower-bound, or mutual subtype, of two @@ -312,14 +312,15 @@ impl<'a, 'tcx> At<'a, 'tcx> { where T: ToTrace<'tcx>, { - let mut fields = CombineFields::new( + let mut op = LatticeOp::new( self.infcx, ToTrace::to_trace(self.cause, expected, actual), self.param_env, define_opaque_types, + LatticeOpKind::Glb, ); - let value = fields.glb().relate(expected, actual)?; - Ok(InferOk { value, obligations: fields.into_obligations() }) + let value = op.relate(expected, actual)?; + Ok(InferOk { value, obligations: op.into_obligations() }) } } diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index 89dfa01925368..c179c1dcfe174 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -14,7 +14,6 @@ use region_constraints::{ GenericKind, RegionConstraintCollector, RegionConstraintStorage, VarInfos, VerifyBound, }; pub use relate::StructurallyRelateAliases; -use relate::combine::CombineFields; pub use relate::combine::PredicateEmittingRelation; use rustc_data_structures::captures::Captures; use rustc_data_structures::fx::{FxHashSet, FxIndexMap}; diff --git a/compiler/rustc_infer/src/infer/relate/combine.rs b/compiler/rustc_infer/src/infer/relate/combine.rs index 450437f217647..c4f5a85a8bee7 100644 --- a/compiler/rustc_infer/src/infer/relate/combine.rs +++ b/compiler/rustc_infer/src/infer/relate/combine.rs @@ -1,4 +1,4 @@ -//! There are four type combiners: [TypeRelating], `Lub`, and `Glb`, +//! There are four type combiners: `TypeRelating`, `Lub`, and `Glb`, //! and `NllTypeRelating` in rustc_borrowck, which is only used for NLL. //! //! Each implements the trait [TypeRelation] and contains methods for @@ -20,56 +20,13 @@ use rustc_middle::bug; use rustc_middle::infer::unify_key::EffectVarValue; -use rustc_middle::traits::solve::Goal; use rustc_middle::ty::error::{ExpectedFound, TypeError}; -use rustc_middle::ty::{self, InferConst, IntType, Ty, TyCtxt, TypeVisitableExt, UintType, Upcast}; +use rustc_middle::ty::{self, InferConst, IntType, Ty, TypeVisitableExt, UintType}; pub use rustc_next_trait_solver::relate::combine::*; use tracing::debug; -use super::lattice::{LatticeOp, LatticeOpKind}; -use super::type_relating::TypeRelating; use super::{RelateResult, StructurallyRelateAliases}; -use crate::infer::{DefineOpaqueTypes, InferCtxt, TypeTrace, relate}; -use crate::traits::{Obligation, PredicateObligation}; - -#[derive(Clone)] -pub(crate) struct CombineFields<'infcx, 'tcx> { - pub infcx: &'infcx InferCtxt<'tcx>, - // Immutable fields - pub trace: TypeTrace<'tcx>, - pub param_env: ty::ParamEnv<'tcx>, - pub define_opaque_types: DefineOpaqueTypes, - // Mutable fields - // - // Adding any additional field likely requires - // changes to the cache of `TypeRelating`. - pub goals: Vec>>, -} - -impl<'infcx, 'tcx> CombineFields<'infcx, 'tcx> { - pub(crate) fn new( - infcx: &'infcx InferCtxt<'tcx>, - trace: TypeTrace<'tcx>, - param_env: ty::ParamEnv<'tcx>, - define_opaque_types: DefineOpaqueTypes, - ) -> Self { - Self { infcx, trace, param_env, define_opaque_types, goals: vec![] } - } - - pub(crate) fn into_obligations(self) -> Vec> { - self.goals - .into_iter() - .map(|goal| { - Obligation::new( - self.infcx.tcx, - self.trace.cause.clone(), - goal.param_env, - goal.predicate, - ) - }) - .collect() - } -} +use crate::infer::{InferCtxt, relate}; impl<'tcx> InferCtxt<'tcx> { pub fn super_combine_tys( @@ -281,50 +238,3 @@ impl<'tcx> InferCtxt<'tcx> { val } } - -impl<'infcx, 'tcx> CombineFields<'infcx, 'tcx> { - pub(crate) fn tcx(&self) -> TyCtxt<'tcx> { - self.infcx.tcx - } - - pub(crate) fn equate<'a>( - &'a mut self, - structurally_relate_aliases: StructurallyRelateAliases, - ) -> TypeRelating<'a, 'infcx, 'tcx> { - TypeRelating::new(self, structurally_relate_aliases, ty::Invariant) - } - - pub(crate) fn sub<'a>(&'a mut self) -> TypeRelating<'a, 'infcx, 'tcx> { - TypeRelating::new(self, StructurallyRelateAliases::No, ty::Covariant) - } - - pub(crate) fn sup<'a>(&'a mut self) -> TypeRelating<'a, 'infcx, 'tcx> { - TypeRelating::new(self, StructurallyRelateAliases::No, ty::Contravariant) - } - - pub(crate) fn lub<'a>(&'a mut self) -> LatticeOp<'a, 'infcx, 'tcx> { - LatticeOp::new(self, LatticeOpKind::Lub) - } - - pub(crate) fn glb<'a>(&'a mut self) -> LatticeOp<'a, 'infcx, 'tcx> { - LatticeOp::new(self, LatticeOpKind::Glb) - } - - pub(crate) fn register_obligations( - &mut self, - obligations: impl IntoIterator>>, - ) { - self.goals.extend(obligations); - } - - pub(crate) fn register_predicates( - &mut self, - obligations: impl IntoIterator, ty::Predicate<'tcx>>>, - ) { - self.goals.extend( - obligations - .into_iter() - .map(|to_pred| Goal::new(self.infcx.tcx, self.param_env, to_pred)), - ) - } -} diff --git a/compiler/rustc_infer/src/infer/relate/lattice.rs b/compiler/rustc_infer/src/infer/relate/lattice.rs index 9564baa6ab287..877cb713c1e46 100644 --- a/compiler/rustc_infer/src/infer/relate/lattice.rs +++ b/compiler/rustc_infer/src/infer/relate/lattice.rs @@ -24,8 +24,9 @@ use rustc_span::Span; use tracing::{debug, instrument}; use super::StructurallyRelateAliases; -use super::combine::{CombineFields, PredicateEmittingRelation}; -use crate::infer::{DefineOpaqueTypes, InferCtxt, SubregionOrigin}; +use super::combine::PredicateEmittingRelation; +use crate::infer::{DefineOpaqueTypes, InferCtxt, SubregionOrigin, TypeTrace}; +use crate::traits::{Obligation, PredicateObligation}; #[derive(Clone, Copy)] pub(crate) enum LatticeOpKind { @@ -43,23 +44,36 @@ impl LatticeOpKind { } /// A greatest lower bound" (common subtype) or least upper bound (common supertype). -pub(crate) struct LatticeOp<'combine, 'infcx, 'tcx> { - fields: &'combine mut CombineFields<'infcx, 'tcx>, +pub(crate) struct LatticeOp<'infcx, 'tcx> { + infcx: &'infcx InferCtxt<'tcx>, + // Immutable fields + trace: TypeTrace<'tcx>, + param_env: ty::ParamEnv<'tcx>, + define_opaque_types: DefineOpaqueTypes, + // Mutable fields kind: LatticeOpKind, + obligations: Vec>, } -impl<'combine, 'infcx, 'tcx> LatticeOp<'combine, 'infcx, 'tcx> { +impl<'infcx, 'tcx> LatticeOp<'infcx, 'tcx> { pub(crate) fn new( - fields: &'combine mut CombineFields<'infcx, 'tcx>, + infcx: &'infcx InferCtxt<'tcx>, + trace: TypeTrace<'tcx>, + param_env: ty::ParamEnv<'tcx>, + define_opaque_types: DefineOpaqueTypes, kind: LatticeOpKind, - ) -> LatticeOp<'combine, 'infcx, 'tcx> { - LatticeOp { fields, kind } + ) -> LatticeOp<'infcx, 'tcx> { + LatticeOp { infcx, trace, param_env, define_opaque_types, kind, obligations: vec![] } + } + + pub(crate) fn into_obligations(self) -> Vec> { + self.obligations } } -impl<'tcx> TypeRelation> for LatticeOp<'_, '_, 'tcx> { +impl<'tcx> TypeRelation> for LatticeOp<'_, 'tcx> { fn cx(&self) -> TyCtxt<'tcx> { - self.fields.tcx() + self.infcx.tcx } fn relate_with_variance>>( @@ -70,7 +84,15 @@ impl<'tcx> TypeRelation> for LatticeOp<'_, '_, 'tcx> { b: T, ) -> RelateResult<'tcx, T> { match variance { - ty::Invariant => self.fields.equate(StructurallyRelateAliases::No).relate(a, b), + ty::Invariant => { + self.obligations.extend( + self.infcx + .at(&self.trace.cause, self.param_env) + .eq_trace(self.define_opaque_types, self.trace.clone(), a, b)? + .into_obligations(), + ); + Ok(a) + } ty::Covariant => self.relate(a, b), // FIXME(#41044) -- not correct, need test ty::Bivariant => Ok(a), @@ -90,7 +112,7 @@ impl<'tcx> TypeRelation> for LatticeOp<'_, '_, 'tcx> { return Ok(a); } - let infcx = self.fields.infcx; + let infcx = self.infcx; let a = infcx.shallow_resolve(a); let b = infcx.shallow_resolve(b); @@ -115,12 +137,12 @@ impl<'tcx> TypeRelation> for LatticeOp<'_, '_, 'tcx> { // iterate on the subtype obligations that are returned, but I // think this suffices. -nmatsakis (&ty::Infer(TyVar(..)), _) => { - let v = infcx.next_ty_var(self.fields.trace.cause.span); + let v = infcx.next_ty_var(self.trace.cause.span); self.relate_bound(v, b, a)?; Ok(v) } (_, &ty::Infer(TyVar(..))) => { - let v = infcx.next_ty_var(self.fields.trace.cause.span); + let v = infcx.next_ty_var(self.trace.cause.span); self.relate_bound(v, a, b)?; Ok(v) } @@ -132,7 +154,7 @@ impl<'tcx> TypeRelation> for LatticeOp<'_, '_, 'tcx> { (&ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }), _) | (_, &ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. })) - if self.fields.define_opaque_types == DefineOpaqueTypes::Yes + if self.define_opaque_types == DefineOpaqueTypes::Yes && def_id.is_local() && !infcx.next_trait_solver() => { @@ -155,8 +177,8 @@ impl<'tcx> TypeRelation> for LatticeOp<'_, '_, 'tcx> { a: ty::Region<'tcx>, b: ty::Region<'tcx>, ) -> RelateResult<'tcx, ty::Region<'tcx>> { - let origin = SubregionOrigin::Subtype(Box::new(self.fields.trace.clone())); - let mut inner = self.fields.infcx.inner.borrow_mut(); + let origin = SubregionOrigin::Subtype(Box::new(self.trace.clone())); + let mut inner = self.infcx.inner.borrow_mut(); let mut constraints = inner.unwrap_region_constraints(); Ok(match self.kind { // GLB(&'static u8, &'a u8) == &RegionLUB('static, 'a) u8 == &'static u8 @@ -173,7 +195,7 @@ impl<'tcx> TypeRelation> for LatticeOp<'_, '_, 'tcx> { a: ty::Const<'tcx>, b: ty::Const<'tcx>, ) -> RelateResult<'tcx, ty::Const<'tcx>> { - self.fields.infcx.super_combine_consts(self, a, b) + self.infcx.super_combine_consts(self, a, b) } fn binders( @@ -202,7 +224,7 @@ impl<'tcx> TypeRelation> for LatticeOp<'_, '_, 'tcx> { } } -impl<'combine, 'infcx, 'tcx> LatticeOp<'combine, 'infcx, 'tcx> { +impl<'infcx, 'tcx> LatticeOp<'infcx, 'tcx> { // Relates the type `v` to `a` and `b` such that `v` represents // the LUB/GLB of `a` and `b` as appropriate. // @@ -210,24 +232,24 @@ impl<'combine, 'infcx, 'tcx> LatticeOp<'combine, 'infcx, 'tcx> { // relates `v` to `a` first, which may help us to avoid unnecessary // type variable obligations. See caller for details. fn relate_bound(&mut self, v: Ty<'tcx>, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, ()> { - let mut sub = self.fields.sub(); + let at = self.infcx.at(&self.trace.cause, self.param_env); match self.kind { LatticeOpKind::Glb => { - sub.relate(v, a)?; - sub.relate(v, b)?; + self.obligations.extend(at.sub(self.define_opaque_types, v, a)?.into_obligations()); + self.obligations.extend(at.sub(self.define_opaque_types, v, b)?.into_obligations()); } LatticeOpKind::Lub => { - sub.relate(a, v)?; - sub.relate(b, v)?; + self.obligations.extend(at.sub(self.define_opaque_types, a, v)?.into_obligations()); + self.obligations.extend(at.sub(self.define_opaque_types, b, v)?.into_obligations()); } } Ok(()) } } -impl<'tcx> PredicateEmittingRelation> for LatticeOp<'_, '_, 'tcx> { +impl<'tcx> PredicateEmittingRelation> for LatticeOp<'_, 'tcx> { fn span(&self) -> Span { - self.fields.trace.span() + self.trace.span() } fn structurally_relate_aliases(&self) -> StructurallyRelateAliases { @@ -235,21 +257,27 @@ impl<'tcx> PredicateEmittingRelation> for LatticeOp<'_, '_, 'tcx } fn param_env(&self) -> ty::ParamEnv<'tcx> { - self.fields.param_env + self.param_env } fn register_predicates( &mut self, - obligations: impl IntoIterator, ty::Predicate<'tcx>>>, + preds: impl IntoIterator, ty::Predicate<'tcx>>>, ) { - self.fields.register_predicates(obligations); + self.obligations.extend(preds.into_iter().map(|pred| { + Obligation::new(self.infcx.tcx, self.trace.cause.clone(), self.param_env, pred) + })) } - fn register_goals( - &mut self, - obligations: impl IntoIterator>>, - ) { - self.fields.register_obligations(obligations); + fn register_goals(&mut self, goals: impl IntoIterator>>) { + self.obligations.extend(goals.into_iter().map(|goal| { + Obligation::new( + self.infcx.tcx, + self.trace.cause.clone(), + goal.param_env, + goal.predicate, + ) + })) } fn register_alias_relate_predicate(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) { diff --git a/compiler/rustc_infer/src/infer/relate/mod.rs b/compiler/rustc_infer/src/infer/relate/mod.rs index 85158faa65d13..baab5bb274a09 100644 --- a/compiler/rustc_infer/src/infer/relate/mod.rs +++ b/compiler/rustc_infer/src/infer/relate/mod.rs @@ -11,5 +11,5 @@ pub use self::combine::PredicateEmittingRelation; pub(super) mod combine; mod generalize; mod higher_ranked; -mod lattice; -mod type_relating; +pub(super) mod lattice; +pub(super) mod type_relating; diff --git a/compiler/rustc_infer/src/infer/relate/type_relating.rs b/compiler/rustc_infer/src/infer/relate/type_relating.rs index 7537ceec307a3..4b4b13e919cea 100644 --- a/compiler/rustc_infer/src/infer/relate/type_relating.rs +++ b/compiler/rustc_infer/src/infer/relate/type_relating.rs @@ -7,29 +7,31 @@ use rustc_span::Span; use rustc_type_ir::data_structures::DelayedSet; use tracing::{debug, instrument}; -use super::combine::CombineFields; use crate::infer::BoundRegionConversionTime::HigherRankedType; use crate::infer::relate::{PredicateEmittingRelation, StructurallyRelateAliases}; -use crate::infer::{DefineOpaqueTypes, InferCtxt, SubregionOrigin}; +use crate::infer::{DefineOpaqueTypes, InferCtxt, SubregionOrigin, TypeTrace}; +use crate::traits::{Obligation, PredicateObligation}; /// Enforce that `a` is equal to or a subtype of `b`. -pub(crate) struct TypeRelating<'combine, 'a, 'tcx> { - // Immutable except for the `InferCtxt` and the - // resulting nested `goals`. - fields: &'combine mut CombineFields<'a, 'tcx>, +pub(crate) struct TypeRelating<'infcx, 'tcx> { + infcx: &'infcx InferCtxt<'tcx>, - // Immutable field. + // Immutable fields + trace: TypeTrace<'tcx>, + param_env: ty::ParamEnv<'tcx>, + define_opaque_types: DefineOpaqueTypes, structurally_relate_aliases: StructurallyRelateAliases, - // Mutable field. - ambient_variance: ty::Variance, + // Mutable fields. + ambient_variance: ty::Variance, + obligations: Vec>, /// The cache only tracks the `ambient_variance` as it's the /// only field which is mutable and which meaningfully changes /// the result when relating types. /// /// The cache does not track whether the state of the /// `InferCtxt` has been changed or whether we've added any - /// obligations to `self.fields.goals`. Whether a goal is added + /// obligations to `self.goals`. Whether a goal is added /// once or multiple times is not really meaningful. /// /// Changes in the inference state may delay some type inference to @@ -48,24 +50,35 @@ pub(crate) struct TypeRelating<'combine, 'a, 'tcx> { cache: DelayedSet<(ty::Variance, Ty<'tcx>, Ty<'tcx>)>, } -impl<'combine, 'infcx, 'tcx> TypeRelating<'combine, 'infcx, 'tcx> { +impl<'infcx, 'tcx> TypeRelating<'infcx, 'tcx> { pub(crate) fn new( - f: &'combine mut CombineFields<'infcx, 'tcx>, + infcx: &'infcx InferCtxt<'tcx>, + trace: TypeTrace<'tcx>, + param_env: ty::ParamEnv<'tcx>, + define_opaque_types: DefineOpaqueTypes, structurally_relate_aliases: StructurallyRelateAliases, ambient_variance: ty::Variance, - ) -> TypeRelating<'combine, 'infcx, 'tcx> { + ) -> TypeRelating<'infcx, 'tcx> { TypeRelating { - fields: f, + infcx, + trace, + param_env, + define_opaque_types, structurally_relate_aliases, ambient_variance, + obligations: vec![], cache: Default::default(), } } + + pub(crate) fn into_obligations(self) -> Vec> { + self.obligations + } } -impl<'tcx> TypeRelation> for TypeRelating<'_, '_, 'tcx> { +impl<'tcx> TypeRelation> for TypeRelating<'_, 'tcx> { fn cx(&self) -> TyCtxt<'tcx> { - self.fields.infcx.tcx + self.infcx.tcx } fn relate_item_args( @@ -109,7 +122,7 @@ impl<'tcx> TypeRelation> for TypeRelating<'_, '_, 'tcx> { return Ok(a); } - let infcx = self.fields.infcx; + let infcx = self.infcx; let a = infcx.shallow_resolve(a); let b = infcx.shallow_resolve(b); @@ -123,9 +136,10 @@ impl<'tcx> TypeRelation> for TypeRelating<'_, '_, 'tcx> { ty::Covariant => { // can't make progress on `A <: B` if both A and B are // type variables, so record an obligation. - self.fields.goals.push(Goal::new( + self.obligations.push(Obligation::new( self.cx(), - self.fields.param_env, + self.trace.cause.clone(), + self.param_env, ty::Binder::dummy(ty::PredicateKind::Subtype(ty::SubtypePredicate { a_is_expected: true, a, @@ -136,9 +150,10 @@ impl<'tcx> TypeRelation> for TypeRelating<'_, '_, 'tcx> { ty::Contravariant => { // can't make progress on `B <: A` if both A and B are // type variables, so record an obligation. - self.fields.goals.push(Goal::new( + self.obligations.push(Obligation::new( self.cx(), - self.fields.param_env, + self.trace.cause.clone(), + self.param_env, ty::Binder::dummy(ty::PredicateKind::Subtype(ty::SubtypePredicate { a_is_expected: false, a: b, @@ -182,14 +197,14 @@ impl<'tcx> TypeRelation> for TypeRelating<'_, '_, 'tcx> { (&ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }), _) | (_, &ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. })) - if self.fields.define_opaque_types == DefineOpaqueTypes::Yes + if self.define_opaque_types == DefineOpaqueTypes::Yes && def_id.is_local() && !infcx.next_trait_solver() => { - self.fields.goals.extend(infcx.handle_opaque_type( + self.register_goals(infcx.handle_opaque_type( a, b, - self.fields.trace.cause.span, + self.trace.cause.span, self.param_env(), )?); } @@ -210,13 +225,12 @@ impl<'tcx> TypeRelation> for TypeRelating<'_, '_, 'tcx> { a: ty::Region<'tcx>, b: ty::Region<'tcx>, ) -> RelateResult<'tcx, ty::Region<'tcx>> { - let origin = SubregionOrigin::Subtype(Box::new(self.fields.trace.clone())); + let origin = SubregionOrigin::Subtype(Box::new(self.trace.clone())); match self.ambient_variance { // Subtype(&'a u8, &'b u8) => Outlives('a: 'b) => SubRegion('b, 'a) ty::Covariant => { - self.fields - .infcx + self.infcx .inner .borrow_mut() .unwrap_region_constraints() @@ -224,16 +238,14 @@ impl<'tcx> TypeRelation> for TypeRelating<'_, '_, 'tcx> { } // Suptype(&'a u8, &'b u8) => Outlives('b: 'a) => SubRegion('a, 'b) ty::Contravariant => { - self.fields - .infcx + self.infcx .inner .borrow_mut() .unwrap_region_constraints() .make_subregion(origin, a, b); } ty::Invariant => { - self.fields - .infcx + self.infcx .inner .borrow_mut() .unwrap_region_constraints() @@ -253,7 +265,7 @@ impl<'tcx> TypeRelation> for TypeRelating<'_, '_, 'tcx> { a: ty::Const<'tcx>, b: ty::Const<'tcx>, ) -> RelateResult<'tcx, ty::Const<'tcx>> { - self.fields.infcx.super_combine_consts(self, a, b) + self.infcx.super_combine_consts(self, a, b) } fn binders( @@ -271,8 +283,8 @@ impl<'tcx> TypeRelation> for TypeRelating<'_, '_, 'tcx> { { self.relate(a, b)?; } else { - let span = self.fields.trace.cause.span; - let infcx = self.fields.infcx; + let span = self.trace.cause.span; + let infcx = self.infcx; match self.ambient_variance { // Checks whether `for<..> sub <: for<..> sup` holds. @@ -335,13 +347,13 @@ impl<'tcx> TypeRelation> for TypeRelating<'_, '_, 'tcx> { } } -impl<'tcx> PredicateEmittingRelation> for TypeRelating<'_, '_, 'tcx> { +impl<'tcx> PredicateEmittingRelation> for TypeRelating<'_, 'tcx> { fn span(&self) -> Span { - self.fields.trace.span() + self.trace.span() } fn param_env(&self) -> ty::ParamEnv<'tcx> { - self.fields.param_env + self.param_env } fn structurally_relate_aliases(&self) -> StructurallyRelateAliases { @@ -350,16 +362,22 @@ impl<'tcx> PredicateEmittingRelation> for TypeRelating<'_, '_, ' fn register_predicates( &mut self, - obligations: impl IntoIterator, ty::Predicate<'tcx>>>, + preds: impl IntoIterator, ty::Predicate<'tcx>>>, ) { - self.fields.register_predicates(obligations); + self.obligations.extend(preds.into_iter().map(|pred| { + Obligation::new(self.infcx.tcx, self.trace.cause.clone(), self.param_env, pred) + })) } - fn register_goals( - &mut self, - obligations: impl IntoIterator>>, - ) { - self.fields.register_obligations(obligations); + fn register_goals(&mut self, goals: impl IntoIterator>>) { + self.obligations.extend(goals.into_iter().map(|goal| { + Obligation::new( + self.infcx.tcx, + self.trace.cause.clone(), + goal.param_env, + goal.predicate, + ) + })) } fn register_alias_relate_predicate(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) { From 5d62afd2baa5609de649db16389c96c953a1a42f Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sun, 6 Oct 2024 22:47:50 -0400 Subject: [PATCH 1973/2194] Remove unnecessary DefineOpaqueTypes from lub --- compiler/rustc_hir_typeck/src/coercion.rs | 26 +++++-------------- compiler/rustc_infer/src/infer/at.rs | 16 ++---------- .../rustc_infer/src/infer/relate/lattice.rs | 18 +++++-------- 3 files changed, 16 insertions(+), 44 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs index 642db3f36b586..bd0b98702983a 100644 --- a/compiler/rustc_hir_typeck/src/coercion.rs +++ b/compiler/rustc_hir_typeck/src/coercion.rs @@ -141,7 +141,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { let at = self.at(&self.cause, self.fcx.param_env); let res = if self.use_lub { - at.lub(DefineOpaqueTypes::Yes, b, a) + at.lub(b, a) } else { at.sup(DefineOpaqueTypes::Yes, b, a) .map(|InferOk { value: (), obligations }| InferOk { value: b, obligations }) @@ -1190,13 +1190,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { (ty::FnDef(..), ty::FnDef(..)) => { // Don't reify if the function types have a LUB, i.e., they // are the same function and their parameters have a LUB. - match self.commit_if_ok(|_| { - self.at(cause, self.param_env).lub( - DefineOpaqueTypes::Yes, - prev_ty, - new_ty, - ) - }) { + match self + .commit_if_ok(|_| self.at(cause, self.param_env).lub(prev_ty, new_ty)) + { // We have a LUB of prev_ty and new_ty, just return it. Ok(ok) => return Ok(self.register_infer_ok_obligations(ok)), Err(_) => { @@ -1239,7 +1235,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let (a_sig, b_sig) = self.normalize(new.span, (a_sig, b_sig)); let sig = self .at(cause, self.param_env) - .lub(DefineOpaqueTypes::Yes, a_sig, b_sig) + .lub(a_sig, b_sig) .map(|ok| self.register_infer_ok_obligations(ok))?; // Reify both sides and return the reified fn pointer type. @@ -1330,9 +1326,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ); return Err(self - .commit_if_ok(|_| { - self.at(cause, self.param_env).lub(DefineOpaqueTypes::Yes, prev_ty, new_ty) - }) + .commit_if_ok(|_| self.at(cause, self.param_env).lub(prev_ty, new_ty)) .unwrap_err()); } } @@ -1344,13 +1338,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { Err(e) } else { Err(self - .commit_if_ok(|_| { - self.at(cause, self.param_env).lub( - DefineOpaqueTypes::Yes, - prev_ty, - new_ty, - ) - }) + .commit_if_ok(|_| self.at(cause, self.param_env).lub(prev_ty, new_ty)) .unwrap_err()) } } diff --git a/compiler/rustc_infer/src/infer/at.rs b/compiler/rustc_infer/src/infer/at.rs index ecef90c5ca25d..170f44b17e75c 100644 --- a/compiler/rustc_infer/src/infer/at.rs +++ b/compiler/rustc_infer/src/infer/at.rs @@ -280,12 +280,7 @@ impl<'a, 'tcx> At<'a, 'tcx> { /// this can result in an error (e.g., if asked to compute LUB of /// u32 and i32), it is meaningful to call one of them the /// "expected type". - pub fn lub( - self, - define_opaque_types: DefineOpaqueTypes, - expected: T, - actual: T, - ) -> InferResult<'tcx, T> + pub fn lub(self, expected: T, actual: T) -> InferResult<'tcx, T> where T: ToTrace<'tcx>, { @@ -293,7 +288,6 @@ impl<'a, 'tcx> At<'a, 'tcx> { self.infcx, ToTrace::to_trace(self.cause, expected, actual), self.param_env, - define_opaque_types, LatticeOpKind::Lub, ); let value = op.relate(expected, actual)?; @@ -303,12 +297,7 @@ impl<'a, 'tcx> At<'a, 'tcx> { /// Computes the greatest-lower-bound, or mutual subtype, of two /// values. As with `lub` order doesn't matter, except for error /// cases. - pub fn glb( - self, - define_opaque_types: DefineOpaqueTypes, - expected: T, - actual: T, - ) -> InferResult<'tcx, T> + pub fn glb(self, expected: T, actual: T) -> InferResult<'tcx, T> where T: ToTrace<'tcx>, { @@ -316,7 +305,6 @@ impl<'a, 'tcx> At<'a, 'tcx> { self.infcx, ToTrace::to_trace(self.cause, expected, actual), self.param_env, - define_opaque_types, LatticeOpKind::Glb, ); let value = op.relate(expected, actual)?; diff --git a/compiler/rustc_infer/src/infer/relate/lattice.rs b/compiler/rustc_infer/src/infer/relate/lattice.rs index 877cb713c1e46..8cec312abf75b 100644 --- a/compiler/rustc_infer/src/infer/relate/lattice.rs +++ b/compiler/rustc_infer/src/infer/relate/lattice.rs @@ -49,7 +49,6 @@ pub(crate) struct LatticeOp<'infcx, 'tcx> { // Immutable fields trace: TypeTrace<'tcx>, param_env: ty::ParamEnv<'tcx>, - define_opaque_types: DefineOpaqueTypes, // Mutable fields kind: LatticeOpKind, obligations: Vec>, @@ -60,10 +59,9 @@ impl<'infcx, 'tcx> LatticeOp<'infcx, 'tcx> { infcx: &'infcx InferCtxt<'tcx>, trace: TypeTrace<'tcx>, param_env: ty::ParamEnv<'tcx>, - define_opaque_types: DefineOpaqueTypes, kind: LatticeOpKind, ) -> LatticeOp<'infcx, 'tcx> { - LatticeOp { infcx, trace, param_env, define_opaque_types, kind, obligations: vec![] } + LatticeOp { infcx, trace, param_env, kind, obligations: vec![] } } pub(crate) fn into_obligations(self) -> Vec> { @@ -88,7 +86,7 @@ impl<'tcx> TypeRelation> for LatticeOp<'_, 'tcx> { self.obligations.extend( self.infcx .at(&self.trace.cause, self.param_env) - .eq_trace(self.define_opaque_types, self.trace.clone(), a, b)? + .eq_trace(DefineOpaqueTypes::Yes, self.trace.clone(), a, b)? .into_obligations(), ); Ok(a) @@ -154,9 +152,7 @@ impl<'tcx> TypeRelation> for LatticeOp<'_, 'tcx> { (&ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }), _) | (_, &ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. })) - if self.define_opaque_types == DefineOpaqueTypes::Yes - && def_id.is_local() - && !infcx.next_trait_solver() => + if def_id.is_local() && !infcx.next_trait_solver() => { self.register_goals(infcx.handle_opaque_type( a, @@ -235,12 +231,12 @@ impl<'infcx, 'tcx> LatticeOp<'infcx, 'tcx> { let at = self.infcx.at(&self.trace.cause, self.param_env); match self.kind { LatticeOpKind::Glb => { - self.obligations.extend(at.sub(self.define_opaque_types, v, a)?.into_obligations()); - self.obligations.extend(at.sub(self.define_opaque_types, v, b)?.into_obligations()); + self.obligations.extend(at.sub(DefineOpaqueTypes::Yes, v, a)?.into_obligations()); + self.obligations.extend(at.sub(DefineOpaqueTypes::Yes, v, b)?.into_obligations()); } LatticeOpKind::Lub => { - self.obligations.extend(at.sub(self.define_opaque_types, a, v)?.into_obligations()); - self.obligations.extend(at.sub(self.define_opaque_types, b, v)?.into_obligations()); + self.obligations.extend(at.sub(DefineOpaqueTypes::Yes, a, v)?.into_obligations()); + self.obligations.extend(at.sub(DefineOpaqueTypes::Yes, b, v)?.into_obligations()); } } Ok(()) From 0c5d2f98d1883cfefe26d755107ccca9f0f0e9e9 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sun, 6 Oct 2024 22:50:29 -0400 Subject: [PATCH 1974/2194] Remove At methods that are unused --- compiler/rustc_infer/src/infer/at.rs | 41 ---------------------------- 1 file changed, 41 deletions(-) diff --git a/compiler/rustc_infer/src/infer/at.rs b/compiler/rustc_infer/src/infer/at.rs index 170f44b17e75c..5422761a6cf74 100644 --- a/compiler/rustc_infer/src/infer/at.rs +++ b/compiler/rustc_infer/src/infer/at.rs @@ -184,30 +184,6 @@ impl<'a, 'tcx> At<'a, 'tcx> { Ok(InferOk { value: (), obligations: op.into_obligations() }) } - /// Equates `expected` and `found` while structurally relating aliases. - /// This should only be used inside of the next generation trait solver - /// when relating rigid aliases. - pub fn eq_structurally_relating_aliases( - self, - expected: T, - actual: T, - ) -> InferResult<'tcx, ()> - where - T: ToTrace<'tcx>, - { - assert!(self.infcx.next_trait_solver()); - let mut op = TypeRelating::new( - self.infcx, - ToTrace::to_trace(self.cause, expected, actual), - self.param_env, - DefineOpaqueTypes::Yes, - StructurallyRelateAliases::Yes, - ty::Invariant, - ); - op.relate(expected, actual)?; - Ok(InferOk { value: (), obligations: op.into_obligations() }) - } - pub fn relate( self, define_opaque_types: DefineOpaqueTypes, @@ -293,23 +269,6 @@ impl<'a, 'tcx> At<'a, 'tcx> { let value = op.relate(expected, actual)?; Ok(InferOk { value, obligations: op.into_obligations() }) } - - /// Computes the greatest-lower-bound, or mutual subtype, of two - /// values. As with `lub` order doesn't matter, except for error - /// cases. - pub fn glb(self, expected: T, actual: T) -> InferResult<'tcx, T> - where - T: ToTrace<'tcx>, - { - let mut op = LatticeOp::new( - self.infcx, - ToTrace::to_trace(self.cause, expected, actual), - self.param_env, - LatticeOpKind::Glb, - ); - let value = op.relate(expected, actual)?; - Ok(InferOk { value, obligations: op.into_obligations() }) - } } impl<'tcx> ToTrace<'tcx> for ImplSubject<'tcx> { From dde78bd9462fa50e035c46f6f7a7dba15194971e Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 7 Oct 2024 12:09:28 +0200 Subject: [PATCH 1975/2194] Add documentation for `runtest::check_rustdoc_test_option` method --- src/tools/compiletest/src/runtest.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 25a135aa32027..0674debd6a283 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -2109,6 +2109,10 @@ impl<'test> TestCx<'test> { .collect() } + /// This method is used for `//@ check-test-line-numbers-match`. + /// + /// It checks that doctests line in the displayed doctest "name" matches where they are + /// defined in source code. fn check_rustdoc_test_option(&self, res: ProcRes) { let mut other_files = Vec::new(); let mut files: HashMap> = HashMap::new(); From 4085b48dfddd742fa4d46c594ee5662b972ae6de Mon Sep 17 00:00:00 2001 From: Michal Piotrowski Date: Mon, 7 Oct 2024 15:02:45 +0200 Subject: [PATCH 1976/2194] Fix used_underscore_binding in rustc_serialize --- compiler/rustc_serialize/src/opaque.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_serialize/src/opaque.rs b/compiler/rustc_serialize/src/opaque.rs index c7c561156e35b..27e9f817894f3 100644 --- a/compiler/rustc_serialize/src/opaque.rs +++ b/compiler/rustc_serialize/src/opaque.rs @@ -437,10 +437,10 @@ impl IntEncodedWithFixedSize { impl Encodable for IntEncodedWithFixedSize { #[inline] fn encode(&self, e: &mut FileEncoder) { - let _start_pos = e.position(); + let start_pos = e.position(); e.write_array(self.0.to_le_bytes()); - let _end_pos = e.position(); - debug_assert_eq!((_end_pos - _start_pos), IntEncodedWithFixedSize::ENCODED_SIZE); + let end_pos = e.position(); + debug_assert_eq!((end_pos - start_pos), IntEncodedWithFixedSize::ENCODED_SIZE); } } From 6d246e47fb55e089589681a41db6dedb20ccdaa3 Mon Sep 17 00:00:00 2001 From: Ben Kimock Date: Wed, 11 Sep 2024 18:04:40 -0400 Subject: [PATCH 1977/2194] Add precondition checks to ptr::offset, ptr::add, ptr::sub --- library/core/src/ptr/const_ptr.rs | 88 ++++++++++++++++++- library/core/src/ptr/mut_ptr.rs | 88 ++++++++++++++++++- tests/codegen/option-as-slice.rs | 8 +- ...e_add_fat.PreCodegen.after.panic-abort.mir | 12 ++- ..._add_fat.PreCodegen.after.panic-unwind.mir | 12 ++- ..._add_thin.PreCodegen.after.panic-abort.mir | 12 ++- ...add_thin.PreCodegen.after.panic-unwind.mir | 12 ++- ...ated_loop.PreCodegen.after.panic-abort.mir | 32 ++++--- ...ted_loop.PreCodegen.after.panic-unwind.mir | 12 ++- ...ward_loop.PreCodegen.after.panic-abort.mir | 8 +- ...ard_loop.PreCodegen.after.panic-unwind.mir | 8 +- ...erse_loop.PreCodegen.after.panic-abort.mir | 14 ++- ...rse_loop.PreCodegen.after.panic-unwind.mir | 14 ++- 13 files changed, 277 insertions(+), 43 deletions(-) diff --git a/library/core/src/ptr/const_ptr.rs b/library/core/src/ptr/const_ptr.rs index 332c5e904d7e0..4727dc77d18d4 100644 --- a/library/core/src/ptr/const_ptr.rs +++ b/library/core/src/ptr/const_ptr.rs @@ -395,6 +395,36 @@ impl *const T { where T: Sized, { + #[inline] + const fn runtime_offset_nowrap(this: *const (), count: isize, size: usize) -> bool { + #[inline] + fn runtime(this: *const (), count: isize, size: usize) -> bool { + // We know `size <= isize::MAX` so the `as` cast here is not lossy. + let Some(byte_offset) = count.checked_mul(size as isize) else { + return false; + }; + let (_, overflow) = this.addr().overflowing_add_signed(byte_offset); + !overflow + } + + const fn comptime(_: *const (), _: isize, _: usize) -> bool { + true + } + + // We can use const_eval_select here because this is only for UB checks. + intrinsics::const_eval_select((this, count, size), comptime, runtime) + } + + ub_checks::assert_unsafe_precondition!( + check_language_ub, + "ptr::offset requires the address calculation to not overflow", + ( + this: *const () = self as *const (), + count: isize = count, + size: usize = size_of::(), + ) => runtime_offset_nowrap(this, count, size) + ); + // SAFETY: the caller must uphold the safety contract for `offset`. unsafe { intrinsics::offset(self, count) } } @@ -726,7 +756,6 @@ impl *const T { true } - #[allow(unused_unsafe)] intrinsics::const_eval_select((this, origin), comptime, runtime) } @@ -858,6 +887,34 @@ impl *const T { where T: Sized, { + #[inline] + const fn runtime_add_nowrap(this: *const (), count: usize, size: usize) -> bool { + #[inline] + fn runtime(this: *const (), count: usize, size: usize) -> bool { + let Some(byte_offset) = count.checked_mul(size) else { + return false; + }; + let (_, overflow) = this.addr().overflowing_add(byte_offset); + byte_offset <= (isize::MAX as usize) && !overflow + } + + const fn comptime(_: *const (), _: usize, _: usize) -> bool { + true + } + + intrinsics::const_eval_select((this, count, size), comptime, runtime) + } + + ub_checks::assert_unsafe_precondition!( + check_language_ub, + "ptr::add requires that the address calculation does not overflow", + ( + this: *const () = self as *const (), + count: usize = count, + size: usize = size_of::(), + ) => runtime_add_nowrap(this, count, size) + ); + // SAFETY: the caller must uphold the safety contract for `offset`. unsafe { intrinsics::offset(self, count) } } @@ -936,6 +993,33 @@ impl *const T { where T: Sized, { + #[inline] + const fn runtime_sub_nowrap(this: *const (), count: usize, size: usize) -> bool { + #[inline] + fn runtime(this: *const (), count: usize, size: usize) -> bool { + let Some(byte_offset) = count.checked_mul(size) else { + return false; + }; + byte_offset <= (isize::MAX as usize) && this.addr() >= byte_offset + } + + const fn comptime(_: *const (), _: usize, _: usize) -> bool { + true + } + + intrinsics::const_eval_select((this, count, size), comptime, runtime) + } + + ub_checks::assert_unsafe_precondition!( + check_language_ub, + "ptr::sub requires that the address calculation does not overflow", + ( + this: *const () = self as *const (), + count: usize = count, + size: usize = size_of::(), + ) => runtime_sub_nowrap(this, count, size) + ); + if T::IS_ZST { // Pointer arithmetic does nothing when the pointee is a ZST. self @@ -943,7 +1027,7 @@ impl *const T { // SAFETY: the caller must uphold the safety contract for `offset`. // Because the pointee is *not* a ZST, that means that `count` is // at most `isize::MAX`, and thus the negation cannot overflow. - unsafe { self.offset((count as isize).unchecked_neg()) } + unsafe { intrinsics::offset(self, intrinsics::unchecked_sub(0, count as isize)) } } } diff --git a/library/core/src/ptr/mut_ptr.rs b/library/core/src/ptr/mut_ptr.rs index 287073497f825..8dbce1fdb984e 100644 --- a/library/core/src/ptr/mut_ptr.rs +++ b/library/core/src/ptr/mut_ptr.rs @@ -393,6 +393,37 @@ impl *mut T { where T: Sized, { + #[inline] + const fn runtime_offset_nowrap(this: *const (), count: isize, size: usize) -> bool { + #[inline] + fn runtime(this: *const (), count: isize, size: usize) -> bool { + // `size` is the size of a Rust type, so we know that + // `size <= isize::MAX` and thus `as` cast here is not lossy. + let Some(byte_offset) = count.checked_mul(size as isize) else { + return false; + }; + let (_, overflow) = this.addr().overflowing_add_signed(byte_offset); + !overflow + } + + const fn comptime(_: *const (), _: isize, _: usize) -> bool { + true + } + + // We can use const_eval_select here because this is only for UB checks. + intrinsics::const_eval_select((this, count, size), comptime, runtime) + } + + ub_checks::assert_unsafe_precondition!( + check_language_ub, + "ptr::offset requires the address calculation to not overflow", + ( + this: *const () = self as *const (), + count: isize = count, + size: usize = size_of::(), + ) => runtime_offset_nowrap(this, count, size) + ); + // SAFETY: the caller must uphold the safety contract for `offset`. // The obtained pointer is valid for writes since the caller must // guarantee that it points to the same allocated object as `self`. @@ -940,6 +971,34 @@ impl *mut T { where T: Sized, { + #[inline] + const fn runtime_add_nowrap(this: *const (), count: usize, size: usize) -> bool { + #[inline] + fn runtime(this: *const (), count: usize, size: usize) -> bool { + let Some(byte_offset) = count.checked_mul(size) else { + return false; + }; + let (_, overflow) = this.addr().overflowing_add(byte_offset); + byte_offset <= (isize::MAX as usize) && !overflow + } + + const fn comptime(_: *const (), _: usize, _: usize) -> bool { + true + } + + intrinsics::const_eval_select((this, count, size), comptime, runtime) + } + + ub_checks::assert_unsafe_precondition!( + check_language_ub, + "ptr::add requires that the address calculation does not overflow", + ( + this: *const () = self as *const (), + count: usize = count, + size: usize = size_of::(), + ) => runtime_add_nowrap(this, count, size) + ); + // SAFETY: the caller must uphold the safety contract for `offset`. unsafe { intrinsics::offset(self, count) } } @@ -1018,6 +1077,33 @@ impl *mut T { where T: Sized, { + #[inline] + const fn runtime_sub_nowrap(this: *const (), count: usize, size: usize) -> bool { + #[inline] + fn runtime(this: *const (), count: usize, size: usize) -> bool { + let Some(byte_offset) = count.checked_mul(size) else { + return false; + }; + byte_offset <= (isize::MAX as usize) && this.addr() >= byte_offset + } + + const fn comptime(_: *const (), _: usize, _: usize) -> bool { + true + } + + intrinsics::const_eval_select((this, count, size), comptime, runtime) + } + + ub_checks::assert_unsafe_precondition!( + check_language_ub, + "ptr::sub requires that the address calculation does not overflow", + ( + this: *const () = self as *const (), + count: usize = count, + size: usize = size_of::(), + ) => runtime_sub_nowrap(this, count, size) + ); + if T::IS_ZST { // Pointer arithmetic does nothing when the pointee is a ZST. self @@ -1025,7 +1111,7 @@ impl *mut T { // SAFETY: the caller must uphold the safety contract for `offset`. // Because the pointee is *not* a ZST, that means that `count` is // at most `isize::MAX`, and thus the negation cannot overflow. - unsafe { self.offset((count as isize).unchecked_neg()) } + unsafe { intrinsics::offset(self, intrinsics::unchecked_sub(0, count as isize)) } } } diff --git a/tests/codegen/option-as-slice.rs b/tests/codegen/option-as-slice.rs index cfa479aa4b2f2..0edbbac11762d 100644 --- a/tests/codegen/option-as-slice.rs +++ b/tests/codegen/option-as-slice.rs @@ -14,7 +14,9 @@ pub fn u64_opt_as_slice(o: &Option) -> &[u64] { // CHECK-NOT: br // CHECK-NOT: switch // CHECK-NOT: icmp - // CHECK: %[[LEN:.+]] = load i64,{{.+}} !range ![[META_U64:.+]], !noundef + // CHECK: %[[LEN:.+]] = load i64 + // CHECK-SAME: !range ![[META_U64:[0-9]+]], + // CHECK-SAME: !noundef // CHECK-NOT: select // CHECK-NOT: br // CHECK-NOT: switch @@ -51,7 +53,9 @@ pub fn u8_opt_as_slice(o: &Option) -> &[u8] { // CHECK-NOT: br // CHECK-NOT: switch // CHECK-NOT: icmp - // CHECK: %[[TAG:.+]] = load i8,{{.+}} !range ![[META_U8:.+]], !noundef + // CHECK: %[[TAG:.+]] = load i8 + // CHECK-SAME: !range ![[META_U8:[0-9]+]], + // CHECK-SAME: !noundef // CHECK: %[[LEN:.+]] = zext{{.*}} i8 %[[TAG]] to i64 // CHECK-NOT: select // CHECK-NOT: br diff --git a/tests/mir-opt/pre-codegen/ptr_offset.demo_byte_add_fat.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/ptr_offset.demo_byte_add_fat.PreCodegen.after.panic-abort.mir index 5faa1e210cf4f..c99c6f7de88c6 100644 --- a/tests/mir-opt/pre-codegen/ptr_offset.demo_byte_add_fat.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/ptr_offset.demo_byte_add_fat.PreCodegen.after.panic-abort.mir @@ -10,12 +10,18 @@ fn demo_byte_add_fat(_1: *const [u32], _2: usize) -> *const [u32] { scope 2 (inlined std::ptr::const_ptr::::cast::) { } scope 3 (inlined std::ptr::const_ptr::::add) { + scope 4 (inlined core::ub_checks::check_language_ub) { + scope 5 (inlined core::ub_checks::check_language_ub::runtime) { + } + } + scope 6 (inlined std::mem::size_of::) { + } } - scope 4 (inlined std::ptr::const_ptr::::with_metadata_of::<[u32]>) { + scope 7 (inlined std::ptr::const_ptr::::with_metadata_of::<[u32]>) { let mut _5: usize; - scope 5 (inlined std::ptr::metadata::<[u32]>) { + scope 8 (inlined std::ptr::metadata::<[u32]>) { } - scope 6 (inlined std::ptr::from_raw_parts::<[u32], ()>) { + scope 9 (inlined std::ptr::from_raw_parts::<[u32], ()>) { } } } diff --git a/tests/mir-opt/pre-codegen/ptr_offset.demo_byte_add_fat.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/ptr_offset.demo_byte_add_fat.PreCodegen.after.panic-unwind.mir index 5faa1e210cf4f..c99c6f7de88c6 100644 --- a/tests/mir-opt/pre-codegen/ptr_offset.demo_byte_add_fat.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/ptr_offset.demo_byte_add_fat.PreCodegen.after.panic-unwind.mir @@ -10,12 +10,18 @@ fn demo_byte_add_fat(_1: *const [u32], _2: usize) -> *const [u32] { scope 2 (inlined std::ptr::const_ptr::::cast::) { } scope 3 (inlined std::ptr::const_ptr::::add) { + scope 4 (inlined core::ub_checks::check_language_ub) { + scope 5 (inlined core::ub_checks::check_language_ub::runtime) { + } + } + scope 6 (inlined std::mem::size_of::) { + } } - scope 4 (inlined std::ptr::const_ptr::::with_metadata_of::<[u32]>) { + scope 7 (inlined std::ptr::const_ptr::::with_metadata_of::<[u32]>) { let mut _5: usize; - scope 5 (inlined std::ptr::metadata::<[u32]>) { + scope 8 (inlined std::ptr::metadata::<[u32]>) { } - scope 6 (inlined std::ptr::from_raw_parts::<[u32], ()>) { + scope 9 (inlined std::ptr::from_raw_parts::<[u32], ()>) { } } } diff --git a/tests/mir-opt/pre-codegen/ptr_offset.demo_byte_add_thin.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/ptr_offset.demo_byte_add_thin.PreCodegen.after.panic-abort.mir index 9429785045a29..07665b2adc81a 100644 --- a/tests/mir-opt/pre-codegen/ptr_offset.demo_byte_add_thin.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/ptr_offset.demo_byte_add_thin.PreCodegen.after.panic-abort.mir @@ -10,11 +10,17 @@ fn demo_byte_add_thin(_1: *const u32, _2: usize) -> *const u32 { scope 2 (inlined std::ptr::const_ptr::::cast::) { } scope 3 (inlined std::ptr::const_ptr::::add) { + scope 4 (inlined core::ub_checks::check_language_ub) { + scope 5 (inlined core::ub_checks::check_language_ub::runtime) { + } + } + scope 6 (inlined std::mem::size_of::) { + } } - scope 4 (inlined std::ptr::const_ptr::::with_metadata_of::) { - scope 5 (inlined std::ptr::metadata::) { + scope 7 (inlined std::ptr::const_ptr::::with_metadata_of::) { + scope 8 (inlined std::ptr::metadata::) { } - scope 6 (inlined std::ptr::from_raw_parts::) { + scope 9 (inlined std::ptr::from_raw_parts::) { } } } diff --git a/tests/mir-opt/pre-codegen/ptr_offset.demo_byte_add_thin.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/ptr_offset.demo_byte_add_thin.PreCodegen.after.panic-unwind.mir index 9429785045a29..07665b2adc81a 100644 --- a/tests/mir-opt/pre-codegen/ptr_offset.demo_byte_add_thin.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/ptr_offset.demo_byte_add_thin.PreCodegen.after.panic-unwind.mir @@ -10,11 +10,17 @@ fn demo_byte_add_thin(_1: *const u32, _2: usize) -> *const u32 { scope 2 (inlined std::ptr::const_ptr::::cast::) { } scope 3 (inlined std::ptr::const_ptr::::add) { + scope 4 (inlined core::ub_checks::check_language_ub) { + scope 5 (inlined core::ub_checks::check_language_ub::runtime) { + } + } + scope 6 (inlined std::mem::size_of::) { + } } - scope 4 (inlined std::ptr::const_ptr::::with_metadata_of::) { - scope 5 (inlined std::ptr::metadata::) { + scope 7 (inlined std::ptr::const_ptr::::with_metadata_of::) { + scope 8 (inlined std::ptr::metadata::) { } - scope 6 (inlined std::ptr::from_raw_parts::) { + scope 9 (inlined std::ptr::from_raw_parts::) { } } } diff --git a/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-abort.mir index 3aa483ed1aefa..da3295bf8c979 100644 --- a/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-abort.mir @@ -19,30 +19,30 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { debug i => _22; debug x => _23; } - scope 17 (inlined > as Iterator>::next) { + scope 20 (inlined > as Iterator>::next) { let mut _14: &mut std::slice::Iter<'_, T>; let mut _15: std::option::Option<&T>; let mut _19: (usize, bool); let mut _20: (usize, &T); - scope 18 { + scope 21 { let _18: usize; - scope 23 { + scope 26 { } } - scope 19 { - scope 20 { - scope 26 (inlined as FromResidual>>::from_residual) { + scope 22 { + scope 23 { + scope 29 (inlined as FromResidual>>::from_residual) { } } } - scope 21 { - scope 22 { + scope 24 { + scope 25 { } } - scope 24 (inlined as Try>::branch) { + scope 27 (inlined as Try>::branch) { let mut _16: isize; let _17: &T; - scope 25 { + scope 28 { } } } @@ -64,6 +64,12 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { scope 12 (inlined NonNull::::as_ptr) { } scope 13 (inlined std::ptr::mut_ptr::::add) { + scope 14 (inlined core::ub_checks::check_language_ub) { + scope 15 (inlined core::ub_checks::check_language_ub::runtime) { + } + } + scope 16 (inlined std::mem::size_of::) { + } } } scope 8 (inlined as From<&[T]>>::from) { @@ -77,11 +83,11 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { } } } - scope 14 (inlined as Iterator>::enumerate) { - scope 15 (inlined Enumerate::>::new) { + scope 17 (inlined as Iterator>::enumerate) { + scope 18 (inlined Enumerate::>::new) { } } - scope 16 (inlined > as IntoIterator>::into_iter) { + scope 19 (inlined > as IntoIterator>::into_iter) { } bb0: { diff --git a/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-unwind.mir index 4cc0aa0ed788d..46c868ba8a16d 100644 --- a/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-unwind.mir @@ -39,6 +39,12 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { scope 12 (inlined NonNull::::as_ptr) { } scope 13 (inlined std::ptr::mut_ptr::::add) { + scope 14 (inlined core::ub_checks::check_language_ub) { + scope 15 (inlined core::ub_checks::check_language_ub::runtime) { + } + } + scope 16 (inlined std::mem::size_of::) { + } } } scope 8 (inlined as From<&[T]>>::from) { @@ -52,11 +58,11 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { } } } - scope 14 (inlined as Iterator>::enumerate) { - scope 15 (inlined Enumerate::>::new) { + scope 17 (inlined as Iterator>::enumerate) { + scope 18 (inlined Enumerate::>::new) { } } - scope 16 (inlined > as IntoIterator>::into_iter) { + scope 19 (inlined > as IntoIterator>::into_iter) { } bb0: { diff --git a/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-abort.mir index 507afa63c6884..cedda097c3890 100644 --- a/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-abort.mir @@ -36,6 +36,12 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () { scope 12 (inlined NonNull::::as_ptr) { } scope 13 (inlined std::ptr::mut_ptr::::add) { + scope 14 (inlined core::ub_checks::check_language_ub) { + scope 15 (inlined core::ub_checks::check_language_ub::runtime) { + } + } + scope 16 (inlined std::mem::size_of::) { + } } } scope 8 (inlined as From<&[T]>>::from) { @@ -49,7 +55,7 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () { } } } - scope 14 (inlined as IntoIterator>::into_iter) { + scope 17 (inlined as IntoIterator>::into_iter) { } bb0: { diff --git a/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-unwind.mir index a25f12edc28e9..e299760d9825a 100644 --- a/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-unwind.mir @@ -36,6 +36,12 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () { scope 12 (inlined NonNull::::as_ptr) { } scope 13 (inlined std::ptr::mut_ptr::::add) { + scope 14 (inlined core::ub_checks::check_language_ub) { + scope 15 (inlined core::ub_checks::check_language_ub::runtime) { + } + } + scope 16 (inlined std::mem::size_of::) { + } } } scope 8 (inlined as From<&[T]>>::from) { @@ -49,7 +55,7 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () { } } } - scope 14 (inlined as IntoIterator>::into_iter) { + scope 17 (inlined as IntoIterator>::into_iter) { } bb0: { diff --git a/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-abort.mir index 1b397a4e4cdde..d01bd4a9a4a5f 100644 --- a/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-abort.mir @@ -18,7 +18,7 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () { scope 2 { debug x => _17; } - scope 17 (inlined > as Iterator>::next) { + scope 20 (inlined > as Iterator>::next) { let mut _14: &mut std::slice::Iter<'_, T>; } } @@ -39,6 +39,12 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () { scope 12 (inlined NonNull::::as_ptr) { } scope 13 (inlined std::ptr::mut_ptr::::add) { + scope 14 (inlined core::ub_checks::check_language_ub) { + scope 15 (inlined core::ub_checks::check_language_ub::runtime) { + } + } + scope 16 (inlined std::mem::size_of::) { + } } } scope 8 (inlined as From<&[T]>>::from) { @@ -52,11 +58,11 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () { } } } - scope 14 (inlined as Iterator>::rev) { - scope 15 (inlined Rev::>::new) { + scope 17 (inlined as Iterator>::rev) { + scope 18 (inlined Rev::>::new) { } } - scope 16 (inlined > as IntoIterator>::into_iter) { + scope 19 (inlined > as IntoIterator>::into_iter) { } bb0: { diff --git a/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-unwind.mir index 77689dd9b513e..d2d0492add466 100644 --- a/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-unwind.mir @@ -18,7 +18,7 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () { scope 2 { debug x => _17; } - scope 17 (inlined > as Iterator>::next) { + scope 20 (inlined > as Iterator>::next) { let mut _14: &mut std::slice::Iter<'_, T>; } } @@ -39,6 +39,12 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () { scope 12 (inlined NonNull::::as_ptr) { } scope 13 (inlined std::ptr::mut_ptr::::add) { + scope 14 (inlined core::ub_checks::check_language_ub) { + scope 15 (inlined core::ub_checks::check_language_ub::runtime) { + } + } + scope 16 (inlined std::mem::size_of::) { + } } } scope 8 (inlined as From<&[T]>>::from) { @@ -52,11 +58,11 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () { } } } - scope 14 (inlined as Iterator>::rev) { - scope 15 (inlined Rev::>::new) { + scope 17 (inlined as Iterator>::rev) { + scope 18 (inlined Rev::>::new) { } } - scope 16 (inlined > as IntoIterator>::into_iter) { + scope 19 (inlined > as IntoIterator>::into_iter) { } bb0: { From 9d5c961fa40cde6a9b70dfde3c1fe59de848d723 Mon Sep 17 00:00:00 2001 From: Ben Kimock Date: Sun, 6 Oct 2024 23:36:22 -0400 Subject: [PATCH 1978/2194] cfg out checks in add and sub but not offset ...because the checks in offset found bugs in a crater run. --- library/core/src/ptr/const_ptr.rs | 4 ++++ library/core/src/ptr/mut_ptr.rs | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/library/core/src/ptr/const_ptr.rs b/library/core/src/ptr/const_ptr.rs index 4727dc77d18d4..c9af7f13e46c4 100644 --- a/library/core/src/ptr/const_ptr.rs +++ b/library/core/src/ptr/const_ptr.rs @@ -887,6 +887,7 @@ impl *const T { where T: Sized, { + #[cfg(debug_assertions)] #[inline] const fn runtime_add_nowrap(this: *const (), count: usize, size: usize) -> bool { #[inline] @@ -905,6 +906,7 @@ impl *const T { intrinsics::const_eval_select((this, count, size), comptime, runtime) } + #[cfg(debug_assertions)] // Expensive, and doesn't catch much in the wild. ub_checks::assert_unsafe_precondition!( check_language_ub, "ptr::add requires that the address calculation does not overflow", @@ -993,6 +995,7 @@ impl *const T { where T: Sized, { + #[cfg(debug_assertions)] #[inline] const fn runtime_sub_nowrap(this: *const (), count: usize, size: usize) -> bool { #[inline] @@ -1010,6 +1013,7 @@ impl *const T { intrinsics::const_eval_select((this, count, size), comptime, runtime) } + #[cfg(debug_assertions)] // Expensive, and doesn't catch much in the wild. ub_checks::assert_unsafe_precondition!( check_language_ub, "ptr::sub requires that the address calculation does not overflow", diff --git a/library/core/src/ptr/mut_ptr.rs b/library/core/src/ptr/mut_ptr.rs index 8dbce1fdb984e..e458bb4642fc6 100644 --- a/library/core/src/ptr/mut_ptr.rs +++ b/library/core/src/ptr/mut_ptr.rs @@ -971,6 +971,7 @@ impl *mut T { where T: Sized, { + #[cfg(debug_assertions)] #[inline] const fn runtime_add_nowrap(this: *const (), count: usize, size: usize) -> bool { #[inline] @@ -989,6 +990,7 @@ impl *mut T { intrinsics::const_eval_select((this, count, size), comptime, runtime) } + #[cfg(debug_assertions)] // Expensive, and doesn't catch much in the wild. ub_checks::assert_unsafe_precondition!( check_language_ub, "ptr::add requires that the address calculation does not overflow", @@ -1077,6 +1079,7 @@ impl *mut T { where T: Sized, { + #[cfg(debug_assertions)] #[inline] const fn runtime_sub_nowrap(this: *const (), count: usize, size: usize) -> bool { #[inline] @@ -1094,6 +1097,7 @@ impl *mut T { intrinsics::const_eval_select((this, count, size), comptime, runtime) } + #[cfg(debug_assertions)] // Expensive, and doesn't catch much in the wild. ub_checks::assert_unsafe_precondition!( check_language_ub, "ptr::sub requires that the address calculation does not overflow", From 128ccc3c26a80be2768abbdd020404fb439b905e Mon Sep 17 00:00:00 2001 From: Ben Kimock Date: Mon, 7 Oct 2024 11:18:37 -0400 Subject: [PATCH 1979/2194] Bless mir-opt tests --- ...e_add_fat.PreCodegen.after.panic-abort.mir | 12 ++----- ..._add_fat.PreCodegen.after.panic-unwind.mir | 12 ++----- ..._add_thin.PreCodegen.after.panic-abort.mir | 12 ++----- ...add_thin.PreCodegen.after.panic-unwind.mir | 12 ++----- ...ated_loop.PreCodegen.after.panic-abort.mir | 32 ++++++++----------- ...ted_loop.PreCodegen.after.panic-unwind.mir | 12 ++----- ...ward_loop.PreCodegen.after.panic-abort.mir | 8 +---- ...ard_loop.PreCodegen.after.panic-unwind.mir | 8 +---- ...erse_loop.PreCodegen.after.panic-abort.mir | 14 +++----- ...rse_loop.PreCodegen.after.panic-unwind.mir | 14 +++----- 10 files changed, 38 insertions(+), 98 deletions(-) diff --git a/tests/mir-opt/pre-codegen/ptr_offset.demo_byte_add_fat.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/ptr_offset.demo_byte_add_fat.PreCodegen.after.panic-abort.mir index c99c6f7de88c6..5faa1e210cf4f 100644 --- a/tests/mir-opt/pre-codegen/ptr_offset.demo_byte_add_fat.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/ptr_offset.demo_byte_add_fat.PreCodegen.after.panic-abort.mir @@ -10,18 +10,12 @@ fn demo_byte_add_fat(_1: *const [u32], _2: usize) -> *const [u32] { scope 2 (inlined std::ptr::const_ptr::::cast::) { } scope 3 (inlined std::ptr::const_ptr::::add) { - scope 4 (inlined core::ub_checks::check_language_ub) { - scope 5 (inlined core::ub_checks::check_language_ub::runtime) { - } - } - scope 6 (inlined std::mem::size_of::) { - } } - scope 7 (inlined std::ptr::const_ptr::::with_metadata_of::<[u32]>) { + scope 4 (inlined std::ptr::const_ptr::::with_metadata_of::<[u32]>) { let mut _5: usize; - scope 8 (inlined std::ptr::metadata::<[u32]>) { + scope 5 (inlined std::ptr::metadata::<[u32]>) { } - scope 9 (inlined std::ptr::from_raw_parts::<[u32], ()>) { + scope 6 (inlined std::ptr::from_raw_parts::<[u32], ()>) { } } } diff --git a/tests/mir-opt/pre-codegen/ptr_offset.demo_byte_add_fat.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/ptr_offset.demo_byte_add_fat.PreCodegen.after.panic-unwind.mir index c99c6f7de88c6..5faa1e210cf4f 100644 --- a/tests/mir-opt/pre-codegen/ptr_offset.demo_byte_add_fat.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/ptr_offset.demo_byte_add_fat.PreCodegen.after.panic-unwind.mir @@ -10,18 +10,12 @@ fn demo_byte_add_fat(_1: *const [u32], _2: usize) -> *const [u32] { scope 2 (inlined std::ptr::const_ptr::::cast::) { } scope 3 (inlined std::ptr::const_ptr::::add) { - scope 4 (inlined core::ub_checks::check_language_ub) { - scope 5 (inlined core::ub_checks::check_language_ub::runtime) { - } - } - scope 6 (inlined std::mem::size_of::) { - } } - scope 7 (inlined std::ptr::const_ptr::::with_metadata_of::<[u32]>) { + scope 4 (inlined std::ptr::const_ptr::::with_metadata_of::<[u32]>) { let mut _5: usize; - scope 8 (inlined std::ptr::metadata::<[u32]>) { + scope 5 (inlined std::ptr::metadata::<[u32]>) { } - scope 9 (inlined std::ptr::from_raw_parts::<[u32], ()>) { + scope 6 (inlined std::ptr::from_raw_parts::<[u32], ()>) { } } } diff --git a/tests/mir-opt/pre-codegen/ptr_offset.demo_byte_add_thin.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/ptr_offset.demo_byte_add_thin.PreCodegen.after.panic-abort.mir index 07665b2adc81a..9429785045a29 100644 --- a/tests/mir-opt/pre-codegen/ptr_offset.demo_byte_add_thin.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/ptr_offset.demo_byte_add_thin.PreCodegen.after.panic-abort.mir @@ -10,17 +10,11 @@ fn demo_byte_add_thin(_1: *const u32, _2: usize) -> *const u32 { scope 2 (inlined std::ptr::const_ptr::::cast::) { } scope 3 (inlined std::ptr::const_ptr::::add) { - scope 4 (inlined core::ub_checks::check_language_ub) { - scope 5 (inlined core::ub_checks::check_language_ub::runtime) { - } - } - scope 6 (inlined std::mem::size_of::) { - } } - scope 7 (inlined std::ptr::const_ptr::::with_metadata_of::) { - scope 8 (inlined std::ptr::metadata::) { + scope 4 (inlined std::ptr::const_ptr::::with_metadata_of::) { + scope 5 (inlined std::ptr::metadata::) { } - scope 9 (inlined std::ptr::from_raw_parts::) { + scope 6 (inlined std::ptr::from_raw_parts::) { } } } diff --git a/tests/mir-opt/pre-codegen/ptr_offset.demo_byte_add_thin.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/ptr_offset.demo_byte_add_thin.PreCodegen.after.panic-unwind.mir index 07665b2adc81a..9429785045a29 100644 --- a/tests/mir-opt/pre-codegen/ptr_offset.demo_byte_add_thin.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/ptr_offset.demo_byte_add_thin.PreCodegen.after.panic-unwind.mir @@ -10,17 +10,11 @@ fn demo_byte_add_thin(_1: *const u32, _2: usize) -> *const u32 { scope 2 (inlined std::ptr::const_ptr::::cast::) { } scope 3 (inlined std::ptr::const_ptr::::add) { - scope 4 (inlined core::ub_checks::check_language_ub) { - scope 5 (inlined core::ub_checks::check_language_ub::runtime) { - } - } - scope 6 (inlined std::mem::size_of::) { - } } - scope 7 (inlined std::ptr::const_ptr::::with_metadata_of::) { - scope 8 (inlined std::ptr::metadata::) { + scope 4 (inlined std::ptr::const_ptr::::with_metadata_of::) { + scope 5 (inlined std::ptr::metadata::) { } - scope 9 (inlined std::ptr::from_raw_parts::) { + scope 6 (inlined std::ptr::from_raw_parts::) { } } } diff --git a/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-abort.mir index da3295bf8c979..3aa483ed1aefa 100644 --- a/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-abort.mir @@ -19,30 +19,30 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { debug i => _22; debug x => _23; } - scope 20 (inlined > as Iterator>::next) { + scope 17 (inlined > as Iterator>::next) { let mut _14: &mut std::slice::Iter<'_, T>; let mut _15: std::option::Option<&T>; let mut _19: (usize, bool); let mut _20: (usize, &T); - scope 21 { + scope 18 { let _18: usize; - scope 26 { + scope 23 { } } - scope 22 { - scope 23 { - scope 29 (inlined as FromResidual>>::from_residual) { + scope 19 { + scope 20 { + scope 26 (inlined as FromResidual>>::from_residual) { } } } - scope 24 { - scope 25 { + scope 21 { + scope 22 { } } - scope 27 (inlined as Try>::branch) { + scope 24 (inlined as Try>::branch) { let mut _16: isize; let _17: &T; - scope 28 { + scope 25 { } } } @@ -64,12 +64,6 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { scope 12 (inlined NonNull::::as_ptr) { } scope 13 (inlined std::ptr::mut_ptr::::add) { - scope 14 (inlined core::ub_checks::check_language_ub) { - scope 15 (inlined core::ub_checks::check_language_ub::runtime) { - } - } - scope 16 (inlined std::mem::size_of::) { - } } } scope 8 (inlined as From<&[T]>>::from) { @@ -83,11 +77,11 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { } } } - scope 17 (inlined as Iterator>::enumerate) { - scope 18 (inlined Enumerate::>::new) { + scope 14 (inlined as Iterator>::enumerate) { + scope 15 (inlined Enumerate::>::new) { } } - scope 19 (inlined > as IntoIterator>::into_iter) { + scope 16 (inlined > as IntoIterator>::into_iter) { } bb0: { diff --git a/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-unwind.mir index 46c868ba8a16d..4cc0aa0ed788d 100644 --- a/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-unwind.mir @@ -39,12 +39,6 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { scope 12 (inlined NonNull::::as_ptr) { } scope 13 (inlined std::ptr::mut_ptr::::add) { - scope 14 (inlined core::ub_checks::check_language_ub) { - scope 15 (inlined core::ub_checks::check_language_ub::runtime) { - } - } - scope 16 (inlined std::mem::size_of::) { - } } } scope 8 (inlined as From<&[T]>>::from) { @@ -58,11 +52,11 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { } } } - scope 17 (inlined as Iterator>::enumerate) { - scope 18 (inlined Enumerate::>::new) { + scope 14 (inlined as Iterator>::enumerate) { + scope 15 (inlined Enumerate::>::new) { } } - scope 19 (inlined > as IntoIterator>::into_iter) { + scope 16 (inlined > as IntoIterator>::into_iter) { } bb0: { diff --git a/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-abort.mir index cedda097c3890..507afa63c6884 100644 --- a/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-abort.mir @@ -36,12 +36,6 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () { scope 12 (inlined NonNull::::as_ptr) { } scope 13 (inlined std::ptr::mut_ptr::::add) { - scope 14 (inlined core::ub_checks::check_language_ub) { - scope 15 (inlined core::ub_checks::check_language_ub::runtime) { - } - } - scope 16 (inlined std::mem::size_of::) { - } } } scope 8 (inlined as From<&[T]>>::from) { @@ -55,7 +49,7 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () { } } } - scope 17 (inlined as IntoIterator>::into_iter) { + scope 14 (inlined as IntoIterator>::into_iter) { } bb0: { diff --git a/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-unwind.mir index e299760d9825a..a25f12edc28e9 100644 --- a/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-unwind.mir @@ -36,12 +36,6 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () { scope 12 (inlined NonNull::::as_ptr) { } scope 13 (inlined std::ptr::mut_ptr::::add) { - scope 14 (inlined core::ub_checks::check_language_ub) { - scope 15 (inlined core::ub_checks::check_language_ub::runtime) { - } - } - scope 16 (inlined std::mem::size_of::) { - } } } scope 8 (inlined as From<&[T]>>::from) { @@ -55,7 +49,7 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () { } } } - scope 17 (inlined as IntoIterator>::into_iter) { + scope 14 (inlined as IntoIterator>::into_iter) { } bb0: { diff --git a/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-abort.mir index d01bd4a9a4a5f..1b397a4e4cdde 100644 --- a/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-abort.mir @@ -18,7 +18,7 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () { scope 2 { debug x => _17; } - scope 20 (inlined > as Iterator>::next) { + scope 17 (inlined > as Iterator>::next) { let mut _14: &mut std::slice::Iter<'_, T>; } } @@ -39,12 +39,6 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () { scope 12 (inlined NonNull::::as_ptr) { } scope 13 (inlined std::ptr::mut_ptr::::add) { - scope 14 (inlined core::ub_checks::check_language_ub) { - scope 15 (inlined core::ub_checks::check_language_ub::runtime) { - } - } - scope 16 (inlined std::mem::size_of::) { - } } } scope 8 (inlined as From<&[T]>>::from) { @@ -58,11 +52,11 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () { } } } - scope 17 (inlined as Iterator>::rev) { - scope 18 (inlined Rev::>::new) { + scope 14 (inlined as Iterator>::rev) { + scope 15 (inlined Rev::>::new) { } } - scope 19 (inlined > as IntoIterator>::into_iter) { + scope 16 (inlined > as IntoIterator>::into_iter) { } bb0: { diff --git a/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-unwind.mir index d2d0492add466..77689dd9b513e 100644 --- a/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-unwind.mir @@ -18,7 +18,7 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () { scope 2 { debug x => _17; } - scope 20 (inlined > as Iterator>::next) { + scope 17 (inlined > as Iterator>::next) { let mut _14: &mut std::slice::Iter<'_, T>; } } @@ -39,12 +39,6 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () { scope 12 (inlined NonNull::::as_ptr) { } scope 13 (inlined std::ptr::mut_ptr::::add) { - scope 14 (inlined core::ub_checks::check_language_ub) { - scope 15 (inlined core::ub_checks::check_language_ub::runtime) { - } - } - scope 16 (inlined std::mem::size_of::) { - } } } scope 8 (inlined as From<&[T]>>::from) { @@ -58,11 +52,11 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () { } } } - scope 17 (inlined as Iterator>::rev) { - scope 18 (inlined Rev::>::new) { + scope 14 (inlined as Iterator>::rev) { + scope 15 (inlined Rev::>::new) { } } - scope 19 (inlined > as IntoIterator>::into_iter) { + scope 16 (inlined > as IntoIterator>::into_iter) { } bb0: { From 65cff8a1ef706bca25d30e1f49e02af846b4a61f Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Mon, 7 Oct 2024 12:17:50 -0400 Subject: [PATCH 1980/2194] Mark Boxy as on vacation --- triagebot.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/triagebot.toml b/triagebot.toml index 737be4cc45760..0172a80b3a5a0 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -921,6 +921,7 @@ cc = ["@kobzol"] warn_non_default_branch = true contributing_url = "https://rustc-dev-guide.rust-lang.org/getting-started.html" users_on_vacation = [ + "BoxyUwU", "fmease", "jhpratt", "jyn514", From 8d562f6cc57b40e3c184f0eb72cb5de845d2e046 Mon Sep 17 00:00:00 2001 From: Ben Kimock Date: Mon, 7 Oct 2024 12:23:27 -0400 Subject: [PATCH 1981/2194] Disable slice_iter mir-opt test in debug builds --- tests/mir-opt/pre-codegen/slice_iter.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/mir-opt/pre-codegen/slice_iter.rs b/tests/mir-opt/pre-codegen/slice_iter.rs index 3f89ab0e6f330..fee4214982d59 100644 --- a/tests/mir-opt/pre-codegen/slice_iter.rs +++ b/tests/mir-opt/pre-codegen/slice_iter.rs @@ -1,6 +1,7 @@ // skip-filecheck //@ compile-flags: -O -C debuginfo=0 -Zmir-opt-level=2 //@ only-64bit (constants for `None::<&T>` show in the output) +//@ ignore-debug: precondition checks on ptr::add are under cfg(debug_assertions) // EMIT_MIR_FOR_EACH_PANIC_STRATEGY #![crate_type = "lib"] From ad7d41ce90a78dea19b6dffe8aad22ce7b9be32f Mon Sep 17 00:00:00 2001 From: clubby789 Date: Mon, 7 Oct 2024 10:28:16 +0000 Subject: [PATCH 1982/2194] Test for issue 23600 --- src/tools/tidy/src/issues.txt | 1 - .../{issue-77062-large-zst-array.rs => large-zst-array-77062.rs} | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) rename tests/ui/consts/{issue-77062-large-zst-array.rs => large-zst-array-77062.rs} (53%) diff --git a/src/tools/tidy/src/issues.txt b/src/tools/tidy/src/issues.txt index 86cae849b9782..8dc1ee38ffd18 100644 --- a/src/tools/tidy/src/issues.txt +++ b/src/tools/tidy/src/issues.txt @@ -802,7 +802,6 @@ ui/consts/issue-70942-trait-vs-impl-mismatch.rs ui/consts/issue-73976-monomorphic.rs ui/consts/issue-73976-polymorphic.rs ui/consts/issue-76064.rs -ui/consts/issue-77062-large-zst-array.rs ui/consts/issue-78655.rs ui/consts/issue-79137-monomorphic.rs ui/consts/issue-79137-toogeneric.rs diff --git a/tests/ui/consts/issue-77062-large-zst-array.rs b/tests/ui/consts/large-zst-array-77062.rs similarity index 53% rename from tests/ui/consts/issue-77062-large-zst-array.rs rename to tests/ui/consts/large-zst-array-77062.rs index ef5178fba9515..089353d0885da 100644 --- a/tests/ui/consts/issue-77062-large-zst-array.rs +++ b/tests/ui/consts/large-zst-array-77062.rs @@ -1,4 +1,5 @@ //@ build-pass +pub static FOO: [(); usize::MAX] = [(); usize::MAX]; fn main() { let _ = &[(); usize::MAX]; From b577b26249826cdd8a2aa1bdafbe7d5a58ec98fd Mon Sep 17 00:00:00 2001 From: clubby789 Date: Mon, 7 Oct 2024 11:30:18 +0000 Subject: [PATCH 1983/2194] Add stdio configuring to run-make Rustc --- src/tools/run-make-support/src/macros.rs | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/src/tools/run-make-support/src/macros.rs b/src/tools/run-make-support/src/macros.rs index f7fe4f5422399..be71470321c82 100644 --- a/src/tools/run-make-support/src/macros.rs +++ b/src/tools/run-make-support/src/macros.rs @@ -70,6 +70,30 @@ macro_rules! impl_common_helpers { self } + /// Configuration for the child process’s standard input (stdin) handle. + /// + /// See [`std::process::Command::stdin`]. + pub fn stdin>(&mut self, cfg: T) -> &mut Self { + self.cmd.stdin(cfg); + self + } + + /// Configuration for the child process’s standard output (stdout) handle. + /// + /// See [`std::process::Command::stdout`]. + pub fn stdout>(&mut self, cfg: T) -> &mut Self { + self.cmd.stdout(cfg); + self + } + + /// Configuration for the child process’s standard error (stderr) handle. + /// + /// See [`std::process::Command::stderr`]. + pub fn stderr>(&mut self, cfg: T) -> &mut Self { + self.cmd.stderr(cfg); + self + } + /// Inspect what the underlying [`Command`] is up to the /// current construction. pub fn inspect(&mut self, inspector: I) -> &mut Self From 3afb7d687c17518684f3aa4a42909e2b1d9887be Mon Sep 17 00:00:00 2001 From: clubby789 Date: Mon, 7 Oct 2024 11:30:51 +0000 Subject: [PATCH 1984/2194] Migrate `emit-to-stdout` to new run-make Co-authored-by: Oneirical Co-authored-by: Chris Denton --- src/tools/run-make-support/src/macros.rs | 6 +- .../tidy/src/allowed_run_make_makefiles.txt | 1 - tests/run-make/emit-to-stdout/Makefile | 51 ------------- tests/run-make/emit-to-stdout/rmake.rs | 73 +++++++++++++++++++ 4 files changed, 76 insertions(+), 55 deletions(-) delete mode 100644 tests/run-make/emit-to-stdout/Makefile create mode 100644 tests/run-make/emit-to-stdout/rmake.rs diff --git a/src/tools/run-make-support/src/macros.rs b/src/tools/run-make-support/src/macros.rs index be71470321c82..cc3d1281d0ab2 100644 --- a/src/tools/run-make-support/src/macros.rs +++ b/src/tools/run-make-support/src/macros.rs @@ -73,7 +73,7 @@ macro_rules! impl_common_helpers { /// Configuration for the child process’s standard input (stdin) handle. /// /// See [`std::process::Command::stdin`]. - pub fn stdin>(&mut self, cfg: T) -> &mut Self { + pub fn stdin>(&mut self, cfg: T) -> &mut Self { self.cmd.stdin(cfg); self } @@ -81,7 +81,7 @@ macro_rules! impl_common_helpers { /// Configuration for the child process’s standard output (stdout) handle. /// /// See [`std::process::Command::stdout`]. - pub fn stdout>(&mut self, cfg: T) -> &mut Self { + pub fn stdout>(&mut self, cfg: T) -> &mut Self { self.cmd.stdout(cfg); self } @@ -89,7 +89,7 @@ macro_rules! impl_common_helpers { /// Configuration for the child process’s standard error (stderr) handle. /// /// See [`std::process::Command::stderr`]. - pub fn stderr>(&mut self, cfg: T) -> &mut Self { + pub fn stderr>(&mut self, cfg: T) -> &mut Self { self.cmd.stderr(cfg); self } diff --git a/src/tools/tidy/src/allowed_run_make_makefiles.txt b/src/tools/tidy/src/allowed_run_make_makefiles.txt index 50d21c7ed4c99..7a0f98d59f00d 100644 --- a/src/tools/tidy/src/allowed_run_make_makefiles.txt +++ b/src/tools/tidy/src/allowed_run_make_makefiles.txt @@ -1,6 +1,5 @@ run-make/branch-protection-check-IBT/Makefile run-make/cat-and-grep-sanity-check/Makefile -run-make/emit-to-stdout/Makefile run-make/extern-fn-reachable/Makefile run-make/incr-add-rust-src-component/Makefile run-make/issue-84395-lto-embed-bitcode/Makefile diff --git a/tests/run-make/emit-to-stdout/Makefile b/tests/run-make/emit-to-stdout/Makefile deleted file mode 100644 index 80e9b6a4ded67..0000000000000 --- a/tests/run-make/emit-to-stdout/Makefile +++ /dev/null @@ -1,51 +0,0 @@ -include ../tools.mk - -SRC=test.rs -OUT=$(TMPDIR)/out - -all: asm llvm-ir dep-info mir llvm-bc obj metadata link multiple-types multiple-types-option-o - -asm: $(OUT) - $(RUSTC) --emit asm=$(OUT)/$@ $(SRC) - $(RUSTC) --emit asm=- $(SRC) | diff - $(OUT)/$@ -llvm-ir: $(OUT) - $(RUSTC) --emit llvm-ir=$(OUT)/$@ $(SRC) - $(RUSTC) --emit llvm-ir=- $(SRC) | diff - $(OUT)/$@ -dep-info: $(OUT) - $(RUSTC) -Z dep-info-omit-d-target=yes --emit dep-info=$(OUT)/$@ $(SRC) - $(RUSTC) --emit dep-info=- $(SRC) | diff - $(OUT)/$@ -mir: $(OUT) - $(RUSTC) --emit mir=$(OUT)/$@ $(SRC) - $(RUSTC) --emit mir=- $(SRC) | diff - $(OUT)/$@ - -llvm-bc: $(OUT) - $(RUSTC) --emit llvm-bc=- $(SRC) 1>/dev/ptmx 2>$(OUT)/$@ || true - diff $(OUT)/$@ emit-llvm-bc.stderr -obj: $(OUT) - $(RUSTC) --emit obj=- $(SRC) 1>/dev/ptmx 2>$(OUT)/$@ || true - diff $(OUT)/$@ emit-obj.stderr - -# For metadata output, a temporary directory will be created to hold the temporary -# metadata file. But when output is stdout, the temporary directory will be located -# in the same place as $(SRC), which is mounted as read-only in the tests. Thus as -# a workaround, $(SRC) is copied to the test output directory $(OUT) and we compile -# it there. -metadata: $(OUT) - cp $(SRC) $(OUT) - (cd $(OUT); $(RUSTC) --emit metadata=- $(SRC) 1>/dev/ptmx 2>$(OUT)/$@ || true) - diff $(OUT)/$@ emit-metadata.stderr - -link: $(OUT) - $(RUSTC) --emit link=- $(SRC) 1>/dev/ptmx 2>$(OUT)/$@ || true - diff $(OUT)/$@ emit-link.stderr - -multiple-types: $(OUT) - $(RUSTC) --emit asm=- --emit llvm-ir=- --emit dep-info=- --emit mir=- $(SRC) 2>$(OUT)/$@ || true - diff $(OUT)/$@ emit-multiple-types.stderr - -multiple-types-option-o: $(OUT) - $(RUSTC) -o - --emit asm,llvm-ir,dep-info,mir $(SRC) 2>$(OUT)/$@ || true - diff $(OUT)/$@ emit-multiple-types.stderr - -$(OUT): - mkdir -p $(OUT) diff --git a/tests/run-make/emit-to-stdout/rmake.rs b/tests/run-make/emit-to-stdout/rmake.rs new file mode 100644 index 0000000000000..a9a3796731b4b --- /dev/null +++ b/tests/run-make/emit-to-stdout/rmake.rs @@ -0,0 +1,73 @@ +//! If `-o -` or `--emit KIND=-` is provided, output should be written to stdout +//! instead. Binary output (`obj`, `llvm-bc`, `link` and `metadata`) +//! being written this way will result in an error if stdout is a tty. +//! Multiple output types going to stdout will trigger an error too, +//! as they would all be mixed together. +//! +//! See . + +use std::fs::File; + +use run_make_support::{diff, run_in_tmpdir, rustc}; + +// Test emitting text outputs to stdout works correctly +fn run_diff(name: &str, file_args: &[&str]) { + rustc().emit(format!("{name}={name}")).input("test.rs").args(file_args).run(); + let out = rustc().emit(format!("{name}=-")).input("test.rs").run().stdout_utf8(); + diff().expected_file(name).actual_text("stdout", &out).run(); +} + +// Test that emitting binary formats to a terminal gives the correct error +fn run_terminal_err_diff(name: &str) { + #[cfg(not(windows))] + let terminal = File::create("/dev/ptmx").unwrap(); + // FIXME: If this test fails and the compiler does print to the console, + // then this will produce a lot of output. + // We should spawn a new console instead to print stdout. + #[cfg(windows)] + let terminal = File::options().read(true).write(true).open(r"\\.\CONOUT$").unwrap(); + + let err = File::create(name).unwrap(); + rustc().emit(format!("{name}=-")).input("test.rs").stdout(terminal).stderr(err).run_fail(); + diff().expected_file(format!("emit-{name}.stderr")).actual_file(name).run(); +} + +fn main() { + run_in_tmpdir(|| { + run_diff("asm", &[]); + run_diff("llvm-ir", &[]); + run_diff("dep-info", &["-Zdep-info-omit-d-target=yes"]); + run_diff("mir", &[]); + + run_terminal_err_diff("llvm-bc"); + run_terminal_err_diff("obj"); + run_terminal_err_diff("metadata"); + run_terminal_err_diff("link"); + + // Test error for emitting multiple types to stdout + rustc() + .input("test.rs") + .emit("asm=-") + .emit("llvm-ir=-") + .emit("dep-info=-") + .emit("mir=-") + .stderr(File::create("multiple-types").unwrap()) + .run_fail(); + diff().expected_file("emit-multiple-types.stderr").actual_file("multiple-types").run(); + + // Same as above, but using `-o` + rustc() + .input("test.rs") + .output("-") + .emit("asm,llvm-ir,dep-info,mir") + .stderr(File::create("multiple-types-option-o").unwrap()) + .run_fail(); + diff() + .expected_file("emit-multiple-types.stderr") + .actual_file("multiple-types-option-o") + .run(); + + // Test that `-o -` redirected to a file works correctly (#26719) + rustc().input("test.rs").output("-").stdout(File::create("out-stdout").unwrap()).run(); + }); +} From b27c22d6b0a230fc122d541356580f0fb2be2366 Mon Sep 17 00:00:00 2001 From: clubby789 Date: Mon, 7 Oct 2024 11:32:53 +0000 Subject: [PATCH 1985/2194] Add test for issue 28994 --- .../fn-pointer/hrtb-assoc-fn-traits-28994.rs | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 tests/ui/traits/fn-pointer/hrtb-assoc-fn-traits-28994.rs diff --git a/tests/ui/traits/fn-pointer/hrtb-assoc-fn-traits-28994.rs b/tests/ui/traits/fn-pointer/hrtb-assoc-fn-traits-28994.rs new file mode 100644 index 0000000000000..e2f02053f959f --- /dev/null +++ b/tests/ui/traits/fn-pointer/hrtb-assoc-fn-traits-28994.rs @@ -0,0 +1,22 @@ +//@ check-pass +//! Tests that a HRTB + FnOnce bound involving an associated type don't prevent +//! a function pointer from implementing `Fn` traits. +//! Test for + +trait LifetimeToType<'a> { + type Out; +} + +impl<'a> LifetimeToType<'a> for () { + type Out = &'a (); +} + +fn id<'a>(val: &'a ()) -> <() as LifetimeToType<'a>>::Out { + val +} + +fn assert_fn FnOnce(&'a ()) -> <() as LifetimeToType<'a>>::Out>(_func: F) { } + +fn main() { + assert_fn(id); +} From fa4f18be5553bd23856abf717ad86acf0412a2ef Mon Sep 17 00:00:00 2001 From: clubby789 Date: Mon, 7 Oct 2024 11:36:47 +0000 Subject: [PATCH 1986/2194] Add test for issue 30472 --- .../assoc-type-hrtb-normalization-30472.rs | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 tests/ui/traits/assoc-type-hrtb-normalization-30472.rs diff --git a/tests/ui/traits/assoc-type-hrtb-normalization-30472.rs b/tests/ui/traits/assoc-type-hrtb-normalization-30472.rs new file mode 100644 index 0000000000000..4ce3b9b3b7764 --- /dev/null +++ b/tests/ui/traits/assoc-type-hrtb-normalization-30472.rs @@ -0,0 +1,32 @@ +//@ check-pass +//! Tests that associated type projections normalize properly in the presence of HRTBs. +//! Original issue: + + +pub trait MyFrom {} +impl MyFrom for T {} + +pub trait MyInto {} +impl MyInto for T where U: MyFrom {} + + +pub trait A<'self_> { + type T; +} +pub trait B: for<'self_> A<'self_> { + // Originally caused the `type U = usize` example below to fail with a type mismatch error + type U: for<'self_> MyFrom<>::T>; +} + + +pub struct M; +impl<'self_> A<'self_> for M { + type T = usize; +} + +impl B for M { + type U = usize; +} + + +fn main() {} From 382365bfe3f136fe97273e58532d799a82b373ea Mon Sep 17 00:00:00 2001 From: clubby789 Date: Mon, 7 Oct 2024 11:36:58 +0000 Subject: [PATCH 1987/2194] Add test for issue 30867 --- tests/ui/traits/hrtb-related-type-params-30867.rs | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 tests/ui/traits/hrtb-related-type-params-30867.rs diff --git a/tests/ui/traits/hrtb-related-type-params-30867.rs b/tests/ui/traits/hrtb-related-type-params-30867.rs new file mode 100644 index 0000000000000..ec1e3355bfba7 --- /dev/null +++ b/tests/ui/traits/hrtb-related-type-params-30867.rs @@ -0,0 +1,14 @@ +//@ check-pass +//! Tests that HRTB impl selection covers type parameters not directly related +//! to the trait. +//! Test for + +#![crate_type = "lib"] + +trait Unary {} +impl U> Unary for F {} +fn unary Unary<&'a T>, T>() {} + +pub fn test Fn(&'a i32) -> &'a i32>() { + unary::() +} From 126cb9bb78854f10310129869a583536a947517c Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 7 Oct 2024 18:41:32 +0200 Subject: [PATCH 1988/2194] Remove dead code --- src/librustdoc/html/markdown.rs | 49 +------------- .../passes/collect_intra_doc_links.rs | 67 ------------------- 2 files changed, 1 insertion(+), 115 deletions(-) diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs index b18d621478c7d..b86fbf77e595f 100644 --- a/src/librustdoc/html/markdown.rs +++ b/src/librustdoc/html/markdown.rs @@ -35,8 +35,7 @@ use std::str::{self, CharIndices}; use std::sync::OnceLock; use pulldown_cmark::{ - BrokenLink, BrokenLinkCallback, CodeBlockKind, CowStr, Event, LinkType, OffsetIter, Options, - Parser, Tag, TagEnd, html, + BrokenLink, CodeBlockKind, CowStr, Event, LinkType, Options, Parser, Tag, TagEnd, html, }; use rustc_data_structures::fx::FxHashMap; use rustc_errors::{Diag, DiagMessage}; @@ -1683,7 +1682,6 @@ pub(crate) fn html_text_from_events<'a>( pub(crate) struct MarkdownLink { pub kind: LinkType, pub link: String, - pub display_text: Option, pub range: MarkdownLinkRange, } @@ -1845,23 +1843,9 @@ pub(crate) fn markdown_links<'md, R>( LinkType::Autolink | LinkType::Email => unreachable!(), }; - let display_text = if matches!( - link_type, - LinkType::Inline - | LinkType::ReferenceUnknown - | LinkType::Reference - | LinkType::Shortcut - | LinkType::ShortcutUnknown - ) { - collect_link_data(&mut event_iter) - } else { - None - }; - if let Some(link) = preprocess_link(MarkdownLink { kind: link_type, link: dest_url.into_string(), - display_text, range, }) { links.push(link); @@ -1874,37 +1858,6 @@ pub(crate) fn markdown_links<'md, R>( links } -/// Collects additional data of link. -fn collect_link_data<'input, F: BrokenLinkCallback<'input>>( - event_iter: &mut OffsetIter<'input, F>, -) -> Option { - let mut display_text: Option = None; - let mut append_text = |text: CowStr<'_>| { - if let Some(display_text) = &mut display_text { - display_text.push_str(&text); - } else { - display_text = Some(text.to_string()); - } - }; - - while let Some((event, _span)) = event_iter.next() { - match event { - Event::Text(text) => { - append_text(text); - } - Event::Code(code) => { - append_text(code); - } - Event::End(_) => { - break; - } - _ => {} - } - } - - display_text -} - #[derive(Debug)] pub(crate) struct RustCodeBlock { /// The range in the markdown that the code block occupies. Note that this includes the fences diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs index e95e8762b1db5..2656612a13eb7 100644 --- a/src/librustdoc/passes/collect_intra_doc_links.rs +++ b/src/librustdoc/passes/collect_intra_doc_links.rs @@ -1028,21 +1028,6 @@ impl LinkCollector<'_, '_> { false, )?; - if ori_link.display_text.is_some() { - self.resolve_display_text( - path_str, - ResolutionInfo { - item_id, - module_id, - dis: disambiguator, - path_str: ori_link.display_text.clone()?.into_boxed_str(), - extra_fragment: extra_fragment.clone(), - }, - &ori_link, - &diag_info, - ); - } - // Check for a primitive which might conflict with a module // Report the ambiguity and require that the user specify which one they meant. // FIXME: could there ever be a primitive not in the type namespace? @@ -1385,58 +1370,6 @@ impl LinkCollector<'_, '_> { } } } - - /// Resolve display text if the provided link has separated parts of links. - /// - /// For example: - /// Inline link `[display_text](dest_link)` and reference link `[display_text][reference_link]` has - /// separated parts of links. - fn resolve_display_text( - &mut self, - explicit_link: &Box, - display_res_info: ResolutionInfo, - ori_link: &MarkdownLink, - diag_info: &DiagnosticInfo<'_>, - ) { - // Check if explicit resolution's path is same as resolution of original link's display text path, see - // tests/rustdoc-ui/lint/redundant_explicit_links.rs for more cases. - // - // To avoid disambiguator from panicking, we check if display text path is possible to be disambiguated - // into explicit path. - if !matches!( - ori_link.kind, - LinkType::Inline | LinkType::Reference | LinkType::ReferenceUnknown - ) { - return; - } - - // Algorithm to check if display text could possibly be the explicit link: - // - // Consider 2 links which are display text and explicit link, pick the shorter - // one as symbol and longer one as full qualified path, and tries to match symbol - // to the full qualified path's last symbol. - // - // Otherwise, check if 2 links are same, if so, skip the resolve process. - // - // Notice that this algorithm is passive, might possibly miss actual redundant cases. - let explicit_link = explicit_link.to_string(); - let display_text = ori_link.display_text.as_ref().unwrap(); - - if display_text.len() == explicit_link.len() { - // Whether they are same or not, skip the resolve process. - return; - } - - if explicit_link.ends_with(&display_text[..]) || display_text.ends_with(&explicit_link[..]) - { - self.resolve_with_disambiguator_cached( - display_res_info, - diag_info.clone(), // this struct should really be Copy, but Range is not :( - false, - true, - ); - } - } } /// Get the section of a link between the backticks, From 4d7c6ca1bba06574ab04ea4f4d40f42216c05e56 Mon Sep 17 00:00:00 2001 From: rustbot <47979223+rustbot@users.noreply.github.com> Date: Mon, 7 Oct 2024 13:01:01 -0400 Subject: [PATCH 1989/2194] Update books --- src/doc/book | 2 +- src/doc/embedded-book | 2 +- src/doc/nomicon | 2 +- src/doc/reference | 2 +- src/doc/rust-by-example | 2 +- src/doc/rustc-dev-guide | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/doc/book b/src/doc/book index 99cf75a5414fa..f38ce8baef98c 160000 --- a/src/doc/book +++ b/src/doc/book @@ -1 +1 @@ -Subproject commit 99cf75a5414fa8adbe3974bd0836661ca901708f +Subproject commit f38ce8baef98cb20229e56f1be2d50e345f11792 diff --git a/src/doc/embedded-book b/src/doc/embedded-book index dbae36bf3f841..f40a8b420ec4b 160000 --- a/src/doc/embedded-book +++ b/src/doc/embedded-book @@ -1 +1 @@ -Subproject commit dbae36bf3f8410aa4313b3bad42e374735d48a9d +Subproject commit f40a8b420ec4b4505d9489965e261f1d5c28ba23 diff --git a/src/doc/nomicon b/src/doc/nomicon index 14649f15d232d..456b904f79175 160000 --- a/src/doc/nomicon +++ b/src/doc/nomicon @@ -1 +1 @@ -Subproject commit 14649f15d232d509478206ee9ed5105641aa60d0 +Subproject commit 456b904f791751892b01282fd2757904993c4c26 diff --git a/src/doc/reference b/src/doc/reference index 24fb2687cdbc5..c64e52a3d306e 160000 --- a/src/doc/reference +++ b/src/doc/reference @@ -1 +1 @@ -Subproject commit 24fb2687cdbc54fa18ae4acf5d879cfceca77b2c +Subproject commit c64e52a3d306eac0129f3ad6c6d8806ab99ae2e9 diff --git a/src/doc/rust-by-example b/src/doc/rust-by-example index c79ec345f08a1..8bede1b919a81 160000 --- a/src/doc/rust-by-example +++ b/src/doc/rust-by-example @@ -1 +1 @@ -Subproject commit c79ec345f08a1e94494cdc8c999709a90203fd88 +Subproject commit 8bede1b919a81ab7d0c961f6bbf68d3efa297bd2 diff --git a/src/doc/rustc-dev-guide b/src/doc/rustc-dev-guide index 555f3de2fa0d6..07bc9ca9eb1cd 160000 --- a/src/doc/rustc-dev-guide +++ b/src/doc/rustc-dev-guide @@ -1 +1 @@ -Subproject commit 555f3de2fa0d61c4294b74d245f1cbad6fcbf589 +Subproject commit 07bc9ca9eb1cd6d9fbbf758c2753b748804a134f From e23419fc97a8ca2fb3f6331115c13b2a5948d2c9 Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Mon, 7 Oct 2024 10:30:27 -0700 Subject: [PATCH 1990/2194] rustdoc: improve ``-insertion for SCREAMING_CAMEL_CASE --- src/librustdoc/html/escape.rs | 2 +- src/librustdoc/html/escape/tests.rs | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/librustdoc/html/escape.rs b/src/librustdoc/html/escape.rs index 691f86847b56d..72ad42c2bd0ff 100644 --- a/src/librustdoc/html/escape.rs +++ b/src/librustdoc/html/escape.rs @@ -108,7 +108,7 @@ impl<'a> fmt::Display for EscapeBodyTextWithWbr<'a> { || pk.map_or(true, |(_, t)| t.chars().any(|c| c.is_uppercase())); let next_is_underscore = || pk.map_or(true, |(_, t)| t.contains('_')); let next_is_colon = || pk.map_or(true, |(_, t)| t.contains(':')); - if i - last > 3 && is_uppercase() && !next_is_uppercase() { + if i - last > 3 && is_uppercase() && !next_is_uppercase() && !next_is_underscore() { EscapeBodyText(&text[last..i]).fmt(fmt)?; fmt.write_str("")?; last = i; diff --git a/src/librustdoc/html/escape/tests.rs b/src/librustdoc/html/escape/tests.rs index a09649e9e18dc..de702e1606353 100644 --- a/src/librustdoc/html/escape/tests.rs +++ b/src/librustdoc/html/escape/tests.rs @@ -24,6 +24,10 @@ fn escape_body_text_with_wbr() { assert_eq!(&E("first:second").to_string(), "first:second"); assert_eq!(&E("first::second").to_string(), "first::second"); assert_eq!(&E("MY_CONSTANT").to_string(), "MY_CONSTANT"); + assert_eq!( + &E("_SIDD_MASKED_NEGATIVE_POLARITY").to_string(), + "_SIDD_MASKED_NEGATIVE_POLARITY" + ); // a string won't get wrapped if it's less than 8 bytes assert_eq!(&E("HashSet").to_string(), "HashSet"); // an individual word won't get wrapped if it's less than 4 bytes From f7eced3a21a3a0377b2a23ba6fb0f8a346e837f1 Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Mon, 7 Oct 2024 13:27:50 -0700 Subject: [PATCH 1991/2194] Add comment to describe camelcase line break --- src/librustdoc/html/escape.rs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/librustdoc/html/escape.rs b/src/librustdoc/html/escape.rs index 72ad42c2bd0ff..31a2701f06a54 100644 --- a/src/librustdoc/html/escape.rs +++ b/src/librustdoc/html/escape.rs @@ -108,6 +108,16 @@ impl<'a> fmt::Display for EscapeBodyTextWithWbr<'a> { || pk.map_or(true, |(_, t)| t.chars().any(|c| c.is_uppercase())); let next_is_underscore = || pk.map_or(true, |(_, t)| t.contains('_')); let next_is_colon = || pk.map_or(true, |(_, t)| t.contains(':')); + // Check for CamelCase. + // + // `i - last > 3` avoids turning FmRadio into FmRadio, which is technically + // correct, but needlessly bloated. + // + // is_uppercase && !next_is_uppercase checks for camelCase. HTTPSProxy, + // for example, should become HTTPSProxy. + // + // !next_is_underscore avoids turning TEST_RUN into TEST_RUN, which is also + // needlessly bloated. if i - last > 3 && is_uppercase() && !next_is_uppercase() && !next_is_underscore() { EscapeBodyText(&text[last..i]).fmt(fmt)?; fmt.write_str("")?; From 5fb71c677f2fc7922147764f928bbb104e0ebe87 Mon Sep 17 00:00:00 2001 From: Miguel Ojeda Date: Mon, 7 Oct 2024 23:32:05 +0200 Subject: [PATCH 1992/2194] CI: rfl: move job forward to Linux v6.12-rc2 Signed-off-by: Miguel Ojeda --- src/ci/docker/scripts/rfl-build.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ci/docker/scripts/rfl-build.sh b/src/ci/docker/scripts/rfl-build.sh index 8011e07e92e60..27dbfc6040ce0 100755 --- a/src/ci/docker/scripts/rfl-build.sh +++ b/src/ci/docker/scripts/rfl-build.sh @@ -2,7 +2,7 @@ set -euo pipefail -LINUX_VERSION=4c7864e81d8bbd51036dacf92fb0a400e13aaeee +LINUX_VERSION=v6.12-rc2 # Build rustc, rustdoc, cargo, clippy-driver and rustfmt ../x.py build --stage 2 library rustdoc clippy rustfmt From 89b0f8a6891ce111ab256269dba1cfa09695b818 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Mon, 7 Oct 2024 14:36:49 -0700 Subject: [PATCH 1993/2194] Fix utf8-bom test The BOM was accidentally removed in https://github.com/rust-lang/rust/pull/57108 --- tests/ui/utf8-bom.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/tests/ui/utf8-bom.rs b/tests/ui/utf8-bom.rs index e2e4ccd63c164..5b9e27fb7b942 100644 --- a/tests/ui/utf8-bom.rs +++ b/tests/ui/utf8-bom.rs @@ -1,6 +1,4 @@ +// This file has utf-8 BOM, it should be compiled normally without error. //@ run-pass -// - -// This file has utf-8 BOM, it should be compiled normally without error. pub fn main() {} From cb267b4c560715f9e5fa60010c92be4003655c67 Mon Sep 17 00:00:00 2001 From: AngelicosPhosphoros Date: Tue, 8 Oct 2024 00:23:53 +0200 Subject: [PATCH 1994/2194] Add docs about slicing slices at the ends Closes https://github.com/rust-lang/rust/issues/60783 --- library/core/src/primitive_docs.rs | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/library/core/src/primitive_docs.rs b/library/core/src/primitive_docs.rs index c25501f12001a..89936dc12ac36 100644 --- a/library/core/src/primitive_docs.rs +++ b/library/core/src/primitive_docs.rs @@ -862,6 +862,27 @@ mod prim_array {} /// assert_eq!(x, &[1, 7, 3]); /// ``` /// +/// It is possible to slice empty subranges of slices by using empty ranges (including `slice.len()..slice.len()`): +/// ``` +/// let x = [1, 2, 3]; +/// let empty = &x[0..0]; // subslice before the first element +/// assert_eq!(empty, &[]); +/// let empty = &x[..0]; // same as &x[0..0] +/// assert_eq!(empty, &[]); +/// let empty = &x[1..1]; // empty subslice in the middle +/// assert_eq!(empty, &[]); +/// let empty = &x[3..3]; // subslice after the last element +/// assert_eq!(empty, &[]); +/// let empty = &x[3..]; // same as &x[3..3] +/// assert_eq!(empty, &[]); +/// ``` +/// +/// It is not allowed to use subranges that start with lower bound bigger than `slice.len()`: +/// ```should_panic +/// let x = vec![1, 2, 3]; +/// let _ = &x[4..4]; +/// ``` +/// /// As slices store the length of the sequence they refer to, they have twice /// the size of pointers to [`Sized`](marker/trait.Sized.html) types. /// Also see the reference on From 03abf6756ded764648c500d39e506d34ca30868b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=AE=B8=E6=9D=B0=E5=8F=8B=20Jieyou=20Xu=20=28Joe=29?= Date: Thu, 3 Oct 2024 14:27:47 +0000 Subject: [PATCH 1995/2194] Use untracked env var to pass `-Zon-broken-pipe=kill` for tools - Don't touch rustc's `-Zon-broken-pipe=kill` env var in `compile.rs`. - Use an untracked env var to pass `-Zon-broken-pipe=kill` for tools but skip cargo still, because cargo wants `-Zon-broken-pipe=kill` unset. --- src/bootstrap/src/bin/rustc.rs | 8 ++++++ src/bootstrap/src/core/build_steps/compile.rs | 15 +++++++++-- src/bootstrap/src/core/build_steps/tool.rs | 25 ++++++++++++++++--- 3 files changed, 42 insertions(+), 6 deletions(-) diff --git a/src/bootstrap/src/bin/rustc.rs b/src/bootstrap/src/bin/rustc.rs index 780979ed98121..6f7ccde5e5bc7 100644 --- a/src/bootstrap/src/bin/rustc.rs +++ b/src/bootstrap/src/bin/rustc.rs @@ -136,6 +136,14 @@ fn main() { cmd.args(lint_flags.split_whitespace()); } + // Conditionally pass `-Zon-broken-pipe=kill` to rustc bin shim when this shim is *not* used to + // build cargo itself, i.e. set `-Zon-broken-pipe=kill` only when building non-cargo tools. + // + // See for more context. + if env::var_os("FORCE_ON_BROKEN_PIPE_KILL").is_some() { + cmd.arg("-Z").arg("on-broken-pipe=kill"); + } + if target.is_some() { // The stage0 compiler has a special sysroot distinct from what we // actually downloaded, so we just always pass the `--sysroot` option, diff --git a/src/bootstrap/src/core/build_steps/compile.rs b/src/bootstrap/src/core/build_steps/compile.rs index b5be7d841dd93..27bbc8bd8ff22 100644 --- a/src/bootstrap/src/core/build_steps/compile.rs +++ b/src/bootstrap/src/core/build_steps/compile.rs @@ -1053,8 +1053,19 @@ pub fn rustc_cargo( cargo.rustdocflag("-Zcrate-attr=warn(rust_2018_idioms)"); - // If the rustc output is piped to e.g. `head -n1` we want the process to be - // killed, rather than having an error bubble up and cause a panic. + // If the rustc output is piped to e.g. `head -n1` we want the process to be killed, rather than + // having an error bubble up and cause a panic. + // + // FIXME(jieyouxu): this flag is load-bearing for rustc to not ICE on broken pipes, because + // rustc internally sometimes uses std `println!` -- but std `println!` by default will panic on + // broken pipes, and uncaught panics will manifest as an ICE. The compiler *should* handle this + // properly, but this flag is set in the meantime to paper over the I/O errors. + // + // See for details. + // + // Also see the discussion for properly handling I/O errors related to broken pipes, i.e. safe + // variants of `println!` in + // . cargo.rustflag("-Zon-broken-pipe=kill"); if builder.config.llvm_enzyme { diff --git a/src/bootstrap/src/core/build_steps/tool.rs b/src/bootstrap/src/core/build_steps/tool.rs index e2fcd13efe3aa..a01497c2bb98a 100644 --- a/src/bootstrap/src/core/build_steps/tool.rs +++ b/src/bootstrap/src/core/build_steps/tool.rs @@ -209,11 +209,28 @@ pub fn prepare_tool_cargo( // See https://github.com/rust-lang/rust/issues/116538 cargo.rustflag("-Zunstable-options"); - // `-Zon-broken-pipe=kill` breaks cargo tests + // NOTE: The root cause of needing `-Zon-broken-pipe=kill` in the first place is because `rustc` + // and `rustdoc` doesn't gracefully handle I/O errors due to usages of raw std `println!` macros + // which panics upon encountering broken pipes. `-Zon-broken-pipe=kill` just papers over that + // and stops rustc/rustdoc ICEing on e.g. `rustc --print=sysroot | false`. + // + // cargo explicitly does not want the `-Zon-broken-pipe=kill` paper because it does actually use + // variants of `println!` that handles I/O errors gracefully. It's also a breaking change for a + // spawn process not written in Rust, especially if the language default handler is not + // `SIG_IGN`. Thankfully cargo tests will break if we do set the flag. + // + // For the cargo discussion, see + // . + // + // For the rustc discussion, see + // + // for proper solutions. if !path.ends_with("cargo") { - // If the output is piped to e.g. `head -n1` we want the process to be killed, - // rather than having an error bubble up and cause a panic. - cargo.rustflag("-Zon-broken-pipe=kill"); + // Use an untracked env var `FORCE_ON_BROKEN_PIPE_KILL` here instead of `RUSTFLAGS`. + // `RUSTFLAGS` is tracked by cargo. Conditionally omitting `-Zon-broken-pipe=kill` from + // `RUSTFLAGS` causes unnecessary tool rebuilds due to cache invalidation from building e.g. + // cargo *without* `-Zon-broken-pipe=kill` but then rustdoc *with* `-Zon-broken-pipe=kill`. + cargo.env("FORCE_ON_BROKEN_PIPE_KILL", "-Zon-broken-pipe=kill"); } cargo From db6e31bba789a9afff3fdbf0633a0922bde6af6a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=AE=B8=E6=9D=B0=E5=8F=8B=20Jieyou=20Xu=20=28Joe=29?= Date: Mon, 7 Oct 2024 23:40:17 +0000 Subject: [PATCH 1996/2194] Remove myself from vacation --- triagebot.toml | 1 - 1 file changed, 1 deletion(-) diff --git a/triagebot.toml b/triagebot.toml index 0172a80b3a5a0..d3e4af9b71899 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -926,7 +926,6 @@ users_on_vacation = [ "jhpratt", "jyn514", "oli-obk", - "jieyouxu", ] [assign.adhoc_groups] From e502a7f13a4605503e1b73cfdfb69d64d11ea722 Mon Sep 17 00:00:00 2001 From: Henry Jiang Date: Mon, 7 Oct 2024 20:40:55 -0400 Subject: [PATCH 1997/2194] add aix aggregate test --- tests/assembly/powerpc64-struct-abi.rs | 43 +++++++++++++++++++++++--- 1 file changed, 39 insertions(+), 4 deletions(-) diff --git a/tests/assembly/powerpc64-struct-abi.rs b/tests/assembly/powerpc64-struct-abi.rs index 9a3540d8b4163..7052937acf661 100644 --- a/tests/assembly/powerpc64-struct-abi.rs +++ b/tests/assembly/powerpc64-struct-abi.rs @@ -1,4 +1,4 @@ -//@ revisions: elfv1-be elfv2-be elfv2-le +//@ revisions: elfv1-be elfv2-be elfv2-le aix //@ assembly-output: emit-asm //@ compile-flags: -O //@[elfv1-be] compile-flags: --target powerpc64-unknown-linux-gnu @@ -7,8 +7,13 @@ //@[elfv2-be] needs-llvm-components: powerpc //@[elfv2-le] compile-flags: --target powerpc64le-unknown-linux-gnu //@[elfv2-le] needs-llvm-components: powerpc +//@[aix] compile-flags: --target powerpc64-ibm-aix +//@[aix] needs-llvm-components: powerpc //@[elfv1-be] filecheck-flags: --check-prefix be //@[elfv2-be] filecheck-flags: --check-prefix be +//@[elfv1-be] filecheck-flags: --check-prefix elf +//@[elfv2-be] filecheck-flags: --check-prefix elf +//@[elfv2-le] filecheck-flags: --check-prefix elf #![feature(no_core, lang_items)] #![no_std] @@ -44,6 +49,10 @@ struct FiveU16s(u16, u16, u16, u16, u16); struct ThreeU8s(u8, u8, u8); // CHECK-LABEL: read_large +// aix: lwz [[REG1:.*]], 16(4) +// aix-NEXT: lxvd2x 0, 0, 4 +// aix-NEXT: stw [[REG1]], 16(3) +// aix-NEXT: stxvd2x 0, 0, 3 // be: lwz [[REG1:.*]], 16(4) // be-NEXT: stw [[REG1]], 16(3) // be-NEXT: ld [[REG2:.*]], 8(4) @@ -61,6 +70,10 @@ extern "C" fn read_large(x: &FiveU32s) -> FiveU32s { } // CHECK-LABEL: read_medium +// aix: lhz [[REG1:.*]], 8(4) +// aix-NEXT: ld [[REG2:.*]], 0(4) +// aix-NEXT: sth [[REG1]], 8(3) +// aix-NEXT: std [[REG2]], 0(3) // elfv1-be: lhz [[REG1:.*]], 8(4) // elfv1-be-NEXT: ld [[REG2:.*]], 0(4) // elfv1-be-NEXT: sth [[REG1]], 8(3) @@ -78,6 +91,10 @@ extern "C" fn read_medium(x: &FiveU16s) -> FiveU16s { } // CHECK-LABEL: read_small +// aix: lbz [[REG1:.*]], 2(4) +// aix-NEXT: lhz [[REG2:.*]], 0(4) +// aix-NEXT: stb [[REG1]], 2(3) +// aix-NEXT: sth [[REG2]], 0(3) // elfv1-be: lbz [[REG1:.*]], 2(4) // elfv1-be-NEXT: lhz [[REG2:.*]], 0(4) // elfv1-be-NEXT: stb [[REG1]], 2(3) @@ -95,9 +112,17 @@ extern "C" fn read_small(x: &ThreeU8s) -> ThreeU8s { } // CHECK-LABEL: write_large -// CHECK: std 3, 0(6) +// aix: std 3, 48(1) +// aix-NEXT: rldicl [[REG1:.*]], 5, 32, 32 +// aix-NEXT: std 5, 64(1) +// aix-NEXT: std 4, 56(1) +// aix-NEXT: stw [[REG1]], 16(6) +// aix-NEXT: addi [[REG2:.*]], 1, 48 +// aix-NEXT: lxvd2x 0, 0, [[REG2]] +// aix-NEXT: stxvd2x 0, 0, 6 +// elf: std 3, 0(6) // be-NEXT: rldicl [[REG1:.*]], 5, 32, 32 -// CHECK-NEXT: std 4, 8(6) +// elf-NEXT: std 4, 8(6) // be-NEXT: stw [[REG1]], 16(6) // elfv2-le-NEXT: stw 5, 16(6) // CHECK-NEXT: blr @@ -107,7 +132,12 @@ extern "C" fn write_large(x: FiveU32s, dest: &mut FiveU32s) { } // CHECK-LABEL: write_medium -// CHECK: std 3, 0(5) +// aix: std 4, 56(1) +// aix-NEXT: rldicl [[REG1:.*]], 4, 16, 48 +// aix-NEXT: std 3, 48(1) +// aix-NEXT: std 3, 0(5) +// aix-NEXT: sth [[REG1]], 8(5) +// elf: std 3, 0(5) // be-NEXT: rldicl [[REG1:.*]], 4, 16, 48 // be-NEXT: sth [[REG1]], 8(5) // elfv2-le-NEXT: sth 4, 8(5) @@ -118,6 +148,11 @@ extern "C" fn write_medium(x: FiveU16s, dest: &mut FiveU16s) { } // CHECK-LABEL: write_small +// aix: std 3, 48(1) +// aix-NEXT: rldicl [[REG1:.*]], 3, 16, 48 +// aix-NEXT: sth 3, 0(4) +// aix-NEXT: lbz 3, 50(1) +// aix-NEXT: stb [[REG1]], 2(4) // be: stb 3, 2(4) // be-NEXT: srwi [[REG1:.*]], 3, 8 // be-NEXT: sth [[REG1]], 0(4) From 5c0131641d2edfc21e4f627f94f0aadc6cfc6e47 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=AE=B8=E6=9D=B0=E5=8F=8B=20Jieyou=20Xu=20=28Joe=29?= Date: Thu, 3 Oct 2024 16:27:11 +0000 Subject: [PATCH 1998/2194] Add regression test for rustc/rustdoc broken pipe ICEs --- src/bootstrap/src/bin/rustc.rs | 6 +- tests/run-make/broken-pipe-no-ice/rmake.rs | 73 ++++++++++++++++++++++ 2 files changed, 75 insertions(+), 4 deletions(-) create mode 100644 tests/run-make/broken-pipe-no-ice/rmake.rs diff --git a/src/bootstrap/src/bin/rustc.rs b/src/bootstrap/src/bin/rustc.rs index 6f7ccde5e5bc7..18f5a1a58db93 100644 --- a/src/bootstrap/src/bin/rustc.rs +++ b/src/bootstrap/src/bin/rustc.rs @@ -136,10 +136,8 @@ fn main() { cmd.args(lint_flags.split_whitespace()); } - // Conditionally pass `-Zon-broken-pipe=kill` to rustc bin shim when this shim is *not* used to - // build cargo itself, i.e. set `-Zon-broken-pipe=kill` only when building non-cargo tools. - // - // See for more context. + // Conditionally pass `-Zon-broken-pipe=kill` to underlying rustc. Not all binaries want + // `-Zon-broken-pipe=kill`, which includes cargo itself. if env::var_os("FORCE_ON_BROKEN_PIPE_KILL").is_some() { cmd.arg("-Z").arg("on-broken-pipe=kill"); } diff --git a/tests/run-make/broken-pipe-no-ice/rmake.rs b/tests/run-make/broken-pipe-no-ice/rmake.rs new file mode 100644 index 0000000000000..d1db0bc736883 --- /dev/null +++ b/tests/run-make/broken-pipe-no-ice/rmake.rs @@ -0,0 +1,73 @@ +//! Check that `rustc` and `rustdoc` does not ICE upon encountering a broken pipe due to unhandled +//! panics from raw std `println!` usages. +//! +//! Regression test for . + +//@ ignore-cross-compile (needs to run test binary) + +#![feature(anonymous_pipe)] + +use std::io::Read; +use std::process::{Command, Stdio}; + +use run_make_support::env_var; + +#[derive(Debug, PartialEq)] +enum Binary { + Rustc, + Rustdoc, +} + +fn check_broken_pipe_handled_gracefully(bin: Binary, mut cmd: Command) { + let (reader, writer) = std::pipe::pipe().unwrap(); + drop(reader); // close read-end + cmd.stdout(writer).stderr(Stdio::piped()); + + let mut child = cmd.spawn().unwrap(); + + let mut stderr = String::new(); + child.stderr.as_mut().unwrap().read_to_string(&mut stderr).unwrap(); + let status = child.wait().unwrap(); + + assert!(!status.success(), "{bin:?} unexpectedly succeeded"); + + const PANIC_ICE_EXIT_CODE: i32 = 101; + + #[cfg(not(windows))] + { + // On non-Windows, rustc/rustdoc built with `-Zon-broken-pipe=kill` shouldn't have an exit + // code of 101 because it should have an wait status that corresponds to SIGPIPE signal + // number. + assert_ne!(status.code(), Some(PANIC_ICE_EXIT_CODE), "{bin:?}"); + // And the stderr should be empty because rustc/rustdoc should've gotten killed. + assert!(stderr.is_empty(), "{bin:?} stderr:\n{}", stderr); + } + + #[cfg(windows)] + { + match bin { + // On Windows, rustc has a paper that propagates the panic exit code of 101 but converts + // broken pipe errors into fatal errors instead of ICEs. + Binary::Rustc => { + assert_eq!(status.code(), Some(PANIC_ICE_EXIT_CODE), "{bin:?}"); + // But make sure it doesn't manifest as an ICE. + assert!(!stderr.contains("internal compiler error"), "{bin:?} ICE'd"); + } + // On Windows, rustdoc seems to cleanly exit with exit code of 1. + Binary::Rustdoc => { + assert_eq!(status.code(), Some(1), "{bin:?}"); + assert!(!stderr.contains("panic"), "{bin:?} stderr contains panic"); + } + } + } +} + +fn main() { + let mut rustc = Command::new(env_var("RUSTC")); + rustc.arg("--print=sysroot"); + check_broken_pipe_handled_gracefully(Binary::Rustc, rustc); + + let mut rustdoc = Command::new(env_var("RUSTDOC")); + rustdoc.arg("--version"); + check_broken_pipe_handled_gracefully(Binary::Rustdoc, rustdoc); +} From 911ac56e955f52c221660608b9389d8919cdb095 Mon Sep 17 00:00:00 2001 From: zhuyunxing Date: Wed, 19 Jun 2024 17:49:10 +0800 Subject: [PATCH 1999/2194] coverage. Disable supporting mcdc on llvm-18 --- compiler/rustc_codegen_llvm/src/builder.rs | 13 ++++++ .../llvm-wrapper/CoverageMappingWrapper.cpp | 45 ++++--------------- .../rustc_llvm/llvm-wrapper/RustWrapper.cpp | 14 +++--- tests/coverage/mcdc/condition-limit.coverage | 2 +- tests/coverage/mcdc/condition-limit.rs | 2 +- tests/coverage/mcdc/if.coverage | 2 +- tests/coverage/mcdc/if.rs | 2 +- .../mcdc/inlined_expressions.coverage | 2 +- tests/coverage/mcdc/inlined_expressions.rs | 2 +- tests/coverage/mcdc/nested_if.coverage | 2 +- tests/coverage/mcdc/nested_if.rs | 2 +- tests/coverage/mcdc/non_control_flow.coverage | 2 +- tests/coverage/mcdc/non_control_flow.rs | 2 +- 13 files changed, 38 insertions(+), 54 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/builder.rs b/compiler/rustc_codegen_llvm/src/builder.rs index 4e0c62c8bf8c9..3abebdf6ca1cf 100644 --- a/compiler/rustc_codegen_llvm/src/builder.rs +++ b/compiler/rustc_codegen_llvm/src/builder.rs @@ -1683,6 +1683,11 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> { ) { debug!("mcdc_parameters() with args ({:?}, {:?}, {:?})", fn_name, hash, bitmap_bytes); + assert!( + crate::llvm_util::get_version() >= (19, 0, 0), + "MCDC intrinsics require LLVM 19 or later" + ); + let llfn = unsafe { llvm::LLVMRustGetInstrProfMCDCParametersIntrinsic(self.cx().llmod) }; let llty = self.cx.type_func( &[self.cx.type_ptr(), self.cx.type_i64(), self.cx.type_i32()], @@ -1716,6 +1721,10 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> { "mcdc_tvbitmap_update() with args ({:?}, {:?}, {:?}, {:?}, {:?})", fn_name, hash, bitmap_bytes, bitmap_index, mcdc_temp ); + assert!( + crate::llvm_util::get_version() >= (19, 0, 0), + "MCDC intrinsics require LLVM 19 or later" + ); let llfn = unsafe { llvm::LLVMRustGetInstrProfMCDCTVBitmapUpdateIntrinsic(self.cx().llmod) }; @@ -1757,6 +1766,10 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> { "mcdc_condbitmap_update() with args ({:?}, {:?}, {:?}, {:?}, {:?})", fn_name, hash, cond_loc, mcdc_temp, bool_value ); + assert!( + crate::llvm_util::get_version() >= (19, 0, 0), + "MCDC intrinsics require LLVM 19 or later" + ); let llfn = unsafe { llvm::LLVMRustGetInstrProfMCDCCondBitmapIntrinsic(self.cx().llmod) }; let llty = self.cx.type_func( &[ diff --git a/compiler/rustc_llvm/llvm-wrapper/CoverageMappingWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/CoverageMappingWrapper.cpp index 4532fd8d48d07..8ee0597732083 100644 --- a/compiler/rustc_llvm/llvm-wrapper/CoverageMappingWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/CoverageMappingWrapper.cpp @@ -88,38 +88,7 @@ struct LLVMRustMCDCParameters { LLVMRustMCDCBranchParameters BranchParameters; }; -// LLVM representations for `MCDCParameters` evolved from LLVM 18 to 19. -// Look at representations in 18 -// https://github.com/rust-lang/llvm-project/blob/66a2881a/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h#L253-L263 -// and representations in 19 -// https://github.com/llvm/llvm-project/blob/843cc474faefad1d639f4c44c1cf3ad7dbda76c8/llvm/include/llvm/ProfileData/Coverage/MCDCTypes.h -#if LLVM_VERSION_LT(19, 0) -static coverage::CounterMappingRegion::MCDCParameters -fromRust(LLVMRustMCDCParameters Params) { - auto parameter = coverage::CounterMappingRegion::MCDCParameters{}; - switch (Params.Tag) { - case LLVMRustMCDCParametersTag::None: - return parameter; - case LLVMRustMCDCParametersTag::Decision: - parameter.BitmapIdx = - static_cast(Params.DecisionParameters.BitmapIdx), - parameter.NumConditions = - static_cast(Params.DecisionParameters.NumConditions); - return parameter; - case LLVMRustMCDCParametersTag::Branch: - parameter.ID = static_cast( - Params.BranchParameters.ConditionID), - parameter.FalseID = - static_cast( - Params.BranchParameters.ConditionIDs[0]), - parameter.TrueID = - static_cast( - Params.BranchParameters.ConditionIDs[1]); - return parameter; - } - report_fatal_error("Bad LLVMRustMCDCParametersTag!"); -} -#else +#if LLVM_VERSION_GE(19, 0) static coverage::mcdc::Parameters fromRust(LLVMRustMCDCParameters Params) { switch (Params.Tag) { case LLVMRustMCDCParametersTag::None: @@ -214,13 +183,17 @@ extern "C" void LLVMRustCoverageWriteMappingToBuffer( RustMappingRegions, NumMappingRegions)) { MappingRegions.emplace_back( fromRust(Region.Count), fromRust(Region.FalseCount), -#if LLVM_VERSION_LT(19, 0) - // LLVM 19 may move this argument to last. - fromRust(Region.MCDCParameters), +#if LLVM_VERSION_GE(18, 0) && LLVM_VERSION_LT(19, 0) + coverage::CounterMappingRegion::MCDCParameters{}, #endif Region.FileID, Region.ExpandedFileID, // File IDs, then region info. Region.LineStart, Region.ColumnStart, Region.LineEnd, Region.ColumnEnd, - fromRust(Region.Kind)); + fromRust(Region.Kind) +#if LLVM_VERSION_GE(19, 0) + , + fromRust(Region.MCDCParameters) +#endif + ); } std::vector Expressions; diff --git a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp index f9fc2bd6da3b0..8faa521240830 100644 --- a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp @@ -1539,23 +1539,21 @@ LLVMRustGetInstrProfIncrementIntrinsic(LLVMModuleRef M) { extern "C" LLVMValueRef LLVMRustGetInstrProfMCDCParametersIntrinsic(LLVMModuleRef M) { +#if LLVM_VERSION_GE(19, 0) return wrap(llvm::Intrinsic::getDeclaration( unwrap(M), llvm::Intrinsic::instrprof_mcdc_parameters)); +#else + report_fatal_error("LLVM 19.0 is required for mcdc intrinsic functions"); +#endif } extern "C" LLVMValueRef LLVMRustGetInstrProfMCDCTVBitmapUpdateIntrinsic(LLVMModuleRef M) { +#if LLVM_VERSION_GE(19, 0) return wrap(llvm::Intrinsic::getDeclaration( unwrap(M), llvm::Intrinsic::instrprof_mcdc_tvbitmap_update)); -} - -extern "C" LLVMValueRef -LLVMRustGetInstrProfMCDCCondBitmapIntrinsic(LLVMModuleRef M) { -#if LLVM_VERSION_LT(19, 0) - return wrap(llvm::Intrinsic::getDeclaration( - unwrap(M), llvm::Intrinsic::instrprof_mcdc_condbitmap_update)); #else - report_fatal_error("LLVM 18.0 is required for mcdc intrinsic functions"); + report_fatal_error("LLVM 19.0 is required for mcdc intrinsic functions"); #endif } diff --git a/tests/coverage/mcdc/condition-limit.coverage b/tests/coverage/mcdc/condition-limit.coverage index ae8596bb9611a..6330f2533d0e0 100644 --- a/tests/coverage/mcdc/condition-limit.coverage +++ b/tests/coverage/mcdc/condition-limit.coverage @@ -1,6 +1,6 @@ LL| |#![feature(coverage_attribute)] LL| |//@ edition: 2021 - LL| |//@ ignore-llvm-version: 19 - 99 + LL| |//@ min-llvm-version: 19 LL| |//@ compile-flags: -Zcoverage-options=mcdc LL| |//@ llvm-cov-flags: --show-branches=count --show-mcdc LL| | diff --git a/tests/coverage/mcdc/condition-limit.rs b/tests/coverage/mcdc/condition-limit.rs index 0d8546b01cd58..2d6fd35ab5781 100644 --- a/tests/coverage/mcdc/condition-limit.rs +++ b/tests/coverage/mcdc/condition-limit.rs @@ -1,6 +1,6 @@ #![feature(coverage_attribute)] //@ edition: 2021 -//@ ignore-llvm-version: 19 - 99 +//@ min-llvm-version: 19 //@ compile-flags: -Zcoverage-options=mcdc //@ llvm-cov-flags: --show-branches=count --show-mcdc diff --git a/tests/coverage/mcdc/if.coverage b/tests/coverage/mcdc/if.coverage index d71de28c6f613..d5cf590d96eff 100644 --- a/tests/coverage/mcdc/if.coverage +++ b/tests/coverage/mcdc/if.coverage @@ -1,6 +1,6 @@ LL| |#![feature(coverage_attribute)] LL| |//@ edition: 2021 - LL| |//@ ignore-llvm-version: 19 - 99 + LL| |//@ min-llvm-version: 19 LL| |//@ compile-flags: -Zcoverage-options=mcdc LL| |//@ llvm-cov-flags: --show-branches=count --show-mcdc LL| | diff --git a/tests/coverage/mcdc/if.rs b/tests/coverage/mcdc/if.rs index 17247f5e0c182..6ade8d34d5449 100644 --- a/tests/coverage/mcdc/if.rs +++ b/tests/coverage/mcdc/if.rs @@ -1,6 +1,6 @@ #![feature(coverage_attribute)] //@ edition: 2021 -//@ ignore-llvm-version: 19 - 99 +//@ min-llvm-version: 19 //@ compile-flags: -Zcoverage-options=mcdc //@ llvm-cov-flags: --show-branches=count --show-mcdc diff --git a/tests/coverage/mcdc/inlined_expressions.coverage b/tests/coverage/mcdc/inlined_expressions.coverage index af0b78477d4dc..57c655a20547e 100644 --- a/tests/coverage/mcdc/inlined_expressions.coverage +++ b/tests/coverage/mcdc/inlined_expressions.coverage @@ -1,6 +1,6 @@ LL| |#![feature(coverage_attribute)] LL| |//@ edition: 2021 - LL| |//@ ignore-llvm-version: 19 - 99 + LL| |//@ min-llvm-version: 19 LL| |//@ compile-flags: -Zcoverage-options=mcdc -Copt-level=z -Cllvm-args=--inline-threshold=0 LL| |//@ llvm-cov-flags: --show-branches=count --show-mcdc LL| | diff --git a/tests/coverage/mcdc/inlined_expressions.rs b/tests/coverage/mcdc/inlined_expressions.rs index 5c1fde6681ab8..651e2fe843876 100644 --- a/tests/coverage/mcdc/inlined_expressions.rs +++ b/tests/coverage/mcdc/inlined_expressions.rs @@ -1,6 +1,6 @@ #![feature(coverage_attribute)] //@ edition: 2021 -//@ ignore-llvm-version: 19 - 99 +//@ min-llvm-version: 19 //@ compile-flags: -Zcoverage-options=mcdc -Copt-level=z -Cllvm-args=--inline-threshold=0 //@ llvm-cov-flags: --show-branches=count --show-mcdc diff --git a/tests/coverage/mcdc/nested_if.coverage b/tests/coverage/mcdc/nested_if.coverage index 37aa33d5c57d9..f14969dc8c9f7 100644 --- a/tests/coverage/mcdc/nested_if.coverage +++ b/tests/coverage/mcdc/nested_if.coverage @@ -1,6 +1,6 @@ LL| |#![feature(coverage_attribute)] LL| |//@ edition: 2021 - LL| |//@ ignore-llvm-version: 19 - 99 + LL| |//@ min-llvm-version: 19 LL| |//@ compile-flags: -Zcoverage-options=mcdc LL| |//@ llvm-cov-flags: --show-branches=count --show-mcdc LL| | diff --git a/tests/coverage/mcdc/nested_if.rs b/tests/coverage/mcdc/nested_if.rs index 1443ccc23abc4..83f188ea47e3a 100644 --- a/tests/coverage/mcdc/nested_if.rs +++ b/tests/coverage/mcdc/nested_if.rs @@ -1,6 +1,6 @@ #![feature(coverage_attribute)] //@ edition: 2021 -//@ ignore-llvm-version: 19 - 99 +//@ min-llvm-version: 19 //@ compile-flags: -Zcoverage-options=mcdc //@ llvm-cov-flags: --show-branches=count --show-mcdc diff --git a/tests/coverage/mcdc/non_control_flow.coverage b/tests/coverage/mcdc/non_control_flow.coverage index 74c19cf12dfee..570f565de74d4 100644 --- a/tests/coverage/mcdc/non_control_flow.coverage +++ b/tests/coverage/mcdc/non_control_flow.coverage @@ -1,6 +1,6 @@ LL| |#![feature(coverage_attribute)] LL| |//@ edition: 2021 - LL| |//@ ignore-llvm-version: 19 - 99 + LL| |//@ min-llvm-version: 19 LL| |//@ compile-flags: -Zcoverage-options=mcdc LL| |//@ llvm-cov-flags: --show-branches=count --show-mcdc LL| | diff --git a/tests/coverage/mcdc/non_control_flow.rs b/tests/coverage/mcdc/non_control_flow.rs index e0145ed8268a9..6cfce6fae9356 100644 --- a/tests/coverage/mcdc/non_control_flow.rs +++ b/tests/coverage/mcdc/non_control_flow.rs @@ -1,6 +1,6 @@ #![feature(coverage_attribute)] //@ edition: 2021 -//@ ignore-llvm-version: 19 - 99 +//@ min-llvm-version: 19 //@ compile-flags: -Zcoverage-options=mcdc //@ llvm-cov-flags: --show-branches=count --show-mcdc From 99bd601df5f65331b4751217eb533abeca7914cb Mon Sep 17 00:00:00 2001 From: zhuyunxing Date: Thu, 25 Jul 2024 14:26:36 +0800 Subject: [PATCH 2000/2194] coverage. MCDC ConditionId start from 0 to keep with llvm 19 --- .../src/coverageinfo/ffi.rs | 13 +++++---- compiler/rustc_middle/src/mir/coverage.rs | 16 ++-------- .../src/build/coverageinfo/mcdc.rs | 29 +++++++++++-------- 3 files changed, 27 insertions(+), 31 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/ffi.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/ffi.rs index 77821ca89bc14..90f7dd733ca18 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/ffi.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/ffi.rs @@ -111,7 +111,7 @@ enum RegionKind { } mod mcdc { - use rustc_middle::mir::coverage::{ConditionInfo, DecisionInfo}; + use rustc_middle::mir::coverage::{ConditionId, ConditionInfo, DecisionInfo}; /// Must match the layout of `LLVMRustMCDCDecisionParameters`. #[repr(C)] @@ -167,12 +167,13 @@ mod mcdc { impl From for BranchParameters { fn from(value: ConditionInfo) -> Self { + let to_llvm_cond_id = |cond_id: Option| { + cond_id.and_then(|id| LLVMConditionId::try_from(id.as_usize()).ok()).unwrap_or(-1) + }; + let ConditionInfo { condition_id, true_next_id, false_next_id } = value; Self { - condition_id: value.condition_id.as_u32() as LLVMConditionId, - condition_ids: [ - value.false_next_id.as_u32() as LLVMConditionId, - value.true_next_id.as_u32() as LLVMConditionId, - ], + condition_id: to_llvm_cond_id(Some(condition_id)), + condition_ids: [to_llvm_cond_id(false_next_id), to_llvm_cond_id(true_next_id)], } } } diff --git a/compiler/rustc_middle/src/mir/coverage.rs b/compiler/rustc_middle/src/mir/coverage.rs index bfe2a2c2cb3db..9a0f5a653214f 100644 --- a/compiler/rustc_middle/src/mir/coverage.rs +++ b/compiler/rustc_middle/src/mir/coverage.rs @@ -67,7 +67,7 @@ rustc_index::newtype_index! { } impl ConditionId { - pub const NONE: Self = Self::from_u32(0); + pub const START: Self = Self::from_usize(0); } /// Enum that can hold a constant zero value, the ID of an physical coverage @@ -291,18 +291,8 @@ pub struct BranchSpan { #[derive(TyEncodable, TyDecodable, Hash, HashStable, TypeFoldable, TypeVisitable)] pub struct ConditionInfo { pub condition_id: ConditionId, - pub true_next_id: ConditionId, - pub false_next_id: ConditionId, -} - -impl Default for ConditionInfo { - fn default() -> Self { - Self { - condition_id: ConditionId::NONE, - true_next_id: ConditionId::NONE, - false_next_id: ConditionId::NONE, - } - } + pub true_next_id: Option, + pub false_next_id: Option, } #[derive(Clone, Debug)] diff --git a/compiler/rustc_mir_build/src/build/coverageinfo/mcdc.rs b/compiler/rustc_mir_build/src/build/coverageinfo/mcdc.rs index 6019a93e7876a..5c45a7a33a297 100644 --- a/compiler/rustc_mir_build/src/build/coverageinfo/mcdc.rs +++ b/compiler/rustc_mir_build/src/build/coverageinfo/mcdc.rs @@ -106,22 +106,27 @@ impl MCDCState { }), }; - let parent_condition = decision_ctx.decision_stack.pop_back().unwrap_or_default(); - let lhs_id = if parent_condition.condition_id == ConditionId::NONE { + let parent_condition = decision_ctx.decision_stack.pop_back().unwrap_or_else(|| { + assert_eq!( + decision.num_conditions, 0, + "decision stack must be empty only for empty decision" + ); decision.num_conditions += 1; - ConditionId::from(decision.num_conditions) - } else { - parent_condition.condition_id - }; + ConditionInfo { + condition_id: ConditionId::START, + true_next_id: None, + false_next_id: None, + } + }); + let lhs_id = parent_condition.condition_id; - decision.num_conditions += 1; let rhs_condition_id = ConditionId::from(decision.num_conditions); - + decision.num_conditions += 1; let (lhs, rhs) = match op { LogicalOp::And => { let lhs = ConditionInfo { condition_id: lhs_id, - true_next_id: rhs_condition_id, + true_next_id: Some(rhs_condition_id), false_next_id: parent_condition.false_next_id, }; let rhs = ConditionInfo { @@ -135,7 +140,7 @@ impl MCDCState { let lhs = ConditionInfo { condition_id: lhs_id, true_next_id: parent_condition.true_next_id, - false_next_id: rhs_condition_id, + false_next_id: Some(rhs_condition_id), }; let rhs = ConditionInfo { condition_id: rhs_condition_id, @@ -164,10 +169,10 @@ impl MCDCState { let Some(decision) = decision_ctx.processing_decision.as_mut() else { bug!("Processing decision should have been created before any conditions are taken"); }; - if condition_info.true_next_id == ConditionId::NONE { + if condition_info.true_next_id.is_none() { decision.end_markers.push(true_marker); } - if condition_info.false_next_id == ConditionId::NONE { + if condition_info.false_next_id.is_none() { decision.end_markers.push(false_marker); } From 6e3e19f714d0ff938c24901195f2c1be6e6e7f6f Mon Sep 17 00:00:00 2001 From: zhuyunxing Date: Thu, 25 Jul 2024 15:23:35 +0800 Subject: [PATCH 2001/2194] coverage. Adapt to mcdc mapping formats introduced by llvm 19 --- compiler/rustc_codegen_llvm/src/builder.rs | 63 +---- .../src/coverageinfo/mod.rs | 29 +-- compiler/rustc_codegen_llvm/src/llvm/ffi.rs | 1 - compiler/rustc_middle/src/mir/coverage.rs | 29 +-- compiler/rustc_middle/src/mir/pretty.rs | 32 ++- .../rustc_mir_build/src/build/coverageinfo.rs | 6 +- .../src/build/coverageinfo/mcdc.rs | 88 ++++--- .../src/coverage/mappings.rs | 235 +++++++++++++----- .../rustc_mir_transform/src/coverage/mod.rs | 154 ++++++++---- tests/coverage/mcdc/condition-limit.cov-map | 96 +------ tests/coverage/mcdc/condition-limit.coverage | 68 ++--- tests/coverage/mcdc/condition-limit.rs | 22 +- tests/coverage/mcdc/if.cov-map | 30 +-- tests/coverage/mcdc/if.coverage | 16 +- tests/coverage/mcdc/if.rs | 2 +- .../coverage/mcdc/inlined_expressions.cov-map | 4 +- tests/coverage/mcdc/nested_if.cov-map | 26 +- tests/coverage/mcdc/nested_if.coverage | 24 +- tests/coverage/mcdc/non_control_flow.cov-map | 24 +- tests/coverage/mcdc/non_control_flow.coverage | 8 +- .../mcdc-condition-limit.bad.stderr | 8 - .../mcdc-condition-limit.rs | 16 +- 22 files changed, 493 insertions(+), 488 deletions(-) delete mode 100644 tests/ui/instrument-coverage/mcdc-condition-limit.bad.stderr diff --git a/compiler/rustc_codegen_llvm/src/builder.rs b/compiler/rustc_codegen_llvm/src/builder.rs index 3abebdf6ca1cf..30d7ba4421bff 100644 --- a/compiler/rustc_codegen_llvm/src/builder.rs +++ b/compiler/rustc_codegen_llvm/src/builder.rs @@ -1679,9 +1679,9 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> { &mut self, fn_name: &'ll Value, hash: &'ll Value, - bitmap_bytes: &'ll Value, + bitmap_bits: &'ll Value, ) { - debug!("mcdc_parameters() with args ({:?}, {:?}, {:?})", fn_name, hash, bitmap_bytes); + debug!("mcdc_parameters() with args ({:?}, {:?}, {:?})", fn_name, hash, bitmap_bits); assert!( crate::llvm_util::get_version() >= (19, 0, 0), @@ -1693,7 +1693,7 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> { &[self.cx.type_ptr(), self.cx.type_i64(), self.cx.type_i32()], self.cx.type_void(), ); - let args = &[fn_name, hash, bitmap_bytes]; + let args = &[fn_name, hash, bitmap_bits]; let args = self.check_call("call", llty, llfn, args); unsafe { @@ -1713,13 +1713,12 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> { &mut self, fn_name: &'ll Value, hash: &'ll Value, - bitmap_bytes: &'ll Value, bitmap_index: &'ll Value, mcdc_temp: &'ll Value, ) { debug!( - "mcdc_tvbitmap_update() with args ({:?}, {:?}, {:?}, {:?}, {:?})", - fn_name, hash, bitmap_bytes, bitmap_index, mcdc_temp + "mcdc_tvbitmap_update() with args ({:?}, {:?}, {:?}, {:?})", + fn_name, hash, bitmap_index, mcdc_temp ); assert!( crate::llvm_util::get_version() >= (19, 0, 0), @@ -1729,16 +1728,10 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> { let llfn = unsafe { llvm::LLVMRustGetInstrProfMCDCTVBitmapUpdateIntrinsic(self.cx().llmod) }; let llty = self.cx.type_func( - &[ - self.cx.type_ptr(), - self.cx.type_i64(), - self.cx.type_i32(), - self.cx.type_i32(), - self.cx.type_ptr(), - ], + &[self.cx.type_ptr(), self.cx.type_i64(), self.cx.type_i32(), self.cx.type_ptr()], self.cx.type_void(), ); - let args = &[fn_name, hash, bitmap_bytes, bitmap_index, mcdc_temp]; + let args = &[fn_name, hash, bitmap_index, mcdc_temp]; let args = self.check_call("call", llty, llfn, args); unsafe { let _ = llvm::LLVMRustBuildCall( @@ -1754,45 +1747,15 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> { self.store(self.const_i32(0), mcdc_temp, self.tcx.data_layout.i32_align.abi); } - pub(crate) fn mcdc_condbitmap_update( - &mut self, - fn_name: &'ll Value, - hash: &'ll Value, - cond_loc: &'ll Value, - mcdc_temp: &'ll Value, - bool_value: &'ll Value, - ) { - debug!( - "mcdc_condbitmap_update() with args ({:?}, {:?}, {:?}, {:?}, {:?})", - fn_name, hash, cond_loc, mcdc_temp, bool_value - ); + pub(crate) fn mcdc_condbitmap_update(&mut self, cond_index: &'ll Value, mcdc_temp: &'ll Value) { + debug!("mcdc_condbitmap_update() with args ({:?}, {:?})", cond_index, mcdc_temp); assert!( crate::llvm_util::get_version() >= (19, 0, 0), "MCDC intrinsics require LLVM 19 or later" ); - let llfn = unsafe { llvm::LLVMRustGetInstrProfMCDCCondBitmapIntrinsic(self.cx().llmod) }; - let llty = self.cx.type_func( - &[ - self.cx.type_ptr(), - self.cx.type_i64(), - self.cx.type_i32(), - self.cx.type_ptr(), - self.cx.type_i1(), - ], - self.cx.type_void(), - ); - let args = &[fn_name, hash, cond_loc, mcdc_temp, bool_value]; - self.check_call("call", llty, llfn, args); - unsafe { - let _ = llvm::LLVMRustBuildCall( - self.llbuilder, - llty, - llfn, - args.as_ptr() as *const &llvm::Value, - args.len() as c_uint, - [].as_ptr(), - 0 as c_uint, - ); - } + let align = self.tcx.data_layout.i32_align.abi; + let current_tv_index = self.load(self.cx.type_i32(), mcdc_temp, align); + let new_tv_index = self.add(current_tv_index, cond_index); + self.store(new_tv_index, mcdc_temp, align); } } diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs index 3a80d216f47ee..d7d29eebf8593 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs @@ -98,14 +98,14 @@ impl<'tcx> CoverageInfoBuilderMethods<'tcx> for Builder<'_, '_, 'tcx> { }; // If there are no MC/DC bitmaps to set up, return immediately. - if function_coverage_info.mcdc_bitmap_bytes == 0 { + if function_coverage_info.mcdc_bitmap_bits == 0 { return; } let fn_name = self.get_pgo_func_name_var(instance); let hash = self.const_u64(function_coverage_info.function_source_hash); - let bitmap_bytes = self.const_u32(function_coverage_info.mcdc_bitmap_bytes); - self.mcdc_parameters(fn_name, hash, bitmap_bytes); + let bitmap_bits = self.const_u32(function_coverage_info.mcdc_bitmap_bits as u32); + self.mcdc_parameters(fn_name, hash, bitmap_bits); // Create pointers named `mcdc.addr.{i}` to stack-allocated condition bitmaps. let mut cond_bitmaps = vec![]; @@ -185,35 +185,28 @@ impl<'tcx> CoverageInfoBuilderMethods<'tcx> for Builder<'_, '_, 'tcx> { CoverageKind::ExpressionUsed { id } => { func_coverage.mark_expression_id_seen(id); } - CoverageKind::CondBitmapUpdate { id, value, decision_depth } => { + CoverageKind::CondBitmapUpdate { index, decision_depth } => { drop(coverage_map); - assert_ne!( - id.as_u32(), - 0, - "ConditionId of evaluated conditions should never be zero" - ); let cond_bitmap = coverage_context .try_get_mcdc_condition_bitmap(&instance, decision_depth) .expect("mcdc cond bitmap should have been allocated for updating"); - let cond_loc = bx.const_i32(id.as_u32() as i32 - 1); - let bool_value = bx.const_bool(value); - let fn_name = bx.get_pgo_func_name_var(instance); - let hash = bx.const_u64(function_coverage_info.function_source_hash); - bx.mcdc_condbitmap_update(fn_name, hash, cond_loc, cond_bitmap, bool_value); + let cond_index = bx.const_i32(index as i32); + bx.mcdc_condbitmap_update(cond_index, cond_bitmap); } CoverageKind::TestVectorBitmapUpdate { bitmap_idx, decision_depth } => { drop(coverage_map); let cond_bitmap = coverage_context .try_get_mcdc_condition_bitmap(&instance, decision_depth) .expect("mcdc cond bitmap should have been allocated for merging into the global bitmap"); - let bitmap_bytes = function_coverage_info.mcdc_bitmap_bytes; - assert!(bitmap_idx < bitmap_bytes, "bitmap index of the decision out of range"); + assert!( + bitmap_idx as usize <= function_coverage_info.mcdc_bitmap_bits, + "bitmap index of the decision out of range" + ); let fn_name = bx.get_pgo_func_name_var(instance); let hash = bx.const_u64(function_coverage_info.function_source_hash); - let bitmap_bytes = bx.const_u32(bitmap_bytes); let bitmap_index = bx.const_u32(bitmap_idx); - bx.mcdc_tvbitmap_update(fn_name, hash, bitmap_bytes, bitmap_index, cond_bitmap); + bx.mcdc_tvbitmap_update(fn_name, hash, bitmap_index, cond_bitmap); } } } diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs index d3950df91fbd0..661debbb9f126 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs @@ -1614,7 +1614,6 @@ unsafe extern "C" { pub fn LLVMRustGetInstrProfIncrementIntrinsic(M: &Module) -> &Value; pub fn LLVMRustGetInstrProfMCDCParametersIntrinsic(M: &Module) -> &Value; pub fn LLVMRustGetInstrProfMCDCTVBitmapUpdateIntrinsic(M: &Module) -> &Value; - pub fn LLVMRustGetInstrProfMCDCCondBitmapIntrinsic(M: &Module) -> &Value; pub fn LLVMRustBuildCall<'a>( B: &Builder<'a>, diff --git a/compiler/rustc_middle/src/mir/coverage.rs b/compiler/rustc_middle/src/mir/coverage.rs index 9a0f5a653214f..4a876dc1228e5 100644 --- a/compiler/rustc_middle/src/mir/coverage.rs +++ b/compiler/rustc_middle/src/mir/coverage.rs @@ -128,8 +128,8 @@ pub enum CoverageKind { /// Marks the point in MIR control flow represented by a evaluated condition. /// - /// This is eventually lowered to `llvm.instrprof.mcdc.condbitmap.update` in LLVM IR. - CondBitmapUpdate { id: ConditionId, value: bool, decision_depth: u16 }, + /// This is eventually lowered to instruments updating mcdc temp variables. + CondBitmapUpdate { index: u32, decision_depth: u16 }, /// Marks the point in MIR control flow represented by a evaluated decision. /// @@ -145,14 +145,8 @@ impl Debug for CoverageKind { BlockMarker { id } => write!(fmt, "BlockMarker({:?})", id.index()), CounterIncrement { id } => write!(fmt, "CounterIncrement({:?})", id.index()), ExpressionUsed { id } => write!(fmt, "ExpressionUsed({:?})", id.index()), - CondBitmapUpdate { id, value, decision_depth } => { - write!( - fmt, - "CondBitmapUpdate({:?}, {:?}, depth={:?})", - id.index(), - value, - decision_depth - ) + CondBitmapUpdate { index, decision_depth } => { + write!(fmt, "CondBitmapUpdate(index={:?}, depth={:?})", index, decision_depth) } TestVectorBitmapUpdate { bitmap_idx, decision_depth } => { write!(fmt, "TestVectorUpdate({:?}, depth={:?})", bitmap_idx, decision_depth) @@ -253,7 +247,7 @@ pub struct Mapping { pub struct FunctionCoverageInfo { pub function_source_hash: u64, pub num_counters: usize, - pub mcdc_bitmap_bytes: u32, + pub mcdc_bitmap_bits: usize, pub expressions: IndexVec, pub mappings: Vec, /// The depth of the deepest decision is used to know how many @@ -275,8 +269,10 @@ pub struct CoverageInfoHi { /// data structures without having to scan the entire body first. pub num_block_markers: usize, pub branch_spans: Vec, - pub mcdc_branch_spans: Vec, - pub mcdc_decision_spans: Vec, + /// Branch spans generated by mcdc. Because of some limits mcdc builder give up generating + /// decisions including them so that they are handled as normal branch spans. + pub mcdc_degraded_branch_spans: Vec, + pub mcdc_spans: Vec<(MCDCDecisionSpan, Vec)>, } #[derive(Clone, Debug)] @@ -299,12 +295,9 @@ pub struct ConditionInfo { #[derive(TyEncodable, TyDecodable, Hash, HashStable, TypeFoldable, TypeVisitable)] pub struct MCDCBranchSpan { pub span: Span, - /// If `None`, this actually represents a normal branch span inserted for - /// code that was too complex for MC/DC. - pub condition_info: Option, + pub condition_info: ConditionInfo, pub true_marker: BlockMarkerId, pub false_marker: BlockMarkerId, - pub decision_depth: u16, } #[derive(Copy, Clone, Debug)] @@ -318,7 +311,7 @@ pub struct DecisionInfo { #[derive(TyEncodable, TyDecodable, Hash, HashStable, TypeFoldable, TypeVisitable)] pub struct MCDCDecisionSpan { pub span: Span, - pub num_conditions: usize, pub end_markers: Vec, pub decision_depth: u16, + pub num_conditions: usize, } diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs index 9cafe804a8ee9..2a3a070a6e715 100644 --- a/compiler/rustc_middle/src/mir/pretty.rs +++ b/compiler/rustc_middle/src/mir/pretty.rs @@ -538,8 +538,8 @@ fn write_coverage_info_hi( let coverage::CoverageInfoHi { num_block_markers: _, branch_spans, - mcdc_branch_spans, - mcdc_decision_spans, + mcdc_degraded_branch_spans, + mcdc_spans, } = coverage_info_hi; // Only add an extra trailing newline if we printed at least one thing. @@ -553,29 +553,35 @@ fn write_coverage_info_hi( did_print = true; } - for coverage::MCDCBranchSpan { - span, - condition_info, - true_marker, - false_marker, - decision_depth, - } in mcdc_branch_spans + for coverage::MCDCBranchSpan { span, true_marker, false_marker, .. } in + mcdc_degraded_branch_spans { writeln!( w, - "{INDENT}coverage mcdc branch {{ condition_id: {:?}, true: {true_marker:?}, false: {false_marker:?}, depth: {decision_depth:?} }} => {span:?}", - condition_info.map(|info| info.condition_id) + "{INDENT}coverage branch {{ true: {true_marker:?}, false: {false_marker:?} }} => {span:?}", )?; did_print = true; } - for coverage::MCDCDecisionSpan { span, num_conditions, end_markers, decision_depth } in - mcdc_decision_spans + for ( + coverage::MCDCDecisionSpan { span, end_markers, decision_depth, num_conditions: _ }, + conditions, + ) in mcdc_spans { + let num_conditions = conditions.len(); writeln!( w, "{INDENT}coverage mcdc decision {{ num_conditions: {num_conditions:?}, end: {end_markers:?}, depth: {decision_depth:?} }} => {span:?}" )?; + for coverage::MCDCBranchSpan { span, condition_info, true_marker, false_marker } in + conditions + { + writeln!( + w, + "{INDENT}coverage mcdc branch {{ condition_id: {:?}, true: {true_marker:?}, false: {false_marker:?} }} => {span:?}", + condition_info.condition_id + )?; + } did_print = true; } diff --git a/compiler/rustc_mir_build/src/build/coverageinfo.rs b/compiler/rustc_mir_build/src/build/coverageinfo.rs index 204ee45bfa2d7..52a4a4b4b510d 100644 --- a/compiler/rustc_mir_build/src/build/coverageinfo.rs +++ b/compiler/rustc_mir_build/src/build/coverageinfo.rs @@ -175,7 +175,7 @@ impl CoverageInfoBuilder { let branch_spans = branch_info.map(|branch_info| branch_info.branch_spans).unwrap_or_default(); - let (mcdc_decision_spans, mcdc_branch_spans) = + let (mcdc_spans, mcdc_degraded_branch_spans) = mcdc_info.map(MCDCInfoBuilder::into_done).unwrap_or_default(); // For simplicity, always return an info struct (without Option), even @@ -183,8 +183,8 @@ impl CoverageInfoBuilder { Box::new(CoverageInfoHi { num_block_markers, branch_spans, - mcdc_branch_spans, - mcdc_decision_spans, + mcdc_degraded_branch_spans, + mcdc_spans, }) } } diff --git a/compiler/rustc_mir_build/src/build/coverageinfo/mcdc.rs b/compiler/rustc_mir_build/src/build/coverageinfo/mcdc.rs index 5c45a7a33a297..343d400004315 100644 --- a/compiler/rustc_mir_build/src/build/coverageinfo/mcdc.rs +++ b/compiler/rustc_mir_build/src/build/coverageinfo/mcdc.rs @@ -12,16 +12,16 @@ use rustc_span::Span; use crate::build::Builder; use crate::errors::MCDCExceedsConditionLimit; -/// The MCDC bitmap scales exponentially (2^n) based on the number of conditions seen, -/// So llvm sets a maximum value prevents the bitmap footprint from growing too large without the user's knowledge. -/// This limit may be relaxed if the [upstream change](https://github.com/llvm/llvm-project/pull/82448) is merged. -const MAX_CONDITIONS_IN_DECISION: usize = 6; +/// LLVM uses `i16` to represent condition id. Hence `i16::MAX` is the hard limit for number of +/// conditions in a decision. +const MAX_CONDITIONS_IN_DECISION: usize = i16::MAX as usize; #[derive(Default)] struct MCDCDecisionCtx { /// To construct condition evaluation tree. decision_stack: VecDeque, processing_decision: Option, + conditions: Vec, } struct MCDCState { @@ -155,16 +155,29 @@ impl MCDCState { decision_ctx.decision_stack.push_back(lhs); } - fn take_condition( + fn try_finish_decision( &mut self, + span: Span, true_marker: BlockMarkerId, false_marker: BlockMarkerId, - ) -> (Option, Option) { + degraded_branches: &mut Vec, + ) -> Option<(MCDCDecisionSpan, Vec)> { let Some(decision_ctx) = self.decision_ctx_stack.last_mut() else { bug!("Unexpected empty decision_ctx_stack") }; let Some(condition_info) = decision_ctx.decision_stack.pop_back() else { - return (None, None); + let branch = MCDCBranchSpan { + span, + condition_info: ConditionInfo { + condition_id: ConditionId::START, + true_next_id: None, + false_next_id: None, + }, + true_marker, + false_marker, + }; + degraded_branches.push(branch); + return None; }; let Some(decision) = decision_ctx.processing_decision.as_mut() else { bug!("Processing decision should have been created before any conditions are taken"); @@ -175,24 +188,31 @@ impl MCDCState { if condition_info.false_next_id.is_none() { decision.end_markers.push(false_marker); } + decision_ctx.conditions.push(MCDCBranchSpan { + span, + condition_info, + true_marker, + false_marker, + }); if decision_ctx.decision_stack.is_empty() { - (Some(condition_info), decision_ctx.processing_decision.take()) + let conditions = std::mem::take(&mut decision_ctx.conditions); + decision_ctx.processing_decision.take().map(|decision| (decision, conditions)) } else { - (Some(condition_info), None) + None } } } pub(crate) struct MCDCInfoBuilder { - branch_spans: Vec, - decision_spans: Vec, + degraded_spans: Vec, + mcdc_spans: Vec<(MCDCDecisionSpan, Vec)>, state: MCDCState, } impl MCDCInfoBuilder { pub(crate) fn new() -> Self { - Self { branch_spans: vec![], decision_spans: vec![], state: MCDCState::new() } + Self { degraded_spans: vec![], mcdc_spans: vec![], state: MCDCState::new() } } pub(crate) fn visit_evaluated_condition( @@ -206,50 +226,44 @@ impl MCDCInfoBuilder { let true_marker = inject_block_marker(source_info, true_block); let false_marker = inject_block_marker(source_info, false_block); - let decision_depth = self.state.decision_depth(); - let (mut condition_info, decision_result) = - self.state.take_condition(true_marker, false_marker); // take_condition() returns Some for decision_result when the decision stack // is empty, i.e. when all the conditions of the decision were instrumented, // and the decision is "complete". - if let Some(decision) = decision_result { - match decision.num_conditions { + if let Some((decision, conditions)) = self.state.try_finish_decision( + source_info.span, + true_marker, + false_marker, + &mut self.degraded_spans, + ) { + let num_conditions = conditions.len(); + assert_eq!( + num_conditions, decision.num_conditions, + "final number of conditions is not correct" + ); + match num_conditions { 0 => { unreachable!("Decision with no condition is not expected"); } 1..=MAX_CONDITIONS_IN_DECISION => { - self.decision_spans.push(decision); + self.mcdc_spans.push((decision, conditions)); } _ => { - // Do not generate mcdc mappings and statements for decisions with too many conditions. - // Therefore, first erase the condition info of the (N-1) previous branch spans. - let rebase_idx = self.branch_spans.len() - (decision.num_conditions - 1); - for branch in &mut self.branch_spans[rebase_idx..] { - branch.condition_info = None; - } - - // Then, erase this last branch span's info too, for a total of N. - condition_info = None; + self.degraded_spans.extend(conditions); tcx.dcx().emit_warn(MCDCExceedsConditionLimit { span: decision.span, - num_conditions: decision.num_conditions, + num_conditions, max_conditions: MAX_CONDITIONS_IN_DECISION, }); } } } - self.branch_spans.push(MCDCBranchSpan { - span: source_info.span, - condition_info, - true_marker, - false_marker, - decision_depth, - }); } - pub(crate) fn into_done(self) -> (Vec, Vec) { - (self.decision_spans, self.branch_spans) + pub(crate) fn into_done( + self, + ) -> (Vec<(MCDCDecisionSpan, Vec)>, Vec) { + (self.mcdc_spans, self.degraded_spans) } } diff --git a/compiler/rustc_mir_transform/src/coverage/mappings.rs b/compiler/rustc_mir_transform/src/coverage/mappings.rs index ec5ba354805f1..c20f7a6f3263c 100644 --- a/compiler/rustc_mir_transform/src/coverage/mappings.rs +++ b/compiler/rustc_mir_transform/src/coverage/mappings.rs @@ -1,10 +1,11 @@ use std::collections::BTreeSet; +use rustc_data_structures::fx::FxIndexMap; use rustc_data_structures::graph::DirectedGraph; use rustc_index::IndexVec; use rustc_index::bit_set::BitSet; use rustc_middle::mir::coverage::{ - BlockMarkerId, BranchSpan, ConditionInfo, CoverageInfoHi, CoverageKind, + BlockMarkerId, BranchSpan, ConditionId, ConditionInfo, CoverageInfoHi, CoverageKind, }; use rustc_middle::mir::{self, BasicBlock, StatementKind}; use rustc_middle::ty::TyCtxt; @@ -38,10 +39,11 @@ pub(super) struct MCDCBranch { pub(super) span: Span, pub(super) true_bcb: BasicCoverageBlock, pub(super) false_bcb: BasicCoverageBlock, - /// If `None`, this actually represents a normal branch mapping inserted - /// for code that was too complex for MC/DC. - pub(super) condition_info: Option, - pub(super) decision_depth: u16, + pub(super) condition_info: ConditionInfo, + // Offset added to test vector idx if this branch is evaluated to true. + pub(super) true_index: usize, + // Offset added to test vector idx if this branch is evaluated to false. + pub(super) false_index: usize, } /// Associates an MC/DC decision with its join BCBs. @@ -49,11 +51,15 @@ pub(super) struct MCDCBranch { pub(super) struct MCDCDecision { pub(super) span: Span, pub(super) end_bcbs: BTreeSet, - pub(super) bitmap_idx: u32, - pub(super) num_conditions: u16, + pub(super) bitmap_idx: usize, + pub(super) num_test_vectors: usize, pub(super) decision_depth: u16, } +// LLVM uses `i32` to index the bitmap. Thus `i32::MAX` is the hard limit for number of all test vectors +// in a function. +const MCDC_MAX_BITMAP_SIZE: usize = i32::MAX as usize; + #[derive(Default)] pub(super) struct ExtractedMappings { /// Store our own copy of [`CoverageGraph::num_nodes`], so that we don't @@ -62,9 +68,9 @@ pub(super) struct ExtractedMappings { pub(super) num_bcbs: usize, pub(super) code_mappings: Vec, pub(super) branch_pairs: Vec, - pub(super) mcdc_bitmap_bytes: u32, - pub(super) mcdc_branches: Vec, - pub(super) mcdc_decisions: Vec, + pub(super) mcdc_bitmap_bits: usize, + pub(super) mcdc_degraded_branches: Vec, + pub(super) mcdc_mappings: Vec<(MCDCDecision, Vec)>, } /// Extracts coverage-relevant spans from MIR, and associates them with @@ -77,9 +83,9 @@ pub(super) fn extract_all_mapping_info_from_mir<'tcx>( ) -> ExtractedMappings { let mut code_mappings = vec![]; let mut branch_pairs = vec![]; - let mut mcdc_bitmap_bytes = 0; - let mut mcdc_branches = vec![]; - let mut mcdc_decisions = vec![]; + let mut mcdc_bitmap_bits = 0; + let mut mcdc_degraded_branches = vec![]; + let mut mcdc_mappings = vec![]; if hir_info.is_async_fn || tcx.sess.coverage_no_mir_spans() { // An async function desugars into a function that returns a future, @@ -104,18 +110,18 @@ pub(super) fn extract_all_mapping_info_from_mir<'tcx>( mir_body, hir_info.body_span, basic_coverage_blocks, - &mut mcdc_bitmap_bytes, - &mut mcdc_branches, - &mut mcdc_decisions, + &mut mcdc_bitmap_bits, + &mut mcdc_degraded_branches, + &mut mcdc_mappings, ); ExtractedMappings { num_bcbs: basic_coverage_blocks.num_nodes(), code_mappings, branch_pairs, - mcdc_bitmap_bytes, - mcdc_branches, - mcdc_decisions, + mcdc_bitmap_bits, + mcdc_degraded_branches, + mcdc_mappings, } } @@ -126,9 +132,9 @@ impl ExtractedMappings { num_bcbs, code_mappings, branch_pairs, - mcdc_bitmap_bytes: _, - mcdc_branches, - mcdc_decisions, + mcdc_bitmap_bits: _, + mcdc_degraded_branches, + mcdc_mappings, } = self; // Identify which BCBs have one or more mappings. @@ -144,7 +150,10 @@ impl ExtractedMappings { insert(true_bcb); insert(false_bcb); } - for &MCDCBranch { true_bcb, false_bcb, .. } in mcdc_branches { + for &MCDCBranch { true_bcb, false_bcb, .. } in mcdc_degraded_branches + .iter() + .chain(mcdc_mappings.iter().map(|(_, branches)| branches.into_iter()).flatten()) + { insert(true_bcb); insert(false_bcb); } @@ -152,8 +161,8 @@ impl ExtractedMappings { // MC/DC decisions refer to BCBs, but don't require those BCBs to have counters. if bcbs_with_counter_mappings.is_empty() { debug_assert!( - mcdc_decisions.is_empty(), - "A function with no counter mappings shouldn't have any decisions: {mcdc_decisions:?}", + mcdc_mappings.is_empty(), + "A function with no counter mappings shouldn't have any decisions: {mcdc_mappings:?}", ); } @@ -232,9 +241,9 @@ pub(super) fn extract_mcdc_mappings( mir_body: &mir::Body<'_>, body_span: Span, basic_coverage_blocks: &CoverageGraph, - mcdc_bitmap_bytes: &mut u32, - mcdc_branches: &mut impl Extend, - mcdc_decisions: &mut impl Extend, + mcdc_bitmap_bits: &mut usize, + mcdc_degraded_branches: &mut impl Extend, + mcdc_mappings: &mut impl Extend<(MCDCDecision, Vec)>, ) { let Some(coverage_info_hi) = mir_body.coverage_info_hi.as_deref() else { return }; @@ -257,43 +266,143 @@ pub(super) fn extract_mcdc_mappings( Some((span, true_bcb, false_bcb)) }; - mcdc_branches.extend(coverage_info_hi.mcdc_branch_spans.iter().filter_map( - |&mir::coverage::MCDCBranchSpan { - span: raw_span, - condition_info, - true_marker, - false_marker, - decision_depth, - }| { - let (span, true_bcb, false_bcb) = - check_branch_bcb(raw_span, true_marker, false_marker)?; - Some(MCDCBranch { span, true_bcb, false_bcb, condition_info, decision_depth }) - }, - )); - - mcdc_decisions.extend(coverage_info_hi.mcdc_decision_spans.iter().filter_map( - |decision: &mir::coverage::MCDCDecisionSpan| { - let span = unexpand_into_body_span(decision.span, body_span)?; - - let end_bcbs = decision - .end_markers - .iter() - .map(|&marker| bcb_from_marker(marker)) - .collect::>()?; - - // Each decision containing N conditions needs 2^N bits of space in - // the bitmap, rounded up to a whole number of bytes. - // The decision's "bitmap index" points to its first byte in the bitmap. - let bitmap_idx = *mcdc_bitmap_bytes; - *mcdc_bitmap_bytes += (1_u32 << decision.num_conditions).div_ceil(8); - - Some(MCDCDecision { + let to_mcdc_branch = |&mir::coverage::MCDCBranchSpan { + span: raw_span, + condition_info, + true_marker, + false_marker, + }| { + let (span, true_bcb, false_bcb) = check_branch_bcb(raw_span, true_marker, false_marker)?; + Some(MCDCBranch { + span, + true_bcb, + false_bcb, + condition_info, + true_index: usize::MAX, + false_index: usize::MAX, + }) + }; + + let mut get_bitmap_idx = |num_test_vectors: usize| -> Option { + let bitmap_idx = *mcdc_bitmap_bits; + let next_bitmap_bits = bitmap_idx.saturating_add(num_test_vectors); + (next_bitmap_bits <= MCDC_MAX_BITMAP_SIZE).then(|| { + *mcdc_bitmap_bits = next_bitmap_bits; + bitmap_idx + }) + }; + mcdc_degraded_branches + .extend(coverage_info_hi.mcdc_degraded_branch_spans.iter().filter_map(to_mcdc_branch)); + + mcdc_mappings.extend(coverage_info_hi.mcdc_spans.iter().filter_map(|(decision, branches)| { + if branches.len() == 0 { + return None; + } + let decision_span = unexpand_into_body_span(decision.span, body_span)?; + + let end_bcbs = decision + .end_markers + .iter() + .map(|&marker| bcb_from_marker(marker)) + .collect::>()?; + let mut branch_mappings: Vec<_> = branches.into_iter().filter_map(to_mcdc_branch).collect(); + if branch_mappings.len() != branches.len() { + mcdc_degraded_branches.extend(branch_mappings); + return None; + } + let num_test_vectors = calc_test_vectors_index(&mut branch_mappings); + let Some(bitmap_idx) = get_bitmap_idx(num_test_vectors) else { + // TODO warn about bitmap + mcdc_degraded_branches.extend(branch_mappings); + return None; + }; + // LLVM requires span of the decision contains all spans of its conditions. + // Usually the decision span meets the requirement well but in cases like macros it may not. + let span = branch_mappings + .iter() + .map(|branch| branch.span) + .reduce(|lhs, rhs| lhs.to(rhs)) + .map( + |joint_span| { + if decision_span.contains(joint_span) { decision_span } else { joint_span } + }, + ) + .expect("branch mappings are ensured to be non-empty as checked above"); + Some(( + MCDCDecision { span, end_bcbs, bitmap_idx, - num_conditions: decision.num_conditions as u16, + num_test_vectors, decision_depth: decision.decision_depth, - }) - }, - )); + }, + branch_mappings, + )) + })); +} + +// LLVM checks the executed test vector by accumulating indices of tested branches. +// We calculate number of all possible test vectors of the decision and assign indices +// to branches here. +// See [the rfc](https://discourse.llvm.org/t/rfc-coverage-new-algorithm-and-file-format-for-mc-dc/76798/) +// for more details about the algorithm. +// This function is mostly like [`TVIdxBuilder::TvIdxBuilder`](https://github.com/llvm/llvm-project/blob/d594d9f7f4dc6eb748b3261917db689fdc348b96/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp#L226) +fn calc_test_vectors_index(conditions: &mut Vec) -> usize { + let mut indegree_stats = IndexVec::::from_elem_n(0, conditions.len()); + // `num_paths` is `width` described at the llvm rfc, which indicates how many paths reaching the condition node. + let mut num_paths_stats = IndexVec::::from_elem_n(0, conditions.len()); + let mut next_conditions = conditions + .iter_mut() + .map(|branch| { + let ConditionInfo { condition_id, true_next_id, false_next_id } = branch.condition_info; + [true_next_id, false_next_id] + .into_iter() + .filter_map(std::convert::identity) + .for_each(|next_id| indegree_stats[next_id] += 1); + (condition_id, branch) + }) + .collect::>(); + + let mut queue = std::collections::VecDeque::from_iter( + next_conditions.swap_remove(&ConditionId::START).into_iter(), + ); + num_paths_stats[ConditionId::START] = 1; + let mut decision_end_nodes = Vec::new(); + while let Some(branch) = queue.pop_front() { + let ConditionInfo { condition_id, true_next_id, false_next_id } = branch.condition_info; + let (false_index, true_index) = (&mut branch.false_index, &mut branch.true_index); + let this_paths_count = num_paths_stats[condition_id]; + // Note. First check the false next to ensure conditions are touched in same order with llvm-cov. + for (next, index) in [(false_next_id, false_index), (true_next_id, true_index)] { + if let Some(next_id) = next { + let next_paths_count = &mut num_paths_stats[next_id]; + *index = *next_paths_count; + *next_paths_count = next_paths_count.saturating_add(this_paths_count); + let next_indegree = &mut indegree_stats[next_id]; + *next_indegree -= 1; + if *next_indegree == 0 { + queue.push_back(next_conditions.swap_remove(&next_id).expect( + "conditions with non-zero indegree before must be in next_conditions", + )); + } + } else { + decision_end_nodes.push((this_paths_count, condition_id, index)); + } + } + } + assert!(next_conditions.is_empty(), "the decision tree has untouched nodes"); + let mut cur_idx = 0; + // LLVM hopes the end nodes are sorted in descending order by `num_paths` so that it can + // optimize bitmap size for decisions in tree form such as `a && b && c && d && ...`. + decision_end_nodes.sort_by_key(|(num_paths, _, _)| usize::MAX - *num_paths); + for (num_paths, condition_id, index) in decision_end_nodes { + assert_eq!( + num_paths, num_paths_stats[condition_id], + "end nodes should not be updated since they were visited" + ); + assert_eq!(*index, usize::MAX, "end nodes should not be assigned index before"); + *index = cur_idx; + cur_idx += num_paths; + } + cur_idx } diff --git a/compiler/rustc_mir_transform/src/coverage/mod.rs b/compiler/rustc_mir_transform/src/coverage/mod.rs index 79482ba39198e..d0f30314e79a9 100644 --- a/compiler/rustc_mir_transform/src/coverage/mod.rs +++ b/compiler/rustc_mir_transform/src/coverage/mod.rs @@ -114,16 +114,16 @@ fn instrument_function_for_coverage<'tcx>(tcx: TyCtxt<'tcx>, mir_body: &mut mir: inject_mcdc_statements(mir_body, &basic_coverage_blocks, &extracted_mappings); let mcdc_num_condition_bitmaps = extracted_mappings - .mcdc_decisions + .mcdc_mappings .iter() - .map(|&mappings::MCDCDecision { decision_depth, .. }| decision_depth) + .map(|&(mappings::MCDCDecision { decision_depth, .. }, _)| decision_depth) .max() .map_or(0, |max| usize::from(max) + 1); mir_body.function_coverage_info = Some(Box::new(FunctionCoverageInfo { function_source_hash: hir_info.function_source_hash, num_counters: coverage_counters.num_counters(), - mcdc_bitmap_bytes: extracted_mappings.mcdc_bitmap_bytes, + mcdc_bitmap_bits: extracted_mappings.mcdc_bitmap_bits, expressions: coverage_counters.into_expressions(), mappings, mcdc_num_condition_bitmaps, @@ -161,9 +161,9 @@ fn create_mappings<'tcx>( num_bcbs: _, code_mappings, branch_pairs, - mcdc_bitmap_bytes: _, - mcdc_branches, - mcdc_decisions, + mcdc_bitmap_bits: _, + mcdc_degraded_branches, + mcdc_mappings, } = extracted_mappings; let mut mappings = Vec::new(); @@ -186,26 +186,79 @@ fn create_mappings<'tcx>( }, )); - mappings.extend(mcdc_branches.iter().filter_map( - |&mappings::MCDCBranch { span, true_bcb, false_bcb, condition_info, decision_depth: _ }| { + let term_for_bcb = + |bcb| coverage_counters.term_for_bcb(bcb).expect("all BCBs with spans were given counters"); + + // MCDC branch mappings are appended with their decisions in case decisions were ignored. + mappings.extend(mcdc_degraded_branches.iter().filter_map( + |&mappings::MCDCBranch { + span, + true_bcb, + false_bcb, + condition_info: _, + true_index: _, + false_index: _, + }| { let source_region = region_for_span(span)?; let true_term = term_for_bcb(true_bcb); let false_term = term_for_bcb(false_bcb); - let kind = match condition_info { - Some(mcdc_params) => MappingKind::MCDCBranch { true_term, false_term, mcdc_params }, - None => MappingKind::Branch { true_term, false_term }, - }; - Some(Mapping { kind, source_region }) + Some(Mapping { kind: MappingKind::Branch { true_term, false_term }, source_region }) }, )); - mappings.extend(mcdc_decisions.iter().filter_map( - |&mappings::MCDCDecision { span, bitmap_idx, num_conditions, .. }| { - let source_region = region_for_span(span)?; - let kind = MappingKind::MCDCDecision(DecisionInfo { bitmap_idx, num_conditions }); - Some(Mapping { kind, source_region }) - }, - )); + for (decision, branches) in mcdc_mappings { + let num_conditions = branches.len() as u16; + let conditions = branches + .into_iter() + .filter_map( + |&mappings::MCDCBranch { + span, + true_bcb, + false_bcb, + condition_info, + true_index: _, + false_index: _, + }| { + let source_region = region_for_span(span)?; + let true_term = term_for_bcb(true_bcb); + let false_term = term_for_bcb(false_bcb); + Some(Mapping { + kind: MappingKind::MCDCBranch { + true_term, + false_term, + mcdc_params: condition_info, + }, + source_region, + }) + }, + ) + .collect::>(); + + if conditions.len() == num_conditions as usize + && let Some(source_region) = region_for_span(decision.span) + { + // LLVM requires end index for counter mapping regions. + let kind = MappingKind::MCDCDecision(DecisionInfo { + bitmap_idx: (decision.bitmap_idx + decision.num_test_vectors) as u32, + num_conditions, + }); + mappings.extend( + std::iter::once(Mapping { kind, source_region }).chain(conditions.into_iter()), + ); + } else { + mappings.extend(conditions.into_iter().map(|mapping| { + let MappingKind::MCDCBranch { true_term, false_term, mcdc_params: _ } = + mapping.kind + else { + unreachable!("all mappings here are MCDCBranch as shown above"); + }; + Mapping { + kind: MappingKind::Branch { true_term, false_term }, + source_region: mapping.source_region, + } + })) + } + } mappings } @@ -274,44 +327,41 @@ fn inject_mcdc_statements<'tcx>( basic_coverage_blocks: &CoverageGraph, extracted_mappings: &ExtractedMappings, ) { - // Inject test vector update first because `inject_statement` always insert new statement at - // head. - for &mappings::MCDCDecision { - span: _, - ref end_bcbs, - bitmap_idx, - num_conditions: _, - decision_depth, - } in &extracted_mappings.mcdc_decisions - { - for end in end_bcbs { - let end_bb = basic_coverage_blocks[*end].leader_bb(); + for (decision, conditions) in &extracted_mappings.mcdc_mappings { + // Inject test vector update first because `inject_statement` always insert new statement at head. + for &end in &decision.end_bcbs { + let end_bb = basic_coverage_blocks[end].leader_bb(); inject_statement( mir_body, - CoverageKind::TestVectorBitmapUpdate { bitmap_idx, decision_depth }, + CoverageKind::TestVectorBitmapUpdate { + bitmap_idx: decision.bitmap_idx as u32, + decision_depth: decision.decision_depth, + }, end_bb, ); } - } - - for &mappings::MCDCBranch { span: _, true_bcb, false_bcb, condition_info, decision_depth } in - &extracted_mappings.mcdc_branches - { - let Some(condition_info) = condition_info else { continue }; - let id = condition_info.condition_id; - let true_bb = basic_coverage_blocks[true_bcb].leader_bb(); - inject_statement( - mir_body, - CoverageKind::CondBitmapUpdate { id, value: true, decision_depth }, - true_bb, - ); - let false_bb = basic_coverage_blocks[false_bcb].leader_bb(); - inject_statement( - mir_body, - CoverageKind::CondBitmapUpdate { id, value: false, decision_depth }, - false_bb, - ); + for &mappings::MCDCBranch { + span: _, + true_bcb, + false_bcb, + condition_info: _, + true_index, + false_index, + } in conditions + { + for (index, bcb) in [(false_index, false_bcb), (true_index, true_bcb)] { + let bb = basic_coverage_blocks[bcb].leader_bb(); + inject_statement( + mir_body, + CoverageKind::CondBitmapUpdate { + index: index as u32, + decision_depth: decision.decision_depth, + }, + bb, + ); + } + } } } diff --git a/tests/coverage/mcdc/condition-limit.cov-map b/tests/coverage/mcdc/condition-limit.cov-map index b4447a33691ad..9d1e7518f9ea4 100644 --- a/tests/coverage/mcdc/condition-limit.cov-map +++ b/tests/coverage/mcdc/condition-limit.cov-map @@ -1,5 +1,5 @@ -Function name: condition_limit::bad -Raw bytes (204): 0x[01, 01, 2c, 01, 05, 05, 1d, 05, 1d, 7a, 19, 05, 1d, 7a, 19, 05, 1d, 76, 15, 7a, 19, 05, 1d, 76, 15, 7a, 19, 05, 1d, 72, 11, 76, 15, 7a, 19, 05, 1d, 72, 11, 76, 15, 7a, 19, 05, 1d, 6e, 0d, 72, 11, 76, 15, 7a, 19, 05, 1d, 6e, 0d, 72, 11, 76, 15, 7a, 19, 05, 1d, 9f, 01, 02, a3, 01, 1d, a7, 01, 19, ab, 01, 15, af, 01, 11, 09, 0d, 21, 9b, 01, 9f, 01, 02, a3, 01, 1d, a7, 01, 19, ab, 01, 15, af, 01, 11, 09, 0d, 11, 01, 14, 01, 03, 09, 20, 05, 02, 03, 08, 00, 09, 05, 00, 0d, 00, 0e, 20, 7a, 1d, 00, 0d, 00, 0e, 7a, 00, 12, 00, 13, 20, 76, 19, 00, 12, 00, 13, 76, 00, 17, 00, 18, 20, 72, 15, 00, 17, 00, 18, 72, 00, 1c, 00, 1d, 20, 6e, 11, 00, 1c, 00, 1d, 6e, 00, 21, 00, 22, 20, 6a, 0d, 00, 21, 00, 22, 6a, 00, 26, 00, 27, 20, 21, 09, 00, 26, 00, 27, 21, 00, 28, 02, 06, 9b, 01, 02, 06, 00, 07, 97, 01, 01, 01, 00, 02] +Function name: condition_limit::accept_7_conditions +Raw bytes (232): 0x[01, 01, 2c, 01, 05, 05, 1d, 05, 1d, 7a, 19, 05, 1d, 7a, 19, 05, 1d, 76, 15, 7a, 19, 05, 1d, 76, 15, 7a, 19, 05, 1d, 72, 11, 76, 15, 7a, 19, 05, 1d, 72, 11, 76, 15, 7a, 19, 05, 1d, 6e, 0d, 72, 11, 76, 15, 7a, 19, 05, 1d, 6e, 0d, 72, 11, 76, 15, 7a, 19, 05, 1d, 9f, 01, 02, a3, 01, 1d, a7, 01, 19, ab, 01, 15, af, 01, 11, 09, 0d, 21, 9b, 01, 9f, 01, 02, a3, 01, 1d, a7, 01, 19, ab, 01, 15, af, 01, 11, 09, 0d, 12, 01, 07, 01, 02, 09, 28, 08, 07, 02, 08, 00, 27, 30, 05, 02, 01, 07, 00, 00, 08, 00, 09, 05, 00, 0d, 00, 0e, 30, 7a, 1d, 07, 06, 00, 00, 0d, 00, 0e, 7a, 00, 12, 00, 13, 30, 76, 19, 06, 05, 00, 00, 12, 00, 13, 76, 00, 17, 00, 18, 30, 72, 15, 05, 04, 00, 00, 17, 00, 18, 72, 00, 1c, 00, 1d, 30, 6e, 11, 04, 03, 00, 00, 1c, 00, 1d, 6e, 00, 21, 00, 22, 30, 6a, 0d, 03, 02, 00, 00, 21, 00, 22, 6a, 00, 26, 00, 27, 30, 21, 09, 02, 00, 00, 00, 26, 00, 27, 21, 00, 28, 02, 06, 9b, 01, 02, 06, 00, 07, 97, 01, 01, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 44 @@ -47,38 +47,39 @@ Number of expressions: 44 - expression 41 operands: lhs = Expression(42, Add), rhs = Counter(5) - expression 42 operands: lhs = Expression(43, Add), rhs = Counter(4) - expression 43 operands: lhs = Counter(2), rhs = Counter(3) -Number of file 0 mappings: 17 -- Code(Counter(0)) at (prev + 20, 1) to (start + 3, 9) -- Branch { true: Counter(1), false: Expression(0, Sub) } at (prev + 3, 8) to (start + 0, 9) +Number of file 0 mappings: 18 +- Code(Counter(0)) at (prev + 7, 1) to (start + 2, 9) +- MCDCDecision { bitmap_idx: 8, conditions_num: 7 } at (prev + 2, 8) to (start + 0, 39) +- MCDCBranch { true: Counter(1), false: Expression(0, Sub), condition_id: 1, true_next_id: 7, false_next_id: 0 } at (prev + 0, 8) to (start + 0, 9) true = c1 false = (c0 - c1) - Code(Counter(1)) at (prev + 0, 13) to (start + 0, 14) -- Branch { true: Expression(30, Sub), false: Counter(7) } at (prev + 0, 13) to (start + 0, 14) +- MCDCBranch { true: Expression(30, Sub), false: Counter(7), condition_id: 7, true_next_id: 6, false_next_id: 0 } at (prev + 0, 13) to (start + 0, 14) true = (c1 - c7) false = c7 - Code(Expression(30, Sub)) at (prev + 0, 18) to (start + 0, 19) = (c1 - c7) -- Branch { true: Expression(29, Sub), false: Counter(6) } at (prev + 0, 18) to (start + 0, 19) +- MCDCBranch { true: Expression(29, Sub), false: Counter(6), condition_id: 6, true_next_id: 5, false_next_id: 0 } at (prev + 0, 18) to (start + 0, 19) true = ((c1 - c7) - c6) false = c6 - Code(Expression(29, Sub)) at (prev + 0, 23) to (start + 0, 24) = ((c1 - c7) - c6) -- Branch { true: Expression(28, Sub), false: Counter(5) } at (prev + 0, 23) to (start + 0, 24) +- MCDCBranch { true: Expression(28, Sub), false: Counter(5), condition_id: 5, true_next_id: 4, false_next_id: 0 } at (prev + 0, 23) to (start + 0, 24) true = (((c1 - c7) - c6) - c5) false = c5 - Code(Expression(28, Sub)) at (prev + 0, 28) to (start + 0, 29) = (((c1 - c7) - c6) - c5) -- Branch { true: Expression(27, Sub), false: Counter(4) } at (prev + 0, 28) to (start + 0, 29) +- MCDCBranch { true: Expression(27, Sub), false: Counter(4), condition_id: 4, true_next_id: 3, false_next_id: 0 } at (prev + 0, 28) to (start + 0, 29) true = ((((c1 - c7) - c6) - c5) - c4) false = c4 - Code(Expression(27, Sub)) at (prev + 0, 33) to (start + 0, 34) = ((((c1 - c7) - c6) - c5) - c4) -- Branch { true: Expression(26, Sub), false: Counter(3) } at (prev + 0, 33) to (start + 0, 34) +- MCDCBranch { true: Expression(26, Sub), false: Counter(3), condition_id: 3, true_next_id: 2, false_next_id: 0 } at (prev + 0, 33) to (start + 0, 34) true = (((((c1 - c7) - c6) - c5) - c4) - c3) false = c3 - Code(Expression(26, Sub)) at (prev + 0, 38) to (start + 0, 39) = (((((c1 - c7) - c6) - c5) - c4) - c3) -- Branch { true: Counter(8), false: Counter(2) } at (prev + 0, 38) to (start + 0, 39) +- MCDCBranch { true: Counter(8), false: Counter(2), condition_id: 2, true_next_id: 0, false_next_id: 0 } at (prev + 0, 38) to (start + 0, 39) true = c8 false = c2 - Code(Counter(8)) at (prev + 0, 40) to (start + 2, 6) @@ -87,76 +88,3 @@ Number of file 0 mappings: 17 - Code(Expression(37, Add)) at (prev + 1, 1) to (start + 0, 2) = (c8 + ((((((c2 + c3) + c4) + c5) + c6) + c7) + (c0 - c1))) -Function name: condition_limit::good -Raw bytes (180): 0x[01, 01, 20, 01, 05, 05, 19, 05, 19, 52, 15, 05, 19, 52, 15, 05, 19, 4e, 11, 52, 15, 05, 19, 4e, 11, 52, 15, 05, 19, 4a, 0d, 4e, 11, 52, 15, 05, 19, 4a, 0d, 4e, 11, 52, 15, 05, 19, 73, 02, 77, 19, 7b, 15, 7f, 11, 09, 0d, 1d, 6f, 73, 02, 77, 19, 7b, 15, 7f, 11, 09, 0d, 10, 01, 0c, 01, 03, 09, 28, 00, 06, 03, 08, 00, 22, 30, 05, 02, 01, 06, 00, 00, 08, 00, 09, 05, 00, 0d, 00, 0e, 30, 52, 19, 06, 05, 00, 00, 0d, 00, 0e, 52, 00, 12, 00, 13, 30, 4e, 15, 05, 04, 00, 00, 12, 00, 13, 4e, 00, 17, 00, 18, 30, 4a, 11, 04, 03, 00, 00, 17, 00, 18, 4a, 00, 1c, 00, 1d, 30, 46, 0d, 03, 02, 00, 00, 1c, 00, 1d, 46, 00, 21, 00, 22, 30, 1d, 09, 02, 00, 00, 00, 21, 00, 22, 1d, 00, 23, 02, 06, 6f, 02, 06, 00, 07, 6b, 01, 01, 00, 02] -Number of files: 1 -- file 0 => global file 1 -Number of expressions: 32 -- expression 0 operands: lhs = Counter(0), rhs = Counter(1) -- expression 1 operands: lhs = Counter(1), rhs = Counter(6) -- expression 2 operands: lhs = Counter(1), rhs = Counter(6) -- expression 3 operands: lhs = Expression(20, Sub), rhs = Counter(5) -- expression 4 operands: lhs = Counter(1), rhs = Counter(6) -- expression 5 operands: lhs = Expression(20, Sub), rhs = Counter(5) -- expression 6 operands: lhs = Counter(1), rhs = Counter(6) -- expression 7 operands: lhs = Expression(19, Sub), rhs = Counter(4) -- expression 8 operands: lhs = Expression(20, Sub), rhs = Counter(5) -- expression 9 operands: lhs = Counter(1), rhs = Counter(6) -- expression 10 operands: lhs = Expression(19, Sub), rhs = Counter(4) -- expression 11 operands: lhs = Expression(20, Sub), rhs = Counter(5) -- expression 12 operands: lhs = Counter(1), rhs = Counter(6) -- expression 13 operands: lhs = Expression(18, Sub), rhs = Counter(3) -- expression 14 operands: lhs = Expression(19, Sub), rhs = Counter(4) -- expression 15 operands: lhs = Expression(20, Sub), rhs = Counter(5) -- expression 16 operands: lhs = Counter(1), rhs = Counter(6) -- expression 17 operands: lhs = Expression(18, Sub), rhs = Counter(3) -- expression 18 operands: lhs = Expression(19, Sub), rhs = Counter(4) -- expression 19 operands: lhs = Expression(20, Sub), rhs = Counter(5) -- expression 20 operands: lhs = Counter(1), rhs = Counter(6) -- expression 21 operands: lhs = Expression(28, Add), rhs = Expression(0, Sub) -- expression 22 operands: lhs = Expression(29, Add), rhs = Counter(6) -- expression 23 operands: lhs = Expression(30, Add), rhs = Counter(5) -- expression 24 operands: lhs = Expression(31, Add), rhs = Counter(4) -- expression 25 operands: lhs = Counter(2), rhs = Counter(3) -- expression 26 operands: lhs = Counter(7), rhs = Expression(27, Add) -- expression 27 operands: lhs = Expression(28, Add), rhs = Expression(0, Sub) -- expression 28 operands: lhs = Expression(29, Add), rhs = Counter(6) -- expression 29 operands: lhs = Expression(30, Add), rhs = Counter(5) -- expression 30 operands: lhs = Expression(31, Add), rhs = Counter(4) -- expression 31 operands: lhs = Counter(2), rhs = Counter(3) -Number of file 0 mappings: 16 -- Code(Counter(0)) at (prev + 12, 1) to (start + 3, 9) -- MCDCDecision { bitmap_idx: 0, conditions_num: 6 } at (prev + 3, 8) to (start + 0, 34) -- MCDCBranch { true: Counter(1), false: Expression(0, Sub), condition_id: 1, true_next_id: 6, false_next_id: 0 } at (prev + 0, 8) to (start + 0, 9) - true = c1 - false = (c0 - c1) -- Code(Counter(1)) at (prev + 0, 13) to (start + 0, 14) -- MCDCBranch { true: Expression(20, Sub), false: Counter(6), condition_id: 6, true_next_id: 5, false_next_id: 0 } at (prev + 0, 13) to (start + 0, 14) - true = (c1 - c6) - false = c6 -- Code(Expression(20, Sub)) at (prev + 0, 18) to (start + 0, 19) - = (c1 - c6) -- MCDCBranch { true: Expression(19, Sub), false: Counter(5), condition_id: 5, true_next_id: 4, false_next_id: 0 } at (prev + 0, 18) to (start + 0, 19) - true = ((c1 - c6) - c5) - false = c5 -- Code(Expression(19, Sub)) at (prev + 0, 23) to (start + 0, 24) - = ((c1 - c6) - c5) -- MCDCBranch { true: Expression(18, Sub), false: Counter(4), condition_id: 4, true_next_id: 3, false_next_id: 0 } at (prev + 0, 23) to (start + 0, 24) - true = (((c1 - c6) - c5) - c4) - false = c4 -- Code(Expression(18, Sub)) at (prev + 0, 28) to (start + 0, 29) - = (((c1 - c6) - c5) - c4) -- MCDCBranch { true: Expression(17, Sub), false: Counter(3), condition_id: 3, true_next_id: 2, false_next_id: 0 } at (prev + 0, 28) to (start + 0, 29) - true = ((((c1 - c6) - c5) - c4) - c3) - false = c3 -- Code(Expression(17, Sub)) at (prev + 0, 33) to (start + 0, 34) - = ((((c1 - c6) - c5) - c4) - c3) -- MCDCBranch { true: Counter(7), false: Counter(2), condition_id: 2, true_next_id: 0, false_next_id: 0 } at (prev + 0, 33) to (start + 0, 34) - true = c7 - false = c2 -- Code(Counter(7)) at (prev + 0, 35) to (start + 2, 6) -- Code(Expression(27, Add)) at (prev + 2, 6) to (start + 0, 7) - = (((((c2 + c3) + c4) + c5) + c6) + (c0 - c1)) -- Code(Expression(26, Add)) at (prev + 1, 1) to (start + 0, 2) - = (c7 + (((((c2 + c3) + c4) + c5) + c6) + (c0 - c1))) - diff --git a/tests/coverage/mcdc/condition-limit.coverage b/tests/coverage/mcdc/condition-limit.coverage index 6330f2533d0e0..d11b8a17710b1 100644 --- a/tests/coverage/mcdc/condition-limit.coverage +++ b/tests/coverage/mcdc/condition-limit.coverage @@ -4,73 +4,53 @@ LL| |//@ compile-flags: -Zcoverage-options=mcdc LL| |//@ llvm-cov-flags: --show-branches=count --show-mcdc LL| | - LL| |// Check that MC/DC instrumentation can gracefully handle conditions that - LL| |// exceed LLVM's limit of 6 conditions per decision. - LL| |// - LL| |// (The limit is enforced in `compiler/rustc_mir_build/src/build/coverageinfo/mcdc.rs`.) - LL| | - LL| 1|fn good() { - LL| 1| // With only 6 conditions, perform full MC/DC instrumentation. - LL| 1| let [a, b, c, d, e, f] = <[bool; 6]>::default(); - LL| 1| if a && b && c && d && e && f { - ^0 ^0 ^0 ^0 ^0 + LL| 2|fn accept_7_conditions(bool_arr: [bool; 7]) { + LL| 2| let [a, b, c, d, e, f, g] = bool_arr; + LL| 2| if a && b && c && d && e && f && g { + ^1 ^1 ^1 ^1 ^1 ^1 ------------------ - | Branch (LL:8): [True: 0, False: 1] - | Branch (LL:13): [True: 0, False: 0] - | Branch (LL:18): [True: 0, False: 0] - | Branch (LL:23): [True: 0, False: 0] - | Branch (LL:28): [True: 0, False: 0] - | Branch (LL:33): [True: 0, False: 0] + | Branch (LL:8): [True: 1, False: 1] + | Branch (LL:13): [True: 1, False: 0] + | Branch (LL:18): [True: 1, False: 0] + | Branch (LL:23): [True: 1, False: 0] + | Branch (LL:28): [True: 1, False: 0] + | Branch (LL:33): [True: 1, False: 0] + | Branch (LL:38): [True: 1, False: 0] ------------------ - |---> MC/DC Decision Region (LL:8) to (LL:34) + |---> MC/DC Decision Region (LL:8) to (LL:39) | - | Number of Conditions: 6 + | Number of Conditions: 7 | Condition C1 --> (LL:8) | Condition C2 --> (LL:13) | Condition C3 --> (LL:18) | Condition C4 --> (LL:23) | Condition C5 --> (LL:28) | Condition C6 --> (LL:33) + | Condition C7 --> (LL:38) | | Executed MC/DC Test Vectors: | - | C1, C2, C3, C4, C5, C6 Result - | 1 { F, -, -, -, -, - = F } + | C1, C2, C3, C4, C5, C6, C7 Result + | 1 { F, -, -, -, -, -, - = F } + | 2 { T, T, T, T, T, T, T = T } | - | C1-Pair: not covered + | C1-Pair: covered: (1,2) | C2-Pair: not covered | C3-Pair: not covered | C4-Pair: not covered | C5-Pair: not covered | C6-Pair: not covered - | MC/DC Coverage for Decision: 0.00% + | C7-Pair: not covered + | MC/DC Coverage for Decision: 14.29% | ------------------ - LL| 0| core::hint::black_box("hello"); - LL| 1| } - LL| 1|} - LL| | - LL| 1|fn bad() { - LL| 1| // With 7 conditions, fall back to branch instrumentation only. - LL| 1| let [a, b, c, d, e, f, g] = <[bool; 7]>::default(); - LL| 1| if a && b && c && d && e && f && g { - ^0 ^0 ^0 ^0 ^0 ^0 - ------------------ - | Branch (LL:8): [True: 0, False: 1] - | Branch (LL:13): [True: 0, False: 0] - | Branch (LL:18): [True: 0, False: 0] - | Branch (LL:23): [True: 0, False: 0] - | Branch (LL:28): [True: 0, False: 0] - | Branch (LL:33): [True: 0, False: 0] - | Branch (LL:38): [True: 0, False: 0] - ------------------ - LL| 0| core::hint::black_box("hello"); + LL| 1| core::hint::black_box("hello"); LL| 1| } - LL| 1|} + LL| 2|} LL| | LL| |#[coverage(off)] LL| |fn main() { - LL| | good(); - LL| | bad(); + LL| | accept_7_conditions([false; 7]); + LL| | accept_7_conditions([true; 7]); LL| |} diff --git a/tests/coverage/mcdc/condition-limit.rs b/tests/coverage/mcdc/condition-limit.rs index 2d6fd35ab5781..2e8f161937930 100644 --- a/tests/coverage/mcdc/condition-limit.rs +++ b/tests/coverage/mcdc/condition-limit.rs @@ -4,22 +4,8 @@ //@ compile-flags: -Zcoverage-options=mcdc //@ llvm-cov-flags: --show-branches=count --show-mcdc -// Check that MC/DC instrumentation can gracefully handle conditions that -// exceed LLVM's limit of 6 conditions per decision. -// -// (The limit is enforced in `compiler/rustc_mir_build/src/build/coverageinfo/mcdc.rs`.) - -fn good() { - // With only 6 conditions, perform full MC/DC instrumentation. - let [a, b, c, d, e, f] = <[bool; 6]>::default(); - if a && b && c && d && e && f { - core::hint::black_box("hello"); - } -} - -fn bad() { - // With 7 conditions, fall back to branch instrumentation only. - let [a, b, c, d, e, f, g] = <[bool; 7]>::default(); +fn accept_7_conditions(bool_arr: [bool; 7]) { + let [a, b, c, d, e, f, g] = bool_arr; if a && b && c && d && e && f && g { core::hint::black_box("hello"); } @@ -27,6 +13,6 @@ fn bad() { #[coverage(off)] fn main() { - good(); - bad(); + accept_7_conditions([false; 7]); + accept_7_conditions([true; 7]); } diff --git a/tests/coverage/mcdc/if.cov-map b/tests/coverage/mcdc/if.cov-map index 9a7d15f700df0..576c9b14ed14c 100644 --- a/tests/coverage/mcdc/if.cov-map +++ b/tests/coverage/mcdc/if.cov-map @@ -1,5 +1,5 @@ Function name: if::mcdc_check_a -Raw bytes (64): 0x[01, 01, 04, 01, 05, 09, 02, 0d, 0f, 09, 02, 08, 01, 0f, 01, 01, 09, 28, 00, 02, 01, 08, 00, 0e, 30, 05, 02, 01, 02, 00, 00, 08, 00, 09, 05, 00, 0d, 00, 0e, 30, 0d, 09, 02, 00, 00, 00, 0d, 00, 0e, 0d, 00, 0f, 02, 06, 0f, 02, 0c, 02, 06, 0b, 03, 01, 00, 02] +Raw bytes (64): 0x[01, 01, 04, 01, 05, 09, 02, 0d, 0f, 09, 02, 08, 01, 0f, 01, 01, 09, 28, 03, 02, 01, 08, 00, 0e, 30, 05, 02, 01, 02, 00, 00, 08, 00, 09, 05, 00, 0d, 00, 0e, 30, 0d, 09, 02, 00, 00, 00, 0d, 00, 0e, 0d, 00, 0f, 02, 06, 0f, 02, 0c, 02, 06, 0b, 03, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 4 @@ -9,7 +9,7 @@ Number of expressions: 4 - expression 3 operands: lhs = Counter(2), rhs = Expression(0, Sub) Number of file 0 mappings: 8 - Code(Counter(0)) at (prev + 15, 1) to (start + 1, 9) -- MCDCDecision { bitmap_idx: 0, conditions_num: 2 } at (prev + 1, 8) to (start + 0, 14) +- MCDCDecision { bitmap_idx: 3, conditions_num: 2 } at (prev + 1, 8) to (start + 0, 14) - MCDCBranch { true: Counter(1), false: Expression(0, Sub), condition_id: 1, true_next_id: 2, false_next_id: 0 } at (prev + 0, 8) to (start + 0, 9) true = c1 false = (c0 - c1) @@ -24,7 +24,7 @@ Number of file 0 mappings: 8 = (c3 + (c2 + (c0 - c1))) Function name: if::mcdc_check_b -Raw bytes (64): 0x[01, 01, 04, 01, 05, 09, 02, 0d, 0f, 09, 02, 08, 01, 17, 01, 01, 09, 28, 00, 02, 01, 08, 00, 0e, 30, 05, 02, 01, 02, 00, 00, 08, 00, 09, 05, 00, 0d, 00, 0e, 30, 0d, 09, 02, 00, 00, 00, 0d, 00, 0e, 0d, 00, 0f, 02, 06, 0f, 02, 0c, 02, 06, 0b, 03, 01, 00, 02] +Raw bytes (64): 0x[01, 01, 04, 01, 05, 09, 02, 0d, 0f, 09, 02, 08, 01, 17, 01, 01, 09, 28, 03, 02, 01, 08, 00, 0e, 30, 05, 02, 01, 02, 00, 00, 08, 00, 09, 05, 00, 0d, 00, 0e, 30, 0d, 09, 02, 00, 00, 00, 0d, 00, 0e, 0d, 00, 0f, 02, 06, 0f, 02, 0c, 02, 06, 0b, 03, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 4 @@ -34,7 +34,7 @@ Number of expressions: 4 - expression 3 operands: lhs = Counter(2), rhs = Expression(0, Sub) Number of file 0 mappings: 8 - Code(Counter(0)) at (prev + 23, 1) to (start + 1, 9) -- MCDCDecision { bitmap_idx: 0, conditions_num: 2 } at (prev + 1, 8) to (start + 0, 14) +- MCDCDecision { bitmap_idx: 3, conditions_num: 2 } at (prev + 1, 8) to (start + 0, 14) - MCDCBranch { true: Counter(1), false: Expression(0, Sub), condition_id: 1, true_next_id: 2, false_next_id: 0 } at (prev + 0, 8) to (start + 0, 9) true = c1 false = (c0 - c1) @@ -49,7 +49,7 @@ Number of file 0 mappings: 8 = (c3 + (c2 + (c0 - c1))) Function name: if::mcdc_check_both -Raw bytes (64): 0x[01, 01, 04, 01, 05, 09, 02, 0d, 0f, 09, 02, 08, 01, 1f, 01, 01, 09, 28, 00, 02, 01, 08, 00, 0e, 30, 05, 02, 01, 02, 00, 00, 08, 00, 09, 05, 00, 0d, 00, 0e, 30, 0d, 09, 02, 00, 00, 00, 0d, 00, 0e, 0d, 00, 0f, 02, 06, 0f, 02, 0c, 02, 06, 0b, 03, 01, 00, 02] +Raw bytes (64): 0x[01, 01, 04, 01, 05, 09, 02, 0d, 0f, 09, 02, 08, 01, 1f, 01, 01, 09, 28, 03, 02, 01, 08, 00, 0e, 30, 05, 02, 01, 02, 00, 00, 08, 00, 09, 05, 00, 0d, 00, 0e, 30, 0d, 09, 02, 00, 00, 00, 0d, 00, 0e, 0d, 00, 0f, 02, 06, 0f, 02, 0c, 02, 06, 0b, 03, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 4 @@ -59,7 +59,7 @@ Number of expressions: 4 - expression 3 operands: lhs = Counter(2), rhs = Expression(0, Sub) Number of file 0 mappings: 8 - Code(Counter(0)) at (prev + 31, 1) to (start + 1, 9) -- MCDCDecision { bitmap_idx: 0, conditions_num: 2 } at (prev + 1, 8) to (start + 0, 14) +- MCDCDecision { bitmap_idx: 3, conditions_num: 2 } at (prev + 1, 8) to (start + 0, 14) - MCDCBranch { true: Counter(1), false: Expression(0, Sub), condition_id: 1, true_next_id: 2, false_next_id: 0 } at (prev + 0, 8) to (start + 0, 9) true = c1 false = (c0 - c1) @@ -74,7 +74,7 @@ Number of file 0 mappings: 8 = (c3 + (c2 + (c0 - c1))) Function name: if::mcdc_check_neither -Raw bytes (64): 0x[01, 01, 04, 01, 05, 09, 02, 0d, 0f, 09, 02, 08, 01, 07, 01, 01, 09, 28, 00, 02, 01, 08, 00, 0e, 30, 05, 02, 01, 02, 00, 00, 08, 00, 09, 05, 00, 0d, 00, 0e, 30, 0d, 09, 02, 00, 00, 00, 0d, 00, 0e, 0d, 00, 0f, 02, 06, 0f, 02, 0c, 02, 06, 0b, 03, 01, 00, 02] +Raw bytes (64): 0x[01, 01, 04, 01, 05, 09, 02, 0d, 0f, 09, 02, 08, 01, 07, 01, 01, 09, 28, 03, 02, 01, 08, 00, 0e, 30, 05, 02, 01, 02, 00, 00, 08, 00, 09, 05, 00, 0d, 00, 0e, 30, 0d, 09, 02, 00, 00, 00, 0d, 00, 0e, 0d, 00, 0f, 02, 06, 0f, 02, 0c, 02, 06, 0b, 03, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 4 @@ -84,7 +84,7 @@ Number of expressions: 4 - expression 3 operands: lhs = Counter(2), rhs = Expression(0, Sub) Number of file 0 mappings: 8 - Code(Counter(0)) at (prev + 7, 1) to (start + 1, 9) -- MCDCDecision { bitmap_idx: 0, conditions_num: 2 } at (prev + 1, 8) to (start + 0, 14) +- MCDCDecision { bitmap_idx: 3, conditions_num: 2 } at (prev + 1, 8) to (start + 0, 14) - MCDCBranch { true: Counter(1), false: Expression(0, Sub), condition_id: 1, true_next_id: 2, false_next_id: 0 } at (prev + 0, 8) to (start + 0, 9) true = c1 false = (c0 - c1) @@ -99,7 +99,7 @@ Number of file 0 mappings: 8 = (c3 + (c2 + (c0 - c1))) Function name: if::mcdc_check_not_tree_decision -Raw bytes (87): 0x[01, 01, 08, 01, 05, 02, 09, 05, 09, 0d, 1e, 02, 09, 11, 1b, 0d, 1e, 02, 09, 0a, 01, 31, 01, 03, 0a, 28, 00, 03, 03, 08, 00, 15, 30, 05, 02, 01, 02, 03, 00, 09, 00, 0a, 02, 00, 0e, 00, 0f, 30, 09, 1e, 03, 02, 00, 00, 0e, 00, 0f, 0b, 00, 14, 00, 15, 30, 11, 0d, 02, 00, 00, 00, 14, 00, 15, 11, 00, 16, 02, 06, 1b, 02, 0c, 02, 06, 17, 03, 01, 00, 02] +Raw bytes (87): 0x[01, 01, 08, 01, 05, 02, 09, 05, 09, 0d, 1e, 02, 09, 11, 1b, 0d, 1e, 02, 09, 0a, 01, 31, 01, 03, 0a, 28, 05, 03, 03, 08, 00, 15, 30, 05, 02, 01, 02, 03, 00, 09, 00, 0a, 02, 00, 0e, 00, 0f, 30, 09, 1e, 03, 02, 00, 00, 0e, 00, 0f, 0b, 00, 14, 00, 15, 30, 11, 0d, 02, 00, 00, 00, 14, 00, 15, 11, 00, 16, 02, 06, 1b, 02, 0c, 02, 06, 17, 03, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 8 @@ -113,7 +113,7 @@ Number of expressions: 8 - expression 7 operands: lhs = Expression(0, Sub), rhs = Counter(2) Number of file 0 mappings: 10 - Code(Counter(0)) at (prev + 49, 1) to (start + 3, 10) -- MCDCDecision { bitmap_idx: 0, conditions_num: 3 } at (prev + 3, 8) to (start + 0, 21) +- MCDCDecision { bitmap_idx: 5, conditions_num: 3 } at (prev + 3, 8) to (start + 0, 21) - MCDCBranch { true: Counter(1), false: Expression(0, Sub), condition_id: 1, true_next_id: 2, false_next_id: 3 } at (prev + 0, 9) to (start + 0, 10) true = c1 false = (c0 - c1) @@ -134,7 +134,7 @@ Number of file 0 mappings: 10 = (c4 + (c3 + ((c0 - c1) - c2))) Function name: if::mcdc_check_tree_decision -Raw bytes (87): 0x[01, 01, 08, 01, 05, 05, 0d, 05, 0d, 0d, 11, 09, 02, 1b, 1f, 0d, 11, 09, 02, 0a, 01, 27, 01, 03, 09, 28, 00, 03, 03, 08, 00, 15, 30, 05, 02, 01, 02, 00, 00, 08, 00, 09, 05, 00, 0e, 00, 0f, 30, 0d, 0a, 02, 00, 03, 00, 0e, 00, 0f, 0a, 00, 13, 00, 14, 30, 11, 09, 03, 00, 00, 00, 13, 00, 14, 1b, 00, 16, 02, 06, 1f, 02, 0c, 02, 06, 17, 03, 01, 00, 02] +Raw bytes (87): 0x[01, 01, 08, 01, 05, 05, 0d, 05, 0d, 0d, 11, 09, 02, 1b, 1f, 0d, 11, 09, 02, 0a, 01, 27, 01, 03, 09, 28, 04, 03, 03, 08, 00, 15, 30, 05, 02, 01, 02, 00, 00, 08, 00, 09, 05, 00, 0e, 00, 0f, 30, 0d, 0a, 02, 00, 03, 00, 0e, 00, 0f, 0a, 00, 13, 00, 14, 30, 11, 09, 03, 00, 00, 00, 13, 00, 14, 1b, 00, 16, 02, 06, 1f, 02, 0c, 02, 06, 17, 03, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 8 @@ -148,7 +148,7 @@ Number of expressions: 8 - expression 7 operands: lhs = Counter(2), rhs = Expression(0, Sub) Number of file 0 mappings: 10 - Code(Counter(0)) at (prev + 39, 1) to (start + 3, 9) -- MCDCDecision { bitmap_idx: 0, conditions_num: 3 } at (prev + 3, 8) to (start + 0, 21) +- MCDCDecision { bitmap_idx: 4, conditions_num: 3 } at (prev + 3, 8) to (start + 0, 21) - MCDCBranch { true: Counter(1), false: Expression(0, Sub), condition_id: 1, true_next_id: 2, false_next_id: 0 } at (prev + 0, 8) to (start + 0, 9) true = c1 false = (c0 - c1) @@ -169,7 +169,7 @@ Number of file 0 mappings: 10 = ((c3 + c4) + (c2 + (c0 - c1))) Function name: if::mcdc_nested_if -Raw bytes (124): 0x[01, 01, 0d, 01, 05, 02, 09, 05, 09, 1b, 15, 05, 09, 1b, 15, 05, 09, 11, 15, 02, 09, 2b, 32, 0d, 2f, 11, 15, 02, 09, 0e, 01, 3b, 01, 01, 09, 28, 00, 02, 01, 08, 00, 0e, 30, 05, 02, 01, 00, 02, 00, 08, 00, 09, 02, 00, 0d, 00, 0e, 30, 09, 32, 02, 00, 00, 00, 0d, 00, 0e, 1b, 01, 09, 01, 0d, 28, 01, 02, 01, 0c, 00, 12, 30, 16, 15, 01, 02, 00, 00, 0c, 00, 0d, 16, 00, 11, 00, 12, 30, 0d, 11, 02, 00, 00, 00, 11, 00, 12, 0d, 00, 13, 02, 0a, 2f, 02, 0a, 00, 0b, 32, 01, 0c, 02, 06, 27, 03, 01, 00, 02] +Raw bytes (124): 0x[01, 01, 0d, 01, 05, 02, 09, 05, 09, 1b, 15, 05, 09, 1b, 15, 05, 09, 11, 15, 02, 09, 2b, 32, 0d, 2f, 11, 15, 02, 09, 0e, 01, 3b, 01, 01, 09, 28, 03, 02, 01, 08, 00, 0e, 30, 05, 02, 01, 00, 02, 00, 08, 00, 09, 02, 00, 0d, 00, 0e, 30, 09, 32, 02, 00, 00, 00, 0d, 00, 0e, 1b, 01, 09, 01, 0d, 28, 06, 02, 01, 0c, 00, 12, 30, 16, 15, 01, 02, 00, 00, 0c, 00, 0d, 16, 00, 11, 00, 12, 30, 0d, 11, 02, 00, 00, 00, 11, 00, 12, 0d, 00, 13, 02, 0a, 2f, 02, 0a, 00, 0b, 32, 01, 0c, 02, 06, 27, 03, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 13 @@ -188,7 +188,7 @@ Number of expressions: 13 - expression 12 operands: lhs = Expression(0, Sub), rhs = Counter(2) Number of file 0 mappings: 14 - Code(Counter(0)) at (prev + 59, 1) to (start + 1, 9) -- MCDCDecision { bitmap_idx: 0, conditions_num: 2 } at (prev + 1, 8) to (start + 0, 14) +- MCDCDecision { bitmap_idx: 3, conditions_num: 2 } at (prev + 1, 8) to (start + 0, 14) - MCDCBranch { true: Counter(1), false: Expression(0, Sub), condition_id: 1, true_next_id: 0, false_next_id: 2 } at (prev + 0, 8) to (start + 0, 9) true = c1 false = (c0 - c1) @@ -199,7 +199,7 @@ Number of file 0 mappings: 14 false = ((c0 - c1) - c2) - Code(Expression(6, Add)) at (prev + 1, 9) to (start + 1, 13) = (c1 + c2) -- MCDCDecision { bitmap_idx: 1, conditions_num: 2 } at (prev + 1, 12) to (start + 0, 18) +- MCDCDecision { bitmap_idx: 6, conditions_num: 2 } at (prev + 1, 12) to (start + 0, 18) - MCDCBranch { true: Expression(5, Sub), false: Counter(5), condition_id: 1, true_next_id: 2, false_next_id: 0 } at (prev + 0, 12) to (start + 0, 13) true = ((c1 + c2) - c5) false = c5 diff --git a/tests/coverage/mcdc/if.coverage b/tests/coverage/mcdc/if.coverage index d5cf590d96eff..b000c7d5d2f8e 100644 --- a/tests/coverage/mcdc/if.coverage +++ b/tests/coverage/mcdc/if.coverage @@ -145,12 +145,12 @@ | C1, C2, C3 Result | 1 { F, -, - = F } | 2 { T, F, F = F } - | 3 { T, T, - = T } - | 4 { T, F, T = T } + | 3 { T, F, T = T } + | 4 { T, T, - = T } | | C1-Pair: covered: (1,3) - | C2-Pair: covered: (2,3) - | C3-Pair: covered: (2,4) + | C2-Pair: covered: (2,4) + | C3-Pair: covered: (2,3) | MC/DC Coverage for Decision: 100.00% | ------------------ @@ -162,7 +162,7 @@ LL| | LL| 4|fn mcdc_check_not_tree_decision(a: bool, b: bool, c: bool) { LL| 4| // Contradict to `mcdc_check_tree_decision`, - LL| 4| // 100% branch coverage of this expression does not mean indicates 100% mcdc coverage. + LL| 4| // 100% branch coverage of this expression does not indicate 100% mcdc coverage. LL| 4| if (a || b) && c { ^1 ------------------ @@ -181,12 +181,12 @@ | | C1, C2, C3 Result | 1 { T, -, F = F } - | 2 { T, -, T = T } - | 3 { F, T, T = T } + | 2 { F, T, T = T } + | 3 { T, -, T = T } | | C1-Pair: not covered | C2-Pair: not covered - | C3-Pair: covered: (1,2) + | C3-Pair: covered: (1,3) | MC/DC Coverage for Decision: 33.33% | ------------------ diff --git a/tests/coverage/mcdc/if.rs b/tests/coverage/mcdc/if.rs index 6ade8d34d5449..a2abb2edf115e 100644 --- a/tests/coverage/mcdc/if.rs +++ b/tests/coverage/mcdc/if.rs @@ -48,7 +48,7 @@ fn mcdc_check_tree_decision(a: bool, b: bool, c: bool) { fn mcdc_check_not_tree_decision(a: bool, b: bool, c: bool) { // Contradict to `mcdc_check_tree_decision`, - // 100% branch coverage of this expression does not mean indicates 100% mcdc coverage. + // 100% branch coverage of this expression does not indicate 100% mcdc coverage. if (a || b) && c { say("pass"); } else { diff --git a/tests/coverage/mcdc/inlined_expressions.cov-map b/tests/coverage/mcdc/inlined_expressions.cov-map index 09b7291c96493..bfde7d75d622f 100644 --- a/tests/coverage/mcdc/inlined_expressions.cov-map +++ b/tests/coverage/mcdc/inlined_expressions.cov-map @@ -1,5 +1,5 @@ Function name: inlined_expressions::inlined_instance -Raw bytes (52): 0x[01, 01, 03, 01, 05, 0b, 02, 09, 0d, 06, 01, 08, 01, 01, 06, 28, 00, 02, 01, 05, 00, 0b, 30, 05, 02, 01, 02, 00, 00, 05, 00, 06, 05, 00, 0a, 00, 0b, 30, 09, 0d, 02, 00, 00, 00, 0a, 00, 0b, 07, 01, 01, 00, 02] +Raw bytes (52): 0x[01, 01, 03, 01, 05, 0b, 02, 09, 0d, 06, 01, 08, 01, 01, 06, 28, 03, 02, 01, 05, 00, 0b, 30, 05, 02, 01, 02, 00, 00, 05, 00, 06, 05, 00, 0a, 00, 0b, 30, 09, 0d, 02, 00, 00, 00, 0a, 00, 0b, 07, 01, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 3 @@ -8,7 +8,7 @@ Number of expressions: 3 - expression 2 operands: lhs = Counter(2), rhs = Counter(3) Number of file 0 mappings: 6 - Code(Counter(0)) at (prev + 8, 1) to (start + 1, 6) -- MCDCDecision { bitmap_idx: 0, conditions_num: 2 } at (prev + 1, 5) to (start + 0, 11) +- MCDCDecision { bitmap_idx: 3, conditions_num: 2 } at (prev + 1, 5) to (start + 0, 11) - MCDCBranch { true: Counter(1), false: Expression(0, Sub), condition_id: 1, true_next_id: 2, false_next_id: 0 } at (prev + 0, 5) to (start + 0, 6) true = c1 false = (c0 - c1) diff --git a/tests/coverage/mcdc/nested_if.cov-map b/tests/coverage/mcdc/nested_if.cov-map index adeb6cbc1fb89..3da98ff4a514e 100644 --- a/tests/coverage/mcdc/nested_if.cov-map +++ b/tests/coverage/mcdc/nested_if.cov-map @@ -1,5 +1,5 @@ Function name: nested_if::doubly_nested_if_in_condition -Raw bytes (168): 0x[01, 01, 0e, 01, 05, 05, 11, 05, 11, 26, 19, 05, 11, 19, 1d, 19, 1d, 1d, 22, 26, 19, 05, 11, 11, 15, 09, 02, 0d, 37, 09, 02, 14, 01, 0f, 01, 01, 09, 28, 02, 02, 01, 08, 00, 4e, 30, 05, 02, 01, 02, 00, 00, 08, 00, 09, 30, 0d, 09, 02, 00, 00, 00, 0d, 00, 4e, 05, 00, 10, 00, 11, 28, 01, 02, 00, 10, 00, 36, 30, 11, 26, 01, 00, 02, 00, 10, 00, 11, 30, 15, 21, 02, 00, 00, 00, 15, 00, 36, 26, 00, 18, 00, 19, 28, 00, 02, 00, 18, 00, 1e, 30, 19, 22, 01, 02, 00, 00, 18, 00, 19, 19, 00, 1d, 00, 1e, 30, 1a, 1d, 02, 00, 00, 00, 1d, 00, 1e, 1a, 00, 21, 00, 25, 1f, 00, 2f, 00, 34, 2b, 00, 39, 00, 3e, 21, 00, 48, 00, 4c, 0d, 00, 4f, 02, 06, 37, 02, 0c, 02, 06, 33, 03, 01, 00, 02] +Raw bytes (168): 0x[01, 01, 0e, 01, 05, 05, 11, 05, 11, 26, 19, 05, 11, 19, 1d, 19, 1d, 1d, 22, 26, 19, 05, 11, 11, 15, 09, 02, 0d, 37, 09, 02, 14, 01, 0f, 01, 01, 09, 28, 09, 02, 01, 08, 00, 4e, 30, 05, 02, 01, 02, 00, 00, 08, 00, 09, 30, 0d, 09, 02, 00, 00, 00, 0d, 00, 4e, 05, 00, 10, 00, 11, 28, 06, 02, 00, 10, 00, 36, 30, 11, 26, 01, 00, 02, 00, 10, 00, 11, 30, 15, 21, 02, 00, 00, 00, 15, 00, 36, 26, 00, 18, 00, 19, 28, 03, 02, 00, 18, 00, 1e, 30, 19, 22, 01, 02, 00, 00, 18, 00, 19, 19, 00, 1d, 00, 1e, 30, 1a, 1d, 02, 00, 00, 00, 1d, 00, 1e, 1a, 00, 21, 00, 25, 1f, 00, 2f, 00, 34, 2b, 00, 39, 00, 3e, 21, 00, 48, 00, 4c, 0d, 00, 4f, 02, 06, 37, 02, 0c, 02, 06, 33, 03, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 14 @@ -19,7 +19,7 @@ Number of expressions: 14 - expression 13 operands: lhs = Counter(2), rhs = Expression(0, Sub) Number of file 0 mappings: 20 - Code(Counter(0)) at (prev + 15, 1) to (start + 1, 9) -- MCDCDecision { bitmap_idx: 2, conditions_num: 2 } at (prev + 1, 8) to (start + 0, 78) +- MCDCDecision { bitmap_idx: 9, conditions_num: 2 } at (prev + 1, 8) to (start + 0, 78) - MCDCBranch { true: Counter(1), false: Expression(0, Sub), condition_id: 1, true_next_id: 2, false_next_id: 0 } at (prev + 0, 8) to (start + 0, 9) true = c1 false = (c0 - c1) @@ -27,7 +27,7 @@ Number of file 0 mappings: 20 true = c3 false = c2 - Code(Counter(1)) at (prev + 0, 16) to (start + 0, 17) -- MCDCDecision { bitmap_idx: 1, conditions_num: 2 } at (prev + 0, 16) to (start + 0, 54) +- MCDCDecision { bitmap_idx: 6, conditions_num: 2 } at (prev + 0, 16) to (start + 0, 54) - MCDCBranch { true: Counter(4), false: Expression(9, Sub), condition_id: 1, true_next_id: 0, false_next_id: 2 } at (prev + 0, 16) to (start + 0, 17) true = c4 false = (c1 - c4) @@ -36,7 +36,7 @@ Number of file 0 mappings: 20 false = c8 - Code(Expression(9, Sub)) at (prev + 0, 24) to (start + 0, 25) = (c1 - c4) -- MCDCDecision { bitmap_idx: 0, conditions_num: 2 } at (prev + 0, 24) to (start + 0, 30) +- MCDCDecision { bitmap_idx: 3, conditions_num: 2 } at (prev + 0, 24) to (start + 0, 30) - MCDCBranch { true: Counter(6), false: Expression(8, Sub), condition_id: 1, true_next_id: 2, false_next_id: 0 } at (prev + 0, 24) to (start + 0, 25) true = c6 false = ((c1 - c4) - c6) @@ -58,7 +58,7 @@ Number of file 0 mappings: 20 = (c3 + (c2 + (c0 - c1))) Function name: nested_if::nested_if_in_condition -Raw bytes (120): 0x[01, 01, 0b, 01, 05, 05, 11, 05, 11, 1e, 15, 05, 11, 11, 15, 1e, 15, 05, 11, 09, 02, 0d, 2b, 09, 02, 0e, 01, 07, 01, 01, 09, 28, 01, 02, 01, 08, 00, 2e, 30, 05, 02, 01, 02, 00, 00, 08, 00, 09, 30, 0d, 09, 02, 00, 00, 00, 0d, 00, 2e, 05, 00, 10, 00, 11, 28, 00, 02, 00, 10, 00, 16, 30, 11, 1e, 01, 00, 02, 00, 10, 00, 11, 1e, 00, 15, 00, 16, 30, 15, 1a, 02, 00, 00, 00, 15, 00, 16, 17, 00, 19, 00, 1d, 1a, 00, 27, 00, 2c, 0d, 00, 2f, 02, 06, 2b, 02, 0c, 02, 06, 27, 03, 01, 00, 02] +Raw bytes (120): 0x[01, 01, 0b, 01, 05, 05, 11, 05, 11, 1e, 15, 05, 11, 11, 15, 1e, 15, 05, 11, 09, 02, 0d, 2b, 09, 02, 0e, 01, 07, 01, 01, 09, 28, 06, 02, 01, 08, 00, 2e, 30, 05, 02, 01, 02, 00, 00, 08, 00, 09, 30, 0d, 09, 02, 00, 00, 00, 0d, 00, 2e, 05, 00, 10, 00, 11, 28, 03, 02, 00, 10, 00, 16, 30, 11, 1e, 01, 00, 02, 00, 10, 00, 11, 1e, 00, 15, 00, 16, 30, 15, 1a, 02, 00, 00, 00, 15, 00, 16, 17, 00, 19, 00, 1d, 1a, 00, 27, 00, 2c, 0d, 00, 2f, 02, 06, 2b, 02, 0c, 02, 06, 27, 03, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 11 @@ -75,7 +75,7 @@ Number of expressions: 11 - expression 10 operands: lhs = Counter(2), rhs = Expression(0, Sub) Number of file 0 mappings: 14 - Code(Counter(0)) at (prev + 7, 1) to (start + 1, 9) -- MCDCDecision { bitmap_idx: 1, conditions_num: 2 } at (prev + 1, 8) to (start + 0, 46) +- MCDCDecision { bitmap_idx: 6, conditions_num: 2 } at (prev + 1, 8) to (start + 0, 46) - MCDCBranch { true: Counter(1), false: Expression(0, Sub), condition_id: 1, true_next_id: 2, false_next_id: 0 } at (prev + 0, 8) to (start + 0, 9) true = c1 false = (c0 - c1) @@ -83,7 +83,7 @@ Number of file 0 mappings: 14 true = c3 false = c2 - Code(Counter(1)) at (prev + 0, 16) to (start + 0, 17) -- MCDCDecision { bitmap_idx: 0, conditions_num: 2 } at (prev + 0, 16) to (start + 0, 22) +- MCDCDecision { bitmap_idx: 3, conditions_num: 2 } at (prev + 0, 16) to (start + 0, 22) - MCDCBranch { true: Counter(4), false: Expression(7, Sub), condition_id: 1, true_next_id: 0, false_next_id: 2 } at (prev + 0, 16) to (start + 0, 17) true = c4 false = (c1 - c4) @@ -103,7 +103,7 @@ Number of file 0 mappings: 14 = (c3 + (c2 + (c0 - c1))) Function name: nested_if::nested_in_then_block_in_condition -Raw bytes (176): 0x[01, 01, 12, 01, 05, 05, 11, 05, 11, 3a, 15, 05, 11, 11, 15, 33, 19, 11, 15, 19, 1d, 19, 1d, 1d, 2e, 33, 19, 11, 15, 3a, 15, 05, 11, 09, 02, 0d, 47, 09, 02, 14, 01, 22, 01, 01, 09, 28, 02, 02, 01, 08, 00, 4b, 30, 05, 02, 01, 02, 00, 00, 08, 00, 09, 30, 0d, 09, 02, 00, 00, 00, 0d, 00, 4b, 05, 00, 10, 00, 11, 28, 00, 02, 00, 10, 00, 16, 30, 11, 3a, 01, 00, 02, 00, 10, 00, 11, 3a, 00, 15, 00, 16, 30, 15, 36, 02, 00, 00, 00, 15, 00, 16, 33, 00, 1c, 00, 1d, 28, 01, 02, 00, 1c, 00, 22, 30, 19, 2e, 01, 02, 00, 00, 1c, 00, 1d, 19, 00, 21, 00, 22, 30, 26, 1d, 02, 00, 00, 00, 21, 00, 22, 26, 00, 25, 00, 29, 2b, 00, 33, 00, 38, 36, 00, 44, 00, 49, 0d, 00, 4c, 02, 06, 47, 02, 0c, 02, 06, 43, 03, 01, 00, 02] +Raw bytes (176): 0x[01, 01, 12, 01, 05, 05, 11, 05, 11, 3a, 15, 05, 11, 11, 15, 33, 19, 11, 15, 19, 1d, 19, 1d, 1d, 2e, 33, 19, 11, 15, 3a, 15, 05, 11, 09, 02, 0d, 47, 09, 02, 14, 01, 22, 01, 01, 09, 28, 09, 02, 01, 08, 00, 4b, 30, 05, 02, 01, 02, 00, 00, 08, 00, 09, 30, 0d, 09, 02, 00, 00, 00, 0d, 00, 4b, 05, 00, 10, 00, 11, 28, 03, 02, 00, 10, 00, 16, 30, 11, 3a, 01, 00, 02, 00, 10, 00, 11, 3a, 00, 15, 00, 16, 30, 15, 36, 02, 00, 00, 00, 15, 00, 16, 33, 00, 1c, 00, 1d, 28, 06, 02, 00, 1c, 00, 22, 30, 19, 2e, 01, 02, 00, 00, 1c, 00, 1d, 19, 00, 21, 00, 22, 30, 26, 1d, 02, 00, 00, 00, 21, 00, 22, 26, 00, 25, 00, 29, 2b, 00, 33, 00, 38, 36, 00, 44, 00, 49, 0d, 00, 4c, 02, 06, 47, 02, 0c, 02, 06, 43, 03, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 18 @@ -127,7 +127,7 @@ Number of expressions: 18 - expression 17 operands: lhs = Counter(2), rhs = Expression(0, Sub) Number of file 0 mappings: 20 - Code(Counter(0)) at (prev + 34, 1) to (start + 1, 9) -- MCDCDecision { bitmap_idx: 2, conditions_num: 2 } at (prev + 1, 8) to (start + 0, 75) +- MCDCDecision { bitmap_idx: 9, conditions_num: 2 } at (prev + 1, 8) to (start + 0, 75) - MCDCBranch { true: Counter(1), false: Expression(0, Sub), condition_id: 1, true_next_id: 2, false_next_id: 0 } at (prev + 0, 8) to (start + 0, 9) true = c1 false = (c0 - c1) @@ -135,7 +135,7 @@ Number of file 0 mappings: 20 true = c3 false = c2 - Code(Counter(1)) at (prev + 0, 16) to (start + 0, 17) -- MCDCDecision { bitmap_idx: 0, conditions_num: 2 } at (prev + 0, 16) to (start + 0, 22) +- MCDCDecision { bitmap_idx: 3, conditions_num: 2 } at (prev + 0, 16) to (start + 0, 22) - MCDCBranch { true: Counter(4), false: Expression(14, Sub), condition_id: 1, true_next_id: 0, false_next_id: 2 } at (prev + 0, 16) to (start + 0, 17) true = c4 false = (c1 - c4) @@ -146,7 +146,7 @@ Number of file 0 mappings: 20 false = ((c1 - c4) - c5) - Code(Expression(12, Add)) at (prev + 0, 28) to (start + 0, 29) = (c4 + c5) -- MCDCDecision { bitmap_idx: 1, conditions_num: 2 } at (prev + 0, 28) to (start + 0, 34) +- MCDCDecision { bitmap_idx: 6, conditions_num: 2 } at (prev + 0, 28) to (start + 0, 34) - MCDCBranch { true: Counter(6), false: Expression(11, Sub), condition_id: 1, true_next_id: 2, false_next_id: 0 } at (prev + 0, 28) to (start + 0, 29) true = c6 false = ((c4 + c5) - c6) @@ -167,7 +167,7 @@ Number of file 0 mappings: 20 = (c3 + (c2 + (c0 - c1))) Function name: nested_if::nested_single_condition_decision -Raw bytes (85): 0x[01, 01, 06, 01, 05, 05, 11, 05, 11, 09, 02, 0d, 17, 09, 02, 0b, 01, 17, 01, 04, 09, 28, 00, 02, 04, 08, 00, 29, 30, 05, 02, 01, 02, 00, 00, 08, 00, 09, 30, 0d, 09, 02, 00, 00, 00, 0d, 00, 29, 05, 00, 10, 00, 11, 20, 11, 0a, 00, 10, 00, 11, 11, 00, 14, 00, 19, 0a, 00, 23, 00, 27, 0d, 00, 2a, 02, 06, 17, 02, 0c, 02, 06, 13, 03, 01, 00, 02] +Raw bytes (85): 0x[01, 01, 06, 01, 05, 05, 11, 05, 11, 09, 02, 0d, 17, 09, 02, 0b, 01, 17, 01, 04, 09, 28, 03, 02, 04, 08, 00, 29, 30, 05, 02, 01, 02, 00, 00, 08, 00, 09, 30, 0d, 09, 02, 00, 00, 00, 0d, 00, 29, 05, 00, 10, 00, 11, 20, 11, 0a, 00, 10, 00, 11, 11, 00, 14, 00, 19, 0a, 00, 23, 00, 27, 0d, 00, 2a, 02, 06, 17, 02, 0c, 02, 06, 13, 03, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 6 @@ -179,7 +179,7 @@ Number of expressions: 6 - expression 5 operands: lhs = Counter(2), rhs = Expression(0, Sub) Number of file 0 mappings: 11 - Code(Counter(0)) at (prev + 23, 1) to (start + 4, 9) -- MCDCDecision { bitmap_idx: 0, conditions_num: 2 } at (prev + 4, 8) to (start + 0, 41) +- MCDCDecision { bitmap_idx: 3, conditions_num: 2 } at (prev + 4, 8) to (start + 0, 41) - MCDCBranch { true: Counter(1), false: Expression(0, Sub), condition_id: 1, true_next_id: 2, false_next_id: 0 } at (prev + 0, 8) to (start + 0, 9) true = c1 false = (c0 - c1) diff --git a/tests/coverage/mcdc/nested_if.coverage b/tests/coverage/mcdc/nested_if.coverage index f14969dc8c9f7..ca0cb54d58150 100644 --- a/tests/coverage/mcdc/nested_if.coverage +++ b/tests/coverage/mcdc/nested_if.coverage @@ -40,11 +40,11 @@ | | C1, C2 Result | 1 { F, F = F } - | 2 { T, - = T } - | 3 { F, T = T } + | 2 { F, T = T } + | 3 { T, - = T } | - | C1-Pair: covered: (1,2) - | C2-Pair: covered: (1,3) + | C1-Pair: covered: (1,3) + | C2-Pair: covered: (1,2) | MC/DC Coverage for Decision: 100.00% | ------------------ @@ -92,11 +92,11 @@ | | C1, C2 Result | 1 { F, F = F } - | 2 { T, - = T } - | 3 { F, T = T } + | 2 { F, T = T } + | 3 { T, - = T } | - | C1-Pair: covered: (1,2) - | C2-Pair: covered: (1,3) + | C1-Pair: covered: (1,3) + | C2-Pair: covered: (1,2) | MC/DC Coverage for Decision: 100.00% | |---> MC/DC Decision Region (LL:24) to (LL:30) @@ -195,11 +195,11 @@ | | C1, C2 Result | 1 { F, F = F } - | 2 { T, - = T } - | 3 { F, T = T } + | 2 { F, T = T } + | 3 { T, - = T } | - | C1-Pair: covered: (1,2) - | C2-Pair: covered: (1,3) + | C1-Pair: covered: (1,3) + | C2-Pair: covered: (1,2) | MC/DC Coverage for Decision: 100.00% | |---> MC/DC Decision Region (LL:28) to (LL:34) diff --git a/tests/coverage/mcdc/non_control_flow.cov-map b/tests/coverage/mcdc/non_control_flow.cov-map index f8576831e75f1..d5383a197616b 100644 --- a/tests/coverage/mcdc/non_control_flow.cov-map +++ b/tests/coverage/mcdc/non_control_flow.cov-map @@ -1,5 +1,5 @@ Function name: non_control_flow::assign_3 -Raw bytes (89): 0x[01, 01, 09, 05, 07, 0b, 11, 09, 0d, 01, 05, 01, 05, 22, 11, 01, 05, 22, 11, 01, 05, 0a, 01, 16, 01, 00, 28, 03, 01, 09, 00, 0a, 01, 00, 0d, 00, 0e, 28, 00, 03, 00, 0d, 00, 18, 30, 05, 22, 01, 00, 02, 00, 0d, 00, 0e, 22, 00, 12, 00, 13, 30, 1e, 11, 02, 03, 00, 00, 12, 00, 13, 1e, 00, 17, 00, 18, 30, 09, 0d, 03, 00, 00, 00, 17, 00, 18, 03, 01, 05, 01, 02] +Raw bytes (89): 0x[01, 01, 09, 05, 07, 0b, 11, 09, 0d, 01, 05, 01, 05, 22, 11, 01, 05, 22, 11, 01, 05, 0a, 01, 16, 01, 00, 28, 03, 01, 09, 00, 0a, 01, 00, 0d, 00, 0e, 28, 04, 03, 00, 0d, 00, 18, 30, 05, 22, 01, 00, 02, 00, 0d, 00, 0e, 22, 00, 12, 00, 13, 30, 1e, 11, 02, 03, 00, 00, 12, 00, 13, 1e, 00, 17, 00, 18, 30, 09, 0d, 03, 00, 00, 00, 17, 00, 18, 03, 01, 05, 01, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 9 @@ -17,7 +17,7 @@ Number of file 0 mappings: 10 - Code(Expression(0, Add)) at (prev + 1, 9) to (start + 0, 10) = (c1 + ((c2 + c3) + c4)) - Code(Counter(0)) at (prev + 0, 13) to (start + 0, 14) -- MCDCDecision { bitmap_idx: 0, conditions_num: 3 } at (prev + 0, 13) to (start + 0, 24) +- MCDCDecision { bitmap_idx: 4, conditions_num: 3 } at (prev + 0, 13) to (start + 0, 24) - MCDCBranch { true: Counter(1), false: Expression(8, Sub), condition_id: 1, true_next_id: 0, false_next_id: 2 } at (prev + 0, 13) to (start + 0, 14) true = c1 false = (c0 - c1) @@ -35,7 +35,7 @@ Number of file 0 mappings: 10 = (c1 + ((c2 + c3) + c4)) Function name: non_control_flow::assign_3_bis -Raw bytes (85): 0x[01, 01, 07, 07, 11, 09, 0d, 01, 05, 05, 09, 16, 1a, 05, 09, 01, 05, 0a, 01, 1b, 01, 00, 2c, 03, 01, 09, 00, 0a, 01, 00, 0d, 00, 0e, 28, 00, 03, 00, 0d, 00, 18, 30, 05, 1a, 01, 03, 02, 00, 0d, 00, 0e, 05, 00, 12, 00, 13, 30, 09, 16, 03, 00, 02, 00, 12, 00, 13, 13, 00, 17, 00, 18, 30, 0d, 11, 02, 00, 00, 00, 17, 00, 18, 03, 01, 05, 01, 02] +Raw bytes (85): 0x[01, 01, 07, 07, 11, 09, 0d, 01, 05, 05, 09, 16, 1a, 05, 09, 01, 05, 0a, 01, 1b, 01, 00, 2c, 03, 01, 09, 00, 0a, 01, 00, 0d, 00, 0e, 28, 05, 03, 00, 0d, 00, 18, 30, 05, 1a, 01, 03, 02, 00, 0d, 00, 0e, 05, 00, 12, 00, 13, 30, 09, 16, 03, 00, 02, 00, 12, 00, 13, 13, 00, 17, 00, 18, 30, 0d, 11, 02, 00, 00, 00, 17, 00, 18, 03, 01, 05, 01, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 7 @@ -51,7 +51,7 @@ Number of file 0 mappings: 10 - Code(Expression(0, Add)) at (prev + 1, 9) to (start + 0, 10) = ((c2 + c3) + c4) - Code(Counter(0)) at (prev + 0, 13) to (start + 0, 14) -- MCDCDecision { bitmap_idx: 0, conditions_num: 3 } at (prev + 0, 13) to (start + 0, 24) +- MCDCDecision { bitmap_idx: 5, conditions_num: 3 } at (prev + 0, 13) to (start + 0, 24) - MCDCBranch { true: Counter(1), false: Expression(6, Sub), condition_id: 1, true_next_id: 3, false_next_id: 2 } at (prev + 0, 13) to (start + 0, 14) true = c1 false = (c0 - c1) @@ -68,7 +68,7 @@ Number of file 0 mappings: 10 = ((c2 + c3) + c4) Function name: non_control_flow::assign_and -Raw bytes (64): 0x[01, 01, 04, 07, 0e, 09, 0d, 01, 05, 01, 05, 08, 01, 0c, 01, 00, 21, 03, 01, 09, 00, 0a, 01, 00, 0d, 00, 0e, 28, 00, 02, 00, 0d, 00, 13, 30, 05, 0e, 01, 02, 00, 00, 0d, 00, 0e, 05, 00, 12, 00, 13, 30, 09, 0d, 02, 00, 00, 00, 12, 00, 13, 03, 01, 05, 01, 02] +Raw bytes (64): 0x[01, 01, 04, 07, 0e, 09, 0d, 01, 05, 01, 05, 08, 01, 0c, 01, 00, 21, 03, 01, 09, 00, 0a, 01, 00, 0d, 00, 0e, 28, 03, 02, 00, 0d, 00, 13, 30, 05, 0e, 01, 02, 00, 00, 0d, 00, 0e, 05, 00, 12, 00, 13, 30, 09, 0d, 02, 00, 00, 00, 12, 00, 13, 03, 01, 05, 01, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 4 @@ -81,7 +81,7 @@ Number of file 0 mappings: 8 - Code(Expression(0, Add)) at (prev + 1, 9) to (start + 0, 10) = ((c2 + c3) + (c0 - c1)) - Code(Counter(0)) at (prev + 0, 13) to (start + 0, 14) -- MCDCDecision { bitmap_idx: 0, conditions_num: 2 } at (prev + 0, 13) to (start + 0, 19) +- MCDCDecision { bitmap_idx: 3, conditions_num: 2 } at (prev + 0, 13) to (start + 0, 19) - MCDCBranch { true: Counter(1), false: Expression(3, Sub), condition_id: 1, true_next_id: 2, false_next_id: 0 } at (prev + 0, 13) to (start + 0, 14) true = c1 false = (c0 - c1) @@ -93,7 +93,7 @@ Number of file 0 mappings: 8 = ((c2 + c3) + (c0 - c1)) Function name: non_control_flow::assign_or -Raw bytes (64): 0x[01, 01, 04, 07, 0d, 05, 09, 01, 05, 01, 05, 08, 01, 11, 01, 00, 20, 03, 01, 09, 00, 0a, 01, 00, 0d, 00, 0e, 28, 00, 02, 00, 0d, 00, 13, 30, 05, 0e, 01, 00, 02, 00, 0d, 00, 0e, 0e, 00, 12, 00, 13, 30, 09, 0d, 02, 00, 00, 00, 12, 00, 13, 03, 01, 05, 01, 02] +Raw bytes (64): 0x[01, 01, 04, 07, 0d, 05, 09, 01, 05, 01, 05, 08, 01, 11, 01, 00, 20, 03, 01, 09, 00, 0a, 01, 00, 0d, 00, 0e, 28, 03, 02, 00, 0d, 00, 13, 30, 05, 0e, 01, 00, 02, 00, 0d, 00, 0e, 0e, 00, 12, 00, 13, 30, 09, 0d, 02, 00, 00, 00, 12, 00, 13, 03, 01, 05, 01, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 4 @@ -106,7 +106,7 @@ Number of file 0 mappings: 8 - Code(Expression(0, Add)) at (prev + 1, 9) to (start + 0, 10) = ((c1 + c2) + c3) - Code(Counter(0)) at (prev + 0, 13) to (start + 0, 14) -- MCDCDecision { bitmap_idx: 0, conditions_num: 2 } at (prev + 0, 13) to (start + 0, 19) +- MCDCDecision { bitmap_idx: 3, conditions_num: 2 } at (prev + 0, 13) to (start + 0, 19) - MCDCBranch { true: Counter(1), false: Expression(3, Sub), condition_id: 1, true_next_id: 0, false_next_id: 2 } at (prev + 0, 13) to (start + 0, 14) true = c1 false = (c0 - c1) @@ -127,7 +127,7 @@ Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 37, 1) to (start + 2, 2) Function name: non_control_flow::func_call -Raw bytes (52): 0x[01, 01, 03, 01, 05, 0b, 02, 09, 0d, 06, 01, 29, 01, 01, 0a, 28, 00, 02, 01, 09, 00, 0f, 30, 05, 02, 01, 02, 00, 00, 09, 00, 0a, 05, 00, 0e, 00, 0f, 30, 09, 0d, 02, 00, 00, 00, 0e, 00, 0f, 07, 01, 01, 00, 02] +Raw bytes (52): 0x[01, 01, 03, 01, 05, 0b, 02, 09, 0d, 06, 01, 29, 01, 01, 0a, 28, 03, 02, 01, 09, 00, 0f, 30, 05, 02, 01, 02, 00, 00, 09, 00, 0a, 05, 00, 0e, 00, 0f, 30, 09, 0d, 02, 00, 00, 00, 0e, 00, 0f, 07, 01, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 3 @@ -136,7 +136,7 @@ Number of expressions: 3 - expression 2 operands: lhs = Counter(2), rhs = Counter(3) Number of file 0 mappings: 6 - Code(Counter(0)) at (prev + 41, 1) to (start + 1, 10) -- MCDCDecision { bitmap_idx: 0, conditions_num: 2 } at (prev + 1, 9) to (start + 0, 15) +- MCDCDecision { bitmap_idx: 3, conditions_num: 2 } at (prev + 1, 9) to (start + 0, 15) - MCDCBranch { true: Counter(1), false: Expression(0, Sub), condition_id: 1, true_next_id: 2, false_next_id: 0 } at (prev + 0, 9) to (start + 0, 10) true = c1 false = (c0 - c1) @@ -148,7 +148,7 @@ Number of file 0 mappings: 6 = ((c2 + c3) + (c0 - c1)) Function name: non_control_flow::right_comb_tree -Raw bytes (139): 0x[01, 01, 13, 07, 1a, 0b, 19, 0f, 15, 13, 11, 09, 0d, 01, 05, 01, 05, 05, 19, 05, 19, 4a, 15, 05, 19, 4a, 15, 05, 19, 46, 11, 4a, 15, 05, 19, 46, 11, 4a, 15, 05, 19, 0e, 01, 20, 01, 00, 41, 03, 01, 09, 00, 0a, 01, 00, 0d, 00, 0e, 28, 00, 05, 00, 0d, 00, 2a, 30, 05, 1a, 01, 02, 00, 00, 0d, 00, 0e, 05, 00, 13, 00, 14, 30, 4a, 19, 02, 03, 00, 00, 13, 00, 14, 4a, 00, 19, 00, 1a, 30, 46, 15, 03, 04, 00, 00, 19, 00, 1a, 46, 00, 1f, 00, 20, 30, 42, 11, 04, 05, 00, 00, 1f, 00, 20, 42, 00, 24, 00, 27, 30, 09, 0d, 05, 00, 00, 00, 24, 00, 27, 03, 01, 05, 01, 02] +Raw bytes (139): 0x[01, 01, 13, 07, 1a, 0b, 19, 0f, 15, 13, 11, 09, 0d, 01, 05, 01, 05, 05, 19, 05, 19, 4a, 15, 05, 19, 4a, 15, 05, 19, 46, 11, 4a, 15, 05, 19, 46, 11, 4a, 15, 05, 19, 0e, 01, 20, 01, 00, 41, 03, 01, 09, 00, 0a, 01, 00, 0d, 00, 0e, 28, 06, 05, 00, 0d, 00, 2a, 30, 05, 1a, 01, 02, 00, 00, 0d, 00, 0e, 05, 00, 13, 00, 14, 30, 4a, 19, 02, 03, 00, 00, 13, 00, 14, 4a, 00, 19, 00, 1a, 30, 46, 15, 03, 04, 00, 00, 19, 00, 1a, 46, 00, 1f, 00, 20, 30, 42, 11, 04, 05, 00, 00, 1f, 00, 20, 42, 00, 24, 00, 27, 30, 09, 0d, 05, 00, 00, 00, 24, 00, 27, 03, 01, 05, 01, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 19 @@ -176,7 +176,7 @@ Number of file 0 mappings: 14 - Code(Expression(0, Add)) at (prev + 1, 9) to (start + 0, 10) = (((((c2 + c3) + c4) + c5) + c6) + (c0 - c1)) - Code(Counter(0)) at (prev + 0, 13) to (start + 0, 14) -- MCDCDecision { bitmap_idx: 0, conditions_num: 5 } at (prev + 0, 13) to (start + 0, 42) +- MCDCDecision { bitmap_idx: 6, conditions_num: 5 } at (prev + 0, 13) to (start + 0, 42) - MCDCBranch { true: Counter(1), false: Expression(6, Sub), condition_id: 1, true_next_id: 2, false_next_id: 0 } at (prev + 0, 13) to (start + 0, 14) true = c1 false = (c0 - c1) diff --git a/tests/coverage/mcdc/non_control_flow.coverage b/tests/coverage/mcdc/non_control_flow.coverage index 570f565de74d4..cead419fbdf93 100644 --- a/tests/coverage/mcdc/non_control_flow.coverage +++ b/tests/coverage/mcdc/non_control_flow.coverage @@ -83,11 +83,11 @@ | | C1, C2, C3 Result | 1 { F, F, - = F } - | 2 { T, -, - = T } - | 3 { F, T, T = T } + | 2 { F, T, T = T } + | 3 { T, -, - = T } | - | C1-Pair: covered: (1,2) - | C2-Pair: covered: (1,3) + | C1-Pair: covered: (1,3) + | C2-Pair: covered: (1,2) | C3-Pair: not covered | MC/DC Coverage for Decision: 66.67% | diff --git a/tests/ui/instrument-coverage/mcdc-condition-limit.bad.stderr b/tests/ui/instrument-coverage/mcdc-condition-limit.bad.stderr deleted file mode 100644 index b8b7d6e1a5e93..0000000000000 --- a/tests/ui/instrument-coverage/mcdc-condition-limit.bad.stderr +++ /dev/null @@ -1,8 +0,0 @@ -warning: number of conditions in decision (7) exceeds limit (6), so MC/DC analysis will not count this expression - --> $DIR/mcdc-condition-limit.rs:28:8 - | -LL | if a && b && c && d && e && f && g { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -warning: 1 warning emitted - diff --git a/tests/ui/instrument-coverage/mcdc-condition-limit.rs b/tests/ui/instrument-coverage/mcdc-condition-limit.rs index 91ff6381df766..118ae482fc6ce 100644 --- a/tests/ui/instrument-coverage/mcdc-condition-limit.rs +++ b/tests/ui/instrument-coverage/mcdc-condition-limit.rs @@ -1,5 +1,6 @@ //@ edition: 2021 -//@ revisions: good bad +//@ min-llvm-version: 19 +//@ revisions: good //@ check-pass //@ compile-flags: -Cinstrument-coverage -Zcoverage-options=mcdc -Zno-profiler-runtime @@ -14,18 +15,9 @@ #[cfg(good)] fn main() { - // 6 conditions is OK, so no diagnostic. - let [a, b, c, d, e, f] = <[bool; 6]>::default(); - if a && b && c && d && e && f { - core::hint::black_box("hello"); - } -} - -#[cfg(bad)] -fn main() { - // 7 conditions is too many, so issue a diagnostic. + // 7 conditions is allowed, so no diagnostic. let [a, b, c, d, e, f, g] = <[bool; 7]>::default(); - if a && b && c && d && e && f && g { //[bad]~ WARNING number of conditions in decision + if a && b && c && d && e && f && g { core::hint::black_box("hello"); } } From acd64fa0d9e5c17de02a5b2a592163a377e33bcc Mon Sep 17 00:00:00 2001 From: zhuyunxing Date: Tue, 9 Jul 2024 16:14:14 +0800 Subject: [PATCH 2002/2194] coverage. Warn about too many test vectors --- compiler/rustc_mir_transform/messages.ftl | 2 ++ compiler/rustc_mir_transform/src/coverage/mappings.rs | 8 +++++++- compiler/rustc_mir_transform/src/errors.rs | 8 ++++++++ 3 files changed, 17 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_mir_transform/messages.ftl b/compiler/rustc_mir_transform/messages.ftl index b81c090673476..c8992b8b83430 100644 --- a/compiler/rustc_mir_transform/messages.ftl +++ b/compiler/rustc_mir_transform/messages.ftl @@ -9,6 +9,8 @@ mir_transform_const_mut_borrow = taking a mutable reference to a `const` item .note2 = the mutable reference will refer to this temporary, not the original `const` item .note3 = mutable reference created due to call to this method +mir_transform_exceeds_mcdc_test_vector_limit = number of total test vectors in one function will exceed limit ({$max_num_test_vectors}) if this decision is instrumented, so MC/DC analysis ignores it + mir_transform_ffi_unwind_call = call to {$foreign -> [true] foreign function *[false] function pointer diff --git a/compiler/rustc_mir_transform/src/coverage/mappings.rs b/compiler/rustc_mir_transform/src/coverage/mappings.rs index c20f7a6f3263c..bc86ae22a0dbd 100644 --- a/compiler/rustc_mir_transform/src/coverage/mappings.rs +++ b/compiler/rustc_mir_transform/src/coverage/mappings.rs @@ -15,6 +15,7 @@ use crate::coverage::ExtractedHirInfo; use crate::coverage::graph::{BasicCoverageBlock, CoverageGraph, START_BCB}; use crate::coverage::spans::extract_refined_covspans; use crate::coverage::unexpand::unexpand_into_body_span; +use crate::errors::MCDCExceedsTestVectorLimit; /// Associates an ordinary executable code span with its corresponding BCB. #[derive(Debug)] @@ -108,6 +109,7 @@ pub(super) fn extract_all_mapping_info_from_mir<'tcx>( extract_mcdc_mappings( mir_body, + tcx, hir_info.body_span, basic_coverage_blocks, &mut mcdc_bitmap_bits, @@ -239,6 +241,7 @@ pub(super) fn extract_branch_pairs( pub(super) fn extract_mcdc_mappings( mir_body: &mir::Body<'_>, + tcx: TyCtxt<'_>, body_span: Span, basic_coverage_blocks: &CoverageGraph, mcdc_bitmap_bits: &mut usize, @@ -312,7 +315,10 @@ pub(super) fn extract_mcdc_mappings( } let num_test_vectors = calc_test_vectors_index(&mut branch_mappings); let Some(bitmap_idx) = get_bitmap_idx(num_test_vectors) else { - // TODO warn about bitmap + tcx.dcx().emit_warn(MCDCExceedsTestVectorLimit { + span: decision_span, + max_num_test_vectors: MCDC_MAX_BITMAP_SIZE, + }); mcdc_degraded_branches.extend(branch_mappings); return None; }; diff --git a/compiler/rustc_mir_transform/src/errors.rs b/compiler/rustc_mir_transform/src/errors.rs index fa279ace43139..8b309147c64cd 100644 --- a/compiler/rustc_mir_transform/src/errors.rs +++ b/compiler/rustc_mir_transform/src/errors.rs @@ -89,6 +89,14 @@ pub(crate) struct FnItemRef { pub ident: String, } +#[derive(Diagnostic)] +#[diag(mir_transform_exceeds_mcdc_test_vector_limit)] +pub(crate) struct MCDCExceedsTestVectorLimit { + #[primary_span] + pub(crate) span: Span, + pub(crate) max_num_test_vectors: usize, +} + pub(crate) struct MustNotSupend<'a, 'tcx> { pub tcx: TyCtxt<'tcx>, pub yield_sp: Span, From abf212c16cbc2fdef9dc4b515165f144c716f3d3 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 2 Oct 2024 17:38:42 +1000 Subject: [PATCH 2003/2194] Remove `OutlivesEnvironmentBuilder`. `OutlivesEnvironment::new` can call `OutlivesEnvironment::with_bounds` with an empty `extra_bounds`. And once that's done, `OutlivesEnvironmentBuilder` has a single use and can be inlined and removed into `OutlivesEnvironment::with_bounds`. --- .../rustc_infer/src/infer/outlives/env.rs | 87 ++++++------------- 1 file changed, 26 insertions(+), 61 deletions(-) diff --git a/compiler/rustc_infer/src/infer/outlives/env.rs b/compiler/rustc_infer/src/infer/outlives/env.rs index a071b84a1a00f..9300fc574dc29 100644 --- a/compiler/rustc_infer/src/infer/outlives/env.rs +++ b/compiler/rustc_infer/src/infer/outlives/env.rs @@ -1,8 +1,7 @@ use rustc_data_structures::fx::FxIndexSet; use rustc_data_structures::transitive_relation::TransitiveRelationBuilder; -use rustc_middle::bug; -use rustc_middle::ty::{self, Region}; -use tracing::{debug, instrument}; +use rustc_middle::{bug, ty}; +use tracing::debug; use super::explicit_outlives_bounds; use crate::infer::GenericKind; @@ -54,37 +53,16 @@ pub struct OutlivesEnvironment<'tcx> { region_bound_pairs: RegionBoundPairs<'tcx>, } -/// Builder of OutlivesEnvironment. -#[derive(Debug)] -struct OutlivesEnvironmentBuilder<'tcx> { - param_env: ty::ParamEnv<'tcx>, - region_relation: TransitiveRelationBuilder>, - region_bound_pairs: RegionBoundPairs<'tcx>, -} - /// "Region-bound pairs" tracks outlives relations that are known to /// be true, either because of explicit where-clauses like `T: 'a` or /// because of implied bounds. pub type RegionBoundPairs<'tcx> = FxIndexSet>>; impl<'tcx> OutlivesEnvironment<'tcx> { - /// Create a builder using `ParamEnv` and add explicit outlives bounds into it. - fn builder(param_env: ty::ParamEnv<'tcx>) -> OutlivesEnvironmentBuilder<'tcx> { - let mut builder = OutlivesEnvironmentBuilder { - param_env, - region_relation: Default::default(), - region_bound_pairs: Default::default(), - }; - - builder.add_outlives_bounds(explicit_outlives_bounds(param_env)); - - builder - } - - #[inline] /// Create a new `OutlivesEnvironment` without extra outlives bounds. + #[inline] pub fn new(param_env: ty::ParamEnv<'tcx>) -> Self { - Self::builder(param_env).build() + Self::with_bounds(param_env, vec![]) } /// Create a new `OutlivesEnvironment` with extra outlives bounds. @@ -92,56 +70,27 @@ impl<'tcx> OutlivesEnvironment<'tcx> { param_env: ty::ParamEnv<'tcx>, extra_bounds: impl IntoIterator>, ) -> Self { - let mut builder = Self::builder(param_env); - builder.add_outlives_bounds(extra_bounds); - builder.build() - } + let mut region_relation = TransitiveRelationBuilder::default(); + let mut region_bound_pairs = RegionBoundPairs::default(); - /// Borrows current value of the `free_region_map`. - pub fn free_region_map(&self) -> &FreeRegionMap<'tcx> { - &self.free_region_map - } - - /// Borrows current `region_bound_pairs`. - pub fn region_bound_pairs(&self) -> &RegionBoundPairs<'tcx> { - &self.region_bound_pairs - } -} - -impl<'tcx> OutlivesEnvironmentBuilder<'tcx> { - #[inline] - #[instrument(level = "debug")] - fn build(self) -> OutlivesEnvironment<'tcx> { - OutlivesEnvironment { - param_env: self.param_env, - free_region_map: FreeRegionMap { relation: self.region_relation.freeze() }, - region_bound_pairs: self.region_bound_pairs, - } - } - - /// Processes outlives bounds that are known to hold, whether from implied or other sources. - fn add_outlives_bounds(&mut self, outlives_bounds: I) - where - I: IntoIterator>, - { // Record relationships such as `T:'x` that don't go into the // free-region-map but which we use here. - for outlives_bound in outlives_bounds { + for outlives_bound in explicit_outlives_bounds(param_env).chain(extra_bounds) { debug!("add_outlives_bounds: outlives_bound={:?}", outlives_bound); match outlives_bound { OutlivesBound::RegionSubParam(r_a, param_b) => { - self.region_bound_pairs + region_bound_pairs .insert(ty::OutlivesPredicate(GenericKind::Param(param_b), r_a)); } OutlivesBound::RegionSubAlias(r_a, alias_b) => { - self.region_bound_pairs + region_bound_pairs .insert(ty::OutlivesPredicate(GenericKind::Alias(alias_b), r_a)); } OutlivesBound::RegionSubRegion(r_a, r_b) => match (*r_a, *r_b) { ( ty::ReStatic | ty::ReEarlyParam(_) | ty::ReLateParam(_), ty::ReStatic | ty::ReEarlyParam(_) | ty::ReLateParam(_), - ) => self.region_relation.add(r_a, r_b), + ) => region_relation.add(r_a, r_b), (ty::ReError(_), _) | (_, ty::ReError(_)) => {} // FIXME(#109628): We shouldn't have existential variables in implied bounds. // Panic here once the linked issue is resolved! @@ -150,5 +99,21 @@ impl<'tcx> OutlivesEnvironmentBuilder<'tcx> { }, } } + + OutlivesEnvironment { + param_env, + free_region_map: FreeRegionMap { relation: region_relation.freeze() }, + region_bound_pairs, + } + } + + /// Borrows current value of the `free_region_map`. + pub fn free_region_map(&self) -> &FreeRegionMap<'tcx> { + &self.free_region_map + } + + /// Borrows current `region_bound_pairs`. + pub fn region_bound_pairs(&self) -> &RegionBoundPairs<'tcx> { + &self.region_bound_pairs } } From 27dad009c61e6a21fc7cb438a08597cf0ec0b1c8 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 3 Oct 2024 09:25:41 +1000 Subject: [PATCH 2004/2194] Add a useful comment about `InferOk`. Prompted by #131134, which tried to remove `InferOk<'tcx, ()>` occurrences. --- compiler/rustc_infer/src/infer/mod.rs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index cb60d9f286b13..29936fadc57d8 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -67,6 +67,13 @@ pub mod resolve; pub(crate) mod snapshot; mod type_variable; +/// `InferOk<'tcx, ()>` is used a lot. It may seem like a useless wrapper +/// around `Vec>`, but it has one important property: +/// because `InferOk` is marked with `#[must_use]`, if you have a method +/// `InferCtxt::f` that returns `InferResult<'tcx, ()>` and you call it with +/// `infcx.f()?;` you'll get a warning about the obligations being discarded +/// without use, which is probably unintentional and has been a source of bugs +/// in the past. #[must_use] #[derive(Debug)] pub struct InferOk<'tcx, T> { From 0293827e093b233eda3a403a5238c164200bfc98 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 2 Oct 2024 14:07:57 +1000 Subject: [PATCH 2005/2194] Improve formatting of some comments. I.e. fixing comments lines that are too long or too short. --- compiler/rustc_infer/src/infer/mod.rs | 12 ++--- .../rustc_infer/src/infer/opaque_types/mod.rs | 10 ++-- .../src/infer/outlives/obligations.rs | 11 ++-- .../infer/region_constraints/leak_check.rs | 11 ++-- .../src/infer/relate/generalize.rs | 6 ++- compiler/rustc_infer/src/traits/project.rs | 53 ++++++++----------- 6 files changed, 50 insertions(+), 53 deletions(-) diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index 29936fadc57d8..f2cb28fd6f6f4 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -1011,8 +1011,8 @@ impl<'tcx> InferCtxt<'tcx> { ty::Const::new_infer(self.tcx, ty::InferConst::EffectVar(effect_vid)).into() } - /// Given a set of generics defined on a type or impl, returns the generic parameters mapping each - /// type/region parameter to a fresh inference variable. + /// Given a set of generics defined on a type or impl, returns the generic parameters mapping + /// each type/region parameter to a fresh inference variable. pub fn fresh_args_for_item(&self, span: Span, def_id: DefId) -> GenericArgsRef<'tcx> { GenericArgs::for_item(self.tcx, def_id, |param, _| self.var_for_def(span, param)) } @@ -1390,10 +1390,10 @@ impl<'tcx> InferCtxt<'tcx> { /// /// The constant can be located on a trait like `::C`, in which case the given /// generic parameters and environment are used to resolve the constant. Alternatively if the - /// constant has generic parameters in scope the instantiations are used to evaluate the value of - /// the constant. For example in `fn foo() { let _ = [0; bar::()]; }` the repeat count - /// constant `bar::()` requires a instantiation for `T`, if the instantiation for `T` is still - /// too generic for the constant to be evaluated then `Err(ErrorHandled::TooGeneric)` is + /// constant has generic parameters in scope the instantiations are used to evaluate the value + /// of the constant. For example in `fn foo() { let _ = [0; bar::()]; }` the repeat count + /// constant `bar::()` requires a instantiation for `T`, if the instantiation for `T` is + /// still too generic for the constant to be evaluated then `Err(ErrorHandled::TooGeneric)` is /// returned. /// /// This handles inferences variables within both `param_env` and `args` by diff --git a/compiler/rustc_infer/src/infer/opaque_types/mod.rs b/compiler/rustc_infer/src/infer/opaque_types/mod.rs index 5a2ffbf029eb2..365ddaba138ff 100644 --- a/compiler/rustc_infer/src/infer/opaque_types/mod.rs +++ b/compiler/rustc_infer/src/infer/opaque_types/mod.rs @@ -148,11 +148,11 @@ impl<'tcx> InferCtxt<'tcx> { } if let ty::Alias(ty::Opaque, ty::AliasTy { def_id: b_def_id, .. }) = *b.kind() { - // We could accept this, but there are various ways to handle this situation, and we don't - // want to make a decision on it right now. Likely this case is so super rare anyway, that - // no one encounters it in practice. - // It does occur however in `fn fut() -> impl Future { async { 42 } }`, - // where it is of no concern, so we only check for TAITs. + // We could accept this, but there are various ways to handle this situation, + // and we don't want to make a decision on it right now. Likely this case is so + // super rare anyway, that no one encounters it in practice. It does occur + // however in `fn fut() -> impl Future { async { 42 } }`, where + // it is of no concern, so we only check for TAITs. if self.can_define_opaque_ty(b_def_id) && self.tcx.is_type_alias_impl_trait(b_def_id) { diff --git a/compiler/rustc_infer/src/infer/outlives/obligations.rs b/compiler/rustc_infer/src/infer/outlives/obligations.rs index 634cda86bc338..e0e03a2922010 100644 --- a/compiler/rustc_infer/src/infer/outlives/obligations.rs +++ b/compiler/rustc_infer/src/infer/outlives/obligations.rs @@ -396,11 +396,12 @@ where // 'a` in the environment but `trait Foo<'b> { type Item: 'b // }` in the trait definition. approx_env_bounds.retain(|bound_outlives| { - // OK to skip binder because we only manipulate and compare against other - // values from the same binder. e.g. if we have (e.g.) `for<'a> >::Item: 'a` - // in `bound`, the `'a` will be a `^1` (bound, debruijn index == innermost) region. - // If the declaration is `trait Trait<'b> { type Item: 'b; }`, then `projection_declared_bounds_from_trait` - // will be invoked with `['b => ^1]` and so we will get `^1` returned. + // OK to skip binder because we only manipulate and compare against other values from + // the same binder. e.g. if we have (e.g.) `for<'a> >::Item: 'a` in + // `bound`, the `'a` will be a `^1` (bound, debruijn index == innermost) region. If the + // declaration is `trait Trait<'b> { type Item: 'b; }`, then + // `projection_declared_bounds_from_trait` will be invoked with `['b => ^1]` and so we + // will get `^1` returned. let bound = bound_outlives.skip_binder(); let ty::Alias(_, alias_ty) = bound.0.kind() else { bug!("expected AliasTy") }; self.verify_bound.declared_bounds_from_definition(*alias_ty).all(|r| r != bound.1) diff --git a/compiler/rustc_infer/src/infer/region_constraints/leak_check.rs b/compiler/rustc_infer/src/infer/region_constraints/leak_check.rs index 7913f0e340e09..30eba3e8f4fb7 100644 --- a/compiler/rustc_infer/src/infer/region_constraints/leak_check.rs +++ b/compiler/rustc_infer/src/infer/region_constraints/leak_check.rs @@ -55,8 +55,8 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> { /// * what placeholder they must outlive transitively /// * if they must also be equal to a placeholder, report an error because `P1: P2` /// * minimum universe U of all SCCs they must outlive - /// * if they must also be equal to a placeholder P, and U cannot name P, report an error, as that - /// indicates `P: R` and `R` is in an incompatible universe + /// * if they must also be equal to a placeholder P, and U cannot name P, report an error, as + /// that indicates `P: R` and `R` is in an incompatible universe /// /// To improve performance and for the old trait solver caching to be sound, this takes /// an optional snapshot in which case we only look at region constraints added in that @@ -216,8 +216,8 @@ impl<'a, 'b, 'tcx> LeakCheck<'a, 'b, 'tcx> { // Walk over each `scc2` such that `scc1: scc2` and compute: // // * `scc1_universe`: the minimum universe of `scc2` and the constituents of `scc1` - // * `succ_bound`: placeholder `P` that the successors must outlive, if any (if there are multiple, - // we pick one arbitrarily) + // * `succ_bound`: placeholder `P` that the successors must outlive, if any (if there + // are multiple, we pick one arbitrarily) let mut scc1_universe = self.scc_universes[scc1]; let mut succ_bound = None; for &scc2 in self.mini_graph.sccs.successors(scc1) { @@ -260,7 +260,8 @@ impl<'a, 'b, 'tcx> LeakCheck<'a, 'b, 'tcx> { self.scc_placeholders[scc1] = succ_bound; } - // At this point, `scc_placeholder[scc1]` stores some placeholder that `scc1` must outlive (if any). + // At this point, `scc_placeholder[scc1]` stores some placeholder that `scc1` must + // outlive (if any). } Ok(()) } diff --git a/compiler/rustc_infer/src/infer/relate/generalize.rs b/compiler/rustc_infer/src/infer/relate/generalize.rs index a6d10aa5968c7..726a2296d11a3 100644 --- a/compiler/rustc_infer/src/infer/relate/generalize.rs +++ b/compiler/rustc_infer/src/infer/relate/generalize.rs @@ -50,7 +50,8 @@ impl<'tcx> InferCtxt<'tcx> { // Then the `generalized_ty` would be `&'?2 ?3`, where `'?2` and `?3` are fresh // region/type inference variables. // - // We then relate `generalized_ty <: source_ty`,adding constraints like `'x: '?2` and `?1 <: ?3`. + // We then relate `generalized_ty <: source_ty`, adding constraints like `'x: '?2` and + // `?1 <: ?3`. let Generalization { value_may_be_infer: generalized_ty, has_unconstrained_ty_var } = self .generalize( relation.span(), @@ -104,7 +105,8 @@ impl<'tcx> InferCtxt<'tcx> { &ty::Alias(ty::Projection, data) => { // FIXME: This does not handle subtyping correctly, we could // instead create a new inference variable `?normalized_source`, emitting - // `Projection(normalized_source, ?ty_normalized)` and `?normalized_source <: generalized_ty`. + // `Projection(normalized_source, ?ty_normalized)` and + // `?normalized_source <: generalized_ty`. relation.register_predicates([ty::ProjectionPredicate { projection_term: data.into(), term: generalized_ty.into(), diff --git a/compiler/rustc_infer/src/traits/project.rs b/compiler/rustc_infer/src/traits/project.rs index fa813d0f90ca0..64b72de398622 100644 --- a/compiler/rustc_infer/src/traits/project.rs +++ b/compiler/rustc_infer/src/traits/project.rs @@ -92,38 +92,31 @@ pub enum ProjectionCacheEntry<'tcx> { Error, NormalizedTerm { ty: NormalizedTerm<'tcx>, - /// If we were able to successfully evaluate the - /// corresponding cache entry key during predicate - /// evaluation, then this field stores the final - /// result obtained from evaluating all of the projection - /// sub-obligations. During evaluation, we will skip - /// evaluating the cached sub-obligations in `ty` - /// if this field is set. Evaluation only - /// cares about the final result, so we don't - /// care about any region constraint side-effects - /// produced by evaluating the sub-obligations. + /// If we were able to successfully evaluate the corresponding cache + /// entry key during predicate evaluation, then this field stores the + /// final result obtained from evaluating all of the projection + /// sub-obligations. During evaluation, we will skip evaluating the + /// cached sub-obligations in `ty` if this field is set. Evaluation + /// only cares about the final result, so we don't care about any + /// region constraint side-effects produced by evaluating the + /// sub-obligations. /// - /// Additionally, we will clear out the sub-obligations - /// entirely if we ever evaluate the cache entry (along - /// with all its sub obligations) to `EvaluatedToOk`. - /// This affects all users of the cache, not just evaluation. - /// Since a result of `EvaluatedToOk` means that there were - /// no region obligations that need to be tracked, it's - /// fine to forget about the sub-obligations - they - /// don't provide any additional information. However, - /// we do *not* discard any obligations when we see - /// `EvaluatedToOkModuloRegions` - we don't know - /// which sub-obligations may introduce region constraints, - /// so we keep them all to be safe. + /// Additionally, we will clear out the sub-obligations entirely if we + /// ever evaluate the cache entry (along with all its sub obligations) + /// to `EvaluatedToOk`. This affects all users of the cache, not just + /// evaluation. Since a result of `EvaluatedToOk` means that there were + /// no region obligations that need to be tracked, it's fine to forget + /// about the sub-obligations - they don't provide any additional + /// information. However, we do *not* discard any obligations when we + /// see `EvaluatedToOkModuloRegions` - we don't know which + /// sub-obligations may introduce region constraints, so we keep them + /// all to be safe. /// - /// When we are not performing evaluation - /// (e.g. in `FulfillmentContext`), we ignore this field, - /// and always re-process the cached sub-obligations - /// (which may have been cleared out - see the above - /// paragraph). - /// This ensures that we do not lose any regions - /// constraints that arise from processing the - /// sub-obligations. + /// When we are not performing evaluation (e.g. in + /// `FulfillmentContext`), we ignore this field, and always re-process + /// the cached sub-obligations (which may have been cleared out - see + /// the above paragraph). This ensures that we do not lose any regions + /// constraints that arise from processing the sub-obligations. complete: Option, }, } From 2b57a785a917faa8a1c44414ed3d43e13e626f63 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 3 Oct 2024 10:44:48 +1000 Subject: [PATCH 2006/2194] Inline and remove `RegionConstraintCollector::into_infos_and_data`. It's a weird method, and used weirdly: - It's on `RegionConstraintCollector` but operates on `RegionConstraintStorage`. So at both call sites we create a temporary `RegionConstraintCollector`, using `with_log`, to call it. - It `take`s just two of the six fields in `RegionConstraintStorage`. At one of the two call sites we unnecessarily clone the entire `RegionConstraintStorage` just to take those two fields. This commit just inlines and removes it. We no longer need to `take` the two fields, we can just use them directly. --- compiler/rustc_infer/src/infer/mod.rs | 23 ++++++++----------- .../rustc_infer/src/infer/outlives/mod.rs | 15 +++++------- .../src/infer/region_constraints/mod.rs | 12 ++-------- 3 files changed, 18 insertions(+), 32 deletions(-) diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index f2cb28fd6f6f4..785ef8f939e14 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -18,7 +18,7 @@ pub use relate::combine::PredicateEmittingRelation; use rustc_data_structures::captures::Captures; use rustc_data_structures::fx::{FxHashSet, FxIndexMap}; use rustc_data_structures::sync::Lrc; -use rustc_data_structures::undo_log::Rollback; +use rustc_data_structures::undo_log::{Rollback, UndoLogs}; use rustc_data_structures::unify as ut; use rustc_errors::{DiagCtxtHandle, ErrorGuaranteed}; use rustc_hir as hir; @@ -50,6 +50,7 @@ use snapshot::undo_log::InferCtxtUndoLogs; use tracing::{debug, instrument}; use type_variable::TypeVariableOrigin; +use crate::infer::region_constraints::UndoLog; use crate::traits::{self, ObligationCause, ObligationInspector, PredicateObligation, TraitEngine}; pub mod at; @@ -1043,18 +1044,14 @@ impl<'tcx> InferCtxt<'tcx> { /// Clone the list of variable regions. This is used only during NLL processing /// to put the set of region variables into the NLL region context. pub fn get_region_var_origins(&self) -> VarInfos { - let mut inner = self.inner.borrow_mut(); - let (var_infos, data) = inner - .region_constraint_storage - // We clone instead of taking because borrowck still wants to use - // the inference context after calling this for diagnostics - // and the new trait solver. - .clone() - .expect("regions already resolved") - .with_log(&mut inner.undo_log) - .into_infos_and_data(); - assert!(data.is_empty()); - var_infos + let inner = self.inner.borrow(); + assert!(!UndoLogs::>::in_snapshot(&inner.undo_log)); + let storage = inner.region_constraint_storage.as_ref().expect("regions already resolved"); + assert!(storage.data.is_empty()); + // We clone instead of taking because borrowck still wants to use the + // inference context after calling this for diagnostics and the new + // trait solver. + storage.var_infos.clone() } #[instrument(level = "debug", skip(self), ret)] diff --git a/compiler/rustc_infer/src/infer/outlives/mod.rs b/compiler/rustc_infer/src/infer/outlives/mod.rs index a270f9322f39b..e23bb1aaa5631 100644 --- a/compiler/rustc_infer/src/infer/outlives/mod.rs +++ b/compiler/rustc_infer/src/infer/outlives/mod.rs @@ -1,11 +1,12 @@ //! Various code related to computing outlives relations. +use rustc_data_structures::undo_log::UndoLogs; use rustc_middle::traits::query::{NoSolution, OutlivesBound}; use rustc_middle::ty; use tracing::instrument; use self::env::OutlivesEnvironment; -use super::region_constraints::RegionConstraintData; +use super::region_constraints::{RegionConstraintData, UndoLog}; use super::{InferCtxt, RegionResolutionError, SubregionOrigin}; use crate::infer::free_regions::RegionRelations; use crate::infer::lexical_region_resolve; @@ -63,7 +64,7 @@ impl<'tcx> InferCtxt<'tcx> { } }; - let (var_infos, data) = { + let storage = { let mut inner = self.inner.borrow_mut(); let inner = &mut *inner; assert!( @@ -71,18 +72,14 @@ impl<'tcx> InferCtxt<'tcx> { "region_obligations not empty: {:#?}", inner.region_obligations ); - inner - .region_constraint_storage - .take() - .expect("regions already resolved") - .with_log(&mut inner.undo_log) - .into_infos_and_data() + assert!(!UndoLogs::>::in_snapshot(&inner.undo_log)); + inner.region_constraint_storage.take().expect("regions already resolved") }; let region_rels = &RegionRelations::new(self.tcx, outlives_env.free_region_map()); let (lexical_region_resolutions, errors) = - lexical_region_resolve::resolve(region_rels, var_infos, data); + lexical_region_resolve::resolve(region_rels, storage.var_infos, storage.data); let old_value = self.lexical_region_resolutions.replace(Some(lexical_region_resolutions)); assert!(old_value.is_none()); diff --git a/compiler/rustc_infer/src/infer/region_constraints/mod.rs b/compiler/rustc_infer/src/infer/region_constraints/mod.rs index 4411f8db72a1e..0d9249bb552d8 100644 --- a/compiler/rustc_infer/src/infer/region_constraints/mod.rs +++ b/compiler/rustc_infer/src/infer/region_constraints/mod.rs @@ -27,9 +27,9 @@ pub use rustc_middle::infer::MemberConstraint; #[derive(Clone, Default)] pub struct RegionConstraintStorage<'tcx> { /// For each `RegionVid`, the corresponding `RegionVariableOrigin`. - var_infos: IndexVec, + pub(super) var_infos: IndexVec, - data: RegionConstraintData<'tcx>, + pub(super) data: RegionConstraintData<'tcx>, /// For a given pair of regions (R1, R2), maps to a region R3 that /// is designated as their LUB (edges R1 <= R3 and R2 <= R3 @@ -354,14 +354,6 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> { &self.data } - /// Once all the constraints have been gathered, extract out the final data. - /// - /// Not legal during a snapshot. - pub fn into_infos_and_data(self) -> (VarInfos, RegionConstraintData<'tcx>) { - assert!(!UndoLogs::>::in_snapshot(&self.undo_log)); - (mem::take(&mut self.storage.var_infos), mem::take(&mut self.storage.data)) - } - /// Takes (and clears) the current set of constraints. Note that /// the set of variables remains intact, but all relationships /// between them are reset. This is used during NLL checking to From 85507cffc32de9211f03b5e257acfad4a24fcea5 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 3 Oct 2024 12:06:34 +1000 Subject: [PATCH 2007/2194] Inline and remove `RegionConstraintStorage::remove_constraint_entry`. It has a single call site. --- .../src/infer/region_constraints/mod.rs | 44 +++++++++---------- 1 file changed, 20 insertions(+), 24 deletions(-) diff --git a/compiler/rustc_infer/src/infer/region_constraints/mod.rs b/compiler/rustc_infer/src/infer/region_constraints/mod.rs index 0d9249bb552d8..a60954ad545d8 100644 --- a/compiler/rustc_infer/src/infer/region_constraints/mod.rs +++ b/compiler/rustc_infer/src/infer/region_constraints/mod.rs @@ -320,29 +320,6 @@ impl<'tcx> RegionConstraintStorage<'tcx> { ) -> RegionConstraintCollector<'a, 'tcx> { RegionConstraintCollector { storage: self, undo_log } } - - fn rollback_undo_entry(&mut self, undo_entry: UndoLog<'tcx>) { - match undo_entry { - AddVar(vid) => { - self.var_infos.pop().unwrap(); - assert_eq!(self.var_infos.len(), vid.index()); - } - AddConstraint(index) => { - self.data.constraints.pop().unwrap(); - assert_eq!(self.data.constraints.len(), index); - } - AddVerify(index) => { - self.data.verifys.pop(); - assert_eq!(self.data.verifys.len(), index); - } - AddCombination(Glb, ref regions) => { - self.glbs.remove(regions); - } - AddCombination(Lub, ref regions) => { - self.lubs.remove(regions); - } - } - } } impl<'tcx> RegionConstraintCollector<'_, 'tcx> { @@ -793,6 +770,25 @@ impl<'tcx> RegionConstraintData<'tcx> { impl<'tcx> Rollback> for RegionConstraintStorage<'tcx> { fn reverse(&mut self, undo: UndoLog<'tcx>) { - self.rollback_undo_entry(undo) + match undo { + AddVar(vid) => { + self.var_infos.pop().unwrap(); + assert_eq!(self.var_infos.len(), vid.index()); + } + AddConstraint(index) => { + self.data.constraints.pop().unwrap(); + assert_eq!(self.data.constraints.len(), index); + } + AddVerify(index) => { + self.data.verifys.pop(); + assert_eq!(self.data.verifys.len(), index); + } + AddCombination(Glb, ref regions) => { + self.glbs.remove(regions); + } + AddCombination(Lub, ref regions) => { + self.lubs.remove(regions); + } + } } } From e8a0bd65498976656fbb7fff7d74fbc91cc442d1 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 3 Oct 2024 13:58:13 +1000 Subject: [PATCH 2008/2194] Remove unnecessary lifetime from `LeakCheck`. `LeakCheck` can own `mini_graph` and `rcc` instead of holding references to them. This requires inlining `assign_scc_value` to avoid a borrowck error, but that's fine because it has a single call site. --- .../infer/region_constraints/leak_check.rs | 54 ++++++++----------- 1 file changed, 22 insertions(+), 32 deletions(-) diff --git a/compiler/rustc_infer/src/infer/region_constraints/leak_check.rs b/compiler/rustc_infer/src/infer/region_constraints/leak_check.rs index 30eba3e8f4fb7..3cfc58dea05bd 100644 --- a/compiler/rustc_infer/src/infer/region_constraints/leak_check.rs +++ b/compiler/rustc_infer/src/infer/region_constraints/leak_check.rs @@ -73,7 +73,7 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> { /// * R: P1, R: P2, as above #[instrument(level = "debug", skip(self, tcx, only_consider_snapshot), ret)] pub fn leak_check( - &mut self, + self, tcx: TyCtxt<'tcx>, outer_universe: ty::UniverseIndex, max_universe: ty::UniverseIndex, @@ -83,7 +83,7 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> { return Ok(()); } - let mini_graph = &MiniGraph::new(tcx, self, only_consider_snapshot); + let mini_graph = MiniGraph::new(tcx, &self, only_consider_snapshot); let mut leak_check = LeakCheck::new(tcx, outer_universe, max_universe, mini_graph, self); leak_check.assign_placeholder_values()?; @@ -92,11 +92,11 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> { } } -struct LeakCheck<'a, 'b, 'tcx> { +struct LeakCheck<'a, 'tcx> { tcx: TyCtxt<'tcx>, outer_universe: ty::UniverseIndex, - mini_graph: &'a MiniGraph<'tcx>, - rcc: &'a mut RegionConstraintCollector<'b, 'tcx>, + mini_graph: MiniGraph<'tcx>, + rcc: RegionConstraintCollector<'a, 'tcx>, // Initially, for each SCC S, stores a placeholder `P` such that `S = P` // must hold. @@ -115,26 +115,27 @@ struct LeakCheck<'a, 'b, 'tcx> { // either the placeholder `P1` or the empty region in that same universe. // // To detect errors, we look for an SCC S where the values in - // `scc_values[S]` (if any) cannot be stored into `scc_universes[S]`. + // `scc_placeholders[S]` (if any) cannot be stored into `scc_universes[S]`. scc_universes: IndexVec>, } -impl<'a, 'b, 'tcx> LeakCheck<'a, 'b, 'tcx> { +impl<'a, 'tcx> LeakCheck<'a, 'tcx> { fn new( tcx: TyCtxt<'tcx>, outer_universe: ty::UniverseIndex, max_universe: ty::UniverseIndex, - mini_graph: &'a MiniGraph<'tcx>, - rcc: &'a mut RegionConstraintCollector<'b, 'tcx>, + mini_graph: MiniGraph<'tcx>, + rcc: RegionConstraintCollector<'a, 'tcx>, ) -> Self { let dummy_scc_universe = SccUniverse { universe: max_universe, region: None }; + let num_sccs = mini_graph.sccs.num_sccs(); Self { tcx, outer_universe, mini_graph, rcc, - scc_placeholders: IndexVec::from_elem_n(None, mini_graph.sccs.num_sccs()), - scc_universes: IndexVec::from_elem_n(dummy_scc_universe, mini_graph.sccs.num_sccs()), + scc_placeholders: IndexVec::from_elem_n(None, num_sccs), + scc_universes: IndexVec::from_elem_n(dummy_scc_universe, num_sccs), } } @@ -156,7 +157,16 @@ impl<'a, 'b, 'tcx> LeakCheck<'a, 'b, 'tcx> { // Detect those SCCs that directly contain a placeholder if let ty::RePlaceholder(placeholder) = **region { if self.outer_universe.cannot_name(placeholder.universe) { - self.assign_scc_value(scc, placeholder)?; + // Update `scc_placeholders` to account for the fact that `P: S` must hold. + match self.scc_placeholders[scc] { + Some(p) => { + assert_ne!(p, placeholder); + return Err(self.placeholder_error(p, placeholder)); + } + None => { + self.scc_placeholders[scc] = Some(placeholder); + } + } } } } @@ -164,26 +174,6 @@ impl<'a, 'b, 'tcx> LeakCheck<'a, 'b, 'tcx> { Ok(()) } - // assign_scc_value(S, P): Update `scc_values` to account for the fact that `P: S` must hold. - // This may create an error. - fn assign_scc_value( - &mut self, - scc: LeakCheckScc, - placeholder: ty::PlaceholderRegion, - ) -> RelateResult<'tcx, ()> { - match self.scc_placeholders[scc] { - Some(p) => { - assert_ne!(p, placeholder); - return Err(self.placeholder_error(p, placeholder)); - } - None => { - self.scc_placeholders[scc] = Some(placeholder); - } - }; - - Ok(()) - } - /// For each SCC S, iterate over each successor S1 where `S: S1`: /// /// * Compute From 8b05df44f96978b81df4af51f469c266b21df793 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 3 Oct 2024 14:16:55 +1000 Subject: [PATCH 2009/2194] Remove `Deref`/`DerefMut` impls for `RegionConstraintCollector`. `Deref`/`DerefMut` can be useful, but they can also obfuscate. I don't think they're worth it for `RegionConstraintCollector`. They're also not present on the similar types `OpaqueTypeTable` and `TypeVariableTable`. --- .../src/infer/region_constraints/mod.rs | 50 +++++++------------ 1 file changed, 18 insertions(+), 32 deletions(-) diff --git a/compiler/rustc_infer/src/infer/region_constraints/mod.rs b/compiler/rustc_infer/src/infer/region_constraints/mod.rs index a60954ad545d8..c7dd65330be50 100644 --- a/compiler/rustc_infer/src/infer/region_constraints/mod.rs +++ b/compiler/rustc_infer/src/infer/region_constraints/mod.rs @@ -61,21 +61,6 @@ pub struct RegionConstraintCollector<'a, 'tcx> { undo_log: &'a mut InferCtxtUndoLogs<'tcx>, } -impl<'tcx> std::ops::Deref for RegionConstraintCollector<'_, 'tcx> { - type Target = RegionConstraintStorage<'tcx>; - #[inline] - fn deref(&self) -> &RegionConstraintStorage<'tcx> { - self.storage - } -} - -impl<'tcx> std::ops::DerefMut for RegionConstraintCollector<'_, 'tcx> { - #[inline] - fn deref_mut(&mut self) -> &mut RegionConstraintStorage<'tcx> { - self.storage - } -} - pub type VarInfos = IndexVec; /// The full set of region constraints gathered up by the collector. @@ -324,11 +309,11 @@ impl<'tcx> RegionConstraintStorage<'tcx> { impl<'tcx> RegionConstraintCollector<'_, 'tcx> { pub fn num_region_vars(&self) -> usize { - self.var_infos.len() + self.storage.var_infos.len() } pub fn region_constraint_data(&self) -> &RegionConstraintData<'tcx> { - &self.data + &self.storage.data } /// Takes (and clears) the current set of constraints. Note that @@ -384,17 +369,17 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> { } pub fn data(&self) -> &RegionConstraintData<'tcx> { - &self.data + &self.storage.data } pub(super) fn start_snapshot(&mut self) -> RegionSnapshot { debug!("RegionConstraintCollector: start_snapshot"); - RegionSnapshot { any_unifications: self.any_unifications } + RegionSnapshot { any_unifications: self.storage.any_unifications } } pub(super) fn rollback_to(&mut self, snapshot: RegionSnapshot) { debug!("RegionConstraintCollector: rollback_to({:?})", snapshot); - self.any_unifications = snapshot.any_unifications; + self.storage.any_unifications = snapshot.any_unifications; } pub(super) fn new_region_var( @@ -402,7 +387,7 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> { universe: ty::UniverseIndex, origin: RegionVariableOrigin, ) -> RegionVid { - let vid = self.var_infos.push(RegionVariableInfo { origin, universe }); + let vid = self.storage.var_infos.push(RegionVariableInfo { origin, universe }); let u_vid = self.unification_table_mut().new_key(RegionVariableValue::Unknown { universe }); assert_eq!(vid, u_vid.vid); @@ -413,7 +398,7 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> { /// Returns the origin for the given variable. pub(super) fn var_origin(&self, vid: RegionVid) -> RegionVariableOrigin { - self.var_infos[vid].origin + self.storage.var_infos[vid].origin } fn add_constraint(&mut self, constraint: Constraint<'tcx>, origin: SubregionOrigin<'tcx>) { @@ -436,8 +421,8 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> { return; } - let index = self.data.verifys.len(); - self.data.verifys.push(verify); + let index = self.storage.data.verifys.len(); + self.storage.data.verifys.push(verify); self.undo_log.push(AddVerify(index)); } @@ -457,7 +442,7 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> { (ty::ReVar(a), ty::ReVar(b)) => { debug!("make_eqregion: unifying {:?} with {:?}", a, b); if self.unification_table_mut().unify_var_var(a, b).is_ok() { - self.any_unifications = true; + self.storage.any_unifications = true; } } (ty::ReVar(vid), _) => { @@ -467,7 +452,7 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> { .unify_var_value(vid, RegionVariableValue::Known { value: b }) .is_ok() { - self.any_unifications = true; + self.storage.any_unifications = true; }; } (_, ty::ReVar(vid)) => { @@ -477,7 +462,7 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> { .unify_var_value(vid, RegionVariableValue::Known { value: a }) .is_ok() { - self.any_unifications = true; + self.storage.any_unifications = true; }; } (_, _) => {} @@ -499,7 +484,7 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> { return; } - self.data.member_constraints.push(MemberConstraint { + self.storage.data.member_constraints.push(MemberConstraint { key, definition_span, hidden_ty, @@ -615,8 +600,8 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> { fn combine_map(&mut self, t: CombineMapType) -> &mut CombineMap<'tcx> { match t { - Glb => &mut self.glbs, - Lub => &mut self.lubs, + Glb => &mut self.storage.glbs, + Lub => &mut self.storage.lubs, } } @@ -669,11 +654,12 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> { &self, value_count: usize, ) -> (Range, Vec) { - let range = RegionVid::from(value_count)..RegionVid::from(self.unification_table.len()); + let range = + RegionVid::from(value_count)..RegionVid::from(self.storage.unification_table.len()); ( range.clone(), (range.start.index()..range.end.index()) - .map(|index| self.var_infos[ty::RegionVid::from(index)].origin) + .map(|index| self.storage.var_infos[ty::RegionVid::from(index)].origin) .collect(), ) } From 4df21f2ca0a51e0687fd7443c99ed32edb080988 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 3 Oct 2024 14:33:28 +1000 Subject: [PATCH 2010/2194] Downgrade a `&mut self` to `&self`. --- compiler/rustc_infer/src/infer/region_constraints/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_infer/src/infer/region_constraints/mod.rs b/compiler/rustc_infer/src/infer/region_constraints/mod.rs index c7dd65330be50..6a7f30a5dcf5d 100644 --- a/compiler/rustc_infer/src/infer/region_constraints/mod.rs +++ b/compiler/rustc_infer/src/infer/region_constraints/mod.rs @@ -372,7 +372,7 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> { &self.storage.data } - pub(super) fn start_snapshot(&mut self) -> RegionSnapshot { + pub(super) fn start_snapshot(&self) -> RegionSnapshot { debug!("RegionConstraintCollector: start_snapshot"); RegionSnapshot { any_unifications: self.storage.any_unifications } } From 1dac23f6fef62faf178d3bbdab15b99fc19abafa Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 3 Oct 2024 14:40:05 +1000 Subject: [PATCH 2011/2194] Use `Default` more in `InferCtxtInner`. --- compiler/rustc_infer/src/infer/mod.rs | 12 ++++++------ .../rustc_infer/src/infer/region_constraints/mod.rs | 4 ---- compiler/rustc_infer/src/infer/type_variable.rs | 9 +-------- 3 files changed, 7 insertions(+), 18 deletions(-) diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index 785ef8f939e14..21f9bf028d5ea 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -171,12 +171,12 @@ impl<'tcx> InferCtxtInner<'tcx> { undo_log: InferCtxtUndoLogs::default(), projection_cache: Default::default(), - type_variable_storage: type_variable::TypeVariableStorage::new(), - const_unification_storage: ut::UnificationTableStorage::new(), - int_unification_storage: ut::UnificationTableStorage::new(), - float_unification_storage: ut::UnificationTableStorage::new(), - effect_unification_storage: ut::UnificationTableStorage::new(), - region_constraint_storage: Some(RegionConstraintStorage::new()), + type_variable_storage: Default::default(), + const_unification_storage: Default::default(), + int_unification_storage: Default::default(), + float_unification_storage: Default::default(), + effect_unification_storage: Default::default(), + region_constraint_storage: Some(Default::default()), region_obligations: vec![], opaque_type_storage: Default::default(), } diff --git a/compiler/rustc_infer/src/infer/region_constraints/mod.rs b/compiler/rustc_infer/src/infer/region_constraints/mod.rs index 6a7f30a5dcf5d..270217e26b78c 100644 --- a/compiler/rustc_infer/src/infer/region_constraints/mod.rs +++ b/compiler/rustc_infer/src/infer/region_constraints/mod.rs @@ -294,10 +294,6 @@ pub(crate) struct RegionSnapshot { } impl<'tcx> RegionConstraintStorage<'tcx> { - pub fn new() -> Self { - Self::default() - } - #[inline] pub(crate) fn with_log<'a>( &'a mut self, diff --git a/compiler/rustc_infer/src/infer/type_variable.rs b/compiler/rustc_infer/src/infer/type_variable.rs index c50477b2922be..779ce976becc0 100644 --- a/compiler/rustc_infer/src/infer/type_variable.rs +++ b/compiler/rustc_infer/src/infer/type_variable.rs @@ -19,7 +19,7 @@ impl<'tcx> Rollback>>> for TypeVariabl } } -#[derive(Clone)] +#[derive(Clone, Default)] pub(crate) struct TypeVariableStorage<'tcx> { /// The origins of each type variable. values: IndexVec, @@ -74,13 +74,6 @@ impl<'tcx> TypeVariableValue<'tcx> { } impl<'tcx> TypeVariableStorage<'tcx> { - pub(crate) fn new() -> TypeVariableStorage<'tcx> { - TypeVariableStorage { - values: Default::default(), - eq_relations: ut::UnificationTableStorage::new(), - } - } - #[inline] pub(crate) fn with_log<'a>( &'a mut self, From 3b1eee775550530c51131161d3b397517ef69f10 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 7 Oct 2024 10:01:37 +1100 Subject: [PATCH 2012/2194] Remove unnecessary `return` keyword. --- compiler/rustc_infer/src/infer/resolve.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_infer/src/infer/resolve.rs b/compiler/rustc_infer/src/infer/resolve.rs index 025c3a629fabf..64cc76f827eb8 100644 --- a/compiler/rustc_infer/src/infer/resolve.rs +++ b/compiler/rustc_infer/src/infer/resolve.rs @@ -38,7 +38,7 @@ impl<'a, 'tcx> TypeFolder> for OpportunisticVarResolver<'a, 'tcx> { if !t.has_non_region_infer() { t // micro-optimize -- if there is nothing in this type that this fold affects... } else if let Some(&ty) = self.cache.get(&t) { - return ty; + ty } else { let shallow = self.infcx.shallow_resolve(t); let res = shallow.super_fold_with(self); From b81a3c81998b03cab4925801edf11c3113b26184 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=AE=B8=E6=9D=B0=E5=8F=8B=20Jieyou=20Xu=20=28Joe=29?= Date: Tue, 8 Oct 2024 04:30:19 +0000 Subject: [PATCH 2013/2194] Drop compiletest legacy directive checks Sufficient time has passed (> 6 months) since we migrated from `//` to `//@`, so let's drop the legacy directive check as it causes friction due to false positives. --- src/tools/compiletest/src/header.rs | 129 +++++++----------- .../test-auxillary/known_legacy_directive.rs | 1 - src/tools/compiletest/src/header/tests.rs | 11 -- 3 files changed, 48 insertions(+), 93 deletions(-) delete mode 100644 src/tools/compiletest/src/header/test-auxillary/known_legacy_directive.rs diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs index 83a10c5620864..a6830a6aa173f 100644 --- a/src/tools/compiletest/src/header.rs +++ b/src/tools/compiletest/src/header.rs @@ -5,9 +5,7 @@ use std::io::BufReader; use std::io::prelude::*; use std::path::{Path, PathBuf}; use std::process::Command; -use std::sync::OnceLock; -use regex::Regex; use tracing::*; use crate::common::{Config, Debugger, FailMode, Mode, PassMode}; @@ -797,7 +795,6 @@ struct HeaderLine<'ln> { pub(crate) struct CheckDirectiveResult<'ln> { is_known_directive: bool, - directive_name: &'ln str, trailing_directive: Option<&'ln str>, } @@ -832,11 +829,7 @@ pub(crate) fn check_directive<'a>( } .then_some(trailing); - CheckDirectiveResult { - is_known_directive: is_known(&directive_name), - directive_name: directive_ln, - trailing_directive, - } + CheckDirectiveResult { is_known_directive: is_known(&directive_name), trailing_directive } } fn iter_header( @@ -851,16 +844,17 @@ fn iter_header( return; } - // Coverage tests in coverage-run mode always have these extra directives, - // without needing to specify them manually in every test file. - // (Some of the comments below have been copied over from the old - // `tests/run-make/coverage-reports/Makefile`, which no longer exists.) + // Coverage tests in coverage-run mode always have these extra directives, without needing to + // specify them manually in every test file. (Some of the comments below have been copied over + // from the old `tests/run-make/coverage-reports/Makefile`, which no longer exists.) + // + // FIXME(jieyouxu): I feel like there's a better way to do this, leaving for later. if mode == Mode::CoverageRun { let extra_directives: &[&str] = &[ "needs-profiler-support", - // FIXME(pietroalbini): this test currently does not work on cross-compiled - // targets because remote-test is not capable of sending back the *.profraw - // files generated by the LLVM instrumentation. + // FIXME(pietroalbini): this test currently does not work on cross-compiled targets + // because remote-test is not capable of sending back the *.profraw files generated by + // the LLVM instrumentation. "ignore-cross-compile", ]; // Process the extra implied directives, with a dummy line number of 0. @@ -869,17 +863,13 @@ fn iter_header( } } + // NOTE(jieyouxu): once we get rid of `Makefile`s we can unconditionally check for `//@`. let comment = if testfile.extension().is_some_and(|e| e == "rs") { "//@" } else { "#" }; let mut rdr = BufReader::with_capacity(1024, rdr); let mut ln = String::new(); let mut line_number = 0; - // Match on error annotations like `//~ERROR`. - static REVISION_MAGIC_COMMENT_RE: OnceLock = OnceLock::new(); - let revision_magic_comment_re = - REVISION_MAGIC_COMMENT_RE.get_or_init(|| Regex::new("//(\\[.*\\])?~.*").unwrap()); - loop { line_number += 1; ln.clear(); @@ -892,85 +882,62 @@ fn iter_header( // with a warm page cache. Maybe with a cold one. let original_line = &ln; let ln = ln.trim(); + + // Assume that any directives will be found before the first module or function. This + // doesn't seem to be an optimization with a warm page cache. Maybe with a cold one. + // FIXME(jieyouxu): this will cause `//@` directives in the rest of the test file to + // not be checked. if ln.starts_with("fn") || ln.starts_with("mod") { return; + } - // First try to accept `ui_test` style comments (`//@`) - } else if let Some((header_revision, non_revisioned_directive_line)) = - line_directive(comment, ln) - { - // Perform unknown directive check on Rust files. - if testfile.extension().map(|e| e == "rs").unwrap_or(false) { - let directive_ln = non_revisioned_directive_line.trim(); - - let CheckDirectiveResult { is_known_directive, trailing_directive, .. } = - check_directive(directive_ln, mode, ln); - - if !is_known_directive { - *poisoned = true; - - eprintln!( - "error: detected unknown compiletest test directive `{}` in {}:{}", - directive_ln, - testfile.display(), - line_number, - ); - - return; - } + let Some((header_revision, non_revisioned_directive_line)) = line_directive(comment, ln) + else { + continue; + }; - if let Some(trailing_directive) = &trailing_directive { - *poisoned = true; + // Perform unknown directive check on Rust files. + if testfile.extension().map(|e| e == "rs").unwrap_or(false) { + let directive_ln = non_revisioned_directive_line.trim(); - eprintln!( - "error: detected trailing compiletest test directive `{}` in {}:{}\n \ - help: put the trailing directive in it's own line: `//@ {}`", - trailing_directive, - testfile.display(), - line_number, - trailing_directive, - ); + let CheckDirectiveResult { is_known_directive, trailing_directive } = + check_directive(directive_ln, mode, ln); - return; - } - } + if !is_known_directive { + *poisoned = true; - it(HeaderLine { - line_number, - original_line, - header_revision, - directive: non_revisioned_directive_line, - }); - // Then we try to check for legacy-style candidates, which are not the magic ~ERROR family - // error annotations. - } else if !revision_magic_comment_re.is_match(ln) { - let Some((_, rest)) = line_directive("//", ln) else { - continue; - }; + eprintln!( + "error: detected unknown compiletest test directive `{}` in {}:{}", + directive_ln, + testfile.display(), + line_number, + ); - if rest.trim_start().starts_with(':') { - // This is likely a markdown link: - // `[link_name]: https://example.org` - continue; + return; } - let rest = rest.trim_start(); - - let CheckDirectiveResult { is_known_directive, directive_name, .. } = - check_directive(rest, mode, ln); - - if is_known_directive { + if let Some(trailing_directive) = &trailing_directive { *poisoned = true; + eprintln!( - "error: detected legacy-style directive {} in compiletest test: {}:{}, please use `ui_test`-style directives `//@` instead: {:#?}", - directive_name, + "error: detected trailing compiletest test directive `{}` in {}:{}\n \ + help: put the trailing directive in it's own line: `//@ {}`", + trailing_directive, testfile.display(), line_number, - line_directive("//", ln), + trailing_directive, ); + return; } } + + it(HeaderLine { + line_number, + original_line, + header_revision, + directive: non_revisioned_directive_line, + }); } } diff --git a/src/tools/compiletest/src/header/test-auxillary/known_legacy_directive.rs b/src/tools/compiletest/src/header/test-auxillary/known_legacy_directive.rs deleted file mode 100644 index 108ca432e1308..0000000000000 --- a/src/tools/compiletest/src/header/test-auxillary/known_legacy_directive.rs +++ /dev/null @@ -1 +0,0 @@ -// ignore-wasm diff --git a/src/tools/compiletest/src/header/tests.rs b/src/tools/compiletest/src/header/tests.rs index 76a8b129198dc..b70b4b27f400d 100644 --- a/src/tools/compiletest/src/header/tests.rs +++ b/src/tools/compiletest/src/header/tests.rs @@ -618,17 +618,6 @@ fn test_unknown_directive_check() { assert!(poisoned); } -#[test] -fn test_known_legacy_directive_check() { - let mut poisoned = false; - run_path( - &mut poisoned, - Path::new("a.rs"), - include_bytes!("./test-auxillary/known_legacy_directive.rs"), - ); - assert!(poisoned); -} - #[test] fn test_known_directive_check_no_error() { let mut poisoned = false; From ac5361f95f2100e7ccf411f22b62f1e47b8b6a93 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lauren=C8=9Biu=20Nicola?= Date: Tue, 8 Oct 2024 13:00:58 +0300 Subject: [PATCH 2014/2194] Use macos-13 runners and bump MACOSX_DEPLOYMENT_TARGET --- src/tools/rust-analyzer/.github/workflows/release.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/tools/rust-analyzer/.github/workflows/release.yaml b/src/tools/rust-analyzer/.github/workflows/release.yaml index e11d6e15d1058..39ac652de0f86 100644 --- a/src/tools/rust-analyzer/.github/workflows/release.yaml +++ b/src/tools/rust-analyzer/.github/workflows/release.yaml @@ -16,7 +16,7 @@ env: RUSTFLAGS: "-D warnings -W unreachable-pub" RUSTUP_MAX_RETRIES: 10 FETCH_DEPTH: 0 # pull in the tags for the version string - MACOSX_DEPLOYMENT_TARGET: 10.15 + MACOSX_DEPLOYMENT_TARGET: 13.0 CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER: aarch64-linux-gnu-gcc CARGO_TARGET_ARM_UNKNOWN_LINUX_GNUEABIHF_LINKER: arm-linux-gnueabihf-gcc @@ -43,10 +43,10 @@ jobs: - os: ubuntu-20.04 target: arm-unknown-linux-gnueabihf code-target: linux-armhf - - os: macos-12 + - os: macos-13 target: x86_64-apple-darwin code-target: darwin-x64 - - os: macos-12 + - os: macos-13 target: aarch64-apple-darwin code-target: darwin-arm64 From aeaea1b4b1a0b7bb7f3269d11d816251dc99aa00 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Tue, 8 Oct 2024 12:08:16 +0200 Subject: [PATCH 2015/2194] Add a mailmap entry for bjorn3 --- .mailmap | 1 + 1 file changed, 1 insertion(+) diff --git a/.mailmap b/.mailmap index 9ac7f1a9b494c..0f58762e0233c 100644 --- a/.mailmap +++ b/.mailmap @@ -74,6 +74,7 @@ Ben Striegel Benjamin Jackman Benoît Cortier Bheesham Persaud Bheesham Persaud +bjorn3 <17426603+bjorn3@users.noreply.github.com> Björn Steinbrink blake2-ppc blyxyas Alejandra González From 537fb8d1bb2405b118898c663bc076815a1762c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lauren=C8=9Biu=20Nicola?= Date: Tue, 8 Oct 2024 14:25:24 +0300 Subject: [PATCH 2016/2194] Preparing for merge from rust-lang/rust --- src/tools/rust-analyzer/rust-version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/rust-analyzer/rust-version b/src/tools/rust-analyzer/rust-version index 79ed6cc7d74b8..f217c6a19cbd3 100644 --- a/src/tools/rust-analyzer/rust-version +++ b/src/tools/rust-analyzer/rust-version @@ -1 +1 @@ -1b5aa96d6016bafe50e071b45d4d2e3c90fd766f +cf24c73141a77db730f4b7fda69dcd7e8b113b51 From 27583378d317b7f7e0b8b8d87e0e9ff306641d81 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Tue, 8 Oct 2024 19:08:54 +1100 Subject: [PATCH 2017/2194] Simplify the directives for ignoring coverage-test modes --- src/tools/compiletest/src/command-list.rs | 4 ++-- src/tools/compiletest/src/header/cfg.rs | 9 +++------ src/tools/compiletest/src/header/tests.rs | 20 +++++++++----------- tests/coverage/color.coverage | 2 +- tests/coverage/color.rs | 2 +- tests/coverage/ignore_map.coverage | 2 +- tests/coverage/ignore_map.rs | 2 +- tests/coverage/ignore_run.rs | 2 +- 8 files changed, 19 insertions(+), 24 deletions(-) diff --git a/src/tools/compiletest/src/command-list.rs b/src/tools/compiletest/src/command-list.rs index bcdd4a69b66c3..b34c276ab1981 100644 --- a/src/tools/compiletest/src/command-list.rs +++ b/src/tools/compiletest/src/command-list.rs @@ -42,6 +42,8 @@ const KNOWN_DIRECTIVE_NAMES: &[&str] = &[ "ignore-cdb", "ignore-compare-mode-next-solver", "ignore-compare-mode-polonius", + "ignore-coverage-map", + "ignore-coverage-run", "ignore-cross-compile", "ignore-debug", "ignore-eabi", @@ -64,8 +66,6 @@ const KNOWN_DIRECTIVE_NAMES: &[&str] = &[ "ignore-loongarch64", "ignore-macabi", "ignore-macos", - "ignore-mode-coverage-map", - "ignore-mode-coverage-run", "ignore-msp430", "ignore-msvc", "ignore-musl", diff --git a/src/tools/compiletest/src/header/cfg.rs b/src/tools/compiletest/src/header/cfg.rs index f3835637a1ec2..6e351aa27b909 100644 --- a/src/tools/compiletest/src/header/cfg.rs +++ b/src/tools/compiletest/src/header/cfg.rs @@ -217,13 +217,10 @@ pub(super) fn parse_cfg_name_directive<'a>( } // Coverage tests run the same test file in multiple modes. // If a particular test should not be run in one of the modes, ignore it - // with "ignore-mode-coverage-map" or "ignore-mode-coverage-run". + // with "ignore-coverage-map" or "ignore-coverage-run". condition! { - name: format!("mode-{}", config.mode.to_str()), - allowed_names: ContainsPrefixed { - prefix: "mode-", - inner: ["coverage-run", "coverage-map"], - }, + name: config.mode.to_str(), + allowed_names: ["coverage-map", "coverage-run"], message: "when the test mode is {name}", } diff --git a/src/tools/compiletest/src/header/tests.rs b/src/tools/compiletest/src/header/tests.rs index 76a8b129198dc..c467b5c45ec26 100644 --- a/src/tools/compiletest/src/header/tests.rs +++ b/src/tools/compiletest/src/header/tests.rs @@ -572,17 +572,15 @@ fn families() { } #[test] -fn ignore_mode() { - for mode in ["coverage-map", "coverage-run"] { - // Indicate profiler support so that "coverage-run" tests aren't skipped. - let config: Config = cfg().mode(mode).profiler_support(true).build(); - let other = if mode == "coverage-run" { "coverage-map" } else { "coverage-run" }; - - assert_ne!(mode, other); - - assert!(check_ignore(&config, &format!("//@ ignore-mode-{mode}"))); - assert!(!check_ignore(&config, &format!("//@ ignore-mode-{other}"))); - } +fn ignore_coverage() { + // Indicate profiler support so that "coverage-run" tests aren't skipped. + let config = cfg().mode("coverage-map").profiler_support(true).build(); + assert!(check_ignore(&config, "//@ ignore-coverage-map")); + assert!(!check_ignore(&config, "//@ ignore-coverage-run")); + + let config = cfg().mode("coverage-run").profiler_support(true).build(); + assert!(!check_ignore(&config, "//@ ignore-coverage-map")); + assert!(check_ignore(&config, "//@ ignore-coverage-run")); } #[test] diff --git a/tests/coverage/color.coverage b/tests/coverage/color.coverage index b12f20204b4ff..4e6ef6b60ce0e 100644 --- a/tests/coverage/color.coverage +++ b/tests/coverage/color.coverage @@ -1,5 +1,5 @@ LL| |//@ edition: 2021 - LL| |//@ ignore-mode-coverage-map + LL| |//@ ignore-coverage-map LL| |//@ ignore-windows LL| |//@ llvm-cov-flags: --use-color LL| | diff --git a/tests/coverage/color.rs b/tests/coverage/color.rs index 144e798ba5d72..bdb81c088f51f 100644 --- a/tests/coverage/color.rs +++ b/tests/coverage/color.rs @@ -1,5 +1,5 @@ //@ edition: 2021 -//@ ignore-mode-coverage-map +//@ ignore-coverage-map //@ ignore-windows //@ llvm-cov-flags: --use-color diff --git a/tests/coverage/ignore_map.coverage b/tests/coverage/ignore_map.coverage index a796a7375a760..466f9e298159e 100644 --- a/tests/coverage/ignore_map.coverage +++ b/tests/coverage/ignore_map.coverage @@ -1,4 +1,4 @@ - LL| |//@ ignore-mode-coverage-map + LL| |//@ ignore-coverage-map LL| | LL| 1|fn main() {} diff --git a/tests/coverage/ignore_map.rs b/tests/coverage/ignore_map.rs index deee6e27d99b7..95df6cbbf0d63 100644 --- a/tests/coverage/ignore_map.rs +++ b/tests/coverage/ignore_map.rs @@ -1,3 +1,3 @@ -//@ ignore-mode-coverage-map +//@ ignore-coverage-map fn main() {} diff --git a/tests/coverage/ignore_run.rs b/tests/coverage/ignore_run.rs index 0363524d369d1..2d67ebe6f3a5c 100644 --- a/tests/coverage/ignore_run.rs +++ b/tests/coverage/ignore_run.rs @@ -1,3 +1,3 @@ -//@ ignore-mode-coverage-run +//@ ignore-coverage-run fn main() {} From 287eb03838d5ff211706c8df8f5357034219472f Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 8 Oct 2024 12:25:26 +0200 Subject: [PATCH 2018/2194] fix/update teach_note from 'escaping mutable ref/ptr' const-check --- compiler/rustc_const_eval/messages.ftl | 51 ++++++++++--------- .../src/check_consts/check.rs | 1 + .../rustc_const_eval/src/check_consts/ops.rs | 6 +-- compiler/rustc_const_eval/src/errors.rs | 12 ++--- tests/ui/error-codes/E0010-teach.stderr | 2 +- 5 files changed, 37 insertions(+), 35 deletions(-) diff --git a/compiler/rustc_const_eval/messages.ftl b/compiler/rustc_const_eval/messages.ftl index 73a9a1569f64e..24dbe688f363b 100644 --- a/compiler/rustc_const_eval/messages.ftl +++ b/compiler/rustc_const_eval/messages.ftl @@ -134,14 +134,16 @@ const_eval_incompatible_return_types = const_eval_incompatible_types = calling a function with argument of type {$callee_ty} passing data of type {$caller_ty} -const_eval_interior_mutable_data_refer = +const_eval_interior_mutable_ref_escaping = {const_eval_const_context}s cannot refer to interior mutable data .label = this borrow of an interior mutable value may end up in the final value .help = to fix this, the value can be extracted to a separate `static` item and then referenced .teach_note = - A constant containing interior mutable data behind a reference can allow you to modify that data. - This would make multiple uses of a constant to be able to see different values and allow circumventing - the `Send` and `Sync` requirements for shared mutable data, which is unsound. + References that escape into the final value of a constant or static must be immutable. + This is to avoid accidentally creating shared mutable state. + + + If you really want global mutable state, try using an interior mutable `static` or a `static mut`. const_eval_intern_kind = {$kind -> [static] static @@ -229,6 +231,24 @@ const_eval_modified_global = const_eval_mutable_ptr_in_final = encountered mutable pointer in final value of {const_eval_intern_kind} +const_eval_mutable_raw_escaping = + raw mutable pointers are not allowed in the final value of {const_eval_const_context}s + .teach_note = + Pointers that escape into the final value of a constant or static must be immutable. + This is to avoid accidentally creating shared mutable state. + + + If you really want global mutable state, try using an interior mutable `static` or a `static mut`. + +const_eval_mutable_ref_escaping = + mutable references are not allowed in the final value of {const_eval_const_context}s + .teach_note = + References that escape into the final value of a constant or static must be immutable. + This is to avoid accidentally creating shared mutable state. + + + If you really want global mutable state, try using an interior mutable `static` or a `static mut`. + const_eval_nested_static_in_thread_local = #[thread_local] does not support implicit nested statics, please create explicit static items and refer to them instead const_eval_non_const_fmt_macro_call = cannot call non-const formatting macro in {const_eval_const_context}s @@ -364,30 +384,11 @@ const_eval_unallowed_fn_pointer_call = function pointer calls are not allowed in const_eval_unallowed_heap_allocations = allocations are not allowed in {const_eval_const_context}s .label = allocation not allowed in {const_eval_const_context}s - .teach_note = The value of statics and constants must be known at compile time, and they live for the entire lifetime of a program. Creating a boxed value allocates memory on the heap at runtime, and therefore cannot be done at compile time. + .teach_note = + The runtime heap is not yet available at compile-time, so no runtime heap allocations can be created. const_eval_unallowed_inline_asm = inline assembly is not allowed in {const_eval_const_context}s -const_eval_unallowed_mutable_raw = - raw mutable pointers are not allowed in the final value of {const_eval_const_context}s - .teach_note = - References in statics and constants may only refer to immutable values. - - - Statics are shared everywhere, and if they refer to mutable data one might violate memory - safety since holding multiple mutable references to shared data is not allowed. - - - If you really want global mutable state, try using static mut or a global UnsafeCell. - -const_eval_unallowed_mutable_refs = - mutable references are not allowed in the final value of {const_eval_const_context}s - .teach_note = - Statics are shared everywhere, and if they refer to mutable data one might violate memory - safety since holding multiple mutable references to shared data is not allowed. - - - If you really want global mutable state, try using static mut or a global UnsafeCell. const_eval_unallowed_op_in_const_context = {$msg} diff --git a/compiler/rustc_const_eval/src/check_consts/check.rs b/compiler/rustc_const_eval/src/check_consts/check.rs index 2cbf242fcf28d..463a66d4e2e46 100644 --- a/compiler/rustc_const_eval/src/check_consts/check.rs +++ b/compiler/rustc_const_eval/src/check_consts/check.rs @@ -666,6 +666,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> { } } + // This can be called on stable via the `vec!` macro. if tcx.is_lang_item(callee, LangItem::ExchangeMalloc) { self.check_op(ops::HeapAllocation); return; diff --git a/compiler/rustc_const_eval/src/check_consts/ops.rs b/compiler/rustc_const_eval/src/check_consts/ops.rs index 6eb33c29e1d89..5c4a899f28a14 100644 --- a/compiler/rustc_const_eval/src/check_consts/ops.rs +++ b/compiler/rustc_const_eval/src/check_consts/ops.rs @@ -402,7 +402,7 @@ impl<'tcx> NonConstOp<'tcx> for EscapingCellBorrow { DiagImportance::Secondary } fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> Diag<'tcx> { - ccx.dcx().create_err(errors::InteriorMutableDataRefer { + ccx.dcx().create_err(errors::InteriorMutableRefEscaping { span, opt_help: matches!(ccx.const_kind(), hir::ConstContext::Static(_)), kind: ccx.const_kind(), @@ -430,12 +430,12 @@ impl<'tcx> NonConstOp<'tcx> for EscapingMutBorrow { fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> Diag<'tcx> { match self.0 { - hir::BorrowKind::Raw => ccx.tcx.dcx().create_err(errors::UnallowedMutableRaw { + hir::BorrowKind::Raw => ccx.tcx.dcx().create_err(errors::MutableRawEscaping { span, kind: ccx.const_kind(), teach: ccx.tcx.sess.teach(E0764), }), - hir::BorrowKind::Ref => ccx.dcx().create_err(errors::UnallowedMutableRefs { + hir::BorrowKind::Ref => ccx.dcx().create_err(errors::MutableRefEscaping { span, kind: ccx.const_kind(), teach: ccx.tcx.sess.teach(E0764), diff --git a/compiler/rustc_const_eval/src/errors.rs b/compiler/rustc_const_eval/src/errors.rs index c60bacb85067f..c943236affc56 100644 --- a/compiler/rustc_const_eval/src/errors.rs +++ b/compiler/rustc_const_eval/src/errors.rs @@ -118,8 +118,8 @@ pub(crate) struct UnstableConstFn { } #[derive(Diagnostic)] -#[diag(const_eval_unallowed_mutable_refs, code = E0764)] -pub(crate) struct UnallowedMutableRefs { +#[diag(const_eval_mutable_ref_escaping, code = E0764)] +pub(crate) struct MutableRefEscaping { #[primary_span] pub span: Span, pub kind: ConstContext, @@ -128,8 +128,8 @@ pub(crate) struct UnallowedMutableRefs { } #[derive(Diagnostic)] -#[diag(const_eval_unallowed_mutable_raw, code = E0764)] -pub(crate) struct UnallowedMutableRaw { +#[diag(const_eval_mutable_raw_escaping, code = E0764)] +pub(crate) struct MutableRawEscaping { #[primary_span] pub span: Span, pub kind: ConstContext, @@ -181,8 +181,8 @@ pub(crate) struct UnallowedInlineAsm { } #[derive(Diagnostic)] -#[diag(const_eval_interior_mutable_data_refer, code = E0492)] -pub(crate) struct InteriorMutableDataRefer { +#[diag(const_eval_interior_mutable_ref_escaping, code = E0492)] +pub(crate) struct InteriorMutableRefEscaping { #[primary_span] #[label] pub span: Span, diff --git a/tests/ui/error-codes/E0010-teach.stderr b/tests/ui/error-codes/E0010-teach.stderr index 7634970f36e2e..37a9892ccbf49 100644 --- a/tests/ui/error-codes/E0010-teach.stderr +++ b/tests/ui/error-codes/E0010-teach.stderr @@ -4,7 +4,7 @@ error[E0010]: allocations are not allowed in constants LL | const CON: Vec = vec![1, 2, 3]; | ^^^^^^^^^^^^^ allocation not allowed in constants | - = note: The value of statics and constants must be known at compile time, and they live for the entire lifetime of a program. Creating a boxed value allocates memory on the heap at runtime, and therefore cannot be done at compile time. + = note: The runtime heap is not yet available at compile-time, so no runtime heap allocations can be created. = note: this error originates in the macro `vec` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0015]: cannot call non-const fn `slice::::into_vec::` in constants From 076927b7cfdcac9d740c85ebdc84025292d9caf5 Mon Sep 17 00:00:00 2001 From: ismailarilik Date: Tue, 8 Oct 2024 16:06:22 +0300 Subject: [PATCH 2019/2194] fix(rustdoc): add space between struct fields and their descriptions --- src/librustdoc/html/static/css/rustdoc.css | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css index 5f6f3c65c7ff7..1e3b70d69219d 100644 --- a/src/librustdoc/html/static/css/rustdoc.css +++ b/src/librustdoc/html/static/css/rustdoc.css @@ -230,6 +230,9 @@ h4.code-header { padding: 0; white-space: pre-wrap; } +.structfield { + margin: 0.6em 0; +} #crate-search, h1, h2, h3, h4, h5, h6, From c9b4d1bfb13b371a1f90be398b56a015f2ee73ba Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 8 Oct 2024 15:13:26 +0200 Subject: [PATCH 2020/2194] Remove unneeded argument of `LinkCollector::verify_disambiguator` --- src/librustdoc/passes/collect_intra_doc_links.rs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs index 2656612a13eb7..a930ffca5db32 100644 --- a/src/librustdoc/passes/collect_intra_doc_links.rs +++ b/src/librustdoc/passes/collect_intra_doc_links.rs @@ -1061,7 +1061,7 @@ impl LinkCollector<'_, '_> { // valid omission. See https://github.com/rust-lang/rust/pull/80660#discussion_r551585677 // for discussion on the matter. let kind = self.cx.tcx.def_kind(id); - self.verify_disambiguator(path_str, kind, id, disambiguator, item, &diag_info)?; + self.verify_disambiguator(path_str, kind, id, disambiguator, &diag_info)?; } else { match disambiguator { Some(Disambiguator::Primitive | Disambiguator::Namespace(_)) | None => {} @@ -1090,7 +1090,6 @@ impl LinkCollector<'_, '_> { kind_for_dis, id_for_dis, disambiguator, - item, &diag_info, )?; @@ -1111,7 +1110,6 @@ impl LinkCollector<'_, '_> { kind: DefKind, id: DefId, disambiguator: Option, - item: &Item, diag_info: &DiagnosticInfo<'_>, ) -> Option<()> { debug!("intra-doc link to {path_str} resolved to {:?}", (kind, id)); @@ -1138,7 +1136,7 @@ impl LinkCollector<'_, '_> { // item can be non-local e.g. when using `#[rustc_doc_primitive = "pointer"]` if let Some((src_id, dst_id)) = id.as_local().and_then(|dst_id| { - item.item_id.expect_def_id().as_local().map(|src_id| (src_id, dst_id)) + diag_info.item.item_id.expect_def_id().as_local().map(|src_id| (src_id, dst_id)) }) { if self.cx.tcx.effective_visibilities(()).is_exported(src_id) && !self.cx.tcx.effective_visibilities(()).is_exported(dst_id) From 7ab466697faf64aaeda40d6407c01f6bfff83fdb Mon Sep 17 00:00:00 2001 From: Michal Piotrowski Date: Tue, 8 Oct 2024 15:17:45 +0200 Subject: [PATCH 2021/2194] Fix needless_lifetimes in rustc_serialize --- compiler/rustc_serialize/src/serialize.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_serialize/src/serialize.rs b/compiler/rustc_serialize/src/serialize.rs index 2d37f5bdab800..bae5f259fccf4 100644 --- a/compiler/rustc_serialize/src/serialize.rs +++ b/compiler/rustc_serialize/src/serialize.rs @@ -325,7 +325,7 @@ impl Decodable for [u8; N] { } } -impl<'a, S: Encoder, T: Encodable> Encodable for Cow<'a, [T]> +impl> Encodable for Cow<'_, [T]> where [T]: ToOwned>, { @@ -345,14 +345,14 @@ where } } -impl<'a, S: Encoder> Encodable for Cow<'a, str> { +impl Encodable for Cow<'_, str> { fn encode(&self, s: &mut S) { let val: &str = self; val.encode(s) } } -impl<'a, D: Decoder> Decodable for Cow<'a, str> { +impl Decodable for Cow<'_, str> { fn decode(d: &mut D) -> Cow<'static, str> { let v: String = Decodable::decode(d); Cow::Owned(v) From 11af16c9838f0a693040c693e98a64c68c0c2da0 Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Wed, 24 Apr 2024 17:06:11 +0300 Subject: [PATCH 2022/2194] use precompiled rustc for non-dist builders by default Signed-off-by: onur-ozkan --- src/ci/run.sh | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/ci/run.sh b/src/ci/run.sh index c8201d9bcfd27..06e3b57375824 100755 --- a/src/ci/run.sh +++ b/src/ci/run.sh @@ -173,6 +173,10 @@ else # included with LLVM, since a dynamic libstdcpp may not be available. RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --set llvm.static-libstdcpp" fi + + if [ "$NO_DOWNLOAD_CI_RUSTC" = "" ]; then + RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --set rust.download-rustc=if-unchanged" + fi fi if [ "$ENABLE_GCC_CODEGEN" = "1" ]; then From 9826e3ece3a5a52e9cc2af5401218f4bd71a749a Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Wed, 24 Apr 2024 19:59:46 +0300 Subject: [PATCH 2023/2194] disable CI rustc when not using CI LLVM Signed-off-by: onur-ozkan --- src/ci/run.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/ci/run.sh b/src/ci/run.sh index 06e3b57375824..c33a376c2d666 100755 --- a/src/ci/run.sh +++ b/src/ci/run.sh @@ -169,6 +169,8 @@ else if [ "$NO_DOWNLOAD_CI_LLVM" = "" ]; then RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --set llvm.download-ci-llvm=if-unchanged" else + # CI rustc requires CI LLVM to be enabled (see https://github.com/rust-lang/rust/issues/123586). + NO_DOWNLOAD_CI_RUSTC=1 # When building for CI we want to use the static C++ Standard library # included with LLVM, since a dynamic libstdcpp may not be available. RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --set llvm.static-libstdcpp" From bfcd00190d798ce97e0e5c9b964b70c92174d46a Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Sun, 12 May 2024 09:55:26 +0300 Subject: [PATCH 2024/2194] add test for ci rustc's if-unchanged logic Signed-off-by: onur-ozkan --- src/bootstrap/src/core/builder/tests.rs | 49 +++++++++++++++++++++++++ src/bootstrap/src/core/config/tests.rs | 2 +- 2 files changed, 50 insertions(+), 1 deletion(-) diff --git a/src/bootstrap/src/core/builder/tests.rs b/src/bootstrap/src/core/builder/tests.rs index bd81dc930be05..363a9c8269923 100644 --- a/src/bootstrap/src/core/builder/tests.rs +++ b/src/bootstrap/src/core/builder/tests.rs @@ -212,6 +212,55 @@ fn alias_and_path_for_library() { assert_eq!(first(cache.all::()), &[doc_std!(A => A, stage = 0)]); } +#[test] +fn ci_rustc_if_unchanged_logic() { + let config = Config::parse_inner( + Flags::parse(&[ + "build".to_owned(), + "--dry-run".to_owned(), + "--set=rust.download-rustc='if-unchanged'".to_owned(), + ]), + |&_| Ok(Default::default()), + ); + + let build = Build::new(config.clone()); + let builder = Builder::new(&build); + + if config.rust_info.is_from_tarball() { + return; + } + + if config.out.exists() { + fs::remove_dir_all(&config.out).unwrap(); + } + + builder.run_step_descriptions(&Builder::get_step_descriptions(config.cmd.kind()), &[]); + + let commit = helpers::get_closest_merge_base_commit( + Some(&builder.config.src), + &builder.config.git_config(), + &builder.config.stage0_metadata.config.git_merge_commit_email, + &[], + ) + .unwrap(); + + let compiler_path = build.src.join("compiler"); + let library_path = build.src.join("library"); + + let has_changes = helpers::git(Some(&builder.src)) + .args(["diff-index", "--quiet", &commit]) + .arg("--") + .args([compiler_path, library_path]) + .as_command_mut() + .status() + .unwrap() + .success(); + + assert!( + has_changes != config.out.join(config.build.to_string()).join("ci-rustc-sysroot").exists() + ); +} + mod defaults { use pretty_assertions::assert_eq; diff --git a/src/bootstrap/src/core/config/tests.rs b/src/bootstrap/src/core/config/tests.rs index 278becdcbc77d..ed89112de9003 100644 --- a/src/bootstrap/src/core/config/tests.rs +++ b/src/bootstrap/src/core/config/tests.rs @@ -12,7 +12,7 @@ use super::{ChangeIdWrapper, Config}; use crate::core::build_steps::clippy::get_clippy_rules_in_order; use crate::core::config::{LldMode, Target, TargetSelection, TomlConfig}; -fn parse(config: &str) -> Config { +pub(crate) fn parse(config: &str) -> Config { Config::parse_inner( Flags::parse(&["check".to_string(), "--config=/does/not/exist".to_string()]), |&_| toml::from_str(&config), From b21949b9623b236617746c8dd4c98f9e110cced6 Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Sun, 12 May 2024 10:31:43 +0300 Subject: [PATCH 2025/2194] make an explicit change on compiler then run bootstrap test Signed-off-by: onur-ozkan --- src/ci/docker/host-x86_64/mingw-check/Dockerfile | 15 ++++++++++++++- src/ci/github-actions/jobs.yml | 3 +++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/src/ci/docker/host-x86_64/mingw-check/Dockerfile b/src/ci/docker/host-x86_64/mingw-check/Dockerfile index 571378774be01..97fe56fbfcbab 100644 --- a/src/ci/docker/host-x86_64/mingw-check/Dockerfile +++ b/src/ci/docker/host-x86_64/mingw-check/Dockerfile @@ -46,7 +46,20 @@ ENV RUN_CHECK_WITH_PARALLEL_QUERIES 1 # Check library crates on all tier 1 targets. # We disable optimized compiler built-ins because that requires a C toolchain for the target. # We also skip the x86_64-unknown-linux-gnu target as it is well-tested by other jobs. -ENV SCRIPT python3 ../x.py check --stage 0 --set build.optimized-compiler-builtins=false core alloc std --target=aarch64-unknown-linux-gnu,i686-pc-windows-msvc,i686-unknown-linux-gnu,x86_64-apple-darwin,x86_64-pc-windows-gnu,x86_64-pc-windows-msvc && \ +ENV SCRIPT \ + # `core::builder::tests::ci_rustc_if_unchanged_logic` bootstrap test covers the `rust.download-rustc=if-unchanged` logic. + # Here we are adding a dummy commit on compiler and running that test to ensure when there is a change on the compiler, + # we never download ci rustc with `rust.download-rustc=if-unchanged` option. + echo \"\" >> ../compiler/rustc/src/main.rs && \ + git config --global user.email \"dummy@dummy.com\" && \ + git config --global user.name \"dummy\" && \ + git add ../compiler/rustc/src/main.rs && \ + git commit -m \"test commit for rust.download-rustc=if-unchanged logic\" && \ + python3 ../x.py test bootstrap -- core::builder::tests::ci_rustc_if_unchanged_logic && \ + # Revert the dummy commit + git reset --hard HEAD~1 && \ + + python3 ../x.py check --stage 0 --set build.optimized-compiler-builtins=false core alloc std --target=aarch64-unknown-linux-gnu,i686-pc-windows-msvc,i686-unknown-linux-gnu,x86_64-apple-darwin,x86_64-pc-windows-gnu,x86_64-pc-windows-msvc && \ /scripts/check-default-config-profiles.sh && \ python3 ../x.py check --target=i686-pc-windows-gnu --host=i686-pc-windows-gnu && \ python3 ../x.py clippy bootstrap -Dwarnings && \ diff --git a/src/ci/github-actions/jobs.yml b/src/ci/github-actions/jobs.yml index 6379f1ade1ce8..e8ad4319aff49 100644 --- a/src/ci/github-actions/jobs.yml +++ b/src/ci/github-actions/jobs.yml @@ -85,6 +85,9 @@ envs: # it in each job definition. pr: - image: mingw-check + env: + # We are adding (temporarily) a dummy commit on the compiler + READ_ONLY_SRC: "0" <<: *job-linux-4c - image: mingw-check-tidy continue_on_error: true From eb5e6239aa6524888821d2a3eac5e22e90d25832 Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Sun, 26 May 2024 22:27:34 +0300 Subject: [PATCH 2026/2194] use if-unchanged only when ci rustc is available Signed-off-by: onur-ozkan --- src/bootstrap/src/core/config/config.rs | 26 ++++++++++------ src/bootstrap/src/core/download.rs | 40 +++++++++++++++++++++++++ 2 files changed, 57 insertions(+), 9 deletions(-) diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs index 7dc3b7b081aea..b0af7f29d5e0a 100644 --- a/src/bootstrap/src/core/config/config.rs +++ b/src/bootstrap/src/core/config/config.rs @@ -22,6 +22,7 @@ use crate::core::build_steps::compile::CODEGEN_BACKEND_PREFIX; use crate::core::build_steps::llvm; pub use crate::core::config::flags::Subcommand; use crate::core::config::flags::{Color, Flags, Warnings}; +use crate::core::download::is_download_ci_available; use crate::utils::cache::{INTERNER, Interned}; use crate::utils::channel::{self, GitInfo}; use crate::utils::helpers::{self, exe, output, t}; @@ -1627,9 +1628,11 @@ impl Config { config.mandir = mandir.map(PathBuf::from); } + config.llvm_assertions = + toml.llvm.as_ref().map_or(false, |llvm| llvm.assertions.unwrap_or(false)); + // Store off these values as options because if they're not provided // we'll infer default values for them later - let mut llvm_assertions = None; let mut llvm_tests = None; let mut llvm_enzyme = None; let mut llvm_plugins = None; @@ -1712,7 +1715,8 @@ impl Config { is_user_configured_rust_channel = channel.is_some(); set(&mut config.channel, channel.clone()); - config.download_rustc_commit = config.download_ci_rustc_commit(download_rustc); + config.download_rustc_commit = + config.download_ci_rustc_commit(download_rustc, config.llvm_assertions); debug = debug_toml; debug_assertions = debug_assertions_toml; @@ -1848,7 +1852,7 @@ impl Config { optimize: optimize_toml, thin_lto, release_debuginfo, - assertions, + assertions: _, tests, enzyme, plugins, @@ -1882,7 +1886,6 @@ impl Config { Some(StringOrBool::Bool(false)) | None => {} } set(&mut config.ninja_in_file, ninja); - llvm_assertions = assertions; llvm_tests = tests; llvm_enzyme = enzyme; llvm_plugins = plugins; @@ -1911,8 +1914,8 @@ impl Config { config.llvm_enable_warnings = enable_warnings.unwrap_or(false); config.llvm_build_config = build_config.clone().unwrap_or(Default::default()); - let asserts = llvm_assertions.unwrap_or(false); - config.llvm_from_ci = config.parse_download_ci_llvm(download_ci_llvm, asserts); + config.llvm_from_ci = + config.parse_download_ci_llvm(download_ci_llvm, config.llvm_assertions); if config.llvm_from_ci { let warn = |option: &str| { @@ -2080,7 +2083,6 @@ impl Config { // Now that we've reached the end of our configuration, infer the // default values for all options that we haven't otherwise stored yet. - config.llvm_assertions = llvm_assertions.unwrap_or(false); config.llvm_tests = llvm_tests.unwrap_or(false); config.llvm_enzyme = llvm_enzyme.unwrap_or(false); config.llvm_plugins = llvm_plugins.unwrap_or(false); @@ -2711,12 +2713,18 @@ impl Config { } /// Returns the commit to download, or `None` if we shouldn't download CI artifacts. - fn download_ci_rustc_commit(&self, download_rustc: Option) -> Option { + fn download_ci_rustc_commit( + &self, + download_rustc: Option, + llvm_assertions: bool, + ) -> Option { // If `download-rustc` is not set, default to rebuilding. let if_unchanged = match download_rustc { None | Some(StringOrBool::Bool(false)) => return None, Some(StringOrBool::Bool(true)) => false, - Some(StringOrBool::String(s)) if s == "if-unchanged" => true, + Some(StringOrBool::String(s)) if s == "if-unchanged" => { + is_download_ci_available(&self.build.triple, llvm_assertions) + } Some(StringOrBool::String(other)) => { panic!("unrecognized option for download-rustc: {other}") } diff --git a/src/bootstrap/src/core/download.rs b/src/bootstrap/src/core/download.rs index 444b75876f248..db1f5b0833826 100644 --- a/src/bootstrap/src/core/download.rs +++ b/src/bootstrap/src/core/download.rs @@ -832,3 +832,43 @@ fn path_is_dylib(path: &Path) -> bool { // The .so is not necessarily the extension, it might be libLLVM.so.18.1 path.to_str().map_or(false, |path| path.contains(".so")) } + +/// Checks whether the CI rustc is available for the given target triple. +pub(crate) fn is_download_ci_available(target_triple: &str, llvm_assertions: bool) -> bool { + // All tier 1 targets and tier 2 targets with host tools. + const SUPPORTED_PLATFORMS: &[&str] = &[ + "aarch64-apple-darwin", + "aarch64-pc-windows-msvc", + "aarch64-unknown-linux-gnu", + "aarch64-unknown-linux-musl", + "arm-unknown-linux-gnueabi", + "arm-unknown-linux-gnueabihf", + "armv7-unknown-linux-gnueabihf", + "i686-pc-windows-gnu", + "i686-pc-windows-msvc", + "i686-unknown-linux-gnu", + "loongarch64-unknown-linux-gnu", + "powerpc-unknown-linux-gnu", + "powerpc64-unknown-linux-gnu", + "powerpc64le-unknown-linux-gnu", + "riscv64gc-unknown-linux-gnu", + "s390x-unknown-linux-gnu", + "x86_64-apple-darwin", + "x86_64-pc-windows-gnu", + "x86_64-pc-windows-msvc", + "x86_64-unknown-freebsd", + "x86_64-unknown-illumos", + "x86_64-unknown-linux-gnu", + "x86_64-unknown-linux-musl", + "x86_64-unknown-netbsd", + ]; + + const SUPPORTED_PLATFORMS_WITH_ASSERTIONS: &[&str] = + &["x86_64-unknown-linux-gnu", "x86_64-pc-windows-msvc"]; + + if llvm_assertions { + SUPPORTED_PLATFORMS_WITH_ASSERTIONS.contains(&target_triple) + } else { + SUPPORTED_PLATFORMS.contains(&target_triple) + } +} From 1090d8920c4a2804b1ba5d6ca45712ba1a21b29e Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Mon, 5 Aug 2024 14:25:24 +0300 Subject: [PATCH 2027/2194] improve ci-rustc finding logic Signed-off-by: onur-ozkan --- src/bootstrap/src/core/config/config.rs | 29 +++++++++++++++++++++---- 1 file changed, 25 insertions(+), 4 deletions(-) diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs index b0af7f29d5e0a..e3641254b19d5 100644 --- a/src/bootstrap/src/core/config/config.rs +++ b/src/bootstrap/src/core/config/config.rs @@ -13,6 +13,7 @@ use std::str::FromStr; use std::sync::OnceLock; use std::{cmp, env, fs}; +use build_helper::ci::CiEnv; use build_helper::exit; use build_helper::git::{GitConfig, get_closest_merge_commit, output_result}; use serde::{Deserialize, Deserializer}; @@ -2718,13 +2719,15 @@ impl Config { download_rustc: Option, llvm_assertions: bool, ) -> Option { + if !is_download_ci_available(&self.build.triple, llvm_assertions) { + return None; + } + // If `download-rustc` is not set, default to rebuilding. let if_unchanged = match download_rustc { None | Some(StringOrBool::Bool(false)) => return None, Some(StringOrBool::Bool(true)) => false, - Some(StringOrBool::String(s)) if s == "if-unchanged" => { - is_download_ci_available(&self.build.triple, llvm_assertions) - } + Some(StringOrBool::String(s)) if s == "if-unchanged" => true, Some(StringOrBool::String(other)) => { panic!("unrecognized option for download-rustc: {other}") } @@ -2732,7 +2735,12 @@ impl Config { // Look for a version to compare to based on the current commit. // Only commits merged by bors will have CI artifacts. - let commit = get_closest_merge_commit(Some(&self.src), &self.git_config(), &[]).unwrap(); + let commit = get_closest_merge_commit( + Some(&self.src), + &self.git_config(), + &[self.src.join("compiler"), self.src.join("library")], + ) + .unwrap(); if commit.is_empty() { println!("ERROR: could not find commit hash for downloading rustc"); println!("HELP: maybe your repository history is too shallow?"); @@ -2741,6 +2749,19 @@ impl Config { crate::exit!(1); } + if CiEnv::is_ci() && { + let head_sha = + output(helpers::git(Some(&self.src)).arg("rev-parse").arg("HEAD").as_command_mut()); + let head_sha = head_sha.trim(); + commit == head_sha + } { + eprintln!("CI rustc commit matches with HEAD and we are in CI."); + eprintln!( + "`rustc.download-ci` functionality will be skipped as artifacts are not available." + ); + return None; + } + // Warn if there were changes to the compiler or standard library since the ancestor commit. let has_changes = !t!(helpers::git(Some(&self.src)) .args(["diff-index", "--quiet", &commit]) From ee5f51af30a009d08a76e99b005e0cbe03359873 Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Tue, 28 May 2024 11:56:15 +0300 Subject: [PATCH 2028/2194] disable read-only mode in mingw-check image for merge pipeline Signed-off-by: onur-ozkan --- src/ci/github-actions/jobs.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/ci/github-actions/jobs.yml b/src/ci/github-actions/jobs.yml index e8ad4319aff49..4bbebbc469799 100644 --- a/src/ci/github-actions/jobs.yml +++ b/src/ci/github-actions/jobs.yml @@ -210,6 +210,8 @@ auto: <<: *job-linux-8c - image: mingw-check + env: + READ_ONLY_SRC: 0 <<: *job-linux-4c - image: test-various From a3bb170e370e5711ec401fe971411b40cfc254c8 Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Tue, 28 May 2024 19:17:00 +0300 Subject: [PATCH 2029/2194] disable download-rustc on x86_64-gnu-integration Signed-off-by: onur-ozkan --- src/ci/docker/host-x86_64/x86_64-fuchsia/Dockerfile | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/ci/docker/host-x86_64/x86_64-fuchsia/Dockerfile b/src/ci/docker/host-x86_64/x86_64-fuchsia/Dockerfile index ba3e8bdb68754..0cae83a85b3a4 100644 --- a/src/ci/docker/host-x86_64/x86_64-fuchsia/Dockerfile +++ b/src/ci/docker/host-x86_64/x86_64-fuchsia/Dockerfile @@ -58,6 +58,9 @@ RUN mkdir -p $RUST_INSTALL_DIR/etc # Fuchsia only supports LLVM. ENV CODEGEN_BACKENDS llvm +# download-rustc is not allowed for `x install` +ENV NO_DOWNLOAD_CI_RUSTC 1 + ENV RUST_CONFIGURE_ARGS \ --prefix=$RUST_INSTALL_DIR \ --sysconfdir=etc \ @@ -70,6 +73,7 @@ ENV RUST_CONFIGURE_ARGS \ --set target.x86_64-unknown-fuchsia.ar=/usr/local/bin/llvm-ar \ --set target.x86_64-unknown-fuchsia.ranlib=/usr/local/bin/llvm-ranlib \ --set target.x86_64-unknown-fuchsia.linker=/usr/local/bin/ld.lld + ENV SCRIPT \ python3 ../x.py install --target $TARGETS compiler/rustc library/std clippy && \ bash ../src/ci/docker/host-x86_64/x86_64-fuchsia/build-fuchsia.sh From b0b4f4a1f3bbad98abc08c4ea9dd447d39890b74 Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Wed, 29 May 2024 09:25:24 +0300 Subject: [PATCH 2030/2194] fail on {dist, install} subcommand if download-rustc is enabled --- src/bootstrap/src/core/builder.rs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/bootstrap/src/core/builder.rs b/src/bootstrap/src/core/builder.rs index 155c6515db8d5..d32830c0a96c1 100644 --- a/src/bootstrap/src/core/builder.rs +++ b/src/bootstrap/src/core/builder.rs @@ -414,6 +414,15 @@ impl StepDescription { .map(|desc| (desc.should_run)(ShouldRun::new(builder, desc.kind))) .collect::>(); + if builder.download_rustc() && (builder.kind == Kind::Dist || builder.kind == Kind::Install) + { + eprintln!( + "ERROR: '{}' subcommand is incompatible with `rust.download-rustc`.", + builder.kind.as_str() + ); + crate::exit!(1); + } + // sanity checks on rules for (desc, should_run) in v.iter().zip(&should_runs) { assert!( From 8a5f418f147204ca3803b986db36d4867cc1cf20 Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Mon, 5 Aug 2024 15:04:39 +0300 Subject: [PATCH 2031/2194] handle CI rustc incompatible runners Signed-off-by: onur-ozkan --- src/ci/docker/run.sh | 1 + src/ci/run.sh | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/src/ci/docker/run.sh b/src/ci/docker/run.sh index fad4b5af0953f..28487bce48280 100755 --- a/src/ci/docker/run.sh +++ b/src/ci/docker/run.sh @@ -343,6 +343,7 @@ docker \ --env PR_CI_JOB \ --env OBJDIR_ON_HOST="$objdir" \ --env CODEGEN_BACKENDS \ + --env DISABLE_CI_RUSTC_IF_INCOMPATIBLE="$DISABLE_CI_RUSTC_IF_INCOMPATIBLE" \ --init \ --rm \ rust-ci \ diff --git a/src/ci/run.sh b/src/ci/run.sh index c33a376c2d666..8a8d26f83028b 100755 --- a/src/ci/run.sh +++ b/src/ci/run.sh @@ -52,6 +52,11 @@ if [ "$CI" != "" ]; then RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --set change-id=99999999" fi +# If runner uses an incompatible option and `FORCE_CI_RUSTC` is not defined, switch to in-tree rustc. +if [ "$FORCE_CI_RUSTC" == "" ]; then + DISABLE_CI_RUSTC_IF_INCOMPATIBLE=1 +fi + if ! isCI || isCiBranch auto || isCiBranch beta || isCiBranch try || isCiBranch try-perf || \ isCiBranch automation/bors/try; then RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --set build.print-step-timings --enable-verbose-tests" From abac4dc8889bc741d1c1880c89abb8c1ca4420f8 Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Mon, 5 Aug 2024 16:26:39 +0300 Subject: [PATCH 2032/2194] fix `ci_rustc_if_unchanged_logic` test Signed-off-by: onur-ozkan --- src/bootstrap/src/core/builder/tests.rs | 25 +++++++++---------- src/bootstrap/src/core/config/config.rs | 5 ++-- .../docker/host-x86_64/mingw-check/Dockerfile | 2 +- src/ci/run.sh | 3 ++- 4 files changed, 18 insertions(+), 17 deletions(-) diff --git a/src/bootstrap/src/core/builder/tests.rs b/src/bootstrap/src/core/builder/tests.rs index 363a9c8269923..3d2e3daf915ae 100644 --- a/src/bootstrap/src/core/builder/tests.rs +++ b/src/bootstrap/src/core/builder/tests.rs @@ -1,5 +1,7 @@ use std::thread; +use build_helper::git::get_closest_merge_commit; + use super::*; use crate::Flags; use crate::core::build_steps::doc::DocumentationFormat; @@ -223,31 +225,30 @@ fn ci_rustc_if_unchanged_logic() { |&_| Ok(Default::default()), ); - let build = Build::new(config.clone()); - let builder = Builder::new(&build); - if config.rust_info.is_from_tarball() { return; } + let build = Build::new(config.clone()); + let builder = Builder::new(&build); + if config.out.exists() { fs::remove_dir_all(&config.out).unwrap(); } builder.run_step_descriptions(&Builder::get_step_descriptions(config.cmd.kind()), &[]); - let commit = helpers::get_closest_merge_base_commit( + let compiler_path = build.src.join("compiler"); + let library_path = build.src.join("compiler"); + + let commit = get_closest_merge_commit( Some(&builder.config.src), &builder.config.git_config(), - &builder.config.stage0_metadata.config.git_merge_commit_email, - &[], + &[compiler_path.clone(), library_path.clone()], ) .unwrap(); - let compiler_path = build.src.join("compiler"); - let library_path = build.src.join("library"); - - let has_changes = helpers::git(Some(&builder.src)) + let has_changes = !helpers::git(Some(&builder.src)) .args(["diff-index", "--quiet", &commit]) .arg("--") .args([compiler_path, library_path]) @@ -256,9 +257,7 @@ fn ci_rustc_if_unchanged_logic() { .unwrap() .success(); - assert!( - has_changes != config.out.join(config.build.to_string()).join("ci-rustc-sysroot").exists() - ); + assert!(has_changes == config.download_rustc_commit.is_none()); } mod defaults { diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs index e3641254b19d5..76e3343e86f0c 100644 --- a/src/bootstrap/src/core/config/config.rs +++ b/src/bootstrap/src/core/config/config.rs @@ -2422,8 +2422,9 @@ impl Config { ci_config_toml, ); - let disable_ci_rustc_if_incompatible = - env::var_os("DISABLE_CI_RUSTC_IF_INCOMPATIBLE") + // Primarily used by CI runners to avoid handling download-rustc incompatible + // options one by one on shell scripts. + let disable_ci_rustc_if_incompatible = env::var_os("DISABLE_CI_RUSTC_IF_INCOMPATIBLE") .is_some_and(|s| s == "1" || s == "true"); if disable_ci_rustc_if_incompatible && res.is_err() { diff --git a/src/ci/docker/host-x86_64/mingw-check/Dockerfile b/src/ci/docker/host-x86_64/mingw-check/Dockerfile index 97fe56fbfcbab..467ca1dac67a4 100644 --- a/src/ci/docker/host-x86_64/mingw-check/Dockerfile +++ b/src/ci/docker/host-x86_64/mingw-check/Dockerfile @@ -55,7 +55,7 @@ ENV SCRIPT \ git config --global user.name \"dummy\" && \ git add ../compiler/rustc/src/main.rs && \ git commit -m \"test commit for rust.download-rustc=if-unchanged logic\" && \ - python3 ../x.py test bootstrap -- core::builder::tests::ci_rustc_if_unchanged_logic && \ + DISABLE_CI_RUSTC_IF_INCOMPATIBLE=0 python3 ../x.py test bootstrap -- core::builder::tests::ci_rustc_if_unchanged_logic && \ # Revert the dummy commit git reset --hard HEAD~1 && \ diff --git a/src/ci/run.sh b/src/ci/run.sh index 8a8d26f83028b..457f36bdd20be 100755 --- a/src/ci/run.sh +++ b/src/ci/run.sh @@ -52,7 +52,8 @@ if [ "$CI" != "" ]; then RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --set change-id=99999999" fi -# If runner uses an incompatible option and `FORCE_CI_RUSTC` is not defined, switch to in-tree rustc. +# If runner uses an incompatible option and `FORCE_CI_RUSTC` is not defined, +# switch to in-tree rustc. if [ "$FORCE_CI_RUSTC" == "" ]; then DISABLE_CI_RUSTC_IF_INCOMPATIBLE=1 fi From 4082f9f77567b6b5b61f411d9c08b66853e87a95 Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Fri, 16 Aug 2024 21:57:28 +0300 Subject: [PATCH 2033/2194] force `download-rustc=if-unchanged` for x86_64-gnu-tools runner Signed-off-by: onur-ozkan --- src/bootstrap/src/core/builder/tests.rs | 12 ++++++------ src/bootstrap/src/core/config/config.rs | 9 ++++----- .../docker/host-x86_64/x86_64-gnu-tools/Dockerfile | 1 + src/ci/run.sh | 1 + 4 files changed, 12 insertions(+), 11 deletions(-) diff --git a/src/bootstrap/src/core/builder/tests.rs b/src/bootstrap/src/core/builder/tests.rs index 3d2e3daf915ae..4a96ecf1421d1 100644 --- a/src/bootstrap/src/core/builder/tests.rs +++ b/src/bootstrap/src/core/builder/tests.rs @@ -241,12 +241,12 @@ fn ci_rustc_if_unchanged_logic() { let compiler_path = build.src.join("compiler"); let library_path = build.src.join("compiler"); - let commit = get_closest_merge_commit( - Some(&builder.config.src), - &builder.config.git_config(), - &[compiler_path.clone(), library_path.clone()], - ) - .unwrap(); + let commit = + get_closest_merge_commit(Some(&builder.config.src), &builder.config.git_config(), &[ + compiler_path.clone(), + library_path.clone(), + ]) + .unwrap(); let has_changes = !helpers::git(Some(&builder.src)) .args(["diff-index", "--quiet", &commit]) diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs index 76e3343e86f0c..9f84b492b80a2 100644 --- a/src/bootstrap/src/core/config/config.rs +++ b/src/bootstrap/src/core/config/config.rs @@ -2736,11 +2736,10 @@ impl Config { // Look for a version to compare to based on the current commit. // Only commits merged by bors will have CI artifacts. - let commit = get_closest_merge_commit( - Some(&self.src), - &self.git_config(), - &[self.src.join("compiler"), self.src.join("library")], - ) + let commit = get_closest_merge_commit(Some(&self.src), &self.git_config(), &[ + self.src.join("compiler"), + self.src.join("library"), + ]) .unwrap(); if commit.is_empty() { println!("ERROR: could not find commit hash for downloading rustc"); diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-tools/Dockerfile b/src/ci/docker/host-x86_64/x86_64-gnu-tools/Dockerfile index 145f41f21e1f4..17fc1a5749299 100644 --- a/src/ci/docker/host-x86_64/x86_64-gnu-tools/Dockerfile +++ b/src/ci/docker/host-x86_64/x86_64-gnu-tools/Dockerfile @@ -84,6 +84,7 @@ ENV RUST_CONFIGURE_ARGS \ --enable-new-symbol-mangling ENV HOST_TARGET x86_64-unknown-linux-gnu +ENV FORCE_CI_RUSTC 1 COPY host-x86_64/dist-x86_64-linux/shared.sh /scripts/ COPY host-x86_64/dist-x86_64-linux/build-gccjit.sh /scripts/ diff --git a/src/ci/run.sh b/src/ci/run.sh index 457f36bdd20be..1ce54f9ecb342 100755 --- a/src/ci/run.sh +++ b/src/ci/run.sh @@ -55,6 +55,7 @@ fi # If runner uses an incompatible option and `FORCE_CI_RUSTC` is not defined, # switch to in-tree rustc. if [ "$FORCE_CI_RUSTC" == "" ]; then + echo "debug: `DISABLE_CI_RUSTC_IF_INCOMPATIBLE` configured." DISABLE_CI_RUSTC_IF_INCOMPATIBLE=1 fi From 17eca60c2432d4b140ec0dca441cc6fde6562698 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 8 Oct 2024 16:46:00 -0400 Subject: [PATCH 2034/2194] Dont ICE when encountering post-mono layout cycle error --- compiler/rustc_codegen_llvm/src/context.rs | 11 ++-- tests/ui/layout/post-mono-layout-cycle-2.rs | 59 +++++++++++++++++++ .../ui/layout/post-mono-layout-cycle-2.stderr | 23 ++++++++ tests/ui/layout/post-mono-layout-cycle.rs | 25 ++++++++ tests/ui/layout/post-mono-layout-cycle.stderr | 16 +++++ 5 files changed, 129 insertions(+), 5 deletions(-) create mode 100644 tests/ui/layout/post-mono-layout-cycle-2.rs create mode 100644 tests/ui/layout/post-mono-layout-cycle-2.stderr create mode 100644 tests/ui/layout/post-mono-layout-cycle.rs create mode 100644 tests/ui/layout/post-mono-layout-cycle.stderr diff --git a/compiler/rustc_codegen_llvm/src/context.rs b/compiler/rustc_codegen_llvm/src/context.rs index 81b828404725c..0a116971e0783 100644 --- a/compiler/rustc_codegen_llvm/src/context.rs +++ b/compiler/rustc_codegen_llvm/src/context.rs @@ -1187,10 +1187,11 @@ impl<'tcx> FnAbiOfHelpers<'tcx> for CodegenCx<'_, 'tcx> { span: Span, fn_abi_request: FnAbiRequest<'tcx>, ) -> ! { - if let FnAbiError::Layout(LayoutError::SizeOverflow(_)) = err { - self.tcx.dcx().emit_fatal(Spanned { span, node: err }) - } else { - match fn_abi_request { + match err { + FnAbiError::Layout(LayoutError::SizeOverflow(_) | LayoutError::Cycle(_)) => { + self.tcx.dcx().emit_fatal(Spanned { span, node: err }); + } + _ => match fn_abi_request { FnAbiRequest::OfFnPtr { sig, extra_args } => { span_bug!(span, "`fn_abi_of_fn_ptr({sig}, {extra_args:?})` failed: {err:?}",); } @@ -1200,7 +1201,7 @@ impl<'tcx> FnAbiOfHelpers<'tcx> for CodegenCx<'_, 'tcx> { "`fn_abi_of_instance({instance}, {extra_args:?})` failed: {err:?}", ); } - } + }, } } } diff --git a/tests/ui/layout/post-mono-layout-cycle-2.rs b/tests/ui/layout/post-mono-layout-cycle-2.rs new file mode 100644 index 0000000000000..356f1e777c7d0 --- /dev/null +++ b/tests/ui/layout/post-mono-layout-cycle-2.rs @@ -0,0 +1,59 @@ +//@ build-fail +//@ edition: 2021 + +#![feature(async_closure, noop_waker)] + +use std::future::Future; +use std::pin::pin; +use std::task::*; + +pub fn block_on(fut: impl Future) -> T { + let mut fut = pin!(fut); + // Poll loop, just to test the future... + let ctx = &mut Context::from_waker(Waker::noop()); + + loop { + match fut.as_mut().poll(ctx) { + Poll::Pending => {} + Poll::Ready(t) => break t, + } + } +} + +trait Blah { + async fn iter(&mut self, iterator: T) + where + T: IntoIterator; +} + +impl Blah for () { + async fn iter(&mut self, iterator: T) + //~^ ERROR recursion in an async fn requires boxing + where + T: IntoIterator, + { + Blah::iter(self, iterator).await + } +} + +struct Wrap { + t: T, +} + +impl Wrap +where + T: Blah, +{ + async fn ice(&mut self) { + //~^ ERROR a cycle occurred during layout computation + let arr: [(); 0] = []; + self.t.iter(arr.into_iter()).await; + } +} + +fn main() { + block_on(async { + let mut t = Wrap { t: () }; + t.ice(); + }) +} diff --git a/tests/ui/layout/post-mono-layout-cycle-2.stderr b/tests/ui/layout/post-mono-layout-cycle-2.stderr new file mode 100644 index 0000000000000..ad01c2694faf5 --- /dev/null +++ b/tests/ui/layout/post-mono-layout-cycle-2.stderr @@ -0,0 +1,23 @@ +error[E0733]: recursion in an async fn requires boxing + --> $DIR/post-mono-layout-cycle-2.rs:30:5 + | +LL | / async fn iter(&mut self, iterator: T) +LL | | +LL | | where +LL | | T: IntoIterator, + | |___________________________________^ +LL | { +LL | Blah::iter(self, iterator).await + | -------------------------------- recursive call here + | + = note: a recursive `async fn` call must introduce indirection such as `Box::pin` to avoid an infinitely sized future + +error: a cycle occurred during layout computation + --> $DIR/post-mono-layout-cycle-2.rs:47:5 + | +LL | async fn ice(&mut self) { + | ^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0733`. diff --git a/tests/ui/layout/post-mono-layout-cycle.rs b/tests/ui/layout/post-mono-layout-cycle.rs new file mode 100644 index 0000000000000..8d136190c0052 --- /dev/null +++ b/tests/ui/layout/post-mono-layout-cycle.rs @@ -0,0 +1,25 @@ +//@ build-fail +//~^ cycle detected when computing layout of `Wrapper<()>` + +trait Trait { + type Assoc; +} + +impl Trait for () { + type Assoc = Wrapper<()>; +} + +struct Wrapper { + _x: ::Assoc, +} + +fn abi(_: Option>) {} +//~^ ERROR a cycle occurred during layout computation + +fn indirect() { + abi::(None); +} + +fn main() { + indirect::<()>(); +} diff --git a/tests/ui/layout/post-mono-layout-cycle.stderr b/tests/ui/layout/post-mono-layout-cycle.stderr new file mode 100644 index 0000000000000..47f7f30b1cb4c --- /dev/null +++ b/tests/ui/layout/post-mono-layout-cycle.stderr @@ -0,0 +1,16 @@ +error[E0391]: cycle detected when computing layout of `Wrapper<()>` + | + = note: ...which requires computing layout of `<() as Trait>::Assoc`... + = note: ...which again requires computing layout of `Wrapper<()>`, completing the cycle + = note: cycle used when computing layout of `core::option::Option>` + = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information + +error: a cycle occurred during layout computation + --> $DIR/post-mono-layout-cycle.rs:16:1 + | +LL | fn abi(_: Option>) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0391`. From 35d9bdbcdebeb95e747efa366dac2c811ceab92d Mon Sep 17 00:00:00 2001 From: Noa Date: Tue, 8 Oct 2024 15:33:50 -0500 Subject: [PATCH 2035/2194] Use throw intrinsic from stdarch in wasm libunwind --- library/unwind/src/lib.rs | 3 +-- library/unwind/src/wasm.rs | 24 ++++++++++-------------- 2 files changed, 11 insertions(+), 16 deletions(-) diff --git a/library/unwind/src/lib.rs b/library/unwind/src/lib.rs index 46026324d2f82..5a476d5843b2f 100644 --- a/library/unwind/src/lib.rs +++ b/library/unwind/src/lib.rs @@ -3,11 +3,10 @@ #![feature(link_cfg)] #![feature(staged_api)] #![feature(strict_provenance)] -#![cfg_attr(target_arch = "wasm64", feature(simd_wasm64))] #![cfg_attr(not(target_env = "msvc"), feature(libc))] #![cfg_attr( all(target_family = "wasm", not(target_os = "emscripten")), - feature(link_llvm_intrinsics) + feature(simd_wasm64, wasm_exception_handling_intrinsics) )] #![allow(internal_features)] diff --git a/library/unwind/src/wasm.rs b/library/unwind/src/wasm.rs index f4ffac1ba16da..2d36a8be00469 100644 --- a/library/unwind/src/wasm.rs +++ b/library/unwind/src/wasm.rs @@ -40,29 +40,25 @@ pub unsafe fn _Unwind_DeleteException(exception: *mut _Unwind_Exception) { } pub unsafe fn _Unwind_RaiseException(exception: *mut _Unwind_Exception) -> _Unwind_Reason_Code { - #[cfg(panic = "unwind")] - extern "C" { - /// LLVM lowers this intrinsic to the `throw` instruction. - // FIXME(coolreader18): move to stdarch - #[link_name = "llvm.wasm.throw"] - fn wasm_throw(tag: i32, ptr: *mut u8) -> !; - } - // The wasm `throw` instruction takes a "tag", which differentiates certain // types of exceptions from others. LLVM currently just identifies these // via integers, with 0 corresponding to C++ exceptions and 1 to C setjmp()/longjmp(). // Ideally, we'd be able to choose something unique for Rust, but for now, // we pretend to be C++ and implement the Itanium exception-handling ABI. cfg_if::cfg_if! { - // for now, unless we're -Zbuild-std with panic=unwind, never codegen a throw. + // panic=abort is default for wasm targets. Because an unknown instruction is a load-time + // error on wasm, instead of a runtime error like on traditional architectures, we never + // want to codegen a `throw` instruction, as that would break users using runtimes that + // don't yet support exceptions. The only time this first branch would be selected is if + // the user explicitly opts in to wasm exceptions, via -Zbuild-std with -Cpanic=unwind. if #[cfg(panic = "unwind")] { - wasm_throw(0, exception.cast()) + // corresponds with llvm::WebAssembly::Tag::CPP_EXCEPTION + // in llvm-project/llvm/include/llvm/CodeGen/WasmEHFuncInfo.h + const CPP_EXCEPTION_TAG: i32 = 0; + core::arch::wasm::throw::(exception.cast()) } else { let _ = exception; - #[cfg(target_arch = "wasm32")] - core::arch::wasm32::unreachable(); - #[cfg(target_arch = "wasm64")] - core::arch::wasm64::unreachable(); + core::arch::wasm::unreachable() } } } From 7018a99172ea325fb5fd29d452858824517e85b4 Mon Sep 17 00:00:00 2001 From: Weihang Lo Date: Tue, 8 Oct 2024 19:14:49 -0400 Subject: [PATCH 2036/2194] Update cargo MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This also adds three license exceptions to Cargo. * arrayref — BSD-2-Clause * blake3 — CC0-1.0 OR Apache-2.0 OR Apache-2.0 WITH LLVM-exception * constant_time_eq — CC0-1.0 OR MIT-0 OR Apache-2.0 These exceptions were added to rustc in rust-lang/rust#126930, so should be fine for Cargo as well. --- src/tools/cargo | 2 +- src/tools/tidy/src/deps.rs | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/tools/cargo b/src/tools/cargo index ad074abe3a18c..15fbd2f607d4d 160000 --- a/src/tools/cargo +++ b/src/tools/cargo @@ -1 +1 @@ -Subproject commit ad074abe3a18ce8444c06f962ceecfd056acfc73 +Subproject commit 15fbd2f607d4defc87053b8b76bf5038f2483cf4 diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs index 1ffad06457f9b..5163f039a2329 100644 --- a/src/tools/tidy/src/deps.rs +++ b/src/tools/tidy/src/deps.rs @@ -129,11 +129,14 @@ const EXCEPTIONS_STDARCH: ExceptionList = &[ const EXCEPTIONS_CARGO: ExceptionList = &[ // tidy-alphabetical-start + ("arrayref", "BSD-2-Clause"), ("bitmaps", "MPL-2.0+"), + ("blake3", "CC0-1.0 OR Apache-2.0 OR Apache-2.0 WITH LLVM-exception"), ("bytesize", "Apache-2.0"), ("ciborium", "Apache-2.0"), ("ciborium-io", "Apache-2.0"), ("ciborium-ll", "Apache-2.0"), + ("constant_time_eq", "CC0-1.0 OR MIT-0 OR Apache-2.0"), ("dunce", "CC0-1.0 OR MIT-0 OR Apache-2.0"), ("encoding_rs", "(Apache-2.0 OR MIT) AND BSD-3-Clause"), ("fiat-crypto", "MIT OR Apache-2.0 OR BSD-1-Clause"), From 321a5db7d4026cf703d6deebc413c855ba133142 Mon Sep 17 00:00:00 2001 From: Peter Jaszkowiak Date: Sun, 14 Apr 2024 17:37:45 -0600 Subject: [PATCH 2037/2194] Reserve guarded string literals (RFC 3593) --- compiler/rustc_lexer/src/lib.rs | 93 +++++- compiler/rustc_lint/messages.ftl | 3 + .../rustc_lint/src/context/diagnostics.rs | 3 + compiler/rustc_lint/src/lints.rs | 7 + compiler/rustc_lint_defs/src/builtin.rs | 41 +++ compiler/rustc_lint_defs/src/lib.rs | 2 + compiler/rustc_parse/messages.ftl | 4 + compiler/rustc_parse/src/errors.rs | 18 ++ compiler/rustc_parse/src/lexer/mod.rs | 84 ++++- src/librustdoc/html/highlight.rs | 1 + .../crates/parser/src/lexed_str.rs | 6 + .../reserved-guarded-strings-macro-2021.rs | 20 ++ .../reserved-guarded-strings-macro-2024.rs | 21 ++ .../reserved-guarded-strings-lexing.rs | 80 +++++ .../reserved-guarded-strings-lexing.stderr | 271 ++++++++++++++++ .../reserved-guarded-strings-migration.fixed | 99 ++++++ .../reserved-guarded-strings-migration.rs | 99 ++++++ .../reserved-guarded-strings-migration.stderr | 293 ++++++++++++++++++ .../reserved-guarded-strings-via-macro-2.rs | 18 ++ ...eserved-guarded-strings-via-macro-2.stderr | 20 ++ .../reserved-guarded-strings-via-macro.rs | 12 + .../ui/rust-2024/reserved-guarded-strings.rs | 74 +++++ .../rust-2024/reserved-guarded-strings.stderr | 254 +++++++++++++++ 23 files changed, 1514 insertions(+), 9 deletions(-) create mode 100644 tests/ui/rust-2024/auxiliary/reserved-guarded-strings-macro-2021.rs create mode 100644 tests/ui/rust-2024/auxiliary/reserved-guarded-strings-macro-2024.rs create mode 100644 tests/ui/rust-2024/reserved-guarded-strings-lexing.rs create mode 100644 tests/ui/rust-2024/reserved-guarded-strings-lexing.stderr create mode 100644 tests/ui/rust-2024/reserved-guarded-strings-migration.fixed create mode 100644 tests/ui/rust-2024/reserved-guarded-strings-migration.rs create mode 100644 tests/ui/rust-2024/reserved-guarded-strings-migration.stderr create mode 100644 tests/ui/rust-2024/reserved-guarded-strings-via-macro-2.rs create mode 100644 tests/ui/rust-2024/reserved-guarded-strings-via-macro-2.stderr create mode 100644 tests/ui/rust-2024/reserved-guarded-strings-via-macro.rs create mode 100644 tests/ui/rust-2024/reserved-guarded-strings.rs create mode 100644 tests/ui/rust-2024/reserved-guarded-strings.stderr diff --git a/compiler/rustc_lexer/src/lib.rs b/compiler/rustc_lexer/src/lib.rs index 60aab668cbaa6..b0ab50dd77388 100644 --- a/compiler/rustc_lexer/src/lib.rs +++ b/compiler/rustc_lexer/src/lib.rs @@ -104,6 +104,12 @@ pub enum TokenKind { /// for emoji identifier recovery, as those are not meant to be ever accepted. InvalidPrefix, + /// Guarded string literal prefix: `#"` or `##`. + /// + /// Used for reserving "guarded strings" (RFC 3598) in edition 2024. + /// Split into the component tokens on older editions. + GuardedStrPrefix, + /// Examples: `12u8`, `1.0e-40`, `b"123"`. Note that `_` is an invalid /// suffix, but may be present here on string and float literals. Users of /// this type will need to check for and reject that case. @@ -191,30 +197,41 @@ pub enum DocStyle { /// `rustc_ast::ast::LitKind`). #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)] pub enum LiteralKind { - /// "12_u8", "0o100", "0b120i99", "1f32". + /// `12_u8`, `0o100`, `0b120i99`, `1f32`. Int { base: Base, empty_int: bool }, - /// "12.34f32", "1e3", but not "1f32". + /// `12.34f32`, `1e3`, but not `1f32`. Float { base: Base, empty_exponent: bool }, - /// "'a'", "'\\'", "'''", "';" + /// `'a'`, `'\\'`, `'''`, `';` Char { terminated: bool }, - /// "b'a'", "b'\\'", "b'''", "b';" + /// `b'a'`, `b'\\'`, `b'''`, `b';` Byte { terminated: bool }, - /// ""abc"", ""abc" + /// `"abc"`, `"abc` Str { terminated: bool }, - /// "b"abc"", "b"abc" + /// `b"abc"`, `b"abc` ByteStr { terminated: bool }, /// `c"abc"`, `c"abc` CStr { terminated: bool }, - /// "r"abc"", "r#"abc"#", "r####"ab"###"c"####", "r#"a". `None` indicates + /// `r"abc"`, `r#"abc"#`, `r####"ab"###"c"####`, `r#"a`. `None` indicates /// an invalid literal. RawStr { n_hashes: Option }, - /// "br"abc"", "br#"abc"#", "br####"ab"###"c"####", "br#"a". `None` + /// `br"abc"`, `br#"abc"#`, `br####"ab"###"c"####`, `br#"a`. `None` /// indicates an invalid literal. RawByteStr { n_hashes: Option }, /// `cr"abc"`, "cr#"abc"#", `cr#"a`. `None` indicates an invalid literal. RawCStr { n_hashes: Option }, } +/// `#"abc"#`, `##"a"` (fewer closing), or even `#"a` (unterminated). +/// +/// Can capture fewer closing hashes than starting hashes, +/// for more efficient lexing and better backwards diagnostics. +#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)] +pub struct GuardedStr { + pub n_hashes: u32, + pub terminated: bool, + pub token_len: u32, +} + #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)] pub enum RawStrError { /// Non `#` characters exist between `r` and `"`, e.g. `r##~"abcde"##` @@ -403,6 +420,12 @@ impl Cursor<'_> { TokenKind::Literal { kind: literal_kind, suffix_start } } + // Guarded string literal prefix: `#"` or `##` + '#' if matches!(self.first(), '"' | '#') => { + self.bump(); + TokenKind::GuardedStrPrefix + } + // One-symbol tokens. ';' => Semi, ',' => Comma, @@ -780,6 +803,60 @@ impl Cursor<'_> { false } + /// Attempt to lex for a guarded string literal. + /// + /// Used by `rustc_parse::lexer` to lex for guarded strings + /// conditionally based on edition. + /// + /// Note: this will not reset the `Cursor` when a + /// guarded string is not found. It is the caller's + /// responsibility to do so. + pub fn guarded_double_quoted_string(&mut self) -> Option { + debug_assert!(self.prev() != '#'); + + let mut n_start_hashes: u32 = 0; + while self.first() == '#' { + n_start_hashes += 1; + self.bump(); + } + + if self.first() != '"' { + return None; + } + self.bump(); + debug_assert!(self.prev() == '"'); + + // Lex the string itself as a normal string literal + // so we can recover that for older editions later. + let terminated = self.double_quoted_string(); + if !terminated { + let token_len = self.pos_within_token(); + self.reset_pos_within_token(); + + return Some(GuardedStr { n_hashes: n_start_hashes, terminated: false, token_len }); + } + + // Consume closing '#' symbols. + // Note that this will not consume extra trailing `#` characters: + // `###"abcde"####` is lexed as a `GuardedStr { n_end_hashes: 3, .. }` + // followed by a `#` token. + let mut n_end_hashes = 0; + while self.first() == '#' && n_end_hashes < n_start_hashes { + n_end_hashes += 1; + self.bump(); + } + + // Reserved syntax, always an error, so it doesn't matter if + // `n_start_hashes != n_end_hashes`. + + self.eat_literal_suffix(); + + let token_len = self.pos_within_token(); + self.reset_pos_within_token(); + + Some(GuardedStr { n_hashes: n_start_hashes, terminated: true, token_len }) + } + /// Eats the double-quoted string and returns `n_hashes` and an error if encountered. fn raw_double_quoted_string(&mut self, prefix_len: u32) -> Result { // Wrap the actual function to handle the error with too many hashes. diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl index d379959487191..e733e92c7cb33 100644 --- a/compiler/rustc_lint/messages.ftl +++ b/compiler/rustc_lint/messages.ftl @@ -740,6 +740,9 @@ lint_reserved_prefix = prefix `{$prefix}` is unknown .label = unknown prefix .suggestion = insert whitespace here to avoid this being parsed as a prefix in Rust 2021 +lint_reserved_string = will be parsed as a guarded string in Rust 2024 + .suggestion = insert whitespace here to avoid this being parsed as a guarded string in Rust 2024 + lint_shadowed_into_iter = this method call resolves to `<&{$target} as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to `<{$target} as IntoIterator>::into_iter` in Rust {$edition} .use_iter_suggestion = use `.iter()` instead of `.into_iter()` to avoid ambiguity diff --git a/compiler/rustc_lint/src/context/diagnostics.rs b/compiler/rustc_lint/src/context/diagnostics.rs index b5ab56912cb2d..565c3c0425256 100644 --- a/compiler/rustc_lint/src/context/diagnostics.rs +++ b/compiler/rustc_lint/src/context/diagnostics.rs @@ -176,6 +176,9 @@ pub(super) fn decorate_lint(sess: &Session, diagnostic: BuiltinLintDiag, diag: & lints::RawPrefix { label: label_span, suggestion: label_span.shrink_to_hi() } .decorate_lint(diag); } + BuiltinLintDiag::ReservedString(suggestion) => { + lints::ReservedString { suggestion }.decorate_lint(diag); + } BuiltinLintDiag::UnusedBuiltinAttribute { attr_name, macro_name, invoc_span } => { lints::UnusedBuiltinAttribute { invoc_span, attr_name, macro_name }.decorate_lint(diag); } diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index a861894a44493..87afeca0b28f6 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -3053,3 +3053,10 @@ pub(crate) enum MutRefSugg { #[derive(LintDiagnostic)] #[diag(lint_unqualified_local_imports)] pub(crate) struct UnqualifiedLocalImportsDiag {} + +#[derive(LintDiagnostic)] +#[diag(lint_reserved_string)] +pub(crate) struct ReservedString { + #[suggestion(code = " ", applicability = "machine-applicable")] + pub suggestion: Span, +} diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index a123059df8f12..827791c54be01 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs @@ -92,6 +92,7 @@ declare_lint_pass! { RUST_2021_INCOMPATIBLE_OR_PATTERNS, RUST_2021_PREFIXES_INCOMPATIBLE_SYNTAX, RUST_2021_PRELUDE_COLLISIONS, + RUST_2024_GUARDED_STRING_INCOMPATIBLE_SYNTAX, RUST_2024_INCOMPATIBLE_PAT, RUST_2024_PRELUDE_COLLISIONS, SELF_CONSTRUCTOR_FROM_OUTER_ITEM, @@ -4996,3 +4997,43 @@ declare_lint! { Warn, "detects pointer to integer transmutes in const functions and associated constants", } + +declare_lint! { + /// The `rust_2024_guarded_string_incompatible_syntax` lint detects `#` tokens + /// that will be parsed as part of a guarded string literal in Rust 2024. + /// + /// ### Example + /// + /// ```rust,edition2021,compile_fail + /// #![deny(rust_2024_guarded_string_incompatible_syntax)] + /// + /// macro_rules! m { + /// (# $x:expr #) => (); + /// (# $x:expr) => (); + /// } + /// + /// m!(#"hey"#); + /// m!(#"hello"); + /// ``` + /// + /// {{produces}} + /// + /// ### Explanation + /// + /// Prior to Rust 2024, `#"hey"#` is three tokens: the first `#` + /// followed by the string literal `"hey"` then the final `#`. + /// In Rust 2024, the whole sequence is considered a single token. + /// + /// This lint suggests to add whitespace between the leading `#` + /// and the string to keep them separated in Rust 2024. + // Allow this lint -- rustdoc doesn't yet support threading edition into this lint's parser. + #[allow(rustdoc::invalid_rust_codeblocks)] + pub RUST_2024_GUARDED_STRING_INCOMPATIBLE_SYNTAX, + Allow, + "will be parsed as a guarded string in Rust 2024", + @future_incompatible = FutureIncompatibleInfo { + reason: FutureIncompatibilityReason::EditionError(Edition::Edition2024), + reference: "issue #123735 ", + }; + crate_level_only +} diff --git a/compiler/rustc_lint_defs/src/lib.rs b/compiler/rustc_lint_defs/src/lib.rs index 386918a5c4157..c01fa5c54d65e 100644 --- a/compiler/rustc_lint_defs/src/lib.rs +++ b/compiler/rustc_lint_defs/src/lib.rs @@ -614,6 +614,8 @@ pub enum BuiltinLintDiag { ReservedPrefix(Span, String), /// `'r#` in edition < 2021. RawPrefix(Span), + /// `##` or `#"` is edition < 2024. + ReservedString(Span), TrailingMacro(bool, Ident), BreakWithLabelAndLoop(Span), UnicodeTextFlow(Span, String), diff --git a/compiler/rustc_parse/messages.ftl b/compiler/rustc_parse/messages.ftl index 948199fd55c65..ba5e2ddf4fcd1 100644 --- a/compiler/rustc_parse/messages.ftl +++ b/compiler/rustc_parse/messages.ftl @@ -706,6 +706,10 @@ parse_require_colon_after_labeled_expression = labeled expression must be follow .label = the label .suggestion = add `:` after the label +parse_reserved_string = invalid string literal + .note = unprefixed guarded string literals are reserved for future use since Rust 2024 + .suggestion_whitespace = consider inserting whitespace here + parse_return_types_use_thin_arrow = return types are denoted using `->` .suggestion = use `->` instead diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs index dade39127515f..124975f67f1ac 100644 --- a/compiler/rustc_parse/src/errors.rs +++ b/compiler/rustc_parse/src/errors.rs @@ -2110,6 +2110,24 @@ pub(crate) enum UnknownPrefixSugg { }, } +#[derive(Diagnostic)] +#[diag(parse_reserved_string)] +#[note] +pub(crate) struct ReservedString { + #[primary_span] + pub span: Span, + #[subdiagnostic] + pub sugg: Option, +} +#[derive(Subdiagnostic)] +#[suggestion( + parse_suggestion_whitespace, + code = " ", + applicability = "maybe-incorrect", + style = "verbose" +)] +pub(crate) struct GuardedStringSugg(#[primary_span] pub Span); + #[derive(Diagnostic)] #[diag(parse_too_many_hashes)] pub(crate) struct TooManyHashes { diff --git a/compiler/rustc_parse/src/lexer/mod.rs b/compiler/rustc_parse/src/lexer/mod.rs index 3e46fc93fa49d..d627ef3d2cbe3 100644 --- a/compiler/rustc_parse/src/lexer/mod.rs +++ b/compiler/rustc_parse/src/lexer/mod.rs @@ -10,7 +10,8 @@ use rustc_lexer::unescape::{self, EscapeError, Mode}; use rustc_lexer::{Base, Cursor, DocStyle, LiteralKind, RawStrError}; use rustc_session::lint::BuiltinLintDiag; use rustc_session::lint::builtin::{ - RUST_2021_PREFIXES_INCOMPATIBLE_SYNTAX, TEXT_DIRECTION_CODEPOINT_IN_COMMENT, + RUST_2021_PREFIXES_INCOMPATIBLE_SYNTAX, RUST_2024_GUARDED_STRING_INCOMPATIBLE_SYNTAX, + TEXT_DIRECTION_CODEPOINT_IN_COMMENT, }; use rustc_session::parse::ParseSess; use rustc_span::symbol::Symbol; @@ -251,6 +252,7 @@ impl<'psess, 'src> StringReader<'psess, 'src> { let prefix_span = self.mk_sp(start, lit_start); return (Token::new(self.ident(start), prefix_span), preceded_by_whitespace); } + rustc_lexer::TokenKind::GuardedStrPrefix => self.maybe_report_guarded_str(start, str_before), rustc_lexer::TokenKind::Literal { kind, suffix_start } => { let suffix_start = start + BytePos(suffix_start); let (kind, symbol) = self.cook_lexer_literal(start, suffix_start, kind); @@ -781,6 +783,86 @@ impl<'psess, 'src> StringReader<'psess, 'src> { } } + /// Detect guarded string literal syntax + /// + /// RFC 3598 reserved this syntax for future use. As of Rust 2024, + /// using this syntax produces an error. In earlier editions, however, it + /// only results in an (allowed by default) lint, and is treated as + /// separate tokens. + fn maybe_report_guarded_str(&mut self, start: BytePos, str_before: &'src str) -> TokenKind { + let span = self.mk_sp(start, self.pos); + let edition2024 = span.edition().at_least_rust_2024(); + + let space_pos = start + BytePos(1); + let space_span = self.mk_sp(space_pos, space_pos); + + let mut cursor = Cursor::new(str_before); + + let (span, unterminated) = match cursor.guarded_double_quoted_string() { + Some(rustc_lexer::GuardedStr { n_hashes, terminated, token_len }) => { + let end = start + BytePos(token_len); + let span = self.mk_sp(start, end); + let str_start = start + BytePos(n_hashes); + + if edition2024 { + self.cursor = cursor; + self.pos = end; + } + + let unterminated = if terminated { None } else { Some(str_start) }; + + (span, unterminated) + } + _ => { + // We should only get here in the `##+` case. + debug_assert_eq!(self.str_from_to(start, start + BytePos(2)), "##"); + + (span, None) + } + }; + if edition2024 { + if let Some(str_start) = unterminated { + // Only a fatal error if string is unterminated. + self.dcx() + .struct_span_fatal( + self.mk_sp(str_start, self.pos), + "unterminated double quote string", + ) + .with_code(E0765) + .emit() + } + + let sugg = if span.from_expansion() { + None + } else { + Some(errors::GuardedStringSugg(space_span)) + }; + + // In Edition 2024 and later, emit a hard error. + let err = self.dcx().emit_err(errors::ReservedString { span, sugg }); + + token::Literal(token::Lit { + kind: token::Err(err), + symbol: self.symbol_from_to(start, self.pos), + suffix: None, + }) + } else { + // Before Rust 2024, only emit a lint for migration. + self.psess.buffer_lint( + RUST_2024_GUARDED_STRING_INCOMPATIBLE_SYNTAX, + span, + ast::CRATE_NODE_ID, + BuiltinLintDiag::ReservedString(space_span), + ); + + // For backwards compatibility, roll back to after just the first `#` + // and return the `Pound` token. + self.pos = start + BytePos(1); + self.cursor = Cursor::new(&str_before[1..]); + token::Pound + } + } + fn report_too_many_hashes(&self, start: BytePos, num: u32) -> ! { self.dcx().emit_fatal(errors::TooManyHashes { span: self.mk_sp(start, self.pos), num }); } diff --git a/src/librustdoc/html/highlight.rs b/src/librustdoc/html/highlight.rs index e7ddd4b73b47b..b68b729509635 100644 --- a/src/librustdoc/html/highlight.rs +++ b/src/librustdoc/html/highlight.rs @@ -845,6 +845,7 @@ impl<'src> Classifier<'src> { // Number literals. LiteralKind::Float { .. } | LiteralKind::Int { .. } => Class::Number, }, + TokenKind::GuardedStrPrefix => return no_highlight(sink), TokenKind::Ident | TokenKind::RawIdent if lookahead == Some(TokenKind::Bang) => { self.in_macro = true; sink(Highlight::EnterSpan { class: Class::Macro(self.new_span(before, text)) }); diff --git a/src/tools/rust-analyzer/crates/parser/src/lexed_str.rs b/src/tools/rust-analyzer/crates/parser/src/lexed_str.rs index dceac815e0b5c..7ea23b4f752c1 100644 --- a/src/tools/rust-analyzer/crates/parser/src/lexed_str.rs +++ b/src/tools/rust-analyzer/crates/parser/src/lexed_str.rs @@ -187,6 +187,12 @@ impl<'a> Converter<'a> { } rustc_lexer::TokenKind::RawIdent => IDENT, + + rustc_lexer::TokenKind::GuardedStrPrefix => { + err = "Invalid string literal (reserved syntax)"; + ERROR + }, + rustc_lexer::TokenKind::Literal { kind, .. } => { self.extend_literal(token_text.len(), kind); return; diff --git a/tests/ui/rust-2024/auxiliary/reserved-guarded-strings-macro-2021.rs b/tests/ui/rust-2024/auxiliary/reserved-guarded-strings-macro-2021.rs new file mode 100644 index 0000000000000..81080fcdce307 --- /dev/null +++ b/tests/ui/rust-2024/auxiliary/reserved-guarded-strings-macro-2021.rs @@ -0,0 +1,20 @@ +//@ force-host +//@ edition:2021 +//@ no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::TokenStream; +use std::str::FromStr; + +#[proc_macro] +pub fn number_of_tokens_in_a_guarded_string_literal(_: TokenStream) -> TokenStream { + TokenStream::from_str("#\"abc\"#").unwrap().into_iter().count().to_string().parse().unwrap() +} + +#[proc_macro] +pub fn number_of_tokens_in_a_guarded_unterminated_string_literal(_: TokenStream) -> TokenStream { + TokenStream::from_str("#\"abc\"").unwrap().into_iter().count().to_string().parse().unwrap() +} diff --git a/tests/ui/rust-2024/auxiliary/reserved-guarded-strings-macro-2024.rs b/tests/ui/rust-2024/auxiliary/reserved-guarded-strings-macro-2024.rs new file mode 100644 index 0000000000000..2c3dc30f0ae9b --- /dev/null +++ b/tests/ui/rust-2024/auxiliary/reserved-guarded-strings-macro-2024.rs @@ -0,0 +1,21 @@ +//@ force-host +//@ compile-flags: -Zunstable-options +//@ edition:2024 +//@ no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::TokenStream; +use std::str::FromStr; + +#[proc_macro] +pub fn number_of_tokens_in_a_guarded_string_literal(_: TokenStream) -> TokenStream { + TokenStream::from_str("#\"abc\"#").unwrap().into_iter().count().to_string().parse().unwrap() +} + +#[proc_macro] +pub fn number_of_tokens_in_a_guarded_unterminated_string_literal(_: TokenStream) -> TokenStream { + TokenStream::from_str("#\"abc\"").unwrap().into_iter().count().to_string().parse().unwrap() +} diff --git a/tests/ui/rust-2024/reserved-guarded-strings-lexing.rs b/tests/ui/rust-2024/reserved-guarded-strings-lexing.rs new file mode 100644 index 0000000000000..83e0dcbb4bebc --- /dev/null +++ b/tests/ui/rust-2024/reserved-guarded-strings-lexing.rs @@ -0,0 +1,80 @@ +//@ edition:2021 +// ignore-tidy-linelength + +#![warn(rust_2024_guarded_string_incompatible_syntax)] + +macro_rules! demo2 { + ( $a:tt $b:tt ) => { println!("two tokens") }; +} + +macro_rules! demo3 { + ( $a:tt $b:tt $c:tt ) => { println!("three tokens") }; +} + +macro_rules! demo4 { + ( $a:tt $b:tt $c:tt $d:tt ) => { println!("four tokens") }; +} + +macro_rules! demo5 { + ( $a:tt $b:tt $c:tt $d:tt $e:tt ) => { println!("five tokens") }; +} + +macro_rules! demo7 { + ( $a:tt $b:tt $c:tt $d:tt $e:tt $f:tt $g:tt ) => { println!("seven tokens") }; +} + + +fn main() { + demo3!(## "foo"); + //~^ WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] + //~| WARNING hard error in Rust 2024 + demo4!(### "foo"); + //~^ WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] + //~| WARNING hard error in Rust 2024 + //~| WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] + //~| WARNING hard error in Rust 2024 + demo4!(## "foo"#); + //~^ WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] + //~| WARNING hard error in Rust 2024 + demo7!(### "foo"###); + //~^ WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] + //~| WARNING hard error in Rust 2024 + //~| WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] + //~| WARNING hard error in Rust 2024 + //~| WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] + //~| WARNING hard error in Rust 2024 + //~| WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] + //~| WARNING hard error in Rust 2024 + + demo5!(###"foo"#); + //~^ WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] + //~| WARNING hard error in Rust 2024 + //~| WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] + //~| WARNING hard error in Rust 2024 + //~| WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] + //~| WARNING hard error in Rust 2024 + demo5!(#"foo"###); + //~^ WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] + //~| WARNING hard error in Rust 2024 + //~| WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] + //~| WARNING hard error in Rust 2024 + //~| WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] + //~| WARNING hard error in Rust 2024 + demo4!("foo"###); + //~^ WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] + //~| WARNING hard error in Rust 2024 + //~| WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] + //~| WARNING hard error in Rust 2024 + + // Non-ascii identifiers + demo2!(Ñ"foo"); + //~^ ERROR prefix `Ñ` is unknown + demo4!(Ñ#""#); + //~^ ERROR prefix `Ñ` is unknown + //~| WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] + //~| WARNING hard error in Rust 2024 + demo3!(🙃#""); + //~^ ERROR identifiers cannot contain emoji + //~| WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] + //~| WARNING hard error in Rust 2024 +} diff --git a/tests/ui/rust-2024/reserved-guarded-strings-lexing.stderr b/tests/ui/rust-2024/reserved-guarded-strings-lexing.stderr new file mode 100644 index 0000000000000..e2e1ac42f05c2 --- /dev/null +++ b/tests/ui/rust-2024/reserved-guarded-strings-lexing.stderr @@ -0,0 +1,271 @@ +error: prefix `Ñ` is unknown + --> $DIR/reserved-guarded-strings-lexing.rs:70:12 + | +LL | demo2!(Ñ"foo"); + | ^ unknown prefix + | + = note: prefixed identifiers and literals are reserved since Rust 2021 +help: consider inserting whitespace here + | +LL | demo2!(Ñ "foo"); + | + + +error: prefix `Ñ` is unknown + --> $DIR/reserved-guarded-strings-lexing.rs:72:12 + | +LL | demo4!(Ñ#""#); + | ^ unknown prefix + | + = note: prefixed identifiers and literals are reserved since Rust 2021 +help: consider inserting whitespace here + | +LL | demo4!(Ñ #""#); + | + + +error: identifiers cannot contain emoji: `🙃` + --> $DIR/reserved-guarded-strings-lexing.rs:76:12 + | +LL | demo3!(🙃#""); + | ^^ + +warning: will be parsed as a guarded string in Rust 2024 + --> $DIR/reserved-guarded-strings-lexing.rs:28:12 + | +LL | demo3!(## "foo"); + | ^^ + | + = warning: this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024! + = note: for more information, see issue #123735 +note: the lint level is defined here + --> $DIR/reserved-guarded-strings-lexing.rs:4:9 + | +LL | #![warn(rust_2024_guarded_string_incompatible_syntax)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: insert whitespace here to avoid this being parsed as a guarded string in Rust 2024 + | +LL | demo3!(# # "foo"); + | + + +warning: will be parsed as a guarded string in Rust 2024 + --> $DIR/reserved-guarded-strings-lexing.rs:31:12 + | +LL | demo4!(### "foo"); + | ^^ + | + = warning: this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024! + = note: for more information, see issue #123735 +help: insert whitespace here to avoid this being parsed as a guarded string in Rust 2024 + | +LL | demo4!(# ## "foo"); + | + + +warning: will be parsed as a guarded string in Rust 2024 + --> $DIR/reserved-guarded-strings-lexing.rs:31:13 + | +LL | demo4!(### "foo"); + | ^^ + | + = warning: this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024! + = note: for more information, see issue #123735 +help: insert whitespace here to avoid this being parsed as a guarded string in Rust 2024 + | +LL | demo4!(## # "foo"); + | + + +warning: will be parsed as a guarded string in Rust 2024 + --> $DIR/reserved-guarded-strings-lexing.rs:36:12 + | +LL | demo4!(## "foo"#); + | ^^ + | + = warning: this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024! + = note: for more information, see issue #123735 +help: insert whitespace here to avoid this being parsed as a guarded string in Rust 2024 + | +LL | demo4!(# # "foo"#); + | + + +warning: will be parsed as a guarded string in Rust 2024 + --> $DIR/reserved-guarded-strings-lexing.rs:39:12 + | +LL | demo7!(### "foo"###); + | ^^ + | + = warning: this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024! + = note: for more information, see issue #123735 +help: insert whitespace here to avoid this being parsed as a guarded string in Rust 2024 + | +LL | demo7!(# ## "foo"###); + | + + +warning: will be parsed as a guarded string in Rust 2024 + --> $DIR/reserved-guarded-strings-lexing.rs:39:13 + | +LL | demo7!(### "foo"###); + | ^^ + | + = warning: this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024! + = note: for more information, see issue #123735 +help: insert whitespace here to avoid this being parsed as a guarded string in Rust 2024 + | +LL | demo7!(## # "foo"###); + | + + +warning: will be parsed as a guarded string in Rust 2024 + --> $DIR/reserved-guarded-strings-lexing.rs:39:21 + | +LL | demo7!(### "foo"###); + | ^^ + | + = warning: this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024! + = note: for more information, see issue #123735 +help: insert whitespace here to avoid this being parsed as a guarded string in Rust 2024 + | +LL | demo7!(### "foo"# ##); + | + + +warning: will be parsed as a guarded string in Rust 2024 + --> $DIR/reserved-guarded-strings-lexing.rs:39:22 + | +LL | demo7!(### "foo"###); + | ^^ + | + = warning: this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024! + = note: for more information, see issue #123735 +help: insert whitespace here to avoid this being parsed as a guarded string in Rust 2024 + | +LL | demo7!(### "foo"## #); + | + + +warning: will be parsed as a guarded string in Rust 2024 + --> $DIR/reserved-guarded-strings-lexing.rs:49:12 + | +LL | demo5!(###"foo"#); + | ^^^^^^^^^ + | + = warning: this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024! + = note: for more information, see issue #123735 +help: insert whitespace here to avoid this being parsed as a guarded string in Rust 2024 + | +LL | demo5!(# ##"foo"#); + | + + +warning: will be parsed as a guarded string in Rust 2024 + --> $DIR/reserved-guarded-strings-lexing.rs:49:13 + | +LL | demo5!(###"foo"#); + | ^^^^^^^^ + | + = warning: this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024! + = note: for more information, see issue #123735 +help: insert whitespace here to avoid this being parsed as a guarded string in Rust 2024 + | +LL | demo5!(## #"foo"#); + | + + +warning: will be parsed as a guarded string in Rust 2024 + --> $DIR/reserved-guarded-strings-lexing.rs:49:14 + | +LL | demo5!(###"foo"#); + | ^^^^^^^ + | + = warning: this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024! + = note: for more information, see issue #123735 +help: insert whitespace here to avoid this being parsed as a guarded string in Rust 2024 + | +LL | demo5!(### "foo"#); + | + + +warning: will be parsed as a guarded string in Rust 2024 + --> $DIR/reserved-guarded-strings-lexing.rs:56:12 + | +LL | demo5!(#"foo"###); + | ^^^^^^^ + | + = warning: this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024! + = note: for more information, see issue #123735 +help: insert whitespace here to avoid this being parsed as a guarded string in Rust 2024 + | +LL | demo5!(# "foo"###); + | + + +warning: will be parsed as a guarded string in Rust 2024 + --> $DIR/reserved-guarded-strings-lexing.rs:56:18 + | +LL | demo5!(#"foo"###); + | ^^ + | + = warning: this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024! + = note: for more information, see issue #123735 +help: insert whitespace here to avoid this being parsed as a guarded string in Rust 2024 + | +LL | demo5!(#"foo"# ##); + | + + +warning: will be parsed as a guarded string in Rust 2024 + --> $DIR/reserved-guarded-strings-lexing.rs:56:19 + | +LL | demo5!(#"foo"###); + | ^^ + | + = warning: this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024! + = note: for more information, see issue #123735 +help: insert whitespace here to avoid this being parsed as a guarded string in Rust 2024 + | +LL | demo5!(#"foo"## #); + | + + +warning: will be parsed as a guarded string in Rust 2024 + --> $DIR/reserved-guarded-strings-lexing.rs:63:17 + | +LL | demo4!("foo"###); + | ^^ + | + = warning: this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024! + = note: for more information, see issue #123735 +help: insert whitespace here to avoid this being parsed as a guarded string in Rust 2024 + | +LL | demo4!("foo"# ##); + | + + +warning: will be parsed as a guarded string in Rust 2024 + --> $DIR/reserved-guarded-strings-lexing.rs:63:18 + | +LL | demo4!("foo"###); + | ^^ + | + = warning: this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024! + = note: for more information, see issue #123735 +help: insert whitespace here to avoid this being parsed as a guarded string in Rust 2024 + | +LL | demo4!("foo"## #); + | + + +warning: will be parsed as a guarded string in Rust 2024 + --> $DIR/reserved-guarded-strings-lexing.rs:72:13 + | +LL | demo4!(Ñ#""#); + | ^^^^ + | + = warning: this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024! + = note: for more information, see issue #123735 +help: insert whitespace here to avoid this being parsed as a guarded string in Rust 2024 + | +LL | demo4!(Ñ# ""#); + | + + +warning: will be parsed as a guarded string in Rust 2024 + --> $DIR/reserved-guarded-strings-lexing.rs:76:13 + | +LL | demo3!(🙃#""); + | ^^^ + | + = warning: this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024! + = note: for more information, see issue #123735 +help: insert whitespace here to avoid this being parsed as a guarded string in Rust 2024 + | +LL | demo3!(🙃# ""); + | + + +error: aborting due to 3 previous errors; 18 warnings emitted + diff --git a/tests/ui/rust-2024/reserved-guarded-strings-migration.fixed b/tests/ui/rust-2024/reserved-guarded-strings-migration.fixed new file mode 100644 index 0000000000000..d92df7b5375a7 --- /dev/null +++ b/tests/ui/rust-2024/reserved-guarded-strings-migration.fixed @@ -0,0 +1,99 @@ +//@ check-pass +//@ run-rustfix +//@ edition:2021 + +#![warn(rust_2024_guarded_string_incompatible_syntax)] + +macro_rules! demo1 { + ( $a:tt ) => { println!("one tokens") }; +} + +macro_rules! demo2 { + ( $a:tt $b:tt ) => { println!("two tokens") }; +} + +macro_rules! demo3 { + ( $a:tt $b:tt $c:tt ) => { println!("three tokens") }; +} + +macro_rules! demo4 { + ( $a:tt $b:tt $c:tt $d:tt ) => { println!("four tokens") }; +} + +macro_rules! demo5 { + ( $a:tt $b:tt $c:tt $d:tt $e:tt ) => { println!("five tokens") }; +} + +macro_rules! demo6 { + ( $a:tt $b:tt $c:tt $d:tt $e:tt $f:tt ) => { println!("six tokens") }; +} + + +fn main() { + demo1!(""); + demo2!(# ""); + demo3!(# ""#); + demo2!(# "foo"); + demo3!(# "foo"#); + demo2!("foo"#); + + demo3!(# # "foo"); + //~^ WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] + //~| WARNING hard error in Rust 2024 + demo4!(# # # "foo"); + //~^ WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] + //~| WARNING hard error in Rust 2024 + //~| WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] + //~| WARNING hard error in Rust 2024 + demo4!(# # "foo"#); + //~^ WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] + //~| WARNING hard error in Rust 2024 + demo6!(# # # "foo"# #); + //~^ WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] + //~| WARNING hard error in Rust 2024 + //~| WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] + //~| WARNING hard error in Rust 2024 + //~| WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] + //~| WARNING hard error in Rust 2024 + + demo4!("foo"# # #); + //~^ WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] + //~| WARNING hard error in Rust 2024 + //~| WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] + //~| WARNING hard error in Rust 2024 + + demo2!(# ""); + //~^ WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] + //~| WARNING hard error in Rust 2024 + demo3!(# ""#); + //~^ WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] + //~| WARNING hard error in Rust 2024 + demo3!(# # ""); + //~^ WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] + //~| WARNING hard error in Rust 2024 + //~| WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] + //~| WARNING hard error in Rust 2024 + demo2!(# "foo"); + //~^ WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] + //~| WARNING hard error in Rust 2024 + demo3!(# # "foo"); + //~^ WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] + //~| WARNING hard error in Rust 2024 + //~| WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] + //~| WARNING hard error in Rust 2024 + demo3!(# "foo"#); + //~^ WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] + //~| WARNING hard error in Rust 2024 + demo4!(# # "foo"#); + //~^ WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] + //~| WARNING hard error in Rust 2024 + //~| WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] + //~| WARNING hard error in Rust 2024 + demo5!(# # "foo"# #); + //~^ WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] + //~| WARNING hard error in Rust 2024 + //~| WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] + //~| WARNING hard error in Rust 2024 + //~| WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] + //~| WARNING hard error in Rust 2024 +} diff --git a/tests/ui/rust-2024/reserved-guarded-strings-migration.rs b/tests/ui/rust-2024/reserved-guarded-strings-migration.rs new file mode 100644 index 0000000000000..5905f2abe3232 --- /dev/null +++ b/tests/ui/rust-2024/reserved-guarded-strings-migration.rs @@ -0,0 +1,99 @@ +//@ check-pass +//@ run-rustfix +//@ edition:2021 + +#![warn(rust_2024_guarded_string_incompatible_syntax)] + +macro_rules! demo1 { + ( $a:tt ) => { println!("one tokens") }; +} + +macro_rules! demo2 { + ( $a:tt $b:tt ) => { println!("two tokens") }; +} + +macro_rules! demo3 { + ( $a:tt $b:tt $c:tt ) => { println!("three tokens") }; +} + +macro_rules! demo4 { + ( $a:tt $b:tt $c:tt $d:tt ) => { println!("four tokens") }; +} + +macro_rules! demo5 { + ( $a:tt $b:tt $c:tt $d:tt $e:tt ) => { println!("five tokens") }; +} + +macro_rules! demo6 { + ( $a:tt $b:tt $c:tt $d:tt $e:tt $f:tt ) => { println!("six tokens") }; +} + + +fn main() { + demo1!(""); + demo2!(# ""); + demo3!(# ""#); + demo2!(# "foo"); + demo3!(# "foo"#); + demo2!("foo"#); + + demo3!(## "foo"); + //~^ WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] + //~| WARNING hard error in Rust 2024 + demo4!(### "foo"); + //~^ WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] + //~| WARNING hard error in Rust 2024 + //~| WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] + //~| WARNING hard error in Rust 2024 + demo4!(## "foo"#); + //~^ WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] + //~| WARNING hard error in Rust 2024 + demo6!(### "foo"##); + //~^ WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] + //~| WARNING hard error in Rust 2024 + //~| WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] + //~| WARNING hard error in Rust 2024 + //~| WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] + //~| WARNING hard error in Rust 2024 + + demo4!("foo"###); + //~^ WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] + //~| WARNING hard error in Rust 2024 + //~| WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] + //~| WARNING hard error in Rust 2024 + + demo2!(#""); + //~^ WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] + //~| WARNING hard error in Rust 2024 + demo3!(#""#); + //~^ WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] + //~| WARNING hard error in Rust 2024 + demo3!(##""); + //~^ WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] + //~| WARNING hard error in Rust 2024 + //~| WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] + //~| WARNING hard error in Rust 2024 + demo2!(#"foo"); + //~^ WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] + //~| WARNING hard error in Rust 2024 + demo3!(##"foo"); + //~^ WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] + //~| WARNING hard error in Rust 2024 + //~| WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] + //~| WARNING hard error in Rust 2024 + demo3!(#"foo"#); + //~^ WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] + //~| WARNING hard error in Rust 2024 + demo4!(##"foo"#); + //~^ WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] + //~| WARNING hard error in Rust 2024 + //~| WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] + //~| WARNING hard error in Rust 2024 + demo5!(##"foo"##); + //~^ WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] + //~| WARNING hard error in Rust 2024 + //~| WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] + //~| WARNING hard error in Rust 2024 + //~| WARNING parsed as a guarded string in Rust 2024 [rust_2024_guarded_string_incompatible_syntax] + //~| WARNING hard error in Rust 2024 +} diff --git a/tests/ui/rust-2024/reserved-guarded-strings-migration.stderr b/tests/ui/rust-2024/reserved-guarded-strings-migration.stderr new file mode 100644 index 0000000000000..d7f8e5c9b4b24 --- /dev/null +++ b/tests/ui/rust-2024/reserved-guarded-strings-migration.stderr @@ -0,0 +1,293 @@ +warning: will be parsed as a guarded string in Rust 2024 + --> $DIR/reserved-guarded-strings-migration.rs:40:12 + | +LL | demo3!(## "foo"); + | ^^ + | + = warning: this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024! + = note: for more information, see issue #123735 +note: the lint level is defined here + --> $DIR/reserved-guarded-strings-migration.rs:5:9 + | +LL | #![warn(rust_2024_guarded_string_incompatible_syntax)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: insert whitespace here to avoid this being parsed as a guarded string in Rust 2024 + | +LL | demo3!(# # "foo"); + | + + +warning: will be parsed as a guarded string in Rust 2024 + --> $DIR/reserved-guarded-strings-migration.rs:43:12 + | +LL | demo4!(### "foo"); + | ^^ + | + = warning: this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024! + = note: for more information, see issue #123735 +help: insert whitespace here to avoid this being parsed as a guarded string in Rust 2024 + | +LL | demo4!(# ## "foo"); + | + + +warning: will be parsed as a guarded string in Rust 2024 + --> $DIR/reserved-guarded-strings-migration.rs:43:13 + | +LL | demo4!(### "foo"); + | ^^ + | + = warning: this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024! + = note: for more information, see issue #123735 +help: insert whitespace here to avoid this being parsed as a guarded string in Rust 2024 + | +LL | demo4!(## # "foo"); + | + + +warning: will be parsed as a guarded string in Rust 2024 + --> $DIR/reserved-guarded-strings-migration.rs:48:12 + | +LL | demo4!(## "foo"#); + | ^^ + | + = warning: this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024! + = note: for more information, see issue #123735 +help: insert whitespace here to avoid this being parsed as a guarded string in Rust 2024 + | +LL | demo4!(# # "foo"#); + | + + +warning: will be parsed as a guarded string in Rust 2024 + --> $DIR/reserved-guarded-strings-migration.rs:51:12 + | +LL | demo6!(### "foo"##); + | ^^ + | + = warning: this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024! + = note: for more information, see issue #123735 +help: insert whitespace here to avoid this being parsed as a guarded string in Rust 2024 + | +LL | demo6!(# ## "foo"##); + | + + +warning: will be parsed as a guarded string in Rust 2024 + --> $DIR/reserved-guarded-strings-migration.rs:51:13 + | +LL | demo6!(### "foo"##); + | ^^ + | + = warning: this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024! + = note: for more information, see issue #123735 +help: insert whitespace here to avoid this being parsed as a guarded string in Rust 2024 + | +LL | demo6!(## # "foo"##); + | + + +warning: will be parsed as a guarded string in Rust 2024 + --> $DIR/reserved-guarded-strings-migration.rs:51:21 + | +LL | demo6!(### "foo"##); + | ^^ + | + = warning: this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024! + = note: for more information, see issue #123735 +help: insert whitespace here to avoid this being parsed as a guarded string in Rust 2024 + | +LL | demo6!(### "foo"# #); + | + + +warning: will be parsed as a guarded string in Rust 2024 + --> $DIR/reserved-guarded-strings-migration.rs:59:17 + | +LL | demo4!("foo"###); + | ^^ + | + = warning: this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024! + = note: for more information, see issue #123735 +help: insert whitespace here to avoid this being parsed as a guarded string in Rust 2024 + | +LL | demo4!("foo"# ##); + | + + +warning: will be parsed as a guarded string in Rust 2024 + --> $DIR/reserved-guarded-strings-migration.rs:59:18 + | +LL | demo4!("foo"###); + | ^^ + | + = warning: this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024! + = note: for more information, see issue #123735 +help: insert whitespace here to avoid this being parsed as a guarded string in Rust 2024 + | +LL | demo4!("foo"## #); + | + + +warning: will be parsed as a guarded string in Rust 2024 + --> $DIR/reserved-guarded-strings-migration.rs:65:12 + | +LL | demo2!(#""); + | ^^^ + | + = warning: this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024! + = note: for more information, see issue #123735 +help: insert whitespace here to avoid this being parsed as a guarded string in Rust 2024 + | +LL | demo2!(# ""); + | + + +warning: will be parsed as a guarded string in Rust 2024 + --> $DIR/reserved-guarded-strings-migration.rs:68:12 + | +LL | demo3!(#""#); + | ^^^^ + | + = warning: this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024! + = note: for more information, see issue #123735 +help: insert whitespace here to avoid this being parsed as a guarded string in Rust 2024 + | +LL | demo3!(# ""#); + | + + +warning: will be parsed as a guarded string in Rust 2024 + --> $DIR/reserved-guarded-strings-migration.rs:71:12 + | +LL | demo3!(##""); + | ^^^^ + | + = warning: this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024! + = note: for more information, see issue #123735 +help: insert whitespace here to avoid this being parsed as a guarded string in Rust 2024 + | +LL | demo3!(# #""); + | + + +warning: will be parsed as a guarded string in Rust 2024 + --> $DIR/reserved-guarded-strings-migration.rs:71:13 + | +LL | demo3!(##""); + | ^^^ + | + = warning: this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024! + = note: for more information, see issue #123735 +help: insert whitespace here to avoid this being parsed as a guarded string in Rust 2024 + | +LL | demo3!(## ""); + | + + +warning: will be parsed as a guarded string in Rust 2024 + --> $DIR/reserved-guarded-strings-migration.rs:76:12 + | +LL | demo2!(#"foo"); + | ^^^^^^ + | + = warning: this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024! + = note: for more information, see issue #123735 +help: insert whitespace here to avoid this being parsed as a guarded string in Rust 2024 + | +LL | demo2!(# "foo"); + | + + +warning: will be parsed as a guarded string in Rust 2024 + --> $DIR/reserved-guarded-strings-migration.rs:79:12 + | +LL | demo3!(##"foo"); + | ^^^^^^^ + | + = warning: this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024! + = note: for more information, see issue #123735 +help: insert whitespace here to avoid this being parsed as a guarded string in Rust 2024 + | +LL | demo3!(# #"foo"); + | + + +warning: will be parsed as a guarded string in Rust 2024 + --> $DIR/reserved-guarded-strings-migration.rs:79:13 + | +LL | demo3!(##"foo"); + | ^^^^^^ + | + = warning: this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024! + = note: for more information, see issue #123735 +help: insert whitespace here to avoid this being parsed as a guarded string in Rust 2024 + | +LL | demo3!(## "foo"); + | + + +warning: will be parsed as a guarded string in Rust 2024 + --> $DIR/reserved-guarded-strings-migration.rs:84:12 + | +LL | demo3!(#"foo"#); + | ^^^^^^^ + | + = warning: this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024! + = note: for more information, see issue #123735 +help: insert whitespace here to avoid this being parsed as a guarded string in Rust 2024 + | +LL | demo3!(# "foo"#); + | + + +warning: will be parsed as a guarded string in Rust 2024 + --> $DIR/reserved-guarded-strings-migration.rs:87:12 + | +LL | demo4!(##"foo"#); + | ^^^^^^^^ + | + = warning: this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024! + = note: for more information, see issue #123735 +help: insert whitespace here to avoid this being parsed as a guarded string in Rust 2024 + | +LL | demo4!(# #"foo"#); + | + + +warning: will be parsed as a guarded string in Rust 2024 + --> $DIR/reserved-guarded-strings-migration.rs:87:13 + | +LL | demo4!(##"foo"#); + | ^^^^^^^ + | + = warning: this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024! + = note: for more information, see issue #123735 +help: insert whitespace here to avoid this being parsed as a guarded string in Rust 2024 + | +LL | demo4!(## "foo"#); + | + + +warning: will be parsed as a guarded string in Rust 2024 + --> $DIR/reserved-guarded-strings-migration.rs:92:12 + | +LL | demo5!(##"foo"##); + | ^^^^^^^^^ + | + = warning: this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024! + = note: for more information, see issue #123735 +help: insert whitespace here to avoid this being parsed as a guarded string in Rust 2024 + | +LL | demo5!(# #"foo"##); + | + + +warning: will be parsed as a guarded string in Rust 2024 + --> $DIR/reserved-guarded-strings-migration.rs:92:13 + | +LL | demo5!(##"foo"##); + | ^^^^^^^ + | + = warning: this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024! + = note: for more information, see issue #123735 +help: insert whitespace here to avoid this being parsed as a guarded string in Rust 2024 + | +LL | demo5!(## "foo"##); + | + + +warning: will be parsed as a guarded string in Rust 2024 + --> $DIR/reserved-guarded-strings-migration.rs:92:19 + | +LL | demo5!(##"foo"##); + | ^^ + | + = warning: this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024! + = note: for more information, see issue #123735 +help: insert whitespace here to avoid this being parsed as a guarded string in Rust 2024 + | +LL | demo5!(##"foo"# #); + | + + +warning: 22 warnings emitted + diff --git a/tests/ui/rust-2024/reserved-guarded-strings-via-macro-2.rs b/tests/ui/rust-2024/reserved-guarded-strings-via-macro-2.rs new file mode 100644 index 0000000000000..3f9f373ba227b --- /dev/null +++ b/tests/ui/rust-2024/reserved-guarded-strings-via-macro-2.rs @@ -0,0 +1,18 @@ +//@ edition:2021 +//@ aux-build:reserved-guarded-strings-macro-2021.rs +//@ aux-build:reserved-guarded-strings-macro-2024.rs + +extern crate reserved_guarded_strings_macro_2021 as m2021; +extern crate reserved_guarded_strings_macro_2024 as m2024; + +fn main() { + // Ok: + m2021::number_of_tokens_in_a_guarded_string_literal!(); + m2021::number_of_tokens_in_a_guarded_unterminated_string_literal!(); + + // Error, even though *this* crate is 2021: + m2024::number_of_tokens_in_a_guarded_string_literal!(); + //~^ ERROR invalid string literal + m2024::number_of_tokens_in_a_guarded_unterminated_string_literal!(); + //~^ ERROR invalid string literal +} diff --git a/tests/ui/rust-2024/reserved-guarded-strings-via-macro-2.stderr b/tests/ui/rust-2024/reserved-guarded-strings-via-macro-2.stderr new file mode 100644 index 0000000000000..1074c8a682bfb --- /dev/null +++ b/tests/ui/rust-2024/reserved-guarded-strings-via-macro-2.stderr @@ -0,0 +1,20 @@ +error: invalid string literal + --> $DIR/reserved-guarded-strings-via-macro-2.rs:14:5 + | +LL | m2024::number_of_tokens_in_a_guarded_string_literal!(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: unprefixed guarded string literals are reserved for future use since Rust 2024 + = note: this error originates in the macro `m2024::number_of_tokens_in_a_guarded_string_literal` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: invalid string literal + --> $DIR/reserved-guarded-strings-via-macro-2.rs:16:5 + | +LL | m2024::number_of_tokens_in_a_guarded_unterminated_string_literal!(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: unprefixed guarded string literals are reserved for future use since Rust 2024 + = note: this error originates in the macro `m2024::number_of_tokens_in_a_guarded_unterminated_string_literal` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 2 previous errors + diff --git a/tests/ui/rust-2024/reserved-guarded-strings-via-macro.rs b/tests/ui/rust-2024/reserved-guarded-strings-via-macro.rs new file mode 100644 index 0000000000000..f9e3c1e3c51b4 --- /dev/null +++ b/tests/ui/rust-2024/reserved-guarded-strings-via-macro.rs @@ -0,0 +1,12 @@ +//@ run-pass +//@ compile-flags: -Zunstable-options +//@ edition:2024 +//@ aux-build:reserved-guarded-strings-macro-2021.rs + +extern crate reserved_guarded_strings_macro_2021 as m2021; + +fn main() { + // Ok, even though *this* crate is 2024: + assert_eq!(m2021::number_of_tokens_in_a_guarded_string_literal!(), 3); + assert_eq!(m2021::number_of_tokens_in_a_guarded_unterminated_string_literal!(), 2); +} diff --git a/tests/ui/rust-2024/reserved-guarded-strings.rs b/tests/ui/rust-2024/reserved-guarded-strings.rs new file mode 100644 index 0000000000000..dab97039be03f --- /dev/null +++ b/tests/ui/rust-2024/reserved-guarded-strings.rs @@ -0,0 +1,74 @@ +//@ compile-flags: -Zunstable-options +//@ edition:2024 +// ignore-tidy-linelength + +macro_rules! demo1 { + ( $a:tt ) => { println!("one tokens") }; +} + +macro_rules! demo2 { + ( $a:tt $b:tt ) => { println!("two tokens") }; +} + +macro_rules! demo3 { + ( $a:tt $b:tt $c:tt ) => { println!("three tokens") }; +} + +macro_rules! demo4 { + ( $a:tt $b:tt $c:tt $d:tt ) => { println!("four tokens") }; +} + +macro_rules! demo5 { + ( $a:tt $b:tt $c:tt $d:tt $e:tt ) => { println!("five tokens") }; +} + +macro_rules! demo6 { + ( $a:tt $b:tt $c:tt $d:tt $e:tt $f:tt ) => { println!("six tokens") }; +} + +macro_rules! demo7 { + ( $a:tt $b:tt $c:tt $d:tt $e:tt $f:tt $g:tt ) => { println!("seven tokens") }; +} + +macro_rules! demon { + ( $($n:tt)* ) => { println!("unknown number of tokens") }; +} + +fn main() { + demo1!(""); + demo2!(# ""); + demo3!(# ""#); + demo2!(# "foo"); + demo3!(# "foo"#); + demo2!("foo"#); + + demo2!(blah"xx"); //~ ERROR prefix `blah` is unknown + demo2!(blah#"xx"#); + //~^ ERROR prefix `blah` is unknown + //~| ERROR invalid string literal + + demo2!(## "foo"); //~ ERROR invalid string literal + demo3!("foo"###); //~ ERROR invalid string literal + demo3!(### "foo"); //~ ERROR invalid string literal + demo3!(## "foo"#); //~ ERROR invalid string literal + demo5!(### "foo"###); + //~^ ERROR invalid string literal + //~| ERROR invalid string literal + + demo1!(#""); //~ ERROR invalid string literal + demo1!(#""#); //~ ERROR invalid string literal + demo1!(####""); //~ ERROR invalid string literal + demo1!(#"foo"); //~ ERROR invalid string literal + demo1!(###"foo"); //~ ERROR invalid string literal + demo1!(#"foo"#); //~ ERROR invalid string literal + demo1!(###"foo"#); //~ ERROR invalid string literal + demo1!(###"foo"##); //~ ERROR invalid string literal + demo1!(###"foo"###); //~ ERROR invalid string literal + demo2!(#"foo"###); + //~^ ERROR invalid string literal + //~| ERROR invalid string literal + + // More than 255 hashes + demon!(####################################################################################################################################################################################################################################################################"foo"); + //~^ ERROR invalid string literal +} diff --git a/tests/ui/rust-2024/reserved-guarded-strings.stderr b/tests/ui/rust-2024/reserved-guarded-strings.stderr new file mode 100644 index 0000000000000..f465ba7944a08 --- /dev/null +++ b/tests/ui/rust-2024/reserved-guarded-strings.stderr @@ -0,0 +1,254 @@ +error: prefix `blah` is unknown + --> $DIR/reserved-guarded-strings.rs:45:12 + | +LL | demo2!(blah"xx"); + | ^^^^ unknown prefix + | + = note: prefixed identifiers and literals are reserved since Rust 2021 +help: consider inserting whitespace here + | +LL | demo2!(blah "xx"); + | + + +error: prefix `blah` is unknown + --> $DIR/reserved-guarded-strings.rs:46:12 + | +LL | demo2!(blah#"xx"#); + | ^^^^ unknown prefix + | + = note: prefixed identifiers and literals are reserved since Rust 2021 +help: consider inserting whitespace here + | +LL | demo2!(blah #"xx"#); + | + + +error: invalid string literal + --> $DIR/reserved-guarded-strings.rs:46:16 + | +LL | demo2!(blah#"xx"#); + | ^^^^^^ + | + = note: unprefixed guarded string literals are reserved for future use since Rust 2024 +help: consider inserting whitespace here + | +LL | demo2!(blah# "xx"#); + | + + +error: invalid string literal + --> $DIR/reserved-guarded-strings.rs:50:12 + | +LL | demo2!(## "foo"); + | ^^ + | + = note: unprefixed guarded string literals are reserved for future use since Rust 2024 +help: consider inserting whitespace here + | +LL | demo2!(# # "foo"); + | + + +error: invalid string literal + --> $DIR/reserved-guarded-strings.rs:51:17 + | +LL | demo3!("foo"###); + | ^^ + | + = note: unprefixed guarded string literals are reserved for future use since Rust 2024 +help: consider inserting whitespace here + | +LL | demo3!("foo"# ##); + | + + +error: invalid string literal + --> $DIR/reserved-guarded-strings.rs:52:12 + | +LL | demo3!(### "foo"); + | ^^ + | + = note: unprefixed guarded string literals are reserved for future use since Rust 2024 +help: consider inserting whitespace here + | +LL | demo3!(# ## "foo"); + | + + +error: invalid string literal + --> $DIR/reserved-guarded-strings.rs:53:12 + | +LL | demo3!(## "foo"#); + | ^^ + | + = note: unprefixed guarded string literals are reserved for future use since Rust 2024 +help: consider inserting whitespace here + | +LL | demo3!(# # "foo"#); + | + + +error: invalid string literal + --> $DIR/reserved-guarded-strings.rs:54:12 + | +LL | demo5!(### "foo"###); + | ^^ + | + = note: unprefixed guarded string literals are reserved for future use since Rust 2024 +help: consider inserting whitespace here + | +LL | demo5!(# ## "foo"###); + | + + +error: invalid string literal + --> $DIR/reserved-guarded-strings.rs:54:21 + | +LL | demo5!(### "foo"###); + | ^^ + | + = note: unprefixed guarded string literals are reserved for future use since Rust 2024 +help: consider inserting whitespace here + | +LL | demo5!(### "foo"# ##); + | + + +error: invalid string literal + --> $DIR/reserved-guarded-strings.rs:58:12 + | +LL | demo1!(#""); + | ^^^ + | + = note: unprefixed guarded string literals are reserved for future use since Rust 2024 +help: consider inserting whitespace here + | +LL | demo1!(# ""); + | + + +error: invalid string literal + --> $DIR/reserved-guarded-strings.rs:59:12 + | +LL | demo1!(#""#); + | ^^^^ + | + = note: unprefixed guarded string literals are reserved for future use since Rust 2024 +help: consider inserting whitespace here + | +LL | demo1!(# ""#); + | + + +error: invalid string literal + --> $DIR/reserved-guarded-strings.rs:60:12 + | +LL | demo1!(####""); + | ^^^^^^ + | + = note: unprefixed guarded string literals are reserved for future use since Rust 2024 +help: consider inserting whitespace here + | +LL | demo1!(# ###""); + | + + +error: invalid string literal + --> $DIR/reserved-guarded-strings.rs:61:12 + | +LL | demo1!(#"foo"); + | ^^^^^^ + | + = note: unprefixed guarded string literals are reserved for future use since Rust 2024 +help: consider inserting whitespace here + | +LL | demo1!(# "foo"); + | + + +error: invalid string literal + --> $DIR/reserved-guarded-strings.rs:62:12 + | +LL | demo1!(###"foo"); + | ^^^^^^^^ + | + = note: unprefixed guarded string literals are reserved for future use since Rust 2024 +help: consider inserting whitespace here + | +LL | demo1!(# ##"foo"); + | + + +error: invalid string literal + --> $DIR/reserved-guarded-strings.rs:63:12 + | +LL | demo1!(#"foo"#); + | ^^^^^^^ + | + = note: unprefixed guarded string literals are reserved for future use since Rust 2024 +help: consider inserting whitespace here + | +LL | demo1!(# "foo"#); + | + + +error: invalid string literal + --> $DIR/reserved-guarded-strings.rs:64:12 + | +LL | demo1!(###"foo"#); + | ^^^^^^^^^ + | + = note: unprefixed guarded string literals are reserved for future use since Rust 2024 +help: consider inserting whitespace here + | +LL | demo1!(# ##"foo"#); + | + + +error: invalid string literal + --> $DIR/reserved-guarded-strings.rs:65:12 + | +LL | demo1!(###"foo"##); + | ^^^^^^^^^^ + | + = note: unprefixed guarded string literals are reserved for future use since Rust 2024 +help: consider inserting whitespace here + | +LL | demo1!(# ##"foo"##); + | + + +error: invalid string literal + --> $DIR/reserved-guarded-strings.rs:66:12 + | +LL | demo1!(###"foo"###); + | ^^^^^^^^^^^ + | + = note: unprefixed guarded string literals are reserved for future use since Rust 2024 +help: consider inserting whitespace here + | +LL | demo1!(# ##"foo"###); + | + + +error: invalid string literal + --> $DIR/reserved-guarded-strings.rs:67:12 + | +LL | demo2!(#"foo"###); + | ^^^^^^^ + | + = note: unprefixed guarded string literals are reserved for future use since Rust 2024 +help: consider inserting whitespace here + | +LL | demo2!(# "foo"###); + | + + +error: invalid string literal + --> $DIR/reserved-guarded-strings.rs:67:19 + | +LL | demo2!(#"foo"###); + | ^^ + | + = note: unprefixed guarded string literals are reserved for future use since Rust 2024 +help: consider inserting whitespace here + | +LL | demo2!(#"foo"## #); + | + + +error: invalid string literal + --> $DIR/reserved-guarded-strings.rs:72:12 + | +LL | ...n!(####################################################################################################################################################################################################################################################################"foo... + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: unprefixed guarded string literals are reserved for future use since Rust 2024 +help: consider inserting whitespace here + | +LL | demon!(# ###################################################################################################################################################################################################################################################################"foo"); + | + + +error: aborting due to 21 previous errors + From 8da92b5ce24a218347b331ddfbe7d08db6aa73f3 Mon Sep 17 00:00:00 2001 From: Jubilee Young Date: Tue, 8 Oct 2024 16:13:54 -0700 Subject: [PATCH 2038/2194] compiler: Factor rustc_target::abi::* out of middle::ty::layout --- compiler/rustc_middle/Cargo.toml | 1 + compiler/rustc_middle/src/ty/layout.rs | 24 +++++++++++++++++------- 2 files changed, 18 insertions(+), 7 deletions(-) diff --git a/compiler/rustc_middle/Cargo.toml b/compiler/rustc_middle/Cargo.toml index b23589afb5874..8cb602d9ea841 100644 --- a/compiler/rustc_middle/Cargo.toml +++ b/compiler/rustc_middle/Cargo.toml @@ -12,6 +12,7 @@ field-offset = "0.3.5" gsgdt = "0.1.2" polonius-engine = "0.13.0" rustc-rayon-core = { version = "0.5.0", optional = true } +rustc_abi = { path = "../rustc_abi" } rustc_apfloat = "0.2.0" rustc_arena = { path = "../rustc_arena" } rustc_ast = { path = "../rustc_ast" } diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index 4ba2a9b1d73bc..6c12b691c26c0 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -2,11 +2,15 @@ use std::num::NonZero; use std::ops::Bound; use std::{cmp, fmt}; +use rustc_abi::Primitive::{self, Float, Int, Pointer}; +use rustc_abi::{ + Abi, AddressSpace, Align, FieldsShape, HasDataLayout, Integer, LayoutCalculator, LayoutS, + PointeeInfo, PointerKind, ReprOptions, Scalar, Size, TagEncoding, TargetDataLayout, Variants, +}; use rustc_error_messages::DiagMessage; use rustc_errors::{ Diag, DiagArgValue, DiagCtxtHandle, Diagnostic, EmissionGuarantee, IntoDiagArg, Level, }; -use rustc_hir as hir; use rustc_hir::LangItem; use rustc_hir::def_id::DefId; use rustc_index::IndexVec; @@ -15,10 +19,11 @@ use rustc_session::config::OptLevel; use rustc_span::symbol::{Symbol, sym}; use rustc_span::{DUMMY_SP, ErrorGuaranteed, Span}; use rustc_target::abi::call::FnAbi; -use rustc_target::abi::*; +use rustc_target::abi::{FieldIdx, TyAbiInterface, VariantIdx, call}; use rustc_target::spec::abi::Abi as SpecAbi; use rustc_target::spec::{HasTargetSpec, HasWasmCAbiOpt, PanicStrategy, Target, WasmCAbi}; use tracing::debug; +use {rustc_abi as abi, rustc_hir as hir}; use crate::error::UnsupportedFnAbi; use crate::middle::codegen_fn_attrs::CodegenFnAttrFlags; @@ -27,9 +32,10 @@ use crate::ty::normalize_erasing_regions::NormalizationError; use crate::ty::{self, CoroutineArgsExt, Ty, TyCtxt, TypeVisitableExt}; #[extension(pub trait IntegerExt)] -impl Integer { +impl abi::Integer { #[inline] fn to_ty<'tcx>(&self, tcx: TyCtxt<'tcx>, signed: bool) -> Ty<'tcx> { + use abi::Integer::{I8, I16, I32, I64, I128}; match (*self, signed) { (I8, false) => tcx.types.u8, (I16, false) => tcx.types.u16, @@ -44,7 +50,8 @@ impl Integer { } } - fn from_int_ty(cx: &C, ity: ty::IntTy) -> Integer { + fn from_int_ty(cx: &C, ity: ty::IntTy) -> abi::Integer { + use abi::Integer::{I8, I16, I32, I64, I128}; match ity { ty::IntTy::I8 => I8, ty::IntTy::I16 => I16, @@ -54,7 +61,8 @@ impl Integer { ty::IntTy::Isize => cx.data_layout().ptr_sized_integer(), } } - fn from_uint_ty(cx: &C, ity: ty::UintTy) -> Integer { + fn from_uint_ty(cx: &C, ity: ty::UintTy) -> abi::Integer { + use abi::Integer::{I8, I16, I32, I64, I128}; match ity { ty::UintTy::U8 => I8, ty::UintTy::U16 => I16, @@ -102,7 +110,7 @@ impl Integer { tcx.data_layout().c_enum_min_size } else { // repr(Rust) enums try to be as small as possible - I8 + Integer::I8 }; // If there are no negative values, we can use the unsigned fit. @@ -115,9 +123,10 @@ impl Integer { } #[extension(pub trait FloatExt)] -impl Float { +impl abi::Float { #[inline] fn to_ty<'tcx>(&self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> { + use abi::Float::*; match *self { F16 => tcx.types.f16, F32 => tcx.types.f32, @@ -127,6 +136,7 @@ impl Float { } fn from_float_ty(fty: ty::FloatTy) -> Self { + use abi::Float::*; match fty { ty::FloatTy::F16 => F16, ty::FloatTy::F32 => F32, From 11c48bee11150987e4cce40ff83d0dc083d5c172 Mon Sep 17 00:00:00 2001 From: Jubilee Young Date: Tue, 8 Oct 2024 16:58:27 -0700 Subject: [PATCH 2039/2194] compiler: Factor rustc_target::abi::* out of ty_utils --- compiler/rustc_ty_utils/Cargo.toml | 1 + compiler/rustc_ty_utils/src/abi.rs | 4 +++- compiler/rustc_ty_utils/src/layout.rs | 20 +++++++++++++------- 3 files changed, 17 insertions(+), 8 deletions(-) diff --git a/compiler/rustc_ty_utils/Cargo.toml b/compiler/rustc_ty_utils/Cargo.toml index 01d5251bfa0cc..40356e0c97855 100644 --- a/compiler/rustc_ty_utils/Cargo.toml +++ b/compiler/rustc_ty_utils/Cargo.toml @@ -6,6 +6,7 @@ edition = "2021" [dependencies] # tidy-alphabetical-start itertools = "0.12" +rustc_abi = { path = "../rustc_abi" } rustc_ast_ir = { path = "../rustc_ast_ir" } rustc_data_structures = { path = "../rustc_data_structures" } rustc_errors = { path = "../rustc_errors" } diff --git a/compiler/rustc_ty_utils/src/abi.rs b/compiler/rustc_ty_utils/src/abi.rs index 3d6c09bf89c7e..deda16b76b587 100644 --- a/compiler/rustc_ty_utils/src/abi.rs +++ b/compiler/rustc_ty_utils/src/abi.rs @@ -1,5 +1,8 @@ use std::iter; +use rustc_abi::Float::*; +use rustc_abi::Primitive::{Float, Pointer}; +use rustc_abi::{Abi, AddressSpace, PointerKind, Scalar, Size}; use rustc_hir as hir; use rustc_hir::lang_items::LangItem; use rustc_middle::bug; @@ -14,7 +17,6 @@ use rustc_target::abi::call::{ ArgAbi, ArgAttribute, ArgAttributes, ArgExtension, Conv, FnAbi, PassMode, Reg, RegKind, RiscvInterruptKind, }; -use rustc_target::abi::*; use rustc_target::spec::abi::Abi as SpecAbi; use tracing::debug; diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs index 34c9f1b63c066..afdfa2e80c1f6 100644 --- a/compiler/rustc_ty_utils/src/layout.rs +++ b/compiler/rustc_ty_utils/src/layout.rs @@ -2,7 +2,12 @@ use std::fmt::Debug; use std::iter; use hir::def_id::DefId; -use rustc_hir as hir; +use rustc_abi::Integer::{I8, I32}; +use rustc_abi::Primitive::{self, Float, Int, Pointer}; +use rustc_abi::{ + Abi, AbiAndPrefAlign, AddressSpace, Align, FieldsShape, HasDataLayout, LayoutCalculatorError, + LayoutS, Niche, ReprOptions, Scalar, Size, StructKind, TagEncoding, Variants, WrappingRange, +}; use rustc_index::bit_set::BitSet; use rustc_index::{IndexSlice, IndexVec}; use rustc_middle::bug; @@ -18,8 +23,9 @@ use rustc_middle::ty::{ use rustc_session::{DataTypeKind, FieldInfo, FieldKind, SizeKind, VariantInfo}; use rustc_span::sym; use rustc_span::symbol::Symbol; -use rustc_target::abi::*; +use rustc_target::abi::{FIRST_VARIANT, FieldIdx, Layout, VariantIdx}; use tracing::{debug, instrument, trace}; +use {rustc_abi as abi, rustc_hir as hir}; use crate::errors::{ MultipleArrayFieldsSimdType, NonPrimitiveSimdType, OversizedSimdType, ZeroLengthSimdType, @@ -202,9 +208,9 @@ fn layout_of_uncached<'tcx>( value: Int(I32, false), valid_range: WrappingRange { start: 0, end: 0x10FFFF }, })), - ty::Int(ity) => scalar(Int(Integer::from_int_ty(dl, ity), true)), - ty::Uint(ity) => scalar(Int(Integer::from_uint_ty(dl, ity), false)), - ty::Float(fty) => scalar(Float(Float::from_float_ty(fty))), + ty::Int(ity) => scalar(Int(abi::Integer::from_int_ty(dl, ity), true)), + ty::Uint(ity) => scalar(Int(abi::Integer::from_uint_ty(dl, ity), false)), + ty::Float(fty) => scalar(Float(abi::Float::from_float_ty(fty))), ty::FnPtr(..) => { let mut ptr = scalar_unit(Pointer(dl.instruction_address_space)); ptr.valid_range_mut().start = 1; @@ -563,7 +569,7 @@ fn layout_of_uncached<'tcx>( } let get_discriminant_type = - |min, max| Integer::repr_discr(tcx, ty, &def.repr(), min, max); + |min, max| abi::Integer::repr_discr(tcx, ty, &def.repr(), min, max); let discriminants_iter = || { def.is_enum() @@ -816,7 +822,7 @@ fn coroutine_layout<'tcx>( // `info.variant_fields` already accounts for the reserved variants, so no need to add them. let max_discr = (info.variant_fields.len() - 1) as u128; - let discr_int = Integer::fit_unsigned(max_discr); + let discr_int = abi::Integer::fit_unsigned(max_discr); let tag = Scalar::Initialized { value: Primitive::Int(discr_int, /* signed = */ false), valid_range: WrappingRange { start: 0, end: max_discr }, From 9d95c8bd1606b914a0fc1ae9ba21efb3490491ce Mon Sep 17 00:00:00 2001 From: Jubilee Young Date: Tue, 8 Oct 2024 16:59:24 -0700 Subject: [PATCH 2040/2194] compiler: Factor rustc_target::abi out of const_eval --- compiler/rustc_const_eval/Cargo.toml | 1 + .../rustc_const_eval/src/interpret/operand.rs | 15 ++++++++------- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/compiler/rustc_const_eval/Cargo.toml b/compiler/rustc_const_eval/Cargo.toml index c4f8841d71c63..41136019a88df 100644 --- a/compiler/rustc_const_eval/Cargo.toml +++ b/compiler/rustc_const_eval/Cargo.toml @@ -6,6 +6,7 @@ edition = "2021" [dependencies] # tidy-alphabetical-start either = "1" +rustc_abi = { path = "../rustc_abi" } rustc_apfloat = "0.2.0" rustc_ast = { path = "../rustc_ast" } rustc_attr = { path = "../rustc_attr" } diff --git a/compiler/rustc_const_eval/src/interpret/operand.rs b/compiler/rustc_const_eval/src/interpret/operand.rs index 3b5af113e9963..cd5e2aeca855e 100644 --- a/compiler/rustc_const_eval/src/interpret/operand.rs +++ b/compiler/rustc_const_eval/src/interpret/operand.rs @@ -4,13 +4,14 @@ use std::assert_matches::assert_matches; use either::{Either, Left, Right}; +use rustc_abi as abi; +use rustc_abi::{Abi, HasDataLayout, Size}; use rustc_hir::def::Namespace; use rustc_middle::mir::interpret::ScalarSizeMismatch; use rustc_middle::ty::layout::{HasParamEnv, HasTyCtxt, LayoutOf, TyAndLayout}; use rustc_middle::ty::print::{FmtPrinter, PrettyPrinter}; use rustc_middle::ty::{ConstInt, ScalarInt, Ty, TyCtxt}; use rustc_middle::{bug, mir, span_bug, ty}; -use rustc_target::abi::{self, Abi, HasDataLayout, Size}; use tracing::trace; use super::{ @@ -117,7 +118,7 @@ impl Immediate { match (self, abi) { (Immediate::Scalar(scalar), Abi::Scalar(s)) => { assert_eq!(scalar.size(), s.size(cx), "{msg}: scalar value has wrong size"); - if !matches!(s.primitive(), abi::Pointer(..)) { + if !matches!(s.primitive(), abi::Primitive::Pointer(..)) { // This is not a pointer, it should not carry provenance. assert!( matches!(scalar, Scalar::Int(..)), @@ -131,7 +132,7 @@ impl Immediate { a.size(cx), "{msg}: first component of scalar pair has wrong size" ); - if !matches!(a.primitive(), abi::Pointer(..)) { + if !matches!(a.primitive(), abi::Primitive::Pointer(..)) { assert!( matches!(a_val, Scalar::Int(..)), "{msg}: first component of scalar pair should be an integer, but has provenance" @@ -142,7 +143,7 @@ impl Immediate { b.size(cx), "{msg}: second component of scalar pair has wrong size" ); - if !matches!(b.primitive(), abi::Pointer(..)) { + if !matches!(b.primitive(), abi::Primitive::Pointer(..)) { assert!( matches!(b_val, Scalar::Int(..)), "{msg}: second component of scalar pair should be an integer, but has provenance" @@ -572,7 +573,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { assert_eq!(size, mplace.layout.size, "abi::Scalar size does not match layout size"); let scalar = alloc.read_scalar( alloc_range(Size::ZERO, size), - /*read_provenance*/ matches!(s, abi::Pointer(_)), + /*read_provenance*/ matches!(s, abi::Primitive::Pointer(_)), )?; Some(ImmTy::from_scalar(scalar, mplace.layout)) } @@ -588,11 +589,11 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { assert!(b_offset.bytes() > 0); // in `operand_field` we use the offset to tell apart the fields let a_val = alloc.read_scalar( alloc_range(Size::ZERO, a_size), - /*read_provenance*/ matches!(a, abi::Pointer(_)), + /*read_provenance*/ matches!(a, abi::Primitive::Pointer(_)), )?; let b_val = alloc.read_scalar( alloc_range(b_offset, b_size), - /*read_provenance*/ matches!(b, abi::Pointer(_)), + /*read_provenance*/ matches!(b, abi::Primitive::Pointer(_)), )?; Some(ImmTy::from_immediate(Immediate::ScalarPair(a_val, b_val), mplace.layout)) } From ff17ce2f6a9110ff45ca2b9e14de255a47cbbaa8 Mon Sep 17 00:00:00 2001 From: Jubilee Young Date: Tue, 8 Oct 2024 17:25:22 -0700 Subject: [PATCH 2041/2194] compiler: Factor rustc_target::abi out of hir_typeck --- compiler/rustc_hir_typeck/Cargo.toml | 1 + compiler/rustc_hir_typeck/src/intrinsicck.rs | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_hir_typeck/Cargo.toml b/compiler/rustc_hir_typeck/Cargo.toml index 73a775690d66b..894402a8c2e88 100644 --- a/compiler/rustc_hir_typeck/Cargo.toml +++ b/compiler/rustc_hir_typeck/Cargo.toml @@ -6,6 +6,7 @@ edition = "2021" [dependencies] # tidy-alphabetical-start itertools = "0.12" +rustc_abi = { path = "../rustc_abi" } rustc_ast = { path = "../rustc_ast" } rustc_ast_ir = { path = "../rustc_ast_ir" } rustc_attr = { path = "../rustc_attr" } diff --git a/compiler/rustc_hir_typeck/src/intrinsicck.rs b/compiler/rustc_hir_typeck/src/intrinsicck.rs index a4121adf628af..8a7005ac32893 100644 --- a/compiler/rustc_hir_typeck/src/intrinsicck.rs +++ b/compiler/rustc_hir_typeck/src/intrinsicck.rs @@ -1,4 +1,5 @@ use hir::HirId; +use rustc_abi::Primitive::Pointer; use rustc_errors::codes::*; use rustc_errors::struct_span_code_err; use rustc_hir as hir; @@ -6,7 +7,7 @@ use rustc_index::Idx; use rustc_middle::bug; use rustc_middle::ty::layout::{LayoutError, SizeSkeleton}; use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt}; -use rustc_target::abi::{Pointer, VariantIdx}; +use rustc_target::abi::VariantIdx; use tracing::trace; use super::FnCtxt; From 839cf1c1a4f60575f9000b9f6d5676ec1efbe3e8 Mon Sep 17 00:00:00 2001 From: Jubilee Young Date: Tue, 8 Oct 2024 17:27:32 -0700 Subject: [PATCH 2042/2194] compiler: Factor rustc_target::abi out of cg_ssa --- compiler/rustc_codegen_ssa/Cargo.toml | 1 + compiler/rustc_codegen_ssa/src/mir/operand.rs | 5 +++-- compiler/rustc_codegen_ssa/src/mir/place.rs | 6 +++--- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_codegen_ssa/Cargo.toml b/compiler/rustc_codegen_ssa/Cargo.toml index 58baf40b5812b..dffb7a7271e09 100644 --- a/compiler/rustc_codegen_ssa/Cargo.toml +++ b/compiler/rustc_codegen_ssa/Cargo.toml @@ -14,6 +14,7 @@ itertools = "0.12" jobserver = "0.1.28" pathdiff = "0.2.0" regex = "1.4" +rustc_abi = { path = "../rustc_abi" } rustc_arena = { path = "../rustc_arena" } rustc_ast = { path = "../rustc_ast" } rustc_attr = { path = "../rustc_attr" } diff --git a/compiler/rustc_codegen_ssa/src/mir/operand.rs b/compiler/rustc_codegen_ssa/src/mir/operand.rs index 0bcd7d6d08150..88ceff327d0aa 100644 --- a/compiler/rustc_codegen_ssa/src/mir/operand.rs +++ b/compiler/rustc_codegen_ssa/src/mir/operand.rs @@ -3,12 +3,13 @@ use std::fmt; use arrayvec::ArrayVec; use either::Either; +use rustc_abi as abi; +use rustc_abi::{Abi, Align, Size}; use rustc_middle::bug; use rustc_middle::mir::interpret::{Pointer, Scalar, alloc_range}; use rustc_middle::mir::{self, ConstValue}; use rustc_middle::ty::Ty; use rustc_middle::ty::layout::{LayoutOf, TyAndLayout}; -use rustc_target::abi::{self, Abi, Align, Size}; use tracing::debug; use super::place::{PlaceRef, PlaceValue}; @@ -207,7 +208,7 @@ impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, V> { match alloc.0.read_scalar( bx, alloc_range(start, size), - /*read_provenance*/ matches!(s.primitive(), abi::Pointer(_)), + /*read_provenance*/ matches!(s.primitive(), abi::Primitive::Pointer(_)), ) { Ok(val) => bx.scalar_to_backend(val, s, ty), Err(_) => bx.const_poison(ty), diff --git a/compiler/rustc_codegen_ssa/src/mir/place.rs b/compiler/rustc_codegen_ssa/src/mir/place.rs index 0b764ae7747d8..a7d5541481a6c 100644 --- a/compiler/rustc_codegen_ssa/src/mir/place.rs +++ b/compiler/rustc_codegen_ssa/src/mir/place.rs @@ -1,10 +1,10 @@ +use rustc_abi::Primitive::{Int, Pointer}; +use rustc_abi::{Align, FieldsShape, Size, TagEncoding, Variants}; use rustc_middle::mir::tcx::PlaceTy; use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf, TyAndLayout}; use rustc_middle::ty::{self, Ty}; use rustc_middle::{bug, mir}; -use rustc_target::abi::{ - Align, FieldsShape, Int, Pointer, Size, TagEncoding, VariantIdx, Variants, -}; +use rustc_target::abi::VariantIdx; use tracing::{debug, instrument}; use super::operand::OperandValue; From 1379ef592aa201095f0e827a4f28d27cbc3fdb05 Mon Sep 17 00:00:00 2001 From: Jubilee Young Date: Tue, 8 Oct 2024 17:29:00 -0700 Subject: [PATCH 2043/2194] compiler: Factor rustc_target::abi out of cg_llvm --- compiler/rustc_codegen_llvm/Cargo.toml | 1 + compiler/rustc_codegen_llvm/src/abi.rs | 4 +++- compiler/rustc_codegen_llvm/src/builder.rs | 9 +++++---- compiler/rustc_codegen_llvm/src/common.rs | 4 +++- compiler/rustc_codegen_llvm/src/type_of.rs | 3 ++- 5 files changed, 14 insertions(+), 7 deletions(-) diff --git a/compiler/rustc_codegen_llvm/Cargo.toml b/compiler/rustc_codegen_llvm/Cargo.toml index a93baf88413a1..03a871297c481 100644 --- a/compiler/rustc_codegen_llvm/Cargo.toml +++ b/compiler/rustc_codegen_llvm/Cargo.toml @@ -14,6 +14,7 @@ libc = "0.2" measureme = "11" object = { version = "0.36.3", default-features = false, features = ["std", "read"] } rustc-demangle = "0.1.21" +rustc_abi = { path = "../rustc_abi" } rustc_ast = { path = "../rustc_ast" } rustc_attr = { path = "../rustc_attr" } rustc_codegen_ssa = { path = "../rustc_codegen_ssa" } diff --git a/compiler/rustc_codegen_llvm/src/abi.rs b/compiler/rustc_codegen_llvm/src/abi.rs index 6a29eb5fa04ab..2fe5ed32daa31 100644 --- a/compiler/rustc_codegen_llvm/src/abi.rs +++ b/compiler/rustc_codegen_llvm/src/abi.rs @@ -1,6 +1,9 @@ use std::cmp; use libc::c_uint; +use rustc_abi as abi; +use rustc_abi::Primitive::Int; +use rustc_abi::{HasDataLayout, Size}; use rustc_codegen_ssa::MemFlags; use rustc_codegen_ssa::mir::operand::{OperandRef, OperandValue}; use rustc_codegen_ssa::mir::place::{PlaceRef, PlaceValue}; @@ -11,7 +14,6 @@ pub(crate) use rustc_middle::ty::layout::{WIDE_PTR_ADDR, WIDE_PTR_EXTRA}; use rustc_middle::{bug, ty}; use rustc_session::config; pub(crate) use rustc_target::abi::call::*; -use rustc_target::abi::{self, HasDataLayout, Int, Size}; use rustc_target::spec::SanitizerSet; pub(crate) use rustc_target::spec::abi::Abi; use smallvec::SmallVec; diff --git a/compiler/rustc_codegen_llvm/src/builder.rs b/compiler/rustc_codegen_llvm/src/builder.rs index 30d7ba4421bff..dbf5298d64ba3 100644 --- a/compiler/rustc_codegen_llvm/src/builder.rs +++ b/compiler/rustc_codegen_llvm/src/builder.rs @@ -3,6 +3,8 @@ use std::ops::Deref; use std::{iter, ptr}; use libc::{c_char, c_uint}; +use rustc_abi as abi; +use rustc_abi::{Align, Size, WrappingRange}; use rustc_codegen_ssa::MemFlags; use rustc_codegen_ssa::common::{IntPredicate, RealPredicate, SynchronizationScope, TypeKind}; use rustc_codegen_ssa::mir::operand::{OperandRef, OperandValue}; @@ -20,7 +22,6 @@ use rustc_sanitizers::{cfi, kcfi}; use rustc_session::config::OptLevel; use rustc_span::Span; use rustc_target::abi::call::FnAbi; -use rustc_target::abi::{self, Align, Size, WrappingRange}; use rustc_target::spec::{HasTargetSpec, SanitizerSet, Target}; use smallvec::SmallVec; use tracing::{debug, instrument}; @@ -505,12 +506,12 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { } match scalar.primitive() { - abi::Int(..) => { + abi::Primitive::Int(..) => { if !scalar.is_always_valid(bx) { bx.range_metadata(load, scalar.valid_range(bx)); } } - abi::Pointer(_) => { + abi::Primitive::Pointer(_) => { if !scalar.valid_range(bx).contains(0) { bx.nonnull_metadata(load); } @@ -521,7 +522,7 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { } } } - abi::Float(_) => {} + abi::Primitive::Float(_) => {} } } diff --git a/compiler/rustc_codegen_llvm/src/common.rs b/compiler/rustc_codegen_llvm/src/common.rs index 31d59905446f3..4ca19ab2f12b8 100644 --- a/compiler/rustc_codegen_llvm/src/common.rs +++ b/compiler/rustc_codegen_llvm/src/common.rs @@ -1,6 +1,9 @@ //! Code that is useful in various codegen modules. use libc::{c_char, c_uint}; +use rustc_abi as abi; +use rustc_abi::Primitive::Pointer; +use rustc_abi::{AddressSpace, HasDataLayout}; use rustc_ast::Mutability; use rustc_codegen_ssa::traits::*; use rustc_data_structures::stable_hasher::{Hash128, HashStable, StableHasher}; @@ -9,7 +12,6 @@ use rustc_middle::bug; use rustc_middle::mir::interpret::{ConstAllocation, GlobalAlloc, Scalar}; use rustc_middle::ty::TyCtxt; use rustc_session::cstore::DllImport; -use rustc_target::abi::{self, AddressSpace, HasDataLayout, Pointer}; use tracing::debug; use crate::consts::const_alloc_to_llvm; diff --git a/compiler/rustc_codegen_llvm/src/type_of.rs b/compiler/rustc_codegen_llvm/src/type_of.rs index 7071dd86ee0d2..1af666f818bba 100644 --- a/compiler/rustc_codegen_llvm/src/type_of.rs +++ b/compiler/rustc_codegen_llvm/src/type_of.rs @@ -1,11 +1,12 @@ use std::fmt::Write; +use rustc_abi::Primitive::{Float, Int, Pointer}; +use rustc_abi::{Abi, Align, FieldsShape, Scalar, Size, Variants}; use rustc_codegen_ssa::traits::*; use rustc_middle::bug; use rustc_middle::ty::layout::{LayoutOf, TyAndLayout}; use rustc_middle::ty::print::{with_no_trimmed_paths, with_no_visible_paths}; use rustc_middle::ty::{self, CoroutineArgsExt, Ty, TypeVisitableExt}; -use rustc_target::abi::{Abi, Align, FieldsShape, Float, Int, Pointer, Scalar, Size, Variants}; use tracing::debug; use crate::common::*; From b3beb4efc7cd2240a3ef96dd1e35cbd148ef97ef Mon Sep 17 00:00:00 2001 From: Jubilee Young Date: Tue, 8 Oct 2024 17:26:42 -0700 Subject: [PATCH 2044/2194] cg_clif: Factor out rustc_target::abi --- compiler/rustc_codegen_cranelift/src/discriminant.rs | 3 ++- compiler/rustc_codegen_cranelift/src/lib.rs | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_codegen_cranelift/src/discriminant.rs b/compiler/rustc_codegen_cranelift/src/discriminant.rs index e7ac084558a5a..d462dcd63a925 100644 --- a/compiler/rustc_codegen_cranelift/src/discriminant.rs +++ b/compiler/rustc_codegen_cranelift/src/discriminant.rs @@ -3,7 +3,8 @@ //! Adapted from //! () -use rustc_target::abi::{Int, TagEncoding, Variants}; +use rustc_abi::Primitive::Int; +use rustc_abi::{TagEncoding, Variants}; use crate::prelude::*; diff --git a/compiler/rustc_codegen_cranelift/src/lib.rs b/compiler/rustc_codegen_cranelift/src/lib.rs index f6b7981395a5f..b6f9ce8fc2988 100644 --- a/compiler/rustc_codegen_cranelift/src/lib.rs +++ b/compiler/rustc_codegen_cranelift/src/lib.rs @@ -15,6 +15,7 @@ extern crate jobserver; #[macro_use] extern crate rustc_middle; +extern crate rustc_abi; extern crate rustc_ast; extern crate rustc_codegen_ssa; extern crate rustc_data_structures; From d92aee556d92214f972ed91499e61474ad38aa9d Mon Sep 17 00:00:00 2001 From: Jubilee Young Date: Tue, 8 Oct 2024 17:27:02 -0700 Subject: [PATCH 2045/2194] cg_gcc: Factor out rustc_target::abi --- compiler/rustc_codegen_gcc/src/builder.rs | 7 ++++--- compiler/rustc_codegen_gcc/src/common.rs | 4 +++- compiler/rustc_codegen_gcc/src/lib.rs | 1 + compiler/rustc_codegen_gcc/src/type_of.rs | 8 ++++---- 4 files changed, 12 insertions(+), 8 deletions(-) diff --git a/compiler/rustc_codegen_gcc/src/builder.rs b/compiler/rustc_codegen_gcc/src/builder.rs index acd5358883166..b611f9ba8bcb3 100644 --- a/compiler/rustc_codegen_gcc/src/builder.rs +++ b/compiler/rustc_codegen_gcc/src/builder.rs @@ -7,6 +7,8 @@ use gccjit::{ BinaryOp, Block, ComparisonOp, Context, Function, LValue, Location, RValue, ToRValue, Type, UnaryOp, }; +use rustc_abi as abi; +use rustc_abi::{Align, HasDataLayout, Size, TargetDataLayout, WrappingRange}; use rustc_apfloat::{Float, Round, Status, ieee}; use rustc_codegen_ssa::MemFlags; use rustc_codegen_ssa::common::{ @@ -28,7 +30,6 @@ use rustc_middle::ty::{Instance, ParamEnv, Ty, TyCtxt}; use rustc_span::Span; use rustc_span::def_id::DefId; use rustc_target::abi::call::FnAbi; -use rustc_target::abi::{self, Align, HasDataLayout, Size, TargetDataLayout, WrappingRange}; use rustc_target::spec::{HasTargetSpec, HasWasmCAbiOpt, Target, WasmCAbi}; use crate::common::{SignType, TypeReflection, type_is_pointer}; @@ -998,12 +999,12 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { ) { let vr = scalar.valid_range(bx); match scalar.primitive() { - abi::Int(..) => { + abi::Primitive::Int(..) => { if !scalar.is_always_valid(bx) { bx.range_metadata(load, vr); } } - abi::Pointer(_) if vr.start < vr.end && !vr.contains(0) => { + abi::Primitive::Pointer(_) if vr.start < vr.end && !vr.contains(0) => { bx.nonnull_metadata(load); } _ => {} diff --git a/compiler/rustc_codegen_gcc/src/common.rs b/compiler/rustc_codegen_gcc/src/common.rs index 726b126e727dd..0d3e7083d56ad 100644 --- a/compiler/rustc_codegen_gcc/src/common.rs +++ b/compiler/rustc_codegen_gcc/src/common.rs @@ -1,11 +1,13 @@ use gccjit::{LValue, RValue, ToRValue, Type}; +use rustc_abi as abi; +use rustc_abi::HasDataLayout; +use rustc_abi::Primitive::Pointer; use rustc_codegen_ssa::traits::{ BaseTypeCodegenMethods, ConstCodegenMethods, MiscCodegenMethods, StaticCodegenMethods, }; use rustc_middle::mir::Mutability; use rustc_middle::mir::interpret::{ConstAllocation, GlobalAlloc, Scalar}; use rustc_middle::ty::layout::LayoutOf; -use rustc_target::abi::{self, HasDataLayout, Pointer}; use crate::consts::const_alloc_to_gcc; use crate::context::CodegenCx; diff --git a/compiler/rustc_codegen_gcc/src/lib.rs b/compiler/rustc_codegen_gcc/src/lib.rs index a7a32e285d8fa..7486eefeb85a7 100644 --- a/compiler/rustc_codegen_gcc/src/lib.rs +++ b/compiler/rustc_codegen_gcc/src/lib.rs @@ -32,6 +32,7 @@ extern crate tempfile; extern crate tracing; // The rustc crates we need +extern crate rustc_abi; extern crate rustc_apfloat; extern crate rustc_ast; extern crate rustc_attr; diff --git a/compiler/rustc_codegen_gcc/src/type_of.rs b/compiler/rustc_codegen_gcc/src/type_of.rs index 5b0d862ae6d4e..183e9ddf8bf98 100644 --- a/compiler/rustc_codegen_gcc/src/type_of.rs +++ b/compiler/rustc_codegen_gcc/src/type_of.rs @@ -1,6 +1,9 @@ use std::fmt::Write; use gccjit::{Struct, Type}; +use rustc_abi as abi; +use rustc_abi::Primitive::*; +use rustc_abi::{Abi, FieldsShape, Integer, PointeeInfo, Size, Variants}; use rustc_codegen_ssa::traits::{ BaseTypeCodegenMethods, DerivedTypeCodegenMethods, LayoutTypeCodegenMethods, }; @@ -8,11 +11,8 @@ use rustc_middle::bug; use rustc_middle::ty::layout::{LayoutOf, TyAndLayout}; use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_middle::ty::{self, CoroutineArgsExt, Ty, TypeVisitableExt}; +use rustc_target::abi::TyAbiInterface; use rustc_target::abi::call::{CastTarget, FnAbi, Reg}; -use rustc_target::abi::{ - self, Abi, FieldsShape, Float, Int, Integer, PointeeInfo, Pointer, Size, TyAbiInterface, - Variants, -}; use crate::abi::{FnAbiGcc, FnAbiGccExt, GccType}; use crate::context::CodegenCx; From 43e198a3ae23f469e1c87b099789af1bc025fe50 Mon Sep 17 00:00:00 2001 From: Jubilee Young Date: Tue, 8 Oct 2024 17:32:52 -0700 Subject: [PATCH 2046/2194] compiler: Seal off the rustc_target::abi enum glob imports --- Cargo.lock | 6 ++++++ compiler/rustc_target/src/abi/mod.rs | 5 ++--- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 502920350d5c5..faca061967379 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3416,6 +3416,7 @@ dependencies = [ "measureme", "object 0.36.4", "rustc-demangle", + "rustc_abi", "rustc_ast", "rustc_attr", "rustc_codegen_ssa", @@ -3456,6 +3457,7 @@ dependencies = [ "object 0.36.4", "pathdiff", "regex", + "rustc_abi", "rustc_arena", "rustc_ast", "rustc_attr", @@ -3493,6 +3495,7 @@ name = "rustc_const_eval" version = "0.0.0" dependencies = [ "either", + "rustc_abi", "rustc_apfloat", "rustc_ast", "rustc_attr", @@ -3772,6 +3775,7 @@ name = "rustc_hir_typeck" version = "0.0.0" dependencies = [ "itertools", + "rustc_abi", "rustc_ast", "rustc_ast_ir", "rustc_attr", @@ -4027,6 +4031,7 @@ dependencies = [ "gsgdt", "polonius-engine", "rustc-rayon-core", + "rustc_abi", "rustc_apfloat", "rustc_arena", "rustc_ast", @@ -4522,6 +4527,7 @@ name = "rustc_ty_utils" version = "0.0.0" dependencies = [ "itertools", + "rustc_abi", "rustc_ast_ir", "rustc_data_structures", "rustc_errors", diff --git a/compiler/rustc_target/src/abi/mod.rs b/compiler/rustc_target/src/abi/mod.rs index fc92e755feaea..b744d5ad4edae 100644 --- a/compiler/rustc_target/src/abi/mod.rs +++ b/compiler/rustc_target/src/abi/mod.rs @@ -1,9 +1,8 @@ use std::fmt; use std::ops::Deref; -pub use Float::*; -pub use Integer::*; -pub use Primitive::*; +use Float::*; +use Primitive::*; use rustc_data_structures::intern::Interned; use rustc_macros::HashStable_Generic; From af5a7045486404145544e3ec2ec2ec450b31e6f6 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Tue, 8 Oct 2024 18:31:44 -0700 Subject: [PATCH 2047/2194] Fix quotation marks around debug line in `src/ci/run.sh` Without this change, the markdown-style backticks are treated as a shell command substitution, which fails like so: /checkout/src/ci/run.sh: line 58: DISABLE_CI_RUSTC_IF_INCOMPATIBLE: command not found debug: configured. --- src/ci/run.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ci/run.sh b/src/ci/run.sh index 1ce54f9ecb342..3962c354c10e5 100755 --- a/src/ci/run.sh +++ b/src/ci/run.sh @@ -55,7 +55,7 @@ fi # If runner uses an incompatible option and `FORCE_CI_RUSTC` is not defined, # switch to in-tree rustc. if [ "$FORCE_CI_RUSTC" == "" ]; then - echo "debug: `DISABLE_CI_RUSTC_IF_INCOMPATIBLE` configured." + echo 'debug: `DISABLE_CI_RUSTC_IF_INCOMPATIBLE` configured.' DISABLE_CI_RUSTC_IF_INCOMPATIBLE=1 fi From f2d1edfea5689ac638904080ddb972c40e7acc8c Mon Sep 17 00:00:00 2001 From: Yuri Astrakhan Date: Sat, 28 Sep 2024 01:46:03 -0400 Subject: [PATCH 2048/2194] Change a few `&Option` into `Option<&T>` --- library/std/src/sys/pal/sgx/net.rs | 14 +++++++------- .../std/src/sys/pal/unix/process/process_common.rs | 4 ++-- .../std/src/sys/pal/unix/process/process_unix.rs | 2 +- library/test/src/lib.rs | 11 ++++++----- library/test/src/test_result.rs | 8 ++++---- 5 files changed, 20 insertions(+), 19 deletions(-) diff --git a/library/std/src/sys/pal/sgx/net.rs b/library/std/src/sys/pal/sgx/net.rs index 44913ffe3a9ff..c966886d16344 100644 --- a/library/std/src/sys/pal/sgx/net.rs +++ b/library/std/src/sys/pal/sgx/net.rs @@ -78,9 +78,8 @@ fn io_err_to_addr(result: io::Result<&SocketAddr>) -> io::Result { } } -fn addr_to_sockaddr(addr: &Option) -> io::Result { - addr.as_ref() - .ok_or(io::ErrorKind::AddrNotAvailable)? +fn addr_to_sockaddr(addr: Option<&str>) -> io::Result { + addr.ok_or(io::ErrorKind::AddrNotAvailable)? .to_socket_addrs() // unwrap OK: if an iterator is returned, we're guaranteed to get exactly one entry .map(|mut it| it.next().unwrap()) @@ -161,11 +160,11 @@ impl TcpStream { } pub fn peer_addr(&self) -> io::Result { - addr_to_sockaddr(&self.peer_addr) + addr_to_sockaddr(self.peer_addr.as_deref()) } pub fn socket_addr(&self) -> io::Result { - addr_to_sockaddr(&self.inner.local_addr) + addr_to_sockaddr(self.inner.local_addr.as_deref()) } pub fn shutdown(&self, _: Shutdown) -> io::Result<()> { @@ -255,13 +254,14 @@ impl TcpListener { } pub fn socket_addr(&self) -> io::Result { - addr_to_sockaddr(&self.inner.local_addr) + addr_to_sockaddr(self.inner.local_addr.as_deref()) } pub fn accept(&self) -> io::Result<(TcpStream, SocketAddr)> { let (fd, local_addr, peer_addr) = usercalls::accept_stream(self.inner.inner.raw())?; let peer_addr = Some(peer_addr); - let ret_peer = addr_to_sockaddr(&peer_addr).unwrap_or_else(|_| ([0; 4], 0).into()); + let ret_peer = + addr_to_sockaddr(peer_addr.as_deref()).unwrap_or_else(|_| ([0; 4], 0).into()); Ok((TcpStream { inner: Socket::new(fd, local_addr), peer_addr }, ret_peer)) } diff --git a/library/std/src/sys/pal/unix/process/process_common.rs b/library/std/src/sys/pal/unix/process/process_common.rs index d9c41d4348756..13290fed762ae 100644 --- a/library/std/src/sys/pal/unix/process/process_common.rs +++ b/library/std/src/sys/pal/unix/process/process_common.rs @@ -312,8 +312,8 @@ impl Command { } #[allow(dead_code)] - pub fn get_cwd(&self) -> &Option { - &self.cwd + pub fn get_cwd(&self) -> Option<&CStr> { + self.cwd.as_deref() } #[allow(dead_code)] pub fn get_uid(&self) -> Option { diff --git a/library/std/src/sys/pal/unix/process/process_unix.rs b/library/std/src/sys/pal/unix/process/process_unix.rs index 5d30f388da18e..0fa6551772f43 100644 --- a/library/std/src/sys/pal/unix/process/process_unix.rs +++ b/library/std/src/sys/pal/unix/process/process_unix.rs @@ -335,7 +335,7 @@ impl Command { cvt(libc::setuid(u as uid_t))?; } } - if let Some(ref cwd) = *self.get_cwd() { + if let Some(ref cwd) = self.get_cwd() { cvt(libc::chdir(cwd.as_ptr()))?; } diff --git a/library/test/src/lib.rs b/library/test/src/lib.rs index 4b2c65cfdf548..30ccfe2af8dbd 100644 --- a/library/test/src/lib.rs +++ b/library/test/src/lib.rs @@ -650,8 +650,8 @@ fn run_test_in_process( io::set_output_capture(None); let test_result = match result { - Ok(()) => calc_result(&desc, Ok(()), &time_opts, &exec_time), - Err(e) => calc_result(&desc, Err(e.as_ref()), &time_opts, &exec_time), + Ok(()) => calc_result(&desc, Ok(()), time_opts.as_ref(), exec_time.as_ref()), + Err(e) => calc_result(&desc, Err(e.as_ref()), time_opts.as_ref(), exec_time.as_ref()), }; let stdout = data.lock().unwrap_or_else(|e| e.into_inner()).to_vec(); let message = CompletedTest::new(id, desc, test_result, exec_time, stdout); @@ -712,7 +712,8 @@ fn spawn_test_subprocess( formatters::write_stderr_delimiter(&mut test_output, &desc.name); test_output.extend_from_slice(&stderr); - let result = get_result_from_exit_code(&desc, status, &time_opts, &exec_time); + let result = + get_result_from_exit_code(&desc, status, time_opts.as_ref(), exec_time.as_ref()); (result, test_output, exec_time) })(); @@ -724,8 +725,8 @@ fn run_test_in_spawned_subprocess(desc: TestDesc, runnable_test: RunnableTest) - let builtin_panic_hook = panic::take_hook(); let record_result = Arc::new(move |panic_info: Option<&'_ PanicHookInfo<'_>>| { let test_result = match panic_info { - Some(info) => calc_result(&desc, Err(info.payload()), &None, &None), - None => calc_result(&desc, Ok(()), &None, &None), + Some(info) => calc_result(&desc, Err(info.payload()), None, None), + None => calc_result(&desc, Ok(()), None, None), }; // We don't support serializing TrFailedMsg, so just diff --git a/library/test/src/test_result.rs b/library/test/src/test_result.rs index c5f4b03bfc96c..79fe07bc1ac5c 100644 --- a/library/test/src/test_result.rs +++ b/library/test/src/test_result.rs @@ -42,8 +42,8 @@ pub enum TestResult { pub fn calc_result<'a>( desc: &TestDesc, task_result: Result<(), &'a (dyn Any + 'static + Send)>, - time_opts: &Option, - exec_time: &Option, + time_opts: Option<&time::TestTimeOptions>, + exec_time: Option<&time::TestExecTime>, ) -> TestResult { let result = match (&desc.should_panic, task_result) { (&ShouldPanic::No, Ok(())) | (&ShouldPanic::Yes, Err(_)) => TestResult::TrOk, @@ -96,8 +96,8 @@ pub fn calc_result<'a>( pub fn get_result_from_exit_code( desc: &TestDesc, status: ExitStatus, - time_opts: &Option, - exec_time: &Option, + time_opts: Option<&time::TestTimeOptions>, + exec_time: Option<&time::TestExecTime>, ) -> TestResult { let result = match status.code() { Some(TR_OK) => TestResult::TrOk, From d2f93c97079a5c7e2b3fff6d3a63f862ce88bb3f Mon Sep 17 00:00:00 2001 From: Yuri Astrakhan Date: Wed, 2 Oct 2024 14:25:14 -0400 Subject: [PATCH 2049/2194] Update library/std/src/sys/pal/unix/process/process_unix.rs Co-authored-by: Josh Stone --- library/std/src/sys/pal/unix/process/process_unix.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/std/src/sys/pal/unix/process/process_unix.rs b/library/std/src/sys/pal/unix/process/process_unix.rs index 0fa6551772f43..4551d49e841f7 100644 --- a/library/std/src/sys/pal/unix/process/process_unix.rs +++ b/library/std/src/sys/pal/unix/process/process_unix.rs @@ -335,7 +335,7 @@ impl Command { cvt(libc::setuid(u as uid_t))?; } } - if let Some(ref cwd) = self.get_cwd() { + if let Some(cwd) = self.get_cwd() { cvt(libc::chdir(cwd.as_ptr()))?; } From 442d766cc12014a4a2c5b207ad41019b97fce03b Mon Sep 17 00:00:00 2001 From: Yuri Astrakhan Date: Tue, 8 Oct 2024 20:21:27 -0400 Subject: [PATCH 2050/2194] fix ref in process_vxworks.rs --- library/std/src/sys/pal/unix/process/process_vxworks.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/std/src/sys/pal/unix/process/process_vxworks.rs b/library/std/src/sys/pal/unix/process/process_vxworks.rs index 2d9a304c49512..6add0850a7018 100644 --- a/library/std/src/sys/pal/unix/process/process_vxworks.rs +++ b/library/std/src/sys/pal/unix/process/process_vxworks.rs @@ -57,7 +57,7 @@ impl Command { t!(cvt_r(|| libc::dup2(fd, libc::STDERR_FILENO))); } - if let Some(ref cwd) = *self.get_cwd() { + if let Some(cwd) = *self.get_cwd() { t!(cvt(libc::chdir(cwd.as_ptr()))); } From a278f157241e296ced392a81be5be7e8f608bd3c Mon Sep 17 00:00:00 2001 From: Yuri Astrakhan Date: Tue, 8 Oct 2024 22:17:16 -0400 Subject: [PATCH 2051/2194] Update library/std/src/sys/pal/unix/process/process_vxworks.rs Co-authored-by: Josh Stone --- library/std/src/sys/pal/unix/process/process_vxworks.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/std/src/sys/pal/unix/process/process_vxworks.rs b/library/std/src/sys/pal/unix/process/process_vxworks.rs index 6add0850a7018..38daf6af91808 100644 --- a/library/std/src/sys/pal/unix/process/process_vxworks.rs +++ b/library/std/src/sys/pal/unix/process/process_vxworks.rs @@ -57,7 +57,7 @@ impl Command { t!(cvt_r(|| libc::dup2(fd, libc::STDERR_FILENO))); } - if let Some(cwd) = *self.get_cwd() { + if let Some(cwd) = self.get_cwd() { t!(cvt(libc::chdir(cwd.as_ptr()))); } From 4474018500b8a18edc5fc26003740287779bc8ac Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Wed, 9 Oct 2024 07:45:48 +0300 Subject: [PATCH 2052/2194] fix `ci_rustc_if_unchanged_logic` test Signed-off-by: onur-ozkan --- src/bootstrap/src/core/builder/tests.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bootstrap/src/core/builder/tests.rs b/src/bootstrap/src/core/builder/tests.rs index 4a96ecf1421d1..ab36193f8b614 100644 --- a/src/bootstrap/src/core/builder/tests.rs +++ b/src/bootstrap/src/core/builder/tests.rs @@ -239,7 +239,7 @@ fn ci_rustc_if_unchanged_logic() { builder.run_step_descriptions(&Builder::get_step_descriptions(config.cmd.kind()), &[]); let compiler_path = build.src.join("compiler"); - let library_path = build.src.join("compiler"); + let library_path = build.src.join("library"); let commit = get_closest_merge_commit(Some(&builder.config.src), &builder.config.git_config(), &[ From fe87487b367e31ec76df3f3124e5d70a0f60a20d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=AE=B8=E6=9D=B0=E5=8F=8B=20Jieyou=20Xu=20=28Joe=29?= Date: Wed, 9 Oct 2024 04:49:27 +0000 Subject: [PATCH 2053/2194] Ignore broken-pipe-no-ice on apple for now --- tests/run-make/broken-pipe-no-ice/rmake.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tests/run-make/broken-pipe-no-ice/rmake.rs b/tests/run-make/broken-pipe-no-ice/rmake.rs index d1db0bc736883..378c3289cb7bc 100644 --- a/tests/run-make/broken-pipe-no-ice/rmake.rs +++ b/tests/run-make/broken-pipe-no-ice/rmake.rs @@ -5,6 +5,12 @@ //@ ignore-cross-compile (needs to run test binary) +//@ ignore-apple +// FIXME(#131436): on macOS rustc is still reporting the std broken pipe io error panick but it +// doesn't fail with 101 exit status (it terminates with a wait status of SIGPIPE). It doesn't say +// Internal Compiler Error strangely, but it doesn't even go through normal diagnostic infra. Very +// strange. + #![feature(anonymous_pipe)] use std::io::Read; From 461b49d96dd012dd13e172a166b7dad9ed7543d9 Mon Sep 17 00:00:00 2001 From: ultrabear Date: Wed, 18 Sep 2024 19:16:28 -0700 Subject: [PATCH 2054/2194] stabilize `{slice,array}::from_mut` --- library/core/src/array/mod.rs | 3 ++- library/core/src/lib.rs | 2 -- library/core/src/slice/raw.rs | 3 ++- library/core/tests/lib.rs | 2 -- 4 files changed, 4 insertions(+), 6 deletions(-) diff --git a/library/core/src/array/mod.rs b/library/core/src/array/mod.rs index 24c42bc85dd91..a95046162d284 100644 --- a/library/core/src/array/mod.rs +++ b/library/core/src/array/mod.rs @@ -146,7 +146,8 @@ pub const fn from_ref(s: &T) -> &[T; 1] { /// Converts a mutable reference to `T` into a mutable reference to an array of length 1 (without copying). #[stable(feature = "array_from_ref", since = "1.53.0")] -#[rustc_const_unstable(feature = "const_array_from_ref", issue = "90206")] +#[rustc_const_stable(feature = "const_array_from_ref", since = "CURRENT_RUSTC_VERSION")] +#[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] pub const fn from_mut(s: &mut T) -> &mut [T; 1] { // SAFETY: Converting `&mut T` to `&mut [T; 1]` is sound. unsafe { &mut *(s as *mut T).cast::<[T; 1]>() } diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index e323e88f26141..96ab5755328e1 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -114,7 +114,6 @@ #![feature(const_align_offset)] #![feature(const_alloc_layout)] #![feature(const_arguments_as_str)] -#![feature(const_array_from_ref)] #![feature(const_array_into_iter_constructors)] #![feature(const_bigint_helper_methods)] #![feature(const_black_box)] @@ -145,7 +144,6 @@ #![feature(const_replace)] #![feature(const_size_of_val)] #![feature(const_size_of_val_raw)] -#![feature(const_slice_from_ref)] #![feature(const_strict_overflow_ops)] #![feature(const_swap)] #![feature(const_try)] diff --git a/library/core/src/slice/raw.rs b/library/core/src/slice/raw.rs index 84e916b9a84e7..998f9360332ff 100644 --- a/library/core/src/slice/raw.rs +++ b/library/core/src/slice/raw.rs @@ -204,7 +204,8 @@ pub const fn from_ref(s: &T) -> &[T] { /// Converts a reference to T into a slice of length 1 (without copying). #[stable(feature = "from_ref", since = "1.28.0")] -#[rustc_const_unstable(feature = "const_slice_from_ref", issue = "90206")] +#[rustc_const_stable(feature = "const_slice_from_ref", since = "CURRENT_RUSTC_VERSION")] +#[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] #[must_use] pub const fn from_mut(s: &mut T) -> &mut [T] { array::from_mut(s) diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs index 196e91ee3e926..0d4ec96f8426f 100644 --- a/library/core/tests/lib.rs +++ b/library/core/tests/lib.rs @@ -16,7 +16,6 @@ #![feature(clone_to_uninit)] #![feature(const_align_of_val_raw)] #![feature(const_align_offset)] -#![feature(const_array_from_ref)] #![feature(const_black_box)] #![feature(const_hash)] #![feature(const_heap)] @@ -31,7 +30,6 @@ #![feature(const_pointer_is_aligned)] #![feature(const_ptr_write)] #![feature(const_result)] -#![feature(const_slice_from_ref)] #![feature(const_three_way_compare)] #![feature(const_trait_impl)] #![feature(core_intrinsics)] From 622d5898c2d825028ff2703fa46a140c175d5fbf Mon Sep 17 00:00:00 2001 From: Zalathar Date: Wed, 9 Oct 2024 13:51:26 +1100 Subject: [PATCH 2055/2194] Rename directive `needs-profiler-support` to `needs-profiler-runtime` --- src/tools/compiletest/src/command-list.rs | 2 +- src/tools/compiletest/src/common.rs | 2 +- src/tools/compiletest/src/header.rs | 2 +- src/tools/compiletest/src/header/needs.rs | 4 ++-- src/tools/compiletest/src/header/tests.rs | 4 ++-- tests/run-make/cross-lang-lto-pgo-smoketest-clang/rmake.rs | 2 +- tests/run-make/optimization-remarks-dir-pgo/rmake.rs | 2 +- tests/run-make/pgo-branch-weights/rmake.rs | 2 +- tests/run-make/pgo-gen-lto/rmake.rs | 2 +- tests/run-make/pgo-gen/rmake.rs | 2 +- tests/run-make/pgo-indirect-call-promotion/rmake.rs | 2 +- tests/run-make/pgo-use/rmake.rs | 2 +- tests/run-make/profile/rmake.rs | 2 +- tests/run-make/track-pgo-dep-info/rmake.rs | 2 +- tests/ui/coverage-attr/bad-attr-ice.rs | 2 +- tests/ui/issues/issue-85461.rs | 2 +- 16 files changed, 18 insertions(+), 18 deletions(-) diff --git a/src/tools/compiletest/src/command-list.rs b/src/tools/compiletest/src/command-list.rs index b34c276ab1981..53db55d0c10ff 100644 --- a/src/tools/compiletest/src/command-list.rs +++ b/src/tools/compiletest/src/command-list.rs @@ -129,7 +129,7 @@ const KNOWN_DIRECTIVE_NAMES: &[&str] = &[ "needs-git-hash", "needs-llvm-components", "needs-llvm-zstd", - "needs-profiler-support", + "needs-profiler-runtime", "needs-relocation-model-pic", "needs-run-enabled", "needs-rust-lld", diff --git a/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs index 17ec6ea430169..37f8a3df82e92 100644 --- a/src/tools/compiletest/src/common.rs +++ b/src/tools/compiletest/src/common.rs @@ -385,7 +385,7 @@ pub struct Config { pub git_merge_commit_email: String, /// True if the profiler runtime is enabled for this target. - /// Used by the "needs-profiler-support" header in test files. + /// Used by the "needs-profiler-runtime" directive in test files. pub profiler_support: bool, } diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs index a6830a6aa173f..bd0ed6321bc1c 100644 --- a/src/tools/compiletest/src/header.rs +++ b/src/tools/compiletest/src/header.rs @@ -851,7 +851,7 @@ fn iter_header( // FIXME(jieyouxu): I feel like there's a better way to do this, leaving for later. if mode == Mode::CoverageRun { let extra_directives: &[&str] = &[ - "needs-profiler-support", + "needs-profiler-runtime", // FIXME(pietroalbini): this test currently does not work on cross-compiled targets // because remote-test is not capable of sending back the *.profraw files generated by // the LLVM instrumentation. diff --git a/src/tools/compiletest/src/header/needs.rs b/src/tools/compiletest/src/header/needs.rs index f5dd722ed3711..ca7600d4dcb40 100644 --- a/src/tools/compiletest/src/header/needs.rs +++ b/src/tools/compiletest/src/header/needs.rs @@ -100,9 +100,9 @@ pub(super) fn handle_needs( ignore_reason: "ignored on targets without unwinding support", }, Need { - name: "needs-profiler-support", + name: "needs-profiler-runtime", condition: cache.profiler_support, - ignore_reason: "ignored when profiler support is disabled", + ignore_reason: "ignored when the profiler runtime is not available", }, Need { name: "needs-force-clang-based-tests", diff --git a/src/tools/compiletest/src/header/tests.rs b/src/tools/compiletest/src/header/tests.rs index 18e26635ac025..9b1294ad5fecf 100644 --- a/src/tools/compiletest/src/header/tests.rs +++ b/src/tools/compiletest/src/header/tests.rs @@ -370,10 +370,10 @@ fn sanitizers() { #[test] fn profiler_support() { let config: Config = cfg().profiler_support(false).build(); - assert!(check_ignore(&config, "//@ needs-profiler-support")); + assert!(check_ignore(&config, "//@ needs-profiler-runtime")); let config: Config = cfg().profiler_support(true).build(); - assert!(!check_ignore(&config, "//@ needs-profiler-support")); + assert!(!check_ignore(&config, "//@ needs-profiler-runtime")); } #[test] diff --git a/tests/run-make/cross-lang-lto-pgo-smoketest-clang/rmake.rs b/tests/run-make/cross-lang-lto-pgo-smoketest-clang/rmake.rs index 03c9af4bb8982..50790e18cec10 100644 --- a/tests/run-make/cross-lang-lto-pgo-smoketest-clang/rmake.rs +++ b/tests/run-make/cross-lang-lto-pgo-smoketest-clang/rmake.rs @@ -9,7 +9,7 @@ // RUSTBUILD_FORCE_CLANG_BASED_TESTS and only runs tests which contain "clang" in their // name. -//@ needs-profiler-support +//@ needs-profiler-runtime // FIXME(Oneirical): Except that due to the reliance on llvm-profdata, this test // never runs, because `x86_64-gnu-debug` does not have the `profiler_builtins` crate. diff --git a/tests/run-make/optimization-remarks-dir-pgo/rmake.rs b/tests/run-make/optimization-remarks-dir-pgo/rmake.rs index 228c43cc5f18a..471ce89f188b7 100644 --- a/tests/run-make/optimization-remarks-dir-pgo/rmake.rs +++ b/tests/run-make/optimization-remarks-dir-pgo/rmake.rs @@ -4,7 +4,7 @@ // the output remark files. // See https://github.com/rust-lang/rust/pull/114439 -//@ needs-profiler-support +//@ needs-profiler-runtime //@ ignore-cross-compile use run_make_support::{ diff --git a/tests/run-make/pgo-branch-weights/rmake.rs b/tests/run-make/pgo-branch-weights/rmake.rs index 105c2fafc5a10..1893248e3077a 100644 --- a/tests/run-make/pgo-branch-weights/rmake.rs +++ b/tests/run-make/pgo-branch-weights/rmake.rs @@ -7,7 +7,7 @@ // If the test passes, the expected function call count was added to the use-phase LLVM-IR. // See https://github.com/rust-lang/rust/pull/66631 -//@ needs-profiler-support +//@ needs-profiler-runtime //@ ignore-cross-compile use std::path::Path; diff --git a/tests/run-make/pgo-gen-lto/rmake.rs b/tests/run-make/pgo-gen-lto/rmake.rs index 53d1623bf580e..4f7ae9fb24c91 100644 --- a/tests/run-make/pgo-gen-lto/rmake.rs +++ b/tests/run-make/pgo-gen-lto/rmake.rs @@ -2,7 +2,7 @@ // should be generated. // See https://github.com/rust-lang/rust/pull/48346 -//@ needs-profiler-support +//@ needs-profiler-runtime // Reason: this exercises LTO profiling //@ ignore-cross-compile // Reason: the compiled binary is executed diff --git a/tests/run-make/pgo-gen/rmake.rs b/tests/run-make/pgo-gen/rmake.rs index ad2f6388e8fff..5cd5a4583edaf 100644 --- a/tests/run-make/pgo-gen/rmake.rs +++ b/tests/run-make/pgo-gen/rmake.rs @@ -3,7 +3,7 @@ // optimizes code. This test checks that these files are generated. // See https://github.com/rust-lang/rust/pull/48346 -//@ needs-profiler-support +//@ needs-profiler-runtime //@ ignore-cross-compile use run_make_support::{cwd, has_extension, has_prefix, run, rustc, shallow_find_files}; diff --git a/tests/run-make/pgo-indirect-call-promotion/rmake.rs b/tests/run-make/pgo-indirect-call-promotion/rmake.rs index 28232eb256621..ce9754f13b931 100644 --- a/tests/run-make/pgo-indirect-call-promotion/rmake.rs +++ b/tests/run-make/pgo-indirect-call-promotion/rmake.rs @@ -5,7 +5,7 @@ // whether it can make a direct call instead of the indirect call. // See https://github.com/rust-lang/rust/pull/66631 -//@ needs-profiler-support +//@ needs-profiler-runtime // Reason: llvm_profdata is used //@ ignore-cross-compile // Reason: the compiled binary is executed diff --git a/tests/run-make/pgo-use/rmake.rs b/tests/run-make/pgo-use/rmake.rs index 276af9ea263a7..c09a82353b9be 100644 --- a/tests/run-make/pgo-use/rmake.rs +++ b/tests/run-make/pgo-use/rmake.rs @@ -5,7 +5,7 @@ // be marked as cold. // See https://github.com/rust-lang/rust/pull/60262 -//@ needs-profiler-support +//@ needs-profiler-runtime //@ ignore-cross-compile use run_make_support::{ diff --git a/tests/run-make/profile/rmake.rs b/tests/run-make/profile/rmake.rs index 4287ab0a93150..58a1b53c0406e 100644 --- a/tests/run-make/profile/rmake.rs +++ b/tests/run-make/profile/rmake.rs @@ -6,7 +6,7 @@ // See https://github.com/rust-lang/rust/pull/42433 //@ ignore-cross-compile -//@ needs-profiler-support +//@ needs-profiler-runtime use run_make_support::{path, run, rustc}; diff --git a/tests/run-make/track-pgo-dep-info/rmake.rs b/tests/run-make/track-pgo-dep-info/rmake.rs index 84f4e0bd383e8..5869dbf9c2419 100644 --- a/tests/run-make/track-pgo-dep-info/rmake.rs +++ b/tests/run-make/track-pgo-dep-info/rmake.rs @@ -6,7 +6,7 @@ //@ ignore-cross-compile // Reason: the binary is executed -//@ needs-profiler-support +//@ needs-profiler-runtime use run_make_support::{llvm_profdata, rfs, run, rustc}; diff --git a/tests/ui/coverage-attr/bad-attr-ice.rs b/tests/ui/coverage-attr/bad-attr-ice.rs index ae4d27d65ebd6..55c86d260d4b3 100644 --- a/tests/ui/coverage-attr/bad-attr-ice.rs +++ b/tests/ui/coverage-attr/bad-attr-ice.rs @@ -1,7 +1,7 @@ #![cfg_attr(feat, feature(coverage_attribute))] //@ revisions: feat nofeat //@ compile-flags: -Cinstrument-coverage -//@ needs-profiler-support +//@ needs-profiler-runtime // Malformed `#[coverage(..)]` attributes should not cause an ICE when built // with `-Cinstrument-coverage`. diff --git a/tests/ui/issues/issue-85461.rs b/tests/ui/issues/issue-85461.rs index 7fe7a4aa579fb..72538081ccb3a 100644 --- a/tests/ui/issues/issue-85461.rs +++ b/tests/ui/issues/issue-85461.rs @@ -1,6 +1,6 @@ //@ compile-flags: -Cinstrument-coverage -Ccodegen-units=4 --crate-type dylib -Copt-level=0 //@ build-pass -//@ needs-profiler-support +//@ needs-profiler-runtime //@ needs-dynamic-linking // Regression test for #85461 where MSVC sometimes fails to link instrument-coverage binaries From 8320a0116b66b6148b03ca280123c54d3c9ee218 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Wed, 9 Oct 2024 14:03:10 +1100 Subject: [PATCH 2056/2194] Rename `profiler_support` to `profiler_runtime` throughout compiletest --- src/bootstrap/src/core/build_steps/test.rs | 2 +- src/tools/compiletest/src/common.rs | 2 +- src/tools/compiletest/src/header/needs.rs | 6 +++--- src/tools/compiletest/src/header/tests.rs | 22 +++++++++++----------- src/tools/compiletest/src/lib.rs | 4 ++-- src/tools/compiletest/src/main.rs | 2 +- 6 files changed, 19 insertions(+), 19 deletions(-) diff --git a/src/bootstrap/src/core/build_steps/test.rs b/src/bootstrap/src/core/build_steps/test.rs index 7a49b68b91e65..0dd3d0b3bd115 100644 --- a/src/bootstrap/src/core/build_steps/test.rs +++ b/src/bootstrap/src/core/build_steps/test.rs @@ -2082,7 +2082,7 @@ NOTE: if you're sure you want to do this, please open an issue as to why. In the } if builder.config.profiler_enabled(target) { - cmd.arg("--profiler-support"); + cmd.arg("--profiler-runtime"); } cmd.env("RUST_TEST_TMPDIR", builder.tempdir()); diff --git a/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs index 37f8a3df82e92..a5418ad838488 100644 --- a/src/tools/compiletest/src/common.rs +++ b/src/tools/compiletest/src/common.rs @@ -386,7 +386,7 @@ pub struct Config { /// True if the profiler runtime is enabled for this target. /// Used by the "needs-profiler-runtime" directive in test files. - pub profiler_support: bool, + pub profiler_runtime: bool, } impl Config { diff --git a/src/tools/compiletest/src/header/needs.rs b/src/tools/compiletest/src/header/needs.rs index ca7600d4dcb40..c304cb8601560 100644 --- a/src/tools/compiletest/src/header/needs.rs +++ b/src/tools/compiletest/src/header/needs.rs @@ -101,7 +101,7 @@ pub(super) fn handle_needs( }, Need { name: "needs-profiler-runtime", - condition: cache.profiler_support, + condition: cache.profiler_runtime, ignore_reason: "ignored when the profiler runtime is not available", }, Need { @@ -220,7 +220,7 @@ pub(super) struct CachedNeedsConditions { sanitizer_memtag: bool, sanitizer_shadow_call_stack: bool, sanitizer_safestack: bool, - profiler_support: bool, + profiler_runtime: bool, xray: bool, rust_lld: bool, dlltool: bool, @@ -247,7 +247,7 @@ impl CachedNeedsConditions { sanitizer_memtag: sanitizers.contains(&Sanitizer::Memtag), sanitizer_shadow_call_stack: sanitizers.contains(&Sanitizer::ShadowCallStack), sanitizer_safestack: sanitizers.contains(&Sanitizer::Safestack), - profiler_support: config.profiler_support, + profiler_runtime: config.profiler_runtime, xray: config.target_cfg().xray, // For tests using the `needs-rust-lld` directive (e.g. for `-Clink-self-contained=+linker`), diff --git a/src/tools/compiletest/src/header/tests.rs b/src/tools/compiletest/src/header/tests.rs index 9b1294ad5fecf..10ec2a1806f8d 100644 --- a/src/tools/compiletest/src/header/tests.rs +++ b/src/tools/compiletest/src/header/tests.rs @@ -69,7 +69,7 @@ struct ConfigBuilder { llvm_version: Option, git_hash: bool, system_llvm: bool, - profiler_support: bool, + profiler_runtime: bool, } impl ConfigBuilder { @@ -113,8 +113,8 @@ impl ConfigBuilder { self } - fn profiler_support(&mut self, s: bool) -> &mut Self { - self.profiler_support = s; + fn profiler_runtime(&mut self, is_available: bool) -> &mut Self { + self.profiler_runtime = is_available; self } @@ -162,8 +162,8 @@ impl ConfigBuilder { if self.system_llvm { args.push("--system-llvm".to_owned()); } - if self.profiler_support { - args.push("--profiler-support".to_owned()); + if self.profiler_runtime { + args.push("--profiler-runtime".to_owned()); } args.push("--rustc-path".to_string()); @@ -368,11 +368,11 @@ fn sanitizers() { } #[test] -fn profiler_support() { - let config: Config = cfg().profiler_support(false).build(); +fn profiler_runtime() { + let config: Config = cfg().profiler_runtime(false).build(); assert!(check_ignore(&config, "//@ needs-profiler-runtime")); - let config: Config = cfg().profiler_support(true).build(); + let config: Config = cfg().profiler_runtime(true).build(); assert!(!check_ignore(&config, "//@ needs-profiler-runtime")); } @@ -573,12 +573,12 @@ fn families() { #[test] fn ignore_coverage() { - // Indicate profiler support so that "coverage-run" tests aren't skipped. - let config = cfg().mode("coverage-map").profiler_support(true).build(); + // Indicate profiler runtime availability so that "coverage-run" tests aren't skipped. + let config = cfg().mode("coverage-map").profiler_runtime(true).build(); assert!(check_ignore(&config, "//@ ignore-coverage-map")); assert!(!check_ignore(&config, "//@ ignore-coverage-run")); - let config = cfg().mode("coverage-run").profiler_support(true).build(); + let config = cfg().mode("coverage-run").profiler_runtime(true).build(); assert!(!check_ignore(&config, "//@ ignore-coverage-map")); assert!(check_ignore(&config, "//@ ignore-coverage-run")); } diff --git a/src/tools/compiletest/src/lib.rs b/src/tools/compiletest/src/lib.rs index d9f64cddf5d43..98375a21b04b9 100644 --- a/src/tools/compiletest/src/lib.rs +++ b/src/tools/compiletest/src/lib.rs @@ -153,7 +153,7 @@ pub fn parse_config(args: Vec) -> Config { .optflag("", "force-rerun", "rerun tests even if the inputs are unchanged") .optflag("", "only-modified", "only run tests that result been modified") .optflag("", "nocapture", "") - .optflag("", "profiler-support", "is the profiler runtime enabled for this target") + .optflag("", "profiler-runtime", "is the profiler runtime enabled for this target") .optflag("h", "help", "show this message") .reqopt("", "channel", "current Rust channel", "CHANNEL") .optflag( @@ -355,7 +355,7 @@ pub fn parse_config(args: Vec) -> Config { nightly_branch: matches.opt_str("nightly-branch").unwrap(), git_merge_commit_email: matches.opt_str("git-merge-commit-email").unwrap(), - profiler_support: matches.opt_present("profiler-support"), + profiler_runtime: matches.opt_present("profiler-runtime"), } } diff --git a/src/tools/compiletest/src/main.rs b/src/tools/compiletest/src/main.rs index 9f3eef3776d4e..b0f87593f9532 100644 --- a/src/tools/compiletest/src/main.rs +++ b/src/tools/compiletest/src/main.rs @@ -22,7 +22,7 @@ fn main() { eprintln!("warning: `tidy` is not installed; diffs will not be generated"); } - if !config.profiler_support && config.mode == Mode::CoverageRun { + if !config.profiler_runtime && config.mode == Mode::CoverageRun { let actioned = if config.bless { "blessed" } else { "checked" }; eprintln!( r#" From 7a0e8bd1fd9998765ac99a640566c57eeda9882e Mon Sep 17 00:00:00 2001 From: Zalathar Date: Wed, 9 Oct 2024 14:08:13 +1100 Subject: [PATCH 2057/2194] No need to cache the `profiler_runtime` flag This cache struct entry was a relic from when profiler availability was communicated via an environment variable rather than a command-line flag. --- src/tools/compiletest/src/header/needs.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/tools/compiletest/src/header/needs.rs b/src/tools/compiletest/src/header/needs.rs index c304cb8601560..a744fb61b9cfc 100644 --- a/src/tools/compiletest/src/header/needs.rs +++ b/src/tools/compiletest/src/header/needs.rs @@ -101,7 +101,7 @@ pub(super) fn handle_needs( }, Need { name: "needs-profiler-runtime", - condition: cache.profiler_runtime, + condition: config.profiler_runtime, ignore_reason: "ignored when the profiler runtime is not available", }, Need { @@ -220,7 +220,6 @@ pub(super) struct CachedNeedsConditions { sanitizer_memtag: bool, sanitizer_shadow_call_stack: bool, sanitizer_safestack: bool, - profiler_runtime: bool, xray: bool, rust_lld: bool, dlltool: bool, @@ -247,7 +246,6 @@ impl CachedNeedsConditions { sanitizer_memtag: sanitizers.contains(&Sanitizer::Memtag), sanitizer_shadow_call_stack: sanitizers.contains(&Sanitizer::ShadowCallStack), sanitizer_safestack: sanitizers.contains(&Sanitizer::Safestack), - profiler_runtime: config.profiler_runtime, xray: config.target_cfg().xray, // For tests using the `needs-rust-lld` directive (e.g. for `-Clink-self-contained=+linker`), From becf664e4930ce59fb01905e4c6af38c2df5382e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=AE=B8=E6=9D=B0=E5=8F=8B=20Jieyou=20Xu=20=28Joe=29?= <39484203+jieyouxu@users.noreply.github.com> Date: Wed, 9 Oct 2024 18:52:28 +0800 Subject: [PATCH 2058/2194] Match std RUSTFLAGS for host and target for `mir-opt` test --- src/bootstrap/src/core/build_steps/test.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/bootstrap/src/core/build_steps/test.rs b/src/bootstrap/src/core/build_steps/test.rs index 7a49b68b91e65..5bf4f19b3c417 100644 --- a/src/bootstrap/src/core/build_steps/test.rs +++ b/src/bootstrap/src/core/build_steps/test.rs @@ -1697,7 +1697,11 @@ NOTE: if you're sure you want to do this, please open an issue as to why. In the builder.ensure(TestHelpers { target: compiler.host }); // ensure that `libproc_macro` is available on the host. - builder.ensure(compile::Std::new(compiler, compiler.host)); + if suite == "mir-opt" { + builder.ensure(compile::Std::new_for_mir_opt_tests(compiler, compiler.host)); + } else { + builder.ensure(compile::Std::new(compiler, compiler.host)); + } // As well as the target if suite != "mir-opt" { From 01e248ff974e310be5fb88d374cbed64aa5c4a25 Mon Sep 17 00:00:00 2001 From: Nicola Krumschmidt Date: Wed, 9 Oct 2024 14:39:28 +0200 Subject: [PATCH 2059/2194] Decouple WASIp2 sockets from WasiFd --- library/std/src/os/wasi/mod.rs | 2 + library/std/src/sys/pal/wasip2/net.rs | 74 ++++++++++++++++++++------- 2 files changed, 58 insertions(+), 18 deletions(-) diff --git a/library/std/src/os/wasi/mod.rs b/library/std/src/os/wasi/mod.rs index 33b50c9e53b8f..2ee6aa4660094 100644 --- a/library/std/src/os/wasi/mod.rs +++ b/library/std/src/os/wasi/mod.rs @@ -36,6 +36,8 @@ pub mod ffi; pub mod fs; pub mod io; + +#[cfg(all(target_os = "wasi", target_env = "p1"))] pub mod net; /// A prelude for conveniently writing platform-specific code. diff --git a/library/std/src/sys/pal/wasip2/net.rs b/library/std/src/sys/pal/wasip2/net.rs index c40eb229ba9a4..06e623df8438e 100644 --- a/library/std/src/sys/pal/wasip2/net.rs +++ b/library/std/src/sys/pal/wasip2/net.rs @@ -2,13 +2,12 @@ use libc::{c_int, c_void, size_t}; -use super::fd::WasiFd; use crate::ffi::CStr; use crate::io::{self, BorrowedBuf, BorrowedCursor, IoSlice, IoSliceMut}; use crate::net::{Shutdown, SocketAddr}; -use crate::os::wasi::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, RawFd}; +use crate::os::wasi::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, OwnedFd, RawFd}; use crate::sys::unsupported; -use crate::sys_common::net::{TcpListener, getsockopt, setsockopt, sockaddr_to_addr}; +use crate::sys_common::net::{getsockopt, setsockopt, sockaddr_to_addr}; use crate::sys_common::{AsInner, FromInner, IntoInner}; use crate::time::{Duration, Instant}; use crate::{cmp, mem, str}; @@ -71,7 +70,9 @@ pub fn cvt_gai(err: c_int) -> io::Result<()> { pub fn init() {} -pub struct Socket(WasiFd); +pub struct WasiSocket(OwnedFd); + +pub struct Socket(WasiSocket); impl Socket { pub fn new(addr: &SocketAddr, ty: c_int) -> io::Result { @@ -327,53 +328,90 @@ impl Socket { } } -impl AsInner for Socket { +impl AsInner for WasiSocket { #[inline] - fn as_inner(&self) -> &WasiFd { + fn as_inner(&self) -> &OwnedFd { &self.0 } } -impl IntoInner for Socket { - fn into_inner(self) -> WasiFd { +impl IntoInner for WasiSocket { + fn into_inner(self) -> OwnedFd { self.0 } } -impl FromInner for Socket { - fn from_inner(inner: WasiFd) -> Socket { - Socket(inner) +impl FromInner for WasiSocket { + fn from_inner(owned_fd: OwnedFd) -> Self { + Self(owned_fd) } } -impl AsFd for Socket { +impl AsFd for WasiSocket { fn as_fd(&self) -> BorrowedFd<'_> { self.0.as_fd() } } -impl AsRawFd for Socket { +impl AsRawFd for WasiSocket { #[inline] fn as_raw_fd(&self) -> RawFd { self.0.as_raw_fd() } } -impl IntoRawFd for Socket { +impl IntoRawFd for WasiSocket { fn into_raw_fd(self) -> RawFd { self.0.into_raw_fd() } } -impl FromRawFd for Socket { +impl FromRawFd for WasiSocket { unsafe fn from_raw_fd(raw_fd: RawFd) -> Self { unsafe { Self(FromRawFd::from_raw_fd(raw_fd)) } } } -impl AsInner for TcpListener { +impl AsInner for Socket { + #[inline] + fn as_inner(&self) -> &WasiSocket { + &self.0 + } +} + +impl IntoInner for Socket { + fn into_inner(self) -> WasiSocket { + self.0 + } +} + +impl FromInner for Socket { + fn from_inner(sock: WasiSocket) -> Socket { + Socket(sock) + } +} + +impl AsFd for Socket { + fn as_fd(&self) -> BorrowedFd<'_> { + self.0.as_fd() + } +} + +impl AsRawFd for Socket { #[inline] - fn as_inner(&self) -> &Socket { - &self.socket() + fn as_raw_fd(&self) -> RawFd { + self.0.as_raw_fd() + } +} + +impl IntoRawFd for Socket { + fn into_raw_fd(self) -> RawFd { + self.0.into_raw_fd() + } +} + +impl FromRawFd for Socket { + unsafe fn from_raw_fd(raw_fd: RawFd) -> Self { + unsafe { Self(FromRawFd::from_raw_fd(raw_fd)) } } } From de60931645a1baf5edddd9f0c9027c0e494b46fb Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Wed, 9 Oct 2024 06:01:25 -0700 Subject: [PATCH 2060/2194] Add "reference" as a known compiletest header This adds the "reference" compiletest header so that the Rust reference can add annotations to the test suite in order to link tests to individual rules in the reference. Tooling in the reference repo will be responsible for collecting these annotations and linking to the tests. More details are in MCP 783: https://github.com/rust-lang/compiler-team/issues/783 --- src/tools/compiletest/src/command-list.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/tools/compiletest/src/command-list.rs b/src/tools/compiletest/src/command-list.rs index b34c276ab1981..8349c3085cc82 100644 --- a/src/tools/compiletest/src/command-list.rs +++ b/src/tools/compiletest/src/command-list.rs @@ -208,6 +208,7 @@ const KNOWN_DIRECTIVE_NAMES: &[&str] = &[ "pretty-compare-only", "pretty-expanded", "pretty-mode", + "reference", "regex-error-pattern", "remap-src-base", "revisions", From 6774856e0c81f6cbedd772d295a21005d04a9224 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= Date: Wed, 9 Oct 2024 15:34:45 +0200 Subject: [PATCH 2061/2194] add more crash tests --- tests/crashes/130956.rs | 37 ++++++++++++++++++++++++++++++++++++ tests/crashes/130967.rs | 13 +++++++++++++ tests/crashes/131046.rs | 15 +++++++++++++++ tests/crashes/131048.rs | 7 +++++++ tests/crashes/131050.rs | 27 ++++++++++++++++++++++++++ tests/crashes/131052.rs | 8 ++++++++ tests/crashes/131101.rs | 12 ++++++++++++ tests/crashes/131102.rs | 4 ++++ tests/crashes/131103.rs | 6 ++++++ tests/crashes/131190.rs | 19 +++++++++++++++++++ tests/crashes/131227.rs | 16 ++++++++++++++++ tests/crashes/131292.rs | 7 +++++++ tests/crashes/131294-2.rs | 25 ++++++++++++++++++++++++ tests/crashes/131294.rs | 16 ++++++++++++++++ tests/crashes/131295.rs | 9 +++++++++ tests/crashes/131298.rs | 12 ++++++++++++ tests/crashes/131342-2.rs | 40 +++++++++++++++++++++++++++++++++++++++ tests/crashes/131342.rs | 16 ++++++++++++++++ tests/crashes/131347.rs | 9 +++++++++ tests/crashes/131373.rs | 33 ++++++++++++++++++++++++++++++++ tests/crashes/131406.rs | 12 ++++++++++++ 21 files changed, 343 insertions(+) create mode 100644 tests/crashes/130956.rs create mode 100644 tests/crashes/130967.rs create mode 100644 tests/crashes/131046.rs create mode 100644 tests/crashes/131048.rs create mode 100644 tests/crashes/131050.rs create mode 100644 tests/crashes/131052.rs create mode 100644 tests/crashes/131101.rs create mode 100644 tests/crashes/131102.rs create mode 100644 tests/crashes/131103.rs create mode 100644 tests/crashes/131190.rs create mode 100644 tests/crashes/131227.rs create mode 100644 tests/crashes/131292.rs create mode 100644 tests/crashes/131294-2.rs create mode 100644 tests/crashes/131294.rs create mode 100644 tests/crashes/131295.rs create mode 100644 tests/crashes/131298.rs create mode 100644 tests/crashes/131342-2.rs create mode 100644 tests/crashes/131342.rs create mode 100644 tests/crashes/131347.rs create mode 100644 tests/crashes/131373.rs create mode 100644 tests/crashes/131406.rs diff --git a/tests/crashes/130956.rs b/tests/crashes/130956.rs new file mode 100644 index 0000000000000..ebb986d123f91 --- /dev/null +++ b/tests/crashes/130956.rs @@ -0,0 +1,37 @@ +//@ known-bug: #130956 + +mod impl_trait_mod { + use super::*; + pub type OpaqueBlock = impl Trait; + pub type OpaqueIf = impl Trait; + + pub struct BlockWrapper(OpaqueBlock); + pub struct IfWrapper(pub OpaqueIf); + + pub fn if_impl() -> Parser { + bind(option(block()), |_| block()) + } +} +use impl_trait_mod::*; + +pub trait Trait { + type Assoc; +} +pub struct Parser

    (P); +pub struct Bind(P, F); +impl Trait for Bind { type Assoc = (); } +impl Trait for BlockWrapper { type Assoc = (); } +impl Trait for IfWrapper { type Assoc = (); } + +pub fn block() -> Parser { + loop {} +} +pub fn option(arg: Parser

    ) -> Parser { + bind(arg, |_| block()) +} +fn bind Parser>(_: Parser

    , _: F) -> Parser> + { loop {} } + +fn main() { + if_impl().0; +} diff --git a/tests/crashes/130967.rs b/tests/crashes/130967.rs new file mode 100644 index 0000000000000..8a3aae72c20c5 --- /dev/null +++ b/tests/crashes/130967.rs @@ -0,0 +1,13 @@ +//@ known-bug: #130967 + +trait Producer { + type Produced; + fn make_one() -> Self::Produced; +} + +impl Producer for () { + type Produced = Option; + fn make_one() -> Self::Produced { + loop {} + } +} diff --git a/tests/crashes/131046.rs b/tests/crashes/131046.rs new file mode 100644 index 0000000000000..2638705ae18b2 --- /dev/null +++ b/tests/crashes/131046.rs @@ -0,0 +1,15 @@ +//@ known-bug: #131046 + +trait Owner { + const C: u32; +} + +impl Owner for () { + const C: u32 = N; +} + +fn take0(_: impl Owner = { N }>) {} + +fn main() { + take0::<128>(()); +} diff --git a/tests/crashes/131048.rs b/tests/crashes/131048.rs new file mode 100644 index 0000000000000..d57e9921a8ab5 --- /dev/null +++ b/tests/crashes/131048.rs @@ -0,0 +1,7 @@ +//@ known-bug: #131048 + +impl std::ops::CoerceUnsized for A {} + +fn main() { + format_args!("Hello, world!"); +} diff --git a/tests/crashes/131050.rs b/tests/crashes/131050.rs new file mode 100644 index 0000000000000..07f8662d016f7 --- /dev/null +++ b/tests/crashes/131050.rs @@ -0,0 +1,27 @@ +//@ known-bug: #131050 +//@ compile-flags: --edition=2021 + +fn query_as() {} + +async fn create_user() { + query_as(); +} + +async fn post_user_filter() -> impl Filter { + AndThen(&(), || async { create_user().await }) +} + +async fn get_app() -> impl Send { + post_user_filter().await +} + +trait Filter {} + +struct AndThen(T, F); + +impl Filter for AndThen +where + F: Fn() -> R, + R: Send, +{ +} diff --git a/tests/crashes/131052.rs b/tests/crashes/131052.rs new file mode 100644 index 0000000000000..7ae3ec08f3ed7 --- /dev/null +++ b/tests/crashes/131052.rs @@ -0,0 +1,8 @@ +//@ known-bug: #131052 +#![feature(adt_const_params)] + +struct ConstBytes; + +pub fn main() { + let _: ConstBytes = ConstBytes::; +} diff --git a/tests/crashes/131101.rs b/tests/crashes/131101.rs new file mode 100644 index 0000000000000..3ec441101b7d9 --- /dev/null +++ b/tests/crashes/131101.rs @@ -0,0 +1,12 @@ +//@ known-bug: #131101 +trait Foo { + fn do_x(&self) -> [u8; N]; +} + +struct Bar; + +impl Foo for Bar { + fn do_x(&self) -> [u8; 3] { + [0u8; 3] + } +} diff --git a/tests/crashes/131102.rs b/tests/crashes/131102.rs new file mode 100644 index 0000000000000..12b35f8d1b2ac --- /dev/null +++ b/tests/crashes/131102.rs @@ -0,0 +1,4 @@ +//@ known-bug: #131102 +pub struct Blorb([String; N]); +pub struct Wrap(Blorb<0>); +pub const fn i(_: Wrap) {} diff --git a/tests/crashes/131103.rs b/tests/crashes/131103.rs new file mode 100644 index 0000000000000..70193e8b3bd38 --- /dev/null +++ b/tests/crashes/131103.rs @@ -0,0 +1,6 @@ +//@ known-bug: #131103 +struct Struct(pub [u8; N]); + +pub fn function(value: Struct<3>) -> u8 { + value.0[0] +} diff --git a/tests/crashes/131190.rs b/tests/crashes/131190.rs new file mode 100644 index 0000000000000..3a0e64c69d5b5 --- /dev/null +++ b/tests/crashes/131190.rs @@ -0,0 +1,19 @@ +//@ known-bug: #131190 +//@ compile-flags: -Cinstrument-coverage --edition=2018 + +use std::future::Future; + +pub fn block_on(fut: impl Future) -> T {} + +async fn call_once(f: impl async FnOnce(DropMe)) { + f(DropMe("world")).await; +} + +struct DropMe(&'static str); + +pub fn main() { + block_on(async { + let async_closure = async move |a: DropMe| {}; + call_once(async_closure).await; + }); +} diff --git a/tests/crashes/131227.rs b/tests/crashes/131227.rs new file mode 100644 index 0000000000000..f46185b5b4a66 --- /dev/null +++ b/tests/crashes/131227.rs @@ -0,0 +1,16 @@ +//@ known-bug: #131227 +//@ compile-flags: -Zmir-opt-level=3 + +static mut G: () = (); + +fn myfunc() -> i32 { + let var = &raw mut G; + if var.is_null() { + return 0; + } + 0 +} + +fn main() { + myfunc(); +} diff --git a/tests/crashes/131292.rs b/tests/crashes/131292.rs new file mode 100644 index 0000000000000..01e0eca0bd6d6 --- /dev/null +++ b/tests/crashes/131292.rs @@ -0,0 +1,7 @@ +//@ known-bug: #131292 +//@ only-x86_64 +use std::arch::asm; + +unsafe fn f6() { + asm!(concat!(r#"lJ𐏿Æ�.𐏿�"#, "{}/day{:02}.txt")); +} diff --git a/tests/crashes/131294-2.rs b/tests/crashes/131294-2.rs new file mode 100644 index 0000000000000..130a8b10fb78e --- /dev/null +++ b/tests/crashes/131294-2.rs @@ -0,0 +1,25 @@ +//@ known-bug: #131294 +//@ compile-flags: -Zmir-opt-level=5 -Zvalidate-mir -Zcross-crate-inline-threshold=always + +// https://github.com/rust-lang/rust/issues/131294#issuecomment-2395088049 second comment +struct Rows; + +impl Iterator for Rows { + type Item = String; + + fn next() -> Option { + let args = format_args!("Hello world"); + + { + match args.as_str() { + Some(t) => t.to_owned(), + None => String::new(), + } + } + .into() + } +} + +fn main() { + Rows.next(); +} diff --git a/tests/crashes/131294.rs b/tests/crashes/131294.rs new file mode 100644 index 0000000000000..ec6c95674677e --- /dev/null +++ b/tests/crashes/131294.rs @@ -0,0 +1,16 @@ +//@ known-bug: #131294 +//@ compile-flags: -Zmir-opt-level=5 -Zvalidate-mir -Zcross-crate-inline-threshold=always + +struct Rows; + +impl Iterator for Rows { + type Item = String; + + fn next() -> Option { + std::fmt::format(format_args!("Hello world")).into() + } +} + +fn main() { + Rows.next(); +} diff --git a/tests/crashes/131295.rs b/tests/crashes/131295.rs new file mode 100644 index 0000000000000..f31d6bc324a26 --- /dev/null +++ b/tests/crashes/131295.rs @@ -0,0 +1,9 @@ +//@ known-bug: #131295 + +#![feature(generic_const_exprs)] + +async fn foo<'a>() -> [(); { + let _y: &'a (); + 4 + }] { +} diff --git a/tests/crashes/131298.rs b/tests/crashes/131298.rs new file mode 100644 index 0000000000000..833f1b04ffab9 --- /dev/null +++ b/tests/crashes/131298.rs @@ -0,0 +1,12 @@ +//@ known-bug: #131298 + +fn dyn_hoops() -> *const dyn Iterator { + loop {} +} + +mod typeck { + type Opaque = impl Sized; + fn define() -> Opaque { + let _: Opaque = super::dyn_hoops::(); + } +} diff --git a/tests/crashes/131342-2.rs b/tests/crashes/131342-2.rs new file mode 100644 index 0000000000000..79b6a837a49fb --- /dev/null +++ b/tests/crashes/131342-2.rs @@ -0,0 +1,40 @@ +//@ known-bug: #131342 +// see also: 131342.rs + +fn main() { + problem_thingy(Once); +} + +struct Once; + +impl Iterator for Once { + type Item = (); +} + +fn problem_thingy(items: impl Iterator) { + let peeker = items.peekable(); + problem_thingy(&peeker); +} + +trait Iterator { + type Item; + + fn peekable(self) -> Peekable + where + Self: Sized, + { + loop {} + } +} + +struct Peekable { + _peeked: I::Item, +} + +impl Iterator for Peekable { + type Item = I::Item; +} + +impl Iterator for &I { + type Item = I::Item; +} diff --git a/tests/crashes/131342.rs b/tests/crashes/131342.rs new file mode 100644 index 0000000000000..7f7ee9c9ac110 --- /dev/null +++ b/tests/crashes/131342.rs @@ -0,0 +1,16 @@ +//@ known-bug: #131342 +// see also: 131342-2.rs + +fn main() { + let mut items = vec![1, 2, 3, 4, 5].into_iter(); + problem_thingy(&mut items); +} + +fn problem_thingy(items: &mut impl Iterator) { + let mut peeker = items.peekable(); + match peeker.peek() { + Some(_) => (), + None => return (), + } + problem_thingy(&mut peeker); +} diff --git a/tests/crashes/131347.rs b/tests/crashes/131347.rs new file mode 100644 index 0000000000000..15f367d79e208 --- /dev/null +++ b/tests/crashes/131347.rs @@ -0,0 +1,9 @@ +//@ known-bug: #131347 +//@ compile-flags: -Zmir-opt-level=5 -Zvalidate-mir + +struct S; +static STUFF: [i8] = [0; S::N]; + +fn main() { + assert_eq!(STUFF, [0; 63]); +} diff --git a/tests/crashes/131373.rs b/tests/crashes/131373.rs new file mode 100644 index 0000000000000..661fecd7620b8 --- /dev/null +++ b/tests/crashes/131373.rs @@ -0,0 +1,33 @@ +//@ known-bug: #131373 + +trait LockReference: 'static { + type Ref<'a>; +} + +struct SliceRef<'a, T: ?Sized> { + _x: &'a T, +} + +impl<'a, T: ?Sized, SR: LockReference> IntoIterator for SliceRef<'a, T> +where + &'a T: IntoIterator, +{ + type Item = SR::Ref<'a>; + type IntoIter = std::iter::Map<<&'a T as IntoIterator>::IntoIter, + for<'c> fn(&'c SR) -> SR::Ref<'c>>; + fn into_iter(self) -> Self::IntoIter { + loop {} + } +} + +impl LockReference for () { + type Ref<'a> = (); +} + +fn locked() -> SliceRef<'static, [()]> { + loop {} +} + +fn main() { + let _ = locked().into_iter(); +} diff --git a/tests/crashes/131406.rs b/tests/crashes/131406.rs new file mode 100644 index 0000000000000..ea642f949280d --- /dev/null +++ b/tests/crashes/131406.rs @@ -0,0 +1,12 @@ +//@ known-bug: #131406 + +trait Owner { + const C: u32 = N; +} + +impl Owner for () {} +fn take0(_: impl Owner = { N }>) {} + +fn main() { + take0::<128>(()); +} From e08dc0491a9069681b123bbe27eb388a7861a351 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Le=C3=B3n=20Orell=20Valerian=20Liehr?= Date: Wed, 25 Sep 2024 13:17:58 +0200 Subject: [PATCH 2062/2194] Library: Rename "object safe" to "dyn compatible" --- library/core/src/cell.rs | 6 +++--- library/core/src/error.rs | 21 +++++++++++---------- library/core/src/iter/traits/iterator.rs | 2 +- library/core/src/marker.rs | 3 ++- library/core/src/ops/unsize.rs | 8 +++++--- library/core/tests/hash/mod.rs | 2 +- library/std/src/keyword_docs.rs | 4 +++- 7 files changed, 26 insertions(+), 20 deletions(-) diff --git a/library/core/src/cell.rs b/library/core/src/cell.rs index a3e91bc067090..df32c83f6457d 100644 --- a/library/core/src/cell.rs +++ b/library/core/src/cell.rs @@ -661,7 +661,7 @@ impl Cell { impl, U> CoerceUnsized> for Cell {} // Allow types that wrap `Cell` to also implement `DispatchFromDyn` -// and become object safe method receivers. +// and become dyn-compatible method receivers. // Note that currently `Cell` itself cannot be a method receiver // because it does not implement Deref. // In other words: @@ -2236,7 +2236,7 @@ impl From for UnsafeCell { impl, U> CoerceUnsized> for UnsafeCell {} // Allow types that wrap `UnsafeCell` to also implement `DispatchFromDyn` -// and become object safe method receivers. +// and become dyn-compatible method receivers. // Note that currently `UnsafeCell` itself cannot be a method receiver // because it does not implement Deref. // In other words: @@ -2379,7 +2379,7 @@ impl From for SyncUnsafeCell { impl, U> CoerceUnsized> for SyncUnsafeCell {} // Allow types that wrap `SyncUnsafeCell` to also implement `DispatchFromDyn` -// and become object safe method receivers. +// and become dyn-compatible method receivers. // Note that currently `SyncUnsafeCell` itself cannot be a method receiver // because it does not implement Deref. // In other words: diff --git a/library/core/src/error.rs b/library/core/src/error.rs index cac00b37d1fa7..95a39cc3aed38 100644 --- a/library/core/src/error.rs +++ b/library/core/src/error.rs @@ -335,16 +335,17 @@ impl dyn Error { #[unstable(feature = "error_iter", issue = "58520")] #[inline] pub fn sources(&self) -> Source<'_> { - // You may think this method would be better in the Error trait, and you'd be right. - // Unfortunately that doesn't work, not because of the object safety rules but because we - // save a reference to self in Sources below as a trait object. If this method was - // declared in Error, then self would have the type &T where T is some concrete type which - // implements Error. We would need to coerce self to have type &dyn Error, but that requires - // that Self has a known size (i.e., Self: Sized). We can't put that bound on Error - // since that would forbid Error trait objects, and we can't put that bound on the method - // because that means the method can't be called on trait objects (we'd also need the - // 'static bound, but that isn't allowed because methods with bounds on Self other than - // Sized are not object-safe). Requiring an Unsize bound is not backwards compatible. + // You may think this method would be better in the `Error` trait, and you'd be right. + // Unfortunately that doesn't work, not because of the dyn-incompatibility rules but + // because we save a reference to `self` in `Source`s below as a trait object. + // If this method was declared in `Error`, then `self` would have the type `&T` where + // `T` is some concrete type which implements `Error`. We would need to coerce `self` + // to have type `&dyn Error`, but that requires that `Self` has a known size + // (i.e., `Self: Sized`). We can't put that bound on `Error` since that would forbid + // `Error` trait objects, and we can't put that bound on the method because that means + // the method can't be called on trait objects (we'd also need the `'static` bound, + // but that isn't allowed because methods with bounds on `Self` other than `Sized` are + // dyn-incompatible). Requiring an `Unsize` bound is not backwards compatible. Source { current: Some(self) } } diff --git a/library/core/src/iter/traits/iterator.rs b/library/core/src/iter/traits/iterator.rs index 7963459bfb5d9..302720eddef22 100644 --- a/library/core/src/iter/traits/iterator.rs +++ b/library/core/src/iter/traits/iterator.rs @@ -9,7 +9,7 @@ use crate::cmp::{self, Ordering}; use crate::num::NonZero; use crate::ops::{ChangeOutputType, ControlFlow, FromResidual, Residual, Try}; -fn _assert_is_object_safe(_: &dyn Iterator) {} +fn _assert_is_dyn_compatible(_: &dyn Iterator) {} /// A trait for dealing with iterators. /// diff --git a/library/core/src/marker.rs b/library/core/src/marker.rs index fd41b80cdbd0a..aed6be4c6277b 100644 --- a/library/core/src/marker.rs +++ b/library/core/src/marker.rs @@ -158,7 +158,7 @@ pub trait Sized { /// - Arrays `[T; N]` implement `Unsize<[T]>`. /// - A type implements `Unsize` if all of these conditions are met: /// - The type implements `Trait`. -/// - `Trait` is object safe. +/// - `Trait` is dyn-compatible[^1]. /// - The type is sized. /// - The type outlives `'a`. /// - Structs `Foo<..., T1, ..., Tn, ...>` implement `Unsize>` @@ -178,6 +178,7 @@ pub trait Sized { /// [`Rc`]: ../../std/rc/struct.Rc.html /// [RFC982]: https://github.com/rust-lang/rfcs/blob/master/text/0982-dst-coercion.md /// [nomicon-coerce]: ../../nomicon/coercions.html +/// [^1]: Formerly known as *object safe*. #[unstable(feature = "unsize", issue = "18598")] #[lang = "unsize"] #[rustc_deny_explicit_impl(implement_via_object = false)] diff --git a/library/core/src/ops/unsize.rs b/library/core/src/ops/unsize.rs index b51f12580ea4f..d2a07197f6f6a 100644 --- a/library/core/src/ops/unsize.rs +++ b/library/core/src/ops/unsize.rs @@ -68,8 +68,8 @@ impl, U: ?Sized> CoerceUnsized<*const U> for *mut T {} #[unstable(feature = "coerce_unsized", issue = "18598")] impl, U: ?Sized> CoerceUnsized<*const U> for *const T {} -/// `DispatchFromDyn` is used in the implementation of object safety checks (specifically allowing -/// arbitrary self types), to guarantee that a method's receiver type can be dispatched on. +/// `DispatchFromDyn` is used in the implementation of dyn-compatibility[^1] checks (specifically +/// allowing arbitrary self types), to guarantee that a method's receiver type can be dispatched on. /// /// Note: `DispatchFromDyn` was briefly named `CoerceSized` (and had a slightly different /// interpretation). @@ -80,7 +80,7 @@ impl, U: ?Sized> CoerceUnsized<*const U> for *const T {} /// type). The compiler must generate an implicit conversion from the trait object/wide pointer to /// the concrete reference/narrow pointer. Implementing `DispatchFromDyn` indicates that that /// conversion is allowed and thus that the type implementing `DispatchFromDyn` is safe to use as -/// the self type in an object-safe method. (in the above example, the compiler will require +/// the self type in an dyn-compatible method. (in the above example, the compiler will require /// `DispatchFromDyn` is implemented for `&'a U`). /// /// `DispatchFromDyn` does not specify the conversion from wide pointer to narrow pointer; the @@ -112,6 +112,8 @@ impl, U: ?Sized> CoerceUnsized<*const U> for *const T {} /// T: Unsize, /// {} /// ``` +/// +/// [^1]: Formerly known as *object safety*. #[unstable(feature = "dispatch_from_dyn", issue = "none")] #[lang = "dispatch_from_dyn"] pub trait DispatchFromDyn { diff --git a/library/core/tests/hash/mod.rs b/library/core/tests/hash/mod.rs index 03826fc4c92cd..bf91e9e5df0e2 100644 --- a/library/core/tests/hash/mod.rs +++ b/library/core/tests/hash/mod.rs @@ -164,7 +164,7 @@ fn test_indirect_hasher() { } #[test] -fn test_build_hasher_object_safe() { +fn test_build_hasher_dyn_compatible() { use std::hash::{DefaultHasher, RandomState}; let _: &dyn BuildHasher = &RandomState::new(); diff --git a/library/std/src/keyword_docs.rs b/library/std/src/keyword_docs.rs index 9f4d244b5479e..453b2708daab9 100644 --- a/library/std/src/keyword_docs.rs +++ b/library/std/src/keyword_docs.rs @@ -2349,12 +2349,13 @@ mod async_keyword {} /// [`async`]: ../std/keyword.async.html mod await_keyword {} +// FIXME(dyn_compat_renaming): Update URL and link text. #[doc(keyword = "dyn")] // /// `dyn` is a prefix of a [trait object]'s type. /// /// The `dyn` keyword is used to highlight that calls to methods on the associated `Trait` -/// are [dynamically dispatched]. To use the trait this way, it must be 'object safe'. +/// are [dynamically dispatched]. To use the trait this way, it must be 'dyn-compatible'[^1]. /// /// Unlike generic parameters or `impl Trait`, the compiler does not know the concrete type that /// is being passed. That is, the type has been [erased]. @@ -2382,6 +2383,7 @@ mod await_keyword {} /// [ref-trait-obj]: ../reference/types/trait-object.html /// [ref-obj-safety]: ../reference/items/traits.html#object-safety /// [erased]: https://en.wikipedia.org/wiki/Type_erasure +/// [^1]: Formerly known as 'object safe'. mod dyn_keyword {} #[doc(keyword = "union")] From 12ce6f656428b420b8cd01f56d85dc2c5955492c Mon Sep 17 00:00:00 2001 From: Alyssa Haroldsen Date: Wed, 9 Oct 2024 10:28:16 -0700 Subject: [PATCH 2063/2194] Fix typo in E0793 --- compiler/rustc_error_codes/src/error_codes/E0793.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_error_codes/src/error_codes/E0793.md b/compiler/rustc_error_codes/src/error_codes/E0793.md index b2e51e24e141f..ccd1b43bd194a 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0793.md +++ b/compiler/rustc_error_codes/src/error_codes/E0793.md @@ -1,4 +1,4 @@ -An unaligned references to a field of a [packed] struct got created. +An unaligned reference to a field of a [packed] struct got created. Erroneous code example: From 16844e24850700386b6a7fc482738400a2f115c9 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 8 Oct 2024 20:53:11 +0200 Subject: [PATCH 2064/2194] Fix methods alignment on mobile --- src/librustdoc/html/static/css/rustdoc.css | 2 +- tests/rustdoc-gui/notable-trait.goml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css index 5f6f3c65c7ff7..3fee73d6e5d18 100644 --- a/src/librustdoc/html/static/css/rustdoc.css +++ b/src/librustdoc/html/static/css/rustdoc.css @@ -2435,7 +2435,7 @@ in src-script.js and main.js } /* Position of the "[-]" element. */ - details.toggle:not(.top-doc) > summary { + details.toggle:not(.top-doc) > summary, .impl-items > section { margin-left: 10px; } .impl-items > details.toggle > summary:not(.hideme)::before, diff --git a/tests/rustdoc-gui/notable-trait.goml b/tests/rustdoc-gui/notable-trait.goml index b8fa26b17f6b6..43a7e8a8f517c 100644 --- a/tests/rustdoc-gui/notable-trait.goml +++ b/tests/rustdoc-gui/notable-trait.goml @@ -85,8 +85,8 @@ call-function: ("check-notable-tooltip-position", { // Checking on mobile now. set-window-size: (650, 600) call-function: ("check-notable-tooltip-position-complete", { - "x": 15, - "i_x": 293, + "x": 25, + "i_x": 303, "popover_x": 0, }) From 12d5f0aa2cdd3d53d3d273c360773cd5a1a3c821 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 8 Oct 2024 21:14:13 +0200 Subject: [PATCH 2065/2194] Add GUI regression test for methods left margin on mobile --- tests/rustdoc-gui/methods-left-margin.goml | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 tests/rustdoc-gui/methods-left-margin.goml diff --git a/tests/rustdoc-gui/methods-left-margin.goml b/tests/rustdoc-gui/methods-left-margin.goml new file mode 100644 index 0000000000000..af88bbaefc523 --- /dev/null +++ b/tests/rustdoc-gui/methods-left-margin.goml @@ -0,0 +1,17 @@ +// This test is to ensure that methods are correctly aligned on the left side. + +go-to: "file://" + |DOC_PATH| + "/test_docs/struct.Foo.html" + +// First we ensure that we have methods with and without documentation. +assert: ".impl-items > details.method-toggle > summary > section.method" +assert: ".impl-items > section.method" + +// Checking on desktop. +set-window-size: (900, 600) +store-position: (".impl-items section.method", {"x": x}) +assert-position: (".impl-items section.method", {"x": |x|}, ALL) + +// Checking on mobile. +set-window-size: (600, 600) +store-position: (".impl-items section.method", {"x": x}) +assert-position: (".impl-items section.method", {"x": |x|}, ALL) From 5e6033ea8b25d42a56eca04eba5bb33a530bc381 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 9 Oct 2024 21:23:20 +0200 Subject: [PATCH 2066/2194] Strengthen some GUI tests --- tests/rustdoc-gui/methods-left-margin.goml | 2 ++ tests/rustdoc-gui/notable-trait.goml | 1 + 2 files changed, 3 insertions(+) diff --git a/tests/rustdoc-gui/methods-left-margin.goml b/tests/rustdoc-gui/methods-left-margin.goml index af88bbaefc523..1003cec33f952 100644 --- a/tests/rustdoc-gui/methods-left-margin.goml +++ b/tests/rustdoc-gui/methods-left-margin.goml @@ -8,10 +8,12 @@ assert: ".impl-items > section.method" // Checking on desktop. set-window-size: (900, 600) +wait-for-size: ("body", {"width": 900}) store-position: (".impl-items section.method", {"x": x}) assert-position: (".impl-items section.method", {"x": |x|}, ALL) // Checking on mobile. set-window-size: (600, 600) +wait-for-size: ("body", {"width": 600}) store-position: (".impl-items section.method", {"x": x}) assert-position: (".impl-items section.method", {"x": |x|}, ALL) diff --git a/tests/rustdoc-gui/notable-trait.goml b/tests/rustdoc-gui/notable-trait.goml index 43a7e8a8f517c..e02974e60829a 100644 --- a/tests/rustdoc-gui/notable-trait.goml +++ b/tests/rustdoc-gui/notable-trait.goml @@ -84,6 +84,7 @@ call-function: ("check-notable-tooltip-position", { // Checking on mobile now. set-window-size: (650, 600) +wait-for-size: ("body", {"width": 650}) call-function: ("check-notable-tooltip-position-complete", { "x": 25, "i_x": 303, From 7b52e6bc479bcefc531fde4947c00cc725d8813d Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Wed, 9 Oct 2024 12:43:23 -0700 Subject: [PATCH 2067/2194] Mention allocation errors for `open_buffered` --- library/std/src/fs.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/library/std/src/fs.rs b/library/std/src/fs.rs index 124ef121b186c..675140ff18f5f 100644 --- a/library/std/src/fs.rs +++ b/library/std/src/fs.rs @@ -394,7 +394,8 @@ impl File { /// /// # Errors /// - /// This function will return an error if `path` does not already exist. + /// This function will return an error if `path` does not already exist, + /// or if memory allocation fails for the new buffer. /// Other errors may also be returned according to [`OpenOptions::open`]. /// /// # Examples From 118f7a6b88a2627aba161d7a6e695350329d20e7 Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Wed, 9 Oct 2024 22:11:37 +0300 Subject: [PATCH 2068/2194] ignore `ci_rustc_if_unchanged_logic` test Signed-off-by: onur-ozkan --- src/bootstrap/src/core/builder/tests.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/bootstrap/src/core/builder/tests.rs b/src/bootstrap/src/core/builder/tests.rs index ab36193f8b614..4ab1ef1ad0ffd 100644 --- a/src/bootstrap/src/core/builder/tests.rs +++ b/src/bootstrap/src/core/builder/tests.rs @@ -214,6 +214,8 @@ fn alias_and_path_for_library() { assert_eq!(first(cache.all::()), &[doc_std!(A => A, stage = 0)]); } +// FIXME: This is failing in various runners in merge CI. +#[ignore] #[test] fn ci_rustc_if_unchanged_logic() { let config = Config::parse_inner( From 9c9d3c85bbed439d4b3d8eb2354c4d0e62d7d315 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Wed, 9 Oct 2024 09:45:59 -0700 Subject: [PATCH 2069/2194] Update wasm-component-ld to 0.5.10 This pulls in a bug fix relative to the 0.5.9 release which was updated-to recently. --- Cargo.lock | 48 +++++++++++++------------- src/tools/wasm-component-ld/Cargo.toml | 2 +- 2 files changed, 25 insertions(+), 25 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 502920350d5c5..a11144f1cf422 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5798,16 +5798,16 @@ checksum = "c62a0a307cb4a311d3a07867860911ca130c3494e8c2719593806c08bc5d0484" [[package]] name = "wasm-component-ld" -version = "0.5.9" +version = "0.5.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fde17bc96539700198e12516230c76095cc215c84ef39ad206e1af3f84243e0f" +checksum = "4d4aa6bd7fbe7cffbed29fe3e236fda74419def1bdef6f80f989ec51137edf44" dependencies = [ "anyhow", "clap", "lexopt", "tempfile", "wasi-preview1-component-adapter-provider", - "wasmparser 0.218.0", + "wasmparser 0.219.0", "wat", "wit-component", "wit-parser", @@ -5831,19 +5831,19 @@ dependencies = [ [[package]] name = "wasm-encoder" -version = "0.218.0" +version = "0.219.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22b896fa8ceb71091ace9bcb81e853f54043183a1c9667cf93422c40252ffa0a" +checksum = "e2b1b95711b3ad655656a341e301cc64e33cbee94de9a99a1c5a2ab88efab79d" dependencies = [ "leb128", - "wasmparser 0.218.0", + "wasmparser 0.219.0", ] [[package]] name = "wasm-metadata" -version = "0.218.0" +version = "0.219.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa5eeb071abe8a2132fdd5565dabffee70775ee8c24fc7e300ac43f51f4a8a91" +checksum = "96132fe00dd17d092d2be289eeed5a0a68ad3cf30b68e8875bc953b96f55f0be" dependencies = [ "anyhow", "indexmap", @@ -5851,8 +5851,8 @@ dependencies = [ "serde_derive", "serde_json", "spdx", - "wasm-encoder 0.218.0", - "wasmparser 0.218.0", + "wasm-encoder 0.219.0", + "wasmparser 0.219.0", ] [[package]] @@ -5867,9 +5867,9 @@ dependencies = [ [[package]] name = "wasmparser" -version = "0.218.0" +version = "0.219.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b09e46c7fceceaa72b2dd1a8a137ea7fd8f93dfaa69806010a709918e496c5dc" +checksum = "324b4e56d24439495b88cd81439dad5e97f3c7b1eedc3c7e10455ed1e045e9a2" dependencies = [ "ahash", "bitflags 2.6.0", @@ -5881,22 +5881,22 @@ dependencies = [ [[package]] name = "wast" -version = "218.0.0" +version = "219.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a53cd1f0fa505df97557e36a58bddb8296e2fcdcd089529545ebfdb18a1b9d7" +checksum = "06880ecb25662bc21db6a83f4fcc27c41f71fbcba4f1980b650c88ada92728e1" dependencies = [ "bumpalo", "leb128", "memchr", "unicode-width", - "wasm-encoder 0.218.0", + "wasm-encoder 0.219.0", ] [[package]] name = "wat" -version = "1.218.0" +version = "1.219.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f87f8e14e776762e07927c27c2054d2cf678aab9aae2d431a79b3e31e4dd391" +checksum = "11e56dbf9fc89111b0d97c91e683d7895b1a6e5633a729f2ccad2303724005b6" dependencies = [ "wast", ] @@ -6173,9 +6173,9 @@ dependencies = [ [[package]] name = "wit-component" -version = "0.218.0" +version = "0.219.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa53aa7e6bf2b3e8ccaffbcc963fbdb672a603dc0af393a481b6cec24c266406" +checksum = "99a76111c20444a814019de20499d30940ecd219b9512ee296f034a5edb18a2d" dependencies = [ "anyhow", "bitflags 2.6.0", @@ -6184,17 +6184,17 @@ dependencies = [ "serde", "serde_derive", "serde_json", - "wasm-encoder 0.218.0", + "wasm-encoder 0.219.0", "wasm-metadata", - "wasmparser 0.218.0", + "wasmparser 0.219.0", "wit-parser", ] [[package]] name = "wit-parser" -version = "0.218.0" +version = "0.219.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d3d1066ab761b115f97fef2b191090faabcb0f37b555b758d3caf42d4ed9e55" +checksum = "23102e180c0c464f36e293d31a27b524e3ece930d7b5527d2f33f9d2c963de64" dependencies = [ "anyhow", "id-arena", @@ -6205,7 +6205,7 @@ dependencies = [ "serde_derive", "serde_json", "unicode-xid", - "wasmparser 0.218.0", + "wasmparser 0.219.0", ] [[package]] diff --git a/src/tools/wasm-component-ld/Cargo.toml b/src/tools/wasm-component-ld/Cargo.toml index 49f4e59650e71..acdb1aa1ab7d9 100644 --- a/src/tools/wasm-component-ld/Cargo.toml +++ b/src/tools/wasm-component-ld/Cargo.toml @@ -10,4 +10,4 @@ name = "wasm-component-ld" path = "src/main.rs" [dependencies] -wasm-component-ld = "0.5.9" +wasm-component-ld = "0.5.10" From 6524acf04bd10c1459bba2db18f1a34100c0b241 Mon Sep 17 00:00:00 2001 From: ltdk Date: Tue, 28 May 2024 14:27:25 -0400 Subject: [PATCH 2070/2194] Optimize escape_ascii --- library/core/src/escape.rs | 114 ++++++++++++++++++++++++++++-------- library/core/tests/ascii.rs | 22 ++++++- 2 files changed, 110 insertions(+), 26 deletions(-) diff --git a/library/core/src/escape.rs b/library/core/src/escape.rs index b213cc2b9167c..0685f525dca83 100644 --- a/library/core/src/escape.rs +++ b/library/core/src/escape.rs @@ -18,38 +18,106 @@ const fn backslash(a: ascii::Char) -> ([ascii::Char; N], Range(byte: u8) -> ([ascii::Char; N], Range) { + const { assert!(N >= 4) }; + + let mut output = [ascii::Char::Null; N]; + + let hi = HEX_DIGITS[(byte >> 4) as usize]; + let lo = HEX_DIGITS[(byte & 0xf) as usize]; + + output[0] = ascii::Char::ReverseSolidus; + output[1] = ascii::Char::SmallX; + output[2] = hi; + output[3] = lo; + + (output, 0..4) +} + +#[inline] +const fn verbatim(a: ascii::Char) -> ([ascii::Char; N], Range) { + const { assert!(N >= 1) }; + + let mut output = [ascii::Char::Null; N]; + + output[0] = a; + + (output, 0..1) +} + /// Escapes an ASCII character. /// /// Returns a buffer and the length of the escaped representation. const fn escape_ascii(byte: u8) -> ([ascii::Char; N], Range) { const { assert!(N >= 4) }; - match byte { - b'\t' => backslash(ascii::Char::SmallT), - b'\r' => backslash(ascii::Char::SmallR), - b'\n' => backslash(ascii::Char::SmallN), - b'\\' => backslash(ascii::Char::ReverseSolidus), - b'\'' => backslash(ascii::Char::Apostrophe), - b'\"' => backslash(ascii::Char::QuotationMark), - byte => { - let mut output = [ascii::Char::Null; N]; - - if let Some(c) = byte.as_ascii() - && !byte.is_ascii_control() - { - output[0] = c; - (output, 0..1) - } else { - let hi = HEX_DIGITS[(byte >> 4) as usize]; - let lo = HEX_DIGITS[(byte & 0xf) as usize]; + #[cfg(feature = "optimize_for_size")] + { + match byte { + b'\t' => backslash(ascii::Char::SmallT), + b'\r' => backslash(ascii::Char::SmallR), + b'\n' => backslash(ascii::Char::SmallN), + b'\\' => backslash(ascii::Char::ReverseSolidus), + b'\'' => backslash(ascii::Char::Apostrophe), + b'"' => backslash(ascii::Char::QuotationMark), + 0x00..=0x1F | 0x7F => hex_escape(byte), + _ => match ascii::Char::from_u8(byte) { + Some(a) => verbatim(a), + None => hex_escape(byte), + }, + } + } + + #[cfg(not(feature = "optimize_for_size"))] + { + /// Lookup table helps us determine how to display character. + /// + /// Since ASCII characters will always be 7 bits, we can exploit this to store the 8th bit to + /// indicate whether the result is escaped or unescaped. + /// + /// We additionally use 0x80 (escaped NUL character) to indicate hex-escaped bytes, since + /// escaped NUL will not occur. + const LOOKUP: [u8; 256] = { + let mut arr = [0; 256]; + let mut idx = 0; + while idx <= 255 { + arr[idx] = match idx as u8 { + // use 8th bit to indicate escaped + b'\t' => 0x80 | b't', + b'\r' => 0x80 | b'r', + b'\n' => 0x80 | b'n', + b'\\' => 0x80 | b'\\', + b'\'' => 0x80 | b'\'', + b'"' => 0x80 | b'"', + + // use NUL to indicate hex-escaped + 0x00..=0x1F | 0x7F..=0xFF => 0x80 | b'\0', + + idx => idx, + }; + idx += 1; + } + arr + }; - output[0] = ascii::Char::ReverseSolidus; - output[1] = ascii::Char::SmallX; - output[2] = hi; - output[3] = lo; + let lookup = LOOKUP[byte as usize]; - (output, 0..4) + // 8th bit indicates escape + let lookup_escaped = lookup & 0x80 != 0; + + // SAFETY: We explicitly mask out the eighth bit to get a 7-bit ASCII character. + let lookup_ascii = unsafe { ascii::Char::from_u8_unchecked(lookup & 0x7F) }; + + if lookup_escaped { + // NUL indicates hex-escaped + if matches!(lookup_ascii, ascii::Char::Null) { + hex_escape(byte) + } else { + backslash(lookup_ascii) } + } else { + verbatim(lookup_ascii) } } } diff --git a/library/core/tests/ascii.rs b/library/core/tests/ascii.rs index 3d3f8ac10c603..ce09ee507f11f 100644 --- a/library/core/tests/ascii.rs +++ b/library/core/tests/ascii.rs @@ -481,9 +481,25 @@ fn ascii_ctype_const() { } #[test] -fn test_ascii_display() { - assert_eq!(b"foo'bar".escape_ascii().to_string(), r#"foo\'bar"#); - assert_eq!(b"\0\xff".escape_ascii().to_string(), r#"\x00\xff"#); +fn test_escape_ascii() { + let mut buf = [0u8; 0x1F + 7]; // 0..=0x1F plus two quotes, slash, \x7F, \x80, \xFF + for idx in 0..=0x1F { + buf[idx] = idx as u8; + } + buf[0x20] = b'\''; + buf[0x21] = b'"'; + buf[0x22] = b'\\'; + buf[0x23] = 0x7F; + buf[0x24] = 0x80; + buf[0x25] = 0xff; + assert_eq!( + buf.escape_ascii().to_string(), + r#"\x00\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x0c\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\'\"\\\x7f\x80\xff"# + ); +} + +#[test] +fn test_escape_ascii_iter() { let mut it = b"\0fastpath\xffremainder\xff".escape_ascii(); let _ = it.advance_by(4); let _ = it.advance_back_by(4); From 62b24ea7c53aec6f8176fed05d0acee926b76bdb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Le=C3=B3n=20Orell=20Valerian=20Liehr?= Date: Wed, 9 Oct 2024 20:19:36 +0200 Subject: [PATCH 2071/2194] Compiler: Replace remaining occurrences of "object safe" with "dyn compatible" --- .../src/traits/dyn_compatibility.rs | 20 ++++++++----------- 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs b/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs index d5d7681a8d608..191eda4d34752 100644 --- a/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs +++ b/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs @@ -1,12 +1,8 @@ -//! "Object safety" refers to the ability for a trait to be converted -//! to an object. In general, traits may only be converted to an -//! object if all of their methods meet certain criteria. In particular, -//! they must: +//! "Dyn-compatibility"[^1] refers to the ability for a trait to be converted +//! to a trait object. In general, traits may only be converted to a trait +//! object if certain criteria are met. //! -//! - have a suitable receiver from which we can extract a vtable and coerce to a "thin" version -//! that doesn't contain the vtable; -//! - not reference the erased type `Self` except for in this receiver; -//! - not have generic type parameters. +//! [^1]: Formerly known as "object safety". use std::iter; use std::ops::ControlFlow; @@ -506,8 +502,8 @@ fn virtual_call_violations_for_method<'tcx>( /// This code checks that `receiver_is_dispatchable` is correctly implemented. /// -/// This check is outlined from the object safety check to avoid cycles with -/// layout computation, which relies on knowing whether methods are object safe. +/// This check is outlined from the dyn-compatibility check to avoid cycles with +/// layout computation, which relies on knowing whether methods are dyn-compatible. fn check_receiver_correct<'tcx>(tcx: TyCtxt<'tcx>, trait_def_id: DefId, method: ty::AssocItem) { if !is_vtable_safe_method(tcx, trait_def_id, method) { return; @@ -644,7 +640,7 @@ fn object_ty_for_trait<'tcx>( /// a pointer. /// /// In practice, we cannot use `dyn Trait` explicitly in the obligation because it would result -/// in a new check that `Trait` is object safe, creating a cycle (until object_safe_for_dispatch +/// in a new check that `Trait` is dyn-compatible, creating a cycle (until object_safe_for_dispatch /// is stabilized, see tracking issue ). /// Instead, we fudge a little by introducing a new type parameter `U` such that /// `Self: Unsize` and `U: Trait + ?Sized`, and use `U` in place of `dyn Trait`. @@ -865,7 +861,7 @@ impl<'tcx> TypeVisitor> for IllegalSelfTypeVisitor<'tcx> { } fn visit_const(&mut self, ct: ty::Const<'tcx>) -> Self::Result { - // Constants can only influence object safety if they are generic and reference `Self`. + // Constants can only influence dyn-compatibility if they are generic and reference `Self`. // This is only possible for unevaluated constants, so we walk these here. self.tcx.expand_abstract_consts(ct).super_visit_with(self) } From 2e7a52b22fe222316a48093547f6312252c20f0f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Le=C3=B3n=20Orell=20Valerian=20Liehr?= Date: Wed, 9 Oct 2024 18:37:30 +0200 Subject: [PATCH 2072/2194] Rename feature object_safe_for_dispatch to dyn_compatible_for_dispatch --- compiler/rustc_feature/src/removed.rs | 4 ++ compiler/rustc_feature/src/unstable.rs | 15 ++-- .../rustc_hir_analysis/src/coherence/mod.rs | 2 +- compiler/rustc_span/src/symbol.rs | 1 + .../src/traits/dyn_compatibility.rs | 6 +- .../src/traits/select/candidate_assembly.rs | 2 +- .../rustc_trait_selection/src/traits/wf.rs | 2 +- tests/crashes/120241-2.rs | 2 +- tests/crashes/120241.rs | 2 +- tests/crashes/120482.rs | 2 +- tests/crashes/125512.rs | 2 +- tests/crashes/128176.rs | 2 +- tests/crashes/130521.rs | 2 +- .../coherence-unsafe-trait-object-impl.rs | 2 +- ...eature-gate-dyn_compatible_for_dispatch.rs | 41 +++++++++++ ...e-gate-dyn_compatible_for_dispatch.stderr} | 70 +++++++++---------- .../feature-gate-object_safe_for_dispatch.rs | 41 ----------- ...-bound.dyn_compatible_for_dispatch.stderr} | 0 .../ui/kindck/kindck-inherited-copy-bound.rs | 8 +-- ...consts.dyn_compatible_for_dispatch.stderr} | 0 .../object-safety-associated-consts.rs | 4 +- ...nerics.dyn_compatible_for_dispatch.stderr} | 0 .../object-safety/object-safety-generics.rs | 8 +-- ...s-Self.dyn_compatible_for_dispatch.stderr} | 0 .../object-safety-mentions-Self.rs | 4 +- ...static.dyn_compatible_for_dispatch.stderr} | 0 .../object-safety/object-safety-no-static.rs | 4 +- ...ized-2.dyn_compatible_for_dispatch.stderr} | 0 .../ui/object-safety/object-safety-sized-2.rs | 4 +- ...-sized.dyn_compatible_for_dispatch.stderr} | 0 tests/ui/object-safety/object-safety-sized.rs | 4 +- .../downcast-unsafe-trait-objects.rs | 2 +- ...al-self-impl-for-unsafe-obj.current.stderr | 0 ...anual-self-impl-for-unsafe-obj.next.stderr | 0 .../manual-self-impl-for-unsafe-obj.rs | 2 +- .../static-dispatch-unsafe-object.rs | 2 +- ...t-safe.dyn_compatible_for_dispatch.stderr} | 0 .../arbitrary-self-types-not-object-safe.rs | 6 +- tests/ui/suggestions/issue-104328.rs | 2 +- .../ui/wf/wf-convert-unsafe-trait-obj-box.rs | 2 +- tests/ui/wf/wf-convert-unsafe-trait-obj.rs | 2 +- tests/ui/wf/wf-unsafe-trait-obj-match.rs | 2 +- 42 files changed, 130 insertions(+), 124 deletions(-) create mode 100644 tests/ui/feature-gates/feature-gate-dyn_compatible_for_dispatch.rs rename tests/ui/feature-gates/{feature-gate-object_safe_for_dispatch.stderr => feature-gate-dyn_compatible_for_dispatch.stderr} (50%) delete mode 100644 tests/ui/feature-gates/feature-gate-object_safe_for_dispatch.rs rename tests/ui/kindck/{kindck-inherited-copy-bound.object_safe_for_dispatch.stderr => kindck-inherited-copy-bound.dyn_compatible_for_dispatch.stderr} (100%) rename tests/ui/object-safety/{object-safety-associated-consts.object_safe_for_dispatch.stderr => object-safety-associated-consts.dyn_compatible_for_dispatch.stderr} (100%) rename tests/ui/object-safety/{object-safety-generics.object_safe_for_dispatch.stderr => object-safety-generics.dyn_compatible_for_dispatch.stderr} (100%) rename tests/ui/object-safety/{object-safety-mentions-Self.object_safe_for_dispatch.stderr => object-safety-mentions-Self.dyn_compatible_for_dispatch.stderr} (100%) rename tests/ui/object-safety/{object-safety-no-static.object_safe_for_dispatch.stderr => object-safety-no-static.dyn_compatible_for_dispatch.stderr} (100%) rename tests/ui/object-safety/{object-safety-sized-2.object_safe_for_dispatch.stderr => object-safety-sized-2.dyn_compatible_for_dispatch.stderr} (100%) rename tests/ui/object-safety/{object-safety-sized.object_safe_for_dispatch.stderr => object-safety-sized.dyn_compatible_for_dispatch.stderr} (100%) rename tests/ui/rfcs/{rfc-2027-object-safe-for-dispatch => rfc-2027-dyn-compatible-for-dispatch}/downcast-unsafe-trait-objects.rs (90%) rename tests/ui/rfcs/{rfc-2027-object-safe-for-dispatch => rfc-2027-dyn-compatible-for-dispatch}/manual-self-impl-for-unsafe-obj.current.stderr (100%) rename tests/ui/rfcs/{rfc-2027-object-safe-for-dispatch => rfc-2027-dyn-compatible-for-dispatch}/manual-self-impl-for-unsafe-obj.next.stderr (100%) rename tests/ui/rfcs/{rfc-2027-object-safe-for-dispatch => rfc-2027-dyn-compatible-for-dispatch}/manual-self-impl-for-unsafe-obj.rs (97%) rename tests/ui/rfcs/{rfc-2027-object-safe-for-dispatch => rfc-2027-dyn-compatible-for-dispatch}/static-dispatch-unsafe-object.rs (94%) rename tests/ui/self/{arbitrary-self-types-not-object-safe.object_safe_for_dispatch.stderr => arbitrary-self-types-not-object-safe.dyn_compatible_for_dispatch.stderr} (100%) diff --git a/compiler/rustc_feature/src/removed.rs b/compiler/rustc_feature/src/removed.rs index 0cd0963d4e328..c275ad31b87bf 100644 --- a/compiler/rustc_feature/src/removed.rs +++ b/compiler/rustc_feature/src/removed.rs @@ -154,6 +154,10 @@ declare_features! ( /// then removed. But there was no utility storing it separately, so now /// it's in this list. (removed, no_stack_check, "1.0.0", None, None), + /// Allows making `dyn Trait` well-formed even if `Trait` is not dyn-compatible (object safe). + /// Renamed to `dyn_compatible_for_dispatch`. + (removed, object_safe_for_dispatch, "CURRENT_RUSTC_VERSION", Some(43561), + Some("renamed to `dyn_compatible_for_dispatch`")), /// Allows using `#[on_unimplemented(..)]` on traits. /// (Moved to `rustc_attrs`.) (removed, on_unimplemented, "1.40.0", None, None), diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index c5530097e9606..110ffa75b0523 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -259,6 +259,14 @@ declare_features! ( (unstable, doc_notable_trait, "1.52.0", Some(45040)), /// Allows using the `may_dangle` attribute (RFC 1327). (unstable, dropck_eyepatch, "1.10.0", Some(34761)), + /// Allows making `dyn Trait` well-formed even if `Trait` is not dyn-compatible[^1]. + /// In that case, `dyn Trait: Trait` does not hold. Moreover, coercions and + /// casts in safe Rust to `dyn Trait` for such a `Trait` is also forbidden. + /// + /// Renamed from `object_safe_for_dispatch`. + /// + /// [^1]: Formerly known as "object safe". + (unstable, dyn_compatible_for_dispatch, "CURRENT_RUSTC_VERSION", Some(43561)), /// Allows using the `#[fundamental]` attribute. (unstable, fundamental, "1.0.0", Some(29635)), /// Allows using `#[link_name="llvm.*"]`. @@ -544,13 +552,6 @@ declare_features! ( (unstable, non_exhaustive_omitted_patterns_lint, "1.57.0", Some(89554)), /// Allows `for` binders in where-clauses (incomplete, non_lifetime_binders, "1.69.0", Some(108185)), - /// Allows making `dyn Trait` well-formed even if `Trait` is not dyn-compatible[^1]. - /// In that case, `dyn Trait: Trait` does not hold. Moreover, coercions and - /// casts in safe Rust to `dyn Trait` for such a `Trait` is also forbidden. - /// - /// [^1]: Formerly known as "object safe". - // FIXME(dyn_compat_renaming): Rename feature. - (unstable, object_safe_for_dispatch, "1.40.0", Some(43561)), /// Allows using enums in offset_of! (unstable, offset_of_enum, "1.75.0", Some(120141)), /// Allows using fields with slice type in offset_of! diff --git a/compiler/rustc_hir_analysis/src/coherence/mod.rs b/compiler/rustc_hir_analysis/src/coherence/mod.rs index 69d3642644709..eea5a16ac6fd3 100644 --- a/compiler/rustc_hir_analysis/src/coherence/mod.rs +++ b/compiler/rustc_hir_analysis/src/coherence/mod.rs @@ -199,7 +199,7 @@ fn check_object_overlap<'tcx>( for component_def_id in component_def_ids { if !tcx.is_dyn_compatible(component_def_id) { // FIXME(dyn_compat_renaming): Rename test and update comment. - // Without the 'object_safe_for_dispatch' feature this is an error + // Without the 'dyn_compatible_for_dispatch' feature this is an error // which will be reported by wfcheck. Ignore it here. // This is tested by `coherence-impl-trait-for-trait-object-safe.rs`. // With the feature enabled, the trait is not implemented automatically, diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index e8aa129c6cdbe..9e2df84830987 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -776,6 +776,7 @@ symbols! { dropck_eyepatch, dropck_parametricity, dylib, + dyn_compatible_for_dispatch, dyn_metadata, dyn_star, dyn_trait, diff --git a/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs b/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs index 191eda4d34752..45e7de942fb61 100644 --- a/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs +++ b/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs @@ -639,8 +639,8 @@ fn object_ty_for_trait<'tcx>( /// contained by the trait object, because the object that needs to be coerced is behind /// a pointer. /// -/// In practice, we cannot use `dyn Trait` explicitly in the obligation because it would result -/// in a new check that `Trait` is dyn-compatible, creating a cycle (until object_safe_for_dispatch +/// In practice, we cannot use `dyn Trait` explicitly in the obligation because it would result in +/// a new check that `Trait` is dyn-compatible, creating a cycle (until dyn_compatible_for_dispatch /// is stabilized, see tracking issue ). /// Instead, we fudge a little by introducing a new type parameter `U` such that /// `Self: Unsize` and `U: Trait + ?Sized`, and use `U` in place of `dyn Trait`. @@ -674,7 +674,7 @@ fn receiver_is_dispatchable<'tcx>( // the type `U` in the query // use a bogus type parameter to mimic a forall(U) query using u32::MAX for now. - // FIXME(mikeyhew) this is a total hack. Once object_safe_for_dispatch is stabilized, we can + // FIXME(mikeyhew) this is a total hack. Once dyn_compatible_for_dispatch is stabilized, we can // replace this with `dyn Trait` let unsized_self_ty: Ty<'tcx> = Ty::new_param(tcx, u32::MAX, Symbol::intern("RustaceansAreAwesome")); diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs index 084b61115dbcf..20adda6f0de29 100644 --- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs +++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs @@ -881,7 +881,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } if let Some(principal) = data.principal() { - if !self.infcx.tcx.features().object_safe_for_dispatch { + if !self.infcx.tcx.features().dyn_compatible_for_dispatch { principal.with_self_ty(self.tcx(), self_ty) } else if self.tcx().is_dyn_compatible(principal.def_id()) { principal.with_self_ty(self.tcx(), self_ty) diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs index 7e140ecfee08b..a849cdfe1257a 100644 --- a/compiler/rustc_trait_selection/src/traits/wf.rs +++ b/compiler/rustc_trait_selection/src/traits/wf.rs @@ -829,7 +829,7 @@ impl<'a, 'tcx> TypeVisitor> for WfPredicates<'a, 'tcx> { // obligations that don't refer to Self and // checking those - let defer_to_coercion = tcx.features().object_safe_for_dispatch; + let defer_to_coercion = tcx.features().dyn_compatible_for_dispatch; if !defer_to_coercion { if let Some(principal) = data.principal_def_id() { diff --git a/tests/crashes/120241-2.rs b/tests/crashes/120241-2.rs index 9c4a3a50293e3..91ec33620908e 100644 --- a/tests/crashes/120241-2.rs +++ b/tests/crashes/120241-2.rs @@ -1,6 +1,6 @@ //@ known-bug: #120241 //@ edition:2021 -#![feature(object_safe_for_dispatch)] +#![feature(dyn_compatible_for_dispatch)] #![feature(unsized_fn_params)] fn guard(_s: Copy) -> bool { diff --git a/tests/crashes/120241.rs b/tests/crashes/120241.rs index f18347a006cb6..b4fcb903714db 100644 --- a/tests/crashes/120241.rs +++ b/tests/crashes/120241.rs @@ -1,6 +1,6 @@ //@ known-bug: #120241 //@ edition:2021 -#![feature(object_safe_for_dispatch)] +#![feature(dyn_compatible_for_dispatch)] trait B { fn f(a: A) -> A; diff --git a/tests/crashes/120482.rs b/tests/crashes/120482.rs index 6cbc2009c5f63..a395855d796f1 100644 --- a/tests/crashes/120482.rs +++ b/tests/crashes/120482.rs @@ -1,6 +1,6 @@ //@ known-bug: #120482 //@ edition:2021 -#![feature(object_safe_for_dispatch)] +#![feature(dyn_compatible_for_dispatch)] trait B { fn bar(&self, x: &Self); diff --git a/tests/crashes/125512.rs b/tests/crashes/125512.rs index 1672b24a11437..37dbdf2f32f85 100644 --- a/tests/crashes/125512.rs +++ b/tests/crashes/125512.rs @@ -1,6 +1,6 @@ //@ known-bug: rust-lang/rust#125512 //@ edition:2021 -#![feature(object_safe_for_dispatch)] +#![feature(dyn_compatible_for_dispatch)] trait B { fn f(a: A) -> A; } diff --git a/tests/crashes/128176.rs b/tests/crashes/128176.rs index 70fada4f0fec2..970ad9ff2cd55 100644 --- a/tests/crashes/128176.rs +++ b/tests/crashes/128176.rs @@ -1,7 +1,7 @@ //@ known-bug: rust-lang/rust#128176 #![feature(generic_const_exprs)] -#![feature(object_safe_for_dispatch)] +#![feature(dyn_compatible_for_dispatch)] trait X { type Y; } diff --git a/tests/crashes/130521.rs b/tests/crashes/130521.rs index 2d30b658024e0..7c078ab579094 100644 --- a/tests/crashes/130521.rs +++ b/tests/crashes/130521.rs @@ -1,6 +1,6 @@ //@ known-bug: #130521 -#![feature(object_safe_for_dispatch)] +#![feature(dyn_compatible_for_dispatch)] struct Vtable(dyn Cap); trait Cap<'a> {} diff --git a/tests/ui/coherence/coherence-unsafe-trait-object-impl.rs b/tests/ui/coherence/coherence-unsafe-trait-object-impl.rs index 9859a226efd00..16baf0958a674 100644 --- a/tests/ui/coherence/coherence-unsafe-trait-object-impl.rs +++ b/tests/ui/coherence/coherence-unsafe-trait-object-impl.rs @@ -1,7 +1,7 @@ // Check that unsafe trait object do not implement themselves // automatically -#![feature(object_safe_for_dispatch)] +#![feature(dyn_compatible_for_dispatch)] trait Trait: Sized { fn call(&self); diff --git a/tests/ui/feature-gates/feature-gate-dyn_compatible_for_dispatch.rs b/tests/ui/feature-gates/feature-gate-dyn_compatible_for_dispatch.rs new file mode 100644 index 0000000000000..2dbba370a51e5 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-dyn_compatible_for_dispatch.rs @@ -0,0 +1,41 @@ +// Test that the use of the dyn-incompatible trait objects +// are gated by the `dyn_compatible_for_dispatch` feature gate. + +trait DynIncompatible1: Sized {} + +trait DynIncompatible2 { + fn static_fn() {} +} + +trait DynIncompatible3 { + fn foo(&self); +} + +trait DynIncompatible4 { + fn foo(&self, s: &Self); +} + +fn takes_non_object_safe_ref(obj: &dyn DynIncompatible1) { + //~^ ERROR E0038 +} + +fn return_non_object_safe_ref() -> &'static dyn DynIncompatible2 { + //~^ ERROR E0038 + loop {} +} + +fn takes_non_object_safe_box(obj: Box) { + //~^ ERROR E0038 +} + +fn return_non_object_safe_rc() -> std::rc::Rc { + //~^ ERROR E0038 + loop {} +} + +trait Trait {} + +impl Trait for dyn DynIncompatible1 {} +//~^ ERROR E0038 + +fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-object_safe_for_dispatch.stderr b/tests/ui/feature-gates/feature-gate-dyn_compatible_for_dispatch.stderr similarity index 50% rename from tests/ui/feature-gates/feature-gate-object_safe_for_dispatch.stderr rename to tests/ui/feature-gates/feature-gate-dyn_compatible_for_dispatch.stderr index fd5ed9c40f7ab..3cb73dfd52c68 100644 --- a/tests/ui/feature-gates/feature-gate-object_safe_for_dispatch.stderr +++ b/tests/ui/feature-gates/feature-gate-dyn_compatible_for_dispatch.stderr @@ -1,28 +1,28 @@ -error[E0038]: the trait `NonObjectSafe1` cannot be made into an object - --> $DIR/feature-gate-object_safe_for_dispatch.rs:18:39 +error[E0038]: the trait `DynIncompatible1` cannot be made into an object + --> $DIR/feature-gate-dyn_compatible_for_dispatch.rs:18:39 | -LL | fn takes_non_object_safe_ref(obj: &dyn NonObjectSafe1) { - | ^^^^^^^^^^^^^^^^^^ `NonObjectSafe1` cannot be made into an object +LL | fn takes_non_object_safe_ref(obj: &dyn DynIncompatible1) { + | ^^^^^^^^^^^^^^^^^^^^ `DynIncompatible1` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/feature-gate-object_safe_for_dispatch.rs:4:23 + --> $DIR/feature-gate-dyn_compatible_for_dispatch.rs:4:25 | -LL | trait NonObjectSafe1: Sized {} - | -------------- ^^^^^ ...because it requires `Self: Sized` +LL | trait DynIncompatible1: Sized {} + | ---------------- ^^^^^ ...because it requires `Self: Sized` | | | this trait cannot be made into an object... -error[E0038]: the trait `NonObjectSafe2` cannot be made into an object - --> $DIR/feature-gate-object_safe_for_dispatch.rs:22:45 +error[E0038]: the trait `DynIncompatible2` cannot be made into an object + --> $DIR/feature-gate-dyn_compatible_for_dispatch.rs:22:45 | -LL | fn return_non_object_safe_ref() -> &'static dyn NonObjectSafe2 { - | ^^^^^^^^^^^^^^^^^^ `NonObjectSafe2` cannot be made into an object +LL | fn return_non_object_safe_ref() -> &'static dyn DynIncompatible2 { + | ^^^^^^^^^^^^^^^^^^^^ `DynIncompatible2` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/feature-gate-object_safe_for_dispatch.rs:7:8 + --> $DIR/feature-gate-dyn_compatible_for_dispatch.rs:7:8 | -LL | trait NonObjectSafe2 { - | -------------- this trait cannot be made into an object... +LL | trait DynIncompatible2 { + | ---------------- this trait cannot be made into an object... LL | fn static_fn() {} | ^^^^^^^^^ ...because associated function `static_fn` has no `self` parameter help: consider turning `static_fn` into a method by giving it a `&self` argument @@ -34,47 +34,47 @@ help: alternatively, consider constraining `static_fn` so it does not apply to t LL | fn static_fn() where Self: Sized {} | +++++++++++++++++ -error[E0038]: the trait `NonObjectSafe3` cannot be made into an object - --> $DIR/feature-gate-object_safe_for_dispatch.rs:27:39 +error[E0038]: the trait `DynIncompatible3` cannot be made into an object + --> $DIR/feature-gate-dyn_compatible_for_dispatch.rs:27:39 | -LL | fn takes_non_object_safe_box(obj: Box) { - | ^^^^^^^^^^^^^^^^^^ `NonObjectSafe3` cannot be made into an object +LL | fn takes_non_object_safe_box(obj: Box) { + | ^^^^^^^^^^^^^^^^^^^^ `DynIncompatible3` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/feature-gate-object_safe_for_dispatch.rs:11:8 + --> $DIR/feature-gate-dyn_compatible_for_dispatch.rs:11:8 | -LL | trait NonObjectSafe3 { - | -------------- this trait cannot be made into an object... +LL | trait DynIncompatible3 { + | ---------------- this trait cannot be made into an object... LL | fn foo(&self); | ^^^ ...because method `foo` has generic type parameters = help: consider moving `foo` to another trait -error[E0038]: the trait `NonObjectSafe4` cannot be made into an object - --> $DIR/feature-gate-object_safe_for_dispatch.rs:31:47 +error[E0038]: the trait `DynIncompatible4` cannot be made into an object + --> $DIR/feature-gate-dyn_compatible_for_dispatch.rs:31:47 | -LL | fn return_non_object_safe_rc() -> std::rc::Rc { - | ^^^^^^^^^^^^^^^^^^ `NonObjectSafe4` cannot be made into an object +LL | fn return_non_object_safe_rc() -> std::rc::Rc { + | ^^^^^^^^^^^^^^^^^^^^ `DynIncompatible4` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/feature-gate-object_safe_for_dispatch.rs:15:22 + --> $DIR/feature-gate-dyn_compatible_for_dispatch.rs:15:22 | -LL | trait NonObjectSafe4 { - | -------------- this trait cannot be made into an object... +LL | trait DynIncompatible4 { + | ---------------- this trait cannot be made into an object... LL | fn foo(&self, s: &Self); | ^^^^^ ...because method `foo` references the `Self` type in this parameter = help: consider moving `foo` to another trait -error[E0038]: the trait `NonObjectSafe1` cannot be made into an object - --> $DIR/feature-gate-object_safe_for_dispatch.rs:38:16 +error[E0038]: the trait `DynIncompatible1` cannot be made into an object + --> $DIR/feature-gate-dyn_compatible_for_dispatch.rs:38:16 | -LL | impl Trait for dyn NonObjectSafe1 {} - | ^^^^^^^^^^^^^^^^^^ `NonObjectSafe1` cannot be made into an object +LL | impl Trait for dyn DynIncompatible1 {} + | ^^^^^^^^^^^^^^^^^^^^ `DynIncompatible1` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/feature-gate-object_safe_for_dispatch.rs:4:23 + --> $DIR/feature-gate-dyn_compatible_for_dispatch.rs:4:25 | -LL | trait NonObjectSafe1: Sized {} - | -------------- ^^^^^ ...because it requires `Self: Sized` +LL | trait DynIncompatible1: Sized {} + | ---------------- ^^^^^ ...because it requires `Self: Sized` | | | this trait cannot be made into an object... diff --git a/tests/ui/feature-gates/feature-gate-object_safe_for_dispatch.rs b/tests/ui/feature-gates/feature-gate-object_safe_for_dispatch.rs deleted file mode 100644 index 37348e476d408..0000000000000 --- a/tests/ui/feature-gates/feature-gate-object_safe_for_dispatch.rs +++ /dev/null @@ -1,41 +0,0 @@ -// Test that the use of the non object-safe trait objects -// are gated by `object_safe_for_dispatch` feature gate. - -trait NonObjectSafe1: Sized {} - -trait NonObjectSafe2 { - fn static_fn() {} -} - -trait NonObjectSafe3 { - fn foo(&self); -} - -trait NonObjectSafe4 { - fn foo(&self, s: &Self); -} - -fn takes_non_object_safe_ref(obj: &dyn NonObjectSafe1) { - //~^ ERROR E0038 -} - -fn return_non_object_safe_ref() -> &'static dyn NonObjectSafe2 { - //~^ ERROR E0038 - loop {} -} - -fn takes_non_object_safe_box(obj: Box) { - //~^ ERROR E0038 -} - -fn return_non_object_safe_rc() -> std::rc::Rc { - //~^ ERROR E0038 - loop {} -} - -trait Trait {} - -impl Trait for dyn NonObjectSafe1 {} -//~^ ERROR E0038 - -fn main() {} diff --git a/tests/ui/kindck/kindck-inherited-copy-bound.object_safe_for_dispatch.stderr b/tests/ui/kindck/kindck-inherited-copy-bound.dyn_compatible_for_dispatch.stderr similarity index 100% rename from tests/ui/kindck/kindck-inherited-copy-bound.object_safe_for_dispatch.stderr rename to tests/ui/kindck/kindck-inherited-copy-bound.dyn_compatible_for_dispatch.stderr diff --git a/tests/ui/kindck/kindck-inherited-copy-bound.rs b/tests/ui/kindck/kindck-inherited-copy-bound.rs index c785736f42e4b..dda95229ddf00 100644 --- a/tests/ui/kindck/kindck-inherited-copy-bound.rs +++ b/tests/ui/kindck/kindck-inherited-copy-bound.rs @@ -1,8 +1,8 @@ // Test that Copy bounds inherited by trait are checked. // -//@ revisions: curr object_safe_for_dispatch +//@ revisions: curr dyn_compatible_for_dispatch -#![cfg_attr(object_safe_for_dispatch, feature(object_safe_for_dispatch))] +#![cfg_attr(dyn_compatible_for_dispatch, feature(dyn_compatible_for_dispatch))] use std::any::Any; @@ -19,7 +19,7 @@ fn take_param(foo: &T) { } fn a() { let x: Box<_> = Box::new(3); take_param(&x); //[curr]~ ERROR E0277 - //[object_safe_for_dispatch]~^ ERROR E0277 + //[dyn_compatible_for_dispatch]~^ ERROR E0277 } fn b() { @@ -28,7 +28,7 @@ fn b() { let z = &x as &dyn Foo; //[curr]~^ ERROR E0038 //[curr]~| ERROR E0038 - //[object_safe_for_dispatch]~^^^ ERROR E0038 + //[dyn_compatible_for_dispatch]~^^^ ERROR E0038 } fn main() { } diff --git a/tests/ui/object-safety/object-safety-associated-consts.object_safe_for_dispatch.stderr b/tests/ui/object-safety/object-safety-associated-consts.dyn_compatible_for_dispatch.stderr similarity index 100% rename from tests/ui/object-safety/object-safety-associated-consts.object_safe_for_dispatch.stderr rename to tests/ui/object-safety/object-safety-associated-consts.dyn_compatible_for_dispatch.stderr diff --git a/tests/ui/object-safety/object-safety-associated-consts.rs b/tests/ui/object-safety/object-safety-associated-consts.rs index a090214bbb404..fc7b372b782a4 100644 --- a/tests/ui/object-safety/object-safety-associated-consts.rs +++ b/tests/ui/object-safety/object-safety-associated-consts.rs @@ -1,9 +1,9 @@ // Check that we correctly prevent users from making trait objects // from traits with associated consts. // -//@ revisions: curr object_safe_for_dispatch +//@ revisions: curr dyn_compatible_for_dispatch -#![cfg_attr(object_safe_for_dispatch, feature(object_safe_for_dispatch))] +#![cfg_attr(dyn_compatible_for_dispatch, feature(dyn_compatible_for_dispatch))] trait Bar { const X: usize; diff --git a/tests/ui/object-safety/object-safety-generics.object_safe_for_dispatch.stderr b/tests/ui/object-safety/object-safety-generics.dyn_compatible_for_dispatch.stderr similarity index 100% rename from tests/ui/object-safety/object-safety-generics.object_safe_for_dispatch.stderr rename to tests/ui/object-safety/object-safety-generics.dyn_compatible_for_dispatch.stderr diff --git a/tests/ui/object-safety/object-safety-generics.rs b/tests/ui/object-safety/object-safety-generics.rs index f005a689ac45c..b51555aa500c5 100644 --- a/tests/ui/object-safety/object-safety-generics.rs +++ b/tests/ui/object-safety/object-safety-generics.rs @@ -1,9 +1,9 @@ // Check that we correctly prevent users from making trait objects // from traits with generic methods, unless `where Self : Sized` is // present. -//@ revisions: curr object_safe_for_dispatch +//@ revisions: curr dyn_compatible_for_dispatch -#![cfg_attr(object_safe_for_dispatch, feature(object_safe_for_dispatch))] +#![cfg_attr(dyn_compatible_for_dispatch, feature(dyn_compatible_for_dispatch))] trait Bar { @@ -18,14 +18,14 @@ trait Quux { fn make_bar(t: &T) -> &dyn Bar { //[curr]~^ ERROR E0038 t - //[object_safe_for_dispatch]~^ ERROR E0038 + //[dyn_compatible_for_dispatch]~^ ERROR E0038 //[curr]~^^ ERROR E0038 } fn make_bar_explicit(t: &T) -> &dyn Bar { //[curr]~^ ERROR E0038 t as &dyn Bar - //[object_safe_for_dispatch]~^ ERROR E0038 + //[dyn_compatible_for_dispatch]~^ ERROR E0038 //[curr]~^^ ERROR E0038 //[curr]~| ERROR E0038 } diff --git a/tests/ui/object-safety/object-safety-mentions-Self.object_safe_for_dispatch.stderr b/tests/ui/object-safety/object-safety-mentions-Self.dyn_compatible_for_dispatch.stderr similarity index 100% rename from tests/ui/object-safety/object-safety-mentions-Self.object_safe_for_dispatch.stderr rename to tests/ui/object-safety/object-safety-mentions-Self.dyn_compatible_for_dispatch.stderr diff --git a/tests/ui/object-safety/object-safety-mentions-Self.rs b/tests/ui/object-safety/object-safety-mentions-Self.rs index 1311faf97bc36..84c229e252d30 100644 --- a/tests/ui/object-safety/object-safety-mentions-Self.rs +++ b/tests/ui/object-safety/object-safety-mentions-Self.rs @@ -2,9 +2,9 @@ // form traits that make use of `Self` in an argument or return // position, unless `where Self : Sized` is present.. // -//@ revisions: curr object_safe_for_dispatch +//@ revisions: curr dyn_compatible_for_dispatch -#![cfg_attr(object_safe_for_dispatch, feature(object_safe_for_dispatch))] +#![cfg_attr(dyn_compatible_for_dispatch, feature(dyn_compatible_for_dispatch))] trait Bar { diff --git a/tests/ui/object-safety/object-safety-no-static.object_safe_for_dispatch.stderr b/tests/ui/object-safety/object-safety-no-static.dyn_compatible_for_dispatch.stderr similarity index 100% rename from tests/ui/object-safety/object-safety-no-static.object_safe_for_dispatch.stderr rename to tests/ui/object-safety/object-safety-no-static.dyn_compatible_for_dispatch.stderr diff --git a/tests/ui/object-safety/object-safety-no-static.rs b/tests/ui/object-safety/object-safety-no-static.rs index 4f4e03d734e8e..54af16fe18eb6 100644 --- a/tests/ui/object-safety/object-safety-no-static.rs +++ b/tests/ui/object-safety/object-safety-no-static.rs @@ -1,9 +1,9 @@ // Check that we correctly prevent users from making trait objects // from traits with static methods. // -//@ revisions: curr object_safe_for_dispatch +//@ revisions: curr dyn_compatible_for_dispatch -#![cfg_attr(object_safe_for_dispatch, feature(object_safe_for_dispatch))] +#![cfg_attr(dyn_compatible_for_dispatch, feature(dyn_compatible_for_dispatch))] trait Foo { fn foo() {} diff --git a/tests/ui/object-safety/object-safety-sized-2.object_safe_for_dispatch.stderr b/tests/ui/object-safety/object-safety-sized-2.dyn_compatible_for_dispatch.stderr similarity index 100% rename from tests/ui/object-safety/object-safety-sized-2.object_safe_for_dispatch.stderr rename to tests/ui/object-safety/object-safety-sized-2.dyn_compatible_for_dispatch.stderr diff --git a/tests/ui/object-safety/object-safety-sized-2.rs b/tests/ui/object-safety/object-safety-sized-2.rs index cfb5d588d70df..f5edd287f24d8 100644 --- a/tests/ui/object-safety/object-safety-sized-2.rs +++ b/tests/ui/object-safety/object-safety-sized-2.rs @@ -1,9 +1,9 @@ // Check that we correctly prevent users from making trait objects // from traits where `Self : Sized`. // -//@ revisions: curr object_safe_for_dispatch +//@ revisions: curr dyn_compatible_for_dispatch -#![cfg_attr(object_safe_for_dispatch, feature(object_safe_for_dispatch))] +#![cfg_attr(dyn_compatible_for_dispatch, feature(dyn_compatible_for_dispatch))] trait Bar where Self : Sized diff --git a/tests/ui/object-safety/object-safety-sized.object_safe_for_dispatch.stderr b/tests/ui/object-safety/object-safety-sized.dyn_compatible_for_dispatch.stderr similarity index 100% rename from tests/ui/object-safety/object-safety-sized.object_safe_for_dispatch.stderr rename to tests/ui/object-safety/object-safety-sized.dyn_compatible_for_dispatch.stderr diff --git a/tests/ui/object-safety/object-safety-sized.rs b/tests/ui/object-safety/object-safety-sized.rs index f4d6c945b33d5..4c4fe3f8f2593 100644 --- a/tests/ui/object-safety/object-safety-sized.rs +++ b/tests/ui/object-safety/object-safety-sized.rs @@ -1,9 +1,9 @@ // Check that we correctly prevent users from making trait objects // from traits where `Self : Sized`. // -//@ revisions: curr object_safe_for_dispatch +//@ revisions: curr dyn_compatible_for_dispatch -#![cfg_attr(object_safe_for_dispatch, feature(object_safe_for_dispatch))] +#![cfg_attr(dyn_compatible_for_dispatch, feature(dyn_compatible_for_dispatch))] trait Bar: Sized { fn bar(&self, t: T); diff --git a/tests/ui/rfcs/rfc-2027-object-safe-for-dispatch/downcast-unsafe-trait-objects.rs b/tests/ui/rfcs/rfc-2027-dyn-compatible-for-dispatch/downcast-unsafe-trait-objects.rs similarity index 90% rename from tests/ui/rfcs/rfc-2027-object-safe-for-dispatch/downcast-unsafe-trait-objects.rs rename to tests/ui/rfcs/rfc-2027-dyn-compatible-for-dispatch/downcast-unsafe-trait-objects.rs index d4337dcb16543..e9206789756e7 100644 --- a/tests/ui/rfcs/rfc-2027-object-safe-for-dispatch/downcast-unsafe-trait-objects.rs +++ b/tests/ui/rfcs/rfc-2027-dyn-compatible-for-dispatch/downcast-unsafe-trait-objects.rs @@ -3,7 +3,7 @@ // //@ check-pass -#![feature(object_safe_for_dispatch)] +#![feature(dyn_compatible_for_dispatch)] trait Trait: Sized {} diff --git a/tests/ui/rfcs/rfc-2027-object-safe-for-dispatch/manual-self-impl-for-unsafe-obj.current.stderr b/tests/ui/rfcs/rfc-2027-dyn-compatible-for-dispatch/manual-self-impl-for-unsafe-obj.current.stderr similarity index 100% rename from tests/ui/rfcs/rfc-2027-object-safe-for-dispatch/manual-self-impl-for-unsafe-obj.current.stderr rename to tests/ui/rfcs/rfc-2027-dyn-compatible-for-dispatch/manual-self-impl-for-unsafe-obj.current.stderr diff --git a/tests/ui/rfcs/rfc-2027-object-safe-for-dispatch/manual-self-impl-for-unsafe-obj.next.stderr b/tests/ui/rfcs/rfc-2027-dyn-compatible-for-dispatch/manual-self-impl-for-unsafe-obj.next.stderr similarity index 100% rename from tests/ui/rfcs/rfc-2027-object-safe-for-dispatch/manual-self-impl-for-unsafe-obj.next.stderr rename to tests/ui/rfcs/rfc-2027-dyn-compatible-for-dispatch/manual-self-impl-for-unsafe-obj.next.stderr diff --git a/tests/ui/rfcs/rfc-2027-object-safe-for-dispatch/manual-self-impl-for-unsafe-obj.rs b/tests/ui/rfcs/rfc-2027-dyn-compatible-for-dispatch/manual-self-impl-for-unsafe-obj.rs similarity index 97% rename from tests/ui/rfcs/rfc-2027-object-safe-for-dispatch/manual-self-impl-for-unsafe-obj.rs rename to tests/ui/rfcs/rfc-2027-dyn-compatible-for-dispatch/manual-self-impl-for-unsafe-obj.rs index a020d91fb1407..37e6f948ad118 100644 --- a/tests/ui/rfcs/rfc-2027-object-safe-for-dispatch/manual-self-impl-for-unsafe-obj.rs +++ b/tests/ui/rfcs/rfc-2027-dyn-compatible-for-dispatch/manual-self-impl-for-unsafe-obj.rs @@ -5,7 +5,7 @@ //@[next] compile-flags: -Znext-solver //@ run-pass -#![feature(object_safe_for_dispatch)] +#![feature(dyn_compatible_for_dispatch)] trait Bad { fn stat() -> char { diff --git a/tests/ui/rfcs/rfc-2027-object-safe-for-dispatch/static-dispatch-unsafe-object.rs b/tests/ui/rfcs/rfc-2027-dyn-compatible-for-dispatch/static-dispatch-unsafe-object.rs similarity index 94% rename from tests/ui/rfcs/rfc-2027-object-safe-for-dispatch/static-dispatch-unsafe-object.rs rename to tests/ui/rfcs/rfc-2027-dyn-compatible-for-dispatch/static-dispatch-unsafe-object.rs index cbf76a6830b8f..c38928a9f44e9 100644 --- a/tests/ui/rfcs/rfc-2027-object-safe-for-dispatch/static-dispatch-unsafe-object.rs +++ b/tests/ui/rfcs/rfc-2027-dyn-compatible-for-dispatch/static-dispatch-unsafe-object.rs @@ -3,7 +3,7 @@ // //@ check-pass -#![feature(object_safe_for_dispatch)] +#![feature(dyn_compatible_for_dispatch)] trait Statics { fn plain() {} diff --git a/tests/ui/self/arbitrary-self-types-not-object-safe.object_safe_for_dispatch.stderr b/tests/ui/self/arbitrary-self-types-not-object-safe.dyn_compatible_for_dispatch.stderr similarity index 100% rename from tests/ui/self/arbitrary-self-types-not-object-safe.object_safe_for_dispatch.stderr rename to tests/ui/self/arbitrary-self-types-not-object-safe.dyn_compatible_for_dispatch.stderr diff --git a/tests/ui/self/arbitrary-self-types-not-object-safe.rs b/tests/ui/self/arbitrary-self-types-not-object-safe.rs index 0053eb5f73948..940b2f1e8e2fa 100644 --- a/tests/ui/self/arbitrary-self-types-not-object-safe.rs +++ b/tests/ui/self/arbitrary-self-types-not-object-safe.rs @@ -1,6 +1,6 @@ -//@ revisions: curr object_safe_for_dispatch +//@ revisions: curr dyn_compatible_for_dispatch -#![cfg_attr(object_safe_for_dispatch, feature(object_safe_for_dispatch))] +#![cfg_attr(dyn_compatible_for_dispatch, feature(dyn_compatible_for_dispatch))] use std::rc::Rc; @@ -33,7 +33,7 @@ fn make_foo() { let x = Rc::new(5usize) as Rc; //[curr]~^ ERROR E0038 //[curr]~| ERROR E0038 - //[object_safe_for_dispatch]~^^^ ERROR E0038 + //[dyn_compatible_for_dispatch]~^^^ ERROR E0038 } fn make_bar() { diff --git a/tests/ui/suggestions/issue-104328.rs b/tests/ui/suggestions/issue-104328.rs index c3707baf79fc3..2b0fbdb8d35bb 100644 --- a/tests/ui/suggestions/issue-104328.rs +++ b/tests/ui/suggestions/issue-104328.rs @@ -1,4 +1,4 @@ -#![feature(object_safe_for_dispatch)] +#![feature(dyn_compatible_for_dispatch)] trait Foo { fn f() {} diff --git a/tests/ui/wf/wf-convert-unsafe-trait-obj-box.rs b/tests/ui/wf/wf-convert-unsafe-trait-obj-box.rs index ffdb49a3be5c7..e32b04c471524 100644 --- a/tests/ui/wf/wf-convert-unsafe-trait-obj-box.rs +++ b/tests/ui/wf/wf-convert-unsafe-trait-obj-box.rs @@ -1,7 +1,7 @@ // Check that we do not allow casts or coercions // to object unsafe trait objects inside a Box -#![feature(object_safe_for_dispatch)] +#![feature(dyn_compatible_for_dispatch)] trait Trait: Sized {} diff --git a/tests/ui/wf/wf-convert-unsafe-trait-obj.rs b/tests/ui/wf/wf-convert-unsafe-trait-obj.rs index 143b854ed6b2d..6f38635281983 100644 --- a/tests/ui/wf/wf-convert-unsafe-trait-obj.rs +++ b/tests/ui/wf/wf-convert-unsafe-trait-obj.rs @@ -1,7 +1,7 @@ // Check that we do not allow casts or coercions // to object unsafe trait objects by ref -#![feature(object_safe_for_dispatch)] +#![feature(dyn_compatible_for_dispatch)] trait Trait: Sized {} diff --git a/tests/ui/wf/wf-unsafe-trait-obj-match.rs b/tests/ui/wf/wf-unsafe-trait-obj-match.rs index c8731a8ecafa4..07e90538b85dd 100644 --- a/tests/ui/wf/wf-unsafe-trait-obj-match.rs +++ b/tests/ui/wf/wf-unsafe-trait-obj-match.rs @@ -1,7 +1,7 @@ // Check that we do not allow coercions to object // unsafe trait objects in match arms -#![feature(object_safe_for_dispatch)] +#![feature(dyn_compatible_for_dispatch)] trait Trait: Sized {} From 20cebae31203a9781f99081b075abe0dc2504a98 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Le=C3=B3n=20Orell=20Valerian=20Liehr?= Date: Wed, 9 Oct 2024 23:31:01 +0200 Subject: [PATCH 2073/2194] UI tests: Rename "object safe" to "dyn compatible" --- src/tools/tidy/src/issues.txt | 4 -- tests/ui/allocator/dyn-compatible.rs | 13 ++++ tests/ui/allocator/object-safe.rs | 13 ---- ....rs => entails-sized-dyn-compatibility.rs} | 12 ++-- ...{object-safety.rs => dyn-compatibility.rs} | 0 ...safety.stderr => dyn-compatibility.stderr} | 4 +- ...ce-impl-trait-for-trait-dyn-compatible.rs} | 6 +- ...impl-trait-for-trait-dyn-compatible.stderr | 27 +++++++ ...ce-impl-trait-for-trait-object-safe.stderr | 27 ------- ...rs => const_param_ty_dyn_compatibility.rs} | 0 ...> const_param_ty_dyn_compatibility.stderr} | 4 +- ...rr-ret.rs => dyn-compatibility-err-ret.rs} | 0 ...tderr => dyn-compatibility-err-ret.stderr} | 8 +-- ... => dyn-compatibility-err-where-bounds.rs} | 0 ...dyn-compatibility-err-where-bounds.stderr} | 8 +-- ...r.rs => dyn-compatibility-ok-infer-err.rs} | 0 ... => dyn-compatibility-ok-infer-err.stderr} | 8 +-- ...t-safety-ok.rs => dyn-compatibility-ok.rs} | 0 .../almost-supertrait-associated-type.rs | 2 +- .../almost-supertrait-associated-type.stderr | 0 .../assoc_const_bounds.rs | 0 .../assoc_const_bounds_sized.rs | 0 .../assoc_type_bounds.rs | 0 .../assoc_type_bounds.stderr | 0 .../assoc_type_bounds2.rs | 0 .../assoc_type_bounds2.stderr | 0 .../assoc_type_bounds_implicit_sized.fixed | 0 .../assoc_type_bounds_implicit_sized.rs | 0 .../assoc_type_bounds_implicit_sized.stderr | 0 .../assoc_type_bounds_sized.rs | 0 .../assoc_type_bounds_sized_others.rs | 0 .../assoc_type_bounds_sized_others.stderr | 0 .../assoc_type_bounds_sized_unnecessary.rs | 0 ...assoc_type_bounds_sized_unnecessary.stderr | 0 .../assoc_type_bounds_sized_used.rs | 0 .../assoc_type_bounds_sized_used.stderr | 0 .../associated-consts.curr.stderr} | 8 +-- ...consts.dyn_compatible_for_dispatch.stderr} | 4 +- .../associated-consts.rs} | 0 .../avoid-ice-on-warning-2.new.stderr | 0 .../avoid-ice-on-warning-2.old.stderr | 0 .../avoid-ice-on-warning-2.rs | 0 .../avoid-ice-on-warning-3.new.stderr | 0 .../avoid-ice-on-warning-3.old.stderr | 0 .../avoid-ice-on-warning-3.rs | 0 .../avoid-ice-on-warning.new.stderr | 0 .../avoid-ice-on-warning.old.stderr | 0 .../avoid-ice-on-warning.rs | 0 .../bare-trait-dont-suggest-dyn.new.fixed | 0 .../bare-trait-dont-suggest-dyn.new.stderr | 0 .../bare-trait-dont-suggest-dyn.old.stderr | 0 .../bare-trait-dont-suggest-dyn.rs | 0 .../bounds.rs} | 2 +- .../bounds.stderr} | 4 +- .../by-value-self-use.rs} | 2 +- .../by-value-self-use.stderr} | 2 +- .../by-value-self.rs} | 2 +- .../call-when-assoc-ty-is-sized.rs | 0 .../elaborated-predicates-ordering.rs} | 1 + .../erroneous_signature.rs | 0 .../erroneous_signature.stderr | 0 .../generics.curr.stderr} | 20 +++--- ...nerics.dyn_compatible_for_dispatch.stderr} | 8 +-- .../generics.rs} | 0 ...s-multiple_supertrait_upcastable-check.rs} | 1 + .../item-bounds-can-reference-self.rs | 0 ...mention-correct-dyn-incompatible-trait.rs} | 2 + ...ion-correct-dyn-incompatible-trait.stderr} | 8 +-- .../mentions-Self-in-super-predicates.rs} | 0 .../mentions-Self-in-super-predicates.stderr} | 12 ++-- .../mentions-Self.curr.stderr} | 16 ++--- ...s-Self.dyn_compatible_for_dispatch.stderr} | 8 +-- .../mentions-Self.rs} | 0 .../missing-assoc-type.rs} | 0 .../missing-assoc-type.stderr} | 16 ++--- .../no-static.curr.stderr} | 12 ++-- ...static.dyn_compatible_for_dispatch.stderr} | 4 +- .../no-static.rs} | 0 .../phantom-fn.rs} | 2 +- ...t-in-fn-inputs-and-outputs-issue-125139.rs | 0 ...-fn-inputs-and-outputs-issue-125139.stderr | 0 .../sized-2.curr.stderr} | 8 +-- ...ized-2.dyn_compatible_for_dispatch.stderr} | 4 +- .../sized-2.rs} | 0 .../sized.curr.stderr} | 8 +-- .../sized.dyn_compatible_for_dispatch.stderr} | 4 +- .../sized.rs} | 0 .../supertrait-mentions-GAT.rs} | 0 .../supertrait-mentions-GAT.stderr} | 8 +-- .../supertrait-mentions-Self.rs} | 0 .../supertrait-mentions-Self.stderr} | 8 +-- ...chable-receiver-and-wc-references-Self.rs} | 5 +- ...le-receiver-and-wc-references-Self.stderr} | 12 ++-- ...ure-gate-dispatch-from-dyn-missing-impl.rs | 2 +- ...eature-gate-dyn_compatible_for_dispatch.rs | 8 +-- ...re-gate-dyn_compatible_for_dispatch.stderr | 24 +++---- .../generic-associated-types/trait-objects.rs | 2 +- ...ble-trait-in-return-position-dyn-trait.rs} | 11 +-- ...trait-in-return-position-dyn-trait.stderr} | 72 +++++++++---------- ...le-trait-in-return-position-impl-trait.rs} | 16 ++--- ...rait-in-return-position-impl-trait.stderr} | 12 ++-- ...ilities-during-dyn-compatibility-check.rs} | 0 ...ies-during-dyn-compatibility-check.stderr} | 16 ++--- ...ty-sized.rs => dyn-compatibility-sized.rs} | 0 ...{object-safety.rs => dyn-compatibility.rs} | 0 ...safety.stderr => dyn-compatibility.stderr} | 16 ++--- tests/ui/issues/issue-58734.rs | 8 +-- .../downcast-unsafe-trait-objects.rs | 2 +- .../manual-self-impl-for-unsafe-obj.rs | 2 +- tests/ui/sanitizer/cfi/async-closures.rs | 2 +- ...y-self-types-dyn-incompatible.curr.stderr} | 8 +-- ...atible.dyn_compatible_for_dispatch.stderr} | 4 +- ... arbitrary-self-types-dyn-incompatible.rs} | 0 ...itrary_self_types_pointers_and_wrappers.rs | 6 +- ...compatibility-sized-self-by-value-self.rs} | 2 +- ...ompatibility-sized-self-generic-method.rs} | 2 +- ...n-compatibility-sized-self-return-Self.rs} | 2 +- tests/ui/specialization/issue-44861.rs | 8 +-- ...not-object-safe.rs => dyn-incompatible.rs} | 0 ...dyn-incompatible-trait-references-self.rs} | 0 ...incompatible-trait-references-self.stderr} | 14 ++-- ...trait-should-use-self-2021-without-dyn.rs} | 0 ...t-should-use-self-2021-without-dyn.stderr} | 30 ++++---- ...ncompatible-trait-should-use-self-2021.rs} | 0 ...patible-trait-should-use-self-2021.stderr} | 12 ++-- ...dyn-incompatible-trait-should-use-self.rs} | 0 ...incompatible-trait-should-use-self.stderr} | 12 ++-- ...atible-trait-should-use-where-sized.fixed} | 0 ...ompatible-trait-should-use-where-sized.rs} | 0 ...tible-trait-should-use-where-sized.stderr} | 6 +- tests/ui/suggestions/issue-98500.rs | 6 +- tests/ui/suggestions/issue-98500.stderr | 2 +- tests/ui/traits/alias/no-duplicates.rs | 4 +- tests/ui/traits/alias/no-extra-traits.rs | 2 +- tests/ui/traits/alias/object-wf.rs | 4 +- ...ect-unsafety.rs => dyn-incompatibility.rs} | 0 ...fety.stderr => dyn-incompatibility.stderr} | 10 +-- ...ety.rs => supertrait-dyn-compatibility.rs} | 0 ...rr => supertrait-dyn-compatibility.stderr} | 14 ++-- tests/ui/traits/object/print_vtable_sizes.rs | 2 +- tests/ui/traits/object/safety.rs | 2 +- ...ect-safe.rs => vtable-dyn-incompatible.rs} | 2 +- ....stderr => vtable-dyn-incompatible.stderr} | 2 +- tests/ui/traits/wf-object/no-duplicates.rs | 4 +- tests/ui/traits/wf-object/reverse-order.rs | 2 +- ...by-value-trait-dyn-compatibility-rpass.rs} | 0 ...e-trait-dyn-compatibility-with-default.rs} | 0 ...rs => by-value-trait-dyn-compatibility.rs} | 0 ...> by-value-trait-dyn-compatibility.stderr} | 4 +- ... wf-convert-dyn-incompat-trait-obj-box.rs} | 2 +- ...convert-dyn-incompat-trait-obj-box.stderr} | 12 ++-- ...s => wf-convert-dyn-incompat-trait-obj.rs} | 2 +- ... wf-convert-dyn-incompat-trait-obj.stderr} | 12 ++-- ....rs => wf-dyn-incompat-trait-obj-match.rs} | 0 ...=> wf-dyn-incompat-trait-obj-match.stderr} | 10 +-- ...-object-safe.rs => wf-dyn-incompatible.rs} | 2 +- ...safe.stderr => wf-dyn-incompatible.stderr} | 4 +- 157 files changed, 366 insertions(+), 364 deletions(-) create mode 100644 tests/ui/allocator/dyn-compatible.rs delete mode 100644 tests/ui/allocator/object-safe.rs rename tests/ui/associated-type-bounds/{entails-sized-object-safety.rs => entails-sized-dyn-compatibility.rs} (67%) rename tests/ui/async-await/in-trait/{object-safety.rs => dyn-compatibility.rs} (100%) rename tests/ui/async-await/in-trait/{object-safety.stderr => dyn-compatibility.stderr} (90%) rename tests/ui/coherence/{coherence-impl-trait-for-trait-object-safe.rs => coherence-impl-trait-for-trait-dyn-compatible.rs} (54%) create mode 100644 tests/ui/coherence/coherence-impl-trait-for-trait-dyn-compatible.stderr delete mode 100644 tests/ui/coherence/coherence-impl-trait-for-trait-object-safe.stderr rename tests/ui/const-generics/adt_const_params/{const_param_ty_object_safety.rs => const_param_ty_dyn_compatibility.rs} (100%) rename tests/ui/const-generics/adt_const_params/{const_param_ty_object_safety.stderr => const_param_ty_dyn_compatibility.stderr} (93%) rename tests/ui/const-generics/generic_const_exprs/{object-safety-err-ret.rs => dyn-compatibility-err-ret.rs} (100%) rename tests/ui/const-generics/generic_const_exprs/{object-safety-err-ret.stderr => dyn-compatibility-err-ret.stderr} (91%) rename tests/ui/const-generics/generic_const_exprs/{object-safety-err-where-bounds.rs => dyn-compatibility-err-where-bounds.rs} (100%) rename tests/ui/const-generics/generic_const_exprs/{object-safety-err-where-bounds.stderr => dyn-compatibility-err-where-bounds.stderr} (88%) rename tests/ui/const-generics/generic_const_exprs/{object-safety-ok-infer-err.rs => dyn-compatibility-ok-infer-err.rs} (100%) rename tests/ui/const-generics/generic_const_exprs/{object-safety-ok-infer-err.stderr => dyn-compatibility-ok-infer-err.stderr} (85%) rename tests/ui/const-generics/generic_const_exprs/{object-safety-ok.rs => dyn-compatibility-ok.rs} (100%) rename tests/ui/{object-safety => dyn-compatibility}/almost-supertrait-associated-type.rs (95%) rename tests/ui/{object-safety => dyn-compatibility}/almost-supertrait-associated-type.stderr (100%) rename tests/ui/{object-safety => dyn-compatibility}/assoc_const_bounds.rs (100%) rename tests/ui/{object-safety => dyn-compatibility}/assoc_const_bounds_sized.rs (100%) rename tests/ui/{object-safety => dyn-compatibility}/assoc_type_bounds.rs (100%) rename tests/ui/{object-safety => dyn-compatibility}/assoc_type_bounds.stderr (100%) rename tests/ui/{object-safety => dyn-compatibility}/assoc_type_bounds2.rs (100%) rename tests/ui/{object-safety => dyn-compatibility}/assoc_type_bounds2.stderr (100%) rename tests/ui/{object-safety => dyn-compatibility}/assoc_type_bounds_implicit_sized.fixed (100%) rename tests/ui/{object-safety => dyn-compatibility}/assoc_type_bounds_implicit_sized.rs (100%) rename tests/ui/{object-safety => dyn-compatibility}/assoc_type_bounds_implicit_sized.stderr (100%) rename tests/ui/{object-safety => dyn-compatibility}/assoc_type_bounds_sized.rs (100%) rename tests/ui/{object-safety => dyn-compatibility}/assoc_type_bounds_sized_others.rs (100%) rename tests/ui/{object-safety => dyn-compatibility}/assoc_type_bounds_sized_others.stderr (100%) rename tests/ui/{object-safety => dyn-compatibility}/assoc_type_bounds_sized_unnecessary.rs (100%) rename tests/ui/{object-safety => dyn-compatibility}/assoc_type_bounds_sized_unnecessary.stderr (100%) rename tests/ui/{object-safety => dyn-compatibility}/assoc_type_bounds_sized_used.rs (100%) rename tests/ui/{object-safety => dyn-compatibility}/assoc_type_bounds_sized_used.stderr (100%) rename tests/ui/{object-safety/object-safety-associated-consts.curr.stderr => dyn-compatibility/associated-consts.curr.stderr} (86%) rename tests/ui/{object-safety/object-safety-associated-consts.dyn_compatible_for_dispatch.stderr => dyn-compatibility/associated-consts.dyn_compatible_for_dispatch.stderr} (87%) rename tests/ui/{object-safety/object-safety-associated-consts.rs => dyn-compatibility/associated-consts.rs} (100%) rename tests/ui/{object-safety => dyn-compatibility}/avoid-ice-on-warning-2.new.stderr (100%) rename tests/ui/{object-safety => dyn-compatibility}/avoid-ice-on-warning-2.old.stderr (100%) rename tests/ui/{object-safety => dyn-compatibility}/avoid-ice-on-warning-2.rs (100%) rename tests/ui/{object-safety => dyn-compatibility}/avoid-ice-on-warning-3.new.stderr (100%) rename tests/ui/{object-safety => dyn-compatibility}/avoid-ice-on-warning-3.old.stderr (100%) rename tests/ui/{object-safety => dyn-compatibility}/avoid-ice-on-warning-3.rs (100%) rename tests/ui/{object-safety => dyn-compatibility}/avoid-ice-on-warning.new.stderr (100%) rename tests/ui/{object-safety => dyn-compatibility}/avoid-ice-on-warning.old.stderr (100%) rename tests/ui/{object-safety => dyn-compatibility}/avoid-ice-on-warning.rs (100%) rename tests/ui/{object-safety => dyn-compatibility}/bare-trait-dont-suggest-dyn.new.fixed (100%) rename tests/ui/{object-safety => dyn-compatibility}/bare-trait-dont-suggest-dyn.new.stderr (100%) rename tests/ui/{object-safety => dyn-compatibility}/bare-trait-dont-suggest-dyn.old.stderr (100%) rename tests/ui/{object-safety => dyn-compatibility}/bare-trait-dont-suggest-dyn.rs (100%) rename tests/ui/{object-safety/object-safety-bounds.rs => dyn-compatibility/bounds.rs} (72%) rename tests/ui/{object-safety/object-safety-bounds.stderr => dyn-compatibility/bounds.stderr} (89%) rename tests/ui/{object-safety/object-safety-by-value-self-use.rs => dyn-compatibility/by-value-self-use.rs} (79%) rename tests/ui/{object-safety/object-safety-by-value-self-use.stderr => dyn-compatibility/by-value-self-use.stderr} (83%) rename tests/ui/{object-safety/object-safety-by-value-self.rs => dyn-compatibility/by-value-self.rs} (90%) rename tests/ui/{object-safety => dyn-compatibility}/call-when-assoc-ty-is-sized.rs (100%) rename tests/ui/{object-safety/issue-102933.rs => dyn-compatibility/elaborated-predicates-ordering.rs} (93%) rename tests/ui/{object-safety => dyn-compatibility}/erroneous_signature.rs (100%) rename tests/ui/{object-safety => dyn-compatibility}/erroneous_signature.stderr (100%) rename tests/ui/{object-safety/object-safety-generics.curr.stderr => dyn-compatibility/generics.curr.stderr} (88%) rename tests/ui/{object-safety/object-safety-generics.dyn_compatible_for_dispatch.stderr => dyn-compatibility/generics.dyn_compatible_for_dispatch.stderr} (89%) rename tests/ui/{object-safety/object-safety-generics.rs => dyn-compatibility/generics.rs} (100%) rename tests/ui/{object-safety/issue-106247.rs => dyn-compatibility/impossible-predicates-multiple_supertrait_upcastable-check.rs} (73%) rename tests/ui/{object-safety => dyn-compatibility}/item-bounds-can-reference-self.rs (100%) rename tests/ui/{object-safety/issue-19538.rs => dyn-compatibility/mention-correct-dyn-incompatible-trait.rs} (90%) rename tests/ui/{object-safety/issue-19538.stderr => dyn-compatibility/mention-correct-dyn-incompatible-trait.stderr} (87%) rename tests/ui/{object-safety/object-safety-issue-22040.rs => dyn-compatibility/mentions-Self-in-super-predicates.rs} (100%) rename tests/ui/{object-safety/object-safety-issue-22040.stderr => dyn-compatibility/mentions-Self-in-super-predicates.stderr} (87%) rename tests/ui/{object-safety/object-safety-mentions-Self.curr.stderr => dyn-compatibility/mentions-Self.curr.stderr} (88%) rename tests/ui/{object-safety/object-safety-mentions-Self.dyn_compatible_for_dispatch.stderr => dyn-compatibility/mentions-Self.dyn_compatible_for_dispatch.stderr} (88%) rename tests/ui/{object-safety/object-safety-mentions-Self.rs => dyn-compatibility/mentions-Self.rs} (100%) rename tests/ui/{traits/object/object-unsafe-missing-assoc-type.rs => dyn-compatibility/missing-assoc-type.rs} (100%) rename tests/ui/{traits/object/object-unsafe-missing-assoc-type.stderr => dyn-compatibility/missing-assoc-type.stderr} (86%) rename tests/ui/{object-safety/object-safety-no-static.curr.stderr => dyn-compatibility/no-static.curr.stderr} (92%) rename tests/ui/{object-safety/object-safety-no-static.dyn_compatible_for_dispatch.stderr => dyn-compatibility/no-static.dyn_compatible_for_dispatch.stderr} (93%) rename tests/ui/{object-safety/object-safety-no-static.rs => dyn-compatibility/no-static.rs} (100%) rename tests/ui/{object-safety/object-safety-phantom-fn.rs => dyn-compatibility/phantom-fn.rs} (92%) rename tests/ui/{object-safety => dyn-compatibility}/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs (100%) rename tests/ui/{object-safety => dyn-compatibility}/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.stderr (100%) rename tests/ui/{object-safety/object-safety-sized-2.curr.stderr => dyn-compatibility/sized-2.curr.stderr} (88%) rename tests/ui/{object-safety/object-safety-sized-2.dyn_compatible_for_dispatch.stderr => dyn-compatibility/sized-2.dyn_compatible_for_dispatch.stderr} (89%) rename tests/ui/{object-safety/object-safety-sized-2.rs => dyn-compatibility/sized-2.rs} (100%) rename tests/ui/{object-safety/object-safety-sized.curr.stderr => dyn-compatibility/sized.curr.stderr} (88%) rename tests/ui/{object-safety/object-safety-sized.dyn_compatible_for_dispatch.stderr => dyn-compatibility/sized.dyn_compatible_for_dispatch.stderr} (89%) rename tests/ui/{object-safety/object-safety-sized.rs => dyn-compatibility/sized.rs} (100%) rename tests/ui/{object-safety/object-safety-supertrait-mentions-GAT.rs => dyn-compatibility/supertrait-mentions-GAT.rs} (100%) rename tests/ui/{object-safety/object-safety-supertrait-mentions-GAT.stderr => dyn-compatibility/supertrait-mentions-GAT.stderr} (86%) rename tests/ui/{object-safety/object-safety-supertrait-mentions-Self.rs => dyn-compatibility/supertrait-mentions-Self.rs} (100%) rename tests/ui/{object-safety/object-safety-supertrait-mentions-Self.stderr => dyn-compatibility/supertrait-mentions-Self.stderr} (86%) rename tests/ui/{object-safety/issue-102762.rs => dyn-compatibility/undispatchable-receiver-and-wc-references-Self.rs} (79%) rename tests/ui/{object-safety/issue-102762.stderr => dyn-compatibility/undispatchable-receiver-and-wc-references-Self.stderr} (87%) rename tests/ui/impl-trait/{object-unsafe-trait-in-return-position-dyn-trait.rs => dyn-incompatible-trait-in-return-position-dyn-trait.rs} (59%) rename tests/ui/impl-trait/{object-unsafe-trait-in-return-position-dyn-trait.stderr => dyn-incompatible-trait-in-return-position-dyn-trait.stderr} (62%) rename tests/ui/impl-trait/{object-unsafe-trait-in-return-position-impl-trait.rs => dyn-incompatible-trait-in-return-position-impl-trait.rs} (61%) rename tests/ui/impl-trait/{object-unsafe-trait-in-return-position-impl-trait.stderr => dyn-incompatible-trait-in-return-position-impl-trait.stderr} (54%) rename tests/ui/impl-trait/in-trait/{cycle-effective-visibilities-during-object-safety.rs => cycle-effective-visibilities-during-dyn-compatibility-check.rs} (100%) rename tests/ui/impl-trait/in-trait/{cycle-effective-visibilities-during-object-safety.stderr => cycle-effective-visibilities-during-dyn-compatibility-check.stderr} (82%) rename tests/ui/impl-trait/in-trait/{object-safety-sized.rs => dyn-compatibility-sized.rs} (100%) rename tests/ui/impl-trait/in-trait/{object-safety.rs => dyn-compatibility.rs} (100%) rename tests/ui/impl-trait/in-trait/{object-safety.stderr => dyn-compatibility.stderr} (91%) rename tests/ui/self/{arbitrary-self-types-not-object-safe.curr.stderr => arbitrary-self-types-dyn-incompatible.curr.stderr} (89%) rename tests/ui/self/{arbitrary-self-types-not-object-safe.dyn_compatible_for_dispatch.stderr => arbitrary-self-types-dyn-incompatible.dyn_compatible_for_dispatch.stderr} (90%) rename tests/ui/self/{arbitrary-self-types-not-object-safe.rs => arbitrary-self-types-dyn-incompatible.rs} (100%) rename tests/ui/self/{object-safety-sized-self-by-value-self.rs => dyn-compatibility-sized-self-by-value-self.rs} (90%) rename tests/ui/self/{object-safety-sized-self-generic-method.rs => dyn-compatibility-sized-self-generic-method.rs} (90%) rename tests/ui/self/{object-safety-sized-self-return-Self.rs => dyn-compatibility-sized-self-return-Self.rs} (90%) rename tests/ui/suggestions/auxiliary/{not-object-safe.rs => dyn-incompatible.rs} (100%) rename tests/ui/suggestions/{object-unsafe-trait-references-self.rs => dyn-incompatible-trait-references-self.rs} (100%) rename tests/ui/suggestions/{object-unsafe-trait-references-self.stderr => dyn-incompatible-trait-references-self.stderr} (87%) rename tests/ui/suggestions/{object-unsafe-trait-should-use-self-2021-without-dyn.rs => dyn-incompatible-trait-should-use-self-2021-without-dyn.rs} (100%) rename tests/ui/suggestions/{object-unsafe-trait-should-use-self-2021-without-dyn.stderr => dyn-incompatible-trait-should-use-self-2021-without-dyn.stderr} (83%) rename tests/ui/suggestions/{object-unsafe-trait-should-use-self-2021.rs => dyn-incompatible-trait-should-use-self-2021.rs} (100%) rename tests/ui/suggestions/{object-unsafe-trait-should-use-self-2021.stderr => dyn-incompatible-trait-should-use-self-2021.stderr} (85%) rename tests/ui/suggestions/{object-unsafe-trait-should-use-self.rs => dyn-incompatible-trait-should-use-self.rs} (100%) rename tests/ui/suggestions/{object-unsafe-trait-should-use-self.stderr => dyn-incompatible-trait-should-use-self.stderr} (86%) rename tests/ui/suggestions/{object-unsafe-trait-should-use-where-sized.fixed => dyn-incompatible-trait-should-use-where-sized.fixed} (100%) rename tests/ui/suggestions/{object-unsafe-trait-should-use-where-sized.rs => dyn-incompatible-trait-should-use-where-sized.rs} (100%) rename tests/ui/suggestions/{object-unsafe-trait-should-use-where-sized.stderr => dyn-incompatible-trait-should-use-where-sized.stderr} (89%) rename tests/ui/traits/next-solver/{object-unsafety.rs => dyn-incompatibility.rs} (100%) rename tests/ui/traits/next-solver/{object-unsafety.stderr => dyn-incompatibility.stderr} (90%) rename tests/ui/traits/non_lifetime_binders/{supertrait-object-safety.rs => supertrait-dyn-compatibility.rs} (100%) rename tests/ui/traits/non_lifetime_binders/{supertrait-object-safety.stderr => supertrait-dyn-compatibility.stderr} (88%) rename tests/ui/traits/vtable/{vtable-non-object-safe.rs => vtable-dyn-incompatible.rs} (78%) rename tests/ui/traits/vtable/{vtable-non-object-safe.stderr => vtable-dyn-incompatible.stderr} (92%) rename tests/ui/unsized-locals/{by-value-trait-object-safety-rpass.rs => by-value-trait-dyn-compatibility-rpass.rs} (100%) rename tests/ui/unsized-locals/{by-value-trait-object-safety-withdefault.rs => by-value-trait-dyn-compatibility-with-default.rs} (100%) rename tests/ui/unsized-locals/{by-value-trait-object-safety.rs => by-value-trait-dyn-compatibility.rs} (100%) rename tests/ui/unsized-locals/{by-value-trait-object-safety.stderr => by-value-trait-dyn-compatibility.stderr} (84%) rename tests/ui/wf/{wf-convert-unsafe-trait-obj-box.rs => wf-convert-dyn-incompat-trait-obj-box.rs} (87%) rename tests/ui/wf/{wf-convert-unsafe-trait-obj-box.stderr => wf-convert-dyn-incompat-trait-obj-box.stderr} (86%) rename tests/ui/wf/{wf-convert-unsafe-trait-obj.rs => wf-convert-dyn-incompat-trait-obj.rs} (87%) rename tests/ui/wf/{wf-convert-unsafe-trait-obj.stderr => wf-convert-dyn-incompat-trait-obj.stderr} (87%) rename tests/ui/wf/{wf-unsafe-trait-obj-match.rs => wf-dyn-incompat-trait-obj-match.rs} (100%) rename tests/ui/wf/{wf-unsafe-trait-obj-match.stderr => wf-dyn-incompat-trait-obj-match.stderr} (89%) rename tests/ui/wf/{wf-object-safe.rs => wf-dyn-incompatible.rs} (57%) rename tests/ui/wf/{wf-object-safe.stderr => wf-dyn-incompatible.stderr} (90%) diff --git a/src/tools/tidy/src/issues.txt b/src/tools/tidy/src/issues.txt index 86cae849b9782..92aafc5a98e8a 100644 --- a/src/tools/tidy/src/issues.txt +++ b/src/tools/tidy/src/issues.txt @@ -3173,10 +3173,6 @@ ui/nll/user-annotations/issue-55241.rs ui/nll/user-annotations/issue-55748-pat-types-constrain-bindings.rs ui/nll/user-annotations/issue-57731-ascibed-coupled-types.rs ui/numbers-arithmetic/issue-8460.rs -ui/object-safety/issue-102762.rs -ui/object-safety/issue-102933.rs -ui/object-safety/issue-106247.rs -ui/object-safety/issue-19538.rs ui/on-unimplemented/issue-104140.rs ui/or-patterns/issue-64879-trailing-before-guard.rs ui/or-patterns/issue-67514-irrefutable-param.rs diff --git a/tests/ui/allocator/dyn-compatible.rs b/tests/ui/allocator/dyn-compatible.rs new file mode 100644 index 0000000000000..9d8235e58d929 --- /dev/null +++ b/tests/ui/allocator/dyn-compatible.rs @@ -0,0 +1,13 @@ +//@ run-pass + +// Check that `Allocator` is dyn-compatible, this allows for polymorphic allocators + +#![feature(allocator_api)] + +use std::alloc::{Allocator, System}; + +fn ensure_dyn_compatible(_: &dyn Allocator) {} + +fn main() { + ensure_dyn_compatible(&System); +} diff --git a/tests/ui/allocator/object-safe.rs b/tests/ui/allocator/object-safe.rs deleted file mode 100644 index 1c1f4fe0bf6ce..0000000000000 --- a/tests/ui/allocator/object-safe.rs +++ /dev/null @@ -1,13 +0,0 @@ -//@ run-pass - -// Check that `Allocator` is object safe, this allows for polymorphic allocators - -#![feature(allocator_api)] - -use std::alloc::{Allocator, System}; - -fn ensure_object_safe(_: &dyn Allocator) {} - -fn main() { - ensure_object_safe(&System); -} diff --git a/tests/ui/associated-type-bounds/entails-sized-object-safety.rs b/tests/ui/associated-type-bounds/entails-sized-dyn-compatibility.rs similarity index 67% rename from tests/ui/associated-type-bounds/entails-sized-object-safety.rs rename to tests/ui/associated-type-bounds/entails-sized-dyn-compatibility.rs index ad2cbe4820981..943df68493fb1 100644 --- a/tests/ui/associated-type-bounds/entails-sized-object-safety.rs +++ b/tests/ui/associated-type-bounds/entails-sized-dyn-compatibility.rs @@ -4,21 +4,21 @@ trait Tr1: Sized { type As1; } trait Tr2<'a>: Sized { type As2; } trait ObjTr1 { fn foo() -> Self where Self: Tr1; } -fn _assert_obj_safe_1(_: Box) {} +fn _assert_dyn_compat_1(_: Box) {} trait ObjTr2 { fn foo() -> Self where Self: Tr1; } -fn _assert_obj_safe_2(_: Box) {} +fn _assert_dyn_compat_2(_: Box) {} trait ObjTr3 { fn foo() -> Self where Self: Tr1 + 'static + Copy>; } -fn _assert_obj_safe_3(_: Box) {} +fn _assert_dyn_compat_3(_: Box) {} trait ObjTr4 { fn foo() -> Self where Self: Tr1 Tr2<'a>>; } -fn _assert_obj_safe_4(_: Box) {} +fn _assert_dyn_compat_4(_: Box) {} trait ObjTr5 { fn foo() -> Self where for<'a> Self: Tr1>; } -fn _assert_obj_safe_5(_: Box) {} +fn _assert_dyn_compat_5(_: Box) {} trait ObjTr6 { fn foo() -> Self where Self: for<'a> Tr1 Tr2<'b>>>; } -fn _assert_obj_safe_6(_: Box) {} +fn _assert_dyn_compat_6(_: Box) {} fn main() {} diff --git a/tests/ui/async-await/in-trait/object-safety.rs b/tests/ui/async-await/in-trait/dyn-compatibility.rs similarity index 100% rename from tests/ui/async-await/in-trait/object-safety.rs rename to tests/ui/async-await/in-trait/dyn-compatibility.rs diff --git a/tests/ui/async-await/in-trait/object-safety.stderr b/tests/ui/async-await/in-trait/dyn-compatibility.stderr similarity index 90% rename from tests/ui/async-await/in-trait/object-safety.stderr rename to tests/ui/async-await/in-trait/dyn-compatibility.stderr index 8e73abab9335f..5cc3b6800ddbc 100644 --- a/tests/ui/async-await/in-trait/object-safety.stderr +++ b/tests/ui/async-await/in-trait/dyn-compatibility.stderr @@ -1,11 +1,11 @@ error[E0038]: the trait `Foo` cannot be made into an object - --> $DIR/object-safety.rs:9:12 + --> $DIR/dyn-compatibility.rs:9:12 | LL | let x: &dyn Foo = todo!(); | ^^^^^^^^ `Foo` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/object-safety.rs:5:14 + --> $DIR/dyn-compatibility.rs:5:14 | LL | trait Foo { | --- this trait cannot be made into an object... diff --git a/tests/ui/coherence/coherence-impl-trait-for-trait-object-safe.rs b/tests/ui/coherence/coherence-impl-trait-for-trait-dyn-compatible.rs similarity index 54% rename from tests/ui/coherence/coherence-impl-trait-for-trait-object-safe.rs rename to tests/ui/coherence/coherence-impl-trait-for-trait-dyn-compatible.rs index bce3b0fd729fe..f41d3a783abca 100644 --- a/tests/ui/coherence/coherence-impl-trait-for-trait-object-safe.rs +++ b/tests/ui/coherence/coherence-impl-trait-for-trait-dyn-compatible.rs @@ -1,10 +1,10 @@ // Test that we give suitable error messages when the user attempts to // impl a trait `Trait` for its own object type. -// If the trait is not object-safe, we give a more tailored message +// If the trait is dyn-incompatible, we give a more tailored message // because we're such schnuckels: -trait NotObjectSafe { fn eq(&self, other: Self); } -impl NotObjectSafe for dyn NotObjectSafe { } +trait DynIncompatible { fn eq(&self, other: Self); } +impl DynIncompatible for dyn DynIncompatible { } //~^ ERROR E0038 //~| ERROR E0046 diff --git a/tests/ui/coherence/coherence-impl-trait-for-trait-dyn-compatible.stderr b/tests/ui/coherence/coherence-impl-trait-for-trait-dyn-compatible.stderr new file mode 100644 index 0000000000000..542be2dbc305c --- /dev/null +++ b/tests/ui/coherence/coherence-impl-trait-for-trait-dyn-compatible.stderr @@ -0,0 +1,27 @@ +error[E0038]: the trait `DynIncompatible` cannot be made into an object + --> $DIR/coherence-impl-trait-for-trait-dyn-compatible.rs:7:26 + | +LL | impl DynIncompatible for dyn DynIncompatible { } + | ^^^^^^^^^^^^^^^^^^^ `DynIncompatible` cannot be made into an object + | +note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $DIR/coherence-impl-trait-for-trait-dyn-compatible.rs:6:45 + | +LL | trait DynIncompatible { fn eq(&self, other: Self); } + | --------------- ^^^^ ...because method `eq` references the `Self` type in this parameter + | | + | this trait cannot be made into an object... + = help: consider moving `eq` to another trait + +error[E0046]: not all trait items implemented, missing: `eq` + --> $DIR/coherence-impl-trait-for-trait-dyn-compatible.rs:7:1 + | +LL | trait DynIncompatible { fn eq(&self, other: Self); } + | -------------------------- `eq` from trait +LL | impl DynIncompatible for dyn DynIncompatible { } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing `eq` in implementation + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0038, E0046. +For more information about an error, try `rustc --explain E0038`. diff --git a/tests/ui/coherence/coherence-impl-trait-for-trait-object-safe.stderr b/tests/ui/coherence/coherence-impl-trait-for-trait-object-safe.stderr deleted file mode 100644 index ce65e079ab45a..0000000000000 --- a/tests/ui/coherence/coherence-impl-trait-for-trait-object-safe.stderr +++ /dev/null @@ -1,27 +0,0 @@ -error[E0038]: the trait `NotObjectSafe` cannot be made into an object - --> $DIR/coherence-impl-trait-for-trait-object-safe.rs:7:24 - | -LL | impl NotObjectSafe for dyn NotObjectSafe { } - | ^^^^^^^^^^^^^^^^^ `NotObjectSafe` cannot be made into an object - | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/coherence-impl-trait-for-trait-object-safe.rs:6:43 - | -LL | trait NotObjectSafe { fn eq(&self, other: Self); } - | ------------- ^^^^ ...because method `eq` references the `Self` type in this parameter - | | - | this trait cannot be made into an object... - = help: consider moving `eq` to another trait - -error[E0046]: not all trait items implemented, missing: `eq` - --> $DIR/coherence-impl-trait-for-trait-object-safe.rs:7:1 - | -LL | trait NotObjectSafe { fn eq(&self, other: Self); } - | -------------------------- `eq` from trait -LL | impl NotObjectSafe for dyn NotObjectSafe { } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing `eq` in implementation - -error: aborting due to 2 previous errors - -Some errors have detailed explanations: E0038, E0046. -For more information about an error, try `rustc --explain E0038`. diff --git a/tests/ui/const-generics/adt_const_params/const_param_ty_object_safety.rs b/tests/ui/const-generics/adt_const_params/const_param_ty_dyn_compatibility.rs similarity index 100% rename from tests/ui/const-generics/adt_const_params/const_param_ty_object_safety.rs rename to tests/ui/const-generics/adt_const_params/const_param_ty_dyn_compatibility.rs diff --git a/tests/ui/const-generics/adt_const_params/const_param_ty_object_safety.stderr b/tests/ui/const-generics/adt_const_params/const_param_ty_dyn_compatibility.stderr similarity index 93% rename from tests/ui/const-generics/adt_const_params/const_param_ty_object_safety.stderr rename to tests/ui/const-generics/adt_const_params/const_param_ty_dyn_compatibility.stderr index 831b40887ac42..84281eb53c946 100644 --- a/tests/ui/const-generics/adt_const_params/const_param_ty_object_safety.stderr +++ b/tests/ui/const-generics/adt_const_params/const_param_ty_dyn_compatibility.stderr @@ -1,5 +1,5 @@ error[E0038]: the trait `ConstParamTy_` cannot be made into an object - --> $DIR/const_param_ty_object_safety.rs:6:12 + --> $DIR/const_param_ty_dyn_compatibility.rs:6:12 | LL | fn foo(a: &dyn ConstParamTy_) {} | ^^^^^^^^^^^^^^^^^ `ConstParamTy_` cannot be made into an object @@ -14,7 +14,7 @@ LL | fn foo(a: &impl ConstParamTy_) {} | ~~~~ error[E0038]: the trait `UnsizedConstParamTy` cannot be made into an object - --> $DIR/const_param_ty_object_safety.rs:9:12 + --> $DIR/const_param_ty_dyn_compatibility.rs:9:12 | LL | fn bar(a: &dyn UnsizedConstParamTy) {} | ^^^^^^^^^^^^^^^^^^^^^^^ `UnsizedConstParamTy` cannot be made into an object diff --git a/tests/ui/const-generics/generic_const_exprs/object-safety-err-ret.rs b/tests/ui/const-generics/generic_const_exprs/dyn-compatibility-err-ret.rs similarity index 100% rename from tests/ui/const-generics/generic_const_exprs/object-safety-err-ret.rs rename to tests/ui/const-generics/generic_const_exprs/dyn-compatibility-err-ret.rs diff --git a/tests/ui/const-generics/generic_const_exprs/object-safety-err-ret.stderr b/tests/ui/const-generics/generic_const_exprs/dyn-compatibility-err-ret.stderr similarity index 91% rename from tests/ui/const-generics/generic_const_exprs/object-safety-err-ret.stderr rename to tests/ui/const-generics/generic_const_exprs/dyn-compatibility-err-ret.stderr index fb57da42bb297..d2017615e67db 100644 --- a/tests/ui/const-generics/generic_const_exprs/object-safety-err-ret.stderr +++ b/tests/ui/const-generics/generic_const_exprs/dyn-compatibility-err-ret.stderr @@ -1,11 +1,11 @@ error[E0038]: the trait `Foo` cannot be made into an object - --> $DIR/object-safety-err-ret.rs:17:16 + --> $DIR/dyn-compatibility-err-ret.rs:17:16 | LL | fn use_dyn(v: &dyn Foo) { | ^^^^^^^ `Foo` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/object-safety-err-ret.rs:8:8 + --> $DIR/dyn-compatibility-err-ret.rs:8:8 | LL | trait Foo { | --- this trait cannot be made into an object... @@ -17,13 +17,13 @@ LL | fn test(&self) -> [u8; bar::()]; = help: only type `()` implements the trait, consider using it directly instead error[E0038]: the trait `Foo` cannot be made into an object - --> $DIR/object-safety-err-ret.rs:18:5 + --> $DIR/dyn-compatibility-err-ret.rs:18:5 | LL | v.test(); | ^^^^^^^^ `Foo` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/object-safety-err-ret.rs:8:8 + --> $DIR/dyn-compatibility-err-ret.rs:8:8 | LL | trait Foo { | --- this trait cannot be made into an object... diff --git a/tests/ui/const-generics/generic_const_exprs/object-safety-err-where-bounds.rs b/tests/ui/const-generics/generic_const_exprs/dyn-compatibility-err-where-bounds.rs similarity index 100% rename from tests/ui/const-generics/generic_const_exprs/object-safety-err-where-bounds.rs rename to tests/ui/const-generics/generic_const_exprs/dyn-compatibility-err-where-bounds.rs diff --git a/tests/ui/const-generics/generic_const_exprs/object-safety-err-where-bounds.stderr b/tests/ui/const-generics/generic_const_exprs/dyn-compatibility-err-where-bounds.stderr similarity index 88% rename from tests/ui/const-generics/generic_const_exprs/object-safety-err-where-bounds.stderr rename to tests/ui/const-generics/generic_const_exprs/dyn-compatibility-err-where-bounds.stderr index 831bda7129542..26ca2d4df5ffc 100644 --- a/tests/ui/const-generics/generic_const_exprs/object-safety-err-where-bounds.stderr +++ b/tests/ui/const-generics/generic_const_exprs/dyn-compatibility-err-where-bounds.stderr @@ -1,11 +1,11 @@ error[E0038]: the trait `Foo` cannot be made into an object - --> $DIR/object-safety-err-where-bounds.rs:15:16 + --> $DIR/dyn-compatibility-err-where-bounds.rs:15:16 | LL | fn use_dyn(v: &dyn Foo) { | ^^^^^^^ `Foo` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/object-safety-err-where-bounds.rs:8:8 + --> $DIR/dyn-compatibility-err-where-bounds.rs:8:8 | LL | trait Foo { | --- this trait cannot be made into an object... @@ -15,13 +15,13 @@ LL | fn test(&self) where [u8; bar::()]: Sized; = help: only type `()` implements the trait, consider using it directly instead error[E0038]: the trait `Foo` cannot be made into an object - --> $DIR/object-safety-err-where-bounds.rs:17:5 + --> $DIR/dyn-compatibility-err-where-bounds.rs:17:5 | LL | v.test(); | ^^^^^^^^ `Foo` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/object-safety-err-where-bounds.rs:8:8 + --> $DIR/dyn-compatibility-err-where-bounds.rs:8:8 | LL | trait Foo { | --- this trait cannot be made into an object... diff --git a/tests/ui/const-generics/generic_const_exprs/object-safety-ok-infer-err.rs b/tests/ui/const-generics/generic_const_exprs/dyn-compatibility-ok-infer-err.rs similarity index 100% rename from tests/ui/const-generics/generic_const_exprs/object-safety-ok-infer-err.rs rename to tests/ui/const-generics/generic_const_exprs/dyn-compatibility-ok-infer-err.rs diff --git a/tests/ui/const-generics/generic_const_exprs/object-safety-ok-infer-err.stderr b/tests/ui/const-generics/generic_const_exprs/dyn-compatibility-ok-infer-err.stderr similarity index 85% rename from tests/ui/const-generics/generic_const_exprs/object-safety-ok-infer-err.stderr rename to tests/ui/const-generics/generic_const_exprs/dyn-compatibility-ok-infer-err.stderr index d1e1c976da664..a124fbc60920d 100644 --- a/tests/ui/const-generics/generic_const_exprs/object-safety-ok-infer-err.stderr +++ b/tests/ui/const-generics/generic_const_exprs/dyn-compatibility-ok-infer-err.stderr @@ -1,11 +1,11 @@ error[E0284]: type annotations needed - --> $DIR/object-safety-ok-infer-err.rs:19:5 + --> $DIR/dyn-compatibility-ok-infer-err.rs:19:5 | LL | use_dyn(&()); | ^^^^^^^ cannot infer the value of the const parameter `N` declared on the function `use_dyn` | note: required by a const generic parameter in `use_dyn` - --> $DIR/object-safety-ok-infer-err.rs:14:12 + --> $DIR/dyn-compatibility-ok-infer-err.rs:14:12 | LL | fn use_dyn(v: &dyn Foo) where [u8; N + 1]: Sized { | ^^^^^^^^^^^^^^ required by this const generic parameter in `use_dyn` @@ -15,7 +15,7 @@ LL | use_dyn::(&()); | +++++ error[E0284]: type annotations needed - --> $DIR/object-safety-ok-infer-err.rs:19:5 + --> $DIR/dyn-compatibility-ok-infer-err.rs:19:5 | LL | use_dyn(&()); | ^^^^^^^ --- type must be known at this point @@ -23,7 +23,7 @@ LL | use_dyn(&()); | cannot infer the value of the const parameter `N` declared on the function `use_dyn` | note: required for `()` to implement `Foo<_>` - --> $DIR/object-safety-ok-infer-err.rs:8:22 + --> $DIR/dyn-compatibility-ok-infer-err.rs:8:22 | LL | impl Foo for () { | -------------- ^^^^^^ ^^ diff --git a/tests/ui/const-generics/generic_const_exprs/object-safety-ok.rs b/tests/ui/const-generics/generic_const_exprs/dyn-compatibility-ok.rs similarity index 100% rename from tests/ui/const-generics/generic_const_exprs/object-safety-ok.rs rename to tests/ui/const-generics/generic_const_exprs/dyn-compatibility-ok.rs diff --git a/tests/ui/object-safety/almost-supertrait-associated-type.rs b/tests/ui/dyn-compatibility/almost-supertrait-associated-type.rs similarity index 95% rename from tests/ui/object-safety/almost-supertrait-associated-type.rs rename to tests/ui/dyn-compatibility/almost-supertrait-associated-type.rs index 963cdff526ee6..83076f7d5fc3b 100644 --- a/tests/ui/object-safety/almost-supertrait-associated-type.rs +++ b/tests/ui/dyn-compatibility/almost-supertrait-associated-type.rs @@ -1,5 +1,5 @@ // Test for fixed unsoundness in #126079. -// Enforces that the associated types that are object safe +// Enforces that the associated types that are dyn-compatible. use std::marker::PhantomData; diff --git a/tests/ui/object-safety/almost-supertrait-associated-type.stderr b/tests/ui/dyn-compatibility/almost-supertrait-associated-type.stderr similarity index 100% rename from tests/ui/object-safety/almost-supertrait-associated-type.stderr rename to tests/ui/dyn-compatibility/almost-supertrait-associated-type.stderr diff --git a/tests/ui/object-safety/assoc_const_bounds.rs b/tests/ui/dyn-compatibility/assoc_const_bounds.rs similarity index 100% rename from tests/ui/object-safety/assoc_const_bounds.rs rename to tests/ui/dyn-compatibility/assoc_const_bounds.rs diff --git a/tests/ui/object-safety/assoc_const_bounds_sized.rs b/tests/ui/dyn-compatibility/assoc_const_bounds_sized.rs similarity index 100% rename from tests/ui/object-safety/assoc_const_bounds_sized.rs rename to tests/ui/dyn-compatibility/assoc_const_bounds_sized.rs diff --git a/tests/ui/object-safety/assoc_type_bounds.rs b/tests/ui/dyn-compatibility/assoc_type_bounds.rs similarity index 100% rename from tests/ui/object-safety/assoc_type_bounds.rs rename to tests/ui/dyn-compatibility/assoc_type_bounds.rs diff --git a/tests/ui/object-safety/assoc_type_bounds.stderr b/tests/ui/dyn-compatibility/assoc_type_bounds.stderr similarity index 100% rename from tests/ui/object-safety/assoc_type_bounds.stderr rename to tests/ui/dyn-compatibility/assoc_type_bounds.stderr diff --git a/tests/ui/object-safety/assoc_type_bounds2.rs b/tests/ui/dyn-compatibility/assoc_type_bounds2.rs similarity index 100% rename from tests/ui/object-safety/assoc_type_bounds2.rs rename to tests/ui/dyn-compatibility/assoc_type_bounds2.rs diff --git a/tests/ui/object-safety/assoc_type_bounds2.stderr b/tests/ui/dyn-compatibility/assoc_type_bounds2.stderr similarity index 100% rename from tests/ui/object-safety/assoc_type_bounds2.stderr rename to tests/ui/dyn-compatibility/assoc_type_bounds2.stderr diff --git a/tests/ui/object-safety/assoc_type_bounds_implicit_sized.fixed b/tests/ui/dyn-compatibility/assoc_type_bounds_implicit_sized.fixed similarity index 100% rename from tests/ui/object-safety/assoc_type_bounds_implicit_sized.fixed rename to tests/ui/dyn-compatibility/assoc_type_bounds_implicit_sized.fixed diff --git a/tests/ui/object-safety/assoc_type_bounds_implicit_sized.rs b/tests/ui/dyn-compatibility/assoc_type_bounds_implicit_sized.rs similarity index 100% rename from tests/ui/object-safety/assoc_type_bounds_implicit_sized.rs rename to tests/ui/dyn-compatibility/assoc_type_bounds_implicit_sized.rs diff --git a/tests/ui/object-safety/assoc_type_bounds_implicit_sized.stderr b/tests/ui/dyn-compatibility/assoc_type_bounds_implicit_sized.stderr similarity index 100% rename from tests/ui/object-safety/assoc_type_bounds_implicit_sized.stderr rename to tests/ui/dyn-compatibility/assoc_type_bounds_implicit_sized.stderr diff --git a/tests/ui/object-safety/assoc_type_bounds_sized.rs b/tests/ui/dyn-compatibility/assoc_type_bounds_sized.rs similarity index 100% rename from tests/ui/object-safety/assoc_type_bounds_sized.rs rename to tests/ui/dyn-compatibility/assoc_type_bounds_sized.rs diff --git a/tests/ui/object-safety/assoc_type_bounds_sized_others.rs b/tests/ui/dyn-compatibility/assoc_type_bounds_sized_others.rs similarity index 100% rename from tests/ui/object-safety/assoc_type_bounds_sized_others.rs rename to tests/ui/dyn-compatibility/assoc_type_bounds_sized_others.rs diff --git a/tests/ui/object-safety/assoc_type_bounds_sized_others.stderr b/tests/ui/dyn-compatibility/assoc_type_bounds_sized_others.stderr similarity index 100% rename from tests/ui/object-safety/assoc_type_bounds_sized_others.stderr rename to tests/ui/dyn-compatibility/assoc_type_bounds_sized_others.stderr diff --git a/tests/ui/object-safety/assoc_type_bounds_sized_unnecessary.rs b/tests/ui/dyn-compatibility/assoc_type_bounds_sized_unnecessary.rs similarity index 100% rename from tests/ui/object-safety/assoc_type_bounds_sized_unnecessary.rs rename to tests/ui/dyn-compatibility/assoc_type_bounds_sized_unnecessary.rs diff --git a/tests/ui/object-safety/assoc_type_bounds_sized_unnecessary.stderr b/tests/ui/dyn-compatibility/assoc_type_bounds_sized_unnecessary.stderr similarity index 100% rename from tests/ui/object-safety/assoc_type_bounds_sized_unnecessary.stderr rename to tests/ui/dyn-compatibility/assoc_type_bounds_sized_unnecessary.stderr diff --git a/tests/ui/object-safety/assoc_type_bounds_sized_used.rs b/tests/ui/dyn-compatibility/assoc_type_bounds_sized_used.rs similarity index 100% rename from tests/ui/object-safety/assoc_type_bounds_sized_used.rs rename to tests/ui/dyn-compatibility/assoc_type_bounds_sized_used.rs diff --git a/tests/ui/object-safety/assoc_type_bounds_sized_used.stderr b/tests/ui/dyn-compatibility/assoc_type_bounds_sized_used.stderr similarity index 100% rename from tests/ui/object-safety/assoc_type_bounds_sized_used.stderr rename to tests/ui/dyn-compatibility/assoc_type_bounds_sized_used.stderr diff --git a/tests/ui/object-safety/object-safety-associated-consts.curr.stderr b/tests/ui/dyn-compatibility/associated-consts.curr.stderr similarity index 86% rename from tests/ui/object-safety/object-safety-associated-consts.curr.stderr rename to tests/ui/dyn-compatibility/associated-consts.curr.stderr index 3c070f17c82ad..17d184942c701 100644 --- a/tests/ui/object-safety/object-safety-associated-consts.curr.stderr +++ b/tests/ui/dyn-compatibility/associated-consts.curr.stderr @@ -1,11 +1,11 @@ error[E0038]: the trait `Bar` cannot be made into an object - --> $DIR/object-safety-associated-consts.rs:12:31 + --> $DIR/associated-consts.rs:12:31 | LL | fn make_bar(t: &T) -> &dyn Bar { | ^^^^^^^ `Bar` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/object-safety-associated-consts.rs:9:11 + --> $DIR/associated-consts.rs:9:11 | LL | trait Bar { | --- this trait cannot be made into an object... @@ -14,13 +14,13 @@ LL | const X: usize; = help: consider moving `X` to another trait error[E0038]: the trait `Bar` cannot be made into an object - --> $DIR/object-safety-associated-consts.rs:14:5 + --> $DIR/associated-consts.rs:14:5 | LL | t | ^ `Bar` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/object-safety-associated-consts.rs:9:11 + --> $DIR/associated-consts.rs:9:11 | LL | trait Bar { | --- this trait cannot be made into an object... diff --git a/tests/ui/object-safety/object-safety-associated-consts.dyn_compatible_for_dispatch.stderr b/tests/ui/dyn-compatibility/associated-consts.dyn_compatible_for_dispatch.stderr similarity index 87% rename from tests/ui/object-safety/object-safety-associated-consts.dyn_compatible_for_dispatch.stderr rename to tests/ui/dyn-compatibility/associated-consts.dyn_compatible_for_dispatch.stderr index 5b98cc35505c6..cc5120232c244 100644 --- a/tests/ui/object-safety/object-safety-associated-consts.dyn_compatible_for_dispatch.stderr +++ b/tests/ui/dyn-compatibility/associated-consts.dyn_compatible_for_dispatch.stderr @@ -1,11 +1,11 @@ error[E0038]: the trait `Bar` cannot be made into an object - --> $DIR/object-safety-associated-consts.rs:14:5 + --> $DIR/associated-consts.rs:14:5 | LL | t | ^ `Bar` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/object-safety-associated-consts.rs:9:11 + --> $DIR/associated-consts.rs:9:11 | LL | trait Bar { | --- this trait cannot be made into an object... diff --git a/tests/ui/object-safety/object-safety-associated-consts.rs b/tests/ui/dyn-compatibility/associated-consts.rs similarity index 100% rename from tests/ui/object-safety/object-safety-associated-consts.rs rename to tests/ui/dyn-compatibility/associated-consts.rs diff --git a/tests/ui/object-safety/avoid-ice-on-warning-2.new.stderr b/tests/ui/dyn-compatibility/avoid-ice-on-warning-2.new.stderr similarity index 100% rename from tests/ui/object-safety/avoid-ice-on-warning-2.new.stderr rename to tests/ui/dyn-compatibility/avoid-ice-on-warning-2.new.stderr diff --git a/tests/ui/object-safety/avoid-ice-on-warning-2.old.stderr b/tests/ui/dyn-compatibility/avoid-ice-on-warning-2.old.stderr similarity index 100% rename from tests/ui/object-safety/avoid-ice-on-warning-2.old.stderr rename to tests/ui/dyn-compatibility/avoid-ice-on-warning-2.old.stderr diff --git a/tests/ui/object-safety/avoid-ice-on-warning-2.rs b/tests/ui/dyn-compatibility/avoid-ice-on-warning-2.rs similarity index 100% rename from tests/ui/object-safety/avoid-ice-on-warning-2.rs rename to tests/ui/dyn-compatibility/avoid-ice-on-warning-2.rs diff --git a/tests/ui/object-safety/avoid-ice-on-warning-3.new.stderr b/tests/ui/dyn-compatibility/avoid-ice-on-warning-3.new.stderr similarity index 100% rename from tests/ui/object-safety/avoid-ice-on-warning-3.new.stderr rename to tests/ui/dyn-compatibility/avoid-ice-on-warning-3.new.stderr diff --git a/tests/ui/object-safety/avoid-ice-on-warning-3.old.stderr b/tests/ui/dyn-compatibility/avoid-ice-on-warning-3.old.stderr similarity index 100% rename from tests/ui/object-safety/avoid-ice-on-warning-3.old.stderr rename to tests/ui/dyn-compatibility/avoid-ice-on-warning-3.old.stderr diff --git a/tests/ui/object-safety/avoid-ice-on-warning-3.rs b/tests/ui/dyn-compatibility/avoid-ice-on-warning-3.rs similarity index 100% rename from tests/ui/object-safety/avoid-ice-on-warning-3.rs rename to tests/ui/dyn-compatibility/avoid-ice-on-warning-3.rs diff --git a/tests/ui/object-safety/avoid-ice-on-warning.new.stderr b/tests/ui/dyn-compatibility/avoid-ice-on-warning.new.stderr similarity index 100% rename from tests/ui/object-safety/avoid-ice-on-warning.new.stderr rename to tests/ui/dyn-compatibility/avoid-ice-on-warning.new.stderr diff --git a/tests/ui/object-safety/avoid-ice-on-warning.old.stderr b/tests/ui/dyn-compatibility/avoid-ice-on-warning.old.stderr similarity index 100% rename from tests/ui/object-safety/avoid-ice-on-warning.old.stderr rename to tests/ui/dyn-compatibility/avoid-ice-on-warning.old.stderr diff --git a/tests/ui/object-safety/avoid-ice-on-warning.rs b/tests/ui/dyn-compatibility/avoid-ice-on-warning.rs similarity index 100% rename from tests/ui/object-safety/avoid-ice-on-warning.rs rename to tests/ui/dyn-compatibility/avoid-ice-on-warning.rs diff --git a/tests/ui/object-safety/bare-trait-dont-suggest-dyn.new.fixed b/tests/ui/dyn-compatibility/bare-trait-dont-suggest-dyn.new.fixed similarity index 100% rename from tests/ui/object-safety/bare-trait-dont-suggest-dyn.new.fixed rename to tests/ui/dyn-compatibility/bare-trait-dont-suggest-dyn.new.fixed diff --git a/tests/ui/object-safety/bare-trait-dont-suggest-dyn.new.stderr b/tests/ui/dyn-compatibility/bare-trait-dont-suggest-dyn.new.stderr similarity index 100% rename from tests/ui/object-safety/bare-trait-dont-suggest-dyn.new.stderr rename to tests/ui/dyn-compatibility/bare-trait-dont-suggest-dyn.new.stderr diff --git a/tests/ui/object-safety/bare-trait-dont-suggest-dyn.old.stderr b/tests/ui/dyn-compatibility/bare-trait-dont-suggest-dyn.old.stderr similarity index 100% rename from tests/ui/object-safety/bare-trait-dont-suggest-dyn.old.stderr rename to tests/ui/dyn-compatibility/bare-trait-dont-suggest-dyn.old.stderr diff --git a/tests/ui/object-safety/bare-trait-dont-suggest-dyn.rs b/tests/ui/dyn-compatibility/bare-trait-dont-suggest-dyn.rs similarity index 100% rename from tests/ui/object-safety/bare-trait-dont-suggest-dyn.rs rename to tests/ui/dyn-compatibility/bare-trait-dont-suggest-dyn.rs diff --git a/tests/ui/object-safety/object-safety-bounds.rs b/tests/ui/dyn-compatibility/bounds.rs similarity index 72% rename from tests/ui/object-safety/object-safety-bounds.rs rename to tests/ui/dyn-compatibility/bounds.rs index 44bd369324a4b..1e04d11c516cb 100644 --- a/tests/ui/object-safety/object-safety-bounds.rs +++ b/tests/ui/dyn-compatibility/bounds.rs @@ -1,4 +1,4 @@ -// Traits with bounds mentioning `Self` are not object safe +// Traits with bounds mentioning `Self` are dyn-incompatible. trait X { type U: PartialEq; diff --git a/tests/ui/object-safety/object-safety-bounds.stderr b/tests/ui/dyn-compatibility/bounds.stderr similarity index 89% rename from tests/ui/object-safety/object-safety-bounds.stderr rename to tests/ui/dyn-compatibility/bounds.stderr index 96a81a69639bd..9231d524fd173 100644 --- a/tests/ui/object-safety/object-safety-bounds.stderr +++ b/tests/ui/dyn-compatibility/bounds.stderr @@ -1,11 +1,11 @@ error[E0038]: the trait `X` cannot be made into an object - --> $DIR/object-safety-bounds.rs:7:15 + --> $DIR/bounds.rs:7:15 | LL | fn f() -> Box> { | ^^^^^^^^^^^^^^ `X` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/object-safety-bounds.rs:4:13 + --> $DIR/bounds.rs:4:13 | LL | trait X { | - this trait cannot be made into an object... diff --git a/tests/ui/object-safety/object-safety-by-value-self-use.rs b/tests/ui/dyn-compatibility/by-value-self-use.rs similarity index 79% rename from tests/ui/object-safety/object-safety-by-value-self-use.rs rename to tests/ui/dyn-compatibility/by-value-self-use.rs index 8e93c538217bb..3c04ec0cd888c 100644 --- a/tests/ui/object-safety/object-safety-by-value-self-use.rs +++ b/tests/ui/dyn-compatibility/by-value-self-use.rs @@ -1,4 +1,4 @@ -// Check that while a trait with by-value self is object-safe, we +// Check that while a trait with by-value self is dyn-compatible, we // can't actually invoke it from an object (yet...?). #![feature(rustc_attrs)] diff --git a/tests/ui/object-safety/object-safety-by-value-self-use.stderr b/tests/ui/dyn-compatibility/by-value-self-use.stderr similarity index 83% rename from tests/ui/object-safety/object-safety-by-value-self-use.stderr rename to tests/ui/dyn-compatibility/by-value-self-use.stderr index 1701f6059a8ee..14785b982a39e 100644 --- a/tests/ui/object-safety/object-safety-by-value-self-use.stderr +++ b/tests/ui/dyn-compatibility/by-value-self-use.stderr @@ -1,5 +1,5 @@ error[E0161]: cannot move a value of type `dyn Bar` - --> $DIR/object-safety-by-value-self-use.rs:15:5 + --> $DIR/by-value-self-use.rs:15:5 | LL | t.bar() | ^ the size of `dyn Bar` cannot be statically determined diff --git a/tests/ui/object-safety/object-safety-by-value-self.rs b/tests/ui/dyn-compatibility/by-value-self.rs similarity index 90% rename from tests/ui/object-safety/object-safety-by-value-self.rs rename to tests/ui/dyn-compatibility/by-value-self.rs index 0d20032327cae..a057a7ff0b57a 100644 --- a/tests/ui/object-safety/object-safety-by-value-self.rs +++ b/tests/ui/dyn-compatibility/by-value-self.rs @@ -1,4 +1,4 @@ -// Check that a trait with by-value self is considered object-safe. +// Check that a trait with by-value self is considered dyn-compatible. //@ build-pass (FIXME(62277): could be check-pass?) #![allow(dead_code)] diff --git a/tests/ui/object-safety/call-when-assoc-ty-is-sized.rs b/tests/ui/dyn-compatibility/call-when-assoc-ty-is-sized.rs similarity index 100% rename from tests/ui/object-safety/call-when-assoc-ty-is-sized.rs rename to tests/ui/dyn-compatibility/call-when-assoc-ty-is-sized.rs diff --git a/tests/ui/object-safety/issue-102933.rs b/tests/ui/dyn-compatibility/elaborated-predicates-ordering.rs similarity index 93% rename from tests/ui/object-safety/issue-102933.rs rename to tests/ui/dyn-compatibility/elaborated-predicates-ordering.rs index aa678fea17620..d3c3963a673d5 100644 --- a/tests/ui/object-safety/issue-102933.rs +++ b/tests/ui/dyn-compatibility/elaborated-predicates-ordering.rs @@ -1,4 +1,5 @@ //@ check-pass +// issue: rust-lang/rust#102933 use std::future::Future; diff --git a/tests/ui/object-safety/erroneous_signature.rs b/tests/ui/dyn-compatibility/erroneous_signature.rs similarity index 100% rename from tests/ui/object-safety/erroneous_signature.rs rename to tests/ui/dyn-compatibility/erroneous_signature.rs diff --git a/tests/ui/object-safety/erroneous_signature.stderr b/tests/ui/dyn-compatibility/erroneous_signature.stderr similarity index 100% rename from tests/ui/object-safety/erroneous_signature.stderr rename to tests/ui/dyn-compatibility/erroneous_signature.stderr diff --git a/tests/ui/object-safety/object-safety-generics.curr.stderr b/tests/ui/dyn-compatibility/generics.curr.stderr similarity index 88% rename from tests/ui/object-safety/object-safety-generics.curr.stderr rename to tests/ui/dyn-compatibility/generics.curr.stderr index 7528785d90b47..c63db38a080b4 100644 --- a/tests/ui/object-safety/object-safety-generics.curr.stderr +++ b/tests/ui/dyn-compatibility/generics.curr.stderr @@ -1,11 +1,11 @@ error[E0038]: the trait `Bar` cannot be made into an object - --> $DIR/object-safety-generics.rs:18:31 + --> $DIR/generics.rs:18:31 | LL | fn make_bar(t: &T) -> &dyn Bar { | ^^^^^^^ `Bar` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/object-safety-generics.rs:10:8 + --> $DIR/generics.rs:10:8 | LL | trait Bar { | --- this trait cannot be made into an object... @@ -14,13 +14,13 @@ LL | fn bar(&self, t: T); = help: consider moving `bar` to another trait error[E0038]: the trait `Bar` cannot be made into an object - --> $DIR/object-safety-generics.rs:25:40 + --> $DIR/generics.rs:25:40 | LL | fn make_bar_explicit(t: &T) -> &dyn Bar { | ^^^^^^^ `Bar` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/object-safety-generics.rs:10:8 + --> $DIR/generics.rs:10:8 | LL | trait Bar { | --- this trait cannot be made into an object... @@ -29,13 +29,13 @@ LL | fn bar(&self, t: T); = help: consider moving `bar` to another trait error[E0038]: the trait `Bar` cannot be made into an object - --> $DIR/object-safety-generics.rs:20:5 + --> $DIR/generics.rs:20:5 | LL | t | ^ `Bar` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/object-safety-generics.rs:10:8 + --> $DIR/generics.rs:10:8 | LL | trait Bar { | --- this trait cannot be made into an object... @@ -45,13 +45,13 @@ LL | fn bar(&self, t: T); = note: required for the cast from `&T` to `&dyn Bar` error[E0038]: the trait `Bar` cannot be made into an object - --> $DIR/object-safety-generics.rs:27:10 + --> $DIR/generics.rs:27:10 | LL | t as &dyn Bar | ^^^^^^^^ `Bar` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/object-safety-generics.rs:10:8 + --> $DIR/generics.rs:10:8 | LL | trait Bar { | --- this trait cannot be made into an object... @@ -60,13 +60,13 @@ LL | fn bar(&self, t: T); = help: consider moving `bar` to another trait error[E0038]: the trait `Bar` cannot be made into an object - --> $DIR/object-safety-generics.rs:27:5 + --> $DIR/generics.rs:27:5 | LL | t as &dyn Bar | ^ `Bar` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/object-safety-generics.rs:10:8 + --> $DIR/generics.rs:10:8 | LL | trait Bar { | --- this trait cannot be made into an object... diff --git a/tests/ui/object-safety/object-safety-generics.dyn_compatible_for_dispatch.stderr b/tests/ui/dyn-compatibility/generics.dyn_compatible_for_dispatch.stderr similarity index 89% rename from tests/ui/object-safety/object-safety-generics.dyn_compatible_for_dispatch.stderr rename to tests/ui/dyn-compatibility/generics.dyn_compatible_for_dispatch.stderr index 4686b994b33ed..ba2546ef2dc5c 100644 --- a/tests/ui/object-safety/object-safety-generics.dyn_compatible_for_dispatch.stderr +++ b/tests/ui/dyn-compatibility/generics.dyn_compatible_for_dispatch.stderr @@ -1,11 +1,11 @@ error[E0038]: the trait `Bar` cannot be made into an object - --> $DIR/object-safety-generics.rs:20:5 + --> $DIR/generics.rs:20:5 | LL | t | ^ `Bar` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/object-safety-generics.rs:10:8 + --> $DIR/generics.rs:10:8 | LL | trait Bar { | --- this trait cannot be made into an object... @@ -15,13 +15,13 @@ LL | fn bar(&self, t: T); = note: required for the cast from `&T` to `&dyn Bar` error[E0038]: the trait `Bar` cannot be made into an object - --> $DIR/object-safety-generics.rs:27:5 + --> $DIR/generics.rs:27:5 | LL | t as &dyn Bar | ^ `Bar` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/object-safety-generics.rs:10:8 + --> $DIR/generics.rs:10:8 | LL | trait Bar { | --- this trait cannot be made into an object... diff --git a/tests/ui/object-safety/object-safety-generics.rs b/tests/ui/dyn-compatibility/generics.rs similarity index 100% rename from tests/ui/object-safety/object-safety-generics.rs rename to tests/ui/dyn-compatibility/generics.rs diff --git a/tests/ui/object-safety/issue-106247.rs b/tests/ui/dyn-compatibility/impossible-predicates-multiple_supertrait_upcastable-check.rs similarity index 73% rename from tests/ui/object-safety/issue-106247.rs rename to tests/ui/dyn-compatibility/impossible-predicates-multiple_supertrait_upcastable-check.rs index 20a451a59a164..c2b8ecc141d7d 100644 --- a/tests/ui/object-safety/issue-106247.rs +++ b/tests/ui/dyn-compatibility/impossible-predicates-multiple_supertrait_upcastable-check.rs @@ -1,4 +1,5 @@ //@ check-pass +// issue: rust-lang/rust#106247 pub trait Trait { fn method(&self) where Self: Sync; diff --git a/tests/ui/object-safety/item-bounds-can-reference-self.rs b/tests/ui/dyn-compatibility/item-bounds-can-reference-self.rs similarity index 100% rename from tests/ui/object-safety/item-bounds-can-reference-self.rs rename to tests/ui/dyn-compatibility/item-bounds-can-reference-self.rs diff --git a/tests/ui/object-safety/issue-19538.rs b/tests/ui/dyn-compatibility/mention-correct-dyn-incompatible-trait.rs similarity index 90% rename from tests/ui/object-safety/issue-19538.rs rename to tests/ui/dyn-compatibility/mention-correct-dyn-incompatible-trait.rs index 7054ef41b1c82..1289d2d7874aa 100644 --- a/tests/ui/object-safety/issue-19538.rs +++ b/tests/ui/dyn-compatibility/mention-correct-dyn-incompatible-trait.rs @@ -1,3 +1,5 @@ +// issue: rust-lang/rust#19538 + trait Foo { fn foo(&self, val: T); } diff --git a/tests/ui/object-safety/issue-19538.stderr b/tests/ui/dyn-compatibility/mention-correct-dyn-incompatible-trait.stderr similarity index 87% rename from tests/ui/object-safety/issue-19538.stderr rename to tests/ui/dyn-compatibility/mention-correct-dyn-incompatible-trait.stderr index 3dbe389686a44..7378ec023c926 100644 --- a/tests/ui/object-safety/issue-19538.stderr +++ b/tests/ui/dyn-compatibility/mention-correct-dyn-incompatible-trait.stderr @@ -1,11 +1,11 @@ error[E0038]: the trait `Bar` cannot be made into an object - --> $DIR/issue-19538.rs:17:15 + --> $DIR/mention-correct-dyn-incompatible-trait.rs:19:15 | LL | let test: &mut dyn Bar = &mut thing; | ^^^^^^^^^^^^ `Bar` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/issue-19538.rs:2:8 + --> $DIR/mention-correct-dyn-incompatible-trait.rs:4:8 | LL | fn foo(&self, val: T); | ^^^ ...because method `foo` has generic type parameters @@ -16,13 +16,13 @@ LL | trait Bar: Foo { } = help: only type `Thing` implements the trait, consider using it directly instead error[E0038]: the trait `Bar` cannot be made into an object - --> $DIR/issue-19538.rs:17:30 + --> $DIR/mention-correct-dyn-incompatible-trait.rs:19:30 | LL | let test: &mut dyn Bar = &mut thing; | ^^^^^^^^^^ `Bar` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/issue-19538.rs:2:8 + --> $DIR/mention-correct-dyn-incompatible-trait.rs:4:8 | LL | fn foo(&self, val: T); | ^^^ ...because method `foo` has generic type parameters diff --git a/tests/ui/object-safety/object-safety-issue-22040.rs b/tests/ui/dyn-compatibility/mentions-Self-in-super-predicates.rs similarity index 100% rename from tests/ui/object-safety/object-safety-issue-22040.rs rename to tests/ui/dyn-compatibility/mentions-Self-in-super-predicates.rs diff --git a/tests/ui/object-safety/object-safety-issue-22040.stderr b/tests/ui/dyn-compatibility/mentions-Self-in-super-predicates.stderr similarity index 87% rename from tests/ui/object-safety/object-safety-issue-22040.stderr rename to tests/ui/dyn-compatibility/mentions-Self-in-super-predicates.stderr index e5723f12258fe..7578edce7d19e 100644 --- a/tests/ui/object-safety/object-safety-issue-22040.stderr +++ b/tests/ui/dyn-compatibility/mentions-Self-in-super-predicates.stderr @@ -1,11 +1,11 @@ error[E0038]: the trait `Expr` cannot be made into an object - --> $DIR/object-safety-issue-22040.rs:12:23 + --> $DIR/mentions-Self-in-super-predicates.rs:12:23 | LL | elements: Vec>, | ^^^^^^^^^^^^^ `Expr` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/object-safety-issue-22040.rs:5:21 + --> $DIR/mentions-Self-in-super-predicates.rs:5:21 | LL | trait Expr: Debug + PartialEq { | ---- ^^^^^^^^^ ...because it uses `Self` as a type parameter @@ -14,13 +14,13 @@ LL | trait Expr: Debug + PartialEq { = help: only type `SExpr<'x>` implements the trait, consider using it directly instead error[E0038]: the trait `Expr` cannot be made into an object - --> $DIR/object-safety-issue-22040.rs:38:16 + --> $DIR/mentions-Self-in-super-predicates.rs:38:16 | LL | let a: Box = Box::new(SExpr::new()); | ^^^^^^^^ `Expr` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/object-safety-issue-22040.rs:5:21 + --> $DIR/mentions-Self-in-super-predicates.rs:5:21 | LL | trait Expr: Debug + PartialEq { | ---- ^^^^^^^^^ ...because it uses `Self` as a type parameter @@ -29,13 +29,13 @@ LL | trait Expr: Debug + PartialEq { = help: only type `SExpr<'x>` implements the trait, consider using it directly instead error[E0038]: the trait `Expr` cannot be made into an object - --> $DIR/object-safety-issue-22040.rs:40:16 + --> $DIR/mentions-Self-in-super-predicates.rs:40:16 | LL | let b: Box = Box::new(SExpr::new()); | ^^^^^^^^ `Expr` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/object-safety-issue-22040.rs:5:21 + --> $DIR/mentions-Self-in-super-predicates.rs:5:21 | LL | trait Expr: Debug + PartialEq { | ---- ^^^^^^^^^ ...because it uses `Self` as a type parameter diff --git a/tests/ui/object-safety/object-safety-mentions-Self.curr.stderr b/tests/ui/dyn-compatibility/mentions-Self.curr.stderr similarity index 88% rename from tests/ui/object-safety/object-safety-mentions-Self.curr.stderr rename to tests/ui/dyn-compatibility/mentions-Self.curr.stderr index 7efb6ec3542d0..434e41cf2182d 100644 --- a/tests/ui/object-safety/object-safety-mentions-Self.curr.stderr +++ b/tests/ui/dyn-compatibility/mentions-Self.curr.stderr @@ -1,11 +1,11 @@ error[E0038]: the trait `Bar` cannot be made into an object - --> $DIR/object-safety-mentions-Self.rs:22:31 + --> $DIR/mentions-Self.rs:22:31 | LL | fn make_bar(t: &T) -> &dyn Bar { | ^^^^^^^ `Bar` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/object-safety-mentions-Self.rs:11:22 + --> $DIR/mentions-Self.rs:11:22 | LL | trait Bar { | --- this trait cannot be made into an object... @@ -14,13 +14,13 @@ LL | fn bar(&self, x: &Self); = help: consider moving `bar` to another trait error[E0038]: the trait `Baz` cannot be made into an object - --> $DIR/object-safety-mentions-Self.rs:28:31 + --> $DIR/mentions-Self.rs:28:31 | LL | fn make_baz(t: &T) -> &dyn Baz { | ^^^^^^^ `Baz` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/object-safety-mentions-Self.rs:15:22 + --> $DIR/mentions-Self.rs:15:22 | LL | trait Baz { | --- this trait cannot be made into an object... @@ -29,13 +29,13 @@ LL | fn baz(&self) -> Self; = help: consider moving `baz` to another trait error[E0038]: the trait `Bar` cannot be made into an object - --> $DIR/object-safety-mentions-Self.rs:24:5 + --> $DIR/mentions-Self.rs:24:5 | LL | t | ^ `Bar` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/object-safety-mentions-Self.rs:11:22 + --> $DIR/mentions-Self.rs:11:22 | LL | trait Bar { | --- this trait cannot be made into an object... @@ -45,13 +45,13 @@ LL | fn bar(&self, x: &Self); = note: required for the cast from `&T` to `&dyn Bar` error[E0038]: the trait `Baz` cannot be made into an object - --> $DIR/object-safety-mentions-Self.rs:30:5 + --> $DIR/mentions-Self.rs:30:5 | LL | t | ^ `Baz` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/object-safety-mentions-Self.rs:15:22 + --> $DIR/mentions-Self.rs:15:22 | LL | trait Baz { | --- this trait cannot be made into an object... diff --git a/tests/ui/object-safety/object-safety-mentions-Self.dyn_compatible_for_dispatch.stderr b/tests/ui/dyn-compatibility/mentions-Self.dyn_compatible_for_dispatch.stderr similarity index 88% rename from tests/ui/object-safety/object-safety-mentions-Self.dyn_compatible_for_dispatch.stderr rename to tests/ui/dyn-compatibility/mentions-Self.dyn_compatible_for_dispatch.stderr index d0efb9c587e4e..dc2d1f87eb737 100644 --- a/tests/ui/object-safety/object-safety-mentions-Self.dyn_compatible_for_dispatch.stderr +++ b/tests/ui/dyn-compatibility/mentions-Self.dyn_compatible_for_dispatch.stderr @@ -1,11 +1,11 @@ error[E0038]: the trait `Bar` cannot be made into an object - --> $DIR/object-safety-mentions-Self.rs:24:5 + --> $DIR/mentions-Self.rs:24:5 | LL | t | ^ `Bar` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/object-safety-mentions-Self.rs:11:22 + --> $DIR/mentions-Self.rs:11:22 | LL | trait Bar { | --- this trait cannot be made into an object... @@ -15,13 +15,13 @@ LL | fn bar(&self, x: &Self); = note: required for the cast from `&T` to `&dyn Bar` error[E0038]: the trait `Baz` cannot be made into an object - --> $DIR/object-safety-mentions-Self.rs:30:5 + --> $DIR/mentions-Self.rs:30:5 | LL | t | ^ `Baz` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/object-safety-mentions-Self.rs:15:22 + --> $DIR/mentions-Self.rs:15:22 | LL | trait Baz { | --- this trait cannot be made into an object... diff --git a/tests/ui/object-safety/object-safety-mentions-Self.rs b/tests/ui/dyn-compatibility/mentions-Self.rs similarity index 100% rename from tests/ui/object-safety/object-safety-mentions-Self.rs rename to tests/ui/dyn-compatibility/mentions-Self.rs diff --git a/tests/ui/traits/object/object-unsafe-missing-assoc-type.rs b/tests/ui/dyn-compatibility/missing-assoc-type.rs similarity index 100% rename from tests/ui/traits/object/object-unsafe-missing-assoc-type.rs rename to tests/ui/dyn-compatibility/missing-assoc-type.rs diff --git a/tests/ui/traits/object/object-unsafe-missing-assoc-type.stderr b/tests/ui/dyn-compatibility/missing-assoc-type.stderr similarity index 86% rename from tests/ui/traits/object/object-unsafe-missing-assoc-type.stderr rename to tests/ui/dyn-compatibility/missing-assoc-type.stderr index 9258b38f26c3a..f8450ba212d03 100644 --- a/tests/ui/traits/object/object-unsafe-missing-assoc-type.stderr +++ b/tests/ui/dyn-compatibility/missing-assoc-type.stderr @@ -1,11 +1,11 @@ error[E0038]: the trait `Foo` cannot be made into an object - --> $DIR/object-unsafe-missing-assoc-type.rs:5:16 + --> $DIR/missing-assoc-type.rs:5:16 | LL | fn bar(x: &dyn Foo) {} | ^^^ `Foo` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/object-unsafe-missing-assoc-type.rs:2:10 + --> $DIR/missing-assoc-type.rs:2:10 | LL | trait Foo { | --- this trait cannot be made into an object... @@ -14,13 +14,13 @@ LL | type Bar; = help: consider moving `Bar` to another trait error[E0038]: the trait `Foo` cannot be made into an object - --> $DIR/object-unsafe-missing-assoc-type.rs:5:16 + --> $DIR/missing-assoc-type.rs:5:16 | LL | fn bar(x: &dyn Foo) {} | ^^^ `Foo` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/object-unsafe-missing-assoc-type.rs:2:10 + --> $DIR/missing-assoc-type.rs:2:10 | LL | trait Foo { | --- this trait cannot be made into an object... @@ -30,13 +30,13 @@ LL | type Bar; = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error[E0038]: the trait `Foo` cannot be made into an object - --> $DIR/object-unsafe-missing-assoc-type.rs:5:16 + --> $DIR/missing-assoc-type.rs:5:16 | LL | fn bar(x: &dyn Foo) {} | ^^^ `Foo` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/object-unsafe-missing-assoc-type.rs:2:10 + --> $DIR/missing-assoc-type.rs:2:10 | LL | trait Foo { | --- this trait cannot be made into an object... @@ -46,13 +46,13 @@ LL | type Bar; = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error[E0038]: the trait `Foo` cannot be made into an object - --> $DIR/object-unsafe-missing-assoc-type.rs:5:12 + --> $DIR/missing-assoc-type.rs:5:12 | LL | fn bar(x: &dyn Foo) {} | ^^^^^^^ `Foo` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/object-unsafe-missing-assoc-type.rs:2:10 + --> $DIR/missing-assoc-type.rs:2:10 | LL | trait Foo { | --- this trait cannot be made into an object... diff --git a/tests/ui/object-safety/object-safety-no-static.curr.stderr b/tests/ui/dyn-compatibility/no-static.curr.stderr similarity index 92% rename from tests/ui/object-safety/object-safety-no-static.curr.stderr rename to tests/ui/dyn-compatibility/no-static.curr.stderr index 91c3d89602e86..584db77985566 100644 --- a/tests/ui/object-safety/object-safety-no-static.curr.stderr +++ b/tests/ui/dyn-compatibility/no-static.curr.stderr @@ -1,11 +1,11 @@ error[E0038]: the trait `Foo` cannot be made into an object - --> $DIR/object-safety-no-static.rs:12:22 + --> $DIR/no-static.rs:12:22 | LL | fn diverges() -> Box { | ^^^^^^^ `Foo` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/object-safety-no-static.rs:9:8 + --> $DIR/no-static.rs:9:8 | LL | trait Foo { | --- this trait cannot be made into an object... @@ -22,13 +22,13 @@ LL | fn foo() where Self: Sized {} | +++++++++++++++++ error[E0038]: the trait `Foo` cannot be made into an object - --> $DIR/object-safety-no-static.rs:22:12 + --> $DIR/no-static.rs:22:12 | LL | let b: Box = Box::new(Bar); | ^^^^^^^^^^^^ `Foo` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/object-safety-no-static.rs:9:8 + --> $DIR/no-static.rs:9:8 | LL | trait Foo { | --- this trait cannot be made into an object... @@ -45,13 +45,13 @@ LL | fn foo() where Self: Sized {} | +++++++++++++++++ error[E0038]: the trait `Foo` cannot be made into an object - --> $DIR/object-safety-no-static.rs:22:27 + --> $DIR/no-static.rs:22:27 | LL | let b: Box = Box::new(Bar); | ^^^^^^^^^^^^^ `Foo` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/object-safety-no-static.rs:9:8 + --> $DIR/no-static.rs:9:8 | LL | trait Foo { | --- this trait cannot be made into an object... diff --git a/tests/ui/object-safety/object-safety-no-static.dyn_compatible_for_dispatch.stderr b/tests/ui/dyn-compatibility/no-static.dyn_compatible_for_dispatch.stderr similarity index 93% rename from tests/ui/object-safety/object-safety-no-static.dyn_compatible_for_dispatch.stderr rename to tests/ui/dyn-compatibility/no-static.dyn_compatible_for_dispatch.stderr index 52f6865b6f3cb..f2deb3b8d84b9 100644 --- a/tests/ui/object-safety/object-safety-no-static.dyn_compatible_for_dispatch.stderr +++ b/tests/ui/dyn-compatibility/no-static.dyn_compatible_for_dispatch.stderr @@ -1,11 +1,11 @@ error[E0038]: the trait `Foo` cannot be made into an object - --> $DIR/object-safety-no-static.rs:22:27 + --> $DIR/no-static.rs:22:27 | LL | let b: Box = Box::new(Bar); | ^^^^^^^^^^^^^ `Foo` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/object-safety-no-static.rs:9:8 + --> $DIR/no-static.rs:9:8 | LL | trait Foo { | --- this trait cannot be made into an object... diff --git a/tests/ui/object-safety/object-safety-no-static.rs b/tests/ui/dyn-compatibility/no-static.rs similarity index 100% rename from tests/ui/object-safety/object-safety-no-static.rs rename to tests/ui/dyn-compatibility/no-static.rs diff --git a/tests/ui/object-safety/object-safety-phantom-fn.rs b/tests/ui/dyn-compatibility/phantom-fn.rs similarity index 92% rename from tests/ui/object-safety/object-safety-phantom-fn.rs rename to tests/ui/dyn-compatibility/phantom-fn.rs index 1019c24859fba..9e410da82eed5 100644 --- a/tests/ui/object-safety/object-safety-phantom-fn.rs +++ b/tests/ui/dyn-compatibility/phantom-fn.rs @@ -1,4 +1,4 @@ -// Check that `Self` appearing in a phantom fn does not make a trait not object safe. +// Check that `Self` appearing in a phantom fn does not make a trait dyn-incompatible. //@ build-pass (FIXME(62277): could be check-pass?) #![allow(dead_code)] diff --git a/tests/ui/object-safety/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs b/tests/ui/dyn-compatibility/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs similarity index 100% rename from tests/ui/object-safety/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs rename to tests/ui/dyn-compatibility/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs diff --git a/tests/ui/object-safety/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.stderr b/tests/ui/dyn-compatibility/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.stderr similarity index 100% rename from tests/ui/object-safety/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.stderr rename to tests/ui/dyn-compatibility/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.stderr diff --git a/tests/ui/object-safety/object-safety-sized-2.curr.stderr b/tests/ui/dyn-compatibility/sized-2.curr.stderr similarity index 88% rename from tests/ui/object-safety/object-safety-sized-2.curr.stderr rename to tests/ui/dyn-compatibility/sized-2.curr.stderr index 4ce7ac5704e42..1017fde53d313 100644 --- a/tests/ui/object-safety/object-safety-sized-2.curr.stderr +++ b/tests/ui/dyn-compatibility/sized-2.curr.stderr @@ -1,11 +1,11 @@ error[E0038]: the trait `Bar` cannot be made into an object - --> $DIR/object-safety-sized-2.rs:14:31 + --> $DIR/sized-2.rs:14:31 | LL | fn make_bar(t: &T) -> &dyn Bar { | ^^^^^^^ `Bar` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/object-safety-sized-2.rs:9:18 + --> $DIR/sized-2.rs:9:18 | LL | trait Bar | --- this trait cannot be made into an object... @@ -13,13 +13,13 @@ LL | where Self : Sized | ^^^^^ ...because it requires `Self: Sized` error[E0038]: the trait `Bar` cannot be made into an object - --> $DIR/object-safety-sized-2.rs:16:5 + --> $DIR/sized-2.rs:16:5 | LL | t | ^ `Bar` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/object-safety-sized-2.rs:9:18 + --> $DIR/sized-2.rs:9:18 | LL | trait Bar | --- this trait cannot be made into an object... diff --git a/tests/ui/object-safety/object-safety-sized-2.dyn_compatible_for_dispatch.stderr b/tests/ui/dyn-compatibility/sized-2.dyn_compatible_for_dispatch.stderr similarity index 89% rename from tests/ui/object-safety/object-safety-sized-2.dyn_compatible_for_dispatch.stderr rename to tests/ui/dyn-compatibility/sized-2.dyn_compatible_for_dispatch.stderr index 99066c104b7cb..534cf0f1b033f 100644 --- a/tests/ui/object-safety/object-safety-sized-2.dyn_compatible_for_dispatch.stderr +++ b/tests/ui/dyn-compatibility/sized-2.dyn_compatible_for_dispatch.stderr @@ -1,11 +1,11 @@ error[E0038]: the trait `Bar` cannot be made into an object - --> $DIR/object-safety-sized-2.rs:16:5 + --> $DIR/sized-2.rs:16:5 | LL | t | ^ `Bar` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/object-safety-sized-2.rs:9:18 + --> $DIR/sized-2.rs:9:18 | LL | trait Bar | --- this trait cannot be made into an object... diff --git a/tests/ui/object-safety/object-safety-sized-2.rs b/tests/ui/dyn-compatibility/sized-2.rs similarity index 100% rename from tests/ui/object-safety/object-safety-sized-2.rs rename to tests/ui/dyn-compatibility/sized-2.rs diff --git a/tests/ui/object-safety/object-safety-sized.curr.stderr b/tests/ui/dyn-compatibility/sized.curr.stderr similarity index 88% rename from tests/ui/object-safety/object-safety-sized.curr.stderr rename to tests/ui/dyn-compatibility/sized.curr.stderr index b61f968d90210..613833aad12ee 100644 --- a/tests/ui/object-safety/object-safety-sized.curr.stderr +++ b/tests/ui/dyn-compatibility/sized.curr.stderr @@ -1,11 +1,11 @@ error[E0038]: the trait `Bar` cannot be made into an object - --> $DIR/object-safety-sized.rs:12:32 + --> $DIR/sized.rs:12:32 | LL | fn make_bar(t: &T) -> &dyn Bar { | ^^^^^^^ `Bar` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/object-safety-sized.rs:8:12 + --> $DIR/sized.rs:8:12 | LL | trait Bar: Sized { | --- ^^^^^ ...because it requires `Self: Sized` @@ -13,13 +13,13 @@ LL | trait Bar: Sized { | this trait cannot be made into an object... error[E0038]: the trait `Bar` cannot be made into an object - --> $DIR/object-safety-sized.rs:14:5 + --> $DIR/sized.rs:14:5 | LL | t | ^ `Bar` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/object-safety-sized.rs:8:12 + --> $DIR/sized.rs:8:12 | LL | trait Bar: Sized { | --- ^^^^^ ...because it requires `Self: Sized` diff --git a/tests/ui/object-safety/object-safety-sized.dyn_compatible_for_dispatch.stderr b/tests/ui/dyn-compatibility/sized.dyn_compatible_for_dispatch.stderr similarity index 89% rename from tests/ui/object-safety/object-safety-sized.dyn_compatible_for_dispatch.stderr rename to tests/ui/dyn-compatibility/sized.dyn_compatible_for_dispatch.stderr index 5ce713375a49a..cf847bc157785 100644 --- a/tests/ui/object-safety/object-safety-sized.dyn_compatible_for_dispatch.stderr +++ b/tests/ui/dyn-compatibility/sized.dyn_compatible_for_dispatch.stderr @@ -1,11 +1,11 @@ error[E0038]: the trait `Bar` cannot be made into an object - --> $DIR/object-safety-sized.rs:14:5 + --> $DIR/sized.rs:14:5 | LL | t | ^ `Bar` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/object-safety-sized.rs:8:12 + --> $DIR/sized.rs:8:12 | LL | trait Bar: Sized { | --- ^^^^^ ...because it requires `Self: Sized` diff --git a/tests/ui/object-safety/object-safety-sized.rs b/tests/ui/dyn-compatibility/sized.rs similarity index 100% rename from tests/ui/object-safety/object-safety-sized.rs rename to tests/ui/dyn-compatibility/sized.rs diff --git a/tests/ui/object-safety/object-safety-supertrait-mentions-GAT.rs b/tests/ui/dyn-compatibility/supertrait-mentions-GAT.rs similarity index 100% rename from tests/ui/object-safety/object-safety-supertrait-mentions-GAT.rs rename to tests/ui/dyn-compatibility/supertrait-mentions-GAT.rs diff --git a/tests/ui/object-safety/object-safety-supertrait-mentions-GAT.stderr b/tests/ui/dyn-compatibility/supertrait-mentions-GAT.stderr similarity index 86% rename from tests/ui/object-safety/object-safety-supertrait-mentions-GAT.stderr rename to tests/ui/dyn-compatibility/supertrait-mentions-GAT.stderr index 4d44627e77926..ac5a5b28d94d4 100644 --- a/tests/ui/object-safety/object-safety-supertrait-mentions-GAT.stderr +++ b/tests/ui/dyn-compatibility/supertrait-mentions-GAT.stderr @@ -1,14 +1,14 @@ error[E0311]: the parameter type `Self` may not live long enough | note: ...that is required by this bound - --> $DIR/object-safety-supertrait-mentions-GAT.rs:6:15 + --> $DIR/supertrait-mentions-GAT.rs:6:15 | LL | Self: 'a; | ^^ = help: consider adding an explicit lifetime bound `Self: 'a`... error: associated item referring to unboxed trait object for its own trait - --> $DIR/object-safety-supertrait-mentions-GAT.rs:10:20 + --> $DIR/supertrait-mentions-GAT.rs:10:20 | LL | trait SuperTrait: for<'a> GatTrait = T> { | ---------- in this trait @@ -21,13 +21,13 @@ LL | fn c(&self) -> Self; | ~~~~ error[E0038]: the trait `SuperTrait` cannot be made into an object - --> $DIR/object-safety-supertrait-mentions-GAT.rs:10:20 + --> $DIR/supertrait-mentions-GAT.rs:10:20 | LL | fn c(&self) -> dyn SuperTrait; | ^^^^^^^^^^^^^^^^^ `SuperTrait` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/object-safety-supertrait-mentions-GAT.rs:4:10 + --> $DIR/supertrait-mentions-GAT.rs:4:10 | LL | type Gat<'a> | ^^^ ...because it contains the generic associated type `Gat` diff --git a/tests/ui/object-safety/object-safety-supertrait-mentions-Self.rs b/tests/ui/dyn-compatibility/supertrait-mentions-Self.rs similarity index 100% rename from tests/ui/object-safety/object-safety-supertrait-mentions-Self.rs rename to tests/ui/dyn-compatibility/supertrait-mentions-Self.rs diff --git a/tests/ui/object-safety/object-safety-supertrait-mentions-Self.stderr b/tests/ui/dyn-compatibility/supertrait-mentions-Self.stderr similarity index 86% rename from tests/ui/object-safety/object-safety-supertrait-mentions-Self.stderr rename to tests/ui/dyn-compatibility/supertrait-mentions-Self.stderr index b1a70fb859d7f..6474b115c4628 100644 --- a/tests/ui/object-safety/object-safety-supertrait-mentions-Self.stderr +++ b/tests/ui/dyn-compatibility/supertrait-mentions-Self.stderr @@ -1,11 +1,11 @@ error[E0277]: the size for values of type `Self` cannot be known at compilation time - --> $DIR/object-safety-supertrait-mentions-Self.rs:8:13 + --> $DIR/supertrait-mentions-Self.rs:8:13 | LL | trait Baz : Bar { | ^^^^^^^^^ doesn't have a size known at compile-time | note: required by an implicit `Sized` bound in `Bar` - --> $DIR/object-safety-supertrait-mentions-Self.rs:4:11 + --> $DIR/supertrait-mentions-Self.rs:4:11 | LL | trait Bar { | ^ required by the implicit `Sized` requirement on this type parameter in `Bar` @@ -19,13 +19,13 @@ LL | trait Bar { | ++++++++ error[E0038]: the trait `Baz` cannot be made into an object - --> $DIR/object-safety-supertrait-mentions-Self.rs:16:31 + --> $DIR/supertrait-mentions-Self.rs:16:31 | LL | fn make_baz(t: &T) -> &dyn Baz { | ^^^^^^^ `Baz` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/object-safety-supertrait-mentions-Self.rs:8:13 + --> $DIR/supertrait-mentions-Self.rs:8:13 | LL | trait Baz : Bar { | --- ^^^^^^^^^ ...because it uses `Self` as a type parameter diff --git a/tests/ui/object-safety/issue-102762.rs b/tests/ui/dyn-compatibility/undispatchable-receiver-and-wc-references-Self.rs similarity index 79% rename from tests/ui/object-safety/issue-102762.rs rename to tests/ui/dyn-compatibility/undispatchable-receiver-and-wc-references-Self.rs index 576f73e08bcf9..5c71bd7769ce1 100644 --- a/tests/ui/object-safety/issue-102762.rs +++ b/tests/ui/dyn-compatibility/undispatchable-receiver-and-wc-references-Self.rs @@ -1,7 +1,8 @@ //@ compile-flags: --crate-type=lib // This test checks that the `where_clauses_object_safety` lint does not cause -// other object safety *hard errors* to be suppressed, because we currently -// only emit one object safety error per trait... +// other dyn-compatibility *hard errors* to be suppressed, because we currently +// only emit one dyn-compatibility error per trait... +// issue: rust-lang/rust#102762 use std::future::Future; use std::pin::Pin; diff --git a/tests/ui/object-safety/issue-102762.stderr b/tests/ui/dyn-compatibility/undispatchable-receiver-and-wc-references-Self.stderr similarity index 87% rename from tests/ui/object-safety/issue-102762.stderr rename to tests/ui/dyn-compatibility/undispatchable-receiver-and-wc-references-Self.stderr index 05451eb8399cf..8d62ac9d923f9 100644 --- a/tests/ui/object-safety/issue-102762.stderr +++ b/tests/ui/dyn-compatibility/undispatchable-receiver-and-wc-references-Self.stderr @@ -1,5 +1,5 @@ error[E0038]: the trait `Fetcher` cannot be made into an object - --> $DIR/issue-102762.rs:18:21 + --> $DIR/undispatchable-receiver-and-wc-references-Self.rs:19:21 | LL | fn get<'a>(self: &'a Box) -> Pin> + 'a>> | ------------- help: consider changing method `get`'s `self` parameter to be `&self`: `&Self` @@ -8,7 +8,7 @@ LL | fn fetcher() -> Box { | ^^^^^^^^^^^ `Fetcher` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/issue-102762.rs:10:22 + --> $DIR/undispatchable-receiver-and-wc-references-Self.rs:11:22 | LL | pub trait Fetcher: Send + Sync { | ------- this trait cannot be made into an object... @@ -16,7 +16,7 @@ LL | fn get<'a>(self: &'a Box) -> Pin> | ^^^^^^^^^^^^^ ...because method `get`'s `self` parameter cannot be dispatched on error[E0038]: the trait `Fetcher` cannot be made into an object - --> $DIR/issue-102762.rs:24:19 + --> $DIR/undispatchable-receiver-and-wc-references-Self.rs:25:19 | LL | fn get<'a>(self: &'a Box) -> Pin> + 'a>> | ------------- help: consider changing method `get`'s `self` parameter to be `&self`: `&Self` @@ -25,7 +25,7 @@ LL | let fetcher = fetcher(); | ^^^^^^^^^ `Fetcher` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/issue-102762.rs:10:22 + --> $DIR/undispatchable-receiver-and-wc-references-Self.rs:11:22 | LL | pub trait Fetcher: Send + Sync { | ------- this trait cannot be made into an object... @@ -33,7 +33,7 @@ LL | fn get<'a>(self: &'a Box) -> Pin> | ^^^^^^^^^^^^^ ...because method `get`'s `self` parameter cannot be dispatched on error[E0038]: the trait `Fetcher` cannot be made into an object - --> $DIR/issue-102762.rs:26:13 + --> $DIR/undispatchable-receiver-and-wc-references-Self.rs:27:13 | LL | fn get<'a>(self: &'a Box) -> Pin> + 'a>> | ------------- help: consider changing method `get`'s `self` parameter to be `&self`: `&Self` @@ -42,7 +42,7 @@ LL | let _ = fetcher.get(); | ^^^^^^^^^^^^^ `Fetcher` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/issue-102762.rs:10:22 + --> $DIR/undispatchable-receiver-and-wc-references-Self.rs:11:22 | LL | pub trait Fetcher: Send + Sync { | ------- this trait cannot be made into an object... diff --git a/tests/ui/feature-gates/feature-gate-dispatch-from-dyn-missing-impl.rs b/tests/ui/feature-gates/feature-gate-dispatch-from-dyn-missing-impl.rs index 23857cbaca85e..3c9e903d4ba00 100644 --- a/tests/ui/feature-gates/feature-gate-dispatch-from-dyn-missing-impl.rs +++ b/tests/ui/feature-gates/feature-gate-dispatch-from-dyn-missing-impl.rs @@ -1,4 +1,4 @@ -// Check that a self parameter type requires a DispatchFromDyn impl to be object safe +// Check that a self parameter type requires a DispatchFromDyn impl to be dyn-compatible. #![feature(arbitrary_self_types, unsize, coerce_unsized)] diff --git a/tests/ui/feature-gates/feature-gate-dyn_compatible_for_dispatch.rs b/tests/ui/feature-gates/feature-gate-dyn_compatible_for_dispatch.rs index 2dbba370a51e5..e38ab66dbe549 100644 --- a/tests/ui/feature-gates/feature-gate-dyn_compatible_for_dispatch.rs +++ b/tests/ui/feature-gates/feature-gate-dyn_compatible_for_dispatch.rs @@ -15,20 +15,20 @@ trait DynIncompatible4 { fn foo(&self, s: &Self); } -fn takes_non_object_safe_ref(obj: &dyn DynIncompatible1) { +fn takes_dyn_incompatible_ref(obj: &dyn DynIncompatible1) { //~^ ERROR E0038 } -fn return_non_object_safe_ref() -> &'static dyn DynIncompatible2 { +fn return_dyn_incompatible_ref() -> &'static dyn DynIncompatible2 { //~^ ERROR E0038 loop {} } -fn takes_non_object_safe_box(obj: Box) { +fn takes_dyn_incompatible_box(obj: Box) { //~^ ERROR E0038 } -fn return_non_object_safe_rc() -> std::rc::Rc { +fn return_dyn_incompatible_rc() -> std::rc::Rc { //~^ ERROR E0038 loop {} } diff --git a/tests/ui/feature-gates/feature-gate-dyn_compatible_for_dispatch.stderr b/tests/ui/feature-gates/feature-gate-dyn_compatible_for_dispatch.stderr index 3cb73dfd52c68..ed021c154a5b8 100644 --- a/tests/ui/feature-gates/feature-gate-dyn_compatible_for_dispatch.stderr +++ b/tests/ui/feature-gates/feature-gate-dyn_compatible_for_dispatch.stderr @@ -1,8 +1,8 @@ error[E0038]: the trait `DynIncompatible1` cannot be made into an object - --> $DIR/feature-gate-dyn_compatible_for_dispatch.rs:18:39 + --> $DIR/feature-gate-dyn_compatible_for_dispatch.rs:18:40 | -LL | fn takes_non_object_safe_ref(obj: &dyn DynIncompatible1) { - | ^^^^^^^^^^^^^^^^^^^^ `DynIncompatible1` cannot be made into an object +LL | fn takes_dyn_incompatible_ref(obj: &dyn DynIncompatible1) { + | ^^^^^^^^^^^^^^^^^^^^ `DynIncompatible1` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit --> $DIR/feature-gate-dyn_compatible_for_dispatch.rs:4:25 @@ -13,10 +13,10 @@ LL | trait DynIncompatible1: Sized {} | this trait cannot be made into an object... error[E0038]: the trait `DynIncompatible2` cannot be made into an object - --> $DIR/feature-gate-dyn_compatible_for_dispatch.rs:22:45 + --> $DIR/feature-gate-dyn_compatible_for_dispatch.rs:22:46 | -LL | fn return_non_object_safe_ref() -> &'static dyn DynIncompatible2 { - | ^^^^^^^^^^^^^^^^^^^^ `DynIncompatible2` cannot be made into an object +LL | fn return_dyn_incompatible_ref() -> &'static dyn DynIncompatible2 { + | ^^^^^^^^^^^^^^^^^^^^ `DynIncompatible2` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit --> $DIR/feature-gate-dyn_compatible_for_dispatch.rs:7:8 @@ -35,10 +35,10 @@ LL | fn static_fn() where Self: Sized {} | +++++++++++++++++ error[E0038]: the trait `DynIncompatible3` cannot be made into an object - --> $DIR/feature-gate-dyn_compatible_for_dispatch.rs:27:39 + --> $DIR/feature-gate-dyn_compatible_for_dispatch.rs:27:40 | -LL | fn takes_non_object_safe_box(obj: Box) { - | ^^^^^^^^^^^^^^^^^^^^ `DynIncompatible3` cannot be made into an object +LL | fn takes_dyn_incompatible_box(obj: Box) { + | ^^^^^^^^^^^^^^^^^^^^ `DynIncompatible3` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit --> $DIR/feature-gate-dyn_compatible_for_dispatch.rs:11:8 @@ -50,10 +50,10 @@ LL | fn foo(&self); = help: consider moving `foo` to another trait error[E0038]: the trait `DynIncompatible4` cannot be made into an object - --> $DIR/feature-gate-dyn_compatible_for_dispatch.rs:31:47 + --> $DIR/feature-gate-dyn_compatible_for_dispatch.rs:31:48 | -LL | fn return_non_object_safe_rc() -> std::rc::Rc { - | ^^^^^^^^^^^^^^^^^^^^ `DynIncompatible4` cannot be made into an object +LL | fn return_dyn_incompatible_rc() -> std::rc::Rc { + | ^^^^^^^^^^^^^^^^^^^^ `DynIncompatible4` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit --> $DIR/feature-gate-dyn_compatible_for_dispatch.rs:15:22 diff --git a/tests/ui/generic-associated-types/trait-objects.rs b/tests/ui/generic-associated-types/trait-objects.rs index 277ffcc1f0dd3..743a3df0acc81 100644 --- a/tests/ui/generic-associated-types/trait-objects.rs +++ b/tests/ui/generic-associated-types/trait-objects.rs @@ -6,7 +6,7 @@ trait StreamingIterator { type Item<'a> where Self: 'a; fn size_hint(&self) -> (usize, Option); - // Uncommenting makes `StreamingIterator` not object safe + // Uncommenting makes `StreamingIterator` dyn-incompatible. // fn next(&mut self) -> Self::Item<'_>; } diff --git a/tests/ui/impl-trait/object-unsafe-trait-in-return-position-dyn-trait.rs b/tests/ui/impl-trait/dyn-incompatible-trait-in-return-position-dyn-trait.rs similarity index 59% rename from tests/ui/impl-trait/object-unsafe-trait-in-return-position-dyn-trait.rs rename to tests/ui/impl-trait/dyn-incompatible-trait-in-return-position-dyn-trait.rs index 068f7d3eea6da..76dbb05f53d66 100644 --- a/tests/ui/impl-trait/object-unsafe-trait-in-return-position-dyn-trait.rs +++ b/tests/ui/impl-trait/dyn-incompatible-trait-in-return-position-dyn-trait.rs @@ -1,24 +1,25 @@ #![allow(bare_trait_objects)] -trait NotObjectSafe { + +trait DynIncompatible { fn foo() -> Self; } struct A; struct B; -impl NotObjectSafe for A { +impl DynIncompatible for A { fn foo() -> Self { A } } -impl NotObjectSafe for B { +impl DynIncompatible for B { fn foo() -> Self { B } } -fn car() -> dyn NotObjectSafe { //~ ERROR the trait `NotObjectSafe` cannot be made into an object +fn car() -> dyn DynIncompatible { //~ ERROR the trait `DynIncompatible` cannot be made into an object //~^ ERROR return type cannot have an unboxed trait object if true { return A; @@ -26,7 +27,7 @@ fn car() -> dyn NotObjectSafe { //~ ERROR the trait `NotObjectSafe` cannot be ma B } -fn cat() -> Box { //~ ERROR the trait `NotObjectSafe` cannot be made into an +fn cat() -> Box { //~ ERROR the trait `DynIncompatible` cannot be made into an if true { return Box::new(A); //~ ERROR cannot be made into an object } diff --git a/tests/ui/impl-trait/object-unsafe-trait-in-return-position-dyn-trait.stderr b/tests/ui/impl-trait/dyn-incompatible-trait-in-return-position-dyn-trait.stderr similarity index 62% rename from tests/ui/impl-trait/object-unsafe-trait-in-return-position-dyn-trait.stderr rename to tests/ui/impl-trait/dyn-incompatible-trait-in-return-position-dyn-trait.stderr index 2a36824e29254..576bd909cbc7d 100644 --- a/tests/ui/impl-trait/object-unsafe-trait-in-return-position-dyn-trait.stderr +++ b/tests/ui/impl-trait/dyn-incompatible-trait-in-return-position-dyn-trait.stderr @@ -1,17 +1,17 @@ -error[E0038]: the trait `NotObjectSafe` cannot be made into an object - --> $DIR/object-unsafe-trait-in-return-position-dyn-trait.rs:21:13 +error[E0038]: the trait `DynIncompatible` cannot be made into an object + --> $DIR/dyn-incompatible-trait-in-return-position-dyn-trait.rs:22:13 | -LL | fn car() -> dyn NotObjectSafe { - | ^^^^^^^^^^^^^^^^^ `NotObjectSafe` cannot be made into an object +LL | fn car() -> dyn DynIncompatible { + | ^^^^^^^^^^^^^^^^^^^ `DynIncompatible` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/object-unsafe-trait-in-return-position-dyn-trait.rs:3:8 + --> $DIR/dyn-incompatible-trait-in-return-position-dyn-trait.rs:4:8 | -LL | trait NotObjectSafe { - | ------------- this trait cannot be made into an object... +LL | trait DynIncompatible { + | --------------- this trait cannot be made into an object... LL | fn foo() -> Self; | ^^^ ...because associated function `foo` has no `self` parameter - = help: the following types implement the trait, consider defining an enum where each variant holds one of these types, implementing `NotObjectSafe` for this new enum and using it instead: + = help: the following types implement the trait, consider defining an enum where each variant holds one of these types, implementing `DynIncompatible` for this new enum and using it instead: A B help: consider turning `foo` into a method by giving it a `&self` argument @@ -23,20 +23,20 @@ help: alternatively, consider constraining `foo` so it does not apply to trait o LL | fn foo() -> Self where Self: Sized; | +++++++++++++++++ -error[E0038]: the trait `NotObjectSafe` cannot be made into an object - --> $DIR/object-unsafe-trait-in-return-position-dyn-trait.rs:29:17 +error[E0038]: the trait `DynIncompatible` cannot be made into an object + --> $DIR/dyn-incompatible-trait-in-return-position-dyn-trait.rs:30:17 | -LL | fn cat() -> Box { - | ^^^^^^^^^^^^^^^^^ `NotObjectSafe` cannot be made into an object +LL | fn cat() -> Box { + | ^^^^^^^^^^^^^^^^^^^ `DynIncompatible` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/object-unsafe-trait-in-return-position-dyn-trait.rs:3:8 + --> $DIR/dyn-incompatible-trait-in-return-position-dyn-trait.rs:4:8 | -LL | trait NotObjectSafe { - | ------------- this trait cannot be made into an object... +LL | trait DynIncompatible { + | --------------- this trait cannot be made into an object... LL | fn foo() -> Self; | ^^^ ...because associated function `foo` has no `self` parameter - = help: the following types implement the trait, consider defining an enum where each variant holds one of these types, implementing `NotObjectSafe` for this new enum and using it instead: + = help: the following types implement the trait, consider defining an enum where each variant holds one of these types, implementing `DynIncompatible` for this new enum and using it instead: A B help: consider turning `foo` into a method by giving it a `&self` argument @@ -49,15 +49,15 @@ LL | fn foo() -> Self where Self: Sized; | +++++++++++++++++ error[E0746]: return type cannot have an unboxed trait object - --> $DIR/object-unsafe-trait-in-return-position-dyn-trait.rs:21:13 + --> $DIR/dyn-incompatible-trait-in-return-position-dyn-trait.rs:22:13 | -LL | fn car() -> dyn NotObjectSafe { - | ^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time +LL | fn car() -> dyn DynIncompatible { + | ^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time | = help: if there were a single returned type, you could use `impl Trait` instead help: box the return type, and wrap all of the returned values in `Box::new` | -LL ~ fn car() -> Box { +LL ~ fn car() -> Box { LL | LL | if true { LL ~ return Box::new(A); @@ -65,23 +65,23 @@ LL | } LL ~ Box::new(B) | -error[E0038]: the trait `NotObjectSafe` cannot be made into an object - --> $DIR/object-unsafe-trait-in-return-position-dyn-trait.rs:31:16 +error[E0038]: the trait `DynIncompatible` cannot be made into an object + --> $DIR/dyn-incompatible-trait-in-return-position-dyn-trait.rs:32:16 | LL | return Box::new(A); - | ^^^^^^^^^^^ `NotObjectSafe` cannot be made into an object + | ^^^^^^^^^^^ `DynIncompatible` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/object-unsafe-trait-in-return-position-dyn-trait.rs:3:8 + --> $DIR/dyn-incompatible-trait-in-return-position-dyn-trait.rs:4:8 | -LL | trait NotObjectSafe { - | ------------- this trait cannot be made into an object... +LL | trait DynIncompatible { + | --------------- this trait cannot be made into an object... LL | fn foo() -> Self; | ^^^ ...because associated function `foo` has no `self` parameter - = help: the following types implement the trait, consider defining an enum where each variant holds one of these types, implementing `NotObjectSafe` for this new enum and using it instead: + = help: the following types implement the trait, consider defining an enum where each variant holds one of these types, implementing `DynIncompatible` for this new enum and using it instead: A B - = note: required for the cast from `Box` to `Box<(dyn NotObjectSafe + 'static)>` + = note: required for the cast from `Box` to `Box<(dyn DynIncompatible + 'static)>` help: consider turning `foo` into a method by giving it a `&self` argument | LL | fn foo(&self) -> Self; @@ -91,23 +91,23 @@ help: alternatively, consider constraining `foo` so it does not apply to trait o LL | fn foo() -> Self where Self: Sized; | +++++++++++++++++ -error[E0038]: the trait `NotObjectSafe` cannot be made into an object - --> $DIR/object-unsafe-trait-in-return-position-dyn-trait.rs:33:5 +error[E0038]: the trait `DynIncompatible` cannot be made into an object + --> $DIR/dyn-incompatible-trait-in-return-position-dyn-trait.rs:34:5 | LL | Box::new(B) - | ^^^^^^^^^^^ `NotObjectSafe` cannot be made into an object + | ^^^^^^^^^^^ `DynIncompatible` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/object-unsafe-trait-in-return-position-dyn-trait.rs:3:8 + --> $DIR/dyn-incompatible-trait-in-return-position-dyn-trait.rs:4:8 | -LL | trait NotObjectSafe { - | ------------- this trait cannot be made into an object... +LL | trait DynIncompatible { + | --------------- this trait cannot be made into an object... LL | fn foo() -> Self; | ^^^ ...because associated function `foo` has no `self` parameter - = help: the following types implement the trait, consider defining an enum where each variant holds one of these types, implementing `NotObjectSafe` for this new enum and using it instead: + = help: the following types implement the trait, consider defining an enum where each variant holds one of these types, implementing `DynIncompatible` for this new enum and using it instead: A B - = note: required for the cast from `Box` to `Box<(dyn NotObjectSafe + 'static)>` + = note: required for the cast from `Box` to `Box<(dyn DynIncompatible + 'static)>` help: consider turning `foo` into a method by giving it a `&self` argument | LL | fn foo(&self) -> Self; diff --git a/tests/ui/impl-trait/object-unsafe-trait-in-return-position-impl-trait.rs b/tests/ui/impl-trait/dyn-incompatible-trait-in-return-position-impl-trait.rs similarity index 61% rename from tests/ui/impl-trait/object-unsafe-trait-in-return-position-impl-trait.rs rename to tests/ui/impl-trait/dyn-incompatible-trait-in-return-position-impl-trait.rs index 503515013b9ab..25a901e4ff350 100644 --- a/tests/ui/impl-trait/object-unsafe-trait-in-return-position-impl-trait.rs +++ b/tests/ui/impl-trait/dyn-incompatible-trait-in-return-position-impl-trait.rs @@ -1,42 +1,42 @@ -trait NotObjectSafe { +trait DynIncompatible { fn foo() -> Self; } -trait ObjectSafe { +trait DynCompatible { fn bar(&self); } struct A; struct B; -impl NotObjectSafe for A { +impl DynIncompatible for A { fn foo() -> Self { A } } -impl NotObjectSafe for B { +impl DynIncompatible for B { fn foo() -> Self { B } } -impl ObjectSafe for A { +impl DynCompatible for A { fn bar(&self) {} } -impl ObjectSafe for B { +impl DynCompatible for B { fn bar(&self) {} } -fn can() -> impl NotObjectSafe { +fn can() -> impl DynIncompatible { if true { return A; } B //~ ERROR mismatched types } -fn cat() -> impl ObjectSafe { +fn cat() -> impl DynCompatible { if true { return A; } diff --git a/tests/ui/impl-trait/object-unsafe-trait-in-return-position-impl-trait.stderr b/tests/ui/impl-trait/dyn-incompatible-trait-in-return-position-impl-trait.stderr similarity index 54% rename from tests/ui/impl-trait/object-unsafe-trait-in-return-position-impl-trait.stderr rename to tests/ui/impl-trait/dyn-incompatible-trait-in-return-position-impl-trait.stderr index e5147bcea1662..6a485881bfccb 100644 --- a/tests/ui/impl-trait/object-unsafe-trait-in-return-position-impl-trait.stderr +++ b/tests/ui/impl-trait/dyn-incompatible-trait-in-return-position-impl-trait.stderr @@ -1,17 +1,17 @@ error[E0308]: mismatched types - --> $DIR/object-unsafe-trait-in-return-position-impl-trait.rs:36:5 + --> $DIR/dyn-incompatible-trait-in-return-position-impl-trait.rs:36:5 | -LL | fn can() -> impl NotObjectSafe { - | ------------------ expected `A` because of return type +LL | fn can() -> impl DynIncompatible { + | -------------------- expected `A` because of return type ... LL | B | ^ expected `A`, found `B` error[E0308]: mismatched types - --> $DIR/object-unsafe-trait-in-return-position-impl-trait.rs:43:5 + --> $DIR/dyn-incompatible-trait-in-return-position-impl-trait.rs:43:5 | -LL | fn cat() -> impl ObjectSafe { - | --------------- expected `A` because of return type +LL | fn cat() -> impl DynCompatible { + | ------------------ expected `A` because of return type ... LL | B | ^ expected `A`, found `B` diff --git a/tests/ui/impl-trait/in-trait/cycle-effective-visibilities-during-object-safety.rs b/tests/ui/impl-trait/in-trait/cycle-effective-visibilities-during-dyn-compatibility-check.rs similarity index 100% rename from tests/ui/impl-trait/in-trait/cycle-effective-visibilities-during-object-safety.rs rename to tests/ui/impl-trait/in-trait/cycle-effective-visibilities-during-dyn-compatibility-check.rs diff --git a/tests/ui/impl-trait/in-trait/cycle-effective-visibilities-during-object-safety.stderr b/tests/ui/impl-trait/in-trait/cycle-effective-visibilities-during-dyn-compatibility-check.stderr similarity index 82% rename from tests/ui/impl-trait/in-trait/cycle-effective-visibilities-during-object-safety.stderr rename to tests/ui/impl-trait/in-trait/cycle-effective-visibilities-during-dyn-compatibility-check.stderr index af624e2a75871..a975b6204aa5a 100644 --- a/tests/ui/impl-trait/in-trait/cycle-effective-visibilities-during-object-safety.stderr +++ b/tests/ui/impl-trait/in-trait/cycle-effective-visibilities-during-dyn-compatibility-check.stderr @@ -1,5 +1,5 @@ error[E0277]: the trait bound `&dyn MyTrait: MyTrait` is not satisfied - --> $DIR/cycle-effective-visibilities-during-object-safety.rs:20:22 + --> $DIR/cycle-effective-visibilities-during-dyn-compatibility-check.rs:20:22 | LL | MyTrait::foo(&self) | ------------ ^^^^^ the trait `MyTrait` is not implemented for `&dyn MyTrait` @@ -9,13 +9,13 @@ LL | MyTrait::foo(&self) = help: the trait `MyTrait` is implemented for `Outer` error[E0038]: the trait `MyTrait` cannot be made into an object - --> $DIR/cycle-effective-visibilities-during-object-safety.rs:20:9 + --> $DIR/cycle-effective-visibilities-during-dyn-compatibility-check.rs:20:9 | LL | MyTrait::foo(&self) | ^^^^^^^^^^^^ `MyTrait` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/cycle-effective-visibilities-during-object-safety.rs:5:22 + --> $DIR/cycle-effective-visibilities-during-dyn-compatibility-check.rs:5:22 | LL | trait MyTrait { | ------- this trait cannot be made into an object... @@ -25,7 +25,7 @@ LL | fn foo(&self) -> impl Marker; = help: only type `Outer` implements the trait, consider using it directly instead error[E0277]: the trait bound `&dyn MyTrait: MyTrait` is not satisfied - --> $DIR/cycle-effective-visibilities-during-object-safety.rs:20:9 + --> $DIR/cycle-effective-visibilities-during-dyn-compatibility-check.rs:20:9 | LL | MyTrait::foo(&self) | ^^^^^^^^^^^^^^^^^^^ the trait `MyTrait` is not implemented for `&dyn MyTrait` @@ -33,13 +33,13 @@ LL | MyTrait::foo(&self) = help: the trait `MyTrait` is implemented for `Outer` error[E0038]: the trait `MyTrait` cannot be made into an object - --> $DIR/cycle-effective-visibilities-during-object-safety.rs:16:6 + --> $DIR/cycle-effective-visibilities-during-dyn-compatibility-check.rs:16:6 | LL | impl dyn MyTrait { | ^^^^^^^^^^^ `MyTrait` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/cycle-effective-visibilities-during-object-safety.rs:5:22 + --> $DIR/cycle-effective-visibilities-during-dyn-compatibility-check.rs:5:22 | LL | trait MyTrait { | ------- this trait cannot be made into an object... @@ -49,13 +49,13 @@ LL | fn foo(&self) -> impl Marker; = help: only type `Outer` implements the trait, consider using it directly instead error[E0038]: the trait `MyTrait` cannot be made into an object - --> $DIR/cycle-effective-visibilities-during-object-safety.rs:18:15 + --> $DIR/cycle-effective-visibilities-during-dyn-compatibility-check.rs:18:15 | LL | fn other(&self) -> impl Marker { | ^^^^ `MyTrait` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/cycle-effective-visibilities-during-object-safety.rs:5:22 + --> $DIR/cycle-effective-visibilities-during-dyn-compatibility-check.rs:5:22 | LL | trait MyTrait { | ------- this trait cannot be made into an object... diff --git a/tests/ui/impl-trait/in-trait/object-safety-sized.rs b/tests/ui/impl-trait/in-trait/dyn-compatibility-sized.rs similarity index 100% rename from tests/ui/impl-trait/in-trait/object-safety-sized.rs rename to tests/ui/impl-trait/in-trait/dyn-compatibility-sized.rs diff --git a/tests/ui/impl-trait/in-trait/object-safety.rs b/tests/ui/impl-trait/in-trait/dyn-compatibility.rs similarity index 100% rename from tests/ui/impl-trait/in-trait/object-safety.rs rename to tests/ui/impl-trait/in-trait/dyn-compatibility.rs diff --git a/tests/ui/impl-trait/in-trait/object-safety.stderr b/tests/ui/impl-trait/in-trait/dyn-compatibility.stderr similarity index 91% rename from tests/ui/impl-trait/in-trait/object-safety.stderr rename to tests/ui/impl-trait/in-trait/dyn-compatibility.stderr index e2f23bca621c6..115cb014b8c34 100644 --- a/tests/ui/impl-trait/in-trait/object-safety.stderr +++ b/tests/ui/impl-trait/in-trait/dyn-compatibility.stderr @@ -1,11 +1,11 @@ error[E0038]: the trait `Foo` cannot be made into an object - --> $DIR/object-safety.rs:14:33 + --> $DIR/dyn-compatibility.rs:14:33 | LL | let i = Box::new(42_u32) as Box; | ^^^^^^^^^^^^ `Foo` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/object-safety.rs:4:22 + --> $DIR/dyn-compatibility.rs:4:22 | LL | trait Foo { | --- this trait cannot be made into an object... @@ -15,13 +15,13 @@ LL | fn baz(&self) -> impl Debug; = help: only type `u32` implements the trait, consider using it directly instead error[E0038]: the trait `Foo` cannot be made into an object - --> $DIR/object-safety.rs:17:15 + --> $DIR/dyn-compatibility.rs:17:15 | LL | let s = i.baz(); | ^^^ `Foo` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/object-safety.rs:4:22 + --> $DIR/dyn-compatibility.rs:4:22 | LL | trait Foo { | --- this trait cannot be made into an object... @@ -31,13 +31,13 @@ LL | fn baz(&self) -> impl Debug; = help: only type `u32` implements the trait, consider using it directly instead error[E0038]: the trait `Foo` cannot be made into an object - --> $DIR/object-safety.rs:17:13 + --> $DIR/dyn-compatibility.rs:17:13 | LL | let s = i.baz(); | ^^^^^^^ `Foo` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/object-safety.rs:4:22 + --> $DIR/dyn-compatibility.rs:4:22 | LL | trait Foo { | --- this trait cannot be made into an object... @@ -47,13 +47,13 @@ LL | fn baz(&self) -> impl Debug; = help: only type `u32` implements the trait, consider using it directly instead error[E0038]: the trait `Foo` cannot be made into an object - --> $DIR/object-safety.rs:14:13 + --> $DIR/dyn-compatibility.rs:14:13 | LL | let i = Box::new(42_u32) as Box; | ^^^^^^^^^^^^^^^^ `Foo` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/object-safety.rs:4:22 + --> $DIR/dyn-compatibility.rs:4:22 | LL | trait Foo { | --- this trait cannot be made into an object... diff --git a/tests/ui/issues/issue-58734.rs b/tests/ui/issues/issue-58734.rs index c838fde5d73b6..9b630666baf85 100644 --- a/tests/ui/issues/issue-58734.rs +++ b/tests/ui/issues/issue-58734.rs @@ -1,22 +1,22 @@ trait Trait { fn exists(self) -> (); - fn not_object_safe() -> Self; + fn dyn_incompatible() -> Self; } impl Trait for () { fn exists(self) -> () { } - fn not_object_safe() -> Self { + fn dyn_incompatible() -> Self { () } } fn main() { - // object-safe or not, this call is OK + // dyn-compatible or not, this call is OK Trait::exists(()); - // no object safety error + // no dyn-compatibility error Trait::nonexistent(()); //~^ ERROR no function or associated item named `nonexistent` found //~| WARN trait objects without an explicit `dyn` are deprecated diff --git a/tests/ui/rfcs/rfc-2027-dyn-compatible-for-dispatch/downcast-unsafe-trait-objects.rs b/tests/ui/rfcs/rfc-2027-dyn-compatible-for-dispatch/downcast-unsafe-trait-objects.rs index e9206789756e7..b1b2dcf3eb9fd 100644 --- a/tests/ui/rfcs/rfc-2027-dyn-compatible-for-dispatch/downcast-unsafe-trait-objects.rs +++ b/tests/ui/rfcs/rfc-2027-dyn-compatible-for-dispatch/downcast-unsafe-trait-objects.rs @@ -1,4 +1,4 @@ -// Check that we if we get ahold of an object unsafe trait +// Check that we if we get ahold of a dyn-incompatible trait // object with auto traits and lifetimes, we can downcast it // //@ check-pass diff --git a/tests/ui/rfcs/rfc-2027-dyn-compatible-for-dispatch/manual-self-impl-for-unsafe-obj.rs b/tests/ui/rfcs/rfc-2027-dyn-compatible-for-dispatch/manual-self-impl-for-unsafe-obj.rs index 37e6f948ad118..425dc130d4587 100644 --- a/tests/ui/rfcs/rfc-2027-dyn-compatible-for-dispatch/manual-self-impl-for-unsafe-obj.rs +++ b/tests/ui/rfcs/rfc-2027-dyn-compatible-for-dispatch/manual-self-impl-for-unsafe-obj.rs @@ -1,4 +1,4 @@ -// Check that we can manually implement an object-unsafe trait for its trait object. +// Check that we can manually implement a dyn-incompatible trait for its trait object. //@ revisions: current next //@ ignore-compare-mode-next-solver (explicit revisions) diff --git a/tests/ui/sanitizer/cfi/async-closures.rs b/tests/ui/sanitizer/cfi/async-closures.rs index d94f2992d8428..4eaa44cfa3f47 100644 --- a/tests/ui/sanitizer/cfi/async-closures.rs +++ b/tests/ui/sanitizer/cfi/async-closures.rs @@ -21,7 +21,7 @@ use std::ops::AsyncFn; #[inline(never)] fn identity(x: T) -> T { x } -// We can't actually create a `dyn AsyncFn()`, because it's not object-safe, but we should check +// We can't actually create a `dyn AsyncFn()`, because it's dyn-incompatible, but we should check // that we don't bug out when we encounter one. fn main() { diff --git a/tests/ui/self/arbitrary-self-types-not-object-safe.curr.stderr b/tests/ui/self/arbitrary-self-types-dyn-incompatible.curr.stderr similarity index 89% rename from tests/ui/self/arbitrary-self-types-not-object-safe.curr.stderr rename to tests/ui/self/arbitrary-self-types-dyn-incompatible.curr.stderr index e2d73fc08f6d7..2eb7597d5c105 100644 --- a/tests/ui/self/arbitrary-self-types-not-object-safe.curr.stderr +++ b/tests/ui/self/arbitrary-self-types-dyn-incompatible.curr.stderr @@ -1,5 +1,5 @@ error[E0038]: the trait `Foo` cannot be made into an object - --> $DIR/arbitrary-self-types-not-object-safe.rs:33:32 + --> $DIR/arbitrary-self-types-dyn-incompatible.rs:33:32 | LL | fn foo(self: &Rc) -> usize; | --------- help: consider changing method `foo`'s `self` parameter to be `&self`: `&Self` @@ -8,7 +8,7 @@ LL | let x = Rc::new(5usize) as Rc; | ^^^^^^^^^^^ `Foo` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/arbitrary-self-types-not-object-safe.rs:8:18 + --> $DIR/arbitrary-self-types-dyn-incompatible.rs:8:18 | LL | trait Foo { | --- this trait cannot be made into an object... @@ -17,7 +17,7 @@ LL | fn foo(self: &Rc) -> usize; = help: only type `usize` implements the trait, consider using it directly instead error[E0038]: the trait `Foo` cannot be made into an object - --> $DIR/arbitrary-self-types-not-object-safe.rs:33:13 + --> $DIR/arbitrary-self-types-dyn-incompatible.rs:33:13 | LL | fn foo(self: &Rc) -> usize; | --------- help: consider changing method `foo`'s `self` parameter to be `&self`: `&Self` @@ -26,7 +26,7 @@ LL | let x = Rc::new(5usize) as Rc; | ^^^^^^^^^^^^^^^ `Foo` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/arbitrary-self-types-not-object-safe.rs:8:18 + --> $DIR/arbitrary-self-types-dyn-incompatible.rs:8:18 | LL | trait Foo { | --- this trait cannot be made into an object... diff --git a/tests/ui/self/arbitrary-self-types-not-object-safe.dyn_compatible_for_dispatch.stderr b/tests/ui/self/arbitrary-self-types-dyn-incompatible.dyn_compatible_for_dispatch.stderr similarity index 90% rename from tests/ui/self/arbitrary-self-types-not-object-safe.dyn_compatible_for_dispatch.stderr rename to tests/ui/self/arbitrary-self-types-dyn-incompatible.dyn_compatible_for_dispatch.stderr index fda07765c6620..02af692c4a352 100644 --- a/tests/ui/self/arbitrary-self-types-not-object-safe.dyn_compatible_for_dispatch.stderr +++ b/tests/ui/self/arbitrary-self-types-dyn-incompatible.dyn_compatible_for_dispatch.stderr @@ -1,5 +1,5 @@ error[E0038]: the trait `Foo` cannot be made into an object - --> $DIR/arbitrary-self-types-not-object-safe.rs:33:13 + --> $DIR/arbitrary-self-types-dyn-incompatible.rs:33:13 | LL | fn foo(self: &Rc) -> usize; | --------- help: consider changing method `foo`'s `self` parameter to be `&self`: `&Self` @@ -8,7 +8,7 @@ LL | let x = Rc::new(5usize) as Rc; | ^^^^^^^^^^^^^^^ `Foo` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/arbitrary-self-types-not-object-safe.rs:8:18 + --> $DIR/arbitrary-self-types-dyn-incompatible.rs:8:18 | LL | trait Foo { | --- this trait cannot be made into an object... diff --git a/tests/ui/self/arbitrary-self-types-not-object-safe.rs b/tests/ui/self/arbitrary-self-types-dyn-incompatible.rs similarity index 100% rename from tests/ui/self/arbitrary-self-types-not-object-safe.rs rename to tests/ui/self/arbitrary-self-types-dyn-incompatible.rs diff --git a/tests/ui/self/arbitrary_self_types_pointers_and_wrappers.rs b/tests/ui/self/arbitrary_self_types_pointers_and_wrappers.rs index d7149002e7bca..76d7754384ebe 100644 --- a/tests/ui/self/arbitrary_self_types_pointers_and_wrappers.rs +++ b/tests/ui/self/arbitrary_self_types_pointers_and_wrappers.rs @@ -50,9 +50,9 @@ impl, U> DispatchFromDyn> for Wrapper {} trait Trait { - // This method isn't object-safe yet. Unsized by-value `self` is object-safe (but not callable - // without unsized_locals), but wrappers arond `Self` currently are not. - // FIXME (mikeyhew) uncomment this when unsized rvalues object-safety is implemented + // This method isn't dyn-compatible yet. Unsized by-value `self` is dyn-compatible (but not + // callable without unsized_locals), but wrappers arond `Self` currently are not. + // FIXME (mikeyhew) uncomment this when unsized rvalues dyn-compatibility is implemented // fn wrapper(self: Wrapper) -> i32; fn ptr_wrapper(self: Ptr>) -> i32; fn wrapper_ptr(self: Wrapper>) -> i32; diff --git a/tests/ui/self/object-safety-sized-self-by-value-self.rs b/tests/ui/self/dyn-compatibility-sized-self-by-value-self.rs similarity index 90% rename from tests/ui/self/object-safety-sized-self-by-value-self.rs rename to tests/ui/self/dyn-compatibility-sized-self-by-value-self.rs index d902812eb9a67..658371c95e2f5 100644 --- a/tests/ui/self/object-safety-sized-self-by-value-self.rs +++ b/tests/ui/self/dyn-compatibility-sized-self-by-value-self.rs @@ -1,6 +1,6 @@ //@ run-pass #![allow(unused_mut)] -// Check that a trait is still object-safe (and usable) if it has +// Check that a trait is still dyn-compatible (and usable) if it has // methods with by-value self so long as they require `Self : Sized`. diff --git a/tests/ui/self/object-safety-sized-self-generic-method.rs b/tests/ui/self/dyn-compatibility-sized-self-generic-method.rs similarity index 90% rename from tests/ui/self/object-safety-sized-self-generic-method.rs rename to tests/ui/self/dyn-compatibility-sized-self-generic-method.rs index 7a2ebd2cb7935..a7b5013694ff2 100644 --- a/tests/ui/self/object-safety-sized-self-generic-method.rs +++ b/tests/ui/self/dyn-compatibility-sized-self-generic-method.rs @@ -1,6 +1,6 @@ //@ run-pass #![allow(unused_variables)] -// Check that a trait is still object-safe (and usable) if it has +// Check that a trait is still dyn-compatible (and usable) if it has // generic methods so long as they require `Self : Sized`. diff --git a/tests/ui/self/object-safety-sized-self-return-Self.rs b/tests/ui/self/dyn-compatibility-sized-self-return-Self.rs similarity index 90% rename from tests/ui/self/object-safety-sized-self-return-Self.rs rename to tests/ui/self/dyn-compatibility-sized-self-return-Self.rs index 9fc3f85677223..a15f4fd781360 100644 --- a/tests/ui/self/object-safety-sized-self-return-Self.rs +++ b/tests/ui/self/dyn-compatibility-sized-self-return-Self.rs @@ -1,5 +1,5 @@ //@ run-pass -// Check that a trait is still object-safe (and usable) if it has +// Check that a trait is still dyn-compatible (and usable) if it has // methods that return `Self` so long as they require `Self : Sized`. diff --git a/tests/ui/specialization/issue-44861.rs b/tests/ui/specialization/issue-44861.rs index 79d9b9490d09d..9d6517e613a22 100644 --- a/tests/ui/specialization/issue-44861.rs +++ b/tests/ui/specialization/issue-44861.rs @@ -12,9 +12,9 @@ pub trait Smartass { type Data2: CoerceUnsized<*const [u8]>; } -pub trait MaybeObjectSafe {} +pub trait MaybeDynCompatible {} -impl MaybeObjectSafe for () {} +impl MaybeDynCompatible for () {} impl Smartass for T { type Data = ::Data2; @@ -26,7 +26,7 @@ impl Smartass for () { type Data2 = *const [u8; 1]; } -impl Smartass for dyn MaybeObjectSafe { +impl Smartass for dyn MaybeDynCompatible { type Data = *const [u8]; type Data2 = *const [u8; 0]; } @@ -35,6 +35,6 @@ impl CoerceUnsized> for S where ::Data: std::ops::CoerceUnsized<::Data> {} -pub fn conv(s: SmartassPtr<()>) -> SmartassPtr { +pub fn conv(s: SmartassPtr<()>) -> SmartassPtr { s } diff --git a/tests/ui/suggestions/auxiliary/not-object-safe.rs b/tests/ui/suggestions/auxiliary/dyn-incompatible.rs similarity index 100% rename from tests/ui/suggestions/auxiliary/not-object-safe.rs rename to tests/ui/suggestions/auxiliary/dyn-incompatible.rs diff --git a/tests/ui/suggestions/object-unsafe-trait-references-self.rs b/tests/ui/suggestions/dyn-incompatible-trait-references-self.rs similarity index 100% rename from tests/ui/suggestions/object-unsafe-trait-references-self.rs rename to tests/ui/suggestions/dyn-incompatible-trait-references-self.rs diff --git a/tests/ui/suggestions/object-unsafe-trait-references-self.stderr b/tests/ui/suggestions/dyn-incompatible-trait-references-self.stderr similarity index 87% rename from tests/ui/suggestions/object-unsafe-trait-references-self.stderr rename to tests/ui/suggestions/dyn-incompatible-trait-references-self.stderr index c00bb3efbf640..242c44abd9d66 100644 --- a/tests/ui/suggestions/object-unsafe-trait-references-self.stderr +++ b/tests/ui/suggestions/dyn-incompatible-trait-references-self.stderr @@ -1,11 +1,11 @@ error[E0038]: the trait `Trait` cannot be made into an object - --> $DIR/object-unsafe-trait-references-self.rs:9:12 + --> $DIR/dyn-incompatible-trait-references-self.rs:9:12 | LL | fn bar(x: &dyn Trait) {} | ^^^^^^^^^ `Trait` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/object-unsafe-trait-references-self.rs:2:22 + --> $DIR/dyn-incompatible-trait-references-self.rs:2:22 | LL | trait Trait { | ----- this trait cannot be made into an object... @@ -18,13 +18,13 @@ LL | fn bat(&self) -> Self {} = help: consider moving `bat` to another trait error[E0038]: the trait `Other` cannot be made into an object - --> $DIR/object-unsafe-trait-references-self.rs:13:12 + --> $DIR/dyn-incompatible-trait-references-self.rs:13:12 | LL | fn foo(x: &dyn Other) {} | ^^^^^^^^^ `Other` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/object-unsafe-trait-references-self.rs:11:14 + --> $DIR/dyn-incompatible-trait-references-self.rs:11:14 | LL | trait Other: Sized {} | ----- ^^^^^ ...because it requires `Self: Sized` @@ -32,7 +32,7 @@ LL | trait Other: Sized {} | this trait cannot be made into an object... error[E0277]: the size for values of type `Self` cannot be known at compilation time - --> $DIR/object-unsafe-trait-references-self.rs:2:22 + --> $DIR/dyn-incompatible-trait-references-self.rs:2:22 | LL | fn baz(&self, _: Self) {} | ^^^^ doesn't have a size known at compile-time @@ -48,7 +48,7 @@ LL | fn baz(&self, _: &Self) {} | + error[E0308]: mismatched types - --> $DIR/object-unsafe-trait-references-self.rs:4:27 + --> $DIR/dyn-incompatible-trait-references-self.rs:4:27 | LL | trait Trait { | ----------- expected this type parameter @@ -60,7 +60,7 @@ LL | fn bat(&self) -> Self {} found unit type `()` error[E0277]: the size for values of type `Self` cannot be known at compilation time - --> $DIR/object-unsafe-trait-references-self.rs:4:22 + --> $DIR/dyn-incompatible-trait-references-self.rs:4:22 | LL | fn bat(&self) -> Self {} | ^^^^ doesn't have a size known at compile-time diff --git a/tests/ui/suggestions/object-unsafe-trait-should-use-self-2021-without-dyn.rs b/tests/ui/suggestions/dyn-incompatible-trait-should-use-self-2021-without-dyn.rs similarity index 100% rename from tests/ui/suggestions/object-unsafe-trait-should-use-self-2021-without-dyn.rs rename to tests/ui/suggestions/dyn-incompatible-trait-should-use-self-2021-without-dyn.rs diff --git a/tests/ui/suggestions/object-unsafe-trait-should-use-self-2021-without-dyn.stderr b/tests/ui/suggestions/dyn-incompatible-trait-should-use-self-2021-without-dyn.stderr similarity index 83% rename from tests/ui/suggestions/object-unsafe-trait-should-use-self-2021-without-dyn.stderr rename to tests/ui/suggestions/dyn-incompatible-trait-should-use-self-2021-without-dyn.stderr index a17f821ebec48..5330438258488 100644 --- a/tests/ui/suggestions/object-unsafe-trait-should-use-self-2021-without-dyn.stderr +++ b/tests/ui/suggestions/dyn-incompatible-trait-should-use-self-2021-without-dyn.stderr @@ -1,5 +1,5 @@ error: associated item referring to unboxed trait object for its own trait - --> $DIR/object-unsafe-trait-should-use-self-2021-without-dyn.rs:4:13 + --> $DIR/dyn-incompatible-trait-should-use-self-2021-without-dyn.rs:4:13 | LL | trait A: Sized { | - in this trait @@ -12,13 +12,13 @@ LL | fn f(a: Self) -> Self; | ~~~~ ~~~~ error[E0038]: the trait `A` cannot be made into an object - --> $DIR/object-unsafe-trait-should-use-self-2021-without-dyn.rs:4:13 + --> $DIR/dyn-incompatible-trait-should-use-self-2021-without-dyn.rs:4:13 | LL | fn f(a: A) -> A; | ^ `A` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/object-unsafe-trait-should-use-self-2021-without-dyn.rs:3:10 + --> $DIR/dyn-incompatible-trait-should-use-self-2021-without-dyn.rs:3:10 | LL | trait A: Sized { | - ^^^^^ ...because it requires `Self: Sized` @@ -26,7 +26,7 @@ LL | trait A: Sized { | this trait cannot be made into an object... error: associated item referring to unboxed trait object for its own trait - --> $DIR/object-unsafe-trait-should-use-self-2021-without-dyn.rs:11:13 + --> $DIR/dyn-incompatible-trait-should-use-self-2021-without-dyn.rs:11:13 | LL | trait B { | - in this trait @@ -39,13 +39,13 @@ LL | fn f(b: Self) -> Self; | ~~~~ ~~~~ error[E0038]: the trait `B` cannot be made into an object - --> $DIR/object-unsafe-trait-should-use-self-2021-without-dyn.rs:11:13 + --> $DIR/dyn-incompatible-trait-should-use-self-2021-without-dyn.rs:11:13 | LL | fn f(b: B) -> B; | ^ `B` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/object-unsafe-trait-should-use-self-2021-without-dyn.rs:11:8 + --> $DIR/dyn-incompatible-trait-should-use-self-2021-without-dyn.rs:11:8 | LL | trait B { | - this trait cannot be made into an object... @@ -61,7 +61,7 @@ LL | fn f(b: B) -> B where Self: Sized; | +++++++++++++++++ error: associated item referring to unboxed trait object for its own trait - --> $DIR/object-unsafe-trait-should-use-self-2021-without-dyn.rs:18:20 + --> $DIR/dyn-incompatible-trait-should-use-self-2021-without-dyn.rs:18:20 | LL | trait C { | - in this trait @@ -74,7 +74,7 @@ LL | fn f(&self, c: Self) -> Self; | ~~~~ ~~~~ error[E0038]: the trait `C` cannot be made into an object - --> $DIR/object-unsafe-trait-should-use-self-2021-without-dyn.rs:18:20 + --> $DIR/dyn-incompatible-trait-should-use-self-2021-without-dyn.rs:18:20 | LL | fn f(&self, c: C) -> C; | ----- ^ `C` cannot be made into an object @@ -82,7 +82,7 @@ LL | fn f(&self, c: C) -> C; | help: consider changing method `f`'s `self` parameter to be `&self` (notice the capitalization): `&Self` | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/object-unsafe-trait-should-use-self-2021-without-dyn.rs:18:10 + --> $DIR/dyn-incompatible-trait-should-use-self-2021-without-dyn.rs:18:10 | LL | trait C { | - this trait cannot be made into an object... @@ -90,7 +90,7 @@ LL | fn f(&self, c: C) -> C; | ^^^^^ ...because method `f`'s `self` parameter cannot be dispatched on error[E0782]: trait objects must include the `dyn` keyword - --> $DIR/object-unsafe-trait-should-use-self-2021-without-dyn.rs:4:13 + --> $DIR/dyn-incompatible-trait-should-use-self-2021-without-dyn.rs:4:13 | LL | fn f(a: A) -> A; | ^ @@ -106,7 +106,7 @@ LL | fn f(a: impl A) -> A; | ++++ error[E0782]: trait objects must include the `dyn` keyword - --> $DIR/object-unsafe-trait-should-use-self-2021-without-dyn.rs:4:19 + --> $DIR/dyn-incompatible-trait-should-use-self-2021-without-dyn.rs:4:19 | LL | fn f(a: A) -> A; | ^ @@ -117,7 +117,7 @@ LL | fn f(a: A) -> impl A; | ++++ error[E0782]: trait objects must include the `dyn` keyword - --> $DIR/object-unsafe-trait-should-use-self-2021-without-dyn.rs:11:13 + --> $DIR/dyn-incompatible-trait-should-use-self-2021-without-dyn.rs:11:13 | LL | fn f(b: B) -> B; | ^ @@ -133,7 +133,7 @@ LL | fn f(b: impl B) -> B; | ++++ error[E0782]: trait objects must include the `dyn` keyword - --> $DIR/object-unsafe-trait-should-use-self-2021-without-dyn.rs:11:19 + --> $DIR/dyn-incompatible-trait-should-use-self-2021-without-dyn.rs:11:19 | LL | fn f(b: B) -> B; | ^ @@ -144,7 +144,7 @@ LL | fn f(b: B) -> impl B; | ++++ error[E0782]: trait objects must include the `dyn` keyword - --> $DIR/object-unsafe-trait-should-use-self-2021-without-dyn.rs:18:20 + --> $DIR/dyn-incompatible-trait-should-use-self-2021-without-dyn.rs:18:20 | LL | fn f(&self, c: C) -> C; | ^ @@ -160,7 +160,7 @@ LL | fn f(&self, c: impl C) -> C; | ++++ error[E0782]: trait objects must include the `dyn` keyword - --> $DIR/object-unsafe-trait-should-use-self-2021-without-dyn.rs:18:26 + --> $DIR/dyn-incompatible-trait-should-use-self-2021-without-dyn.rs:18:26 | LL | fn f(&self, c: C) -> C; | ^ diff --git a/tests/ui/suggestions/object-unsafe-trait-should-use-self-2021.rs b/tests/ui/suggestions/dyn-incompatible-trait-should-use-self-2021.rs similarity index 100% rename from tests/ui/suggestions/object-unsafe-trait-should-use-self-2021.rs rename to tests/ui/suggestions/dyn-incompatible-trait-should-use-self-2021.rs diff --git a/tests/ui/suggestions/object-unsafe-trait-should-use-self-2021.stderr b/tests/ui/suggestions/dyn-incompatible-trait-should-use-self-2021.stderr similarity index 85% rename from tests/ui/suggestions/object-unsafe-trait-should-use-self-2021.stderr rename to tests/ui/suggestions/dyn-incompatible-trait-should-use-self-2021.stderr index a7d36d9ebee5d..5e0d1a1445230 100644 --- a/tests/ui/suggestions/object-unsafe-trait-should-use-self-2021.stderr +++ b/tests/ui/suggestions/dyn-incompatible-trait-should-use-self-2021.stderr @@ -1,5 +1,5 @@ error: associated item referring to unboxed trait object for its own trait - --> $DIR/object-unsafe-trait-should-use-self-2021.rs:4:13 + --> $DIR/dyn-incompatible-trait-should-use-self-2021.rs:4:13 | LL | trait A: Sized { | - in this trait @@ -12,13 +12,13 @@ LL | fn f(a: Self) -> Self; | ~~~~ ~~~~ error[E0038]: the trait `A` cannot be made into an object - --> $DIR/object-unsafe-trait-should-use-self-2021.rs:4:13 + --> $DIR/dyn-incompatible-trait-should-use-self-2021.rs:4:13 | LL | fn f(a: dyn A) -> dyn A; | ^^^^^ `A` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/object-unsafe-trait-should-use-self-2021.rs:3:10 + --> $DIR/dyn-incompatible-trait-should-use-self-2021.rs:3:10 | LL | trait A: Sized { | - ^^^^^ ...because it requires `Self: Sized` @@ -26,7 +26,7 @@ LL | trait A: Sized { | this trait cannot be made into an object... error: associated item referring to unboxed trait object for its own trait - --> $DIR/object-unsafe-trait-should-use-self-2021.rs:9:13 + --> $DIR/dyn-incompatible-trait-should-use-self-2021.rs:9:13 | LL | trait B { | - in this trait @@ -39,13 +39,13 @@ LL | fn f(a: Self) -> Self; | ~~~~ ~~~~ error[E0038]: the trait `B` cannot be made into an object - --> $DIR/object-unsafe-trait-should-use-self-2021.rs:9:13 + --> $DIR/dyn-incompatible-trait-should-use-self-2021.rs:9:13 | LL | fn f(a: dyn B) -> dyn B; | ^^^^^ `B` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/object-unsafe-trait-should-use-self-2021.rs:9:8 + --> $DIR/dyn-incompatible-trait-should-use-self-2021.rs:9:8 | LL | trait B { | - this trait cannot be made into an object... diff --git a/tests/ui/suggestions/object-unsafe-trait-should-use-self.rs b/tests/ui/suggestions/dyn-incompatible-trait-should-use-self.rs similarity index 100% rename from tests/ui/suggestions/object-unsafe-trait-should-use-self.rs rename to tests/ui/suggestions/dyn-incompatible-trait-should-use-self.rs diff --git a/tests/ui/suggestions/object-unsafe-trait-should-use-self.stderr b/tests/ui/suggestions/dyn-incompatible-trait-should-use-self.stderr similarity index 86% rename from tests/ui/suggestions/object-unsafe-trait-should-use-self.stderr rename to tests/ui/suggestions/dyn-incompatible-trait-should-use-self.stderr index 28952933c644f..93f6ea2b12e67 100644 --- a/tests/ui/suggestions/object-unsafe-trait-should-use-self.stderr +++ b/tests/ui/suggestions/dyn-incompatible-trait-should-use-self.stderr @@ -1,5 +1,5 @@ error: associated item referring to unboxed trait object for its own trait - --> $DIR/object-unsafe-trait-should-use-self.rs:3:13 + --> $DIR/dyn-incompatible-trait-should-use-self.rs:3:13 | LL | trait A: Sized { | - in this trait @@ -12,13 +12,13 @@ LL | fn f(a: Self) -> Self; | ~~~~ ~~~~ error[E0038]: the trait `A` cannot be made into an object - --> $DIR/object-unsafe-trait-should-use-self.rs:3:13 + --> $DIR/dyn-incompatible-trait-should-use-self.rs:3:13 | LL | fn f(a: A) -> A; | ^ `A` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/object-unsafe-trait-should-use-self.rs:2:10 + --> $DIR/dyn-incompatible-trait-should-use-self.rs:2:10 | LL | trait A: Sized { | - ^^^^^ ...because it requires `Self: Sized` @@ -26,7 +26,7 @@ LL | trait A: Sized { | this trait cannot be made into an object... error: associated item referring to unboxed trait object for its own trait - --> $DIR/object-unsafe-trait-should-use-self.rs:8:13 + --> $DIR/dyn-incompatible-trait-should-use-self.rs:8:13 | LL | trait B { | - in this trait @@ -39,13 +39,13 @@ LL | fn f(a: Self) -> Self; | ~~~~ ~~~~ error[E0038]: the trait `B` cannot be made into an object - --> $DIR/object-unsafe-trait-should-use-self.rs:8:13 + --> $DIR/dyn-incompatible-trait-should-use-self.rs:8:13 | LL | fn f(a: B) -> B; | ^ `B` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/object-unsafe-trait-should-use-self.rs:8:8 + --> $DIR/dyn-incompatible-trait-should-use-self.rs:8:8 | LL | trait B { | - this trait cannot be made into an object... diff --git a/tests/ui/suggestions/object-unsafe-trait-should-use-where-sized.fixed b/tests/ui/suggestions/dyn-incompatible-trait-should-use-where-sized.fixed similarity index 100% rename from tests/ui/suggestions/object-unsafe-trait-should-use-where-sized.fixed rename to tests/ui/suggestions/dyn-incompatible-trait-should-use-where-sized.fixed diff --git a/tests/ui/suggestions/object-unsafe-trait-should-use-where-sized.rs b/tests/ui/suggestions/dyn-incompatible-trait-should-use-where-sized.rs similarity index 100% rename from tests/ui/suggestions/object-unsafe-trait-should-use-where-sized.rs rename to tests/ui/suggestions/dyn-incompatible-trait-should-use-where-sized.rs diff --git a/tests/ui/suggestions/object-unsafe-trait-should-use-where-sized.stderr b/tests/ui/suggestions/dyn-incompatible-trait-should-use-where-sized.stderr similarity index 89% rename from tests/ui/suggestions/object-unsafe-trait-should-use-where-sized.stderr rename to tests/ui/suggestions/dyn-incompatible-trait-should-use-where-sized.stderr index 5e3a0290d42c0..beafd7c2ab00f 100644 --- a/tests/ui/suggestions/object-unsafe-trait-should-use-where-sized.stderr +++ b/tests/ui/suggestions/dyn-incompatible-trait-should-use-where-sized.stderr @@ -1,11 +1,11 @@ error[E0038]: the trait `Trait` cannot be made into an object - --> $DIR/object-unsafe-trait-should-use-where-sized.rs:9:12 + --> $DIR/dyn-incompatible-trait-should-use-where-sized.rs:9:12 | LL | fn bar(x: &dyn Trait) {} | ^^^^^^^^^ `Trait` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/object-unsafe-trait-should-use-where-sized.rs:5:8 + --> $DIR/dyn-incompatible-trait-should-use-where-sized.rs:5:8 | LL | trait Trait { | ----- this trait cannot be made into an object... @@ -27,7 +27,7 @@ LL | fn bar(self: &Self) {} | ~~~~~ error[E0307]: invalid `self` parameter type: `()` - --> $DIR/object-unsafe-trait-should-use-where-sized.rs:6:18 + --> $DIR/dyn-incompatible-trait-should-use-where-sized.rs:6:18 | LL | fn bar(self: ()) {} | ^^ diff --git a/tests/ui/suggestions/issue-98500.rs b/tests/ui/suggestions/issue-98500.rs index b6fd9e7c23fe3..289b16abf4b37 100644 --- a/tests/ui/suggestions/issue-98500.rs +++ b/tests/ui/suggestions/issue-98500.rs @@ -1,9 +1,9 @@ -//@ aux-build:not-object-safe.rs +//@ aux-build:dyn-incompatible.rs -extern crate not_object_safe; +extern crate dyn_incompatible; pub trait B where - Self: not_object_safe::A, + Self: dyn_incompatible::A, { fn f2(&self); } diff --git a/tests/ui/suggestions/issue-98500.stderr b/tests/ui/suggestions/issue-98500.stderr index c4b446763afe5..d7136ec1a649f 100644 --- a/tests/ui/suggestions/issue-98500.stderr +++ b/tests/ui/suggestions/issue-98500.stderr @@ -5,7 +5,7 @@ LL | struct S(Box); | ^^^^^ `B` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/auxiliary/not-object-safe.rs:4:8 + --> $DIR/auxiliary/dyn-incompatible.rs:4:8 | LL | fn f(); | ^ ...because associated function `f` has no `self` parameter diff --git a/tests/ui/traits/alias/no-duplicates.rs b/tests/ui/traits/alias/no-duplicates.rs index 88feb89170dd3..d0829ab4cecbf 100644 --- a/tests/ui/traits/alias/no-duplicates.rs +++ b/tests/ui/traits/alias/no-duplicates.rs @@ -1,4 +1,4 @@ -// The purpose of this test is to demonstrate that duplicating object safe traits +// The purpose of this test is to demonstrate that duplicating dyn-compatible traits // that are not auto traits is rejected with trait aliases even though one could // reasonably accept this. @@ -6,7 +6,7 @@ use std::marker::Unpin; -// Some arbitrary object-safe trait: +// Some arbitrary dyn-compatible trait: trait Obj {} // Nest a few levels deep: diff --git a/tests/ui/traits/alias/no-extra-traits.rs b/tests/ui/traits/alias/no-extra-traits.rs index 4dad8c0f87349..f3d35a8cd034d 100644 --- a/tests/ui/traits/alias/no-extra-traits.rs +++ b/tests/ui/traits/alias/no-extra-traits.rs @@ -5,7 +5,7 @@ use std::marker::Unpin; -// Some arbitrary object-safe traits: +// Some arbitrary dyn-compatible traits: trait ObjA {} trait ObjB {} diff --git a/tests/ui/traits/alias/object-wf.rs b/tests/ui/traits/alias/object-wf.rs index 3abffd22d142f..a14cfea3bd7ad 100644 --- a/tests/ui/traits/alias/object-wf.rs +++ b/tests/ui/traits/alias/object-wf.rs @@ -20,7 +20,7 @@ fn _f0() { let _: Box; } -// Include object safe traits: +// Include dyn-compatible traits: fn _f1() { let _: Box; @@ -28,7 +28,7 @@ fn _f1() { let _: Box; } -// And when the object safe trait is in a trait alias: +// And when the dyn-compatible trait is in a trait alias: trait _2 = Obj; diff --git a/tests/ui/traits/next-solver/object-unsafety.rs b/tests/ui/traits/next-solver/dyn-incompatibility.rs similarity index 100% rename from tests/ui/traits/next-solver/object-unsafety.rs rename to tests/ui/traits/next-solver/dyn-incompatibility.rs diff --git a/tests/ui/traits/next-solver/object-unsafety.stderr b/tests/ui/traits/next-solver/dyn-incompatibility.stderr similarity index 90% rename from tests/ui/traits/next-solver/object-unsafety.stderr rename to tests/ui/traits/next-solver/dyn-incompatibility.stderr index 75d0ce244132e..7f2c0646ef501 100644 --- a/tests/ui/traits/next-solver/object-unsafety.stderr +++ b/tests/ui/traits/next-solver/dyn-incompatibility.stderr @@ -1,12 +1,12 @@ error[E0277]: the trait bound `T: Copy` is not satisfied in `dyn Setup` - --> $DIR/object-unsafety.rs:12:12 + --> $DIR/dyn-incompatibility.rs:12:12 | LL | copy::>(t) | ^^^^^^^^^^^^^^^^^ within `dyn Setup`, the trait `Copy` is not implemented for `T`, which is required by `dyn Setup: Setup` | = note: required because it appears within the type `dyn Setup` note: required by a bound in `copy` - --> $DIR/object-unsafety.rs:7:12 + --> $DIR/dyn-incompatibility.rs:7:12 | LL | fn copy(from: &U::From) -> U::From { | ^^^^^ required by this bound in `copy` @@ -16,7 +16,7 @@ LL | pub fn copy_any(t: &T) -> T { | +++++++++++++++++++ error[E0308]: mismatched types - --> $DIR/object-unsafety.rs:12:31 + --> $DIR/dyn-incompatibility.rs:12:31 | LL | copy::>(t) | ------------------------- ^ types differ @@ -26,13 +26,13 @@ LL | copy::>(t) = note: expected reference `& as Setup>::From` found reference `&T` note: function defined here - --> $DIR/object-unsafety.rs:7:4 + --> $DIR/dyn-incompatibility.rs:7:4 | LL | fn copy(from: &U::From) -> U::From { | ^^^^ -------------- error[E0277]: the trait bound `T: Copy` is not satisfied in `dyn Setup` - --> $DIR/object-unsafety.rs:12:5 + --> $DIR/dyn-incompatibility.rs:12:5 | LL | copy::>(t) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ within `dyn Setup`, the trait `Copy` is not implemented for `T`, which is required by `dyn Setup: Setup` diff --git a/tests/ui/traits/non_lifetime_binders/supertrait-object-safety.rs b/tests/ui/traits/non_lifetime_binders/supertrait-dyn-compatibility.rs similarity index 100% rename from tests/ui/traits/non_lifetime_binders/supertrait-object-safety.rs rename to tests/ui/traits/non_lifetime_binders/supertrait-dyn-compatibility.rs diff --git a/tests/ui/traits/non_lifetime_binders/supertrait-object-safety.stderr b/tests/ui/traits/non_lifetime_binders/supertrait-dyn-compatibility.stderr similarity index 88% rename from tests/ui/traits/non_lifetime_binders/supertrait-object-safety.stderr rename to tests/ui/traits/non_lifetime_binders/supertrait-dyn-compatibility.stderr index 0854ea28150fb..dd2dca74f9087 100644 --- a/tests/ui/traits/non_lifetime_binders/supertrait-object-safety.stderr +++ b/tests/ui/traits/non_lifetime_binders/supertrait-dyn-compatibility.stderr @@ -1,5 +1,5 @@ warning: the feature `non_lifetime_binders` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/supertrait-object-safety.rs:1:12 + --> $DIR/supertrait-dyn-compatibility.rs:1:12 | LL | #![feature(non_lifetime_binders)] | ^^^^^^^^^^^^^^^^^^^^ @@ -8,13 +8,13 @@ LL | #![feature(non_lifetime_binders)] = note: `#[warn(incomplete_features)]` on by default error[E0038]: the trait `Foo` cannot be made into an object - --> $DIR/supertrait-object-safety.rs:19:23 + --> $DIR/supertrait-dyn-compatibility.rs:19:23 | LL | let x: &dyn Foo = &(); | ^^^ `Foo` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/supertrait-object-safety.rs:4:12 + --> $DIR/supertrait-dyn-compatibility.rs:4:12 | LL | trait Foo: for Bar {} | --- ^^^^^^^^^^^^^ ...because where clause cannot reference non-lifetime `for<...>` variables @@ -24,13 +24,13 @@ LL | trait Foo: for Bar {} = note: required for the cast from `&()` to `&dyn Foo` error[E0038]: the trait `Foo` cannot be made into an object - --> $DIR/supertrait-object-safety.rs:19:12 + --> $DIR/supertrait-dyn-compatibility.rs:19:12 | LL | let x: &dyn Foo = &(); | ^^^^^^^^ `Foo` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/supertrait-object-safety.rs:4:12 + --> $DIR/supertrait-dyn-compatibility.rs:4:12 | LL | trait Foo: for Bar {} | --- ^^^^^^^^^^^^^ ...because where clause cannot reference non-lifetime `for<...>` variables @@ -39,13 +39,13 @@ LL | trait Foo: for Bar {} = help: only type `()` implements the trait, consider using it directly instead error[E0038]: the trait `Foo` cannot be made into an object - --> $DIR/supertrait-object-safety.rs:22:5 + --> $DIR/supertrait-dyn-compatibility.rs:22:5 | LL | needs_bar(x); | ^^^^^^^^^ `Foo` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/supertrait-object-safety.rs:4:12 + --> $DIR/supertrait-dyn-compatibility.rs:4:12 | LL | trait Foo: for Bar {} | --- ^^^^^^^^^^^^^ ...because where clause cannot reference non-lifetime `for<...>` variables diff --git a/tests/ui/traits/object/print_vtable_sizes.rs b/tests/ui/traits/object/print_vtable_sizes.rs index 684458d079e5e..2b1745da5f308 100644 --- a/tests/ui/traits/object/print_vtable_sizes.rs +++ b/tests/ui/traits/object/print_vtable_sizes.rs @@ -7,7 +7,7 @@ trait A: AsRef<[T::V]> + AsMut<[T::V]> {} trait B: AsRef + AsRef + AsRef + AsRef {} trait C { - fn x() {} // not object safe, shouldn't be reported + fn x() {} // not dyn-compatible, shouldn't be reported } // This does not have any upcasting cost, diff --git a/tests/ui/traits/object/safety.rs b/tests/ui/traits/object/safety.rs index f43d332d69637..f4abcf8542e5f 100644 --- a/tests/ui/traits/object/safety.rs +++ b/tests/ui/traits/object/safety.rs @@ -1,4 +1,4 @@ -// Check that static methods are not object-safe. +// Check that static methods render the trait dyn-incompatible. trait Tr { fn foo(); diff --git a/tests/ui/traits/vtable/vtable-non-object-safe.rs b/tests/ui/traits/vtable/vtable-dyn-incompatible.rs similarity index 78% rename from tests/ui/traits/vtable/vtable-non-object-safe.rs rename to tests/ui/traits/vtable/vtable-dyn-incompatible.rs index f98af0f23b732..64a8138bdcfb3 100644 --- a/tests/ui/traits/vtable/vtable-non-object-safe.rs +++ b/tests/ui/traits/vtable/vtable-dyn-incompatible.rs @@ -1,7 +1,7 @@ //@ build-fail #![feature(rustc_attrs)] -// Ensure that non-object-safe methods in Iterator does not generate +// Ensure that dyn-incompatible methods in Iterator does not generate // vtable entries. #[rustc_dump_vtable] diff --git a/tests/ui/traits/vtable/vtable-non-object-safe.stderr b/tests/ui/traits/vtable/vtable-dyn-incompatible.stderr similarity index 92% rename from tests/ui/traits/vtable/vtable-non-object-safe.stderr rename to tests/ui/traits/vtable/vtable-dyn-incompatible.stderr index 53eef5d0b13ca..e442c3eac00ea 100644 --- a/tests/ui/traits/vtable/vtable-non-object-safe.stderr +++ b/tests/ui/traits/vtable/vtable-dyn-incompatible.stderr @@ -7,7 +7,7 @@ error: vtable entries for ` as A>`: [ Method( as Iterator>::advance_by), Method( as Iterator>::nth), ] - --> $DIR/vtable-non-object-safe.rs:8:1 + --> $DIR/vtable-dyn-incompatible.rs:8:1 | LL | trait A: Iterator {} | ^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/traits/wf-object/no-duplicates.rs b/tests/ui/traits/wf-object/no-duplicates.rs index 678ede58296a4..83544064ce210 100644 --- a/tests/ui/traits/wf-object/no-duplicates.rs +++ b/tests/ui/traits/wf-object/no-duplicates.rs @@ -1,7 +1,7 @@ -// The purpose of this test is to demonstrate that duplicating object safe traits +// The purpose of this test is to demonstrate that duplicating dyn-compatible traits // that are not auto-traits is rejected even though one could reasonably accept this. -// Some arbitrary object-safe trait: +// Some arbitrary dyn-compatible trait: trait Obj {} // Demonstrate that recursive expansion of trait aliases doesn't affect stable behavior: diff --git a/tests/ui/traits/wf-object/reverse-order.rs b/tests/ui/traits/wf-object/reverse-order.rs index b8f2aae89663b..99c727cc332b2 100644 --- a/tests/ui/traits/wf-object/reverse-order.rs +++ b/tests/ui/traits/wf-object/reverse-order.rs @@ -2,7 +2,7 @@ // Ensure that `dyn $($AutoTrait)+ ObjSafe` is well-formed. -// Some arbitrary object-safe trait: +// Some arbitrary dyn-compatible trait: trait Obj {} type _0 = dyn Unpin; diff --git a/tests/ui/unsized-locals/by-value-trait-object-safety-rpass.rs b/tests/ui/unsized-locals/by-value-trait-dyn-compatibility-rpass.rs similarity index 100% rename from tests/ui/unsized-locals/by-value-trait-object-safety-rpass.rs rename to tests/ui/unsized-locals/by-value-trait-dyn-compatibility-rpass.rs diff --git a/tests/ui/unsized-locals/by-value-trait-object-safety-withdefault.rs b/tests/ui/unsized-locals/by-value-trait-dyn-compatibility-with-default.rs similarity index 100% rename from tests/ui/unsized-locals/by-value-trait-object-safety-withdefault.rs rename to tests/ui/unsized-locals/by-value-trait-dyn-compatibility-with-default.rs diff --git a/tests/ui/unsized-locals/by-value-trait-object-safety.rs b/tests/ui/unsized-locals/by-value-trait-dyn-compatibility.rs similarity index 100% rename from tests/ui/unsized-locals/by-value-trait-object-safety.rs rename to tests/ui/unsized-locals/by-value-trait-dyn-compatibility.rs diff --git a/tests/ui/unsized-locals/by-value-trait-object-safety.stderr b/tests/ui/unsized-locals/by-value-trait-dyn-compatibility.stderr similarity index 84% rename from tests/ui/unsized-locals/by-value-trait-object-safety.stderr rename to tests/ui/unsized-locals/by-value-trait-dyn-compatibility.stderr index 6a93464febb10..223624cfca4dd 100644 --- a/tests/ui/unsized-locals/by-value-trait-object-safety.stderr +++ b/tests/ui/unsized-locals/by-value-trait-dyn-compatibility.stderr @@ -1,5 +1,5 @@ warning: the feature `unsized_locals` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/by-value-trait-object-safety.rs:1:12 + --> $DIR/by-value-trait-dyn-compatibility.rs:1:12 | LL | #![feature(unsized_locals)] | ^^^^^^^^^^^^^^ @@ -8,7 +8,7 @@ LL | #![feature(unsized_locals)] = note: `#[warn(incomplete_features)]` on by default error: the `foo` method cannot be invoked on a trait object - --> $DIR/by-value-trait-object-safety.rs:20:7 + --> $DIR/by-value-trait-dyn-compatibility.rs:20:7 | LL | Self: Sized; | ----- this has a `Sized` requirement diff --git a/tests/ui/wf/wf-convert-unsafe-trait-obj-box.rs b/tests/ui/wf/wf-convert-dyn-incompat-trait-obj-box.rs similarity index 87% rename from tests/ui/wf/wf-convert-unsafe-trait-obj-box.rs rename to tests/ui/wf/wf-convert-dyn-incompat-trait-obj-box.rs index e32b04c471524..26292a1d218c9 100644 --- a/tests/ui/wf/wf-convert-unsafe-trait-obj-box.rs +++ b/tests/ui/wf/wf-convert-dyn-incompat-trait-obj-box.rs @@ -1,5 +1,5 @@ // Check that we do not allow casts or coercions -// to object unsafe trait objects inside a Box +// to dyn-incompatible trait objects inside a Box #![feature(dyn_compatible_for_dispatch)] diff --git a/tests/ui/wf/wf-convert-unsafe-trait-obj-box.stderr b/tests/ui/wf/wf-convert-dyn-incompat-trait-obj-box.stderr similarity index 86% rename from tests/ui/wf/wf-convert-unsafe-trait-obj-box.stderr rename to tests/ui/wf/wf-convert-dyn-incompat-trait-obj-box.stderr index 2565e25a24297..38426545bc8cb 100644 --- a/tests/ui/wf/wf-convert-unsafe-trait-obj-box.stderr +++ b/tests/ui/wf/wf-convert-dyn-incompat-trait-obj-box.stderr @@ -1,11 +1,11 @@ error[E0038]: the trait `Trait` cannot be made into an object - --> $DIR/wf-convert-unsafe-trait-obj-box.rs:16:33 + --> $DIR/wf-convert-dyn-incompat-trait-obj-box.rs:16:33 | LL | let t_box: Box = Box::new(S); | ^^^^^^^^^^^ `Trait` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/wf-convert-unsafe-trait-obj-box.rs:6:14 + --> $DIR/wf-convert-dyn-incompat-trait-obj-box.rs:6:14 | LL | trait Trait: Sized {} | ----- ^^^^^ ...because it requires `Self: Sized` @@ -15,13 +15,13 @@ LL | trait Trait: Sized {} = note: required for the cast from `Box` to `Box` error[E0038]: the trait `Trait` cannot be made into an object - --> $DIR/wf-convert-unsafe-trait-obj-box.rs:17:15 + --> $DIR/wf-convert-dyn-incompat-trait-obj-box.rs:17:15 | LL | takes_box(Box::new(S)); | ^^^^^^^^^^^ `Trait` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/wf-convert-unsafe-trait-obj-box.rs:6:14 + --> $DIR/wf-convert-dyn-incompat-trait-obj-box.rs:6:14 | LL | trait Trait: Sized {} | ----- ^^^^^ ...because it requires `Self: Sized` @@ -31,13 +31,13 @@ LL | trait Trait: Sized {} = note: required for the cast from `Box` to `Box<(dyn Trait + 'static)>` error[E0038]: the trait `Trait` cannot be made into an object - --> $DIR/wf-convert-unsafe-trait-obj-box.rs:15:5 + --> $DIR/wf-convert-dyn-incompat-trait-obj-box.rs:15:5 | LL | Box::new(S) as Box; | ^^^^^^^^^^^ `Trait` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/wf-convert-unsafe-trait-obj-box.rs:6:14 + --> $DIR/wf-convert-dyn-incompat-trait-obj-box.rs:6:14 | LL | trait Trait: Sized {} | ----- ^^^^^ ...because it requires `Self: Sized` diff --git a/tests/ui/wf/wf-convert-unsafe-trait-obj.rs b/tests/ui/wf/wf-convert-dyn-incompat-trait-obj.rs similarity index 87% rename from tests/ui/wf/wf-convert-unsafe-trait-obj.rs rename to tests/ui/wf/wf-convert-dyn-incompat-trait-obj.rs index 6f38635281983..ec4bb2897f9dc 100644 --- a/tests/ui/wf/wf-convert-unsafe-trait-obj.rs +++ b/tests/ui/wf/wf-convert-dyn-incompat-trait-obj.rs @@ -1,5 +1,5 @@ // Check that we do not allow casts or coercions -// to object unsafe trait objects by ref +// to dyn-incompatible trait objects by ref #![feature(dyn_compatible_for_dispatch)] diff --git a/tests/ui/wf/wf-convert-unsafe-trait-obj.stderr b/tests/ui/wf/wf-convert-dyn-incompat-trait-obj.stderr similarity index 87% rename from tests/ui/wf/wf-convert-unsafe-trait-obj.stderr rename to tests/ui/wf/wf-convert-dyn-incompat-trait-obj.stderr index 97f6bcd0428b6..94259aa5b0aa8 100644 --- a/tests/ui/wf/wf-convert-unsafe-trait-obj.stderr +++ b/tests/ui/wf/wf-convert-dyn-incompat-trait-obj.stderr @@ -1,11 +1,11 @@ error[E0038]: the trait `Trait` cannot be made into an object - --> $DIR/wf-convert-unsafe-trait-obj.rs:16:25 + --> $DIR/wf-convert-dyn-incompat-trait-obj.rs:16:25 | LL | let t: &dyn Trait = &S; | ^^ `Trait` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/wf-convert-unsafe-trait-obj.rs:6:14 + --> $DIR/wf-convert-dyn-incompat-trait-obj.rs:6:14 | LL | trait Trait: Sized {} | ----- ^^^^^ ...because it requires `Self: Sized` @@ -15,13 +15,13 @@ LL | trait Trait: Sized {} = note: required for the cast from `&S` to `&dyn Trait` error[E0038]: the trait `Trait` cannot be made into an object - --> $DIR/wf-convert-unsafe-trait-obj.rs:17:17 + --> $DIR/wf-convert-dyn-incompat-trait-obj.rs:17:17 | LL | takes_trait(&S); | ^^ `Trait` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/wf-convert-unsafe-trait-obj.rs:6:14 + --> $DIR/wf-convert-dyn-incompat-trait-obj.rs:6:14 | LL | trait Trait: Sized {} | ----- ^^^^^ ...because it requires `Self: Sized` @@ -31,13 +31,13 @@ LL | trait Trait: Sized {} = note: required for the cast from `&S` to `&dyn Trait` error[E0038]: the trait `Trait` cannot be made into an object - --> $DIR/wf-convert-unsafe-trait-obj.rs:15:5 + --> $DIR/wf-convert-dyn-incompat-trait-obj.rs:15:5 | LL | &S as &dyn Trait; | ^^ `Trait` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/wf-convert-unsafe-trait-obj.rs:6:14 + --> $DIR/wf-convert-dyn-incompat-trait-obj.rs:6:14 | LL | trait Trait: Sized {} | ----- ^^^^^ ...because it requires `Self: Sized` diff --git a/tests/ui/wf/wf-unsafe-trait-obj-match.rs b/tests/ui/wf/wf-dyn-incompat-trait-obj-match.rs similarity index 100% rename from tests/ui/wf/wf-unsafe-trait-obj-match.rs rename to tests/ui/wf/wf-dyn-incompat-trait-obj-match.rs diff --git a/tests/ui/wf/wf-unsafe-trait-obj-match.stderr b/tests/ui/wf/wf-dyn-incompat-trait-obj-match.stderr similarity index 89% rename from tests/ui/wf/wf-unsafe-trait-obj-match.stderr rename to tests/ui/wf/wf-dyn-incompat-trait-obj-match.stderr index edbdec6a5efc6..d7366e12256a2 100644 --- a/tests/ui/wf/wf-unsafe-trait-obj-match.stderr +++ b/tests/ui/wf/wf-dyn-incompat-trait-obj-match.stderr @@ -1,5 +1,5 @@ error[E0308]: `match` arms have incompatible types - --> $DIR/wf-unsafe-trait-obj-match.rs:23:17 + --> $DIR/wf-dyn-incompat-trait-obj-match.rs:23:17 | LL | / match opt() { LL | | Some(()) => &S, @@ -13,13 +13,13 @@ LL | | } found reference `&R` error[E0038]: the trait `Trait` cannot be made into an object - --> $DIR/wf-unsafe-trait-obj-match.rs:26:21 + --> $DIR/wf-dyn-incompat-trait-obj-match.rs:26:21 | LL | Some(()) => &S, | ^^ `Trait` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/wf-unsafe-trait-obj-match.rs:6:14 + --> $DIR/wf-dyn-incompat-trait-obj-match.rs:6:14 | LL | trait Trait: Sized {} | ----- ^^^^^ ...because it requires `Self: Sized` @@ -31,7 +31,7 @@ LL | trait Trait: Sized {} = note: required for the cast from `&S` to `&dyn Trait` error[E0038]: the trait `Trait` cannot be made into an object - --> $DIR/wf-unsafe-trait-obj-match.rs:25:25 + --> $DIR/wf-dyn-incompat-trait-obj-match.rs:25:25 | LL | let t: &dyn Trait = match opt() { | _________________________^ @@ -41,7 +41,7 @@ LL | | }; | |_____^ `Trait` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/wf-unsafe-trait-obj-match.rs:6:14 + --> $DIR/wf-dyn-incompat-trait-obj-match.rs:6:14 | LL | trait Trait: Sized {} | ----- ^^^^^ ...because it requires `Self: Sized` diff --git a/tests/ui/wf/wf-object-safe.rs b/tests/ui/wf/wf-dyn-incompatible.rs similarity index 57% rename from tests/ui/wf/wf-object-safe.rs rename to tests/ui/wf/wf-dyn-incompatible.rs index 42e6917551fd9..16e7ca1cbc618 100644 --- a/tests/ui/wf/wf-object-safe.rs +++ b/tests/ui/wf/wf-dyn-incompatible.rs @@ -1,4 +1,4 @@ -// Check that object-safe traits are not WF when used as object types. +// Check that dyn-incompatible traits are not WF when used as trait object types. // Issue #21953. trait A { diff --git a/tests/ui/wf/wf-object-safe.stderr b/tests/ui/wf/wf-dyn-incompatible.stderr similarity index 90% rename from tests/ui/wf/wf-object-safe.stderr rename to tests/ui/wf/wf-dyn-incompatible.stderr index 7c14f3d2f8bf6..cf016b63c7405 100644 --- a/tests/ui/wf/wf-object-safe.stderr +++ b/tests/ui/wf/wf-dyn-incompatible.stderr @@ -1,11 +1,11 @@ error[E0038]: the trait `A` cannot be made into an object - --> $DIR/wf-object-safe.rs:9:13 + --> $DIR/wf-dyn-incompatible.rs:9:13 | LL | let _x: &dyn A; | ^^^^^^ `A` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/wf-object-safe.rs:5:23 + --> $DIR/wf-dyn-incompatible.rs:5:23 | LL | trait A { | - this trait cannot be made into an object... From d6aaf7b036868c29e74ec380493f81ecbd1a4503 Mon Sep 17 00:00:00 2001 From: Mads Marquart Date: Thu, 10 Oct 2024 03:38:10 +0200 Subject: [PATCH 2074/2194] Avoid redundant -Wl,-dylib flag when linking --- compiler/rustc_codegen_ssa/src/back/linker.rs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/back/linker.rs b/compiler/rustc_codegen_ssa/src/back/linker.rs index 3f3d305da0142..c4bb82d0dd7b1 100644 --- a/compiler/rustc_codegen_ssa/src/back/linker.rs +++ b/compiler/rustc_codegen_ssa/src/back/linker.rs @@ -404,12 +404,14 @@ impl<'a> GccLinker<'a> { fn build_dylib(&mut self, crate_type: CrateType, out_filename: &Path) { // On mac we need to tell the linker to let this library be rpathed if self.sess.target.is_like_osx { - if !self.is_ld { + if self.is_cc() { + // `-dynamiclib` makes `cc` pass `-dylib` to the linker. self.cc_arg("-dynamiclib"); + } else { + self.link_arg("-dylib"); + // Clang also sets `-dynamic`, but that's implied by `-dylib`, so unnecessary. } - self.link_arg("-dylib"); - // Note that the `osx_rpath_install_name` option here is a hack // purely to support bootstrap right now, we should get a more // principled solution at some point to force the compiler to pass From 09b634a4ba72336f1de2e3f5dccadd6e5bc3a011 Mon Sep 17 00:00:00 2001 From: Mads Marquart Date: Thu, 10 Oct 2024 04:03:48 +0200 Subject: [PATCH 2075/2194] Fix hardcoded strip path when cross-compiling from Linux to Darwin --- compiler/rustc_codegen_ssa/src/back/link.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index e7b1c63a82251..34dc599e4fddd 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -1087,7 +1087,9 @@ fn link_natively( let strip = sess.opts.cg.strip; if sess.target.is_like_osx { - let stripcmd = "/usr/bin/strip"; + // Use system `strip` when running on host macOS. + // + let stripcmd = if cfg!(target_os = "macos") { "/usr/bin/strip" } else { "strip" }; match (strip, crate_type) { (Strip::Debuginfo, _) => { strip_symbols_with_external_utility(sess, stripcmd, out_filename, Some("-S")) From 2a8f08083f32ed64fb367282b4896ee792f0c4a8 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Thu, 10 Oct 2024 00:20:37 -0400 Subject: [PATCH 2076/2194] Structurallyresolve adts and tuples expectations too --- compiler/rustc_hir_typeck/src/expr.rs | 4 +-- .../traits/next-solver/typeck/guide-ctors.rs | 32 +++++++++++++++++++ 2 files changed, 34 insertions(+), 2 deletions(-) create mode 100644 tests/ui/traits/next-solver/typeck/guide-ctors.rs diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index 95ca3e6647272..c5b7fc1eabd7c 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -1783,7 +1783,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { expr: &'tcx hir::Expr<'tcx>, ) -> Ty<'tcx> { let flds = expected.only_has_type(self).and_then(|ty| { - let ty = self.resolve_vars_with_obligations(ty); + let ty = self.try_structurally_resolve_type(expr.span, ty); match ty.kind() { ty::Tuple(flds) => Some(&flds[..]), _ => None, @@ -1861,7 +1861,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ) { let tcx = self.tcx; - let adt_ty = self.resolve_vars_with_obligations(adt_ty); + let adt_ty = self.try_structurally_resolve_type(span, adt_ty); let adt_ty_hint = expected.only_has_type(self).and_then(|expected| { self.fudge_inference_if_ok(|| { let ocx = ObligationCtxt::new(self); diff --git a/tests/ui/traits/next-solver/typeck/guide-ctors.rs b/tests/ui/traits/next-solver/typeck/guide-ctors.rs new file mode 100644 index 0000000000000..7432ea78a56a0 --- /dev/null +++ b/tests/ui/traits/next-solver/typeck/guide-ctors.rs @@ -0,0 +1,32 @@ +//@ compile-flags: -Znext-solver +//@ check-pass + +// Makes sure we structurally normalize before trying to use expectation to guide +// coercion in adt and tuples. + +use std::any::Any; + +trait Coerce { + type Assoc; +} + +struct TupleGuidance; +impl Coerce for TupleGuidance { + type Assoc = (&'static dyn Any,); +} + +struct AdtGuidance; +impl Coerce for AdtGuidance { + type Assoc = Adt<&'static dyn Any>; +} + +struct Adt { + f: T, +} + +fn foo<'a, T: Coerce>(_: T::Assoc) {} + +fn main() { + foo::((&0u32,)); + foo::(Adt { f: &0u32 }); +} From e48159953692320c4866c960e144f7af5551c998 Mon Sep 17 00:00:00 2001 From: Jacob Pratt Date: Thu, 10 Oct 2024 01:09:13 -0400 Subject: [PATCH 2077/2194] Add myself back to review rotation --- triagebot.toml | 1 - 1 file changed, 1 deletion(-) diff --git a/triagebot.toml b/triagebot.toml index d3e4af9b71899..231a7bba1f7c9 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -923,7 +923,6 @@ contributing_url = "https://rustc-dev-guide.rust-lang.org/getting-started.html" users_on_vacation = [ "BoxyUwU", "fmease", - "jhpratt", "jyn514", "oli-obk", ] From b198a4666505a94efbd0a5fb443bb3cf8997be9a Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Thu, 10 Oct 2024 08:54:23 +0300 Subject: [PATCH 2078/2194] disable `download-rustc` if LLVM submodule has changes in CI Signed-off-by: onur-ozkan --- src/bootstrap/src/core/config/config.rs | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs index 9f84b492b80a2..3f025a198cb97 100644 --- a/src/bootstrap/src/core/config/config.rs +++ b/src/bootstrap/src/core/config/config.rs @@ -2399,6 +2399,20 @@ impl Config { Some(commit) => { self.download_ci_rustc(commit); + // CI-rustc can't be used without CI-LLVM. If `self.llvm_from_ci` is false, it means the "if-unchanged" + // logic has detected some changes in the LLVM submodule (download-ci-llvm=false can't happen here as + // we don't allow it while parsing the configuration). + if !self.llvm_from_ci { + // This happens when LLVM submodule is updated in CI, we should disable ci-rustc without an error + // to not break CI. For non-CI environments, we should return an error. + if CiEnv::is_ci() { + println!("WARNING: LLVM submodule has changes, `download-rustc` will be disabled."); + return None; + } else { + panic!("ERROR: LLVM submodule has changes, `download-rustc` can't be used."); + } + } + if let Some(config_path) = &self.config { let ci_config_toml = match self.get_builder_toml("ci-rustc") { Ok(ci_config_toml) => ci_config_toml, From ef5157765691acba2b82e071b0ca4410ed71a252 Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Sat, 5 Oct 2024 21:50:21 +0300 Subject: [PATCH 2079/2194] make `llvm::is_ci_llvm_modified` logic more precise Signed-off-by: onur-ozkan --- src/bootstrap/src/core/build_steps/llvm.rs | 35 +++++++++++++++------- 1 file changed, 24 insertions(+), 11 deletions(-) diff --git a/src/bootstrap/src/core/build_steps/llvm.rs b/src/bootstrap/src/core/build_steps/llvm.rs index 3021358415790..4b403407a2048 100644 --- a/src/bootstrap/src/core/build_steps/llvm.rs +++ b/src/bootstrap/src/core/build_steps/llvm.rs @@ -20,10 +20,9 @@ use build_helper::git::get_closest_merge_commit; use crate::core::builder::{Builder, RunConfig, ShouldRun, Step}; use crate::core::config::{Config, TargetSelection}; -use crate::utils::channel; use crate::utils::exec::command; use crate::utils::helpers::{ - self, HashStamp, exe, get_clang_cl_resource_dir, output, t, unhashed_basename, up_to_date, + self, HashStamp, exe, get_clang_cl_resource_dir, t, unhashed_basename, up_to_date, }; use crate::{CLang, GitRepo, Kind, generate_smart_stamp_hash}; @@ -166,7 +165,7 @@ pub(crate) fn detect_llvm_sha(config: &Config, is_git: bool) -> String { config.src.join("src/version"), ]) .unwrap() - } else if let Some(info) = channel::read_commit_info_file(&config.src) { + } else if let Some(info) = crate::utils::channel::read_commit_info_file(&config.src) { info.sha.trim().to_owned() } else { "".to_owned() @@ -242,15 +241,29 @@ pub(crate) fn is_ci_llvm_available(config: &Config, asserts: bool) -> bool { /// Returns true if we're running in CI with modified LLVM (and thus can't download it) pub(crate) fn is_ci_llvm_modified(config: &Config) -> bool { - CiEnv::is_rust_lang_managed_ci_job() && config.rust_info.is_managed_git_subrepository() && { - // We assume we have access to git, so it's okay to unconditionally pass - // `true` here. - let llvm_sha = detect_llvm_sha(config, true); - let head_sha = - output(helpers::git(Some(&config.src)).arg("rev-parse").arg("HEAD").as_command_mut()); - let head_sha = head_sha.trim(); - llvm_sha == head_sha + // If not running in a CI environment, return false. + if !CiEnv::is_ci() { + return false; + } + + // In rust-lang/rust managed CI, assert the existence of the LLVM submodule. + if CiEnv::is_rust_lang_managed_ci_job() { + assert!( + config.in_tree_llvm_info.is_managed_git_subrepository(), + "LLVM submodule must be fetched in rust-lang/rust managed CI builders." + ); } + // If LLVM submodule isn't present, skip the change check as it won't work. + else if !config.in_tree_llvm_info.is_managed_git_subrepository() { + return false; + } + + let llvm_sha = detect_llvm_sha(config, true); + let head_sha = crate::output( + helpers::git(Some(&config.src)).arg("rev-parse").arg("HEAD").as_command_mut(), + ); + let head_sha = head_sha.trim(); + llvm_sha == head_sha } #[derive(Debug, Clone, Hash, PartialEq, Eq)] From f6b75575e1228762fb1bbe735cb25bf868c48d8b Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Thu, 10 Oct 2024 10:24:41 +0300 Subject: [PATCH 2080/2194] stabilize `download_ci_llvm` test Signed-off-by: onur-ozkan --- src/bootstrap/src/core/config/tests.rs | 36 ++++++++++---------------- 1 file changed, 14 insertions(+), 22 deletions(-) diff --git a/src/bootstrap/src/core/config/tests.rs b/src/bootstrap/src/core/config/tests.rs index e38d4eac051d8..01379db500bfe 100644 --- a/src/bootstrap/src/core/config/tests.rs +++ b/src/bootstrap/src/core/config/tests.rs @@ -20,29 +20,21 @@ fn parse(config: &str) -> Config { #[test] fn download_ci_llvm() { - if crate::core::build_steps::llvm::is_ci_llvm_modified(&parse("")) { - eprintln!("Detected LLVM as non-available: running in CI and modified LLVM in this change"); - return; + assert!(parse("").llvm_from_ci); + assert!(parse("llvm.download-ci-llvm = true").llvm_from_ci); + assert!(!parse("llvm.download-ci-llvm = false").llvm_from_ci); + + let if_unchanged_config = parse("llvm.download-ci-llvm = \"if-unchanged\""); + if if_unchanged_config.llvm_from_ci { + let has_changes = if_unchanged_config + .last_modified_commit(&["src/llvm-project"], "download-ci-llvm", true) + .is_none(); + + assert!( + !has_changes, + "CI LLVM can't be enabled with 'if-unchanged' while there are changes in LLVM submodule." + ); } - - let parse_llvm = |s| parse(s).llvm_from_ci; - let if_unchanged = parse_llvm("llvm.download-ci-llvm = \"if-unchanged\""); - - assert!(parse_llvm("llvm.download-ci-llvm = true")); - assert!(!parse_llvm("llvm.download-ci-llvm = false")); - assert_eq!(parse_llvm(""), if_unchanged); - assert_eq!(parse_llvm("rust.channel = \"dev\""), if_unchanged); - assert!(parse_llvm("rust.channel = \"stable\"")); - assert_eq!(parse_llvm("build.build = \"x86_64-unknown-linux-gnu\""), if_unchanged); - assert_eq!( - parse_llvm( - "llvm.assertions = true \r\n build.build = \"x86_64-unknown-linux-gnu\" \r\n llvm.download-ci-llvm = \"if-unchanged\"" - ), - if_unchanged - ); - assert!(!parse_llvm( - "llvm.assertions = true \r\n build.build = \"aarch64-apple-darwin\" \r\n llvm.download-ci-llvm = \"if-unchanged\"" - )); } // FIXME(onur-ozkan): extend scope of the test From b27aee9b8b21b367d12b499de29023d429b0ba79 Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Wed, 9 Oct 2024 22:22:13 +0300 Subject: [PATCH 2081/2194] stabilize `ci_rustc_if_unchanged_logic` test Signed-off-by: onur-ozkan --- src/bootstrap/src/core/builder/tests.rs | 39 +++++++------------------ 1 file changed, 11 insertions(+), 28 deletions(-) diff --git a/src/bootstrap/src/core/builder/tests.rs b/src/bootstrap/src/core/builder/tests.rs index 4ab1ef1ad0ffd..695a66834d45d 100644 --- a/src/bootstrap/src/core/builder/tests.rs +++ b/src/bootstrap/src/core/builder/tests.rs @@ -1,7 +1,5 @@ use std::thread; -use build_helper::git::get_closest_merge_commit; - use super::*; use crate::Flags; use crate::core::build_steps::doc::DocumentationFormat; @@ -214,8 +212,6 @@ fn alias_and_path_for_library() { assert_eq!(first(cache.all::()), &[doc_std!(A => A, stage = 0)]); } -// FIXME: This is failing in various runners in merge CI. -#[ignore] #[test] fn ci_rustc_if_unchanged_logic() { let config = Config::parse_inner( @@ -227,10 +223,6 @@ fn ci_rustc_if_unchanged_logic() { |&_| Ok(Default::default()), ); - if config.rust_info.is_from_tarball() { - return; - } - let build = Build::new(config.clone()); let builder = Builder::new(&build); @@ -240,26 +232,17 @@ fn ci_rustc_if_unchanged_logic() { builder.run_step_descriptions(&Builder::get_step_descriptions(config.cmd.kind()), &[]); - let compiler_path = build.src.join("compiler"); - let library_path = build.src.join("library"); - - let commit = - get_closest_merge_commit(Some(&builder.config.src), &builder.config.git_config(), &[ - compiler_path.clone(), - library_path.clone(), - ]) - .unwrap(); - - let has_changes = !helpers::git(Some(&builder.src)) - .args(["diff-index", "--quiet", &commit]) - .arg("--") - .args([compiler_path, library_path]) - .as_command_mut() - .status() - .unwrap() - .success(); - - assert!(has_changes == config.download_rustc_commit.is_none()); + // Make sure "if-unchanged" logic doesn't try to use CI rustc while there are changes + // in compiler and/or library. + if config.download_rustc_commit.is_some() { + let has_changes = + config.last_modified_commit(&["compiler", "library"], "download-rustc", true).is_none(); + + assert!( + !has_changes, + "CI-rustc can't be used with 'if-unchanged' while there are changes in compiler and/or library." + ); + } } mod defaults { From de744eafe134a2f0ddde8db1b0d94ec5f8bc1481 Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Thu, 10 Oct 2024 08:33:14 +0300 Subject: [PATCH 2082/2194] update `rustc_borrowck::places_conflict` doc-comment Signed-off-by: onur-ozkan --- compiler/rustc_borrowck/src/places_conflict.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_borrowck/src/places_conflict.rs b/compiler/rustc_borrowck/src/places_conflict.rs index 519ba0b9e0c9f..679e111caa984 100644 --- a/compiler/rustc_borrowck/src/places_conflict.rs +++ b/compiler/rustc_borrowck/src/places_conflict.rs @@ -3,7 +3,7 @@ //! we can prove overlap one way or another. Essentially, we treat `Overlap` as //! a monoid and report a conflict if the product ends up not being `Disjoint`. //! -//! At each step, if we didn't run out of borrow or place, we know that our elements +//! On each step, if we didn't run out of borrow or place, we know that our elements //! have the same type, and that they only overlap if they are the identical. //! //! For example, if we are comparing these: From a21a9fe3322cf3c3707f6e6ac644dfbe118a66dc Mon Sep 17 00:00:00 2001 From: bors Date: Thu, 10 Oct 2024 09:17:20 +0000 Subject: [PATCH 2083/2194] Auto merge of #13464 - y21:issue13458, r=flip1995 Don't warn on proc macro generated code in `needless_return` Fixes #13458 Fixes #13457 Fixes #13467 Fixes #13479 Fixes #13481 Fixes #13526 Fixes #13486 The fix is unfortunately a little more convoluted than just simply adding a `is_from_proc_macro`. That check *does* fix the issue, however it also introduces a bunch of false negatives in the tests, specifically when the returned expression is in a different syntax context, e.g. `return format!(..)`. The proc macro check builds up a start and end pattern based on the HIR nodes and compares it to a snippet of the span, however that would currently fail for `return format!(..)` because we would have the patterns `("return", )`, which doesn't compare equal. So we now return an empty string pattern for when it's in a different syntax context. "Hide whitespace" helps a bit for reviewing the proc macro detection change changelog: none --- src/tools/clippy/clippy_lints/src/returns.rs | 2 +- .../clippy_utils/src/check_proc_macro.rs | 135 +++++++++++------- .../clippy/tests/ui/dbg_macro/dbg_macro.fixed | 2 +- .../clippy/tests/ui/dbg_macro/dbg_macro.rs | 2 +- .../clippy/tests/ui/needless_return.fixed | 8 ++ src/tools/clippy/tests/ui/needless_return.rs | 8 ++ .../clippy/tests/ui/needless_return.stderr | 108 +++++++------- 7 files changed, 154 insertions(+), 111 deletions(-) diff --git a/src/tools/clippy/clippy_lints/src/returns.rs b/src/tools/clippy/clippy_lints/src/returns.rs index f6f75d8c798a6..662745e4b5d67 100644 --- a/src/tools/clippy/clippy_lints/src/returns.rs +++ b/src/tools/clippy/clippy_lints/src/returns.rs @@ -407,7 +407,7 @@ fn check_final_expr<'tcx>( } } - if ret_span.from_expansion() { + if ret_span.from_expansion() || is_from_proc_macro(cx, expr) { return; } diff --git a/src/tools/clippy/clippy_utils/src/check_proc_macro.rs b/src/tools/clippy/clippy_utils/src/check_proc_macro.rs index b18997e6ee420..bfb3a76ad251c 100644 --- a/src/tools/clippy/clippy_utils/src/check_proc_macro.rs +++ b/src/tools/clippy/clippy_utils/src/check_proc_macro.rs @@ -141,62 +141,89 @@ fn path_search_pat(path: &Path<'_>) -> (Pat, Pat) { /// Get the search patterns to use for the given expression fn expr_search_pat(tcx: TyCtxt<'_>, e: &Expr<'_>) -> (Pat, Pat) { - match e.kind { - ExprKind::ConstBlock(_) => (Pat::Str("const"), Pat::Str("}")), - // Parenthesis are trimmed from the text before the search patterns are matched. - // See: `span_matches_pat` - ExprKind::Tup([]) => (Pat::Str(")"), Pat::Str("(")), - ExprKind::Unary(UnOp::Deref, e) => (Pat::Str("*"), expr_search_pat(tcx, e).1), - ExprKind::Unary(UnOp::Not, e) => (Pat::Str("!"), expr_search_pat(tcx, e).1), - ExprKind::Unary(UnOp::Neg, e) => (Pat::Str("-"), expr_search_pat(tcx, e).1), - ExprKind::Lit(lit) => lit_search_pat(&lit.node), - ExprKind::Array(_) | ExprKind::Repeat(..) => (Pat::Str("["), Pat::Str("]")), - ExprKind::Call(e, []) | ExprKind::MethodCall(_, e, [], _) => (expr_search_pat(tcx, e).0, Pat::Str("(")), - ExprKind::Call(first, [.., last]) - | ExprKind::MethodCall(_, first, [.., last], _) - | ExprKind::Binary(_, first, last) - | ExprKind::Tup([first, .., last]) - | ExprKind::Assign(first, last, _) - | ExprKind::AssignOp(_, first, last) => (expr_search_pat(tcx, first).0, expr_search_pat(tcx, last).1), - ExprKind::Tup([e]) | ExprKind::DropTemps(e) => expr_search_pat(tcx, e), - ExprKind::Cast(e, _) | ExprKind::Type(e, _) => (expr_search_pat(tcx, e).0, Pat::Str("")), - ExprKind::Let(let_expr) => (Pat::Str("let"), expr_search_pat(tcx, let_expr.init).1), - ExprKind::If(..) => (Pat::Str("if"), Pat::Str("}")), - ExprKind::Loop(_, Some(_), _, _) | ExprKind::Block(_, Some(_)) => (Pat::Str("'"), Pat::Str("}")), - ExprKind::Loop(_, None, LoopSource::Loop, _) => (Pat::Str("loop"), Pat::Str("}")), - ExprKind::Loop(_, None, LoopSource::While, _) => (Pat::Str("while"), Pat::Str("}")), - ExprKind::Loop(_, None, LoopSource::ForLoop, _) | ExprKind::Match(_, _, MatchSource::ForLoopDesugar) => { - (Pat::Str("for"), Pat::Str("}")) - }, - ExprKind::Match(_, _, MatchSource::Normal) => (Pat::Str("match"), Pat::Str("}")), - ExprKind::Match(e, _, MatchSource::TryDesugar(_)) => (expr_search_pat(tcx, e).0, Pat::Str("?")), - ExprKind::Match(e, _, MatchSource::AwaitDesugar) | ExprKind::Yield(e, YieldSource::Await { .. }) => { - (expr_search_pat(tcx, e).0, Pat::Str("await")) - }, - ExprKind::Closure(&Closure { body, .. }) => (Pat::Str(""), expr_search_pat(tcx, tcx.hir().body(body).value).1), - ExprKind::Block( - Block { - rules: BlockCheckMode::UnsafeBlock(UnsafeSource::UserProvided), - .. + fn expr_search_pat_inner(tcx: TyCtxt<'_>, e: &Expr<'_>, outer_span: Span) -> (Pat, Pat) { + // The expression can have subexpressions in different contexts, in which case + // building up a search pattern from the macro expansion would lead to false positives; + // e.g. `return format!(..)` would be considered to be from a proc macro + // if we build up a pattern for the macro expansion and compare it to the invocation `format!()`. + // So instead we return an empty pattern such that `span_matches_pat` always returns true. + if !e.span.eq_ctxt(outer_span) { + return (Pat::Str(""), Pat::Str("")); + } + + match e.kind { + ExprKind::ConstBlock(_) => (Pat::Str("const"), Pat::Str("}")), + // Parenthesis are trimmed from the text before the search patterns are matched. + // See: `span_matches_pat` + ExprKind::Tup([]) => (Pat::Str(")"), Pat::Str("(")), + ExprKind::Unary(UnOp::Deref, e) => (Pat::Str("*"), expr_search_pat_inner(tcx, e, outer_span).1), + ExprKind::Unary(UnOp::Not, e) => (Pat::Str("!"), expr_search_pat_inner(tcx, e, outer_span).1), + ExprKind::Unary(UnOp::Neg, e) => (Pat::Str("-"), expr_search_pat_inner(tcx, e, outer_span).1), + ExprKind::Lit(lit) => lit_search_pat(&lit.node), + ExprKind::Array(_) | ExprKind::Repeat(..) => (Pat::Str("["), Pat::Str("]")), + ExprKind::Call(e, []) | ExprKind::MethodCall(_, e, [], _) => { + (expr_search_pat_inner(tcx, e, outer_span).0, Pat::Str("(")) }, - None, - ) => (Pat::Str("unsafe"), Pat::Str("}")), - ExprKind::Block(_, None) => (Pat::Str("{"), Pat::Str("}")), - ExprKind::Field(e, name) => (expr_search_pat(tcx, e).0, Pat::Sym(name.name)), - ExprKind::Index(e, _, _) => (expr_search_pat(tcx, e).0, Pat::Str("]")), - ExprKind::Path(ref path) => qpath_search_pat(path), - ExprKind::AddrOf(_, _, e) => (Pat::Str("&"), expr_search_pat(tcx, e).1), - ExprKind::Break(Destination { label: None, .. }, None) => (Pat::Str("break"), Pat::Str("break")), - ExprKind::Break(Destination { label: Some(name), .. }, None) => (Pat::Str("break"), Pat::Sym(name.ident.name)), - ExprKind::Break(_, Some(e)) => (Pat::Str("break"), expr_search_pat(tcx, e).1), - ExprKind::Continue(Destination { label: None, .. }) => (Pat::Str("continue"), Pat::Str("continue")), - ExprKind::Continue(Destination { label: Some(name), .. }) => (Pat::Str("continue"), Pat::Sym(name.ident.name)), - ExprKind::Ret(None) => (Pat::Str("return"), Pat::Str("return")), - ExprKind::Ret(Some(e)) => (Pat::Str("return"), expr_search_pat(tcx, e).1), - ExprKind::Struct(path, _, _) => (qpath_search_pat(path).0, Pat::Str("}")), - ExprKind::Yield(e, YieldSource::Yield) => (Pat::Str("yield"), expr_search_pat(tcx, e).1), - _ => (Pat::Str(""), Pat::Str("")), + ExprKind::Call(first, [.., last]) + | ExprKind::MethodCall(_, first, [.., last], _) + | ExprKind::Binary(_, first, last) + | ExprKind::Tup([first, .., last]) + | ExprKind::Assign(first, last, _) + | ExprKind::AssignOp(_, first, last) => ( + expr_search_pat_inner(tcx, first, outer_span).0, + expr_search_pat_inner(tcx, last, outer_span).1, + ), + ExprKind::Tup([e]) | ExprKind::DropTemps(e) => expr_search_pat_inner(tcx, e, outer_span), + ExprKind::Cast(e, _) | ExprKind::Type(e, _) => (expr_search_pat_inner(tcx, e, outer_span).0, Pat::Str("")), + ExprKind::Let(let_expr) => (Pat::Str("let"), expr_search_pat_inner(tcx, let_expr.init, outer_span).1), + ExprKind::If(..) => (Pat::Str("if"), Pat::Str("}")), + ExprKind::Loop(_, Some(_), _, _) | ExprKind::Block(_, Some(_)) => (Pat::Str("'"), Pat::Str("}")), + ExprKind::Loop(_, None, LoopSource::Loop, _) => (Pat::Str("loop"), Pat::Str("}")), + ExprKind::Loop(_, None, LoopSource::While, _) => (Pat::Str("while"), Pat::Str("}")), + ExprKind::Loop(_, None, LoopSource::ForLoop, _) | ExprKind::Match(_, _, MatchSource::ForLoopDesugar) => { + (Pat::Str("for"), Pat::Str("}")) + }, + ExprKind::Match(_, _, MatchSource::Normal) => (Pat::Str("match"), Pat::Str("}")), + ExprKind::Match(e, _, MatchSource::TryDesugar(_)) => { + (expr_search_pat_inner(tcx, e, outer_span).0, Pat::Str("?")) + }, + ExprKind::Match(e, _, MatchSource::AwaitDesugar) | ExprKind::Yield(e, YieldSource::Await { .. }) => { + (expr_search_pat_inner(tcx, e, outer_span).0, Pat::Str("await")) + }, + ExprKind::Closure(&Closure { body, .. }) => ( + Pat::Str(""), + expr_search_pat_inner(tcx, tcx.hir().body(body).value, outer_span).1, + ), + ExprKind::Block( + Block { + rules: BlockCheckMode::UnsafeBlock(UnsafeSource::UserProvided), + .. + }, + None, + ) => (Pat::Str("unsafe"), Pat::Str("}")), + ExprKind::Block(_, None) => (Pat::Str("{"), Pat::Str("}")), + ExprKind::Field(e, name) => (expr_search_pat_inner(tcx, e, outer_span).0, Pat::Sym(name.name)), + ExprKind::Index(e, _, _) => (expr_search_pat_inner(tcx, e, outer_span).0, Pat::Str("]")), + ExprKind::Path(ref path) => qpath_search_pat(path), + ExprKind::AddrOf(_, _, e) => (Pat::Str("&"), expr_search_pat_inner(tcx, e, outer_span).1), + ExprKind::Break(Destination { label: None, .. }, None) => (Pat::Str("break"), Pat::Str("break")), + ExprKind::Break(Destination { label: Some(name), .. }, None) => { + (Pat::Str("break"), Pat::Sym(name.ident.name)) + }, + ExprKind::Break(_, Some(e)) => (Pat::Str("break"), expr_search_pat_inner(tcx, e, outer_span).1), + ExprKind::Continue(Destination { label: None, .. }) => (Pat::Str("continue"), Pat::Str("continue")), + ExprKind::Continue(Destination { label: Some(name), .. }) => { + (Pat::Str("continue"), Pat::Sym(name.ident.name)) + }, + ExprKind::Ret(None) => (Pat::Str("return"), Pat::Str("return")), + ExprKind::Ret(Some(e)) => (Pat::Str("return"), expr_search_pat_inner(tcx, e, outer_span).1), + ExprKind::Struct(path, _, _) => (qpath_search_pat(path).0, Pat::Str("}")), + ExprKind::Yield(e, YieldSource::Yield) => (Pat::Str("yield"), expr_search_pat_inner(tcx, e, outer_span).1), + _ => (Pat::Str(""), Pat::Str("")), + } } + + expr_search_pat_inner(tcx, e, e.span) } fn fn_header_search_pat(header: FnHeader) -> Pat { diff --git a/src/tools/clippy/tests/ui/dbg_macro/dbg_macro.fixed b/src/tools/clippy/tests/ui/dbg_macro/dbg_macro.fixed index e352519142332..bda9221a5e1e9 100644 --- a/src/tools/clippy/tests/ui/dbg_macro/dbg_macro.fixed +++ b/src/tools/clippy/tests/ui/dbg_macro/dbg_macro.fixed @@ -1,5 +1,5 @@ #![warn(clippy::dbg_macro)] -#![allow(clippy::unnecessary_operation, clippy::no_effect)] +#![allow(clippy::unnecessary_operation, clippy::no_effect, clippy::unit_arg)] fn foo(n: u32) -> u32 { if let Some(n) = n.checked_sub(4) { n } else { n } diff --git a/src/tools/clippy/tests/ui/dbg_macro/dbg_macro.rs b/src/tools/clippy/tests/ui/dbg_macro/dbg_macro.rs index 80606c2db054a..8244254026be7 100644 --- a/src/tools/clippy/tests/ui/dbg_macro/dbg_macro.rs +++ b/src/tools/clippy/tests/ui/dbg_macro/dbg_macro.rs @@ -1,5 +1,5 @@ #![warn(clippy::dbg_macro)] -#![allow(clippy::unnecessary_operation, clippy::no_effect)] +#![allow(clippy::unnecessary_operation, clippy::no_effect, clippy::unit_arg)] fn foo(n: u32) -> u32 { if let Some(n) = dbg!(n.checked_sub(4)) { n } else { n } diff --git a/src/tools/clippy/tests/ui/needless_return.fixed b/src/tools/clippy/tests/ui/needless_return.fixed index ca422e605d666..aa2a274525bce 100644 --- a/src/tools/clippy/tests/ui/needless_return.fixed +++ b/src/tools/clippy/tests/ui/needless_return.fixed @@ -1,3 +1,4 @@ +//@aux-build:proc_macros.rs #![feature(yeet_expr)] #![allow(unused)] #![allow( @@ -9,6 +10,9 @@ )] #![warn(clippy::needless_return)] +extern crate proc_macros; +use proc_macros::with_span; + use std::cell::RefCell; macro_rules! the_answer { @@ -359,6 +363,10 @@ fn issue12907() -> String { "".split("").next().unwrap().to_string() } +fn issue13458() { + with_span!(span return); +} + fn main() {} fn a(x: Option) -> Option { diff --git a/src/tools/clippy/tests/ui/needless_return.rs b/src/tools/clippy/tests/ui/needless_return.rs index aad6e13136f1a..bf67cfd3698a1 100644 --- a/src/tools/clippy/tests/ui/needless_return.rs +++ b/src/tools/clippy/tests/ui/needless_return.rs @@ -1,3 +1,4 @@ +//@aux-build:proc_macros.rs #![feature(yeet_expr)] #![allow(unused)] #![allow( @@ -9,6 +10,9 @@ )] #![warn(clippy::needless_return)] +extern crate proc_macros; +use proc_macros::with_span; + use std::cell::RefCell; macro_rules! the_answer { @@ -369,6 +373,10 @@ fn issue12907() -> String { return "".split("").next().unwrap().to_string(); } +fn issue13458() { + with_span!(span return); +} + fn main() {} fn a(x: Option) -> Option { diff --git a/src/tools/clippy/tests/ui/needless_return.stderr b/src/tools/clippy/tests/ui/needless_return.stderr index da0fa220d8c4a..d3c2a6badc0f4 100644 --- a/src/tools/clippy/tests/ui/needless_return.stderr +++ b/src/tools/clippy/tests/ui/needless_return.stderr @@ -1,5 +1,5 @@ error: unneeded `return` statement - --> tests/ui/needless_return.rs:25:5 + --> tests/ui/needless_return.rs:29:5 | LL | return true; | ^^^^^^^^^^^ @@ -13,7 +13,7 @@ LL + true | error: unneeded `return` statement - --> tests/ui/needless_return.rs:29:5 + --> tests/ui/needless_return.rs:33:5 | LL | return true; | ^^^^^^^^^^^ @@ -25,7 +25,7 @@ LL + true | error: unneeded `return` statement - --> tests/ui/needless_return.rs:34:5 + --> tests/ui/needless_return.rs:38:5 | LL | return true;;; | ^^^^^^^^^^^ @@ -37,7 +37,7 @@ LL + true | error: unneeded `return` statement - --> tests/ui/needless_return.rs:39:5 + --> tests/ui/needless_return.rs:43:5 | LL | return true;; ; ; | ^^^^^^^^^^^ @@ -49,7 +49,7 @@ LL + true | error: unneeded `return` statement - --> tests/ui/needless_return.rs:44:9 + --> tests/ui/needless_return.rs:48:9 | LL | return true; | ^^^^^^^^^^^ @@ -61,7 +61,7 @@ LL + true | error: unneeded `return` statement - --> tests/ui/needless_return.rs:46:9 + --> tests/ui/needless_return.rs:50:9 | LL | return false; | ^^^^^^^^^^^^ @@ -73,7 +73,7 @@ LL + false | error: unneeded `return` statement - --> tests/ui/needless_return.rs:52:17 + --> tests/ui/needless_return.rs:56:17 | LL | true => return false, | ^^^^^^^^^^^^ @@ -84,7 +84,7 @@ LL | true => false, | ~~~~~ error: unneeded `return` statement - --> tests/ui/needless_return.rs:54:13 + --> tests/ui/needless_return.rs:58:13 | LL | return true; | ^^^^^^^^^^^ @@ -96,7 +96,7 @@ LL + true | error: unneeded `return` statement - --> tests/ui/needless_return.rs:61:9 + --> tests/ui/needless_return.rs:65:9 | LL | return true; | ^^^^^^^^^^^ @@ -108,7 +108,7 @@ LL + true | error: unneeded `return` statement - --> tests/ui/needless_return.rs:63:16 + --> tests/ui/needless_return.rs:67:16 | LL | let _ = || return true; | ^^^^^^^^^^^ @@ -119,7 +119,7 @@ LL | let _ = || true; | ~~~~ error: unneeded `return` statement - --> tests/ui/needless_return.rs:67:5 + --> tests/ui/needless_return.rs:71:5 | LL | return the_answer!(); | ^^^^^^^^^^^^^^^^^^^^ @@ -131,7 +131,7 @@ LL + the_answer!() | error: unneeded `return` statement - --> tests/ui/needless_return.rs:70:21 + --> tests/ui/needless_return.rs:74:21 | LL | fn test_void_fun() { | _____________________^ @@ -146,7 +146,7 @@ LL + fn test_void_fun() { | error: unneeded `return` statement - --> tests/ui/needless_return.rs:75:11 + --> tests/ui/needless_return.rs:79:11 | LL | if b { | ___________^ @@ -161,7 +161,7 @@ LL + if b { | error: unneeded `return` statement - --> tests/ui/needless_return.rs:77:13 + --> tests/ui/needless_return.rs:81:13 | LL | } else { | _____________^ @@ -176,7 +176,7 @@ LL + } else { | error: unneeded `return` statement - --> tests/ui/needless_return.rs:85:14 + --> tests/ui/needless_return.rs:89:14 | LL | _ => return, | ^^^^^^ @@ -187,7 +187,7 @@ LL | _ => (), | ~~ error: unneeded `return` statement - --> tests/ui/needless_return.rs:93:24 + --> tests/ui/needless_return.rs:97:24 | LL | let _ = 42; | ________________________^ @@ -202,7 +202,7 @@ LL + let _ = 42; | error: unneeded `return` statement - --> tests/ui/needless_return.rs:96:14 + --> tests/ui/needless_return.rs:100:14 | LL | _ => return, | ^^^^^^ @@ -213,7 +213,7 @@ LL | _ => (), | ~~ error: unneeded `return` statement - --> tests/ui/needless_return.rs:109:9 + --> tests/ui/needless_return.rs:113:9 | LL | return String::from("test"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -225,7 +225,7 @@ LL + String::from("test") | error: unneeded `return` statement - --> tests/ui/needless_return.rs:111:9 + --> tests/ui/needless_return.rs:115:9 | LL | return String::new(); | ^^^^^^^^^^^^^^^^^^^^ @@ -237,7 +237,7 @@ LL + String::new() | error: unneeded `return` statement - --> tests/ui/needless_return.rs:133:32 + --> tests/ui/needless_return.rs:137:32 | LL | bar.unwrap_or_else(|_| return) | ^^^^^^ @@ -248,7 +248,7 @@ LL | bar.unwrap_or_else(|_| {}) | ~~ error: unneeded `return` statement - --> tests/ui/needless_return.rs:137:21 + --> tests/ui/needless_return.rs:141:21 | LL | let _ = || { | _____________________^ @@ -263,7 +263,7 @@ LL + let _ = || { | error: unneeded `return` statement - --> tests/ui/needless_return.rs:140:20 + --> tests/ui/needless_return.rs:144:20 | LL | let _ = || return; | ^^^^^^ @@ -274,7 +274,7 @@ LL | let _ = || {}; | ~~ error: unneeded `return` statement - --> tests/ui/needless_return.rs:146:32 + --> tests/ui/needless_return.rs:150:32 | LL | res.unwrap_or_else(|_| return Foo) | ^^^^^^^^^^ @@ -285,7 +285,7 @@ LL | res.unwrap_or_else(|_| Foo) | ~~~ error: unneeded `return` statement - --> tests/ui/needless_return.rs:155:5 + --> tests/ui/needless_return.rs:159:5 | LL | return true; | ^^^^^^^^^^^ @@ -297,7 +297,7 @@ LL + true | error: unneeded `return` statement - --> tests/ui/needless_return.rs:159:5 + --> tests/ui/needless_return.rs:163:5 | LL | return true; | ^^^^^^^^^^^ @@ -309,7 +309,7 @@ LL + true | error: unneeded `return` statement - --> tests/ui/needless_return.rs:164:9 + --> tests/ui/needless_return.rs:168:9 | LL | return true; | ^^^^^^^^^^^ @@ -321,7 +321,7 @@ LL + true | error: unneeded `return` statement - --> tests/ui/needless_return.rs:166:9 + --> tests/ui/needless_return.rs:170:9 | LL | return false; | ^^^^^^^^^^^^ @@ -333,7 +333,7 @@ LL + false | error: unneeded `return` statement - --> tests/ui/needless_return.rs:172:17 + --> tests/ui/needless_return.rs:176:17 | LL | true => return false, | ^^^^^^^^^^^^ @@ -344,7 +344,7 @@ LL | true => false, | ~~~~~ error: unneeded `return` statement - --> tests/ui/needless_return.rs:174:13 + --> tests/ui/needless_return.rs:178:13 | LL | return true; | ^^^^^^^^^^^ @@ -356,7 +356,7 @@ LL + true | error: unneeded `return` statement - --> tests/ui/needless_return.rs:181:9 + --> tests/ui/needless_return.rs:185:9 | LL | return true; | ^^^^^^^^^^^ @@ -368,7 +368,7 @@ LL + true | error: unneeded `return` statement - --> tests/ui/needless_return.rs:183:16 + --> tests/ui/needless_return.rs:187:16 | LL | let _ = || return true; | ^^^^^^^^^^^ @@ -379,7 +379,7 @@ LL | let _ = || true; | ~~~~ error: unneeded `return` statement - --> tests/ui/needless_return.rs:187:5 + --> tests/ui/needless_return.rs:191:5 | LL | return the_answer!(); | ^^^^^^^^^^^^^^^^^^^^ @@ -391,7 +391,7 @@ LL + the_answer!() | error: unneeded `return` statement - --> tests/ui/needless_return.rs:190:33 + --> tests/ui/needless_return.rs:194:33 | LL | async fn async_test_void_fun() { | _________________________________^ @@ -406,7 +406,7 @@ LL + async fn async_test_void_fun() { | error: unneeded `return` statement - --> tests/ui/needless_return.rs:195:11 + --> tests/ui/needless_return.rs:199:11 | LL | if b { | ___________^ @@ -421,7 +421,7 @@ LL + if b { | error: unneeded `return` statement - --> tests/ui/needless_return.rs:197:13 + --> tests/ui/needless_return.rs:201:13 | LL | } else { | _____________^ @@ -436,7 +436,7 @@ LL + } else { | error: unneeded `return` statement - --> tests/ui/needless_return.rs:205:14 + --> tests/ui/needless_return.rs:209:14 | LL | _ => return, | ^^^^^^ @@ -447,7 +447,7 @@ LL | _ => (), | ~~ error: unneeded `return` statement - --> tests/ui/needless_return.rs:218:9 + --> tests/ui/needless_return.rs:222:9 | LL | return String::from("test"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -459,7 +459,7 @@ LL + String::from("test") | error: unneeded `return` statement - --> tests/ui/needless_return.rs:220:9 + --> tests/ui/needless_return.rs:224:9 | LL | return String::new(); | ^^^^^^^^^^^^^^^^^^^^ @@ -471,7 +471,7 @@ LL + String::new() | error: unneeded `return` statement - --> tests/ui/needless_return.rs:236:5 + --> tests/ui/needless_return.rs:240:5 | LL | return format!("Hello {}", "world!"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -483,7 +483,7 @@ LL + format!("Hello {}", "world!") | error: unneeded `return` statement - --> tests/ui/needless_return.rs:277:9 + --> tests/ui/needless_return.rs:281:9 | LL | return true; | ^^^^^^^^^^^ @@ -497,7 +497,7 @@ LL ~ } | error: unneeded `return` statement - --> tests/ui/needless_return.rs:279:9 + --> tests/ui/needless_return.rs:283:9 | LL | return false; | ^^^^^^^^^^^^ @@ -509,7 +509,7 @@ LL ~ } | error: unneeded `return` statement - --> tests/ui/needless_return.rs:286:13 + --> tests/ui/needless_return.rs:290:13 | LL | return 10; | ^^^^^^^^^ @@ -524,7 +524,7 @@ LL ~ } | error: unneeded `return` statement - --> tests/ui/needless_return.rs:289:13 + --> tests/ui/needless_return.rs:293:13 | LL | return 100; | ^^^^^^^^^^ @@ -537,7 +537,7 @@ LL ~ } | error: unneeded `return` statement - --> tests/ui/needless_return.rs:297:9 + --> tests/ui/needless_return.rs:301:9 | LL | return 0; | ^^^^^^^^ @@ -549,7 +549,7 @@ LL ~ } | error: unneeded `return` statement - --> tests/ui/needless_return.rs:304:13 + --> tests/ui/needless_return.rs:308:13 | LL | return *(x as *const isize); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -564,7 +564,7 @@ LL ~ } | error: unneeded `return` statement - --> tests/ui/needless_return.rs:306:13 + --> tests/ui/needless_return.rs:310:13 | LL | return !*(x as *const isize); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -577,7 +577,7 @@ LL ~ } | error: unneeded `return` statement - --> tests/ui/needless_return.rs:313:20 + --> tests/ui/needless_return.rs:317:20 | LL | let _ = 42; | ____________________^ @@ -594,7 +594,7 @@ LL + let _ = 42; | error: unneeded `return` statement - --> tests/ui/needless_return.rs:320:20 + --> tests/ui/needless_return.rs:324:20 | LL | let _ = 42; return; | ^^^^^^^ @@ -606,7 +606,7 @@ LL + let _ = 42; | error: unneeded `return` statement - --> tests/ui/needless_return.rs:332:9 + --> tests/ui/needless_return.rs:336:9 | LL | return Ok(format!("ok!")); | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -618,7 +618,7 @@ LL + Ok(format!("ok!")) | error: unneeded `return` statement - --> tests/ui/needless_return.rs:334:9 + --> tests/ui/needless_return.rs:338:9 | LL | return Err(format!("err!")); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -630,7 +630,7 @@ LL + Err(format!("err!")) | error: unneeded `return` statement - --> tests/ui/needless_return.rs:340:9 + --> tests/ui/needless_return.rs:344:9 | LL | return if true { 1 } else { 2 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -642,7 +642,7 @@ LL + if true { 1 } else { 2 } | error: unneeded `return` statement - --> tests/ui/needless_return.rs:344:9 + --> tests/ui/needless_return.rs:348:9 | LL | return if b1 { 0 } else { 1 } | if b2 { 2 } else { 3 } | if b3 { 4 } else { 5 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -654,7 +654,7 @@ LL + (if b1 { 0 } else { 1 } | if b2 { 2 } else { 3 } | if b3 { 4 } else | error: unneeded `return` statement - --> tests/ui/needless_return.rs:365:5 + --> tests/ui/needless_return.rs:369:5 | LL | return { "a".to_string() } + "b" + { "c" }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -666,7 +666,7 @@ LL + ({ "a".to_string() } + "b" + { "c" }) | error: unneeded `return` statement - --> tests/ui/needless_return.rs:369:5 + --> tests/ui/needless_return.rs:373:5 | LL | return "".split("").next().unwrap().to_string(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ From b12dc2091012d1e8074ccea0ffe6ac16de1ba802 Mon Sep 17 00:00:00 2001 From: Manuel Drehwald Date: Thu, 10 Oct 2024 11:38:28 +0200 Subject: [PATCH 2084/2194] add config to explicitely test rustc with autodiff/enzyme disabled --- src/tools/compiletest/src/command-list.rs | 1 + src/tools/compiletest/src/header/cfg.rs | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/src/tools/compiletest/src/command-list.rs b/src/tools/compiletest/src/command-list.rs index 53db55d0c10ff..ab57320b4d910 100644 --- a/src/tools/compiletest/src/command-list.rs +++ b/src/tools/compiletest/src/command-list.rs @@ -49,6 +49,7 @@ const KNOWN_DIRECTIVE_NAMES: &[&str] = &[ "ignore-eabi", "ignore-emscripten", "ignore-endian-big", + "ignore-enzyme", "ignore-freebsd", "ignore-fuchsia", "ignore-gdb", diff --git a/src/tools/compiletest/src/header/cfg.rs b/src/tools/compiletest/src/header/cfg.rs index 6e351aa27b909..b9314f0abbbc8 100644 --- a/src/tools/compiletest/src/header/cfg.rs +++ b/src/tools/compiletest/src/header/cfg.rs @@ -166,6 +166,12 @@ pub(super) fn parse_cfg_name_directive<'a>( message: "when the target vendor is Apple" } + condition! { + name: "enzyme", + condition: config.has_enzyme, + message: "when rustc is built with LLVM Enzyme" + } + // Technically the locally built compiler uses the "dev" channel rather than the "nightly" // channel, even though most people don't know or won't care about it. To avoid confusion, we // treat the "dev" channel as the "nightly" channel when processing the directive. From 1edff466e19c4e2e2f8035de5a25d8a2dc2fef96 Mon Sep 17 00:00:00 2001 From: Mads Marquart Date: Thu, 10 Oct 2024 11:46:11 +0200 Subject: [PATCH 2085/2194] Avoid redundant additions to PATH when linking --- compiler/rustc_session/src/session.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index d67e69fe0fb72..27879d817b208 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -454,6 +454,8 @@ impl Session { let bin_path = filesearch::make_target_bin_path(&self.sysroot, config::host_triple()); let fallback_sysroot_paths = filesearch::sysroot_candidates() .into_iter() + // Ignore sysroot candidate if it was the same as the sysroot path we just used. + .filter(|sysroot| *sysroot != self.sysroot) .map(|sysroot| filesearch::make_target_bin_path(&sysroot, config::host_triple())); let search_paths = std::iter::once(bin_path).chain(fallback_sysroot_paths); From 09da2ebd63107997e1319c2a076021660285ef40 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Fri, 4 Oct 2024 11:56:45 -0400 Subject: [PATCH 2086/2194] Move ty::Error branch into super_combine_tys --- .../rustc_infer/src/infer/relate/combine.rs | 5 ++++ .../src/infer/relate/type_relating.rs | 5 ---- ...invalid-type-bound-suggest-issue-127555.rs | 1 - ...lid-type-bound-suggest-issue-127555.stderr | 16 ++--------- ...-predicate-entailment-error.current.stderr | 28 +------------------ ...lse-positive-predicate-entailment-error.rs | 3 +- .../in-trait/return-dont-satisfy-bounds.rs | 1 - .../return-dont-satisfy-bounds.stderr | 14 ++-------- .../rpitit-captures-more-method-lifetimes.rs | 1 - ...itit-captures-more-method-lifetimes.stderr | 19 +------------ 10 files changed, 12 insertions(+), 81 deletions(-) diff --git a/compiler/rustc_infer/src/infer/relate/combine.rs b/compiler/rustc_infer/src/infer/relate/combine.rs index c4f5a85a8bee7..f879fbc5578cb 100644 --- a/compiler/rustc_infer/src/infer/relate/combine.rs +++ b/compiler/rustc_infer/src/infer/relate/combine.rs @@ -43,6 +43,11 @@ impl<'tcx> InferCtxt<'tcx> { debug_assert!(!b.has_escaping_bound_vars()); match (a.kind(), b.kind()) { + (&ty::Error(e), _) | (_, &ty::Error(e)) => { + self.set_tainted_by_errors(e); + return Ok(Ty::new_error(self.tcx, e)); + } + // Relate integral variables to other types (&ty::Infer(ty::IntVar(a_id)), &ty::Infer(ty::IntVar(b_id))) => { self.inner.borrow_mut().int_unification_table().union(a_id, b_id); diff --git a/compiler/rustc_infer/src/infer/relate/type_relating.rs b/compiler/rustc_infer/src/infer/relate/type_relating.rs index 4b4b13e919cea..d99acabb82587 100644 --- a/compiler/rustc_infer/src/infer/relate/type_relating.rs +++ b/compiler/rustc_infer/src/infer/relate/type_relating.rs @@ -183,11 +183,6 @@ impl<'tcx> TypeRelation> for TypeRelating<'_, 'tcx> { )?; } - (&ty::Error(e), _) | (_, &ty::Error(e)) => { - infcx.set_tainted_by_errors(e); - return Ok(Ty::new_error(self.cx(), e)); - } - ( &ty::Alias(ty::Opaque, ty::AliasTy { def_id: a_def_id, .. }), &ty::Alias(ty::Opaque, ty::AliasTy { def_id: b_def_id, .. }), diff --git a/tests/ui/associated-types/remove-invalid-type-bound-suggest-issue-127555.rs b/tests/ui/associated-types/remove-invalid-type-bound-suggest-issue-127555.rs index 6083cc7d96dca..b4df58b3c25a8 100644 --- a/tests/ui/associated-types/remove-invalid-type-bound-suggest-issue-127555.rs +++ b/tests/ui/associated-types/remove-invalid-type-bound-suggest-issue-127555.rs @@ -14,7 +14,6 @@ impl Foo for Baz { //~^ ERROR `F` cannot be sent between threads safely where F: FnMut() + Send, - //~^ ERROR impl has stricter requirements than trait { () } diff --git a/tests/ui/associated-types/remove-invalid-type-bound-suggest-issue-127555.stderr b/tests/ui/associated-types/remove-invalid-type-bound-suggest-issue-127555.stderr index 7f3cd2a590053..e6379954776df 100644 --- a/tests/ui/associated-types/remove-invalid-type-bound-suggest-issue-127555.stderr +++ b/tests/ui/associated-types/remove-invalid-type-bound-suggest-issue-127555.stderr @@ -16,18 +16,6 @@ LL | async fn bar(&mut self, _func: F) -> () LL | F: FnMut() + Send, | ^^^^ required by this bound in `::bar` -error[E0276]: impl has stricter requirements than trait - --> $DIR/remove-invalid-type-bound-suggest-issue-127555.rs:16:22 - | -LL | / fn bar(&mut self, func: F) -> impl std::future::Future + Send -LL | | where -LL | | F: FnMut(); - | |___________________- definition of `bar` from trait -... -LL | F: FnMut() + Send, - | ^^^^ impl has extra requirement `F: Send` - -error: aborting due to 2 previous errors +error: aborting due to 1 previous error -Some errors have detailed explanations: E0276, E0277. -For more information about an error, try `rustc --explain E0276`. +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/impl-trait/in-trait/false-positive-predicate-entailment-error.current.stderr b/tests/ui/impl-trait/in-trait/false-positive-predicate-entailment-error.current.stderr index d71c1768a6a3b..058517f0014e9 100644 --- a/tests/ui/impl-trait/in-trait/false-positive-predicate-entailment-error.current.stderr +++ b/tests/ui/impl-trait/in-trait/false-positive-predicate-entailment-error.current.stderr @@ -73,32 +73,6 @@ help: consider further restricting this bound LL | F: Callback + MyFn, | +++++++++++ -error[E0277]: the trait bound `F: Callback` is not satisfied - --> $DIR/false-positive-predicate-entailment-error.rs:43:12 - | -LL | F: Callback, - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `MyFn` is not implemented for `F`, which is required by `F: Callback` - | -note: required for `F` to implement `Callback` - --> $DIR/false-positive-predicate-entailment-error.rs:14:21 - | -LL | impl> Callback for F { - | ------- ^^^^^^^^^^^ ^ - | | - | unsatisfied trait bound introduced here -note: the requirement `F: Callback` appears on the `impl`'s method `autobatch` but not on the corresponding trait's method - --> $DIR/false-positive-predicate-entailment-error.rs:25:8 - | -LL | trait ChannelSender { - | ------------- in this trait -... -LL | fn autobatch(self) -> impl Trait - | ^^^^^^^^^ this trait's method doesn't have the requirement `F: Callback` -help: consider further restricting this bound - | -LL | F: Callback + MyFn, - | +++++++++++ - error[E0277]: the trait bound `F: MyFn` is not satisfied --> $DIR/false-positive-predicate-entailment-error.rs:36:30 | @@ -168,6 +142,6 @@ help: consider further restricting this bound LL | F: Callback + MyFn, | +++++++++++ -error: aborting due to 8 previous errors +error: aborting due to 7 previous errors For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/impl-trait/in-trait/false-positive-predicate-entailment-error.rs b/tests/ui/impl-trait/in-trait/false-positive-predicate-entailment-error.rs index 59fdeab9e0a9f..2987d183e0401 100644 --- a/tests/ui/impl-trait/in-trait/false-positive-predicate-entailment-error.rs +++ b/tests/ui/impl-trait/in-trait/false-positive-predicate-entailment-error.rs @@ -41,8 +41,7 @@ impl ChannelSender for Sender { //[current]~| ERROR the trait bound `F: MyFn` is not satisfied where F: Callback, - //[current]~^ ERROR the trait bound `F: Callback` is not satisfied - //[current]~| ERROR the trait bound `F: MyFn` is not satisfied + //[current]~^ ERROR the trait bound `F: MyFn` is not satisfied { Thing } diff --git a/tests/ui/impl-trait/in-trait/return-dont-satisfy-bounds.rs b/tests/ui/impl-trait/in-trait/return-dont-satisfy-bounds.rs index 84bc39d926307..ee47de2c73283 100644 --- a/tests/ui/impl-trait/in-trait/return-dont-satisfy-bounds.rs +++ b/tests/ui/impl-trait/in-trait/return-dont-satisfy-bounds.rs @@ -8,7 +8,6 @@ impl Foo for Bar { fn foo>(self) -> impl Foo { //~^ ERROR: the trait bound `impl Foo: Foo` is not satisfied [E0277] //~| ERROR: the trait bound `Bar: Foo` is not satisfied [E0277] - //~| ERROR: impl has stricter requirements than trait //~| ERROR: the trait bound `F2: Foo` is not satisfied self } diff --git a/tests/ui/impl-trait/in-trait/return-dont-satisfy-bounds.stderr b/tests/ui/impl-trait/in-trait/return-dont-satisfy-bounds.stderr index ae4490999878f..768224e4c515c 100644 --- a/tests/ui/impl-trait/in-trait/return-dont-satisfy-bounds.stderr +++ b/tests/ui/impl-trait/in-trait/return-dont-satisfy-bounds.stderr @@ -23,15 +23,6 @@ note: required by a bound in `>::foo` LL | fn foo>(self) -> impl Foo { | ^^^^^^^ required by this bound in `>::foo` -error[E0276]: impl has stricter requirements than trait - --> $DIR/return-dont-satisfy-bounds.rs:8:16 - | -LL | fn foo(self) -> impl Foo; - | -------------------------------- definition of `foo` from trait -... -LL | fn foo>(self) -> impl Foo { - | ^^^^^^^ impl has extra requirement `F2: Foo` - error[E0277]: the trait bound `Bar: Foo` is not satisfied --> $DIR/return-dont-satisfy-bounds.rs:8:34 | @@ -44,7 +35,6 @@ LL | self = help: the trait `Foo` is implemented for `Bar` = help: for that trait implementation, expected `char`, found `u8` -error: aborting due to 4 previous errors +error: aborting due to 3 previous errors -Some errors have detailed explanations: E0276, E0277. -For more information about an error, try `rustc --explain E0276`. +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/impl-trait/precise-capturing/rpitit-captures-more-method-lifetimes.rs b/tests/ui/impl-trait/precise-capturing/rpitit-captures-more-method-lifetimes.rs index 71a91fe319e8d..062351afecbdf 100644 --- a/tests/ui/impl-trait/precise-capturing/rpitit-captures-more-method-lifetimes.rs +++ b/tests/ui/impl-trait/precise-capturing/rpitit-captures-more-method-lifetimes.rs @@ -10,7 +10,6 @@ pub trait Foo { impl Foo for () { fn bar<'im: 'im>(&'im mut self) -> impl Sized + 'im {} //~^ ERROR return type captures more lifetimes than trait definition - //~| WARN impl trait in impl method signature does not match trait method signature } fn main() {} diff --git a/tests/ui/impl-trait/precise-capturing/rpitit-captures-more-method-lifetimes.stderr b/tests/ui/impl-trait/precise-capturing/rpitit-captures-more-method-lifetimes.stderr index 339e2e6335e2d..b390a23eef414 100644 --- a/tests/ui/impl-trait/precise-capturing/rpitit-captures-more-method-lifetimes.stderr +++ b/tests/ui/impl-trait/precise-capturing/rpitit-captures-more-method-lifetimes.stderr @@ -21,22 +21,5 @@ LL | fn bar<'tr: 'tr>(&'tr mut self) -> impl Sized + use; | ^^^^^^^^^^^^^^^^^^^^^^ = note: hidden type inferred to be `impl Sized + 'im` -warning: impl trait in impl method signature does not match trait method signature - --> $DIR/rpitit-captures-more-method-lifetimes.rs:11:40 - | -LL | fn bar<'tr: 'tr>(&'tr mut self) -> impl Sized + use; - | ---------------------- return type from trait method defined here -... -LL | fn bar<'im: 'im>(&'im mut self) -> impl Sized + 'im {} - | ^^^^^^^^^^^^^^^^ - | - = note: add `#[allow(refining_impl_trait)]` if it is intended for this to be part of the public API of this crate - = note: we are soliciting feedback, see issue #121718 for more information - = note: `#[warn(refining_impl_trait_reachable)]` on by default -help: replace the return type so that it matches the trait - | -LL | fn bar<'im: 'im>(&'im mut self) -> impl Sized {} - | ~~~~~~~~~~ - -error: aborting due to 2 previous errors; 1 warning emitted +error: aborting due to 2 previous errors From ce7a61b9d0bb4b7bb99ade4bff2449fabc9afd3f Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Fri, 4 Oct 2024 12:33:51 -0400 Subject: [PATCH 2087/2194] Uplift super_combine --- .../src/type_check/relate_tys.rs | 1 + compiler/rustc_infer/src/infer/context.rs | 69 ++++- .../rustc_infer/src/infer/relate/combine.rs | 245 ----------------- .../src/infer/relate/generalize.rs | 2 +- .../rustc_infer/src/infer/relate/lattice.rs | 1 + compiler/rustc_infer/src/infer/relate/mod.rs | 6 +- .../src/infer/relate/type_relating.rs | 1 + compiler/rustc_next_trait_solver/src/lib.rs | 1 - .../rustc_next_trait_solver/src/relate.rs | 15 -- .../src/relate/combine.rs | 34 --- compiler/rustc_type_ir/src/infer_ctxt.rs | 37 ++- compiler/rustc_type_ir/src/relate.rs | 14 + compiler/rustc_type_ir/src/relate/combine.rs | 255 ++++++++++++++++++ 13 files changed, 376 insertions(+), 305 deletions(-) delete mode 100644 compiler/rustc_infer/src/infer/relate/combine.rs delete mode 100644 compiler/rustc_next_trait_solver/src/relate.rs delete mode 100644 compiler/rustc_next_trait_solver/src/relate/combine.rs create mode 100644 compiler/rustc_type_ir/src/relate/combine.rs diff --git a/compiler/rustc_borrowck/src/type_check/relate_tys.rs b/compiler/rustc_borrowck/src/type_check/relate_tys.rs index bf079e813f16b..e72c21e8fadf4 100644 --- a/compiler/rustc_borrowck/src/type_check/relate_tys.rs +++ b/compiler/rustc_borrowck/src/type_check/relate_tys.rs @@ -11,6 +11,7 @@ use rustc_middle::span_bug; use rustc_middle::traits::ObligationCause; use rustc_middle::traits::query::NoSolution; use rustc_middle::ty::fold::FnMutDelegate; +use rustc_middle::ty::relate::combine::InferCtxtCombineExt; use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt}; use rustc_span::symbol::sym; use rustc_span::{Span, Symbol}; diff --git a/compiler/rustc_infer/src/infer/context.rs b/compiler/rustc_infer/src/infer/context.rs index c06836edcfb55..10b22c98a0d21 100644 --- a/compiler/rustc_infer/src/infer/context.rs +++ b/compiler/rustc_infer/src/infer/context.rs @@ -1,22 +1,27 @@ ///! Definition of `InferCtxtLike` from the librarified type layer. use rustc_hir::def_id::{DefId, LocalDefId}; +use rustc_middle::infer::unify_key::EffectVarValue; use rustc_middle::traits::ObligationCause; use rustc_middle::traits::solve::{Goal, NoSolution, SolverMode}; use rustc_middle::ty::fold::TypeFoldable; +use rustc_middle::ty::relate::combine::PredicateEmittingRelation; +use rustc_middle::ty::relate::{Relate, RelateResult}; use rustc_middle::ty::{self, Ty, TyCtxt}; -use rustc_span::DUMMY_SP; -use rustc_type_ir::InferCtxtLike; -use rustc_type_ir::relate::Relate; +use rustc_span::{DUMMY_SP, ErrorGuaranteed}; use super::{BoundRegionConversionTime, InferCtxt, SubregionOrigin}; -impl<'tcx> InferCtxtLike for InferCtxt<'tcx> { +impl<'tcx> rustc_type_ir::InferCtxtLike for InferCtxt<'tcx> { type Interner = TyCtxt<'tcx>; fn cx(&self) -> TyCtxt<'tcx> { self.tcx } + fn next_trait_solver(&self) -> bool { + self.next_trait_solver + } + fn solver_mode(&self) -> ty::solve::SolverMode { match self.intercrate { true => SolverMode::Coherence, @@ -131,6 +136,59 @@ impl<'tcx> InferCtxtLike for InferCtxt<'tcx> { self.enter_forall(value, f) } + fn equate_int_vids_raw(&self, a: rustc_type_ir::IntVid, b: rustc_type_ir::IntVid) { + self.inner.borrow_mut().int_unification_table().union(a, b); + } + + fn equate_float_vids_raw(&self, a: rustc_type_ir::FloatVid, b: rustc_type_ir::FloatVid) { + self.inner.borrow_mut().float_unification_table().union(a, b); + } + + fn equate_const_vids_raw(&self, a: rustc_type_ir::ConstVid, b: rustc_type_ir::ConstVid) { + self.inner.borrow_mut().const_unification_table().union(a, b); + } + + fn equate_effect_vids_raw(&self, a: rustc_type_ir::EffectVid, b: rustc_type_ir::EffectVid) { + self.inner.borrow_mut().effect_unification_table().union(a, b); + } + + fn instantiate_int_var_raw( + &self, + vid: rustc_type_ir::IntVid, + value: rustc_type_ir::IntVarValue, + ) { + self.inner.borrow_mut().int_unification_table().union_value(vid, value); + } + + fn instantiate_float_var_raw( + &self, + vid: rustc_type_ir::FloatVid, + value: rustc_type_ir::FloatVarValue, + ) { + self.inner.borrow_mut().float_unification_table().union_value(vid, value); + } + + fn instantiate_effect_var_raw(&self, vid: rustc_type_ir::EffectVid, value: ty::Const<'tcx>) { + self.inner + .borrow_mut() + .effect_unification_table() + .union_value(vid, EffectVarValue::Known(value)); + } + + fn instantiate_const_var_raw>( + &self, + relation: &mut R, + target_is_expected: bool, + target_vid: rustc_type_ir::ConstVid, + source_ct: ty::Const<'tcx>, + ) -> RelateResult<'tcx, ()> { + self.instantiate_const_var(relation, target_is_expected, target_vid, source_ct) + } + + fn set_tainted_by_errors(&self, e: ErrorGuaranteed) { + self.set_tainted_by_errors(e) + } + fn relate>>( &self, param_env: ty::ParamEnv<'tcx>, @@ -154,6 +212,9 @@ impl<'tcx> InferCtxtLike for InferCtxt<'tcx> { fn shallow_resolve(&self, ty: Ty<'tcx>) -> Ty<'tcx> { self.shallow_resolve(ty) } + fn shallow_resolve_const(&self, ct: ty::Const<'tcx>) -> ty::Const<'tcx> { + self.shallow_resolve_const(ct) + } fn resolve_vars_if_possible(&self, value: T) -> T where diff --git a/compiler/rustc_infer/src/infer/relate/combine.rs b/compiler/rustc_infer/src/infer/relate/combine.rs deleted file mode 100644 index f879fbc5578cb..0000000000000 --- a/compiler/rustc_infer/src/infer/relate/combine.rs +++ /dev/null @@ -1,245 +0,0 @@ -//! There are four type combiners: `TypeRelating`, `Lub`, and `Glb`, -//! and `NllTypeRelating` in rustc_borrowck, which is only used for NLL. -//! -//! Each implements the trait [TypeRelation] and contains methods for -//! combining two instances of various things and yielding a new instance. -//! These combiner methods always yield a `Result`. To relate two -//! types, you can use `infcx.at(cause, param_env)` which then allows -//! you to use the relevant methods of [At](crate::infer::at::At). -//! -//! Combiners mostly do their specific behavior and then hand off the -//! bulk of the work to [InferCtxt::super_combine_tys] and -//! [InferCtxt::super_combine_consts]. -//! -//! Combining two types may have side-effects on the inference contexts -//! which can be undone by using snapshots. You probably want to use -//! either [InferCtxt::commit_if_ok] or [InferCtxt::probe]. -//! -//! On success, the LUB/GLB operations return the appropriate bound. The -//! return value of `Equate` or `Sub` shouldn't really be used. - -use rustc_middle::bug; -use rustc_middle::infer::unify_key::EffectVarValue; -use rustc_middle::ty::error::{ExpectedFound, TypeError}; -use rustc_middle::ty::{self, InferConst, IntType, Ty, TypeVisitableExt, UintType}; -pub use rustc_next_trait_solver::relate::combine::*; -use tracing::debug; - -use super::{RelateResult, StructurallyRelateAliases}; -use crate::infer::{InferCtxt, relate}; - -impl<'tcx> InferCtxt<'tcx> { - pub fn super_combine_tys( - &self, - relation: &mut R, - a: Ty<'tcx>, - b: Ty<'tcx>, - ) -> RelateResult<'tcx, Ty<'tcx>> - where - R: PredicateEmittingRelation>, - { - debug!("super_combine_tys::<{}>({:?}, {:?})", std::any::type_name::(), a, b); - debug_assert!(!a.has_escaping_bound_vars()); - debug_assert!(!b.has_escaping_bound_vars()); - - match (a.kind(), b.kind()) { - (&ty::Error(e), _) | (_, &ty::Error(e)) => { - self.set_tainted_by_errors(e); - return Ok(Ty::new_error(self.tcx, e)); - } - - // Relate integral variables to other types - (&ty::Infer(ty::IntVar(a_id)), &ty::Infer(ty::IntVar(b_id))) => { - self.inner.borrow_mut().int_unification_table().union(a_id, b_id); - Ok(a) - } - (&ty::Infer(ty::IntVar(v_id)), &ty::Int(v)) => { - self.unify_integral_variable(v_id, IntType(v)); - Ok(b) - } - (&ty::Int(v), &ty::Infer(ty::IntVar(v_id))) => { - self.unify_integral_variable(v_id, IntType(v)); - Ok(a) - } - (&ty::Infer(ty::IntVar(v_id)), &ty::Uint(v)) => { - self.unify_integral_variable(v_id, UintType(v)); - Ok(b) - } - (&ty::Uint(v), &ty::Infer(ty::IntVar(v_id))) => { - self.unify_integral_variable(v_id, UintType(v)); - Ok(a) - } - - // Relate floating-point variables to other types - (&ty::Infer(ty::FloatVar(a_id)), &ty::Infer(ty::FloatVar(b_id))) => { - self.inner.borrow_mut().float_unification_table().union(a_id, b_id); - Ok(a) - } - (&ty::Infer(ty::FloatVar(v_id)), &ty::Float(v)) => { - self.unify_float_variable(v_id, ty::FloatVarValue::Known(v)); - Ok(b) - } - (&ty::Float(v), &ty::Infer(ty::FloatVar(v_id))) => { - self.unify_float_variable(v_id, ty::FloatVarValue::Known(v)); - Ok(a) - } - - // We don't expect `TyVar` or `Fresh*` vars at this point with lazy norm. - (ty::Alias(..), ty::Infer(ty::TyVar(_))) | (ty::Infer(ty::TyVar(_)), ty::Alias(..)) - if self.next_trait_solver() => - { - bug!( - "We do not expect to encounter `TyVar` this late in combine \ - -- they should have been handled earlier" - ) - } - (_, ty::Infer(ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_))) - | (ty::Infer(ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)), _) - if self.next_trait_solver() => - { - bug!("We do not expect to encounter `Fresh` variables in the new solver") - } - - (_, ty::Alias(..)) | (ty::Alias(..), _) if self.next_trait_solver() => { - match relation.structurally_relate_aliases() { - StructurallyRelateAliases::Yes => { - relate::structurally_relate_tys(relation, a, b) - } - StructurallyRelateAliases::No => { - relation.register_alias_relate_predicate(a, b); - Ok(a) - } - } - } - - // All other cases of inference are errors - (&ty::Infer(_), _) | (_, &ty::Infer(_)) => { - Err(TypeError::Sorts(ExpectedFound::new(true, a, b))) - } - - // During coherence, opaque types should be treated as *possibly* - // equal to any other type (except for possibly itself). This is an - // extremely heavy hammer, but can be relaxed in a forwards-compatible - // way later. - (&ty::Alias(ty::Opaque, _), _) | (_, &ty::Alias(ty::Opaque, _)) if self.intercrate => { - relation.register_predicates([ty::Binder::dummy(ty::PredicateKind::Ambiguous)]); - Ok(a) - } - - _ => relate::structurally_relate_tys(relation, a, b), - } - } - - pub fn super_combine_consts( - &self, - relation: &mut R, - a: ty::Const<'tcx>, - b: ty::Const<'tcx>, - ) -> RelateResult<'tcx, ty::Const<'tcx>> - where - R: PredicateEmittingRelation>, - { - debug!("super_combine_consts::<{}>({:?}, {:?})", std::any::type_name::(), a, b); - debug_assert!(!a.has_escaping_bound_vars()); - debug_assert!(!b.has_escaping_bound_vars()); - - if a == b { - return Ok(a); - } - - let a = self.shallow_resolve_const(a); - let b = self.shallow_resolve_const(b); - - match (a.kind(), b.kind()) { - ( - ty::ConstKind::Infer(InferConst::Var(a_vid)), - ty::ConstKind::Infer(InferConst::Var(b_vid)), - ) => { - self.inner.borrow_mut().const_unification_table().union(a_vid, b_vid); - Ok(a) - } - - ( - ty::ConstKind::Infer(InferConst::EffectVar(a_vid)), - ty::ConstKind::Infer(InferConst::EffectVar(b_vid)), - ) => { - self.inner.borrow_mut().effect_unification_table().union(a_vid, b_vid); - Ok(a) - } - - // All other cases of inference with other variables are errors. - ( - ty::ConstKind::Infer(InferConst::Var(_) | InferConst::EffectVar(_)), - ty::ConstKind::Infer(_), - ) - | ( - ty::ConstKind::Infer(_), - ty::ConstKind::Infer(InferConst::Var(_) | InferConst::EffectVar(_)), - ) => { - bug!( - "tried to combine ConstKind::Infer/ConstKind::Infer(InferConst::Var): {a:?} and {b:?}" - ) - } - - (ty::ConstKind::Infer(InferConst::Var(vid)), _) => { - self.instantiate_const_var(relation, true, vid, b)?; - Ok(b) - } - - (_, ty::ConstKind::Infer(InferConst::Var(vid))) => { - self.instantiate_const_var(relation, false, vid, a)?; - Ok(a) - } - - (ty::ConstKind::Infer(InferConst::EffectVar(vid)), _) => { - Ok(self.unify_effect_variable(vid, b)) - } - - (_, ty::ConstKind::Infer(InferConst::EffectVar(vid))) => { - Ok(self.unify_effect_variable(vid, a)) - } - - (ty::ConstKind::Unevaluated(..), _) | (_, ty::ConstKind::Unevaluated(..)) - if self.tcx.features().generic_const_exprs || self.next_trait_solver() => - { - match relation.structurally_relate_aliases() { - StructurallyRelateAliases::No => { - relation.register_predicates([if self.next_trait_solver() { - ty::PredicateKind::AliasRelate( - a.into(), - b.into(), - ty::AliasRelationDirection::Equate, - ) - } else { - ty::PredicateKind::ConstEquate(a, b) - }]); - - Ok(b) - } - StructurallyRelateAliases::Yes => { - relate::structurally_relate_consts(relation, a, b) - } - } - } - _ => relate::structurally_relate_consts(relation, a, b), - } - } - - #[inline(always)] - fn unify_integral_variable(&self, vid: ty::IntVid, val: ty::IntVarValue) { - self.inner.borrow_mut().int_unification_table().union_value(vid, val); - } - - #[inline(always)] - fn unify_float_variable(&self, vid: ty::FloatVid, val: ty::FloatVarValue) { - self.inner.borrow_mut().float_unification_table().union_value(vid, val); - } - - fn unify_effect_variable(&self, vid: ty::EffectVid, val: ty::Const<'tcx>) -> ty::Const<'tcx> { - self.inner - .borrow_mut() - .effect_unification_table() - .union_value(vid, EffectVarValue::Known(val)); - val - } -} diff --git a/compiler/rustc_infer/src/infer/relate/generalize.rs b/compiler/rustc_infer/src/infer/relate/generalize.rs index 726a2296d11a3..7049444db9b5f 100644 --- a/compiler/rustc_infer/src/infer/relate/generalize.rs +++ b/compiler/rustc_infer/src/infer/relate/generalize.rs @@ -183,7 +183,7 @@ impl<'tcx> InferCtxt<'tcx> { /// /// See `tests/ui/const-generics/occurs-check/` for more examples where this is relevant. #[instrument(level = "debug", skip(self, relation))] - pub(super) fn instantiate_const_var>>( + pub(crate) fn instantiate_const_var>>( &self, relation: &mut R, target_is_expected: bool, diff --git a/compiler/rustc_infer/src/infer/relate/lattice.rs b/compiler/rustc_infer/src/infer/relate/lattice.rs index 8cec312abf75b..fc208a084718e 100644 --- a/compiler/rustc_infer/src/infer/relate/lattice.rs +++ b/compiler/rustc_infer/src/infer/relate/lattice.rs @@ -18,6 +18,7 @@ //! [lattices]: https://en.wikipedia.org/wiki/Lattice_(order) use rustc_middle::traits::solve::Goal; +use rustc_middle::ty::relate::combine::InferCtxtCombineExt; use rustc_middle::ty::relate::{Relate, RelateResult, TypeRelation}; use rustc_middle::ty::{self, Ty, TyCtxt, TyVar, TypeVisitableExt}; use rustc_span::Span; diff --git a/compiler/rustc_infer/src/infer/relate/mod.rs b/compiler/rustc_infer/src/infer/relate/mod.rs index baab5bb274a09..e156f72d78d07 100644 --- a/compiler/rustc_infer/src/infer/relate/mod.rs +++ b/compiler/rustc_infer/src/infer/relate/mod.rs @@ -3,12 +3,10 @@ //! As well as the implementation of `Relate` for interned things (`Ty`/`Const`/etc). pub use rustc_middle::ty::relate::RelateResult; -pub use rustc_next_trait_solver::relate::*; - -pub use self::combine::PredicateEmittingRelation; +pub use rustc_type_ir::relate::combine::PredicateEmittingRelation; +pub use rustc_type_ir::relate::*; #[allow(hidden_glob_reexports)] -pub(super) mod combine; mod generalize; mod higher_ranked; pub(super) mod lattice; diff --git a/compiler/rustc_infer/src/infer/relate/type_relating.rs b/compiler/rustc_infer/src/infer/relate/type_relating.rs index d99acabb82587..d2dc458910341 100644 --- a/compiler/rustc_infer/src/infer/relate/type_relating.rs +++ b/compiler/rustc_infer/src/infer/relate/type_relating.rs @@ -1,4 +1,5 @@ use rustc_middle::traits::solve::Goal; +use rustc_middle::ty::relate::combine::InferCtxtCombineExt; use rustc_middle::ty::relate::{ Relate, RelateResult, TypeRelation, relate_args_invariantly, relate_args_with_variances, }; diff --git a/compiler/rustc_next_trait_solver/src/lib.rs b/compiler/rustc_next_trait_solver/src/lib.rs index ca140500e2cd3..de74ac3280411 100644 --- a/compiler/rustc_next_trait_solver/src/lib.rs +++ b/compiler/rustc_next_trait_solver/src/lib.rs @@ -12,6 +12,5 @@ pub mod canonicalizer; pub mod coherence; pub mod delegate; -pub mod relate; pub mod resolve; pub mod solve; diff --git a/compiler/rustc_next_trait_solver/src/relate.rs b/compiler/rustc_next_trait_solver/src/relate.rs deleted file mode 100644 index db819961bbd75..0000000000000 --- a/compiler/rustc_next_trait_solver/src/relate.rs +++ /dev/null @@ -1,15 +0,0 @@ -pub use rustc_type_ir::relate::*; - -pub mod combine; - -/// Whether aliases should be related structurally or not. Used -/// to adjust the behavior of generalization and combine. -/// -/// This should always be `No` unless in a few special-cases when -/// instantiating canonical responses and in the new solver. Each -/// such case should have a comment explaining why it is used. -#[derive(Debug, Copy, Clone)] -pub enum StructurallyRelateAliases { - Yes, - No, -} diff --git a/compiler/rustc_next_trait_solver/src/relate/combine.rs b/compiler/rustc_next_trait_solver/src/relate/combine.rs deleted file mode 100644 index 96968327d8ee3..0000000000000 --- a/compiler/rustc_next_trait_solver/src/relate/combine.rs +++ /dev/null @@ -1,34 +0,0 @@ -pub use rustc_type_ir::relate::*; -use rustc_type_ir::solve::Goal; -use rustc_type_ir::{InferCtxtLike, Interner, Upcast}; - -use super::StructurallyRelateAliases; - -pub trait PredicateEmittingRelation::Interner>: - TypeRelation -where - Infcx: InferCtxtLike, - I: Interner, -{ - fn span(&self) -> I::Span; - - fn param_env(&self) -> I::ParamEnv; - - /// Whether aliases should be related structurally. This is pretty much - /// always `No` unless you're equating in some specific locations of the - /// new solver. See the comments in these use-cases for more details. - fn structurally_relate_aliases(&self) -> StructurallyRelateAliases; - - /// Register obligations that must hold in order for this relation to hold - fn register_goals(&mut self, obligations: impl IntoIterator>); - - /// Register predicates that must hold in order for this relation to hold. - /// This uses the default `param_env` of the obligation. - fn register_predicates( - &mut self, - obligations: impl IntoIterator>, - ); - - /// Register `AliasRelate` obligation(s) that both types must be related to each other. - fn register_alias_relate_predicate(&mut self, a: I::Ty, b: I::Ty); -} diff --git a/compiler/rustc_type_ir/src/infer_ctxt.rs b/compiler/rustc_type_ir/src/infer_ctxt.rs index 1d0b2345b805f..2f6476c6e233e 100644 --- a/compiler/rustc_type_ir/src/infer_ctxt.rs +++ b/compiler/rustc_type_ir/src/infer_ctxt.rs @@ -1,5 +1,6 @@ use crate::fold::TypeFoldable; -use crate::relate::Relate; +use crate::relate::combine::PredicateEmittingRelation; +use crate::relate::{Relate, RelateResult}; use crate::solve::{Goal, NoSolution, SolverMode}; use crate::{self as ty, Interner}; @@ -7,6 +8,14 @@ pub trait InferCtxtLike: Sized { type Interner: Interner; fn cx(&self) -> Self::Interner; + /// Whether the new trait solver is enabled. This only exists because rustc + /// shares code between the new and old trait solvers; for all other users, + /// this should always be true. If this is unknowingly false and you try to + /// use the new trait solver, things will break badly. + fn next_trait_solver(&self) -> bool { + true + } + fn solver_mode(&self) -> SolverMode; fn universe(&self) -> ty::UniverseIndex; @@ -58,6 +67,28 @@ pub trait InferCtxtLike: Sized { f: impl FnOnce(T) -> U, ) -> U; + fn equate_int_vids_raw(&self, a: ty::IntVid, b: ty::IntVid); + fn equate_float_vids_raw(&self, a: ty::FloatVid, b: ty::FloatVid); + fn equate_const_vids_raw(&self, a: ty::ConstVid, b: ty::ConstVid); + fn equate_effect_vids_raw(&self, a: ty::EffectVid, b: ty::EffectVid); + + fn instantiate_int_var_raw(&self, vid: ty::IntVid, value: ty::IntVarValue); + fn instantiate_float_var_raw(&self, vid: ty::FloatVid, value: ty::FloatVarValue); + fn instantiate_effect_var_raw( + &self, + vid: ty::EffectVid, + value: ::Const, + ); + fn instantiate_const_var_raw>( + &self, + relation: &mut R, + target_is_expected: bool, + target_vid: ty::ConstVid, + source_ct: ::Const, + ) -> RelateResult; + + fn set_tainted_by_errors(&self, e: ::ErrorGuaranteed); + fn relate>( &self, param_env: ::ParamEnv, @@ -77,6 +108,10 @@ pub trait InferCtxtLike: Sized { &self, ty: ::Ty, ) -> ::Ty; + fn shallow_resolve_const( + &self, + ty: ::Const, + ) -> ::Const; fn resolve_vars_if_possible(&self, value: T) -> T where diff --git a/compiler/rustc_type_ir/src/relate.rs b/compiler/rustc_type_ir/src/relate.rs index 9c725f34d8e5b..8e5d917e91569 100644 --- a/compiler/rustc_type_ir/src/relate.rs +++ b/compiler/rustc_type_ir/src/relate.rs @@ -9,8 +9,22 @@ use crate::fold::TypeFoldable; use crate::inherent::*; use crate::{self as ty, Interner}; +pub mod combine; + pub type RelateResult = Result>; +/// Whether aliases should be related structurally or not. Used +/// to adjust the behavior of generalization and combine. +/// +/// This should always be `No` unless in a few special-cases when +/// instantiating canonical responses and in the new solver. Each +/// such case should have a comment explaining why it is used. +#[derive(Debug, Copy, Clone)] +pub enum StructurallyRelateAliases { + Yes, + No, +} + /// Extra information about why we ended up with a particular variance. /// This is only used to add more information to error messages, and /// has no effect on soundness. While choosing the 'wrong' `VarianceDiagInfo` diff --git a/compiler/rustc_type_ir/src/relate/combine.rs b/compiler/rustc_type_ir/src/relate/combine.rs new file mode 100644 index 0000000000000..9dfcde609c71e --- /dev/null +++ b/compiler/rustc_type_ir/src/relate/combine.rs @@ -0,0 +1,255 @@ +use tracing::debug; + +use super::{ + ExpectedFound, RelateResult, StructurallyRelateAliases, TypeRelation, + structurally_relate_consts, structurally_relate_tys, +}; +use crate::error::TypeError; +use crate::inherent::*; +use crate::solve::{Goal, SolverMode}; +use crate::visit::TypeVisitableExt as _; +use crate::{self as ty, InferCtxtLike, Interner, Upcast}; + +pub trait PredicateEmittingRelation::Interner>: + TypeRelation +where + Infcx: InferCtxtLike, + I: Interner, +{ + fn span(&self) -> I::Span; + + fn param_env(&self) -> I::ParamEnv; + + /// Whether aliases should be related structurally. This is pretty much + /// always `No` unless you're equating in some specific locations of the + /// new solver. See the comments in these use-cases for more details. + fn structurally_relate_aliases(&self) -> StructurallyRelateAliases; + + /// Register obligations that must hold in order for this relation to hold + fn register_goals(&mut self, obligations: impl IntoIterator>); + + /// Register predicates that must hold in order for this relation to hold. + /// This uses the default `param_env` of the obligation. + fn register_predicates( + &mut self, + obligations: impl IntoIterator>, + ); + + /// Register `AliasRelate` obligation(s) that both types must be related to each other. + fn register_alias_relate_predicate(&mut self, a: I::Ty, b: I::Ty); +} + +pub trait InferCtxtCombineExt: InferCtxtLike { + fn super_combine_tys(&self, relation: &mut R, a: I::Ty, b: I::Ty) -> RelateResult + where + R: PredicateEmittingRelation; + + fn super_combine_consts( + &self, + relation: &mut R, + a: I::Const, + b: I::Const, + ) -> RelateResult + where + R: PredicateEmittingRelation; +} + +impl> InferCtxtCombineExt for Infcx { + fn super_combine_tys(&self, relation: &mut R, a: I::Ty, b: I::Ty) -> RelateResult + where + R: PredicateEmittingRelation, + { + debug!("super_combine_tys::<{}>({:?}, {:?})", std::any::type_name::(), a, b); + debug_assert!(!a.has_escaping_bound_vars()); + debug_assert!(!b.has_escaping_bound_vars()); + + match (a.kind(), b.kind()) { + (ty::Error(e), _) | (_, ty::Error(e)) => { + self.set_tainted_by_errors(e); + return Ok(Ty::new_error(self.cx(), e)); + } + + // Relate integral variables to other types + (ty::Infer(ty::IntVar(a_id)), ty::Infer(ty::IntVar(b_id))) => { + self.equate_int_vids_raw(a_id, b_id); + Ok(a) + } + (ty::Infer(ty::IntVar(v_id)), ty::Int(v)) => { + self.instantiate_int_var_raw(v_id, ty::IntVarValue::IntType(v)); + Ok(b) + } + (ty::Int(v), ty::Infer(ty::IntVar(v_id))) => { + self.instantiate_int_var_raw(v_id, ty::IntVarValue::IntType(v)); + Ok(a) + } + (ty::Infer(ty::IntVar(v_id)), ty::Uint(v)) => { + self.instantiate_int_var_raw(v_id, ty::IntVarValue::UintType(v)); + Ok(b) + } + (ty::Uint(v), ty::Infer(ty::IntVar(v_id))) => { + self.instantiate_int_var_raw(v_id, ty::IntVarValue::UintType(v)); + Ok(a) + } + + // Relate floating-point variables to other types + (ty::Infer(ty::FloatVar(a_id)), ty::Infer(ty::FloatVar(b_id))) => { + self.equate_float_vids_raw(a_id, b_id); + Ok(a) + } + (ty::Infer(ty::FloatVar(v_id)), ty::Float(v)) => { + self.instantiate_float_var_raw(v_id, ty::FloatVarValue::Known(v)); + Ok(b) + } + (ty::Float(v), ty::Infer(ty::FloatVar(v_id))) => { + self.instantiate_float_var_raw(v_id, ty::FloatVarValue::Known(v)); + Ok(a) + } + + // We don't expect `TyVar` or `Fresh*` vars at this point with lazy norm. + (ty::Alias(..), ty::Infer(ty::TyVar(_))) | (ty::Infer(ty::TyVar(_)), ty::Alias(..)) + if self.next_trait_solver() => + { + panic!( + "We do not expect to encounter `TyVar` this late in combine \ + -- they should have been handled earlier" + ) + } + (_, ty::Infer(ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_))) + | (ty::Infer(ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)), _) + if self.next_trait_solver() => + { + panic!("We do not expect to encounter `Fresh` variables in the new solver") + } + + (_, ty::Alias(..)) | (ty::Alias(..), _) if self.next_trait_solver() => { + match relation.structurally_relate_aliases() { + StructurallyRelateAliases::Yes => structurally_relate_tys(relation, a, b), + StructurallyRelateAliases::No => { + relation.register_alias_relate_predicate(a, b); + Ok(a) + } + } + } + + // All other cases of inference are errors + (ty::Infer(_), _) | (_, ty::Infer(_)) => { + Err(TypeError::Sorts(ExpectedFound::new(true, a, b))) + } + + (ty::Alias(ty::Opaque, _), _) | (_, ty::Alias(ty::Opaque, _)) => { + match self.solver_mode() { + SolverMode::Normal => { + assert!(!self.next_trait_solver()); + structurally_relate_tys(relation, a, b) + } + // During coherence, opaque types should be treated as *possibly* + // equal to any other type (except for possibly itself). This is an + // extremely heavy hammer, but can be relaxed in a forwards-compatible + // way later. + SolverMode::Coherence => { + relation + .register_predicates([ty::Binder::dummy(ty::PredicateKind::Ambiguous)]); + Ok(a) + } + } + } + + _ => structurally_relate_tys(relation, a, b), + } + } + + fn super_combine_consts( + &self, + relation: &mut R, + a: I::Const, + b: I::Const, + ) -> RelateResult + where + R: PredicateEmittingRelation, + { + debug!("super_combine_consts::<{}>({:?}, {:?})", std::any::type_name::(), a, b); + debug_assert!(!a.has_escaping_bound_vars()); + debug_assert!(!b.has_escaping_bound_vars()); + + if a == b { + return Ok(a); + } + + let a = self.shallow_resolve_const(a); + let b = self.shallow_resolve_const(b); + + match (a.kind(), b.kind()) { + ( + ty::ConstKind::Infer(ty::InferConst::Var(a_vid)), + ty::ConstKind::Infer(ty::InferConst::Var(b_vid)), + ) => { + self.equate_const_vids_raw(a_vid, b_vid); + Ok(a) + } + + ( + ty::ConstKind::Infer(ty::InferConst::EffectVar(a_vid)), + ty::ConstKind::Infer(ty::InferConst::EffectVar(b_vid)), + ) => { + self.equate_effect_vids_raw(a_vid, b_vid); + Ok(a) + } + + // All other cases of inference with other variables are errors. + ( + ty::ConstKind::Infer(ty::InferConst::Var(_) | ty::InferConst::EffectVar(_)), + ty::ConstKind::Infer(_), + ) + | ( + ty::ConstKind::Infer(_), + ty::ConstKind::Infer(ty::InferConst::Var(_) | ty::InferConst::EffectVar(_)), + ) => { + panic!( + "tried to combine ConstKind::Infer/ConstKind::Infer(InferConst::Var): {a:?} and {b:?}" + ) + } + + (ty::ConstKind::Infer(ty::InferConst::Var(vid)), _) => { + self.instantiate_const_var_raw(relation, true, vid, b)?; + Ok(b) + } + + (_, ty::ConstKind::Infer(ty::InferConst::Var(vid))) => { + self.instantiate_const_var_raw(relation, false, vid, a)?; + Ok(a) + } + + (ty::ConstKind::Infer(ty::InferConst::EffectVar(vid)), _) => { + self.instantiate_effect_var_raw(vid, b); + Ok(b) + } + + (_, ty::ConstKind::Infer(ty::InferConst::EffectVar(vid))) => { + self.instantiate_effect_var_raw(vid, a); + Ok(a) + } + + (ty::ConstKind::Unevaluated(..), _) | (_, ty::ConstKind::Unevaluated(..)) + if self.cx().features().generic_const_exprs() || self.next_trait_solver() => + { + match relation.structurally_relate_aliases() { + StructurallyRelateAliases::No => { + relation.register_predicates([if self.next_trait_solver() { + ty::PredicateKind::AliasRelate( + a.into(), + b.into(), + ty::AliasRelationDirection::Equate, + ) + } else { + ty::PredicateKind::ConstEquate(a, b) + }]); + + Ok(b) + } + StructurallyRelateAliases::Yes => structurally_relate_consts(relation, a, b), + } + } + _ => structurally_relate_consts(relation, a, b), + } + } +} From efb1c23ff602485531d65d31ed014d4575a12cec Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Fri, 4 Oct 2024 12:58:20 -0400 Subject: [PATCH 2088/2194] Introduce SolverRelating --- compiler/rustc_infer/src/infer/context.rs | 35 +- compiler/rustc_middle/src/ty/context.rs | 6 + compiler/rustc_type_ir/src/infer_ctxt.rs | 15 + compiler/rustc_type_ir/src/inherent.rs | 4 + compiler/rustc_type_ir/src/interner.rs | 2 +- compiler/rustc_type_ir/src/lib.rs | 4 +- compiler/rustc_type_ir/src/relate.rs | 1 + .../src/relate/solver_relating.rs | 324 ++++++++++++++++++ 8 files changed, 387 insertions(+), 4 deletions(-) create mode 100644 compiler/rustc_type_ir/src/relate/solver_relating.rs diff --git a/compiler/rustc_infer/src/infer/context.rs b/compiler/rustc_infer/src/infer/context.rs index 10b22c98a0d21..497be6b540431 100644 --- a/compiler/rustc_infer/src/infer/context.rs +++ b/compiler/rustc_infer/src/infer/context.rs @@ -136,6 +136,10 @@ impl<'tcx> rustc_type_ir::InferCtxtLike for InferCtxt<'tcx> { self.enter_forall(value, f) } + fn equate_ty_vids_raw(&self, a: rustc_type_ir::TyVid, b: rustc_type_ir::TyVid) { + self.inner.borrow_mut().type_variables().equate(a, b); + } + fn equate_int_vids_raw(&self, a: rustc_type_ir::IntVid, b: rustc_type_ir::IntVid) { self.inner.borrow_mut().int_unification_table().union(a, b); } @@ -152,6 +156,23 @@ impl<'tcx> rustc_type_ir::InferCtxtLike for InferCtxt<'tcx> { self.inner.borrow_mut().effect_unification_table().union(a, b); } + fn instantiate_ty_var_raw>( + &self, + relation: &mut R, + target_is_expected: bool, + target_vid: rustc_type_ir::TyVid, + instantiation_variance: rustc_type_ir::Variance, + source_ty: Ty<'tcx>, + ) -> RelateResult<'tcx, ()> { + self.instantiate_ty_var( + relation, + target_is_expected, + target_vid, + instantiation_variance, + source_ty, + ) + } + fn instantiate_int_var_raw( &self, vid: rustc_type_ir::IntVid, @@ -228,7 +249,19 @@ impl<'tcx> rustc_type_ir::InferCtxtLike for InferCtxt<'tcx> { } fn sub_regions(&self, sub: ty::Region<'tcx>, sup: ty::Region<'tcx>) { - self.sub_regions(SubregionOrigin::RelateRegionParamBound(DUMMY_SP, None), sub, sup) + self.inner.borrow_mut().unwrap_region_constraints().make_subregion( + SubregionOrigin::RelateRegionParamBound(DUMMY_SP, None), + sub, + sup, + ); + } + + fn equate_regions(&self, a: ty::Region<'tcx>, b: ty::Region<'tcx>) { + self.inner.borrow_mut().unwrap_region_constraints().make_eqregion( + SubregionOrigin::RelateRegionParamBound(DUMMY_SP, None), + a, + b, + ); } fn register_ty_outlives(&self, ty: Ty<'tcx>, r: ty::Region<'tcx>) { diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 4a02fce5e7d03..90265f67bc1f6 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -698,6 +698,12 @@ impl<'tcx> rustc_type_ir::inherent::Features> for &'tcx rustc_featu } } +impl<'tcx> rustc_type_ir::inherent::Span> for Span { + fn dummy() -> Self { + DUMMY_SP + } +} + type InternedSet<'tcx, T> = ShardedHashMap, ()>; pub struct CtxtInterners<'tcx> { diff --git a/compiler/rustc_type_ir/src/infer_ctxt.rs b/compiler/rustc_type_ir/src/infer_ctxt.rs index 2f6476c6e233e..4b44b5a495ec0 100644 --- a/compiler/rustc_type_ir/src/infer_ctxt.rs +++ b/compiler/rustc_type_ir/src/infer_ctxt.rs @@ -67,11 +67,20 @@ pub trait InferCtxtLike: Sized { f: impl FnOnce(T) -> U, ) -> U; + fn equate_ty_vids_raw(&self, a: ty::TyVid, b: ty::TyVid); fn equate_int_vids_raw(&self, a: ty::IntVid, b: ty::IntVid); fn equate_float_vids_raw(&self, a: ty::FloatVid, b: ty::FloatVid); fn equate_const_vids_raw(&self, a: ty::ConstVid, b: ty::ConstVid); fn equate_effect_vids_raw(&self, a: ty::EffectVid, b: ty::EffectVid); + fn instantiate_ty_var_raw>( + &self, + relation: &mut R, + target_is_expected: bool, + target_vid: ty::TyVid, + instantiation_variance: ty::Variance, + source_ty: ::Ty, + ) -> RelateResult; fn instantiate_int_var_raw(&self, vid: ty::IntVid, value: ty::IntVarValue); fn instantiate_float_var_raw(&self, vid: ty::FloatVid, value: ty::FloatVarValue); fn instantiate_effect_var_raw( @@ -125,6 +134,12 @@ pub trait InferCtxtLike: Sized { sup: ::Region, ); + fn equate_regions( + &self, + a: ::Region, + b: ::Region, + ); + fn register_ty_outlives( &self, ty: ::Ty, diff --git a/compiler/rustc_type_ir/src/inherent.rs b/compiler/rustc_type_ir/src/inherent.rs index 69665df4bfc26..f7875bb515270 100644 --- a/compiler/rustc_type_ir/src/inherent.rs +++ b/compiler/rustc_type_ir/src/inherent.rs @@ -565,6 +565,10 @@ pub trait BoundExistentialPredicates: ) -> impl IntoIterator>>; } +pub trait Span: Copy + Debug + Hash + Eq + TypeFoldable { + fn dummy() -> Self; +} + pub trait SliceLike: Sized + Copy { type Item: Copy; type IntoIter: Iterator; diff --git a/compiler/rustc_type_ir/src/interner.rs b/compiler/rustc_type_ir/src/interner.rs index b2ac67efef611..a72e7b482a6fd 100644 --- a/compiler/rustc_type_ir/src/interner.rs +++ b/compiler/rustc_type_ir/src/interner.rs @@ -36,7 +36,7 @@ pub trait Interner: { type DefId: DefId; type LocalDefId: Copy + Debug + Hash + Eq + Into + TypeFoldable; - type Span: Copy + Debug + Hash + Eq + TypeFoldable; + type Span: Span; type GenericArgs: GenericArgs; type GenericArgsSlice: Copy + Debug + Hash + Eq + SliceLike; diff --git a/compiler/rustc_type_ir/src/lib.rs b/compiler/rustc_type_ir/src/lib.rs index 02a9ad1e35fab..51c887fc4daa1 100644 --- a/compiler/rustc_type_ir/src/lib.rs +++ b/compiler/rustc_type_ir/src/lib.rs @@ -206,8 +206,8 @@ pub fn debug_bound_var( } } -#[derive(Copy, Clone, PartialEq, Eq)] -#[cfg_attr(feature = "nightly", derive(Decodable, Encodable, Hash, HashStable_NoContext))] +#[derive(Copy, Clone, PartialEq, Eq, Hash)] +#[cfg_attr(feature = "nightly", derive(Decodable, Encodable, HashStable_NoContext))] #[cfg_attr(feature = "nightly", rustc_pass_by_value)] pub enum Variance { Covariant, // T <: T iff A <: B -- e.g., function return type diff --git a/compiler/rustc_type_ir/src/relate.rs b/compiler/rustc_type_ir/src/relate.rs index 8e5d917e91569..1302906adab1f 100644 --- a/compiler/rustc_type_ir/src/relate.rs +++ b/compiler/rustc_type_ir/src/relate.rs @@ -10,6 +10,7 @@ use crate::inherent::*; use crate::{self as ty, Interner}; pub mod combine; +pub mod solver_relating; pub type RelateResult = Result>; diff --git a/compiler/rustc_type_ir/src/relate/solver_relating.rs b/compiler/rustc_type_ir/src/relate/solver_relating.rs new file mode 100644 index 0000000000000..18a4d5189bbcd --- /dev/null +++ b/compiler/rustc_type_ir/src/relate/solver_relating.rs @@ -0,0 +1,324 @@ +pub use rustc_type_ir::relate::*; +use rustc_type_ir::solve::Goal; +use rustc_type_ir::{self as ty, InferCtxtLike, Interner}; +use tracing::{debug, instrument}; + +use self::combine::{InferCtxtCombineExt, PredicateEmittingRelation}; +use crate::data_structures::DelayedSet; + +#[allow(unused)] +/// Enforce that `a` is equal to or a subtype of `b`. +pub struct SolverRelating<'infcx, Infcx, I: Interner> { + infcx: &'infcx Infcx, + // Immutable fields. + structurally_relate_aliases: StructurallyRelateAliases, + param_env: I::ParamEnv, + // Mutable fields. + ambient_variance: ty::Variance, + goals: Vec>, + /// The cache only tracks the `ambient_variance` as it's the + /// only field which is mutable and which meaningfully changes + /// the result when relating types. + /// + /// The cache does not track whether the state of the + /// `Infcx` has been changed or whether we've added any + /// goals to `self.goals`. Whether a goal is added once or multiple + /// times is not really meaningful. + /// + /// Changes in the inference state may delay some type inference to + /// the next fulfillment loop. Given that this loop is already + /// necessary, this is also not a meaningful change. Consider + /// the following three relations: + /// ```text + /// Vec sub Vec + /// ?0 eq u32 + /// Vec sub Vec + /// ``` + /// Without a cache, the second `Vec sub Vec` would eagerly + /// constrain `?1` to `u32`. When using the cache entry from the + /// first time we've related these types, this only happens when + /// later proving the `Subtype(?0, ?1)` goal from the first relation. + cache: DelayedSet<(ty::Variance, I::Ty, I::Ty)>, +} + +impl<'infcx, Infcx, I> SolverRelating<'infcx, Infcx, I> +where + Infcx: InferCtxtLike, + I: Interner, +{ +} + +impl TypeRelation for SolverRelating<'_, Infcx, I> +where + Infcx: InferCtxtLike, + I: Interner, +{ + fn cx(&self) -> I { + self.infcx.cx() + } + + fn relate_item_args( + &mut self, + item_def_id: I::DefId, + a_arg: I::GenericArgs, + b_arg: I::GenericArgs, + ) -> RelateResult { + if self.ambient_variance == ty::Invariant { + // Avoid fetching the variance if we are in an invariant + // context; no need, and it can induce dependency cycles + // (e.g., #41849). + relate_args_invariantly(self, a_arg, b_arg) + } else { + let tcx = self.cx(); + let opt_variances = tcx.variances_of(item_def_id); + relate_args_with_variances(self, item_def_id, opt_variances, a_arg, b_arg, false) + } + } + + fn relate_with_variance>( + &mut self, + variance: ty::Variance, + _info: VarianceDiagInfo, + a: T, + b: T, + ) -> RelateResult { + let old_ambient_variance = self.ambient_variance; + self.ambient_variance = self.ambient_variance.xform(variance); + debug!(?self.ambient_variance, "new ambient variance"); + + let r = if self.ambient_variance == ty::Bivariant { Ok(a) } else { self.relate(a, b) }; + + self.ambient_variance = old_ambient_variance; + r + } + + #[instrument(skip(self), level = "trace")] + fn tys(&mut self, a: I::Ty, b: I::Ty) -> RelateResult { + if a == b { + return Ok(a); + } + + let infcx = self.infcx; + let a = infcx.shallow_resolve(a); + let b = infcx.shallow_resolve(b); + + if self.cache.contains(&(self.ambient_variance, a, b)) { + return Ok(a); + } + + match (a.kind(), b.kind()) { + (ty::Infer(ty::TyVar(a_id)), ty::Infer(ty::TyVar(b_id))) => { + match self.ambient_variance { + ty::Covariant => { + // can't make progress on `A <: B` if both A and B are + // type variables, so record an obligation. + self.goals.push(Goal::new( + self.cx(), + self.param_env, + ty::Binder::dummy(ty::PredicateKind::Subtype(ty::SubtypePredicate { + a_is_expected: true, + a, + b, + })), + )); + } + ty::Contravariant => { + // can't make progress on `B <: A` if both A and B are + // type variables, so record an obligation. + self.goals.push(Goal::new( + self.cx(), + self.param_env, + ty::Binder::dummy(ty::PredicateKind::Subtype(ty::SubtypePredicate { + a_is_expected: false, + a: b, + b: a, + })), + )); + } + ty::Invariant => { + infcx.equate_ty_vids_raw(a_id, b_id); + } + ty::Bivariant => { + unreachable!("Expected bivariance to be handled in relate_with_variance") + } + } + } + + (ty::Infer(ty::TyVar(a_vid)), _) => { + infcx.instantiate_ty_var_raw(self, true, a_vid, self.ambient_variance, b)?; + } + (_, ty::Infer(ty::TyVar(b_vid))) => { + infcx.instantiate_ty_var_raw( + self, + false, + b_vid, + self.ambient_variance.xform(ty::Contravariant), + a, + )?; + } + + _ => { + self.infcx.super_combine_tys(self, a, b)?; + } + } + + assert!(self.cache.insert((self.ambient_variance, a, b))); + + Ok(a) + } + + #[instrument(skip(self), level = "trace")] + fn regions(&mut self, a: I::Region, b: I::Region) -> RelateResult { + match self.ambient_variance { + // Subtype(&'a u8, &'b u8) => Outlives('a: 'b) => SubRegion('b, 'a) + ty::Covariant => self.infcx.sub_regions(b, a), + // Suptype(&'a u8, &'b u8) => Outlives('b: 'a) => SubRegion('a, 'b) + ty::Contravariant => self.infcx.sub_regions(a, b), + ty::Invariant => self.infcx.equate_regions(a, b), + ty::Bivariant => { + unreachable!("Expected bivariance to be handled in relate_with_variance") + } + } + + Ok(a) + } + + #[instrument(skip(self), level = "trace")] + fn consts(&mut self, a: I::Const, b: I::Const) -> RelateResult { + self.infcx.super_combine_consts(self, a, b) + } + + fn binders( + &mut self, + a: ty::Binder, + b: ty::Binder, + ) -> RelateResult> + where + T: Relate, + { + // If they're equal, then short-circuit. + if a == b { + return Ok(a); + } + + // If they have no bound vars, relate normally. + if let Some(a_inner) = a.no_bound_vars() { + if let Some(b_inner) = b.no_bound_vars() { + self.relate(a_inner, b_inner)?; + return Ok(a); + } + }; + + match self.ambient_variance { + // Checks whether `for<..> sub <: for<..> sup` holds. + // + // For this to hold, **all** instantiations of the super type + // have to be a super type of **at least one** instantiation of + // the subtype. + // + // This is implemented by first entering a new universe. + // We then replace all bound variables in `sup` with placeholders, + // and all bound variables in `sub` with inference vars. + // We can then just relate the two resulting types as normal. + // + // Note: this is a subtle algorithm. For a full explanation, please see + // the [rustc dev guide][rd] + // + // [rd]: https://rustc-dev-guide.rust-lang.org/borrow_check/region_inference/placeholders_and_universes.html + ty::Covariant => { + self.infcx.enter_forall(b, |b| { + let a = self.infcx.instantiate_binder_with_infer(a); + self.relate(a, b) + })?; + } + ty::Contravariant => { + self.infcx.enter_forall(a, |a| { + let b = self.infcx.instantiate_binder_with_infer(b); + self.relate(a, b) + })?; + } + + // When **equating** binders, we check that there is a 1-to-1 + // correspondence between the bound vars in both types. + // + // We do so by separately instantiating one of the binders with + // placeholders and the other with inference variables and then + // equating the instantiated types. + // + // We want `for<..> A == for<..> B` -- therefore we want + // `exists<..> A == for<..> B` and `exists<..> B == for<..> A`. + // Check if `exists<..> A == for<..> B` + ty::Invariant => { + self.infcx.enter_forall(b, |b| { + let a = self.infcx.instantiate_binder_with_infer(a); + self.relate(a, b) + })?; + + // Check if `exists<..> B == for<..> A`. + self.infcx.enter_forall(a, |a| { + let b = self.infcx.instantiate_binder_with_infer(b); + self.relate(a, b) + })?; + } + ty::Bivariant => { + unreachable!("Expected bivariance to be handled in relate_with_variance") + } + } + Ok(a) + } +} + +impl PredicateEmittingRelation for SolverRelating<'_, Infcx, I> +where + Infcx: InferCtxtLike, + I: Interner, +{ + fn span(&self) -> I::Span { + Span::dummy() + } + + fn param_env(&self) -> I::ParamEnv { + self.param_env + } + + fn structurally_relate_aliases(&self) -> StructurallyRelateAliases { + self.structurally_relate_aliases + } + + fn register_predicates( + &mut self, + obligations: impl IntoIterator>, + ) { + self.goals.extend( + obligations.into_iter().map(|pred| Goal::new(self.infcx.cx(), self.param_env, pred)), + ); + } + + fn register_goals(&mut self, obligations: impl IntoIterator>) { + self.goals.extend(obligations); + } + + fn register_alias_relate_predicate(&mut self, a: I::Ty, b: I::Ty) { + self.register_predicates([ty::Binder::dummy(match self.ambient_variance { + ty::Covariant => ty::PredicateKind::AliasRelate( + a.into(), + b.into(), + ty::AliasRelationDirection::Subtype, + ), + // a :> b is b <: a + ty::Contravariant => ty::PredicateKind::AliasRelate( + b.into(), + a.into(), + ty::AliasRelationDirection::Subtype, + ), + ty::Invariant => ty::PredicateKind::AliasRelate( + a.into(), + b.into(), + ty::AliasRelationDirection::Equate, + ), + ty::Bivariant => { + unreachable!("Expected bivariance to be handled in relate_with_variance") + } + })]); + } +} From 3da257a98d44efb5f1a7df2e4237935bcf0f2b92 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 6 Aug 2024 12:50:18 -0400 Subject: [PATCH 2089/2194] Use SolverRelating in new solver --- compiler/rustc_infer/src/infer/at.rs | 43 ------------- compiler/rustc_infer/src/infer/context.rs | 24 +------ compiler/rustc_infer/src/infer/mod.rs | 6 -- compiler/rustc_infer/src/infer/relate/mod.rs | 1 - .../src/solve/eval_ctxt/canonical.rs | 1 + .../src/solve/eval_ctxt/mod.rs | 1 + .../src/error_reporting/infer/mod.rs | 6 -- compiler/rustc_type_ir/src/infer_ctxt.rs | 19 +----- .../src/relate/solver_relating.rs | 64 ++++++++++++++++++- 9 files changed, 68 insertions(+), 97 deletions(-) diff --git a/compiler/rustc_infer/src/infer/at.rs b/compiler/rustc_infer/src/infer/at.rs index 5422761a6cf74..ee9f548c1d4be 100644 --- a/compiler/rustc_infer/src/infer/at.rs +++ b/compiler/rustc_infer/src/infer/at.rs @@ -208,49 +208,6 @@ impl<'a, 'tcx> At<'a, 'tcx> { } } - /// Used in the new solver since we don't care about tracking an `ObligationCause`. - pub fn relate_no_trace( - self, - expected: T, - variance: ty::Variance, - actual: T, - ) -> Result>>, NoSolution> - where - T: Relate>, - { - let mut op = TypeRelating::new( - self.infcx, - TypeTrace::dummy(self.cause), - self.param_env, - DefineOpaqueTypes::Yes, - StructurallyRelateAliases::No, - variance, - ); - op.relate(expected, actual)?; - Ok(op.into_obligations().into_iter().map(|o| o.into()).collect()) - } - - /// Used in the new solver since we don't care about tracking an `ObligationCause`. - pub fn eq_structurally_relating_aliases_no_trace( - self, - expected: T, - actual: T, - ) -> Result>>, NoSolution> - where - T: Relate>, - { - let mut op = TypeRelating::new( - self.infcx, - TypeTrace::dummy(self.cause), - self.param_env, - DefineOpaqueTypes::Yes, - StructurallyRelateAliases::Yes, - ty::Invariant, - ); - op.relate(expected, actual)?; - Ok(op.into_obligations().into_iter().map(|o| o.into()).collect()) - } - /// Computes the least-upper-bound, or mutual supertype, of two /// values. The order of the arguments doesn't matter, but since /// this can result in an error (e.g., if asked to compute LUB of diff --git a/compiler/rustc_infer/src/infer/context.rs b/compiler/rustc_infer/src/infer/context.rs index 497be6b540431..57007752cade3 100644 --- a/compiler/rustc_infer/src/infer/context.rs +++ b/compiler/rustc_infer/src/infer/context.rs @@ -2,10 +2,10 @@ use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_middle::infer::unify_key::EffectVarValue; use rustc_middle::traits::ObligationCause; -use rustc_middle::traits::solve::{Goal, NoSolution, SolverMode}; +use rustc_middle::traits::solve::SolverMode; use rustc_middle::ty::fold::TypeFoldable; +use rustc_middle::ty::relate::RelateResult; use rustc_middle::ty::relate::combine::PredicateEmittingRelation; -use rustc_middle::ty::relate::{Relate, RelateResult}; use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_span::{DUMMY_SP, ErrorGuaranteed}; @@ -210,26 +210,6 @@ impl<'tcx> rustc_type_ir::InferCtxtLike for InferCtxt<'tcx> { self.set_tainted_by_errors(e) } - fn relate>>( - &self, - param_env: ty::ParamEnv<'tcx>, - lhs: T, - variance: ty::Variance, - rhs: T, - ) -> Result>>, NoSolution> { - self.at(&ObligationCause::dummy(), param_env).relate_no_trace(lhs, variance, rhs) - } - - fn eq_structurally_relating_aliases>>( - &self, - param_env: ty::ParamEnv<'tcx>, - lhs: T, - rhs: T, - ) -> Result>>, NoSolution> { - self.at(&ObligationCause::dummy(), param_env) - .eq_structurally_relating_aliases_no_trace(lhs, rhs) - } - fn shallow_resolve(&self, ty: Ty<'tcx>) -> Ty<'tcx> { self.shallow_resolve(ty) } diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index 21f9bf028d5ea..bc813305ba480 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -32,7 +32,6 @@ use rustc_middle::infer::unify_key::{ use rustc_middle::mir::ConstraintCategory; use rustc_middle::mir::interpret::{ErrorHandled, EvalToValTreeResult}; use rustc_middle::traits::select; -use rustc_middle::traits::solve::{Goal, NoSolution}; pub use rustc_middle::ty::IntVarValue; use rustc_middle::ty::error::{ExpectedFound, TypeError}; use rustc_middle::ty::fold::{ @@ -340,7 +339,6 @@ pub enum ValuePairs<'tcx> { PolySigs(ExpectedFound>), ExistentialTraitRef(ExpectedFound>), ExistentialProjection(ExpectedFound>), - Dummy, } impl<'tcx> ValuePairs<'tcx> { @@ -1638,10 +1636,6 @@ impl<'tcx> TypeTrace<'tcx> { values: ValuePairs::Terms(ExpectedFound::new(a_is_expected, a.into(), b.into())), } } - - fn dummy(cause: &ObligationCause<'tcx>) -> TypeTrace<'tcx> { - TypeTrace { cause: cause.clone(), values: ValuePairs::Dummy } - } } impl<'tcx> SubregionOrigin<'tcx> { diff --git a/compiler/rustc_infer/src/infer/relate/mod.rs b/compiler/rustc_infer/src/infer/relate/mod.rs index e156f72d78d07..e6d1003cab61e 100644 --- a/compiler/rustc_infer/src/infer/relate/mod.rs +++ b/compiler/rustc_infer/src/infer/relate/mod.rs @@ -6,7 +6,6 @@ pub use rustc_middle::ty::relate::RelateResult; pub use rustc_type_ir::relate::combine::PredicateEmittingRelation; pub use rustc_type_ir::relate::*; -#[allow(hidden_glob_reexports)] mod generalize; mod higher_ranked; pub(super) mod lattice; diff --git a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/canonical.rs b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/canonical.rs index 252a9ed1a2e79..3b6197c675957 100644 --- a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/canonical.rs +++ b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/canonical.rs @@ -14,6 +14,7 @@ use std::iter; use rustc_index::IndexVec; use rustc_type_ir::fold::TypeFoldable; use rustc_type_ir::inherent::*; +use rustc_type_ir::relate::solver_relating::RelateExt; use rustc_type_ir::{self as ty, Canonical, CanonicalVarValues, InferCtxtLike, Interner}; use tracing::{instrument, trace}; diff --git a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs index ffa800348f2ce..970ef905dfd8f 100644 --- a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs @@ -7,6 +7,7 @@ use rustc_type_ir::data_structures::{HashMap, HashSet, ensure_sufficient_stack}; use rustc_type_ir::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable}; use rustc_type_ir::inherent::*; use rustc_type_ir::relate::Relate; +use rustc_type_ir::relate::solver_relating::RelateExt; use rustc_type_ir::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor}; use rustc_type_ir::{self as ty, CanonicalVarValues, InferCtxtLike, Interner}; use rustc_type_ir_macros::{Lift_Generic, TypeFoldable_Generic, TypeVisitable_Generic}; diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs index c7b3f704330bd..bd78a6ee3aff7 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs @@ -1285,9 +1285,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { ValuePairs::ExistentialProjection(_) => { (false, Mismatch::Fixed("existential projection")) } - ValuePairs::Dummy => { - bug!("do not expect to report a type error from a ValuePairs::Dummy") - } }; let Some(vals) = self.values_str(values) else { // Derived error. Cancel the emitter. @@ -1853,9 +1850,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { let (exp, fnd) = self.cmp_fn_sig(&exp_found.expected, &exp_found.found); Some((exp, fnd, None)) } - ValuePairs::Dummy => { - bug!("do not expect to report a type error from a ValuePairs::Dummy") - } } } diff --git a/compiler/rustc_type_ir/src/infer_ctxt.rs b/compiler/rustc_type_ir/src/infer_ctxt.rs index 4b44b5a495ec0..b9f5cde653eaa 100644 --- a/compiler/rustc_type_ir/src/infer_ctxt.rs +++ b/compiler/rustc_type_ir/src/infer_ctxt.rs @@ -1,7 +1,7 @@ use crate::fold::TypeFoldable; +use crate::relate::RelateResult; use crate::relate::combine::PredicateEmittingRelation; -use crate::relate::{Relate, RelateResult}; -use crate::solve::{Goal, NoSolution, SolverMode}; +use crate::solve::SolverMode; use crate::{self as ty, Interner}; pub trait InferCtxtLike: Sized { @@ -98,21 +98,6 @@ pub trait InferCtxtLike: Sized { fn set_tainted_by_errors(&self, e: ::ErrorGuaranteed); - fn relate>( - &self, - param_env: ::ParamEnv, - lhs: T, - variance: ty::Variance, - rhs: T, - ) -> Result::Predicate>>, NoSolution>; - - fn eq_structurally_relating_aliases>( - &self, - param_env: ::ParamEnv, - lhs: T, - rhs: T, - ) -> Result::Predicate>>, NoSolution>; - fn shallow_resolve( &self, ty: ::Ty, diff --git a/compiler/rustc_type_ir/src/relate/solver_relating.rs b/compiler/rustc_type_ir/src/relate/solver_relating.rs index 18a4d5189bbcd..a2521eda6dd38 100644 --- a/compiler/rustc_type_ir/src/relate/solver_relating.rs +++ b/compiler/rustc_type_ir/src/relate/solver_relating.rs @@ -1,12 +1,57 @@ pub use rustc_type_ir::relate::*; -use rustc_type_ir::solve::Goal; +use rustc_type_ir::solve::{Goal, NoSolution}; use rustc_type_ir::{self as ty, InferCtxtLike, Interner}; use tracing::{debug, instrument}; use self::combine::{InferCtxtCombineExt, PredicateEmittingRelation}; use crate::data_structures::DelayedSet; -#[allow(unused)] +pub trait RelateExt: InferCtxtLike { + fn relate>( + &self, + param_env: ::ParamEnv, + lhs: T, + variance: ty::Variance, + rhs: T, + ) -> Result::Predicate>>, NoSolution>; + + fn eq_structurally_relating_aliases>( + &self, + param_env: ::ParamEnv, + lhs: T, + rhs: T, + ) -> Result::Predicate>>, NoSolution>; +} + +impl RelateExt for Infcx { + fn relate>( + &self, + param_env: ::ParamEnv, + lhs: T, + variance: ty::Variance, + rhs: T, + ) -> Result::Predicate>>, NoSolution> + { + let mut relate = + SolverRelating::new(self, StructurallyRelateAliases::No, variance, param_env); + relate.relate(lhs, rhs)?; + Ok(relate.goals) + } + + fn eq_structurally_relating_aliases>( + &self, + param_env: ::ParamEnv, + lhs: T, + rhs: T, + ) -> Result::Predicate>>, NoSolution> + { + let mut relate = + SolverRelating::new(self, StructurallyRelateAliases::Yes, ty::Invariant, param_env); + relate.relate(lhs, rhs)?; + Ok(relate.goals) + } +} + /// Enforce that `a` is equal to or a subtype of `b`. pub struct SolverRelating<'infcx, Infcx, I: Interner> { infcx: &'infcx Infcx, @@ -46,6 +91,21 @@ where Infcx: InferCtxtLike, I: Interner, { + fn new( + infcx: &'infcx Infcx, + structurally_relate_aliases: StructurallyRelateAliases, + ambient_variance: ty::Variance, + param_env: I::ParamEnv, + ) -> Self { + SolverRelating { + infcx, + structurally_relate_aliases, + ambient_variance, + param_env, + goals: vec![], + cache: Default::default(), + } + } } impl TypeRelation for SolverRelating<'_, Infcx, I> From 30a2ecddb45f30dc62946770ef88df115f194b17 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Fri, 4 Oct 2024 13:07:34 -0400 Subject: [PATCH 2090/2194] Remove unnecessary StructurallyRelateAliases from CombineFields/TypeRelating --- compiler/rustc_infer/src/infer/at.rs | 5 +---- compiler/rustc_infer/src/infer/relate/type_relating.rs | 5 +---- 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/compiler/rustc_infer/src/infer/at.rs b/compiler/rustc_infer/src/infer/at.rs index ee9f548c1d4be..1b99effabc000 100644 --- a/compiler/rustc_infer/src/infer/at.rs +++ b/compiler/rustc_infer/src/infer/at.rs @@ -31,7 +31,7 @@ use rustc_middle::ty::{Const, ImplSubject}; use super::*; use crate::infer::relate::type_relating::TypeRelating; -use crate::infer::relate::{Relate, StructurallyRelateAliases, TypeRelation}; +use crate::infer::relate::{Relate, TypeRelation}; /// Whether we should define opaque types or just treat them opaquely. /// @@ -114,7 +114,6 @@ impl<'a, 'tcx> At<'a, 'tcx> { ToTrace::to_trace(self.cause, expected, actual), self.param_env, define_opaque_types, - StructurallyRelateAliases::No, ty::Contravariant, ); op.relate(expected, actual)?; @@ -136,7 +135,6 @@ impl<'a, 'tcx> At<'a, 'tcx> { ToTrace::to_trace(self.cause, expected, actual), self.param_env, define_opaque_types, - StructurallyRelateAliases::No, ty::Covariant, ); op.relate(expected, actual)?; @@ -177,7 +175,6 @@ impl<'a, 'tcx> At<'a, 'tcx> { trace, self.param_env, define_opaque_types, - StructurallyRelateAliases::No, ty::Invariant, ); op.relate(expected, actual)?; diff --git a/compiler/rustc_infer/src/infer/relate/type_relating.rs b/compiler/rustc_infer/src/infer/relate/type_relating.rs index d2dc458910341..6129faf3d50cd 100644 --- a/compiler/rustc_infer/src/infer/relate/type_relating.rs +++ b/compiler/rustc_infer/src/infer/relate/type_relating.rs @@ -21,7 +21,6 @@ pub(crate) struct TypeRelating<'infcx, 'tcx> { trace: TypeTrace<'tcx>, param_env: ty::ParamEnv<'tcx>, define_opaque_types: DefineOpaqueTypes, - structurally_relate_aliases: StructurallyRelateAliases, // Mutable fields. ambient_variance: ty::Variance, @@ -57,7 +56,6 @@ impl<'infcx, 'tcx> TypeRelating<'infcx, 'tcx> { trace: TypeTrace<'tcx>, param_env: ty::ParamEnv<'tcx>, define_opaque_types: DefineOpaqueTypes, - structurally_relate_aliases: StructurallyRelateAliases, ambient_variance: ty::Variance, ) -> TypeRelating<'infcx, 'tcx> { TypeRelating { @@ -65,7 +63,6 @@ impl<'infcx, 'tcx> TypeRelating<'infcx, 'tcx> { trace, param_env, define_opaque_types, - structurally_relate_aliases, ambient_variance, obligations: vec![], cache: Default::default(), @@ -353,7 +350,7 @@ impl<'tcx> PredicateEmittingRelation> for TypeRelating<'_, 'tcx> } fn structurally_relate_aliases(&self) -> StructurallyRelateAliases { - self.structurally_relate_aliases + StructurallyRelateAliases::No } fn register_predicates( From a4cd2202ef10e217e2905ba905dd5536958528ab Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Fri, 4 Oct 2024 13:30:51 -0400 Subject: [PATCH 2091/2194] Use SolverRelating in favor of TypeRelating in the old solver where possible --- compiler/rustc_infer/src/infer/at.rs | 98 ++++++++++++++----- .../src/infer/relate/type_relating.rs | 5 +- .../src/solve/eval_ctxt/mod.rs | 2 +- .../src/relate/solver_relating.rs | 26 +++-- 4 files changed, 92 insertions(+), 39 deletions(-) diff --git a/compiler/rustc_infer/src/infer/at.rs b/compiler/rustc_infer/src/infer/at.rs index 1b99effabc000..8c943a961e76a 100644 --- a/compiler/rustc_infer/src/infer/at.rs +++ b/compiler/rustc_infer/src/infer/at.rs @@ -27,11 +27,14 @@ use relate::lattice::{LatticeOp, LatticeOpKind}; use rustc_middle::bug; +use rustc_middle::ty::relate::solver_relating::RelateExt as NextSolverRelate; use rustc_middle::ty::{Const, ImplSubject}; use super::*; use crate::infer::relate::type_relating::TypeRelating; use crate::infer::relate::{Relate, TypeRelation}; +use crate::traits::Obligation; +use crate::traits::solve::Goal; /// Whether we should define opaque types or just treat them opaquely. /// @@ -109,15 +112,26 @@ impl<'a, 'tcx> At<'a, 'tcx> { where T: ToTrace<'tcx>, { - let mut op = TypeRelating::new( - self.infcx, - ToTrace::to_trace(self.cause, expected, actual), - self.param_env, - define_opaque_types, - ty::Contravariant, - ); - op.relate(expected, actual)?; - Ok(InferOk { value: (), obligations: op.into_obligations() }) + if self.infcx.next_trait_solver { + NextSolverRelate::relate( + self.infcx, + self.param_env, + expected, + ty::Contravariant, + actual, + ) + .map(|goals| self.goals_to_obligations(goals)) + } else { + let mut op = TypeRelating::new( + self.infcx, + ToTrace::to_trace(self.cause, expected, actual), + self.param_env, + define_opaque_types, + ty::Contravariant, + ); + op.relate(expected, actual)?; + Ok(InferOk { value: (), obligations: op.into_obligations() }) + } } /// Makes `expected <: actual`. @@ -130,15 +144,20 @@ impl<'a, 'tcx> At<'a, 'tcx> { where T: ToTrace<'tcx>, { - let mut op = TypeRelating::new( - self.infcx, - ToTrace::to_trace(self.cause, expected, actual), - self.param_env, - define_opaque_types, - ty::Covariant, - ); - op.relate(expected, actual)?; - Ok(InferOk { value: (), obligations: op.into_obligations() }) + if self.infcx.next_trait_solver { + NextSolverRelate::relate(self.infcx, self.param_env, expected, ty::Covariant, actual) + .map(|goals| self.goals_to_obligations(goals)) + } else { + let mut op = TypeRelating::new( + self.infcx, + ToTrace::to_trace(self.cause, expected, actual), + self.param_env, + define_opaque_types, + ty::Covariant, + ); + op.relate(expected, actual)?; + Ok(InferOk { value: (), obligations: op.into_obligations() }) + } } /// Makes `expected == actual`. @@ -170,15 +189,20 @@ impl<'a, 'tcx> At<'a, 'tcx> { where T: Relate>, { - let mut op = TypeRelating::new( - self.infcx, - trace, - self.param_env, - define_opaque_types, - ty::Invariant, - ); - op.relate(expected, actual)?; - Ok(InferOk { value: (), obligations: op.into_obligations() }) + if self.infcx.next_trait_solver { + NextSolverRelate::relate(self.infcx, self.param_env, expected, ty::Invariant, actual) + .map(|goals| self.goals_to_obligations(goals)) + } else { + let mut op = TypeRelating::new( + self.infcx, + trace, + self.param_env, + define_opaque_types, + ty::Invariant, + ); + op.relate(expected, actual)?; + Ok(InferOk { value: (), obligations: op.into_obligations() }) + } } pub fn relate( @@ -223,6 +247,26 @@ impl<'a, 'tcx> At<'a, 'tcx> { let value = op.relate(expected, actual)?; Ok(InferOk { value, obligations: op.into_obligations() }) } + + fn goals_to_obligations( + &self, + goals: Vec>>, + ) -> InferOk<'tcx, ()> { + InferOk { + value: (), + obligations: goals + .into_iter() + .map(|goal| { + Obligation::new( + self.infcx.tcx, + self.cause.clone(), + goal.param_env, + goal.predicate, + ) + }) + .collect(), + } + } } impl<'tcx> ToTrace<'tcx> for ImplSubject<'tcx> { diff --git a/compiler/rustc_infer/src/infer/relate/type_relating.rs b/compiler/rustc_infer/src/infer/relate/type_relating.rs index 6129faf3d50cd..1cc968ca27550 100644 --- a/compiler/rustc_infer/src/infer/relate/type_relating.rs +++ b/compiler/rustc_infer/src/infer/relate/type_relating.rs @@ -58,6 +58,7 @@ impl<'infcx, 'tcx> TypeRelating<'infcx, 'tcx> { define_opaque_types: DefineOpaqueTypes, ambient_variance: ty::Variance, ) -> TypeRelating<'infcx, 'tcx> { + assert!(!infcx.next_trait_solver); TypeRelating { infcx, trace, @@ -190,9 +191,7 @@ impl<'tcx> TypeRelation> for TypeRelating<'_, 'tcx> { (&ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }), _) | (_, &ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. })) - if self.define_opaque_types == DefineOpaqueTypes::Yes - && def_id.is_local() - && !infcx.next_trait_solver() => + if self.define_opaque_types == DefineOpaqueTypes::Yes && def_id.is_local() => { self.register_goals(infcx.handle_opaque_type( a, diff --git a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs index 970ef905dfd8f..785bed4ec6928 100644 --- a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs @@ -836,7 +836,7 @@ where lhs: T, rhs: T, ) -> Result>, NoSolution> { - self.delegate.relate(param_env, lhs, ty::Variance::Invariant, rhs) + Ok(self.delegate.relate(param_env, lhs, ty::Variance::Invariant, rhs)?) } pub(super) fn instantiate_binder_with_infer + Copy>( diff --git a/compiler/rustc_type_ir/src/relate/solver_relating.rs b/compiler/rustc_type_ir/src/relate/solver_relating.rs index a2521eda6dd38..edbfaed97095b 100644 --- a/compiler/rustc_type_ir/src/relate/solver_relating.rs +++ b/compiler/rustc_type_ir/src/relate/solver_relating.rs @@ -1,5 +1,5 @@ pub use rustc_type_ir::relate::*; -use rustc_type_ir::solve::{Goal, NoSolution}; +use rustc_type_ir::solve::Goal; use rustc_type_ir::{self as ty, InferCtxtLike, Interner}; use tracing::{debug, instrument}; @@ -13,14 +13,20 @@ pub trait RelateExt: InferCtxtLike { lhs: T, variance: ty::Variance, rhs: T, - ) -> Result::Predicate>>, NoSolution>; + ) -> Result< + Vec::Predicate>>, + TypeError, + >; fn eq_structurally_relating_aliases>( &self, param_env: ::ParamEnv, lhs: T, rhs: T, - ) -> Result::Predicate>>, NoSolution>; + ) -> Result< + Vec::Predicate>>, + TypeError, + >; } impl RelateExt for Infcx { @@ -30,8 +36,10 @@ impl RelateExt for Infcx { lhs: T, variance: ty::Variance, rhs: T, - ) -> Result::Predicate>>, NoSolution> - { + ) -> Result< + Vec::Predicate>>, + TypeError, + > { let mut relate = SolverRelating::new(self, StructurallyRelateAliases::No, variance, param_env); relate.relate(lhs, rhs)?; @@ -43,8 +51,10 @@ impl RelateExt for Infcx { param_env: ::ParamEnv, lhs: T, rhs: T, - ) -> Result::Predicate>>, NoSolution> - { + ) -> Result< + Vec::Predicate>>, + TypeError, + > { let mut relate = SolverRelating::new(self, StructurallyRelateAliases::Yes, ty::Invariant, param_env); relate.relate(lhs, rhs)?; @@ -91,7 +101,7 @@ where Infcx: InferCtxtLike, I: Interner, { - fn new( + pub fn new( infcx: &'infcx Infcx, structurally_relate_aliases: StructurallyRelateAliases, ambient_variance: ty::Variance, From 8715bfbf0ef398780451e9f45d036cf8353b1e60 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Thu, 10 Oct 2024 05:40:56 -0400 Subject: [PATCH 2092/2194] Make super combine into fns --- .../src/type_check/relate_tys.rs | 8 +- .../rustc_infer/src/infer/relate/lattice.rs | 8 +- .../src/infer/relate/type_relating.rs | 8 +- compiler/rustc_type_ir/src/relate/combine.rs | 365 +++++++++--------- .../src/relate/solver_relating.rs | 6 +- 5 files changed, 193 insertions(+), 202 deletions(-) diff --git a/compiler/rustc_borrowck/src/type_check/relate_tys.rs b/compiler/rustc_borrowck/src/type_check/relate_tys.rs index e72c21e8fadf4..cfc14d146bd2c 100644 --- a/compiler/rustc_borrowck/src/type_check/relate_tys.rs +++ b/compiler/rustc_borrowck/src/type_check/relate_tys.rs @@ -11,7 +11,7 @@ use rustc_middle::span_bug; use rustc_middle::traits::ObligationCause; use rustc_middle::traits::query::NoSolution; use rustc_middle::ty::fold::FnMutDelegate; -use rustc_middle::ty::relate::combine::InferCtxtCombineExt; +use rustc_middle::ty::relate::combine::{super_combine_consts, super_combine_tys}; use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt}; use rustc_span::symbol::sym; use rustc_span::{Span, Symbol}; @@ -363,7 +363,7 @@ impl<'b, 'tcx> TypeRelation> for NllTypeRelating<'_, 'b, 'tcx> { &ty::Alias(ty::Opaque, ty::AliasTy { def_id: a_def_id, .. }), &ty::Alias(ty::Opaque, ty::AliasTy { def_id: b_def_id, .. }), ) if a_def_id == b_def_id || infcx.next_trait_solver() => { - infcx.super_combine_tys(self, a, b).map(|_| ()).or_else(|err| { + super_combine_tys(&infcx.infcx, self, a, b).map(|_| ()).or_else(|err| { // This behavior is only there for the old solver, the new solver // shouldn't ever fail. Instead, it unconditionally emits an // alias-relate goal. @@ -386,7 +386,7 @@ impl<'b, 'tcx> TypeRelation> for NllTypeRelating<'_, 'b, 'tcx> { debug!(?a, ?b, ?self.ambient_variance); // Will also handle unification of `IntVar` and `FloatVar`. - self.type_checker.infcx.super_combine_tys(self, a, b)?; + super_combine_tys(&self.type_checker.infcx.infcx, self, a, b)?; } } @@ -423,7 +423,7 @@ impl<'b, 'tcx> TypeRelation> for NllTypeRelating<'_, 'b, 'tcx> { assert!(!a.has_non_region_infer(), "unexpected inference var {:?}", a); assert!(!b.has_non_region_infer(), "unexpected inference var {:?}", b); - self.type_checker.infcx.super_combine_consts(self, a, b) + super_combine_consts(&self.type_checker.infcx.infcx, self, a, b) } #[instrument(skip(self), level = "trace")] diff --git a/compiler/rustc_infer/src/infer/relate/lattice.rs b/compiler/rustc_infer/src/infer/relate/lattice.rs index fc208a084718e..7eb61abfbc124 100644 --- a/compiler/rustc_infer/src/infer/relate/lattice.rs +++ b/compiler/rustc_infer/src/infer/relate/lattice.rs @@ -18,7 +18,7 @@ //! [lattices]: https://en.wikipedia.org/wiki/Lattice_(order) use rustc_middle::traits::solve::Goal; -use rustc_middle::ty::relate::combine::InferCtxtCombineExt; +use rustc_middle::ty::relate::combine::{super_combine_consts, super_combine_tys}; use rustc_middle::ty::relate::{Relate, RelateResult, TypeRelation}; use rustc_middle::ty::{self, Ty, TyCtxt, TyVar, TypeVisitableExt}; use rustc_span::Span; @@ -149,7 +149,7 @@ impl<'tcx> TypeRelation> for LatticeOp<'_, 'tcx> { ( &ty::Alias(ty::Opaque, ty::AliasTy { def_id: a_def_id, .. }), &ty::Alias(ty::Opaque, ty::AliasTy { def_id: b_def_id, .. }), - ) if a_def_id == b_def_id => infcx.super_combine_tys(self, a, b), + ) if a_def_id == b_def_id => super_combine_tys(infcx, self, a, b), (&ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }), _) | (_, &ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. })) @@ -164,7 +164,7 @@ impl<'tcx> TypeRelation> for LatticeOp<'_, 'tcx> { Ok(a) } - _ => infcx.super_combine_tys(self, a, b), + _ => super_combine_tys(infcx, self, a, b), } } @@ -192,7 +192,7 @@ impl<'tcx> TypeRelation> for LatticeOp<'_, 'tcx> { a: ty::Const<'tcx>, b: ty::Const<'tcx>, ) -> RelateResult<'tcx, ty::Const<'tcx>> { - self.infcx.super_combine_consts(self, a, b) + super_combine_consts(self.infcx, self, a, b) } fn binders( diff --git a/compiler/rustc_infer/src/infer/relate/type_relating.rs b/compiler/rustc_infer/src/infer/relate/type_relating.rs index 1cc968ca27550..35103c070c27d 100644 --- a/compiler/rustc_infer/src/infer/relate/type_relating.rs +++ b/compiler/rustc_infer/src/infer/relate/type_relating.rs @@ -1,5 +1,5 @@ use rustc_middle::traits::solve::Goal; -use rustc_middle::ty::relate::combine::InferCtxtCombineExt; +use rustc_middle::ty::relate::combine::{super_combine_consts, super_combine_tys}; use rustc_middle::ty::relate::{ Relate, RelateResult, TypeRelation, relate_args_invariantly, relate_args_with_variances, }; @@ -186,7 +186,7 @@ impl<'tcx> TypeRelation> for TypeRelating<'_, 'tcx> { &ty::Alias(ty::Opaque, ty::AliasTy { def_id: a_def_id, .. }), &ty::Alias(ty::Opaque, ty::AliasTy { def_id: b_def_id, .. }), ) if a_def_id == b_def_id => { - infcx.super_combine_tys(self, a, b)?; + super_combine_tys(infcx, self, a, b)?; } (&ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }), _) @@ -202,7 +202,7 @@ impl<'tcx> TypeRelation> for TypeRelating<'_, 'tcx> { } _ => { - infcx.super_combine_tys(self, a, b)?; + super_combine_tys(infcx, self, a, b)?; } } @@ -257,7 +257,7 @@ impl<'tcx> TypeRelation> for TypeRelating<'_, 'tcx> { a: ty::Const<'tcx>, b: ty::Const<'tcx>, ) -> RelateResult<'tcx, ty::Const<'tcx>> { - self.infcx.super_combine_consts(self, a, b) + super_combine_consts(self.infcx, self, a, b) } fn binders( diff --git a/compiler/rustc_type_ir/src/relate/combine.rs b/compiler/rustc_type_ir/src/relate/combine.rs index 9dfcde609c71e..60a953801a479 100644 --- a/compiler/rustc_type_ir/src/relate/combine.rs +++ b/compiler/rustc_type_ir/src/relate/combine.rs @@ -39,217 +39,208 @@ where fn register_alias_relate_predicate(&mut self, a: I::Ty, b: I::Ty); } -pub trait InferCtxtCombineExt: InferCtxtLike { - fn super_combine_tys(&self, relation: &mut R, a: I::Ty, b: I::Ty) -> RelateResult - where - R: PredicateEmittingRelation; - - fn super_combine_consts( - &self, - relation: &mut R, - a: I::Const, - b: I::Const, - ) -> RelateResult - where - R: PredicateEmittingRelation; -} - -impl> InferCtxtCombineExt for Infcx { - fn super_combine_tys(&self, relation: &mut R, a: I::Ty, b: I::Ty) -> RelateResult - where - R: PredicateEmittingRelation, - { - debug!("super_combine_tys::<{}>({:?}, {:?})", std::any::type_name::(), a, b); - debug_assert!(!a.has_escaping_bound_vars()); - debug_assert!(!b.has_escaping_bound_vars()); - - match (a.kind(), b.kind()) { - (ty::Error(e), _) | (_, ty::Error(e)) => { - self.set_tainted_by_errors(e); - return Ok(Ty::new_error(self.cx(), e)); - } +pub fn super_combine_tys( + infcx: &Infcx, + relation: &mut R, + a: I::Ty, + b: I::Ty, +) -> RelateResult +where + Infcx: InferCtxtLike, + I: Interner, + R: PredicateEmittingRelation, +{ + debug!("super_combine_tys::<{}>({:?}, {:?})", std::any::type_name::(), a, b); + debug_assert!(!a.has_escaping_bound_vars()); + debug_assert!(!b.has_escaping_bound_vars()); + + match (a.kind(), b.kind()) { + (ty::Error(e), _) | (_, ty::Error(e)) => { + infcx.set_tainted_by_errors(e); + return Ok(Ty::new_error(infcx.cx(), e)); + } - // Relate integral variables to other types - (ty::Infer(ty::IntVar(a_id)), ty::Infer(ty::IntVar(b_id))) => { - self.equate_int_vids_raw(a_id, b_id); - Ok(a) - } - (ty::Infer(ty::IntVar(v_id)), ty::Int(v)) => { - self.instantiate_int_var_raw(v_id, ty::IntVarValue::IntType(v)); - Ok(b) - } - (ty::Int(v), ty::Infer(ty::IntVar(v_id))) => { - self.instantiate_int_var_raw(v_id, ty::IntVarValue::IntType(v)); - Ok(a) - } - (ty::Infer(ty::IntVar(v_id)), ty::Uint(v)) => { - self.instantiate_int_var_raw(v_id, ty::IntVarValue::UintType(v)); - Ok(b) - } - (ty::Uint(v), ty::Infer(ty::IntVar(v_id))) => { - self.instantiate_int_var_raw(v_id, ty::IntVarValue::UintType(v)); - Ok(a) - } + // Relate integral variables to other types + (ty::Infer(ty::IntVar(a_id)), ty::Infer(ty::IntVar(b_id))) => { + infcx.equate_int_vids_raw(a_id, b_id); + Ok(a) + } + (ty::Infer(ty::IntVar(v_id)), ty::Int(v)) => { + infcx.instantiate_int_var_raw(v_id, ty::IntVarValue::IntType(v)); + Ok(b) + } + (ty::Int(v), ty::Infer(ty::IntVar(v_id))) => { + infcx.instantiate_int_var_raw(v_id, ty::IntVarValue::IntType(v)); + Ok(a) + } + (ty::Infer(ty::IntVar(v_id)), ty::Uint(v)) => { + infcx.instantiate_int_var_raw(v_id, ty::IntVarValue::UintType(v)); + Ok(b) + } + (ty::Uint(v), ty::Infer(ty::IntVar(v_id))) => { + infcx.instantiate_int_var_raw(v_id, ty::IntVarValue::UintType(v)); + Ok(a) + } - // Relate floating-point variables to other types - (ty::Infer(ty::FloatVar(a_id)), ty::Infer(ty::FloatVar(b_id))) => { - self.equate_float_vids_raw(a_id, b_id); - Ok(a) - } - (ty::Infer(ty::FloatVar(v_id)), ty::Float(v)) => { - self.instantiate_float_var_raw(v_id, ty::FloatVarValue::Known(v)); - Ok(b) - } - (ty::Float(v), ty::Infer(ty::FloatVar(v_id))) => { - self.instantiate_float_var_raw(v_id, ty::FloatVarValue::Known(v)); - Ok(a) - } + // Relate floating-point variables to other types + (ty::Infer(ty::FloatVar(a_id)), ty::Infer(ty::FloatVar(b_id))) => { + infcx.equate_float_vids_raw(a_id, b_id); + Ok(a) + } + (ty::Infer(ty::FloatVar(v_id)), ty::Float(v)) => { + infcx.instantiate_float_var_raw(v_id, ty::FloatVarValue::Known(v)); + Ok(b) + } + (ty::Float(v), ty::Infer(ty::FloatVar(v_id))) => { + infcx.instantiate_float_var_raw(v_id, ty::FloatVarValue::Known(v)); + Ok(a) + } - // We don't expect `TyVar` or `Fresh*` vars at this point with lazy norm. - (ty::Alias(..), ty::Infer(ty::TyVar(_))) | (ty::Infer(ty::TyVar(_)), ty::Alias(..)) - if self.next_trait_solver() => - { - panic!( - "We do not expect to encounter `TyVar` this late in combine \ + // We don't expect `TyVar` or `Fresh*` vars at this point with lazy norm. + (ty::Alias(..), ty::Infer(ty::TyVar(_))) | (ty::Infer(ty::TyVar(_)), ty::Alias(..)) + if infcx.next_trait_solver() => + { + panic!( + "We do not expect to encounter `TyVar` this late in combine \ -- they should have been handled earlier" - ) - } - (_, ty::Infer(ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_))) - | (ty::Infer(ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)), _) - if self.next_trait_solver() => - { - panic!("We do not expect to encounter `Fresh` variables in the new solver") - } + ) + } + (_, ty::Infer(ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_))) + | (ty::Infer(ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)), _) + if infcx.next_trait_solver() => + { + panic!("We do not expect to encounter `Fresh` variables in the new solver") + } - (_, ty::Alias(..)) | (ty::Alias(..), _) if self.next_trait_solver() => { - match relation.structurally_relate_aliases() { - StructurallyRelateAliases::Yes => structurally_relate_tys(relation, a, b), - StructurallyRelateAliases::No => { - relation.register_alias_relate_predicate(a, b); - Ok(a) - } + (_, ty::Alias(..)) | (ty::Alias(..), _) if infcx.next_trait_solver() => { + match relation.structurally_relate_aliases() { + StructurallyRelateAliases::Yes => structurally_relate_tys(relation, a, b), + StructurallyRelateAliases::No => { + relation.register_alias_relate_predicate(a, b); + Ok(a) } } + } - // All other cases of inference are errors - (ty::Infer(_), _) | (_, ty::Infer(_)) => { - Err(TypeError::Sorts(ExpectedFound::new(true, a, b))) - } + // All other cases of inference are errors + (ty::Infer(_), _) | (_, ty::Infer(_)) => { + Err(TypeError::Sorts(ExpectedFound::new(true, a, b))) + } - (ty::Alias(ty::Opaque, _), _) | (_, ty::Alias(ty::Opaque, _)) => { - match self.solver_mode() { - SolverMode::Normal => { - assert!(!self.next_trait_solver()); - structurally_relate_tys(relation, a, b) - } - // During coherence, opaque types should be treated as *possibly* - // equal to any other type (except for possibly itself). This is an - // extremely heavy hammer, but can be relaxed in a forwards-compatible - // way later. - SolverMode::Coherence => { - relation - .register_predicates([ty::Binder::dummy(ty::PredicateKind::Ambiguous)]); - Ok(a) - } + (ty::Alias(ty::Opaque, _), _) | (_, ty::Alias(ty::Opaque, _)) => { + match infcx.solver_mode() { + SolverMode::Normal => { + assert!(!infcx.next_trait_solver()); + structurally_relate_tys(relation, a, b) + } + // During coherence, opaque types should be treated as *possibly* + // equal to any other type (except for possibly itinfcx). This is an + // extremely heavy hammer, but can be relaxed in a forwards-compatible + // way later. + SolverMode::Coherence => { + relation.register_predicates([ty::Binder::dummy(ty::PredicateKind::Ambiguous)]); + Ok(a) } } - - _ => structurally_relate_tys(relation, a, b), } + + _ => structurally_relate_tys(relation, a, b), } +} - fn super_combine_consts( - &self, - relation: &mut R, - a: I::Const, - b: I::Const, - ) -> RelateResult - where - R: PredicateEmittingRelation, - { - debug!("super_combine_consts::<{}>({:?}, {:?})", std::any::type_name::(), a, b); - debug_assert!(!a.has_escaping_bound_vars()); - debug_assert!(!b.has_escaping_bound_vars()); - - if a == b { - return Ok(a); - } - - let a = self.shallow_resolve_const(a); - let b = self.shallow_resolve_const(b); - - match (a.kind(), b.kind()) { - ( - ty::ConstKind::Infer(ty::InferConst::Var(a_vid)), - ty::ConstKind::Infer(ty::InferConst::Var(b_vid)), - ) => { - self.equate_const_vids_raw(a_vid, b_vid); - Ok(a) - } +pub fn super_combine_consts( + infcx: &Infcx, + relation: &mut R, + a: I::Const, + b: I::Const, +) -> RelateResult +where + Infcx: InferCtxtLike, + I: Interner, + R: PredicateEmittingRelation, +{ + debug!("super_combine_consts::<{}>({:?}, {:?})", std::any::type_name::(), a, b); + debug_assert!(!a.has_escaping_bound_vars()); + debug_assert!(!b.has_escaping_bound_vars()); - ( - ty::ConstKind::Infer(ty::InferConst::EffectVar(a_vid)), - ty::ConstKind::Infer(ty::InferConst::EffectVar(b_vid)), - ) => { - self.equate_effect_vids_raw(a_vid, b_vid); - Ok(a) - } + if a == b { + return Ok(a); + } + + let a = infcx.shallow_resolve_const(a); + let b = infcx.shallow_resolve_const(b); - // All other cases of inference with other variables are errors. - ( - ty::ConstKind::Infer(ty::InferConst::Var(_) | ty::InferConst::EffectVar(_)), - ty::ConstKind::Infer(_), + match (a.kind(), b.kind()) { + ( + ty::ConstKind::Infer(ty::InferConst::Var(a_vid)), + ty::ConstKind::Infer(ty::InferConst::Var(b_vid)), + ) => { + infcx.equate_const_vids_raw(a_vid, b_vid); + Ok(a) + } + + ( + ty::ConstKind::Infer(ty::InferConst::EffectVar(a_vid)), + ty::ConstKind::Infer(ty::InferConst::EffectVar(b_vid)), + ) => { + infcx.equate_effect_vids_raw(a_vid, b_vid); + Ok(a) + } + + // All other cases of inference with other variables are errors. + ( + ty::ConstKind::Infer(ty::InferConst::Var(_) | ty::InferConst::EffectVar(_)), + ty::ConstKind::Infer(_), + ) + | ( + ty::ConstKind::Infer(_), + ty::ConstKind::Infer(ty::InferConst::Var(_) | ty::InferConst::EffectVar(_)), + ) => { + panic!( + "tried to combine ConstKind::Infer/ConstKind::Infer(InferConst::Var): {a:?} and {b:?}" ) - | ( - ty::ConstKind::Infer(_), - ty::ConstKind::Infer(ty::InferConst::Var(_) | ty::InferConst::EffectVar(_)), - ) => { - panic!( - "tried to combine ConstKind::Infer/ConstKind::Infer(InferConst::Var): {a:?} and {b:?}" - ) - } + } - (ty::ConstKind::Infer(ty::InferConst::Var(vid)), _) => { - self.instantiate_const_var_raw(relation, true, vid, b)?; - Ok(b) - } + (ty::ConstKind::Infer(ty::InferConst::Var(vid)), _) => { + infcx.instantiate_const_var_raw(relation, true, vid, b)?; + Ok(b) + } - (_, ty::ConstKind::Infer(ty::InferConst::Var(vid))) => { - self.instantiate_const_var_raw(relation, false, vid, a)?; - Ok(a) - } + (_, ty::ConstKind::Infer(ty::InferConst::Var(vid))) => { + infcx.instantiate_const_var_raw(relation, false, vid, a)?; + Ok(a) + } - (ty::ConstKind::Infer(ty::InferConst::EffectVar(vid)), _) => { - self.instantiate_effect_var_raw(vid, b); - Ok(b) - } + (ty::ConstKind::Infer(ty::InferConst::EffectVar(vid)), _) => { + infcx.instantiate_effect_var_raw(vid, b); + Ok(b) + } - (_, ty::ConstKind::Infer(ty::InferConst::EffectVar(vid))) => { - self.instantiate_effect_var_raw(vid, a); - Ok(a) - } + (_, ty::ConstKind::Infer(ty::InferConst::EffectVar(vid))) => { + infcx.instantiate_effect_var_raw(vid, a); + Ok(a) + } - (ty::ConstKind::Unevaluated(..), _) | (_, ty::ConstKind::Unevaluated(..)) - if self.cx().features().generic_const_exprs() || self.next_trait_solver() => - { - match relation.structurally_relate_aliases() { - StructurallyRelateAliases::No => { - relation.register_predicates([if self.next_trait_solver() { - ty::PredicateKind::AliasRelate( - a.into(), - b.into(), - ty::AliasRelationDirection::Equate, - ) - } else { - ty::PredicateKind::ConstEquate(a, b) - }]); - - Ok(b) - } - StructurallyRelateAliases::Yes => structurally_relate_consts(relation, a, b), + (ty::ConstKind::Unevaluated(..), _) | (_, ty::ConstKind::Unevaluated(..)) + if infcx.cx().features().generic_const_exprs() || infcx.next_trait_solver() => + { + match relation.structurally_relate_aliases() { + StructurallyRelateAliases::No => { + relation.register_predicates([if infcx.next_trait_solver() { + ty::PredicateKind::AliasRelate( + a.into(), + b.into(), + ty::AliasRelationDirection::Equate, + ) + } else { + ty::PredicateKind::ConstEquate(a, b) + }]); + + Ok(b) } + StructurallyRelateAliases::Yes => structurally_relate_consts(relation, a, b), } - _ => structurally_relate_consts(relation, a, b), } + _ => structurally_relate_consts(relation, a, b), } } diff --git a/compiler/rustc_type_ir/src/relate/solver_relating.rs b/compiler/rustc_type_ir/src/relate/solver_relating.rs index edbfaed97095b..ad10ad5af9caf 100644 --- a/compiler/rustc_type_ir/src/relate/solver_relating.rs +++ b/compiler/rustc_type_ir/src/relate/solver_relating.rs @@ -3,7 +3,7 @@ use rustc_type_ir::solve::Goal; use rustc_type_ir::{self as ty, InferCtxtLike, Interner}; use tracing::{debug, instrument}; -use self::combine::{InferCtxtCombineExt, PredicateEmittingRelation}; +use self::combine::{PredicateEmittingRelation, super_combine_consts, super_combine_tys}; use crate::data_structures::DelayedSet; pub trait RelateExt: InferCtxtLike { @@ -228,7 +228,7 @@ where } _ => { - self.infcx.super_combine_tys(self, a, b)?; + super_combine_tys(self.infcx, self, a, b)?; } } @@ -255,7 +255,7 @@ where #[instrument(skip(self), level = "trace")] fn consts(&mut self, a: I::Const, b: I::Const) -> RelateResult { - self.infcx.super_combine_consts(self, a, b) + super_combine_consts(self.infcx, self, a, b) } fn binders( From d6fd45c2e3ee24bedbc1b7643b622ab97f29537f Mon Sep 17 00:00:00 2001 From: lcnr Date: Thu, 10 Oct 2024 09:26:49 +0000 Subject: [PATCH 2093/2194] impossible obligations check fast path --- .../src/solve/eval_ctxt/mod.rs | 72 ++++++++++++++----- .../rustc_next_trait_solver/src/solve/mod.rs | 8 +++ .../src/solve/search_graph.rs | 3 - compiler/rustc_trait_selection/src/solve.rs | 1 + .../src/solve/fulfill.rs | 15 ++-- .../src/traits/coherence.rs | 13 +++- .../rustc_type_ir/src/search_graph/mod.rs | 12 ++-- tests/crashes/124894.rs | 11 --- 8 files changed, 90 insertions(+), 45 deletions(-) delete mode 100644 tests/crashes/124894.rs diff --git a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs index ffa800348f2ce..bc324dcbf51f4 100644 --- a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs @@ -18,8 +18,8 @@ use crate::solve::inspect::{self, ProofTreeBuilder}; use crate::solve::search_graph::SearchGraph; use crate::solve::{ CanonicalInput, CanonicalResponse, Certainty, FIXPOINT_STEP_LIMIT, Goal, GoalEvaluationKind, - GoalSource, NestedNormalizationGoals, NoSolution, PredefinedOpaquesData, QueryResult, - SolverMode, + GoalSource, HasChanged, NestedNormalizationGoals, NoSolution, PredefinedOpaquesData, + QueryResult, SolverMode, }; pub(super) mod canonical; @@ -126,11 +126,31 @@ pub enum GenerateProofTree { } pub trait SolverDelegateEvalExt: SolverDelegate { + /// Evaluates a goal from **outside** of the trait solver. + /// + /// Using this while inside of the solver is wrong as it uses a new + /// search graph which would break cycle detection. fn evaluate_root_goal( &self, goal: Goal::Predicate>, generate_proof_tree: GenerateProofTree, - ) -> (Result<(bool, Certainty), NoSolution>, Option>); + ) -> ( + Result<(HasChanged, Certainty), NoSolution>, + Option>, + ); + + /// Check whether evaluating `goal` with a depth of `root_depth` may + /// succeed. This only returns `false` if the goal is guaranteed to + /// not hold. In case evaluation overflows and fails with ambiguity this + /// returns `true`. + /// + /// This is only intended to be used as a performance optimization + /// in coherence checking. + fn root_goal_may_hold_with_depth( + &self, + root_depth: usize, + goal: Goal::Predicate>, + ) -> bool; // FIXME: This is only exposed because we need to use it in `analyse.rs` // which is not yet uplifted. Once that's done, we should remove this. @@ -139,7 +159,7 @@ pub trait SolverDelegateEvalExt: SolverDelegate { goal: Goal::Predicate>, generate_proof_tree: GenerateProofTree, ) -> ( - Result<(NestedNormalizationGoals, bool, Certainty), NoSolution>, + Result<(NestedNormalizationGoals, HasChanged, Certainty), NoSolution>, Option>, ); } @@ -149,31 +169,41 @@ where D: SolverDelegate, I: Interner, { - /// Evaluates a goal from **outside** of the trait solver. - /// - /// Using this while inside of the solver is wrong as it uses a new - /// search graph which would break cycle detection. #[instrument(level = "debug", skip(self))] fn evaluate_root_goal( &self, goal: Goal, generate_proof_tree: GenerateProofTree, - ) -> (Result<(bool, Certainty), NoSolution>, Option>) { - EvalCtxt::enter_root(self, generate_proof_tree, |ecx| { + ) -> (Result<(HasChanged, Certainty), NoSolution>, Option>) { + EvalCtxt::enter_root(self, self.cx().recursion_limit(), generate_proof_tree, |ecx| { ecx.evaluate_goal(GoalEvaluationKind::Root, GoalSource::Misc, goal) }) } + fn root_goal_may_hold_with_depth( + &self, + root_depth: usize, + goal: Goal::Predicate>, + ) -> bool { + self.probe(|| { + EvalCtxt::enter_root(self, root_depth, GenerateProofTree::No, |ecx| { + ecx.evaluate_goal(GoalEvaluationKind::Root, GoalSource::Misc, goal) + }) + .0 + }) + .is_ok() + } + #[instrument(level = "debug", skip(self))] fn evaluate_root_goal_raw( &self, goal: Goal, generate_proof_tree: GenerateProofTree, ) -> ( - Result<(NestedNormalizationGoals, bool, Certainty), NoSolution>, + Result<(NestedNormalizationGoals, HasChanged, Certainty), NoSolution>, Option>, ) { - EvalCtxt::enter_root(self, generate_proof_tree, |ecx| { + EvalCtxt::enter_root(self, self.cx().recursion_limit(), generate_proof_tree, |ecx| { ecx.evaluate_goal_raw(GoalEvaluationKind::Root, GoalSource::Misc, goal) }) } @@ -197,10 +227,11 @@ where /// over using this manually (such as [`SolverDelegateEvalExt::evaluate_root_goal`]). pub(super) fn enter_root( delegate: &D, + root_depth: usize, generate_proof_tree: GenerateProofTree, f: impl FnOnce(&mut EvalCtxt<'_, D>) -> R, ) -> (R, Option>) { - let mut search_graph = SearchGraph::new(delegate.solver_mode()); + let mut search_graph = SearchGraph::new(delegate.solver_mode(), root_depth); let mut ecx = EvalCtxt { delegate, @@ -339,7 +370,7 @@ where goal_evaluation_kind: GoalEvaluationKind, source: GoalSource, goal: Goal, - ) -> Result<(bool, Certainty), NoSolution> { + ) -> Result<(HasChanged, Certainty), NoSolution> { let (normalization_nested_goals, has_changed, certainty) = self.evaluate_goal_raw(goal_evaluation_kind, source, goal)?; assert!(normalization_nested_goals.is_empty()); @@ -360,7 +391,7 @@ where goal_evaluation_kind: GoalEvaluationKind, _source: GoalSource, goal: Goal, - ) -> Result<(NestedNormalizationGoals, bool, Certainty), NoSolution> { + ) -> Result<(NestedNormalizationGoals, HasChanged, Certainty), NoSolution> { let (orig_values, canonical_goal) = self.canonicalize_goal(goal); let mut goal_evaluation = self.inspect.new_goal_evaluation(goal, &orig_values, goal_evaluation_kind); @@ -378,8 +409,13 @@ where Ok(response) => response, }; - let has_changed = !response.value.var_values.is_identity_modulo_regions() - || !response.value.external_constraints.opaque_types.is_empty(); + let has_changed = if !response.value.var_values.is_identity_modulo_regions() + || !response.value.external_constraints.opaque_types.is_empty() + { + HasChanged::Yes + } else { + HasChanged::No + }; let (normalization_nested_goals, certainty) = self.instantiate_and_apply_query_response(goal.param_env, orig_values, response); @@ -552,7 +588,7 @@ where for (source, goal) in goals.goals { let (has_changed, certainty) = self.evaluate_goal(GoalEvaluationKind::Nested, source, goal)?; - if has_changed { + if has_changed == HasChanged::Yes { unchanged_certainty = None; } diff --git a/compiler/rustc_next_trait_solver/src/solve/mod.rs b/compiler/rustc_next_trait_solver/src/solve/mod.rs index 309ab7f28d154..97f7c71f3fccc 100644 --- a/compiler/rustc_next_trait_solver/src/solve/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/mod.rs @@ -48,6 +48,14 @@ enum GoalEvaluationKind { Nested, } +/// Whether evaluating this goal ended up changing the +/// inference state. +#[derive(PartialEq, Eq, Debug, Hash, Clone, Copy)] +pub enum HasChanged { + Yes, + No, +} + // FIXME(trait-system-refactor-initiative#117): we don't detect whether a response // ended up pulling down any universes. fn has_no_inference_or_external_constraints( diff --git a/compiler/rustc_next_trait_solver/src/solve/search_graph.rs b/compiler/rustc_next_trait_solver/src/solve/search_graph.rs index e47cc03f5adf9..0e3f179b0c846 100644 --- a/compiler/rustc_next_trait_solver/src/solve/search_graph.rs +++ b/compiler/rustc_next_trait_solver/src/solve/search_graph.rs @@ -40,9 +40,6 @@ where } const DIVIDE_AVAILABLE_DEPTH_ON_OVERFLOW: usize = 4; - fn recursion_limit(cx: I) -> usize { - cx.recursion_limit() - } fn initial_provisional_result( cx: I, diff --git a/compiler/rustc_trait_selection/src/solve.rs b/compiler/rustc_trait_selection/src/solve.rs index e47f5389cd180..d425ab50ae0fd 100644 --- a/compiler/rustc_trait_selection/src/solve.rs +++ b/compiler/rustc_trait_selection/src/solve.rs @@ -6,6 +6,7 @@ pub mod inspect; mod normalize; mod select; +pub(crate) use delegate::SolverDelegate; pub use fulfill::{FulfillmentCtxt, NextSolverError}; pub(crate) use normalize::deeply_normalize_for_diagnostics; pub use normalize::{deeply_normalize, deeply_normalize_with_skipped_universes}; diff --git a/compiler/rustc_trait_selection/src/solve/fulfill.rs b/compiler/rustc_trait_selection/src/solve/fulfill.rs index c6e3ba3c95735..081d7a6a769a1 100644 --- a/compiler/rustc_trait_selection/src/solve/fulfill.rs +++ b/compiler/rustc_trait_selection/src/solve/fulfill.rs @@ -12,7 +12,7 @@ use rustc_infer::traits::{ use rustc_middle::bug; use rustc_middle::ty::error::{ExpectedFound, TypeError}; use rustc_middle::ty::{self, TyCtxt}; -use rustc_next_trait_solver::solve::{GenerateProofTree, SolverDelegateEvalExt as _}; +use rustc_next_trait_solver::solve::{GenerateProofTree, HasChanged, SolverDelegateEvalExt as _}; use tracing::instrument; use super::Certainty; @@ -86,10 +86,7 @@ impl<'tcx> ObligationStorage<'tcx> { let result = <&SolverDelegate<'tcx>>::from(infcx) .evaluate_root_goal(goal, GenerateProofTree::No) .0; - match result { - Ok((has_changed, _)) => has_changed, - _ => false, - } + matches!(result, Ok((HasChanged::Yes, _))) })); }) } @@ -113,7 +110,7 @@ impl<'tcx, E: 'tcx> FulfillmentCtxt<'tcx, E> { &self, infcx: &InferCtxt<'tcx>, obligation: &PredicateObligation<'tcx>, - result: &Result<(bool, Certainty), NoSolution>, + result: &Result<(HasChanged, Certainty), NoSolution>, ) { if let Some(inspector) = infcx.obligation_inspector.get() { let result = match result { @@ -181,7 +178,11 @@ where continue; } }; - has_changed |= changed; + + if changed == HasChanged::Yes { + has_changed = true; + } + match certainty { Certainty::Yes => {} Certainty::Maybe(_) => self.obligations.register(obligation), diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs index 27d2a3c15b9ac..b29e41beab551 100644 --- a/compiler/rustc_trait_selection/src/traits/coherence.rs +++ b/compiler/rustc_trait_selection/src/traits/coherence.rs @@ -19,6 +19,7 @@ use rustc_middle::ty::fast_reject::DeepRejectCtxt; use rustc_middle::ty::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor}; use rustc_middle::ty::{self, Ty, TyCtxt}; pub use rustc_next_trait_solver::coherence::*; +use rustc_next_trait_solver::solve::SolverDelegateEvalExt; use rustc_span::symbol::sym; use rustc_span::{DUMMY_SP, Span}; use tracing::{debug, instrument, warn}; @@ -28,7 +29,7 @@ use crate::error_reporting::traits::suggest_new_overflow_limit; use crate::infer::InferOk; use crate::infer::outlives::env::OutlivesEnvironment; use crate::solve::inspect::{InspectGoal, ProofTreeInferCtxtExt, ProofTreeVisitor}; -use crate::solve::{deeply_normalize_for_diagnostics, inspect}; +use crate::solve::{SolverDelegate, deeply_normalize_for_diagnostics, inspect}; use crate::traits::query::evaluate_obligation::InferCtxtExt; use crate::traits::select::IntercrateAmbiguityCause; use crate::traits::{ @@ -333,6 +334,16 @@ fn impl_intersection_has_impossible_obligation<'a, 'cx, 'tcx>( let infcx = selcx.infcx; if infcx.next_trait_solver() { + // A fast path optimization, try evaluating all goals with + // a very low recursion depth and bail if any of them don't + // hold. + if !obligations.iter().all(|o| { + <&SolverDelegate<'tcx>>::from(infcx) + .root_goal_may_hold_with_depth(8, Goal::new(infcx.tcx, o.param_env, o.predicate)) + }) { + return IntersectionHasImpossibleObligations::Yes; + } + let ocx = ObligationCtxt::new_with_diagnostics(infcx); ocx.register_obligations(obligations.iter().cloned()); let errors_and_ambiguities = ocx.select_all_or_error(); diff --git a/compiler/rustc_type_ir/src/search_graph/mod.rs b/compiler/rustc_type_ir/src/search_graph/mod.rs index ac4d0795a92e8..f4fb03562de9c 100644 --- a/compiler/rustc_type_ir/src/search_graph/mod.rs +++ b/compiler/rustc_type_ir/src/search_graph/mod.rs @@ -81,7 +81,6 @@ pub trait Delegate { fn inspect_is_noop(inspect: &mut Self::ProofTreeBuilder) -> bool; const DIVIDE_AVAILABLE_DEPTH_ON_OVERFLOW: usize; - fn recursion_limit(cx: Self::Cx) -> usize; fn initial_provisional_result( cx: Self::Cx, @@ -156,7 +155,7 @@ impl AvailableDepth { /// the remaining depth of all nested goals to prevent hangs /// in case there is exponential blowup. fn allowed_depth_for_nested( - cx: D::Cx, + root_depth: AvailableDepth, stack: &IndexVec>, ) -> Option { if let Some(last) = stack.raw.last() { @@ -170,7 +169,7 @@ impl AvailableDepth { AvailableDepth(last.available_depth.0 - 1) }) } else { - Some(AvailableDepth(D::recursion_limit(cx))) + Some(root_depth) } } @@ -360,6 +359,7 @@ struct ProvisionalCacheEntry { pub struct SearchGraph, X: Cx = ::Cx> { mode: SolverMode, + root_depth: AvailableDepth, /// The stack of goals currently being computed. /// /// An element is *deeper* in the stack if its index is *lower*. @@ -374,9 +374,10 @@ pub struct SearchGraph, X: Cx = ::Cx> { } impl, X: Cx> SearchGraph { - pub fn new(mode: SolverMode) -> SearchGraph { + pub fn new(mode: SolverMode, root_depth: usize) -> SearchGraph { Self { mode, + root_depth: AvailableDepth(root_depth), stack: Default::default(), provisional_cache: Default::default(), _marker: PhantomData, @@ -460,7 +461,8 @@ impl, X: Cx> SearchGraph { inspect: &mut D::ProofTreeBuilder, mut evaluate_goal: impl FnMut(&mut Self, &mut D::ProofTreeBuilder) -> X::Result, ) -> X::Result { - let Some(available_depth) = AvailableDepth::allowed_depth_for_nested::(cx, &self.stack) + let Some(available_depth) = + AvailableDepth::allowed_depth_for_nested::(self.root_depth, &self.stack) else { return self.handle_overflow(cx, input, inspect); }; diff --git a/tests/crashes/124894.rs b/tests/crashes/124894.rs deleted file mode 100644 index 230cf4a89c151..0000000000000 --- a/tests/crashes/124894.rs +++ /dev/null @@ -1,11 +0,0 @@ -//@ known-bug: rust-lang/rust#124894 -//@ compile-flags: -Znext-solver=coherence - -#![feature(generic_const_exprs)] - -pub trait IsTrue {} -impl IsZST for T where (): IsTrue<{ std::mem::size_of::() == 0 }> {} - -pub trait IsZST {} - -impl IsZST for IsZST {} From 2900c58a02c48da60a2d2d45613acf25164efa2b Mon Sep 17 00:00:00 2001 From: Kajetan Puchalski Date: Thu, 19 Sep 2024 08:28:09 +0000 Subject: [PATCH 2094/2194] stdarch: Bump stdarch submodule --- library/stdarch | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/stdarch b/library/stdarch index ace72223a0e32..c881fe3231b39 160000 --- a/library/stdarch +++ b/library/stdarch @@ -1 +1 @@ -Subproject commit ace72223a0e321c1b0a37b5862aa756fe8ab5111 +Subproject commit c881fe3231b3947a4766aa15a26a93022fbb8723 From 335f67b6527cbeb576151dab1dadec161eaede45 Mon Sep 17 00:00:00 2001 From: Kajetan Puchalski Date: Tue, 3 Sep 2024 13:51:54 +0100 Subject: [PATCH 2095/2194] rustc_target: Add sme-b16b16 as an explicit aarch64 target feature LLVM 20 split out what used to be called b16b16 and correspond to aarch64 FEAT_SVE_B16B16 into sve-b16b16 and sme-b16b16. Add sme-b16b16 as an explicit feature and update the codegen accordingly. --- compiler/rustc_codegen_llvm/src/llvm_util.rs | 4 +++- compiler/rustc_target/src/target_features.rs | 4 +++- library/std/tests/run-time-detect.rs | 1 + tests/ui/check-cfg/mix.stderr | 2 +- tests/ui/check-cfg/well-known-values.stderr | 2 +- 5 files changed, 9 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/llvm_util.rs b/compiler/rustc_codegen_llvm/src/llvm_util.rs index bd847cd0068e5..8290e1a95441b 100644 --- a/compiler/rustc_codegen_llvm/src/llvm_util.rs +++ b/compiler/rustc_codegen_llvm/src/llvm_util.rs @@ -247,7 +247,9 @@ pub(crate) fn to_llvm_features<'a>(sess: &Session, s: &'a str) -> Option Some(LLVMFeature::new("perfmon")), ("aarch64", "paca") => Some(LLVMFeature::new("pauth")), ("aarch64", "pacg") => Some(LLVMFeature::new("pauth")), - ("aarch64", "sve-b16b16") => Some(LLVMFeature::new("b16b16")), + // Before LLVM 20 those two features were packaged together as b16b16 + ("aarch64", "sve-b16b16") if get_version().0 < 20 => Some(LLVMFeature::new("b16b16")), + ("aarch64", "sme-b16b16") if get_version().0 < 20 => Some(LLVMFeature::new("b16b16")), ("aarch64", "flagm2") => Some(LLVMFeature::new("altnzcv")), // Rust ties fp and neon together. ("aarch64", "neon") => { diff --git a/compiler/rustc_target/src/target_features.rs b/compiler/rustc_target/src/target_features.rs index 0a98b363b1a6e..e92366d5c5c3f 100644 --- a/compiler/rustc_target/src/target_features.rs +++ b/compiler/rustc_target/src/target_features.rs @@ -191,6 +191,8 @@ const AARCH64_ALLOWED_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ ("sm4", Stable, &["neon"]), // FEAT_SME ("sme", Unstable(sym::aarch64_unstable_target_feature), &["bf16"]), + // FEAT_SME_B16B16 + ("sme-b16b16", Unstable(sym::aarch64_unstable_target_feature), &["bf16", "sme2", "sve-b16b16"]), // FEAT_SME_F16F16 ("sme-f16f16", Unstable(sym::aarch64_unstable_target_feature), &["sme2"]), // FEAT_SME_F64F64 @@ -227,7 +229,7 @@ const AARCH64_ALLOWED_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ // // "For backwards compatibility, Neon and VFP are required in the latest architectures." ("sve", Stable, &["neon"]), - // FEAT_SVE_B16B16 (SVE or SME Instructions) + // FEAT_SVE_B16B16 (SVE or SME Z-targeting instructions) ("sve-b16b16", Unstable(sym::aarch64_unstable_target_feature), &["bf16"]), // FEAT_SVE2 ("sve2", Stable, &["sve"]), diff --git a/library/std/tests/run-time-detect.rs b/library/std/tests/run-time-detect.rs index dcd5cd7f6b9c7..dd14c0266aa4d 100644 --- a/library/std/tests/run-time-detect.rs +++ b/library/std/tests/run-time-detect.rs @@ -82,6 +82,7 @@ fn aarch64_linux() { println!("sha2: {}", is_aarch64_feature_detected!("sha2")); println!("sha3: {}", is_aarch64_feature_detected!("sha3")); println!("sm4: {}", is_aarch64_feature_detected!("sm4")); + println!("sme-b16b16: {}", is_aarch64_feature_detected!("sme-b16b16")); println!("sme-f16f16: {}", is_aarch64_feature_detected!("sme-f16f16")); println!("sme-f64f64: {}", is_aarch64_feature_detected!("sme-f64f64")); println!("sme-f8f16: {}", is_aarch64_feature_detected!("sme-f8f16")); diff --git a/tests/ui/check-cfg/mix.stderr b/tests/ui/check-cfg/mix.stderr index 7726c2d52f571..c21016e929093 100644 --- a/tests/ui/check-cfg/mix.stderr +++ b/tests/ui/check-cfg/mix.stderr @@ -251,7 +251,7 @@ warning: unexpected `cfg` condition value: `zebra` LL | cfg!(target_feature = "zebra"); | ^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: expected values for `target_feature` are: `10e60`, `2e3`, `3e3r1`, `3e3r2`, `3e3r3`, `3e7`, `7e10`, `a`, `aclass`, `adx`, `aes`, `altivec`, `alu32`, `amx-bf16`, `amx-complex`, `amx-fp16`, `amx-int8`, `amx-tile`, `atomics`, `avx`, `avx2`, `avx512bf16`, `avx512bitalg`, `avx512bw`, `avx512cd`, `avx512dq`, `avx512f`, `avx512fp16`, `avx512ifma`, `avx512vbmi`, `avx512vbmi2`, `avx512vl`, `avx512vnni`, `avx512vp2intersect`, and `avx512vpopcntdq` and 244 more + = note: expected values for `target_feature` are: `10e60`, `2e3`, `3e3r1`, `3e3r2`, `3e3r3`, `3e7`, `7e10`, `a`, `aclass`, `adx`, `aes`, `altivec`, `alu32`, `amx-bf16`, `amx-complex`, `amx-fp16`, `amx-int8`, `amx-tile`, `atomics`, `avx`, `avx2`, `avx512bf16`, `avx512bitalg`, `avx512bw`, `avx512cd`, `avx512dq`, `avx512f`, `avx512fp16`, `avx512ifma`, `avx512vbmi`, `avx512vbmi2`, `avx512vl`, `avx512vnni`, `avx512vp2intersect`, and `avx512vpopcntdq` and 245 more = note: see for more information about checking conditional configuration warning: 27 warnings emitted diff --git a/tests/ui/check-cfg/well-known-values.stderr b/tests/ui/check-cfg/well-known-values.stderr index c6d403104ea6b..da790bbd52859 100644 --- a/tests/ui/check-cfg/well-known-values.stderr +++ b/tests/ui/check-cfg/well-known-values.stderr @@ -174,7 +174,7 @@ warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` LL | target_feature = "_UNEXPECTED_VALUE", | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: expected values for `target_feature` are: `10e60`, `2e3`, `3e3r1`, `3e3r2`, `3e3r3`, `3e7`, `7e10`, `a`, `aclass`, `adx`, `aes`, `altivec`, `alu32`, `amx-bf16`, `amx-complex`, `amx-fp16`, `amx-int8`, `amx-tile`, `atomics`, `avx`, `avx2`, `avx512bf16`, `avx512bitalg`, `avx512bw`, `avx512cd`, `avx512dq`, `avx512f`, `avx512fp16`, `avx512ifma`, `avx512vbmi`, `avx512vbmi2`, `avx512vl`, `avx512vnni`, `avx512vp2intersect`, `avx512vpopcntdq`, `avxifma`, `avxneconvert`, `avxvnni`, `avxvnniint16`, `avxvnniint8`, `backchain`, `bf16`, `bmi1`, `bmi2`, `bti`, `bulk-memory`, `c`, `cache`, `cmpxchg16b`, `crc`, `crt-static`, `cssc`, `d`, `d32`, `dit`, `doloop`, `dotprod`, `dpb`, `dpb2`, `dsp`, `dsp1e2`, `dspe60`, `e`, `e1`, `e2`, `ecv`, `edsp`, `elrw`, `ermsb`, `exception-handling`, `extended-const`, `f`, `f16c`, `f32mm`, `f64mm`, `faminmax`, `fcma`, `fdivdu`, `fhm`, `flagm`, `flagm2`, `float1e2`, `float1e3`, `float3e4`, `float7e60`, `floate1`, `fma`, `fp-armv8`, `fp16`, `fp64`, `fp8`, `fp8dot2`, `fp8dot4`, `fp8fma`, `fpuv2_df`, `fpuv2_sf`, `fpuv3_df`, `fpuv3_hf`, `fpuv3_hi`, `fpuv3_sf`, `frecipe`, `frintts`, `fxsr`, `gfni`, `hard-float`, `hard-float-abi`, `hard-tp`, `hbc`, `high-registers`, `hvx`, `hvx-length128b`, `hwdiv`, `i8mm`, `jsconv`, `lahfsahf`, `lasx`, `lbt`, `lor`, `lse`, `lse128`, `lse2`, `lsx`, `lut`, `lvz`, `lzcnt`, `m`, `mclass`, `mops`, `movbe`, `mp`, `mp1e2`, `msa`, `mte`, `multivalue`, `mutable-globals`, `neon`, `nontrapping-fptoint`, `nvic`, `paca`, `pacg`, `pan`, `partword-atomics`, `pclmulqdq`, `pmuv3`, `popcnt`, `power10-vector`, `power8-altivec`, `power8-vector`, `power9-altivec`, `power9-vector`, `prfchw`, `quadword-atomics`, `rand`, `ras`, `rclass`, `rcpc`, `rcpc2`, `rcpc3`, `rdm`, `rdrand`, `rdseed`, `reference-types`, `relax`, `relaxed-simd`, `rtm`, `sb`, `sha`, `sha2`, `sha3`, `sha512`, `sign-ext`, `simd128`, `sm3`, `sm4`, `sme`, `sme-f16f16`, `sme-f64f64`, `sme-f8f16`, `sme-f8f32`, `sme-fa64`, `sme-i16i64`, `sme-lutv2`, `sme2`, `sme2p1`, `spe`, `ssbs`, `sse`, `sse2`, `sse3`, `sse4.1`, `sse4.2`, `sse4a`, `ssse3`, `ssve-fp8dot2`, `ssve-fp8dot4`, `ssve-fp8fma`, `sve`, `sve-b16b16`, `sve2`, `sve2-aes`, `sve2-bitperm`, `sve2-sha3`, `sve2-sm4`, `sve2p1`, `tbm`, `thumb-mode`, `thumb2`, `tme`, `trust`, `trustzone`, `ual`, `unaligned-scalar-mem`, `v`, `v5te`, `v6`, `v6k`, `v6t2`, `v7`, `v8`, `v8.1a`, `v8.2a`, `v8.3a`, `v8.4a`, `v8.5a`, `v8.6a`, `v8.7a`, `v8.8a`, `v8.9a`, `v9.1a`, `v9.2a`, `v9.3a`, `v9.4a`, `v9.5a`, `v9a`, `vaes`, `vdsp2e60f`, `vdspv1`, `vdspv2`, `vector`, `vfp2`, `vfp3`, `vfp4`, `vh`, `virt`, `virtualization`, `vpclmulqdq`, `vsx`, `wfxt`, `xop`, `xsave`, `xsavec`, `xsaveopt`, `xsaves`, `zaamo`, `zabha`, `zalrsc`, `zba`, `zbb`, `zbc`, `zbkb`, `zbkc`, `zbkx`, `zbs`, `zdinx`, `zfh`, `zfhmin`, `zfinx`, `zhinx`, `zhinxmin`, `zk`, `zkn`, `zknd`, `zkne`, `zknh`, `zkr`, `zks`, `zksed`, `zksh`, and `zkt` + = note: expected values for `target_feature` are: `10e60`, `2e3`, `3e3r1`, `3e3r2`, `3e3r3`, `3e7`, `7e10`, `a`, `aclass`, `adx`, `aes`, `altivec`, `alu32`, `amx-bf16`, `amx-complex`, `amx-fp16`, `amx-int8`, `amx-tile`, `atomics`, `avx`, `avx2`, `avx512bf16`, `avx512bitalg`, `avx512bw`, `avx512cd`, `avx512dq`, `avx512f`, `avx512fp16`, `avx512ifma`, `avx512vbmi`, `avx512vbmi2`, `avx512vl`, `avx512vnni`, `avx512vp2intersect`, `avx512vpopcntdq`, `avxifma`, `avxneconvert`, `avxvnni`, `avxvnniint16`, `avxvnniint8`, `backchain`, `bf16`, `bmi1`, `bmi2`, `bti`, `bulk-memory`, `c`, `cache`, `cmpxchg16b`, `crc`, `crt-static`, `cssc`, `d`, `d32`, `dit`, `doloop`, `dotprod`, `dpb`, `dpb2`, `dsp`, `dsp1e2`, `dspe60`, `e`, `e1`, `e2`, `ecv`, `edsp`, `elrw`, `ermsb`, `exception-handling`, `extended-const`, `f`, `f16c`, `f32mm`, `f64mm`, `faminmax`, `fcma`, `fdivdu`, `fhm`, `flagm`, `flagm2`, `float1e2`, `float1e3`, `float3e4`, `float7e60`, `floate1`, `fma`, `fp-armv8`, `fp16`, `fp64`, `fp8`, `fp8dot2`, `fp8dot4`, `fp8fma`, `fpuv2_df`, `fpuv2_sf`, `fpuv3_df`, `fpuv3_hf`, `fpuv3_hi`, `fpuv3_sf`, `frecipe`, `frintts`, `fxsr`, `gfni`, `hard-float`, `hard-float-abi`, `hard-tp`, `hbc`, `high-registers`, `hvx`, `hvx-length128b`, `hwdiv`, `i8mm`, `jsconv`, `lahfsahf`, `lasx`, `lbt`, `lor`, `lse`, `lse128`, `lse2`, `lsx`, `lut`, `lvz`, `lzcnt`, `m`, `mclass`, `mops`, `movbe`, `mp`, `mp1e2`, `msa`, `mte`, `multivalue`, `mutable-globals`, `neon`, `nontrapping-fptoint`, `nvic`, `paca`, `pacg`, `pan`, `partword-atomics`, `pclmulqdq`, `pmuv3`, `popcnt`, `power10-vector`, `power8-altivec`, `power8-vector`, `power9-altivec`, `power9-vector`, `prfchw`, `quadword-atomics`, `rand`, `ras`, `rclass`, `rcpc`, `rcpc2`, `rcpc3`, `rdm`, `rdrand`, `rdseed`, `reference-types`, `relax`, `relaxed-simd`, `rtm`, `sb`, `sha`, `sha2`, `sha3`, `sha512`, `sign-ext`, `simd128`, `sm3`, `sm4`, `sme`, `sme-b16b16`, `sme-f16f16`, `sme-f64f64`, `sme-f8f16`, `sme-f8f32`, `sme-fa64`, `sme-i16i64`, `sme-lutv2`, `sme2`, `sme2p1`, `spe`, `ssbs`, `sse`, `sse2`, `sse3`, `sse4.1`, `sse4.2`, `sse4a`, `ssse3`, `ssve-fp8dot2`, `ssve-fp8dot4`, `ssve-fp8fma`, `sve`, `sve-b16b16`, `sve2`, `sve2-aes`, `sve2-bitperm`, `sve2-sha3`, `sve2-sm4`, `sve2p1`, `tbm`, `thumb-mode`, `thumb2`, `tme`, `trust`, `trustzone`, `ual`, `unaligned-scalar-mem`, `v`, `v5te`, `v6`, `v6k`, `v6t2`, `v7`, `v8`, `v8.1a`, `v8.2a`, `v8.3a`, `v8.4a`, `v8.5a`, `v8.6a`, `v8.7a`, `v8.8a`, `v8.9a`, `v9.1a`, `v9.2a`, `v9.3a`, `v9.4a`, `v9.5a`, `v9a`, `vaes`, `vdsp2e60f`, `vdspv1`, `vdspv2`, `vector`, `vfp2`, `vfp3`, `vfp4`, `vh`, `virt`, `virtualization`, `vpclmulqdq`, `vsx`, `wfxt`, `xop`, `xsave`, `xsavec`, `xsaveopt`, `xsaves`, `zaamo`, `zabha`, `zalrsc`, `zba`, `zbb`, `zbc`, `zbkb`, `zbkc`, `zbkx`, `zbs`, `zdinx`, `zfh`, `zfhmin`, `zfinx`, `zhinx`, `zhinxmin`, `zk`, `zkn`, `zknd`, `zkne`, `zknh`, `zkr`, `zks`, `zksed`, `zksh`, and `zkt` = note: see for more information about checking conditional configuration warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` From 57ae34ad3c2d733c8b272ed2c46f8d10a01d9ed7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=AE=B8=E6=9D=B0=E5=8F=8B=20Jieyou=20Xu=20=28Joe=29?= <39484203+jieyouxu@users.noreply.github.com> Date: Thu, 10 Oct 2024 19:02:58 +0800 Subject: [PATCH 2096/2194] Add myself to bootstrap review rotation --- triagebot.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/triagebot.toml b/triagebot.toml index d3e4af9b71899..6c9cdc3223b2c 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -971,6 +971,7 @@ bootstrap = [ "@albertlarsan68", "@onur-ozkan", "@kobzol", + "@jieyouxu", ] infra-ci = [ "@Mark-Simulacrum", From 00f98275990f4673641d5ae787bb4c1d2d4d3f78 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gabriel=20Bj=C3=B8rnager=20Jensen?= Date: Wed, 9 Oct 2024 22:15:38 +0200 Subject: [PATCH 2097/2194] Stabilise 'const_char_encode_utf8'; --- library/core/src/char/methods.rs | 7 +++++-- library/core/src/lib.rs | 1 - 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/library/core/src/char/methods.rs b/library/core/src/char/methods.rs index 7f3c998aaa5bc..6bedb0d0dc4e5 100644 --- a/library/core/src/char/methods.rs +++ b/library/core/src/char/methods.rs @@ -674,8 +674,9 @@ impl char { /// 'ß'.encode_utf8(&mut b); /// ``` #[stable(feature = "unicode_encode_char", since = "1.15.0")] - #[rustc_const_unstable(feature = "const_char_encode_utf8", issue = "130512")] + #[rustc_const_stable(feature = "const_char_encode_utf8", since = "CURRENT_RUSTC_VERSION")] #[inline] + #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] pub const fn encode_utf8(self, dst: &mut [u8]) -> &mut str { // SAFETY: `char` is not a surrogate, so this is valid UTF-8. unsafe { from_utf8_unchecked_mut(encode_utf8_raw(self as u32, dst)) } @@ -1770,9 +1771,11 @@ const fn len_utf16(code: u32) -> usize { /// Panics if the buffer is not large enough. /// A buffer of length four is large enough to encode any `char`. #[unstable(feature = "char_internals", reason = "exposed only for libstd", issue = "none")] -#[rustc_const_unstable(feature = "const_char_encode_utf8", issue = "130512")] +#[rustc_const_stable(feature = "const_char_encode_utf8", since = "CURRENT_RUSTC_VERSION")] #[doc(hidden)] #[inline] +#[rustc_allow_const_fn_unstable(const_eval_select)] +#[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] pub const fn encode_utf8_raw(code: u32, dst: &mut [u8]) -> &mut [u8] { const fn panic_at_const(_code: u32, _len: usize, _dst_len: usize) { // Note that we cannot format in constant expressions. diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index 817d9e3b962e3..ce5a1791f5ed4 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -119,7 +119,6 @@ #![feature(const_bigint_helper_methods)] #![feature(const_black_box)] #![feature(const_char_encode_utf16)] -#![feature(const_char_encode_utf8)] #![feature(const_eval_select)] #![feature(const_exact_div)] #![feature(const_float_classify)] From 203573701a186490db661f52bbf852906d45a2fb Mon Sep 17 00:00:00 2001 From: "Tim (Theemathas) Chirananthavat" Date: Thu, 10 Oct 2024 23:12:03 +0700 Subject: [PATCH 2098/2194] More clearly document Stdin::read_line These are common pitfalls for beginners, so I think it's worth making the subtleties more visible. --- library/std/src/io/stdio.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/library/std/src/io/stdio.rs b/library/std/src/io/stdio.rs index bf242e715bd94..35b38ed783ff2 100644 --- a/library/std/src/io/stdio.rs +++ b/library/std/src/io/stdio.rs @@ -370,7 +370,12 @@ impl Stdin { /// Locks this handle and reads a line of input, appending it to the specified buffer. /// /// For detailed semantics of this method, see the documentation on - /// [`BufRead::read_line`]. + /// [`BufRead::read_line`]. In particular: + /// * Previous content of the buffer will be preserved. To avoid appending + /// to the buffer, you need to [`clear`] it first. + /// * The trailing newline character, if any, is included in the buffer. + /// + /// [`clear`]: String::clear /// /// # Examples /// From b7297ac4407e25f7872cd061246196cd4c8b485b Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sun, 29 Sep 2024 13:08:48 -0400 Subject: [PATCH 2099/2194] Add gate for precise capturing in traits --- compiler/rustc_ast_lowering/src/lib.rs | 19 ++++++++++++++----- compiler/rustc_feature/src/unstable.rs | 2 ++ compiler/rustc_span/src/symbol.rs | 1 + ...eature-gate-precise_capturing_in_traits.rs | 6 ++++++ ...re-gate-precise_capturing_in_traits.stderr | 13 +++++++++++++ .../forgot-to-capture-type.stderr | 3 +++ .../precise-capturing/redundant.rpitit.stderr | 6 ++++++ ...itit-captures-more-method-lifetimes.stderr | 3 +++ .../precise-capturing/rpitit.stderr | 3 +++ .../precise-capturing/self-capture.stderr | 3 +++ 10 files changed, 54 insertions(+), 5 deletions(-) create mode 100644 tests/ui/feature-gates/feature-gate-precise_capturing_in_traits.rs create mode 100644 tests/ui/feature-gates/feature-gate-precise_capturing_in_traits.stderr diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index b26797f42032f..35af4d63cc760 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -1573,11 +1573,20 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // Feature gate for RPITIT + use<..> match origin { rustc_hir::OpaqueTyOrigin::FnReturn { in_trait_or_impl: Some(_), .. } => { - if let Some(span) = bounds.iter().find_map(|bound| match *bound { - ast::GenericBound::Use(_, span) => Some(span), - _ => None, - }) { - self.tcx.dcx().emit_err(errors::NoPreciseCapturesOnRpitit { span }); + if !self.tcx.features().precise_capturing_in_traits + && let Some(span) = bounds.iter().find_map(|bound| match *bound { + ast::GenericBound::Use(_, span) => Some(span), + _ => None, + }) + { + let mut diag = + self.tcx.dcx().create_err(errors::NoPreciseCapturesOnRpitit { span }); + add_feature_diagnostics( + &mut diag, + self.tcx.sess, + sym::precise_capturing_in_traits, + ); + diag.emit(); } } _ => {} diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index 380e36fe40566..19a6960cf4d88 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -565,6 +565,8 @@ declare_features! ( (incomplete, pin_ergonomics, "CURRENT_RUSTC_VERSION", Some(130494)), /// Allows postfix match `expr.match { ... }` (unstable, postfix_match, "1.79.0", Some(121618)), + /// Allows `use<..>` precise capturign on impl Trait in traits. + (unstable, precise_capturing_in_traits, "CURRENT_RUSTC_VERSION", Some(130044)), /// Allows macro attributes on expressions, statements and non-inline modules. (unstable, proc_macro_hygiene, "1.30.0", Some(54727)), /// Makes `&` and `&mut` patterns eat only one layer of references in Rust 2024. diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 1527600e764c0..683f59a89995e 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1479,6 +1479,7 @@ symbols! { powif64, pre_dash_lto: "pre-lto", precise_capturing, + precise_capturing_in_traits, precise_pointer_size_matching, pref_align_of, prefetch_read_data, diff --git a/tests/ui/feature-gates/feature-gate-precise_capturing_in_traits.rs b/tests/ui/feature-gates/feature-gate-precise_capturing_in_traits.rs new file mode 100644 index 0000000000000..308b41dfc68ab --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-precise_capturing_in_traits.rs @@ -0,0 +1,6 @@ +trait Foo { + fn test() -> impl Sized + use; + //~^ ERROR `use<...>` precise capturing syntax is currently not allowed in return-position +} + +fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-precise_capturing_in_traits.stderr b/tests/ui/feature-gates/feature-gate-precise_capturing_in_traits.stderr new file mode 100644 index 0000000000000..b2c6bf61124d9 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-precise_capturing_in_traits.stderr @@ -0,0 +1,13 @@ +error: `use<...>` precise capturing syntax is currently not allowed in return-position `impl Trait` in traits + --> $DIR/feature-gate-precise_capturing_in_traits.rs:2:31 + | +LL | fn test() -> impl Sized + use; + | ^^^^^^^^^ + | + = note: currently, return-position `impl Trait` in traits and trait implementations capture all lifetimes in scope + = note: see issue #130044 for more information + = help: add `#![feature(precise_capturing_in_traits)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error: aborting due to 1 previous error + diff --git a/tests/ui/impl-trait/precise-capturing/forgot-to-capture-type.stderr b/tests/ui/impl-trait/precise-capturing/forgot-to-capture-type.stderr index d9be9d543e450..23d6a3bd11e82 100644 --- a/tests/ui/impl-trait/precise-capturing/forgot-to-capture-type.stderr +++ b/tests/ui/impl-trait/precise-capturing/forgot-to-capture-type.stderr @@ -5,6 +5,9 @@ LL | fn bar() -> impl Sized + use<>; | ^^^^^ | = note: currently, return-position `impl Trait` in traits and trait implementations capture all lifetimes in scope + = note: see issue #130044 for more information + = help: add `#![feature(precise_capturing_in_traits)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error: `impl Trait` must mention all type parameters in scope in `use<...>` --> $DIR/forgot-to-capture-type.rs:1:23 diff --git a/tests/ui/impl-trait/precise-capturing/redundant.rpitit.stderr b/tests/ui/impl-trait/precise-capturing/redundant.rpitit.stderr index 213888356e572..27f8ff92d3e65 100644 --- a/tests/ui/impl-trait/precise-capturing/redundant.rpitit.stderr +++ b/tests/ui/impl-trait/precise-capturing/redundant.rpitit.stderr @@ -5,6 +5,9 @@ LL | fn in_trait() -> impl Sized + use<'a, Self>; | ^^^^^^^^^^^^^ | = note: currently, return-position `impl Trait` in traits and trait implementations capture all lifetimes in scope + = note: see issue #130044 for more information + = help: add `#![feature(precise_capturing_in_traits)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error: `use<...>` precise capturing syntax is currently not allowed in return-position `impl Trait` in traits --> $DIR/redundant.rs:21:35 @@ -13,6 +16,9 @@ LL | fn in_trait() -> impl Sized + use<'a> {} | ^^^^^^^ | = note: currently, return-position `impl Trait` in traits and trait implementations capture all lifetimes in scope + = note: see issue #130044 for more information + = help: add `#![feature(precise_capturing_in_traits)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error: aborting due to 2 previous errors diff --git a/tests/ui/impl-trait/precise-capturing/rpitit-captures-more-method-lifetimes.stderr b/tests/ui/impl-trait/precise-capturing/rpitit-captures-more-method-lifetimes.stderr index b390a23eef414..ffd9646a4038b 100644 --- a/tests/ui/impl-trait/precise-capturing/rpitit-captures-more-method-lifetimes.stderr +++ b/tests/ui/impl-trait/precise-capturing/rpitit-captures-more-method-lifetimes.stderr @@ -5,6 +5,9 @@ LL | fn bar<'tr: 'tr>(&'tr mut self) -> impl Sized + use; | ^^^^^^^^^ | = note: currently, return-position `impl Trait` in traits and trait implementations capture all lifetimes in scope + = note: see issue #130044 for more information + = help: add `#![feature(precise_capturing_in_traits)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error: return type captures more lifetimes than trait definition --> $DIR/rpitit-captures-more-method-lifetimes.rs:11:40 diff --git a/tests/ui/impl-trait/precise-capturing/rpitit.stderr b/tests/ui/impl-trait/precise-capturing/rpitit.stderr index 5a120df9f047a..c162875f327cc 100644 --- a/tests/ui/impl-trait/precise-capturing/rpitit.stderr +++ b/tests/ui/impl-trait/precise-capturing/rpitit.stderr @@ -5,6 +5,9 @@ LL | fn hello() -> impl PartialEq + use; | ^^^^^^^^^ | = note: currently, return-position `impl Trait` in traits and trait implementations capture all lifetimes in scope + = note: see issue #130044 for more information + = help: add `#![feature(precise_capturing_in_traits)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error: `impl Trait` captures lifetime parameter, but it is not mentioned in `use<...>` precise captures list --> $DIR/rpitit.rs:9:19 diff --git a/tests/ui/impl-trait/precise-capturing/self-capture.stderr b/tests/ui/impl-trait/precise-capturing/self-capture.stderr index c1974600f30c5..45ebc429d88a7 100644 --- a/tests/ui/impl-trait/precise-capturing/self-capture.stderr +++ b/tests/ui/impl-trait/precise-capturing/self-capture.stderr @@ -5,6 +5,9 @@ LL | fn bar<'a>() -> impl Sized + use; | ^^^^^^^^^ | = note: currently, return-position `impl Trait` in traits and trait implementations capture all lifetimes in scope + = note: see issue #130044 for more information + = help: add `#![feature(precise_capturing_in_traits)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error: aborting due to 1 previous error From a7dc98733da8b84cfc21a538541a41803c4529a0 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sun, 29 Sep 2024 13:41:13 -0400 Subject: [PATCH 2100/2194] Add variances to RPITITs --- .../rustc_hir_analysis/src/variance/mod.rs | 49 +++++++++++++-- compiler/rustc_metadata/src/rmeta/encoder.rs | 5 +- compiler/rustc_middle/src/ty/context.rs | 4 ++ compiler/rustc_type_ir/src/interner.rs | 2 + compiler/rustc_type_ir/src/relate.rs | 10 ++++ tests/ui/impl-trait/in-trait/variance.rs | 23 ++++---- tests/ui/impl-trait/in-trait/variance.stderr | 34 +++++++---- .../forgot-to-capture-type.rs | 3 +- .../forgot-to-capture-type.stderr | 17 +----- .../precise-capturing/redundant.normal.stderr | 20 ------- .../precise-capturing/redundant.rpitit.stderr | 24 -------- .../impl-trait/precise-capturing/redundant.rs | 15 +++-- .../precise-capturing/redundant.stderr | 36 +++++++++++ .../rpitit-captures-more-method-lifetimes.rs | 5 +- ...itit-captures-more-method-lifetimes.stderr | 23 ++------ .../rpitit-impl-captures-too-much.rs | 14 +++++ .../rpitit-impl-captures-too-much.stderr | 17 ++++++ .../ui/impl-trait/precise-capturing/rpitit.rs | 31 +++++++--- .../precise-capturing/rpitit.stderr | 59 ++++++++----------- .../precise-capturing/self-capture.rs | 5 +- .../precise-capturing/self-capture.stderr | 13 ---- 21 files changed, 241 insertions(+), 168 deletions(-) delete mode 100644 tests/ui/impl-trait/precise-capturing/redundant.normal.stderr delete mode 100644 tests/ui/impl-trait/precise-capturing/redundant.rpitit.stderr create mode 100644 tests/ui/impl-trait/precise-capturing/redundant.stderr create mode 100644 tests/ui/impl-trait/precise-capturing/rpitit-impl-captures-too-much.rs create mode 100644 tests/ui/impl-trait/precise-capturing/rpitit-impl-captures-too-much.stderr delete mode 100644 tests/ui/impl-trait/precise-capturing/self-capture.stderr diff --git a/compiler/rustc_hir_analysis/src/variance/mod.rs b/compiler/rustc_hir_analysis/src/variance/mod.rs index 12bb9a3f9e0f3..02cfb57b836f6 100644 --- a/compiler/rustc_hir_analysis/src/variance/mod.rs +++ b/compiler/rustc_hir_analysis/src/variance/mod.rs @@ -5,6 +5,7 @@ use itertools::Itertools; use rustc_arena::DroplessArena; +use rustc_hir as hir; use rustc_hir::def::DefKind; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_middle::query::Providers; @@ -63,8 +64,29 @@ fn variances_of(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[ty::Variance] { let crate_map = tcx.crate_variances(()); return crate_map.variances.get(&item_def_id.to_def_id()).copied().unwrap_or(&[]); } + DefKind::AssocTy => match tcx.opt_rpitit_info(item_def_id.to_def_id()) { + Some(ty::ImplTraitInTraitData::Trait { opaque_def_id, .. }) => { + return variance_of_opaque( + tcx, + opaque_def_id.expect_local(), + ForceCaptureTraitArgs::Yes, + ); + } + None | Some(ty::ImplTraitInTraitData::Impl { .. }) => {} + }, DefKind::OpaqueTy => { - return variance_of_opaque(tcx, item_def_id); + let force_capture_trait_args = if let hir::OpaqueTyOrigin::FnReturn { + parent: _, + in_trait_or_impl: Some(hir::RpitContext::Trait), + } = + tcx.hir_node_by_def_id(item_def_id).expect_opaque_ty().origin + { + ForceCaptureTraitArgs::Yes + } else { + ForceCaptureTraitArgs::No + }; + + return variance_of_opaque(tcx, item_def_id, force_capture_trait_args); } _ => {} } @@ -73,8 +95,18 @@ fn variances_of(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[ty::Variance] { span_bug!(tcx.def_span(item_def_id), "asked to compute variance for wrong kind of item"); } +#[derive(Debug, Copy, Clone)] +enum ForceCaptureTraitArgs { + Yes, + No, +} + #[instrument(level = "trace", skip(tcx), ret)] -fn variance_of_opaque(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[ty::Variance] { +fn variance_of_opaque( + tcx: TyCtxt<'_>, + item_def_id: LocalDefId, + force_capture_trait_args: ForceCaptureTraitArgs, +) -> &[ty::Variance] { let generics = tcx.generics_of(item_def_id); // Opaque types may only use regions that are bound. So for @@ -115,9 +147,7 @@ fn variance_of_opaque(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[ty::Varianc #[instrument(level = "trace", skip(self), ret)] fn visit_ty(&mut self, t: Ty<'tcx>) { match t.kind() { - ty::Alias(_, ty::AliasTy { def_id, args, .. }) - if matches!(self.tcx.def_kind(*def_id), DefKind::OpaqueTy) => - { + ty::Alias(ty::Opaque, ty::AliasTy { def_id, args, .. }) => { self.visit_opaque(*def_id, args); } _ => t.super_visit_with(self), @@ -135,6 +165,15 @@ fn variance_of_opaque(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[ty::Varianc let mut generics = generics; while let Some(def_id) = generics.parent { generics = tcx.generics_of(def_id); + + // Don't mark trait params generic if we're in an RPITIT. + if matches!(force_capture_trait_args, ForceCaptureTraitArgs::Yes) + && generics.parent.is_none() + { + debug_assert_eq!(tcx.def_kind(def_id), DefKind::Trait); + break; + } + for param in &generics.own_params { match param.kind { ty::GenericParamDefKind::Lifetime => { diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 610c682d3a461..afe03531861c9 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -1100,9 +1100,12 @@ fn should_encode_variances<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, def_kind: Def | DefKind::Fn | DefKind::Ctor(..) | DefKind::AssocFn => true, + DefKind::AssocTy => { + // Only encode variances for RPITITs (for traits) + matches!(tcx.opt_rpitit_info(def_id), Some(ty::ImplTraitInTraitData::Trait { .. })) + } DefKind::Mod | DefKind::Field - | DefKind::AssocTy | DefKind::AssocConst | DefKind::TyParam | DefKind::ConstParam diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 90265f67bc1f6..590e1d336f340 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -539,6 +539,10 @@ impl<'tcx> Interner for TyCtxt<'tcx> { self.trait_def(trait_def_id).implement_via_object } + fn is_impl_trait_in_trait(self, def_id: DefId) -> bool { + self.is_impl_trait_in_trait(def_id) + } + fn delay_bug(self, msg: impl ToString) -> ErrorGuaranteed { self.dcx().span_delayed_bug(DUMMY_SP, msg.to_string()) } diff --git a/compiler/rustc_type_ir/src/interner.rs b/compiler/rustc_type_ir/src/interner.rs index a72e7b482a6fd..f06017d7e5c35 100644 --- a/compiler/rustc_type_ir/src/interner.rs +++ b/compiler/rustc_type_ir/src/interner.rs @@ -261,6 +261,8 @@ pub trait Interner: fn trait_may_be_implemented_via_object(self, trait_def_id: Self::DefId) -> bool; + fn is_impl_trait_in_trait(self, def_id: Self::DefId) -> bool; + fn delay_bug(self, msg: impl ToString) -> Self::ErrorGuaranteed; fn is_general_coroutine(self, coroutine_def_id: Self::DefId) -> bool; diff --git a/compiler/rustc_type_ir/src/relate.rs b/compiler/rustc_type_ir/src/relate.rs index 1302906adab1f..e1f3e493e36e3 100644 --- a/compiler/rustc_type_ir/src/relate.rs +++ b/compiler/rustc_type_ir/src/relate.rs @@ -254,6 +254,16 @@ impl Relate for ty::AliasTy { b.args, false, // do not fetch `type_of(a_def_id)`, as it will cause a cycle )?, + ty::Projection if relation.cx().is_impl_trait_in_trait(a.def_id) => { + relate_args_with_variances( + relation, + a.def_id, + relation.cx().variances_of(a.def_id), + a.args, + b.args, + false, // do not fetch `type_of(a_def_id)`, as it will cause a cycle + )? + } ty::Projection | ty::Weak | ty::Inherent => { relate_args_invariantly(relation, a.args, b.args)? } diff --git a/tests/ui/impl-trait/in-trait/variance.rs b/tests/ui/impl-trait/in-trait/variance.rs index 0ac44bf7546c2..19905c608e3b5 100644 --- a/tests/ui/impl-trait/in-trait/variance.rs +++ b/tests/ui/impl-trait/in-trait/variance.rs @@ -1,22 +1,25 @@ -#![feature(rustc_attrs)] +#![feature(rustc_attrs, precise_capturing_in_traits)] #![allow(internal_features)] #![rustc_variance_of_opaques] -trait Captures<'a> {} -impl Captures<'_> for T {} - trait Foo<'i> { fn implicit_capture_early<'a: 'a>() -> impl Sized {} - //~^ [Self: o, 'i: *, 'a: *, 'a: o, 'i: o] + //~^ [Self: o, 'i: o, 'a: *, 'a: o, 'i: o] + + fn explicit_capture_early<'a: 'a>() -> impl Sized + use<'i, 'a, Self> {} + //~^ [Self: o, 'i: o, 'a: *, 'i: o, 'a: o] - fn explicit_capture_early<'a: 'a>() -> impl Sized + Captures<'a> {} - //~^ [Self: o, 'i: *, 'a: *, 'a: o, 'i: o] + fn not_captured_early<'a: 'a>() -> impl Sized + use<'i, Self> {} + //~^ [Self: o, 'i: o, 'a: *, 'i: o] fn implicit_capture_late<'a>(_: &'a ()) -> impl Sized {} - //~^ [Self: o, 'i: *, 'a: o, 'i: o] + //~^ [Self: o, 'i: o, 'a: o, 'i: o] + + fn explicit_capture_late<'a>(_: &'a ()) -> impl Sized + use<'i, 'a, Self> {} + //~^ [Self: o, 'i: o, 'i: o, 'a: o] - fn explicit_capture_late<'a>(_: &'a ()) -> impl Sized + Captures<'a> {} - //~^ [Self: o, 'i: *, 'a: o, 'i: o] + fn not_cpatured_late<'a>(_: &'a ()) -> impl Sized + use<'i, Self> {} + //~^ [Self: o, 'i: o, 'i: o] } fn main() {} diff --git a/tests/ui/impl-trait/in-trait/variance.stderr b/tests/ui/impl-trait/in-trait/variance.stderr index 54e0afbaa950d..f65174e1c358c 100644 --- a/tests/ui/impl-trait/in-trait/variance.stderr +++ b/tests/ui/impl-trait/in-trait/variance.stderr @@ -1,26 +1,38 @@ -error: [Self: o, 'i: *, 'a: *, 'a: o, 'i: o] - --> $DIR/variance.rs:9:44 +error: [Self: o, 'i: o, 'a: *, 'a: o, 'i: o] + --> $DIR/variance.rs:6:44 | LL | fn implicit_capture_early<'a: 'a>() -> impl Sized {} | ^^^^^^^^^^ -error: [Self: o, 'i: *, 'a: *, 'a: o, 'i: o] - --> $DIR/variance.rs:12:44 +error: [Self: o, 'i: o, 'a: *, 'i: o, 'a: o] + --> $DIR/variance.rs:9:44 + | +LL | fn explicit_capture_early<'a: 'a>() -> impl Sized + use<'i, 'a, Self> {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: [Self: o, 'i: o, 'a: *, 'i: o] + --> $DIR/variance.rs:12:40 | -LL | fn explicit_capture_early<'a: 'a>() -> impl Sized + Captures<'a> {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | fn not_captured_early<'a: 'a>() -> impl Sized + use<'i, Self> {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: [Self: o, 'i: *, 'a: o, 'i: o] +error: [Self: o, 'i: o, 'a: o, 'i: o] --> $DIR/variance.rs:15:48 | LL | fn implicit_capture_late<'a>(_: &'a ()) -> impl Sized {} | ^^^^^^^^^^ -error: [Self: o, 'i: *, 'a: o, 'i: o] +error: [Self: o, 'i: o, 'i: o, 'a: o] --> $DIR/variance.rs:18:48 | -LL | fn explicit_capture_late<'a>(_: &'a ()) -> impl Sized + Captures<'a> {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | fn explicit_capture_late<'a>(_: &'a ()) -> impl Sized + use<'i, 'a, Self> {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: [Self: o, 'i: o, 'i: o] + --> $DIR/variance.rs:21:44 + | +LL | fn not_cpatured_late<'a>(_: &'a ()) -> impl Sized + use<'i, Self> {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 4 previous errors +error: aborting due to 6 previous errors diff --git a/tests/ui/impl-trait/precise-capturing/forgot-to-capture-type.rs b/tests/ui/impl-trait/precise-capturing/forgot-to-capture-type.rs index 9d68819f657db..6c2477c9744ab 100644 --- a/tests/ui/impl-trait/precise-capturing/forgot-to-capture-type.rs +++ b/tests/ui/impl-trait/precise-capturing/forgot-to-capture-type.rs @@ -1,10 +1,11 @@ +#![feature(precise_capturing_in_traits)] + fn type_param() -> impl Sized + use<> {} //~^ ERROR `impl Trait` must mention all type parameters in scope trait Foo { fn bar() -> impl Sized + use<>; //~^ ERROR `impl Trait` must mention the `Self` type of the trait - //~| ERROR `use<...>` precise capturing syntax is currently not allowed in return-position `impl Trait` in traits } fn main() {} diff --git a/tests/ui/impl-trait/precise-capturing/forgot-to-capture-type.stderr b/tests/ui/impl-trait/precise-capturing/forgot-to-capture-type.stderr index 23d6a3bd11e82..93b44a0c18c27 100644 --- a/tests/ui/impl-trait/precise-capturing/forgot-to-capture-type.stderr +++ b/tests/ui/impl-trait/precise-capturing/forgot-to-capture-type.stderr @@ -1,16 +1,5 @@ -error: `use<...>` precise capturing syntax is currently not allowed in return-position `impl Trait` in traits - --> $DIR/forgot-to-capture-type.rs:5:30 - | -LL | fn bar() -> impl Sized + use<>; - | ^^^^^ - | - = note: currently, return-position `impl Trait` in traits and trait implementations capture all lifetimes in scope - = note: see issue #130044 for more information - = help: add `#![feature(precise_capturing_in_traits)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - error: `impl Trait` must mention all type parameters in scope in `use<...>` - --> $DIR/forgot-to-capture-type.rs:1:23 + --> $DIR/forgot-to-capture-type.rs:3:23 | LL | fn type_param() -> impl Sized + use<> {} | - ^^^^^^^^^^^^^^^^^^ @@ -20,7 +9,7 @@ LL | fn type_param() -> impl Sized + use<> {} = note: currently, all type parameters are required to be mentioned in the precise captures list error: `impl Trait` must mention the `Self` type of the trait in `use<...>` - --> $DIR/forgot-to-capture-type.rs:5:17 + --> $DIR/forgot-to-capture-type.rs:7:17 | LL | trait Foo { | --------- `Self` type parameter is implicitly captured by this `impl Trait` @@ -29,5 +18,5 @@ LL | fn bar() -> impl Sized + use<>; | = note: currently, all type parameters are required to be mentioned in the precise captures list -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors diff --git a/tests/ui/impl-trait/precise-capturing/redundant.normal.stderr b/tests/ui/impl-trait/precise-capturing/redundant.normal.stderr deleted file mode 100644 index d1bcbaa33ae2b..0000000000000 --- a/tests/ui/impl-trait/precise-capturing/redundant.normal.stderr +++ /dev/null @@ -1,20 +0,0 @@ -warning: all possible in-scope parameters are already captured, so `use<...>` syntax is redundant - --> $DIR/redundant.rs:5:19 - | -LL | fn hello<'a>() -> impl Sized + use<'a> {} - | ^^^^^^^^^^^^^------- - | | - | help: remove the `use<...>` syntax - | - = note: `#[warn(impl_trait_redundant_captures)]` on by default - -warning: all possible in-scope parameters are already captured, so `use<...>` syntax is redundant - --> $DIR/redundant.rs:10:27 - | -LL | fn inherent(&self) -> impl Sized + use<'_> {} - | ^^^^^^^^^^^^^------- - | | - | help: remove the `use<...>` syntax - -warning: 2 warnings emitted - diff --git a/tests/ui/impl-trait/precise-capturing/redundant.rpitit.stderr b/tests/ui/impl-trait/precise-capturing/redundant.rpitit.stderr deleted file mode 100644 index 27f8ff92d3e65..0000000000000 --- a/tests/ui/impl-trait/precise-capturing/redundant.rpitit.stderr +++ /dev/null @@ -1,24 +0,0 @@ -error: `use<...>` precise capturing syntax is currently not allowed in return-position `impl Trait` in traits - --> $DIR/redundant.rs:16:35 - | -LL | fn in_trait() -> impl Sized + use<'a, Self>; - | ^^^^^^^^^^^^^ - | - = note: currently, return-position `impl Trait` in traits and trait implementations capture all lifetimes in scope - = note: see issue #130044 for more information - = help: add `#![feature(precise_capturing_in_traits)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - -error: `use<...>` precise capturing syntax is currently not allowed in return-position `impl Trait` in traits - --> $DIR/redundant.rs:21:35 - | -LL | fn in_trait() -> impl Sized + use<'a> {} - | ^^^^^^^ - | - = note: currently, return-position `impl Trait` in traits and trait implementations capture all lifetimes in scope - = note: see issue #130044 for more information - = help: add `#![feature(precise_capturing_in_traits)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - -error: aborting due to 2 previous errors - diff --git a/tests/ui/impl-trait/precise-capturing/redundant.rs b/tests/ui/impl-trait/precise-capturing/redundant.rs index 4a08ffb61be03..e19d935f5b0d4 100644 --- a/tests/ui/impl-trait/precise-capturing/redundant.rs +++ b/tests/ui/impl-trait/precise-capturing/redundant.rs @@ -1,25 +1,24 @@ //@ compile-flags: -Zunstable-options --edition=2024 -//@ revisions: normal rpitit -//@[normal] check-pass +//@ check-pass + +#![feature(precise_capturing_in_traits)] fn hello<'a>() -> impl Sized + use<'a> {} -//[normal]~^ WARN all possible in-scope parameters are already captured +//~^ WARN all possible in-scope parameters are already captured struct Inherent; impl Inherent { fn inherent(&self) -> impl Sized + use<'_> {} - //[normal]~^ WARN all possible in-scope parameters are already captured + //~^ WARN all possible in-scope parameters are already captured } -#[cfg(rpitit)] trait Test<'a> { fn in_trait() -> impl Sized + use<'a, Self>; - //[rpitit]~^ ERROR `use<...>` precise capturing syntax is currently not allowed in return-position `impl Trait` in traits + //~^ WARN all possible in-scope parameters are already captured } -#[cfg(rpitit)] impl<'a> Test<'a> for () { fn in_trait() -> impl Sized + use<'a> {} - //[rpitit]~^ ERROR `use<...>` precise capturing syntax is currently not allowed in return-position `impl Trait` in traits + //~^ WARN all possible in-scope parameters are already captured } fn main() {} diff --git a/tests/ui/impl-trait/precise-capturing/redundant.stderr b/tests/ui/impl-trait/precise-capturing/redundant.stderr new file mode 100644 index 0000000000000..274d9d2375f7d --- /dev/null +++ b/tests/ui/impl-trait/precise-capturing/redundant.stderr @@ -0,0 +1,36 @@ +warning: all possible in-scope parameters are already captured, so `use<...>` syntax is redundant + --> $DIR/redundant.rs:6:19 + | +LL | fn hello<'a>() -> impl Sized + use<'a> {} + | ^^^^^^^^^^^^^------- + | | + | help: remove the `use<...>` syntax + | + = note: `#[warn(impl_trait_redundant_captures)]` on by default + +warning: all possible in-scope parameters are already captured, so `use<...>` syntax is redundant + --> $DIR/redundant.rs:11:27 + | +LL | fn inherent(&self) -> impl Sized + use<'_> {} + | ^^^^^^^^^^^^^------- + | | + | help: remove the `use<...>` syntax + +warning: all possible in-scope parameters are already captured, so `use<...>` syntax is redundant + --> $DIR/redundant.rs:16:22 + | +LL | fn in_trait() -> impl Sized + use<'a, Self>; + | ^^^^^^^^^^^^^------------- + | | + | help: remove the `use<...>` syntax + +warning: all possible in-scope parameters are already captured, so `use<...>` syntax is redundant + --> $DIR/redundant.rs:20:22 + | +LL | fn in_trait() -> impl Sized + use<'a> {} + | ^^^^^^^^^^^^^------- + | | + | help: remove the `use<...>` syntax + +warning: 4 warnings emitted + diff --git a/tests/ui/impl-trait/precise-capturing/rpitit-captures-more-method-lifetimes.rs b/tests/ui/impl-trait/precise-capturing/rpitit-captures-more-method-lifetimes.rs index 062351afecbdf..b39c1408c0509 100644 --- a/tests/ui/impl-trait/precise-capturing/rpitit-captures-more-method-lifetimes.rs +++ b/tests/ui/impl-trait/precise-capturing/rpitit-captures-more-method-lifetimes.rs @@ -2,13 +2,14 @@ // trait definition, which is not allowed. Due to the default lifetime capture // rules of RPITITs, this is only doable if we use precise capturing. +#![feature(precise_capturing_in_traits)] + pub trait Foo { fn bar<'tr: 'tr>(&'tr mut self) -> impl Sized + use; - //~^ ERROR `use<...>` precise capturing syntax is currently not allowed in return-position `impl Trait` in traits } impl Foo for () { - fn bar<'im: 'im>(&'im mut self) -> impl Sized + 'im {} + fn bar<'im: 'im>(&'im mut self) -> impl Sized + use<'im> {} //~^ ERROR return type captures more lifetimes than trait definition } diff --git a/tests/ui/impl-trait/precise-capturing/rpitit-captures-more-method-lifetimes.stderr b/tests/ui/impl-trait/precise-capturing/rpitit-captures-more-method-lifetimes.stderr index ffd9646a4038b..45f755d3cc1be 100644 --- a/tests/ui/impl-trait/precise-capturing/rpitit-captures-more-method-lifetimes.stderr +++ b/tests/ui/impl-trait/precise-capturing/rpitit-captures-more-method-lifetimes.stderr @@ -1,28 +1,17 @@ -error: `use<...>` precise capturing syntax is currently not allowed in return-position `impl Trait` in traits - --> $DIR/rpitit-captures-more-method-lifetimes.rs:6:53 - | -LL | fn bar<'tr: 'tr>(&'tr mut self) -> impl Sized + use; - | ^^^^^^^^^ - | - = note: currently, return-position `impl Trait` in traits and trait implementations capture all lifetimes in scope - = note: see issue #130044 for more information - = help: add `#![feature(precise_capturing_in_traits)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - error: return type captures more lifetimes than trait definition - --> $DIR/rpitit-captures-more-method-lifetimes.rs:11:40 + --> $DIR/rpitit-captures-more-method-lifetimes.rs:12:40 | -LL | fn bar<'im: 'im>(&'im mut self) -> impl Sized + 'im {} - | --- ^^^^^^^^^^^^^^^^ +LL | fn bar<'im: 'im>(&'im mut self) -> impl Sized + use<'im> {} + | --- ^^^^^^^^^^^^^^^^^^^^^ | | | this lifetime was captured | note: hidden type must only reference lifetimes captured by this impl trait - --> $DIR/rpitit-captures-more-method-lifetimes.rs:6:40 + --> $DIR/rpitit-captures-more-method-lifetimes.rs:8:40 | LL | fn bar<'tr: 'tr>(&'tr mut self) -> impl Sized + use; | ^^^^^^^^^^^^^^^^^^^^^^ - = note: hidden type inferred to be `impl Sized + 'im` + = note: hidden type inferred to be `impl Sized` -error: aborting due to 2 previous errors +error: aborting due to 1 previous error diff --git a/tests/ui/impl-trait/precise-capturing/rpitit-impl-captures-too-much.rs b/tests/ui/impl-trait/precise-capturing/rpitit-impl-captures-too-much.rs new file mode 100644 index 0000000000000..b16b0522d6e11 --- /dev/null +++ b/tests/ui/impl-trait/precise-capturing/rpitit-impl-captures-too-much.rs @@ -0,0 +1,14 @@ +#![feature(precise_capturing_in_traits)] + +struct Invariant<'a>(&'a mut &'a mut ()); + +trait Trait { + fn hello(self_: Invariant<'_>) -> impl Sized + use; +} + +impl Trait for () { + fn hello(self_: Invariant<'_>) -> impl Sized + use<'_> {} + //~^ ERROR return type captures more lifetimes than trait definition +} + +fn main() {} diff --git a/tests/ui/impl-trait/precise-capturing/rpitit-impl-captures-too-much.stderr b/tests/ui/impl-trait/precise-capturing/rpitit-impl-captures-too-much.stderr new file mode 100644 index 0000000000000..e1856b929106e --- /dev/null +++ b/tests/ui/impl-trait/precise-capturing/rpitit-impl-captures-too-much.stderr @@ -0,0 +1,17 @@ +error: return type captures more lifetimes than trait definition + --> $DIR/rpitit-impl-captures-too-much.rs:10:39 + | +LL | fn hello(self_: Invariant<'_>) -> impl Sized + use<'_> {} + | -- ^^^^^^^^^^^^^^^^^^^^ + | | + | this lifetime was captured + | +note: hidden type must only reference lifetimes captured by this impl trait + --> $DIR/rpitit-impl-captures-too-much.rs:6:39 + | +LL | fn hello(self_: Invariant<'_>) -> impl Sized + use; + | ^^^^^^^^^^^^^^^^^^^^^^ + = note: hidden type inferred to be `impl Sized` + +error: aborting due to 1 previous error + diff --git a/tests/ui/impl-trait/precise-capturing/rpitit.rs b/tests/ui/impl-trait/precise-capturing/rpitit.rs index feeeb1461e827..3f887e8e47f1c 100644 --- a/tests/ui/impl-trait/precise-capturing/rpitit.rs +++ b/tests/ui/impl-trait/precise-capturing/rpitit.rs @@ -1,19 +1,34 @@ -//@ known-bug: unknown - // RPITITs don't have variances in their GATs, so they always relate invariantly // and act as if they capture all their args. // To fix this soundly, we need to make sure that all the trait header args // remain captured, since they affect trait selection. -trait Foo<'a> { - fn hello() -> impl PartialEq + use; +#![feature(precise_capturing_in_traits)] + +fn eq_types(_: T, _: T) {} + +trait TraitLt<'a: 'a> { + fn hello() -> impl Sized + use; + //~^ ERROR `impl Trait` captures lifetime parameter, but it is not mentioned in `use<...>` precise captures list +} +fn trait_lt<'a, 'b, T: for<'r> TraitLt<'r>> () { + eq_types( + //~^ ERROR lifetime may not live long enough + //~| ERROR lifetime may not live long enough + >::hello(), + >::hello(), + ); } -fn test<'a, 'b, T: for<'r> Foo<'r>>() { - PartialEq::eq( - &>::hello(), - &>::hello(), +trait MethodLt { + fn hello<'a: 'a>() -> impl Sized + use; +} +fn method_lt<'a, 'b, T: MethodLt> () { + eq_types( + T::hello::<'a>(), + T::hello::<'b>(), ); + // Good! } fn main() {} diff --git a/tests/ui/impl-trait/precise-capturing/rpitit.stderr b/tests/ui/impl-trait/precise-capturing/rpitit.stderr index c162875f327cc..8c219bb04a278 100644 --- a/tests/ui/impl-trait/precise-capturing/rpitit.stderr +++ b/tests/ui/impl-trait/precise-capturing/rpitit.stderr @@ -1,47 +1,40 @@ -error: `use<...>` precise capturing syntax is currently not allowed in return-position `impl Trait` in traits - --> $DIR/rpitit.rs:9:36 - | -LL | fn hello() -> impl PartialEq + use; - | ^^^^^^^^^ - | - = note: currently, return-position `impl Trait` in traits and trait implementations capture all lifetimes in scope - = note: see issue #130044 for more information - = help: add `#![feature(precise_capturing_in_traits)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - error: `impl Trait` captures lifetime parameter, but it is not mentioned in `use<...>` precise captures list - --> $DIR/rpitit.rs:9:19 + --> $DIR/rpitit.rs:11:19 | -LL | trait Foo<'a> { - | -- this lifetime parameter is captured -LL | fn hello() -> impl PartialEq + use; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ lifetime captured due to being mentioned in the bounds of the `impl Trait` +LL | trait TraitLt<'a: 'a> { + | -- this lifetime parameter is captured +LL | fn hello() -> impl Sized + use; + | ^^^^^^^^^^^^^^^^^^^^^^ lifetime captured due to being mentioned in the bounds of the `impl Trait` error: lifetime may not live long enough - --> $DIR/rpitit.rs:13:5 + --> $DIR/rpitit.rs:15:5 | -LL | fn test<'a, 'b, T: for<'r> Foo<'r>>() { - | -- -- lifetime `'b` defined here - | | - | lifetime `'a` defined here -LL | / PartialEq::eq( -LL | | &>::hello(), -LL | | &>::hello(), +LL | fn trait_lt<'a, 'b, T: for<'r> TraitLt<'r>> () { + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +LL | / eq_types( +LL | | +LL | | +LL | | >::hello(), +LL | | >::hello(), LL | | ); | |_____^ argument requires that `'a` must outlive `'b` | = help: consider adding the following bound: `'a: 'b` error: lifetime may not live long enough - --> $DIR/rpitit.rs:13:5 + --> $DIR/rpitit.rs:15:5 | -LL | fn test<'a, 'b, T: for<'r> Foo<'r>>() { - | -- -- lifetime `'b` defined here - | | - | lifetime `'a` defined here -LL | / PartialEq::eq( -LL | | &>::hello(), -LL | | &>::hello(), +LL | fn trait_lt<'a, 'b, T: for<'r> TraitLt<'r>> () { + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +LL | / eq_types( +LL | | +LL | | +LL | | >::hello(), +LL | | >::hello(), LL | | ); | |_____^ argument requires that `'b` must outlive `'a` | @@ -49,5 +42,5 @@ LL | | ); help: `'a` and `'b` must be the same: replace one with the other -error: aborting due to 4 previous errors +error: aborting due to 3 previous errors diff --git a/tests/ui/impl-trait/precise-capturing/self-capture.rs b/tests/ui/impl-trait/precise-capturing/self-capture.rs index a61a7f06edc1d..15985da50b55e 100644 --- a/tests/ui/impl-trait/precise-capturing/self-capture.rs +++ b/tests/ui/impl-trait/precise-capturing/self-capture.rs @@ -1,6 +1,9 @@ +//@ check-pass + +#![feature(precise_capturing_in_traits)] + trait Foo { fn bar<'a>() -> impl Sized + use; - //~^ ERROR `use<...>` precise capturing syntax is currently not allowed in return-position `impl Trait` in traits } fn main() {} diff --git a/tests/ui/impl-trait/precise-capturing/self-capture.stderr b/tests/ui/impl-trait/precise-capturing/self-capture.stderr deleted file mode 100644 index 45ebc429d88a7..0000000000000 --- a/tests/ui/impl-trait/precise-capturing/self-capture.stderr +++ /dev/null @@ -1,13 +0,0 @@ -error: `use<...>` precise capturing syntax is currently not allowed in return-position `impl Trait` in traits - --> $DIR/self-capture.rs:2:34 - | -LL | fn bar<'a>() -> impl Sized + use; - | ^^^^^^^^^ - | - = note: currently, return-position `impl Trait` in traits and trait implementations capture all lifetimes in scope - = note: see issue #130044 for more information - = help: add `#![feature(precise_capturing_in_traits)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - -error: aborting due to 1 previous error - From 36076ecdc726c4e1104e70df2d142f39501a4f48 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sun, 29 Sep 2024 13:49:32 -0400 Subject: [PATCH 2101/2194] Clarify implicit captures for RPITIT --- compiler/rustc_hir_analysis/messages.ftl | 3 +++ .../rustc_hir_analysis/src/check/check.rs | 25 ++++++++++++------- .../src/errors/precise_captures.rs | 9 +++++++ .../precise-capturing/rpitit.stderr | 4 +-- 4 files changed, 30 insertions(+), 11 deletions(-) diff --git a/compiler/rustc_hir_analysis/messages.ftl b/compiler/rustc_hir_analysis/messages.ftl index c73826c489f96..a80dc87c62242 100644 --- a/compiler/rustc_hir_analysis/messages.ftl +++ b/compiler/rustc_hir_analysis/messages.ftl @@ -259,6 +259,9 @@ hir_analysis_late_bound_lifetime_in_apit = `impl Trait` can only mention lifetim hir_analysis_late_bound_type_in_apit = `impl Trait` can only mention type parameters from an fn or impl .label = type parameter declared here +hir_analysis_lifetime_implicitly_captured = `impl Trait` captures lifetime parameter, but it is not mentioned in `use<...>` precise captures list + .param_label = all lifetime parameters originating from a trait are captured implicitly + hir_analysis_lifetime_must_be_first = lifetime parameter `{$name}` must be listed before non-lifetime parameters .label = move the lifetime before this parameter diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index eb62ff86c7179..d0063b449f894 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -589,15 +589,22 @@ fn check_opaque_precise_captures<'tcx>(tcx: TyCtxt<'tcx>, opaque_def_id: LocalDe param_span: tcx.def_span(def_id), }); } else { - // If the `use_span` is actually just the param itself, then we must - // have not duplicated the lifetime but captured the original. - // The "effective" `use_span` will be the span of the opaque itself, - // and the param span will be the def span of the param. - tcx.dcx().emit_err(errors::LifetimeNotCaptured { - opaque_span, - use_span: opaque_span, - param_span: use_span, - }); + if tcx.def_kind(tcx.parent(param.def_id)) == DefKind::Trait { + tcx.dcx().emit_err(errors::LifetimeImplicitlyCaptured { + opaque_span, + param_span: tcx.def_span(param.def_id), + }); + } else { + // If the `use_span` is actually just the param itself, then we must + // have not duplicated the lifetime but captured the original. + // The "effective" `use_span` will be the span of the opaque itself, + // and the param span will be the def span of the param. + tcx.dcx().emit_err(errors::LifetimeNotCaptured { + opaque_span, + use_span: opaque_span, + param_span: use_span, + }); + } } continue; } diff --git a/compiler/rustc_hir_analysis/src/errors/precise_captures.rs b/compiler/rustc_hir_analysis/src/errors/precise_captures.rs index b6cffb90805b3..8a83866b7fa46 100644 --- a/compiler/rustc_hir_analysis/src/errors/precise_captures.rs +++ b/compiler/rustc_hir_analysis/src/errors/precise_captures.rs @@ -34,6 +34,15 @@ pub(crate) struct LifetimeNotCaptured { pub opaque_span: Span, } +#[derive(Diagnostic)] +#[diag(hir_analysis_lifetime_implicitly_captured)] +pub(crate) struct LifetimeImplicitlyCaptured { + #[primary_span] + pub opaque_span: Span, + #[label(hir_analysis_param_label)] + pub param_span: Span, +} + #[derive(Diagnostic)] #[diag(hir_analysis_bad_precise_capture)] pub(crate) struct BadPreciseCapture { diff --git a/tests/ui/impl-trait/precise-capturing/rpitit.stderr b/tests/ui/impl-trait/precise-capturing/rpitit.stderr index 8c219bb04a278..498eae54a1c68 100644 --- a/tests/ui/impl-trait/precise-capturing/rpitit.stderr +++ b/tests/ui/impl-trait/precise-capturing/rpitit.stderr @@ -2,9 +2,9 @@ error: `impl Trait` captures lifetime parameter, but it is not mentioned in `use --> $DIR/rpitit.rs:11:19 | LL | trait TraitLt<'a: 'a> { - | -- this lifetime parameter is captured + | -- all lifetime parameters originating from a trait are captured implicitly LL | fn hello() -> impl Sized + use; - | ^^^^^^^^^^^^^^^^^^^^^^ lifetime captured due to being mentioned in the bounds of the `impl Trait` + | ^^^^^^^^^^^^^^^^^^^^^^ error: lifetime may not live long enough --> $DIR/rpitit.rs:15:5 From 322c4bdac595e7689dcf08b847d0bd4d82a4bad9 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sun, 29 Sep 2024 13:49:53 -0400 Subject: [PATCH 2102/2194] Don't fire refinement lint if there are errors --- .../rustc_hir_analysis/src/check/compare_impl_item/refine.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs index 80334c6efe7d6..2d6b9813271e2 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs @@ -64,6 +64,10 @@ pub(super) fn check_refining_return_position_impl_trait_in_trait<'tcx>( return; }; + if hidden_tys.items().any(|(_, &ty)| ty.skip_binder().references_error()) { + return; + } + let mut collector = ImplTraitInTraitCollector { tcx, types: FxIndexSet::default() }; trait_m_sig.visit_with(&mut collector); From 82433eeedf3d009262f1dc5d8f73d6c13acad7fc Mon Sep 17 00:00:00 2001 From: Julia Ryan Date: Thu, 10 Oct 2024 12:35:26 -0700 Subject: [PATCH 2103/2194] Update .mailmap --- .mailmap | 1 + 1 file changed, 1 insertion(+) diff --git a/.mailmap b/.mailmap index 0f58762e0233c..dc5bfe6d5fc76 100644 --- a/.mailmap +++ b/.mailmap @@ -312,6 +312,7 @@ Josh Driver Josh Holmer Josh Stone Josh Stone +Julia Ryan Julian Knodt jumbatm <30644300+jumbatm@users.noreply.github.com> Junyoung Cho From 8b754fbb4f4fa05f0e7550c8a3aa4c9e8bd95e11 Mon Sep 17 00:00:00 2001 From: Johnathan W <12262567+j7nw4r@users.noreply.github.com> Date: Thu, 10 Oct 2024 16:11:30 -0400 Subject: [PATCH 2104/2194] Fixing rustDoc for LayoutError. --- library/core/src/alloc/layout.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/library/core/src/alloc/layout.rs b/library/core/src/alloc/layout.rs index 107d82267e576..fca32b9d3c59d 100644 --- a/library/core/src/alloc/layout.rs +++ b/library/core/src/alloc/layout.rs @@ -540,7 +540,8 @@ impl Layout { )] pub type LayoutErr = LayoutError; -/// The parameters given to `Layout::from_size_align` +/// The `LayoutError` is returned when the parameters given +/// to `Layout::from_size_align` /// or some other `Layout` constructor /// do not satisfy its documented constraints. #[stable(feature = "alloc_layout_error", since = "1.50.0")] From 8a9b67028cd9e3e580318007e7bc6391a7c6b86c Mon Sep 17 00:00:00 2001 From: Alona Enraght-Moony Date: Thu, 10 Oct 2024 20:53:57 +0000 Subject: [PATCH 2105/2194] rustdoc-json: Add tests for unsafe/safe extern blocks (RFC 3484) --- tests/rustdoc-json/fns/extern_safe.rs | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 tests/rustdoc-json/fns/extern_safe.rs diff --git a/tests/rustdoc-json/fns/extern_safe.rs b/tests/rustdoc-json/fns/extern_safe.rs new file mode 100644 index 0000000000000..a4a2d2c7f8c1e --- /dev/null +++ b/tests/rustdoc-json/fns/extern_safe.rs @@ -0,0 +1,17 @@ +extern "C" { + //@ is "$.index[*][?(@.name=='f1')].inner.function.header.is_unsafe" true + pub fn f1(); + + // items in unadorned `extern` blocks cannot have safety qualifiers +} + +unsafe extern "C" { + //@ is "$.index[*][?(@.name=='f4')].inner.function.header.is_unsafe" true + pub fn f4(); + + //@ is "$.index[*][?(@.name=='f5')].inner.function.header.is_unsafe" true + pub unsafe fn f5(); + + //@ is "$.index[*][?(@.name=='f6')].inner.function.header.is_unsafe" false + pub safe fn f6(); +} From 42c0494499b3ee271bafa68bbfe5eb5176442c4d Mon Sep 17 00:00:00 2001 From: David Lattimore Date: Fri, 11 Oct 2024 07:58:36 +1100 Subject: [PATCH 2106/2194] Use Default visibility for rustc-generated C symbol declarations Non-default visibilities should only be used for definitions, not declarations, otherwise linking can fail. Co-authored-by: Collin Baker --- compiler/rustc_codegen_llvm/src/declare.rs | 7 +++---- tests/codegen/default-visibility.rs | 16 ++++++++++++++++ 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/declare.rs b/compiler/rustc_codegen_llvm/src/declare.rs index 7be44dd51b577..33258cb46fad2 100644 --- a/compiler/rustc_codegen_llvm/src/declare.rs +++ b/compiler/rustc_codegen_llvm/src/declare.rs @@ -84,10 +84,9 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> { unnamed: llvm::UnnamedAddr, fn_type: &'ll Type, ) -> &'ll Value { - // Declare C ABI functions with the visibility used by C by default. - let visibility = Visibility::from_generic(self.tcx.sess.default_visibility()); - - declare_raw_fn(self, name, llvm::CCallConv, unnamed, visibility, fn_type) + // Visibility should always be default for declarations, otherwise the linker may report an + // error. + declare_raw_fn(self, name, llvm::CCallConv, unnamed, Visibility::Default, fn_type) } /// Declare an entry Function diff --git a/tests/codegen/default-visibility.rs b/tests/codegen/default-visibility.rs index 884d386ec20a3..88ff9fee25447 100644 --- a/tests/codegen/default-visibility.rs +++ b/tests/codegen/default-visibility.rs @@ -31,3 +31,19 @@ pub static tested_symbol: [u8; 6] = *b"foobar"; // PROTECTED: @{{.*}}default_visibility{{.*}}tested_symbol{{.*}} = protected constant // INTERPOSABLE: @{{.*}}default_visibility{{.*}}tested_symbol{{.*}} = constant // DEFAULT: @{{.*}}default_visibility{{.*}}tested_symbol{{.*}} = constant + +pub fn do_memcmp(left: &[u8], right: &[u8]) -> i32 { + left.cmp(right) as i32 +} + +// CHECK: define {{.*}} @{{.*}}do_memcmp{{.*}} { +// CHECK: } + +// `do_memcmp` should invoke core::intrinsic::compare_bytes which emits a call +// to the C symbol `memcmp` (at least on x86_64-unknown-linux-gnu). This symbol +// should *not* be declared hidden or protected. + +// HIDDEN: declare i32 @memcmp +// PROTECTED: declare i32 @memcmp +// INTERPOSABLE: declare i32 @memcmp +// DEFAULT: declare i32 @memcmp From 96224d80ce94fe461088d6e6338627130625923d Mon Sep 17 00:00:00 2001 From: Zalathar Date: Fri, 11 Oct 2024 11:16:12 +1100 Subject: [PATCH 2107/2194] compiletest: Remove the magic hacks for finding output with `lto=thin` This hack was intended to handle the case where `-Clto=thin` causes the compiler to emit multiple output files (when producing LLVM-IR or assembly). The hack only affects 4 tests, of which 3 are just meta-tests for the hack itself. The one remaining test that motivated the hack currently doesn't even need it! (`tests/codegen/issues/issue-81408-dllimport-thinlto-windows.rs`) --- src/tools/compiletest/src/runtest.rs | 56 +++------------------------- tests/assembly/thin-lto.rs | 7 ---- tests/codegen/thin-lto.rs | 6 --- tests/coverage/thin-lto.cov-map | 8 ---- tests/coverage/thin-lto.coverage | 4 -- tests/coverage/thin-lto.rs | 3 -- 6 files changed, 6 insertions(+), 78 deletions(-) delete mode 100644 tests/assembly/thin-lto.rs delete mode 100644 tests/codegen/thin-lto.rs delete mode 100644 tests/coverage/thin-lto.cov-map delete mode 100644 tests/coverage/thin-lto.coverage delete mode 100644 tests/coverage/thin-lto.rs diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 256b88758f042..5e75a74a64c83 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -1780,58 +1780,14 @@ impl<'test> TestCx<'test> { proc_res.fatal(None, || on_failure(*self)); } - fn get_output_file(&self, extension: &str) -> TargetLocation { - let thin_lto = self.props.compile_flags.iter().any(|s| s.ends_with("lto=thin")); - if thin_lto { - TargetLocation::ThisDirectory(self.output_base_dir()) - } else { - // This works with both `--emit asm` (as default output name for the assembly) - // and `ptx-linker` because the latter can write output at requested location. - let output_path = self.output_base_name().with_extension(extension); - - TargetLocation::ThisFile(output_path.clone()) - } - } - - fn get_filecheck_file(&self, extension: &str) -> PathBuf { - let thin_lto = self.props.compile_flags.iter().any(|s| s.ends_with("lto=thin")); - if thin_lto { - let name = self.testpaths.file.file_stem().unwrap().to_str().unwrap(); - let canonical_name = name.replace('-', "_"); - let mut output_file = None; - for entry in self.output_base_dir().read_dir().unwrap() { - if let Ok(entry) = entry { - let entry_path = entry.path(); - let entry_file = entry_path.file_name().unwrap().to_str().unwrap(); - if entry_file.starts_with(&format!("{}.{}", name, canonical_name)) - && entry_file.ends_with(extension) - { - assert!( - output_file.is_none(), - "thinlto doesn't support multiple cgu tests" - ); - output_file = Some(entry_file.to_string()); - } - } - } - if let Some(output_file) = output_file { - self.output_base_dir().join(output_file) - } else { - self.output_base_name().with_extension(extension) - } - } else { - self.output_base_name().with_extension(extension) - } - } - // codegen tests (using FileCheck) fn compile_test_and_save_ir(&self) -> (ProcRes, PathBuf) { - let output_file = self.get_output_file("ll"); + let output_path = self.output_base_name().with_extension("ll"); let input_file = &self.testpaths.file; let rustc = self.make_compile_args( input_file, - output_file, + TargetLocation::ThisFile(output_path.clone()), Emit::LlvmIr, AllowUnused::No, LinkToAux::Yes, @@ -1839,12 +1795,13 @@ impl<'test> TestCx<'test> { ); let proc_res = self.compose_and_run_compiler(rustc, None, self.testpaths); - let output_path = self.get_filecheck_file("ll"); (proc_res, output_path) } fn compile_test_and_save_assembly(&self) -> (ProcRes, PathBuf) { - let output_file = self.get_output_file("s"); + // This works with both `--emit asm` (as default output name for the assembly) + // and `ptx-linker` because the latter can write output at requested location. + let output_path = self.output_base_name().with_extension("s"); let input_file = &self.testpaths.file; let mut emit = Emit::None; @@ -1867,7 +1824,7 @@ impl<'test> TestCx<'test> { let rustc = self.make_compile_args( input_file, - output_file, + TargetLocation::ThisFile(output_path.clone()), emit, AllowUnused::No, LinkToAux::Yes, @@ -1875,7 +1832,6 @@ impl<'test> TestCx<'test> { ); let proc_res = self.compose_and_run_compiler(rustc, None, self.testpaths); - let output_path = self.get_filecheck_file("s"); (proc_res, output_path) } diff --git a/tests/assembly/thin-lto.rs b/tests/assembly/thin-lto.rs deleted file mode 100644 index 7b67b2de1e63b..0000000000000 --- a/tests/assembly/thin-lto.rs +++ /dev/null @@ -1,7 +0,0 @@ -//@ compile-flags: -O -C lto=thin -C prefer-dynamic=no -//@ only-x86_64-unknown-linux-gnu -//@ assembly-output: emit-asm - -// CHECK: main - -pub fn main() {} diff --git a/tests/codegen/thin-lto.rs b/tests/codegen/thin-lto.rs deleted file mode 100644 index 4339d20532ea6..0000000000000 --- a/tests/codegen/thin-lto.rs +++ /dev/null @@ -1,6 +0,0 @@ -//@ compile-flags: -O -C lto=thin -C prefer-dynamic=no -//@ only-x86_64-unknown-linux-gnu - -// CHECK: main - -pub fn main() {} diff --git a/tests/coverage/thin-lto.cov-map b/tests/coverage/thin-lto.cov-map deleted file mode 100644 index 1f61b805f622b..0000000000000 --- a/tests/coverage/thin-lto.cov-map +++ /dev/null @@ -1,8 +0,0 @@ -Function name: thin_lto::main -Raw bytes (9): 0x[01, 01, 00, 01, 01, 03, 01, 00, 11] -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, 1) to (start + 0, 17) - diff --git a/tests/coverage/thin-lto.coverage b/tests/coverage/thin-lto.coverage deleted file mode 100644 index 5255aa7f5a408..0000000000000 --- a/tests/coverage/thin-lto.coverage +++ /dev/null @@ -1,4 +0,0 @@ - LL| |//@ compile-flags: -O -C lto=thin -C prefer-dynamic=no - LL| | - LL| 1|pub fn main() {} - diff --git a/tests/coverage/thin-lto.rs b/tests/coverage/thin-lto.rs deleted file mode 100644 index 08843ea32ee18..0000000000000 --- a/tests/coverage/thin-lto.rs +++ /dev/null @@ -1,3 +0,0 @@ -//@ compile-flags: -O -C lto=thin -C prefer-dynamic=no - -pub fn main() {} From 4637630ed7e64a5a3f56ff8e4f5d2552f0df455b Mon Sep 17 00:00:00 2001 From: Zalathar Date: Fri, 11 Oct 2024 11:50:43 +1100 Subject: [PATCH 2108/2194] Simplify the choice of `--emit` mode for assembly tests --- src/tools/compiletest/src/runtest.rs | 25 ++++++++----------------- 1 file changed, 8 insertions(+), 17 deletions(-) diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 256b88758f042..f3e7137967e0b 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -1847,23 +1847,14 @@ impl<'test> TestCx<'test> { let output_file = self.get_output_file("s"); let input_file = &self.testpaths.file; - let mut emit = Emit::None; - match self.props.assembly_output.as_ref().map(AsRef::as_ref) { - Some("emit-asm") => { - emit = Emit::Asm; - } - - Some("bpf-linker") => { - emit = Emit::LinkArgsAsm; - } - - Some("ptx-linker") => { - // No extra flags needed. - } - - Some(header) => self.fatal(&format!("unknown 'assembly-output' header: {header}")), - None => self.fatal("missing 'assembly-output' header"), - } + // Use the `//@ assembly-output:` directive to determine how to emit assembly. + let emit = match self.props.assembly_output.as_deref() { + Some("emit-asm") => Emit::Asm, + Some("bpf-linker") => Emit::LinkArgsAsm, + Some("ptx-linker") => Emit::None, // No extra flags needed. + Some(other) => self.fatal(&format!("unknown 'assembly-output' directive: {other}")), + None => self.fatal("missing 'assembly-output' directive"), + }; let rustc = self.make_compile_args( input_file, From 1b5c05433a9e69f89183d121ab8c906623c981b8 Mon Sep 17 00:00:00 2001 From: m Date: Thu, 10 Oct 2024 20:59:28 -0700 Subject: [PATCH 2109/2194] fix typo in rustdoc-json-types comment --- src/rustdoc-json-types/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rustdoc-json-types/lib.rs b/src/rustdoc-json-types/lib.rs index b3707cf615714..c8b54728d9094 100644 --- a/src/rustdoc-json-types/lib.rs +++ b/src/rustdoc-json-types/lib.rs @@ -677,7 +677,7 @@ pub struct FunctionHeader { /// on unwinding for more info. #[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] pub enum Abi { - // We only have a concrete listing here for stable ABI's because their are so many + // We only have a concrete listing here for stable ABI's because there are so many // See rustc_ast_passes::feature_gate::PostExpansionVisitor::check_abi for the list /// The default ABI, but that can also be written explicitly with `extern "Rust"`. Rust, From 7e05da8d42a730c15983bbd56dfbf744b32032d4 Mon Sep 17 00:00:00 2001 From: Urgau Date: Thu, 10 Oct 2024 14:22:20 +0200 Subject: [PATCH 2110/2194] Consider outermost const-anon in non_local_def lint --- compiler/rustc_lint/src/non_local_def.rs | 90 ++++++++++++------- tests/ui/lint/non-local-defs/consts.rs | 7 ++ tests/ui/lint/non-local-defs/consts.stderr | 20 ++++- .../convoluted-locals-131474-with-mods.rs | 34 +++++++ .../convoluted-locals-131474.rs | 24 +++++ tests/ui/lint/non-local-defs/local.rs | 7 ++ 6 files changed, 148 insertions(+), 34 deletions(-) create mode 100644 tests/ui/lint/non-local-defs/convoluted-locals-131474-with-mods.rs create mode 100644 tests/ui/lint/non-local-defs/convoluted-locals-131474.rs diff --git a/compiler/rustc_lint/src/non_local_def.rs b/compiler/rustc_lint/src/non_local_def.rs index 56f930ea7f62e..6fecddb331947 100644 --- a/compiler/rustc_lint/src/non_local_def.rs +++ b/compiler/rustc_lint/src/non_local_def.rs @@ -124,16 +124,6 @@ impl<'tcx> LateLintPass<'tcx> for NonLocalDefinitions { // If that's the case this means that this impl block declaration // is using local items and so we don't lint on it. - // We also ignore anon-const in item by including the anon-const - // parent as well. - let parent_parent = if parent_def_kind == DefKind::Const - && parent_opt_item_name == Some(kw::Underscore) - { - Some(cx.tcx.parent(parent)) - } else { - None - }; - // 1. We collect all the `hir::Path` from the `Self` type and `Trait` ref // of the `impl` definition let mut collector = PathCollector { paths: Vec::new() }; @@ -148,13 +138,33 @@ impl<'tcx> LateLintPass<'tcx> for NonLocalDefinitions { |p| matches!(p.res, Res::Def(def_kind, _) if def_kind != DefKind::TyParam), ); - // 2. We check if any of path reference a "local" parent and if that the case - // we bail out as asked by T-lang, even though this isn't correct from a - // type-system point of view, as inference exists and could still leak the impl. + // 1.9. We retrieve the parent def id of the impl item, ... + // + // ... modulo const-anons items, for enhanced compatibility with the ecosystem + // as that pattern is common with `serde`, `bevy`, ... + // + // For this example we want the `DefId` parent of the outermost const-anon items. + // ``` + // const _: () = { // the parent of this const-anon + // const _: () = { + // impl Foo {} + // }; + // }; + // ``` + let outermost_impl_parent = peel_parent_while(cx.tcx, parent, |tcx, did| { + tcx.def_kind(did) == DefKind::Const + && tcx.opt_item_name(did) == Some(kw::Underscore) + }); + + // 2. We check if any of the paths reference a the `impl`-parent. + // + // If that the case we bail out, as was asked by T-lang, even though this isn't + // correct from a type-system point of view, as inference exists and one-impl-rule + // make its so that we could still leak the impl. if collector .paths .iter() - .any(|path| path_has_local_parent(path, cx, parent, parent_parent)) + .any(|path| path_has_local_parent(path, cx, parent, outermost_impl_parent)) { return; } @@ -253,8 +263,8 @@ impl<'tcx> Visitor<'tcx> for PathCollector<'tcx> { } } -/// Given a path and a parent impl def id, this checks if the if parent resolution -/// def id correspond to the def id of the parent impl definition. +/// Given a path, this checks if the if the parent resolution def id corresponds to +/// the def id of the parent impl definition (the direct one and the outermost one). /// /// Given this path, we will look at the path (and ignore any generic args): /// @@ -267,32 +277,50 @@ fn path_has_local_parent( path: &Path<'_>, cx: &LateContext<'_>, impl_parent: DefId, - impl_parent_parent: Option, + outermost_impl_parent: Option, ) -> bool { path.res .opt_def_id() - .is_some_and(|did| did_has_local_parent(did, cx.tcx, impl_parent, impl_parent_parent)) + .is_some_and(|did| did_has_local_parent(did, cx.tcx, impl_parent, outermost_impl_parent)) } -/// Given a def id and a parent impl def id, this checks if the parent -/// def id (modulo modules) correspond to the def id of the parent impl definition. +/// Given a def id this checks if the parent def id (modulo modules) correspond to +/// the def id of the parent impl definition (the direct one and the outermost one). #[inline] fn did_has_local_parent( did: DefId, tcx: TyCtxt<'_>, impl_parent: DefId, - impl_parent_parent: Option, + outermost_impl_parent: Option, ) -> bool { - did.is_local() - && if let Some(did_parent) = tcx.opt_parent(did) { - did_parent == impl_parent - || Some(did_parent) == impl_parent_parent - || !did_parent.is_crate_root() - && tcx.def_kind(did_parent) == DefKind::Mod - && did_has_local_parent(did_parent, tcx, impl_parent, impl_parent_parent) - } else { - false - } + if !did.is_local() { + return false; + } + + let Some(parent_did) = tcx.opt_parent(did) else { + return false; + }; + + peel_parent_while(tcx, parent_did, |tcx, did| tcx.def_kind(did) == DefKind::Mod) + .map(|parent_did| parent_did == impl_parent || Some(parent_did) == outermost_impl_parent) + .unwrap_or(false) +} + +/// Given a `DefId` checks if it satisfies `f` if it does check with it's parent and continue +/// until it doesn't satisfies `f` and return the last `DefId` checked. +/// +/// In other word this method return the first `DefId` that doesn't satisfies `f`. +#[inline] +fn peel_parent_while( + tcx: TyCtxt<'_>, + mut did: DefId, + mut f: impl FnMut(TyCtxt<'_>, DefId) -> bool, +) -> Option { + while !did.is_crate_root() && f(tcx, did) { + did = tcx.opt_parent(did).filter(|parent_did| parent_did.is_local())?; + } + + Some(did) } /// Return for a given `Path` the span until the last args diff --git a/tests/ui/lint/non-local-defs/consts.rs b/tests/ui/lint/non-local-defs/consts.rs index d8a497e43e502..5b9dab3cfd369 100644 --- a/tests/ui/lint/non-local-defs/consts.rs +++ b/tests/ui/lint/non-local-defs/consts.rs @@ -63,6 +63,13 @@ fn main() { 1 }; + + const _: () = { + const _: () = { + impl Test {} + //~^ WARN non-local `impl` definition + }; + }; } trait Uto9 {} diff --git a/tests/ui/lint/non-local-defs/consts.stderr b/tests/ui/lint/non-local-defs/consts.stderr index 7f76056c0210c..4bf50bae5eac1 100644 --- a/tests/ui/lint/non-local-defs/consts.stderr +++ b/tests/ui/lint/non-local-defs/consts.stderr @@ -95,7 +95,21 @@ LL | impl Test { = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item - --> $DIR/consts.rs:72:9 + --> $DIR/consts.rs:69:13 + | +LL | const _: () = { + | ----------- move the `impl` block outside of this constant `_` and up 3 bodies +LL | impl Test {} + | ^^^^^---- + | | + | `Test` is not local + | + = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` + = note: items in an anonymous const item (`const _: () = { ... }`) are treated as in the same scope as the anonymous const's declaration for the purpose of this lint + = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue + +warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item + --> $DIR/consts.rs:79:9 | LL | let _a = || { | -- move the `impl` block outside of this closure `` and up 2 bodies @@ -109,7 +123,7 @@ LL | impl Uto9 for Test {} = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item - --> $DIR/consts.rs:79:9 + --> $DIR/consts.rs:86:9 | LL | type A = [u32; { | ____________________- @@ -126,5 +140,5 @@ LL | | }]; = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue -warning: 8 warnings emitted +warning: 9 warnings emitted diff --git a/tests/ui/lint/non-local-defs/convoluted-locals-131474-with-mods.rs b/tests/ui/lint/non-local-defs/convoluted-locals-131474-with-mods.rs new file mode 100644 index 0000000000000..cef0f0205e809 --- /dev/null +++ b/tests/ui/lint/non-local-defs/convoluted-locals-131474-with-mods.rs @@ -0,0 +1,34 @@ +// This test check that no matter the nesting of const-anons and modules +// we consider them as transparent. +// +// Similar to https://github.com/rust-lang/rust/issues/131474 + +//@ check-pass + +pub mod tmp { + pub mod tmp { + pub struct Test; + } +} + +const _: () = { + const _: () = { + const _: () = { + const _: () = { + impl tmp::tmp::Test {} + }; + }; + }; +}; + +const _: () = { + const _: () = { + mod tmp { + pub(super) struct InnerTest; + } + + impl tmp::InnerTest {} + }; +}; + +fn main() {} diff --git a/tests/ui/lint/non-local-defs/convoluted-locals-131474.rs b/tests/ui/lint/non-local-defs/convoluted-locals-131474.rs new file mode 100644 index 0000000000000..4881723f13bce --- /dev/null +++ b/tests/ui/lint/non-local-defs/convoluted-locals-131474.rs @@ -0,0 +1,24 @@ +// This test check that no matter the nesting of const-anons we consider +// them as transparent. +// +// https://github.com/rust-lang/rust/issues/131474 + +//@ check-pass + +pub struct Test; + +const _: () = { + const _: () = { + impl Test {} + }; +}; + +const _: () = { + const _: () = { + struct InnerTest; + + impl InnerTest {} + }; +}; + +fn main() {} diff --git a/tests/ui/lint/non-local-defs/local.rs b/tests/ui/lint/non-local-defs/local.rs index 166ee88c0210c..f7ecd68f59e90 100644 --- a/tests/ui/lint/non-local-defs/local.rs +++ b/tests/ui/lint/non-local-defs/local.rs @@ -51,3 +51,10 @@ fn bitflags() { impl Flags {} }; } + +fn bitflags_internal() { + const _: () = { + struct InternalFlags; + impl InternalFlags {} + }; +} From 599f95ecc26fb68cccbf79780dd1825a4cf73eb0 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Tue, 8 Oct 2024 13:13:05 +1100 Subject: [PATCH 2111/2194] coverage: Include the highest counter ID seen in `.cov-map` dumps When making changes that have a large impact on coverage counter creation, this makes it easier to see whether the number of physical counters has changed. (The highest counter ID seen in coverage maps is not necessarily the same as the number of physical counters actually used by the instrumented code, but it's the best approximation we can get from looking only at the coverage maps, and it should be reasonably accurate in most cases.) --- src/tools/coverage-dump/src/covfun.rs | 42 +++++++++++++++++++ tests/coverage/abort.cov-map | 2 + tests/coverage/assert-ne.cov-map | 1 + tests/coverage/assert.cov-map | 2 + tests/coverage/assert_not.cov-map | 1 + tests/coverage/async.cov-map | 25 +++++++++++ tests/coverage/async2.cov-map | 6 +++ tests/coverage/async_block.cov-map | 2 + tests/coverage/attr/impl.cov-map | 3 ++ tests/coverage/attr/module.cov-map | 3 ++ tests/coverage/attr/nested.cov-map | 2 + tests/coverage/attr/off-on-sandwich.cov-map | 3 ++ tests/coverage/await_ready.cov-map | 2 + tests/coverage/bad_counter_ids.cov-map | 8 ++++ tests/coverage/bench.cov-map | 1 + tests/coverage/branch/generics.cov-map | 3 ++ tests/coverage/branch/guard.cov-map | 1 + tests/coverage/branch/if-let.cov-map | 2 + tests/coverage/branch/if.cov-map | 4 ++ tests/coverage/branch/lazy-boolean.cov-map | 4 ++ tests/coverage/branch/let-else.cov-map | 1 + tests/coverage/branch/match-arms.cov-map | 3 ++ tests/coverage/branch/match-trivial.cov-map | 2 + tests/coverage/branch/no-mir-spans.cov-map | 4 ++ tests/coverage/branch/while.cov-map | 4 ++ tests/coverage/closure.cov-map | 21 ++++++++++ tests/coverage/closure_bug.cov-map | 5 +++ tests/coverage/closure_macro.cov-map | 3 ++ tests/coverage/closure_macro_async.cov-map | 4 ++ tests/coverage/closure_unit_return.cov-map | 4 ++ tests/coverage/condition/conditions.cov-map | 7 ++++ tests/coverage/conditions.cov-map | 1 + tests/coverage/continue.cov-map | 1 + tests/coverage/coroutine.cov-map | 3 ++ tests/coverage/coverage_attr_closure.cov-map | 4 ++ tests/coverage/dead_code.cov-map | 3 ++ tests/coverage/drop_trait.cov-map | 2 + tests/coverage/fn_sig_into_try.cov-map | 4 ++ tests/coverage/generics.cov-map | 5 +++ tests/coverage/holes.cov-map | 5 +++ tests/coverage/if.cov-map | 1 + tests/coverage/if_else.cov-map | 1 + tests/coverage/if_not.cov-map | 1 + tests/coverage/ignore_run.cov-map | 1 + tests/coverage/inline-dead.cov-map | 4 ++ tests/coverage/inline.cov-map | 7 ++++ tests/coverage/inner_items.cov-map | 4 ++ tests/coverage/issue-83601.cov-map | 1 + tests/coverage/issue-84561.cov-map | 6 +++ tests/coverage/issue-85461.cov-map | 1 + tests/coverage/issue-93054.cov-map | 3 ++ tests/coverage/lazy_boolean.cov-map | 1 + tests/coverage/let_else_loop.cov-map | 3 ++ tests/coverage/long_and_wide.cov-map | 4 ++ tests/coverage/loop-break.cov-map | 1 + tests/coverage/loop_break_value.cov-map | 1 + tests/coverage/loops_branches.cov-map | 3 ++ tests/coverage/macro_in_closure.cov-map | 2 + tests/coverage/macro_name_span.cov-map | 2 + tests/coverage/match_or_pattern.cov-map | 1 + tests/coverage/mcdc/condition-limit.cov-map | 1 + tests/coverage/mcdc/if.cov-map | 7 ++++ .../coverage/mcdc/inlined_expressions.cov-map | 1 + tests/coverage/mcdc/nested_if.cov-map | 4 ++ tests/coverage/mcdc/non_control_flow.cov-map | 7 ++++ tests/coverage/nested_loops.cov-map | 1 + tests/coverage/no_cov_crate.cov-map | 7 ++++ tests/coverage/no_spans.cov-map | 2 + tests/coverage/no_spans_if_not.cov-map | 2 + tests/coverage/overflow.cov-map | 2 + tests/coverage/panic_unwind.cov-map | 2 + tests/coverage/partial_eq.cov-map | 2 + tests/coverage/simple_loop.cov-map | 1 + tests/coverage/simple_match.cov-map | 1 + tests/coverage/sort_groups.cov-map | 6 +++ tests/coverage/test_harness.cov-map | 2 + tests/coverage/tight_inf_loop.cov-map | 1 + tests/coverage/trivial.cov-map | 1 + tests/coverage/try_error_result.cov-map | 6 +++ tests/coverage/unicode.cov-map | 3 ++ tests/coverage/unreachable.cov-map | 3 ++ tests/coverage/unused.cov-map | 7 ++++ tests/coverage/unused_mod.cov-map | 2 + tests/coverage/uses_crate.cov-map | 5 +++ tests/coverage/uses_inline_crate.cov-map | 6 +++ tests/coverage/while.cov-map | 1 + tests/coverage/while_early_ret.cov-map | 1 + tests/coverage/yield.cov-map | 3 ++ 88 files changed, 338 insertions(+) diff --git a/src/tools/coverage-dump/src/covfun.rs b/src/tools/coverage-dump/src/covfun.rs index c779dd0583c4e..33fac3edccd11 100644 --- a/src/tools/coverage-dump/src/covfun.rs +++ b/src/tools/coverage-dump/src/covfun.rs @@ -56,6 +56,7 @@ pub(crate) fn dump_covfun_mappings( expression_resolver.push_operands(lhs, rhs); } + let mut max_counter = None; for i in 0..num_files { let num_mappings = parser.read_uleb128_u32()?; println!("Number of file {i} mappings: {num_mappings}"); @@ -63,6 +64,11 @@ pub(crate) fn dump_covfun_mappings( for _ in 0..num_mappings { let (kind, region) = parser.read_mapping_kind_and_region()?; println!("- {kind:?} at {region:?}"); + kind.for_each_term(|term| { + if let CovTerm::Counter(n) = term { + max_counter = max_counter.max(Some(n)); + } + }); match kind { // Also print expression mappings in resolved form. @@ -83,6 +89,16 @@ pub(crate) fn dump_covfun_mappings( } parser.ensure_empty()?; + + // Printing the highest counter ID seen in the functions mappings makes + // it easier to determine whether a change to coverage instrumentation + // has increased or decreased the number of physical counters needed. + // (It's possible for the generated code to have more counters that + // aren't used by any mappings, but that should hopefully be rare.) + println!("Highest counter ID seen: {}", match max_counter { + Some(id) => format!("c{id}"), + None => "(none)".to_owned(), + }); println!(); } Ok(()) @@ -271,6 +287,32 @@ enum MappingKind { }, } +impl MappingKind { + fn for_each_term(&self, mut callback: impl FnMut(CovTerm)) { + match *self { + Self::Code(term) => callback(term), + Self::Gap(term) => callback(term), + Self::Expansion(_id) => {} + Self::Skip => {} + Self::Branch { r#true, r#false } => { + callback(r#true); + callback(r#false); + } + Self::MCDCBranch { + r#true, + r#false, + condition_id: _, + true_next_id: _, + false_next_id: _, + } => { + callback(r#true); + callback(r#false); + } + Self::MCDCDecision { bitmap_idx: _, conditions_num: _ } => {} + } + } +} + struct MappingRegion { /// Offset of this region's start line, relative to the *start line* of /// the *previous mapping* (or 0). Line numbers are 1-based. diff --git a/tests/coverage/abort.cov-map b/tests/coverage/abort.cov-map index 15156ec9811b1..06dce43c3cabc 100644 --- a/tests/coverage/abort.cov-map +++ b/tests/coverage/abort.cov-map @@ -34,6 +34,7 @@ Number of file 0 mappings: 13 - Code(Expression(9, Add)) at (prev + 1, 9) to (start + 0, 23) = (c1 + c2) - Code(Counter(3)) at (prev + 2, 5) to (start + 1, 2) +Highest counter ID seen: c5 Function name: abort::might_abort Raw bytes (21): 0x[01, 01, 01, 01, 05, 03, 01, 03, 01, 01, 14, 05, 02, 09, 01, 24, 02, 02, 0c, 03, 02] @@ -46,4 +47,5 @@ Number of file 0 mappings: 3 - Code(Counter(1)) at (prev + 2, 9) to (start + 1, 36) - Code(Expression(0, Sub)) at (prev + 2, 12) to (start + 3, 2) = (c0 - c1) +Highest counter ID seen: c1 diff --git a/tests/coverage/assert-ne.cov-map b/tests/coverage/assert-ne.cov-map index 6d9906fd7f573..906abcd3c2e59 100644 --- a/tests/coverage/assert-ne.cov-map +++ b/tests/coverage/assert-ne.cov-map @@ -10,4 +10,5 @@ Number of file 0 mappings: 4 - Code(Expression(0, Sub)) at (prev + 2, 13) to (start + 0, 19) = (c0 - c1) - Code(Counter(2)) at (prev + 3, 5) to (start + 1, 2) +Highest counter ID seen: c2 diff --git a/tests/coverage/assert.cov-map b/tests/coverage/assert.cov-map index dd413123de729..018fcc2c3dbb3 100644 --- a/tests/coverage/assert.cov-map +++ b/tests/coverage/assert.cov-map @@ -25,6 +25,7 @@ Number of file 0 mappings: 9 - Code(Expression(6, Add)) at (prev + 1, 9) to (start + 0, 23) = (c1 + (c2 + c3)) - Code(Counter(4)) at (prev + 2, 5) to (start + 1, 2) +Highest counter ID seen: c4 Function name: assert::might_fail_assert Raw bytes (21): 0x[01, 01, 01, 01, 05, 03, 01, 04, 01, 02, 0f, 02, 02, 25, 00, 3d, 05, 01, 01, 00, 02] @@ -37,4 +38,5 @@ Number of file 0 mappings: 3 - Code(Expression(0, Sub)) at (prev + 2, 37) to (start + 0, 61) = (c0 - c1) - Code(Counter(1)) at (prev + 1, 1) to (start + 0, 2) +Highest counter ID seen: c1 diff --git a/tests/coverage/assert_not.cov-map b/tests/coverage/assert_not.cov-map index 788bc5dbf58f3..401dd6450e952 100644 --- a/tests/coverage/assert_not.cov-map +++ b/tests/coverage/assert_not.cov-map @@ -13,4 +13,5 @@ Number of file 0 mappings: 5 - Code(Counter(3)) at (prev + 1, 5) to (start + 0, 22) - Code(Expression(1, Sub)) at (prev + 1, 1) to (start + 0, 2) = (c3 - Zero) +Highest counter ID seen: c3 diff --git a/tests/coverage/async.cov-map b/tests/coverage/async.cov-map index 43b497a1d3fe9..9a67cefcf985f 100644 --- a/tests/coverage/async.cov-map +++ b/tests/coverage/async.cov-map @@ -5,6 +5,7 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 12, 1) to (start + 0, 25) +Highest counter ID seen: c0 Function name: async::c::{closure#0} Raw bytes (26): 0x[01, 01, 01, 01, 05, 04, 01, 0c, 19, 01, 0e, 05, 02, 09, 00, 0a, 02, 02, 09, 00, 0a, 01, 02, 01, 00, 02] @@ -18,6 +19,7 @@ Number of file 0 mappings: 4 - Code(Expression(0, Sub)) at (prev + 2, 9) to (start + 0, 10) = (c0 - c1) - Code(Counter(0)) at (prev + 2, 1) to (start + 0, 2) +Highest counter ID seen: c1 Function name: async::d Raw bytes (9): 0x[01, 01, 00, 01, 01, 14, 01, 00, 14] @@ -26,6 +28,7 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 20, 1) to (start + 0, 20) +Highest counter ID seen: c0 Function name: async::d::{closure#0} Raw bytes (9): 0x[01, 01, 00, 01, 01, 14, 14, 00, 19] @@ -34,6 +37,7 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 20, 20) to (start + 0, 25) +Highest counter ID seen: c0 Function name: async::e (unused) Raw bytes (9): 0x[01, 01, 00, 01, 00, 16, 01, 00, 14] @@ -42,6 +46,7 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Zero) at (prev + 22, 1) to (start + 0, 20) +Highest counter ID seen: (none) Function name: async::e::{closure#0} (unused) Raw bytes (9): 0x[01, 01, 00, 01, 00, 16, 14, 00, 19] @@ -50,6 +55,7 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Zero) at (prev + 22, 20) to (start + 0, 25) +Highest counter ID seen: (none) Function name: async::f Raw bytes (9): 0x[01, 01, 00, 01, 01, 18, 01, 00, 14] @@ -58,6 +64,7 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 24, 1) to (start + 0, 20) +Highest counter ID seen: c0 Function name: async::f::{closure#0} Raw bytes (9): 0x[01, 01, 00, 01, 01, 18, 14, 00, 19] @@ -66,6 +73,7 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 24, 20) to (start + 0, 25) +Highest counter ID seen: c0 Function name: async::foo (unused) Raw bytes (9): 0x[01, 01, 00, 01, 00, 1a, 01, 00, 1e] @@ -74,6 +82,7 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Zero) at (prev + 26, 1) to (start + 0, 30) +Highest counter ID seen: (none) Function name: async::foo::{closure#0} (unused) Raw bytes (9): 0x[01, 01, 00, 01, 00, 1a, 1e, 00, 2d] @@ -82,6 +91,7 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Zero) at (prev + 26, 30) to (start + 0, 45) +Highest counter ID seen: (none) Function name: async::g Raw bytes (9): 0x[01, 01, 00, 01, 01, 1c, 01, 00, 17] @@ -90,6 +100,7 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 28, 1) to (start + 0, 23) +Highest counter ID seen: c0 Function name: async::g::{closure#0} (unused) Raw bytes (59): 0x[01, 01, 00, 0b, 00, 1c, 17, 01, 0c, 00, 02, 09, 00, 0a, 00, 00, 0e, 00, 17, 00, 00, 1b, 00, 1c, 00, 00, 20, 00, 22, 00, 01, 09, 00, 0a, 00, 00, 0e, 00, 17, 00, 00, 1b, 00, 1c, 00, 00, 20, 00, 22, 00, 01, 0e, 00, 10, 00, 02, 01, 00, 02] @@ -108,6 +119,7 @@ Number of file 0 mappings: 11 - Code(Zero) at (prev + 0, 32) to (start + 0, 34) - Code(Zero) at (prev + 1, 14) to (start + 0, 16) - Code(Zero) at (prev + 2, 1) to (start + 0, 2) +Highest counter ID seen: (none) Function name: async::h Raw bytes (9): 0x[01, 01, 00, 01, 01, 24, 01, 00, 16] @@ -116,6 +128,7 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 36, 1) to (start + 0, 22) +Highest counter ID seen: c0 Function name: async::h::{closure#0} (unused) Raw bytes (39): 0x[01, 01, 00, 07, 00, 24, 16, 03, 0c, 00, 04, 09, 00, 0a, 00, 00, 0e, 00, 19, 00, 00, 1a, 00, 1b, 00, 00, 20, 00, 22, 00, 01, 0e, 00, 10, 00, 02, 01, 00, 02] @@ -130,6 +143,7 @@ Number of file 0 mappings: 7 - Code(Zero) at (prev + 0, 32) to (start + 0, 34) - Code(Zero) at (prev + 1, 14) to (start + 0, 16) - Code(Zero) at (prev + 2, 1) to (start + 0, 2) +Highest counter ID seen: (none) Function name: async::i Raw bytes (9): 0x[01, 01, 00, 01, 01, 2d, 01, 00, 13] @@ -138,6 +152,7 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 45, 1) to (start + 0, 19) +Highest counter ID seen: c0 Function name: async::i::{closure#0} Raw bytes (63): 0x[01, 01, 02, 07, 19, 11, 15, 0b, 01, 2d, 13, 04, 0c, 09, 05, 09, 00, 0a, 01, 00, 0e, 00, 18, 05, 00, 1c, 00, 21, 09, 00, 27, 00, 30, 15, 01, 09, 00, 0a, 0d, 00, 0e, 00, 17, 1d, 00, 1b, 00, 20, 15, 00, 24, 00, 26, 19, 01, 0e, 00, 10, 03, 02, 01, 00, 02] @@ -159,6 +174,7 @@ Number of file 0 mappings: 11 - Code(Counter(6)) at (prev + 1, 14) to (start + 0, 16) - Code(Expression(0, Add)) at (prev + 2, 1) to (start + 0, 2) = ((c4 + c5) + c6) +Highest counter ID seen: c7 Function name: async::j Raw bytes (58): 0x[01, 01, 02, 07, 0d, 05, 09, 0a, 01, 38, 01, 00, 0d, 01, 0b, 0b, 00, 0c, 05, 01, 09, 00, 0a, 01, 00, 0e, 00, 1b, 05, 00, 1f, 00, 27, 09, 01, 09, 00, 0a, 11, 00, 0e, 00, 1a, 09, 00, 1e, 00, 20, 0d, 01, 0e, 00, 10, 03, 02, 01, 00, 02] @@ -179,6 +195,7 @@ Number of file 0 mappings: 10 - Code(Counter(3)) at (prev + 1, 14) to (start + 0, 16) - Code(Expression(0, Add)) at (prev + 2, 1) to (start + 0, 2) = ((c1 + c2) + c3) +Highest counter ID seen: c4 Function name: async::j::c Raw bytes (26): 0x[01, 01, 01, 01, 05, 04, 01, 3a, 05, 01, 12, 05, 02, 0d, 00, 0e, 02, 02, 0d, 00, 0e, 01, 02, 05, 00, 06] @@ -192,6 +209,7 @@ Number of file 0 mappings: 4 - Code(Expression(0, Sub)) at (prev + 2, 13) to (start + 0, 14) = (c0 - c1) - Code(Counter(0)) at (prev + 2, 5) to (start + 0, 6) +Highest counter ID seen: c1 Function name: async::j::d Raw bytes (9): 0x[01, 01, 00, 01, 01, 41, 05, 00, 17] @@ -200,6 +218,7 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 65, 5) to (start + 0, 23) +Highest counter ID seen: c0 Function name: async::j::f Raw bytes (9): 0x[01, 01, 00, 01, 01, 42, 05, 00, 17] @@ -208,6 +227,7 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 66, 5) to (start + 0, 23) +Highest counter ID seen: c0 Function name: async::k (unused) Raw bytes (29): 0x[01, 01, 00, 05, 00, 4a, 01, 01, 0c, 00, 02, 0e, 00, 10, 00, 01, 0e, 00, 10, 00, 01, 0e, 00, 10, 00, 02, 01, 00, 02] @@ -220,6 +240,7 @@ Number of file 0 mappings: 5 - Code(Zero) at (prev + 1, 14) to (start + 0, 16) - Code(Zero) at (prev + 1, 14) to (start + 0, 16) - Code(Zero) at (prev + 2, 1) to (start + 0, 2) +Highest counter ID seen: (none) Function name: async::l Raw bytes (37): 0x[01, 01, 04, 01, 07, 05, 09, 0f, 02, 09, 05, 05, 01, 52, 01, 01, 0c, 02, 02, 0e, 00, 10, 05, 01, 0e, 00, 10, 09, 01, 0e, 00, 10, 0b, 02, 01, 00, 02] @@ -238,6 +259,7 @@ Number of file 0 mappings: 5 - Code(Counter(2)) at (prev + 1, 14) to (start + 0, 16) - Code(Expression(2, Add)) at (prev + 2, 1) to (start + 0, 2) = ((c2 + c1) + (c0 - (c1 + c2))) +Highest counter ID seen: c2 Function name: async::m Raw bytes (9): 0x[01, 01, 00, 01, 01, 5a, 01, 00, 19] @@ -246,6 +268,7 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 90, 1) to (start + 0, 25) +Highest counter ID seen: c0 Function name: async::m::{closure#0} (unused) Raw bytes (9): 0x[01, 01, 00, 01, 00, 5a, 19, 00, 22] @@ -254,6 +277,7 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Zero) at (prev + 90, 25) to (start + 0, 34) +Highest counter ID seen: (none) Function name: async::main Raw bytes (9): 0x[01, 01, 00, 01, 01, 5c, 01, 08, 02] @@ -262,4 +286,5 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 92, 1) to (start + 8, 2) +Highest counter ID seen: c0 diff --git a/tests/coverage/async2.cov-map b/tests/coverage/async2.cov-map index 3816401ac6346..ed61e91efc29a 100644 --- a/tests/coverage/async2.cov-map +++ b/tests/coverage/async2.cov-map @@ -5,6 +5,7 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 16, 1) to (start + 0, 23) +Highest counter ID seen: c0 Function name: async2::async_func::{closure#0} Raw bytes (24): 0x[01, 01, 00, 04, 01, 10, 17, 03, 09, 05, 03, 0a, 02, 06, 00, 02, 06, 00, 07, 01, 01, 01, 00, 02] @@ -16,6 +17,7 @@ Number of file 0 mappings: 4 - Code(Counter(1)) at (prev + 3, 10) to (start + 2, 6) - Code(Zero) at (prev + 2, 6) to (start + 0, 7) - Code(Counter(0)) at (prev + 1, 1) to (start + 0, 2) +Highest counter ID seen: c1 Function name: async2::async_func_just_println Raw bytes (9): 0x[01, 01, 00, 01, 01, 18, 01, 00, 24] @@ -24,6 +26,7 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 24, 1) to (start + 0, 36) +Highest counter ID seen: c0 Function name: async2::async_func_just_println::{closure#0} Raw bytes (9): 0x[01, 01, 00, 01, 01, 18, 24, 02, 02] @@ -32,6 +35,7 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 24, 36) to (start + 2, 2) +Highest counter ID seen: c0 Function name: async2::main Raw bytes (9): 0x[01, 01, 00, 01, 01, 1c, 01, 07, 02] @@ -40,6 +44,7 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 28, 1) to (start + 7, 2) +Highest counter ID seen: c0 Function name: async2::non_async_func Raw bytes (24): 0x[01, 01, 00, 04, 01, 08, 01, 03, 09, 05, 03, 0a, 02, 06, 00, 02, 06, 00, 07, 01, 01, 01, 00, 02] @@ -51,4 +56,5 @@ Number of file 0 mappings: 4 - Code(Counter(1)) at (prev + 3, 10) to (start + 2, 6) - Code(Zero) at (prev + 2, 6) to (start + 0, 7) - Code(Counter(0)) at (prev + 1, 1) to (start + 0, 2) +Highest counter ID seen: c1 diff --git a/tests/coverage/async_block.cov-map b/tests/coverage/async_block.cov-map index 65f3d821f6e46..e3309bd51b40a 100644 --- a/tests/coverage/async_block.cov-map +++ b/tests/coverage/async_block.cov-map @@ -12,6 +12,7 @@ Number of file 0 mappings: 6 - Code(Counter(1)) at (prev + 0, 20) to (start + 1, 22) - Code(Counter(1)) at (prev + 7, 10) to (start + 2, 6) - Code(Counter(0)) at (prev + 3, 1) to (start + 0, 2) +Highest counter ID seen: c1 Function name: async_block::main::{closure#0} Raw bytes (26): 0x[01, 01, 01, 01, 05, 04, 01, 0a, 1c, 01, 17, 05, 01, 18, 02, 0e, 02, 02, 14, 02, 0e, 01, 03, 09, 00, 0a] @@ -25,4 +26,5 @@ Number of file 0 mappings: 4 - Code(Expression(0, Sub)) at (prev + 2, 20) to (start + 2, 14) = (c0 - c1) - Code(Counter(0)) at (prev + 3, 9) to (start + 0, 10) +Highest counter ID seen: c1 diff --git a/tests/coverage/attr/impl.cov-map b/tests/coverage/attr/impl.cov-map index 9b0deed8b64c0..4d068c290f42f 100644 --- a/tests/coverage/attr/impl.cov-map +++ b/tests/coverage/attr/impl.cov-map @@ -5,6 +5,7 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Zero) at (prev + 14, 5) to (start + 0, 19) +Highest counter ID seen: (none) Function name: ::on_inherit (unused) Raw bytes (9): 0x[01, 01, 00, 01, 00, 16, 05, 00, 17] @@ -13,6 +14,7 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Zero) at (prev + 22, 5) to (start + 0, 23) +Highest counter ID seen: (none) Function name: ::on_on (unused) Raw bytes (9): 0x[01, 01, 00, 01, 00, 19, 05, 00, 12] @@ -21,4 +23,5 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Zero) at (prev + 25, 5) to (start + 0, 18) +Highest counter ID seen: (none) diff --git a/tests/coverage/attr/module.cov-map b/tests/coverage/attr/module.cov-map index 34898eb4ca81d..b318ac85a6c85 100644 --- a/tests/coverage/attr/module.cov-map +++ b/tests/coverage/attr/module.cov-map @@ -5,6 +5,7 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Zero) at (prev + 12, 5) to (start + 0, 15) +Highest counter ID seen: (none) Function name: module::on::inherit (unused) Raw bytes (9): 0x[01, 01, 00, 01, 00, 14, 05, 00, 14] @@ -13,6 +14,7 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Zero) at (prev + 20, 5) to (start + 0, 20) +Highest counter ID seen: (none) Function name: module::on::on (unused) Raw bytes (9): 0x[01, 01, 00, 01, 00, 17, 05, 00, 0f] @@ -21,4 +23,5 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Zero) at (prev + 23, 5) to (start + 0, 15) +Highest counter ID seen: (none) diff --git a/tests/coverage/attr/nested.cov-map b/tests/coverage/attr/nested.cov-map index 466aec8956e0e..2bd9532537325 100644 --- a/tests/coverage/attr/nested.cov-map +++ b/tests/coverage/attr/nested.cov-map @@ -6,6 +6,7 @@ Number of expressions: 0 Number of file 0 mappings: 2 - Code(Counter(0)) at (prev + 63, 1) to (start + 1, 15) - Code(Counter(0)) at (prev + 11, 5) to (start + 1, 2) +Highest counter ID seen: c0 Function name: nested::closure_tail Raw bytes (14): 0x[01, 01, 00, 02, 01, 4e, 01, 01, 0f, 01, 11, 05, 01, 02] @@ -15,4 +16,5 @@ Number of expressions: 0 Number of file 0 mappings: 2 - Code(Counter(0)) at (prev + 78, 1) to (start + 1, 15) - Code(Counter(0)) at (prev + 17, 5) to (start + 1, 2) +Highest counter ID seen: c0 diff --git a/tests/coverage/attr/off-on-sandwich.cov-map b/tests/coverage/attr/off-on-sandwich.cov-map index d5fbac6ebf74b..ae5c9bd19a29b 100644 --- a/tests/coverage/attr/off-on-sandwich.cov-map +++ b/tests/coverage/attr/off-on-sandwich.cov-map @@ -6,6 +6,7 @@ Number of expressions: 0 Number of file 0 mappings: 2 - Code(Counter(0)) at (prev + 15, 5) to (start + 2, 18) - Code(Counter(0)) at (prev + 7, 5) to (start + 0, 6) +Highest counter ID seen: c0 Function name: off_on_sandwich::sparse_a::sparse_b::sparse_c Raw bytes (14): 0x[01, 01, 00, 02, 01, 21, 09, 02, 17, 01, 0b, 09, 00, 0a] @@ -15,6 +16,7 @@ Number of expressions: 0 Number of file 0 mappings: 2 - Code(Counter(0)) at (prev + 33, 9) to (start + 2, 23) - Code(Counter(0)) at (prev + 11, 9) to (start + 0, 10) +Highest counter ID seen: c0 Function name: off_on_sandwich::sparse_a::sparse_b::sparse_c::sparse_d Raw bytes (14): 0x[01, 01, 00, 02, 01, 24, 0d, 02, 1b, 01, 07, 0d, 00, 0e] @@ -24,4 +26,5 @@ Number of expressions: 0 Number of file 0 mappings: 2 - Code(Counter(0)) at (prev + 36, 13) to (start + 2, 27) - Code(Counter(0)) at (prev + 7, 13) to (start + 0, 14) +Highest counter ID seen: c0 diff --git a/tests/coverage/await_ready.cov-map b/tests/coverage/await_ready.cov-map index 38c2cf7b2d36c..95dbf68a191c4 100644 --- a/tests/coverage/await_ready.cov-map +++ b/tests/coverage/await_ready.cov-map @@ -5,6 +5,7 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 15, 1) to (start + 0, 30) +Highest counter ID seen: c0 Function name: await_ready::await_ready::{closure#0} Raw bytes (14): 0x[01, 01, 00, 02, 01, 0f, 1e, 03, 0f, 05, 04, 01, 00, 02] @@ -14,4 +15,5 @@ Number of expressions: 0 Number of file 0 mappings: 2 - Code(Counter(0)) at (prev + 15, 30) to (start + 3, 15) - Code(Counter(1)) at (prev + 4, 1) to (start + 0, 2) +Highest counter ID seen: c1 diff --git a/tests/coverage/bad_counter_ids.cov-map b/tests/coverage/bad_counter_ids.cov-map index 7eff7f5f02f3c..2b5399f33bbd3 100644 --- a/tests/coverage/bad_counter_ids.cov-map +++ b/tests/coverage/bad_counter_ids.cov-map @@ -6,6 +6,7 @@ Number of expressions: 0 Number of file 0 mappings: 2 - Code(Counter(0)) at (prev + 36, 1) to (start + 2, 31) - Code(Zero) at (prev + 3, 1) to (start + 0, 2) +Highest counter ID seen: c0 Function name: bad_counter_ids::eq_bad_message Raw bytes (21): 0x[01, 01, 01, 01, 00, 03, 01, 29, 01, 02, 0f, 02, 02, 20, 00, 2b, 00, 01, 01, 00, 02] @@ -18,6 +19,7 @@ Number of file 0 mappings: 3 - Code(Expression(0, Sub)) at (prev + 2, 32) to (start + 0, 43) = (c0 - Zero) - Code(Zero) at (prev + 1, 1) to (start + 0, 2) +Highest counter ID seen: c0 Function name: bad_counter_ids::eq_good Raw bytes (14): 0x[01, 01, 00, 02, 01, 10, 01, 02, 1f, 05, 03, 01, 00, 02] @@ -27,6 +29,7 @@ Number of expressions: 0 Number of file 0 mappings: 2 - Code(Counter(0)) at (prev + 16, 1) to (start + 2, 31) - Code(Counter(1)) at (prev + 3, 1) to (start + 0, 2) +Highest counter ID seen: c1 Function name: bad_counter_ids::eq_good_message Raw bytes (19): 0x[01, 01, 00, 03, 01, 15, 01, 02, 0f, 00, 02, 20, 00, 2b, 05, 01, 01, 00, 02] @@ -37,6 +40,7 @@ Number of file 0 mappings: 3 - Code(Counter(0)) at (prev + 21, 1) to (start + 2, 15) - Code(Zero) at (prev + 2, 32) to (start + 0, 43) - Code(Counter(1)) at (prev + 1, 1) to (start + 0, 2) +Highest counter ID seen: c1 Function name: bad_counter_ids::ne_bad Raw bytes (14): 0x[01, 01, 00, 02, 01, 2e, 01, 02, 1f, 00, 03, 01, 00, 02] @@ -46,6 +50,7 @@ Number of expressions: 0 Number of file 0 mappings: 2 - Code(Counter(0)) at (prev + 46, 1) to (start + 2, 31) - Code(Zero) at (prev + 3, 1) to (start + 0, 2) +Highest counter ID seen: c0 Function name: bad_counter_ids::ne_bad_message Raw bytes (19): 0x[01, 01, 00, 03, 01, 33, 01, 02, 0f, 05, 02, 20, 00, 2b, 00, 01, 01, 00, 02] @@ -56,6 +61,7 @@ Number of file 0 mappings: 3 - Code(Counter(0)) at (prev + 51, 1) to (start + 2, 15) - Code(Counter(1)) at (prev + 2, 32) to (start + 0, 43) - Code(Zero) at (prev + 1, 1) to (start + 0, 2) +Highest counter ID seen: c1 Function name: bad_counter_ids::ne_good Raw bytes (16): 0x[01, 01, 01, 01, 00, 02, 01, 1a, 01, 02, 1f, 02, 03, 01, 00, 02] @@ -67,6 +73,7 @@ Number of file 0 mappings: 2 - Code(Counter(0)) at (prev + 26, 1) to (start + 2, 31) - Code(Expression(0, Sub)) at (prev + 3, 1) to (start + 0, 2) = (c0 - Zero) +Highest counter ID seen: c0 Function name: bad_counter_ids::ne_good_message Raw bytes (21): 0x[01, 01, 01, 01, 00, 03, 01, 1f, 01, 02, 0f, 00, 02, 20, 00, 2b, 02, 01, 01, 00, 02] @@ -79,4 +86,5 @@ Number of file 0 mappings: 3 - Code(Zero) at (prev + 2, 32) to (start + 0, 43) - Code(Expression(0, Sub)) at (prev + 1, 1) to (start + 0, 2) = (c0 - Zero) +Highest counter ID seen: c0 diff --git a/tests/coverage/bench.cov-map b/tests/coverage/bench.cov-map index aa702a4868185..9ee6510f69048 100644 --- a/tests/coverage/bench.cov-map +++ b/tests/coverage/bench.cov-map @@ -5,4 +5,5 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 8, 1) to (start + 0, 39) +Highest counter ID seen: c0 diff --git a/tests/coverage/branch/generics.cov-map b/tests/coverage/branch/generics.cov-map index 2e5668c8b568e..656890634ff4e 100644 --- a/tests/coverage/branch/generics.cov-map +++ b/tests/coverage/branch/generics.cov-map @@ -13,6 +13,7 @@ Number of file 0 mappings: 5 - Code(Expression(0, Sub)) at (prev + 2, 12) to (start + 2, 6) = (c0 - c1) - Code(Counter(0)) at (prev + 3, 1) to (start + 0, 2) +Highest counter ID seen: c1 Function name: generics::print_size:: Raw bytes (33): 0x[01, 01, 01, 01, 05, 05, 01, 06, 01, 01, 24, 20, 05, 02, 01, 08, 00, 24, 05, 00, 25, 02, 06, 02, 02, 0c, 02, 06, 01, 03, 01, 00, 02] @@ -29,6 +30,7 @@ Number of file 0 mappings: 5 - Code(Expression(0, Sub)) at (prev + 2, 12) to (start + 2, 6) = (c0 - c1) - Code(Counter(0)) at (prev + 3, 1) to (start + 0, 2) +Highest counter ID seen: c1 Function name: generics::print_size:: Raw bytes (33): 0x[01, 01, 01, 01, 05, 05, 01, 06, 01, 01, 24, 20, 05, 02, 01, 08, 00, 24, 05, 00, 25, 02, 06, 02, 02, 0c, 02, 06, 01, 03, 01, 00, 02] @@ -45,4 +47,5 @@ Number of file 0 mappings: 5 - Code(Expression(0, Sub)) at (prev + 2, 12) to (start + 2, 6) = (c0 - c1) - Code(Counter(0)) at (prev + 3, 1) to (start + 0, 2) +Highest counter ID seen: c1 diff --git a/tests/coverage/branch/guard.cov-map b/tests/coverage/branch/guard.cov-map index d67c3d349a14e..0f33ed17a0acc 100644 --- a/tests/coverage/branch/guard.cov-map +++ b/tests/coverage/branch/guard.cov-map @@ -29,4 +29,5 @@ Number of file 0 mappings: 13 = (c1 + c2) - Code(Expression(2, Add)) at (prev + 4, 1) to (start + 0, 2) = ((((c1 + c2) + c3) + c4) + c5) +Highest counter ID seen: c7 diff --git a/tests/coverage/branch/if-let.cov-map b/tests/coverage/branch/if-let.cov-map index 0b098bc6497ce..380765c7af4bc 100644 --- a/tests/coverage/branch/if-let.cov-map +++ b/tests/coverage/branch/if-let.cov-map @@ -16,6 +16,7 @@ Number of file 0 mappings: 7 = (c1 - c2) - Code(Counter(2)) at (prev + 2, 12) to (start + 2, 6) - Code(Counter(1)) at (prev + 3, 5) to (start + 1, 2) +Highest counter ID seen: c2 Function name: if_let::if_let_chain Raw bytes (66): 0x[01, 01, 04, 01, 05, 05, 09, 0f, 0d, 05, 09, 0a, 01, 17, 01, 00, 33, 20, 02, 05, 01, 0c, 00, 13, 02, 00, 11, 00, 12, 01, 00, 16, 00, 17, 20, 0d, 09, 01, 10, 00, 17, 0d, 00, 15, 00, 16, 02, 00, 1a, 00, 1b, 0d, 01, 05, 03, 06, 0f, 03, 0c, 02, 06, 0b, 03, 05, 01, 02] @@ -45,4 +46,5 @@ Number of file 0 mappings: 10 = (c1 + c2) - Code(Expression(2, Add)) at (prev + 3, 5) to (start + 1, 2) = ((c1 + c2) + c3) +Highest counter ID seen: c3 diff --git a/tests/coverage/branch/if.cov-map b/tests/coverage/branch/if.cov-map index 7f4ee980e2620..4a8cb664dd831 100644 --- a/tests/coverage/branch/if.cov-map +++ b/tests/coverage/branch/if.cov-map @@ -22,6 +22,7 @@ Number of file 0 mappings: 8 = (c3 + (c1 - c2)) - Code(Expression(2, Add)) at (prev + 3, 1) to (start + 0, 2) = (c4 + (c3 + (c1 - c2))) +Highest counter ID seen: c4 Function name: if::branch_not Raw bytes (116): 0x[01, 01, 07, 05, 09, 05, 0d, 05, 0d, 05, 11, 05, 11, 05, 15, 05, 15, 12, 01, 0c, 01, 01, 10, 05, 03, 08, 00, 09, 20, 09, 02, 00, 08, 00, 09, 09, 01, 09, 00, 11, 02, 01, 06, 00, 07, 05, 01, 08, 00, 0a, 20, 0a, 0d, 00, 08, 00, 0a, 0a, 00, 0b, 02, 06, 0d, 02, 06, 00, 07, 05, 01, 08, 00, 0b, 20, 11, 12, 00, 08, 00, 0b, 11, 00, 0c, 02, 06, 12, 02, 06, 00, 07, 05, 01, 08, 00, 0c, 20, 1a, 15, 00, 08, 00, 0c, 1a, 00, 0d, 02, 06, 15, 02, 06, 00, 07, 05, 01, 01, 00, 02] @@ -66,6 +67,7 @@ Number of file 0 mappings: 18 = (c1 - c5) - Code(Counter(5)) at (prev + 2, 6) to (start + 0, 7) - Code(Counter(1)) at (prev + 1, 1) to (start + 0, 2) +Highest counter ID seen: c5 Function name: if::branch_not_as Raw bytes (90): 0x[01, 01, 05, 05, 09, 05, 0d, 05, 0d, 05, 11, 05, 11, 0e, 01, 1d, 01, 01, 10, 05, 03, 08, 00, 14, 20, 02, 09, 00, 08, 00, 14, 02, 00, 15, 02, 06, 09, 02, 06, 00, 07, 05, 01, 08, 00, 15, 20, 0d, 0a, 00, 08, 00, 15, 0d, 00, 16, 02, 06, 0a, 02, 06, 00, 07, 05, 01, 08, 00, 16, 20, 12, 11, 00, 08, 00, 16, 12, 00, 17, 02, 06, 11, 02, 06, 00, 07, 05, 01, 01, 00, 02] @@ -101,6 +103,7 @@ Number of file 0 mappings: 14 = (c1 - c4) - Code(Counter(4)) at (prev + 2, 6) to (start + 0, 7) - Code(Counter(1)) at (prev + 1, 1) to (start + 0, 2) +Highest counter ID seen: c4 Function name: if::branch_or Raw bytes (56): 0x[01, 01, 04, 05, 09, 09, 0d, 0f, 11, 09, 0d, 08, 01, 35, 01, 01, 10, 05, 03, 08, 00, 09, 20, 09, 02, 00, 08, 00, 09, 02, 00, 0d, 00, 0e, 20, 0d, 11, 00, 0d, 00, 0e, 0f, 00, 0f, 02, 06, 11, 02, 0c, 02, 06, 0b, 03, 01, 00, 02] @@ -127,4 +130,5 @@ Number of file 0 mappings: 8 - Code(Counter(4)) at (prev + 2, 12) to (start + 2, 6) - Code(Expression(2, Add)) at (prev + 3, 1) to (start + 0, 2) = ((c2 + c3) + c4) +Highest counter ID seen: c4 diff --git a/tests/coverage/branch/lazy-boolean.cov-map b/tests/coverage/branch/lazy-boolean.cov-map index 09ce91376733b..c2b6a5b8df24b 100644 --- a/tests/coverage/branch/lazy-boolean.cov-map +++ b/tests/coverage/branch/lazy-boolean.cov-map @@ -13,6 +13,7 @@ Number of file 0 mappings: 6 false = (c1 - c2) - Code(Counter(2)) at (prev + 0, 18) to (start + 0, 19) - Code(Counter(1)) at (prev + 1, 5) to (start + 1, 2) +Highest counter ID seen: c2 Function name: lazy_boolean::branch_or Raw bytes (38): 0x[01, 01, 01, 05, 09, 06, 01, 1b, 01, 01, 10, 05, 04, 09, 00, 0a, 05, 00, 0d, 00, 0e, 20, 09, 02, 00, 0d, 00, 0e, 02, 00, 12, 00, 13, 05, 01, 05, 01, 02] @@ -30,6 +31,7 @@ Number of file 0 mappings: 6 - Code(Expression(0, Sub)) at (prev + 0, 18) to (start + 0, 19) = (c1 - c2) - Code(Counter(1)) at (prev + 1, 5) to (start + 1, 2) +Highest counter ID seen: c2 Function name: lazy_boolean::chain Raw bytes (149): 0x[01, 01, 13, 11, 07, 0b, 16, 15, 1a, 09, 0d, 05, 09, 05, 09, 09, 0d, 47, 25, 4b, 21, 19, 1d, 03, 19, 03, 19, 3e, 1d, 03, 19, 3e, 1d, 03, 19, 47, 25, 4b, 21, 19, 1d, 13, 01, 24, 01, 01, 10, 03, 04, 09, 00, 0a, 05, 00, 0d, 00, 12, 20, 09, 16, 00, 0d, 00, 12, 09, 00, 16, 00, 1b, 20, 0d, 1a, 00, 16, 00, 1b, 0d, 00, 1f, 00, 24, 20, 11, 15, 00, 1f, 00, 24, 11, 00, 28, 00, 2d, 03, 01, 05, 00, 11, 43, 03, 09, 00, 0a, 03, 00, 0d, 00, 12, 20, 19, 3e, 00, 0d, 00, 12, 3e, 00, 16, 00, 1b, 20, 1d, 3a, 00, 16, 00, 1b, 3a, 00, 1f, 00, 24, 20, 21, 25, 00, 1f, 00, 24, 25, 00, 28, 00, 2d, 43, 01, 05, 01, 02] @@ -94,6 +96,7 @@ Number of file 0 mappings: 19 - Code(Counter(9)) at (prev + 0, 40) to (start + 0, 45) - Code(Expression(16, Add)) at (prev + 1, 5) to (start + 1, 2) = (((c6 + c7) + c8) + c9) +Highest counter ID seen: c9 Function name: lazy_boolean::nested_mixed Raw bytes (155): 0x[01, 01, 16, 33, 1a, 09, 0d, 1e, 0d, 05, 09, 05, 09, 05, 09, 1e, 0d, 05, 09, 09, 0d, 33, 11, 09, 0d, 33, 11, 09, 0d, 19, 57, 1d, 21, 03, 15, 15, 19, 4a, 4e, 15, 19, 03, 15, 19, 57, 1d, 21, 13, 01, 31, 01, 01, 10, 03, 04, 09, 00, 0a, 05, 00, 0e, 00, 13, 20, 09, 1e, 00, 0e, 00, 13, 1e, 00, 17, 00, 1d, 20, 0d, 1a, 00, 17, 00, 1d, 33, 00, 23, 00, 28, 20, 11, 2e, 00, 23, 00, 28, 2e, 00, 2c, 00, 33, 03, 01, 05, 00, 11, 53, 03, 09, 00, 0a, 03, 00, 0e, 00, 13, 20, 15, 4e, 00, 0e, 00, 13, 15, 00, 17, 00, 1c, 20, 19, 4a, 00, 17, 00, 1c, 47, 00, 22, 00, 28, 20, 1d, 21, 00, 22, 00, 28, 1d, 00, 2c, 00, 33, 53, 01, 05, 01, 02] @@ -163,4 +166,5 @@ Number of file 0 mappings: 19 - Code(Counter(7)) at (prev + 0, 44) to (start + 0, 51) - Code(Expression(20, Add)) at (prev + 1, 5) to (start + 1, 2) = (c6 + (c7 + c8)) +Highest counter ID seen: c8 diff --git a/tests/coverage/branch/let-else.cov-map b/tests/coverage/branch/let-else.cov-map index 0707993446478..e6bf7ed6a9258 100644 --- a/tests/coverage/branch/let-else.cov-map +++ b/tests/coverage/branch/let-else.cov-map @@ -16,4 +16,5 @@ Number of file 0 mappings: 7 - Code(Expression(0, Sub)) at (prev + 4, 5) to (start + 0, 11) = (c1 - c2) - Code(Counter(1)) at (prev + 1, 1) to (start + 0, 2) +Highest counter ID seen: c2 diff --git a/tests/coverage/branch/match-arms.cov-map b/tests/coverage/branch/match-arms.cov-map index 1f17f11baaa07..fd0366ee81838 100644 --- a/tests/coverage/branch/match-arms.cov-map +++ b/tests/coverage/branch/match-arms.cov-map @@ -34,6 +34,7 @@ Number of file 0 mappings: 12 = ((((Zero + c2) + c3) + c4) + c5) - Code(Expression(4, Add)) at (prev + 3, 5) to (start + 1, 2) = ((((((((Zero + c2) + c3) + c4) + c5) + c6) + c7) + c8) + c9) +Highest counter ID seen: c10 Function name: match_arms::match_arms Raw bytes (51): 0x[01, 01, 06, 05, 07, 0b, 11, 09, 0d, 13, 02, 17, 09, 11, 0d, 07, 01, 18, 01, 01, 10, 05, 03, 0b, 00, 10, 11, 01, 11, 00, 21, 0d, 01, 11, 00, 21, 09, 01, 11, 00, 21, 02, 01, 11, 00, 21, 0f, 03, 05, 01, 02] @@ -56,6 +57,7 @@ Number of file 0 mappings: 7 = (c1 - ((c2 + c3) + c4)) - Code(Expression(3, Add)) at (prev + 3, 5) to (start + 1, 2) = (((c4 + c3) + c2) + (c1 - ((c2 + c3) + c4))) +Highest counter ID seen: c4 Function name: match_arms::or_patterns Raw bytes (75): 0x[01, 01, 0d, 11, 0d, 05, 2f, 33, 11, 09, 0d, 09, 2a, 05, 2f, 33, 11, 09, 0d, 03, 27, 09, 2a, 05, 2f, 33, 11, 09, 0d, 09, 01, 25, 01, 01, 10, 05, 03, 0b, 00, 10, 11, 01, 11, 00, 12, 0d, 00, 1e, 00, 1f, 03, 00, 24, 00, 2e, 09, 01, 11, 00, 12, 2a, 00, 1e, 00, 1f, 27, 00, 24, 00, 2e, 23, 03, 05, 01, 02] @@ -89,4 +91,5 @@ Number of file 0 mappings: 9 = (c2 + (c1 - ((c2 + c3) + c4))) - Code(Expression(8, Add)) at (prev + 3, 5) to (start + 1, 2) = ((c4 + c3) + (c2 + (c1 - ((c2 + c3) + c4)))) +Highest counter ID seen: c4 diff --git a/tests/coverage/branch/match-trivial.cov-map b/tests/coverage/branch/match-trivial.cov-map index 1136a529b255c..6af8ce46f5fae 100644 --- a/tests/coverage/branch/match-trivial.cov-map +++ b/tests/coverage/branch/match-trivial.cov-map @@ -5,6 +5,7 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Zero) at (prev + 22, 1) to (start + 1, 16) +Highest counter ID seen: (none) Function name: match_trivial::trivial Raw bytes (14): 0x[01, 01, 00, 02, 01, 1e, 01, 01, 10, 05, 03, 0b, 05, 02] @@ -14,4 +15,5 @@ Number of expressions: 0 Number of file 0 mappings: 2 - Code(Counter(0)) at (prev + 30, 1) to (start + 1, 16) - Code(Counter(1)) at (prev + 3, 11) to (start + 5, 2) +Highest counter ID seen: c1 diff --git a/tests/coverage/branch/no-mir-spans.cov-map b/tests/coverage/branch/no-mir-spans.cov-map index cb19211913f89..ab12732b1ed38 100644 --- a/tests/coverage/branch/no-mir-spans.cov-map +++ b/tests/coverage/branch/no-mir-spans.cov-map @@ -8,6 +8,7 @@ Number of file 0 mappings: 2 - Branch { true: Counter(1), false: Counter(2) } at (prev + 4, 11) to (start + 0, 16) true = c1 false = c2 +Highest counter ID seen: c2 Function name: no_mir_spans::while_cond_not Raw bytes (16): 0x[01, 01, 00, 02, 01, 19, 01, 00, 15, 20, 09, 05, 04, 0b, 00, 14] @@ -19,6 +20,7 @@ Number of file 0 mappings: 2 - Branch { true: Counter(2), false: Counter(1) } at (prev + 4, 11) to (start + 0, 20) true = c2 false = c1 +Highest counter ID seen: c2 Function name: no_mir_spans::while_op_and Raw bytes (25): 0x[01, 01, 01, 09, 0d, 03, 01, 22, 01, 00, 13, 20, 09, 05, 05, 0b, 00, 10, 20, 02, 0d, 00, 14, 00, 19] @@ -34,6 +36,7 @@ Number of file 0 mappings: 3 - Branch { true: Expression(0, Sub), false: Counter(3) } at (prev + 0, 20) to (start + 0, 25) true = (c2 - c3) false = c3 +Highest counter ID seen: c3 Function name: no_mir_spans::while_op_or Raw bytes (25): 0x[01, 01, 01, 09, 0d, 03, 01, 2d, 01, 00, 12, 20, 05, 09, 05, 0b, 00, 10, 20, 0d, 02, 00, 14, 00, 19] @@ -49,4 +52,5 @@ Number of file 0 mappings: 3 - Branch { true: Counter(3), false: Expression(0, Sub) } at (prev + 0, 20) to (start + 0, 25) true = c3 false = (c2 - c3) +Highest counter ID seen: c3 diff --git a/tests/coverage/branch/while.cov-map b/tests/coverage/branch/while.cov-map index fd05bbb69a556..d5840a2c320be 100644 --- a/tests/coverage/branch/while.cov-map +++ b/tests/coverage/branch/while.cov-map @@ -14,6 +14,7 @@ Number of file 0 mappings: 6 false = c1 - Code(Counter(2)) at (prev + 0, 17) to (start + 2, 6) - Code(Counter(1)) at (prev + 3, 1) to (start + 0, 2) +Highest counter ID seen: c2 Function name: while::while_cond_not Raw bytes (38): 0x[01, 01, 01, 05, 09, 06, 01, 15, 01, 01, 10, 05, 03, 09, 00, 12, 03, 01, 0b, 00, 14, 20, 09, 05, 00, 0b, 00, 14, 09, 00, 15, 02, 06, 05, 03, 01, 00, 02] @@ -31,6 +32,7 @@ Number of file 0 mappings: 6 false = c1 - Code(Counter(2)) at (prev + 0, 21) to (start + 2, 6) - Code(Counter(1)) at (prev + 3, 1) to (start + 0, 2) +Highest counter ID seen: c2 Function name: while::while_op_and Raw bytes (56): 0x[01, 01, 04, 05, 09, 03, 0d, 03, 0d, 11, 0d, 08, 01, 1e, 01, 01, 10, 05, 03, 09, 01, 12, 03, 02, 0b, 00, 10, 20, 0a, 0d, 00, 0b, 00, 10, 0a, 00, 14, 00, 19, 20, 09, 11, 00, 14, 00, 19, 09, 00, 1a, 03, 06, 0f, 04, 01, 00, 02] @@ -57,6 +59,7 @@ Number of file 0 mappings: 8 - Code(Counter(2)) at (prev + 0, 26) to (start + 3, 6) - Code(Expression(3, Add)) at (prev + 4, 1) to (start + 0, 2) = (c4 + c3) +Highest counter ID seen: c4 Function name: while::while_op_or Raw bytes (66): 0x[01, 01, 09, 05, 1b, 09, 0d, 03, 09, 03, 09, 22, 0d, 03, 09, 09, 0d, 22, 0d, 03, 09, 08, 01, 29, 01, 01, 10, 05, 03, 09, 01, 12, 03, 02, 0b, 00, 10, 20, 09, 22, 00, 0b, 00, 10, 22, 00, 14, 00, 19, 20, 0d, 1e, 00, 14, 00, 19, 1b, 00, 1a, 03, 06, 1e, 04, 01, 00, 02] @@ -89,4 +92,5 @@ Number of file 0 mappings: 8 = (c2 + c3) - Code(Expression(7, Sub)) at (prev + 4, 1) to (start + 0, 2) = (((c1 + (c2 + c3)) - c2) - c3) +Highest counter ID seen: c3 diff --git a/tests/coverage/closure.cov-map b/tests/coverage/closure.cov-map index 6edd35921fe95..d50f9f8e7afaa 100644 --- a/tests/coverage/closure.cov-map +++ b/tests/coverage/closure.cov-map @@ -30,6 +30,7 @@ Number of file 0 mappings: 24 - Code(Expression(0, Sub)) at (prev + 4, 6) to (start + 0, 7) = (c0 - c1) - Code(Counter(0)) at (prev + 1, 5) to (start + 3, 2) +Highest counter ID seen: c1 Function name: closure::main::{closure#0} Raw bytes (26): 0x[01, 01, 01, 01, 05, 04, 01, 28, 05, 02, 14, 05, 02, 15, 02, 0a, 02, 02, 0a, 00, 0b, 01, 01, 09, 01, 06] @@ -43,6 +44,7 @@ Number of file 0 mappings: 4 - Code(Expression(0, Sub)) at (prev + 2, 10) to (start + 0, 11) = (c0 - c1) - Code(Counter(0)) at (prev + 1, 9) to (start + 1, 6) +Highest counter ID seen: c1 Function name: closure::main::{closure#10} (unused) Raw bytes (10): 0x[01, 01, 00, 01, 00, 9b, 01, 07, 00, 21] @@ -51,6 +53,7 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Zero) at (prev + 155, 7) to (start + 0, 33) +Highest counter ID seen: (none) Function name: closure::main::{closure#11} (unused) Raw bytes (10): 0x[01, 01, 00, 01, 00, 9f, 01, 07, 00, 21] @@ -59,6 +62,7 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Zero) at (prev + 159, 7) to (start + 0, 33) +Highest counter ID seen: (none) Function name: closure::main::{closure#12} (unused) Raw bytes (10): 0x[01, 01, 00, 01, 00, a7, 01, 01, 00, 17] @@ -67,6 +71,7 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Zero) at (prev + 167, 1) to (start + 0, 23) +Highest counter ID seen: (none) Function name: closure::main::{closure#13} (unused) Raw bytes (10): 0x[01, 01, 00, 01, 00, ac, 01, 0d, 02, 0e] @@ -75,6 +80,7 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Zero) at (prev + 172, 13) to (start + 2, 14) +Highest counter ID seen: (none) Function name: closure::main::{closure#14} Raw bytes (27): 0x[01, 01, 01, 01, 05, 04, 01, b3, 01, 0d, 02, 1b, 05, 02, 1e, 00, 25, 02, 00, 2f, 00, 33, 01, 01, 0d, 00, 0e] @@ -88,6 +94,7 @@ Number of file 0 mappings: 4 - Code(Expression(0, Sub)) at (prev + 0, 47) to (start + 0, 51) = (c0 - c1) - Code(Counter(0)) at (prev + 1, 13) to (start + 0, 14) +Highest counter ID seen: c1 Function name: closure::main::{closure#15} Raw bytes (37): 0x[01, 01, 01, 01, 05, 06, 01, bb, 01, 09, 00, 0a, 01, 01, 0d, 00, 15, 01, 01, 11, 01, 1b, 05, 01, 1e, 00, 25, 02, 00, 2f, 00, 33, 01, 02, 09, 00, 0a] @@ -103,6 +110,7 @@ Number of file 0 mappings: 6 - Code(Expression(0, Sub)) at (prev + 0, 47) to (start + 0, 51) = (c0 - c1) - Code(Counter(0)) at (prev + 2, 9) to (start + 0, 10) +Highest counter ID seen: c1 Function name: closure::main::{closure#16} Raw bytes (27): 0x[01, 01, 01, 01, 05, 04, 01, c5, 01, 0d, 02, 1b, 05, 02, 1e, 00, 25, 02, 00, 2f, 00, 33, 01, 01, 0d, 00, 0e] @@ -116,6 +124,7 @@ Number of file 0 mappings: 4 - Code(Expression(0, Sub)) at (prev + 0, 47) to (start + 0, 51) = (c0 - c1) - Code(Counter(0)) at (prev + 1, 13) to (start + 0, 14) +Highest counter ID seen: c1 Function name: closure::main::{closure#17} Raw bytes (37): 0x[01, 01, 01, 01, 05, 06, 01, cd, 01, 09, 00, 0a, 01, 01, 0d, 00, 15, 01, 01, 11, 01, 1b, 05, 01, 1e, 00, 25, 02, 00, 2f, 00, 33, 01, 02, 09, 00, 0a] @@ -131,6 +140,7 @@ Number of file 0 mappings: 6 - Code(Expression(0, Sub)) at (prev + 0, 47) to (start + 0, 51) = (c0 - c1) - Code(Counter(0)) at (prev + 2, 9) to (start + 0, 10) +Highest counter ID seen: c1 Function name: closure::main::{closure#18} (unused) Raw bytes (24): 0x[01, 01, 00, 04, 00, 19, 0d, 02, 1c, 00, 02, 1d, 02, 12, 00, 02, 12, 00, 13, 00, 01, 11, 01, 0e] @@ -142,6 +152,7 @@ Number of file 0 mappings: 4 - Code(Zero) at (prev + 2, 29) to (start + 2, 18) - Code(Zero) at (prev + 2, 18) to (start + 0, 19) - Code(Zero) at (prev + 1, 17) to (start + 1, 14) +Highest counter ID seen: (none) Function name: closure::main::{closure#19} Raw bytes (26): 0x[01, 01, 01, 01, 05, 04, 01, 43, 0d, 02, 1c, 05, 02, 1d, 02, 12, 02, 02, 12, 00, 13, 01, 01, 11, 01, 0e] @@ -155,6 +166,7 @@ Number of file 0 mappings: 4 - Code(Expression(0, Sub)) at (prev + 2, 18) to (start + 0, 19) = (c0 - c1) - Code(Counter(0)) at (prev + 1, 17) to (start + 1, 14) +Highest counter ID seen: c1 Function name: closure::main::{closure#1} Raw bytes (26): 0x[01, 01, 01, 01, 05, 04, 01, 52, 05, 02, 14, 05, 02, 15, 02, 0a, 02, 02, 0a, 00, 0b, 01, 01, 09, 01, 06] @@ -168,6 +180,7 @@ Number of file 0 mappings: 4 - Code(Expression(0, Sub)) at (prev + 2, 10) to (start + 0, 11) = (c0 - c1) - Code(Counter(0)) at (prev + 1, 9) to (start + 1, 6) +Highest counter ID seen: c1 Function name: closure::main::{closure#2} Raw bytes (26): 0x[01, 01, 01, 01, 05, 04, 01, 68, 05, 02, 14, 05, 02, 15, 02, 0a, 02, 02, 0a, 00, 0b, 01, 01, 09, 01, 06] @@ -181,6 +194,7 @@ Number of file 0 mappings: 4 - Code(Expression(0, Sub)) at (prev + 2, 10) to (start + 0, 11) = (c0 - c1) - Code(Counter(0)) at (prev + 1, 9) to (start + 1, 6) +Highest counter ID seen: c1 Function name: closure::main::{closure#3} (unused) Raw bytes (25): 0x[01, 01, 00, 04, 00, 81, 01, 05, 01, 14, 00, 01, 15, 02, 0a, 00, 02, 0a, 00, 0b, 00, 01, 09, 01, 06] @@ -192,6 +206,7 @@ Number of file 0 mappings: 4 - Code(Zero) at (prev + 1, 21) to (start + 2, 10) - Code(Zero) at (prev + 2, 10) to (start + 0, 11) - Code(Zero) at (prev + 1, 9) to (start + 1, 6) +Highest counter ID seen: (none) Function name: closure::main::{closure#4} (unused) Raw bytes (10): 0x[01, 01, 00, 01, 00, 89, 01, 35, 00, 43] @@ -200,6 +215,7 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Zero) at (prev + 137, 53) to (start + 0, 67) +Highest counter ID seen: (none) Function name: closure::main::{closure#5} Raw bytes (10): 0x[01, 01, 00, 01, 01, 8c, 01, 3d, 00, 4f] @@ -208,6 +224,7 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 140, 61) to (start + 0, 79) +Highest counter ID seen: c0 Function name: closure::main::{closure#6} Raw bytes (10): 0x[01, 01, 00, 01, 01, 8d, 01, 41, 00, 57] @@ -216,6 +233,7 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 141, 65) to (start + 0, 87) +Highest counter ID seen: c0 Function name: closure::main::{closure#7} (unused) Raw bytes (10): 0x[01, 01, 00, 01, 00, 8e, 01, 3b, 00, 51] @@ -224,6 +242,7 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Zero) at (prev + 142, 59) to (start + 0, 81) +Highest counter ID seen: (none) Function name: closure::main::{closure#8} (unused) Raw bytes (10): 0x[01, 01, 00, 01, 00, 93, 01, 3b, 00, 55] @@ -232,6 +251,7 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Zero) at (prev + 147, 59) to (start + 0, 85) +Highest counter ID seen: (none) Function name: closure::main::{closure#9} (unused) Raw bytes (10): 0x[01, 01, 00, 01, 00, 95, 01, 38, 02, 06] @@ -240,4 +260,5 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Zero) at (prev + 149, 56) to (start + 2, 6) +Highest counter ID seen: (none) diff --git a/tests/coverage/closure_bug.cov-map b/tests/coverage/closure_bug.cov-map index 32e8db5fb2f4c..96e1e339e569e 100644 --- a/tests/coverage/closure_bug.cov-map +++ b/tests/coverage/closure_bug.cov-map @@ -29,6 +29,7 @@ Number of file 0 mappings: 17 - Code(Expression(3, Sub)) at (prev + 0, 23) to (start + 0, 24) = (c0 - c4) - Code(Counter(0)) at (prev + 1, 1) to (start + 0, 2) +Highest counter ID seen: c4 Function name: closure_bug::main::{closure#0} Raw bytes (26): 0x[01, 01, 01, 01, 05, 04, 01, 0e, 09, 00, 12, 05, 00, 15, 00, 19, 02, 00, 23, 00, 28, 01, 00, 29, 00, 2a] @@ -42,6 +43,7 @@ Number of file 0 mappings: 4 - Code(Expression(0, Sub)) at (prev + 0, 35) to (start + 0, 40) = (c0 - c1) - Code(Counter(0)) at (prev + 0, 41) to (start + 0, 42) +Highest counter ID seen: c1 Function name: closure_bug::main::{closure#1} Raw bytes (26): 0x[01, 01, 01, 01, 05, 04, 01, 17, 09, 00, 12, 05, 00, 15, 00, 19, 02, 00, 23, 00, 28, 01, 00, 29, 00, 2a] @@ -55,6 +57,7 @@ Number of file 0 mappings: 4 - Code(Expression(0, Sub)) at (prev + 0, 35) to (start + 0, 40) = (c0 - c1) - Code(Counter(0)) at (prev + 0, 41) to (start + 0, 42) +Highest counter ID seen: c1 Function name: closure_bug::main::{closure#2} Raw bytes (26): 0x[01, 01, 01, 01, 05, 04, 01, 20, 09, 00, 12, 05, 00, 15, 00, 19, 02, 00, 23, 00, 28, 01, 00, 29, 00, 2a] @@ -68,6 +71,7 @@ Number of file 0 mappings: 4 - Code(Expression(0, Sub)) at (prev + 0, 35) to (start + 0, 40) = (c0 - c1) - Code(Counter(0)) at (prev + 0, 41) to (start + 0, 42) +Highest counter ID seen: c1 Function name: closure_bug::main::{closure#3} Raw bytes (26): 0x[01, 01, 01, 01, 05, 04, 01, 29, 09, 00, 12, 05, 00, 15, 00, 19, 02, 00, 23, 00, 28, 01, 00, 29, 00, 2a] @@ -81,4 +85,5 @@ Number of file 0 mappings: 4 - Code(Expression(0, Sub)) at (prev + 0, 35) to (start + 0, 40) = (c0 - c1) - Code(Counter(0)) at (prev + 0, 41) to (start + 0, 42) +Highest counter ID seen: c1 diff --git a/tests/coverage/closure_macro.cov-map b/tests/coverage/closure_macro.cov-map index fb4a137d4c8ec..7c9d3292f988a 100644 --- a/tests/coverage/closure_macro.cov-map +++ b/tests/coverage/closure_macro.cov-map @@ -5,6 +5,7 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 29, 1) to (start + 2, 2) +Highest counter ID seen: c0 Function name: closure_macro::main Raw bytes (36): 0x[01, 01, 01, 01, 05, 06, 01, 21, 01, 01, 21, 02, 02, 09, 00, 0f, 01, 00, 12, 00, 54, 05, 00, 54, 00, 55, 02, 02, 09, 02, 0b, 01, 03, 01, 00, 02] @@ -21,6 +22,7 @@ Number of file 0 mappings: 6 - Code(Expression(0, Sub)) at (prev + 2, 9) to (start + 2, 11) = (c0 - c1) - Code(Counter(0)) at (prev + 3, 1) to (start + 0, 2) +Highest counter ID seen: c1 Function name: closure_macro::main::{closure#0} Raw bytes (35): 0x[01, 01, 03, 01, 05, 05, 0b, 09, 0d, 05, 01, 10, 1c, 03, 21, 05, 04, 11, 01, 27, 02, 03, 11, 00, 16, 0d, 00, 17, 00, 1e, 07, 02, 09, 00, 0a] @@ -38,4 +40,5 @@ Number of file 0 mappings: 5 - Code(Counter(3)) at (prev + 0, 23) to (start + 0, 30) - Code(Expression(1, Add)) at (prev + 2, 9) to (start + 0, 10) = (c1 + (c2 + c3)) +Highest counter ID seen: c3 diff --git a/tests/coverage/closure_macro_async.cov-map b/tests/coverage/closure_macro_async.cov-map index 091e87909f900..e2a52e57015c4 100644 --- a/tests/coverage/closure_macro_async.cov-map +++ b/tests/coverage/closure_macro_async.cov-map @@ -5,6 +5,7 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 34, 1) to (start + 2, 2) +Highest counter ID seen: c0 Function name: closure_macro_async::test Raw bytes (9): 0x[01, 01, 00, 01, 01, 26, 01, 00, 2b] @@ -13,6 +14,7 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 38, 1) to (start + 0, 43) +Highest counter ID seen: c0 Function name: closure_macro_async::test::{closure#0} Raw bytes (36): 0x[01, 01, 01, 01, 05, 06, 01, 26, 2b, 01, 21, 02, 02, 09, 00, 0f, 01, 00, 12, 00, 54, 05, 00, 54, 00, 55, 02, 02, 09, 02, 0b, 01, 03, 01, 00, 02] @@ -29,6 +31,7 @@ Number of file 0 mappings: 6 - Code(Expression(0, Sub)) at (prev + 2, 9) to (start + 2, 11) = (c0 - c1) - Code(Counter(0)) at (prev + 3, 1) to (start + 0, 2) +Highest counter ID seen: c1 Function name: closure_macro_async::test::{closure#0}::{closure#0} Raw bytes (35): 0x[01, 01, 03, 01, 05, 05, 0b, 09, 0d, 05, 01, 15, 1c, 03, 21, 05, 04, 11, 01, 27, 02, 03, 11, 00, 16, 0d, 00, 17, 00, 1e, 07, 02, 09, 00, 0a] @@ -46,4 +49,5 @@ Number of file 0 mappings: 5 - Code(Counter(3)) at (prev + 0, 23) to (start + 0, 30) - Code(Expression(1, Add)) at (prev + 2, 9) to (start + 0, 10) = (c1 + (c2 + c3)) +Highest counter ID seen: c3 diff --git a/tests/coverage/closure_unit_return.cov-map b/tests/coverage/closure_unit_return.cov-map index c97b4a44dd6b2..9a66e0b0e7729 100644 --- a/tests/coverage/closure_unit_return.cov-map +++ b/tests/coverage/closure_unit_return.cov-map @@ -6,6 +6,7 @@ Number of expressions: 0 Number of file 0 mappings: 2 - Code(Counter(0)) at (prev + 7, 1) to (start + 1, 16) - Code(Counter(0)) at (prev + 5, 5) to (start + 2, 2) +Highest counter ID seen: c0 Function name: closure_unit_return::explicit_unit::{closure#0} (unused) Raw bytes (9): 0x[01, 01, 00, 01, 00, 08, 16, 02, 06] @@ -14,6 +15,7 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Zero) at (prev + 8, 22) to (start + 2, 6) +Highest counter ID seen: (none) Function name: closure_unit_return::implicit_unit Raw bytes (14): 0x[01, 01, 00, 02, 01, 10, 01, 01, 10, 01, 05, 05, 02, 02] @@ -23,6 +25,7 @@ Number of expressions: 0 Number of file 0 mappings: 2 - Code(Counter(0)) at (prev + 16, 1) to (start + 1, 16) - Code(Counter(0)) at (prev + 5, 5) to (start + 2, 2) +Highest counter ID seen: c0 Function name: closure_unit_return::implicit_unit::{closure#0} (unused) Raw bytes (9): 0x[01, 01, 00, 01, 00, 11, 16, 02, 06] @@ -31,4 +34,5 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Zero) at (prev + 17, 22) to (start + 2, 6) +Highest counter ID seen: (none) diff --git a/tests/coverage/condition/conditions.cov-map b/tests/coverage/condition/conditions.cov-map index 74726e269fc67..208d671919cf8 100644 --- a/tests/coverage/condition/conditions.cov-map +++ b/tests/coverage/condition/conditions.cov-map @@ -29,6 +29,7 @@ Number of file 0 mappings: 9 false = c4 - Code(Expression(0, Add)) at (prev + 1, 5) to (start + 1, 2) = ((c2 + c3) + c4) +Highest counter ID seen: c4 Function name: conditions::assign_3_or_and Raw bytes (73): 0x[01, 01, 09, 05, 07, 0b, 11, 09, 0d, 01, 05, 01, 05, 22, 11, 01, 05, 22, 11, 01, 05, 09, 01, 17, 01, 00, 2f, 03, 01, 09, 00, 0a, 01, 00, 0d, 00, 0e, 20, 05, 22, 00, 0d, 00, 0e, 22, 00, 12, 00, 13, 20, 1e, 11, 00, 12, 00, 13, 1e, 00, 17, 00, 18, 20, 09, 0d, 00, 17, 00, 18, 03, 01, 05, 01, 02] @@ -64,6 +65,7 @@ Number of file 0 mappings: 9 false = c3 - Code(Expression(0, Add)) at (prev + 1, 5) to (start + 1, 2) = (c1 + ((c2 + c3) + c4)) +Highest counter ID seen: c4 Function name: conditions::assign_and Raw bytes (51): 0x[01, 01, 04, 07, 0e, 09, 0d, 01, 05, 01, 05, 07, 01, 0d, 01, 00, 21, 03, 01, 09, 00, 0a, 01, 00, 0d, 00, 0e, 20, 05, 0e, 00, 0d, 00, 0e, 05, 00, 12, 00, 13, 20, 09, 0d, 00, 12, 00, 13, 03, 01, 05, 01, 02] @@ -88,6 +90,7 @@ Number of file 0 mappings: 7 false = c3 - Code(Expression(0, Add)) at (prev + 1, 5) to (start + 1, 2) = ((c2 + c3) + (c0 - c1)) +Highest counter ID seen: c3 Function name: conditions::assign_or Raw bytes (51): 0x[01, 01, 04, 07, 0d, 05, 09, 01, 05, 01, 05, 07, 01, 12, 01, 00, 20, 03, 01, 09, 00, 0a, 01, 00, 0d, 00, 0e, 20, 05, 0e, 00, 0d, 00, 0e, 0e, 00, 12, 00, 13, 20, 09, 0d, 00, 12, 00, 13, 03, 01, 05, 01, 02] @@ -113,6 +116,7 @@ Number of file 0 mappings: 7 false = c3 - Code(Expression(0, Add)) at (prev + 1, 5) to (start + 1, 2) = ((c1 + c2) + c3) +Highest counter ID seen: c3 Function name: conditions::foo Raw bytes (9): 0x[01, 01, 00, 01, 01, 21, 01, 02, 02] @@ -121,6 +125,7 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 33, 1) to (start + 2, 2) +Highest counter ID seen: c0 Function name: conditions::func_call Raw bytes (39): 0x[01, 01, 03, 01, 05, 0b, 02, 09, 0d, 05, 01, 25, 01, 01, 0a, 20, 05, 02, 01, 09, 00, 0a, 05, 00, 0e, 00, 0f, 20, 09, 0d, 00, 0e, 00, 0f, 07, 01, 01, 00, 02] @@ -141,6 +146,7 @@ Number of file 0 mappings: 5 false = c3 - Code(Expression(1, Add)) at (prev + 1, 1) to (start + 0, 2) = ((c2 + c3) + (c0 - c1)) +Highest counter ID seen: c3 Function name: conditions::simple_assign Raw bytes (9): 0x[01, 01, 00, 01, 01, 08, 01, 03, 02] @@ -149,4 +155,5 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 8, 1) to (start + 3, 2) +Highest counter ID seen: c0 diff --git a/tests/coverage/conditions.cov-map b/tests/coverage/conditions.cov-map index 17143775b7b40..a392d1b70288e 100644 --- a/tests/coverage/conditions.cov-map +++ b/tests/coverage/conditions.cov-map @@ -260,4 +260,5 @@ Number of file 0 mappings: 68 - Code(Counter(9)) at (prev + 2, 9) to (start + 0, 15) - Code(Expression(137, Add)) at (prev + 2, 1) to (start + 0, 2) = ((c4 + (((c5 + c6) + c7) + c8)) + ((((c9 + c10) + c11) + c12) + ((c0 - c2) - c3))) +Highest counter ID seen: c35 diff --git a/tests/coverage/continue.cov-map b/tests/coverage/continue.cov-map index 810694d7f6623..7781d2d2544c8 100644 --- a/tests/coverage/continue.cov-map +++ b/tests/coverage/continue.cov-map @@ -76,4 +76,5 @@ Number of file 0 mappings: 30 - Code(Counter(16)) at (prev + 3, 9) to (start + 0, 14) - Code(Expression(27, Add)) at (prev + 2, 13) to (start + 1, 2) = (c18 + c17) +Highest counter ID seen: c18 diff --git a/tests/coverage/coroutine.cov-map b/tests/coverage/coroutine.cov-map index 6ff5ed74a96db..2fdc3220c1969 100644 --- a/tests/coverage/coroutine.cov-map +++ b/tests/coverage/coroutine.cov-map @@ -10,6 +10,7 @@ Number of file 0 mappings: 4 - Code(Expression(0, Sub)) at (prev + 2, 9) to (start + 0, 40) = (c0 - c1) - Code(Counter(0)) at (prev + 2, 1) to (start + 0, 2) +Highest counter ID seen: c1 Function name: coroutine::main Raw bytes (65): 0x[01, 01, 08, 07, 0d, 05, 09, 11, 15, 1e, 19, 11, 15, 15, 19, 1e, 19, 11, 15, 09, 01, 13, 01, 02, 16, 01, 08, 0b, 00, 2e, 11, 01, 2b, 00, 2d, 03, 01, 0e, 00, 35, 11, 02, 0b, 00, 2e, 1e, 01, 22, 00, 27, 1a, 00, 2c, 00, 2e, 17, 01, 0e, 00, 35, 1a, 02, 01, 00, 02] @@ -39,6 +40,7 @@ Number of file 0 mappings: 9 = (c5 + c6) - Code(Expression(6, Sub)) at (prev + 2, 1) to (start + 0, 2) = ((c4 - c5) - c6) +Highest counter ID seen: c4 Function name: coroutine::main::{closure#0} Raw bytes (14): 0x[01, 01, 00, 02, 01, 16, 08, 01, 1f, 05, 02, 10, 01, 06] @@ -48,4 +50,5 @@ Number of expressions: 0 Number of file 0 mappings: 2 - Code(Counter(0)) at (prev + 22, 8) to (start + 1, 31) - Code(Counter(1)) at (prev + 2, 16) to (start + 1, 6) +Highest counter ID seen: c1 diff --git a/tests/coverage/coverage_attr_closure.cov-map b/tests/coverage/coverage_attr_closure.cov-map index 5d2c6b00b40f8..fb861996a0d27 100644 --- a/tests/coverage/coverage_attr_closure.cov-map +++ b/tests/coverage/coverage_attr_closure.cov-map @@ -5,6 +5,7 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 6, 15) to (start + 2, 2) +Highest counter ID seen: c0 Function name: coverage_attr_closure::contains_closures_off::{closure#0} (unused) Raw bytes (9): 0x[01, 01, 00, 01, 00, 1d, 13, 02, 06] @@ -13,6 +14,7 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Zero) at (prev + 29, 19) to (start + 2, 6) +Highest counter ID seen: (none) Function name: coverage_attr_closure::contains_closures_on Raw bytes (19): 0x[01, 01, 00, 03, 01, 0f, 01, 01, 1a, 01, 05, 09, 00, 1b, 01, 04, 01, 00, 02] @@ -23,6 +25,7 @@ Number of file 0 mappings: 3 - Code(Counter(0)) at (prev + 15, 1) to (start + 1, 26) - Code(Counter(0)) at (prev + 5, 9) to (start + 0, 27) - Code(Counter(0)) at (prev + 4, 1) to (start + 0, 2) +Highest counter ID seen: c0 Function name: coverage_attr_closure::contains_closures_on::{closure#0} (unused) Raw bytes (9): 0x[01, 01, 00, 01, 00, 11, 13, 02, 06] @@ -31,4 +34,5 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Zero) at (prev + 17, 19) to (start + 2, 6) +Highest counter ID seen: (none) diff --git a/tests/coverage/dead_code.cov-map b/tests/coverage/dead_code.cov-map index 31599d9072c92..b94c6e656abfb 100644 --- a/tests/coverage/dead_code.cov-map +++ b/tests/coverage/dead_code.cov-map @@ -10,6 +10,7 @@ Number of file 0 mappings: 4 - Code(Expression(0, Sub)) at (prev + 2, 6) to (start + 0, 7) = (c0 - c1) - Code(Counter(0)) at (prev + 1, 1) to (start + 0, 2) +Highest counter ID seen: c1 Function name: dead_code::unused_fn (unused) Raw bytes (24): 0x[01, 01, 00, 04, 00, 0f, 01, 07, 0f, 00, 07, 10, 02, 06, 00, 02, 06, 00, 07, 00, 01, 01, 00, 02] @@ -21,6 +22,7 @@ Number of file 0 mappings: 4 - Code(Zero) at (prev + 7, 16) to (start + 2, 6) - Code(Zero) at (prev + 2, 6) to (start + 0, 7) - Code(Zero) at (prev + 1, 1) to (start + 0, 2) +Highest counter ID seen: (none) Function name: dead_code::unused_pub_fn_not_in_library (unused) Raw bytes (24): 0x[01, 01, 00, 04, 00, 03, 01, 07, 0f, 00, 07, 10, 02, 06, 00, 02, 06, 00, 07, 00, 01, 01, 00, 02] @@ -32,4 +34,5 @@ Number of file 0 mappings: 4 - Code(Zero) at (prev + 7, 16) to (start + 2, 6) - Code(Zero) at (prev + 2, 6) to (start + 0, 7) - Code(Zero) at (prev + 1, 1) to (start + 0, 2) +Highest counter ID seen: (none) diff --git a/tests/coverage/drop_trait.cov-map b/tests/coverage/drop_trait.cov-map index eb9d7d7acfdfc..a97c0f8794c43 100644 --- a/tests/coverage/drop_trait.cov-map +++ b/tests/coverage/drop_trait.cov-map @@ -5,6 +5,7 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 9, 5) to (start + 2, 6) +Highest counter ID seen: c0 Function name: drop_trait::main Raw bytes (24): 0x[01, 01, 00, 04, 01, 0e, 01, 05, 0c, 05, 06, 09, 01, 16, 00, 02, 06, 04, 0b, 01, 05, 01, 00, 02] @@ -16,4 +17,5 @@ Number of file 0 mappings: 4 - Code(Counter(1)) at (prev + 6, 9) to (start + 1, 22) - Code(Zero) at (prev + 2, 6) to (start + 4, 11) - Code(Counter(0)) at (prev + 5, 1) to (start + 0, 2) +Highest counter ID seen: c1 diff --git a/tests/coverage/fn_sig_into_try.cov-map b/tests/coverage/fn_sig_into_try.cov-map index 49758954831a1..374811dba9efa 100644 --- a/tests/coverage/fn_sig_into_try.cov-map +++ b/tests/coverage/fn_sig_into_try.cov-map @@ -5,6 +5,7 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 10, 1) to (start + 5, 2) +Highest counter ID seen: c0 Function name: fn_sig_into_try::b Raw bytes (26): 0x[01, 01, 01, 01, 00, 04, 01, 11, 01, 03, 0f, 00, 03, 0f, 00, 10, 02, 01, 05, 00, 0c, 01, 01, 01, 00, 02] @@ -18,6 +19,7 @@ Number of file 0 mappings: 4 - Code(Expression(0, Sub)) at (prev + 1, 5) to (start + 0, 12) = (c0 - Zero) - Code(Counter(0)) at (prev + 1, 1) to (start + 0, 2) +Highest counter ID seen: c0 Function name: fn_sig_into_try::c Raw bytes (26): 0x[01, 01, 01, 01, 00, 04, 01, 18, 01, 03, 17, 00, 03, 17, 00, 18, 02, 01, 05, 00, 0c, 01, 01, 01, 00, 02] @@ -31,6 +33,7 @@ Number of file 0 mappings: 4 - Code(Expression(0, Sub)) at (prev + 1, 5) to (start + 0, 12) = (c0 - Zero) - Code(Counter(0)) at (prev + 1, 1) to (start + 0, 2) +Highest counter ID seen: c0 Function name: fn_sig_into_try::d Raw bytes (26): 0x[01, 01, 01, 01, 00, 04, 01, 1f, 01, 04, 0f, 00, 04, 0f, 00, 10, 02, 01, 05, 00, 0c, 01, 01, 01, 00, 02] @@ -44,4 +47,5 @@ Number of file 0 mappings: 4 - Code(Expression(0, Sub)) at (prev + 1, 5) to (start + 0, 12) = (c0 - Zero) - Code(Counter(0)) at (prev + 1, 1) to (start + 0, 2) +Highest counter ID seen: c0 diff --git a/tests/coverage/generics.cov-map b/tests/coverage/generics.cov-map index 48e191c1156ff..d082bd54493d7 100644 --- a/tests/coverage/generics.cov-map +++ b/tests/coverage/generics.cov-map @@ -5,6 +5,7 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 17, 5) to (start + 2, 6) +Highest counter ID seen: c0 Function name: >::set_strength Raw bytes (9): 0x[01, 01, 00, 01, 01, 0a, 05, 02, 06] @@ -13,6 +14,7 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 10, 5) to (start + 2, 6) +Highest counter ID seen: c0 Function name: as core::ops::drop::Drop>::drop Raw bytes (9): 0x[01, 01, 00, 01, 01, 11, 05, 02, 06] @@ -21,6 +23,7 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 17, 5) to (start + 2, 6) +Highest counter ID seen: c0 Function name: >::set_strength Raw bytes (9): 0x[01, 01, 00, 01, 01, 0a, 05, 02, 06] @@ -29,6 +32,7 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 10, 5) to (start + 2, 6) +Highest counter ID seen: c0 Function name: generics::main Raw bytes (24): 0x[01, 01, 00, 04, 01, 16, 01, 08, 0c, 05, 09, 09, 01, 16, 00, 02, 06, 04, 0b, 01, 05, 01, 00, 02] @@ -40,4 +44,5 @@ Number of file 0 mappings: 4 - Code(Counter(1)) at (prev + 9, 9) to (start + 1, 22) - Code(Zero) at (prev + 2, 6) to (start + 4, 11) - Code(Counter(0)) at (prev + 5, 1) to (start + 0, 2) +Highest counter ID seen: c1 diff --git a/tests/coverage/holes.cov-map b/tests/coverage/holes.cov-map index 9350bd9a405cc..3c740d80ea05a 100644 --- a/tests/coverage/holes.cov-map +++ b/tests/coverage/holes.cov-map @@ -5,6 +5,7 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Zero) at (prev + 37, 9) to (start + 0, 29) +Highest counter ID seen: (none) Function name: holes::main Raw bytes (44): 0x[01, 01, 00, 08, 01, 08, 01, 06, 11, 01, 0f, 05, 00, 12, 01, 04, 05, 00, 12, 01, 07, 05, 00, 12, 01, 06, 05, 00, 12, 01, 06, 05, 03, 0f, 01, 0a, 05, 03, 0f, 01, 0a, 05, 01, 02] @@ -20,6 +21,7 @@ Number of file 0 mappings: 8 - Code(Counter(0)) at (prev + 6, 5) to (start + 3, 15) - Code(Counter(0)) at (prev + 10, 5) to (start + 3, 15) - Code(Counter(0)) at (prev + 10, 5) to (start + 1, 2) +Highest counter ID seen: c0 Function name: holes::main::_unused_fn (unused) Raw bytes (9): 0x[01, 01, 00, 01, 00, 19, 05, 00, 17] @@ -28,6 +30,7 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Zero) at (prev + 25, 5) to (start + 0, 23) +Highest counter ID seen: (none) Function name: holes::main::{closure#0} (unused) Raw bytes (9): 0x[01, 01, 00, 01, 00, 12, 09, 02, 0a] @@ -36,6 +39,7 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Zero) at (prev + 18, 9) to (start + 2, 10) +Highest counter ID seen: (none) Function name: holes::main::{closure#1} (unused) Raw bytes (9): 0x[01, 01, 00, 01, 00, 3d, 09, 02, 0a] @@ -44,4 +48,5 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Zero) at (prev + 61, 9) to (start + 2, 10) +Highest counter ID seen: (none) diff --git a/tests/coverage/if.cov-map b/tests/coverage/if.cov-map index 2b5ae97b406d4..8f12afac02721 100644 --- a/tests/coverage/if.cov-map +++ b/tests/coverage/if.cov-map @@ -10,4 +10,5 @@ Number of file 0 mappings: 4 - Code(Expression(0, Sub)) at (prev + 5, 6) to (start + 0, 7) = (c0 - c1) - Code(Counter(0)) at (prev + 1, 1) to (start + 0, 2) +Highest counter ID seen: c1 diff --git a/tests/coverage/if_else.cov-map b/tests/coverage/if_else.cov-map index c2111917e559e..194ad6ca71f83 100644 --- a/tests/coverage/if_else.cov-map +++ b/tests/coverage/if_else.cov-map @@ -15,4 +15,5 @@ Number of file 0 mappings: 7 - Code(Expression(1, Sub)) at (prev + 7, 5) to (start + 5, 6) = (c0 - c2) - Code(Counter(0)) at (prev + 6, 1) to (start + 0, 2) +Highest counter ID seen: c2 diff --git a/tests/coverage/if_not.cov-map b/tests/coverage/if_not.cov-map index 9e11ed787a887..a2c276b7bb77b 100644 --- a/tests/coverage/if_not.cov-map +++ b/tests/coverage/if_not.cov-map @@ -20,4 +20,5 @@ Number of file 0 mappings: 10 = (c0 - c3) - Code(Counter(3)) at (prev + 2, 12) to (start + 2, 6) - Code(Counter(0)) at (prev + 3, 1) to (start + 0, 2) +Highest counter ID seen: c3 diff --git a/tests/coverage/ignore_run.cov-map b/tests/coverage/ignore_run.cov-map index 9865efae0a1ef..c8ad3821e16f9 100644 --- a/tests/coverage/ignore_run.cov-map +++ b/tests/coverage/ignore_run.cov-map @@ -5,4 +5,5 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 3, 1) to (start + 0, 13) +Highest counter ID seen: c0 diff --git a/tests/coverage/inline-dead.cov-map b/tests/coverage/inline-dead.cov-map index 96b907cbe1532..411f16725bb07 100644 --- a/tests/coverage/inline-dead.cov-map +++ b/tests/coverage/inline-dead.cov-map @@ -5,6 +5,7 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Zero) at (prev + 23, 1) to (start + 2, 2) +Highest counter ID seen: (none) Function name: inline_dead::live:: Raw bytes (26): 0x[01, 01, 01, 01, 00, 04, 01, 0e, 01, 01, 09, 00, 02, 09, 00, 0f, 02, 02, 09, 00, 0a, 01, 02, 01, 00, 02] @@ -18,6 +19,7 @@ Number of file 0 mappings: 4 - Code(Expression(0, Sub)) at (prev + 2, 9) to (start + 0, 10) = (c0 - Zero) - Code(Counter(0)) at (prev + 2, 1) to (start + 0, 2) +Highest counter ID seen: c0 Function name: inline_dead::main Raw bytes (14): 0x[01, 01, 00, 02, 01, 04, 01, 03, 0a, 01, 06, 05, 01, 02] @@ -27,6 +29,7 @@ Number of expressions: 0 Number of file 0 mappings: 2 - Code(Counter(0)) at (prev + 4, 1) to (start + 3, 10) - Code(Counter(0)) at (prev + 6, 5) to (start + 1, 2) +Highest counter ID seen: c0 Function name: inline_dead::main::{closure#0} Raw bytes (23): 0x[01, 01, 02, 00, 06, 01, 00, 03, 01, 07, 17, 01, 16, 00, 01, 17, 00, 18, 03, 01, 05, 00, 06] @@ -40,4 +43,5 @@ Number of file 0 mappings: 3 - Code(Zero) at (prev + 1, 23) to (start + 0, 24) - Code(Expression(0, Add)) at (prev + 1, 5) to (start + 0, 6) = (Zero + (c0 - Zero)) +Highest counter ID seen: c0 diff --git a/tests/coverage/inline.cov-map b/tests/coverage/inline.cov-map index 2366a3bc5345a..ab3a505e92505 100644 --- a/tests/coverage/inline.cov-map +++ b/tests/coverage/inline.cov-map @@ -11,6 +11,7 @@ Number of file 0 mappings: 5 = (c0 + c1) - Code(Counter(1)) at (prev + 0, 17) to (start + 2, 6) - Code(Counter(0)) at (prev + 3, 5) to (start + 1, 2) +Highest counter ID seen: c1 Function name: inline::error Raw bytes (9): 0x[01, 01, 00, 01, 01, 31, 01, 01, 14] @@ -19,6 +20,7 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 49, 1) to (start + 1, 20) +Highest counter ID seen: c0 Function name: inline::length:: Raw bytes (9): 0x[01, 01, 00, 01, 01, 1e, 01, 02, 02] @@ -27,6 +29,7 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 30, 1) to (start + 2, 2) +Highest counter ID seen: c0 Function name: inline::main Raw bytes (9): 0x[01, 01, 00, 01, 01, 05, 01, 02, 02] @@ -35,6 +38,7 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 5, 1) to (start + 2, 2) +Highest counter ID seen: c0 Function name: inline::permutate:: Raw bytes (52): 0x[01, 01, 04, 01, 05, 02, 0d, 05, 0f, 09, 0d, 08, 01, 0f, 01, 02, 0e, 05, 02, 0f, 02, 06, 02, 02, 0f, 00, 14, 11, 01, 0d, 00, 0e, 06, 00, 12, 00, 16, 11, 00, 17, 04, 0a, 0d, 05, 0c, 02, 06, 0b, 03, 01, 00, 02] @@ -57,6 +61,7 @@ Number of file 0 mappings: 8 - Code(Counter(3)) at (prev + 5, 12) to (start + 2, 6) - Code(Expression(2, Add)) at (prev + 3, 1) to (start + 0, 2) = (c1 + (c2 + c3)) +Highest counter ID seen: c4 Function name: inline::permutations:: Raw bytes (9): 0x[01, 01, 00, 01, 01, 0a, 01, 03, 02] @@ -65,6 +70,7 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 10, 1) to (start + 3, 2) +Highest counter ID seen: c0 Function name: inline::swap:: Raw bytes (9): 0x[01, 01, 00, 01, 01, 23, 01, 04, 02] @@ -73,4 +79,5 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 35, 1) to (start + 4, 2) +Highest counter ID seen: c0 diff --git a/tests/coverage/inner_items.cov-map b/tests/coverage/inner_items.cov-map index 6ccc3f0bafc8d..16e86b2cadea9 100644 --- a/tests/coverage/inner_items.cov-map +++ b/tests/coverage/inner_items.cov-map @@ -5,6 +5,7 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 33, 9) to (start + 3, 10) +Highest counter ID seen: c0 Function name: ::trait_func Raw bytes (9): 0x[01, 01, 00, 01, 01, 28, 09, 03, 0a] @@ -13,6 +14,7 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 40, 9) to (start + 3, 10) +Highest counter ID seen: c0 Function name: inner_items::main Raw bytes (43): 0x[01, 01, 02, 01, 05, 01, 09, 07, 01, 03, 01, 07, 0f, 05, 07, 10, 02, 06, 02, 02, 06, 00, 07, 01, 24, 08, 00, 0f, 09, 00, 10, 02, 06, 06, 02, 06, 00, 07, 01, 02, 09, 05, 02] @@ -31,6 +33,7 @@ Number of file 0 mappings: 7 - Code(Expression(1, Sub)) at (prev + 2, 6) to (start + 0, 7) = (c0 - c2) - Code(Counter(0)) at (prev + 2, 9) to (start + 5, 2) +Highest counter ID seen: c2 Function name: inner_items::main::in_func Raw bytes (9): 0x[01, 01, 00, 01, 01, 12, 05, 04, 06] @@ -39,4 +42,5 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 18, 5) to (start + 4, 6) +Highest counter ID seen: c0 diff --git a/tests/coverage/issue-83601.cov-map b/tests/coverage/issue-83601.cov-map index f2447e3c92c8a..c188cca1b517a 100644 --- a/tests/coverage/issue-83601.cov-map +++ b/tests/coverage/issue-83601.cov-map @@ -9,4 +9,5 @@ Number of file 0 mappings: 3 - Code(Counter(1)) at (prev + 3, 9) to (start + 1, 28) - Code(Expression(0, Sub)) at (prev + 2, 5) to (start + 3, 2) = (c1 - c2) +Highest counter ID seen: c1 diff --git a/tests/coverage/issue-84561.cov-map b/tests/coverage/issue-84561.cov-map index d3c4671e0ba4c..a8ad17574ba3d 100644 --- a/tests/coverage/issue-84561.cov-map +++ b/tests/coverage/issue-84561.cov-map @@ -10,6 +10,7 @@ Number of file 0 mappings: 4 - Code(Expression(0, Sub)) at (prev + 1, 9) to (start + 0, 15) = (c0 - c1) - Code(Counter(0)) at (prev + 1, 5) to (start + 0, 6) +Highest counter ID seen: c1 Function name: issue_84561::main Raw bytes (10): 0x[01, 01, 00, 01, 01, b4, 01, 01, 04, 02] @@ -18,6 +19,7 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 180, 1) to (start + 4, 2) +Highest counter ID seen: c0 Function name: issue_84561::test1 Raw bytes (50): 0x[01, 01, 00, 09, 01, 9a, 01, 01, 01, 0b, 05, 01, 0c, 00, 1e, 01, 01, 05, 00, 0b, 09, 00, 0c, 00, 1e, 01, 01, 0d, 01, 0b, 0d, 01, 0c, 00, 1e, 01, 01, 05, 03, 0b, 11, 03, 0c, 00, 1e, 01, 01, 01, 00, 02] @@ -34,6 +36,7 @@ Number of file 0 mappings: 9 - Code(Counter(0)) at (prev + 1, 5) to (start + 3, 11) - Code(Counter(4)) at (prev + 3, 12) to (start + 0, 30) - Code(Counter(0)) at (prev + 1, 1) to (start + 0, 2) +Highest counter ID seen: c4 Function name: issue_84561::test2 Raw bytes (20): 0x[01, 01, 00, 03, 01, b0, 01, 01, 01, 10, 05, 01, 11, 00, 23, 01, 01, 01, 00, 02] @@ -44,6 +47,7 @@ Number of file 0 mappings: 3 - Code(Counter(0)) at (prev + 176, 1) to (start + 1, 16) - Code(Counter(1)) at (prev + 1, 17) to (start + 0, 35) - Code(Counter(0)) at (prev + 1, 1) to (start + 0, 2) +Highest counter ID seen: c1 Function name: issue_84561::test2::call_print Raw bytes (10): 0x[01, 01, 00, 01, 01, a7, 01, 09, 02, 0a] @@ -52,6 +56,7 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 167, 9) to (start + 2, 10) +Highest counter ID seen: c0 Function name: issue_84561::test3 Raw bytes (375): 0x[01, 01, 31, 05, 09, 0d, 00, 15, 19, 12, 00, 15, 19, 21, 00, 1e, 00, 21, 00, 31, 00, 3d, 00, 2e, 45, 3d, 00, 42, 49, 45, 00, 3f, 51, 42, 49, 45, 00, 7a, 55, 51, 00, 7a, 55, 51, 00, 77, 5d, 7a, 55, 51, 00, 77, 61, 7a, 55, 51, 00, 72, 65, 77, 61, 7a, 55, 51, 00, 75, be, 01, c2, 01, 79, 69, 6d, 69, 6d, 69, 6d, c2, 01, 00, 69, 6d, c2, 01, 79, 69, 6d, bb, 01, 7d, 75, be, 01, c2, 01, 79, 69, 6d, b6, 01, 00, bb, 01, 7d, 75, be, 01, c2, 01, 79, 69, 6d, 33, 01, 08, 01, 03, 1c, 05, 04, 09, 01, 1c, 02, 02, 05, 04, 1f, 0d, 05, 05, 00, 1f, 06, 01, 05, 00, 1f, 15, 01, 09, 01, 1c, 12, 02, 05, 00, 1f, 0e, 01, 05, 00, 0f, 00, 00, 20, 00, 30, 21, 01, 05, 03, 0f, 00, 03, 20, 00, 30, 00, 00, 33, 00, 41, 00, 00, 4b, 00, 5a, 1e, 01, 05, 00, 0f, 00, 05, 09, 03, 10, 00, 05, 0d, 00, 1b, 00, 02, 0d, 00, 1c, 1a, 04, 09, 05, 06, 31, 06, 05, 03, 06, 22, 04, 05, 03, 06, 3d, 04, 09, 04, 06, 2e, 05, 08, 00, 0f, 45, 01, 09, 03, 0a, 2a, 05, 09, 03, 0a, 3f, 05, 08, 00, 0f, 51, 01, 09, 00, 13, 00, 03, 0d, 00, 1d, 3a, 03, 09, 00, 13, 00, 03, 0d, 00, 1d, 77, 03, 05, 00, 0f, 77, 01, 0c, 00, 13, 5d, 01, 0d, 00, 13, 56, 02, 0d, 00, 13, 72, 04, 05, 02, 13, 65, 03, 0d, 00, 13, 6e, 02, 0d, 00, 13, bb, 01, 03, 05, 00, 0f, 69, 01, 0c, 00, 13, 6d, 01, 0d, 03, 0e, 75, 04, 0d, 00, 13, c2, 01, 02, 0d, 00, 17, c2, 01, 01, 14, 00, 1b, 00, 01, 15, 00, 1b, 92, 01, 02, 15, 00, 1b, be, 01, 04, 0d, 00, 13, 7d, 03, 09, 00, 19, b6, 01, 02, 05, 00, 0f, b2, 01, 03, 09, 00, 22, 00, 02, 05, 00, 0f, 00, 03, 09, 00, 2c, 00, 02, 01, 00, 02] @@ -182,4 +187,5 @@ Number of file 0 mappings: 51 - Code(Zero) at (prev + 2, 5) to (start + 0, 15) - Code(Zero) at (prev + 3, 9) to (start + 0, 44) - Code(Zero) at (prev + 2, 1) to (start + 0, 2) +Highest counter ID seen: c31 diff --git a/tests/coverage/issue-85461.cov-map b/tests/coverage/issue-85461.cov-map index d1c449b9a355e..349bc2cab8030 100644 --- a/tests/coverage/issue-85461.cov-map +++ b/tests/coverage/issue-85461.cov-map @@ -5,4 +5,5 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 8, 1) to (start + 3, 2) +Highest counter ID seen: c0 diff --git a/tests/coverage/issue-93054.cov-map b/tests/coverage/issue-93054.cov-map index 024ef519fcffe..38cb70a3f97aa 100644 --- a/tests/coverage/issue-93054.cov-map +++ b/tests/coverage/issue-93054.cov-map @@ -5,6 +5,7 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Zero) at (prev + 21, 1) to (start + 0, 29) +Highest counter ID seen: (none) Function name: issue_93054::main Raw bytes (9): 0x[01, 01, 00, 01, 01, 1d, 01, 00, 0d] @@ -13,6 +14,7 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 29, 1) to (start + 0, 13) +Highest counter ID seen: c0 Function name: issue_93054::make (unused) Raw bytes (9): 0x[01, 01, 00, 01, 00, 19, 01, 02, 02] @@ -21,4 +23,5 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Zero) at (prev + 25, 1) to (start + 2, 2) +Highest counter ID seen: (none) diff --git a/tests/coverage/lazy_boolean.cov-map b/tests/coverage/lazy_boolean.cov-map index 8dca205d33f2d..fcb9d8f1ff5cc 100644 --- a/tests/coverage/lazy_boolean.cov-map +++ b/tests/coverage/lazy_boolean.cov-map @@ -46,4 +46,5 @@ Number of file 0 mappings: 28 - Code(Expression(6, Sub)) at (prev + 2, 12) to (start + 2, 6) = (c0 - c9) - Code(Counter(0)) at (prev + 3, 1) to (start + 0, 2) +Highest counter ID seen: c9 diff --git a/tests/coverage/let_else_loop.cov-map b/tests/coverage/let_else_loop.cov-map index 13d0d08adb119..04451596eae4b 100644 --- a/tests/coverage/let_else_loop.cov-map +++ b/tests/coverage/let_else_loop.cov-map @@ -7,6 +7,7 @@ Number of file 0 mappings: 3 - Code(Zero) at (prev + 22, 1) to (start + 1, 12) - Code(Zero) at (prev + 1, 15) to (start + 0, 22) - Code(Zero) at (prev + 0, 32) to (start + 0, 39) +Highest counter ID seen: (none) Function name: let_else_loop::_loop_either_way (unused) Raw bytes (19): 0x[01, 01, 00, 03, 00, 0f, 01, 01, 14, 00, 01, 1c, 00, 23, 00, 01, 05, 00, 0c] @@ -17,6 +18,7 @@ Number of file 0 mappings: 3 - Code(Zero) at (prev + 15, 1) to (start + 1, 20) - Code(Zero) at (prev + 1, 28) to (start + 0, 35) - Code(Zero) at (prev + 1, 5) to (start + 0, 12) +Highest counter ID seen: (none) Function name: let_else_loop::loopy Raw bytes (19): 0x[01, 01, 00, 03, 01, 09, 01, 01, 14, 00, 01, 1c, 00, 23, 05, 01, 01, 00, 02] @@ -27,4 +29,5 @@ Number of file 0 mappings: 3 - Code(Counter(0)) at (prev + 9, 1) to (start + 1, 20) - Code(Zero) at (prev + 1, 28) to (start + 0, 35) - Code(Counter(1)) at (prev + 1, 1) to (start + 0, 2) +Highest counter ID seen: c1 diff --git a/tests/coverage/long_and_wide.cov-map b/tests/coverage/long_and_wide.cov-map index 97aebf9b18ab0..032b7fe102e8f 100644 --- a/tests/coverage/long_and_wide.cov-map +++ b/tests/coverage/long_and_wide.cov-map @@ -5,6 +5,7 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 150, 1) to (start + 0, 21) +Highest counter ID seen: c0 Function name: long_and_wide::long_function Raw bytes (10): 0x[01, 01, 00, 01, 01, 10, 01, 84, 01, 02] @@ -13,6 +14,7 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 16, 1) to (start + 132, 2) +Highest counter ID seen: c0 Function name: long_and_wide::main Raw bytes (9): 0x[01, 01, 00, 01, 01, 07, 01, 04, 02] @@ -21,6 +23,7 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 7, 1) to (start + 4, 2) +Highest counter ID seen: c0 Function name: long_and_wide::wide_function Raw bytes (10): 0x[01, 01, 00, 01, 01, 0e, 01, 00, 8b, 01] @@ -29,4 +32,5 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 14, 1) to (start + 0, 139) +Highest counter ID seen: c0 diff --git a/tests/coverage/loop-break.cov-map b/tests/coverage/loop-break.cov-map index 890d5d84539e4..63280a0bf7cbe 100644 --- a/tests/coverage/loop-break.cov-map +++ b/tests/coverage/loop-break.cov-map @@ -11,4 +11,5 @@ Number of file 0 mappings: 5 - Code(Counter(0)) at (prev + 1, 13) to (start + 0, 18) - Code(Counter(1)) at (prev + 1, 10) to (start + 0, 11) - Code(Counter(0)) at (prev + 2, 1) to (start + 0, 2) +Highest counter ID seen: c1 diff --git a/tests/coverage/loop_break_value.cov-map b/tests/coverage/loop_break_value.cov-map index d8dca8a85c387..e48d078f6722d 100644 --- a/tests/coverage/loop_break_value.cov-map +++ b/tests/coverage/loop_break_value.cov-map @@ -5,4 +5,5 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 4, 1) to (start + 10, 2) +Highest counter ID seen: c0 diff --git a/tests/coverage/loops_branches.cov-map b/tests/coverage/loops_branches.cov-map index 9187dcbd86518..1d263611a3abc 100644 --- a/tests/coverage/loops_branches.cov-map +++ b/tests/coverage/loops_branches.cov-map @@ -75,6 +75,7 @@ Number of file 0 mappings: 20 - Code(Counter(6)) at (prev + 3, 9) to (start + 0, 15) - Code(Expression(34, Add)) at (prev + 1, 5) to (start + 0, 6) = ((c9 + (((((c3 + Zero) + (c4 + Zero)) - c6) - Zero) - c4)) + c6) +Highest counter ID seen: c9 Function name: ::fmt Raw bytes (230): 0x[01, 01, 2b, 01, 00, 02, 00, a3, 01, 19, a7, 01, ab, 01, 00, 0d, 00, 15, a7, 01, ab, 01, 00, 0d, 00, 15, a3, 01, 19, a7, 01, ab, 01, 00, 0d, 00, 15, 9e, 01, 00, a3, 01, 19, a7, 01, ab, 01, 00, 0d, 00, 15, 9a, 01, 00, 9e, 01, 00, a3, 01, 19, a7, 01, ab, 01, 00, 0d, 00, 15, 9e, 01, 00, a3, 01, 19, a7, 01, ab, 01, 00, 0d, 00, 15, 9a, 01, 15, 9e, 01, 00, a3, 01, 19, a7, 01, ab, 01, 00, 0d, 00, 15, 93, 01, 25, 96, 01, 19, 9a, 01, 15, 9e, 01, 00, a3, 01, 19, a7, 01, ab, 01, 00, 0d, 00, 15, 14, 01, 22, 05, 01, 11, 00, 01, 12, 01, 0a, 02, 02, 10, 00, 15, 00, 01, 17, 00, 1b, 00, 00, 1c, 00, 1e, 06, 01, 0e, 00, 0f, 02, 01, 0d, 00, 1e, 25, 00, 1e, 00, 1f, 9e, 01, 02, 0d, 00, 0e, a3, 01, 00, 12, 00, 17, 9e, 01, 01, 10, 00, 15, 00, 00, 16, 01, 0e, 9a, 01, 02, 14, 00, 19, 00, 01, 1b, 00, 1f, 00, 00, 20, 00, 22, 4a, 01, 12, 00, 13, 9a, 01, 01, 11, 00, 22, 96, 01, 00, 22, 00, 23, 19, 03, 09, 00, 0f, 8f, 01, 01, 05, 00, 06] @@ -156,6 +157,7 @@ Number of file 0 mappings: 20 - Code(Counter(6)) at (prev + 3, 9) to (start + 0, 15) - Code(Expression(35, Add)) at (prev + 1, 5) to (start + 0, 6) = (((((((Zero + c3) + (Zero + c5)) - c6) - Zero) - c5) + c6) + c9) +Highest counter ID seen: c9 Function name: loops_branches::main Raw bytes (9): 0x[01, 01, 00, 01, 01, 37, 01, 05, 02] @@ -164,4 +166,5 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 55, 1) to (start + 5, 2) +Highest counter ID seen: c0 diff --git a/tests/coverage/macro_in_closure.cov-map b/tests/coverage/macro_in_closure.cov-map index 2feaab717b5cb..9614154a3668a 100644 --- a/tests/coverage/macro_in_closure.cov-map +++ b/tests/coverage/macro_in_closure.cov-map @@ -5,6 +5,7 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 7, 28) to (start + 0, 45) +Highest counter ID seen: c0 Function name: macro_in_closure::WITH_BLOCK::{closure#0} Raw bytes (9): 0x[01, 01, 00, 01, 01, 09, 1e, 02, 02] @@ -13,4 +14,5 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 9, 30) to (start + 2, 2) +Highest counter ID seen: c0 diff --git a/tests/coverage/macro_name_span.cov-map b/tests/coverage/macro_name_span.cov-map index f3ee44d2a5abc..58620452b2ba6 100644 --- a/tests/coverage/macro_name_span.cov-map +++ b/tests/coverage/macro_name_span.cov-map @@ -5,6 +5,7 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 22, 28) to (start + 1, 64) +Highest counter ID seen: c0 Function name: macro_name_span::main Raw bytes (9): 0x[01, 01, 00, 01, 01, 0b, 01, 02, 02] @@ -13,4 +14,5 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 11, 1) to (start + 2, 2) +Highest counter ID seen: c0 diff --git a/tests/coverage/match_or_pattern.cov-map b/tests/coverage/match_or_pattern.cov-map index 60b7024533d2e..f6491ea262dc5 100644 --- a/tests/coverage/match_or_pattern.cov-map +++ b/tests/coverage/match_or_pattern.cov-map @@ -72,4 +72,5 @@ Number of file 0 mappings: 25 = (c14 + c15) - Code(Expression(26, Add)) at (prev + 2, 1) to (start + 0, 2) = ((c14 + c15) + c16) +Highest counter ID seen: c16 diff --git a/tests/coverage/mcdc/condition-limit.cov-map b/tests/coverage/mcdc/condition-limit.cov-map index 9d1e7518f9ea4..a3e3b1d09c4d1 100644 --- a/tests/coverage/mcdc/condition-limit.cov-map +++ b/tests/coverage/mcdc/condition-limit.cov-map @@ -87,4 +87,5 @@ Number of file 0 mappings: 18 = ((((((c2 + c3) + c4) + c5) + c6) + c7) + (c0 - c1)) - Code(Expression(37, Add)) at (prev + 1, 1) to (start + 0, 2) = (c8 + ((((((c2 + c3) + c4) + c5) + c6) + c7) + (c0 - c1))) +Highest counter ID seen: c8 diff --git a/tests/coverage/mcdc/if.cov-map b/tests/coverage/mcdc/if.cov-map index 576c9b14ed14c..46960d31c01e6 100644 --- a/tests/coverage/mcdc/if.cov-map +++ b/tests/coverage/mcdc/if.cov-map @@ -22,6 +22,7 @@ Number of file 0 mappings: 8 = (c2 + (c0 - c1)) - Code(Expression(2, Add)) at (prev + 3, 1) to (start + 0, 2) = (c3 + (c2 + (c0 - c1))) +Highest counter ID seen: c3 Function name: if::mcdc_check_b Raw bytes (64): 0x[01, 01, 04, 01, 05, 09, 02, 0d, 0f, 09, 02, 08, 01, 17, 01, 01, 09, 28, 03, 02, 01, 08, 00, 0e, 30, 05, 02, 01, 02, 00, 00, 08, 00, 09, 05, 00, 0d, 00, 0e, 30, 0d, 09, 02, 00, 00, 00, 0d, 00, 0e, 0d, 00, 0f, 02, 06, 0f, 02, 0c, 02, 06, 0b, 03, 01, 00, 02] @@ -47,6 +48,7 @@ Number of file 0 mappings: 8 = (c2 + (c0 - c1)) - Code(Expression(2, Add)) at (prev + 3, 1) to (start + 0, 2) = (c3 + (c2 + (c0 - c1))) +Highest counter ID seen: c3 Function name: if::mcdc_check_both Raw bytes (64): 0x[01, 01, 04, 01, 05, 09, 02, 0d, 0f, 09, 02, 08, 01, 1f, 01, 01, 09, 28, 03, 02, 01, 08, 00, 0e, 30, 05, 02, 01, 02, 00, 00, 08, 00, 09, 05, 00, 0d, 00, 0e, 30, 0d, 09, 02, 00, 00, 00, 0d, 00, 0e, 0d, 00, 0f, 02, 06, 0f, 02, 0c, 02, 06, 0b, 03, 01, 00, 02] @@ -72,6 +74,7 @@ Number of file 0 mappings: 8 = (c2 + (c0 - c1)) - Code(Expression(2, Add)) at (prev + 3, 1) to (start + 0, 2) = (c3 + (c2 + (c0 - c1))) +Highest counter ID seen: c3 Function name: if::mcdc_check_neither Raw bytes (64): 0x[01, 01, 04, 01, 05, 09, 02, 0d, 0f, 09, 02, 08, 01, 07, 01, 01, 09, 28, 03, 02, 01, 08, 00, 0e, 30, 05, 02, 01, 02, 00, 00, 08, 00, 09, 05, 00, 0d, 00, 0e, 30, 0d, 09, 02, 00, 00, 00, 0d, 00, 0e, 0d, 00, 0f, 02, 06, 0f, 02, 0c, 02, 06, 0b, 03, 01, 00, 02] @@ -97,6 +100,7 @@ Number of file 0 mappings: 8 = (c2 + (c0 - c1)) - Code(Expression(2, Add)) at (prev + 3, 1) to (start + 0, 2) = (c3 + (c2 + (c0 - c1))) +Highest counter ID seen: c3 Function name: if::mcdc_check_not_tree_decision Raw bytes (87): 0x[01, 01, 08, 01, 05, 02, 09, 05, 09, 0d, 1e, 02, 09, 11, 1b, 0d, 1e, 02, 09, 0a, 01, 31, 01, 03, 0a, 28, 05, 03, 03, 08, 00, 15, 30, 05, 02, 01, 02, 03, 00, 09, 00, 0a, 02, 00, 0e, 00, 0f, 30, 09, 1e, 03, 02, 00, 00, 0e, 00, 0f, 0b, 00, 14, 00, 15, 30, 11, 0d, 02, 00, 00, 00, 14, 00, 15, 11, 00, 16, 02, 06, 1b, 02, 0c, 02, 06, 17, 03, 01, 00, 02] @@ -132,6 +136,7 @@ Number of file 0 mappings: 10 = (c3 + ((c0 - c1) - c2)) - Code(Expression(5, Add)) at (prev + 3, 1) to (start + 0, 2) = (c4 + (c3 + ((c0 - c1) - c2))) +Highest counter ID seen: c4 Function name: if::mcdc_check_tree_decision Raw bytes (87): 0x[01, 01, 08, 01, 05, 05, 0d, 05, 0d, 0d, 11, 09, 02, 1b, 1f, 0d, 11, 09, 02, 0a, 01, 27, 01, 03, 09, 28, 04, 03, 03, 08, 00, 15, 30, 05, 02, 01, 02, 00, 00, 08, 00, 09, 05, 00, 0e, 00, 0f, 30, 0d, 0a, 02, 00, 03, 00, 0e, 00, 0f, 0a, 00, 13, 00, 14, 30, 11, 09, 03, 00, 00, 00, 13, 00, 14, 1b, 00, 16, 02, 06, 1f, 02, 0c, 02, 06, 17, 03, 01, 00, 02] @@ -167,6 +172,7 @@ Number of file 0 mappings: 10 = (c2 + (c0 - c1)) - Code(Expression(5, Add)) at (prev + 3, 1) to (start + 0, 2) = ((c3 + c4) + (c2 + (c0 - c1))) +Highest counter ID seen: c4 Function name: if::mcdc_nested_if Raw bytes (124): 0x[01, 01, 0d, 01, 05, 02, 09, 05, 09, 1b, 15, 05, 09, 1b, 15, 05, 09, 11, 15, 02, 09, 2b, 32, 0d, 2f, 11, 15, 02, 09, 0e, 01, 3b, 01, 01, 09, 28, 03, 02, 01, 08, 00, 0e, 30, 05, 02, 01, 00, 02, 00, 08, 00, 09, 02, 00, 0d, 00, 0e, 30, 09, 32, 02, 00, 00, 00, 0d, 00, 0e, 1b, 01, 09, 01, 0d, 28, 06, 02, 01, 0c, 00, 12, 30, 16, 15, 01, 02, 00, 00, 0c, 00, 0d, 16, 00, 11, 00, 12, 30, 0d, 11, 02, 00, 00, 00, 11, 00, 12, 0d, 00, 13, 02, 0a, 2f, 02, 0a, 00, 0b, 32, 01, 0c, 02, 06, 27, 03, 01, 00, 02] @@ -215,4 +221,5 @@ Number of file 0 mappings: 14 = ((c0 - c1) - c2) - Code(Expression(9, Add)) at (prev + 3, 1) to (start + 0, 2) = ((c3 + (c4 + c5)) + ((c0 - c1) - c2)) +Highest counter ID seen: c5 diff --git a/tests/coverage/mcdc/inlined_expressions.cov-map b/tests/coverage/mcdc/inlined_expressions.cov-map index bfde7d75d622f..4f44e0f2b855c 100644 --- a/tests/coverage/mcdc/inlined_expressions.cov-map +++ b/tests/coverage/mcdc/inlined_expressions.cov-map @@ -18,4 +18,5 @@ Number of file 0 mappings: 6 false = c3 - Code(Expression(1, Add)) at (prev + 1, 1) to (start + 0, 2) = ((c2 + c3) + (c0 - c1)) +Highest counter ID seen: c3 diff --git a/tests/coverage/mcdc/nested_if.cov-map b/tests/coverage/mcdc/nested_if.cov-map index 3da98ff4a514e..3bed49e7a12d1 100644 --- a/tests/coverage/mcdc/nested_if.cov-map +++ b/tests/coverage/mcdc/nested_if.cov-map @@ -56,6 +56,7 @@ Number of file 0 mappings: 20 = (c2 + (c0 - c1)) - Code(Expression(12, Add)) at (prev + 3, 1) to (start + 0, 2) = (c3 + (c2 + (c0 - c1))) +Highest counter ID seen: c8 Function name: nested_if::nested_if_in_condition Raw bytes (120): 0x[01, 01, 0b, 01, 05, 05, 11, 05, 11, 1e, 15, 05, 11, 11, 15, 1e, 15, 05, 11, 09, 02, 0d, 2b, 09, 02, 0e, 01, 07, 01, 01, 09, 28, 06, 02, 01, 08, 00, 2e, 30, 05, 02, 01, 02, 00, 00, 08, 00, 09, 30, 0d, 09, 02, 00, 00, 00, 0d, 00, 2e, 05, 00, 10, 00, 11, 28, 03, 02, 00, 10, 00, 16, 30, 11, 1e, 01, 00, 02, 00, 10, 00, 11, 1e, 00, 15, 00, 16, 30, 15, 1a, 02, 00, 00, 00, 15, 00, 16, 17, 00, 19, 00, 1d, 1a, 00, 27, 00, 2c, 0d, 00, 2f, 02, 06, 2b, 02, 0c, 02, 06, 27, 03, 01, 00, 02] @@ -101,6 +102,7 @@ Number of file 0 mappings: 14 = (c2 + (c0 - c1)) - Code(Expression(9, Add)) at (prev + 3, 1) to (start + 0, 2) = (c3 + (c2 + (c0 - c1))) +Highest counter ID seen: c5 Function name: nested_if::nested_in_then_block_in_condition Raw bytes (176): 0x[01, 01, 12, 01, 05, 05, 11, 05, 11, 3a, 15, 05, 11, 11, 15, 33, 19, 11, 15, 19, 1d, 19, 1d, 1d, 2e, 33, 19, 11, 15, 3a, 15, 05, 11, 09, 02, 0d, 47, 09, 02, 14, 01, 22, 01, 01, 09, 28, 09, 02, 01, 08, 00, 4b, 30, 05, 02, 01, 02, 00, 00, 08, 00, 09, 30, 0d, 09, 02, 00, 00, 00, 0d, 00, 4b, 05, 00, 10, 00, 11, 28, 03, 02, 00, 10, 00, 16, 30, 11, 3a, 01, 00, 02, 00, 10, 00, 11, 3a, 00, 15, 00, 16, 30, 15, 36, 02, 00, 00, 00, 15, 00, 16, 33, 00, 1c, 00, 1d, 28, 06, 02, 00, 1c, 00, 22, 30, 19, 2e, 01, 02, 00, 00, 1c, 00, 1d, 19, 00, 21, 00, 22, 30, 26, 1d, 02, 00, 00, 00, 21, 00, 22, 26, 00, 25, 00, 29, 2b, 00, 33, 00, 38, 36, 00, 44, 00, 49, 0d, 00, 4c, 02, 06, 47, 02, 0c, 02, 06, 43, 03, 01, 00, 02] @@ -165,6 +167,7 @@ Number of file 0 mappings: 20 = (c2 + (c0 - c1)) - Code(Expression(16, Add)) at (prev + 3, 1) to (start + 0, 2) = (c3 + (c2 + (c0 - c1))) +Highest counter ID seen: c7 Function name: nested_if::nested_single_condition_decision Raw bytes (85): 0x[01, 01, 06, 01, 05, 05, 11, 05, 11, 09, 02, 0d, 17, 09, 02, 0b, 01, 17, 01, 04, 09, 28, 03, 02, 04, 08, 00, 29, 30, 05, 02, 01, 02, 00, 00, 08, 00, 09, 30, 0d, 09, 02, 00, 00, 00, 0d, 00, 29, 05, 00, 10, 00, 11, 20, 11, 0a, 00, 10, 00, 11, 11, 00, 14, 00, 19, 0a, 00, 23, 00, 27, 0d, 00, 2a, 02, 06, 17, 02, 0c, 02, 06, 13, 03, 01, 00, 02] @@ -198,4 +201,5 @@ Number of file 0 mappings: 11 = (c2 + (c0 - c1)) - Code(Expression(4, Add)) at (prev + 3, 1) to (start + 0, 2) = (c3 + (c2 + (c0 - c1))) +Highest counter ID seen: c4 diff --git a/tests/coverage/mcdc/non_control_flow.cov-map b/tests/coverage/mcdc/non_control_flow.cov-map index d5383a197616b..677e31e404e42 100644 --- a/tests/coverage/mcdc/non_control_flow.cov-map +++ b/tests/coverage/mcdc/non_control_flow.cov-map @@ -33,6 +33,7 @@ Number of file 0 mappings: 10 false = c3 - Code(Expression(0, Add)) at (prev + 1, 5) to (start + 1, 2) = (c1 + ((c2 + c3) + c4)) +Highest counter ID seen: c4 Function name: non_control_flow::assign_3_bis Raw bytes (85): 0x[01, 01, 07, 07, 11, 09, 0d, 01, 05, 05, 09, 16, 1a, 05, 09, 01, 05, 0a, 01, 1b, 01, 00, 2c, 03, 01, 09, 00, 0a, 01, 00, 0d, 00, 0e, 28, 05, 03, 00, 0d, 00, 18, 30, 05, 1a, 01, 03, 02, 00, 0d, 00, 0e, 05, 00, 12, 00, 13, 30, 09, 16, 03, 00, 02, 00, 12, 00, 13, 13, 00, 17, 00, 18, 30, 0d, 11, 02, 00, 00, 00, 17, 00, 18, 03, 01, 05, 01, 02] @@ -66,6 +67,7 @@ Number of file 0 mappings: 10 false = c4 - Code(Expression(0, Add)) at (prev + 1, 5) to (start + 1, 2) = ((c2 + c3) + c4) +Highest counter ID seen: c4 Function name: non_control_flow::assign_and Raw bytes (64): 0x[01, 01, 04, 07, 0e, 09, 0d, 01, 05, 01, 05, 08, 01, 0c, 01, 00, 21, 03, 01, 09, 00, 0a, 01, 00, 0d, 00, 0e, 28, 03, 02, 00, 0d, 00, 13, 30, 05, 0e, 01, 02, 00, 00, 0d, 00, 0e, 05, 00, 12, 00, 13, 30, 09, 0d, 02, 00, 00, 00, 12, 00, 13, 03, 01, 05, 01, 02] @@ -91,6 +93,7 @@ Number of file 0 mappings: 8 false = c3 - Code(Expression(0, Add)) at (prev + 1, 5) to (start + 1, 2) = ((c2 + c3) + (c0 - c1)) +Highest counter ID seen: c3 Function name: non_control_flow::assign_or Raw bytes (64): 0x[01, 01, 04, 07, 0d, 05, 09, 01, 05, 01, 05, 08, 01, 11, 01, 00, 20, 03, 01, 09, 00, 0a, 01, 00, 0d, 00, 0e, 28, 03, 02, 00, 0d, 00, 13, 30, 05, 0e, 01, 00, 02, 00, 0d, 00, 0e, 0e, 00, 12, 00, 13, 30, 09, 0d, 02, 00, 00, 00, 12, 00, 13, 03, 01, 05, 01, 02] @@ -117,6 +120,7 @@ Number of file 0 mappings: 8 false = c3 - Code(Expression(0, Add)) at (prev + 1, 5) to (start + 1, 2) = ((c1 + c2) + c3) +Highest counter ID seen: c3 Function name: non_control_flow::foo Raw bytes (9): 0x[01, 01, 00, 01, 01, 25, 01, 02, 02] @@ -125,6 +129,7 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 37, 1) to (start + 2, 2) +Highest counter ID seen: c0 Function name: non_control_flow::func_call Raw bytes (52): 0x[01, 01, 03, 01, 05, 0b, 02, 09, 0d, 06, 01, 29, 01, 01, 0a, 28, 03, 02, 01, 09, 00, 0f, 30, 05, 02, 01, 02, 00, 00, 09, 00, 0a, 05, 00, 0e, 00, 0f, 30, 09, 0d, 02, 00, 00, 00, 0e, 00, 0f, 07, 01, 01, 00, 02] @@ -146,6 +151,7 @@ Number of file 0 mappings: 6 false = c3 - Code(Expression(1, Add)) at (prev + 1, 1) to (start + 0, 2) = ((c2 + c3) + (c0 - c1)) +Highest counter ID seen: c3 Function name: non_control_flow::right_comb_tree Raw bytes (139): 0x[01, 01, 13, 07, 1a, 0b, 19, 0f, 15, 13, 11, 09, 0d, 01, 05, 01, 05, 05, 19, 05, 19, 4a, 15, 05, 19, 4a, 15, 05, 19, 46, 11, 4a, 15, 05, 19, 46, 11, 4a, 15, 05, 19, 0e, 01, 20, 01, 00, 41, 03, 01, 09, 00, 0a, 01, 00, 0d, 00, 0e, 28, 06, 05, 00, 0d, 00, 2a, 30, 05, 1a, 01, 02, 00, 00, 0d, 00, 0e, 05, 00, 13, 00, 14, 30, 4a, 19, 02, 03, 00, 00, 13, 00, 14, 4a, 00, 19, 00, 1a, 30, 46, 15, 03, 04, 00, 00, 19, 00, 1a, 46, 00, 1f, 00, 20, 30, 42, 11, 04, 05, 00, 00, 1f, 00, 20, 42, 00, 24, 00, 27, 30, 09, 0d, 05, 00, 00, 00, 24, 00, 27, 03, 01, 05, 01, 02] @@ -201,4 +207,5 @@ Number of file 0 mappings: 14 false = c3 - Code(Expression(0, Add)) at (prev + 1, 5) to (start + 1, 2) = (((((c2 + c3) + c4) + c5) + c6) + (c0 - c1)) +Highest counter ID seen: c6 diff --git a/tests/coverage/nested_loops.cov-map b/tests/coverage/nested_loops.cov-map index 35d92594e75e3..c145d4c58433b 100644 --- a/tests/coverage/nested_loops.cov-map +++ b/tests/coverage/nested_loops.cov-map @@ -48,4 +48,5 @@ Number of file 0 mappings: 13 = (c1 + c2) - Code(Expression(22, Add)) at (prev + 2, 1) to (start + 0, 2) = (c4 + c3) +Highest counter ID seen: c6 diff --git a/tests/coverage/no_cov_crate.cov-map b/tests/coverage/no_cov_crate.cov-map index 75234f6c3b7ba..28d0d9ff8ab1d 100644 --- a/tests/coverage/no_cov_crate.cov-map +++ b/tests/coverage/no_cov_crate.cov-map @@ -5,6 +5,7 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 20, 1) to (start + 2, 2) +Highest counter ID seen: c0 Function name: no_cov_crate::add_coverage_2 Raw bytes (9): 0x[01, 01, 00, 01, 01, 18, 01, 02, 02] @@ -13,6 +14,7 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 24, 1) to (start + 2, 2) +Highest counter ID seen: c0 Function name: no_cov_crate::add_coverage_not_called (unused) Raw bytes (9): 0x[01, 01, 00, 01, 00, 1d, 01, 02, 02] @@ -21,6 +23,7 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Zero) at (prev + 29, 1) to (start + 2, 2) +Highest counter ID seen: (none) Function name: no_cov_crate::main Raw bytes (9): 0x[01, 01, 00, 01, 01, 4d, 01, 0b, 02] @@ -29,6 +32,7 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 77, 1) to (start + 11, 2) +Highest counter ID seen: c0 Function name: no_cov_crate::nested_fns::outer Raw bytes (14): 0x[01, 01, 00, 02, 01, 31, 05, 02, 23, 01, 0c, 05, 00, 06] @@ -38,6 +42,7 @@ Number of expressions: 0 Number of file 0 mappings: 2 - Code(Counter(0)) at (prev + 49, 5) to (start + 2, 35) - Code(Counter(0)) at (prev + 12, 5) to (start + 0, 6) +Highest counter ID seen: c0 Function name: no_cov_crate::nested_fns::outer_both_covered Raw bytes (14): 0x[01, 01, 00, 02, 01, 3f, 05, 02, 17, 01, 0b, 05, 00, 06] @@ -47,6 +52,7 @@ Number of expressions: 0 Number of file 0 mappings: 2 - Code(Counter(0)) at (prev + 63, 5) to (start + 2, 23) - Code(Counter(0)) at (prev + 11, 5) to (start + 0, 6) +Highest counter ID seen: c0 Function name: no_cov_crate::nested_fns::outer_both_covered::inner Raw bytes (26): 0x[01, 01, 01, 01, 05, 04, 01, 43, 09, 01, 17, 05, 01, 18, 02, 0e, 02, 02, 14, 02, 0e, 01, 03, 09, 00, 0a] @@ -60,4 +66,5 @@ Number of file 0 mappings: 4 - Code(Expression(0, Sub)) at (prev + 2, 20) to (start + 2, 14) = (c0 - c1) - Code(Counter(0)) at (prev + 3, 9) to (start + 0, 10) +Highest counter ID seen: c1 diff --git a/tests/coverage/no_spans.cov-map b/tests/coverage/no_spans.cov-map index 30171c3f31939..7f43b68fa9043 100644 --- a/tests/coverage/no_spans.cov-map +++ b/tests/coverage/no_spans.cov-map @@ -5,6 +5,7 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 26, 28) to (start + 0, 29) +Highest counter ID seen: c0 Function name: no_spans::affected_function::{closure#0} Raw bytes (9): 0x[01, 01, 00, 01, 01, 1b, 0c, 00, 0e] @@ -13,4 +14,5 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 27, 12) to (start + 0, 14) +Highest counter ID seen: c0 diff --git a/tests/coverage/no_spans_if_not.cov-map b/tests/coverage/no_spans_if_not.cov-map index bc3e14eddd546..9cb7e6a6cff2e 100644 --- a/tests/coverage/no_spans_if_not.cov-map +++ b/tests/coverage/no_spans_if_not.cov-map @@ -9,6 +9,7 @@ Number of file 0 mappings: 3 - Code(Expression(0, Sub)) at (prev + 2, 13) to (start + 0, 15) = (c0 - Zero) - Code(Zero) at (prev + 2, 13) to (start + 0, 15) +Highest counter ID seen: c0 Function name: no_spans_if_not::main Raw bytes (9): 0x[01, 01, 00, 01, 01, 0b, 01, 02, 02] @@ -17,4 +18,5 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 11, 1) to (start + 2, 2) +Highest counter ID seen: c0 diff --git a/tests/coverage/overflow.cov-map b/tests/coverage/overflow.cov-map index cb31f3d1f3e4d..f842ce3e896b1 100644 --- a/tests/coverage/overflow.cov-map +++ b/tests/coverage/overflow.cov-map @@ -25,6 +25,7 @@ Number of file 0 mappings: 9 - Code(Expression(6, Add)) at (prev + 1, 9) to (start + 0, 23) = (c1 + (c2 + c3)) - Code(Counter(4)) at (prev + 2, 5) to (start + 1, 2) +Highest counter ID seen: c4 Function name: overflow::might_overflow Raw bytes (26): 0x[01, 01, 01, 01, 05, 04, 01, 05, 01, 01, 12, 05, 01, 13, 02, 06, 02, 02, 06, 00, 07, 01, 01, 09, 05, 02] @@ -38,4 +39,5 @@ Number of file 0 mappings: 4 - Code(Expression(0, Sub)) at (prev + 2, 6) to (start + 0, 7) = (c0 - c1) - Code(Counter(0)) at (prev + 1, 9) to (start + 5, 2) +Highest counter ID seen: c1 diff --git a/tests/coverage/panic_unwind.cov-map b/tests/coverage/panic_unwind.cov-map index f6089ce55ae29..f4a7894cc1cc1 100644 --- a/tests/coverage/panic_unwind.cov-map +++ b/tests/coverage/panic_unwind.cov-map @@ -25,6 +25,7 @@ Number of file 0 mappings: 9 - Code(Expression(6, Add)) at (prev + 1, 9) to (start + 0, 23) = (c1 + (c2 + c3)) - Code(Counter(4)) at (prev + 2, 5) to (start + 1, 2) +Highest counter ID seen: c4 Function name: panic_unwind::might_panic Raw bytes (21): 0x[01, 01, 01, 01, 05, 03, 01, 04, 01, 01, 14, 05, 02, 09, 01, 19, 02, 02, 0c, 03, 02] @@ -37,4 +38,5 @@ Number of file 0 mappings: 3 - Code(Counter(1)) at (prev + 2, 9) to (start + 1, 25) - Code(Expression(0, Sub)) at (prev + 2, 12) to (start + 3, 2) = (c0 - c1) +Highest counter ID seen: c1 diff --git a/tests/coverage/partial_eq.cov-map b/tests/coverage/partial_eq.cov-map index 6c39ac0e378b8..21c8714ac99ba 100644 --- a/tests/coverage/partial_eq.cov-map +++ b/tests/coverage/partial_eq.cov-map @@ -5,6 +5,7 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 12, 5) to (start + 2, 6) +Highest counter ID seen: c0 Function name: partial_eq::main Raw bytes (9): 0x[01, 01, 00, 01, 01, 11, 01, 0a, 02] @@ -13,4 +14,5 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 17, 1) to (start + 10, 2) +Highest counter ID seen: c0 diff --git a/tests/coverage/simple_loop.cov-map b/tests/coverage/simple_loop.cov-map index 541f7bf8fbdcb..b6f1e8f6afe6a 100644 --- a/tests/coverage/simple_loop.cov-map +++ b/tests/coverage/simple_loop.cov-map @@ -15,4 +15,5 @@ Number of file 0 mappings: 7 - Code(Counter(0)) at (prev + 4, 13) to (start + 0, 18) - Code(Counter(2)) at (prev + 2, 10) to (start + 3, 10) - Code(Counter(0)) at (prev + 6, 1) to (start + 0, 2) +Highest counter ID seen: c2 diff --git a/tests/coverage/simple_match.cov-map b/tests/coverage/simple_match.cov-map index 49819b23482f3..b62edf12650ca 100644 --- a/tests/coverage/simple_match.cov-map +++ b/tests/coverage/simple_match.cov-map @@ -27,4 +27,5 @@ Number of file 0 mappings: 10 - Code(Counter(2)) at (prev + 4, 13) to (start + 7, 14) - Code(Counter(3)) at (prev + 10, 13) to (start + 0, 15) - Code(Counter(4)) at (prev + 3, 1) to (start + 0, 2) +Highest counter ID seen: c4 diff --git a/tests/coverage/sort_groups.cov-map b/tests/coverage/sort_groups.cov-map index 361b70fb74f76..4e7ed059c879d 100644 --- a/tests/coverage/sort_groups.cov-map +++ b/tests/coverage/sort_groups.cov-map @@ -10,6 +10,7 @@ Number of file 0 mappings: 4 - Code(Expression(0, Sub)) at (prev + 2, 6) to (start + 0, 7) = (c0 - c1) - Code(Counter(0)) at (prev + 1, 1) to (start + 0, 2) +Highest counter ID seen: c1 Function name: sort_groups::generic_fn::<()> Raw bytes (26): 0x[01, 01, 01, 01, 05, 04, 01, 11, 01, 01, 0c, 05, 01, 0d, 02, 06, 02, 02, 06, 00, 07, 01, 01, 01, 00, 02] @@ -23,6 +24,7 @@ Number of file 0 mappings: 4 - Code(Expression(0, Sub)) at (prev + 2, 6) to (start + 0, 7) = (c0 - c1) - Code(Counter(0)) at (prev + 1, 1) to (start + 0, 2) +Highest counter ID seen: c1 Function name: sort_groups::generic_fn:: Raw bytes (26): 0x[01, 01, 01, 01, 05, 04, 01, 11, 01, 01, 0c, 05, 01, 0d, 02, 06, 02, 02, 06, 00, 07, 01, 01, 01, 00, 02] @@ -36,6 +38,7 @@ Number of file 0 mappings: 4 - Code(Expression(0, Sub)) at (prev + 2, 6) to (start + 0, 7) = (c0 - c1) - Code(Counter(0)) at (prev + 1, 1) to (start + 0, 2) +Highest counter ID seen: c1 Function name: sort_groups::generic_fn:: Raw bytes (26): 0x[01, 01, 01, 01, 05, 04, 01, 11, 01, 01, 0c, 05, 01, 0d, 02, 06, 02, 02, 06, 00, 07, 01, 01, 01, 00, 02] @@ -49,6 +52,7 @@ Number of file 0 mappings: 4 - Code(Expression(0, Sub)) at (prev + 2, 6) to (start + 0, 7) = (c0 - c1) - Code(Counter(0)) at (prev + 1, 1) to (start + 0, 2) +Highest counter ID seen: c1 Function name: sort_groups::main Raw bytes (26): 0x[01, 01, 01, 01, 05, 04, 01, 06, 01, 04, 23, 05, 04, 24, 02, 06, 02, 02, 06, 00, 07, 01, 01, 05, 02, 02] @@ -62,6 +66,7 @@ Number of file 0 mappings: 4 - Code(Expression(0, Sub)) at (prev + 2, 6) to (start + 0, 7) = (c0 - c1) - Code(Counter(0)) at (prev + 1, 5) to (start + 2, 2) +Highest counter ID seen: c1 Function name: sort_groups::other_fn Raw bytes (9): 0x[01, 01, 00, 01, 01, 17, 01, 00, 11] @@ -70,4 +75,5 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 23, 1) to (start + 0, 17) +Highest counter ID seen: c0 diff --git a/tests/coverage/test_harness.cov-map b/tests/coverage/test_harness.cov-map index f75328b11c9ab..b513b3d054945 100644 --- a/tests/coverage/test_harness.cov-map +++ b/tests/coverage/test_harness.cov-map @@ -5,6 +5,7 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 10, 1) to (start + 0, 16) +Highest counter ID seen: c0 Function name: test_harness::unused (unused) Raw bytes (9): 0x[01, 01, 00, 01, 00, 07, 01, 00, 0f] @@ -13,4 +14,5 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Zero) at (prev + 7, 1) to (start + 0, 15) +Highest counter ID seen: (none) diff --git a/tests/coverage/tight_inf_loop.cov-map b/tests/coverage/tight_inf_loop.cov-map index 7fe3146b0809a..2d2d59bf013ec 100644 --- a/tests/coverage/tight_inf_loop.cov-map +++ b/tests/coverage/tight_inf_loop.cov-map @@ -9,4 +9,5 @@ Number of file 0 mappings: 3 - Code(Zero) at (prev + 2, 9) to (start + 0, 16) - Code(Expression(0, Sub)) at (prev + 1, 6) to (start + 1, 2) = (c0 - Zero) +Highest counter ID seen: c0 diff --git a/tests/coverage/trivial.cov-map b/tests/coverage/trivial.cov-map index 874e294a1c498..05f64896d9ec9 100644 --- a/tests/coverage/trivial.cov-map +++ b/tests/coverage/trivial.cov-map @@ -5,4 +5,5 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 3, 1) to (start + 0, 13) +Highest counter ID seen: c0 diff --git a/tests/coverage/try_error_result.cov-map b/tests/coverage/try_error_result.cov-map index 11a99f5395ec8..246a1ba738b28 100644 --- a/tests/coverage/try_error_result.cov-map +++ b/tests/coverage/try_error_result.cov-map @@ -10,6 +10,7 @@ Number of file 0 mappings: 4 - Code(Expression(0, Sub)) at (prev + 2, 13) to (start + 0, 26) = (c0 - c1) - Code(Counter(0)) at (prev + 2, 5) to (start + 0, 6) +Highest counter ID seen: c1 Function name: ::call Raw bytes (26): 0x[01, 01, 01, 01, 05, 04, 01, 34, 05, 01, 18, 05, 02, 0d, 00, 14, 02, 02, 0d, 00, 13, 01, 02, 05, 00, 06] @@ -23,6 +24,7 @@ Number of file 0 mappings: 4 - Code(Expression(0, Sub)) at (prev + 2, 13) to (start + 0, 19) = (c0 - c1) - Code(Counter(0)) at (prev + 2, 5) to (start + 0, 6) +Highest counter ID seen: c1 Function name: try_error_result::call Raw bytes (26): 0x[01, 01, 01, 01, 05, 04, 01, 05, 01, 01, 14, 05, 02, 09, 00, 10, 02, 02, 09, 00, 0f, 01, 02, 01, 00, 02] @@ -36,6 +38,7 @@ Number of file 0 mappings: 4 - Code(Expression(0, Sub)) at (prev + 2, 9) to (start + 0, 15) = (c0 - c1) - Code(Counter(0)) at (prev + 2, 1) to (start + 0, 2) +Highest counter ID seen: c1 Function name: try_error_result::main Raw bytes (26): 0x[01, 01, 01, 01, 05, 04, 01, 71, 01, 02, 0c, 05, 03, 05, 00, 06, 02, 02, 05, 00, 0b, 01, 01, 01, 00, 02] @@ -49,6 +52,7 @@ Number of file 0 mappings: 4 - Code(Expression(0, Sub)) at (prev + 2, 5) to (start + 0, 11) = (c0 - c1) - Code(Counter(0)) at (prev + 1, 1) to (start + 0, 2) +Highest counter ID seen: c1 Function name: try_error_result::test1 Raw bytes (75): 0x[01, 01, 08, 01, 07, 00, 09, 03, 0d, 12, 1d, 03, 0d, 1b, 0d, 1f, 00, 11, 00, 0b, 01, 0d, 01, 02, 17, 03, 07, 09, 00, 0e, 12, 02, 09, 04, 1a, 1d, 06, 0d, 00, 29, 11, 00, 29, 00, 2a, 00, 01, 0d, 00, 2a, 00, 00, 2a, 00, 2b, 0e, 04, 0d, 00, 2a, 00, 00, 2a, 00, 2b, 0d, 03, 05, 00, 0b, 17, 01, 01, 00, 02] @@ -79,6 +83,7 @@ Number of file 0 mappings: 11 - Code(Counter(3)) at (prev + 3, 5) to (start + 0, 11) - Code(Expression(5, Add)) at (prev + 1, 1) to (start + 0, 2) = (((c4 + Zero) + Zero) + c3) +Highest counter ID seen: c7 Function name: try_error_result::test2 Raw bytes (358): 0x[01, 01, 3b, 01, 07, 05, 09, 03, 0d, 41, 11, 4a, 15, 41, 11, 42, 1d, 46, 19, 4a, 15, 41, 11, 4a, 15, 41, 11, 46, 19, 4a, 15, 41, 11, 42, 1d, 46, 19, 4a, 15, 41, 11, 5e, 25, 49, 21, 49, 21, 5e, 25, 49, 21, 8a, 01, 2d, 8e, 01, 29, 92, 01, 41, 03, 0d, 92, 01, 41, 03, 0d, 8e, 01, 29, 92, 01, 41, 03, 0d, 8a, 01, 2d, 8e, 01, 29, 92, 01, 41, 03, 0d, a6, 01, 35, 45, 31, 45, 31, a6, 01, 35, 45, 31, ba, 01, 3d, 4d, 39, 4d, 39, ba, 01, 3d, 4d, 39, c3, 01, 0d, c7, 01, db, 01, cb, 01, cf, 01, 11, 15, d3, 01, d7, 01, 19, 1d, 21, 25, df, 01, e3, 01, 29, 2d, e7, 01, eb, 01, 31, 35, 39, 3d, 28, 01, 3d, 01, 03, 17, 03, 08, 09, 00, 0e, 92, 01, 02, 09, 04, 1a, 41, 06, 0d, 00, 2f, 11, 00, 2f, 00, 30, 4a, 00, 31, 03, 35, 15, 04, 11, 00, 12, 46, 02, 11, 04, 12, 3e, 05, 11, 00, 14, 46, 00, 17, 00, 41, 19, 00, 41, 00, 42, 42, 00, 43, 00, 5f, 1d, 00, 5f, 00, 60, 3e, 01, 0d, 00, 20, 5a, 01, 11, 00, 14, 49, 00, 17, 00, 41, 21, 00, 41, 00, 42, 5e, 00, 43, 00, 60, 25, 00, 60, 00, 61, 5a, 01, 0d, 00, 20, 86, 01, 04, 11, 00, 14, 8e, 01, 00, 17, 00, 42, 29, 00, 42, 00, 43, 8a, 01, 00, 44, 00, 61, 2d, 00, 61, 00, 62, 86, 01, 01, 0d, 00, 20, a2, 01, 01, 11, 00, 14, 45, 00, 17, 01, 36, 31, 01, 36, 00, 37, a6, 01, 01, 12, 00, 2f, 35, 00, 2f, 00, 30, a2, 01, 01, 0d, 00, 20, b6, 01, 01, 11, 00, 14, 4d, 00, 17, 01, 36, 39, 02, 11, 00, 12, ba, 01, 01, 12, 00, 2f, 3d, 01, 11, 00, 12, b6, 01, 02, 0d, 00, 20, 0d, 03, 05, 00, 0b, bf, 01, 01, 01, 00, 02] @@ -207,4 +212,5 @@ Number of file 0 mappings: 40 - Code(Counter(3)) at (prev + 3, 5) to (start + 0, 11) - Code(Expression(47, Add)) at (prev + 1, 1) to (start + 0, 2) = ((((c4 + c5) + ((c6 + c7) + (c8 + c9))) + ((c10 + c11) + ((c12 + c13) + (c14 + c15)))) + c3) +Highest counter ID seen: c19 diff --git a/tests/coverage/unicode.cov-map b/tests/coverage/unicode.cov-map index 06a2c930498b5..ac4e691ea7abf 100644 --- a/tests/coverage/unicode.cov-map +++ b/tests/coverage/unicode.cov-map @@ -22,6 +22,7 @@ Number of file 0 mappings: 9 = ((c0 - c2) + c3) - Code(Expression(3, Add)) at (prev + 2, 5) to (start + 1, 2) = (c4 + ((c0 - c2) + c3)) +Highest counter ID seen: c4 Function name: unicode::他 (unused) Raw bytes (9): 0x[01, 01, 00, 01, 00, 1e, 19, 00, 25] @@ -30,6 +31,7 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Zero) at (prev + 30, 25) to (start + 0, 37) +Highest counter ID seen: (none) Function name: unicode::申し訳ございません Raw bytes (9): 0x[01, 01, 00, 01, 01, 18, 01, 02, 02] @@ -38,4 +40,5 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 24, 1) to (start + 2, 2) +Highest counter ID seen: c0 diff --git a/tests/coverage/unreachable.cov-map b/tests/coverage/unreachable.cov-map index 09d3b2345431b..d4a5936a78483 100644 --- a/tests/coverage/unreachable.cov-map +++ b/tests/coverage/unreachable.cov-map @@ -5,6 +5,7 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Zero) at (prev + 15, 39) to (start + 0, 71) +Highest counter ID seen: (none) Function name: unreachable::unreachable_function (unused) Raw bytes (9): 0x[01, 01, 00, 01, 00, 11, 01, 01, 25] @@ -13,6 +14,7 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Zero) at (prev + 17, 1) to (start + 1, 37) +Highest counter ID seen: (none) Function name: unreachable::unreachable_intrinsic (unused) Raw bytes (9): 0x[01, 01, 00, 01, 00, 16, 01, 01, 2c] @@ -21,4 +23,5 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Zero) at (prev + 22, 1) to (start + 1, 44) +Highest counter ID seen: (none) diff --git a/tests/coverage/unused.cov-map b/tests/coverage/unused.cov-map index 9383d1e90ac20..9f1ad59ce83dd 100644 --- a/tests/coverage/unused.cov-map +++ b/tests/coverage/unused.cov-map @@ -17,6 +17,7 @@ Number of file 0 mappings: 6 - Code(Expression(3, Add)) at (prev + 1, 9) to (start + 0, 15) = (c1 + c2) - Code(Counter(3)) at (prev + 2, 1) to (start + 0, 2) +Highest counter ID seen: c3 Function name: unused::foo:: Raw bytes (42): 0x[01, 01, 04, 01, 0f, 05, 09, 03, 0d, 05, 09, 06, 01, 03, 01, 01, 12, 03, 02, 0b, 00, 11, 0a, 01, 09, 00, 0f, 09, 00, 13, 00, 19, 0f, 01, 09, 00, 0f, 0d, 02, 01, 00, 02] @@ -37,6 +38,7 @@ Number of file 0 mappings: 6 - Code(Expression(3, Add)) at (prev + 1, 9) to (start + 0, 15) = (c1 + c2) - Code(Counter(3)) at (prev + 2, 1) to (start + 0, 2) +Highest counter ID seen: c3 Function name: unused::main Raw bytes (9): 0x[01, 01, 00, 01, 01, 25, 01, 04, 02] @@ -45,6 +47,7 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 37, 1) to (start + 4, 2) +Highest counter ID seen: c0 Function name: unused::unused_func (unused) Raw bytes (24): 0x[01, 01, 00, 04, 00, 13, 01, 01, 0e, 00, 01, 0f, 02, 06, 00, 02, 06, 00, 07, 00, 01, 01, 00, 02] @@ -56,6 +59,7 @@ Number of file 0 mappings: 4 - Code(Zero) at (prev + 1, 15) to (start + 2, 6) - Code(Zero) at (prev + 2, 6) to (start + 0, 7) - Code(Zero) at (prev + 1, 1) to (start + 0, 2) +Highest counter ID seen: (none) Function name: unused::unused_func2 (unused) Raw bytes (24): 0x[01, 01, 00, 04, 00, 19, 01, 01, 0e, 00, 01, 0f, 02, 06, 00, 02, 06, 00, 07, 00, 01, 01, 00, 02] @@ -67,6 +71,7 @@ Number of file 0 mappings: 4 - Code(Zero) at (prev + 1, 15) to (start + 2, 6) - Code(Zero) at (prev + 2, 6) to (start + 0, 7) - Code(Zero) at (prev + 1, 1) to (start + 0, 2) +Highest counter ID seen: (none) Function name: unused::unused_func3 (unused) Raw bytes (24): 0x[01, 01, 00, 04, 00, 1f, 01, 01, 0e, 00, 01, 0f, 02, 06, 00, 02, 06, 00, 07, 00, 01, 01, 00, 02] @@ -78,6 +83,7 @@ Number of file 0 mappings: 4 - Code(Zero) at (prev + 1, 15) to (start + 2, 6) - Code(Zero) at (prev + 2, 6) to (start + 0, 7) - Code(Zero) at (prev + 1, 1) to (start + 0, 2) +Highest counter ID seen: (none) Function name: unused::unused_template_func::<_> (unused) Raw bytes (34): 0x[01, 01, 00, 06, 00, 0b, 01, 01, 12, 00, 02, 0b, 00, 11, 00, 01, 09, 00, 0f, 00, 00, 13, 00, 19, 00, 01, 09, 00, 0f, 00, 02, 01, 00, 02] @@ -91,4 +97,5 @@ Number of file 0 mappings: 6 - Code(Zero) at (prev + 0, 19) to (start + 0, 25) - Code(Zero) at (prev + 1, 9) to (start + 0, 15) - Code(Zero) at (prev + 2, 1) to (start + 0, 2) +Highest counter ID seen: (none) diff --git a/tests/coverage/unused_mod.cov-map b/tests/coverage/unused_mod.cov-map index 241cb2610ffc0..af10906fa3c54 100644 --- a/tests/coverage/unused_mod.cov-map +++ b/tests/coverage/unused_mod.cov-map @@ -5,6 +5,7 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 4, 1) to (start + 2, 2) +Highest counter ID seen: c0 Function name: unused_mod::unused_module::never_called_function (unused) Raw bytes (9): 0x[01, 01, 00, 01, 00, 02, 01, 02, 02] @@ -13,4 +14,5 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Zero) at (prev + 2, 1) to (start + 2, 2) +Highest counter ID seen: (none) diff --git a/tests/coverage/uses_crate.cov-map b/tests/coverage/uses_crate.cov-map index 9c06eab700507..5c23f88269714 100644 --- a/tests/coverage/uses_crate.cov-map +++ b/tests/coverage/uses_crate.cov-map @@ -5,6 +5,7 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 27, 1) to (start + 2, 2) +Highest counter ID seen: c0 Function name: used_crate::used_only_from_bin_crate_generic_function::<&alloc::vec::Vec> Raw bytes (9): 0x[01, 01, 00, 01, 01, 13, 01, 02, 02] @@ -13,6 +14,7 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 19, 1) to (start + 2, 2) +Highest counter ID seen: c0 Function name: used_crate::used_only_from_bin_crate_generic_function::<&str> Raw bytes (9): 0x[01, 01, 00, 01, 01, 13, 01, 02, 02] @@ -21,6 +23,7 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 19, 1) to (start + 2, 2) +Highest counter ID seen: c0 Function name: used_crate::used_with_same_type_from_bin_crate_and_lib_crate_generic_function::<&str> Raw bytes (9): 0x[01, 01, 00, 01, 01, 1f, 01, 02, 02] @@ -29,6 +32,7 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 31, 1) to (start + 2, 2) +Highest counter ID seen: c0 Function name: uses_crate::main Raw bytes (9): 0x[01, 02, 00, 01, 01, 0c, 01, 07, 02] @@ -37,4 +41,5 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 12, 1) to (start + 7, 2) +Highest counter ID seen: c0 diff --git a/tests/coverage/uses_inline_crate.cov-map b/tests/coverage/uses_inline_crate.cov-map index 55ceb46b0602d..a6909768162bd 100644 --- a/tests/coverage/uses_inline_crate.cov-map +++ b/tests/coverage/uses_inline_crate.cov-map @@ -5,6 +5,7 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 44, 1) to (start + 2, 2) +Highest counter ID seen: c0 Function name: used_inline_crate::used_inline_function Raw bytes (26): 0x[01, 01, 01, 01, 05, 04, 01, 14, 01, 06, 0f, 05, 06, 10, 02, 06, 02, 02, 06, 00, 07, 01, 01, 05, 01, 02] @@ -18,6 +19,7 @@ Number of file 0 mappings: 4 - Code(Expression(0, Sub)) at (prev + 2, 6) to (start + 0, 7) = (c0 - c1) - Code(Counter(0)) at (prev + 1, 5) to (start + 1, 2) +Highest counter ID seen: c1 Function name: used_inline_crate::used_only_from_bin_crate_generic_function::<&alloc::vec::Vec> Raw bytes (9): 0x[01, 01, 00, 01, 01, 21, 01, 02, 02] @@ -26,6 +28,7 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 33, 1) to (start + 2, 2) +Highest counter ID seen: c0 Function name: used_inline_crate::used_only_from_bin_crate_generic_function::<&str> Raw bytes (9): 0x[01, 01, 00, 01, 01, 21, 01, 02, 02] @@ -34,6 +37,7 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 33, 1) to (start + 2, 2) +Highest counter ID seen: c0 Function name: used_inline_crate::used_with_same_type_from_bin_crate_and_lib_crate_generic_function::<&str> Raw bytes (9): 0x[01, 01, 00, 01, 01, 31, 01, 02, 02] @@ -42,6 +46,7 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 49, 1) to (start + 2, 2) +Highest counter ID seen: c0 Function name: uses_inline_crate::main Raw bytes (9): 0x[01, 02, 00, 01, 01, 0c, 01, 0a, 02] @@ -50,4 +55,5 @@ Number of files: 1 Number of expressions: 0 Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 12, 1) to (start + 10, 2) +Highest counter ID seen: c0 diff --git a/tests/coverage/while.cov-map b/tests/coverage/while.cov-map index 4d813a935a058..29493a651dcbb 100644 --- a/tests/coverage/while.cov-map +++ b/tests/coverage/while.cov-map @@ -10,4 +10,5 @@ Number of file 0 mappings: 4 = (c0 + Zero) - Code(Zero) at (prev + 0, 21) to (start + 2, 6) - Code(Counter(0)) at (prev + 3, 1) to (start + 0, 2) +Highest counter ID seen: c0 diff --git a/tests/coverage/while_early_ret.cov-map b/tests/coverage/while_early_ret.cov-map index c883eb4baf200..6254dfbcf010e 100644 --- a/tests/coverage/while_early_ret.cov-map +++ b/tests/coverage/while_early_ret.cov-map @@ -23,4 +23,5 @@ Number of file 0 mappings: 9 - Code(Counter(2)) at (prev + 6, 5) to (start + 0, 11) - Code(Expression(4, Add)) at (prev + 1, 1) to (start + 0, 2) = ((c3 + c4) + c2) +Highest counter ID seen: c4 diff --git a/tests/coverage/yield.cov-map b/tests/coverage/yield.cov-map index a273c688e248a..578994a45305d 100644 --- a/tests/coverage/yield.cov-map +++ b/tests/coverage/yield.cov-map @@ -39,6 +39,7 @@ Number of file 0 mappings: 16 - Code(Expression(10, Add)) at (prev + 1, 14) to (start + 0, 52) = (c9 + c10) - Code(Counter(11)) at (prev + 2, 1) to (start + 0, 2) +Highest counter ID seen: c11 Function name: yield::main::{closure#0} Raw bytes (14): 0x[01, 01, 00, 02, 01, 09, 08, 01, 10, 05, 02, 10, 01, 06] @@ -48,6 +49,7 @@ Number of expressions: 0 Number of file 0 mappings: 2 - Code(Counter(0)) at (prev + 9, 8) to (start + 1, 16) - Code(Counter(1)) at (prev + 2, 16) to (start + 1, 6) +Highest counter ID seen: c1 Function name: yield::main::{closure#1} Raw bytes (24): 0x[01, 01, 00, 04, 01, 18, 08, 01, 10, 05, 02, 09, 00, 10, 09, 01, 09, 00, 10, 0d, 01, 10, 01, 06] @@ -59,4 +61,5 @@ Number of file 0 mappings: 4 - Code(Counter(1)) at (prev + 2, 9) to (start + 0, 16) - Code(Counter(2)) at (prev + 1, 9) to (start + 0, 16) - Code(Counter(3)) at (prev + 1, 16) to (start + 1, 6) +Highest counter ID seen: c3 From 78fd3b53190857d851fbdab06b3b9fa9bd638292 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Fri, 11 Oct 2024 13:13:24 +1100 Subject: [PATCH 2112/2194] Extract auxiliary-crate properties to their own module/struct --- src/tools/compiletest/src/header.rs | 40 ++++------------- src/tools/compiletest/src/header/auxiliary.rs | 44 +++++++++++++++++++ src/tools/compiletest/src/runtest.rs | 18 ++++---- 3 files changed, 62 insertions(+), 40 deletions(-) create mode 100644 src/tools/compiletest/src/header/auxiliary.rs diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs index bd0ed6321bc1c..caae87393ff9a 100644 --- a/src/tools/compiletest/src/header.rs +++ b/src/tools/compiletest/src/header.rs @@ -9,11 +9,13 @@ use std::process::Command; use tracing::*; use crate::common::{Config, Debugger, FailMode, Mode, PassMode}; +use crate::header::auxiliary::{AuxProps, parse_and_update_aux}; use crate::header::cfg::{MatchOutcome, parse_cfg_name_directive}; use crate::header::needs::CachedNeedsConditions; use crate::util::static_regex; use crate::{extract_cdb_version, extract_gdb_version}; +pub(crate) mod auxiliary; mod cfg; mod needs; #[cfg(test)] @@ -98,18 +100,8 @@ pub struct TestProps { // If present, the name of a file that this test should match when // pretty-printed pub pp_exact: Option, - // Other crates that should be compiled (typically from the same - // directory as the test, but for backwards compatibility reasons - // we also check the auxiliary directory) - pub aux_builds: Vec, - // Auxiliary crates that should be compiled as `#![crate_type = "bin"]`. - pub aux_bins: Vec, - // Similar to `aux_builds`, but a list of NAME=somelib.rs of dependencies - // to build and pass with the `--extern` flag. - pub aux_crates: Vec<(String, String)>, - /// Similar to `aux_builds`, but also passes the resulting dylib path to - /// `-Zcodegen-backend`. - pub aux_codegen_backend: Option, + /// Auxiliary crates that should be built and made available to this test. + pub(crate) aux: AuxProps, // Environment settings to use for compiling pub rustc_env: Vec<(String, String)>, // Environment variables to unset prior to compiling. @@ -276,10 +268,7 @@ impl TestProps { run_flags: vec![], doc_flags: vec![], pp_exact: None, - aux_builds: vec![], - aux_bins: vec![], - aux_crates: vec![], - aux_codegen_backend: None, + aux: Default::default(), revisions: vec![], rustc_env: vec![ ("RUSTC_ICE".to_string(), "0".to_string()), @@ -454,21 +443,10 @@ impl TestProps { PRETTY_COMPARE_ONLY, &mut self.pretty_compare_only, ); - config.push_name_value_directive(ln, AUX_BUILD, &mut self.aux_builds, |r| { - r.trim().to_string() - }); - config.push_name_value_directive(ln, AUX_BIN, &mut self.aux_bins, |r| { - r.trim().to_string() - }); - config.push_name_value_directive( - ln, - AUX_CRATE, - &mut self.aux_crates, - Config::parse_aux_crate, - ); - if let Some(r) = config.parse_name_value_directive(ln, AUX_CODEGEN_BACKEND) { - self.aux_codegen_backend = Some(r.trim().to_owned()); - } + + // Call a helper method to deal with aux-related directives. + parse_and_update_aux(config, ln, &mut self.aux); + config.push_name_value_directive( ln, EXEC_ENV, diff --git a/src/tools/compiletest/src/header/auxiliary.rs b/src/tools/compiletest/src/header/auxiliary.rs new file mode 100644 index 0000000000000..2a94622264a26 --- /dev/null +++ b/src/tools/compiletest/src/header/auxiliary.rs @@ -0,0 +1,44 @@ +//! Code for dealing with test directives that request an "auxiliary" crate to +//! be built and made available to the test in some way. + +use crate::common::Config; +use crate::header::directives::{AUX_BIN, AUX_BUILD, AUX_CODEGEN_BACKEND, AUX_CRATE}; + +/// Properties parsed from `aux-*` test directives. +#[derive(Clone, Debug, Default)] +pub(crate) struct AuxProps { + /// Other crates that should be built and made available to this test. + /// These are filenames relative to `./auxiliary/` in the test's directory. + pub(crate) builds: Vec, + /// Auxiliary crates that should be compiled as `#![crate_type = "bin"]`. + pub(crate) bins: Vec, + /// Similar to `builds`, but a list of NAME=somelib.rs of dependencies + /// to build and pass with the `--extern` flag. + pub(crate) crates: Vec<(String, String)>, + /// Similar to `builds`, but also uses the resulting dylib as a + /// `-Zcodegen-backend` when compiling the test file. + pub(crate) codegen_backend: Option, +} + +/// If the given test directive line contains an `aux-*` directive, parse it +/// and update [`AuxProps`] accordingly. +pub(super) fn parse_and_update_aux(config: &Config, ln: &str, aux: &mut AuxProps) { + if !ln.starts_with("aux-") { + return; + } + + config.push_name_value_directive(ln, AUX_BUILD, &mut aux.builds, |r| r.trim().to_string()); + config.push_name_value_directive(ln, AUX_BIN, &mut aux.bins, |r| r.trim().to_string()); + config.push_name_value_directive(ln, AUX_CRATE, &mut aux.crates, parse_aux_crate); + if let Some(r) = config.parse_name_value_directive(ln, AUX_CODEGEN_BACKEND) { + aux.codegen_backend = Some(r.trim().to_owned()); + } +} + +fn parse_aux_crate(r: String) -> (String, String) { + let mut parts = r.trim().splitn(2, '='); + ( + parts.next().expect("missing aux-crate name (e.g. log=log.rs)").to_string(), + parts.next().expect("missing aux-crate value (e.g. log=log.rs)").to_string(), + ) +} diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 1baf0c56e3717..46f7b9c0e7de1 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -841,13 +841,13 @@ impl<'test> TestCx<'test> { /// Auxiliaries, no matter how deep, have the same root_out_dir and root_testpaths. fn document(&self, root_out_dir: &Path, root_testpaths: &TestPaths) -> ProcRes { if self.props.build_aux_docs { - for rel_ab in &self.props.aux_builds { + for rel_ab in &self.props.aux.builds { let aux_testpaths = self.compute_aux_test_paths(root_testpaths, rel_ab); - let aux_props = + let props_for_aux = self.props.from_aux_file(&aux_testpaths.file, self.revision, self.config); let aux_cx = TestCx { config: self.config, - props: &aux_props, + props: &props_for_aux, testpaths: &aux_testpaths, revision: self.revision, }; @@ -1059,11 +1059,11 @@ impl<'test> TestCx<'test> { fn aux_output_dir(&self) -> PathBuf { let aux_dir = self.aux_output_dir_name(); - if !self.props.aux_builds.is_empty() { + if !self.props.aux.builds.is_empty() { remove_and_create_dir_all(&aux_dir); } - if !self.props.aux_bins.is_empty() { + if !self.props.aux.bins.is_empty() { let aux_bin_dir = self.aux_bin_output_dir_name(); remove_and_create_dir_all(&aux_dir); remove_and_create_dir_all(&aux_bin_dir); @@ -1073,15 +1073,15 @@ impl<'test> TestCx<'test> { } fn build_all_auxiliary(&self, of: &TestPaths, aux_dir: &Path, rustc: &mut Command) { - for rel_ab in &self.props.aux_builds { + for rel_ab in &self.props.aux.builds { self.build_auxiliary(of, rel_ab, &aux_dir, false /* is_bin */); } - for rel_ab in &self.props.aux_bins { + for rel_ab in &self.props.aux.bins { self.build_auxiliary(of, rel_ab, &aux_dir, true /* is_bin */); } - for (aux_name, aux_path) in &self.props.aux_crates { + for (aux_name, aux_path) in &self.props.aux.crates { let aux_type = self.build_auxiliary(of, &aux_path, &aux_dir, false /* is_bin */); let lib_name = get_lib_name(&aux_path.trim_end_matches(".rs").replace('-', "_"), aux_type); @@ -1097,7 +1097,7 @@ impl<'test> TestCx<'test> { // Build any `//@ aux-codegen-backend`, and pass the resulting library // to `-Zcodegen-backend` when compiling the test file. - if let Some(aux_file) = &self.props.aux_codegen_backend { + if let Some(aux_file) = &self.props.aux.codegen_backend { let aux_type = self.build_auxiliary(of, aux_file, aux_dir, false); if let Some(lib_name) = get_lib_name(aux_file.trim_end_matches(".rs"), aux_type) { let lib_path = aux_dir.join(&lib_name); From 188f7ce91b2a69988846a6af5adb7807434940b6 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Fri, 11 Oct 2024 13:19:08 +1100 Subject: [PATCH 2113/2194] Use the same `AuxProps` parser for `EarlyProps` --- src/tools/compiletest/src/header.rs | 31 ++++------------------- src/tools/compiletest/src/header/tests.rs | 3 ++- src/tools/compiletest/src/lib.rs | 3 ++- 3 files changed, 9 insertions(+), 28 deletions(-) diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs index caae87393ff9a..63d05886166ae 100644 --- a/src/tools/compiletest/src/header.rs +++ b/src/tools/compiletest/src/header.rs @@ -35,9 +35,10 @@ impl HeadersCache { /// the test. #[derive(Default)] pub struct EarlyProps { - pub aux: Vec, - pub aux_bin: Vec, - pub aux_crate: Vec<(String, String)>, + /// Auxiliary crates that should be built and made available to this test. + /// Included in [`EarlyProps`] so that the indicated files can participate + /// in up-to-date checking. Building happens via [`TestProps::aux`] instead. + pub(crate) aux: AuxProps, pub revisions: Vec, } @@ -57,21 +58,7 @@ impl EarlyProps { testfile, rdr, &mut |HeaderLine { directive: ln, .. }| { - config.push_name_value_directive(ln, directives::AUX_BUILD, &mut props.aux, |r| { - r.trim().to_string() - }); - config.push_name_value_directive( - ln, - directives::AUX_BIN, - &mut props.aux_bin, - |r| r.trim().to_string(), - ); - config.push_name_value_directive( - ln, - directives::AUX_CRATE, - &mut props.aux_crate, - Config::parse_aux_crate, - ); + parse_and_update_aux(config, ln, &mut props.aux); config.parse_and_update_revisions(ln, &mut props.revisions); }, ); @@ -920,14 +907,6 @@ fn iter_header( } impl Config { - fn parse_aux_crate(r: String) -> (String, String) { - let mut parts = r.trim().splitn(2, '='); - ( - parts.next().expect("missing aux-crate name (e.g. log=log.rs)").to_string(), - parts.next().expect("missing aux-crate value (e.g. log=log.rs)").to_string(), - ) - } - fn parse_and_update_revisions(&self, line: &str, existing: &mut Vec) { if let Some(raw) = self.parse_name_value_directive(line, "revisions") { let mut duplicates: HashSet<_> = existing.iter().cloned().collect(); diff --git a/src/tools/compiletest/src/header/tests.rs b/src/tools/compiletest/src/header/tests.rs index 10ec2a1806f8d..22dfa349e2bc3 100644 --- a/src/tools/compiletest/src/header/tests.rs +++ b/src/tools/compiletest/src/header/tests.rs @@ -242,7 +242,8 @@ fn aux_build() { //@ aux-build: b.rs " ) - .aux, + .aux + .builds, vec!["a.rs", "b.rs"], ); } diff --git a/src/tools/compiletest/src/lib.rs b/src/tools/compiletest/src/lib.rs index 98375a21b04b9..30215c0bbe68d 100644 --- a/src/tools/compiletest/src/lib.rs +++ b/src/tools/compiletest/src/lib.rs @@ -862,7 +862,8 @@ fn files_related_to_test( related.push(testpaths.file.clone()); } - for aux in &props.aux { + for aux in &props.aux.builds { + // FIXME(Zalathar): Perform all `auxiliary` path resolution in one place. let path = testpaths.file.parent().unwrap().join("auxiliary").join(aux); related.push(path); } From ec662b9c09ce9f472613a066dd42ae7bd7242e00 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Fri, 11 Oct 2024 20:05:12 +1100 Subject: [PATCH 2114/2194] Include all kinds of auxiliary crates in the up-to-date timestamp This was previously only including ordinary `aux-build` crates, and not files associated with the other three kinds of auxiliary crate. --- src/tools/compiletest/src/header/auxiliary.rs | 16 ++++++++++++++++ src/tools/compiletest/src/lib.rs | 2 +- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/src/tools/compiletest/src/header/auxiliary.rs b/src/tools/compiletest/src/header/auxiliary.rs index 2a94622264a26..6f6538ce196d4 100644 --- a/src/tools/compiletest/src/header/auxiliary.rs +++ b/src/tools/compiletest/src/header/auxiliary.rs @@ -1,6 +1,8 @@ //! Code for dealing with test directives that request an "auxiliary" crate to //! be built and made available to the test in some way. +use std::iter; + use crate::common::Config; use crate::header::directives::{AUX_BIN, AUX_BUILD, AUX_CODEGEN_BACKEND, AUX_CRATE}; @@ -20,6 +22,20 @@ pub(crate) struct AuxProps { pub(crate) codegen_backend: Option, } +impl AuxProps { + /// Yields all of the paths (relative to `./auxiliary/`) that have been + /// specified in `aux-*` directives for this test. + pub(crate) fn all_aux_path_strings(&self) -> impl Iterator { + let Self { builds, bins, crates, codegen_backend } = self; + + iter::empty() + .chain(builds.iter().map(String::as_str)) + .chain(bins.iter().map(String::as_str)) + .chain(crates.iter().map(|(_, path)| path.as_str())) + .chain(codegen_backend.iter().map(String::as_str)) + } +} + /// If the given test directive line contains an `aux-*` directive, parse it /// and update [`AuxProps`] accordingly. pub(super) fn parse_and_update_aux(config: &Config, ln: &str, aux: &mut AuxProps) { diff --git a/src/tools/compiletest/src/lib.rs b/src/tools/compiletest/src/lib.rs index 30215c0bbe68d..30d1644b14836 100644 --- a/src/tools/compiletest/src/lib.rs +++ b/src/tools/compiletest/src/lib.rs @@ -862,7 +862,7 @@ fn files_related_to_test( related.push(testpaths.file.clone()); } - for aux in &props.aux.builds { + for aux in props.aux.all_aux_path_strings() { // FIXME(Zalathar): Perform all `auxiliary` path resolution in one place. let path = testpaths.file.parent().unwrap().join("auxiliary").join(aux); related.push(path); From 5fd7be97e97cb41170c9bbc7f5359886374bea01 Mon Sep 17 00:00:00 2001 From: lcnr Date: Fri, 11 Oct 2024 10:40:36 +0000 Subject: [PATCH 2115/2194] remove outdated FIXMEs --- .../src/solve/eval_ctxt/canonical.rs | 1 - .../src/solve/eval_ctxt/mod.rs | 2 +- compiler/rustc_next_trait_solver/src/solve/mod.rs | 3 --- .../src/solve/normalizes_to/mod.rs | 2 +- .../rustc_next_trait_solver/src/solve/trait_goals.rs | 11 ++--------- compiler/rustc_trait_selection/src/solve/delegate.rs | 2 ++ 6 files changed, 6 insertions(+), 15 deletions(-) diff --git a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/canonical.rs b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/canonical.rs index 3b6197c675957..fdefec33eeb5d 100644 --- a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/canonical.rs +++ b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/canonical.rs @@ -444,7 +444,6 @@ where for &arg in &state.value.var_values.var_values.as_slice() [orig_values.len()..state.value.var_values.len()] { - // FIXME: This is so ugly. let unconstrained = delegate.fresh_var_for_kind_with_span(arg, span); orig_values.push(unconstrained); } diff --git a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs index 8391cdb2ca147..458edf920ab43 100644 --- a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs @@ -92,7 +92,6 @@ where #[derive_where(Clone, Debug, Default; I: Interner)] #[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)] #[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))] -// FIXME: This can be made crate-private once `EvalCtxt` also lives in this crate. struct NestedGoals { /// These normalizes-to goals are treated specially during the evaluation /// loop. In each iteration we take the RHS of the projection, replace it with @@ -421,6 +420,7 @@ where let (normalization_nested_goals, certainty) = self.instantiate_and_apply_query_response(goal.param_env, orig_values, response); self.inspect.goal_evaluation(goal_evaluation); + // FIXME: We previously had an assert here that checked that recomputing // a goal after applying its constraints did not change its response. // diff --git a/compiler/rustc_next_trait_solver/src/solve/mod.rs b/compiler/rustc_next_trait_solver/src/solve/mod.rs index 97f7c71f3fccc..8fe39bb4ee163 100644 --- a/compiler/rustc_next_trait_solver/src/solve/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/mod.rs @@ -10,9 +10,6 @@ //! //! For a high-level overview of how this solver works, check out the relevant //! section of the rustc-dev-guide. -//! -//! FIXME(@lcnr): Write that section. If you read this before then ask me -//! about it on zulip. mod alias_relate; mod assembly; diff --git a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs index fc9c634942b70..005b293621afc 100644 --- a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs @@ -899,7 +899,7 @@ where for ty in types.iter() { // We can't find the intersection if the types used are generic. // - // FIXME(effects) do we want to look at where clauses to get some + // FIXME(effects): do we want to look at where clauses to get some // clue for the case where generic types are being used? let Some(kind) = ty::EffectKind::try_from_ty(cx, ty) else { return Err(NoSolution); diff --git a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs index 2074bdec48531..5828b2ecf34d5 100644 --- a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs +++ b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs @@ -108,7 +108,6 @@ where ecx: &mut EvalCtxt<'_, D>, _guar: I::ErrorGuaranteed, ) -> Result, NoSolution> { - // FIXME: don't need to enter a probe here. ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc) .enter(|ecx| ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)) } @@ -463,7 +462,6 @@ where // Async coroutine unconditionally implement `Future` // Technically, we need to check that the future output type is Sized, // but that's already proven by the coroutine being WF. - // FIXME: use `consider_implied` ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc) .enter(|ecx| ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)) } @@ -489,7 +487,6 @@ where // Gen coroutines unconditionally implement `Iterator` // Technically, we need to check that the iterator output type is Sized, // but that's already proven by the coroutines being WF. - // FIXME: use `consider_implied` ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc) .enter(|ecx| ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)) } @@ -512,8 +509,7 @@ where return Err(NoSolution); } - // Gen coroutines unconditionally implement `FusedIterator` - // FIXME: use `consider_implied` + // Gen coroutines unconditionally implement `FusedIterator`. ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc) .enter(|ecx| ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)) } @@ -539,7 +535,6 @@ where // Gen coroutines unconditionally implement `Iterator` // Technically, we need to check that the iterator output type is Sized, // but that's already proven by the coroutines being WF. - // FIXME: use `consider_implied` ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc) .enter(|ecx| ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)) } @@ -610,7 +605,7 @@ where return Err(NoSolution); } - // FIXME(-Znext-solver): Implement this when we get const working in the new solver + // FIXME(effects): Implement this when we get const working in the new solver // `Destruct` is automatically implemented for every type in // non-const environments. @@ -631,8 +626,6 @@ where return Err(NoSolution); } - // FIXME: This actually should destructure the `Result` we get from transmutability and - // register candidates. We probably need to register >1 since we may have an OR of ANDs. ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| { let certainty = ecx.is_transmutable( goal.param_env, diff --git a/compiler/rustc_trait_selection/src/solve/delegate.rs b/compiler/rustc_trait_selection/src/solve/delegate.rs index 5c344930314a6..df9ac2b80fded 100644 --- a/compiler/rustc_trait_selection/src/solve/delegate.rs +++ b/compiler/rustc_trait_selection/src/solve/delegate.rs @@ -223,6 +223,8 @@ impl<'tcx> rustc_next_trait_solver::delegate::SolverDelegate for SolverDelegate< if eligible { Ok(Some(node_item.item.def_id)) } else { Ok(None) } } + // FIXME: This actually should destructure the `Result` we get from transmutability and + // register candidates. We probably need to register >1 since we may have an OR of ANDs. fn is_transmutable( &self, param_env: ty::ParamEnv<'tcx>, From 9357277de7d452fb542abd0264e9d71bb2403c20 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Fri, 11 Oct 2024 21:44:36 +1100 Subject: [PATCH 2116/2194] coverage: Remove code related to LLVM 17 --- .../src/coverageinfo/mapgen.rs | 21 ++++++------------- .../llvm-wrapper/CoverageMappingWrapper.cpp | 2 +- 2 files changed, 7 insertions(+), 16 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs index 267a22449167d..c2c261da79b68 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs @@ -14,29 +14,20 @@ use crate::coverageinfo::ffi::CounterMappingRegion; use crate::coverageinfo::map_data::{FunctionCoverage, FunctionCoverageCollector}; use crate::{coverageinfo, llvm}; -/// Generates and exports the Coverage Map. +/// Generates and exports the coverage map, which is embedded in special +/// linker sections in the final binary. /// -/// Rust Coverage Map generation supports LLVM Coverage Mapping Format versions -/// 6 and 7 (encoded as 5 and 6 respectively), as described at -/// [LLVM Code Coverage Mapping Format](https://github.com/rust-lang/llvm-project/blob/rustc/18.0-2024-02-13/llvm/docs/CoverageMappingFormat.rst). -/// These versions are supported by the LLVM coverage tools (`llvm-profdata` and `llvm-cov`) -/// distributed in the `llvm-tools-preview` rustup component. -/// -/// Consequently, Rust's bundled version of Clang also generates Coverage Maps compliant with -/// the same version. Clang's implementation of Coverage Map generation was referenced when -/// implementing this Rust version, and though the format documentation is very explicit and -/// detailed, some undocumented details in Clang's implementation (that may or may not be important) -/// were also replicated for Rust's Coverage Map. +/// Those sections are then read and understood by LLVM's `llvm-cov` tool, +/// which is distributed in the `llvm-tools` rustup component. pub(crate) fn finalize(cx: &CodegenCx<'_, '_>) { let tcx = cx.tcx; // Ensure that LLVM is using a version of the coverage mapping format that // agrees with our Rust-side code. Expected versions (encoded as n-1) are: - // - `CovMapVersion::Version6` (5) used by LLVM 13-17 - // - `CovMapVersion::Version7` (6) used by LLVM 18 + // - `CovMapVersion::Version7` (6) used by LLVM 18-19 let covmap_version = { let llvm_covmap_version = coverageinfo::mapping_version(); - let expected_versions = 5..=6; + let expected_versions = 6..=6; assert!( expected_versions.contains(&llvm_covmap_version), "Coverage mapping version exposed by `llvm-wrapper` is out of sync; \ diff --git a/compiler/rustc_llvm/llvm-wrapper/CoverageMappingWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/CoverageMappingWrapper.cpp index 8ee0597732083..cda81d4a9b5b2 100644 --- a/compiler/rustc_llvm/llvm-wrapper/CoverageMappingWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/CoverageMappingWrapper.cpp @@ -183,7 +183,7 @@ extern "C" void LLVMRustCoverageWriteMappingToBuffer( RustMappingRegions, NumMappingRegions)) { MappingRegions.emplace_back( fromRust(Region.Count), fromRust(Region.FalseCount), -#if LLVM_VERSION_GE(18, 0) && LLVM_VERSION_LT(19, 0) +#if LLVM_VERSION_LT(19, 0) coverage::CounterMappingRegion::MCDCParameters{}, #endif Region.FileID, Region.ExpandedFileID, // File IDs, then region info. From b72dbd56caa4b5919bb1fc92fd915c9e9b4e952c Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Fri, 11 Oct 2024 09:39:06 +0300 Subject: [PATCH 2117/2194] move dummy commit logic into x86_64-gnu-llvm-18 Signed-off-by: onur-ozkan --- src/ci/docker/host-x86_64/mingw-check/Dockerfile | 12 ------------ src/ci/docker/scripts/x86_64-gnu-llvm.sh | 16 ++++++++++++++++ src/ci/github-actions/jobs.yml | 8 +++----- 3 files changed, 19 insertions(+), 17 deletions(-) diff --git a/src/ci/docker/host-x86_64/mingw-check/Dockerfile b/src/ci/docker/host-x86_64/mingw-check/Dockerfile index 467ca1dac67a4..0f8ebb987c3aa 100644 --- a/src/ci/docker/host-x86_64/mingw-check/Dockerfile +++ b/src/ci/docker/host-x86_64/mingw-check/Dockerfile @@ -47,18 +47,6 @@ ENV RUN_CHECK_WITH_PARALLEL_QUERIES 1 # We disable optimized compiler built-ins because that requires a C toolchain for the target. # We also skip the x86_64-unknown-linux-gnu target as it is well-tested by other jobs. ENV SCRIPT \ - # `core::builder::tests::ci_rustc_if_unchanged_logic` bootstrap test covers the `rust.download-rustc=if-unchanged` logic. - # Here we are adding a dummy commit on compiler and running that test to ensure when there is a change on the compiler, - # we never download ci rustc with `rust.download-rustc=if-unchanged` option. - echo \"\" >> ../compiler/rustc/src/main.rs && \ - git config --global user.email \"dummy@dummy.com\" && \ - git config --global user.name \"dummy\" && \ - git add ../compiler/rustc/src/main.rs && \ - git commit -m \"test commit for rust.download-rustc=if-unchanged logic\" && \ - DISABLE_CI_RUSTC_IF_INCOMPATIBLE=0 python3 ../x.py test bootstrap -- core::builder::tests::ci_rustc_if_unchanged_logic && \ - # Revert the dummy commit - git reset --hard HEAD~1 && \ - python3 ../x.py check --stage 0 --set build.optimized-compiler-builtins=false core alloc std --target=aarch64-unknown-linux-gnu,i686-pc-windows-msvc,i686-unknown-linux-gnu,x86_64-apple-darwin,x86_64-pc-windows-gnu,x86_64-pc-windows-msvc && \ /scripts/check-default-config-profiles.sh && \ python3 ../x.py check --target=i686-pc-windows-gnu --host=i686-pc-windows-gnu && \ diff --git a/src/ci/docker/scripts/x86_64-gnu-llvm.sh b/src/ci/docker/scripts/x86_64-gnu-llvm.sh index 98290f5a72cd8..dea38b6fd2a4a 100755 --- a/src/ci/docker/scripts/x86_64-gnu-llvm.sh +++ b/src/ci/docker/scripts/x86_64-gnu-llvm.sh @@ -2,6 +2,22 @@ set -ex +if [ "$READ_ONLY_SRC" = "0" ]; then + # `core::builder::tests::ci_rustc_if_unchanged_logic` bootstrap test ensures that + # "download-rustc=if-unchanged" logic don't use CI rustc while there are changes on + # compiler and/or library. Here we are adding a dummy commit on compiler and running + # that test to make sure we never download CI rustc with a change on the compiler tree. + echo "" >> ../compiler/rustc/src/main.rs + git config --global user.email "dummy@dummy.com" + git config --global user.name "dummy" + git add ../compiler/rustc/src/main.rs + git commit -m "test commit for rust.download-rustc=if-unchanged logic" + DISABLE_CI_RUSTC_IF_INCOMPATIBLE=0 ../x.py test bootstrap \ + -- core::builder::tests::ci_rustc_if_unchanged_logic + # Revert the dummy commit + git reset --hard HEAD~1 +fi + # Only run the stage 1 tests on merges, not on PR CI jobs. if [[ -z "${PR_CI_JOB}" ]]; then ../x.py --stage 1 test --skip src/tools/tidy diff --git a/src/ci/github-actions/jobs.yml b/src/ci/github-actions/jobs.yml index 4bbebbc469799..8f49f623afaa4 100644 --- a/src/ci/github-actions/jobs.yml +++ b/src/ci/github-actions/jobs.yml @@ -85,9 +85,6 @@ envs: # it in each job definition. pr: - image: mingw-check - env: - # We are adding (temporarily) a dummy commit on the compiler - READ_ONLY_SRC: "0" <<: *job-linux-4c - image: mingw-check-tidy continue_on_error: true @@ -95,6 +92,8 @@ pr: - image: x86_64-gnu-llvm-18 env: ENABLE_GCC_CODEGEN: "1" + # We are adding (temporarily) a dummy commit on the compiler + READ_ONLY_SRC: "0" <<: *job-linux-16c - image: x86_64-gnu-tools <<: *job-linux-16c @@ -210,8 +209,6 @@ auto: <<: *job-linux-8c - image: mingw-check - env: - READ_ONLY_SRC: 0 <<: *job-linux-4c - image: test-various @@ -264,6 +261,7 @@ auto: - image: x86_64-gnu-llvm-18 env: RUST_BACKTRACE: 1 + READ_ONLY_SRC: "0" <<: *job-linux-8c - image: x86_64-gnu-nopt From 9a2772e1c2d6e770e13716d4691bc0a943cd7d61 Mon Sep 17 00:00:00 2001 From: VulnBandit <183613941+VulnBandit@users.noreply.github.com> Date: Fri, 4 Oct 2024 16:10:28 +0200 Subject: [PATCH 2118/2194] Don't assume traits used as type are trait objs --- .../src/hir_ty_lowering/lint.rs | 53 ++++--- .../src/hir_ty_lowering/mod.rs | 19 ++- tests/crashes/120241-2.rs | 10 -- tests/crashes/120241.rs | 13 -- tests/crashes/120482.rs | 13 -- tests/crashes/125512.rs | 10 -- .../suggest-assoc-ty-bound-on-eq-bound.rs | 20 +-- .../suggest-assoc-ty-bound-on-eq-bound.stderr | 58 ++----- ...to-be-a-closure-or-coroutine-ice-113776.rs | 4 +- ...e-a-closure-or-coroutine-ice-113776.stderr | 39 +---- .../const-generics/not_wf_param_in_rpitit.rs | 3 +- .../not_wf_param_in_rpitit.stderr | 55 +++---- .../avoid-ice-on-warning-2.new.stderr | 40 ++--- .../avoid-ice-on-warning-2.old.stderr | 2 +- .../avoid-ice-on-warning-2.rs | 7 +- .../avoid-ice-on-warning-3.new.stderr | 74 +++++---- .../avoid-ice-on-warning-3.old.stderr | 10 +- .../avoid-ice-on-warning-3.rs | 8 +- .../avoid-ice-on-warning.new.stderr | 16 +- .../dyn-compatibility/avoid-ice-on-warning.rs | 1 + .../bare-trait-dont-suggest-dyn.new.fixed | 3 +- .../bare-trait-dont-suggest-dyn.new.stderr | 15 +- .../bare-trait-dont-suggest-dyn.rs | 3 +- ...t-in-fn-inputs-and-outputs-issue-125139.rs | 57 ++++--- ...-fn-inputs-and-outputs-issue-125139.stderr | 141 +++++++----------- .../ui/dyn-keyword/dyn-2021-edition-error.rs | 6 +- .../dyn-keyword/dyn-2021-edition-error.stderr | 10 +- .../suggest-dyn-on-bare-trait-in-pat.rs | 3 +- .../suggest-dyn-on-bare-trait-in-pat.stderr | 4 +- tests/ui/editions/dyn-trait-sugg-2021.rs | 2 +- tests/ui/editions/dyn-trait-sugg-2021.stderr | 4 +- ...plicit-hrtb-without-dyn.edition2021.stderr | 15 +- .../generic-with-implicit-hrtb-without-dyn.rs | 3 +- tests/ui/resolve/issue-111312.rs | 3 +- tests/ui/resolve/issue-111312.stderr | 21 +-- tests/ui/resolve/issue-111727.rs | 3 +- tests/ui/resolve/issue-111727.stderr | 15 +- .../ice-return-unsized-can-impl-2.rs | 15 ++ .../ice-return-unsized-can-impl-2.stderr | 57 +++++++ .../rust-2021/ice-return-unsized-can-impl.rs | 16 ++ .../ice-return-unsized-can-impl.stderr | 30 ++++ tests/ui/rust-2021/ice-unsized-fn-params-2.rs | 12 ++ .../rust-2021/ice-unsized-fn-params-2.stderr | 19 +++ tests/ui/rust-2021/ice-unsized-fn-params.rs | 18 +++ .../ui/rust-2021/ice-unsized-fn-params.stderr | 57 +++++++ ...-trait-should-use-self-2021-without-dyn.rs | 15 +- ...it-should-use-self-2021-without-dyn.stderr | 81 ++-------- tests/ui/suggestions/issue-116434-2021.rs | 6 +- tests/ui/suggestions/issue-116434-2021.stderr | 27 ++-- .../suggest-blanket-impl-local-trait.rs | 28 ++-- .../suggest-blanket-impl-local-trait.stderr | 28 ++-- ...swapping-self-ty-and-trait-edition-2021.rs | 6 +- ...ping-self-ty-and-trait-edition-2021.stderr | 12 +- .../ui/traits/bound/not-on-bare-trait-2021.rs | 8 +- .../bound/not-on-bare-trait-2021.stderr | 49 +----- tests/ui/traits/issue-106072.rs | 4 +- tests/ui/traits/issue-106072.stderr | 29 +--- .../missing-for-type-in-impl.e2021.stderr | 4 +- tests/ui/traits/missing-for-type-in-impl.rs | 2 +- 59 files changed, 607 insertions(+), 679 deletions(-) delete mode 100644 tests/crashes/120241-2.rs delete mode 100644 tests/crashes/120241.rs delete mode 100644 tests/crashes/120482.rs delete mode 100644 tests/crashes/125512.rs create mode 100644 tests/ui/rust-2021/ice-return-unsized-can-impl-2.rs create mode 100644 tests/ui/rust-2021/ice-return-unsized-can-impl-2.stderr create mode 100644 tests/ui/rust-2021/ice-return-unsized-can-impl.rs create mode 100644 tests/ui/rust-2021/ice-return-unsized-can-impl.stderr create mode 100644 tests/ui/rust-2021/ice-unsized-fn-params-2.rs create mode 100644 tests/ui/rust-2021/ice-unsized-fn-params-2.stderr create mode 100644 tests/ui/rust-2021/ice-unsized-fn-params.rs create mode 100644 tests/ui/rust-2021/ice-unsized-fn-params.stderr diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs index 5607fe873f652..11c0450bfe211 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs @@ -1,6 +1,6 @@ use rustc_ast::TraitObjectSyntax; use rustc_errors::codes::*; -use rustc_errors::{Diag, EmissionGuarantee, StashKey}; +use rustc_errors::{Diag, EmissionGuarantee, ErrorGuaranteed, StashKey, Suggestions}; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; use rustc_lint_defs::Applicability; @@ -15,13 +15,16 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { /// /// *Bare* trait object types are ones that aren't preceded by the keyword `dyn`. /// In edition 2021 and onward we emit a hard error for them. - pub(super) fn prohibit_or_lint_bare_trait_object_ty(&self, self_ty: &hir::Ty<'_>) { + pub(super) fn prohibit_or_lint_bare_trait_object_ty( + &self, + self_ty: &hir::Ty<'_>, + ) -> Option { let tcx = self.tcx(); let hir::TyKind::TraitObject([poly_trait_ref, ..], _, TraitObjectSyntax::None) = self_ty.kind else { - return; + return None; }; let in_path = match tcx.parent_hir_node(self_ty.hir_id) { @@ -70,8 +73,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { } if self_ty.span.edition().at_least_rust_2021() { - let msg = "trait objects must include the `dyn` keyword"; - let label = "add `dyn` keyword before this trait"; + let msg = "expected a type, found a trait"; + let label = "you can add the `dyn` keyword if you want a trait object"; let mut diag = rustc_errors::struct_span_code_err!(self.dcx(), self_ty.span, E0782, "{}", msg); if self_ty.span.can_be_used_for_suggestions() @@ -83,7 +86,17 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { // Check if the impl trait that we are considering is an impl of a local trait. self.maybe_suggest_blanket_trait_impl(self_ty, &mut diag); self.maybe_suggest_assoc_ty_bound(self_ty, &mut diag); - diag.stash(self_ty.span, StashKey::TraitMissingMethod); + // In case there is an associate type with the same name + // Add the suggestion to this error + if let Some(mut sugg) = + tcx.dcx().steal_non_err(self_ty.span, StashKey::AssociatedTypeSuggestion) + && let Suggestions::Enabled(ref mut s1) = diag.suggestions + && let Suggestions::Enabled(ref mut s2) = sugg.suggestions + { + s1.append(s2); + sugg.cancel(); + } + diag.stash(self_ty.span, StashKey::TraitMissingMethod) } else { tcx.node_span_lint(BARE_TRAIT_OBJECTS, self_ty.hir_id, self_ty.span, |lint| { lint.primary_message("trait objects without an explicit `dyn` are deprecated"); @@ -96,6 +109,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { } self.maybe_suggest_blanket_trait_impl(self_ty, lint); }); + None } } @@ -174,41 +188,31 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { // 1. Independent functions // 2. Functions inside trait blocks // 3. Functions inside impl blocks - let (sig, generics, owner) = match tcx.hir_node_by_def_id(parent_id) { + let (sig, generics) = match tcx.hir_node_by_def_id(parent_id) { hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(sig, generics, _), .. }) => { - (sig, generics, None) + (sig, generics) } hir::Node::TraitItem(hir::TraitItem { kind: hir::TraitItemKind::Fn(sig, _), generics, - owner_id, .. - }) => (sig, generics, Some(tcx.parent(owner_id.to_def_id()))), + }) => (sig, generics), hir::Node::ImplItem(hir::ImplItem { kind: hir::ImplItemKind::Fn(sig, _), generics, - owner_id, .. - }) => (sig, generics, Some(tcx.parent(owner_id.to_def_id()))), + }) => (sig, generics), _ => return false, }; let Ok(trait_name) = tcx.sess.source_map().span_to_snippet(self_ty.span) else { return false; }; let impl_sugg = vec![(self_ty.span.shrink_to_lo(), "impl ".to_string())]; - let mut is_downgradable = true; - // Check if trait object is safe for suggesting dynamic dispatch. let is_dyn_compatible = match self_ty.kind { hir::TyKind::TraitObject(objects, ..) => { objects.iter().all(|(o, _)| match o.trait_ref.path.res { - Res::Def(DefKind::Trait, id) => { - if Some(id) == owner { - // For recursive traits, don't downgrade the error. (#119652) - is_downgradable = false; - } - tcx.is_dyn_compatible(id) - } + Res::Def(DefKind::Trait, id) => tcx.is_dyn_compatible(id), _ => false, }) } @@ -255,9 +259,6 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { suggestion, Applicability::MachineApplicable, ); - } else if is_downgradable { - // We'll emit the dyn-compatibility error already, with a structured suggestion. - diag.downgrade_to_delayed_bug(); } return true; } @@ -281,10 +282,6 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { ); if !is_dyn_compatible { diag.note(format!("`{trait_name}` it is dyn-incompatible, so it can't be `dyn`")); - if is_downgradable { - // We'll emit the dyn-compatibility error already, with a structured suggestion. - diag.downgrade_to_delayed_bug(); - } } else { // No ampersand in suggestion if it's borrowed already let (dyn_str, paren_dyn_str) = diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs index 28a1fc887412f..682d29e6e82b8 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -2063,13 +2063,18 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { ) } hir::TyKind::TraitObject(bounds, lifetime, repr) => { - self.prohibit_or_lint_bare_trait_object_ty(hir_ty); - - let repr = match repr { - TraitObjectSyntax::Dyn | TraitObjectSyntax::None => ty::Dyn, - TraitObjectSyntax::DynStar => ty::DynStar, - }; - self.lower_trait_object_ty(hir_ty.span, hir_ty.hir_id, bounds, lifetime, repr) + if let Some(guar) = self.prohibit_or_lint_bare_trait_object_ty(hir_ty) { + // Don't continue with type analysis if the `dyn` keyword is missing + // It generates confusing errors, especially if the user meant to use another + // keyword like `impl` + Ty::new_error(tcx, guar) + } else { + let repr = match repr { + TraitObjectSyntax::Dyn | TraitObjectSyntax::None => ty::Dyn, + TraitObjectSyntax::DynStar => ty::DynStar, + }; + self.lower_trait_object_ty(hir_ty.span, hir_ty.hir_id, bounds, lifetime, repr) + } } // If we encounter a fully qualified path with RTN generics, then it must have // *not* gone through `lower_ty_maybe_return_type_notation`, and therefore diff --git a/tests/crashes/120241-2.rs b/tests/crashes/120241-2.rs deleted file mode 100644 index 91ec33620908e..0000000000000 --- a/tests/crashes/120241-2.rs +++ /dev/null @@ -1,10 +0,0 @@ -//@ known-bug: #120241 -//@ edition:2021 -#![feature(dyn_compatible_for_dispatch)] -#![feature(unsized_fn_params)] - -fn guard(_s: Copy) -> bool { - panic!() -} - -fn main() {} diff --git a/tests/crashes/120241.rs b/tests/crashes/120241.rs deleted file mode 100644 index b4fcb903714db..0000000000000 --- a/tests/crashes/120241.rs +++ /dev/null @@ -1,13 +0,0 @@ -//@ known-bug: #120241 -//@ edition:2021 -#![feature(dyn_compatible_for_dispatch)] - -trait B { - fn f(a: A) -> A; -} - -trait A { - fn g(b: B) -> B; -} - -fn main() {} diff --git a/tests/crashes/120482.rs b/tests/crashes/120482.rs deleted file mode 100644 index a395855d796f1..0000000000000 --- a/tests/crashes/120482.rs +++ /dev/null @@ -1,13 +0,0 @@ -//@ known-bug: #120482 -//@ edition:2021 -#![feature(dyn_compatible_for_dispatch)] - -trait B { - fn bar(&self, x: &Self); -} - -trait A { - fn g(new: B) -> B; -} - -fn main() {} diff --git a/tests/crashes/125512.rs b/tests/crashes/125512.rs deleted file mode 100644 index 37dbdf2f32f85..0000000000000 --- a/tests/crashes/125512.rs +++ /dev/null @@ -1,10 +0,0 @@ -//@ known-bug: rust-lang/rust#125512 -//@ edition:2021 -#![feature(dyn_compatible_for_dispatch)] -trait B { - fn f(a: A) -> A; -} -trait A { - fn concrete(b: B) -> B; -} -fn main() {} diff --git a/tests/ui/associated-type-bounds/suggest-assoc-ty-bound-on-eq-bound.rs b/tests/ui/associated-type-bounds/suggest-assoc-ty-bound-on-eq-bound.rs index 7df042d5f88e6..c8bb0ebd5744b 100644 --- a/tests/ui/associated-type-bounds/suggest-assoc-ty-bound-on-eq-bound.rs +++ b/tests/ui/associated-type-bounds/suggest-assoc-ty-bound-on-eq-bound.rs @@ -2,28 +2,24 @@ //@ edition: 2021 fn f(_: impl Trait) {} -//~^ ERROR trait objects must include the `dyn` keyword -//~| HELP add `dyn` keyword before this trait +//~^ ERROR expected a type, found a trait +//~| HELP you can add the `dyn` keyword if you want a trait object //~| HELP you might have meant to write a bound here -//~| ERROR the trait `Copy` cannot be made into an object fn g(_: impl Trait) {} -//~^ ERROR trait objects must include the `dyn` keyword -//~| HELP add `dyn` keyword before this trait +//~^ ERROR expected a type, found a trait +//~| HELP you can add the `dyn` keyword if you want a trait object //~| HELP you might have meant to write a bound here -//~| ERROR only auto traits can be used as additional traits in a trait object -//~| HELP consider creating a new trait -//~| ERROR the trait `Eq` cannot be made into an object fn h(_: impl Trait = 'static + for<'a> Fn(&'a ())>) {} -//~^ ERROR trait objects must include the `dyn` keyword -//~| HELP add `dyn` keyword before this trait +//~^ ERROR expected a type, found a trait +//~| HELP you can add the `dyn` keyword if you want a trait object //~| HELP you might have meant to write a bound here // Don't suggest assoc ty bound in trait object types, that's not valid: type Obj = dyn Trait; -//~^ ERROR trait objects must include the `dyn` keyword -//~| HELP add `dyn` keyword before this trait +//~^ ERROR expected a type, found a trait +//~| HELP you can add the `dyn` keyword if you want a trait object trait Trait { type T; } diff --git a/tests/ui/associated-type-bounds/suggest-assoc-ty-bound-on-eq-bound.stderr b/tests/ui/associated-type-bounds/suggest-assoc-ty-bound-on-eq-bound.stderr index bec60187e4253..dbe285c531078 100644 --- a/tests/ui/associated-type-bounds/suggest-assoc-ty-bound-on-eq-bound.stderr +++ b/tests/ui/associated-type-bounds/suggest-assoc-ty-bound-on-eq-bound.stderr @@ -1,41 +1,10 @@ -error[E0038]: the trait `Copy` cannot be made into an object - --> $DIR/suggest-assoc-ty-bound-on-eq-bound.rs:4:20 - | -LL | fn f(_: impl Trait) {} - | ^^^^^^^^ `Copy` cannot be made into an object - | - = note: the trait cannot be made into an object because it requires `Self: Sized` - = note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - -error[E0225]: only auto traits can be used as additional traits in a trait object - --> $DIR/suggest-assoc-ty-bound-on-eq-bound.rs:10:42 - | -LL | fn g(_: impl Trait) {} - | --------------- ^^ additional non-auto trait - | | - | first non-auto trait - | - = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Debug + Eq {}` - = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit - -error[E0038]: the trait `Eq` cannot be made into an object - --> $DIR/suggest-assoc-ty-bound-on-eq-bound.rs:10:24 - | -LL | fn g(_: impl Trait) {} - | ^^^^^^^^^^^^^^^^^^^^ `Eq` cannot be made into an object - | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $SRC_DIR/core/src/cmp.rs:LL:COL - | - = note: the trait cannot be made into an object because it uses `Self` as a type parameter - -error[E0782]: trait objects must include the `dyn` keyword +error[E0782]: expected a type, found a trait --> $DIR/suggest-assoc-ty-bound-on-eq-bound.rs:4:24 | LL | fn f(_: impl Trait) {} | ^^^^ | -help: add `dyn` keyword before this trait +help: you can add the `dyn` keyword if you want a trait object | LL | fn f(_: impl Trait) {} | +++ @@ -44,13 +13,13 @@ help: you might have meant to write a bound here LL | fn f(_: impl Trait) {} | ~ -error[E0782]: trait objects must include the `dyn` keyword - --> $DIR/suggest-assoc-ty-bound-on-eq-bound.rs:10:24 +error[E0782]: expected a type, found a trait + --> $DIR/suggest-assoc-ty-bound-on-eq-bound.rs:9:24 | LL | fn g(_: impl Trait) {} | ^^^^^^^^^^^^^^^^^^^^ | -help: add `dyn` keyword before this trait +help: you can add the `dyn` keyword if you want a trait object | LL | fn g(_: impl Trait) {} | +++ @@ -59,13 +28,13 @@ help: you might have meant to write a bound here LL | fn g(_: impl Trait) {} | ~ -error[E0782]: trait objects must include the `dyn` keyword - --> $DIR/suggest-assoc-ty-bound-on-eq-bound.rs:18:26 +error[E0782]: expected a type, found a trait + --> $DIR/suggest-assoc-ty-bound-on-eq-bound.rs:14:26 | LL | fn h(_: impl Trait = 'static + for<'a> Fn(&'a ())>) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -help: add `dyn` keyword before this trait +help: you can add the `dyn` keyword if you want a trait object | LL | fn h(_: impl Trait = dyn 'static + for<'a> Fn(&'a ())>) {} | +++ @@ -74,18 +43,17 @@ help: you might have meant to write a bound here LL | fn h(_: impl Trait: 'static + for<'a> Fn(&'a ())>) {} | ~ -error[E0782]: trait objects must include the `dyn` keyword - --> $DIR/suggest-assoc-ty-bound-on-eq-bound.rs:24:26 +error[E0782]: expected a type, found a trait + --> $DIR/suggest-assoc-ty-bound-on-eq-bound.rs:20:26 | LL | type Obj = dyn Trait; | ^^^^^ | -help: add `dyn` keyword before this trait +help: you can add the `dyn` keyword if you want a trait object | LL | type Obj = dyn Trait; | +++ -error: aborting due to 7 previous errors +error: aborting due to 4 previous errors -Some errors have detailed explanations: E0038, E0225, E0782. -For more information about an error, try `rustc --explain E0038`. +For more information about this error, try `rustc --explain E0782`. diff --git a/tests/ui/const-generics/generic_const_exprs/expected-type-of-closure-body-to-be-a-closure-or-coroutine-ice-113776.rs b/tests/ui/const-generics/generic_const_exprs/expected-type-of-closure-body-to-be-a-closure-or-coroutine-ice-113776.rs index 4bea3ad87f5ed..c1d3321f84077 100644 --- a/tests/ui/const-generics/generic_const_exprs/expected-type-of-closure-body-to-be-a-closure-or-coroutine-ice-113776.rs +++ b/tests/ui/const-generics/generic_const_exprs/expected-type-of-closure-body-to-be-a-closure-or-coroutine-ice-113776.rs @@ -14,10 +14,8 @@ fn f( 1 }], ) -> impl Iterator { -//~^ ERROR the type parameter `Rhs` must be explicitly specified +//~^ ERROR expected a type, found a trait //~| ERROR `()` is not an iterator -//~| ERROR trait objects must include the `dyn` keyword -//~| ERROR the type parameter `Rhs` must be explicitly specified [E0393] } pub fn main() {} diff --git a/tests/ui/const-generics/generic_const_exprs/expected-type-of-closure-body-to-be-a-closure-or-coroutine-ice-113776.stderr b/tests/ui/const-generics/generic_const_exprs/expected-type-of-closure-body-to-be-a-closure-or-coroutine-ice-113776.stderr index 416a938112424..5c4d643a28e97 100644 --- a/tests/ui/const-generics/generic_const_exprs/expected-type-of-closure-body-to-be-a-closure-or-coroutine-ice-113776.stderr +++ b/tests/ui/const-generics/generic_const_exprs/expected-type-of-closure-body-to-be-a-closure-or-coroutine-ice-113776.stderr @@ -16,37 +16,6 @@ help: you might be missing a type parameter LL | fn f( | +++ -error[E0393]: the type parameter `Rhs` must be explicitly specified - --> $DIR/expected-type-of-closure-body-to-be-a-closure-or-coroutine-ice-113776.rs:16:27 - | -LL | ) -> impl Iterator { - | ^^^^^^^^^ - --> $SRC_DIR/core/src/ops/arith.rs:LL:COL - | - = note: type parameter `Rhs` must be specified for this - | - = note: because of the default `Self` reference, type parameters must be specified on object types -help: set the type parameter to the desired type - | -LL | ) -> impl Iterator> { - | +++++ - -error[E0393]: the type parameter `Rhs` must be explicitly specified - --> $DIR/expected-type-of-closure-body-to-be-a-closure-or-coroutine-ice-113776.rs:16:27 - | -LL | ) -> impl Iterator { - | ^^^^^^^^^ - --> $SRC_DIR/core/src/ops/arith.rs:LL:COL - | - = note: type parameter `Rhs` must be specified for this - | - = note: because of the default `Self` reference, type parameters must be specified on object types - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -help: set the type parameter to the desired type - | -LL | ) -> impl Iterator> { - | +++++ - error[E0277]: `()` is not an iterator --> $DIR/expected-type-of-closure-body-to-be-a-closure-or-coroutine-ice-113776.rs:16:6 | @@ -55,13 +24,13 @@ LL | ) -> impl Iterator { | = help: the trait `Iterator` is not implemented for `()` -error[E0782]: trait objects must include the `dyn` keyword +error[E0782]: expected a type, found a trait --> $DIR/expected-type-of-closure-body-to-be-a-closure-or-coroutine-ice-113776.rs:16:27 | LL | ) -> impl Iterator { | ^^^^^^^^^ | -help: add `dyn` keyword before this trait +help: you can add the `dyn` keyword if you want a trait object | LL | ) -> impl Iterator { | +++ @@ -70,7 +39,7 @@ help: you might have meant to write a bound here LL | ) -> impl Iterator { | ~ -error: aborting due to 5 previous errors +error: aborting due to 3 previous errors -Some errors have detailed explanations: E0277, E0393, E0412, E0782. +Some errors have detailed explanations: E0277, E0412, E0782. For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/const-generics/not_wf_param_in_rpitit.rs b/tests/ui/const-generics/not_wf_param_in_rpitit.rs index eb672194340e8..b454562ad497a 100644 --- a/tests/ui/const-generics/not_wf_param_in_rpitit.rs +++ b/tests/ui/const-generics/not_wf_param_in_rpitit.rs @@ -1,12 +1,11 @@ //@ edition:2021 -trait Trait { +trait Trait { //~^ ERROR: cannot find value `bar` in this scope //~| ERROR: cycle detected when computing type of `Trait::N` //~| ERROR: the trait `Trait` cannot be made into an object //~| ERROR: the trait `Trait` cannot be made into an object //~| ERROR: the trait `Trait` cannot be made into an object - //~| ERROR: trait objects must include the `dyn` keyword async fn a() {} } diff --git a/tests/ui/const-generics/not_wf_param_in_rpitit.stderr b/tests/ui/const-generics/not_wf_param_in_rpitit.stderr index ade40550c7389..2500409e82858 100644 --- a/tests/ui/const-generics/not_wf_param_in_rpitit.stderr +++ b/tests/ui/const-generics/not_wf_param_in_rpitit.stderr @@ -1,33 +1,33 @@ error[E0425]: cannot find value `bar` in this scope - --> $DIR/not_wf_param_in_rpitit.rs:3:30 + --> $DIR/not_wf_param_in_rpitit.rs:3:34 | -LL | trait Trait { - | ^^^ not found in this scope +LL | trait Trait { + | ^^^ not found in this scope error[E0391]: cycle detected when computing type of `Trait::N` - --> $DIR/not_wf_param_in_rpitit.rs:3:22 + --> $DIR/not_wf_param_in_rpitit.rs:3:26 | -LL | trait Trait { - | ^^^^^ +LL | trait Trait { + | ^^^^^ | = note: ...which immediately requires computing type of `Trait::N` again note: cycle used when computing explicit predicates of trait `Trait` --> $DIR/not_wf_param_in_rpitit.rs:3:1 | -LL | trait Trait { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | trait Trait { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information error[E0038]: the trait `Trait` cannot be made into an object --> $DIR/not_wf_param_in_rpitit.rs:3:22 | -LL | trait Trait { - | ^^^^^ `Trait` cannot be made into an object +LL | trait Trait { + | ^^^^^^^^^ `Trait` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/not_wf_param_in_rpitit.rs:10:14 + --> $DIR/not_wf_param_in_rpitit.rs:9:14 | -LL | trait Trait { +LL | trait Trait { | ----- this trait cannot be made into an object... ... LL | async fn a() {} @@ -44,13 +44,13 @@ LL | async fn a() where Self: Sized {} error[E0038]: the trait `Trait` cannot be made into an object --> $DIR/not_wf_param_in_rpitit.rs:3:13 | -LL | trait Trait { - | ^^^^^^^^^^^^^^^^^^^^ `Trait` cannot be made into an object +LL | trait Trait { + | ^^^^^^^^^^^^^^^^^^^^^^^^ `Trait` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/not_wf_param_in_rpitit.rs:10:14 + --> $DIR/not_wf_param_in_rpitit.rs:9:14 | -LL | trait Trait { +LL | trait Trait { | ----- this trait cannot be made into an object... ... LL | async fn a() {} @@ -67,13 +67,13 @@ LL | async fn a() where Self: Sized {} error[E0038]: the trait `Trait` cannot be made into an object --> $DIR/not_wf_param_in_rpitit.rs:3:13 | -LL | trait Trait { - | ^^^^^^^^^^^^^^^^^^^^ `Trait` cannot be made into an object +LL | trait Trait { + | ^^^^^^^^^^^^^^^^^^^^^^^^ `Trait` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/not_wf_param_in_rpitit.rs:10:14 + --> $DIR/not_wf_param_in_rpitit.rs:9:14 | -LL | trait Trait { +LL | trait Trait { | ----- this trait cannot be made into an object... ... LL | async fn a() {} @@ -88,18 +88,7 @@ help: alternatively, consider constraining `a` so it does not apply to trait obj LL | async fn a() where Self: Sized {} | +++++++++++++++++ -error[E0782]: trait objects must include the `dyn` keyword - --> $DIR/not_wf_param_in_rpitit.rs:3:22 - | -LL | trait Trait { - | ^^^^^ - | -help: add `dyn` keyword before this trait - | -LL | trait Trait { - | +++ - -error: aborting due to 6 previous errors +error: aborting due to 5 previous errors -Some errors have detailed explanations: E0038, E0391, E0425, E0782. +Some errors have detailed explanations: E0038, E0391, E0425. For more information about an error, try `rustc --explain E0038`. diff --git a/tests/ui/dyn-compatibility/avoid-ice-on-warning-2.new.stderr b/tests/ui/dyn-compatibility/avoid-ice-on-warning-2.new.stderr index 4e3d2ebebade0..83795f3128ec7 100644 --- a/tests/ui/dyn-compatibility/avoid-ice-on-warning-2.new.stderr +++ b/tests/ui/dyn-compatibility/avoid-ice-on-warning-2.new.stderr @@ -1,41 +1,19 @@ -error[E0038]: the trait `Copy` cannot be made into an object +error[E0782]: expected a type, found a trait --> $DIR/avoid-ice-on-warning-2.rs:4:13 | LL | fn id(f: Copy) -> usize { - | ^^^^ `Copy` cannot be made into an object + | ^^^^ | - = note: the trait cannot be made into an object because it requires `Self: Sized` - = note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - -error[E0618]: expected function, found `(dyn Copy + 'static)` - --> $DIR/avoid-ice-on-warning-2.rs:11:5 + = note: `Copy` it is dyn-incompatible, so it can't be `dyn` +help: use a new generic type parameter, constrained by `Copy` | -LL | fn id(f: Copy) -> usize { - | - `f` has type `(dyn Copy + 'static)` -... -LL | f() - | ^-- - | | - | call expression requires function - -error[E0277]: the size for values of type `(dyn Copy + 'static)` cannot be known at compilation time - --> $DIR/avoid-ice-on-warning-2.rs:4:13 - | -LL | fn id(f: Copy) -> usize { - | ^^^^ doesn't have a size known at compile-time - | - = help: the trait `Sized` is not implemented for `(dyn Copy + 'static)` - = help: unsized fn params are gated as an unstable feature -help: you can use `impl Trait` as the argument type +LL | fn id(f: T) -> usize { + | +++++++++ ~ +help: you can also use an opaque type, but users won't be able to specify the type parameter when calling the `fn`, having to rely exclusively on type inference | LL | fn id(f: impl Copy) -> usize { | ++++ -help: function arguments must have a statically known size, borrowed types always have a known size - | -LL | fn id(f: &dyn Copy) -> usize { - | ++++ -error: aborting due to 3 previous errors +error: aborting due to 1 previous error -Some errors have detailed explanations: E0038, E0277, E0618. -For more information about an error, try `rustc --explain E0038`. +For more information about this error, try `rustc --explain E0782`. diff --git a/tests/ui/dyn-compatibility/avoid-ice-on-warning-2.old.stderr b/tests/ui/dyn-compatibility/avoid-ice-on-warning-2.old.stderr index 180cd679dea11..54daefea31c10 100644 --- a/tests/ui/dyn-compatibility/avoid-ice-on-warning-2.old.stderr +++ b/tests/ui/dyn-compatibility/avoid-ice-on-warning-2.old.stderr @@ -36,7 +36,7 @@ LL | fn id(f: Copy) -> usize { = note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit error[E0618]: expected function, found `(dyn Copy + 'static)` - --> $DIR/avoid-ice-on-warning-2.rs:11:5 + --> $DIR/avoid-ice-on-warning-2.rs:12:5 | LL | fn id(f: Copy) -> usize { | - `f` has type `(dyn Copy + 'static)` diff --git a/tests/ui/dyn-compatibility/avoid-ice-on-warning-2.rs b/tests/ui/dyn-compatibility/avoid-ice-on-warning-2.rs index db2f4aea05b58..3c2da667b3924 100644 --- a/tests/ui/dyn-compatibility/avoid-ice-on-warning-2.rs +++ b/tests/ui/dyn-compatibility/avoid-ice-on-warning-2.rs @@ -2,13 +2,14 @@ //@[old] edition:2015 //@[new] edition:2021 fn id(f: Copy) -> usize { -//~^ ERROR the trait `Copy` cannot be made into an object -//~| ERROR: the size for values of type `(dyn Copy + 'static)` +//[new]~^ ERROR expected a type, found a trait +//[old]~^^ ERROR the trait `Copy` cannot be made into an object +//[old]~| ERROR the size for values of type `(dyn Copy + 'static)` //[old]~| WARN trait objects without an explicit `dyn` are deprecated //[old]~| WARN this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! //[old]~| WARN trait objects without an explicit `dyn` are deprecated //[old]~| WARN this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! f() - //~^ ERROR: expected function, found `(dyn Copy + 'static)` + //[old]~^ ERROR: expected function, found `(dyn Copy + 'static)` } fn main() {} diff --git a/tests/ui/dyn-compatibility/avoid-ice-on-warning-3.new.stderr b/tests/ui/dyn-compatibility/avoid-ice-on-warning-3.new.stderr index fdd3e8ab5072a..813b5863738f8 100644 --- a/tests/ui/dyn-compatibility/avoid-ice-on-warning-3.new.stderr +++ b/tests/ui/dyn-compatibility/avoid-ice-on-warning-3.new.stderr @@ -1,47 +1,57 @@ -error[E0038]: the trait `A` cannot be made into an object - --> $DIR/avoid-ice-on-warning-3.rs:4:19 +error[E0782]: expected a type, found a trait + --> $DIR/avoid-ice-on-warning-3.rs:14:19 | -LL | trait B { fn f(a: A) -> A; } - | ^ `A` cannot be made into an object +LL | trait A { fn g(b: B) -> B; } + | ^ | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/avoid-ice-on-warning-3.rs:12:14 + = note: `B` it is dyn-incompatible, so it can't be `dyn` +help: use a new generic type parameter, constrained by `B` + | +LL | trait A { fn g(b: T) -> B; } + | ++++++ ~ +help: you can also use an opaque type, but users won't be able to specify the type parameter when calling the `fn`, having to rely exclusively on type inference + | +LL | trait A { fn g(b: impl B) -> B; } + | ++++ + +error[E0782]: expected a type, found a trait + --> $DIR/avoid-ice-on-warning-3.rs:14:25 | LL | trait A { fn g(b: B) -> B; } - | - ^ ...because associated function `g` has no `self` parameter - | | - | this trait cannot be made into an object... -help: consider turning `g` into a method by giving it a `&self` argument + | ^ | -LL | trait A { fn g(&self, b: B) -> B; } - | ++++++ -help: alternatively, consider constraining `g` so it does not apply to trait objects +help: `B` is dyn-incompatible, use `impl B` to return an opaque type, as long as you return a single underlying type | -LL | trait A { fn g(b: B) -> B where Self: Sized; } - | +++++++++++++++++ +LL | trait A { fn g(b: B) -> impl B; } + | ++++ -error[E0038]: the trait `B` cannot be made into an object - --> $DIR/avoid-ice-on-warning-3.rs:12:19 +error[E0782]: expected a type, found a trait + --> $DIR/avoid-ice-on-warning-3.rs:4:19 | -LL | trait A { fn g(b: B) -> B; } - | ^ `B` cannot be made into an object +LL | trait B { fn f(a: A) -> A; } + | ^ | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/avoid-ice-on-warning-3.rs:4:14 + = note: `A` it is dyn-incompatible, so it can't be `dyn` +help: use a new generic type parameter, constrained by `A` + | +LL | trait B { fn f(a: T) -> A; } + | ++++++ ~ +help: you can also use an opaque type, but users won't be able to specify the type parameter when calling the `fn`, having to rely exclusively on type inference + | +LL | trait B { fn f(a: impl A) -> A; } + | ++++ + +error[E0782]: expected a type, found a trait + --> $DIR/avoid-ice-on-warning-3.rs:4:25 | LL | trait B { fn f(a: A) -> A; } - | - ^ ...because associated function `f` has no `self` parameter - | | - | this trait cannot be made into an object... -help: consider turning `f` into a method by giving it a `&self` argument + | ^ | -LL | trait B { fn f(&self, a: A) -> A; } - | ++++++ -help: alternatively, consider constraining `f` so it does not apply to trait objects +help: `A` is dyn-incompatible, use `impl A` to return an opaque type, as long as you return a single underlying type | -LL | trait B { fn f(a: A) -> A where Self: Sized; } - | +++++++++++++++++ +LL | trait B { fn f(a: A) -> impl A; } + | ++++ -error: aborting due to 2 previous errors +error: aborting due to 4 previous errors -For more information about this error, try `rustc --explain E0038`. +For more information about this error, try `rustc --explain E0782`. diff --git a/tests/ui/dyn-compatibility/avoid-ice-on-warning-3.old.stderr b/tests/ui/dyn-compatibility/avoid-ice-on-warning-3.old.stderr index bd362abb35501..6bc2d73a0d0e4 100644 --- a/tests/ui/dyn-compatibility/avoid-ice-on-warning-3.old.stderr +++ b/tests/ui/dyn-compatibility/avoid-ice-on-warning-3.old.stderr @@ -26,7 +26,7 @@ LL | trait B { fn f(a: A) -> dyn A; } | +++ warning: trait objects without an explicit `dyn` are deprecated - --> $DIR/avoid-ice-on-warning-3.rs:12:19 + --> $DIR/avoid-ice-on-warning-3.rs:14:19 | LL | trait A { fn g(b: B) -> B; } | ^ @@ -39,7 +39,7 @@ LL | trait A { fn g(b: dyn B) -> B; } | +++ warning: trait objects without an explicit `dyn` are deprecated - --> $DIR/avoid-ice-on-warning-3.rs:12:25 + --> $DIR/avoid-ice-on-warning-3.rs:14:25 | LL | trait A { fn g(b: B) -> B; } | ^ @@ -72,7 +72,7 @@ LL | trait B { fn f(a: A) -> A; } | ^ `A` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/avoid-ice-on-warning-3.rs:12:14 + --> $DIR/avoid-ice-on-warning-3.rs:14:14 | LL | trait A { fn g(b: B) -> B; } | - ^ ...because associated function `g` has no `self` parameter @@ -88,7 +88,7 @@ LL | trait A { fn g(b: B) -> B where Self: Sized; } | +++++++++++++++++ warning: trait objects without an explicit `dyn` are deprecated - --> $DIR/avoid-ice-on-warning-3.rs:12:19 + --> $DIR/avoid-ice-on-warning-3.rs:14:19 | LL | trait A { fn g(b: B) -> B; } | ^ @@ -102,7 +102,7 @@ LL | trait A { fn g(b: dyn B) -> B; } | +++ error[E0038]: the trait `B` cannot be made into an object - --> $DIR/avoid-ice-on-warning-3.rs:12:19 + --> $DIR/avoid-ice-on-warning-3.rs:14:19 | LL | trait A { fn g(b: B) -> B; } | ^ `B` cannot be made into an object diff --git a/tests/ui/dyn-compatibility/avoid-ice-on-warning-3.rs b/tests/ui/dyn-compatibility/avoid-ice-on-warning-3.rs index 38bee8142bb9a..00d47225e92fa 100644 --- a/tests/ui/dyn-compatibility/avoid-ice-on-warning-3.rs +++ b/tests/ui/dyn-compatibility/avoid-ice-on-warning-3.rs @@ -2,7 +2,9 @@ //@[old] edition:2015 //@[new] edition:2021 trait B { fn f(a: A) -> A; } -//~^ ERROR the trait `A` cannot be made into an object +//[new]~^ ERROR expected a type, found a trait +//[new]~| ERROR expected a type, found a trait +//[old]~^^^ ERROR the trait `A` cannot be made into an object //[old]~| WARN trait objects without an explicit `dyn` are deprecated //[old]~| WARN trait objects without an explicit `dyn` are deprecated //[old]~| WARN trait objects without an explicit `dyn` are deprecated @@ -10,7 +12,9 @@ trait B { fn f(a: A) -> A; } //[old]~| WARN this is accepted in the current edition //[old]~| WARN this is accepted in the current edition trait A { fn g(b: B) -> B; } -//~^ ERROR the trait `B` cannot be made into an object +//[new]~^ ERROR expected a type, found a trait +//[new]~| ERROR expected a type, found a trait +//[old]~^^^ ERROR the trait `B` cannot be made into an object //[old]~| WARN trait objects without an explicit `dyn` are deprecated //[old]~| WARN trait objects without an explicit `dyn` are deprecated //[old]~| WARN trait objects without an explicit `dyn` are deprecated diff --git a/tests/ui/dyn-compatibility/avoid-ice-on-warning.new.stderr b/tests/ui/dyn-compatibility/avoid-ice-on-warning.new.stderr index 4ff45d7a84858..e9eb1cdd0c233 100644 --- a/tests/ui/dyn-compatibility/avoid-ice-on-warning.new.stderr +++ b/tests/ui/dyn-compatibility/avoid-ice-on-warning.new.stderr @@ -15,6 +15,18 @@ error[E0405]: cannot find trait `call_that` in this scope LL | fn call_this(f: F) : Fn(&str) + call_that {} | ^^^^^^^^^ not found in this scope -error: aborting due to 2 previous errors +error[E0782]: expected a type, found a trait + --> $DIR/avoid-ice-on-warning.rs:4:25 + | +LL | fn call_this(f: F) : Fn(&str) + call_that {} + | ^^^^^^^^^^^^^^^^^^^^ + | +help: `Fn(&str) + call_that` is dyn-incompatible, use `impl Fn(&str) + call_that` to return an opaque type, as long as you return a single underlying type + | +LL | fn call_this(f: F) : impl Fn(&str) + call_that {} + | ++++ + +error: aborting due to 3 previous errors -For more information about this error, try `rustc --explain E0405`. +Some errors have detailed explanations: E0405, E0782. +For more information about an error, try `rustc --explain E0405`. diff --git a/tests/ui/dyn-compatibility/avoid-ice-on-warning.rs b/tests/ui/dyn-compatibility/avoid-ice-on-warning.rs index b90d8911d500b..ef82321df0e3b 100644 --- a/tests/ui/dyn-compatibility/avoid-ice-on-warning.rs +++ b/tests/ui/dyn-compatibility/avoid-ice-on-warning.rs @@ -4,6 +4,7 @@ fn call_this(f: F) : Fn(&str) + call_that {} //~^ ERROR return types are denoted using `->` //~| ERROR cannot find trait `call_that` in this scope +//[new]~| ERROR expected a type, found a trait //[old]~| WARN trait objects without an explicit `dyn` are deprecated //[old]~| WARN this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! fn main() {} diff --git a/tests/ui/dyn-compatibility/bare-trait-dont-suggest-dyn.new.fixed b/tests/ui/dyn-compatibility/bare-trait-dont-suggest-dyn.new.fixed index 4f5310082e18d..a54892afd3e4b 100644 --- a/tests/ui/dyn-compatibility/bare-trait-dont-suggest-dyn.new.fixed +++ b/tests/ui/dyn-compatibility/bare-trait-dont-suggest-dyn.new.fixed @@ -4,7 +4,8 @@ //@[new] run-rustfix #![deny(bare_trait_objects)] fn ord_prefer_dot(s: String) -> impl Ord { - //~^ ERROR the trait `Ord` cannot be made into an object + //[new]~^ ERROR expected a type, found a trait + //[old]~^^ ERROR the trait `Ord` cannot be made into an object //[old]~| ERROR trait objects without an explicit `dyn` are deprecated //[old]~| WARNING this is accepted in the current edition (Rust 2015) (s.starts_with("."), s) diff --git a/tests/ui/dyn-compatibility/bare-trait-dont-suggest-dyn.new.stderr b/tests/ui/dyn-compatibility/bare-trait-dont-suggest-dyn.new.stderr index bb2bf6ddcda8e..52168261a64ea 100644 --- a/tests/ui/dyn-compatibility/bare-trait-dont-suggest-dyn.new.stderr +++ b/tests/ui/dyn-compatibility/bare-trait-dont-suggest-dyn.new.stderr @@ -1,21 +1,14 @@ -error[E0038]: the trait `Ord` cannot be made into an object +error[E0782]: expected a type, found a trait --> $DIR/bare-trait-dont-suggest-dyn.rs:6:33 | LL | fn ord_prefer_dot(s: String) -> Ord { - | ^^^ `Ord` cannot be made into an object + | ^^^ | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $SRC_DIR/core/src/cmp.rs:LL:COL - | - = note: the trait cannot be made into an object because it uses `Self` as a type parameter - ::: $SRC_DIR/core/src/cmp.rs:LL:COL - | - = note: the trait cannot be made into an object because it uses `Self` as a type parameter -help: consider using an opaque type instead +help: `Ord` is dyn-incompatible, use `impl Ord` to return an opaque type, as long as you return a single underlying type | LL | fn ord_prefer_dot(s: String) -> impl Ord { | ++++ error: aborting due to 1 previous error -For more information about this error, try `rustc --explain E0038`. +For more information about this error, try `rustc --explain E0782`. diff --git a/tests/ui/dyn-compatibility/bare-trait-dont-suggest-dyn.rs b/tests/ui/dyn-compatibility/bare-trait-dont-suggest-dyn.rs index cb5a305eab087..cf9be612d2e7e 100644 --- a/tests/ui/dyn-compatibility/bare-trait-dont-suggest-dyn.rs +++ b/tests/ui/dyn-compatibility/bare-trait-dont-suggest-dyn.rs @@ -4,7 +4,8 @@ //@[new] run-rustfix #![deny(bare_trait_objects)] fn ord_prefer_dot(s: String) -> Ord { - //~^ ERROR the trait `Ord` cannot be made into an object + //[new]~^ ERROR expected a type, found a trait + //[old]~^^ ERROR the trait `Ord` cannot be made into an object //[old]~| ERROR trait objects without an explicit `dyn` are deprecated //[old]~| WARNING this is accepted in the current edition (Rust 2015) (s.starts_with("."), s) diff --git a/tests/ui/dyn-compatibility/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs b/tests/ui/dyn-compatibility/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs index dabaa309c16a1..7bc2af463cb9f 100644 --- a/tests/ui/dyn-compatibility/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs +++ b/tests/ui/dyn-compatibility/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs @@ -6,104 +6,102 @@ struct IceCream; impl IceCream { fn foo(_: &Trait) {} - //~^ ERROR: trait objects must include the `dyn` keyword + //~^ ERROR: expected a type, found a trait fn bar(self, _: &'a Trait) {} - //~^ ERROR: trait objects must include the `dyn` keyword + //~^ ERROR: expected a type, found a trait //~| ERROR: use of undeclared lifetime name fn alice<'a>(&self, _: &Trait) {} - //~^ ERROR: trait objects must include the `dyn` keyword + //~^ ERROR: expected a type, found a trait fn bob<'a>(_: &'a Trait) {} - //~^ ERROR: trait objects must include the `dyn` keyword + //~^ ERROR: expected a type, found a trait fn cat() -> &Trait { //~^ ERROR: missing lifetime specifier - //~| ERROR: trait objects must include the `dyn` keyword + //~| ERROR: expected a type, found a trait &Type } fn dog<'a>() -> &Trait { //~^ ERROR: missing lifetime specifier - //~| ERROR: trait objects must include the `dyn` keyword + //~| ERROR: expected a type, found a trait &Type } fn kitten() -> &'a Trait { //~^ ERROR: use of undeclared lifetime name - //~| ERROR: trait objects must include the `dyn` keyword + //~| ERROR: expected a type, found a trait &Type } fn puppy<'a>() -> &'a Trait { - //~^ ERROR: trait objects must include the `dyn` keyword + //~^ ERROR: expected a type, found a trait &Type } fn parrot() -> &mut Trait { //~^ ERROR: missing lifetime specifier - //~| ERROR: trait objects must include the `dyn` keyword + //~| ERROR: expected a type, found a trait &mut Type - //~^ ERROR: cannot return reference to temporary value } } trait Sing { fn foo(_: &Trait); - //~^ ERROR: trait objects must include the `dyn` keyword + //~^ ERROR: expected a type, found a trait fn bar(_: &'a Trait); - //~^ ERROR: trait objects must include the `dyn` keyword + //~^ ERROR: expected a type, found a trait //~| ERROR: use of undeclared lifetime name fn alice<'a>(_: &Trait); - //~^ ERROR: trait objects must include the `dyn` keyword + //~^ ERROR: expected a type, found a trait fn bob<'a>(_: &'a Trait); - //~^ ERROR: trait objects must include the `dyn` keyword + //~^ ERROR: expected a type, found a trait fn cat() -> &Trait; //~^ ERROR: missing lifetime specifier - //~| ERROR: trait objects must include the `dyn` keyword + //~| ERROR: expected a type, found a trait fn dog<'a>() -> &Trait { //~^ ERROR: missing lifetime specifier - //~| ERROR: trait objects must include the `dyn` keyword + //~| ERROR: expected a type, found a trait &Type } fn kitten() -> &'a Trait { //~^ ERROR: use of undeclared lifetime name - //~| ERROR: trait objects must include the `dyn` keyword + //~| ERROR: expected a type, found a trait &Type } fn puppy<'a>() -> &'a Trait { - //~^ ERROR: trait objects must include the `dyn` keyword + //~^ ERROR: expected a type, found a trait &Type } fn parrot() -> &mut Trait { //~^ ERROR: missing lifetime specifier - //~| ERROR: trait objects must include the `dyn` keyword + //~| ERROR: expected a type, found a trait &mut Type - //~^ ERROR: cannot return reference to temporary value } } fn foo(_: &Trait) {} -//~^ ERROR: trait objects must include the `dyn` keyword +//~^ ERROR: expected a type, found a trait fn bar(_: &'a Trait) {} -//~^ ERROR: trait objects must include the `dyn` keyword +//~^ ERROR: expected a type, found a trait //~| ERROR: use of undeclared lifetime name fn alice<'a>(_: &Trait) {} -//~^ ERROR: trait objects must include the `dyn` keyword +//~^ ERROR: expected a type, found a trait fn bob<'a>(_: &'a Trait) {} -//~^ ERROR: trait objects must include the `dyn` keyword +//~^ ERROR: expected a type, found a trait struct Type; @@ -111,32 +109,31 @@ impl Trait for Type {} fn cat() -> &Trait { //~^ ERROR: missing lifetime specifier -//~| ERROR: trait objects must include the `dyn` keyword +//~| ERROR: expected a type, found a trait &Type } fn dog<'a>() -> &Trait { //~^ ERROR: missing lifetime specifier -//~| ERROR: trait objects must include the `dyn` keyword +//~| ERROR: expected a type, found a trait &Type } fn kitten() -> &'a Trait { //~^ ERROR: use of undeclared lifetime name -//~| ERROR: trait objects must include the `dyn` keyword +//~| ERROR: expected a type, found a trait &Type } fn puppy<'a>() -> &'a Trait { -//~^ ERROR: trait objects must include the `dyn` keyword +//~^ ERROR: expected a type, found a trait &Type } fn parrot() -> &mut Trait { //~^ ERROR: missing lifetime specifier - //~| ERROR: trait objects must include the `dyn` keyword + //~| ERROR: expected a type, found a trait &mut Type - //~^ ERROR: cannot return reference to temporary value } fn main() {} diff --git a/tests/ui/dyn-compatibility/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.stderr b/tests/ui/dyn-compatibility/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.stderr index 8bdfea7766e38..4c6d84f05341f 100644 --- a/tests/ui/dyn-compatibility/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.stderr +++ b/tests/ui/dyn-compatibility/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.stderr @@ -65,7 +65,7 @@ LL | fn parrot() -> &'static mut Trait { | +++++++ error[E0261]: use of undeclared lifetime name `'a` - --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:56:16 + --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:55:16 | LL | fn bar(_: &'a Trait); | ^^ undeclared lifetime @@ -80,7 +80,7 @@ LL | trait Sing<'a> { | ++++ error[E0106]: missing lifetime specifier - --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:66:17 + --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:65:17 | LL | fn cat() -> &Trait; | ^ expected named lifetime parameter @@ -97,7 +97,7 @@ LL + fn cat() -> Trait; | error[E0106]: missing lifetime specifier - --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:70:21 + --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:69:21 | LL | fn dog<'a>() -> &Trait { | ^ expected named lifetime parameter @@ -109,7 +109,7 @@ LL | fn dog<'a>() -> &'a Trait { | ++ error[E0261]: use of undeclared lifetime name `'a` - --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:76:21 + --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:75:21 | LL | fn kitten() -> &'a Trait { | ^^ undeclared lifetime @@ -124,7 +124,7 @@ LL | trait Sing<'a> { | ++++ error[E0106]: missing lifetime specifier - --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:87:20 + --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:86:20 | LL | fn parrot() -> &mut Trait { | ^ expected named lifetime parameter @@ -136,7 +136,7 @@ LL | fn parrot() -> &'static mut Trait { | +++++++ error[E0261]: use of undeclared lifetime name `'a` - --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:98:12 + --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:96:12 | LL | fn bar(_: &'a Trait) {} | - ^^ undeclared lifetime @@ -144,7 +144,7 @@ LL | fn bar(_: &'a Trait) {} | help: consider introducing lifetime `'a` here: `<'a>` error[E0106]: missing lifetime specifier - --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:112:13 + --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:110:13 | LL | fn cat() -> &Trait { | ^ expected named lifetime parameter @@ -156,7 +156,7 @@ LL | fn cat() -> &'static Trait { | +++++++ error[E0106]: missing lifetime specifier - --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:118:17 + --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:116:17 | LL | fn dog<'a>() -> &Trait { | ^ expected named lifetime parameter @@ -168,7 +168,7 @@ LL | fn dog<'a>() -> &'a Trait { | ++ error[E0261]: use of undeclared lifetime name `'a` - --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:124:17 + --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:122:17 | LL | fn kitten() -> &'a Trait { | - ^^ undeclared lifetime @@ -176,7 +176,7 @@ LL | fn kitten() -> &'a Trait { | help: consider introducing lifetime `'a` here: `<'a>` error[E0106]: missing lifetime specifier - --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:135:16 + --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:133:16 | LL | fn parrot() -> &mut Trait { | ^ expected named lifetime parameter @@ -187,35 +187,8 @@ help: consider using the `'static` lifetime, but this is uncommon unless you're LL | fn parrot() -> &'static mut Trait { | +++++++ -error[E0515]: cannot return reference to temporary value - --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:47:9 - | -LL | &mut Type - | ^^^^^---- - | | | - | | temporary value created here - | returns a reference to data owned by the current function - -error[E0515]: cannot return reference to temporary value - --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:90:9 - | -LL | &mut Type - | ^^^^^---- - | | | - | | temporary value created here - | returns a reference to data owned by the current function - -error[E0515]: cannot return reference to temporary value - --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:138:5 - | -LL | &mut Type - | ^^^^^---- - | | | - | | temporary value created here - | returns a reference to data owned by the current function - -error[E0782]: trait objects must include the `dyn` keyword - --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:53:16 +error[E0782]: expected a type, found a trait + --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:52:16 | LL | fn foo(_: &Trait); | ^^^^^ @@ -233,8 +206,8 @@ help: alternatively, use a trait object to accept any type that implements `Trai LL | fn foo(_: &dyn Trait); | +++ -error[E0782]: trait objects must include the `dyn` keyword - --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:56:19 +error[E0782]: expected a type, found a trait + --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:55:19 | LL | fn bar(_: &'a Trait); | ^^^^^ @@ -252,8 +225,8 @@ help: alternatively, use a trait object to accept any type that implements `Trai LL | fn bar(_: &'a dyn Trait); | +++ -error[E0782]: trait objects must include the `dyn` keyword - --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:60:22 +error[E0782]: expected a type, found a trait + --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:59:22 | LL | fn alice<'a>(_: &Trait); | ^^^^^ @@ -271,8 +244,8 @@ help: alternatively, use a trait object to accept any type that implements `Trai LL | fn alice<'a>(_: &dyn Trait); | +++ -error[E0782]: trait objects must include the `dyn` keyword - --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:63:23 +error[E0782]: expected a type, found a trait + --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:62:23 | LL | fn bob<'a>(_: &'a Trait); | ^^^^^ @@ -290,8 +263,8 @@ help: alternatively, use a trait object to accept any type that implements `Trai LL | fn bob<'a>(_: &'a dyn Trait); | +++ -error[E0782]: trait objects must include the `dyn` keyword - --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:66:18 +error[E0782]: expected a type, found a trait + --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:65:18 | LL | fn cat() -> &Trait; | ^^^^^ @@ -305,8 +278,8 @@ help: alternatively, you can return an owned trait object LL | fn cat() -> Box; | ~~~~~~~~~~~~~~ -error[E0782]: trait objects must include the `dyn` keyword - --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:70:22 +error[E0782]: expected a type, found a trait + --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:69:22 | LL | fn dog<'a>() -> &Trait { | ^^^^^ @@ -320,8 +293,8 @@ help: alternatively, you can return an owned trait object LL | fn dog<'a>() -> Box { | ~~~~~~~~~~~~~~ -error[E0782]: trait objects must include the `dyn` keyword - --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:76:24 +error[E0782]: expected a type, found a trait + --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:75:24 | LL | fn kitten() -> &'a Trait { | ^^^^^ @@ -335,8 +308,8 @@ help: alternatively, you can return an owned trait object LL | fn kitten() -> Box { | ~~~~~~~~~~~~~~ -error[E0782]: trait objects must include the `dyn` keyword - --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:82:27 +error[E0782]: expected a type, found a trait + --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:81:27 | LL | fn puppy<'a>() -> &'a Trait { | ^^^^^ @@ -350,8 +323,8 @@ help: alternatively, you can return an owned trait object LL | fn puppy<'a>() -> Box { | ~~~~~~~~~~~~~~ -error[E0782]: trait objects must include the `dyn` keyword - --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:87:25 +error[E0782]: expected a type, found a trait + --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:86:25 | LL | fn parrot() -> &mut Trait { | ^^^^^ @@ -365,8 +338,8 @@ help: alternatively, you can return an owned trait object LL | fn parrot() -> Box { | ~~~~~~~~~~~~~~ -error[E0782]: trait objects must include the `dyn` keyword - --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:95:12 +error[E0782]: expected a type, found a trait + --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:93:12 | LL | fn foo(_: &Trait) {} | ^^^^^ @@ -384,8 +357,8 @@ help: alternatively, use a trait object to accept any type that implements `Trai LL | fn foo(_: &dyn Trait) {} | +++ -error[E0782]: trait objects must include the `dyn` keyword - --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:98:15 +error[E0782]: expected a type, found a trait + --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:96:15 | LL | fn bar(_: &'a Trait) {} | ^^^^^ @@ -403,8 +376,8 @@ help: alternatively, use a trait object to accept any type that implements `Trai LL | fn bar(_: &'a dyn Trait) {} | +++ -error[E0782]: trait objects must include the `dyn` keyword - --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:102:18 +error[E0782]: expected a type, found a trait + --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:100:18 | LL | fn alice<'a>(_: &Trait) {} | ^^^^^ @@ -422,8 +395,8 @@ help: alternatively, use a trait object to accept any type that implements `Trai LL | fn alice<'a>(_: &dyn Trait) {} | +++ -error[E0782]: trait objects must include the `dyn` keyword - --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:105:19 +error[E0782]: expected a type, found a trait + --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:103:19 | LL | fn bob<'a>(_: &'a Trait) {} | ^^^^^ @@ -441,8 +414,8 @@ help: alternatively, use a trait object to accept any type that implements `Trai LL | fn bob<'a>(_: &'a dyn Trait) {} | +++ -error[E0782]: trait objects must include the `dyn` keyword - --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:112:14 +error[E0782]: expected a type, found a trait + --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:110:14 | LL | fn cat() -> &Trait { | ^^^^^ @@ -456,8 +429,8 @@ help: alternatively, you can return an owned trait object LL | fn cat() -> Box { | ~~~~~~~~~~~~~~ -error[E0782]: trait objects must include the `dyn` keyword - --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:118:18 +error[E0782]: expected a type, found a trait + --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:116:18 | LL | fn dog<'a>() -> &Trait { | ^^^^^ @@ -471,8 +444,8 @@ help: alternatively, you can return an owned trait object LL | fn dog<'a>() -> Box { | ~~~~~~~~~~~~~~ -error[E0782]: trait objects must include the `dyn` keyword - --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:124:20 +error[E0782]: expected a type, found a trait + --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:122:20 | LL | fn kitten() -> &'a Trait { | ^^^^^ @@ -486,8 +459,8 @@ help: alternatively, you can return an owned trait object LL | fn kitten() -> Box { | ~~~~~~~~~~~~~~ -error[E0782]: trait objects must include the `dyn` keyword - --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:130:23 +error[E0782]: expected a type, found a trait + --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:128:23 | LL | fn puppy<'a>() -> &'a Trait { | ^^^^^ @@ -501,8 +474,8 @@ help: alternatively, you can return an owned trait object LL | fn puppy<'a>() -> Box { | ~~~~~~~~~~~~~~ -error[E0782]: trait objects must include the `dyn` keyword - --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:135:21 +error[E0782]: expected a type, found a trait + --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:133:21 | LL | fn parrot() -> &mut Trait { | ^^^^^ @@ -516,7 +489,7 @@ help: alternatively, you can return an owned trait object LL | fn parrot() -> Box { | ~~~~~~~~~~~~~~ -error[E0782]: trait objects must include the `dyn` keyword +error[E0782]: expected a type, found a trait --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:8:16 | LL | fn foo(_: &Trait) {} @@ -535,7 +508,7 @@ help: alternatively, use a trait object to accept any type that implements `Trai LL | fn foo(_: &dyn Trait) {} | +++ -error[E0782]: trait objects must include the `dyn` keyword +error[E0782]: expected a type, found a trait --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:11:25 | LL | fn bar(self, _: &'a Trait) {} @@ -554,7 +527,7 @@ help: alternatively, use a trait object to accept any type that implements `Trai LL | fn bar(self, _: &'a dyn Trait) {} | +++ -error[E0782]: trait objects must include the `dyn` keyword +error[E0782]: expected a type, found a trait --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:15:29 | LL | fn alice<'a>(&self, _: &Trait) {} @@ -573,7 +546,7 @@ help: alternatively, use a trait object to accept any type that implements `Trai LL | fn alice<'a>(&self, _: &dyn Trait) {} | +++ -error[E0782]: trait objects must include the `dyn` keyword +error[E0782]: expected a type, found a trait --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:18:23 | LL | fn bob<'a>(_: &'a Trait) {} @@ -592,7 +565,7 @@ help: alternatively, use a trait object to accept any type that implements `Trai LL | fn bob<'a>(_: &'a dyn Trait) {} | +++ -error[E0782]: trait objects must include the `dyn` keyword +error[E0782]: expected a type, found a trait --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:21:18 | LL | fn cat() -> &Trait { @@ -607,7 +580,7 @@ help: alternatively, you can return an owned trait object LL | fn cat() -> Box { | ~~~~~~~~~~~~~~ -error[E0782]: trait objects must include the `dyn` keyword +error[E0782]: expected a type, found a trait --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:27:22 | LL | fn dog<'a>() -> &Trait { @@ -622,7 +595,7 @@ help: alternatively, you can return an owned trait object LL | fn dog<'a>() -> Box { | ~~~~~~~~~~~~~~ -error[E0782]: trait objects must include the `dyn` keyword +error[E0782]: expected a type, found a trait --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:33:24 | LL | fn kitten() -> &'a Trait { @@ -637,7 +610,7 @@ help: alternatively, you can return an owned trait object LL | fn kitten() -> Box { | ~~~~~~~~~~~~~~ -error[E0782]: trait objects must include the `dyn` keyword +error[E0782]: expected a type, found a trait --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:39:27 | LL | fn puppy<'a>() -> &'a Trait { @@ -652,7 +625,7 @@ help: alternatively, you can return an owned trait object LL | fn puppy<'a>() -> Box { | ~~~~~~~~~~~~~~ -error[E0782]: trait objects must include the `dyn` keyword +error[E0782]: expected a type, found a trait --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:44:25 | LL | fn parrot() -> &mut Trait { @@ -667,7 +640,7 @@ help: alternatively, you can return an owned trait object LL | fn parrot() -> Box { | ~~~~~~~~~~~~~~ -error: aborting due to 45 previous errors +error: aborting due to 42 previous errors -Some errors have detailed explanations: E0106, E0261, E0515, E0782. +Some errors have detailed explanations: E0106, E0261, E0782. For more information about an error, try `rustc --explain E0106`. diff --git a/tests/ui/dyn-keyword/dyn-2021-edition-error.rs b/tests/ui/dyn-keyword/dyn-2021-edition-error.rs index f98bf4ef5d177..5d607d82ea1ac 100644 --- a/tests/ui/dyn-keyword/dyn-2021-edition-error.rs +++ b/tests/ui/dyn-keyword/dyn-2021-edition-error.rs @@ -1,10 +1,10 @@ //@ edition:2021 fn function(x: &SomeTrait, y: Box) { - //~^ ERROR trait objects must include the `dyn` keyword - //~| ERROR trait objects must include the `dyn` keyword + //~^ ERROR expected a type, found a trait + //~| ERROR expected a type, found a trait let _x: &SomeTrait = todo!(); - //~^ ERROR trait objects must include the `dyn` keyword + //~^ ERROR expected a type, found a trait } trait SomeTrait {} diff --git a/tests/ui/dyn-keyword/dyn-2021-edition-error.stderr b/tests/ui/dyn-keyword/dyn-2021-edition-error.stderr index 52ee6c81ab794..6d1a1618ac033 100644 --- a/tests/ui/dyn-keyword/dyn-2021-edition-error.stderr +++ b/tests/ui/dyn-keyword/dyn-2021-edition-error.stderr @@ -1,4 +1,4 @@ -error[E0782]: trait objects must include the `dyn` keyword +error[E0782]: expected a type, found a trait --> $DIR/dyn-2021-edition-error.rs:3:17 | LL | fn function(x: &SomeTrait, y: Box) { @@ -17,24 +17,24 @@ help: alternatively, use a trait object to accept any type that implements `Some LL | fn function(x: &dyn SomeTrait, y: Box) { | +++ -error[E0782]: trait objects must include the `dyn` keyword +error[E0782]: expected a type, found a trait --> $DIR/dyn-2021-edition-error.rs:3:35 | LL | fn function(x: &SomeTrait, y: Box) { | ^^^^^^^^^ | -help: add `dyn` keyword before this trait +help: you can add the `dyn` keyword if you want a trait object | LL | fn function(x: &SomeTrait, y: Box) { | +++ -error[E0782]: trait objects must include the `dyn` keyword +error[E0782]: expected a type, found a trait --> $DIR/dyn-2021-edition-error.rs:6:14 | LL | let _x: &SomeTrait = todo!(); | ^^^^^^^^^ | -help: add `dyn` keyword before this trait +help: you can add the `dyn` keyword if you want a trait object | LL | let _x: &dyn SomeTrait = todo!(); | +++ diff --git a/tests/ui/dyn-keyword/suggest-dyn-on-bare-trait-in-pat.rs b/tests/ui/dyn-keyword/suggest-dyn-on-bare-trait-in-pat.rs index 19b5edb620f6b..bee15788da925 100644 --- a/tests/ui/dyn-keyword/suggest-dyn-on-bare-trait-in-pat.rs +++ b/tests/ui/dyn-keyword/suggest-dyn-on-bare-trait-in-pat.rs @@ -9,6 +9,7 @@ impl dyn Trait { fn main() { match () { Trait::CONST => {} - //~^ ERROR trait objects must include the `dyn` keyword + //~^ ERROR expected a type, found a trait + //~| HELP you can add the `dyn` keyword if you want a trait object } } diff --git a/tests/ui/dyn-keyword/suggest-dyn-on-bare-trait-in-pat.stderr b/tests/ui/dyn-keyword/suggest-dyn-on-bare-trait-in-pat.stderr index 4446a89b63b15..6a2bb3ec09adf 100644 --- a/tests/ui/dyn-keyword/suggest-dyn-on-bare-trait-in-pat.stderr +++ b/tests/ui/dyn-keyword/suggest-dyn-on-bare-trait-in-pat.stderr @@ -1,10 +1,10 @@ -error[E0782]: trait objects must include the `dyn` keyword +error[E0782]: expected a type, found a trait --> $DIR/suggest-dyn-on-bare-trait-in-pat.rs:11:9 | LL | Trait::CONST => {} | ^^^^^ | -help: add `dyn` keyword before this trait +help: you can add the `dyn` keyword if you want a trait object | LL | ::CONST => {} | ++++ + diff --git a/tests/ui/editions/dyn-trait-sugg-2021.rs b/tests/ui/editions/dyn-trait-sugg-2021.rs index d702bfb2f88db..a536466260016 100644 --- a/tests/ui/editions/dyn-trait-sugg-2021.rs +++ b/tests/ui/editions/dyn-trait-sugg-2021.rs @@ -8,5 +8,5 @@ impl dyn Foo { fn main() { Foo::hi(123); - //~^ ERROR trait objects must include the `dyn` keyword + //~^ ERROR expected a type, found a trait } diff --git a/tests/ui/editions/dyn-trait-sugg-2021.stderr b/tests/ui/editions/dyn-trait-sugg-2021.stderr index 8a65fea11c95c..3aea8ac491d40 100644 --- a/tests/ui/editions/dyn-trait-sugg-2021.stderr +++ b/tests/ui/editions/dyn-trait-sugg-2021.stderr @@ -1,10 +1,10 @@ -error[E0782]: trait objects must include the `dyn` keyword +error[E0782]: expected a type, found a trait --> $DIR/dyn-trait-sugg-2021.rs:10:5 | LL | Foo::hi(123); | ^^^ | -help: add `dyn` keyword before this trait +help: you can add the `dyn` keyword if you want a trait object | LL | ::hi(123); | ++++ + diff --git a/tests/ui/impl-trait/generic-with-implicit-hrtb-without-dyn.edition2021.stderr b/tests/ui/impl-trait/generic-with-implicit-hrtb-without-dyn.edition2021.stderr index 7917fa991ee32..1e268bc7f49b9 100644 --- a/tests/ui/impl-trait/generic-with-implicit-hrtb-without-dyn.edition2021.stderr +++ b/tests/ui/impl-trait/generic-with-implicit-hrtb-without-dyn.edition2021.stderr @@ -1,21 +1,14 @@ -error[E0277]: the trait bound `(): AsRef<(dyn for<'a> Fn(&'a ()) + 'static)>` is not satisfied - --> $DIR/generic-with-implicit-hrtb-without-dyn.rs:6:13 - | -LL | fn ice() -> impl AsRef { - | ^^^^^^^^^^^^^^^^^^^ the trait `AsRef<(dyn for<'a> Fn(&'a ()) + 'static)>` is not implemented for `()` - -error[E0782]: trait objects must include the `dyn` keyword +error[E0782]: expected a type, found a trait --> $DIR/generic-with-implicit-hrtb-without-dyn.rs:6:24 | LL | fn ice() -> impl AsRef { | ^^^^^^^ | -help: add `dyn` keyword before this trait +help: you can add the `dyn` keyword if you want a trait object | LL | fn ice() -> impl AsRef { | +++ -error: aborting due to 2 previous errors +error: aborting due to 1 previous error -Some errors have detailed explanations: E0277, E0782. -For more information about an error, try `rustc --explain E0277`. +For more information about this error, try `rustc --explain E0782`. diff --git a/tests/ui/impl-trait/generic-with-implicit-hrtb-without-dyn.rs b/tests/ui/impl-trait/generic-with-implicit-hrtb-without-dyn.rs index 582386aa7596a..c71f794d5d125 100644 --- a/tests/ui/impl-trait/generic-with-implicit-hrtb-without-dyn.rs +++ b/tests/ui/impl-trait/generic-with-implicit-hrtb-without-dyn.rs @@ -5,8 +5,7 @@ fn ice() -> impl AsRef { //[edition2015]~^ ERROR: the trait bound `(): AsRef<(dyn for<'a> Fn(&'a ()) + 'static)>` is not satisfied [E0277] - //[edition2021]~^^ ERROR: trait objects must include the `dyn` keyword [E0782] - //[edition2021]~| ERROR: the trait bound `(): AsRef<(dyn for<'a> Fn(&'a ()) + 'static)>` is not satisfied [E0277] + //[edition2021]~^^ ERROR: expected a type, found a trait [E0782] todo!() } diff --git a/tests/ui/resolve/issue-111312.rs b/tests/ui/resolve/issue-111312.rs index 79c6f67dadd39..574e9870cd2f7 100644 --- a/tests/ui/resolve/issue-111312.rs +++ b/tests/ui/resolve/issue-111312.rs @@ -8,6 +8,5 @@ trait HasNot {} fn main() { HasNot::has(); - //~^ ERROR trait objects must include the `dyn` keyword - //~| ERROR no function or associated item named `has` found for trait `HasNot` + //~^ ERROR expected a type, found a trait } diff --git a/tests/ui/resolve/issue-111312.stderr b/tests/ui/resolve/issue-111312.stderr index 431802ead30c4..a1f8d6bc46c59 100644 --- a/tests/ui/resolve/issue-111312.stderr +++ b/tests/ui/resolve/issue-111312.stderr @@ -1,27 +1,14 @@ -error[E0782]: trait objects must include the `dyn` keyword +error[E0782]: expected a type, found a trait --> $DIR/issue-111312.rs:10:5 | LL | HasNot::has(); | ^^^^^^ | -help: add `dyn` keyword before this trait +help: you can add the `dyn` keyword if you want a trait object | LL | ::has(); | ++++ + -error[E0599]: no function or associated item named `has` found for trait `HasNot` - --> $DIR/issue-111312.rs:10:13 - | -LL | HasNot::has(); - | ^^^ function or associated item not found in `HasNot` - | -note: `Has` defines an item `has` - --> $DIR/issue-111312.rs:3:1 - | -LL | trait Has { - | ^^^^^^^^^ - -error: aborting due to 2 previous errors +error: aborting due to 1 previous error -Some errors have detailed explanations: E0599, E0782. -For more information about an error, try `rustc --explain E0599`. +For more information about this error, try `rustc --explain E0782`. diff --git a/tests/ui/resolve/issue-111727.rs b/tests/ui/resolve/issue-111727.rs index fcab924b80977..a5c2c0ca8c6aa 100644 --- a/tests/ui/resolve/issue-111727.rs +++ b/tests/ui/resolve/issue-111727.rs @@ -2,6 +2,5 @@ fn main() { std::any::Any::create(); - //~^ ERROR trait objects must include the `dyn` keyword - //~| ERROR no function or associated item named `create` found for trait `Any` + //~^ ERROR expected a type, found a trait } diff --git a/tests/ui/resolve/issue-111727.stderr b/tests/ui/resolve/issue-111727.stderr index 1ef5a1a1d5efb..71ea989ac349f 100644 --- a/tests/ui/resolve/issue-111727.stderr +++ b/tests/ui/resolve/issue-111727.stderr @@ -1,21 +1,14 @@ -error[E0782]: trait objects must include the `dyn` keyword +error[E0782]: expected a type, found a trait --> $DIR/issue-111727.rs:4:5 | LL | std::any::Any::create(); | ^^^^^^^^^^^^^ | -help: add `dyn` keyword before this trait +help: you can add the `dyn` keyword if you want a trait object | LL | ::create(); | ++++ + -error[E0599]: no function or associated item named `create` found for trait `Any` - --> $DIR/issue-111727.rs:4:20 - | -LL | std::any::Any::create(); - | ^^^^^^ function or associated item not found in `Any` - -error: aborting due to 2 previous errors +error: aborting due to 1 previous error -Some errors have detailed explanations: E0599, E0782. -For more information about an error, try `rustc --explain E0599`. +For more information about this error, try `rustc --explain E0782`. diff --git a/tests/ui/rust-2021/ice-return-unsized-can-impl-2.rs b/tests/ui/rust-2021/ice-return-unsized-can-impl-2.rs new file mode 100644 index 0000000000000..e57e9ce4844a4 --- /dev/null +++ b/tests/ui/rust-2021/ice-return-unsized-can-impl-2.rs @@ -0,0 +1,15 @@ +// Doesn't trigger ICE when returning unsized trait that can be impl +// issue https://github.com/rust-lang/rust/issues/125512 +//@ edition:2021 +#![feature(dyn_compatible_for_dispatch)] +trait B { + fn f(a: A) -> A; + //~^ ERROR: expected a type, found a trait + //~| ERROR: expected a type, found a trait +} +trait A { + fn concrete(b: B) -> B; + //~^ ERROR: expected a type, found a trait + //~| ERROR: expected a type, found a trait +} +fn main() {} diff --git a/tests/ui/rust-2021/ice-return-unsized-can-impl-2.stderr b/tests/ui/rust-2021/ice-return-unsized-can-impl-2.stderr new file mode 100644 index 0000000000000..b8a9a5c81297a --- /dev/null +++ b/tests/ui/rust-2021/ice-return-unsized-can-impl-2.stderr @@ -0,0 +1,57 @@ +error[E0782]: expected a type, found a trait + --> $DIR/ice-return-unsized-can-impl-2.rs:11:20 + | +LL | fn concrete(b: B) -> B; + | ^ + | + = note: `B` it is dyn-incompatible, so it can't be `dyn` +help: use a new generic type parameter, constrained by `B` + | +LL | fn concrete(b: T) -> B; + | ++++++ ~ +help: you can also use an opaque type, but users won't be able to specify the type parameter when calling the `fn`, having to rely exclusively on type inference + | +LL | fn concrete(b: impl B) -> B; + | ++++ + +error[E0782]: expected a type, found a trait + --> $DIR/ice-return-unsized-can-impl-2.rs:11:26 + | +LL | fn concrete(b: B) -> B; + | ^ + | +help: `B` is dyn-incompatible, use `impl B` to return an opaque type, as long as you return a single underlying type + | +LL | fn concrete(b: B) -> impl B; + | ++++ + +error[E0782]: expected a type, found a trait + --> $DIR/ice-return-unsized-can-impl-2.rs:6:13 + | +LL | fn f(a: A) -> A; + | ^ + | + = note: `A` it is dyn-incompatible, so it can't be `dyn` +help: use a new generic type parameter, constrained by `A` + | +LL | fn f(a: T) -> A; + | ++++++ ~ +help: you can also use an opaque type, but users won't be able to specify the type parameter when calling the `fn`, having to rely exclusively on type inference + | +LL | fn f(a: impl A) -> A; + | ++++ + +error[E0782]: expected a type, found a trait + --> $DIR/ice-return-unsized-can-impl-2.rs:6:19 + | +LL | fn f(a: A) -> A; + | ^ + | +help: `A` is dyn-incompatible, use `impl A` to return an opaque type, as long as you return a single underlying type + | +LL | fn f(a: A) -> impl A; + | ++++ + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0782`. diff --git a/tests/ui/rust-2021/ice-return-unsized-can-impl.rs b/tests/ui/rust-2021/ice-return-unsized-can-impl.rs new file mode 100644 index 0000000000000..055b11b4424a1 --- /dev/null +++ b/tests/ui/rust-2021/ice-return-unsized-can-impl.rs @@ -0,0 +1,16 @@ +// Doesn't trigger ICE when returning unsized trait that can be impl +// issue https://github.com/rust-lang/rust/issues/120482 +//@ edition:2021 +#![feature(dyn_compatible_for_dispatch)] + +trait B { + fn bar(&self, x: &Self); +} + +trait A { + fn g(new: B) -> B; + //~^ ERROR: expected a type, found a trait + //~| ERROR: expected a type, found a trait +} + +fn main() {} diff --git a/tests/ui/rust-2021/ice-return-unsized-can-impl.stderr b/tests/ui/rust-2021/ice-return-unsized-can-impl.stderr new file mode 100644 index 0000000000000..c0969570e920d --- /dev/null +++ b/tests/ui/rust-2021/ice-return-unsized-can-impl.stderr @@ -0,0 +1,30 @@ +error[E0782]: expected a type, found a trait + --> $DIR/ice-return-unsized-can-impl.rs:11:15 + | +LL | fn g(new: B) -> B; + | ^ + | + = note: `B` it is dyn-incompatible, so it can't be `dyn` +help: use a new generic type parameter, constrained by `B` + | +LL | fn g(new: T) -> B; + | ++++++ ~ +help: you can also use an opaque type, but users won't be able to specify the type parameter when calling the `fn`, having to rely exclusively on type inference + | +LL | fn g(new: impl B) -> B; + | ++++ + +error[E0782]: expected a type, found a trait + --> $DIR/ice-return-unsized-can-impl.rs:11:21 + | +LL | fn g(new: B) -> B; + | ^ + | +help: `B` is dyn-incompatible, use `impl B` to return an opaque type, as long as you return a single underlying type + | +LL | fn g(new: B) -> impl B; + | ++++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0782`. diff --git a/tests/ui/rust-2021/ice-unsized-fn-params-2.rs b/tests/ui/rust-2021/ice-unsized-fn-params-2.rs new file mode 100644 index 0000000000000..2b4f7bd088fbe --- /dev/null +++ b/tests/ui/rust-2021/ice-unsized-fn-params-2.rs @@ -0,0 +1,12 @@ +//@ edition:2021 +// Test that it doesn't trigger an ICE when using an unsized fn params. +// https://github.com/rust-lang/rust/issues/120241 +#![feature(dyn_compatible_for_dispatch)] +#![feature(unsized_fn_params)] + +fn guard(_s: Copy) -> bool { + //~^ ERROR: expected a type, found a trait + panic!() +} + +fn main() {} diff --git a/tests/ui/rust-2021/ice-unsized-fn-params-2.stderr b/tests/ui/rust-2021/ice-unsized-fn-params-2.stderr new file mode 100644 index 0000000000000..d35c8ab3e4254 --- /dev/null +++ b/tests/ui/rust-2021/ice-unsized-fn-params-2.stderr @@ -0,0 +1,19 @@ +error[E0782]: expected a type, found a trait + --> $DIR/ice-unsized-fn-params-2.rs:7:14 + | +LL | fn guard(_s: Copy) -> bool { + | ^^^^ + | + = note: `Copy` it is dyn-incompatible, so it can't be `dyn` +help: use a new generic type parameter, constrained by `Copy` + | +LL | fn guard(_s: T) -> bool { + | +++++++++ ~ +help: you can also use an opaque type, but users won't be able to specify the type parameter when calling the `fn`, having to rely exclusively on type inference + | +LL | fn guard(_s: impl Copy) -> bool { + | ++++ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0782`. diff --git a/tests/ui/rust-2021/ice-unsized-fn-params.rs b/tests/ui/rust-2021/ice-unsized-fn-params.rs new file mode 100644 index 0000000000000..6d8c1c3f152f1 --- /dev/null +++ b/tests/ui/rust-2021/ice-unsized-fn-params.rs @@ -0,0 +1,18 @@ +//@ edition:2021 +// Test that it doesn't trigger an ICE when using an unsized fn params. +// https://github.com/rust-lang/rust/issues/120241 +#![feature(dyn_compatible_for_dispatch)] + +trait B { + fn f(a: A) -> A; + //~^ ERROR: expected a type, found a trait + //~| ERROR: expected a type, found a trait +} + +trait A { + fn g(b: B) -> B; + //~^ ERROR: expected a type, found a trait + //~| ERROR: expected a type, found a trait +} + +fn main() {} diff --git a/tests/ui/rust-2021/ice-unsized-fn-params.stderr b/tests/ui/rust-2021/ice-unsized-fn-params.stderr new file mode 100644 index 0000000000000..d56e9981a2886 --- /dev/null +++ b/tests/ui/rust-2021/ice-unsized-fn-params.stderr @@ -0,0 +1,57 @@ +error[E0782]: expected a type, found a trait + --> $DIR/ice-unsized-fn-params.rs:13:13 + | +LL | fn g(b: B) -> B; + | ^ + | + = note: `B` it is dyn-incompatible, so it can't be `dyn` +help: use a new generic type parameter, constrained by `B` + | +LL | fn g(b: T) -> B; + | ++++++ ~ +help: you can also use an opaque type, but users won't be able to specify the type parameter when calling the `fn`, having to rely exclusively on type inference + | +LL | fn g(b: impl B) -> B; + | ++++ + +error[E0782]: expected a type, found a trait + --> $DIR/ice-unsized-fn-params.rs:13:19 + | +LL | fn g(b: B) -> B; + | ^ + | +help: `B` is dyn-incompatible, use `impl B` to return an opaque type, as long as you return a single underlying type + | +LL | fn g(b: B) -> impl B; + | ++++ + +error[E0782]: expected a type, found a trait + --> $DIR/ice-unsized-fn-params.rs:7:13 + | +LL | fn f(a: A) -> A; + | ^ + | + = note: `A` it is dyn-incompatible, so it can't be `dyn` +help: use a new generic type parameter, constrained by `A` + | +LL | fn f(a: T) -> A; + | ++++++ ~ +help: you can also use an opaque type, but users won't be able to specify the type parameter when calling the `fn`, having to rely exclusively on type inference + | +LL | fn f(a: impl A) -> A; + | ++++ + +error[E0782]: expected a type, found a trait + --> $DIR/ice-unsized-fn-params.rs:7:19 + | +LL | fn f(a: A) -> A; + | ^ + | +help: `A` is dyn-incompatible, use `impl A` to return an opaque type, as long as you return a single underlying type + | +LL | fn f(a: A) -> impl A; + | ++++ + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0782`. diff --git a/tests/ui/suggestions/dyn-incompatible-trait-should-use-self-2021-without-dyn.rs b/tests/ui/suggestions/dyn-incompatible-trait-should-use-self-2021-without-dyn.rs index 37afab6b643ca..10b4781eb0494 100644 --- a/tests/ui/suggestions/dyn-incompatible-trait-should-use-self-2021-without-dyn.rs +++ b/tests/ui/suggestions/dyn-incompatible-trait-should-use-self-2021-without-dyn.rs @@ -2,24 +2,21 @@ #![allow(bare_trait_objects)] trait A: Sized { fn f(a: A) -> A; - //~^ ERROR trait objects must include the `dyn` keyword - //~| ERROR trait objects must include the `dyn` keyword + //~^ ERROR expected a type, found a trait + //~| ERROR expected a type, found a trait //~| ERROR associated item referring to unboxed trait object for its own trait - //~| ERROR the trait `A` cannot be made into an object } trait B { fn f(b: B) -> B; - //~^ ERROR trait objects must include the `dyn` keyword - //~| ERROR trait objects must include the `dyn` keyword + //~^ ERROR expected a type, found a trait + //~| ERROR expected a type, found a trait //~| ERROR associated item referring to unboxed trait object for its own trait - //~| ERROR the trait `B` cannot be made into an object } trait C { fn f(&self, c: C) -> C; - //~^ ERROR trait objects must include the `dyn` keyword - //~| ERROR trait objects must include the `dyn` keyword + //~^ ERROR expected a type, found a trait + //~| ERROR expected a type, found a trait //~| ERROR associated item referring to unboxed trait object for its own trait - //~| ERROR the trait `C` cannot be made into an object } fn main() {} diff --git a/tests/ui/suggestions/dyn-incompatible-trait-should-use-self-2021-without-dyn.stderr b/tests/ui/suggestions/dyn-incompatible-trait-should-use-self-2021-without-dyn.stderr index 5330438258488..c0cfb18955cec 100644 --- a/tests/ui/suggestions/dyn-incompatible-trait-should-use-self-2021-without-dyn.stderr +++ b/tests/ui/suggestions/dyn-incompatible-trait-should-use-self-2021-without-dyn.stderr @@ -11,22 +11,8 @@ help: you might have meant to use `Self` to refer to the implementing type LL | fn f(a: Self) -> Self; | ~~~~ ~~~~ -error[E0038]: the trait `A` cannot be made into an object - --> $DIR/dyn-incompatible-trait-should-use-self-2021-without-dyn.rs:4:13 - | -LL | fn f(a: A) -> A; - | ^ `A` cannot be made into an object - | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/dyn-incompatible-trait-should-use-self-2021-without-dyn.rs:3:10 - | -LL | trait A: Sized { - | - ^^^^^ ...because it requires `Self: Sized` - | | - | this trait cannot be made into an object... - error: associated item referring to unboxed trait object for its own trait - --> $DIR/dyn-incompatible-trait-should-use-self-2021-without-dyn.rs:11:13 + --> $DIR/dyn-incompatible-trait-should-use-self-2021-without-dyn.rs:10:13 | LL | trait B { | - in this trait @@ -38,30 +24,8 @@ help: you might have meant to use `Self` to refer to the implementing type LL | fn f(b: Self) -> Self; | ~~~~ ~~~~ -error[E0038]: the trait `B` cannot be made into an object - --> $DIR/dyn-incompatible-trait-should-use-self-2021-without-dyn.rs:11:13 - | -LL | fn f(b: B) -> B; - | ^ `B` cannot be made into an object - | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/dyn-incompatible-trait-should-use-self-2021-without-dyn.rs:11:8 - | -LL | trait B { - | - this trait cannot be made into an object... -LL | fn f(b: B) -> B; - | ^ ...because associated function `f` has no `self` parameter -help: consider turning `f` into a method by giving it a `&self` argument - | -LL | fn f(&self, b: B) -> B; - | ++++++ -help: alternatively, consider constraining `f` so it does not apply to trait objects - | -LL | fn f(b: B) -> B where Self: Sized; - | +++++++++++++++++ - error: associated item referring to unboxed trait object for its own trait - --> $DIR/dyn-incompatible-trait-should-use-self-2021-without-dyn.rs:18:20 + --> $DIR/dyn-incompatible-trait-should-use-self-2021-without-dyn.rs:16:20 | LL | trait C { | - in this trait @@ -73,23 +37,7 @@ help: you might have meant to use `Self` to refer to the implementing type LL | fn f(&self, c: Self) -> Self; | ~~~~ ~~~~ -error[E0038]: the trait `C` cannot be made into an object - --> $DIR/dyn-incompatible-trait-should-use-self-2021-without-dyn.rs:18:20 - | -LL | fn f(&self, c: C) -> C; - | ----- ^ `C` cannot be made into an object - | | - | help: consider changing method `f`'s `self` parameter to be `&self` (notice the capitalization): `&Self` - | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/dyn-incompatible-trait-should-use-self-2021-without-dyn.rs:18:10 - | -LL | trait C { - | - this trait cannot be made into an object... -LL | fn f(&self, c: C) -> C; - | ^^^^^ ...because method `f`'s `self` parameter cannot be dispatched on - -error[E0782]: trait objects must include the `dyn` keyword +error[E0782]: expected a type, found a trait --> $DIR/dyn-incompatible-trait-should-use-self-2021-without-dyn.rs:4:13 | LL | fn f(a: A) -> A; @@ -105,7 +53,7 @@ help: you can also use an opaque type, but users won't be able to specify the ty LL | fn f(a: impl A) -> A; | ++++ -error[E0782]: trait objects must include the `dyn` keyword +error[E0782]: expected a type, found a trait --> $DIR/dyn-incompatible-trait-should-use-self-2021-without-dyn.rs:4:19 | LL | fn f(a: A) -> A; @@ -116,8 +64,8 @@ help: `A` is dyn-incompatible, use `impl A` to return an opaque type, as long as LL | fn f(a: A) -> impl A; | ++++ -error[E0782]: trait objects must include the `dyn` keyword - --> $DIR/dyn-incompatible-trait-should-use-self-2021-without-dyn.rs:11:13 +error[E0782]: expected a type, found a trait + --> $DIR/dyn-incompatible-trait-should-use-self-2021-without-dyn.rs:10:13 | LL | fn f(b: B) -> B; | ^ @@ -132,8 +80,8 @@ help: you can also use an opaque type, but users won't be able to specify the ty LL | fn f(b: impl B) -> B; | ++++ -error[E0782]: trait objects must include the `dyn` keyword - --> $DIR/dyn-incompatible-trait-should-use-self-2021-without-dyn.rs:11:19 +error[E0782]: expected a type, found a trait + --> $DIR/dyn-incompatible-trait-should-use-self-2021-without-dyn.rs:10:19 | LL | fn f(b: B) -> B; | ^ @@ -143,8 +91,8 @@ help: `B` is dyn-incompatible, use `impl B` to return an opaque type, as long as LL | fn f(b: B) -> impl B; | ++++ -error[E0782]: trait objects must include the `dyn` keyword - --> $DIR/dyn-incompatible-trait-should-use-self-2021-without-dyn.rs:18:20 +error[E0782]: expected a type, found a trait + --> $DIR/dyn-incompatible-trait-should-use-self-2021-without-dyn.rs:16:20 | LL | fn f(&self, c: C) -> C; | ^ @@ -159,8 +107,8 @@ help: you can also use an opaque type, but users won't be able to specify the ty LL | fn f(&self, c: impl C) -> C; | ++++ -error[E0782]: trait objects must include the `dyn` keyword - --> $DIR/dyn-incompatible-trait-should-use-self-2021-without-dyn.rs:18:26 +error[E0782]: expected a type, found a trait + --> $DIR/dyn-incompatible-trait-should-use-self-2021-without-dyn.rs:16:26 | LL | fn f(&self, c: C) -> C; | ^ @@ -170,7 +118,6 @@ help: `C` is dyn-incompatible, use `impl C` to return an opaque type, as long as LL | fn f(&self, c: C) -> impl C; | ++++ -error: aborting due to 12 previous errors +error: aborting due to 9 previous errors -Some errors have detailed explanations: E0038, E0782. -For more information about an error, try `rustc --explain E0038`. +For more information about this error, try `rustc --explain E0782`. diff --git a/tests/ui/suggestions/issue-116434-2021.rs b/tests/ui/suggestions/issue-116434-2021.rs index 6feba3dc6c16d..77cdfb8b614aa 100644 --- a/tests/ui/suggestions/issue-116434-2021.rs +++ b/tests/ui/suggestions/issue-116434-2021.rs @@ -3,7 +3,8 @@ trait Foo { type Clone; fn foo() -> Clone; - //~^ ERROR the trait `Clone` cannot be made into an object [E0038] + //~^ ERROR expected a type, found a trait + //~| HELP `Clone` is dyn-incompatible, use `impl Clone` to return an opaque type, as long as you return a single underlying type //~| HELP there is an associated type with the same name } @@ -12,7 +13,8 @@ trait DbHandle: Sized {} trait DbInterface { type DbHandle; fn handle() -> DbHandle; - //~^ ERROR the trait `DbHandle` cannot be made into an object [E0038] + //~^ ERROR expected a type, found a trait + //~| HELP `DbHandle` is dyn-incompatible, use `impl DbHandle` to return an opaque type, as long as you return a single underlying type //~| HELP there is an associated type with the same name } diff --git a/tests/ui/suggestions/issue-116434-2021.stderr b/tests/ui/suggestions/issue-116434-2021.stderr index 7f8cc147210ea..3853f03f1db67 100644 --- a/tests/ui/suggestions/issue-116434-2021.stderr +++ b/tests/ui/suggestions/issue-116434-2021.stderr @@ -1,29 +1,28 @@ -error[E0038]: the trait `Clone` cannot be made into an object +error[E0782]: expected a type, found a trait --> $DIR/issue-116434-2021.rs:5:17 | LL | fn foo() -> Clone; - | ^^^^^ `Clone` cannot be made into an object + | ^^^^^ | - = note: the trait cannot be made into an object because it requires `Self: Sized` - = note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit +help: `Clone` is dyn-incompatible, use `impl Clone` to return an opaque type, as long as you return a single underlying type + | +LL | fn foo() -> impl Clone; + | ++++ help: there is an associated type with the same name | LL | fn foo() -> Self::Clone; | ++++++ -error[E0038]: the trait `DbHandle` cannot be made into an object - --> $DIR/issue-116434-2021.rs:14:20 +error[E0782]: expected a type, found a trait + --> $DIR/issue-116434-2021.rs:15:20 | LL | fn handle() -> DbHandle; - | ^^^^^^^^ `DbHandle` cannot be made into an object + | ^^^^^^^^ | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/issue-116434-2021.rs:10:17 +help: `DbHandle` is dyn-incompatible, use `impl DbHandle` to return an opaque type, as long as you return a single underlying type | -LL | trait DbHandle: Sized {} - | -------- ^^^^^ ...because it requires `Self: Sized` - | | - | this trait cannot be made into an object... +LL | fn handle() -> impl DbHandle; + | ++++ help: there is an associated type with the same name | LL | fn handle() -> Self::DbHandle; @@ -31,4 +30,4 @@ LL | fn handle() -> Self::DbHandle; error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0038`. +For more information about this error, try `rustc --explain E0782`. diff --git a/tests/ui/suggestions/suggest-blanket-impl-local-trait.rs b/tests/ui/suggestions/suggest-blanket-impl-local-trait.rs index 76300c6a3f424..dd7e203abd7a8 100644 --- a/tests/ui/suggestions/suggest-blanket-impl-local-trait.rs +++ b/tests/ui/suggestions/suggest-blanket-impl-local-trait.rs @@ -11,48 +11,48 @@ trait LocalTraitTwo { } trait GenericTrait {} impl LocalTraitTwo for LocalTraitOne {} -//~^ ERROR trait objects must include the `dyn` keyword -//~| HELP add `dyn` keyword before this trait +//~^ ERROR expected a type, found a trait +//~| HELP you can add the `dyn` keyword if you want a trait object //~| HELP alternatively use a blanket implementation to implement `LocalTraitTwo` for all types that also implement `LocalTraitOne` impl fmt::Display for LocalTraitOne { -//~^ ERROR trait objects must include the `dyn` keyword -//~| HELP add `dyn` keyword before this trait +//~^ ERROR expected a type, found a trait +//~| HELP you can add the `dyn` keyword if you want a trait object fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result { todo!(); } } impl fmt::Display for LocalTraitTwo + Send { -//~^ ERROR trait objects must include the `dyn` keyword -//~| HELP add `dyn` keyword before this trait +//~^ ERROR expected a type, found a trait +//~| HELP you can add the `dyn` keyword if you want a trait object fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result { todo!(); } } impl LocalTraitOne for fmt::Display {} -//~^ ERROR trait objects must include the `dyn` keyword -//~| HELP add `dyn` keyword before this trait +//~^ ERROR expected a type, found a trait +//~| HELP you can add the `dyn` keyword if you want a trait object //~| HELP alternatively use a blanket implementation to implement `LocalTraitOne` for all types that also implement `fmt::Display` impl LocalTraitOne for fmt::Display + Send {} -//~^ ERROR trait objects must include the `dyn` keyword -//~| HELP add `dyn` keyword before this trait +//~^ ERROR expected a type, found a trait +//~| HELP you can add the `dyn` keyword if you want a trait object //~| HELP alternatively use a blanket implementation to implement `LocalTraitOne` for all types that also implement `fmt::Display + Send` impl GenericTrait for LocalTraitOne {} -//~^ ERROR trait objects must include the `dyn` keyword -//~| HELP add `dyn` keyword before this trait +//~^ ERROR expected a type, found a trait +//~| HELP you can add the `dyn` keyword if you want a trait object //~| HELP alternatively use a blanket implementation to implement `GenericTrait` for all types that also implement `LocalTraitOne` trait GenericTraitTwo {} impl GenericTraitTwo for GenericTrait {} -//~^ ERROR trait objects must include the `dyn` keyword -//~| HELP add `dyn` keyword before this trait +//~^ ERROR expected a type, found a trait +//~| HELP you can add the `dyn` keyword if you want a trait object //~| HELP alternatively use a blanket implementation to implement `GenericTraitTwo` for all types that also implement `GenericTrait` fn main() {} diff --git a/tests/ui/suggestions/suggest-blanket-impl-local-trait.stderr b/tests/ui/suggestions/suggest-blanket-impl-local-trait.stderr index 769f3bd64f320..102438e1ec506 100644 --- a/tests/ui/suggestions/suggest-blanket-impl-local-trait.stderr +++ b/tests/ui/suggestions/suggest-blanket-impl-local-trait.stderr @@ -1,10 +1,10 @@ -error[E0782]: trait objects must include the `dyn` keyword +error[E0782]: expected a type, found a trait --> $DIR/suggest-blanket-impl-local-trait.rs:34:24 | LL | impl LocalTraitOne for fmt::Display {} | ^^^^^^^^^^^^ | -help: add `dyn` keyword before this trait +help: you can add the `dyn` keyword if you want a trait object | LL | impl LocalTraitOne for dyn fmt::Display {} | +++ @@ -13,13 +13,13 @@ help: alternatively use a blanket implementation to implement `LocalTraitOne` fo LL | impl LocalTraitOne for T {} | +++++++++++++++++ ~ -error[E0782]: trait objects must include the `dyn` keyword +error[E0782]: expected a type, found a trait --> $DIR/suggest-blanket-impl-local-trait.rs:40:24 | LL | impl LocalTraitOne for fmt::Display + Send {} | ^^^^^^^^^^^^^^^^^^^ | -help: add `dyn` keyword before this trait +help: you can add the `dyn` keyword if you want a trait object | LL | impl LocalTraitOne for dyn fmt::Display + Send {} | +++ @@ -28,13 +28,13 @@ help: alternatively use a blanket implementation to implement `LocalTraitOne` fo LL | impl LocalTraitOne for T {} | ++++++++++++++++++++++++ ~ -error[E0782]: trait objects must include the `dyn` keyword +error[E0782]: expected a type, found a trait --> $DIR/suggest-blanket-impl-local-trait.rs:13:24 | LL | impl LocalTraitTwo for LocalTraitOne {} | ^^^^^^^^^^^^^ | -help: add `dyn` keyword before this trait +help: you can add the `dyn` keyword if you want a trait object | LL | impl LocalTraitTwo for dyn LocalTraitOne {} | +++ @@ -43,13 +43,13 @@ help: alternatively use a blanket implementation to implement `LocalTraitTwo` fo LL | impl LocalTraitTwo for T {} | ++++++++++++++++++ ~ -error[E0782]: trait objects must include the `dyn` keyword +error[E0782]: expected a type, found a trait --> $DIR/suggest-blanket-impl-local-trait.rs:46:29 | LL | impl GenericTrait for LocalTraitOne {} | ^^^^^^^^^^^^^ | -help: add `dyn` keyword before this trait +help: you can add the `dyn` keyword if you want a trait object | LL | impl GenericTrait for dyn LocalTraitOne {} | +++ @@ -58,35 +58,35 @@ help: alternatively use a blanket implementation to implement `GenericTrait` LL | impl GenericTrait for T {} | ++++++++++++++++++ ~ -error[E0782]: trait objects must include the `dyn` keyword +error[E0782]: expected a type, found a trait --> $DIR/suggest-blanket-impl-local-trait.rs:18:23 | LL | impl fmt::Display for LocalTraitOne { | ^^^^^^^^^^^^^ | -help: add `dyn` keyword before this trait +help: you can add the `dyn` keyword if you want a trait object | LL | impl fmt::Display for dyn LocalTraitOne { | +++ -error[E0782]: trait objects must include the `dyn` keyword +error[E0782]: expected a type, found a trait --> $DIR/suggest-blanket-impl-local-trait.rs:26:23 | LL | impl fmt::Display for LocalTraitTwo + Send { | ^^^^^^^^^^^^^^^^^^^^ | -help: add `dyn` keyword before this trait +help: you can add the `dyn` keyword if you want a trait object | LL | impl fmt::Display for dyn LocalTraitTwo + Send { | +++ -error[E0782]: trait objects must include the `dyn` keyword +error[E0782]: expected a type, found a trait --> $DIR/suggest-blanket-impl-local-trait.rs:53:35 | LL | impl GenericTraitTwo for GenericTrait {} | ^^^^^^^^^^^^^^^ | -help: add `dyn` keyword before this trait +help: you can add the `dyn` keyword if you want a trait object | LL | impl GenericTraitTwo for dyn GenericTrait {} | +++ diff --git a/tests/ui/suggestions/suggest-swapping-self-ty-and-trait-edition-2021.rs b/tests/ui/suggestions/suggest-swapping-self-ty-and-trait-edition-2021.rs index a5ab8be7f45a7..fe36d09343005 100644 --- a/tests/ui/suggestions/suggest-swapping-self-ty-and-trait-edition-2021.rs +++ b/tests/ui/suggestions/suggest-swapping-self-ty-and-trait-edition-2021.rs @@ -14,14 +14,14 @@ pub union Union { impl<'a, T> Struct for Trait<'a, T> {} //~^ ERROR expected trait, found struct `Struct` -//~| ERROR trait objects must include the `dyn` keyword +//~| ERROR expected a type, found a trait impl<'a, T> Enum for Trait<'a, T> {} //~^ ERROR expected trait, found enum `Enum` -//~| ERROR trait objects must include the `dyn` keyword +//~| ERROR expected a type, found a trait impl<'a, T> Union for Trait<'a, T> {} //~^ ERROR expected trait, found union `Union` -//~| ERROR trait objects must include the `dyn` keyword +//~| ERROR expected a type, found a trait fn main() {} diff --git a/tests/ui/suggestions/suggest-swapping-self-ty-and-trait-edition-2021.stderr b/tests/ui/suggestions/suggest-swapping-self-ty-and-trait-edition-2021.stderr index 2893370570d24..0bd601e217034 100644 --- a/tests/ui/suggestions/suggest-swapping-self-ty-and-trait-edition-2021.stderr +++ b/tests/ui/suggestions/suggest-swapping-self-ty-and-trait-edition-2021.stderr @@ -58,35 +58,35 @@ LL | pub union Union { = help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData` = help: if you intended `T` to be a const parameter, use `const T: /* Type */` instead -error[E0782]: trait objects must include the `dyn` keyword +error[E0782]: expected a type, found a trait --> $DIR/suggest-swapping-self-ty-and-trait-edition-2021.rs:15:27 | LL | impl<'a, T> Struct for Trait<'a, T> {} | ^^^^^^^^^^^^ | -help: add `dyn` keyword before this trait +help: you can add the `dyn` keyword if you want a trait object | LL | impl<'a, T> Struct for dyn Trait<'a, T> {} | +++ -error[E0782]: trait objects must include the `dyn` keyword +error[E0782]: expected a type, found a trait --> $DIR/suggest-swapping-self-ty-and-trait-edition-2021.rs:19:25 | LL | impl<'a, T> Enum for Trait<'a, T> {} | ^^^^^^^^^^^^ | -help: add `dyn` keyword before this trait +help: you can add the `dyn` keyword if you want a trait object | LL | impl<'a, T> Enum for dyn Trait<'a, T> {} | +++ -error[E0782]: trait objects must include the `dyn` keyword +error[E0782]: expected a type, found a trait --> $DIR/suggest-swapping-self-ty-and-trait-edition-2021.rs:23:26 | LL | impl<'a, T> Union for Trait<'a, T> {} | ^^^^^^^^^^^^ | -help: add `dyn` keyword before this trait +help: you can add the `dyn` keyword if you want a trait object | LL | impl<'a, T> Union for dyn Trait<'a, T> {} | +++ diff --git a/tests/ui/traits/bound/not-on-bare-trait-2021.rs b/tests/ui/traits/bound/not-on-bare-trait-2021.rs index 07b866cb4a65b..93d2f04b54e56 100644 --- a/tests/ui/traits/bound/not-on-bare-trait-2021.rs +++ b/tests/ui/traits/bound/not-on-bare-trait-2021.rs @@ -6,13 +6,11 @@ trait Foo { // This should emit the less confusing error, not the more confusing one. fn foo(_x: Foo + Send) { - //~^ ERROR trait objects must include the `dyn` keyword - //~| ERROR size for values of type + //~^ ERROR expected a type, found a trait } fn bar(x: Foo) -> Foo { - //~^ ERROR trait objects must include the `dyn` keyword - //~| ERROR trait objects must include the `dyn` keyword - //~| ERROR size for values of type + //~^ ERROR expected a type, found a trait + //~| ERROR expected a type, found a trait x } diff --git a/tests/ui/traits/bound/not-on-bare-trait-2021.stderr b/tests/ui/traits/bound/not-on-bare-trait-2021.stderr index e05ae8e526713..e50186aff7e67 100644 --- a/tests/ui/traits/bound/not-on-bare-trait-2021.stderr +++ b/tests/ui/traits/bound/not-on-bare-trait-2021.stderr @@ -1,38 +1,4 @@ -error[E0277]: the size for values of type `(dyn Foo + Send + 'static)` cannot be known at compilation time - --> $DIR/not-on-bare-trait-2021.rs:8:12 - | -LL | fn foo(_x: Foo + Send) { - | ^^^^^^^^^^ doesn't have a size known at compile-time - | - = help: the trait `Sized` is not implemented for `(dyn Foo + Send + 'static)` - = help: unsized fn params are gated as an unstable feature -help: you can use `impl Trait` as the argument type - | -LL | fn foo(_x: impl Foo + Send) { - | ++++ -help: function arguments must have a statically known size, borrowed types always have a known size - | -LL | fn foo(_x: &(dyn Foo + Send)) { - | +++++ + - -error[E0277]: the size for values of type `(dyn Foo + 'static)` cannot be known at compilation time - --> $DIR/not-on-bare-trait-2021.rs:12:11 - | -LL | fn bar(x: Foo) -> Foo { - | ^^^ doesn't have a size known at compile-time - | - = help: the trait `Sized` is not implemented for `(dyn Foo + 'static)` - = help: unsized fn params are gated as an unstable feature -help: you can use `impl Trait` as the argument type - | -LL | fn bar(x: impl Foo) -> Foo { - | ++++ -help: function arguments must have a statically known size, borrowed types always have a known size - | -LL | fn bar(x: &dyn Foo) -> Foo { - | ++++ - -error[E0782]: trait objects must include the `dyn` keyword +error[E0782]: expected a type, found a trait --> $DIR/not-on-bare-trait-2021.rs:8:12 | LL | fn foo(_x: Foo + Send) { @@ -51,8 +17,8 @@ help: alternatively, use a trait object to accept any type that implements `Foo LL | fn foo(_x: &(dyn Foo + Send)) { | +++++ + -error[E0782]: trait objects must include the `dyn` keyword - --> $DIR/not-on-bare-trait-2021.rs:12:11 +error[E0782]: expected a type, found a trait + --> $DIR/not-on-bare-trait-2021.rs:11:11 | LL | fn bar(x: Foo) -> Foo { | ^^^ @@ -70,8 +36,8 @@ help: alternatively, use a trait object to accept any type that implements `Foo` LL | fn bar(x: &dyn Foo) -> Foo { | ++++ -error[E0782]: trait objects must include the `dyn` keyword - --> $DIR/not-on-bare-trait-2021.rs:12:19 +error[E0782]: expected a type, found a trait + --> $DIR/not-on-bare-trait-2021.rs:11:19 | LL | fn bar(x: Foo) -> Foo { | ^^^ @@ -85,7 +51,6 @@ help: alternatively, you can return an owned trait object LL | fn bar(x: Foo) -> Box { | +++++++ + -error: aborting due to 5 previous errors +error: aborting due to 3 previous errors -Some errors have detailed explanations: E0277, E0782. -For more information about an error, try `rustc --explain E0277`. +For more information about this error, try `rustc --explain E0782`. diff --git a/tests/ui/traits/issue-106072.rs b/tests/ui/traits/issue-106072.rs index 8adbac46a5bd8..696bd765ebc5c 100644 --- a/tests/ui/traits/issue-106072.rs +++ b/tests/ui/traits/issue-106072.rs @@ -1,6 +1,4 @@ -#[derive(Clone)] //~ trait objects must include the `dyn` keyword -//~^ ERROR: the size for values of type `(dyn Foo + 'static)` cannot be known -//~| ERROR: return type cannot have an unboxed trait object +#[derive(Clone)] //~ expected a type, found a trait struct Foo; trait Foo {} //~ the name `Foo` is defined multiple times fn main() {} diff --git a/tests/ui/traits/issue-106072.stderr b/tests/ui/traits/issue-106072.stderr index 6476c8b3237ac..4a48e4e898d31 100644 --- a/tests/ui/traits/issue-106072.stderr +++ b/tests/ui/traits/issue-106072.stderr @@ -1,5 +1,5 @@ error[E0428]: the name `Foo` is defined multiple times - --> $DIR/issue-106072.rs:5:1 + --> $DIR/issue-106072.rs:3:1 | LL | struct Foo; | ----------- previous definition of the type `Foo` here @@ -8,26 +8,7 @@ LL | trait Foo {} | = note: `Foo` must be defined only once in the type namespace of this module -error[E0277]: the size for values of type `(dyn Foo + 'static)` cannot be known at compilation time - --> $DIR/issue-106072.rs:1:10 - | -LL | #[derive(Clone)] - | ^^^^^ doesn't have a size known at compile-time - | - = help: the trait `Sized` is not implemented for `(dyn Foo + 'static)` -note: required by a bound in `Clone` - --> $SRC_DIR/core/src/clone.rs:LL:COL - = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info) - -error[E0746]: return type cannot have an unboxed trait object - --> $DIR/issue-106072.rs:1:10 - | -LL | #[derive(Clone)] - | ^^^^^ doesn't have a size known at compile-time - | - = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info) - -error[E0782]: trait objects must include the `dyn` keyword +error[E0782]: expected a type, found a trait --> $DIR/issue-106072.rs:1:10 | LL | #[derive(Clone)] @@ -35,7 +16,7 @@ LL | #[derive(Clone)] | = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to 4 previous errors +error: aborting due to 2 previous errors -Some errors have detailed explanations: E0277, E0428, E0746, E0782. -For more information about an error, try `rustc --explain E0277`. +Some errors have detailed explanations: E0428, E0782. +For more information about an error, try `rustc --explain E0428`. diff --git a/tests/ui/traits/missing-for-type-in-impl.e2021.stderr b/tests/ui/traits/missing-for-type-in-impl.e2021.stderr index b5a607a54cb54..a49c5d9d45b7b 100644 --- a/tests/ui/traits/missing-for-type-in-impl.e2021.stderr +++ b/tests/ui/traits/missing-for-type-in-impl.e2021.stderr @@ -10,13 +10,13 @@ help: this trait has no implementations, consider adding one LL | trait Foo { | ^^^^^^^^^^^^ -error[E0782]: trait objects must include the `dyn` keyword +error[E0782]: expected a type, found a trait --> $DIR/missing-for-type-in-impl.rs:8:6 | LL | impl Foo { | ^^^^^^^^ | -help: add `dyn` keyword before this trait +help: you can add the `dyn` keyword if you want a trait object | LL | impl dyn Foo { | +++ diff --git a/tests/ui/traits/missing-for-type-in-impl.rs b/tests/ui/traits/missing-for-type-in-impl.rs index 7d4ad479e773c..e5dd365160984 100644 --- a/tests/ui/traits/missing-for-type-in-impl.rs +++ b/tests/ui/traits/missing-for-type-in-impl.rs @@ -6,7 +6,7 @@ trait Foo { /* note the "missing" for ... (in this case for i64, in order for this to compile) */ impl Foo { -//[e2021]~^ ERROR trait objects must include the `dyn` keyword +//[e2021]~^ ERROR expected a type, found a trait //[e2015]~^^ WARNING trait objects without an explicit `dyn` are deprecated //[e2015]~| WARNING trait objects without an explicit `dyn` are deprecated //[e2015]~| WARNING this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! From 181e667626c7b4174555b8b400b989d0cfc06599 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 5 Oct 2024 13:20:22 +0200 Subject: [PATCH 2119/2194] stabilize duration_consts_float --- library/core/src/lib.rs | 1 - library/core/src/time.rs | 12 ++++++------ library/core/tests/lib.rs | 1 - 3 files changed, 6 insertions(+), 8 deletions(-) diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index e323e88f26141..5b75273087d4d 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -156,7 +156,6 @@ #![feature(const_unicode_case_lookup)] #![feature(coverage_attribute)] #![feature(do_not_recommend)] -#![feature(duration_consts_float)] #![feature(internal_impls_macro)] #![feature(ip)] #![feature(is_ascii_octdigit)] diff --git a/library/core/src/time.rs b/library/core/src/time.rs index 65560dfcf9d2d..a997874dd9c7b 100644 --- a/library/core/src/time.rs +++ b/library/core/src/time.rs @@ -847,7 +847,7 @@ impl Duration { #[stable(feature = "duration_float", since = "1.38.0")] #[must_use] #[inline] - #[rustc_const_unstable(feature = "duration_consts_float", issue = "72440")] + #[rustc_const_stable(feature = "duration_consts_float", since = "CURRENT_RUSTC_VERSION")] pub const fn as_secs_f64(&self) -> f64 { (self.secs as f64) + (self.nanos.0 as f64) / (NANOS_PER_SEC as f64) } @@ -866,7 +866,7 @@ impl Duration { #[stable(feature = "duration_float", since = "1.38.0")] #[must_use] #[inline] - #[rustc_const_unstable(feature = "duration_consts_float", issue = "72440")] + #[rustc_const_stable(feature = "duration_consts_float", since = "CURRENT_RUSTC_VERSION")] pub const fn as_secs_f32(&self) -> f32 { (self.secs as f32) + (self.nanos.0 as f32) / (NANOS_PER_SEC as f32) } @@ -886,7 +886,7 @@ impl Duration { #[unstable(feature = "duration_millis_float", issue = "122451")] #[must_use] #[inline] - #[rustc_const_unstable(feature = "duration_consts_float", issue = "72440")] + #[rustc_const_unstable(feature = "duration_millis_float", issue = "122451")] pub const fn as_millis_f64(&self) -> f64 { (self.secs as f64) * (MILLIS_PER_SEC as f64) + (self.nanos.0 as f64) / (NANOS_PER_MILLI as f64) @@ -907,7 +907,7 @@ impl Duration { #[unstable(feature = "duration_millis_float", issue = "122451")] #[must_use] #[inline] - #[rustc_const_unstable(feature = "duration_consts_float", issue = "72440")] + #[rustc_const_unstable(feature = "duration_millis_float", issue = "122451")] pub const fn as_millis_f32(&self) -> f32 { (self.secs as f32) * (MILLIS_PER_SEC as f32) + (self.nanos.0 as f32) / (NANOS_PER_MILLI as f32) @@ -1087,7 +1087,7 @@ impl Duration { #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] - #[rustc_const_unstable(feature = "duration_consts_float", issue = "72440")] + #[rustc_const_stable(feature = "duration_consts_float", since = "CURRENT_RUSTC_VERSION")] pub const fn div_duration_f64(self, rhs: Duration) -> f64 { let self_nanos = (self.secs as f64) * (NANOS_PER_SEC as f64) + (self.nanos.0 as f64); let rhs_nanos = (rhs.secs as f64) * (NANOS_PER_SEC as f64) + (rhs.nanos.0 as f64); @@ -1108,7 +1108,7 @@ impl Duration { #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] - #[rustc_const_unstable(feature = "duration_consts_float", issue = "72440")] + #[rustc_const_stable(feature = "duration_consts_float", since = "CURRENT_RUSTC_VERSION")] pub const fn div_duration_f32(self, rhs: Duration) -> f32 { let self_nanos = (self.secs as f32) * (NANOS_PER_SEC as f32) + (self.nanos.0 as f32); let rhs_nanos = (rhs.secs as f32) * (NANOS_PER_SEC as f32) + (rhs.nanos.0 as f32); diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs index 196e91ee3e926..e2d3d86f632cb 100644 --- a/library/core/tests/lib.rs +++ b/library/core/tests/lib.rs @@ -42,7 +42,6 @@ #![feature(dec2flt)] #![feature(duration_constants)] #![feature(duration_constructors)] -#![feature(duration_consts_float)] #![feature(error_generic_member_access)] #![feature(exact_size_is_empty)] #![feature(extern_types)] From 19345d5c6ec522e6037c76c52fccd83860515313 Mon Sep 17 00:00:00 2001 From: Augie Fackler Date: Fri, 11 Oct 2024 11:29:37 -0400 Subject: [PATCH 2120/2194] RustWrapper: adapt for rename of Intrinsic::getDeclaration llvm/llvm-project@fa789dffb1e12c2aece0187aeacc48dfb1768340 renamed getDeclaration to getOrInsertDeclaration. @rustbot label: +llvm-main --- .../rustc_llvm/llvm-wrapper/RustWrapper.cpp | 25 ++++++++++++++----- 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp index 8faa521240830..72b03fa0560e6 100644 --- a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp @@ -1533,27 +1533,40 @@ extern "C" LLVMValueRef LLVMRustBuildCall(LLVMBuilderRef B, LLVMTypeRef Ty, extern "C" LLVMValueRef LLVMRustGetInstrProfIncrementIntrinsic(LLVMModuleRef M) { +#if LLVM_VERSION_GE(20, 0) + return wrap(llvm::Intrinsic::getOrInsertDeclaration( + unwrap(M), llvm::Intrinsic::instrprof_increment)); +#else return wrap(llvm::Intrinsic::getDeclaration( unwrap(M), llvm::Intrinsic::instrprof_increment)); +#endif } extern "C" LLVMValueRef LLVMRustGetInstrProfMCDCParametersIntrinsic(LLVMModuleRef M) { -#if LLVM_VERSION_GE(19, 0) - return wrap(llvm::Intrinsic::getDeclaration( +#if LLVM_VERSION_LT(19, 0) + report_fatal_error("LLVM 19.0 is required for mcdc intrinsic functions"); +#endif +#if LLVM_VERSION_GE(20, 0) + return wrap(llvm::Intrinsic::getOrInsertDeclaration( unwrap(M), llvm::Intrinsic::instrprof_mcdc_parameters)); #else - report_fatal_error("LLVM 19.0 is required for mcdc intrinsic functions"); + return wrap(llvm::Intrinsic::getDeclaration( + unwrap(M), llvm::Intrinsic::instrprof_mcdc_parameters)); #endif } extern "C" LLVMValueRef LLVMRustGetInstrProfMCDCTVBitmapUpdateIntrinsic(LLVMModuleRef M) { -#if LLVM_VERSION_GE(19, 0) - return wrap(llvm::Intrinsic::getDeclaration( +#if LLVM_VERSION_LT(19, 0) + report_fatal_error("LLVM 19.0 is required for mcdc intrinsic functions"); +#endif +#if LLVM_VERSION_GE(20, 0) + return wrap(llvm::Intrinsic::getOrInsertDeclaration( unwrap(M), llvm::Intrinsic::instrprof_mcdc_tvbitmap_update)); #else - report_fatal_error("LLVM 19.0 is required for mcdc intrinsic functions"); + return wrap(llvm::Intrinsic::getDeclaration( + unwrap(M), llvm::Intrinsic::instrprof_mcdc_tvbitmap_update)); #endif } From 92f65684a8433ade29d8fea8c258dd7eed22ea3f Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 5 Oct 2024 13:04:18 +0200 Subject: [PATCH 2121/2194] stabilize const_result --- library/core/src/result.rs | 13 +++++++++---- library/core/tests/lib.rs | 1 - 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/library/core/src/result.rs b/library/core/src/result.rs index 610edae48d36b..95faacbf96db7 100644 --- a/library/core/src/result.rs +++ b/library/core/src/result.rs @@ -734,7 +734,8 @@ impl Result { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_unstable(feature = "const_result", issue = "82814")] + #[rustc_const_stable(feature = "const_result", since = "CURRENT_RUSTC_VERSION")] + #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] pub const fn as_mut(&mut self) -> Result<&mut T, &mut E> { match *self { Ok(ref mut x) => Ok(x), @@ -1536,7 +1537,8 @@ impl Result<&T, E> { /// ``` #[inline] #[stable(feature = "result_copied", since = "1.59.0")] - #[rustc_const_unstable(feature = "const_result", issue = "82814")] + #[rustc_const_stable(feature = "const_result", since = "CURRENT_RUSTC_VERSION")] + #[rustc_allow_const_fn_unstable(const_precise_live_drops)] pub const fn copied(self) -> Result where T: Copy, @@ -1586,7 +1588,9 @@ impl Result<&mut T, E> { /// ``` #[inline] #[stable(feature = "result_copied", since = "1.59.0")] - #[rustc_const_unstable(feature = "const_result", issue = "82814")] + #[rustc_const_stable(feature = "const_result", since = "CURRENT_RUSTC_VERSION")] + #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] + #[rustc_allow_const_fn_unstable(const_precise_live_drops)] pub const fn copied(self) -> Result where T: Copy, @@ -1639,7 +1643,8 @@ impl Result, E> { /// ``` #[inline] #[stable(feature = "transpose_result", since = "1.33.0")] - #[rustc_const_unstable(feature = "const_result", issue = "82814")] + #[rustc_const_stable(feature = "const_result", since = "CURRENT_RUSTC_VERSION")] + #[rustc_allow_const_fn_unstable(const_precise_live_drops)] pub const fn transpose(self) -> Option> { match self { Ok(Some(x)) => Some(Ok(x)), diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs index 0d4ec96f8426f..d5f7010343e8f 100644 --- a/library/core/tests/lib.rs +++ b/library/core/tests/lib.rs @@ -29,7 +29,6 @@ #![feature(const_pin)] #![feature(const_pointer_is_aligned)] #![feature(const_ptr_write)] -#![feature(const_result)] #![feature(const_three_way_compare)] #![feature(const_trait_impl)] #![feature(core_intrinsics)] From 77b3065ed242c497af14afdf18467cf6b8b44b1e Mon Sep 17 00:00:00 2001 From: Urgau Date: Fri, 11 Oct 2024 21:21:32 +0200 Subject: [PATCH 2122/2194] Remove deprecation note in the `non_local_definitions` warning --- compiler/rustc_lint/messages.ftl | 2 -- compiler/rustc_lint/src/lints.rs | 3 --- .../rustdoc-ui/doctest/non-local-defs-impl.stdout | 1 - tests/rustdoc-ui/doctest/non_local_defs.stderr | 1 - tests/ui/lint/non-local-defs/cargo-update.stderr | 1 - tests/ui/lint/non-local-defs/consts.stderr | 9 --------- .../ui/lint/non-local-defs/exhaustive-trait.stderr | 6 ------ tests/ui/lint/non-local-defs/exhaustive.stderr | 14 -------------- .../non-local-defs/from-local-for-global.stderr | 1 - tests/ui/lint/non-local-defs/generics.stderr | 3 --- .../lint/non-local-defs/inside-macro_rules.stderr | 1 - tests/ui/lint/non-local-defs/macro_rules.stderr | 4 ---- tests/ui/lint/non-local-defs/weird-exprs.stderr | 6 ------ tests/ui/proc-macro/nested-macro-rules.stderr | 1 - 14 files changed, 53 deletions(-) diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl index e733e92c7cb33..c4d709aa1f985 100644 --- a/compiler/rustc_lint/messages.ftl +++ b/compiler/rustc_lint/messages.ftl @@ -581,8 +581,6 @@ lint_non_glob_import_type_ir_inherent = non-glob import of `rustc_type_ir::inher lint_non_local_definitions_cargo_update = the {$macro_kind} `{$macro_name}` may come from an old version of the `{$crate_name}` crate, try updating your dependency with `cargo update -p {$crate_name}` -lint_non_local_definitions_deprecation = this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue - lint_non_local_definitions_impl = non-local `impl` definition, `impl` blocks should be written at the same level as their item .non_local = an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` .doctest = make this doc-test a standalone test with its own `fn main() {"{"} ... {"}"}` diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index 87afeca0b28f6..16cfae17d4020 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -1430,8 +1430,6 @@ impl<'a> LintDiagnostic<'a, ()> for NonLocalDefinitionsDiag { ); } } - - diag.note(fluent::lint_non_local_definitions_deprecation); } NonLocalDefinitionsDiag::MacroRules { depth, @@ -1452,7 +1450,6 @@ impl<'a> LintDiagnostic<'a, ()> for NonLocalDefinitionsDiag { } diag.note(fluent::lint_non_local); - diag.note(fluent::lint_non_local_definitions_deprecation); if let Some(cargo_update) = cargo_update { diag.subdiagnostic(cargo_update); diff --git a/tests/rustdoc-ui/doctest/non-local-defs-impl.stdout b/tests/rustdoc-ui/doctest/non-local-defs-impl.stdout index f39d2c2608b88..c1f750017e703 100644 --- a/tests/rustdoc-ui/doctest/non-local-defs-impl.stdout +++ b/tests/rustdoc-ui/doctest/non-local-defs-impl.stdout @@ -18,7 +18,6 @@ LL | impl Trait for &Local {} | `Trait` is not local | = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` - = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue note: the lint level is defined here --> $DIR/non-local-defs-impl.rs:11:9 | diff --git a/tests/rustdoc-ui/doctest/non_local_defs.stderr b/tests/rustdoc-ui/doctest/non_local_defs.stderr index 2b47e6b5bc4d5..e39dc4d5ee048 100644 --- a/tests/rustdoc-ui/doctest/non_local_defs.stderr +++ b/tests/rustdoc-ui/doctest/non_local_defs.stderr @@ -6,7 +6,6 @@ LL | macro_rules! a_macro { () => {} } | = help: remove the `#[macro_export]` or make this doc-test a standalone test with its own `fn main() { ... }` = note: a `macro_rules!` definition is non-local if it is nested inside an item and has a `#[macro_export]` attribute - = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue = note: `#[warn(non_local_definitions)]` on by default warning: 1 warning emitted diff --git a/tests/ui/lint/non-local-defs/cargo-update.stderr b/tests/ui/lint/non-local-defs/cargo-update.stderr index 77ee28b48cc7f..d579fa391fc28 100644 --- a/tests/ui/lint/non-local-defs/cargo-update.stderr +++ b/tests/ui/lint/non-local-defs/cargo-update.stderr @@ -12,7 +12,6 @@ LL | non_local_macro::non_local_impl!(LocalStruct); = note: the macro `non_local_macro::non_local_impl` may come from an old version of the `non_local_macro` crate, try updating your dependency with `cargo update -p non_local_macro` = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` = note: items in an anonymous const item (`const _: () = { ... }`) are treated as in the same scope as the anonymous const's declaration for the purpose of this lint - = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue = note: `#[warn(non_local_definitions)]` on by default = note: this warning originates in the macro `non_local_macro::non_local_impl` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui/lint/non-local-defs/consts.stderr b/tests/ui/lint/non-local-defs/consts.stderr index 4bf50bae5eac1..20fb4a6432e4e 100644 --- a/tests/ui/lint/non-local-defs/consts.stderr +++ b/tests/ui/lint/non-local-defs/consts.stderr @@ -15,7 +15,6 @@ LL | impl Uto for &Test {} | = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` = note: items in an anonymous const item (`const _: () = { ... }`) are treated as in the same scope as the anonymous const's declaration for the purpose of this lint - = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue = note: `#[warn(non_local_definitions)]` on by default warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item @@ -31,7 +30,6 @@ LL | impl Uto2 for Test {} | = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` = note: items in an anonymous const item (`const _: () = { ... }`) are treated as in the same scope as the anonymous const's declaration for the purpose of this lint - = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item --> $DIR/consts.rs:32:5 @@ -46,7 +44,6 @@ LL | impl Uto3 for Test {} | = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` = note: items in an anonymous const item (`const _: () = { ... }`) are treated as in the same scope as the anonymous const's declaration for the purpose of this lint - = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item --> $DIR/consts.rs:43:5 @@ -59,7 +56,6 @@ LL | impl Test { | `Test` is not local | = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` - = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item --> $DIR/consts.rs:50:9 @@ -78,7 +74,6 @@ LL | | }; | |_____- move the `impl` block outside of this inline constant `` and up 2 bodies | = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` - = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item --> $DIR/consts.rs:59:9 @@ -92,7 +87,6 @@ LL | impl Test { | = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` = note: items in an anonymous const item (`const _: () = { ... }`) are treated as in the same scope as the anonymous const's declaration for the purpose of this lint - = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item --> $DIR/consts.rs:69:13 @@ -106,7 +100,6 @@ LL | impl Test {} | = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` = note: items in an anonymous const item (`const _: () = { ... }`) are treated as in the same scope as the anonymous const's declaration for the purpose of this lint - = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item --> $DIR/consts.rs:79:9 @@ -120,7 +113,6 @@ LL | impl Uto9 for Test {} | `Uto9` is not local | = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` - = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item --> $DIR/consts.rs:86:9 @@ -138,7 +130,6 @@ LL | | }]; | |_____- move the `impl` block outside of this constant expression `` and up 2 bodies | = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` - = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: 9 warnings emitted diff --git a/tests/ui/lint/non-local-defs/exhaustive-trait.stderr b/tests/ui/lint/non-local-defs/exhaustive-trait.stderr index c58ec12aaacaa..83e46df185de2 100644 --- a/tests/ui/lint/non-local-defs/exhaustive-trait.stderr +++ b/tests/ui/lint/non-local-defs/exhaustive-trait.stderr @@ -10,7 +10,6 @@ LL | impl PartialEq<()> for Dog { | `PartialEq` is not local | = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` - = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue = note: `#[warn(non_local_definitions)]` on by default warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item @@ -26,7 +25,6 @@ LL | impl PartialEq<()> for &Dog { | `PartialEq` is not local | = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` - = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item --> $DIR/exhaustive-trait.rs:21:5 @@ -41,7 +39,6 @@ LL | impl PartialEq for () { | `PartialEq` is not local | = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` - = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item --> $DIR/exhaustive-trait.rs:28:5 @@ -56,7 +53,6 @@ LL | impl PartialEq<&Dog> for () { | `PartialEq` is not local | = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` - = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item --> $DIR/exhaustive-trait.rs:35:5 @@ -72,7 +68,6 @@ LL | impl PartialEq for &Dog { | `PartialEq` is not local | = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` - = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item --> $DIR/exhaustive-trait.rs:42:5 @@ -88,7 +83,6 @@ LL | impl PartialEq<&Dog> for &Dog { | `PartialEq` is not local | = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` - = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: 6 warnings emitted diff --git a/tests/ui/lint/non-local-defs/exhaustive.stderr b/tests/ui/lint/non-local-defs/exhaustive.stderr index dd41b2206d842..1e6fc910621f6 100644 --- a/tests/ui/lint/non-local-defs/exhaustive.stderr +++ b/tests/ui/lint/non-local-defs/exhaustive.stderr @@ -9,7 +9,6 @@ LL | impl Test { | `Test` is not local | = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` - = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue = note: `#[warn(non_local_definitions)]` on by default warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item @@ -25,7 +24,6 @@ LL | impl Display for Test { | `Display` is not local | = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` - = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item --> $DIR/exhaustive.rs:22:5 @@ -39,7 +37,6 @@ LL | impl dyn Trait {} | `Trait` is not local | = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` - = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item --> $DIR/exhaustive.rs:25:5 @@ -54,7 +51,6 @@ LL | impl Trait for Vec { } | `Trait` is not local | = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` - = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item --> $DIR/exhaustive.rs:28:5 @@ -69,7 +65,6 @@ LL | impl Trait for &dyn Trait {} | `Trait` is not local | = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` - = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item --> $DIR/exhaustive.rs:31:5 @@ -84,7 +79,6 @@ LL | impl Trait for *mut Test {} | `Trait` is not local | = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` - = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item --> $DIR/exhaustive.rs:34:5 @@ -99,7 +93,6 @@ LL | impl Trait for *mut [Test] {} | `Trait` is not local | = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` - = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item --> $DIR/exhaustive.rs:37:5 @@ -114,7 +107,6 @@ LL | impl Trait for [Test; 8] {} | `Trait` is not local | = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` - = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item --> $DIR/exhaustive.rs:40:5 @@ -129,7 +121,6 @@ LL | impl Trait for (Test,) {} | `Trait` is not local | = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` - = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item --> $DIR/exhaustive.rs:43:5 @@ -144,7 +135,6 @@ LL | impl Trait for fn(Test) -> () {} | `Trait` is not local | = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` - = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item --> $DIR/exhaustive.rs:46:5 @@ -159,7 +149,6 @@ LL | impl Trait for fn() -> Test {} | `Trait` is not local | = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` - = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item --> $DIR/exhaustive.rs:50:9 @@ -173,7 +162,6 @@ LL | impl Trait for Test {} | `Trait` is not local | = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` - = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item --> $DIR/exhaustive.rs:67:9 @@ -187,7 +175,6 @@ LL | impl Display for InsideMain { | `Display` is not local | = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` - = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item --> $DIR/exhaustive.rs:74:9 @@ -201,7 +188,6 @@ LL | impl InsideMain { | `InsideMain` is not local | = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` - = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: 14 warnings emitted diff --git a/tests/ui/lint/non-local-defs/from-local-for-global.stderr b/tests/ui/lint/non-local-defs/from-local-for-global.stderr index 6839ebd2c8a3e..f173c054e786f 100644 --- a/tests/ui/lint/non-local-defs/from-local-for-global.stderr +++ b/tests/ui/lint/non-local-defs/from-local-for-global.stderr @@ -10,7 +10,6 @@ LL | impl From for () { | `From` is not local | = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` - = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue = note: `#[warn(non_local_definitions)]` on by default warning: 1 warning emitted diff --git a/tests/ui/lint/non-local-defs/generics.stderr b/tests/ui/lint/non-local-defs/generics.stderr index aefe8921fe2c7..66769cc1e0b8a 100644 --- a/tests/ui/lint/non-local-defs/generics.stderr +++ b/tests/ui/lint/non-local-defs/generics.stderr @@ -11,7 +11,6 @@ LL | impl Global for Vec { } | `Global` is not local | = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` - = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue = note: `#[warn(non_local_definitions)]` on by default warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item @@ -27,7 +26,6 @@ LL | impl Uto7 for Test where Local: std::any::Any {} | `Uto7` is not local | = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` - = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item --> $DIR/generics.rs:23:5 @@ -41,7 +39,6 @@ LL | impl Uto8 for T {} | `Uto8` is not local | = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` - = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: 3 warnings emitted diff --git a/tests/ui/lint/non-local-defs/inside-macro_rules.stderr b/tests/ui/lint/non-local-defs/inside-macro_rules.stderr index faab6aea2b318..b6fe1a921d756 100644 --- a/tests/ui/lint/non-local-defs/inside-macro_rules.stderr +++ b/tests/ui/lint/non-local-defs/inside-macro_rules.stderr @@ -14,7 +14,6 @@ LL | m!(); | = note: the macro `m` defines the non-local `impl`, and may need to be changed = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` - = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue = note: `#[warn(non_local_definitions)]` on by default = note: this warning originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui/lint/non-local-defs/macro_rules.stderr b/tests/ui/lint/non-local-defs/macro_rules.stderr index 4e86fc7b987e6..28779a7806641 100644 --- a/tests/ui/lint/non-local-defs/macro_rules.stderr +++ b/tests/ui/lint/non-local-defs/macro_rules.stderr @@ -6,7 +6,6 @@ LL | macro_rules! m0 { () => { } }; | = help: remove the `#[macro_export]` or move this `macro_rules!` outside the of the current constant `B` = note: a `macro_rules!` definition is non-local if it is nested inside an item and has a `#[macro_export]` attribute - = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue = note: `#[warn(non_local_definitions)]` on by default warning: non-local `macro_rules!` definition, `#[macro_export]` macro should be written at top level module @@ -17,7 +16,6 @@ LL | non_local_macro::non_local_macro_rules!(my_macro); | = help: remove the `#[macro_export]` or move this `macro_rules!` outside the of the current constant `_MACRO_EXPORT` = note: a `macro_rules!` definition is non-local if it is nested inside an item and has a `#[macro_export]` attribute - = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue = note: the macro `non_local_macro::non_local_macro_rules` may come from an old version of the `non_local_macro` crate, try updating your dependency with `cargo update -p non_local_macro` = note: this warning originates in the macro `non_local_macro::non_local_macro_rules` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -29,7 +27,6 @@ LL | macro_rules! m { () => { } }; | = help: remove the `#[macro_export]` or move this `macro_rules!` outside the of the current function `main` = note: a `macro_rules!` definition is non-local if it is nested inside an item and has a `#[macro_export]` attribute - = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `macro_rules!` definition, `#[macro_export]` macro should be written at top level module --> $DIR/macro_rules.rs:29:13 @@ -39,7 +36,6 @@ LL | macro_rules! m2 { () => { } }; | = help: remove the `#[macro_export]` or move this `macro_rules!` outside the of the current associated function `bar` and up 2 bodies = note: a `macro_rules!` definition is non-local if it is nested inside an item and has a `#[macro_export]` attribute - = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: 4 warnings emitted diff --git a/tests/ui/lint/non-local-defs/weird-exprs.stderr b/tests/ui/lint/non-local-defs/weird-exprs.stderr index f6ce063929e8f..ec3517140ef2e 100644 --- a/tests/ui/lint/non-local-defs/weird-exprs.stderr +++ b/tests/ui/lint/non-local-defs/weird-exprs.stderr @@ -14,7 +14,6 @@ LL | | }]; | |_- move the `impl` block outside of this constant expression `` | = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` - = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue = note: `#[warn(non_local_definitions)]` on by default warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item @@ -33,7 +32,6 @@ LL | | } | |_____- move the `impl` block outside of this constant expression `` | = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` - = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item --> $DIR/weird-exprs.rs:25:9 @@ -52,7 +50,6 @@ LL | | }]; | |_____- move the `impl` block outside of this constant expression `` and up 2 bodies | = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` - = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item --> $DIR/weird-exprs.rs:34:9 @@ -70,7 +67,6 @@ LL | | }]; | |_____- move the `impl` block outside of this constant expression `` and up 2 bodies | = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` - = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item --> $DIR/weird-exprs.rs:41:9 @@ -88,7 +84,6 @@ LL | | }]) {} | |_____- move the `impl` block outside of this constant expression `` and up 2 bodies | = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` - = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item --> $DIR/weird-exprs.rs:48:9 @@ -107,7 +102,6 @@ LL | | }] { todo!() } | |_____- move the `impl` block outside of this constant expression `` and up 2 bodies | = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` - = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: 6 warnings emitted diff --git a/tests/ui/proc-macro/nested-macro-rules.stderr b/tests/ui/proc-macro/nested-macro-rules.stderr index 8fe041d61b81e..439297d87ca5d 100644 --- a/tests/ui/proc-macro/nested-macro-rules.stderr +++ b/tests/ui/proc-macro/nested-macro-rules.stderr @@ -19,7 +19,6 @@ LL | nested_macro_rules::outer_macro!(SecondStruct, SecondAttrStruct); | = help: remove the `#[macro_export]` or move this `macro_rules!` outside the of the current function `main` = note: a `macro_rules!` definition is non-local if it is nested inside an item and has a `#[macro_export]` attribute - = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue note: the lint level is defined here --> $DIR/nested-macro-rules.rs:8:9 | From 0d8a978e8a55b08778ec6ee861c2c5ed6703eb6c Mon Sep 17 00:00:00 2001 From: Jed Brown Date: Fri, 5 Jan 2024 21:04:41 -0700 Subject: [PATCH 2123/2194] intrinsics.fmuladdf{16,32,64,128}: expose llvm.fmuladd.* semantics Add intrinsics `fmuladd{f16,f32,f64,f128}`. This computes `(a * b) + c`, to be fused if the code generator determines that (i) the target instruction set has support for a fused operation, and (ii) that the fused operation is more efficient than the equivalent, separate pair of `mul` and `add` instructions. https://llvm.org/docs/LangRef.html#llvm-fmuladd-intrinsic MIRI support is included for f32 and f64. The codegen_cranelift uses the `fma` function from libc, which is a correct implementation, but without the desired performance semantic. I think this requires an update to cranelift to expose a suitable instruction in its IR. I have not tested with codegen_gcc, but it should behave the same way (using `fma` from libc). --- .../src/intrinsics/mod.rs | 5 +- .../rustc_codegen_gcc/src/intrinsic/mod.rs | 3 ++ compiler/rustc_codegen_llvm/src/context.rs | 5 ++ compiler/rustc_codegen_llvm/src/intrinsic.rs | 5 ++ .../rustc_hir_analysis/src/check/intrinsic.rs | 13 +++++ compiler/rustc_span/src/symbol.rs | 4 ++ library/core/src/intrinsics.rs | 53 +++++++++++++++++++ src/tools/miri/src/intrinsics/mod.rs | 31 +++++++++++ src/tools/miri/tests/pass/float.rs | 18 +++++++ .../intrinsics/fmuladd_nondeterministic.rs | 44 +++++++++++++++ tests/ui/intrinsics/intrinsic-fmuladd.rs | 42 +++++++++++++++ 11 files changed, 222 insertions(+), 1 deletion(-) create mode 100644 src/tools/miri/tests/pass/intrinsics/fmuladd_nondeterministic.rs create mode 100644 tests/ui/intrinsics/intrinsic-fmuladd.rs diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs index 19e5adc253854..35f0ccff3f99e 100644 --- a/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs +++ b/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs @@ -328,6 +328,9 @@ fn codegen_float_intrinsic_call<'tcx>( sym::fabsf64 => ("fabs", 1, fx.tcx.types.f64, types::F64), sym::fmaf32 => ("fmaf", 3, fx.tcx.types.f32, types::F32), sym::fmaf64 => ("fma", 3, fx.tcx.types.f64, types::F64), + // FIXME: calling `fma` from libc without FMA target feature uses expensive sofware emulation + sym::fmuladdf32 => ("fmaf", 3, fx.tcx.types.f32, types::F32), // TODO: use cranelift intrinsic analogous to llvm.fmuladd.f32 + sym::fmuladdf64 => ("fma", 3, fx.tcx.types.f64, types::F64), // TODO: use cranelift intrinsic analogous to llvm.fmuladd.f64 sym::copysignf32 => ("copysignf", 2, fx.tcx.types.f32, types::F32), sym::copysignf64 => ("copysign", 2, fx.tcx.types.f64, types::F64), sym::floorf32 => ("floorf", 1, fx.tcx.types.f32, types::F32), @@ -381,7 +384,7 @@ fn codegen_float_intrinsic_call<'tcx>( let layout = fx.layout_of(ty); let res = match intrinsic { - sym::fmaf32 | sym::fmaf64 => { + sym::fmaf32 | sym::fmaf64 | sym::fmuladdf32 | sym::fmuladdf64 => { CValue::by_val(fx.bcx.ins().fma(args[0], args[1], args[2]), layout) } sym::copysignf32 | sym::copysignf64 => { diff --git a/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs b/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs index 945eedf555667..972d66321403d 100644 --- a/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs +++ b/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs @@ -66,6 +66,9 @@ fn get_simple_intrinsic<'gcc, 'tcx>( sym::log2f64 => "log2", sym::fmaf32 => "fmaf", sym::fmaf64 => "fma", + // FIXME: calling `fma` from libc without FMA target feature uses expensive sofware emulation + sym::fmuladdf32 => "fmaf", // TODO: use gcc intrinsic analogous to llvm.fmuladd.f32 + sym::fmuladdf64 => "fma", // TODO: use gcc intrinsic analogous to llvm.fmuladd.f64 sym::fabsf32 => "fabsf", sym::fabsf64 => "fabs", sym::minnumf32 => "fminf", diff --git a/compiler/rustc_codegen_llvm/src/context.rs b/compiler/rustc_codegen_llvm/src/context.rs index 0a116971e0783..c836dd5473f3c 100644 --- a/compiler/rustc_codegen_llvm/src/context.rs +++ b/compiler/rustc_codegen_llvm/src/context.rs @@ -884,6 +884,11 @@ impl<'ll> CodegenCx<'ll, '_> { ifn!("llvm.fma.f64", fn(t_f64, t_f64, t_f64) -> t_f64); ifn!("llvm.fma.f128", fn(t_f128, t_f128, t_f128) -> t_f128); + ifn!("llvm.fmuladd.f16", fn(t_f16, t_f16, t_f16) -> t_f16); + ifn!("llvm.fmuladd.f32", fn(t_f32, t_f32, t_f32) -> t_f32); + ifn!("llvm.fmuladd.f64", fn(t_f64, t_f64, t_f64) -> t_f64); + ifn!("llvm.fmuladd.f128", fn(t_f128, t_f128, t_f128) -> t_f128); + ifn!("llvm.fabs.f16", fn(t_f16) -> t_f16); ifn!("llvm.fabs.f32", fn(t_f32) -> t_f32); ifn!("llvm.fabs.f64", fn(t_f64) -> t_f64); diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs index 30c6f08e894b7..bfe623e7fc354 100644 --- a/compiler/rustc_codegen_llvm/src/intrinsic.rs +++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs @@ -86,6 +86,11 @@ fn get_simple_intrinsic<'ll>( sym::fmaf64 => "llvm.fma.f64", sym::fmaf128 => "llvm.fma.f128", + sym::fmuladdf16 => "llvm.fmuladd.f16", + sym::fmuladdf32 => "llvm.fmuladd.f32", + sym::fmuladdf64 => "llvm.fmuladd.f64", + sym::fmuladdf128 => "llvm.fmuladd.f128", + sym::fabsf16 => "llvm.fabs.f16", sym::fabsf32 => "llvm.fabs.f32", sym::fabsf64 => "llvm.fabs.f64", diff --git a/compiler/rustc_hir_analysis/src/check/intrinsic.rs b/compiler/rustc_hir_analysis/src/check/intrinsic.rs index 25e219ef3f23a..06317a3b3049c 100644 --- a/compiler/rustc_hir_analysis/src/check/intrinsic.rs +++ b/compiler/rustc_hir_analysis/src/check/intrinsic.rs @@ -357,6 +357,19 @@ pub fn check_intrinsic_type( (0, 0, vec![tcx.types.f128, tcx.types.f128, tcx.types.f128], tcx.types.f128) } + sym::fmuladdf16 => { + (0, 0, vec![tcx.types.f16, tcx.types.f16, tcx.types.f16], tcx.types.f16) + } + sym::fmuladdf32 => { + (0, 0, vec![tcx.types.f32, tcx.types.f32, tcx.types.f32], tcx.types.f32) + } + sym::fmuladdf64 => { + (0, 0, vec![tcx.types.f64, tcx.types.f64, tcx.types.f64], tcx.types.f64) + } + sym::fmuladdf128 => { + (0, 0, vec![tcx.types.f128, tcx.types.f128, tcx.types.f128], tcx.types.f128) + } + sym::fabsf16 => (0, 0, vec![tcx.types.f16], tcx.types.f16), sym::fabsf32 => (0, 0, vec![tcx.types.f32], tcx.types.f32), sym::fabsf64 => (0, 0, vec![tcx.types.f64], tcx.types.f64), diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 8e0009695db69..cc3bda99a117b 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -914,6 +914,10 @@ symbols! { fmt_debug, fmul_algebraic, fmul_fast, + fmuladdf128, + fmuladdf16, + fmuladdf32, + fmuladdf64, fn_align, fn_delegation, fn_must_use, diff --git a/library/core/src/intrinsics.rs b/library/core/src/intrinsics.rs index d7a2f1909cabe..061fba9a1f785 100644 --- a/library/core/src/intrinsics.rs +++ b/library/core/src/intrinsics.rs @@ -1795,6 +1795,59 @@ extern "rust-intrinsic" { #[rustc_nounwind] pub fn fmaf128(a: f128, b: f128, c: f128) -> f128; + /// Returns `a * b + c` for `f16` values, non-deterministically executing + /// either a fused multiply-add or two operations with rounding of the + /// intermediate result. + /// + /// The operation is fused if the code generator determines that target + /// instruction set has support for a fused operation, and that the fused + /// operation is more efficient than the equivalent, separate pair of mul + /// and add instructions. It is unspecified whether or not a fused operation + /// is selected, and that may depend on optimization level and context, for + /// example. + #[rustc_nounwind] + #[cfg(not(bootstrap))] + pub fn fmuladdf16(a: f16, b: f16, c: f16) -> f16; + /// Returns `a * b + c` for `f32` values, non-deterministically executing + /// either a fused multiply-add or two operations with rounding of the + /// intermediate result. + /// + /// The operation is fused if the code generator determines that target + /// instruction set has support for a fused operation, and that the fused + /// operation is more efficient than the equivalent, separate pair of mul + /// and add instructions. It is unspecified whether or not a fused operation + /// is selected, and that may depend on optimization level and context, for + /// example. + #[rustc_nounwind] + #[cfg(not(bootstrap))] + pub fn fmuladdf32(a: f32, b: f32, c: f32) -> f32; + /// Returns `a * b + c` for `f64` values, non-deterministically executing + /// either a fused multiply-add or two operations with rounding of the + /// intermediate result. + /// + /// The operation is fused if the code generator determines that target + /// instruction set has support for a fused operation, and that the fused + /// operation is more efficient than the equivalent, separate pair of mul + /// and add instructions. It is unspecified whether or not a fused operation + /// is selected, and that may depend on optimization level and context, for + /// example. + #[rustc_nounwind] + #[cfg(not(bootstrap))] + pub fn fmuladdf64(a: f64, b: f64, c: f64) -> f64; + /// Returns `a * b + c` for `f128` values, non-deterministically executing + /// either a fused multiply-add or two operations with rounding of the + /// intermediate result. + /// + /// The operation is fused if the code generator determines that target + /// instruction set has support for a fused operation, and that the fused + /// operation is more efficient than the equivalent, separate pair of mul + /// and add instructions. It is unspecified whether or not a fused operation + /// is selected, and that may depend on optimization level and context, for + /// example. + #[rustc_nounwind] + #[cfg(not(bootstrap))] + pub fn fmuladdf128(a: f128, b: f128, c: f128) -> f128; + /// Returns the absolute value of an `f16`. /// /// The stabilized version of this intrinsic is diff --git a/src/tools/miri/src/intrinsics/mod.rs b/src/tools/miri/src/intrinsics/mod.rs index 665dd7c441a55..9f772cfa982d8 100644 --- a/src/tools/miri/src/intrinsics/mod.rs +++ b/src/tools/miri/src/intrinsics/mod.rs @@ -295,6 +295,37 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { this.write_scalar(res, dest)?; } + "fmuladdf32" => { + let [a, b, c] = check_arg_count(args)?; + let a = this.read_scalar(a)?.to_f32()?; + let b = this.read_scalar(b)?.to_f32()?; + let c = this.read_scalar(c)?.to_f32()?; + let fuse: bool = this.machine.rng.get_mut().gen(); + let res = if fuse { + // FIXME: Using host floats, to work around https://github.com/rust-lang/rustc_apfloat/issues/11 + a.to_host().mul_add(b.to_host(), c.to_host()).to_soft() + } else { + ((a * b).value + c).value + }; + let res = this.adjust_nan(res, &[a, b, c]); + this.write_scalar(res, dest)?; + } + "fmuladdf64" => { + let [a, b, c] = check_arg_count(args)?; + let a = this.read_scalar(a)?.to_f64()?; + let b = this.read_scalar(b)?.to_f64()?; + let c = this.read_scalar(c)?.to_f64()?; + let fuse: bool = this.machine.rng.get_mut().gen(); + let res = if fuse { + // FIXME: Using host floats, to work around https://github.com/rust-lang/rustc_apfloat/issues/11 + a.to_host().mul_add(b.to_host(), c.to_host()).to_soft() + } else { + ((a * b).value + c).value + }; + let res = this.adjust_nan(res, &[a, b, c]); + this.write_scalar(res, dest)?; + } + "powf32" => { let [f1, f2] = check_arg_count(args)?; let f1 = this.read_scalar(f1)?.to_f32()?; diff --git a/src/tools/miri/tests/pass/float.rs b/src/tools/miri/tests/pass/float.rs index 6ab18a5345ea2..853d3e80517da 100644 --- a/src/tools/miri/tests/pass/float.rs +++ b/src/tools/miri/tests/pass/float.rs @@ -30,6 +30,7 @@ fn main() { libm(); test_fast(); test_algebraic(); + test_fmuladd(); } trait Float: Copy + PartialEq + Debug { @@ -1041,3 +1042,20 @@ fn test_algebraic() { test_operations_f32(11., 2.); test_operations_f32(10., 15.); } + +fn test_fmuladd() { + use std::intrinsics::{fmuladdf32, fmuladdf64}; + + #[inline(never)] + pub fn test_operations_f32(a: f32, b: f32, c: f32) { + assert_approx_eq!(unsafe { fmuladdf32(a, b, c) }, a * b + c); + } + + #[inline(never)] + pub fn test_operations_f64(a: f64, b: f64, c: f64) { + assert_approx_eq!(unsafe { fmuladdf64(a, b, c) }, a * b + c); + } + + test_operations_f32(0.1, 0.2, 0.3); + test_operations_f64(1.1, 1.2, 1.3); +} diff --git a/src/tools/miri/tests/pass/intrinsics/fmuladd_nondeterministic.rs b/src/tools/miri/tests/pass/intrinsics/fmuladd_nondeterministic.rs new file mode 100644 index 0000000000000..b46cf1ddf65df --- /dev/null +++ b/src/tools/miri/tests/pass/intrinsics/fmuladd_nondeterministic.rs @@ -0,0 +1,44 @@ +#![feature(core_intrinsics)] +use std::intrinsics::{fmuladdf32, fmuladdf64}; + +fn main() { + let mut saw_zero = false; + let mut saw_nonzero = false; + for _ in 0..50 { + let a = std::hint::black_box(0.1_f64); + let b = std::hint::black_box(0.2); + let c = std::hint::black_box(-a * b); + // It is unspecified whether the following operation is fused or not. The + // following evaluates to 0.0 if unfused, and nonzero (-1.66e-18) if fused. + let x = unsafe { fmuladdf64(a, b, c) }; + if x == 0.0 { + saw_zero = true; + } else { + saw_nonzero = true; + } + } + assert!( + saw_zero && saw_nonzero, + "`fmuladdf64` failed to be evaluated as both fused and unfused" + ); + + let mut saw_zero = false; + let mut saw_nonzero = false; + for _ in 0..50 { + let a = std::hint::black_box(0.1_f32); + let b = std::hint::black_box(0.2); + let c = std::hint::black_box(-a * b); + // It is unspecified whether the following operation is fused or not. The + // following evaluates to 0.0 if unfused, and nonzero (-8.1956386e-10) if fused. + let x = unsafe { fmuladdf32(a, b, c) }; + if x == 0.0 { + saw_zero = true; + } else { + saw_nonzero = true; + } + } + assert!( + saw_zero && saw_nonzero, + "`fmuladdf32` failed to be evaluated as both fused and unfused" + ); +} diff --git a/tests/ui/intrinsics/intrinsic-fmuladd.rs b/tests/ui/intrinsics/intrinsic-fmuladd.rs new file mode 100644 index 0000000000000..d03297884f791 --- /dev/null +++ b/tests/ui/intrinsics/intrinsic-fmuladd.rs @@ -0,0 +1,42 @@ +//@ run-pass +#![feature(core_intrinsics)] + +use std::intrinsics::*; + +macro_rules! assert_approx_eq { + ($a:expr, $b:expr) => {{ + let (a, b) = (&$a, &$b); + assert!((*a - *b).abs() < 1.0e-6, "{} is not approximately equal to {}", *a, *b); + }}; +} + +fn main() { + unsafe { + let nan: f32 = f32::NAN; + let inf: f32 = f32::INFINITY; + let neg_inf: f32 = f32::NEG_INFINITY; + assert_approx_eq!(fmuladdf32(1.23, 4.5, 0.67), 6.205); + assert_approx_eq!(fmuladdf32(-1.23, -4.5, -0.67), 4.865); + assert_approx_eq!(fmuladdf32(0.0, 8.9, 1.2), 1.2); + assert_approx_eq!(fmuladdf32(3.4, -0.0, 5.6), 5.6); + assert!(fmuladdf32(nan, 7.8, 9.0).is_nan()); + assert_eq!(fmuladdf32(inf, 7.8, 9.0), inf); + assert_eq!(fmuladdf32(neg_inf, 7.8, 9.0), neg_inf); + assert_eq!(fmuladdf32(8.9, inf, 3.2), inf); + assert_eq!(fmuladdf32(-3.2, 2.4, neg_inf), neg_inf); + } + unsafe { + let nan: f64 = f64::NAN; + let inf: f64 = f64::INFINITY; + let neg_inf: f64 = f64::NEG_INFINITY; + assert_approx_eq!(fmuladdf64(1.23, 4.5, 0.67), 6.205); + assert_approx_eq!(fmuladdf64(-1.23, -4.5, -0.67), 4.865); + assert_approx_eq!(fmuladdf64(0.0, 8.9, 1.2), 1.2); + assert_approx_eq!(fmuladdf64(3.4, -0.0, 5.6), 5.6); + assert!(fmuladdf64(nan, 7.8, 9.0).is_nan()); + assert_eq!(fmuladdf64(inf, 7.8, 9.0), inf); + assert_eq!(fmuladdf64(neg_inf, 7.8, 9.0), neg_inf); + assert_eq!(fmuladdf64(8.9, inf, 3.2), inf); + assert_eq!(fmuladdf64(-3.2, 2.4, neg_inf), neg_inf); + } +} From 395b0787d454a21638ae94e7799fcefdb4591696 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Sat, 17 Aug 2024 17:04:29 +1000 Subject: [PATCH 2124/2194] Flatten redundant test module `run_make_support::diff::tests::tests` --- src/tools/run-make-support/src/diff/tests.rs | 66 +++++++++----------- 1 file changed, 30 insertions(+), 36 deletions(-) diff --git a/src/tools/run-make-support/src/diff/tests.rs b/src/tools/run-make-support/src/diff/tests.rs index 286548bef618f..c629519690ee2 100644 --- a/src/tools/run-make-support/src/diff/tests.rs +++ b/src/tools/run-make-support/src/diff/tests.rs @@ -1,28 +1,23 @@ -#[cfg(test)] -mod tests { - use crate::*; - - #[test] - fn test_diff() { - let expected = "foo\nbar\nbaz\n"; - let actual = "foo\nbar\nbaz\n"; +use crate::*; + +#[test] +fn test_diff() { + let expected = "foo\nbar\nbaz\n"; + let actual = "foo\nbar\nbaz\n"; + diff().expected_text("EXPECTED_TEXT", expected).actual_text("ACTUAL_TEXT", actual).run(); +} + +#[test] +fn test_should_panic() { + let expected = "foo\nbar\nbaz\n"; + let actual = "foo\nbaz\nbar\n"; + + let output = std::panic::catch_unwind(|| { diff().expected_text("EXPECTED_TEXT", expected).actual_text("ACTUAL_TEXT", actual).run(); - } - - #[test] - fn test_should_panic() { - let expected = "foo\nbar\nbaz\n"; - let actual = "foo\nbaz\nbar\n"; - - let output = std::panic::catch_unwind(|| { - diff() - .expected_text("EXPECTED_TEXT", expected) - .actual_text("ACTUAL_TEXT", actual) - .run(); - }) - .unwrap_err(); - - let expected_output = "\ + }) + .unwrap_err(); + + let expected_output = "\ test failed: `EXPECTED_TEXT` is different from `ACTUAL_TEXT` --- EXPECTED_TEXT @@ -34,28 +29,27 @@ test failed: `EXPECTED_TEXT` is different from `ACTUAL_TEXT` -baz "; - assert_eq!(output.downcast_ref::().unwrap(), expected_output); - } + assert_eq!(output.downcast_ref::().unwrap(), expected_output); +} - #[test] - fn test_normalize() { - let expected = " +#[test] +fn test_normalize() { + let expected = " running 2 tests .. test result: ok. 2 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME "; - let actual = " + let actual = " running 2 tests .. test result: ok. 2 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.02s "; - diff() - .expected_text("EXPECTED_TEXT", expected) - .actual_text("ACTUAL_TEXT", actual) - .normalize(r#"finished in \d+\.\d+s"#, "finished in $$TIME") - .run(); - } + diff() + .expected_text("EXPECTED_TEXT", expected) + .actual_text("ACTUAL_TEXT", actual) + .normalize(r#"finished in \d+\.\d+s"#, "finished in $$TIME") + .run(); } From f4376c426b9315472d09c15daed72efbce0342b9 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Sat, 12 Oct 2024 11:59:57 +1100 Subject: [PATCH 2125/2194] Avoid cross-file glob import --- src/tools/run-make-support/src/diff/tests.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/run-make-support/src/diff/tests.rs b/src/tools/run-make-support/src/diff/tests.rs index c629519690ee2..6096560ca52a0 100644 --- a/src/tools/run-make-support/src/diff/tests.rs +++ b/src/tools/run-make-support/src/diff/tests.rs @@ -1,4 +1,4 @@ -use crate::*; +use crate::diff; #[test] fn test_diff() { From 1e8d6d1ec3cad6bc7d88c0a8a993f69835e8422f Mon Sep 17 00:00:00 2001 From: surechen Date: Fri, 11 Oct 2024 20:27:46 +0800 Subject: [PATCH 2126/2194] Make unused_parens's suggestion considering expr's attributes For the expr with attributes, like `let _ = (#[inline] || println!("Hello!"));`, the suggestion's span should contains the attributes, or the suggestion will remove them. fixes #129833 --- compiler/rustc_lint/src/unused.rs | 10 +++++- ...or-stmt-expr-attributes-issue-129833.fixed | 15 +++++++++ ...s-for-stmt-expr-attributes-issue-129833.rs | 15 +++++++++ ...r-stmt-expr-attributes-issue-129833.stderr | 31 +++++++++++++++++++ 4 files changed, 70 insertions(+), 1 deletion(-) create mode 100644 tests/ui/lint/unused/unused-parens-for-stmt-expr-attributes-issue-129833.fixed create mode 100644 tests/ui/lint/unused/unused-parens-for-stmt-expr-attributes-issue-129833.rs create mode 100644 tests/ui/lint/unused/unused-parens-for-stmt-expr-attributes-issue-129833.stderr diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs index 12d5b5cf97938..1a00725096148 100644 --- a/compiler/rustc_lint/src/unused.rs +++ b/compiler/rustc_lint/src/unused.rs @@ -804,7 +804,15 @@ trait UnusedDelimLint { .find_ancestor_inside(value.span) .map(|span| (value.span.with_hi(span.lo()), value.span.with_lo(span.hi()))), ast::ExprKind::Paren(ref expr) => { - expr.span.find_ancestor_inside(value.span).map(|expr_span| { + // For the expr with attributes, like `let _ = (#[inline] || println!("Hello!"));`, + // the span should contains the attributes, or the suggestion will remove them. + let expr_span_with_attrs = + if let Some(attr_lo) = expr.attrs.iter().map(|attr| attr.span.lo()).min() { + expr.span.with_lo(attr_lo) + } else { + expr.span + }; + expr_span_with_attrs.find_ancestor_inside(value.span).map(|expr_span| { (value.span.with_hi(expr_span.lo()), value.span.with_lo(expr_span.hi())) }) } diff --git a/tests/ui/lint/unused/unused-parens-for-stmt-expr-attributes-issue-129833.fixed b/tests/ui/lint/unused/unused-parens-for-stmt-expr-attributes-issue-129833.fixed new file mode 100644 index 0000000000000..8287b3d3ac785 --- /dev/null +++ b/tests/ui/lint/unused/unused-parens-for-stmt-expr-attributes-issue-129833.fixed @@ -0,0 +1,15 @@ +//@ run-rustfix +// Check the `unused_parens` suggestion for paren_expr with attributes. +// The suggestion should retain attributes in the front. + +#![feature(stmt_expr_attributes)] +#![deny(unused_parens)] + +pub fn foo() -> impl Fn() { + let _ = #[inline] #[allow(dead_code)] || println!("Hello!"); //~ERROR unnecessary parentheses + #[inline] #[allow(dead_code)] || println!("Hello!") //~ERROR unnecessary parentheses +} + +fn main() { + let _ = foo(); +} diff --git a/tests/ui/lint/unused/unused-parens-for-stmt-expr-attributes-issue-129833.rs b/tests/ui/lint/unused/unused-parens-for-stmt-expr-attributes-issue-129833.rs new file mode 100644 index 0000000000000..0b6edae30e70d --- /dev/null +++ b/tests/ui/lint/unused/unused-parens-for-stmt-expr-attributes-issue-129833.rs @@ -0,0 +1,15 @@ +//@ run-rustfix +// Check the `unused_parens` suggestion for paren_expr with attributes. +// The suggestion should retain attributes in the front. + +#![feature(stmt_expr_attributes)] +#![deny(unused_parens)] + +pub fn foo() -> impl Fn() { + let _ = (#[inline] #[allow(dead_code)] || println!("Hello!")); //~ERROR unnecessary parentheses + (#[inline] #[allow(dead_code)] || println!("Hello!")) //~ERROR unnecessary parentheses +} + +fn main() { + let _ = foo(); +} diff --git a/tests/ui/lint/unused/unused-parens-for-stmt-expr-attributes-issue-129833.stderr b/tests/ui/lint/unused/unused-parens-for-stmt-expr-attributes-issue-129833.stderr new file mode 100644 index 0000000000000..65513553f7e81 --- /dev/null +++ b/tests/ui/lint/unused/unused-parens-for-stmt-expr-attributes-issue-129833.stderr @@ -0,0 +1,31 @@ +error: unnecessary parentheses around assigned value + --> $DIR/unused-parens-for-stmt-expr-attributes-issue-129833.rs:9:13 + | +LL | let _ = (#[inline] #[allow(dead_code)] || println!("Hello!")); + | ^ ^ + | +note: the lint level is defined here + --> $DIR/unused-parens-for-stmt-expr-attributes-issue-129833.rs:6:9 + | +LL | #![deny(unused_parens)] + | ^^^^^^^^^^^^^ +help: remove these parentheses + | +LL - let _ = (#[inline] #[allow(dead_code)] || println!("Hello!")); +LL + let _ = #[inline] #[allow(dead_code)] || println!("Hello!"); + | + +error: unnecessary parentheses around block return value + --> $DIR/unused-parens-for-stmt-expr-attributes-issue-129833.rs:10:5 + | +LL | (#[inline] #[allow(dead_code)] || println!("Hello!")) + | ^ ^ + | +help: remove these parentheses + | +LL - (#[inline] #[allow(dead_code)] || println!("Hello!")) +LL + #[inline] #[allow(dead_code)] || println!("Hello!") + | + +error: aborting due to 2 previous errors + From 1fe079bd62e68d94d5eff51cea94014a7e3c4625 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=AE=B8=E6=9D=B0=E5=8F=8B=20Jieyou=20Xu=20=28Joe=29?= <39484203+jieyouxu@users.noreply.github.com> Date: Sat, 12 Oct 2024 09:41:42 +0800 Subject: [PATCH 2127/2194] Remap path refix in the panic message Otherwise `error-pattern` on the test run stderr can incorrectly match if e.g. the paths in panic backtrace has a matching substring (like if we look for `bar` in the error pattern but username is `baron`). --- tests/ui/meta/revision-bad.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/ui/meta/revision-bad.rs b/tests/ui/meta/revision-bad.rs index c5193b19d9e4a..0af5624ff9c59 100644 --- a/tests/ui/meta/revision-bad.rs +++ b/tests/ui/meta/revision-bad.rs @@ -5,6 +5,7 @@ //@ revisions: foo bar //@ should-fail //@ needs-run-enabled +//@ compile-flags: --remap-path-prefix={{src-base}}=remapped //@[foo] error-pattern:bar //@[bar] error-pattern:foo From 33ac202904e7820268b71b3280a7d2590378e3b9 Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Thu, 10 Oct 2024 09:38:57 +0300 Subject: [PATCH 2128/2194] force "HEAD" for non-CI and `git_upstream_merge_base` for CI environment When rust-lang/rust is configured as remote, some of the git logic (for tracking changed files) that uses get_closest_merge_commit starts to produce annoying results as the upstream branch becomes outdated quickly (since it isn't updated with git pull). We can rely on HEAD for non-CI environments as we specifically treat bors commits as merge commits, which also exist on upstream. As for CI environments, we should use `git_upstream_merge_base` to correctly track modified files as bors commits may be in `HEAD` but not yet on the upstream remote. Signed-off-by: onur-ozkan --- src/tools/build_helper/src/git.rs | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/src/tools/build_helper/src/git.rs b/src/tools/build_helper/src/git.rs index 10c5476cd8f3b..cac5a990a732e 100644 --- a/src/tools/build_helper/src/git.rs +++ b/src/tools/build_helper/src/git.rs @@ -1,6 +1,8 @@ use std::path::{Path, PathBuf}; use std::process::{Command, Stdio}; +use crate::ci::CiEnv; + pub struct GitConfig<'a> { pub git_repository: &'a str, pub nightly_branch: &'a str, @@ -114,8 +116,8 @@ fn git_upstream_merge_base( /// Searches for the nearest merge commit in the repository that also exists upstream. /// -/// If it fails to find the upstream remote, it then looks for the most recent commit made -/// by the merge bot by matching the author's email address with the merge bot's email. +/// It looks for the most recent commit made by the merge bot by matching the author's email +/// address with the merge bot's email. pub fn get_closest_merge_commit( git_dir: Option<&Path>, config: &GitConfig<'_>, @@ -127,7 +129,15 @@ pub fn get_closest_merge_commit( git.current_dir(git_dir); } - let merge_base = git_upstream_merge_base(config, git_dir).unwrap_or_else(|_| "HEAD".into()); + let merge_base = { + if CiEnv::is_ci() { + git_upstream_merge_base(config, git_dir).unwrap() + } else { + // For non-CI environments, ignore rust-lang/rust upstream as it usually gets + // outdated very quickly. + "HEAD".to_string() + } + }; git.args([ "rev-list", From 4454fa998c9da1f1eee1602c8e8cd2732505c104 Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Sat, 12 Oct 2024 07:41:39 +0300 Subject: [PATCH 2129/2194] add new CI step: "setup upstream remote" Signed-off-by: onur-ozkan --- .github/workflows/ci.yml | 3 +++ src/ci/scripts/setup-upstream-remote.sh | 24 ++++++++++++++++++++++++ src/ci/shared.sh | 12 ++++++++++++ 3 files changed, 39 insertions(+) create mode 100755 src/ci/scripts/setup-upstream-remote.sh diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b6dc27f123465..003c1e5d7ebbe 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -122,6 +122,9 @@ jobs: # which then uses log commands to actually set them. EXTRA_VARIABLES: ${{ toJson(matrix.env) }} + - name: setup upstream remote + run: src/ci/scripts/setup-upstream-remote.sh + - name: ensure the channel matches the target branch run: src/ci/scripts/verify-channel.sh diff --git a/src/ci/scripts/setup-upstream-remote.sh b/src/ci/scripts/setup-upstream-remote.sh new file mode 100755 index 0000000000000..52b4c98a89016 --- /dev/null +++ b/src/ci/scripts/setup-upstream-remote.sh @@ -0,0 +1,24 @@ +#!/bin/bash +# In CI environments, bootstrap is forced to use the remote upstream based +# on "git_repository" and "nightly_branch" values from src/stage0 file. +# This script configures the remote as it may not exist by default. + +set -euo pipefail +IFS=$'\n\t' + +ci_dir=$(cd $(dirname $0) && pwd)/.. +source "$ci_dir/shared.sh" + +git_repository=$(parse_stage0_file_by_key "git_repository") +nightly_branch=$(parse_stage0_file_by_key "nightly_branch") + +# Configure "rust-lang/rust" upstream remote only when it's not origin. +if [ -z "$(git config remote.origin.url | grep $git_repository)" ]; then + echo "Configuring https://github.com/$git_repository remote as upstream." + git remote add upstream "https://github.com/$git_repository" + REMOTE_NAME="upstream" +else + REMOTE_NAME="origin" +fi + +git fetch $REMOTE_NAME $nightly_branch diff --git a/src/ci/shared.sh b/src/ci/shared.sh index 2b0a10e4d08d9..1e6a008a5de81 100644 --- a/src/ci/shared.sh +++ b/src/ci/shared.sh @@ -136,3 +136,15 @@ function releaseChannel { echo $RUST_CI_OVERRIDE_RELEASE_CHANNEL fi } + +# Parse values from src/stage0 file by key +function parse_stage0_file_by_key { + local key="$1" + local file="$ci_dir/../stage0" + local value=$(awk -F= '{a[$1]=$2} END {print(a["'$key'"])}' $file) + if [ -z "$value" ]; then + echo "ERROR: Key '$key' not found in '$file'." + exit 1 + fi + echo "$value" +} From 9a523001e3c245f8f547720a176005cf5bdee4f0 Mon Sep 17 00:00:00 2001 From: Jubilee Young Date: Thu, 26 Sep 2024 10:36:59 -0700 Subject: [PATCH 2130/2194] library: Stabilize `const_intrinsic_forget` This is an implicit requirement of stabilizing `const_ptr_write`. Const-stabilizes the internal `core::intrinsics`: - `forget` --- library/core/src/intrinsics.rs | 2 +- library/core/src/lib.rs | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/library/core/src/intrinsics.rs b/library/core/src/intrinsics.rs index d7a2f1909cabe..3be0765443253 100644 --- a/library/core/src/intrinsics.rs +++ b/library/core/src/intrinsics.rs @@ -1084,7 +1084,7 @@ extern "rust-intrinsic" { /// it does not require an `unsafe` block. /// Therefore, implementations must not require the user to uphold /// any safety invariants. - #[rustc_const_unstable(feature = "const_intrinsic_forget", issue = "none")] + #[rustc_const_stable(feature = "const_intrinsic_forget", since = "CURRENT_RUSTC_VERSION")] #[rustc_safe_intrinsic] #[rustc_nounwind] pub fn forget(_: T); diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index f68f19ec6a469..3eacf7261a556 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -124,7 +124,6 @@ #![feature(const_hash)] #![feature(const_heap)] #![feature(const_index_range_slice_index)] -#![feature(const_intrinsic_forget)] #![feature(const_ipv4)] #![feature(const_ipv6)] #![feature(const_likely)] From ddc367ded70b3145ffa92216bb4aaf178233c4ee Mon Sep 17 00:00:00 2001 From: Jubilee Young Date: Thu, 26 Sep 2024 09:30:17 -0700 Subject: [PATCH 2131/2194] library: Stabilize `const_ptr_write` Const-stabilizes: - `write` - `write_bytes` - `write_unaligned` In the following paths: - `core::ptr` - `core::ptr::NonNull` - pointer `<*mut T>` Const-stabilizes the internal `core::intrinsics`: - `write_bytes` - `write_via_move` --- library/alloc/src/lib.rs | 1 - library/alloc/tests/lib.rs | 1 - library/core/src/intrinsics.rs | 6 +++--- library/core/src/lib.rs | 1 - library/core/src/ptr/mod.rs | 5 +++-- library/core/src/ptr/mut_ptr.rs | 6 +++--- library/core/src/ptr/non_null.rs | 6 +++--- library/core/tests/lib.rs | 1 - tests/ui/consts/load-preserves-partial-init.rs | 1 - 9 files changed, 12 insertions(+), 16 deletions(-) diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs index c60c0743c7e12..1d7b7a034541e 100644 --- a/library/alloc/src/lib.rs +++ b/library/alloc/src/lib.rs @@ -173,7 +173,6 @@ #![feature(allow_internal_unstable)] #![feature(cfg_sanitize)] #![feature(const_precise_live_drops)] -#![feature(const_ptr_write)] #![feature(const_try)] #![feature(decl_macro)] #![feature(dropck_eyepatch)] diff --git a/library/alloc/tests/lib.rs b/library/alloc/tests/lib.rs index f43143c6cef65..4d146f1f5fd68 100644 --- a/library/alloc/tests/lib.rs +++ b/library/alloc/tests/lib.rs @@ -7,7 +7,6 @@ #![feature(const_cow_is_borrowed)] #![feature(const_heap)] #![cfg_attr(bootstrap, feature(const_mut_refs))] -#![feature(const_ptr_write)] #![feature(const_try)] #![feature(core_intrinsics)] #![feature(extract_if)] diff --git a/library/core/src/intrinsics.rs b/library/core/src/intrinsics.rs index 3be0765443253..f61b675ac4ed8 100644 --- a/library/core/src/intrinsics.rs +++ b/library/core/src/intrinsics.rs @@ -2635,7 +2635,7 @@ extern "rust-intrinsic" { /// This intrinsic can *only* be called where the pointer is a local without /// projections (`write_via_move(ptr, x)`, not `write_via_move(*ptr, x)`) so /// that it trivially obeys runtime-MIR rules about derefs in operands. - #[rustc_const_unstable(feature = "const_ptr_write", issue = "86302")] + #[rustc_const_stable(feature = "const_ptr_write", since = "CURRENT_RUSTC_VERSION")] #[rustc_nounwind] pub fn write_via_move(ptr: *mut T, value: T); @@ -3472,13 +3472,13 @@ pub const unsafe fn copy(src: *const T, dst: *mut T, count: usize) { #[doc(alias = "memset")] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_allowed_through_unstable_modules] -#[rustc_const_unstable(feature = "const_ptr_write", issue = "86302")] +#[rustc_const_stable(feature = "const_ptr_write", since = "CURRENT_RUSTC_VERSION")] #[inline(always)] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces #[rustc_diagnostic_item = "ptr_write_bytes"] pub const unsafe fn write_bytes(dst: *mut T, val: u8, count: usize) { extern "rust-intrinsic" { - #[rustc_const_unstable(feature = "const_ptr_write", issue = "86302")] + #[rustc_const_stable(feature = "const_ptr_write", since = "CURRENT_RUSTC_VERSION")] #[rustc_nounwind] fn write_bytes(dst: *mut T, val: u8, count: usize); } diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index 3eacf7261a556..97df6ccfa5e02 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -137,7 +137,6 @@ #![feature(const_pointer_is_aligned)] #![feature(const_ptr_is_null)] #![feature(const_ptr_sub_ptr)] -#![feature(const_ptr_write)] #![feature(const_raw_ptr_comparison)] #![feature(const_replace)] #![feature(const_size_of_val)] diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs index 67f1b0cd16de4..6f076caf533d3 100644 --- a/library/core/src/ptr/mod.rs +++ b/library/core/src/ptr/mod.rs @@ -1611,7 +1611,7 @@ pub const unsafe fn read_unaligned(src: *const T) -> T { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] -#[rustc_const_unstable(feature = "const_ptr_write", issue = "86302")] +#[rustc_const_stable(feature = "const_ptr_write", since = "CURRENT_RUSTC_VERSION")] #[rustc_diagnostic_item = "ptr_write"] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub const unsafe fn write(dst: *mut T, src: T) { @@ -1719,7 +1719,8 @@ pub const unsafe fn write(dst: *mut T, src: T) { /// ``` #[inline] #[stable(feature = "ptr_unaligned", since = "1.17.0")] -#[rustc_const_unstable(feature = "const_ptr_write", issue = "86302")] +#[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_refs_to_cell))] +#[rustc_const_stable(feature = "const_ptr_write", since = "CURRENT_RUSTC_VERSION")] #[rustc_diagnostic_item = "ptr_write_unaligned"] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub const unsafe fn write_unaligned(dst: *mut T, src: T) { diff --git a/library/core/src/ptr/mut_ptr.rs b/library/core/src/ptr/mut_ptr.rs index e458bb4642fc6..ced6cb7d520de 100644 --- a/library/core/src/ptr/mut_ptr.rs +++ b/library/core/src/ptr/mut_ptr.rs @@ -1449,7 +1449,7 @@ impl *mut T { /// /// [`ptr::write`]: crate::ptr::write() #[stable(feature = "pointer_methods", since = "1.26.0")] - #[rustc_const_unstable(feature = "const_ptr_write", issue = "86302")] + #[rustc_const_stable(feature = "const_ptr_write", since = "CURRENT_RUSTC_VERSION")] #[inline(always)] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub const unsafe fn write(self, val: T) @@ -1468,7 +1468,7 @@ impl *mut T { /// [`ptr::write_bytes`]: crate::ptr::write_bytes() #[doc(alias = "memset")] #[stable(feature = "pointer_methods", since = "1.26.0")] - #[rustc_const_unstable(feature = "const_ptr_write", issue = "86302")] + #[rustc_const_stable(feature = "const_ptr_write", since = "CURRENT_RUSTC_VERSION")] #[inline(always)] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub const unsafe fn write_bytes(self, val: u8, count: usize) @@ -1509,7 +1509,7 @@ impl *mut T { /// /// [`ptr::write_unaligned`]: crate::ptr::write_unaligned() #[stable(feature = "pointer_methods", since = "1.26.0")] - #[rustc_const_unstable(feature = "const_ptr_write", issue = "86302")] + #[rustc_const_stable(feature = "const_ptr_write", since = "CURRENT_RUSTC_VERSION")] #[inline(always)] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub const unsafe fn write_unaligned(self, val: T) diff --git a/library/core/src/ptr/non_null.rs b/library/core/src/ptr/non_null.rs index 6c5834a1ece88..dc1a7c6220ebe 100644 --- a/library/core/src/ptr/non_null.rs +++ b/library/core/src/ptr/non_null.rs @@ -1013,7 +1013,7 @@ impl NonNull { #[inline(always)] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces #[stable(feature = "non_null_convenience", since = "1.80.0")] - #[rustc_const_unstable(feature = "const_ptr_write", issue = "86302")] + #[rustc_const_stable(feature = "const_ptr_write", since = "CURRENT_RUSTC_VERSION")] pub const unsafe fn write(self, val: T) where T: Sized, @@ -1032,7 +1032,7 @@ impl NonNull { #[doc(alias = "memset")] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces #[stable(feature = "non_null_convenience", since = "1.80.0")] - #[rustc_const_unstable(feature = "const_ptr_write", issue = "86302")] + #[rustc_const_stable(feature = "const_ptr_write", since = "CURRENT_RUSTC_VERSION")] pub const unsafe fn write_bytes(self, val: u8, count: usize) where T: Sized, @@ -1073,7 +1073,7 @@ impl NonNull { #[inline(always)] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces #[stable(feature = "non_null_convenience", since = "1.80.0")] - #[rustc_const_unstable(feature = "const_ptr_write", issue = "86302")] + #[rustc_const_stable(feature = "const_ptr_write", since = "CURRENT_RUSTC_VERSION")] pub const unsafe fn write_unaligned(self, val: T) where T: Sized, diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs index 8ee98de2a7b28..5ec1b311a50c4 100644 --- a/library/core/tests/lib.rs +++ b/library/core/tests/lib.rs @@ -28,7 +28,6 @@ #![feature(const_option_ext)] #![feature(const_pin)] #![feature(const_pointer_is_aligned)] -#![feature(const_ptr_write)] #![feature(const_three_way_compare)] #![feature(const_trait_impl)] #![feature(core_intrinsics)] diff --git a/tests/ui/consts/load-preserves-partial-init.rs b/tests/ui/consts/load-preserves-partial-init.rs index d97e9cb3d9df6..2a8adbd5e1665 100644 --- a/tests/ui/consts/load-preserves-partial-init.rs +++ b/tests/ui/consts/load-preserves-partial-init.rs @@ -1,6 +1,5 @@ //@ run-pass -#![feature(const_ptr_write)] // issue: https://github.com/rust-lang/rust/issues/69488 // Loads of partially-initialized data could produce completely-uninitialized results. // Test to make sure that we no longer do such a "deinitializing" load. From 187c8b0ce90eb3a446aa6bd838d6984764479a5a Mon Sep 17 00:00:00 2001 From: Jubilee Young Date: Thu, 26 Sep 2024 11:49:53 -0700 Subject: [PATCH 2132/2194] library: Stabilize `const_replace` Depends on stabilizing `const_ptr_write`. Const-stabilizes: - `core::mem::replace` - `core::ptr::replace` --- library/core/src/lib.rs | 1 - library/core/src/mem/mod.rs | 3 ++- library/core/src/ptr/mod.rs | 3 ++- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index 97df6ccfa5e02..d407efa069b60 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -138,7 +138,6 @@ #![feature(const_ptr_is_null)] #![feature(const_ptr_sub_ptr)] #![feature(const_raw_ptr_comparison)] -#![feature(const_replace)] #![feature(const_size_of_val)] #![feature(const_size_of_val_raw)] #![feature(const_strict_overflow_ops)] diff --git a/library/core/src/mem/mod.rs b/library/core/src/mem/mod.rs index 414262fcf5ab1..9bf2aa594c047 100644 --- a/library/core/src/mem/mod.rs +++ b/library/core/src/mem/mod.rs @@ -857,7 +857,8 @@ pub fn take(dest: &mut T) -> T { #[inline] #[stable(feature = "rust1", since = "1.0.0")] #[must_use = "if you don't need the old value, you can just assign the new value directly"] -#[rustc_const_unstable(feature = "const_replace", issue = "83164")] +#[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] +#[rustc_const_stable(feature = "const_replace", since = "CURRENT_RUSTC_VERSION")] #[cfg_attr(not(test), rustc_diagnostic_item = "mem_replace")] pub const fn replace(dest: &mut T, src: T) -> T { // It may be tempting to use `swap` to avoid `unsafe` here. Don't! diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs index 6f076caf533d3..6b07449292417 100644 --- a/library/core/src/ptr/mod.rs +++ b/library/core/src/ptr/mod.rs @@ -1263,7 +1263,8 @@ const unsafe fn swap_nonoverlapping_simple_untyped(x: *mut T, y: *mut T, coun /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] -#[rustc_const_unstable(feature = "const_replace", issue = "83164")] +#[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] +#[rustc_const_stable(feature = "const_replace", since = "CURRENT_RUSTC_VERSION")] #[rustc_diagnostic_item = "ptr_replace"] pub const unsafe fn replace(dst: *mut T, src: T) -> T { // SAFETY: the caller must guarantee that `dst` is valid to be From 497100a13c72d290a167ae6eb5566fca653ba99f Mon Sep 17 00:00:00 2001 From: CastilloDel Date: Fri, 11 Oct 2024 22:05:58 +0200 Subject: [PATCH 2133/2194] Emit an error for unstable attributes that reference already stable features Add missing error annotations and .stderr file Acknowledge comments --- compiler/rustc_passes/messages.ftl | 6 ++++ compiler/rustc_passes/src/errors.rs | 11 +++++++ compiler/rustc_passes/src/stability.rs | 16 ++++++++++ ...tribute-rejects-already-stable-features.rs | 10 ++++++ ...ute-rejects-already-stable-features.stderr | 31 +++++++++++++++++++ 5 files changed, 74 insertions(+) create mode 100644 tests/ui/feature-gates/unstable-attribute-rejects-already-stable-features.rs create mode 100644 tests/ui/feature-gates/unstable-attribute-rejects-already-stable-features.stderr diff --git a/compiler/rustc_passes/messages.ftl b/compiler/rustc_passes/messages.ftl index 5369f54afb908..b5e1dc9a4cea9 100644 --- a/compiler/rustc_passes/messages.ftl +++ b/compiler/rustc_passes/messages.ftl @@ -745,6 +745,12 @@ passes_unrecognized_repr_hint = unrecognized representation hint .help = valid reprs are `Rust` (default), `C`, `align`, `packed`, `transparent`, `simd`, `i8`, `u8`, `i16`, `u16`, `i32`, `u32`, `i64`, `u64`, `i128`, `u128`, `isize`, `usize` +passes_unstable_attr_for_already_stable_feature = + can't mark as unstable using an already stable feature + .label = this feature is already stable + .item = the stability attribute annotates this item + .help = consider removing the attribute + passes_unused = unused attribute .suggestion = remove this attribute diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs index 29a087bf75975..021145aff7cfe 100644 --- a/compiler/rustc_passes/src/errors.rs +++ b/compiler/rustc_passes/src/errors.rs @@ -1496,6 +1496,17 @@ pub(crate) struct CannotStabilizeDeprecated { pub item_sp: Span, } +#[derive(Diagnostic)] +#[diag(passes_unstable_attr_for_already_stable_feature)] +pub(crate) struct UnstableAttrForAlreadyStableFeature { + #[primary_span] + #[label] + #[help] + pub span: Span, + #[label(passes_item)] + pub item_sp: Span, +} + #[derive(Diagnostic)] #[diag(passes_missing_stability_attr)] pub(crate) struct MissingStabilityAttr<'a> { diff --git a/compiler/rustc_passes/src/stability.rs b/compiler/rustc_passes/src/stability.rs index 46b67e930d5e9..751c87a9fe519 100644 --- a/compiler/rustc_passes/src/stability.rs +++ b/compiler/rustc_passes/src/stability.rs @@ -10,6 +10,7 @@ use rustc_attr::{ }; use rustc_data_structures::fx::FxIndexMap; use rustc_data_structures::unord::{ExtendUnord, UnordMap, UnordSet}; +use rustc_feature::ACCEPTED_FEATURES; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::{CRATE_DEF_ID, LOCAL_CRATE, LocalDefId, LocalModDefId}; @@ -246,12 +247,27 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> { } } + if let Stability { level: Unstable { .. }, feature } = stab { + if ACCEPTED_FEATURES.iter().find(|f| f.name == feature).is_some() { + self.tcx + .dcx() + .emit_err(errors::UnstableAttrForAlreadyStableFeature { span, item_sp }); + } + } if let Stability { level: Unstable { implied_by: Some(implied_by), .. }, feature } = stab { self.index.implications.insert(implied_by, feature); } + if let Some(ConstStability { level: Unstable { .. }, feature, .. }) = const_stab { + if ACCEPTED_FEATURES.iter().find(|f| f.name == feature).is_some() { + self.tcx.dcx().emit_err(errors::UnstableAttrForAlreadyStableFeature { + span: const_span.unwrap(), // If const_stab contains Some(..), same is true for const_span + item_sp, + }); + } + } if let Some(ConstStability { level: Unstable { implied_by: Some(implied_by), .. }, feature, diff --git a/tests/ui/feature-gates/unstable-attribute-rejects-already-stable-features.rs b/tests/ui/feature-gates/unstable-attribute-rejects-already-stable-features.rs new file mode 100644 index 0000000000000..9e697aaa0dcef --- /dev/null +++ b/tests/ui/feature-gates/unstable-attribute-rejects-already-stable-features.rs @@ -0,0 +1,10 @@ +//! Ensure #[unstable] doesn't accept already stable features + +#![feature(staged_api)] +#![stable(feature = "rust_test", since = "1.0.0")] + +#[unstable(feature = "arbitrary_enum_discriminant", issue = "42")] //~ ERROR can't mark as unstable using an already stable feature +#[rustc_const_unstable(feature = "arbitrary_enum_discriminant", issue = "42")] //~ ERROR can't mark as unstable using an already stable feature +const fn my_fun() {} + +fn main() {} diff --git a/tests/ui/feature-gates/unstable-attribute-rejects-already-stable-features.stderr b/tests/ui/feature-gates/unstable-attribute-rejects-already-stable-features.stderr new file mode 100644 index 0000000000000..319056a9c8898 --- /dev/null +++ b/tests/ui/feature-gates/unstable-attribute-rejects-already-stable-features.stderr @@ -0,0 +1,31 @@ +error: can't mark as unstable using an already stable feature + --> $DIR/unstable-attribute-rejects-already-stable-features.rs:6:1 + | +LL | #[unstable(feature = "arbitrary_enum_discriminant", issue = "42")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this feature is already stable +LL | #[rustc_const_unstable(feature = "arbitrary_enum_discriminant", issue = "42")] +LL | const fn my_fun() {} + | -------------------- the stability attribute annotates this item + | +help: consider removing the attribute + --> $DIR/unstable-attribute-rejects-already-stable-features.rs:6:1 + | +LL | #[unstable(feature = "arbitrary_enum_discriminant", issue = "42")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: can't mark as unstable using an already stable feature + --> $DIR/unstable-attribute-rejects-already-stable-features.rs:7:1 + | +LL | #[rustc_const_unstable(feature = "arbitrary_enum_discriminant", issue = "42")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this feature is already stable +LL | const fn my_fun() {} + | -------------------- the stability attribute annotates this item + | +help: consider removing the attribute + --> $DIR/unstable-attribute-rejects-already-stable-features.rs:7:1 + | +LL | #[rustc_const_unstable(feature = "arbitrary_enum_discriminant", issue = "42")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + From e5906e1591c0aa787003f89e3f3c9236c22f4832 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= Date: Sat, 12 Oct 2024 10:59:12 +0200 Subject: [PATCH 2134/2194] yeet some clones --- compiler/rustc_borrowck/src/nll.rs | 2 +- compiler/rustc_builtin_macros/src/deriving/smart_ptr.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_borrowck/src/nll.rs b/compiler/rustc_borrowck/src/nll.rs index f3207c26bfc0b..3674053409b8d 100644 --- a/compiler/rustc_borrowck/src/nll.rs +++ b/compiler/rustc_borrowck/src/nll.rs @@ -165,7 +165,7 @@ pub(crate) fn compute_regions<'a, 'tcx>( universe_causes, type_tests, liveness_constraints, - elements.clone(), + elements, ); // If requested: dump NLL facts, and run legacy polonius analysis. diff --git a/compiler/rustc_builtin_macros/src/deriving/smart_ptr.rs b/compiler/rustc_builtin_macros/src/deriving/smart_ptr.rs index fab1906eecd50..e3878d90e4143 100644 --- a/compiler/rustc_builtin_macros/src/deriving/smart_ptr.rs +++ b/compiler/rustc_builtin_macros/src/deriving/smart_ptr.rs @@ -312,7 +312,7 @@ pub(crate) fn expand_deriving_smart_ptr( impl_generics.params.insert(pointee_param_idx + 1, extra_param); // Add the impl blocks for `DispatchFromDyn` and `CoerceUnsized`. - let gen_args = vec![GenericArg::Type(alt_self_type.clone())]; + let gen_args = vec![GenericArg::Type(alt_self_type)]; add_impl_block(impl_generics.clone(), sym::DispatchFromDyn, gen_args.clone()); add_impl_block(impl_generics.clone(), sym::CoerceUnsized, gen_args); } From bcd71624d5f5c7a55477dfb05404b30d439d9674 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= Date: Sat, 12 Oct 2024 11:29:38 +0200 Subject: [PATCH 2135/2194] add latest crash tests --- tests/crashes/131507.rs | 10 ++++++++++ tests/crashes/131534.rs | 5 +++++ tests/crashes/131535.rs | 4 ++++ tests/crashes/131538.rs | 13 +++++++++++++ 4 files changed, 32 insertions(+) create mode 100644 tests/crashes/131507.rs create mode 100644 tests/crashes/131534.rs create mode 100644 tests/crashes/131535.rs create mode 100644 tests/crashes/131538.rs diff --git a/tests/crashes/131507.rs b/tests/crashes/131507.rs new file mode 100644 index 0000000000000..d402fb8afc322 --- /dev/null +++ b/tests/crashes/131507.rs @@ -0,0 +1,10 @@ +//@ known-bug: #131507 +//@ compile-flags: -Zmir-opt-level=5 -Zvalidate-mir +#![feature(non_lifetime_binders)] + +fn brick() +where + for T: Copy, +{ + || format_args!(""); +} diff --git a/tests/crashes/131534.rs b/tests/crashes/131534.rs new file mode 100644 index 0000000000000..545b3e68fe8d5 --- /dev/null +++ b/tests/crashes/131534.rs @@ -0,0 +1,5 @@ +//@ known-bug: #131534 +#![feature(generic_const_exprs)] +type Value<'v> = &[[u8; SIZE]]; + +trait Trait: Fn(Value) -> Value {} diff --git a/tests/crashes/131535.rs b/tests/crashes/131535.rs new file mode 100644 index 0000000000000..47ccdf87f2de7 --- /dev/null +++ b/tests/crashes/131535.rs @@ -0,0 +1,4 @@ +//@ known-bug: #131535 +#![feature(non_lifetime_binders)] +trait v0<> {} +fn kind :(v0<'_, > impl for v0<'_, v2 = impl v0 + '_>) {} diff --git a/tests/crashes/131538.rs b/tests/crashes/131538.rs new file mode 100644 index 0000000000000..f971d8b7791e4 --- /dev/null +++ b/tests/crashes/131538.rs @@ -0,0 +1,13 @@ +//@ known-bug: #131538 +#![feature(generic_associated_types_extended)] +#![feature(trivial_bounds)] + +trait HealthCheck { + async fn check(); +} + +fn do_health_check_par() +where + HealthCheck: HealthCheck, +{ +} From 9f91c5099fb7261cf8c85cc638d2692a317060ec Mon Sep 17 00:00:00 2001 From: joboet Date: Sat, 12 Oct 2024 13:01:36 +0200 Subject: [PATCH 2136/2194] std: fix stdout-before-main Fixes #130210. Since #124881, `ReentrantLock` uses `ThreadId` to identify threads. This has the unfortunate consequence of breaking uses of `Stdout` before main: Locking the `ReentrantLock` that synchronizes the output will initialize the thread ID before the handle for the main thread is set in `rt::init`. But since that would overwrite the current thread ID, `thread::set_current` triggers an abort. This PR fixes the problem by using the already initialized thread ID for constructing the main thread handle and allowing `set_current` calls that do not change the thread's ID. --- library/std/src/rt.rs | 21 +++++++++++++--- library/std/src/thread/current.rs | 20 +++++++++------- library/std/src/thread/mod.rs | 24 ++++++++++--------- tests/ui/runtime/stdout-before-main.rs | 24 +++++++++++++++++++ .../ui/runtime/stdout-before-main.run.stdout | 1 + 5 files changed, 67 insertions(+), 23 deletions(-) create mode 100644 tests/ui/runtime/stdout-before-main.rs create mode 100644 tests/ui/runtime/stdout-before-main.run.stdout diff --git a/library/std/src/rt.rs b/library/std/src/rt.rs index 0a841f07e3be7..80e7c3c026bd7 100644 --- a/library/std/src/rt.rs +++ b/library/std/src/rt.rs @@ -102,9 +102,24 @@ unsafe fn init(argc: isize, argv: *const *const u8, sigpipe: u8) { sys::init(argc, argv, sigpipe) }; - // Set up the current thread to give it the right name. - let thread = Thread::new_main(); - thread::set_current(thread); + // Set up the current thread handle to give it the right name. + // + // When code running before main uses `ReentrantLock` (for example by + // using `println!`), the thread ID can become initialized before we + // create this handle. Since `set_current` fails when the ID of the + // handle does not match the current ID, we should attempt to use the + // current thread ID here instead of unconditionally creating a new + // one. Also see #130210. + let thread = Thread::new_main(thread::current_id()); + if let Err(_thread) = thread::set_current(thread) { + // `thread::current` will create a new handle if none has been set yet. + // Thus, if someone uses it before main, this call will fail. That's a + // bad idea though, as we then cannot set the main thread name here. + // + // FIXME: detect the main thread in `thread::current` and use the + // correct name there. + rtabort!("code running before main must not use thread::current"); + } } /// Clean up the thread-local runtime state. This *should* be run after all other diff --git a/library/std/src/thread/current.rs b/library/std/src/thread/current.rs index b38149a0da740..e6eb90c4c30a5 100644 --- a/library/std/src/thread/current.rs +++ b/library/std/src/thread/current.rs @@ -110,22 +110,24 @@ mod id { } } -/// Sets the thread handle for the current thread. -/// -/// Aborts if the handle or the ID has been set already. -pub(crate) fn set_current(thread: Thread) { - if CURRENT.get() != NONE || id::get().is_some() { - // Using `panic` here can add ~3kB to the binary size. We have complete - // control over where this is called, so just abort if there is a bug. - rtabort!("thread::set_current should only be called once per thread"); +/// Tries to set the thread handle for the current thread. Fails if a handle was +/// already set or if the thread ID of `thread` would change an already-set ID. +pub(crate) fn set_current(thread: Thread) -> Result<(), Thread> { + if CURRENT.get() != NONE { + return Err(thread); } - id::set(thread.id()); + match id::get() { + Some(id) if id == thread.id() => {} + None => id::set(thread.id()), + _ => return Err(thread), + } // Make sure that `crate::rt::thread_cleanup` will be run, which will // call `drop_current`. crate::sys::thread_local::guard::enable(); CURRENT.set(thread.into_raw().cast_mut()); + Ok(()) } /// Gets the id of the thread that invokes it. diff --git a/library/std/src/thread/mod.rs b/library/std/src/thread/mod.rs index d1d4eabb9bd45..3975388850998 100644 --- a/library/std/src/thread/mod.rs +++ b/library/std/src/thread/mod.rs @@ -519,9 +519,14 @@ impl Builder { let f = MaybeDangling::new(f); let main = move || { - // Immediately store the thread handle to avoid setting it or its ID - // twice, which would cause an abort. - set_current(their_thread.clone()); + if let Err(_thread) = set_current(their_thread.clone()) { + // Both the current thread handle and the ID should not be + // initialized yet. Since only the C runtime and some of our + // platform code run before this, this point shouldn't be + // reachable. Use an abort to save binary size (see #123356). + rtabort!("something here is badly broken!"); + } + if let Some(name) = their_thread.cname() { imp::Thread::set_name(name); } @@ -1159,9 +1164,6 @@ pub fn park_timeout(dur: Duration) { pub struct ThreadId(NonZero); impl ThreadId { - // DO NOT rely on this value. - const MAIN_THREAD: ThreadId = ThreadId(unsafe { NonZero::new_unchecked(1) }); - // Generate a new unique thread ID. pub(crate) fn new() -> ThreadId { #[cold] @@ -1173,7 +1175,7 @@ impl ThreadId { if #[cfg(target_has_atomic = "64")] { use crate::sync::atomic::AtomicU64; - static COUNTER: AtomicU64 = AtomicU64::new(1); + static COUNTER: AtomicU64 = AtomicU64::new(0); let mut last = COUNTER.load(Ordering::Relaxed); loop { @@ -1189,7 +1191,7 @@ impl ThreadId { } else { use crate::sync::{Mutex, PoisonError}; - static COUNTER: Mutex = Mutex::new(1); + static COUNTER: Mutex = Mutex::new(0); let mut counter = COUNTER.lock().unwrap_or_else(PoisonError::into_inner); let Some(id) = counter.checked_add(1) else { @@ -1326,9 +1328,9 @@ impl Thread { Self::new_inner(id, ThreadName::Unnamed) } - // Used in runtime to construct main thread - pub(crate) fn new_main() -> Thread { - Self::new_inner(ThreadId::MAIN_THREAD, ThreadName::Main) + /// Constructs the thread handle for the main thread. + pub(crate) fn new_main(id: ThreadId) -> Thread { + Self::new_inner(id, ThreadName::Main) } fn new_inner(id: ThreadId, name: ThreadName) -> Thread { diff --git a/tests/ui/runtime/stdout-before-main.rs b/tests/ui/runtime/stdout-before-main.rs new file mode 100644 index 0000000000000..26c734d3e9eed --- /dev/null +++ b/tests/ui/runtime/stdout-before-main.rs @@ -0,0 +1,24 @@ +//@ run-pass +//@ check-run-results +//@ only-gnu +//@ only-linux +// +// Regression test for #130210. +// .init_array doesn't work everywhere, so we limit the test to just GNU/Linux. + +use std::ffi::c_int; +use std::thread; + +#[used] +#[link_section = ".init_array"] +static INIT: extern "C" fn(c_int, *const *const u8, *const *const u8) = { + extern "C" fn init(_argc: c_int, _argv: *const *const u8, _envp: *const *const u8) { + print!("Hello from before "); + } + + init +}; + +fn main() { + println!("{}!", thread::current().name().unwrap()); +} diff --git a/tests/ui/runtime/stdout-before-main.run.stdout b/tests/ui/runtime/stdout-before-main.run.stdout new file mode 100644 index 0000000000000..d7a3a4389eca4 --- /dev/null +++ b/tests/ui/runtime/stdout-before-main.run.stdout @@ -0,0 +1 @@ +Hello from before main! From 52090f071524263fbe48be2e9eec51635f573f64 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=AE=B8=E6=9D=B0=E5=8F=8B=20Jieyou=20Xu=20=28Joe=29?= <39484203+jieyouxu@users.noreply.github.com> Date: Sat, 12 Oct 2024 19:12:19 +0800 Subject: [PATCH 2137/2194] Take a display name for `tool_check_step!` --- src/bootstrap/src/core/build_steps/check.rs | 41 +++++++++++++++------ 1 file changed, 29 insertions(+), 12 deletions(-) diff --git a/src/bootstrap/src/core/build_steps/check.rs b/src/bootstrap/src/core/build_steps/check.rs index 7671fc7e013b7..f419bebdc1263 100644 --- a/src/bootstrap/src/core/build_steps/check.rs +++ b/src/bootstrap/src/core/build_steps/check.rs @@ -398,7 +398,14 @@ impl Step for RustAnalyzer { } macro_rules! tool_check_step { - ($name:ident, $path:literal, $($alias:literal, )* $source_type:path $(, $default:literal )?) => { + ( + $name:ident, + $display_name:literal, + $path:literal, + $($alias:literal, )* + $source_type:path + $(, $default:literal )? + ) => { #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct $name { pub target: TargetSelection, @@ -441,7 +448,7 @@ macro_rules! tool_check_step { cargo.arg("--all-targets"); } - let _guard = builder.msg_check(&concat!(stringify!($name), " artifacts").to_lowercase(), target); + let _guard = builder.msg_check(&format!("{} artifacts", $display_name), target); run_cargo( builder, cargo, @@ -468,20 +475,30 @@ macro_rules! tool_check_step { }; } -tool_check_step!(Rustdoc, "src/tools/rustdoc", "src/librustdoc", SourceType::InTree); +tool_check_step!(Rustdoc, "rustdoc", "src/tools/rustdoc", "src/librustdoc", SourceType::InTree); // Clippy, miri and Rustfmt are hybrids. They are external tools, but use a git subtree instead // of a submodule. Since the SourceType only drives the deny-warnings // behavior, treat it as in-tree so that any new warnings in clippy will be // rejected. -tool_check_step!(Clippy, "src/tools/clippy", SourceType::InTree); -tool_check_step!(Miri, "src/tools/miri", SourceType::InTree); -tool_check_step!(CargoMiri, "src/tools/miri/cargo-miri", SourceType::InTree); -tool_check_step!(Rls, "src/tools/rls", SourceType::InTree); -tool_check_step!(Rustfmt, "src/tools/rustfmt", SourceType::InTree); -tool_check_step!(MiroptTestTools, "src/tools/miropt-test-tools", SourceType::InTree); -tool_check_step!(TestFloatParse, "src/etc/test-float-parse", SourceType::InTree); - -tool_check_step!(Bootstrap, "src/bootstrap", SourceType::InTree, false); +tool_check_step!(Clippy, "clippy", "src/tools/clippy", SourceType::InTree); +tool_check_step!(Miri, "miri", "src/tools/miri", SourceType::InTree); +tool_check_step!(CargoMiri, "cargo-miri", "src/tools/miri/cargo-miri", SourceType::InTree); +tool_check_step!(Rls, "rls", "src/tools/rls", SourceType::InTree); +tool_check_step!(Rustfmt, "rustfmt", "src/tools/rustfmt", SourceType::InTree); +tool_check_step!( + MiroptTestTools, + "miropt-test-tools", + "src/tools/miropt-test-tools", + SourceType::InTree +); +tool_check_step!( + TestFloatParse, + "test-float-parse", + "src/etc/test-float-parse", + SourceType::InTree +); + +tool_check_step!(Bootstrap, "bootstrap", "src/bootstrap", SourceType::InTree, false); /// Cargo's output path for the standard library in a given stage, compiled /// by a particular compiler for the specified target. From 89623439f73d5a744ba5c8a911274b3802d79b86 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 12 Oct 2024 13:13:50 +0200 Subject: [PATCH 2138/2194] mark InterpResult as must_use --- compiler/rustc_middle/src/mir/interpret/error.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/compiler/rustc_middle/src/mir/interpret/error.rs b/compiler/rustc_middle/src/mir/interpret/error.rs index 431043b043192..fcb87e1943505 100644 --- a/compiler/rustc_middle/src/mir/interpret/error.rs +++ b/compiler/rustc_middle/src/mir/interpret/error.rs @@ -754,6 +754,7 @@ impl Drop for Guard { /// /// We also make things panic if this type is ever implicitly dropped. #[derive(Debug)] +#[must_use] pub struct InterpResult_<'tcx, T> { res: Result>, guard: Guard, From 470e9fa1af3e0ec36768e57cdb63bde46af8ee6d Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sat, 12 Oct 2024 09:10:04 -0400 Subject: [PATCH 2139/2194] Shallowly match opaque key in storage --- .../src/solve/eval_ctxt/mod.rs | 51 +++++++------------ .../src/solve/normalizes_to/opaque_types.rs | 34 +++++++++---- 2 files changed, 42 insertions(+), 43 deletions(-) diff --git a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs index 458edf920ab43..daacc6691182d 100644 --- a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs @@ -4,6 +4,7 @@ use derive_where::derive_where; #[cfg(feature = "nightly")] use rustc_macros::{HashStable_NoContext, TyDecodable, TyEncodable}; use rustc_type_ir::data_structures::{HashMap, HashSet, ensure_sufficient_stack}; +use rustc_type_ir::fast_reject::DeepRejectCtxt; use rustc_type_ir::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable}; use rustc_type_ir::inherent::*; use rustc_type_ir::relate::Relate; @@ -18,9 +19,9 @@ use crate::delegate::SolverDelegate; use crate::solve::inspect::{self, ProofTreeBuilder}; use crate::solve::search_graph::SearchGraph; use crate::solve::{ - CanonicalInput, CanonicalResponse, Certainty, FIXPOINT_STEP_LIMIT, Goal, GoalEvaluationKind, - GoalSource, HasChanged, NestedNormalizationGoals, NoSolution, PredefinedOpaquesData, - QueryResult, SolverMode, + CanonicalInput, Certainty, FIXPOINT_STEP_LIMIT, Goal, GoalEvaluationKind, GoalSource, + HasChanged, NestedNormalizationGoals, NoSolution, PredefinedOpaquesData, QueryResult, + SolverMode, }; pub(super) mod canonical; @@ -987,40 +988,22 @@ where // Do something for each opaque/hidden pair defined with `def_id` in the // current inference context. - pub(super) fn unify_existing_opaque_tys( + pub(super) fn probe_existing_opaque_ty( &mut self, - param_env: I::ParamEnv, key: ty::OpaqueTypeKey, - ty: I::Ty, - ) -> Vec> { - // FIXME: Super inefficient to be cloning this... - let opaques = self.delegate.clone_opaque_types_for_query_response(); - - let mut values = vec![]; - for (candidate_key, candidate_ty) in opaques { - if candidate_key.def_id != key.def_id { - continue; - } - values.extend( - self.probe(|result| inspect::ProbeKind::OpaqueTypeStorageLookup { - result: *result, - }) - .enter(|ecx| { - for (a, b) in std::iter::zip(candidate_key.args.iter(), key.args.iter()) { - ecx.eq(param_env, a, b)?; - } - ecx.eq(param_env, candidate_ty, ty)?; - ecx.add_item_bounds_for_hidden_type( - candidate_key.def_id.into(), - candidate_key.args, - param_env, - candidate_ty, - ); - ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) - }), + ) -> Option<(ty::OpaqueTypeKey, I::Ty)> { + let mut matching = + self.delegate.clone_opaque_types_for_query_response().into_iter().filter( + |(candidate_key, _)| { + candidate_key.def_id == key.def_id + && DeepRejectCtxt::relate_rigid_rigid(self.cx()) + .args_may_unify(candidate_key.args, key.args) + }, ); - } - values + let first = matching.next(); + let second = matching.next(); + assert_eq!(second, None); + first } // Try to evaluate a const, or return `None` if the const is too generic. diff --git a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/opaque_types.rs b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/opaque_types.rs index 6a0703c531323..f8d51f304f332 100644 --- a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/opaque_types.rs +++ b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/opaque_types.rs @@ -7,7 +7,9 @@ use rustc_type_ir::inherent::*; use rustc_type_ir::{self as ty, Interner}; use crate::delegate::SolverDelegate; -use crate::solve::{Certainty, EvalCtxt, Goal, NoSolution, QueryResult, Reveal, SolverMode}; +use crate::solve::{ + Certainty, EvalCtxt, Goal, NoSolution, QueryResult, Reveal, SolverMode, inspect, +}; impl EvalCtxt<'_, D> where @@ -52,14 +54,28 @@ where // // If that fails, we insert `expected` as a new hidden type instead of // eagerly emitting an error. - let matches = - self.unify_existing_opaque_tys(goal.param_env, opaque_type_key, expected); - if !matches.is_empty() { - if let Some(response) = self.try_merge_responses(&matches) { - return Ok(response); - } else { - return self.flounder(&matches); - } + let existing = self.probe_existing_opaque_ty(opaque_type_key); + if let Some((candidate_key, candidate_ty)) = existing { + return self + .probe(|result| inspect::ProbeKind::OpaqueTypeStorageLookup { + result: *result, + }) + .enter(|ecx| { + for (a, b) in std::iter::zip( + candidate_key.args.iter(), + opaque_type_key.args.iter(), + ) { + ecx.eq(goal.param_env, a, b)?; + } + ecx.eq(goal.param_env, candidate_ty, expected)?; + ecx.add_item_bounds_for_hidden_type( + candidate_key.def_id.into(), + candidate_key.args, + goal.param_env, + candidate_ty, + ); + ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) + }); } // Otherwise, define a new opaque type From 49202c7b479c0f9727b303985a7a6e45ae5379d3 Mon Sep 17 00:00:00 2001 From: DianQK Date: Sat, 12 Oct 2024 21:41:44 +0800 Subject: [PATCH 2140/2194] Ignore the `download_ci_llvm` test --- src/bootstrap/src/core/config/tests.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/bootstrap/src/core/config/tests.rs b/src/bootstrap/src/core/config/tests.rs index ed89112de9003..57d66a49afda8 100644 --- a/src/bootstrap/src/core/config/tests.rs +++ b/src/bootstrap/src/core/config/tests.rs @@ -19,6 +19,8 @@ pub(crate) fn parse(config: &str) -> Config { ) } +// FIXME: Resume this test after establishing a stabilized change tracking logic. +#[ignore] #[test] fn download_ci_llvm() { if crate::core::build_steps::llvm::is_ci_llvm_modified(&parse("")) { From 4441a8975096217d877d4a11afb4695ec1c560a2 Mon Sep 17 00:00:00 2001 From: DianQK Date: Wed, 9 Oct 2024 21:54:43 +0800 Subject: [PATCH 2141/2194] Update LLVM submodule --- src/llvm-project | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/llvm-project b/src/llvm-project index dd46457da7825..3a17f74904a74 160000 --- a/src/llvm-project +++ b/src/llvm-project @@ -1 +1 @@ -Subproject commit dd46457da782554454106d48ecd4f6b4c2f9af73 +Subproject commit 3a17f74904a74565c54cfac0d67026362d038698 From 1efffe720d40e0c88efe820da01f99d031a4c4d1 Mon Sep 17 00:00:00 2001 From: DianQK Date: Sat, 12 Oct 2024 22:36:14 +0800 Subject: [PATCH 2142/2194] `LLVMConstInt` only allows integer types --- compiler/rustc_codegen_llvm/src/common.rs | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/compiler/rustc_codegen_llvm/src/common.rs b/compiler/rustc_codegen_llvm/src/common.rs index 4ca19ab2f12b8..0ced37b53a841 100644 --- a/compiler/rustc_codegen_llvm/src/common.rs +++ b/compiler/rustc_codegen_llvm/src/common.rs @@ -5,6 +5,7 @@ use rustc_abi as abi; use rustc_abi::Primitive::Pointer; use rustc_abi::{AddressSpace, HasDataLayout}; use rustc_ast::Mutability; +use rustc_codegen_ssa::common::TypeKind; use rustc_codegen_ssa::traits::*; use rustc_data_structures::stable_hasher::{Hash128, HashStable, StableHasher}; use rustc_hir::def_id::DefId; @@ -146,6 +147,10 @@ impl<'ll, 'tcx> ConstCodegenMethods<'tcx> for CodegenCx<'ll, 'tcx> { } fn const_int(&self, t: &'ll Type, i: i64) -> &'ll Value { + debug_assert!( + self.type_kind(t) == TypeKind::Integer, + "only allows integer types in const_int" + ); unsafe { llvm::LLVMConstInt(t, i as u64, True) } } @@ -176,10 +181,18 @@ impl<'ll, 'tcx> ConstCodegenMethods<'tcx> for CodegenCx<'ll, 'tcx> { } fn const_uint(&self, t: &'ll Type, i: u64) -> &'ll Value { + debug_assert!( + self.type_kind(t) == TypeKind::Integer, + "only allows integer types in const_uint" + ); unsafe { llvm::LLVMConstInt(t, i, False) } } fn const_uint_big(&self, t: &'ll Type, u: u128) -> &'ll Value { + debug_assert!( + self.type_kind(t) == TypeKind::Integer, + "only allows integer types in const_uint_big" + ); unsafe { let words = [u as u64, (u >> 64) as u64]; llvm::LLVMConstIntOfArbitraryPrecision(t, 2, words.as_ptr()) From a0661ec331e87758fd7e4a4b45f460200e8394ec Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 12 Oct 2024 19:48:28 +0200 Subject: [PATCH 2143/2194] remove const_cow_is_borrowed feature gate --- library/alloc/src/borrow.rs | 2 -- library/alloc/src/lib.rs | 1 - library/alloc/tests/lib.rs | 1 - 3 files changed, 4 deletions(-) diff --git a/library/alloc/src/borrow.rs b/library/alloc/src/borrow.rs index f86face3f90cb..dbfd2e74abee6 100644 --- a/library/alloc/src/borrow.rs +++ b/library/alloc/src/borrow.rs @@ -225,7 +225,6 @@ impl Cow<'_, B> { /// assert!(!bull.is_borrowed()); /// ``` #[unstable(feature = "cow_is_borrowed", issue = "65143")] - #[rustc_const_unstable(feature = "const_cow_is_borrowed", issue = "65143")] pub const fn is_borrowed(&self) -> bool { match *self { Borrowed(_) => true, @@ -248,7 +247,6 @@ impl Cow<'_, B> { /// assert!(!bull.is_owned()); /// ``` #[unstable(feature = "cow_is_borrowed", issue = "65143")] - #[rustc_const_unstable(feature = "const_cow_is_borrowed", issue = "65143")] pub const fn is_owned(&self) -> bool { !self.is_borrowed() } diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs index c60c0743c7e12..e6b137b4a3739 100644 --- a/library/alloc/src/lib.rs +++ b/library/alloc/src/lib.rs @@ -108,7 +108,6 @@ #![feature(coerce_unsized)] #![feature(const_align_of_val)] #![feature(const_box)] -#![feature(const_cow_is_borrowed)] #![feature(const_eval_select)] #![feature(const_heap)] #![feature(const_maybe_uninit_write)] diff --git a/library/alloc/tests/lib.rs b/library/alloc/tests/lib.rs index f43143c6cef65..36aa312036d29 100644 --- a/library/alloc/tests/lib.rs +++ b/library/alloc/tests/lib.rs @@ -4,7 +4,6 @@ #![feature(assert_matches)] #![feature(btree_extract_if)] #![feature(cow_is_borrowed)] -#![feature(const_cow_is_borrowed)] #![feature(const_heap)] #![cfg_attr(bootstrap, feature(const_mut_refs))] #![feature(const_ptr_write)] From 4bc21e318cc26f688468188b88758202071b0a19 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= Date: Sat, 12 Oct 2024 22:07:46 +0200 Subject: [PATCH 2144/2194] remove a couple of redundant String to String conversion --- compiler/rustc_borrowck/src/diagnostics/move_errors.rs | 2 +- compiler/rustc_codegen_llvm/src/asm.rs | 2 +- compiler/rustc_middle/src/ty/diagnostics.rs | 2 +- compiler/rustc_session/src/utils.rs | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_borrowck/src/diagnostics/move_errors.rs b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs index 98417e8c7a3f4..3871816777c7f 100644 --- a/compiler/rustc_borrowck/src/diagnostics/move_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs @@ -706,7 +706,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { suggestions.push(( pat_span, format!("consider removing the {to_remove}"), - suggestion.to_string(), + suggestion, )); } } diff --git a/compiler/rustc_codegen_llvm/src/asm.rs b/compiler/rustc_codegen_llvm/src/asm.rs index 82ca3f519f740..298cac2fd6e77 100644 --- a/compiler/rustc_codegen_llvm/src/asm.rs +++ b/compiler/rustc_codegen_llvm/src/asm.rs @@ -154,7 +154,7 @@ impl<'ll, 'tcx> AsmBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> { // We prefer the latter because it matches the behavior of // Clang. if late && matches!(reg, InlineAsmRegOrRegClass::Reg(_)) { - constraints.push(reg_to_llvm(reg, Some(&in_value.layout)).to_string()); + constraints.push(reg_to_llvm(reg, Some(&in_value.layout))); } else { constraints.push(format!("{}", op_idx[&idx])); } diff --git a/compiler/rustc_middle/src/ty/diagnostics.rs b/compiler/rustc_middle/src/ty/diagnostics.rs index 751f0c71eb4b5..354ca746b466a 100644 --- a/compiler/rustc_middle/src/ty/diagnostics.rs +++ b/compiler/rustc_middle/src/ty/diagnostics.rs @@ -325,7 +325,7 @@ pub fn suggest_constraining_type_params<'a>( let suggestion = if span_to_replace.is_some() { constraint.clone() } else if constraint.starts_with('<') { - constraint.to_string() + constraint.clone() } else if bound_list_non_empty { format!(" + {constraint}") } else { diff --git a/compiler/rustc_session/src/utils.rs b/compiler/rustc_session/src/utils.rs index 37528a4425f58..9182789cf0269 100644 --- a/compiler/rustc_session/src/utils.rs +++ b/compiler/rustc_session/src/utils.rs @@ -137,7 +137,7 @@ pub fn extra_compiler_flags() -> Option<(Vec, bool)> { let content = if arg.len() == a.len() { // A space-separated option, like `-C incremental=foo` or `--crate-type rlib` match args.next() { - Some(arg) => arg.to_string(), + Some(arg) => arg, None => continue, } } else if arg.get(a.len()..a.len() + 1) == Some("=") { From 19f6c17df486c5f70c1000ecada39c62b9c93550 Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Tue, 1 Oct 2024 17:11:48 -0400 Subject: [PATCH 2145/2194] Stabilize `const_option` This makes the following API stable in const contexts: impl Option { pub const fn as_mut(&mut self) -> Option<&mut T>; pub const fn expect(self, msg: &str) -> T; pub const fn unwrap(self) -> T; pub const unsafe fn unwrap_unchecked(self) -> T; pub const fn take(&mut self) -> Option; pub const fn replace(&mut self, value: T) -> Option; } impl Option<&T> { pub const fn copied(self) -> Option where T: Copy; } impl Option<&mut T> { pub const fn copied(self) -> Option where T: Copy; } impl Option> { pub const fn transpose(self) -> Result, E> } impl Option> { pub const fn flatten(self) -> Option; } The following functions make use of the unstable `const_precise_live_drops` feature: - `expect` - `unwrap` - `unwrap_unchecked` - `transpose` - `flatten` Fixes: --- compiler/rustc_middle/src/lib.rs | 1 - compiler/rustc_serialize/src/lib.rs | 1 - library/alloc/src/lib.rs | 1 - library/core/src/array/ascii.rs | 1 - library/core/src/lib.rs | 1 - library/core/src/option.rs | 30 ++++++++++++------- library/core/src/ptr/non_null.rs | 2 -- library/core/src/time.rs | 1 - library/core/tests/lib.rs | 1 - .../clippy/tests/ui/doc/doc-fixable.fixed | 2 +- src/tools/clippy/tests/ui/doc/doc-fixable.rs | 2 +- src/tools/miri/src/lib.rs | 1 - tests/ui/consts/const-unwrap.rs | 10 +++++-- tests/ui/consts/const-unwrap.stderr | 12 ++++++-- 14 files changed, 37 insertions(+), 29 deletions(-) diff --git a/compiler/rustc_middle/src/lib.rs b/compiler/rustc_middle/src/lib.rs index 70e61df1ab4d1..e9b73d25ba208 100644 --- a/compiler/rustc_middle/src/lib.rs +++ b/compiler/rustc_middle/src/lib.rs @@ -37,7 +37,6 @@ #![feature(box_as_ptr)] #![feature(box_patterns)] #![feature(closure_track_caller)] -#![feature(const_option)] #![feature(const_type_name)] #![feature(core_intrinsics)] #![feature(coroutines)] diff --git a/compiler/rustc_serialize/src/lib.rs b/compiler/rustc_serialize/src/lib.rs index b7977a848ce00..47f72298e22ce 100644 --- a/compiler/rustc_serialize/src/lib.rs +++ b/compiler/rustc_serialize/src/lib.rs @@ -10,7 +10,6 @@ test(attr(allow(unused_variables), deny(warnings))) )] #![doc(rust_logo)] -#![feature(const_option)] #![feature(core_intrinsics)] #![feature(min_specialization)] #![feature(never_type)] diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs index 1d7b7a034541e..ec6ffa7a1059a 100644 --- a/library/alloc/src/lib.rs +++ b/library/alloc/src/lib.rs @@ -112,7 +112,6 @@ #![feature(const_eval_select)] #![feature(const_heap)] #![feature(const_maybe_uninit_write)] -#![feature(const_option)] #![feature(const_pin)] #![feature(const_size_of_val)] #![feature(const_vec_string_slice)] diff --git a/library/core/src/array/ascii.rs b/library/core/src/array/ascii.rs index 05797b042ee4a..e2faef855bc2c 100644 --- a/library/core/src/array/ascii.rs +++ b/library/core/src/array/ascii.rs @@ -9,7 +9,6 @@ impl [u8; N] { /// /// ``` /// #![feature(ascii_char)] - /// #![feature(const_option)] /// /// const HEX_DIGITS: [std::ascii::Char; 16] = /// *b"0123456789abcdef".as_ascii().unwrap(); diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index 61fe024300e2f..726aa209fdf43 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -131,7 +131,6 @@ #![feature(const_maybe_uninit_assume_init)] #![feature(const_nonnull_new)] #![feature(const_num_midpoint)] -#![feature(const_option)] #![feature(const_option_ext)] #![feature(const_pin)] #![feature(const_pointer_is_aligned)] diff --git a/library/core/src/option.rs b/library/core/src/option.rs index 154e52e288bc1..84ccb7a1f6680 100644 --- a/library/core/src/option.rs +++ b/library/core/src/option.rs @@ -723,7 +723,8 @@ impl Option { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_unstable(feature = "const_option", issue = "67441")] + #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] + #[rustc_const_stable(feature = "const_option", since = "CURRENT_RUSTC_VERSION")] pub const fn as_mut(&mut self) -> Option<&mut T> { match *self { Some(ref mut x) => Some(x), @@ -924,7 +925,8 @@ impl Option { #[track_caller] #[stable(feature = "rust1", since = "1.0.0")] #[cfg_attr(not(test), rustc_diagnostic_item = "option_expect")] - #[rustc_const_unstable(feature = "const_option", issue = "67441")] + #[rustc_allow_const_fn_unstable(const_precise_live_drops)] + #[rustc_const_stable(feature = "const_option", since = "CURRENT_RUSTC_VERSION")] pub const fn expect(self, msg: &str) -> T { match self { Some(val) => val, @@ -962,7 +964,8 @@ impl Option { #[track_caller] #[stable(feature = "rust1", since = "1.0.0")] #[cfg_attr(not(test), rustc_diagnostic_item = "option_unwrap")] - #[rustc_const_unstable(feature = "const_option", issue = "67441")] + #[rustc_allow_const_fn_unstable(const_precise_live_drops)] + #[rustc_const_stable(feature = "const_option", since = "CURRENT_RUSTC_VERSION")] pub const fn unwrap(self) -> T { match self { Some(val) => val, @@ -1069,7 +1072,8 @@ impl Option { #[inline] #[track_caller] #[stable(feature = "option_result_unwrap_unchecked", since = "1.58.0")] - #[rustc_const_unstable(feature = "const_option", issue = "67441")] + #[rustc_allow_const_fn_unstable(const_precise_live_drops)] + #[rustc_const_stable(feature = "const_option", since = "CURRENT_RUSTC_VERSION")] pub const unsafe fn unwrap_unchecked(self) -> T { match self { Some(val) => val, @@ -1712,7 +1716,8 @@ impl Option { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_unstable(feature = "const_option", issue = "67441")] + #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] + #[rustc_const_stable(feature = "const_option", since = "CURRENT_RUSTC_VERSION")] pub const fn take(&mut self) -> Option { // FIXME(const-hack) replace `mem::replace` by `mem::take` when the latter is const ready mem::replace(self, None) @@ -1769,8 +1774,9 @@ impl Option { /// assert_eq!(old, None); /// ``` #[inline] - #[rustc_const_unstable(feature = "const_option", issue = "67441")] #[stable(feature = "option_replace", since = "1.31.0")] + #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] + #[rustc_const_stable(feature = "const_option", since = "CURRENT_RUSTC_VERSION")] pub const fn replace(&mut self, value: T) -> Option { mem::replace(self, Some(value)) } @@ -1878,7 +1884,7 @@ impl Option<&T> { /// ``` #[must_use = "`self` will be dropped if the result is not used"] #[stable(feature = "copied", since = "1.35.0")] - #[rustc_const_unstable(feature = "const_option", issue = "67441")] + #[rustc_const_stable(feature = "const_option", since = "CURRENT_RUSTC_VERSION")] pub const fn copied(self) -> Option where T: Copy, @@ -1931,7 +1937,8 @@ impl Option<&mut T> { /// ``` #[must_use = "`self` will be dropped if the result is not used"] #[stable(feature = "copied", since = "1.35.0")] - #[rustc_const_unstable(feature = "const_option", issue = "67441")] + #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] + #[rustc_const_stable(feature = "const_option", since = "CURRENT_RUSTC_VERSION")] pub const fn copied(self) -> Option where T: Copy, @@ -1986,7 +1993,8 @@ impl Option> { /// ``` #[inline] #[stable(feature = "transpose_result", since = "1.33.0")] - #[rustc_const_unstable(feature = "const_option", issue = "67441")] + #[rustc_allow_const_fn_unstable(const_precise_live_drops)] + #[rustc_const_stable(feature = "const_option", since = "CURRENT_RUSTC_VERSION")] pub const fn transpose(self) -> Result, E> { match self { Some(Ok(x)) => Ok(Some(x)), @@ -2009,7 +2017,6 @@ const fn unwrap_failed() -> ! { #[cfg_attr(feature = "panic_immediate_abort", inline)] #[cold] #[track_caller] -#[rustc_const_unstable(feature = "const_option", issue = "67441")] const fn expect_failed(msg: &str) -> ! { panic_display(&msg) } @@ -2534,7 +2541,8 @@ impl Option> { /// ``` #[inline] #[stable(feature = "option_flattening", since = "1.40.0")] - #[rustc_const_unstable(feature = "const_option", issue = "67441")] + #[rustc_allow_const_fn_unstable(const_precise_live_drops)] + #[rustc_const_stable(feature = "const_option", since = "CURRENT_RUSTC_VERSION")] pub const fn flatten(self) -> Option { // FIXME(const-hack): could be written with `and_then` match self { diff --git a/library/core/src/ptr/non_null.rs b/library/core/src/ptr/non_null.rs index dc1a7c6220ebe..980d4a3cf6ceb 100644 --- a/library/core/src/ptr/non_null.rs +++ b/library/core/src/ptr/non_null.rs @@ -1211,7 +1211,6 @@ impl NonNull { /// /// ``` /// #![feature(const_nonnull_new)] - /// #![feature(const_option)] /// #![feature(const_pointer_is_aligned)] /// use std::ptr::NonNull; /// @@ -1264,7 +1263,6 @@ impl NonNull { /// /// ``` /// #![feature(const_pointer_is_aligned)] - /// #![feature(const_option)] /// #![feature(const_nonnull_new)] /// use std::ptr::NonNull; /// diff --git a/library/core/src/time.rs b/library/core/src/time.rs index a997874dd9c7b..f7ea7e06e9cdb 100644 --- a/library/core/src/time.rs +++ b/library/core/src/time.rs @@ -626,7 +626,6 @@ impl Duration { /// ``` #[stable(feature = "duration_abs_diff", since = "1.81.0")] #[rustc_const_stable(feature = "duration_abs_diff", since = "1.81.0")] - #[rustc_allow_const_fn_unstable(const_option)] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs index 02777886b45a3..9e15bb1dd8fcb 100644 --- a/library/core/tests/lib.rs +++ b/library/core/tests/lib.rs @@ -24,7 +24,6 @@ #![feature(const_ipv6)] #![feature(const_likely)] #![feature(const_nonnull_new)] -#![feature(const_option)] #![feature(const_option_ext)] #![feature(const_pin)] #![feature(const_pointer_is_aligned)] diff --git a/src/tools/clippy/tests/ui/doc/doc-fixable.fixed b/src/tools/clippy/tests/ui/doc/doc-fixable.fixed index edfffe8fcfe36..355f2bc773611 100644 --- a/src/tools/clippy/tests/ui/doc/doc-fixable.fixed +++ b/src/tools/clippy/tests/ui/doc/doc-fixable.fixed @@ -3,7 +3,7 @@ #![allow(dead_code, incomplete_features)] #![warn(clippy::doc_markdown)] -#![feature(custom_inner_attributes, generic_const_exprs, const_option)] +#![feature(custom_inner_attributes, generic_const_exprs)] #![rustfmt::skip] /// The `foo_bar` function does _nothing_. See also `foo::bar`. (note the dot there) diff --git a/src/tools/clippy/tests/ui/doc/doc-fixable.rs b/src/tools/clippy/tests/ui/doc/doc-fixable.rs index 3c0f6913e3289..9ced267762210 100644 --- a/src/tools/clippy/tests/ui/doc/doc-fixable.rs +++ b/src/tools/clippy/tests/ui/doc/doc-fixable.rs @@ -3,7 +3,7 @@ #![allow(dead_code, incomplete_features)] #![warn(clippy::doc_markdown)] -#![feature(custom_inner_attributes, generic_const_exprs, const_option)] +#![feature(custom_inner_attributes, generic_const_exprs)] #![rustfmt::skip] /// The foo_bar function does _nothing_. See also foo::bar. (note the dot there) diff --git a/src/tools/miri/src/lib.rs b/src/tools/miri/src/lib.rs index 330147c8f1cf8..f089d1e1bcc36 100644 --- a/src/tools/miri/src/lib.rs +++ b/src/tools/miri/src/lib.rs @@ -1,6 +1,5 @@ #![feature(rustc_private)] #![feature(cell_update)] -#![feature(const_option)] #![feature(float_gamma)] #![feature(map_try_insert)] #![feature(never_type)] diff --git a/tests/ui/consts/const-unwrap.rs b/tests/ui/consts/const-unwrap.rs index bc79c7db2fc80..ea0a15af1be77 100644 --- a/tests/ui/consts/const-unwrap.rs +++ b/tests/ui/consts/const-unwrap.rs @@ -1,11 +1,15 @@ //@ check-fail - -#![feature(const_option)] +// Verify that panicking `const_option` methods do the correct thing const FOO: i32 = Some(42i32).unwrap(); const BAR: i32 = Option::::None.unwrap(); -//~^ERROR: evaluation of constant value failed +//~^ ERROR: evaluation of constant value failed +//~| NOTE: the evaluated program panicked + +const BAZ: i32 = Option::::None.expect("absolutely not!"); +//~^ ERROR: evaluation of constant value failed +//~| NOTE: absolutely not! fn main() { println!("{}", FOO); diff --git a/tests/ui/consts/const-unwrap.stderr b/tests/ui/consts/const-unwrap.stderr index fee22a1d070b8..aa5dd9a5c36c8 100644 --- a/tests/ui/consts/const-unwrap.stderr +++ b/tests/ui/consts/const-unwrap.stderr @@ -1,9 +1,15 @@ error[E0080]: evaluation of constant value failed - --> $DIR/const-unwrap.rs:7:18 + --> $DIR/const-unwrap.rs:6:18 | LL | const BAR: i32 = Option::::None.unwrap(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'called `Option::unwrap()` on a `None` value', $DIR/const-unwrap.rs:7:38 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'called `Option::unwrap()` on a `None` value', $DIR/const-unwrap.rs:6:38 -error: aborting due to 1 previous error +error[E0080]: evaluation of constant value failed + --> $DIR/const-unwrap.rs:10:18 + | +LL | const BAZ: i32 = Option::::None.expect("absolutely not!"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'absolutely not!', $DIR/const-unwrap.rs:10:38 + +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0080`. From 46b41b4fc89d10099dcb04a876bd95be8426519a Mon Sep 17 00:00:00 2001 From: printfn Date: Sat, 12 Oct 2024 21:57:50 +0000 Subject: [PATCH 2146/2194] Update unicode-width to 0.2.0 --- Cargo.lock | 32 +++++++++++++++++++------------- compiler/rustc_parse/Cargo.toml | 2 +- compiler/rustc_span/Cargo.toml | 2 +- 3 files changed, 21 insertions(+), 15 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index c62c379f70d7b..b50b44bd077b4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -96,7 +96,7 @@ version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ccaf7e9dfbb6ab22c82e473cd1a8a7bd313c19a5b7e40970f3d89ef5a5c9e81e" dependencies = [ - "unicode-width", + "unicode-width 0.1.14", "yansi-term", ] @@ -107,7 +107,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "24e35ed54e5ea7997c14ed4c70ba043478db1112e98263b3b035907aa197d991" dependencies = [ "anstyle", - "unicode-width", + "unicode-width 0.1.14", ] [[package]] @@ -168,7 +168,7 @@ dependencies = [ "anstyle", "anstyle-lossy", "html-escape", - "unicode-width", + "unicode-width 0.1.14", ] [[package]] @@ -737,7 +737,7 @@ dependencies = [ "encode_unicode", "lazy_static", "libc", - "unicode-width", + "unicode-width 0.1.14", "windows-sys 0.52.0", ] @@ -1425,7 +1425,7 @@ version = "0.2.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "14dbbfd5c71d70241ecf9e6f13737f7b5ce823821063188d7e46c41d371eebd5" dependencies = [ - "unicode-width", + "unicode-width 0.1.14", ] [[package]] @@ -1788,7 +1788,7 @@ dependencies = [ "instant", "number_prefix", "portable-atomic", - "unicode-width", + "unicode-width 0.1.14", ] [[package]] @@ -2590,7 +2590,7 @@ version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d2ad9b889f1b12e0b9ee24db044b5129150d5eada288edc800f789928dc8c0e3" dependencies = [ - "unicode-width", + "unicode-width 0.1.14", ] [[package]] @@ -2601,7 +2601,7 @@ checksum = "9ad43c07024ef767f9160710b3a6773976194758c7919b17e63b863db0bdf7fb" dependencies = [ "bytecount", "fnv", - "unicode-width", + "unicode-width 0.1.14", ] [[package]] @@ -4188,7 +4188,7 @@ dependencies = [ "thin-vec", "tracing", "unicode-normalization", - "unicode-width", + "unicode-width 0.2.0", ] [[package]] @@ -4422,7 +4422,7 @@ dependencies = [ "sha1", "sha2", "tracing", - "unicode-width", + "unicode-width 0.2.0", ] [[package]] @@ -4687,7 +4687,7 @@ dependencies = [ "tracing-subscriber", "unicode-properties", "unicode-segmentation", - "unicode-width", + "unicode-width 0.1.14", ] [[package]] @@ -5097,7 +5097,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4c998b0c8b921495196a48aabaf1901ff28be0760136e31604f7967b0792050e" dependencies = [ "papergrid", - "unicode-width", + "unicode-width 0.1.14", ] [[package]] @@ -5646,6 +5646,12 @@ version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af" +[[package]] +name = "unicode-width" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fc81956842c57dac11422a97c3b8195a1ff727f06e85c84ed2e8aa277c9a0fd" + [[package]] name = "unicode-xid" version = "0.2.6" @@ -5894,7 +5900,7 @@ dependencies = [ "bumpalo", "leb128", "memchr", - "unicode-width", + "unicode-width 0.1.14", "wasm-encoder 0.219.0", ] diff --git a/compiler/rustc_parse/Cargo.toml b/compiler/rustc_parse/Cargo.toml index c59ae48a07d03..2360914a0aba1 100644 --- a/compiler/rustc_parse/Cargo.toml +++ b/compiler/rustc_parse/Cargo.toml @@ -20,7 +20,7 @@ rustc_span = { path = "../rustc_span" } thin-vec = "0.2.12" tracing = "0.1" unicode-normalization = "0.1.11" -unicode-width = "0.1.4" +unicode-width = "0.2.0" # tidy-alphabetical-end [dev-dependencies] diff --git a/compiler/rustc_span/Cargo.toml b/compiler/rustc_span/Cargo.toml index c52d1fcc07fe2..781fe6a11fe8d 100644 --- a/compiler/rustc_span/Cargo.toml +++ b/compiler/rustc_span/Cargo.toml @@ -19,5 +19,5 @@ scoped-tls = "1.0" sha1 = "0.10.0" sha2 = "0.10.1" tracing = "0.1" -unicode-width = "0.1.4" +unicode-width = "0.2.0" # tidy-alphabetical-end From 4d59c33780c6d264da8bf37d82a74a4d95bba7e7 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Sat, 12 Oct 2024 16:37:27 +1100 Subject: [PATCH 2147/2194] Rename `HeaderLine` to `DirectiveLine` --- src/tools/compiletest/src/header.rs | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs index 63d05886166ae..c833793585d16 100644 --- a/src/tools/compiletest/src/header.rs +++ b/src/tools/compiletest/src/header.rs @@ -57,7 +57,7 @@ impl EarlyProps { &mut poisoned, testfile, rdr, - &mut |HeaderLine { directive: ln, .. }| { + &mut |DirectiveLine { directive: ln, .. }| { parse_and_update_aux(config, ln, &mut props.aux); config.parse_and_update_revisions(ln, &mut props.revisions); }, @@ -344,7 +344,7 @@ impl TestProps { &mut poisoned, testfile, file, - &mut |HeaderLine { header_revision, directive: ln, .. }| { + &mut |DirectiveLine { header_revision, directive: ln, .. }| { if header_revision.is_some() && header_revision != test_revision { return; } @@ -680,7 +680,7 @@ impl TestProps { /// Extract an `(Option, directive)` directive from a line if comment is present. /// -/// See [`HeaderLine`] for a diagram. +/// See [`DirectiveLine`] for a diagram. pub fn line_directive<'line>( comment: &str, original_line: &'line str, @@ -745,7 +745,7 @@ const KNOWN_JSONDOCCK_DIRECTIVE_NAMES: &[&str] = /// ^^^^^^^^^^^^^^^^^ directive /// ^^^^^^^^^^^^^^^^^^^^^^^^^^^ original_line /// ``` -struct HeaderLine<'ln> { +struct DirectiveLine<'ln> { line_number: usize, /// Raw line from the test file, including comment prefix and any revision. original_line: &'ln str, @@ -803,7 +803,7 @@ fn iter_header( poisoned: &mut bool, testfile: &Path, rdr: impl Read, - it: &mut dyn FnMut(HeaderLine<'_>), + it: &mut dyn FnMut(DirectiveLine<'_>), ) { if testfile.is_dir() { return; @@ -824,7 +824,12 @@ fn iter_header( ]; // Process the extra implied directives, with a dummy line number of 0. for directive in extra_directives { - it(HeaderLine { line_number: 0, original_line: "", header_revision: None, directive }); + it(DirectiveLine { + line_number: 0, + original_line: "", + header_revision: None, + directive, + }); } } @@ -897,7 +902,7 @@ fn iter_header( } } - it(HeaderLine { + it(DirectiveLine { line_number, original_line, header_revision, @@ -1292,7 +1297,7 @@ pub fn make_test_description( &mut local_poisoned, path, src, - &mut |HeaderLine { header_revision, original_line, directive: ln, line_number }| { + &mut |DirectiveLine { header_revision, original_line, directive: ln, line_number }| { if header_revision.is_some() && header_revision != test_revision { return; } From f51088021cbb7c683c4de83c42dac2b9e4dbead2 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Sat, 12 Oct 2024 16:33:18 +1100 Subject: [PATCH 2148/2194] Remove the one thing that was checking a directive's `original_line` --- src/tools/compiletest/src/header.rs | 32 ++++------------------------- 1 file changed, 4 insertions(+), 28 deletions(-) diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs index c833793585d16..c5f163dab1e38 100644 --- a/src/tools/compiletest/src/header.rs +++ b/src/tools/compiletest/src/header.rs @@ -738,17 +738,13 @@ const KNOWN_JSONDOCCK_DIRECTIVE_NAMES: &[&str] = /// ```text /// //@ compile-flags: -O /// ^^^^^^^^^^^^^^^^^ directive -/// ^^^^^^^^^^^^^^^^^^^^^ original_line /// /// //@ [foo] compile-flags: -O /// ^^^ header_revision /// ^^^^^^^^^^^^^^^^^ directive -/// ^^^^^^^^^^^^^^^^^^^^^^^^^^^ original_line /// ``` struct DirectiveLine<'ln> { line_number: usize, - /// Raw line from the test file, including comment prefix and any revision. - original_line: &'ln str, /// Some header directives start with a revision name in square brackets /// (e.g. `[foo]`), and only apply to that revision of the test. /// If present, this field contains the revision name (e.g. `foo`). @@ -824,12 +820,7 @@ fn iter_header( ]; // Process the extra implied directives, with a dummy line number of 0. for directive in extra_directives { - it(DirectiveLine { - line_number: 0, - original_line: "", - header_revision: None, - directive, - }); + it(DirectiveLine { line_number: 0, header_revision: None, directive }); } } @@ -846,11 +837,6 @@ fn iter_header( if rdr.read_line(&mut ln).unwrap() == 0 { break; } - - // Assume that any directives will be found before the first - // module or function. This doesn't seem to be an optimization - // with a warm page cache. Maybe with a cold one. - let original_line = &ln; let ln = ln.trim(); // Assume that any directives will be found before the first module or function. This @@ -904,7 +890,6 @@ fn iter_header( it(DirectiveLine { line_number, - original_line, header_revision, directive: non_revisioned_directive_line, }); @@ -1291,13 +1276,14 @@ pub fn make_test_description( let mut local_poisoned = false; + // Scan through the test file to handle `ignore-*`, `only-*`, and `needs-*` directives. iter_header( config.mode, &config.suite, &mut local_poisoned, path, src, - &mut |DirectiveLine { header_revision, original_line, directive: ln, line_number }| { + &mut |DirectiveLine { header_revision, directive: ln, line_number }| { if header_revision.is_some() && header_revision != test_revision { return; } @@ -1322,17 +1308,7 @@ pub fn make_test_description( }; } - if let Some((_, post)) = original_line.trim_start().split_once("//") { - let post = post.trim_start(); - if post.starts_with("ignore-tidy") { - // Not handled by compiletest. - } else { - decision!(cfg::handle_ignore(config, ln)); - } - } else { - decision!(cfg::handle_ignore(config, ln)); - } - + decision!(cfg::handle_ignore(config, ln)); decision!(cfg::handle_only(config, ln)); decision!(needs::handle_needs(&cache.needs, config, ln)); decision!(ignore_llvm(config, ln)); From 9f0f0352f7b6fd9c4062cc4f161ae35d33fb37c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=AE=B8=E6=9D=B0=E5=8F=8B=20Jieyou=20Xu=20=28Joe=29?= <39484203+jieyouxu@users.noreply.github.com> Date: Sun, 13 Oct 2024 00:35:25 +0800 Subject: [PATCH 2149/2194] Error on trying to use revisions in `run-make` tests Currently `run-make` tests do not support revisions. --- src/tools/compiletest/src/header.rs | 17 +++++++++++++---- src/tools/compiletest/src/header/tests.rs | 2 +- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs index 63d05886166ae..b0aa50e894070 100644 --- a/src/tools/compiletest/src/header.rs +++ b/src/tools/compiletest/src/header.rs @@ -59,7 +59,7 @@ impl EarlyProps { rdr, &mut |HeaderLine { directive: ln, .. }| { parse_and_update_aux(config, ln, &mut props.aux); - config.parse_and_update_revisions(ln, &mut props.revisions); + config.parse_and_update_revisions(testfile, ln, &mut props.revisions); }, ); @@ -391,7 +391,7 @@ impl TestProps { has_edition = true; } - config.parse_and_update_revisions(ln, &mut self.revisions); + config.parse_and_update_revisions(testfile, ln, &mut self.revisions); if let Some(flags) = config.parse_name_value_directive(ln, RUN_FLAGS) { self.run_flags.extend(split_flags(&flags)); @@ -907,12 +907,21 @@ fn iter_header( } impl Config { - fn parse_and_update_revisions(&self, line: &str, existing: &mut Vec) { + fn parse_and_update_revisions(&self, testfile: &Path, line: &str, existing: &mut Vec) { if let Some(raw) = self.parse_name_value_directive(line, "revisions") { + if self.mode == Mode::RunMake { + panic!("`run-make` tests do not support revisions: {}", testfile.display()); + } + let mut duplicates: HashSet<_> = existing.iter().cloned().collect(); for revision in raw.split_whitespace().map(|r| r.to_string()) { if !duplicates.insert(revision.clone()) { - panic!("Duplicate revision: `{}` in line `{}`", revision, raw); + panic!( + "duplicate revision: `{}` in line `{}`: {}", + revision, + raw, + testfile.display() + ); } existing.push(revision); } diff --git a/src/tools/compiletest/src/header/tests.rs b/src/tools/compiletest/src/header/tests.rs index 22dfa349e2bc3..c3c9496c4d2d9 100644 --- a/src/tools/compiletest/src/header/tests.rs +++ b/src/tools/compiletest/src/header/tests.rs @@ -423,7 +423,7 @@ fn test_extract_version_range() { } #[test] -#[should_panic(expected = "Duplicate revision: `rpass1` in line ` rpass1 rpass1`")] +#[should_panic(expected = "duplicate revision: `rpass1` in line ` rpass1 rpass1`")] fn test_duplicate_revisions() { let config: Config = cfg().build(); parse_rs(&config, "//@ revisions: rpass1 rpass1"); From 3c6ed4e5418fe8dbc40cfe8c3895dccde8cd7498 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Sun, 13 Oct 2024 17:26:25 +1100 Subject: [PATCH 2150/2194] Move debugger setup code out of `lib.rs` --- src/tools/compiletest/src/debuggers.rs | 272 +++++++++++++++++ src/tools/compiletest/src/header.rs | 2 +- src/tools/compiletest/src/lib.rs | 281 +----------------- .../compiletest/src/runtest/debuginfo.rs | 2 +- src/tools/compiletest/src/tests.rs | 7 +- 5 files changed, 290 insertions(+), 274 deletions(-) create mode 100644 src/tools/compiletest/src/debuggers.rs diff --git a/src/tools/compiletest/src/debuggers.rs b/src/tools/compiletest/src/debuggers.rs new file mode 100644 index 0000000000000..b605bc813f195 --- /dev/null +++ b/src/tools/compiletest/src/debuggers.rs @@ -0,0 +1,272 @@ +use std::env; +use std::ffi::OsString; +use std::path::PathBuf; +use std::process::Command; +use std::sync::Arc; + +use crate::common::{Config, Debugger}; + +pub(crate) fn configure_cdb(config: &Config) -> Option> { + config.cdb.as_ref()?; + + Some(Arc::new(Config { debugger: Some(Debugger::Cdb), ..config.clone() })) +} + +pub(crate) fn configure_gdb(config: &Config) -> Option> { + config.gdb_version?; + + if config.matches_env("msvc") { + return None; + } + + if config.remote_test_client.is_some() && !config.target.contains("android") { + println!( + "WARNING: debuginfo tests are not available when \ + testing with remote" + ); + return None; + } + + if config.target.contains("android") { + println!( + "{} debug-info test uses tcp 5039 port.\ + please reserve it", + config.target + ); + + // android debug-info test uses remote debugger so, we test 1 thread + // at once as they're all sharing the same TCP port to communicate + // over. + // + // we should figure out how to lift this restriction! (run them all + // on different ports allocated dynamically). + env::set_var("RUST_TEST_THREADS", "1"); + } + + Some(Arc::new(Config { debugger: Some(Debugger::Gdb), ..config.clone() })) +} + +pub(crate) fn configure_lldb(config: &Config) -> Option> { + config.lldb_python_dir.as_ref()?; + + if let Some(350) = config.lldb_version { + println!( + "WARNING: The used version of LLDB (350) has a \ + known issue that breaks debuginfo tests. See \ + issue #32520 for more information. Skipping all \ + LLDB-based tests!", + ); + return None; + } + + Some(Arc::new(Config { debugger: Some(Debugger::Lldb), ..config.clone() })) +} + +/// Returns `true` if the given target is an Android target for the +/// purposes of GDB testing. +pub(crate) fn is_android_gdb_target(target: &str) -> bool { + matches!( + &target[..], + "arm-linux-androideabi" | "armv7-linux-androideabi" | "aarch64-linux-android" + ) +} + +/// Returns `true` if the given target is a MSVC target for the purposes of CDB testing. +fn is_pc_windows_msvc_target(target: &str) -> bool { + target.ends_with("-pc-windows-msvc") +} + +fn find_cdb(target: &str) -> Option { + if !(cfg!(windows) && is_pc_windows_msvc_target(target)) { + return None; + } + + let pf86 = env::var_os("ProgramFiles(x86)").or_else(|| env::var_os("ProgramFiles"))?; + let cdb_arch = if cfg!(target_arch = "x86") { + "x86" + } else if cfg!(target_arch = "x86_64") { + "x64" + } else if cfg!(target_arch = "aarch64") { + "arm64" + } else if cfg!(target_arch = "arm") { + "arm" + } else { + return None; // No compatible CDB.exe in the Windows 10 SDK + }; + + let mut path = PathBuf::new(); + path.push(pf86); + path.push(r"Windows Kits\10\Debuggers"); // We could check 8.1 etc. too? + path.push(cdb_arch); + path.push(r"cdb.exe"); + + if !path.exists() { + return None; + } + + Some(path.into_os_string()) +} + +/// Returns Path to CDB +pub(crate) fn analyze_cdb( + cdb: Option, + target: &str, +) -> (Option, Option<[u16; 4]>) { + let cdb = cdb.map(OsString::from).or_else(|| find_cdb(target)); + + let mut version = None; + if let Some(cdb) = cdb.as_ref() { + if let Ok(output) = Command::new(cdb).arg("/version").output() { + if let Some(first_line) = String::from_utf8_lossy(&output.stdout).lines().next() { + version = extract_cdb_version(&first_line); + } + } + } + + (cdb, version) +} + +pub(crate) fn extract_cdb_version(full_version_line: &str) -> Option<[u16; 4]> { + // Example full_version_line: "cdb version 10.0.18362.1" + let version = full_version_line.rsplit(' ').next()?; + let mut components = version.split('.'); + let major: u16 = components.next().unwrap().parse().unwrap(); + let minor: u16 = components.next().unwrap().parse().unwrap(); + let patch: u16 = components.next().unwrap_or("0").parse().unwrap(); + let build: u16 = components.next().unwrap_or("0").parse().unwrap(); + Some([major, minor, patch, build]) +} + +/// Returns (Path to GDB, GDB Version) +pub(crate) fn analyze_gdb( + gdb: Option, + target: &str, + android_cross_path: &PathBuf, +) -> (Option, Option) { + #[cfg(not(windows))] + const GDB_FALLBACK: &str = "gdb"; + #[cfg(windows)] + const GDB_FALLBACK: &str = "gdb.exe"; + + let fallback_gdb = || { + if is_android_gdb_target(target) { + let mut gdb_path = match android_cross_path.to_str() { + Some(x) => x.to_owned(), + None => panic!("cannot find android cross path"), + }; + gdb_path.push_str("/bin/gdb"); + gdb_path + } else { + GDB_FALLBACK.to_owned() + } + }; + + let gdb = match gdb { + None => fallback_gdb(), + Some(ref s) if s.is_empty() => fallback_gdb(), // may be empty if configure found no gdb + Some(ref s) => s.to_owned(), + }; + + let mut version_line = None; + if let Ok(output) = Command::new(&gdb).arg("--version").output() { + if let Some(first_line) = String::from_utf8_lossy(&output.stdout).lines().next() { + version_line = Some(first_line.to_string()); + } + } + + let version = match version_line { + Some(line) => extract_gdb_version(&line), + None => return (None, None), + }; + + (Some(gdb), version) +} + +pub(crate) fn extract_gdb_version(full_version_line: &str) -> Option { + let full_version_line = full_version_line.trim(); + + // GDB versions look like this: "major.minor.patch?.yyyymmdd?", with both + // of the ? sections being optional + + // We will parse up to 3 digits for each component, ignoring the date + + // We skip text in parentheses. This avoids accidentally parsing + // the openSUSE version, which looks like: + // GNU gdb (GDB; openSUSE Leap 15.0) 8.1 + // This particular form is documented in the GNU coding standards: + // https://www.gnu.org/prep/standards/html_node/_002d_002dversion.html#g_t_002d_002dversion + + let unbracketed_part = full_version_line.split('[').next().unwrap(); + let mut splits = unbracketed_part.trim_end().rsplit(' '); + let version_string = splits.next().unwrap(); + + let mut splits = version_string.split('.'); + let major = splits.next().unwrap(); + let minor = splits.next().unwrap(); + let patch = splits.next(); + + let major: u32 = major.parse().unwrap(); + let (minor, patch): (u32, u32) = match minor.find(not_a_digit) { + None => { + let minor = minor.parse().unwrap(); + let patch: u32 = match patch { + Some(patch) => match patch.find(not_a_digit) { + None => patch.parse().unwrap(), + Some(idx) if idx > 3 => 0, + Some(idx) => patch[..idx].parse().unwrap(), + }, + None => 0, + }; + (minor, patch) + } + // There is no patch version after minor-date (e.g. "4-2012"). + Some(idx) => { + let minor = minor[..idx].parse().unwrap(); + (minor, 0) + } + }; + + Some(((major * 1000) + minor) * 1000 + patch) +} + +/// Returns LLDB version +pub(crate) fn extract_lldb_version(full_version_line: &str) -> Option { + // Extract the major LLDB version from the given version string. + // LLDB version strings are different for Apple and non-Apple platforms. + // The Apple variant looks like this: + // + // LLDB-179.5 (older versions) + // lldb-300.2.51 (new versions) + // + // We are only interested in the major version number, so this function + // will return `Some(179)` and `Some(300)` respectively. + // + // Upstream versions look like: + // lldb version 6.0.1 + // + // There doesn't seem to be a way to correlate the Apple version + // with the upstream version, and since the tests were originally + // written against Apple versions, we make a fake Apple version by + // multiplying the first number by 100. This is a hack. + + let full_version_line = full_version_line.trim(); + + if let Some(apple_ver) = + full_version_line.strip_prefix("LLDB-").or_else(|| full_version_line.strip_prefix("lldb-")) + { + if let Some(idx) = apple_ver.find(not_a_digit) { + let version: u32 = apple_ver[..idx].parse().unwrap(); + return Some(version); + } + } else if let Some(lldb_ver) = full_version_line.strip_prefix("lldb version ") { + if let Some(idx) = lldb_ver.find(not_a_digit) { + let version: u32 = lldb_ver[..idx].parse().ok()?; + return Some(version * 100); + } + } + None +} + +fn not_a_digit(c: char) -> bool { + !c.is_ascii_digit() +} diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs index 63d05886166ae..a47cab50f217f 100644 --- a/src/tools/compiletest/src/header.rs +++ b/src/tools/compiletest/src/header.rs @@ -9,11 +9,11 @@ use std::process::Command; use tracing::*; use crate::common::{Config, Debugger, FailMode, Mode, PassMode}; +use crate::debuggers::{extract_cdb_version, extract_gdb_version}; use crate::header::auxiliary::{AuxProps, parse_and_update_aux}; use crate::header::cfg::{MatchOutcome, parse_cfg_name_directive}; use crate::header::needs::CachedNeedsConditions; use crate::util::static_regex; -use crate::{extract_cdb_version, extract_gdb_version}; pub(crate) mod auxiliary; mod cfg; diff --git a/src/tools/compiletest/src/lib.rs b/src/tools/compiletest/src/lib.rs index 30d1644b14836..18000e5602cb7 100644 --- a/src/tools/compiletest/src/lib.rs +++ b/src/tools/compiletest/src/lib.rs @@ -10,6 +10,7 @@ mod tests; pub mod common; pub mod compute_diff; +mod debuggers; pub mod errors; pub mod header; mod json; @@ -36,8 +37,8 @@ use walkdir::WalkDir; use self::header::{EarlyProps, make_test_description}; use crate::common::{ - Config, Debugger, Mode, PassMode, TestPaths, UI_EXTENSIONS, expected_output_path, - output_base_dir, output_relative_path, + Config, Mode, PassMode, TestPaths, UI_EXTENSIONS, expected_output_path, output_base_dir, + output_relative_path, }; use crate::header::HeadersCache; use crate::util::logv; @@ -204,9 +205,11 @@ pub fn parse_config(args: Vec) -> Config { let target = opt_str2(matches.opt_str("target")); let android_cross_path = opt_path(matches, "android-cross-path"); - let (cdb, cdb_version) = analyze_cdb(matches.opt_str("cdb"), &target); - let (gdb, gdb_version) = analyze_gdb(matches.opt_str("gdb"), &target, &android_cross_path); - let lldb_version = matches.opt_str("lldb-version").as_deref().and_then(extract_lldb_version); + let (cdb, cdb_version) = debuggers::analyze_cdb(matches.opt_str("cdb"), &target); + let (gdb, gdb_version) = + debuggers::analyze_gdb(matches.opt_str("gdb"), &target, &android_cross_path); + let lldb_version = + matches.opt_str("lldb-version").as_deref().and_then(debuggers::extract_lldb_version); let color = match matches.opt_str("color").as_deref() { Some("auto") | None => ColorConfig::AutoColor, Some("always") => ColorConfig::AlwaysColor, @@ -443,9 +446,9 @@ pub fn run_tests(config: Arc) { if let Mode::DebugInfo = config.mode { // Debugging emscripten code doesn't make sense today if !config.target.contains("emscripten") { - configs.extend(configure_cdb(&config)); - configs.extend(configure_gdb(&config)); - configs.extend(configure_lldb(&config)); + configs.extend(debuggers::configure_cdb(&config)); + configs.extend(debuggers::configure_gdb(&config)); + configs.extend(debuggers::configure_lldb(&config)); } } else { configs.push(config.clone()); @@ -498,62 +501,6 @@ pub fn run_tests(config: Arc) { } } -fn configure_cdb(config: &Config) -> Option> { - config.cdb.as_ref()?; - - Some(Arc::new(Config { debugger: Some(Debugger::Cdb), ..config.clone() })) -} - -fn configure_gdb(config: &Config) -> Option> { - config.gdb_version?; - - if config.matches_env("msvc") { - return None; - } - - if config.remote_test_client.is_some() && !config.target.contains("android") { - println!( - "WARNING: debuginfo tests are not available when \ - testing with remote" - ); - return None; - } - - if config.target.contains("android") { - println!( - "{} debug-info test uses tcp 5039 port.\ - please reserve it", - config.target - ); - - // android debug-info test uses remote debugger so, we test 1 thread - // at once as they're all sharing the same TCP port to communicate - // over. - // - // we should figure out how to lift this restriction! (run them all - // on different ports allocated dynamically). - env::set_var("RUST_TEST_THREADS", "1"); - } - - Some(Arc::new(Config { debugger: Some(Debugger::Gdb), ..config.clone() })) -} - -fn configure_lldb(config: &Config) -> Option> { - config.lldb_python_dir.as_ref()?; - - if let Some(350) = config.lldb_version { - println!( - "WARNING: The used version of LLDB (350) has a \ - known issue that breaks debuginfo tests. See \ - issue #32520 for more information. Skipping all \ - LLDB-based tests!", - ); - return None; - } - - Some(Arc::new(Config { debugger: Some(Debugger::Lldb), ..config.clone() })) -} - pub fn test_opts(config: &Config) -> test::TestOpts { if env::var("RUST_TEST_NOCAPTURE").is_ok() { eprintln!( @@ -981,212 +928,6 @@ fn make_test_closure( })) } -/// Returns `true` if the given target is an Android target for the -/// purposes of GDB testing. -fn is_android_gdb_target(target: &str) -> bool { - matches!( - &target[..], - "arm-linux-androideabi" | "armv7-linux-androideabi" | "aarch64-linux-android" - ) -} - -/// Returns `true` if the given target is a MSVC target for the purposes of CDB testing. -fn is_pc_windows_msvc_target(target: &str) -> bool { - target.ends_with("-pc-windows-msvc") -} - -fn find_cdb(target: &str) -> Option { - if !(cfg!(windows) && is_pc_windows_msvc_target(target)) { - return None; - } - - let pf86 = env::var_os("ProgramFiles(x86)").or_else(|| env::var_os("ProgramFiles"))?; - let cdb_arch = if cfg!(target_arch = "x86") { - "x86" - } else if cfg!(target_arch = "x86_64") { - "x64" - } else if cfg!(target_arch = "aarch64") { - "arm64" - } else if cfg!(target_arch = "arm") { - "arm" - } else { - return None; // No compatible CDB.exe in the Windows 10 SDK - }; - - let mut path = PathBuf::new(); - path.push(pf86); - path.push(r"Windows Kits\10\Debuggers"); // We could check 8.1 etc. too? - path.push(cdb_arch); - path.push(r"cdb.exe"); - - if !path.exists() { - return None; - } - - Some(path.into_os_string()) -} - -/// Returns Path to CDB -fn analyze_cdb(cdb: Option, target: &str) -> (Option, Option<[u16; 4]>) { - let cdb = cdb.map(OsString::from).or_else(|| find_cdb(target)); - - let mut version = None; - if let Some(cdb) = cdb.as_ref() { - if let Ok(output) = Command::new(cdb).arg("/version").output() { - if let Some(first_line) = String::from_utf8_lossy(&output.stdout).lines().next() { - version = extract_cdb_version(&first_line); - } - } - } - - (cdb, version) -} - -fn extract_cdb_version(full_version_line: &str) -> Option<[u16; 4]> { - // Example full_version_line: "cdb version 10.0.18362.1" - let version = full_version_line.rsplit(' ').next()?; - let mut components = version.split('.'); - let major: u16 = components.next().unwrap().parse().unwrap(); - let minor: u16 = components.next().unwrap().parse().unwrap(); - let patch: u16 = components.next().unwrap_or("0").parse().unwrap(); - let build: u16 = components.next().unwrap_or("0").parse().unwrap(); - Some([major, minor, patch, build]) -} - -/// Returns (Path to GDB, GDB Version) -fn analyze_gdb( - gdb: Option, - target: &str, - android_cross_path: &PathBuf, -) -> (Option, Option) { - #[cfg(not(windows))] - const GDB_FALLBACK: &str = "gdb"; - #[cfg(windows)] - const GDB_FALLBACK: &str = "gdb.exe"; - - let fallback_gdb = || { - if is_android_gdb_target(target) { - let mut gdb_path = match android_cross_path.to_str() { - Some(x) => x.to_owned(), - None => panic!("cannot find android cross path"), - }; - gdb_path.push_str("/bin/gdb"); - gdb_path - } else { - GDB_FALLBACK.to_owned() - } - }; - - let gdb = match gdb { - None => fallback_gdb(), - Some(ref s) if s.is_empty() => fallback_gdb(), // may be empty if configure found no gdb - Some(ref s) => s.to_owned(), - }; - - let mut version_line = None; - if let Ok(output) = Command::new(&gdb).arg("--version").output() { - if let Some(first_line) = String::from_utf8_lossy(&output.stdout).lines().next() { - version_line = Some(first_line.to_string()); - } - } - - let version = match version_line { - Some(line) => extract_gdb_version(&line), - None => return (None, None), - }; - - (Some(gdb), version) -} - -fn extract_gdb_version(full_version_line: &str) -> Option { - let full_version_line = full_version_line.trim(); - - // GDB versions look like this: "major.minor.patch?.yyyymmdd?", with both - // of the ? sections being optional - - // We will parse up to 3 digits for each component, ignoring the date - - // We skip text in parentheses. This avoids accidentally parsing - // the openSUSE version, which looks like: - // GNU gdb (GDB; openSUSE Leap 15.0) 8.1 - // This particular form is documented in the GNU coding standards: - // https://www.gnu.org/prep/standards/html_node/_002d_002dversion.html#g_t_002d_002dversion - - let unbracketed_part = full_version_line.split('[').next().unwrap(); - let mut splits = unbracketed_part.trim_end().rsplit(' '); - let version_string = splits.next().unwrap(); - - let mut splits = version_string.split('.'); - let major = splits.next().unwrap(); - let minor = splits.next().unwrap(); - let patch = splits.next(); - - let major: u32 = major.parse().unwrap(); - let (minor, patch): (u32, u32) = match minor.find(not_a_digit) { - None => { - let minor = minor.parse().unwrap(); - let patch: u32 = match patch { - Some(patch) => match patch.find(not_a_digit) { - None => patch.parse().unwrap(), - Some(idx) if idx > 3 => 0, - Some(idx) => patch[..idx].parse().unwrap(), - }, - None => 0, - }; - (minor, patch) - } - // There is no patch version after minor-date (e.g. "4-2012"). - Some(idx) => { - let minor = minor[..idx].parse().unwrap(); - (minor, 0) - } - }; - - Some(((major * 1000) + minor) * 1000 + patch) -} - -/// Returns LLDB version -fn extract_lldb_version(full_version_line: &str) -> Option { - // Extract the major LLDB version from the given version string. - // LLDB version strings are different for Apple and non-Apple platforms. - // The Apple variant looks like this: - // - // LLDB-179.5 (older versions) - // lldb-300.2.51 (new versions) - // - // We are only interested in the major version number, so this function - // will return `Some(179)` and `Some(300)` respectively. - // - // Upstream versions look like: - // lldb version 6.0.1 - // - // There doesn't seem to be a way to correlate the Apple version - // with the upstream version, and since the tests were originally - // written against Apple versions, we make a fake Apple version by - // multiplying the first number by 100. This is a hack. - - let full_version_line = full_version_line.trim(); - - if let Some(apple_ver) = - full_version_line.strip_prefix("LLDB-").or_else(|| full_version_line.strip_prefix("lldb-")) - { - if let Some(idx) = apple_ver.find(not_a_digit) { - let version: u32 = apple_ver[..idx].parse().unwrap(); - return Some(version); - } - } else if let Some(lldb_ver) = full_version_line.strip_prefix("lldb version ") { - if let Some(idx) = lldb_ver.find(not_a_digit) { - let version: u32 = lldb_ver[..idx].parse().ok()?; - return Some(version * 100); - } - } - None -} - -fn not_a_digit(c: char) -> bool { - !c.is_ascii_digit() -} - fn check_overlapping_tests(found_paths: &HashSet) { let mut collisions = Vec::new(); for path in found_paths { diff --git a/src/tools/compiletest/src/runtest/debuginfo.rs b/src/tools/compiletest/src/runtest/debuginfo.rs index 36127414ab147..bd0845b45241e 100644 --- a/src/tools/compiletest/src/runtest/debuginfo.rs +++ b/src/tools/compiletest/src/runtest/debuginfo.rs @@ -9,8 +9,8 @@ use tracing::debug; use super::debugger::DebuggerCommands; use super::{Debugger, Emit, ProcRes, TestCx, Truncated, WillExecute}; use crate::common::Config; +use crate::debuggers::{extract_gdb_version, is_android_gdb_target}; use crate::util::logv; -use crate::{extract_gdb_version, is_android_gdb_target}; impl TestCx<'_> { pub(super) fn run_debuginfo_test(&self) { diff --git a/src/tools/compiletest/src/tests.rs b/src/tools/compiletest/src/tests.rs index 7c2e7b0f023cc..680579c59aec5 100644 --- a/src/tools/compiletest/src/tests.rs +++ b/src/tools/compiletest/src/tests.rs @@ -1,5 +1,8 @@ -use super::header::extract_llvm_version; -use super::*; +use std::ffi::OsString; + +use crate::debuggers::{extract_gdb_version, extract_lldb_version}; +use crate::header::extract_llvm_version; +use crate::is_test; #[test] fn test_extract_gdb_version() { From 40ca4d8cd3c708bddb4bbba83288d1fe25fe5ab2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=AE=B8=E6=9D=B0=E5=8F=8B=20Jieyou=20Xu=20=28Joe=29?= <39484203+jieyouxu@users.noreply.github.com> Date: Sun, 13 Oct 2024 15:59:55 +0800 Subject: [PATCH 2151/2194] Special case error message for a `build-fail` test that failed check build --- src/tools/compiletest/src/runtest.rs | 25 ++++++++++++++++--- .../compiletest/src/runtest/incremental.rs | 4 +-- src/tools/compiletest/src/runtest/ui.rs | 4 +-- 3 files changed, 26 insertions(+), 7 deletions(-) diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 46f7b9c0e7de1..29f9925de16a2 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -318,10 +318,29 @@ impl<'test> TestCx<'test> { } } - fn check_if_test_should_compile(&self, proc_res: &ProcRes, pm: Option) { - if self.should_compile_successfully(pm) { + fn check_if_test_should_compile( + &self, + fail_mode: Option, + pass_mode: Option, + proc_res: &ProcRes, + ) { + if self.should_compile_successfully(pass_mode) { if !proc_res.status.success() { - self.fatal_proc_rec("test compilation failed although it shouldn't!", proc_res); + match (fail_mode, pass_mode) { + (Some(FailMode::Build), Some(PassMode::Check)) => { + // A `build-fail` test needs to `check-pass`. + self.fatal_proc_rec( + "`build-fail` test is required to pass check build, but check build failed", + proc_res, + ); + } + _ => { + self.fatal_proc_rec( + "test compilation failed although it shouldn't!", + proc_res, + ); + } + } } } else { if proc_res.status.success() { diff --git a/src/tools/compiletest/src/runtest/incremental.rs b/src/tools/compiletest/src/runtest/incremental.rs index bf2b71fef4378..591aff0defeb0 100644 --- a/src/tools/compiletest/src/runtest/incremental.rs +++ b/src/tools/compiletest/src/runtest/incremental.rs @@ -1,4 +1,4 @@ -use super::{TestCx, WillExecute}; +use super::{FailMode, TestCx, WillExecute}; use crate::errors; impl TestCx<'_> { @@ -96,7 +96,7 @@ impl TestCx<'_> { fn run_cfail_test(&self) { let pm = self.pass_mode(); let proc_res = self.compile_test(WillExecute::No, self.should_emit_metadata(pm)); - self.check_if_test_should_compile(&proc_res, pm); + self.check_if_test_should_compile(Some(FailMode::Build), pm, &proc_res); self.check_no_compiler_crash(&proc_res, self.props.should_ice); let output_to_check = self.get_output(&proc_res); diff --git a/src/tools/compiletest/src/runtest/ui.rs b/src/tools/compiletest/src/runtest/ui.rs index bd8ef952a863b..bb747c6802926 100644 --- a/src/tools/compiletest/src/runtest/ui.rs +++ b/src/tools/compiletest/src/runtest/ui.rs @@ -18,14 +18,14 @@ impl TestCx<'_> { let pm = Some(PassMode::Check); let proc_res = self.compile_test_general(WillExecute::No, Emit::Metadata, pm, Vec::new()); - self.check_if_test_should_compile(&proc_res, pm); + self.check_if_test_should_compile(self.props.fail_mode, pm, &proc_res); } let pm = self.pass_mode(); let should_run = self.should_run(pm); let emit_metadata = self.should_emit_metadata(pm); let proc_res = self.compile_test(should_run, emit_metadata); - self.check_if_test_should_compile(&proc_res, pm); + self.check_if_test_should_compile(self.props.fail_mode, pm, &proc_res); if matches!(proc_res.truncated, Truncated::Yes) && !self.props.dont_check_compiler_stdout && !self.props.dont_check_compiler_stderr From 90e4f10f6c40d8bcf290f2ea7bf9c9d310de9d65 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 13 Oct 2024 10:02:51 +0200 Subject: [PATCH 2152/2194] switch unicode-data back to 'static' --- library/core/src/lib.rs | 1 + library/core/src/unicode/unicode_data.rs | 16 ++++++++-------- .../unicode-table-generator/src/raw_emitter.rs | 8 ++++---- 3 files changed, 13 insertions(+), 12 deletions(-) diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index 726aa209fdf43..b21618e28a48e 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -178,6 +178,7 @@ // tidy-alphabetical-start #![cfg_attr(bootstrap, feature(const_mut_refs))] #![cfg_attr(bootstrap, feature(const_refs_to_cell))] +#![cfg_attr(bootstrap, feature(const_refs_to_static))] #![feature(abi_unadjusted)] #![feature(adt_const_params)] #![feature(allow_internal_unsafe)] diff --git a/library/core/src/unicode/unicode_data.rs b/library/core/src/unicode/unicode_data.rs index db2e3ddd754f5..cba53bf5054e6 100644 --- a/library/core/src/unicode/unicode_data.rs +++ b/library/core/src/unicode/unicode_data.rs @@ -331,14 +331,14 @@ pub mod grapheme_extend { #[rustfmt::skip] pub mod lowercase { - const BITSET_CHUNKS_MAP: &'static [u8; 123] = &[ + static BITSET_CHUNKS_MAP: [u8; 123] = [ 14, 17, 0, 0, 9, 0, 0, 12, 13, 10, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0, 15, 0, 8, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 3, 18, 0, 7, ]; - const BITSET_INDEX_CHUNKS: &'static [[u8; 16]; 20] = &[ + static BITSET_INDEX_CHUNKS: [[u8; 16]; 20] = [ [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 61, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 14, 56, 0], @@ -360,7 +360,7 @@ pub mod lowercase { [16, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [65, 41, 55, 12, 77, 63, 18, 1, 7, 64, 76, 20, 73, 74, 4, 45], ]; - const BITSET_CANONICAL: &'static [u64; 56] = &[ + static BITSET_CANONICAL: [u64; 56] = [ 0b0000000000000000000000000000000000000000000000000000000000000000, 0b1111111111111111110000000000000000000000000011111111111111111111, 0b1010101010101010101010101010101010101010101010101010100000000010, @@ -418,7 +418,7 @@ pub mod lowercase { 0b1110011001010001001011010010101001001110001001000011000100101001, 0b1110101111000000000000000000000000001111111111111111111111111100, ]; - const BITSET_MAPPING: &'static [(u8, u8); 22] = &[ + static BITSET_MAPPING: [(u8, u8); 22] = [ (0, 64), (1, 188), (1, 186), (1, 183), (1, 176), (1, 109), (1, 124), (1, 126), (1, 66), (1, 70), (1, 77), (2, 146), (2, 144), (2, 83), (3, 93), (3, 147), (3, 133), (4, 12), (4, 6), (5, 187), (6, 78), (7, 132), @@ -471,14 +471,14 @@ pub mod n { #[rustfmt::skip] pub mod uppercase { - const BITSET_CHUNKS_MAP: &'static [u8; 125] = &[ + static BITSET_CHUNKS_MAP: [u8; 125] = [ 12, 15, 6, 6, 0, 6, 6, 2, 4, 11, 6, 16, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 8, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 5, 6, 14, 6, 10, 6, 6, 1, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 13, 6, 6, 6, 6, 9, 6, 3, ]; - const BITSET_INDEX_CHUNKS: &'static [[u8; 16]; 17] = &[ + static BITSET_INDEX_CHUNKS: [[u8; 16]; 17] = [ [44, 44, 5, 35, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 5, 1], [44, 44, 5, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44], [44, 44, 40, 44, 44, 44, 44, 44, 17, 17, 63, 17, 43, 29, 24, 23], @@ -497,7 +497,7 @@ pub mod uppercase { [58, 19, 2, 18, 10, 48, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44], [58, 38, 17, 27, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44], ]; - const BITSET_CANONICAL: &'static [u64; 44] = &[ + static BITSET_CANONICAL: [u64; 44] = [ 0b0000011111111111111111111111111000000000000000000000000000000000, 0b0000000000111111111111111111111111111111111111111111111111111111, 0b0101010101010101010101010101010101010101010101010101010000000001, @@ -543,7 +543,7 @@ pub mod uppercase { 0b1111011111111111000000000000000000000000000000000000000000000000, 0b1111111100000000111111110000000000111111000000001111111100000000, ]; - const BITSET_MAPPING: &'static [(u8, u8); 25] = &[ + static BITSET_MAPPING: [(u8, u8); 25] = [ (0, 187), (0, 177), (0, 171), (0, 167), (0, 164), (0, 32), (0, 47), (0, 51), (0, 121), (0, 117), (0, 109), (1, 150), (1, 148), (1, 142), (1, 134), (1, 131), (1, 64), (2, 164), (2, 146), (2, 20), (3, 146), (3, 140), (3, 134), (4, 178), (4, 171), diff --git a/src/tools/unicode-table-generator/src/raw_emitter.rs b/src/tools/unicode-table-generator/src/raw_emitter.rs index bfffa1eee600d..8097d6a8caf35 100644 --- a/src/tools/unicode-table-generator/src/raw_emitter.rs +++ b/src/tools/unicode-table-generator/src/raw_emitter.rs @@ -77,7 +77,7 @@ impl RawEmitter { writeln!( &mut self.file, - "const BITSET_CANONICAL: &'static [u64; {}] = &[{}];", + "static BITSET_CANONICAL: [u64; {}] = [{}];", canonicalized.canonical_words.len(), fmt_list(canonicalized.canonical_words.iter().map(|v| Bits(*v))), ) @@ -85,7 +85,7 @@ impl RawEmitter { self.bytes_used += 8 * canonicalized.canonical_words.len(); writeln!( &mut self.file, - "const BITSET_MAPPING: &'static [(u8, u8); {}] = &[{}];", + "static BITSET_MAPPING: [(u8, u8); {}] = [{}];", canonicalized.canonicalized_words.len(), fmt_list(&canonicalized.canonicalized_words), ) @@ -139,7 +139,7 @@ impl RawEmitter { writeln!( &mut self.file, - "const BITSET_CHUNKS_MAP: &'static [u8; {}] = &[{}];", + "static BITSET_CHUNKS_MAP: [u8; {}] = [{}];", chunk_indices.len(), fmt_list(&chunk_indices), ) @@ -147,7 +147,7 @@ impl RawEmitter { self.bytes_used += chunk_indices.len(); writeln!( &mut self.file, - "const BITSET_INDEX_CHUNKS: &'static [[u8; {}]; {}] = &[{}];", + "static BITSET_INDEX_CHUNKS: [[u8; {}]; {}] = [{}];", chunk_length, chunks.len(), fmt_list(chunks.iter()), From 567fd9610cbfd220844443487059335d7e1ff021 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Mon, 14 Oct 2024 10:22:50 -0700 Subject: [PATCH 2153/2194] replace placeholder version --- compiler/rustc_feature/src/accepted.rs | 10 ++++---- compiler/rustc_feature/src/removed.rs | 4 ++-- compiler/rustc_feature/src/unstable.rs | 14 +++++------ library/core/src/array/mod.rs | 2 +- library/core/src/cell.rs | 8 +++---- library/core/src/cell/once.rs | 2 +- library/core/src/char/methods.rs | 6 ++--- library/core/src/fmt/builders.rs | 8 +++---- library/core/src/intrinsics.rs | 20 ++++++++-------- library/core/src/mem/maybe_uninit.rs | 5 +--- library/core/src/mem/mod.rs | 2 +- library/core/src/num/f32.rs | 32 ++++++++++++------------- library/core/src/num/f64.rs | 32 ++++++++++++------------- library/core/src/ops/control_flow.rs | 8 +++---- library/core/src/option.rs | 22 ++++++++--------- library/core/src/ptr/const_ptr.rs | 6 ++--- library/core/src/ptr/metadata.rs | 6 ++--- library/core/src/ptr/mod.rs | 8 +++---- library/core/src/ptr/mut_ptr.rs | 16 ++++++------- library/core/src/ptr/non_null.rs | 21 +++++++--------- library/core/src/result.rs | 8 +++---- library/core/src/slice/mod.rs | 22 ++++++++--------- library/core/src/slice/raw.rs | 4 ++-- library/core/src/str/converts.rs | 5 +--- library/core/src/str/mod.rs | 4 ++-- library/core/src/task/wake.rs | 8 +++---- library/core/src/time.rs | 8 +++---- library/std/src/collections/hash/map.rs | 20 ++++++++-------- library/std/src/collections/hash/set.rs | 4 ++-- library/std/src/io/error.rs | 32 ++++++++++++------------- library/std/src/io/mod.rs | 2 +- 31 files changed, 170 insertions(+), 179 deletions(-) diff --git a/compiler/rustc_feature/src/accepted.rs b/compiler/rustc_feature/src/accepted.rs index a850eb956207e..0c5fe6e8d8b76 100644 --- a/compiler/rustc_feature/src/accepted.rs +++ b/compiler/rustc_feature/src/accepted.rs @@ -116,7 +116,7 @@ declare_features! ( /// Allows calling constructor functions in `const fn`. (accepted, const_constructor, "1.40.0", Some(61456)), /// Allows the definition of `const extern fn` and `const unsafe extern fn`. - (accepted, const_extern_fn, "CURRENT_RUSTC_VERSION", Some(64926)), + (accepted, const_extern_fn, "1.83.0", Some(64926)), /// Allows basic arithmetic on floating point types in a `const fn`. (accepted, const_fn_floating_point_arithmetic, "1.82.0", Some(57241)), /// Allows using and casting function pointers in a `const fn`. @@ -144,15 +144,15 @@ declare_features! ( /// Allows the use of `loop` and `while` in constants. (accepted, const_loop, "1.46.0", Some(52000)), /// Allows using `&mut` in constant functions. - (accepted, const_mut_refs, "CURRENT_RUSTC_VERSION", Some(57349)), + (accepted, const_mut_refs, "1.83.0", Some(57349)), /// Allows panicking during const eval (producing compile-time errors). (accepted, const_panic, "1.57.0", Some(51999)), /// Allows dereferencing raw pointers during const eval. (accepted, const_raw_ptr_deref, "1.58.0", Some(51911)), /// Allows references to types with interior mutability within constants - (accepted, const_refs_to_cell, "CURRENT_RUSTC_VERSION", Some(80384)), + (accepted, const_refs_to_cell, "1.83.0", Some(80384)), /// Allows creating pointers and references to `static` items in constants. - (accepted, const_refs_to_static, "CURRENT_RUSTC_VERSION", Some(119618)), + (accepted, const_refs_to_static, "1.83.0", Some(119618)), /// Allows implementing `Copy` for closures where possible (RFC 2132). (accepted, copy_closures, "1.26.0", Some(44490)), /// Allows `crate` in paths. @@ -190,7 +190,7 @@ declare_features! ( /// Allows explicit generic arguments specification with `impl Trait` present. (accepted, explicit_generic_args_with_impl_trait, "1.63.0", Some(83701)), /// Uses 2024 rules for matching `expr` fragments in macros. Also enables `expr_2021` fragment. - (accepted, expr_fragment_specifier_2024, "CURRENT_RUSTC_VERSION", Some(123742)), + (accepted, expr_fragment_specifier_2024, "1.83.0", Some(123742)), /// Allows arbitrary expressions in key-value attributes at parse time. (accepted, extended_key_value_attributes, "1.54.0", Some(78835)), /// Allows resolving absolute paths as paths from other crates. diff --git a/compiler/rustc_feature/src/removed.rs b/compiler/rustc_feature/src/removed.rs index cba4535156b8a..d797fee000dd9 100644 --- a/compiler/rustc_feature/src/removed.rs +++ b/compiler/rustc_feature/src/removed.rs @@ -156,7 +156,7 @@ declare_features! ( (removed, no_stack_check, "1.0.0", None, None), /// Allows making `dyn Trait` well-formed even if `Trait` is not dyn-compatible (object safe). /// Renamed to `dyn_compatible_for_dispatch`. - (removed, object_safe_for_dispatch, "CURRENT_RUSTC_VERSION", Some(43561), + (removed, object_safe_for_dispatch, "1.83.0", Some(43561), Some("renamed to `dyn_compatible_for_dispatch`")), /// Allows using `#[on_unimplemented(..)]` on traits. /// (Moved to `rustc_attrs`.) @@ -221,7 +221,7 @@ declare_features! ( /// Allows using items which are missing stability attributes (removed, unmarked_api, "1.0.0", None, None), /// Allows unnamed fields of struct and union type - (removed, unnamed_fields, "CURRENT_RUSTC_VERSION", Some(49804), Some("feature needs redesign")), + (removed, unnamed_fields, "1.83.0", Some(49804), Some("feature needs redesign")), (removed, unsafe_no_drop_flag, "1.0.0", None, None), /// Allows `union` fields that don't implement `Copy` as long as they don't have any drop glue. (removed, untagged_unions, "1.13.0", Some(55149), diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index c0398db9c101f..1067156958dc1 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -228,7 +228,7 @@ declare_features! ( /// Added for testing unstable lints; perma-unstable. (internal, test_unstable_lint, "1.60.0", None), /// Helps with formatting for `group_imports = "StdExternalCrate"`. - (unstable, unqualified_local_imports, "CURRENT_RUSTC_VERSION", None), + (unstable, unqualified_local_imports, "1.83.0", None), /// Use for stable + negative coherence and strict coherence depending on trait's /// rustc_strict_coherence value. (unstable, with_negative_coherence, "1.60.0", None), @@ -266,7 +266,7 @@ declare_features! ( /// Renamed from `object_safe_for_dispatch`. /// /// [^1]: Formerly known as "object safe". - (unstable, dyn_compatible_for_dispatch, "CURRENT_RUSTC_VERSION", Some(43561)), + (unstable, dyn_compatible_for_dispatch, "1.83.0", Some(43561)), /// Allows using the `#[fundamental]` attribute. (unstable, fundamental, "1.0.0", Some(29635)), /// Allows using `#[link_name="llvm.*"]`. @@ -360,7 +360,7 @@ declare_features! ( /// Allows inherent and trait methods with arbitrary self types. (unstable, arbitrary_self_types, "1.23.0", Some(44874)), /// Allows inherent and trait methods with arbitrary self types that are raw pointers. - (unstable, arbitrary_self_types_pointers, "CURRENT_RUSTC_VERSION", Some(44874)), + (unstable, arbitrary_self_types_pointers, "1.83.0", Some(44874)), /// Enables experimental inline assembly support for additional architectures. (unstable, asm_experimental_arch, "1.58.0", Some(93335)), /// Allows using `label` operands in inline assembly. @@ -380,7 +380,7 @@ declare_features! ( /// Allows using C-variadics. (unstable, c_variadic, "1.34.0", Some(44930)), /// Allows the use of `#[cfg()]`. - (unstable, cfg_boolean_literals, "CURRENT_RUSTC_VERSION", Some(131204)), + (unstable, cfg_boolean_literals, "1.83.0", Some(131204)), /// Allows the use of `#[cfg(overflow_checks)` to check if integer overflow behaviour. (unstable, cfg_overflow_checks, "1.71.0", Some(111466)), /// Provides the relocation model information as cfg entry @@ -498,7 +498,7 @@ declare_features! ( /// Allows `if let` guard in match arms. (unstable, if_let_guard, "1.47.0", Some(51114)), /// Rescoping temporaries in `if let` to align with Rust 2024. - (unstable, if_let_rescope, "CURRENT_RUSTC_VERSION", Some(124085)), + (unstable, if_let_rescope, "1.83.0", Some(124085)), /// Allows `impl Trait` to be used inside associated types (RFC 2515). (unstable, impl_trait_in_assoc_type, "1.70.0", Some(63063)), /// Allows `impl Trait` as output type in `Fn` traits in return position of functions. @@ -563,11 +563,11 @@ declare_features! ( /// Allows specifying nop padding on functions for dynamic patching. (unstable, patchable_function_entry, "1.81.0", Some(123115)), /// Experimental features that make `Pin` more ergonomic. - (incomplete, pin_ergonomics, "CURRENT_RUSTC_VERSION", Some(130494)), + (incomplete, pin_ergonomics, "1.83.0", Some(130494)), /// Allows postfix match `expr.match { ... }` (unstable, postfix_match, "1.79.0", Some(121618)), /// Allows `use<..>` precise capturign on impl Trait in traits. - (unstable, precise_capturing_in_traits, "CURRENT_RUSTC_VERSION", Some(130044)), + (unstable, precise_capturing_in_traits, "1.83.0", Some(130044)), /// Allows macro attributes on expressions, statements and non-inline modules. (unstable, proc_macro_hygiene, "1.30.0", Some(54727)), /// Makes `&` and `&mut` patterns eat only one layer of references in Rust 2024. diff --git a/library/core/src/array/mod.rs b/library/core/src/array/mod.rs index a95046162d284..72f4887890487 100644 --- a/library/core/src/array/mod.rs +++ b/library/core/src/array/mod.rs @@ -146,7 +146,7 @@ pub const fn from_ref(s: &T) -> &[T; 1] { /// Converts a mutable reference to `T` into a mutable reference to an array of length 1 (without copying). #[stable(feature = "array_from_ref", since = "1.53.0")] -#[rustc_const_stable(feature = "const_array_from_ref", since = "CURRENT_RUSTC_VERSION")] +#[rustc_const_stable(feature = "const_array_from_ref", since = "1.83.0")] #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] pub const fn from_mut(s: &mut T) -> &mut [T; 1] { // SAFETY: Converting `&mut T` to `&mut [T; 1]` is sound. diff --git a/library/core/src/cell.rs b/library/core/src/cell.rs index 8ccd1a44ff163..119be8095e251 100644 --- a/library/core/src/cell.rs +++ b/library/core/src/cell.rs @@ -515,7 +515,7 @@ impl Cell { /// assert_eq!(five, 5); /// ``` #[stable(feature = "move_cell", since = "1.17.0")] - #[rustc_const_stable(feature = "const_cell_into_inner", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_cell_into_inner", since = "1.83.0")] #[rustc_allow_const_fn_unstable(const_precise_live_drops)] pub const fn into_inner(self) -> T { self.value.into_inner() @@ -864,7 +864,7 @@ impl RefCell { /// let five = c.into_inner(); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_stable(feature = "const_cell_into_inner", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_cell_into_inner", since = "1.83.0")] #[rustc_allow_const_fn_unstable(const_precise_live_drops)] #[inline] pub const fn into_inner(self) -> T { @@ -2108,7 +2108,7 @@ impl UnsafeCell { /// ``` #[inline(always)] #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_stable(feature = "const_cell_into_inner", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_cell_into_inner", since = "1.83.0")] #[rustc_allow_const_fn_unstable(const_precise_live_drops)] pub const fn into_inner(self) -> T { self.value @@ -2182,7 +2182,7 @@ impl UnsafeCell { #[inline(always)] #[stable(feature = "unsafe_cell_get_mut", since = "1.50.0")] #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] - #[rustc_const_stable(feature = "const_unsafecell_get_mut", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_unsafecell_get_mut", since = "1.83.0")] pub const fn get_mut(&mut self) -> &mut T { &mut self.value } diff --git a/library/core/src/cell/once.rs b/library/core/src/cell/once.rs index 14c587e0c482e..c14afe0f4761c 100644 --- a/library/core/src/cell/once.rs +++ b/library/core/src/cell/once.rs @@ -309,7 +309,7 @@ impl OnceCell { /// ``` #[inline] #[stable(feature = "once_cell", since = "1.70.0")] - #[rustc_const_stable(feature = "const_cell_into_inner", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_cell_into_inner", since = "1.83.0")] #[rustc_allow_const_fn_unstable(const_precise_live_drops)] pub const fn into_inner(self) -> Option { // Because `into_inner` takes `self` by value, the compiler statically verifies diff --git a/library/core/src/char/methods.rs b/library/core/src/char/methods.rs index 6bedb0d0dc4e5..01b42dcedbfc2 100644 --- a/library/core/src/char/methods.rs +++ b/library/core/src/char/methods.rs @@ -36,7 +36,7 @@ impl char { /// let value_at_min = u32::from(char::MIN); /// assert_eq!(char::from_u32(value_at_min), Some('\0')); /// ``` - #[stable(feature = "char_min", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "char_min", since = "1.83.0")] pub const MIN: char = '\0'; /// The highest valid code point a `char` can have, `'\u{10FFFF}'`. @@ -674,7 +674,7 @@ impl char { /// 'ß'.encode_utf8(&mut b); /// ``` #[stable(feature = "unicode_encode_char", since = "1.15.0")] - #[rustc_const_stable(feature = "const_char_encode_utf8", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_char_encode_utf8", since = "1.83.0")] #[inline] #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] pub const fn encode_utf8(self, dst: &mut [u8]) -> &mut str { @@ -1771,7 +1771,7 @@ const fn len_utf16(code: u32) -> usize { /// Panics if the buffer is not large enough. /// A buffer of length four is large enough to encode any `char`. #[unstable(feature = "char_internals", reason = "exposed only for libstd", issue = "none")] -#[rustc_const_stable(feature = "const_char_encode_utf8", since = "CURRENT_RUSTC_VERSION")] +#[rustc_const_stable(feature = "const_char_encode_utf8", since = "1.83.0")] #[doc(hidden)] #[inline] #[rustc_allow_const_fn_unstable(const_eval_select)] diff --git a/library/core/src/fmt/builders.rs b/library/core/src/fmt/builders.rs index 3d0c9f7c96414..1862be0e86c5d 100644 --- a/library/core/src/fmt/builders.rs +++ b/library/core/src/fmt/builders.rs @@ -383,7 +383,7 @@ impl<'a, 'b: 'a> DebugTuple<'a, 'b> { /// "Foo(10, ..)", /// ); /// ``` - #[stable(feature = "debug_more_non_exhaustive", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "debug_more_non_exhaustive", since = "1.83.0")] pub fn finish_non_exhaustive(&mut self) -> fmt::Result { self.result = self.result.and_then(|_| { if self.fields > 0 { @@ -626,7 +626,7 @@ impl<'a, 'b: 'a> DebugSet<'a, 'b> { /// "{1, 2, ..}", /// ); /// ``` - #[stable(feature = "debug_more_non_exhaustive", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "debug_more_non_exhaustive", since = "1.83.0")] pub fn finish_non_exhaustive(&mut self) -> fmt::Result { self.inner.result = self.inner.result.and_then(|_| { if self.inner.has_fields { @@ -818,7 +818,7 @@ impl<'a, 'b: 'a> DebugList<'a, 'b> { /// "[1, 2, ..]", /// ); /// ``` - #[stable(feature = "debug_more_non_exhaustive", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "debug_more_non_exhaustive", since = "1.83.0")] pub fn finish_non_exhaustive(&mut self) -> fmt::Result { self.inner.result.and_then(|_| { if self.inner.has_fields { @@ -1146,7 +1146,7 @@ impl<'a, 'b: 'a> DebugMap<'a, 'b> { /// r#"{"A": 10, "B": 11, ..}"#, /// ); /// ``` - #[stable(feature = "debug_more_non_exhaustive", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "debug_more_non_exhaustive", since = "1.83.0")] pub fn finish_non_exhaustive(&mut self) -> fmt::Result { self.result = self.result.and_then(|_| { assert!(!self.has_key, "attempted to finish a map with a partial entry"); diff --git a/library/core/src/intrinsics.rs b/library/core/src/intrinsics.rs index e3b4628e1846a..b2a14e484dc55 100644 --- a/library/core/src/intrinsics.rs +++ b/library/core/src/intrinsics.rs @@ -1084,7 +1084,7 @@ extern "rust-intrinsic" { /// it does not require an `unsafe` block. /// Therefore, implementations must not require the user to uphold /// any safety invariants. - #[rustc_const_stable(feature = "const_intrinsic_forget", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_intrinsic_forget", since = "1.83.0")] #[rustc_safe_intrinsic] #[rustc_nounwind] pub fn forget(_: T); @@ -2688,7 +2688,7 @@ extern "rust-intrinsic" { /// This intrinsic can *only* be called where the pointer is a local without /// projections (`write_via_move(ptr, x)`, not `write_via_move(*ptr, x)`) so /// that it trivially obeys runtime-MIR rules about derefs in operands. - #[rustc_const_stable(feature = "const_ptr_write", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_ptr_write", since = "1.83.0")] #[rustc_nounwind] pub fn write_via_move(ptr: *mut T, value: T); @@ -3217,7 +3217,7 @@ pub const fn type_id() -> u128 { /// change the possible layouts of pointers. #[rustc_nounwind] #[unstable(feature = "core_intrinsics", issue = "none")] -#[rustc_const_stable(feature = "ptr_metadata_const", since = "CURRENT_RUSTC_VERSION")] +#[rustc_const_stable(feature = "ptr_metadata_const", since = "1.83.0")] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] pub const fn aggregate_raw_ptr, D, M>(_data: D, _meta: M) -> P { @@ -3242,7 +3242,7 @@ impl AggregateRawPtr<*mut T> for *mut P { /// This is used to implement functions like `ptr::metadata`. #[rustc_nounwind] #[unstable(feature = "core_intrinsics", issue = "none")] -#[rustc_const_stable(feature = "ptr_metadata_const", since = "CURRENT_RUSTC_VERSION")] +#[rustc_const_stable(feature = "ptr_metadata_const", since = "1.83.0")] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] pub const fn ptr_metadata + ?Sized, M>(_ptr: *const P) -> M { @@ -3343,13 +3343,13 @@ pub const fn ptr_metadata + ?Sized, M>(_ptr: *cons #[doc(alias = "memcpy")] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_allowed_through_unstable_modules] -#[rustc_const_stable(feature = "const_intrinsic_copy", since = "CURRENT_RUSTC_VERSION")] +#[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.83.0")] #[inline(always)] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces #[rustc_diagnostic_item = "ptr_copy_nonoverlapping"] pub const unsafe fn copy_nonoverlapping(src: *const T, dst: *mut T, count: usize) { extern "rust-intrinsic" { - #[rustc_const_stable(feature = "const_intrinsic_copy", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.83.0")] #[rustc_nounwind] pub fn copy_nonoverlapping(src: *const T, dst: *mut T, count: usize); } @@ -3445,13 +3445,13 @@ pub const unsafe fn copy_nonoverlapping(src: *const T, dst: *mut T, count: us #[doc(alias = "memmove")] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_allowed_through_unstable_modules] -#[rustc_const_stable(feature = "const_intrinsic_copy", since = "CURRENT_RUSTC_VERSION")] +#[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.83.0")] #[inline(always)] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces #[rustc_diagnostic_item = "ptr_copy"] pub const unsafe fn copy(src: *const T, dst: *mut T, count: usize) { extern "rust-intrinsic" { - #[rustc_const_stable(feature = "const_intrinsic_copy", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.83.0")] #[rustc_nounwind] fn copy(src: *const T, dst: *mut T, count: usize); } @@ -3525,13 +3525,13 @@ pub const unsafe fn copy(src: *const T, dst: *mut T, count: usize) { #[doc(alias = "memset")] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_allowed_through_unstable_modules] -#[rustc_const_stable(feature = "const_ptr_write", since = "CURRENT_RUSTC_VERSION")] +#[rustc_const_stable(feature = "const_ptr_write", since = "1.83.0")] #[inline(always)] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces #[rustc_diagnostic_item = "ptr_write_bytes"] pub const unsafe fn write_bytes(dst: *mut T, val: u8, count: usize) { extern "rust-intrinsic" { - #[rustc_const_stable(feature = "const_ptr_write", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_ptr_write", since = "1.83.0")] #[rustc_nounwind] fn write_bytes(dst: *mut T, val: u8, count: usize); } diff --git a/library/core/src/mem/maybe_uninit.rs b/library/core/src/mem/maybe_uninit.rs index c67796ad3db83..afae21cc95b7d 100644 --- a/library/core/src/mem/maybe_uninit.rs +++ b/library/core/src/mem/maybe_uninit.rs @@ -569,10 +569,7 @@ impl MaybeUninit { /// (Notice that the rules around references to uninitialized data are not finalized yet, but /// until they are, it is advisable to avoid them.) #[stable(feature = "maybe_uninit", since = "1.36.0")] - #[rustc_const_stable( - feature = "const_maybe_uninit_as_mut_ptr", - since = "CURRENT_RUSTC_VERSION" - )] + #[rustc_const_stable(feature = "const_maybe_uninit_as_mut_ptr", since = "1.83.0")] #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] #[inline(always)] pub const fn as_mut_ptr(&mut self) -> *mut T { diff --git a/library/core/src/mem/mod.rs b/library/core/src/mem/mod.rs index 9bf2aa594c047..ada804633065d 100644 --- a/library/core/src/mem/mod.rs +++ b/library/core/src/mem/mod.rs @@ -858,7 +858,7 @@ pub fn take(dest: &mut T) -> T { #[stable(feature = "rust1", since = "1.0.0")] #[must_use = "if you don't need the old value, you can just assign the new value directly"] #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] -#[rustc_const_stable(feature = "const_replace", since = "CURRENT_RUSTC_VERSION")] +#[rustc_const_stable(feature = "const_replace", since = "1.83.0")] #[cfg_attr(not(test), rustc_diagnostic_item = "mem_replace")] pub const fn replace(dest: &mut T, src: T) -> T { // It may be tempting to use `swap` to avoid `unsafe` here. Don't! diff --git a/library/core/src/num/f32.rs b/library/core/src/num/f32.rs index a9a2595c25c29..5a99350acc3a8 100644 --- a/library/core/src/num/f32.rs +++ b/library/core/src/num/f32.rs @@ -517,7 +517,7 @@ impl f32 { /// ``` #[must_use] #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_stable(feature = "const_float_classify", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_float_classify", since = "1.83.0")] #[inline] #[allow(clippy::eq_op)] // > if you intended to check if the operand is NaN, use `.is_nan()` instead :) pub const fn is_nan(self) -> bool { @@ -550,7 +550,7 @@ impl f32 { /// ``` #[must_use] #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_stable(feature = "const_float_classify", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_float_classify", since = "1.83.0")] #[inline] pub const fn is_infinite(self) -> bool { // Getting clever with transmutation can result in incorrect answers on some FPUs @@ -575,7 +575,7 @@ impl f32 { /// ``` #[must_use] #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_stable(feature = "const_float_classify", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_float_classify", since = "1.83.0")] #[inline] pub const fn is_finite(self) -> bool { // There's no need to handle NaN separately: if self is NaN, @@ -603,7 +603,7 @@ impl f32 { /// [subnormal]: https://en.wikipedia.org/wiki/Denormal_number #[must_use] #[stable(feature = "is_subnormal", since = "1.53.0")] - #[rustc_const_stable(feature = "const_float_classify", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_float_classify", since = "1.83.0")] #[inline] pub const fn is_subnormal(self) -> bool { matches!(self.classify(), FpCategory::Subnormal) @@ -630,7 +630,7 @@ impl f32 { /// [subnormal]: https://en.wikipedia.org/wiki/Denormal_number #[must_use] #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_stable(feature = "const_float_classify", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_float_classify", since = "1.83.0")] #[inline] pub const fn is_normal(self) -> bool { matches!(self.classify(), FpCategory::Normal) @@ -650,7 +650,7 @@ impl f32 { /// assert_eq!(inf.classify(), FpCategory::Infinite); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_stable(feature = "const_float_classify", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_float_classify", since = "1.83.0")] pub const fn classify(self) -> FpCategory { // We used to have complicated logic here that avoids the simple bit-based tests to work // around buggy codegen for x87 targets (see @@ -686,7 +686,7 @@ impl f32 { /// ``` #[must_use] #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_stable(feature = "const_float_classify", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_float_classify", since = "1.83.0")] #[inline] pub const fn is_sign_positive(self) -> bool { !self.is_sign_negative() @@ -711,7 +711,7 @@ impl f32 { /// ``` #[must_use] #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_stable(feature = "const_float_classify", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_float_classify", since = "1.83.0")] #[inline] pub const fn is_sign_negative(self) -> bool { // IEEE754 says: isSignMinus(x) is true if and only if x has negative sign. isSignMinus @@ -1088,7 +1088,7 @@ impl f32 { #[must_use = "this returns the result of the operation, \ without modifying the original"] #[stable(feature = "float_bits_conv", since = "1.20.0")] - #[rustc_const_stable(feature = "const_float_bits_conv", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_float_bits_conv", since = "1.83.0")] #[inline] pub const fn to_bits(self) -> u32 { // SAFETY: `u32` is a plain old datatype so we can always transmute to it. @@ -1132,7 +1132,7 @@ impl f32 { /// assert_eq!(v, 12.5); /// ``` #[stable(feature = "float_bits_conv", since = "1.20.0")] - #[rustc_const_stable(feature = "const_float_bits_conv", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_float_bits_conv", since = "1.83.0")] #[must_use] #[inline] pub const fn from_bits(v: u32) -> Self { @@ -1156,7 +1156,7 @@ impl f32 { #[must_use = "this returns the result of the operation, \ without modifying the original"] #[stable(feature = "float_to_from_bytes", since = "1.40.0")] - #[rustc_const_stable(feature = "const_float_bits_conv", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_float_bits_conv", since = "1.83.0")] #[inline] pub const fn to_be_bytes(self) -> [u8; 4] { self.to_bits().to_be_bytes() @@ -1177,7 +1177,7 @@ impl f32 { #[must_use = "this returns the result of the operation, \ without modifying the original"] #[stable(feature = "float_to_from_bytes", since = "1.40.0")] - #[rustc_const_stable(feature = "const_float_bits_conv", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_float_bits_conv", since = "1.83.0")] #[inline] pub const fn to_le_bytes(self) -> [u8; 4] { self.to_bits().to_le_bytes() @@ -1211,7 +1211,7 @@ impl f32 { #[must_use = "this returns the result of the operation, \ without modifying the original"] #[stable(feature = "float_to_from_bytes", since = "1.40.0")] - #[rustc_const_stable(feature = "const_float_bits_conv", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_float_bits_conv", since = "1.83.0")] #[inline] pub const fn to_ne_bytes(self) -> [u8; 4] { self.to_bits().to_ne_bytes() @@ -1229,7 +1229,7 @@ impl f32 { /// assert_eq!(value, 12.5); /// ``` #[stable(feature = "float_to_from_bytes", since = "1.40.0")] - #[rustc_const_stable(feature = "const_float_bits_conv", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_float_bits_conv", since = "1.83.0")] #[must_use] #[inline] pub const fn from_be_bytes(bytes: [u8; 4]) -> Self { @@ -1248,7 +1248,7 @@ impl f32 { /// assert_eq!(value, 12.5); /// ``` #[stable(feature = "float_to_from_bytes", since = "1.40.0")] - #[rustc_const_stable(feature = "const_float_bits_conv", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_float_bits_conv", since = "1.83.0")] #[must_use] #[inline] pub const fn from_le_bytes(bytes: [u8; 4]) -> Self { @@ -1278,7 +1278,7 @@ impl f32 { /// assert_eq!(value, 12.5); /// ``` #[stable(feature = "float_to_from_bytes", since = "1.40.0")] - #[rustc_const_stable(feature = "const_float_bits_conv", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_float_bits_conv", since = "1.83.0")] #[must_use] #[inline] pub const fn from_ne_bytes(bytes: [u8; 4]) -> Self { diff --git a/library/core/src/num/f64.rs b/library/core/src/num/f64.rs index aa7a54ca65080..74d0c0d51d2ff 100644 --- a/library/core/src/num/f64.rs +++ b/library/core/src/num/f64.rs @@ -516,7 +516,7 @@ impl f64 { /// ``` #[must_use] #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_stable(feature = "const_float_classify", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_float_classify", since = "1.83.0")] #[inline] #[allow(clippy::eq_op)] // > if you intended to check if the operand is NaN, use `.is_nan()` instead :) pub const fn is_nan(self) -> bool { @@ -549,7 +549,7 @@ impl f64 { /// ``` #[must_use] #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_stable(feature = "const_float_classify", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_float_classify", since = "1.83.0")] #[inline] pub const fn is_infinite(self) -> bool { // Getting clever with transmutation can result in incorrect answers on some FPUs @@ -574,7 +574,7 @@ impl f64 { /// ``` #[must_use] #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_stable(feature = "const_float_classify", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_float_classify", since = "1.83.0")] #[inline] pub const fn is_finite(self) -> bool { // There's no need to handle NaN separately: if self is NaN, @@ -602,7 +602,7 @@ impl f64 { /// [subnormal]: https://en.wikipedia.org/wiki/Denormal_number #[must_use] #[stable(feature = "is_subnormal", since = "1.53.0")] - #[rustc_const_stable(feature = "const_float_classify", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_float_classify", since = "1.83.0")] #[inline] pub const fn is_subnormal(self) -> bool { matches!(self.classify(), FpCategory::Subnormal) @@ -629,7 +629,7 @@ impl f64 { /// [subnormal]: https://en.wikipedia.org/wiki/Denormal_number #[must_use] #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_stable(feature = "const_float_classify", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_float_classify", since = "1.83.0")] #[inline] pub const fn is_normal(self) -> bool { matches!(self.classify(), FpCategory::Normal) @@ -649,7 +649,7 @@ impl f64 { /// assert_eq!(inf.classify(), FpCategory::Infinite); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_stable(feature = "const_float_classify", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_float_classify", since = "1.83.0")] pub const fn classify(self) -> FpCategory { // We used to have complicated logic here that avoids the simple bit-based tests to work // around buggy codegen for x87 targets (see @@ -685,7 +685,7 @@ impl f64 { /// ``` #[must_use] #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_stable(feature = "const_float_classify", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_float_classify", since = "1.83.0")] #[inline] pub const fn is_sign_positive(self) -> bool { !self.is_sign_negative() @@ -719,7 +719,7 @@ impl f64 { /// ``` #[must_use] #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_stable(feature = "const_float_classify", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_float_classify", since = "1.83.0")] #[inline] pub const fn is_sign_negative(self) -> bool { // IEEE754 says: isSignMinus(x) is true if and only if x has negative sign. isSignMinus @@ -1088,7 +1088,7 @@ impl f64 { #[must_use = "this returns the result of the operation, \ without modifying the original"] #[stable(feature = "float_bits_conv", since = "1.20.0")] - #[rustc_const_stable(feature = "const_float_bits_conv", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_float_bits_conv", since = "1.83.0")] #[inline] pub const fn to_bits(self) -> u64 { // SAFETY: `u64` is a plain old datatype so we can always transmute to it. @@ -1132,7 +1132,7 @@ impl f64 { /// assert_eq!(v, 12.5); /// ``` #[stable(feature = "float_bits_conv", since = "1.20.0")] - #[rustc_const_stable(feature = "const_float_bits_conv", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_float_bits_conv", since = "1.83.0")] #[must_use] #[inline] pub const fn from_bits(v: u64) -> Self { @@ -1156,7 +1156,7 @@ impl f64 { #[must_use = "this returns the result of the operation, \ without modifying the original"] #[stable(feature = "float_to_from_bytes", since = "1.40.0")] - #[rustc_const_stable(feature = "const_float_bits_conv", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_float_bits_conv", since = "1.83.0")] #[inline] pub const fn to_be_bytes(self) -> [u8; 8] { self.to_bits().to_be_bytes() @@ -1177,7 +1177,7 @@ impl f64 { #[must_use = "this returns the result of the operation, \ without modifying the original"] #[stable(feature = "float_to_from_bytes", since = "1.40.0")] - #[rustc_const_stable(feature = "const_float_bits_conv", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_float_bits_conv", since = "1.83.0")] #[inline] pub const fn to_le_bytes(self) -> [u8; 8] { self.to_bits().to_le_bytes() @@ -1211,7 +1211,7 @@ impl f64 { #[must_use = "this returns the result of the operation, \ without modifying the original"] #[stable(feature = "float_to_from_bytes", since = "1.40.0")] - #[rustc_const_stable(feature = "const_float_bits_conv", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_float_bits_conv", since = "1.83.0")] #[inline] pub const fn to_ne_bytes(self) -> [u8; 8] { self.to_bits().to_ne_bytes() @@ -1229,7 +1229,7 @@ impl f64 { /// assert_eq!(value, 12.5); /// ``` #[stable(feature = "float_to_from_bytes", since = "1.40.0")] - #[rustc_const_stable(feature = "const_float_bits_conv", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_float_bits_conv", since = "1.83.0")] #[must_use] #[inline] pub const fn from_be_bytes(bytes: [u8; 8]) -> Self { @@ -1248,7 +1248,7 @@ impl f64 { /// assert_eq!(value, 12.5); /// ``` #[stable(feature = "float_to_from_bytes", since = "1.40.0")] - #[rustc_const_stable(feature = "const_float_bits_conv", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_float_bits_conv", since = "1.83.0")] #[must_use] #[inline] pub const fn from_le_bytes(bytes: [u8; 8]) -> Self { @@ -1278,7 +1278,7 @@ impl f64 { /// assert_eq!(value, 12.5); /// ``` #[stable(feature = "float_to_from_bytes", since = "1.40.0")] - #[rustc_const_stable(feature = "const_float_bits_conv", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_float_bits_conv", since = "1.83.0")] #[must_use] #[inline] pub const fn from_ne_bytes(bytes: [u8; 8]) -> Self { diff --git a/library/core/src/ops/control_flow.rs b/library/core/src/ops/control_flow.rs index 7a8158b823185..55deabbee8fb5 100644 --- a/library/core/src/ops/control_flow.rs +++ b/library/core/src/ops/control_flow.rs @@ -177,7 +177,7 @@ impl ControlFlow { /// assert_eq!(ControlFlow::::Continue(3).break_value(), None); /// ``` #[inline] - #[stable(feature = "control_flow_enum", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "control_flow_enum", since = "1.83.0")] pub fn break_value(self) -> Option { match self { ControlFlow::Continue(..) => None, @@ -188,7 +188,7 @@ impl ControlFlow { /// Maps `ControlFlow` to `ControlFlow` by applying a function /// to the break value in case it exists. #[inline] - #[stable(feature = "control_flow_enum", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "control_flow_enum", since = "1.83.0")] pub fn map_break(self, f: impl FnOnce(B) -> T) -> ControlFlow { match self { ControlFlow::Continue(x) => ControlFlow::Continue(x), @@ -208,7 +208,7 @@ impl ControlFlow { /// assert_eq!(ControlFlow::::Continue(3).continue_value(), Some(3)); /// ``` #[inline] - #[stable(feature = "control_flow_enum", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "control_flow_enum", since = "1.83.0")] pub fn continue_value(self) -> Option { match self { ControlFlow::Continue(x) => Some(x), @@ -219,7 +219,7 @@ impl ControlFlow { /// Maps `ControlFlow` to `ControlFlow` by applying a function /// to the continue value in case it exists. #[inline] - #[stable(feature = "control_flow_enum", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "control_flow_enum", since = "1.83.0")] pub fn map_continue(self, f: impl FnOnce(C) -> T) -> ControlFlow { match self { ControlFlow::Continue(x) => ControlFlow::Continue(f(x)), diff --git a/library/core/src/option.rs b/library/core/src/option.rs index 84ccb7a1f6680..661176ce9fcfa 100644 --- a/library/core/src/option.rs +++ b/library/core/src/option.rs @@ -724,7 +724,7 @@ impl Option { #[inline] #[stable(feature = "rust1", since = "1.0.0")] #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] - #[rustc_const_stable(feature = "const_option", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_option", since = "1.83.0")] pub const fn as_mut(&mut self) -> Option<&mut T> { match *self { Some(ref mut x) => Some(x), @@ -926,7 +926,7 @@ impl Option { #[stable(feature = "rust1", since = "1.0.0")] #[cfg_attr(not(test), rustc_diagnostic_item = "option_expect")] #[rustc_allow_const_fn_unstable(const_precise_live_drops)] - #[rustc_const_stable(feature = "const_option", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_option", since = "1.83.0")] pub const fn expect(self, msg: &str) -> T { match self { Some(val) => val, @@ -965,7 +965,7 @@ impl Option { #[stable(feature = "rust1", since = "1.0.0")] #[cfg_attr(not(test), rustc_diagnostic_item = "option_unwrap")] #[rustc_allow_const_fn_unstable(const_precise_live_drops)] - #[rustc_const_stable(feature = "const_option", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_option", since = "1.83.0")] pub const fn unwrap(self) -> T { match self { Some(val) => val, @@ -1073,7 +1073,7 @@ impl Option { #[track_caller] #[stable(feature = "option_result_unwrap_unchecked", since = "1.58.0")] #[rustc_allow_const_fn_unstable(const_precise_live_drops)] - #[rustc_const_stable(feature = "const_option", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_option", since = "1.83.0")] pub const unsafe fn unwrap_unchecked(self) -> T { match self { Some(val) => val, @@ -1655,7 +1655,7 @@ impl Option { /// assert_eq!(x, Some(7)); /// ``` #[inline] - #[stable(feature = "option_get_or_insert_default", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "option_get_or_insert_default", since = "1.83.0")] pub fn get_or_insert_default(&mut self) -> &mut T where T: Default, @@ -1717,7 +1717,7 @@ impl Option { #[inline] #[stable(feature = "rust1", since = "1.0.0")] #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] - #[rustc_const_stable(feature = "const_option", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_option", since = "1.83.0")] pub const fn take(&mut self) -> Option { // FIXME(const-hack) replace `mem::replace` by `mem::take` when the latter is const ready mem::replace(self, None) @@ -1776,7 +1776,7 @@ impl Option { #[inline] #[stable(feature = "option_replace", since = "1.31.0")] #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] - #[rustc_const_stable(feature = "const_option", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_option", since = "1.83.0")] pub const fn replace(&mut self, value: T) -> Option { mem::replace(self, Some(value)) } @@ -1884,7 +1884,7 @@ impl Option<&T> { /// ``` #[must_use = "`self` will be dropped if the result is not used"] #[stable(feature = "copied", since = "1.35.0")] - #[rustc_const_stable(feature = "const_option", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_option", since = "1.83.0")] pub const fn copied(self) -> Option where T: Copy, @@ -1938,7 +1938,7 @@ impl Option<&mut T> { #[must_use = "`self` will be dropped if the result is not used"] #[stable(feature = "copied", since = "1.35.0")] #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] - #[rustc_const_stable(feature = "const_option", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_option", since = "1.83.0")] pub const fn copied(self) -> Option where T: Copy, @@ -1994,7 +1994,7 @@ impl Option> { #[inline] #[stable(feature = "transpose_result", since = "1.33.0")] #[rustc_allow_const_fn_unstable(const_precise_live_drops)] - #[rustc_const_stable(feature = "const_option", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_option", since = "1.83.0")] pub const fn transpose(self) -> Result, E> { match self { Some(Ok(x)) => Ok(Some(x)), @@ -2542,7 +2542,7 @@ impl Option> { #[inline] #[stable(feature = "option_flattening", since = "1.40.0")] #[rustc_allow_const_fn_unstable(const_precise_live_drops)] - #[rustc_const_stable(feature = "const_option", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_option", since = "1.83.0")] pub const fn flatten(self) -> Option { // FIXME(const-hack): could be written with `and_then` match self { diff --git a/library/core/src/ptr/const_ptr.rs b/library/core/src/ptr/const_ptr.rs index c9af7f13e46c4..62d1fdaa1e965 100644 --- a/library/core/src/ptr/const_ptr.rs +++ b/library/core/src/ptr/const_ptr.rs @@ -92,7 +92,7 @@ impl *const T { /// } /// ``` #[unstable(feature = "set_ptr_value", issue = "75091")] - #[rustc_const_stable(feature = "ptr_metadata_const", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "ptr_metadata_const", since = "1.83.0")] #[must_use = "returns a new pointer rather than modifying its argument"] #[inline] pub const fn with_metadata_of(self, meta: *const U) -> *const U @@ -1278,7 +1278,7 @@ impl *const T { /// See [`ptr::copy`] for safety concerns and examples. /// /// [`ptr::copy`]: crate::ptr::copy() - #[rustc_const_stable(feature = "const_intrinsic_copy", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.83.0")] #[stable(feature = "pointer_methods", since = "1.26.0")] #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces @@ -1298,7 +1298,7 @@ impl *const T { /// See [`ptr::copy_nonoverlapping`] for safety concerns and examples. /// /// [`ptr::copy_nonoverlapping`]: crate::ptr::copy_nonoverlapping() - #[rustc_const_stable(feature = "const_intrinsic_copy", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.83.0")] #[stable(feature = "pointer_methods", since = "1.26.0")] #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces diff --git a/library/core/src/ptr/metadata.rs b/library/core/src/ptr/metadata.rs index feeaf78d3e725..09c4002dbc76c 100644 --- a/library/core/src/ptr/metadata.rs +++ b/library/core/src/ptr/metadata.rs @@ -92,7 +92,7 @@ pub trait Thin = Pointee; /// /// assert_eq!(std::ptr::metadata("foo"), 3_usize); /// ``` -#[rustc_const_stable(feature = "ptr_metadata_const", since = "CURRENT_RUSTC_VERSION")] +#[rustc_const_stable(feature = "ptr_metadata_const", since = "1.83.0")] #[inline] pub const fn metadata(ptr: *const T) -> ::Metadata { ptr_metadata(ptr) @@ -106,7 +106,7 @@ pub const fn metadata(ptr: *const T) -> ::Metadata { /// /// [`slice::from_raw_parts`]: crate::slice::from_raw_parts #[unstable(feature = "ptr_metadata", issue = "81513")] -#[rustc_const_stable(feature = "ptr_metadata_const", since = "CURRENT_RUSTC_VERSION")] +#[rustc_const_stable(feature = "ptr_metadata_const", since = "1.83.0")] #[inline] pub const fn from_raw_parts( data_pointer: *const impl Thin, @@ -120,7 +120,7 @@ pub const fn from_raw_parts( /// /// See the documentation of [`from_raw_parts`] for more details. #[unstable(feature = "ptr_metadata", issue = "81513")] -#[rustc_const_stable(feature = "ptr_metadata_const", since = "CURRENT_RUSTC_VERSION")] +#[rustc_const_stable(feature = "ptr_metadata_const", since = "1.83.0")] #[inline] pub const fn from_raw_parts_mut( data_pointer: *mut impl Thin, diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs index 6b07449292417..4969b2a34f7e1 100644 --- a/library/core/src/ptr/mod.rs +++ b/library/core/src/ptr/mod.rs @@ -992,7 +992,7 @@ pub const fn slice_from_raw_parts(data: *const T, len: usize) -> *const [T] { /// ``` #[inline] #[stable(feature = "slice_from_raw_parts", since = "1.42.0")] -#[rustc_const_stable(feature = "const_slice_from_raw_parts_mut", since = "CURRENT_RUSTC_VERSION")] +#[rustc_const_stable(feature = "const_slice_from_raw_parts_mut", since = "1.83.0")] #[rustc_diagnostic_item = "ptr_slice_from_raw_parts_mut"] pub const fn slice_from_raw_parts_mut(data: *mut T, len: usize) -> *mut [T] { from_raw_parts_mut(data, len) @@ -1264,7 +1264,7 @@ const unsafe fn swap_nonoverlapping_simple_untyped(x: *mut T, y: *mut T, coun #[inline] #[stable(feature = "rust1", since = "1.0.0")] #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] -#[rustc_const_stable(feature = "const_replace", since = "CURRENT_RUSTC_VERSION")] +#[rustc_const_stable(feature = "const_replace", since = "1.83.0")] #[rustc_diagnostic_item = "ptr_replace"] pub const unsafe fn replace(dst: *mut T, src: T) -> T { // SAFETY: the caller must guarantee that `dst` is valid to be @@ -1612,7 +1612,7 @@ pub const unsafe fn read_unaligned(src: *const T) -> T { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] -#[rustc_const_stable(feature = "const_ptr_write", since = "CURRENT_RUSTC_VERSION")] +#[rustc_const_stable(feature = "const_ptr_write", since = "1.83.0")] #[rustc_diagnostic_item = "ptr_write"] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub const unsafe fn write(dst: *mut T, src: T) { @@ -1721,7 +1721,7 @@ pub const unsafe fn write(dst: *mut T, src: T) { #[inline] #[stable(feature = "ptr_unaligned", since = "1.17.0")] #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_refs_to_cell))] -#[rustc_const_stable(feature = "const_ptr_write", since = "CURRENT_RUSTC_VERSION")] +#[rustc_const_stable(feature = "const_ptr_write", since = "1.83.0")] #[rustc_diagnostic_item = "ptr_write_unaligned"] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub const unsafe fn write_unaligned(dst: *mut T, src: T) { diff --git a/library/core/src/ptr/mut_ptr.rs b/library/core/src/ptr/mut_ptr.rs index ced6cb7d520de..478ae44cc377b 100644 --- a/library/core/src/ptr/mut_ptr.rs +++ b/library/core/src/ptr/mut_ptr.rs @@ -74,7 +74,7 @@ impl *mut T { /// } /// ``` #[unstable(feature = "set_ptr_value", issue = "75091")] - #[rustc_const_stable(feature = "ptr_metadata_const", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "ptr_metadata_const", since = "1.83.0")] #[must_use = "returns a new pointer rather than modifying its argument"] #[inline] pub const fn with_metadata_of(self, meta: *const U) -> *mut U @@ -1358,7 +1358,7 @@ impl *mut T { /// See [`ptr::copy`] for safety concerns and examples. /// /// [`ptr::copy`]: crate::ptr::copy() - #[rustc_const_stable(feature = "const_intrinsic_copy", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.83.0")] #[stable(feature = "pointer_methods", since = "1.26.0")] #[inline(always)] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces @@ -1378,7 +1378,7 @@ impl *mut T { /// See [`ptr::copy_nonoverlapping`] for safety concerns and examples. /// /// [`ptr::copy_nonoverlapping`]: crate::ptr::copy_nonoverlapping() - #[rustc_const_stable(feature = "const_intrinsic_copy", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.83.0")] #[stable(feature = "pointer_methods", since = "1.26.0")] #[inline(always)] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces @@ -1398,7 +1398,7 @@ impl *mut T { /// See [`ptr::copy`] for safety concerns and examples. /// /// [`ptr::copy`]: crate::ptr::copy() - #[rustc_const_stable(feature = "const_intrinsic_copy", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.83.0")] #[stable(feature = "pointer_methods", since = "1.26.0")] #[inline(always)] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces @@ -1418,7 +1418,7 @@ impl *mut T { /// See [`ptr::copy_nonoverlapping`] for safety concerns and examples. /// /// [`ptr::copy_nonoverlapping`]: crate::ptr::copy_nonoverlapping() - #[rustc_const_stable(feature = "const_intrinsic_copy", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.83.0")] #[stable(feature = "pointer_methods", since = "1.26.0")] #[inline(always)] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces @@ -1449,7 +1449,7 @@ impl *mut T { /// /// [`ptr::write`]: crate::ptr::write() #[stable(feature = "pointer_methods", since = "1.26.0")] - #[rustc_const_stable(feature = "const_ptr_write", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_ptr_write", since = "1.83.0")] #[inline(always)] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub const unsafe fn write(self, val: T) @@ -1468,7 +1468,7 @@ impl *mut T { /// [`ptr::write_bytes`]: crate::ptr::write_bytes() #[doc(alias = "memset")] #[stable(feature = "pointer_methods", since = "1.26.0")] - #[rustc_const_stable(feature = "const_ptr_write", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_ptr_write", since = "1.83.0")] #[inline(always)] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub const unsafe fn write_bytes(self, val: u8, count: usize) @@ -1509,7 +1509,7 @@ impl *mut T { /// /// [`ptr::write_unaligned`]: crate::ptr::write_unaligned() #[stable(feature = "pointer_methods", since = "1.26.0")] - #[rustc_const_stable(feature = "const_ptr_write", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_ptr_write", since = "1.83.0")] #[inline(always)] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub const unsafe fn write_unaligned(self, val: T) diff --git a/library/core/src/ptr/non_null.rs b/library/core/src/ptr/non_null.rs index 980d4a3cf6ceb..c68391363485e 100644 --- a/library/core/src/ptr/non_null.rs +++ b/library/core/src/ptr/non_null.rs @@ -395,7 +395,7 @@ impl NonNull { /// [the module documentation]: crate::ptr#safety #[stable(feature = "nonnull", since = "1.25.0")] #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] - #[rustc_const_stable(feature = "const_ptr_as_ref", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_ptr_as_ref", since = "1.83.0")] #[must_use] #[inline(always)] pub const unsafe fn as_mut<'a>(&mut self) -> &'a mut T { @@ -923,7 +923,7 @@ impl NonNull { #[inline(always)] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces #[stable(feature = "non_null_convenience", since = "1.80.0")] - #[rustc_const_stable(feature = "const_intrinsic_copy", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.83.0")] pub const unsafe fn copy_to(self, dest: NonNull, count: usize) where T: Sized, @@ -943,7 +943,7 @@ impl NonNull { #[inline(always)] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces #[stable(feature = "non_null_convenience", since = "1.80.0")] - #[rustc_const_stable(feature = "const_intrinsic_copy", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.83.0")] pub const unsafe fn copy_to_nonoverlapping(self, dest: NonNull, count: usize) where T: Sized, @@ -963,7 +963,7 @@ impl NonNull { #[inline(always)] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces #[stable(feature = "non_null_convenience", since = "1.80.0")] - #[rustc_const_stable(feature = "const_intrinsic_copy", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.83.0")] pub const unsafe fn copy_from(self, src: NonNull, count: usize) where T: Sized, @@ -983,7 +983,7 @@ impl NonNull { #[inline(always)] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces #[stable(feature = "non_null_convenience", since = "1.80.0")] - #[rustc_const_stable(feature = "const_intrinsic_copy", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.83.0")] pub const unsafe fn copy_from_nonoverlapping(self, src: NonNull, count: usize) where T: Sized, @@ -1013,7 +1013,7 @@ impl NonNull { #[inline(always)] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces #[stable(feature = "non_null_convenience", since = "1.80.0")] - #[rustc_const_stable(feature = "const_ptr_write", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_ptr_write", since = "1.83.0")] pub const unsafe fn write(self, val: T) where T: Sized, @@ -1032,7 +1032,7 @@ impl NonNull { #[doc(alias = "memset")] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces #[stable(feature = "non_null_convenience", since = "1.80.0")] - #[rustc_const_stable(feature = "const_ptr_write", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_ptr_write", since = "1.83.0")] pub const unsafe fn write_bytes(self, val: u8, count: usize) where T: Sized, @@ -1073,7 +1073,7 @@ impl NonNull { #[inline(always)] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces #[stable(feature = "non_null_convenience", since = "1.80.0")] - #[rustc_const_stable(feature = "const_ptr_write", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_ptr_write", since = "1.83.0")] pub const unsafe fn write_unaligned(self, val: T) where T: Sized, @@ -1432,10 +1432,7 @@ impl NonNull<[T]> { /// (Note that this example artificially demonstrates a use of this method, /// but `let slice = NonNull::from(&x[..]);` would be a better way to write code like this.) #[stable(feature = "nonnull_slice_from_raw_parts", since = "1.70.0")] - #[rustc_const_stable( - feature = "const_slice_from_raw_parts_mut", - since = "CURRENT_RUSTC_VERSION" - )] + #[rustc_const_stable(feature = "const_slice_from_raw_parts_mut", since = "1.83.0")] #[must_use] #[inline] pub const fn slice_from_raw_parts(data: NonNull, len: usize) -> Self { diff --git a/library/core/src/result.rs b/library/core/src/result.rs index 95faacbf96db7..e84c4e3a23980 100644 --- a/library/core/src/result.rs +++ b/library/core/src/result.rs @@ -734,7 +734,7 @@ impl Result { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_stable(feature = "const_result", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_result", since = "1.83.0")] #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] pub const fn as_mut(&mut self) -> Result<&mut T, &mut E> { match *self { @@ -1537,7 +1537,7 @@ impl Result<&T, E> { /// ``` #[inline] #[stable(feature = "result_copied", since = "1.59.0")] - #[rustc_const_stable(feature = "const_result", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_result", since = "1.83.0")] #[rustc_allow_const_fn_unstable(const_precise_live_drops)] pub const fn copied(self) -> Result where @@ -1588,7 +1588,7 @@ impl Result<&mut T, E> { /// ``` #[inline] #[stable(feature = "result_copied", since = "1.59.0")] - #[rustc_const_stable(feature = "const_result", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_result", since = "1.83.0")] #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] #[rustc_allow_const_fn_unstable(const_precise_live_drops)] pub const fn copied(self) -> Result @@ -1643,7 +1643,7 @@ impl Result, E> { /// ``` #[inline] #[stable(feature = "transpose_result", since = "1.33.0")] - #[rustc_const_stable(feature = "const_result", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_result", since = "1.83.0")] #[rustc_allow_const_fn_unstable(const_precise_live_drops)] pub const fn transpose(self) -> Option> { match self { diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs index 90ddc9c1d85d6..9fdcea1f7b737 100644 --- a/library/core/src/slice/mod.rs +++ b/library/core/src/slice/mod.rs @@ -172,7 +172,7 @@ impl [T] { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] - #[rustc_const_stable(feature = "const_slice_first_last", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_slice_first_last", since = "1.83.0")] #[inline] #[must_use] pub const fn first_mut(&mut self) -> Option<&mut T> { @@ -215,7 +215,7 @@ impl [T] { /// ``` #[stable(feature = "slice_splits", since = "1.5.0")] #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] - #[rustc_const_stable(feature = "const_slice_first_last", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_slice_first_last", since = "1.83.0")] #[inline] #[must_use] pub const fn split_first_mut(&mut self) -> Option<(&mut T, &mut [T])> { @@ -258,7 +258,7 @@ impl [T] { /// ``` #[stable(feature = "slice_splits", since = "1.5.0")] #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] - #[rustc_const_stable(feature = "const_slice_first_last", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_slice_first_last", since = "1.83.0")] #[inline] #[must_use] pub const fn split_last_mut(&mut self) -> Option<(&mut T, &mut [T])> { @@ -301,7 +301,7 @@ impl [T] { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] - #[rustc_const_stable(feature = "const_slice_first_last", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_slice_first_last", since = "1.83.0")] #[inline] #[must_use] pub const fn last_mut(&mut self) -> Option<&mut T> { @@ -356,7 +356,7 @@ impl [T] { /// ``` #[inline] #[stable(feature = "slice_first_last_chunk", since = "1.77.0")] - #[rustc_const_stable(feature = "const_slice_first_last_chunk", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_slice_first_last_chunk", since = "1.83.0")] #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] pub const fn first_chunk_mut(&mut self) -> Option<&mut [T; N]> { if self.len() < N { @@ -422,7 +422,7 @@ impl [T] { /// ``` #[inline] #[stable(feature = "slice_first_last_chunk", since = "1.77.0")] - #[rustc_const_stable(feature = "const_slice_first_last_chunk", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_slice_first_last_chunk", since = "1.83.0")] #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] pub const fn split_first_chunk_mut( &mut self, @@ -493,7 +493,7 @@ impl [T] { /// ``` #[inline] #[stable(feature = "slice_first_last_chunk", since = "1.77.0")] - #[rustc_const_stable(feature = "const_slice_first_last_chunk", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_slice_first_last_chunk", since = "1.83.0")] #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] pub const fn split_last_chunk_mut( &mut self, @@ -563,7 +563,7 @@ impl [T] { /// ``` #[inline] #[stable(feature = "slice_first_last_chunk", since = "1.77.0")] - #[rustc_const_stable(feature = "const_slice_first_last_chunk", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_slice_first_last_chunk", since = "1.83.0")] #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] pub const fn last_chunk_mut(&mut self) -> Option<&mut [T; N]> { if self.len() < N { @@ -1907,7 +1907,7 @@ impl [T] { #[inline] #[track_caller] #[must_use] - #[rustc_const_stable(feature = "const_slice_split_at_mut", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_slice_split_at_mut", since = "1.83.0")] #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] pub const fn split_at_mut(&mut self, mid: usize) -> (&mut [T], &mut [T]) { match self.split_at_mut_checked(mid) { @@ -2010,7 +2010,7 @@ impl [T] { /// assert_eq!(v, [1, 2, 3, 4, 5, 6]); /// ``` #[stable(feature = "slice_split_at_unchecked", since = "1.79.0")] - #[rustc_const_stable(feature = "const_slice_split_at_mut", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_slice_split_at_mut", since = "1.83.0")] #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] #[inline] #[must_use] @@ -2111,7 +2111,7 @@ impl [T] { /// assert_eq!(None, v.split_at_mut_checked(7)); /// ``` #[stable(feature = "split_at_checked", since = "1.80.0")] - #[rustc_const_stable(feature = "const_slice_split_at_mut", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_slice_split_at_mut", since = "1.83.0")] #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] #[inline] #[must_use] diff --git a/library/core/src/slice/raw.rs b/library/core/src/slice/raw.rs index 998f9360332ff..fb571d863f459 100644 --- a/library/core/src/slice/raw.rs +++ b/library/core/src/slice/raw.rs @@ -171,7 +171,7 @@ pub const unsafe fn from_raw_parts<'a, T>(data: *const T, len: usize) -> &'a [T] /// [`NonNull::dangling()`]: ptr::NonNull::dangling #[inline] #[stable(feature = "rust1", since = "1.0.0")] -#[rustc_const_stable(feature = "const_slice_from_raw_parts_mut", since = "CURRENT_RUSTC_VERSION")] +#[rustc_const_stable(feature = "const_slice_from_raw_parts_mut", since = "1.83.0")] #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] #[must_use] #[rustc_diagnostic_item = "slice_from_raw_parts_mut"] @@ -204,7 +204,7 @@ pub const fn from_ref(s: &T) -> &[T] { /// Converts a reference to T into a slice of length 1 (without copying). #[stable(feature = "from_ref", since = "1.28.0")] -#[rustc_const_stable(feature = "const_slice_from_ref", since = "CURRENT_RUSTC_VERSION")] +#[rustc_const_stable(feature = "const_slice_from_ref", since = "1.83.0")] #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] #[must_use] pub const fn from_mut(s: &mut T) -> &mut [T] { diff --git a/library/core/src/str/converts.rs b/library/core/src/str/converts.rs index 194db56fdafda..b61ed454cd9ec 100644 --- a/library/core/src/str/converts.rs +++ b/library/core/src/str/converts.rs @@ -196,10 +196,7 @@ pub const unsafe fn from_utf8_unchecked(v: &[u8]) -> &str { #[must_use] #[stable(feature = "str_mut_extras", since = "1.20.0")] #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] -#[rustc_const_stable( - feature = "const_str_from_utf8_unchecked_mut", - since = "CURRENT_RUSTC_VERSION" -)] +#[rustc_const_stable(feature = "const_str_from_utf8_unchecked_mut", since = "1.83.0")] #[rustc_diagnostic_item = "str_from_utf8_unchecked_mut"] pub const unsafe fn from_utf8_unchecked_mut(v: &mut [u8]) -> &mut str { // SAFETY: the caller must guarantee that the bytes `v` diff --git a/library/core/src/str/mod.rs b/library/core/src/str/mod.rs index e93c52f27999e..d737eb2f0f59b 100644 --- a/library/core/src/str/mod.rs +++ b/library/core/src/str/mod.rs @@ -340,7 +340,7 @@ impl str { /// ``` #[stable(feature = "str_mut_extras", since = "1.20.0")] #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] - #[rustc_const_stable(feature = "const_str_as_mut", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_str_as_mut", since = "1.83.0")] #[must_use] #[inline(always)] pub const unsafe fn as_bytes_mut(&mut self) -> &mut [u8] { @@ -387,7 +387,7 @@ impl str { /// modified in a way that it remains valid UTF-8. #[stable(feature = "str_as_mut_ptr", since = "1.36.0")] #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))] - #[rustc_const_stable(feature = "const_str_as_mut", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_str_as_mut", since = "1.83.0")] #[rustc_never_returns_null_ptr] #[must_use] #[inline(always)] diff --git a/library/core/src/task/wake.rs b/library/core/src/task/wake.rs index fc549abd43365..3e795e7b5e3f8 100644 --- a/library/core/src/task/wake.rs +++ b/library/core/src/task/wake.rs @@ -519,8 +519,8 @@ impl Waker { /// [`Wake`]: ../../alloc/task/trait.Wake.html #[inline] #[must_use] - #[stable(feature = "waker_getters", since = "CURRENT_RUSTC_VERSION")] - #[rustc_const_stable(feature = "waker_getters", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "waker_getters", since = "1.83.0")] + #[rustc_const_stable(feature = "waker_getters", since = "1.83.0")] pub const unsafe fn new(data: *const (), vtable: &'static RawWakerVTable) -> Self { Waker { waker: RawWaker { data, vtable } } } @@ -584,7 +584,7 @@ impl Waker { /// Gets the `data` pointer used to create this `Waker`. #[inline] #[must_use] - #[stable(feature = "waker_getters", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "waker_getters", since = "1.83.0")] pub fn data(&self) -> *const () { self.waker.data } @@ -592,7 +592,7 @@ impl Waker { /// Gets the `vtable` pointer used to create this `Waker`. #[inline] #[must_use] - #[stable(feature = "waker_getters", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "waker_getters", since = "1.83.0")] pub fn vtable(&self) -> &'static RawWakerVTable { self.waker.vtable } diff --git a/library/core/src/time.rs b/library/core/src/time.rs index f7ea7e06e9cdb..f00ae67a4020b 100644 --- a/library/core/src/time.rs +++ b/library/core/src/time.rs @@ -846,7 +846,7 @@ impl Duration { #[stable(feature = "duration_float", since = "1.38.0")] #[must_use] #[inline] - #[rustc_const_stable(feature = "duration_consts_float", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "duration_consts_float", since = "1.83.0")] pub const fn as_secs_f64(&self) -> f64 { (self.secs as f64) + (self.nanos.0 as f64) / (NANOS_PER_SEC as f64) } @@ -865,7 +865,7 @@ impl Duration { #[stable(feature = "duration_float", since = "1.38.0")] #[must_use] #[inline] - #[rustc_const_stable(feature = "duration_consts_float", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "duration_consts_float", since = "1.83.0")] pub const fn as_secs_f32(&self) -> f32 { (self.secs as f32) + (self.nanos.0 as f32) / (NANOS_PER_SEC as f32) } @@ -1086,7 +1086,7 @@ impl Duration { #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] - #[rustc_const_stable(feature = "duration_consts_float", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "duration_consts_float", since = "1.83.0")] pub const fn div_duration_f64(self, rhs: Duration) -> f64 { let self_nanos = (self.secs as f64) * (NANOS_PER_SEC as f64) + (self.nanos.0 as f64); let rhs_nanos = (rhs.secs as f64) * (NANOS_PER_SEC as f64) + (rhs.nanos.0 as f64); @@ -1107,7 +1107,7 @@ impl Duration { #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] - #[rustc_const_stable(feature = "duration_consts_float", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "duration_consts_float", since = "1.83.0")] pub const fn div_duration_f32(self, rhs: Duration) -> f32 { let self_nanos = (self.secs as f32) * (NANOS_PER_SEC as f32) + (self.nanos.0 as f32); let rhs_nanos = (rhs.secs as f32) * (NANOS_PER_SEC as f32) + (rhs.nanos.0 as f32); diff --git a/library/std/src/collections/hash/map.rs b/library/std/src/collections/hash/map.rs index f2e523dca779c..ded4f404d781e 100644 --- a/library/std/src/collections/hash/map.rs +++ b/library/std/src/collections/hash/map.rs @@ -1438,7 +1438,7 @@ impl Clone for Iter<'_, K, V> { } } -#[stable(feature = "default_iters_hash", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "default_iters_hash", since = "1.83.0")] impl Default for Iter<'_, K, V> { #[inline] fn default() -> Self { @@ -1484,7 +1484,7 @@ impl<'a, K, V> IterMut<'a, K, V> { } } -#[stable(feature = "default_iters_hash", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "default_iters_hash", since = "1.83.0")] impl Default for IterMut<'_, K, V> { #[inline] fn default() -> Self { @@ -1522,7 +1522,7 @@ impl IntoIter { } } -#[stable(feature = "default_iters_hash", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "default_iters_hash", since = "1.83.0")] impl Default for IntoIter { #[inline] fn default() -> Self { @@ -1562,7 +1562,7 @@ impl Clone for Keys<'_, K, V> { } } -#[stable(feature = "default_iters_hash", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "default_iters_hash", since = "1.83.0")] impl Default for Keys<'_, K, V> { #[inline] fn default() -> Self { @@ -1609,7 +1609,7 @@ impl Clone for Values<'_, K, V> { } } -#[stable(feature = "default_iters_hash", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "default_iters_hash", since = "1.83.0")] impl Default for Values<'_, K, V> { #[inline] fn default() -> Self { @@ -1705,7 +1705,7 @@ pub struct ValuesMut<'a, K: 'a, V: 'a> { inner: IterMut<'a, K, V>, } -#[stable(feature = "default_iters_hash", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "default_iters_hash", since = "1.83.0")] impl Default for ValuesMut<'_, K, V> { #[inline] fn default() -> Self { @@ -1735,7 +1735,7 @@ pub struct IntoKeys { inner: IntoIter, } -#[stable(feature = "default_iters_hash", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "default_iters_hash", since = "1.83.0")] impl Default for IntoKeys { #[inline] fn default() -> Self { @@ -1765,7 +1765,7 @@ pub struct IntoValues { inner: IntoIter, } -#[stable(feature = "default_iters_hash", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "default_iters_hash", since = "1.83.0")] impl Default for IntoValues { #[inline] fn default() -> Self { @@ -2865,7 +2865,7 @@ impl<'a, K, V> Entry<'a, K, V> { /// assert_eq!(entry.key(), &"poneyland"); /// ``` #[inline] - #[stable(feature = "entry_insert", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "entry_insert", since = "1.83.0")] pub fn insert_entry(self, value: V) -> OccupiedEntry<'a, K, V> { match self { Occupied(mut entry) => { @@ -3152,7 +3152,7 @@ impl<'a, K: 'a, V: 'a> VacantEntry<'a, K, V> { /// assert_eq!(map["poneyland"], 37); /// ``` #[inline] - #[stable(feature = "entry_insert", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "entry_insert", since = "1.83.0")] pub fn insert_entry(self, value: V) -> OccupiedEntry<'a, K, V> { let base = self.base.insert_entry(value); OccupiedEntry { base } diff --git a/library/std/src/collections/hash/set.rs b/library/std/src/collections/hash/set.rs index 210f57152250c..e1e0eb36d23f0 100644 --- a/library/std/src/collections/hash/set.rs +++ b/library/std/src/collections/hash/set.rs @@ -1244,7 +1244,7 @@ pub struct Iter<'a, K: 'a> { base: base::Iter<'a, K>, } -#[stable(feature = "default_iters_hash", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "default_iters_hash", since = "1.83.0")] impl Default for Iter<'_, K> { #[inline] fn default() -> Self { @@ -1273,7 +1273,7 @@ pub struct IntoIter { base: base::IntoIter, } -#[stable(feature = "default_iters_hash", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "default_iters_hash", since = "1.83.0")] impl Default for IntoIter { #[inline] fn default() -> Self { diff --git a/library/std/src/io/error.rs b/library/std/src/io/error.rs index f20814dd95cc1..adf103e9430b8 100644 --- a/library/std/src/io/error.rs +++ b/library/std/src/io/error.rs @@ -223,10 +223,10 @@ pub enum ErrorKind { #[stable(feature = "rust1", since = "1.0.0")] ConnectionReset, /// The remote host is not reachable. - #[stable(feature = "io_error_a_bit_more", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "io_error_a_bit_more", since = "1.83.0")] HostUnreachable, /// The network containing the remote host is not reachable. - #[stable(feature = "io_error_a_bit_more", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "io_error_a_bit_more", since = "1.83.0")] NetworkUnreachable, /// The connection was aborted (terminated) by the remote server. #[stable(feature = "rust1", since = "1.0.0")] @@ -243,7 +243,7 @@ pub enum ErrorKind { #[stable(feature = "rust1", since = "1.0.0")] AddrNotAvailable, /// The system's networking is down. - #[stable(feature = "io_error_a_bit_more", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "io_error_a_bit_more", since = "1.83.0")] NetworkDown, /// The operation failed because a pipe was closed. #[stable(feature = "rust1", since = "1.0.0")] @@ -259,18 +259,18 @@ pub enum ErrorKind { /// /// For example, a filesystem path was specified where one of the intermediate directory /// components was, in fact, a plain file. - #[stable(feature = "io_error_a_bit_more", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "io_error_a_bit_more", since = "1.83.0")] NotADirectory, /// The filesystem object is, unexpectedly, a directory. /// /// A directory was specified when a non-directory was expected. - #[stable(feature = "io_error_a_bit_more", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "io_error_a_bit_more", since = "1.83.0")] IsADirectory, /// A non-empty directory was specified where an empty directory was expected. - #[stable(feature = "io_error_a_bit_more", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "io_error_a_bit_more", since = "1.83.0")] DirectoryNotEmpty, /// The filesystem or storage medium is read-only, but a write operation was attempted. - #[stable(feature = "io_error_a_bit_more", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "io_error_a_bit_more", since = "1.83.0")] ReadOnlyFilesystem, /// Loop in the filesystem or IO subsystem; often, too many levels of symbolic links. /// @@ -285,7 +285,7 @@ pub enum ErrorKind { /// /// With some network filesystems, notably NFS, an open file (or directory) can be invalidated /// by problems with the network or server. - #[stable(feature = "io_error_a_bit_more", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "io_error_a_bit_more", since = "1.83.0")] StaleNetworkFileHandle, /// A parameter was incorrect. #[stable(feature = "rust1", since = "1.0.0")] @@ -319,13 +319,13 @@ pub enum ErrorKind { /// The underlying storage (typically, a filesystem) is full. /// /// This does not include out of quota errors. - #[stable(feature = "io_error_a_bit_more", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "io_error_a_bit_more", since = "1.83.0")] StorageFull, /// Seek on unseekable file. /// /// Seeking was attempted on an open file handle which is not suitable for seeking - for /// example, on Unix, a named pipe opened with `File::open`. - #[stable(feature = "io_error_a_bit_more", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "io_error_a_bit_more", since = "1.83.0")] NotSeekable, /// Filesystem quota was exceeded. #[unstable(feature = "io_error_more", issue = "86442")] @@ -335,22 +335,22 @@ pub enum ErrorKind { /// This might arise from a hard limit of the underlying filesystem or file access API, or from /// an administratively imposed resource limitation. Simple disk full, and out of quota, have /// their own errors. - #[stable(feature = "io_error_a_bit_more", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "io_error_a_bit_more", since = "1.83.0")] FileTooLarge, /// Resource is busy. - #[stable(feature = "io_error_a_bit_more", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "io_error_a_bit_more", since = "1.83.0")] ResourceBusy, /// Executable file is busy. /// /// An attempt was made to write to a file which is also in use as a running program. (Not all /// operating systems detect this situation.) - #[stable(feature = "io_error_a_bit_more", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "io_error_a_bit_more", since = "1.83.0")] ExecutableFileBusy, /// Deadlock (avoided). /// /// A file locking operation would result in deadlock. This situation is typically detected, if /// at all, on a best-effort basis. - #[stable(feature = "io_error_a_bit_more", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "io_error_a_bit_more", since = "1.83.0")] Deadlock, /// Cross-device or cross-filesystem (hard) link or rename. #[unstable(feature = "io_error_more", issue = "86442")] @@ -358,7 +358,7 @@ pub enum ErrorKind { /// Too many (hard) links to the same filesystem object. /// /// The filesystem does not support making so many hardlinks to the same file. - #[stable(feature = "io_error_a_bit_more", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "io_error_a_bit_more", since = "1.83.0")] TooManyLinks, /// A filename was invalid. /// @@ -369,7 +369,7 @@ pub enum ErrorKind { /// /// When trying to run an external program, a system or process limit on the size of the /// arguments would have been exceeded. - #[stable(feature = "io_error_a_bit_more", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "io_error_a_bit_more", since = "1.83.0")] ArgumentListTooLong, /// This operation was interrupted. /// diff --git a/library/std/src/io/mod.rs b/library/std/src/io/mod.rs index 8fedcb241d095..71dfd0676c942 100644 --- a/library/std/src/io/mod.rs +++ b/library/std/src/io/mod.rs @@ -2405,7 +2405,7 @@ pub trait BufRead: Read { /// assert_eq!(num_bytes, 11); /// assert_eq!(animal, b"Crustacean\0"); /// ``` - #[stable(feature = "bufread_skip_until", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "bufread_skip_until", since = "1.83.0")] fn skip_until(&mut self, byte: u8) -> Result { skip_until(self, byte) } From 9d86b49b9040f9ae2669de050487364b3c8cf4d1 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Mon, 14 Oct 2024 10:23:50 -0700 Subject: [PATCH 2154/2194] bump channel to beta --- src/ci/channel | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ci/channel b/src/ci/channel index bf867e0ae5b6c..65b2df87f7df3 100644 --- a/src/ci/channel +++ b/src/ci/channel @@ -1 +1 @@ -nightly +beta From 6af8e028a8d03bb7437ae23bcd8f0367e001330a Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Sun, 13 Oct 2024 17:00:41 +0300 Subject: [PATCH 2155/2194] check `stage0`, `channel` and `version` files for CI rustc These files have important role for compiler builds, so include them in the "if-unchanged" rustc logic. Signed-off-by: onur-ozkan (cherry picked from commit 6e6cbdd2df0ae5a025c458d95a4c84df1b6af092) --- src/bootstrap/src/core/config/config.rs | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs index 3f025a198cb97..f768470c4ff0e 100644 --- a/src/bootstrap/src/core/config/config.rs +++ b/src/bootstrap/src/core/config/config.rs @@ -2748,13 +2748,18 @@ impl Config { } }; - // Look for a version to compare to based on the current commit. - // Only commits merged by bors will have CI artifacts. - let commit = get_closest_merge_commit(Some(&self.src), &self.git_config(), &[ + let files_to_track = &[ self.src.join("compiler"), self.src.join("library"), - ]) - .unwrap(); + self.src.join("src/version"), + self.src.join("src/stage0"), + self.src.join("src/ci/channel"), + ]; + + // Look for a version to compare to based on the current commit. + // Only commits merged by bors will have CI artifacts. + let commit = + get_closest_merge_commit(Some(&self.src), &self.git_config(), files_to_track).unwrap(); if commit.is_empty() { println!("ERROR: could not find commit hash for downloading rustc"); println!("HELP: maybe your repository history is too shallow?"); @@ -2780,7 +2785,7 @@ impl Config { let has_changes = !t!(helpers::git(Some(&self.src)) .args(["diff-index", "--quiet", &commit]) .arg("--") - .args([self.src.join("compiler"), self.src.join("library")]) + .args(files_to_track) .as_command_mut() .status()) .success(); From a43016a6f93150235457158cea459294a3a416bb Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Thu, 17 Oct 2024 10:29:19 -0700 Subject: [PATCH 2156/2194] bump stage0 to 1.82.0 --- src/stage0 | 802 +++++++++++++++++++++++------------------------------ 1 file changed, 350 insertions(+), 452 deletions(-) diff --git a/src/stage0 b/src/stage0 index 0d6542d2dd707..c921c28890970 100644 --- a/src/stage0 +++ b/src/stage0 @@ -14,456 +14,354 @@ nightly_branch=master # All changes below this comment will be overridden the next time the # tool is executed. -compiler_date=2024-09-22 -compiler_version=beta -rustfmt_date=2024-09-22 -rustfmt_version=nightly +compiler_date=2024-10-17 +compiler_version=1.82.0 -dist/2024-09-22/rustc-beta-aarch64-apple-darwin.tar.gz=59b70ccc04680e74bbd1e13368bbf5639679fb8e1e7ba39ae4a235f9a96522f6 -dist/2024-09-22/rustc-beta-aarch64-apple-darwin.tar.xz=d4b18e0a269e7b66dbbdf03d7da6b478c6cff9cd52ef34f110b68a9ff0111d0f -dist/2024-09-22/rustc-beta-aarch64-pc-windows-msvc.tar.gz=7cc2e8511801c27360e17cc0380e30e5eb6cc185224aba94bf9ed852e5ff2ce0 -dist/2024-09-22/rustc-beta-aarch64-pc-windows-msvc.tar.xz=a9f8f8e691b9a307ddc4468cc34964063253292f18869d21dc91ca437bbc08fd -dist/2024-09-22/rustc-beta-aarch64-unknown-linux-gnu.tar.gz=5940e8c99d329fae3cc4b1d5709e9481e8f2b1dc799363ae0a1429ea4df4ad41 -dist/2024-09-22/rustc-beta-aarch64-unknown-linux-gnu.tar.xz=c7c36aada972ea10e50e0904530d06b2df074f9981dec4dcc66efeaa16499c1b -dist/2024-09-22/rustc-beta-aarch64-unknown-linux-musl.tar.gz=2ae2b1e2d90c130be5274806db1e4dcdfe0b588fe72f967e58b128aa1d28a7eb -dist/2024-09-22/rustc-beta-aarch64-unknown-linux-musl.tar.xz=d8297b214d4ef841bb5963e71353ce08a4d3aead47a2cdf234e0846ad0b1ccbb -dist/2024-09-22/rustc-beta-arm-unknown-linux-gnueabi.tar.gz=256b62cd5f1bc17c081277752a49d38104ce438e83342e6bbb467442e9250563 -dist/2024-09-22/rustc-beta-arm-unknown-linux-gnueabi.tar.xz=457ea31587b8ff8c9fcc7a9ed4bf958625c7b9e55d640329ccdf432309a6583f -dist/2024-09-22/rustc-beta-arm-unknown-linux-gnueabihf.tar.gz=4cc8f851eff833100fe4d7c421c25e65d4779d8cdbb9b5e2cb3c8f5ebf9f8e98 -dist/2024-09-22/rustc-beta-arm-unknown-linux-gnueabihf.tar.xz=6ab386aaab687a253b3d28b12307ad5c8df2ea1a0af281a8fab6fe6d24ee6130 -dist/2024-09-22/rustc-beta-armv7-unknown-linux-gnueabihf.tar.gz=0b548c45c2ec840942b29a68ad38debd8a2ec7c920d3be7cda91365e0a8fce80 -dist/2024-09-22/rustc-beta-armv7-unknown-linux-gnueabihf.tar.xz=bc1ce3524199c62230fc08b9dab1282d2f31d3cd1a892cbc8bfab0257e0ff5dc -dist/2024-09-22/rustc-beta-i686-pc-windows-gnu.tar.gz=a407a4dda4c24e8e9d510843aa9e8f06291622d240538a14c1d924d8b7d84e33 -dist/2024-09-22/rustc-beta-i686-pc-windows-gnu.tar.xz=fe3b235ed043d14856f47babf433ae214d9b64480b1824053fee8b99ca69cc69 -dist/2024-09-22/rustc-beta-i686-pc-windows-msvc.tar.gz=a156aa0fb17b5edf476f97b8e839f9fe550ed3edd63a2fe2936a7fe0f388ece4 -dist/2024-09-22/rustc-beta-i686-pc-windows-msvc.tar.xz=0e46e75722b10bbbd2631c2676089665f92ce092408ed63aa14c99b1fc385369 -dist/2024-09-22/rustc-beta-i686-unknown-linux-gnu.tar.gz=5523e67362db0840d6f0ab6a1deec99c1b64c32fae94362792b0aa031bfd39d6 -dist/2024-09-22/rustc-beta-i686-unknown-linux-gnu.tar.xz=45a820f2ebd182ec3237436a567960d2bd0f92e9e603aa394b1a6eafbd9ba0fa -dist/2024-09-22/rustc-beta-loongarch64-unknown-linux-gnu.tar.gz=bdbe165ffd50974b32f4b570da7908c125739c0321f700d12cc481f32ab76eaa -dist/2024-09-22/rustc-beta-loongarch64-unknown-linux-gnu.tar.xz=997a8387989676848355e30dea1b131fa96945e62cef8f011025c52351db1269 -dist/2024-09-22/rustc-beta-loongarch64-unknown-linux-musl.tar.gz=a49f46df49a9aa974ff10361ae29267d2c86c10486399803a5a6879e638212f2 -dist/2024-09-22/rustc-beta-loongarch64-unknown-linux-musl.tar.xz=ee236f4dab4a06d23b6040a47afdf73496bc9093b3b29fae896f5f5bbe87c222 -dist/2024-09-22/rustc-beta-powerpc-unknown-linux-gnu.tar.gz=e83c1253643c4ff70301bab198db731ac65c6d3b0ec847d7aa68bd6afef6ee93 -dist/2024-09-22/rustc-beta-powerpc-unknown-linux-gnu.tar.xz=f7f09a5028ca3f45475cedec7518ead06b2e305554292462d82b2032e5d83f73 -dist/2024-09-22/rustc-beta-powerpc64-unknown-linux-gnu.tar.gz=9ef2829f5b2bc9666bba319875eecbda37840d204f7c1493dce2a4f2f45d45c5 -dist/2024-09-22/rustc-beta-powerpc64-unknown-linux-gnu.tar.xz=140489beedcf46e02931ce8f69e9008ea4c7e3c332d0a3482d4495d7fff21b81 -dist/2024-09-22/rustc-beta-powerpc64le-unknown-linux-gnu.tar.gz=63a34f34425d6c11d62768a3cdfc4602d96ae0f11d82344412a69a3b1ec550b9 -dist/2024-09-22/rustc-beta-powerpc64le-unknown-linux-gnu.tar.xz=108d429397a5cef93151439646b684109d1b619c1a6f11544062e407258f4897 -dist/2024-09-22/rustc-beta-riscv64gc-unknown-linux-gnu.tar.gz=77cb4dea8b55779e0f3de1f48e74de966d3a2dc27946228b42b0eae654d53e5a -dist/2024-09-22/rustc-beta-riscv64gc-unknown-linux-gnu.tar.xz=93b7dc39c3da7560cbabef5a35dddec111a4d9c0ec0e2b0648925975c5042b31 -dist/2024-09-22/rustc-beta-s390x-unknown-linux-gnu.tar.gz=58b1eed6046552703f8993b36d2a571d12db806ca9665d276c338fc89f79b980 -dist/2024-09-22/rustc-beta-s390x-unknown-linux-gnu.tar.xz=39ad5c20dd703e5949f008ed21e671b1438a1160b4aece5ba434ae03f32004cf -dist/2024-09-22/rustc-beta-x86_64-apple-darwin.tar.gz=c5082f7773f1573a1f60148ed744f148169b3c58ca38539e72688cb31221003e -dist/2024-09-22/rustc-beta-x86_64-apple-darwin.tar.xz=a797564192dc84184d5af88ecb4d295ab266cde4a1c4407b06c56f656800e336 -dist/2024-09-22/rustc-beta-x86_64-pc-windows-gnu.tar.gz=0f29dc08756a36f42e9937cf9e2f8c5cc7771fab5b791b58dd7b038dcb20e2ca -dist/2024-09-22/rustc-beta-x86_64-pc-windows-gnu.tar.xz=9a9f6178208f01487a132ab91ffb1251722df3f6e3ccc7f4b3e79dc389b7217a -dist/2024-09-22/rustc-beta-x86_64-pc-windows-msvc.tar.gz=2f2b828b46dea57c9896149a5ffc5cc6db368d90067c498f554b9ea75de0990f -dist/2024-09-22/rustc-beta-x86_64-pc-windows-msvc.tar.xz=42c64410633bf748134ba004ef397f2319556e44fc2862a4f3a5e847e334fdbf -dist/2024-09-22/rustc-beta-x86_64-unknown-freebsd.tar.gz=9ba0fdecbd343606bbdf2d4b401d64ed5de82e4bd508c0e6b6bcc21365c4b840 -dist/2024-09-22/rustc-beta-x86_64-unknown-freebsd.tar.xz=aeabedce922b315fb872127a6102a76e9fe5e1932b14a7210f31191f9a85488b -dist/2024-09-22/rustc-beta-x86_64-unknown-illumos.tar.gz=4d5348b0ef100a1691f655acee54447866d76b46f88e23ee641eb5e4b4318b4c -dist/2024-09-22/rustc-beta-x86_64-unknown-illumos.tar.xz=046b8d0139b97d78a741251ef7094629394f67cbb817a7239de704b4ff3a8963 -dist/2024-09-22/rustc-beta-x86_64-unknown-linux-gnu.tar.gz=81ba8a28534746a9c33c98a98aeeea89f6c057333827d919b2f404991e0ded45 -dist/2024-09-22/rustc-beta-x86_64-unknown-linux-gnu.tar.xz=358bbda124aa68416d55d8ed6c9a184f8ea7ae166f3f0427e8c9ac40900bd4b6 -dist/2024-09-22/rustc-beta-x86_64-unknown-linux-musl.tar.gz=8594ed15236342879b4c486e4d5e2440891e9dec52302e1bb6393008eaf876e7 -dist/2024-09-22/rustc-beta-x86_64-unknown-linux-musl.tar.xz=e45cdb771899998e42bf3f9e965a4b4557199b1632843c0472731d48ea664834 -dist/2024-09-22/rustc-beta-x86_64-unknown-netbsd.tar.gz=ba1d8b89c65441cfe6fa1341c6a7e21dc596df13cef8e8038d8d7ac376bd91fc -dist/2024-09-22/rustc-beta-x86_64-unknown-netbsd.tar.xz=95fb21a9730eaf815ba6da5f42b997accca0b578870207912a2ea359b588421e -dist/2024-09-22/rust-std-beta-aarch64-apple-darwin.tar.gz=60127b21a176a56664e537a8e6d81c18c5406706f12e3a406ebad8c86f5fc442 -dist/2024-09-22/rust-std-beta-aarch64-apple-darwin.tar.xz=04d163b5bb40aa4ed7e712006155549eb5ca094e71b89b4a3e5142c40d0b2102 -dist/2024-09-22/rust-std-beta-aarch64-apple-ios.tar.gz=1463a6f3a55b1c7795c0417040423f2dc1d9a3df343ee4bd2d9c96b2de5c84e8 -dist/2024-09-22/rust-std-beta-aarch64-apple-ios.tar.xz=74a06570dd6bd8b501ccdcdf25b9b5ccac25936b883b37be6a0296d5e59394b6 -dist/2024-09-22/rust-std-beta-aarch64-apple-ios-macabi.tar.gz=ccdf0df40f435ca4c5f8d6b67cf06b48c1792d5b1592cb129e7e40e7690c3c5b -dist/2024-09-22/rust-std-beta-aarch64-apple-ios-macabi.tar.xz=4388b9b3ab0e048b6c8349a3ceae6afc078bdc217172d7ef0271afb5e181fb6f -dist/2024-09-22/rust-std-beta-aarch64-apple-ios-sim.tar.gz=4428d02fe8e43b5d082149991e88a4c9d342157fa1c2cd91903812240fb5bb08 -dist/2024-09-22/rust-std-beta-aarch64-apple-ios-sim.tar.xz=21f9c521dc8203584ce0c56536818431ec19f259f86b8d8cab5a33f7e44165cf -dist/2024-09-22/rust-std-beta-aarch64-linux-android.tar.gz=d9d238db60d1e54366cfb4f20e2a6c6b8bc055f83716837970261b074cc93218 -dist/2024-09-22/rust-std-beta-aarch64-linux-android.tar.xz=aab44af6a7f1dc483c943be9fd0b2ade0c938a844acc8deab76843e3dc514355 -dist/2024-09-22/rust-std-beta-aarch64-pc-windows-gnullvm.tar.gz=fccf8f5199da8c0fe2d1dec6ee384c9761f2e6334e5dce28add413f29207e902 -dist/2024-09-22/rust-std-beta-aarch64-pc-windows-gnullvm.tar.xz=d6373d38a862120c08afa569ea9941945b43ce1676f45ca995fb3b30c34500ec -dist/2024-09-22/rust-std-beta-aarch64-pc-windows-msvc.tar.gz=e0b31c36068626fbf2133a352002cbd8f4c2b6a1b5379a0ab0fd3bc640576e9d -dist/2024-09-22/rust-std-beta-aarch64-pc-windows-msvc.tar.xz=d10defe0175f8872ebb68d2dd331fa9bbbeb1fa892188371665547567f7f2738 -dist/2024-09-22/rust-std-beta-aarch64-unknown-fuchsia.tar.gz=dda6f7b74035c963dd89a2e003d6c7baca2e2db9bfdd3007f95743e44bd08cb0 -dist/2024-09-22/rust-std-beta-aarch64-unknown-fuchsia.tar.xz=23944ba7752e89e860f19f3c18d2951bb5c7c6b707bd6e06914f7d48aafee40c -dist/2024-09-22/rust-std-beta-aarch64-unknown-linux-gnu.tar.gz=b00fa5fea66b2af7d173d6405a59c529a1dd0b793d735c2d97fcab7775693ed4 -dist/2024-09-22/rust-std-beta-aarch64-unknown-linux-gnu.tar.xz=34bd748cc5bc0a6b6d8e6d8ea23693d7628bed11ebcd886860cd5c0b31ac3c0d -dist/2024-09-22/rust-std-beta-aarch64-unknown-linux-musl.tar.gz=ecb1b709c48556fabc527d976e6cc69b8b69384cb4c45e691195a12b9cdba383 -dist/2024-09-22/rust-std-beta-aarch64-unknown-linux-musl.tar.xz=2c90df930935dcf9f9725588ed6579100fdf676267305f715f03e413a04c3032 -dist/2024-09-22/rust-std-beta-aarch64-unknown-linux-ohos.tar.gz=56782db097cca16a0d6e8466b83b35bfd7334d5f48b9ac5c500767eeba30c122 -dist/2024-09-22/rust-std-beta-aarch64-unknown-linux-ohos.tar.xz=9b41b551b5f88dfa3fdcc1d22102f102627c5c88e42353edaceda6da3b76d97b -dist/2024-09-22/rust-std-beta-aarch64-unknown-none.tar.gz=087fccd0b40fe73a545885a58758eafb86e9bb7b9588d047c9536e5bd8c201b6 -dist/2024-09-22/rust-std-beta-aarch64-unknown-none.tar.xz=60039451dc07ada83944606e67363ca32b22879293bc41a6d66f6545e7e3f1aa -dist/2024-09-22/rust-std-beta-aarch64-unknown-none-softfloat.tar.gz=0e1f73720beaecff935d0a90272448f5dfb0c912b2e366239c46c6ab3b854cfc -dist/2024-09-22/rust-std-beta-aarch64-unknown-none-softfloat.tar.xz=c2670b262833415d43b22485c2734d87d8748315e6471a2a384249b2cba6e581 -dist/2024-09-22/rust-std-beta-aarch64-unknown-uefi.tar.gz=edfd391f36b6aa6758649ca6f9706d671956f078e572ea9ce5f9423a1310e817 -dist/2024-09-22/rust-std-beta-aarch64-unknown-uefi.tar.xz=59b09f6cef1d97b273262d3ccdd95d9c46766b82e935cb46538514292cd04a39 -dist/2024-09-22/rust-std-beta-arm-linux-androideabi.tar.gz=f84267d71217b79a5e622a281ce926c1a54ee9122e19b2647d1aa85afa9132be -dist/2024-09-22/rust-std-beta-arm-linux-androideabi.tar.xz=57e80fea8463416012339fc6f74e9ae4da7d92042d05311bc8a9620fec3541b2 -dist/2024-09-22/rust-std-beta-arm-unknown-linux-gnueabi.tar.gz=556ff5b6947ed37f5215953fbcbe3e82313e7deb9d32d5b86feabe46c8328e56 -dist/2024-09-22/rust-std-beta-arm-unknown-linux-gnueabi.tar.xz=3f0721bc56fa232ca4203dcb43f1ef8f453373d9a0fa4720d89c51b827407a91 -dist/2024-09-22/rust-std-beta-arm-unknown-linux-gnueabihf.tar.gz=57b81555f7d7695e985e1538795c97b9f0573cd84d6fda25a09d49ac54bd1a24 -dist/2024-09-22/rust-std-beta-arm-unknown-linux-gnueabihf.tar.xz=66d5af25be1dfc99fbeb1aa0c7eee30dc2d3e5766affb73e6e7c0e7b9a78abff -dist/2024-09-22/rust-std-beta-arm-unknown-linux-musleabi.tar.gz=23cfcb1cde1e95f55442ebb8ba155a0e13ec932cd7a8ab20a2ad09596a79b3a4 -dist/2024-09-22/rust-std-beta-arm-unknown-linux-musleabi.tar.xz=660d3f7b05da3d5b01775989546a687fe40090d193289c3ad24317c07c5eb445 -dist/2024-09-22/rust-std-beta-arm-unknown-linux-musleabihf.tar.gz=ee453c78eacca64fd0a6f1c066a6728ddca0ecbd6e184b63a4b4455f77183f07 -dist/2024-09-22/rust-std-beta-arm-unknown-linux-musleabihf.tar.xz=b003790997ebe0bfa095b0fe38db67db179a2f9e93f4b49852f5ec04828337f4 -dist/2024-09-22/rust-std-beta-arm64ec-pc-windows-msvc.tar.gz=60f03912a464169464800a603606e2cb8a302c998bd59f582cdd3b9bf39ecc82 -dist/2024-09-22/rust-std-beta-arm64ec-pc-windows-msvc.tar.xz=6d1858acf2f2cfb3daac89ae21cfc7a7df3e1f57dac0aaa3ee70057b1974c0f2 -dist/2024-09-22/rust-std-beta-armebv7r-none-eabi.tar.gz=b23fd4380d20e289e58b86afaad1df0636004c74a03d7f3ff861f26c6ca308f8 -dist/2024-09-22/rust-std-beta-armebv7r-none-eabi.tar.xz=beac209cec83a56315c109fc3a0e3b6b16f8044de270e23cdd9dc3e2b5db3af3 -dist/2024-09-22/rust-std-beta-armebv7r-none-eabihf.tar.gz=731064c4b9b35d420f740ff5fbc4f6dd1f038e3225db19ca861af6db5f283ea7 -dist/2024-09-22/rust-std-beta-armebv7r-none-eabihf.tar.xz=04b406b44da8aee6a077f9f971b5ba62bc98fb09413fe47fd892c67798381d5b -dist/2024-09-22/rust-std-beta-armv5te-unknown-linux-gnueabi.tar.gz=26dc6030f28453478e790879547f22a63ae810572cac790d4ed944eb68c96d87 -dist/2024-09-22/rust-std-beta-armv5te-unknown-linux-gnueabi.tar.xz=2aa9589c9512388e75c3c93e53b6a90ce5c973d98830a64388b0ec22618504c5 -dist/2024-09-22/rust-std-beta-armv5te-unknown-linux-musleabi.tar.gz=0020c2142cef0ab6bd62c4212f01dce2675104e0da5e701cbf03ee7c45a0fb2c -dist/2024-09-22/rust-std-beta-armv5te-unknown-linux-musleabi.tar.xz=b891ccdcbd8abf7d56d31b84800a17cbe1f6d4242584598433e38eff5a9a16c0 -dist/2024-09-22/rust-std-beta-armv7-linux-androideabi.tar.gz=128b86795a07b47088fbc51a251f6b112379454940878150547b54ffb95890e9 -dist/2024-09-22/rust-std-beta-armv7-linux-androideabi.tar.xz=26497ef07fb7f42198b4fc02b122497fc09bd215eb7e3e01c789b481bd2d86ae -dist/2024-09-22/rust-std-beta-armv7-unknown-linux-gnueabi.tar.gz=933f22ab901b9de042b17548e0218de699275a8553b8056d2d85430858f4e1bc -dist/2024-09-22/rust-std-beta-armv7-unknown-linux-gnueabi.tar.xz=495f8186e0c589882d1e1f1cf21ab28ea5531bad327b6d5ae1ca83d26c77944e -dist/2024-09-22/rust-std-beta-armv7-unknown-linux-gnueabihf.tar.gz=53c87859857618a011e94c14c5641927503c5543831acd16498d7fb244eb00b8 -dist/2024-09-22/rust-std-beta-armv7-unknown-linux-gnueabihf.tar.xz=7ee039186087e320396e56cdd9e5a6b7993c44783e3a80fd86e74e41be646a57 -dist/2024-09-22/rust-std-beta-armv7-unknown-linux-musleabi.tar.gz=fa9f256a201c4fe5cd95363c2cb02d87565a321e27554e83d63f1d61ed55dfda -dist/2024-09-22/rust-std-beta-armv7-unknown-linux-musleabi.tar.xz=fd3eced91b52924bb6d4acb3cc6c3bd7b45a1879e353f22442cb1e76ed5a7f28 -dist/2024-09-22/rust-std-beta-armv7-unknown-linux-musleabihf.tar.gz=b683d929fd6a6b60a786ec154970338158cc2b7bce28601b70966b898017b131 -dist/2024-09-22/rust-std-beta-armv7-unknown-linux-musleabihf.tar.xz=518fa28ee0292b95322bea4c0b714146a1b94c730e49bb6a84038520c91a668b -dist/2024-09-22/rust-std-beta-armv7-unknown-linux-ohos.tar.gz=d0f8659cddfc6da0b0dd815794f86ec1ffa0a243020dc9190c4358c6cdc03fdf -dist/2024-09-22/rust-std-beta-armv7-unknown-linux-ohos.tar.xz=89f39595aa42f23efa2b3853c466cddd6a932043bae3373193c25b788c15efd6 -dist/2024-09-22/rust-std-beta-armv7a-none-eabi.tar.gz=c1fc1973cc683c313e50542f1a6b69f1b5a5b4ac558b45954f79ef4dff9d5f75 -dist/2024-09-22/rust-std-beta-armv7a-none-eabi.tar.xz=00c45dfc370ea40d8993519bdb5cce8f5167401434f0b7553b6fdf7c5b49da87 -dist/2024-09-22/rust-std-beta-armv7r-none-eabi.tar.gz=ef54f8762f1d190b822e58b845889ac9c2dba4250cf0d693a3b1cbf64e2cf8a2 -dist/2024-09-22/rust-std-beta-armv7r-none-eabi.tar.xz=9375a15e96f7b3da4394bcda8ce34c452417f4278f07926830d5b00b155cb338 -dist/2024-09-22/rust-std-beta-armv7r-none-eabihf.tar.gz=85a5ae26f11c47872649699eaf01557aac746831b4c30de7b892438cc736b679 -dist/2024-09-22/rust-std-beta-armv7r-none-eabihf.tar.xz=e9dde209b4e0de6ae76b316c5e3aa2923f208bd9aa7858fef5177ba2e3b06119 -dist/2024-09-22/rust-std-beta-i586-pc-windows-msvc.tar.gz=652bc4cbf176d0780a81cff637684fd8f1cdc99c7a58d68325f54564942d46dc -dist/2024-09-22/rust-std-beta-i586-pc-windows-msvc.tar.xz=367eca53e9c4be297454751d2d8b7f5503caf669962a44ea92290b0772969fb6 -dist/2024-09-22/rust-std-beta-i586-unknown-linux-gnu.tar.gz=7c48fb48b02628358ae3572c92d5cc112734e99606c78d04b29e665ee03f36ec -dist/2024-09-22/rust-std-beta-i586-unknown-linux-gnu.tar.xz=4ac829df3b8b5e7864b883713a90ed18a9b08f45a3da2af2c6b3f700c8d7c27c -dist/2024-09-22/rust-std-beta-i586-unknown-linux-musl.tar.gz=7786d5b5e0cb8489df5456854cbbdfefbb8b4a3755f61e62747abc224e48dfc6 -dist/2024-09-22/rust-std-beta-i586-unknown-linux-musl.tar.xz=e2ec9458a99a159480a45b8107041b3b4054316ba15adaf802690d2bf66b2f22 -dist/2024-09-22/rust-std-beta-i686-linux-android.tar.gz=54edc2ca229e1a5aad5077800c492cf5038da341555eda11fc4b77d1a3896def -dist/2024-09-22/rust-std-beta-i686-linux-android.tar.xz=a75135f1e04b716855fce5b830797ea87bd428d54c06190cc8067ba5952d7215 -dist/2024-09-22/rust-std-beta-i686-pc-windows-gnu.tar.gz=4c5b54eecd6efbb03a3a01f57c265d47c49df49dd584e67b493205fcec92a59b -dist/2024-09-22/rust-std-beta-i686-pc-windows-gnu.tar.xz=7ec6292ac497b450277c17cca3ca87321d5b6bd545bd479b37698ceebdcbf719 -dist/2024-09-22/rust-std-beta-i686-pc-windows-gnullvm.tar.gz=0deb2de1b9830099bb6de1bb99e4658c8e4e3438e555f239c85309b771293e6b -dist/2024-09-22/rust-std-beta-i686-pc-windows-gnullvm.tar.xz=f35566df72b302dd446d449ffc8a775015b30970911c5284a3d4c1866e004a6b -dist/2024-09-22/rust-std-beta-i686-pc-windows-msvc.tar.gz=17e505c8ece5c89988896b1c14400b203e2588bc7777189bef89335cc868fb1d -dist/2024-09-22/rust-std-beta-i686-pc-windows-msvc.tar.xz=197fe430d6fce984ca397ba664beb25d4a0216180cd8fc2797710a8c541573a8 -dist/2024-09-22/rust-std-beta-i686-unknown-freebsd.tar.gz=9d7ff528d75e80ebb8255c9b6ef3f5ec6db579524e03dc3aad540690401fb7b8 -dist/2024-09-22/rust-std-beta-i686-unknown-freebsd.tar.xz=81152e616efe27a4ae80d2ffc86b79211c31ab324faa7847606f6ed839a3d470 -dist/2024-09-22/rust-std-beta-i686-unknown-linux-gnu.tar.gz=b1913a26f2258531596e1ef31fc42d720f807f04b068802ea3a0164d877d694c -dist/2024-09-22/rust-std-beta-i686-unknown-linux-gnu.tar.xz=3be89fd0c0f0a5b6d5cea23feffd32573be29ec1ce6c96b88ac35e04cf1eaa46 -dist/2024-09-22/rust-std-beta-i686-unknown-linux-musl.tar.gz=e446e4cbb904f89fbaf7bd48be6975671db2cc2ad018fc03e967dff2bbce0e3d -dist/2024-09-22/rust-std-beta-i686-unknown-linux-musl.tar.xz=453d6a6b1872e884aeae40936e950b7c2d0ce291c9f5882fc9c15a6b3e9c86fe -dist/2024-09-22/rust-std-beta-i686-unknown-uefi.tar.gz=a330462d4b0ade7028d2c2bd8764b1225cc9eac90b014c8899f971fadf002cba -dist/2024-09-22/rust-std-beta-i686-unknown-uefi.tar.xz=8fdb9e12d0cf92e0c4fcbcdc57daceb2cf17b21786e1252904ec0faba4b90a9d -dist/2024-09-22/rust-std-beta-loongarch64-unknown-linux-gnu.tar.gz=82859d2feb163fa7ac068db184e8c76261771dc47838bd952301ffd8037d885a -dist/2024-09-22/rust-std-beta-loongarch64-unknown-linux-gnu.tar.xz=1fa1ae996cd7010b4ab9006bfcb69098fcadbfc7a8f6988bdd34c62d2d6309f3 -dist/2024-09-22/rust-std-beta-loongarch64-unknown-linux-musl.tar.gz=e4200a2c1eb5a1420071fde891266849da5d46aaf46031129ae329175a3708f8 -dist/2024-09-22/rust-std-beta-loongarch64-unknown-linux-musl.tar.xz=15fc279f0c1370d05543af48c493d91687e3de2dc25123a1b657919494a0653c -dist/2024-09-22/rust-std-beta-loongarch64-unknown-none.tar.gz=4cc49f8231bca8c19e4d449cf3b3cd84d5db9e4665394ebada29ea626cee4dc4 -dist/2024-09-22/rust-std-beta-loongarch64-unknown-none.tar.xz=b3b7959a696c75575edb3676520f64178151df1d523128c6ed6e28cd0c8051b9 -dist/2024-09-22/rust-std-beta-loongarch64-unknown-none-softfloat.tar.gz=7b15fd753967116653b4372e10796ae2ea35910872f517a2d1c6dd3539717915 -dist/2024-09-22/rust-std-beta-loongarch64-unknown-none-softfloat.tar.xz=87f88922e5c3a17af392bade5af1ce94f03aac275e6ed3dbadc9d6c720223c7f -dist/2024-09-22/rust-std-beta-nvptx64-nvidia-cuda.tar.gz=f1d4f6887d12f1316bcf515bd07f9474bb9e036dfe78171720d72e98de580791 -dist/2024-09-22/rust-std-beta-nvptx64-nvidia-cuda.tar.xz=2dcaa78854d5b619e9609db70fa805cdf1e5baf2fac35f3eefb66ae854e78891 -dist/2024-09-22/rust-std-beta-powerpc-unknown-linux-gnu.tar.gz=c4ae30e180d94550da74b09f6005a6224136d8b5d752e9cdb1b44081a95b8c9f -dist/2024-09-22/rust-std-beta-powerpc-unknown-linux-gnu.tar.xz=c6438a341e8008b3c475e3250d52df2cb0a505862a14ed70e89884086a56e54f -dist/2024-09-22/rust-std-beta-powerpc64-unknown-linux-gnu.tar.gz=8ff723f008f1ff81541f2f14d68ad1e77a2842577dcbe4f5109f6c54fdc42726 -dist/2024-09-22/rust-std-beta-powerpc64-unknown-linux-gnu.tar.xz=c5704ef9d690721790d127ca341e4747d572bd34f636894fe897d23660a11467 -dist/2024-09-22/rust-std-beta-powerpc64le-unknown-linux-gnu.tar.gz=13d46982612f710d7aacf1a9636502418fdc673dde21641e1c52d2c55c8c35a1 -dist/2024-09-22/rust-std-beta-powerpc64le-unknown-linux-gnu.tar.xz=9e33e5c0ffd8511705258a741b448e167fdb13229d1d8bb36ef0b41a1f9c49ec -dist/2024-09-22/rust-std-beta-riscv32i-unknown-none-elf.tar.gz=f7e0cc15730cfcd05ac904a3fb6012a99310c15402db19e915860fc4bc1f55ce -dist/2024-09-22/rust-std-beta-riscv32i-unknown-none-elf.tar.xz=af179ee477d53727d01feeb704776370482f8aa6f6bd51d7dcbcf90010d36b74 -dist/2024-09-22/rust-std-beta-riscv32im-unknown-none-elf.tar.gz=9673565000aebce56cddf905d27ec651d2c2845e9a2768ec38d10e18443924d8 -dist/2024-09-22/rust-std-beta-riscv32im-unknown-none-elf.tar.xz=38a5d0812838d5596a7a4804ee46e97bc5f4814056f93ad0988b7f2f34a90325 -dist/2024-09-22/rust-std-beta-riscv32imac-unknown-none-elf.tar.gz=cb397f91bf2c66a0f7d704c320964885aaeacec90a0f562358e8678e749c1e64 -dist/2024-09-22/rust-std-beta-riscv32imac-unknown-none-elf.tar.xz=ff95fa7f5598ed1f25e2aa0be9fb89ef0a7b145ffa9bcba7479bb3c0d83808b5 -dist/2024-09-22/rust-std-beta-riscv32imafc-unknown-none-elf.tar.gz=9049a87a4bea3319c7bf8162d5289ce252897e3ee637a0b6bca841c3507b98c4 -dist/2024-09-22/rust-std-beta-riscv32imafc-unknown-none-elf.tar.xz=e24970b400b30728a9ee5202b0fdb9734c115e015178817629220390badb7e50 -dist/2024-09-22/rust-std-beta-riscv32imc-unknown-none-elf.tar.gz=aa06101ff7386aac69a1dafeb39645344fae3c0ca02537078029c4ba073aa1af -dist/2024-09-22/rust-std-beta-riscv32imc-unknown-none-elf.tar.xz=13e358d57a5bfe3e4ca2c8ca5e6c8d026cfac417b3c050ebd9bcd5d24f3a5f6c -dist/2024-09-22/rust-std-beta-riscv64gc-unknown-linux-gnu.tar.gz=5d880502cba47ed72006ef6e60fe004885c0f215d589a20456d41dcec8238503 -dist/2024-09-22/rust-std-beta-riscv64gc-unknown-linux-gnu.tar.xz=a242f39d05716b72aeebdf83357835bae0d2386feca6759f343721148b7a0d4d -dist/2024-09-22/rust-std-beta-riscv64gc-unknown-linux-musl.tar.gz=117ec2433159f057fcd7fbae9d85042979340ab00f8d1b940c3adc5d3c791803 -dist/2024-09-22/rust-std-beta-riscv64gc-unknown-linux-musl.tar.xz=be0f262d8ed5122fee6b67abd4b78e419839e4005cfff1db9813ae655fbea23f -dist/2024-09-22/rust-std-beta-riscv64gc-unknown-none-elf.tar.gz=78e28d3d341cedd0fe5ef0036b3b3c246b9f86e5e61d3bfd7e03e95d03920985 -dist/2024-09-22/rust-std-beta-riscv64gc-unknown-none-elf.tar.xz=43bb14df9b4947f111c1e4ba9c4092b73a895c9431a299e4b076d387477f5687 -dist/2024-09-22/rust-std-beta-riscv64imac-unknown-none-elf.tar.gz=e325c2ad8623b87456c12e17b29aa7f52ad243971002b4763677052f9b305eff -dist/2024-09-22/rust-std-beta-riscv64imac-unknown-none-elf.tar.xz=ca02e01254defcfbf0a48ab574dc4b5aecd6a6be2ddc835704986284916019d8 -dist/2024-09-22/rust-std-beta-s390x-unknown-linux-gnu.tar.gz=79044a23a910bfd8488c382a3d2eab0c6a7ba9677165878b02f28a6c75d3a0b5 -dist/2024-09-22/rust-std-beta-s390x-unknown-linux-gnu.tar.xz=6a1196d2b2f30e22497a739e3b1ee302339ed442e0b807c707d1c4eb7c53ff3b -dist/2024-09-22/rust-std-beta-sparc64-unknown-linux-gnu.tar.gz=fa3ad826bcf924094ad5cf19779fbfa70f656c1d2e66f4aee5dcf51792af74f4 -dist/2024-09-22/rust-std-beta-sparc64-unknown-linux-gnu.tar.xz=d5f701446546c6cb64b413be37f3c4a0739010f25616b6a295adfcefb16e8642 -dist/2024-09-22/rust-std-beta-sparcv9-sun-solaris.tar.gz=1ac5c327d5a0d0256d16968aab3bf35828c995c818ba73788421da56404f165e -dist/2024-09-22/rust-std-beta-sparcv9-sun-solaris.tar.xz=fd6c7f163d2d6006eb85cc68e2794850f82dfe09f9173390cd0c167d90622d8d -dist/2024-09-22/rust-std-beta-thumbv6m-none-eabi.tar.gz=8f082a38dfe968d8f987bfec0822e221d0ab8ab73dfd451b63de7644ccaeb239 -dist/2024-09-22/rust-std-beta-thumbv6m-none-eabi.tar.xz=044bca675ac6b621ced7f2bc9a9909814c0b0818505ca1bfcd765c1859a9ed7f -dist/2024-09-22/rust-std-beta-thumbv7em-none-eabi.tar.gz=f3e1789a409b58b9769db8587ddbd21352e6634ff5a508b6ad82237cc85409be -dist/2024-09-22/rust-std-beta-thumbv7em-none-eabi.tar.xz=5f36d0504401bf6cbd2eed78e4575a190300ae26c581ee8599ab8d6e32dfafaf -dist/2024-09-22/rust-std-beta-thumbv7em-none-eabihf.tar.gz=a0ed6b4c71570e900e1605302ef865f7df9405e19245ed45ff5f7654eb3cbea7 -dist/2024-09-22/rust-std-beta-thumbv7em-none-eabihf.tar.xz=6fd7fac23460b49ca5246a6471de4f39d92764231ef2eac5f51d177c9d14ce2a -dist/2024-09-22/rust-std-beta-thumbv7m-none-eabi.tar.gz=21e1983e3f9c481677db7c839d5b2b301bae748ef52e1d0b5c3fbf9347732c66 -dist/2024-09-22/rust-std-beta-thumbv7m-none-eabi.tar.xz=ade8b1a2c128c298ba1d20ea7c7585af2a2b3a17b55a8dc6d39f0eebf0f01e66 -dist/2024-09-22/rust-std-beta-thumbv7neon-linux-androideabi.tar.gz=29c7c493c9fee6afa8aea0f337da66118216ee21b373303432ccfb6375cd8428 -dist/2024-09-22/rust-std-beta-thumbv7neon-linux-androideabi.tar.xz=d63e1c8cf97c0834a3825d9a552ed0ce744b2471028f49cbad6f7df1f7bfad7c -dist/2024-09-22/rust-std-beta-thumbv7neon-unknown-linux-gnueabihf.tar.gz=0cec39208ae369c146d49dbc98984edb993c318a5dcbff205d3fa6b651400bc0 -dist/2024-09-22/rust-std-beta-thumbv7neon-unknown-linux-gnueabihf.tar.xz=158f249f6446503ad5c558dba966ca69f57161aa90fa995a9e9b68fb3e38e732 -dist/2024-09-22/rust-std-beta-thumbv8m.base-none-eabi.tar.gz=8df09685f21eb9285adff2493ea6a9b3a04ce2e24b0761a47b44f0257b3485ff -dist/2024-09-22/rust-std-beta-thumbv8m.base-none-eabi.tar.xz=0a119d100a6bddf66047e98d453b8c54ab0952712c38b1e396bbef81114d4423 -dist/2024-09-22/rust-std-beta-thumbv8m.main-none-eabi.tar.gz=e7e234a7a8f687f0649654f562b12e09d332229dfd9e8d81a780afd9d8eac8ea -dist/2024-09-22/rust-std-beta-thumbv8m.main-none-eabi.tar.xz=a3c6c68ad6c24d080af8034168b36bbb24edc30e1fce2ac91bc3fa09ac34a678 -dist/2024-09-22/rust-std-beta-thumbv8m.main-none-eabihf.tar.gz=1662be2b7ec3db6331ef545ac59c844733c3d1cdc728aef78049fecf37a416c5 -dist/2024-09-22/rust-std-beta-thumbv8m.main-none-eabihf.tar.xz=b19dd77e7582da1785f78e85e39a9d966c7a747641e6772dd18cbd489b4940b8 -dist/2024-09-22/rust-std-beta-wasm32-unknown-emscripten.tar.gz=a7ae18e142b5b7a3fbab372bbf4e829626b52a67a10496f2cdecc89aab029310 -dist/2024-09-22/rust-std-beta-wasm32-unknown-emscripten.tar.xz=75a9a2dae5117b714a08024588cb4f5e5a6f07f28af55013f49fbe7cc8e2a690 -dist/2024-09-22/rust-std-beta-wasm32-unknown-unknown.tar.gz=25bf0342788e03ad52ee4835f280f3d92bf2324db3acfcf2654c5f5d37d43431 -dist/2024-09-22/rust-std-beta-wasm32-unknown-unknown.tar.xz=21798a2663b6d0e7347404666d5341b51c5d5de108cd68efbd1466b7c4002a62 -dist/2024-09-22/rust-std-beta-wasm32-wasi.tar.gz=02c1fcc01d28005432f6e53b6f8cecda2b555d482f713ec70ac92b1507121ec7 -dist/2024-09-22/rust-std-beta-wasm32-wasi.tar.xz=f2b4ae22141d39202bddd45e3373a8520684dd71460ceb3cdc9bc7d09aedd774 -dist/2024-09-22/rust-std-beta-wasm32-wasip1.tar.gz=f59a67c3acc927e72278f66553cd10bb3d81e16045c76671d38d09c8a462c78f -dist/2024-09-22/rust-std-beta-wasm32-wasip1.tar.xz=0f4eea80dcd13008f55d7120f2239aed87a6dcf693f70983caffc36a4be72ffb -dist/2024-09-22/rust-std-beta-wasm32-wasip1-threads.tar.gz=2581846fe64f1d9547ec293875be715251174c5b163a7c533dcae81fd55ea6d6 -dist/2024-09-22/rust-std-beta-wasm32-wasip1-threads.tar.xz=ad6d869148eea87192f786fca0302983094b25a1afec2813012ba3133e8994c8 -dist/2024-09-22/rust-std-beta-wasm32-wasip2.tar.gz=091057da389eb1d464353acca41e158130f969ad20f90827a4dc38bd363a68fa -dist/2024-09-22/rust-std-beta-wasm32-wasip2.tar.xz=c91b4440326443a4987758ac161b79f5aa30d23662a5c99a3c0adfedc0eb8e51 -dist/2024-09-22/rust-std-beta-x86_64-apple-darwin.tar.gz=180a9b1d5fb71ec3e88dd4e3a88f6f1da433a191125ecdf98c0169bd7b0511b3 -dist/2024-09-22/rust-std-beta-x86_64-apple-darwin.tar.xz=7d066c7b394c5b15027472fa388b9379ae8a7d4a990e02c0785f63a6f1b7f0c7 -dist/2024-09-22/rust-std-beta-x86_64-apple-ios.tar.gz=4ebdf9f16075859830e76e40547d1d56230ed8715e57f254c82d467634aa63e5 -dist/2024-09-22/rust-std-beta-x86_64-apple-ios.tar.xz=0bdcf11914a169b86b945df232a30c69f991393e3871956b55ca88a0ad65bf79 -dist/2024-09-22/rust-std-beta-x86_64-apple-ios-macabi.tar.gz=45ea8961f12b31e8404ebd178586711f7e4d4729d96ee298623240d8163766aa -dist/2024-09-22/rust-std-beta-x86_64-apple-ios-macabi.tar.xz=a36a3ed36c0224edaa5161b1c2cb7acb2736d0c2845d56064bde1c94af4e2db1 -dist/2024-09-22/rust-std-beta-x86_64-fortanix-unknown-sgx.tar.gz=8d217487118140549fdc2223954d38a7932a2e9004a07924f853139395f8d88d -dist/2024-09-22/rust-std-beta-x86_64-fortanix-unknown-sgx.tar.xz=66d7b8cc0b92af4f0458eab631faee6069c3bdf8e35200fa3d573177b1b354c8 -dist/2024-09-22/rust-std-beta-x86_64-linux-android.tar.gz=7efbe112fdf33d55ada19f3803b2552796d1027281b6c652a19465e4902a22bf -dist/2024-09-22/rust-std-beta-x86_64-linux-android.tar.xz=cacbf59cc9bad0a212d9fb86c81434350fb0b4842918bf7dc51fe978d21402b6 -dist/2024-09-22/rust-std-beta-x86_64-pc-solaris.tar.gz=073833d7b60d396be6890552f7068e885dc0fd4536e5049e88d97c71df31f126 -dist/2024-09-22/rust-std-beta-x86_64-pc-solaris.tar.xz=c6cbc8c41eb2e071cad032ae7587c5ae2e841f1d074c328229e3b7f271fe9330 -dist/2024-09-22/rust-std-beta-x86_64-pc-windows-gnu.tar.gz=0b5c7c007faa77fb28fe7cf275846f23adf0aa3fa1338dc93f86c05f7c605ded -dist/2024-09-22/rust-std-beta-x86_64-pc-windows-gnu.tar.xz=c1ec0ad342ec630f2ed909c54b0ca7f9073a85977da3a86eb5ef68d5c13ad4b9 -dist/2024-09-22/rust-std-beta-x86_64-pc-windows-gnullvm.tar.gz=5cf9a1daad4b60f7946adbdc9bde0d0d3ce438902f0a158f5f4f423f10960886 -dist/2024-09-22/rust-std-beta-x86_64-pc-windows-gnullvm.tar.xz=d8cfeec61cbbf6bb1b4234bd53a777ad2157def8dc232ba4b5f16bc81f4f1524 -dist/2024-09-22/rust-std-beta-x86_64-pc-windows-msvc.tar.gz=795ac3edcb9f0f10f36a19be14641918b5b0d647d5cc38e8652040437e409538 -dist/2024-09-22/rust-std-beta-x86_64-pc-windows-msvc.tar.xz=dacb5baf49d2b3dd8727a159f8fd348967f987a95162e587c8e5add57dd6d31e -dist/2024-09-22/rust-std-beta-x86_64-unknown-freebsd.tar.gz=089f99e1cbeab86b5d7ba9d582c5771c8d229ece1f81ad110716618823692deb -dist/2024-09-22/rust-std-beta-x86_64-unknown-freebsd.tar.xz=8749c2ae47644c16f62a310500ab91e5403a25c3e023a2c6e25cfa16217c98e9 -dist/2024-09-22/rust-std-beta-x86_64-unknown-fuchsia.tar.gz=becef9619e8ad1d4de66796c5877fd9798e5c943fb93a893aacd7819465f8a15 -dist/2024-09-22/rust-std-beta-x86_64-unknown-fuchsia.tar.xz=3801cc566789ae0313a5d10159cd0c94cbbcd8636409ba69ace73fae972ce2eb -dist/2024-09-22/rust-std-beta-x86_64-unknown-illumos.tar.gz=ba74cfa20f8c53865d96d26b9aaaa7abebf2269d1c3fe2bcd70e3cd7bd4e78d1 -dist/2024-09-22/rust-std-beta-x86_64-unknown-illumos.tar.xz=8f0a00cb53e21c90d60eb02853412d4cf671a1667bbbf7fe9a64183d966a9e48 -dist/2024-09-22/rust-std-beta-x86_64-unknown-linux-gnu.tar.gz=1188997812bfef02c93a13a7d31a9df560383a875bb6a3cbdbb03eaf5fa0d649 -dist/2024-09-22/rust-std-beta-x86_64-unknown-linux-gnu.tar.xz=12583cfd10835abf0f340fe8e141683cdce3e4df5a00998a04361b59203321e6 -dist/2024-09-22/rust-std-beta-x86_64-unknown-linux-gnux32.tar.gz=854f01a511c01b003facf4beb89a511395f0efcdc2284ad279b92837349eaa95 -dist/2024-09-22/rust-std-beta-x86_64-unknown-linux-gnux32.tar.xz=b016d4584a44064feee64de50963ccfbfaaecb792c88c97a079f279a0c1df955 -dist/2024-09-22/rust-std-beta-x86_64-unknown-linux-musl.tar.gz=912eea9c27b6fd251c5b92ae24d6321d5effe9586dbbd473e16a8dee2b758291 -dist/2024-09-22/rust-std-beta-x86_64-unknown-linux-musl.tar.xz=96bf10ef8fee6f8571b6601ab89e65562a91312502630c139d986b6e1ec9fbac -dist/2024-09-22/rust-std-beta-x86_64-unknown-linux-ohos.tar.gz=09e42b412f0891d608a9d4030203fe09645fc763ecad4be5ae790122a5d01f4a -dist/2024-09-22/rust-std-beta-x86_64-unknown-linux-ohos.tar.xz=dd84077f22ac4abea1c143d5d293425a85fad62ac65a4b31f18b9100c4e1076e -dist/2024-09-22/rust-std-beta-x86_64-unknown-netbsd.tar.gz=9aa5fa7bf57fbb95c3a6f718c0a2b62f32c6d1c9ccf93b392d4e166d311e0833 -dist/2024-09-22/rust-std-beta-x86_64-unknown-netbsd.tar.xz=765cf1a81b03ce210a88e87404a64d5b378f6615e428c385fac7a33b646f1276 -dist/2024-09-22/rust-std-beta-x86_64-unknown-none.tar.gz=e00c50362ffc95a1704912ea35c7b1792ead7906d98937fd73b9fa9fe31a520c -dist/2024-09-22/rust-std-beta-x86_64-unknown-none.tar.xz=280cf203356db9c32898197a3b5954901897a5b3059547f67c59cf5780c46386 -dist/2024-09-22/rust-std-beta-x86_64-unknown-redox.tar.gz=77069fcc33bc481ac8e18697884c1f3e3004a5fe5b265acb419b5f60c03fd2c9 -dist/2024-09-22/rust-std-beta-x86_64-unknown-redox.tar.xz=254dba227a76cb476fbc2a897169713969bf00f691ef77e03d303473db130523 -dist/2024-09-22/rust-std-beta-x86_64-unknown-uefi.tar.gz=4f1fb25ef423ab3cd5577f3e081771494978998acb8c04dda9de8a7d56cce985 -dist/2024-09-22/rust-std-beta-x86_64-unknown-uefi.tar.xz=fc21de2770ff0d0eb44d0939db5b274b0f408eb1a904c9eaf4db4c9463b5ff8d -dist/2024-09-22/cargo-beta-aarch64-apple-darwin.tar.gz=489c1b6aef3a7275e2e7a644677dde933a738534966089fe28c52c61dff04f2c -dist/2024-09-22/cargo-beta-aarch64-apple-darwin.tar.xz=5fe4d6a15e4f51f0575f2aee12eb644a95e548a4f03a80835296c44b1daf18a6 -dist/2024-09-22/cargo-beta-aarch64-pc-windows-msvc.tar.gz=5c5c408b026e0332c4e5d816c7a6a961ae5af0174f02b793edd613e56c672494 -dist/2024-09-22/cargo-beta-aarch64-pc-windows-msvc.tar.xz=4e060bccd78dc8abba7c7006585103b6bfa473a0f1cdd9e2c6b10d4fb8294f8c -dist/2024-09-22/cargo-beta-aarch64-unknown-linux-gnu.tar.gz=45cee09ecd3655b3a822b9c85e3f61f8e40b3fb510728503a3691f56ce415274 -dist/2024-09-22/cargo-beta-aarch64-unknown-linux-gnu.tar.xz=d8902eb0c3a725ef6345d325907ac10a7eb81e274c59aa589bf05aedea5958cb -dist/2024-09-22/cargo-beta-aarch64-unknown-linux-musl.tar.gz=67e6658e39c0381554ac025c26564888804eb9d8a3e1178726652fff03bc21b4 -dist/2024-09-22/cargo-beta-aarch64-unknown-linux-musl.tar.xz=427e7a4781dcdd2e316eb0c2751257597b4af58da8a5fd8407a8402814b65148 -dist/2024-09-22/cargo-beta-arm-unknown-linux-gnueabi.tar.gz=735d1b824d3a375a6b9c5a5d22fb5e607d3ad06ff70cebe81b84007967c6a5c7 -dist/2024-09-22/cargo-beta-arm-unknown-linux-gnueabi.tar.xz=749c017f8c25d0df23a160e02a765bb5e967f7657fdf3105d0d7ce64afe83524 -dist/2024-09-22/cargo-beta-arm-unknown-linux-gnueabihf.tar.gz=050ae56d0398150212a75493562e6654cc14b7a1ebd6051bde146b5d408d24c8 -dist/2024-09-22/cargo-beta-arm-unknown-linux-gnueabihf.tar.xz=1088b61e20981dabe406ff52965f48ab1542dd84d9673f7d56b21145d0b604b3 -dist/2024-09-22/cargo-beta-armv7-unknown-linux-gnueabihf.tar.gz=43dfb8491dcb64b91e6786366300a0ee3fd00f1815cd84f3bb4247e6b723a6d6 -dist/2024-09-22/cargo-beta-armv7-unknown-linux-gnueabihf.tar.xz=90266fcba10bd88e1f8f5d8420ee6835fe3e337dad1cc43ab7ef79edbe1a1b98 -dist/2024-09-22/cargo-beta-i686-pc-windows-gnu.tar.gz=6dca2e273600ee0f92a416901a7713ffd6db420b953e62d51d95bc85c1dbe27b -dist/2024-09-22/cargo-beta-i686-pc-windows-gnu.tar.xz=36fa46c7edcfc881568435f366e76f1989479356d93b8982981658fd44b80f4d -dist/2024-09-22/cargo-beta-i686-pc-windows-msvc.tar.gz=bd99a9cf662fbe90b79711776f972d2d574fcd6f0053bb672e4cdb35fc67ddf3 -dist/2024-09-22/cargo-beta-i686-pc-windows-msvc.tar.xz=8a995e56a96217cd999e786b16a69de1ec6e9db6412cd2c9c6ce090ed21a84bf -dist/2024-09-22/cargo-beta-i686-unknown-linux-gnu.tar.gz=ae115caa9516a96f144db9751b185503e1c648ea9b7e8b0a6aa10200315e6458 -dist/2024-09-22/cargo-beta-i686-unknown-linux-gnu.tar.xz=54b125ce0c00afa7bdebf5cb592249c37ac21d78479129a46d0b70d86fe6bf17 -dist/2024-09-22/cargo-beta-loongarch64-unknown-linux-gnu.tar.gz=21d2ca9f6d715e44fae058b7c26abc873930ac2823e72c9f8c983f7d089bd91a -dist/2024-09-22/cargo-beta-loongarch64-unknown-linux-gnu.tar.xz=b9b395041d328a09643b7e727705aa7705bf67c08edb3d26b78405ce454c6798 -dist/2024-09-22/cargo-beta-loongarch64-unknown-linux-musl.tar.gz=da7853da9096b6ddebc3b3da948b90ac448663dc9a5d2940cad420360d5934a2 -dist/2024-09-22/cargo-beta-loongarch64-unknown-linux-musl.tar.xz=9997e251abe606e390e3d2c280233f435f8ab46a6a3d24ce95d7a700ec049664 -dist/2024-09-22/cargo-beta-powerpc-unknown-linux-gnu.tar.gz=1715eabf3860f2fa7e1e27f2163a5243c8000b6216c0e7ac8dec993061ff479b -dist/2024-09-22/cargo-beta-powerpc-unknown-linux-gnu.tar.xz=f4e0f364c4ca68dc7b40b40bf13e28284a9bf6e6075b10504b9e6979d4a1a375 -dist/2024-09-22/cargo-beta-powerpc64-unknown-linux-gnu.tar.gz=70cb2337910933f0ce22ef57e8dec4ab5732855d0657e56ed237e3e483aa07d2 -dist/2024-09-22/cargo-beta-powerpc64-unknown-linux-gnu.tar.xz=1e9e383a093b54b8f7bff8dbf2f38590c148d0c9e18399bc128a09a6c67565bd -dist/2024-09-22/cargo-beta-powerpc64le-unknown-linux-gnu.tar.gz=6e01a5a6cf68b8385d2a2eaa07984ba62ef4df6811be2ade5dd7b22ba7d4bd69 -dist/2024-09-22/cargo-beta-powerpc64le-unknown-linux-gnu.tar.xz=70d0e45fba27db3322c3e4d802cdcd37503d2a848b9c0c2b9b759d48611c19ab -dist/2024-09-22/cargo-beta-riscv64gc-unknown-linux-gnu.tar.gz=baabb56c3670a0dab62fc7c0e5cb07474de795e81a6be42c57a91c2249e9b960 -dist/2024-09-22/cargo-beta-riscv64gc-unknown-linux-gnu.tar.xz=fd87e580bd0d4b47340b797fb52aeda83854556328869ebd1ce7136bcf8ead78 -dist/2024-09-22/cargo-beta-s390x-unknown-linux-gnu.tar.gz=dbf01fb97c1aa9db57b68fa863dca5df81e1f83c1686bdbc01c702b0148bba7a -dist/2024-09-22/cargo-beta-s390x-unknown-linux-gnu.tar.xz=f2eaf49ad1a05b5acf3050159aeb7351544c5aa14a46b381b0e2659eb857bce8 -dist/2024-09-22/cargo-beta-x86_64-apple-darwin.tar.gz=cdd90fe77bff57d0acae21499c0188fac2ddf7aa24dba07dcbf900444ceb1295 -dist/2024-09-22/cargo-beta-x86_64-apple-darwin.tar.xz=2c8acbf6eb4076ad876993f09714a2b1664031a41a12ff395c1f9c4bd0283640 -dist/2024-09-22/cargo-beta-x86_64-pc-windows-gnu.tar.gz=f16189ad7a0d311b17b6bb6ced913cde0115ac07e9a950b85d4336c488456c6c -dist/2024-09-22/cargo-beta-x86_64-pc-windows-gnu.tar.xz=1d4bf171c84def4110ee3f4e4798ab3ee52d0323bc2fc4abd564f229a23846da -dist/2024-09-22/cargo-beta-x86_64-pc-windows-msvc.tar.gz=c3e27d6a38eb46fca153ef17cea76b11664e8171e0aa76af594e67ed9dffbef5 -dist/2024-09-22/cargo-beta-x86_64-pc-windows-msvc.tar.xz=b64792d6ec70ee083dac929343ab45f4a52039c7fbc6cb223b02663591c8f544 -dist/2024-09-22/cargo-beta-x86_64-unknown-freebsd.tar.gz=40bf96a087dc1d57ba495733975ff34a4e75e51d7ddffc025561f0951adb57ca -dist/2024-09-22/cargo-beta-x86_64-unknown-freebsd.tar.xz=7912a49f7a181145b71a197014e3de6594b216959cd7c95a003fcd13854cb056 -dist/2024-09-22/cargo-beta-x86_64-unknown-illumos.tar.gz=1c3dfd5dcb8e7c8ba947b67f5bc466bae26ca1518a74798cfe5a21997bfcf71d -dist/2024-09-22/cargo-beta-x86_64-unknown-illumos.tar.xz=6f620a91c2bc145f894f5736a9818f7b54583a93e7eb2d0ac202f46a38040b99 -dist/2024-09-22/cargo-beta-x86_64-unknown-linux-gnu.tar.gz=c6c20977054f56fc279e666cf02da65acb376c1b08bbbc998cf34d0cc2b5bb7b -dist/2024-09-22/cargo-beta-x86_64-unknown-linux-gnu.tar.xz=9cca7e46ad35f0f69d8fe628a95e44388ed5cb62c1b77f2bab03dab28a05a650 -dist/2024-09-22/cargo-beta-x86_64-unknown-linux-musl.tar.gz=74005a4511ca2087ebb92db7e19a2e31e3ddcdef93e27da544bbc444df01dc32 -dist/2024-09-22/cargo-beta-x86_64-unknown-linux-musl.tar.xz=94215716623cadc8bf4a119612ad7482661905748d4e43ddff1855d4746f3972 -dist/2024-09-22/cargo-beta-x86_64-unknown-netbsd.tar.gz=fd9b2dd77b76b2ac44dbeb80e46371669223fe8ca57e4d480deeb162168c38d5 -dist/2024-09-22/cargo-beta-x86_64-unknown-netbsd.tar.xz=d419dbb9d1c905eb841c6870ddc8afe946b7618d3a0c6f39f8feeba6ecc74f0d -dist/2024-09-22/clippy-beta-aarch64-apple-darwin.tar.gz=60aba239287116d7e0f58fc71e510fdb7582003efdb3011765f732b1e494c7e1 -dist/2024-09-22/clippy-beta-aarch64-apple-darwin.tar.xz=00ef2da71c8e3f5be8401128509ff99130eebd5c0b90b5b5c16dc0465c2a18f8 -dist/2024-09-22/clippy-beta-aarch64-pc-windows-msvc.tar.gz=7ff2952e057849ec69a7d1147920c2b6ecb99fe7984afe627c5514c8c6a8811c -dist/2024-09-22/clippy-beta-aarch64-pc-windows-msvc.tar.xz=cc3e145daaf3674c1436d4380171ce5e26b075975121dac5c1d5c5d6cfa1a6e6 -dist/2024-09-22/clippy-beta-aarch64-unknown-linux-gnu.tar.gz=430c6d5ded52d04bfe93fce17f8fef57ce3ab05715767b85d6c9b59e521671b2 -dist/2024-09-22/clippy-beta-aarch64-unknown-linux-gnu.tar.xz=df4b9444dd435133bcfe386955b1d4b63c13e4acd766dc3bb9742c21431926d4 -dist/2024-09-22/clippy-beta-aarch64-unknown-linux-musl.tar.gz=7064208f59db897b1107072a3cc1a516d53888ea1c549bdf3cfd8479c65ec0c3 -dist/2024-09-22/clippy-beta-aarch64-unknown-linux-musl.tar.xz=1d33c3e2b4daa1ba7f1a6399790d1b76fdfe1ac9d293859983412d5e1e3663a1 -dist/2024-09-22/clippy-beta-arm-unknown-linux-gnueabi.tar.gz=b851cb5bcb31a2105039b55a613d937113fd45f5c1fbd4e3d24eecbed85a0bb0 -dist/2024-09-22/clippy-beta-arm-unknown-linux-gnueabi.tar.xz=a17f46c82fa28bfa9e3c9ff99cd25a888b6ff0c08a887ef4056b8ae29437a67a -dist/2024-09-22/clippy-beta-arm-unknown-linux-gnueabihf.tar.gz=784a1a0134d54cff72c9bf59ee1e750d0493fef5bde06bf778bc98321d833031 -dist/2024-09-22/clippy-beta-arm-unknown-linux-gnueabihf.tar.xz=c11461066103bf92f21298e5cb3b009cf4ac07bde5d99ce9ab97c1cbdf7c73f5 -dist/2024-09-22/clippy-beta-armv7-unknown-linux-gnueabihf.tar.gz=98c74f6a0692482355045bb4b0977887b419a8aa3c4654b9b59cd0d867f261ac -dist/2024-09-22/clippy-beta-armv7-unknown-linux-gnueabihf.tar.xz=20c82e6bbefdbaca22911a63a41d0aa05ed0ffad4571090c053cb354b49acd23 -dist/2024-09-22/clippy-beta-i686-pc-windows-gnu.tar.gz=3da558108df227ceb0ff7a2837d1bd2f5a75a0c7167f0b3c380d1aa5b2fa3e77 -dist/2024-09-22/clippy-beta-i686-pc-windows-gnu.tar.xz=f657f1cdc9f91243112834afbe5fe60f8b43e914504c8aed1994a13ac98bc575 -dist/2024-09-22/clippy-beta-i686-pc-windows-msvc.tar.gz=cf27f06843f5e0706aace4be4b9973fd164b57697b44d00852a9545d336c6fd2 -dist/2024-09-22/clippy-beta-i686-pc-windows-msvc.tar.xz=74dd229cdf65ce19ded1ed27cf5fb31c20f6a45879b277ad43aedc818eed514c -dist/2024-09-22/clippy-beta-i686-unknown-linux-gnu.tar.gz=4d22b439675ec118d021a85dc75540d7a3331364395e21bc1a2d76c26aabe9d3 -dist/2024-09-22/clippy-beta-i686-unknown-linux-gnu.tar.xz=bfc60e9fe1dbed050904efc71e8d0e5c90dae7f949fc7c81312de0c129f4d058 -dist/2024-09-22/clippy-beta-loongarch64-unknown-linux-gnu.tar.gz=25df67e21543e3a3b71500f55da1abe6182a24aabe1f5bb1e57fe99821a22d97 -dist/2024-09-22/clippy-beta-loongarch64-unknown-linux-gnu.tar.xz=7b56b6f7704742821f42396f5c517adda129b68f05da258d371cc8a3bc7356f3 -dist/2024-09-22/clippy-beta-loongarch64-unknown-linux-musl.tar.gz=f7305d23b8b850b4169a2ae6816c9db721a989ffbb642a4645ed95068a6553fe -dist/2024-09-22/clippy-beta-loongarch64-unknown-linux-musl.tar.xz=9576586590c11c86e8b029c32f17916ebd13d27d8750e30a927a4a986dd47aea -dist/2024-09-22/clippy-beta-powerpc-unknown-linux-gnu.tar.gz=1eb483594b3ca3ab8e0eac99e7699be151791fcdf0349714b0da923ea33b92bc -dist/2024-09-22/clippy-beta-powerpc-unknown-linux-gnu.tar.xz=42b9373a18ebf76394513cb75f8072ca094efbdfd8c60cc2249b04fad344f677 -dist/2024-09-22/clippy-beta-powerpc64-unknown-linux-gnu.tar.gz=fa6438d40613bb99062118bfb293f6f252a21c927d222c7cdfe4cee865d30d16 -dist/2024-09-22/clippy-beta-powerpc64-unknown-linux-gnu.tar.xz=7cfba858f149b327cbd9bf292080a2ae20404018228ab556eeefc3776f429785 -dist/2024-09-22/clippy-beta-powerpc64le-unknown-linux-gnu.tar.gz=5f6d94333400f99bbb0762be18fa9390885c13f4fe0ad7ea05b57808b26653e4 -dist/2024-09-22/clippy-beta-powerpc64le-unknown-linux-gnu.tar.xz=38042ee6161d8e8b04faf58a4bca98cf7940ece6ec42eb44ce29bdb9aedb6c89 -dist/2024-09-22/clippy-beta-riscv64gc-unknown-linux-gnu.tar.gz=b5056a3d8a8b3bbd888647117b316404b2701803bff09737cca18e16611ed3cd -dist/2024-09-22/clippy-beta-riscv64gc-unknown-linux-gnu.tar.xz=9322024609e563bb0d1f342bae2deab1d0c0ae951c2e94fe74ddc22fe2c7d3f2 -dist/2024-09-22/clippy-beta-s390x-unknown-linux-gnu.tar.gz=8b52721fc1df5cd158e12ae80a2936929f64a7b2506c55793b4a7d28522f0e3e -dist/2024-09-22/clippy-beta-s390x-unknown-linux-gnu.tar.xz=66dedbc154a11588a03616b92823c63502276123e66e9ff110c2e63cc7ed3529 -dist/2024-09-22/clippy-beta-x86_64-apple-darwin.tar.gz=66ba82b5e5097a2e35053fcb5db9ca44a152c1172f75d689688454561c8b3712 -dist/2024-09-22/clippy-beta-x86_64-apple-darwin.tar.xz=cfaa2e71b847103660336ad58025fff26f2928a4d7bcc5907fef91e70b63e1fc -dist/2024-09-22/clippy-beta-x86_64-pc-windows-gnu.tar.gz=fef4e4f2c68294908e170c78efb657c02166fbfbc45b6ce65fbfb5c76ce6d20c -dist/2024-09-22/clippy-beta-x86_64-pc-windows-gnu.tar.xz=0eec7155f78dfd0cc2e6ac996053492d7ba8a4fa5203f779a92b04ad42e8f651 -dist/2024-09-22/clippy-beta-x86_64-pc-windows-msvc.tar.gz=4dc7b6c972ed13417fa831ee20b9e4cc0a3895c39d4f059d1a14ebe51f7430e3 -dist/2024-09-22/clippy-beta-x86_64-pc-windows-msvc.tar.xz=c9f3fb89a31cbba2b575cbb7fc74c09c087940b138b34015239c8938ed6d6f14 -dist/2024-09-22/clippy-beta-x86_64-unknown-freebsd.tar.gz=cd7e5a9ee6be58a627b13d2e85c05aebd64414f854229aca917f3334acbe2352 -dist/2024-09-22/clippy-beta-x86_64-unknown-freebsd.tar.xz=7d81d8fd02506935f289e22c6a8f3433bc2c78ea02bbfa4950a31f49eb95344b -dist/2024-09-22/clippy-beta-x86_64-unknown-illumos.tar.gz=d38eda29de151d13b0fb1f58b090b63e049e095a326e26b76055383ba13285a0 -dist/2024-09-22/clippy-beta-x86_64-unknown-illumos.tar.xz=3100a9e357e6ded30499d4a60a6ff64f26d99e1cbd1eea11ca7fcf92a9c1f293 -dist/2024-09-22/clippy-beta-x86_64-unknown-linux-gnu.tar.gz=c09c9e00e653ffdb51c4edca6aa1e23572092c45a1cb81235f05bc75331d68c3 -dist/2024-09-22/clippy-beta-x86_64-unknown-linux-gnu.tar.xz=1e2fa4de890d7bc6c2828df95a729a55cb2b255a25d96194ccca0c3e06a580ba -dist/2024-09-22/clippy-beta-x86_64-unknown-linux-musl.tar.gz=ac80d0b1b7f3e451c3bd00fd882b547a9b87e95c3fc0d332050859ff827782a9 -dist/2024-09-22/clippy-beta-x86_64-unknown-linux-musl.tar.xz=1178ff5a580bd131ecb9a7b0ad2894c09f2882bcfc483ca14e1fd780925e97ed -dist/2024-09-22/clippy-beta-x86_64-unknown-netbsd.tar.gz=b69d92c035e456d4d1dd8a09032a92f8226c9f39579966e86c2e202ac9995d29 -dist/2024-09-22/clippy-beta-x86_64-unknown-netbsd.tar.xz=a0e827a24ffe8d2b38efff5da0972eee15e098f790b49035b21a72ebf1cb17ef -dist/2024-09-22/rustfmt-nightly-aarch64-apple-darwin.tar.gz=4e632df4953f955b24414d929c352ce1f6e196c50cedde3da4d8663f5f1dd77e -dist/2024-09-22/rustfmt-nightly-aarch64-apple-darwin.tar.xz=d7f8d8442b25053e767ec85e50aa2a6f9bb01e45a2ec3fdec56ef1c305a91ba2 -dist/2024-09-22/rustfmt-nightly-aarch64-pc-windows-msvc.tar.gz=eaee820d549347d15f1b96e3c85517a65e2a5655b86e27927eb6646a7c1d7b67 -dist/2024-09-22/rustfmt-nightly-aarch64-pc-windows-msvc.tar.xz=5fb16519d2acb68df963800c9a5036f1ee38b6ea02a115c40b6622338cf7052c -dist/2024-09-22/rustfmt-nightly-aarch64-unknown-linux-gnu.tar.gz=037999e2fed25ae76b70960133a811a29707712d2141fc74a1db312cfe6020e1 -dist/2024-09-22/rustfmt-nightly-aarch64-unknown-linux-gnu.tar.xz=b10d1947baafc6160ce8d5902936c2b3469a1558b71263671e581ac5b1c14f0e -dist/2024-09-22/rustfmt-nightly-aarch64-unknown-linux-musl.tar.gz=eb33ec39c232a6ddeab1b8038222f96407b9671052f995e0a60ada332a1ccb3f -dist/2024-09-22/rustfmt-nightly-aarch64-unknown-linux-musl.tar.xz=396775133e37dac5de8e71e5d8fea26c19dbfc7841244a35c3529f5dfec93163 -dist/2024-09-22/rustfmt-nightly-arm-unknown-linux-gnueabi.tar.gz=4885a99dbab8f33288501532b287c20f981bdcd10ea4d9ccffe585d5338c43d3 -dist/2024-09-22/rustfmt-nightly-arm-unknown-linux-gnueabi.tar.xz=af165d8090fd3c32efc7e5f58dd57d4a2c228cc6a9939c40024d896c35119bf6 -dist/2024-09-22/rustfmt-nightly-arm-unknown-linux-gnueabihf.tar.gz=150086cbd94e084b30faaebabc809cff11eca87a4aa4ff2b2b89286e0af6760e -dist/2024-09-22/rustfmt-nightly-arm-unknown-linux-gnueabihf.tar.xz=49ab34e495e893037431851e65a35ea7e9d0b46ba651f7d73591bd659c031bd7 -dist/2024-09-22/rustfmt-nightly-armv7-unknown-linux-gnueabihf.tar.gz=c61c6bb8a96c19a848155a38560e0a6dac91ec5f1ee2c602a060cd6039324839 -dist/2024-09-22/rustfmt-nightly-armv7-unknown-linux-gnueabihf.tar.xz=81b7ae3c5e27830fa10a17e062c56bcfe66413b994b27951b63f67faabd296d4 -dist/2024-09-22/rustfmt-nightly-i686-pc-windows-gnu.tar.gz=585896ee3c2b1644ebcba6a81b2f2dabc47da151f6100b5660e208c3a2967952 -dist/2024-09-22/rustfmt-nightly-i686-pc-windows-gnu.tar.xz=ca875f395d33249cbfd657cfab1b4c596de1453c4451c7bb4466ebec639ad016 -dist/2024-09-22/rustfmt-nightly-i686-pc-windows-msvc.tar.gz=4dbce4c329cac38785408eb1a8b2ff5358fd18b59276435695324a03a7018fa9 -dist/2024-09-22/rustfmt-nightly-i686-pc-windows-msvc.tar.xz=10aea1e2abaae9d098afff8d080cc9d84bfb3f77e2e72ec0a639d61dc5900fd8 -dist/2024-09-22/rustfmt-nightly-i686-unknown-linux-gnu.tar.gz=140897d538c0f7df473c3f704ec7e9198c9e903b5882688f0494166647dbd91e -dist/2024-09-22/rustfmt-nightly-i686-unknown-linux-gnu.tar.xz=06e85fa8391eb7d82902ef55af8ee89a16f07b32e4839a848ac09b506f4227e3 -dist/2024-09-22/rustfmt-nightly-loongarch64-unknown-linux-gnu.tar.gz=4103e5daf242f72c0c7875044ea2ee5f2c88bc5c87ba1e685eee526038663e7d -dist/2024-09-22/rustfmt-nightly-loongarch64-unknown-linux-gnu.tar.xz=fe424f1c13eb8257036db3e843d4c6b7b0e3bbf310f1d42719046f86dd635c95 -dist/2024-09-22/rustfmt-nightly-loongarch64-unknown-linux-musl.tar.gz=86304bb8673decae3d6e8b923765b410948277ea00d0cc5b14bb448da149aa8d -dist/2024-09-22/rustfmt-nightly-loongarch64-unknown-linux-musl.tar.xz=743abf4d3ea8b3e1e8dbed6d9f75ee84680b0636e8e7c536b13bd69a41c8a0d9 -dist/2024-09-22/rustfmt-nightly-powerpc-unknown-linux-gnu.tar.gz=db68cf7bfaa00b8f6c544b615eabdea998540ae70ec23af6b7370153a6706a64 -dist/2024-09-22/rustfmt-nightly-powerpc-unknown-linux-gnu.tar.xz=fe1abd02ed36a3720c41c46c77136c89c5addc2c8e5e2cbe25331a34082f4b7a -dist/2024-09-22/rustfmt-nightly-powerpc64-unknown-linux-gnu.tar.gz=c6bb214d68fe7d631398a8684df49f4d1faeb42f9d422c247328e508bdaee830 -dist/2024-09-22/rustfmt-nightly-powerpc64-unknown-linux-gnu.tar.xz=230e19228f80fa4da3036d4eac5b9f9dde02b47d32c43278190da4d322461fd1 -dist/2024-09-22/rustfmt-nightly-powerpc64le-unknown-linux-gnu.tar.gz=b21b569a1831a2ea621c35e19a1820f236fdfc54d38a387789b7750b1af26043 -dist/2024-09-22/rustfmt-nightly-powerpc64le-unknown-linux-gnu.tar.xz=28f8c4aa4cf00561d6c9dfddc13fdf5fba7b936f9f510b9ecc84160385d590d0 -dist/2024-09-22/rustfmt-nightly-riscv64gc-unknown-linux-gnu.tar.gz=5cd81cb8c792abb3c31da225424ef5d1f6006163d3ddee06a95bb4286a29123e -dist/2024-09-22/rustfmt-nightly-riscv64gc-unknown-linux-gnu.tar.xz=58eedfc8cda153ea5ee92278bf08a0625d129d3e208b3e0244e2b90819c7cc2e -dist/2024-09-22/rustfmt-nightly-s390x-unknown-linux-gnu.tar.gz=17a0c073de3c6e3769a86d0438b1132762456153f3739c6652f94fca270e3a4b -dist/2024-09-22/rustfmt-nightly-s390x-unknown-linux-gnu.tar.xz=d7001fc75844be6859a57d2263075ff1b7ac2d88c62452bd42fef97b0afe03d7 -dist/2024-09-22/rustfmt-nightly-x86_64-apple-darwin.tar.gz=7bc303ca8b36c782f2034441cbb6d3dc3ea891114895d2027cce9d8cd25ce348 -dist/2024-09-22/rustfmt-nightly-x86_64-apple-darwin.tar.xz=119dcbdeda0fc6cb80d18e6e908646cbaedd615f5a501922344c795ffd1dc7d8 -dist/2024-09-22/rustfmt-nightly-x86_64-pc-windows-gnu.tar.gz=b14962a790a48b609eda7e1a847c85759cd7dc7f9d0ac9914f126f458b4ae268 -dist/2024-09-22/rustfmt-nightly-x86_64-pc-windows-gnu.tar.xz=3a710fdf3d35c0a42f5c43341aa00390644d82e76c52aa59f4d652a6ab980b3d -dist/2024-09-22/rustfmt-nightly-x86_64-pc-windows-msvc.tar.gz=946233868c179df3c133fa04bde2c863028a69776c7416aa4a33adb102d63783 -dist/2024-09-22/rustfmt-nightly-x86_64-pc-windows-msvc.tar.xz=1db1094ee7c9cad7a16b227de6763b835bc33c0650ba2eb9b380c430a766b81c -dist/2024-09-22/rustfmt-nightly-x86_64-unknown-freebsd.tar.gz=68bc0322c947af0d98f63fc3e41322c12ce8be2bd185091b14407792d407f59b -dist/2024-09-22/rustfmt-nightly-x86_64-unknown-freebsd.tar.xz=66e380f40e18c8a1ce91a9eaf7f662cacd580fc2b276cc854c03d795a5b9d547 -dist/2024-09-22/rustfmt-nightly-x86_64-unknown-illumos.tar.gz=5048bd14d07ed54f5120b0488925f69ff92d2fe00f1e19ae3a8a39a56201c09b -dist/2024-09-22/rustfmt-nightly-x86_64-unknown-illumos.tar.xz=d2f903f996c265b4d70bb88d47e85dd7382b3298f9ff02ad4502f32d6f9919dd -dist/2024-09-22/rustfmt-nightly-x86_64-unknown-linux-gnu.tar.gz=f0c150cb2fcbb7cfc4982426be6760093aa6cf854d84ed3c793f766fba6a0cc8 -dist/2024-09-22/rustfmt-nightly-x86_64-unknown-linux-gnu.tar.xz=5d5cc741435c63b162417f425f7cf9445a13c109687cc85f28424fc51192e333 -dist/2024-09-22/rustfmt-nightly-x86_64-unknown-linux-musl.tar.gz=a3252a997f60b086ea8c9c32665277f33cf574fdefee859ee448dc0b7eed5be9 -dist/2024-09-22/rustfmt-nightly-x86_64-unknown-linux-musl.tar.xz=b888f58dce3689e75ea6c23904481f7fec110f0aea45b75a9390d2160e0d3151 -dist/2024-09-22/rustfmt-nightly-x86_64-unknown-netbsd.tar.gz=4663adcc009bd376b0787760854fb694eaa0edff88f72b4cf486f7180f6a1c2b -dist/2024-09-22/rustfmt-nightly-x86_64-unknown-netbsd.tar.xz=bfc83277d2217b3a908c3f9153db1336b63270c70c6cd83a2628cf18c41db47f -dist/2024-09-22/rustc-nightly-aarch64-apple-darwin.tar.gz=ade996e00dd338a86cdcb25961d07c936edec1392526d78dd5de156ba012fe55 -dist/2024-09-22/rustc-nightly-aarch64-apple-darwin.tar.xz=147d0cfe57be988564d30fcba7fc0c69979b5fbdd91e4a08ac8e580be8a1cc6f -dist/2024-09-22/rustc-nightly-aarch64-pc-windows-msvc.tar.gz=e6a59a0303abbabb3b373fda7fb697ad2cfd31011f231fbdfd45c1cbd64e8bd7 -dist/2024-09-22/rustc-nightly-aarch64-pc-windows-msvc.tar.xz=9ee27bc608470ef29a51272656d0ed5e03946dcc3411412ef8b05cc70f97f8b9 -dist/2024-09-22/rustc-nightly-aarch64-unknown-linux-gnu.tar.gz=3ec6f8cee20883195c102bdcffee31d695698bb6eaf45502720edbc16b02f471 -dist/2024-09-22/rustc-nightly-aarch64-unknown-linux-gnu.tar.xz=7f8fabd6433acb752131071c5bee76752fcc88e08ffff4684a7badb9ed4bc50e -dist/2024-09-22/rustc-nightly-aarch64-unknown-linux-musl.tar.gz=7a8756afcd643b78aa6834497935d7bc0ede1ae74150fa83fff85243deb5e554 -dist/2024-09-22/rustc-nightly-aarch64-unknown-linux-musl.tar.xz=de39081dbeeb0715d433e0cd56e62db45c3bb5bf04d1e7dc3fa097e7b3ca97dc -dist/2024-09-22/rustc-nightly-arm-unknown-linux-gnueabi.tar.gz=ea6bd6b337d24a7c9995fa95d8884e66755d016fb1d50fea063129a410bec22a -dist/2024-09-22/rustc-nightly-arm-unknown-linux-gnueabi.tar.xz=fa195b2588675831274ca21c0d2420e5729d1c21c4c245f2fd1d2c044d7ede1c -dist/2024-09-22/rustc-nightly-arm-unknown-linux-gnueabihf.tar.gz=6f0719613ec54221e978e7136baa00eb25b8b3d627e5de5ee3488c9d9e869b97 -dist/2024-09-22/rustc-nightly-arm-unknown-linux-gnueabihf.tar.xz=9e0bbd283a0377f881f1c048660c54700561762e220ff2713566d3fb6eb56cce -dist/2024-09-22/rustc-nightly-armv7-unknown-linux-gnueabihf.tar.gz=c8f88bb948119a9ff218571eb3ff0144915b2ce4a404d445db9f8f9c25044aa3 -dist/2024-09-22/rustc-nightly-armv7-unknown-linux-gnueabihf.tar.xz=1c41588099d929a7e9dd56cba22782f5202fac2829b924b1aa7dab3e03c52960 -dist/2024-09-22/rustc-nightly-i686-pc-windows-gnu.tar.gz=af2d30b4925e786ace64d4a11bb05ac6f7df1636989a3656d1aa9fe56cdc330f -dist/2024-09-22/rustc-nightly-i686-pc-windows-gnu.tar.xz=4bfe618c3702ea805b63beac19cbf0561d262e67d87765a4e10ea9defded53c4 -dist/2024-09-22/rustc-nightly-i686-pc-windows-msvc.tar.gz=c4e57fe6fec40d874c8fb54227b310072dc98f35f99b8cc741e6818a67941f6d -dist/2024-09-22/rustc-nightly-i686-pc-windows-msvc.tar.xz=ed10535a830e2e1ab22767a24b82b3314b7ef4ac3c318954ee8f2384b287d8e7 -dist/2024-09-22/rustc-nightly-i686-unknown-linux-gnu.tar.gz=da5e36f6bb3d9f00b8e5db5aceefcf8ad38552b85a1a4f60f7b700148cd49152 -dist/2024-09-22/rustc-nightly-i686-unknown-linux-gnu.tar.xz=5831b0209eb64a44b6bfc8aa4b092faaae85101f58f79c4e869bffec22361f1b -dist/2024-09-22/rustc-nightly-loongarch64-unknown-linux-gnu.tar.gz=f31871890aa6249528b43119d0f050d27c5f404b560d48660cd4c9e7a3a80b76 -dist/2024-09-22/rustc-nightly-loongarch64-unknown-linux-gnu.tar.xz=19dc59393d25edef8a341bb137ad1f4ca20741038b0111dc81d6e61c0a7a1975 -dist/2024-09-22/rustc-nightly-loongarch64-unknown-linux-musl.tar.gz=8ebea352863ef014e4dafbafe5a28ddfff6a26f3e4cf728fb4099ecd3444a3ec -dist/2024-09-22/rustc-nightly-loongarch64-unknown-linux-musl.tar.xz=97196b586f44022d2c24b7378830f716abceb451244035f74c40b6c1587f6c50 -dist/2024-09-22/rustc-nightly-powerpc-unknown-linux-gnu.tar.gz=6f4d2428ec7a4d5e1540b53e35904b9f9ff5b8fcd05cf3311b005dbfd426d65b -dist/2024-09-22/rustc-nightly-powerpc-unknown-linux-gnu.tar.xz=c2bc66d7d763c1d4c5752b60ab563fe5b870dd35533712046acd40f258f7a337 -dist/2024-09-22/rustc-nightly-powerpc64-unknown-linux-gnu.tar.gz=d0e6f42aafc8d8b289b55c1ba4a34039c747a7445b347f05017606801a7d81a4 -dist/2024-09-22/rustc-nightly-powerpc64-unknown-linux-gnu.tar.xz=9612777e56955ab5446e3ef20e0d579fbeceedc3bdc4d0053367be2191551fd7 -dist/2024-09-22/rustc-nightly-powerpc64le-unknown-linux-gnu.tar.gz=811099c8b6adc017678c4e43c8f7b02b2bde267eac1bbc023b1f22c184894231 -dist/2024-09-22/rustc-nightly-powerpc64le-unknown-linux-gnu.tar.xz=f766dab0fa46122c26e5a7736da65e8a2df9c2c6578093b6532dbd88a162d1a5 -dist/2024-09-22/rustc-nightly-riscv64gc-unknown-linux-gnu.tar.gz=21e9896e5184d797445a19ce5788d8dabe86302d5f63bf8c07105b52a237c13b -dist/2024-09-22/rustc-nightly-riscv64gc-unknown-linux-gnu.tar.xz=002da974c9606726cc7e6f68cda012ef305e420cf6f7a0de84bf791c007fecd6 -dist/2024-09-22/rustc-nightly-s390x-unknown-linux-gnu.tar.gz=adfa4248f4ad883a04d67f923325c28b7400853063f2d8017cca8f4100ec1125 -dist/2024-09-22/rustc-nightly-s390x-unknown-linux-gnu.tar.xz=8334aa8a99d2a8034267394d44b0e5036d053c247812dbd5bc90bdb2344e4713 -dist/2024-09-22/rustc-nightly-x86_64-apple-darwin.tar.gz=385aa935fb1762423d1a11c0928597e502adbab9809a86c17d98096c31f65775 -dist/2024-09-22/rustc-nightly-x86_64-apple-darwin.tar.xz=f2bb16e1618dbcc7dda85e0ff4460ee270a99871477380a6412f575bd02f4cf5 -dist/2024-09-22/rustc-nightly-x86_64-pc-windows-gnu.tar.gz=6e3894c7651bfb48c741aba516ee99690616431643db82cd186fe408675d07b4 -dist/2024-09-22/rustc-nightly-x86_64-pc-windows-gnu.tar.xz=5661b5ba3a496106f4b0019d4ce81dbcb4b4a0db68a90bac64a95a0bd9201514 -dist/2024-09-22/rustc-nightly-x86_64-pc-windows-msvc.tar.gz=564f7a0582f3b900201cda4fe502e191b651a845210d21a40a119b94e2e51133 -dist/2024-09-22/rustc-nightly-x86_64-pc-windows-msvc.tar.xz=1804ebc7ade5c49ec4b82cac2261cf159b8c852a7e06f3faafbf990214936d2b -dist/2024-09-22/rustc-nightly-x86_64-unknown-freebsd.tar.gz=7455de95ddb8e565ddeaf2da7d80d890c60bc653f52afcab5244476d35305e0b -dist/2024-09-22/rustc-nightly-x86_64-unknown-freebsd.tar.xz=36a7cf6e8245c3879c08d5e3acfb0155ebcdc6c5b06edc51d43376c44d9ed0b4 -dist/2024-09-22/rustc-nightly-x86_64-unknown-illumos.tar.gz=143f5ce723a8f5e54af64a3b31d83243a808355705b1402be5de821759187066 -dist/2024-09-22/rustc-nightly-x86_64-unknown-illumos.tar.xz=c88c8d2ae8f221fe1db978802c98368472381b443bed9501371c03617865785d -dist/2024-09-22/rustc-nightly-x86_64-unknown-linux-gnu.tar.gz=0ea098f78927d9fdf4ec075a04e989b6ac83bc1f1225aca5960281cd65046a3b -dist/2024-09-22/rustc-nightly-x86_64-unknown-linux-gnu.tar.xz=33e5e1e0b758de383281ae704d3dd1ee337d8e28515d6b4584dd2691587c7f0e -dist/2024-09-22/rustc-nightly-x86_64-unknown-linux-musl.tar.gz=723f5eaceef968b05286a17b7868c7e0cf222ac33d23a9ac3f761fc274b87c38 -dist/2024-09-22/rustc-nightly-x86_64-unknown-linux-musl.tar.xz=1b00b14a57b6f3b7edbf9adc05d3ed28ed1e2b8ced921a444d13dd1ef577e715 -dist/2024-09-22/rustc-nightly-x86_64-unknown-netbsd.tar.gz=6cd2651e4e8aedd8aef8d325a72cf18694ee7a14077c7331d96e2e7c03b9c57a -dist/2024-09-22/rustc-nightly-x86_64-unknown-netbsd.tar.xz=0c6144559f040a209183d6f02f61caf485f0174190e643870d1d6c9744bfede3 \ No newline at end of file +dist/2024-10-17/rustc-1.82.0-aarch64-apple-darwin.tar.gz=1328567478da2dbf9e05303efddfbff6623d38227fa80e4d77252418cbfb493b +dist/2024-10-17/rustc-1.82.0-aarch64-apple-darwin.tar.xz=ca9b9cab552c86ac7a28d8fb757c95a363bb5d6413b854b19472950eab2a9fa4 +dist/2024-10-17/rustc-1.82.0-aarch64-pc-windows-msvc.tar.gz=2831b9f073adb36bf30de8587d0ebbf58badf2807b3ff6929a96473152e6a92f +dist/2024-10-17/rustc-1.82.0-aarch64-pc-windows-msvc.tar.xz=3ce2b4bd65eb90341b7979a839262bc415d81391c0ad0587597fb53976033d30 +dist/2024-10-17/rustc-1.82.0-aarch64-unknown-linux-gnu.tar.gz=4e8a37508e732cfc95f0a03ebe51bd05e1212f126747c612bef608dd2223cbde +dist/2024-10-17/rustc-1.82.0-aarch64-unknown-linux-gnu.tar.xz=2958e667202819f6ba1ea88a2a36d7b6a49aad7e460b79ebbb5cf9221b96f599 +dist/2024-10-17/rustc-1.82.0-aarch64-unknown-linux-musl.tar.gz=3b138c781e9291c4d08bbac1e8dced14ae9a734d90f01c66396d971603dcb0b7 +dist/2024-10-17/rustc-1.82.0-aarch64-unknown-linux-musl.tar.xz=0871614a8b17e7ab7dd17cbad7697b2c6658aff1d079c50719bf16b576a3cab9 +dist/2024-10-17/rustc-1.82.0-arm-unknown-linux-gnueabi.tar.gz=b1007e3e8ca340211552220baaf56ba157c9232f7957272089dda554a3f27d2f +dist/2024-10-17/rustc-1.82.0-arm-unknown-linux-gnueabi.tar.xz=e3aed98123ce8cf28390c87061a6215f515316996fca2996d5cb6beb3f7b8487 +dist/2024-10-17/rustc-1.82.0-arm-unknown-linux-gnueabihf.tar.gz=c1859e6cd8524e2b8b130eb096f17b85522287381231f13e7e512e13b37ad4bd +dist/2024-10-17/rustc-1.82.0-arm-unknown-linux-gnueabihf.tar.xz=a3174f8d6b25ac452da100ca0e35066e02b871952cbdc9f9023f36e1305f4d01 +dist/2024-10-17/rustc-1.82.0-armv7-unknown-linux-gnueabihf.tar.gz=c6f13a6f313b866df4e76e5817e01dd52194ca205d37604bc94500205618c7f1 +dist/2024-10-17/rustc-1.82.0-armv7-unknown-linux-gnueabihf.tar.xz=17b1236e171b9d92eb62996d41a84d877d0cc48309619ee0b35be2edd111c733 +dist/2024-10-17/rustc-1.82.0-i686-pc-windows-gnu.tar.gz=a77e0ecc6fa1a97ed99898ba32263a5525ff8e1dc7d6a5a83038458a7898cee1 +dist/2024-10-17/rustc-1.82.0-i686-pc-windows-gnu.tar.xz=8caa097840f91846363f2c7712cf4edd974716f5b5c251f97920037825bf606a +dist/2024-10-17/rustc-1.82.0-i686-pc-windows-msvc.tar.gz=0bcfa88ecece3b7ea8d7d91975fe2bc63379892891421ffbc2fdc02d12d765bc +dist/2024-10-17/rustc-1.82.0-i686-pc-windows-msvc.tar.xz=f35f7073e6027d2b112a8344a83703be88fa6ff9e276a10ad124cd85e88f9a2b +dist/2024-10-17/rustc-1.82.0-i686-unknown-linux-gnu.tar.gz=28bbbe8f9632bb72736a475fc00b887062b631b21014012af9b65fdd4e0341f4 +dist/2024-10-17/rustc-1.82.0-i686-unknown-linux-gnu.tar.xz=92bab38ce88b7738fb62a1bccf496b1b2975fe984cc4fc506903a03ed37e1e4a +dist/2024-10-17/rustc-1.82.0-loongarch64-unknown-linux-gnu.tar.gz=c88cc7a64c7cec8b0e740e5d8ca6c187740f09da1fa81b776415ff3165b4cb38 +dist/2024-10-17/rustc-1.82.0-loongarch64-unknown-linux-gnu.tar.xz=2bdbf08c8c7d3a4dc8bddddbc4cf2cdec5a3d0f4a42e19183a14bed24d8d580c +dist/2024-10-17/rustc-1.82.0-loongarch64-unknown-linux-musl.tar.gz=6efbdf4bd394282703317556e4a1797774def882ada75fa1a1ed9d1e94b6379e +dist/2024-10-17/rustc-1.82.0-loongarch64-unknown-linux-musl.tar.xz=8b6cb386c5412b4e969bf7fa4f220dcddcf99918990698e73c87a505f972d10c +dist/2024-10-17/rustc-1.82.0-powerpc-unknown-linux-gnu.tar.gz=98bc0939ff1068ee1e60b87569e756e33ebd2f401e50d1543a2e1ef0a0536066 +dist/2024-10-17/rustc-1.82.0-powerpc-unknown-linux-gnu.tar.xz=0d93e17a06cd284bdc0a97df64733f4b2f9f8c3cd9163935d85812ebc8520d2f +dist/2024-10-17/rustc-1.82.0-powerpc64-unknown-linux-gnu.tar.gz=4d3db920a5c859a48e4226a100b34199bf887fbd3250536de64e4289f10ca544 +dist/2024-10-17/rustc-1.82.0-powerpc64-unknown-linux-gnu.tar.xz=8795c642f94d15c81420a8eff77efbbac553869a00c627a1e3f881c542388b4a +dist/2024-10-17/rustc-1.82.0-powerpc64le-unknown-linux-gnu.tar.gz=c08ed2722ea4d638bdc522ce40f5d5ec859a162e0686afdbddfc86fb18f5d8e2 +dist/2024-10-17/rustc-1.82.0-powerpc64le-unknown-linux-gnu.tar.xz=0b22b37e51dd1dab6cc80a02968873ecb5f886fe1a65cd47131e3d10be48a23b +dist/2024-10-17/rustc-1.82.0-riscv64gc-unknown-linux-gnu.tar.gz=deb1433106713e86228903ed96c34d178326c530bf0bf6cd1537e796b5433964 +dist/2024-10-17/rustc-1.82.0-riscv64gc-unknown-linux-gnu.tar.xz=225726a3fedeb6cf136d5af503fb6853a0ce3c735fd972d40d678d734e65f5e8 +dist/2024-10-17/rustc-1.82.0-s390x-unknown-linux-gnu.tar.gz=c170f803214198c42a657e10ec8e5798e937d38d234ac0eca9b0bc5b229462e9 +dist/2024-10-17/rustc-1.82.0-s390x-unknown-linux-gnu.tar.xz=bd46920849468c4ab78c53b21c962e538b1e8a9f38c736a9e52d790c75d55c45 +dist/2024-10-17/rustc-1.82.0-x86_64-apple-darwin.tar.gz=fae80442b096cad7a3d0f8b7422280ac8b28878dff150dcf1fce93362c17cdae +dist/2024-10-17/rustc-1.82.0-x86_64-apple-darwin.tar.xz=f74ade16cc926a240208ec87d02dcb30f6bb29f9ce9b36479bca57a159e6d96b +dist/2024-10-17/rustc-1.82.0-x86_64-pc-windows-gnu.tar.gz=c5b5205d17d136d1a99d81e02a0021d2cf41ef05d2bc152b3172078465272a76 +dist/2024-10-17/rustc-1.82.0-x86_64-pc-windows-gnu.tar.xz=5094026cfedf63f14ea253102ceac324caa2e81a592b6a36cdca26e8ceab67c0 +dist/2024-10-17/rustc-1.82.0-x86_64-pc-windows-msvc.tar.gz=ca3f1fb9a59747f75d1cb6281453d355a5a983d774e11c2f1a814336cb2ad123 +dist/2024-10-17/rustc-1.82.0-x86_64-pc-windows-msvc.tar.xz=edbb7f4b54570cec577239d69558c6da117a5f7b7d3811e875ddcbe91dbaab68 +dist/2024-10-17/rustc-1.82.0-x86_64-unknown-freebsd.tar.gz=3a848b0349d44cf750df1086554f2c3beeda03298b4587193c4fdd588005882a +dist/2024-10-17/rustc-1.82.0-x86_64-unknown-freebsd.tar.xz=c999758547af811f0e533aca2891f769215a86ae5fb7312da7846221e3d529d6 +dist/2024-10-17/rustc-1.82.0-x86_64-unknown-illumos.tar.gz=d6898f4c03365e0fcaa16cb29490a778e8c539f72b9159ffde8a33fbd422208f +dist/2024-10-17/rustc-1.82.0-x86_64-unknown-illumos.tar.xz=8945eace2fb36d896f46b613c2b59e5abe96ff882c3935adc53f0395d95947e7 +dist/2024-10-17/rustc-1.82.0-x86_64-unknown-linux-gnu.tar.gz=94d5ac7d978a2397fd112704985fc892fb0a813e384682c697c47071ab2d3807 +dist/2024-10-17/rustc-1.82.0-x86_64-unknown-linux-gnu.tar.xz=90b61494f5ccfd4d1ca9a5ce4a0af49a253ca435c701d9c44e3e44b5faf70cb8 +dist/2024-10-17/rustc-1.82.0-x86_64-unknown-linux-musl.tar.gz=92ad2482b6ee4a7abd699d3882c37e4768ac4d4fa3ae30e9309945aa7ab59ffd +dist/2024-10-17/rustc-1.82.0-x86_64-unknown-linux-musl.tar.xz=e08b8490246ae1b6278274f6dd0a648c590a42e0af6aaf220a030cdf1dadf30a +dist/2024-10-17/rustc-1.82.0-x86_64-unknown-netbsd.tar.gz=7cfd197e016f65435575c47192baae61868050916c5ea412348386b04a74eaa8 +dist/2024-10-17/rustc-1.82.0-x86_64-unknown-netbsd.tar.xz=4be0bfb3cbbbea8b54abd273dfc9b0eefd7bce409f25690fd5e532ff3f28c4ac +dist/2024-10-17/rust-std-1.82.0-aarch64-apple-darwin.tar.gz=5ec28e75ed8715efaa2490d76ae026a34b13df6899d98b14d0a6995556f4e6b4 +dist/2024-10-17/rust-std-1.82.0-aarch64-apple-darwin.tar.xz=8b0786c55e02f3adc5df030861b6b60bc336326b9e372f6b1bf3040257621a90 +dist/2024-10-17/rust-std-1.82.0-aarch64-apple-ios.tar.gz=f7dc318da711f1975882f27ab29e7129a076013707b46cbfba44a35f9b877226 +dist/2024-10-17/rust-std-1.82.0-aarch64-apple-ios.tar.xz=7362a6629e09c0d3c8723809217b80a425d5f9466ff312fcf02245050168e116 +dist/2024-10-17/rust-std-1.82.0-aarch64-apple-ios-macabi.tar.gz=98b9336a333d4dc78a241667a54e3e91ea45da6bd6f3bed660bc15534c7aab1a +dist/2024-10-17/rust-std-1.82.0-aarch64-apple-ios-macabi.tar.xz=1a2b30a6f43dfe4bfa7b28ece9893eea3aee1eda96dd78f816a0bc79c9843833 +dist/2024-10-17/rust-std-1.82.0-aarch64-apple-ios-sim.tar.gz=730400195c04c7080da25de04f85ca7e14c8007112c4a6650d56a1d631069b0f +dist/2024-10-17/rust-std-1.82.0-aarch64-apple-ios-sim.tar.xz=02c2347fbeadaf45d53ec1aeb646947ce9a115f3395f1dd700429ab9f2acff95 +dist/2024-10-17/rust-std-1.82.0-aarch64-linux-android.tar.gz=2ae7787121d3b51fbbf96f0191147c1ea1698f9b92bee1096adad3ea74860eab +dist/2024-10-17/rust-std-1.82.0-aarch64-linux-android.tar.xz=93b3502ebd3dcbb1854dd713ba4a3c716fbfab788c811449ba0257e9138f30d8 +dist/2024-10-17/rust-std-1.82.0-aarch64-pc-windows-gnullvm.tar.gz=7956b40dc972a746c19695c50efcf5644c29b3a810b826f7b0dc7e7c3e8a8f0a +dist/2024-10-17/rust-std-1.82.0-aarch64-pc-windows-gnullvm.tar.xz=cfe0754e28b5b827267afd050970b620e6767c759126ab9b7e6e0989ca8d6923 +dist/2024-10-17/rust-std-1.82.0-aarch64-pc-windows-msvc.tar.gz=4b6684f108abe940de2bf3546a9cc6b15d9526ea18df335888719bf271496f0b +dist/2024-10-17/rust-std-1.82.0-aarch64-pc-windows-msvc.tar.xz=d96cf028593374741696bf7319198ecb4ee0de2b4f1a72f9ce0c515be3c670bd +dist/2024-10-17/rust-std-1.82.0-aarch64-unknown-fuchsia.tar.gz=5416e041426b7a3e1304b9acc63428a434671b65d60575091de26279a6216873 +dist/2024-10-17/rust-std-1.82.0-aarch64-unknown-fuchsia.tar.xz=d66c6573443db41d6f0bd8e693ce25831e318b6dc3b6c51388cc2688d2b6000e +dist/2024-10-17/rust-std-1.82.0-aarch64-unknown-linux-gnu.tar.gz=82b2308ee531775bf4d1faa57bddfae85f363bec43ca36ba6db4ebad7c1450d4 +dist/2024-10-17/rust-std-1.82.0-aarch64-unknown-linux-gnu.tar.xz=1359ac1f3a123ae5da0ee9e47b98bb9e799578eefd9f347ff9bafd57a1d74a7f +dist/2024-10-17/rust-std-1.82.0-aarch64-unknown-linux-musl.tar.gz=1ea6dcf3a0c0d3a7133fa75f157bd17a3e1363be135f39325ab89ee1775de96b +dist/2024-10-17/rust-std-1.82.0-aarch64-unknown-linux-musl.tar.xz=a364a4b506865fbd56aac67e2b540a824cd9abda621bb38a8b678166d33b8ec2 +dist/2024-10-17/rust-std-1.82.0-aarch64-unknown-linux-ohos.tar.gz=553792b1b061d557a9b442477c645509b3c9f4a6e5bb819422b7a5e0692b4b88 +dist/2024-10-17/rust-std-1.82.0-aarch64-unknown-linux-ohos.tar.xz=1c8174a7dfcf8651ee3e811ffa51b55ca99319e4234098a46b1d441ab5698cb4 +dist/2024-10-17/rust-std-1.82.0-aarch64-unknown-none.tar.gz=455c3bd2240e20feee3133ceeabb7e67575ce418e9cb38a9ccd5f1035623332d +dist/2024-10-17/rust-std-1.82.0-aarch64-unknown-none.tar.xz=1b9514d6f4a6a1d1b37125b20bb97b10853a70619c1da15182e7d28b97b2ddf8 +dist/2024-10-17/rust-std-1.82.0-aarch64-unknown-none-softfloat.tar.gz=c814a68f17380f77c5cfcc274ec8288746df46d72a4e74fe0b622735feda0d81 +dist/2024-10-17/rust-std-1.82.0-aarch64-unknown-none-softfloat.tar.xz=3d9111a4a6dd3651a65559f1ccda6427f0f6c02bc0dad99fa8239beaedc28f09 +dist/2024-10-17/rust-std-1.82.0-aarch64-unknown-uefi.tar.gz=20a138a49f44ec6150fb83c81e399dc20aefef89ba838dae50a18712d4373f66 +dist/2024-10-17/rust-std-1.82.0-aarch64-unknown-uefi.tar.xz=50ee71050599b9386ce50e0fadb06d535662e0088c45dbe06f0e58296f76c847 +dist/2024-10-17/rust-std-1.82.0-arm-linux-androideabi.tar.gz=0874d6ed437f531d19229028927c879769e82f18e48c5216b5f0411ecda74b84 +dist/2024-10-17/rust-std-1.82.0-arm-linux-androideabi.tar.xz=47e624938b52e013e258c9bac155f838d1da45ba54b87ded39e19fac8e3a41dc +dist/2024-10-17/rust-std-1.82.0-arm-unknown-linux-gnueabi.tar.gz=c99f382c52b796c12702c92bf816a4366cfad877445236e1423a04efc79afcb2 +dist/2024-10-17/rust-std-1.82.0-arm-unknown-linux-gnueabi.tar.xz=bec0b04e6e1e183fc21521e9cc2dc89be41c3ccacff3fb5ca48419b47af94fe1 +dist/2024-10-17/rust-std-1.82.0-arm-unknown-linux-gnueabihf.tar.gz=3543becabab676100418c8a41d3976f93cf512dfa2291f4b0eb47f446eeec7c1 +dist/2024-10-17/rust-std-1.82.0-arm-unknown-linux-gnueabihf.tar.xz=fa379cc69b23782cbaddf66025889bf5ca9c32ddb60766fe158b43cfe49a2b2b +dist/2024-10-17/rust-std-1.82.0-arm-unknown-linux-musleabi.tar.gz=76aa0be6279456aff30637fd3bb6e0ac423d8aa945a4b0d06fdfa5ceda0b5da6 +dist/2024-10-17/rust-std-1.82.0-arm-unknown-linux-musleabi.tar.xz=cd5e1577c1772ba309d003c49a2df2f06ccbc1cd1bf3ee9c1cfada210979f26e +dist/2024-10-17/rust-std-1.82.0-arm-unknown-linux-musleabihf.tar.gz=984c9830fe9951430f36a1167d6504edf8aed33466c56d451ac83fddef48e2e6 +dist/2024-10-17/rust-std-1.82.0-arm-unknown-linux-musleabihf.tar.xz=86f2242347c1cbae354cd0ff66c9bfe735f1b371c189aaf0157a3b55004590cb +dist/2024-10-17/rust-std-1.82.0-arm64ec-pc-windows-msvc.tar.gz=c9c63f33e1baf5df9f73d77c5a9dc611f3afe8b82e790b3f4352d514c70cd1aa +dist/2024-10-17/rust-std-1.82.0-arm64ec-pc-windows-msvc.tar.xz=0bb5d2a54b557a59eed411cdf41d7a5f178399d6bee719e4a95a4862b1821d2d +dist/2024-10-17/rust-std-1.82.0-armebv7r-none-eabi.tar.gz=8c829edd5e7c2f569ba3e02acdb85d301b24149e653329f15ed3341204756237 +dist/2024-10-17/rust-std-1.82.0-armebv7r-none-eabi.tar.xz=127e1551afee90d629c5ca386408e777f53abb301b8facea90d318bd97e30374 +dist/2024-10-17/rust-std-1.82.0-armebv7r-none-eabihf.tar.gz=c82ebc6382d91fad8a1c49a5723965b25958268af149035f2c2210007dc1b143 +dist/2024-10-17/rust-std-1.82.0-armebv7r-none-eabihf.tar.xz=14741ce98f6b99d6a5b7d35a2a0a04e599d59aeb6f7c23e8fb3183d63ee40ea9 +dist/2024-10-17/rust-std-1.82.0-armv5te-unknown-linux-gnueabi.tar.gz=3058af47cfb839c31402c9990efea1dd5ab57ed9e4afa42f35693b2461776463 +dist/2024-10-17/rust-std-1.82.0-armv5te-unknown-linux-gnueabi.tar.xz=e3c74773cf6f09a3cda1b64c3058f5a88abea0a98f172de895c0ecf7b7b760b2 +dist/2024-10-17/rust-std-1.82.0-armv5te-unknown-linux-musleabi.tar.gz=dc884fba6a42b498e624515a41ed13ea85859a4d6b9f2e3139fb43dd0934b9b5 +dist/2024-10-17/rust-std-1.82.0-armv5te-unknown-linux-musleabi.tar.xz=df0a3be0e71ca8aa8be4915f7142661af32411949a75c1729a314e6ab5c78b0b +dist/2024-10-17/rust-std-1.82.0-armv7-linux-androideabi.tar.gz=6a3ebc28aa474fbef5cc231acd012e51cfbd3377cac42491408cb723a052c493 +dist/2024-10-17/rust-std-1.82.0-armv7-linux-androideabi.tar.xz=28fd4f08d1c79d2ec41f41b6a3682f8cd1251731bad19295c2eb7232aa41f39f +dist/2024-10-17/rust-std-1.82.0-armv7-unknown-linux-gnueabi.tar.gz=4a1f5425fa7e60c95ed8473aadf80b26b6126fb381dbeaf33ccc56c2a2644cda +dist/2024-10-17/rust-std-1.82.0-armv7-unknown-linux-gnueabi.tar.xz=4d692c1696ad49285a45bc5f636ce9c13ccb32b99ed14be428eaaf1e0cae6b33 +dist/2024-10-17/rust-std-1.82.0-armv7-unknown-linux-gnueabihf.tar.gz=5dd8b36467e03ba47bfa7ea5d7578c66bccb648dd2129d7cec6fb3ff00f81ca3 +dist/2024-10-17/rust-std-1.82.0-armv7-unknown-linux-gnueabihf.tar.xz=34d258a07c9051803786405731c05fb19f7980e13308acf4b16e8c836bd73ac8 +dist/2024-10-17/rust-std-1.82.0-armv7-unknown-linux-musleabi.tar.gz=45831c0e70ca333858742b1d83aedd74ca6b2b19e7c2f59211b8dcbe9544f12f +dist/2024-10-17/rust-std-1.82.0-armv7-unknown-linux-musleabi.tar.xz=1e318fcff01379cf4459f02526309b1f086530004be4fb5e00988ce7b1d821f5 +dist/2024-10-17/rust-std-1.82.0-armv7-unknown-linux-musleabihf.tar.gz=8015b98c45ad6251475e7ae94689e47c3ffd74af87b5ba4a84f50211d3c793f8 +dist/2024-10-17/rust-std-1.82.0-armv7-unknown-linux-musleabihf.tar.xz=bf93c79abc56bfcc3d48f2defcb0ca720405d01a50ba08d6d24830ae034bbc2d +dist/2024-10-17/rust-std-1.82.0-armv7-unknown-linux-ohos.tar.gz=a56d544aa57bcbe49104b927f9429db4dcb2647282eaa4a98aba5bb015f06ffa +dist/2024-10-17/rust-std-1.82.0-armv7-unknown-linux-ohos.tar.xz=a2c8ddc17bb29172f236800e14051b00b5a3288485870b1fe55b30924ec42abe +dist/2024-10-17/rust-std-1.82.0-armv7a-none-eabi.tar.gz=1210376c4a9c8c235c671058479625af4ee52c93c3a2f20ce2053ba442c7cb91 +dist/2024-10-17/rust-std-1.82.0-armv7a-none-eabi.tar.xz=1b449b2184f15b474b7ce6848c282e28cd704a84b2d59ae3e54a605ee99f74ea +dist/2024-10-17/rust-std-1.82.0-armv7r-none-eabi.tar.gz=93d8d438e54133d59d6e323f1e3a30f0a21c9f921eedd8c2c6256a5bac367d4d +dist/2024-10-17/rust-std-1.82.0-armv7r-none-eabi.tar.xz=1db8cac61ae6aa1345c45cc69cc023b8c360b53326ba081266a68a9dc39d4f74 +dist/2024-10-17/rust-std-1.82.0-armv7r-none-eabihf.tar.gz=113d210f6340ec52c8acaa1ad2194df4c186ae9393889215f4491559e8e6616b +dist/2024-10-17/rust-std-1.82.0-armv7r-none-eabihf.tar.xz=470c2d3bf9c9d83e5d0dd80e6d240988b491456bf1ee9e93469cce3ce1299661 +dist/2024-10-17/rust-std-1.82.0-i586-pc-windows-msvc.tar.gz=5e2c1506621e8066047fed73c6b0b974a8fc45555943039abbefff05e4d8a2e7 +dist/2024-10-17/rust-std-1.82.0-i586-pc-windows-msvc.tar.xz=41948efdcf250cd512cb19128983ba2639dcd191943e62da5f9151c9a7340e28 +dist/2024-10-17/rust-std-1.82.0-i586-unknown-linux-gnu.tar.gz=140be2f72822b514ae29e6b6e4c53ffd89205aea116dab69c658c7476f89608c +dist/2024-10-17/rust-std-1.82.0-i586-unknown-linux-gnu.tar.xz=f56585c55664898c7484f4b7bd139770c99d7b4da6e56e4016f71cb053b1aee2 +dist/2024-10-17/rust-std-1.82.0-i586-unknown-linux-musl.tar.gz=4838c5fe110a57e6a70c823fc07d8e6a674befe03c908431c2c8f15b9553a993 +dist/2024-10-17/rust-std-1.82.0-i586-unknown-linux-musl.tar.xz=711c03ffb5bb53fcc97278b015d1ea9f503ce826ba390855f576c0e3b77c4bdb +dist/2024-10-17/rust-std-1.82.0-i686-linux-android.tar.gz=080ab4138df25f7a5101e803f9a74133fac59d7991632161cf4e4aea7d29a732 +dist/2024-10-17/rust-std-1.82.0-i686-linux-android.tar.xz=047d68ed5fad92ca7cd70d5eb710c17da3d6777ef2b036a1d4f5b1fc20ce49ac +dist/2024-10-17/rust-std-1.82.0-i686-pc-windows-gnu.tar.gz=90e89abc88569526626c295c934d2b33d7dd24dc80ff6d07bb79f3a82e183fb0 +dist/2024-10-17/rust-std-1.82.0-i686-pc-windows-gnu.tar.xz=874520c9444fef60ed1ab26142f15f86909dfadb6ae8b1c9bbb2a023d769579a +dist/2024-10-17/rust-std-1.82.0-i686-pc-windows-gnullvm.tar.gz=f645d70577ebbb4a89641edf300e5b9ff742f8695094ced3ff5b45902202a3ca +dist/2024-10-17/rust-std-1.82.0-i686-pc-windows-gnullvm.tar.xz=a01849b1a382ad2a24d30442a020e2799b8864cd2d4cfe4b00ee3365b7cf69ea +dist/2024-10-17/rust-std-1.82.0-i686-pc-windows-msvc.tar.gz=9a360bea07f309a19f4abb395e9b1a34e26d64737f1e89e4eebf3ac2f0f9145f +dist/2024-10-17/rust-std-1.82.0-i686-pc-windows-msvc.tar.xz=a901305f6073074692693c653e885d058206b050b9a7b2253b0eaf5854bcd81f +dist/2024-10-17/rust-std-1.82.0-i686-unknown-freebsd.tar.gz=6d7823950c64f2052199e09111f65424eb5aadb4caddeec3e2c3030e696d192a +dist/2024-10-17/rust-std-1.82.0-i686-unknown-freebsd.tar.xz=b6aec2476e14176cd78e08e2367986955846f0cd5454417951c1e1e1948c7679 +dist/2024-10-17/rust-std-1.82.0-i686-unknown-linux-gnu.tar.gz=b2776d74e3c6ca272b20d92bc7593065803525119a649163fdb359c9fa2b7ab6 +dist/2024-10-17/rust-std-1.82.0-i686-unknown-linux-gnu.tar.xz=c7ebb02b6ca349999b3b7dce768efaca5e0d9060f55397523e11a64cd10a9405 +dist/2024-10-17/rust-std-1.82.0-i686-unknown-linux-musl.tar.gz=1d5c6281996565d4832355e881a677a1e05c15d7989df11fd980a18df1404c82 +dist/2024-10-17/rust-std-1.82.0-i686-unknown-linux-musl.tar.xz=3c5ee32afc4b83313832c7a78175c05a5e568e6053fde7e65e2a9b19ce104c10 +dist/2024-10-17/rust-std-1.82.0-i686-unknown-uefi.tar.gz=24d269a98cd59541096b1e5007920c3a9436d66f44bed940fb985412a7c37f01 +dist/2024-10-17/rust-std-1.82.0-i686-unknown-uefi.tar.xz=bb2801d89b86e06c7ccd3cceee86a647eb83b34a1727fd866d8ffe98fdf03009 +dist/2024-10-17/rust-std-1.82.0-loongarch64-unknown-linux-gnu.tar.gz=e7dd5cd1fdb6c5e498c31223a2a054d64b6d1aba64a504960a9ae10eb2d29ca2 +dist/2024-10-17/rust-std-1.82.0-loongarch64-unknown-linux-gnu.tar.xz=8cc1399b0460b3bc4b7295165dcdcee310fd643dc29569e1786944650f2a3700 +dist/2024-10-17/rust-std-1.82.0-loongarch64-unknown-linux-musl.tar.gz=7ecb5cdce9f8c9907694fd5b11bc5be5162f829d29f17c4c2ba9143ca06c7413 +dist/2024-10-17/rust-std-1.82.0-loongarch64-unknown-linux-musl.tar.xz=fa2009715b96b16394034c59ca34b12f378884a0b27064931f8b41362572edcb +dist/2024-10-17/rust-std-1.82.0-loongarch64-unknown-none.tar.gz=55ed2817d732b2de4666d689635fc727ccaeb1228c2308209ee7e30cb81e1518 +dist/2024-10-17/rust-std-1.82.0-loongarch64-unknown-none.tar.xz=f9aee76b42c2b7376fcc74fa2474d3edf2729c94bc19859807a09d71e8ddb63f +dist/2024-10-17/rust-std-1.82.0-loongarch64-unknown-none-softfloat.tar.gz=5f4c3aa18aeb93bc5eadb1211665399c9af3dcc30e700dab10c8d2f93062b79a +dist/2024-10-17/rust-std-1.82.0-loongarch64-unknown-none-softfloat.tar.xz=4d4992ceab05ee423a32c9dbf79349d3ad158239692fb704630a3130cde45b79 +dist/2024-10-17/rust-std-1.82.0-nvptx64-nvidia-cuda.tar.gz=eaaf52db9f76bd327f33daaa6c5285f4776da6153179fbb4ed57fd02b170df3f +dist/2024-10-17/rust-std-1.82.0-nvptx64-nvidia-cuda.tar.xz=99ca45210cb6a3c54675c852a6406b5d3374ea97d9f42a503d338e9c85ba00e8 +dist/2024-10-17/rust-std-1.82.0-powerpc-unknown-linux-gnu.tar.gz=04cb6222f53b0bdff950e8ddaf5e869639a3726022cbd8c4e78190bdccf1f1cb +dist/2024-10-17/rust-std-1.82.0-powerpc-unknown-linux-gnu.tar.xz=827989a42526206199025f764d08d7cd319fee58bf2e08dcaf75df9ead6f094e +dist/2024-10-17/rust-std-1.82.0-powerpc64-unknown-linux-gnu.tar.gz=16d0b159cdd964e0a1f479baabc4f560ffddbe18f282a8fabe2d32dff38acab3 +dist/2024-10-17/rust-std-1.82.0-powerpc64-unknown-linux-gnu.tar.xz=cdfadb39f1325319de8152504413f34671ac09fa7ecb97f967c25ece3645bc5e +dist/2024-10-17/rust-std-1.82.0-powerpc64le-unknown-linux-gnu.tar.gz=142c7c2896fa4596b5c4c35d9d5e4d80acd5a699e5fa0560d92a89eda035ece3 +dist/2024-10-17/rust-std-1.82.0-powerpc64le-unknown-linux-gnu.tar.xz=4954a44305622b8f68ca088138b9a69432e350336da1a415a282ce148beb340d +dist/2024-10-17/rust-std-1.82.0-riscv32i-unknown-none-elf.tar.gz=670ccca647a4ced67d454c5358fd9c600cc78d0547c282b1e227d27fb7e37af7 +dist/2024-10-17/rust-std-1.82.0-riscv32i-unknown-none-elf.tar.xz=0c845cc2b274d0268f0089c3ed6a10cefdac7946b0583bebb04c573888028ce5 +dist/2024-10-17/rust-std-1.82.0-riscv32im-unknown-none-elf.tar.gz=e46f1a6feef04db6df867f274313027ebdf5b89a7789704e033271d81f53a3c6 +dist/2024-10-17/rust-std-1.82.0-riscv32im-unknown-none-elf.tar.xz=b3ab26cd2e852aee9eca2ec84a3cb07bd0ca396618865cd77e6767f337b8250f +dist/2024-10-17/rust-std-1.82.0-riscv32imac-unknown-none-elf.tar.gz=118df0850ee1166238ebf671f02319c3d45de6b97ab4c9ce0b9e6db9ee16f97c +dist/2024-10-17/rust-std-1.82.0-riscv32imac-unknown-none-elf.tar.xz=6465a6cad21352639a5eb438c0628970e781b88332058fa8080c5bcf8b657c37 +dist/2024-10-17/rust-std-1.82.0-riscv32imafc-unknown-none-elf.tar.gz=d085edd92048647d568c22a9b5eb6a8a6c0efb16b90a270a61aaa82e717257a4 +dist/2024-10-17/rust-std-1.82.0-riscv32imafc-unknown-none-elf.tar.xz=aebb06650b57c2c625a541fc1171f67fdcf3d2eee82e29aa0785bba072243f2c +dist/2024-10-17/rust-std-1.82.0-riscv32imc-unknown-none-elf.tar.gz=0b46013f24e6bfd42bdf07c1f14b4036da8e539366e5f7b8072471db189213bc +dist/2024-10-17/rust-std-1.82.0-riscv32imc-unknown-none-elf.tar.xz=fc7d70722e698dd816f55ee3cbfb435f4440ed2b78b27d74f57fc6f642ce7dcd +dist/2024-10-17/rust-std-1.82.0-riscv64gc-unknown-linux-gnu.tar.gz=7b35c8207c77e3fc2f7f7a26dea989cc2cdc13a955851ff74d4882f96f4e14dd +dist/2024-10-17/rust-std-1.82.0-riscv64gc-unknown-linux-gnu.tar.xz=5649f9b4e107d6c5f72fb7f82cfe15370b80b8d983670602e02e0b615bc6dc88 +dist/2024-10-17/rust-std-1.82.0-riscv64gc-unknown-linux-musl.tar.gz=f1c562e3085b237f8b7a27bdb3beafae96f7216706c9ccfd0493de36e70486c7 +dist/2024-10-17/rust-std-1.82.0-riscv64gc-unknown-linux-musl.tar.xz=16fadf1214cbea6de40f3f7c6726d7197f1ed7a985a8341fe08f320896bc4d55 +dist/2024-10-17/rust-std-1.82.0-riscv64gc-unknown-none-elf.tar.gz=464ea9949b1120494a7206e3b6b4d6784914a771a0cbfe93b6ac670680918d00 +dist/2024-10-17/rust-std-1.82.0-riscv64gc-unknown-none-elf.tar.xz=fe6a526508c337910c5821fb98b83d3f33e75d608d14ed6605820da90488c99f +dist/2024-10-17/rust-std-1.82.0-riscv64imac-unknown-none-elf.tar.gz=1c12d9222e1b41cdbb2eb817b46b9fbc9b1c616f964d84128ff7749444e8ae2c +dist/2024-10-17/rust-std-1.82.0-riscv64imac-unknown-none-elf.tar.xz=d379fac8a4cec097afa77c6fc4be985900f852168e3b3ebff986033005473906 +dist/2024-10-17/rust-std-1.82.0-s390x-unknown-linux-gnu.tar.gz=dd67b9750820db1c45e6fba18bff0c432ca4cef695e61464d624b5851ccc16c5 +dist/2024-10-17/rust-std-1.82.0-s390x-unknown-linux-gnu.tar.xz=454b83668b57bdef28fc49aca8fd4c38e395b49011e653afdf3f9bb2dae8aa63 +dist/2024-10-17/rust-std-1.82.0-sparc64-unknown-linux-gnu.tar.gz=9cf3146aa0e1ecccf49c2a4fe1dba9cb975307bff7600d080215e7436294c95b +dist/2024-10-17/rust-std-1.82.0-sparc64-unknown-linux-gnu.tar.xz=87db52d782131a8817b76f65eefcae2c24a49b2a6f19ed9bd4699167305c22aa +dist/2024-10-17/rust-std-1.82.0-sparcv9-sun-solaris.tar.gz=30337599f006e8e1c605829ff23ac28479f3c34d09e1c404227c93985cb88f7a +dist/2024-10-17/rust-std-1.82.0-sparcv9-sun-solaris.tar.xz=6367aa2aab40ff001df1ae36edb430639a7c2ba61635fd8a12313c22a6ab15fd +dist/2024-10-17/rust-std-1.82.0-thumbv6m-none-eabi.tar.gz=59fad27db1564a7553e36c3b5946311d9c33e1fe3585baf7b8078ebc5275674b +dist/2024-10-17/rust-std-1.82.0-thumbv6m-none-eabi.tar.xz=22c9915698516cbdcedcf3171522b615ae035d8fa18a3affe0f461cd047f546c +dist/2024-10-17/rust-std-1.82.0-thumbv7em-none-eabi.tar.gz=33a80d74aa9758044fde77e72f61569f1f953906b8f042bff353f6a8d39267ea +dist/2024-10-17/rust-std-1.82.0-thumbv7em-none-eabi.tar.xz=908bde5254a6606a4c4ade1b07afe0d07de2fc260904d8879007e6291cb8b3fa +dist/2024-10-17/rust-std-1.82.0-thumbv7em-none-eabihf.tar.gz=c89afce812ed2aed71c1439cf85b7f1da07ae0dee6be1f7826085d602ba2a5ce +dist/2024-10-17/rust-std-1.82.0-thumbv7em-none-eabihf.tar.xz=b05ddea444053a1387ad39037d1e5dc2130274399c4bb0d592f0cc19e6d6f3e6 +dist/2024-10-17/rust-std-1.82.0-thumbv7m-none-eabi.tar.gz=c2a65cc8449aaf144ba743372efae162c093998bd51d72a1124bef57fd396a20 +dist/2024-10-17/rust-std-1.82.0-thumbv7m-none-eabi.tar.xz=afc6d541335eb18b32dc7ba66f3d0f680ddbbff7df7f73f3429f909bd1e7db5e +dist/2024-10-17/rust-std-1.82.0-thumbv7neon-linux-androideabi.tar.gz=3ee6a219bdc39bf586d4a7d25a508674e878698aa03352a7d913b9c36280091e +dist/2024-10-17/rust-std-1.82.0-thumbv7neon-linux-androideabi.tar.xz=b33a50f5489aa84008282fae1e1cfee0851e43bfb63b0f703b16f9f711d9823d +dist/2024-10-17/rust-std-1.82.0-thumbv7neon-unknown-linux-gnueabihf.tar.gz=c940d08d695b9e72ed90efc727d8ef9e8b69aad5332e3270191974a33b1450ab +dist/2024-10-17/rust-std-1.82.0-thumbv7neon-unknown-linux-gnueabihf.tar.xz=c42728bf0c927873e1030091f16b88e21389046dabffd5927d05864e68f9daea +dist/2024-10-17/rust-std-1.82.0-thumbv8m.base-none-eabi.tar.gz=76629217823a505a25873593f700f66babf7ba669c0d7f2410428a2a2a688a31 +dist/2024-10-17/rust-std-1.82.0-thumbv8m.base-none-eabi.tar.xz=897c03e40b6dfc1e07a1033fd696e2a223b35aec1b99535ad024ae4c838d5c73 +dist/2024-10-17/rust-std-1.82.0-thumbv8m.main-none-eabi.tar.gz=50a3cdbc32b5b7e4acb200469e8365087301ec24414ae4aebc1f5ec90bdd54ae +dist/2024-10-17/rust-std-1.82.0-thumbv8m.main-none-eabi.tar.xz=60ea281d351e9998de293e5ac4678e28194e64d328fe6246d5c3e9b5731905e2 +dist/2024-10-17/rust-std-1.82.0-thumbv8m.main-none-eabihf.tar.gz=0caef862e86023fec0bd6f137688b61b3316e3d00da9c108b5c8da438bf4750d +dist/2024-10-17/rust-std-1.82.0-thumbv8m.main-none-eabihf.tar.xz=ff3bb4ccacd48c2de26dc8538e4d48756fce153d5464b8a0d7871480ea742cdd +dist/2024-10-17/rust-std-1.82.0-wasm32-unknown-emscripten.tar.gz=b61443ca7dd871d92c942aafae677e0ce689b3ac835ab0c7bb101e021132fbb5 +dist/2024-10-17/rust-std-1.82.0-wasm32-unknown-emscripten.tar.xz=42d6653edbf53f297bd1806384c37fa492c1dacdb94f437342cb0fbdc3614636 +dist/2024-10-17/rust-std-1.82.0-wasm32-unknown-unknown.tar.gz=c0b7be8188c1539b0508e6f64c58589775674cba5f8fe997f731d399431258f1 +dist/2024-10-17/rust-std-1.82.0-wasm32-unknown-unknown.tar.xz=6b4593a0f9d3d031e3da6d3aeac1beb78dc86ec866a1e07a7a56fc2acc10fbb5 +dist/2024-10-17/rust-std-1.82.0-wasm32-wasi.tar.gz=9ee7b61555d4b82a5b4e67d97a18b463704bdba242d83260804724308e0a9dbd +dist/2024-10-17/rust-std-1.82.0-wasm32-wasi.tar.xz=93d0ecaaebde79f7babc922e606fdb19e061fdfaccb2239191ea7fbfba33b985 +dist/2024-10-17/rust-std-1.82.0-wasm32-wasip1.tar.gz=41cce791e0b2e27838f9ef09707605bb2d4571293fc0e157cd260a0adc90a628 +dist/2024-10-17/rust-std-1.82.0-wasm32-wasip1.tar.xz=13b64a23d3f3e44dd74633f882024d7f25f0fceb5271b8f6822b2d5a1584d7a8 +dist/2024-10-17/rust-std-1.82.0-wasm32-wasip1-threads.tar.gz=b2173e51fde48629919882cd8e2fd19dbb3e723faac9e6b4d9d3a9479c45114a +dist/2024-10-17/rust-std-1.82.0-wasm32-wasip1-threads.tar.xz=891bc63667994f39fad679b10784f12b712b583f086560ca41ee677dfd99ff47 +dist/2024-10-17/rust-std-1.82.0-wasm32-wasip2.tar.gz=5ee71ee1909e1bd960977b3f2c0bc25e77aae5c447bbc6802a19495f7f30538f +dist/2024-10-17/rust-std-1.82.0-wasm32-wasip2.tar.xz=07de7cfa27698e7ccb5d2d18f0b22a4bf29bcfa8527b2c0bc7755d49480f9706 +dist/2024-10-17/rust-std-1.82.0-x86_64-apple-darwin.tar.gz=52084c8cdb34ca139a00f9f03f1a582d96b677e9f223a8d1aa31ae575a06cc16 +dist/2024-10-17/rust-std-1.82.0-x86_64-apple-darwin.tar.xz=5e35d52cb3bd414fbe39f747e0080398f22eba06514c630e3a01e63417b4ca35 +dist/2024-10-17/rust-std-1.82.0-x86_64-apple-ios.tar.gz=abbd7e5ff3d9ec9e1275a7210eef2d8e77333951d44ab204f01456ff1838fbbc +dist/2024-10-17/rust-std-1.82.0-x86_64-apple-ios.tar.xz=08d820161b41ac8fa0b8521c796741a123bb0258ef210d1d322590e848883005 +dist/2024-10-17/rust-std-1.82.0-x86_64-apple-ios-macabi.tar.gz=0a087bf5984e15d93bfa74030696ebf4f65188fc9b0a2eec88b68734b08aa62a +dist/2024-10-17/rust-std-1.82.0-x86_64-apple-ios-macabi.tar.xz=599369ac9dd08f61b9da0bb08b332c8c4aaec025fc81f63f315a7e4a00dc79fb +dist/2024-10-17/rust-std-1.82.0-x86_64-fortanix-unknown-sgx.tar.gz=223cb067245b6b965c8015c20851cb3c9e241649b68749ebd6650cf253664045 +dist/2024-10-17/rust-std-1.82.0-x86_64-fortanix-unknown-sgx.tar.xz=bf826838661f509b845196dffe38634e5f7730fb4f5d4b2423575d87baae41d6 +dist/2024-10-17/rust-std-1.82.0-x86_64-linux-android.tar.gz=8cecd2b17ba6eab1d5ecaada0fbf0fa2a158b8e8e69ccf80cffb8753f6b83239 +dist/2024-10-17/rust-std-1.82.0-x86_64-linux-android.tar.xz=b962df8c8e355e7797dfbbc0e7019151975aef6430cfa0fdad4fe65fbd965ec7 +dist/2024-10-17/rust-std-1.82.0-x86_64-pc-solaris.tar.gz=dcedce4abc9195f3b008a2be4c9c322b1fee6f4e4f598592740fda54da4c4e9c +dist/2024-10-17/rust-std-1.82.0-x86_64-pc-solaris.tar.xz=6c6eb567c36eb978fb473ce528774347a929c4a2fa51ca421c1398b35eff10c3 +dist/2024-10-17/rust-std-1.82.0-x86_64-pc-windows-gnu.tar.gz=32d42270b114c9341e5bc9b1d24f336024889ddd32a7d22e4700cc3c45fe9d3d +dist/2024-10-17/rust-std-1.82.0-x86_64-pc-windows-gnu.tar.xz=37435bd117db952bb83f578b7dd56e468c012b49e20c41a75eb91496c0b486ca +dist/2024-10-17/rust-std-1.82.0-x86_64-pc-windows-gnullvm.tar.gz=0a3c988ddf48108f484ad13132bbc8e112f3da984b7d5df499b39c6c47adcca1 +dist/2024-10-17/rust-std-1.82.0-x86_64-pc-windows-gnullvm.tar.xz=157d2060e30c499efedf83e6da34692bd69b501be95b0bfc124ae3356a4ac4c1 +dist/2024-10-17/rust-std-1.82.0-x86_64-pc-windows-msvc.tar.gz=e579f3ac4c546e68b4decffa64f2e9a98fe32a373fd5cc89b0449ca57528b1b8 +dist/2024-10-17/rust-std-1.82.0-x86_64-pc-windows-msvc.tar.xz=83d33c2d7788a0251dd43366e8080f5d4f12419a320b0c9ae74a9a77d3918112 +dist/2024-10-17/rust-std-1.82.0-x86_64-unknown-freebsd.tar.gz=be1acaf3c2f15d42b05b1f032db5ac3b11a0ac5a91c0efef26f2d8135d68a829 +dist/2024-10-17/rust-std-1.82.0-x86_64-unknown-freebsd.tar.xz=3c69d7c99288fbcb65428dcb0aebfb0bf9b246aac94511986ebda4befa0bd037 +dist/2024-10-17/rust-std-1.82.0-x86_64-unknown-fuchsia.tar.gz=28629d0872df32e39d29f431a1d7b576ec4efa1e0eed29989e81caa8047b016d +dist/2024-10-17/rust-std-1.82.0-x86_64-unknown-fuchsia.tar.xz=4ba2c757ebbe3b1b3696c152a6984b827f08d68d751869f4de98bb235e0e0176 +dist/2024-10-17/rust-std-1.82.0-x86_64-unknown-illumos.tar.gz=827bea0f115c1f8ea350cc34806fd8893ca980f0cb53d622b378c3e81501980a +dist/2024-10-17/rust-std-1.82.0-x86_64-unknown-illumos.tar.xz=a80214f13cdaab65c5bea23a7f3255619564af3c58c645544a5b6a1778e9970f +dist/2024-10-17/rust-std-1.82.0-x86_64-unknown-linux-gnu.tar.gz=e7e808b8745298369fa3bbc3c0b7af9ca0fb995661bd684a7022d14bc9ae0057 +dist/2024-10-17/rust-std-1.82.0-x86_64-unknown-linux-gnu.tar.xz=2eca3d36f7928f877c334909f35fe202fbcecce109ccf3b439284c2cb7849594 +dist/2024-10-17/rust-std-1.82.0-x86_64-unknown-linux-gnux32.tar.gz=ddb625204d36acea79929884c2d5ff3b082d2a328144e18cbd1d229995fb118e +dist/2024-10-17/rust-std-1.82.0-x86_64-unknown-linux-gnux32.tar.xz=22757c57d36d431ba7fc6e02ec1c020fec4ce0043f91ac1772712ac4ceda0497 +dist/2024-10-17/rust-std-1.82.0-x86_64-unknown-linux-musl.tar.gz=92170a6423a606948118d9500febc234dac83c567eccfeeb75307c77d848a529 +dist/2024-10-17/rust-std-1.82.0-x86_64-unknown-linux-musl.tar.xz=1c99a4c81f51b687ba55746c7d3f19b5b860fe4eff604d3c7d803e08c9cc89bb +dist/2024-10-17/rust-std-1.82.0-x86_64-unknown-linux-ohos.tar.gz=130f540afdd2772fd7f34f851761fe03ef1ffecd1cba8e6f66436b40991f7768 +dist/2024-10-17/rust-std-1.82.0-x86_64-unknown-linux-ohos.tar.xz=1ceaa2bb1de6a91e19893d97c084085fda4bb21a31c842ff88080a3e0fe77371 +dist/2024-10-17/rust-std-1.82.0-x86_64-unknown-netbsd.tar.gz=406bfd06f1883e0e19c656968d0cea321efc255e0bac2bdf02b08c1f45662bf8 +dist/2024-10-17/rust-std-1.82.0-x86_64-unknown-netbsd.tar.xz=bd604d9e0e6c763b506d819367dbe6e8cb92aebc454b9d6f1b2f769edba50578 +dist/2024-10-17/rust-std-1.82.0-x86_64-unknown-none.tar.gz=a642804f0024bef25627f11888d73092e275fa0e2a327dc013d63f52e87002a5 +dist/2024-10-17/rust-std-1.82.0-x86_64-unknown-none.tar.xz=f38d1f9c15fb5be67f0a313c1fad3d97cb4c65694f6a516cc6d39f2bd623f781 +dist/2024-10-17/rust-std-1.82.0-x86_64-unknown-redox.tar.gz=62ca780bacca396cc2593393d17661f431295d51a30e76e03108abb0a33084fe +dist/2024-10-17/rust-std-1.82.0-x86_64-unknown-redox.tar.xz=579594f82c412b06cc83c0c7cec1cdb2735951007f8cef939c8b9cbb3b22f4d7 +dist/2024-10-17/rust-std-1.82.0-x86_64-unknown-uefi.tar.gz=8afe8c1984db09e4791f1a5f6682c418d2fcffd8947c3a1c11a30ac113cae2df +dist/2024-10-17/rust-std-1.82.0-x86_64-unknown-uefi.tar.xz=171f5ca70dcf638dfdfe68364ab60763213a07a3227200d0d1cd920726fa586f +dist/2024-10-17/cargo-1.82.0-aarch64-apple-darwin.tar.gz=9cbe6badf70899297fb605cf361c1c07ea17cba58ddccb86c0967b1733e4b8f7 +dist/2024-10-17/cargo-1.82.0-aarch64-apple-darwin.tar.xz=66b9acc4629a21896ebd96076016263461567b8faf4eb0b76d0a72614790f29a +dist/2024-10-17/cargo-1.82.0-aarch64-pc-windows-msvc.tar.gz=3355fc89c9f00abf0cc28ff38cce3d478d07210ebb74d4c04c10a2a1ec3a3a4e +dist/2024-10-17/cargo-1.82.0-aarch64-pc-windows-msvc.tar.xz=d49a921b458a5837c8135c186cc6503480da9b90a8a3e9b335d1cb58251bda83 +dist/2024-10-17/cargo-1.82.0-aarch64-unknown-linux-gnu.tar.gz=8bb600421fe7fa98bf1808332ced563c8d9e1f27d6cbe6240eed3e6eea9ac2e7 +dist/2024-10-17/cargo-1.82.0-aarch64-unknown-linux-gnu.tar.xz=05c0d904a82cddb8a00b0bbdd276ad7e24dea62a7b6c380413ab1e5a4ed70a56 +dist/2024-10-17/cargo-1.82.0-aarch64-unknown-linux-musl.tar.gz=51a4d143bd480b3f16877c473efc2d84edc7dabf213086b2266c6edc5312582e +dist/2024-10-17/cargo-1.82.0-aarch64-unknown-linux-musl.tar.xz=2a9185236614bfa3f5ede8a09f1176381be26d960a701c770d902ef5e15d2bb7 +dist/2024-10-17/cargo-1.82.0-arm-unknown-linux-gnueabi.tar.gz=6fdd084d7cc52e8f2fb7922bbc14847431227514b9258f0759903f40c4a5acde +dist/2024-10-17/cargo-1.82.0-arm-unknown-linux-gnueabi.tar.xz=cebea8ce24a1ae47ef843a84570e0fba657635825b80f7f30c4461eea0a13fba +dist/2024-10-17/cargo-1.82.0-arm-unknown-linux-gnueabihf.tar.gz=9fb4c48e2e5c364a17f58fbc974924957c5bf784c4f835940f2e2d251149c4da +dist/2024-10-17/cargo-1.82.0-arm-unknown-linux-gnueabihf.tar.xz=eb98ac225f08ebd50eaed439eca687ba074344bd50ae7d95fff9a07a7ccc0899 +dist/2024-10-17/cargo-1.82.0-armv7-unknown-linux-gnueabihf.tar.gz=0f835d6e54624af1ffc23a4cc5492ee82873436b86ec3d0d52344c32dc9d14bd +dist/2024-10-17/cargo-1.82.0-armv7-unknown-linux-gnueabihf.tar.xz=fe8e24fa680c1a7db26824267103d1f552ee97acbed9e3a5eea73369e8818aeb +dist/2024-10-17/cargo-1.82.0-i686-pc-windows-gnu.tar.gz=098a8a0a610fbfe254ae66fe09289725303749b5c2d42b58211dcab7751605ae +dist/2024-10-17/cargo-1.82.0-i686-pc-windows-gnu.tar.xz=5678c0ee55c8e009deb355359921b0e912ab11b11f3bfd05bc858343ded06794 +dist/2024-10-17/cargo-1.82.0-i686-pc-windows-msvc.tar.gz=0a2ecada238fb68af1fb13f449f360c7bcabb09ff5e24f601819a66afab60cfb +dist/2024-10-17/cargo-1.82.0-i686-pc-windows-msvc.tar.xz=e11c4094786c59770747766cdd9fc86beb7c755d033b3264c54951f94c14abfa +dist/2024-10-17/cargo-1.82.0-i686-unknown-linux-gnu.tar.gz=5ebecd4a81f54ed9aaa3d287e01497dd86ce80bfbd4b9c81ba506ae249323b4e +dist/2024-10-17/cargo-1.82.0-i686-unknown-linux-gnu.tar.xz=1cf5bae93e9724f50f1a20a752f05870565e0ce83baa157aad632aa162fd97d5 +dist/2024-10-17/cargo-1.82.0-loongarch64-unknown-linux-gnu.tar.gz=c432a96b72e018a5f6b868d4395e1fde1377677cd1b786077c5461d6c774edfd +dist/2024-10-17/cargo-1.82.0-loongarch64-unknown-linux-gnu.tar.xz=01709e6d5b16e972e6c5e826a36331c645766ecda8f0aa48559f20c0d1129f44 +dist/2024-10-17/cargo-1.82.0-loongarch64-unknown-linux-musl.tar.gz=5af7332b3ab57fae3c082deea9bf51d5d47ae33458cf3f51886c757798ef7a9c +dist/2024-10-17/cargo-1.82.0-loongarch64-unknown-linux-musl.tar.xz=f8fb0b097edb2ea88acca7616a7a74e8bab4841e024e5efaeb53bcf6075bab9c +dist/2024-10-17/cargo-1.82.0-powerpc-unknown-linux-gnu.tar.gz=26a5340b4b3af173c0638e06d805c1615ae3cb5d4f6ee1bcd47c448de6a3c98b +dist/2024-10-17/cargo-1.82.0-powerpc-unknown-linux-gnu.tar.xz=7c11f69eb52c6e26cd8a33daeae7d630b6af49de30c1af16f4e998ca25a48bfd +dist/2024-10-17/cargo-1.82.0-powerpc64-unknown-linux-gnu.tar.gz=e72ef738b0144cfcb689f344476c563eaded6ee221686385a54e0af765a285ed +dist/2024-10-17/cargo-1.82.0-powerpc64-unknown-linux-gnu.tar.xz=94d828f3cbd848f15ec72e904bccd904a7fac0cd88d6afecfc472e48da032cb2 +dist/2024-10-17/cargo-1.82.0-powerpc64le-unknown-linux-gnu.tar.gz=5e4242cbbb6a985ac65f425f290d35243e34e4c740904d7467185e68124f31c6 +dist/2024-10-17/cargo-1.82.0-powerpc64le-unknown-linux-gnu.tar.xz=ce5918e9c1a41b9e9a1b3e15f6525ddc01df06d9cea63d574dc59e8a401c1b67 +dist/2024-10-17/cargo-1.82.0-riscv64gc-unknown-linux-gnu.tar.gz=94cf4555fe88f93bbd94b51b2a583ad3085c1a42bab1fe669e508af5bd4ac019 +dist/2024-10-17/cargo-1.82.0-riscv64gc-unknown-linux-gnu.tar.xz=4779732566542099491c35a9f4342361bb8366e76c7d37ade0b5b7ae6f470df3 +dist/2024-10-17/cargo-1.82.0-s390x-unknown-linux-gnu.tar.gz=f63b26a50ec2ed4c0cb0383dc4c4d2f18d426b76557a5504f8c8a648d0c1431e +dist/2024-10-17/cargo-1.82.0-s390x-unknown-linux-gnu.tar.xz=55d95ce07117430b92d1153e5b1ff40222687bd344872260e0a19ecf7b4c28a2 +dist/2024-10-17/cargo-1.82.0-x86_64-apple-darwin.tar.gz=6cdf3228c074a24ef74ed000c46a20521f083199ce0223d0a34365744a9db9a5 +dist/2024-10-17/cargo-1.82.0-x86_64-apple-darwin.tar.xz=29c43175bcdff3e21f82561ca930f80661136b9aeffbfa6914667992362caad8 +dist/2024-10-17/cargo-1.82.0-x86_64-pc-windows-gnu.tar.gz=8c4d15fcd6acc052cc48442024e9adb4b454928f6444e29735e28d4743b092ea +dist/2024-10-17/cargo-1.82.0-x86_64-pc-windows-gnu.tar.xz=81df190acb5297ce468457c6443bc57e2eb3bedc5886ee16139a6b9bfca4bd68 +dist/2024-10-17/cargo-1.82.0-x86_64-pc-windows-msvc.tar.gz=c7e0aa511aca8ee0e410dafbb06b4a3724fc42580f8c58dfc2a62ebc8bcc95d6 +dist/2024-10-17/cargo-1.82.0-x86_64-pc-windows-msvc.tar.xz=338005e213796d734c5665ed8a7418a1786b3b9a23590bc461a66ba76cd343fb +dist/2024-10-17/cargo-1.82.0-x86_64-unknown-freebsd.tar.gz=fb9968172e3855a3e5859ab57fd4170979cd343f9ef287d1a463f1ca40ea6f0d +dist/2024-10-17/cargo-1.82.0-x86_64-unknown-freebsd.tar.xz=3860a3435dd02abd91847d6a3ec40b79a9faff5208e41d04349b1de52dd63496 +dist/2024-10-17/cargo-1.82.0-x86_64-unknown-illumos.tar.gz=8a6c7f17192b416177fcbaf55435446ced577a3c1369182afe4d93e8aecc345b +dist/2024-10-17/cargo-1.82.0-x86_64-unknown-illumos.tar.xz=65e13c3c24b1593dfd50c9242eac8b6cf03fc094e3736e6d8798611c06b35607 +dist/2024-10-17/cargo-1.82.0-x86_64-unknown-linux-gnu.tar.gz=45594e7c01a27c4d9c128852735b84c80439fe1a07cffb664944e8a1036fd9f0 +dist/2024-10-17/cargo-1.82.0-x86_64-unknown-linux-gnu.tar.xz=97aeae783874a932c4500f4d36473297945edf6294d63871784217d608718e70 +dist/2024-10-17/cargo-1.82.0-x86_64-unknown-linux-musl.tar.gz=eb8136de2f6ff8c0a367fa68b4888cd017e92df89ece3afa5e7fd35d3d01c723 +dist/2024-10-17/cargo-1.82.0-x86_64-unknown-linux-musl.tar.xz=a66b3129cb483d55188742769bf8282d9546630f2e25434ff233b22bbec5009e +dist/2024-10-17/cargo-1.82.0-x86_64-unknown-netbsd.tar.gz=5fabc431dad66b259ba020630cc23ad96cc59fec07a9e261132c55900ad2dce2 +dist/2024-10-17/cargo-1.82.0-x86_64-unknown-netbsd.tar.xz=b5f24d9c61e3f6d18b843ebdf36a6218ff63e7a46e91d37c472e673f8711dab6 +dist/2024-10-17/clippy-1.82.0-aarch64-apple-darwin.tar.gz=0508639c3b7d9c07739b809f83196cca27ec5f02edaa97137e4d9ec0d1d6533f +dist/2024-10-17/clippy-1.82.0-aarch64-apple-darwin.tar.xz=bd1ba77f237df9e9dac704d5195281e0baec4509facd347ff716d793b131bbaa +dist/2024-10-17/clippy-1.82.0-aarch64-pc-windows-msvc.tar.gz=e9bedbab2307227853cd7f60762de3964491454350e736b100271cfc0fff1729 +dist/2024-10-17/clippy-1.82.0-aarch64-pc-windows-msvc.tar.xz=4a0ed91d370cc8266d99456db2f1aed882c76f61f9b832ca804490ff91f7fc8b +dist/2024-10-17/clippy-1.82.0-aarch64-unknown-linux-gnu.tar.gz=0691e12a19f1cd0e45e586c16286598f062ed110c2432a12cb203d5a936cf8bc +dist/2024-10-17/clippy-1.82.0-aarch64-unknown-linux-gnu.tar.xz=1e01808028b67a49f57925ea72b8a2155fbec346cd694d951577c63312ba9217 +dist/2024-10-17/clippy-1.82.0-aarch64-unknown-linux-musl.tar.gz=bb623b977333572540c2d022ae1ce3a0cbd82f2824274c63bc5966be61130cf1 +dist/2024-10-17/clippy-1.82.0-aarch64-unknown-linux-musl.tar.xz=1b3d137f6c33df944393414cd10b8b865f1cca5a71d4535a2b56e3c3cca140aa +dist/2024-10-17/clippy-1.82.0-arm-unknown-linux-gnueabi.tar.gz=a9465a6f294c1e78f9aebcf9d0c193a45be7558a17e31d892fbe6d9943de76cb +dist/2024-10-17/clippy-1.82.0-arm-unknown-linux-gnueabi.tar.xz=6dee9cb004568d40ddf67c6d602bbeb990e0e4bc1f93d07b8c7df836a4e01fea +dist/2024-10-17/clippy-1.82.0-arm-unknown-linux-gnueabihf.tar.gz=f62368a9c40b7d61834db454b342c9f032cf8144dbe47112fdf9781ec13b1bbb +dist/2024-10-17/clippy-1.82.0-arm-unknown-linux-gnueabihf.tar.xz=9a6196b83cf298fa461584bdc1904ee32a57be5edf2f0d5c65d617aa2650ab7d +dist/2024-10-17/clippy-1.82.0-armv7-unknown-linux-gnueabihf.tar.gz=8d6197a820e9271b1d1005e06d2cb9206f54ba2fee974977bad02a51ac497b20 +dist/2024-10-17/clippy-1.82.0-armv7-unknown-linux-gnueabihf.tar.xz=bd2c3db2fd9b42b7a15cc625df2c8d12971d8b9e5a83f9ecf86e6e850eef118f +dist/2024-10-17/clippy-1.82.0-i686-pc-windows-gnu.tar.gz=10bb2be0e2f6477aad1538c443c7898e36df8459af0648d101f27a874a9ce762 +dist/2024-10-17/clippy-1.82.0-i686-pc-windows-gnu.tar.xz=b9d16616d27349d7781b483bcd6cf795b30d75797d27c9533011fe30a155f644 +dist/2024-10-17/clippy-1.82.0-i686-pc-windows-msvc.tar.gz=81020effcd1433845a32d54a1dacd2dad3dbc663152f0c5ec44c444cc0aee4b1 +dist/2024-10-17/clippy-1.82.0-i686-pc-windows-msvc.tar.xz=feb921088ec3cd9e799d5c8fe6c727f9f64282fe62aef0775a9abfa81e693f4a +dist/2024-10-17/clippy-1.82.0-i686-unknown-linux-gnu.tar.gz=e6735c6bdcea30f527a761f501db7447b8cccf2c89a046b0104f6882d0e0b7c1 +dist/2024-10-17/clippy-1.82.0-i686-unknown-linux-gnu.tar.xz=a4c20f20c8e53747e00948f90d74380ae890c1836a067d504eca540c6a60157f +dist/2024-10-17/clippy-1.82.0-loongarch64-unknown-linux-gnu.tar.gz=c966ca4a9114790bd485c384a595e71f58f6aaa36412d5305661baeebc6e0599 +dist/2024-10-17/clippy-1.82.0-loongarch64-unknown-linux-gnu.tar.xz=ddbd18682a7fa0794d3bf159ba5cc5aee8c7bd6860d2edd8c9f4591753b5f05c +dist/2024-10-17/clippy-1.82.0-loongarch64-unknown-linux-musl.tar.gz=2097450601353ec0d53710089faad759b5db7b030586c857844a8c344b6bd167 +dist/2024-10-17/clippy-1.82.0-loongarch64-unknown-linux-musl.tar.xz=52241ec13c61590fb1189e209551c61cb30371d00716e5ea4116668eb0650a3d +dist/2024-10-17/clippy-1.82.0-powerpc-unknown-linux-gnu.tar.gz=25898f3caf8982d1b5ee6f43ce70cd79bd918eb0aed5618e027367e765772a63 +dist/2024-10-17/clippy-1.82.0-powerpc-unknown-linux-gnu.tar.xz=a33f459a5cc13573e4ed73bd5667bba4bdf658e30b629f36a221eb5249d4acc6 +dist/2024-10-17/clippy-1.82.0-powerpc64-unknown-linux-gnu.tar.gz=3586985f770947b70b67ecaa6a17d139ea51294fbe92d067ef542fd849518ccf +dist/2024-10-17/clippy-1.82.0-powerpc64-unknown-linux-gnu.tar.xz=c849be4677f42dc9439ac2458ca3964b69a2d6621e57f979151e7b59de22d895 +dist/2024-10-17/clippy-1.82.0-powerpc64le-unknown-linux-gnu.tar.gz=8de846466f9d29d67d60d5fdfb1f58bab530e98819ede28ff85d6ff3de6d6d8f +dist/2024-10-17/clippy-1.82.0-powerpc64le-unknown-linux-gnu.tar.xz=a633c961cc9225c5ec1af6f153e33fd103057c9ebc66eb80f388687f34215fbf +dist/2024-10-17/clippy-1.82.0-riscv64gc-unknown-linux-gnu.tar.gz=872d1a1d4e242e25d7c2a950d91957358f62e8dcdd43106a7b87f72a0925fdee +dist/2024-10-17/clippy-1.82.0-riscv64gc-unknown-linux-gnu.tar.xz=1399034c20e3037288cd659359e0a9eeb1d8a125488bbea28bbe146792a18d1a +dist/2024-10-17/clippy-1.82.0-s390x-unknown-linux-gnu.tar.gz=faf3782192058e957570c2bb253dc47f1fb894184a717c4e5bbb5fa8b552fb27 +dist/2024-10-17/clippy-1.82.0-s390x-unknown-linux-gnu.tar.xz=9c8c4b9d3a39383aa043a9a534478bd2ab6adf7a2a48c1d4d29864974f23005f +dist/2024-10-17/clippy-1.82.0-x86_64-apple-darwin.tar.gz=5f8c863c6075dbda96cff7cbbbfad144fe007bc634233b02d4b9dcc4eb60b4bd +dist/2024-10-17/clippy-1.82.0-x86_64-apple-darwin.tar.xz=77b7ced4e10d5e3a64fd4285d7c4fc011eb6b9d604ace9c0aa382691c803dbb2 +dist/2024-10-17/clippy-1.82.0-x86_64-pc-windows-gnu.tar.gz=aac6f5d8bed311fd52d8da41cb8fffb3f09add6f7257f49b2f82adca6f11441c +dist/2024-10-17/clippy-1.82.0-x86_64-pc-windows-gnu.tar.xz=719f739579c76e0098863096bd9d08c7f0ed59e8c46e16722945ef8a53d95863 +dist/2024-10-17/clippy-1.82.0-x86_64-pc-windows-msvc.tar.gz=9661b55f8cc2ed0510bbd252800aff2022c41a72704f8412808fac327d40fa40 +dist/2024-10-17/clippy-1.82.0-x86_64-pc-windows-msvc.tar.xz=adc63968b9998f345d9ccef5bb77af275be396d9000f784d08fb7339a38192df +dist/2024-10-17/clippy-1.82.0-x86_64-unknown-freebsd.tar.gz=44c9bd98a54e2e958e6e8844adfe6be2c92b78b70db534699c6ba757db77228c +dist/2024-10-17/clippy-1.82.0-x86_64-unknown-freebsd.tar.xz=2859cfe5bcc7f42a502a4aaea76606e22ef8d7f68852b3a980731afc59a6ae4c +dist/2024-10-17/clippy-1.82.0-x86_64-unknown-illumos.tar.gz=1cab4af7cc2bf9f688698e3044aa2a7863aa88099f6a9f4de77c232b2748a006 +dist/2024-10-17/clippy-1.82.0-x86_64-unknown-illumos.tar.xz=ed010aeadf64edc8f9b182d5da45b7f4f68779bd7d8470899fa5bf4d20837072 +dist/2024-10-17/clippy-1.82.0-x86_64-unknown-linux-gnu.tar.gz=e81e9e8dd3c514626a1a0c705ef5e037bcafcf9d79fa34f718d3043e8fd2987e +dist/2024-10-17/clippy-1.82.0-x86_64-unknown-linux-gnu.tar.xz=ea4fbf6fbd3686d4f6e2a77953e2d42a86ea31e49a5f79ec038762c413b15577 +dist/2024-10-17/clippy-1.82.0-x86_64-unknown-linux-musl.tar.gz=bd1a26e7fc93b8edfd42b01ba8eff5359e8b8cfa10ce288ccd8dba2785cfb63e +dist/2024-10-17/clippy-1.82.0-x86_64-unknown-linux-musl.tar.xz=292e0ccf9186716fac65c2d2ccbdd1392aa6365f9a6b94e06e5b05987051eaa9 +dist/2024-10-17/clippy-1.82.0-x86_64-unknown-netbsd.tar.gz=19bb69f36d863149199042f312b8ecda3c6148594649ab6ccd96e58c1da526bc +dist/2024-10-17/clippy-1.82.0-x86_64-unknown-netbsd.tar.xz=d4dee88e1b92214bdb5915b5559dddaf61e57b0cd9604b53b1c7d1f3615d2245 \ No newline at end of file From 601863bf305f4db04c0a6b9ae7434a84d2fd8903 Mon Sep 17 00:00:00 2001 From: Philipp Krones Date: Tue, 15 Oct 2024 17:27:44 +0200 Subject: [PATCH 2157/2194] Move `too_long_first_doc_paragraph` to `nursery` (cherry picked from commit a365aebdf03872722b8c78bdeb62c43851f0c72f) --- src/tools/clippy/clippy_lints/src/doc/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/clippy/clippy_lints/src/doc/mod.rs b/src/tools/clippy/clippy_lints/src/doc/mod.rs index e090644ae4410..89c6a4e08dc44 100644 --- a/src/tools/clippy/clippy_lints/src/doc/mod.rs +++ b/src/tools/clippy/clippy_lints/src/doc/mod.rs @@ -452,7 +452,7 @@ declare_clippy_lint! { /// ``` #[clippy::version = "1.82.0"] pub TOO_LONG_FIRST_DOC_PARAGRAPH, - style, + nursery, "ensure that the first line of a documentation paragraph isn't too long" } From d04ae764ccdd8a2883991f2c60df4cbe75bc1e3f Mon Sep 17 00:00:00 2001 From: Urgau Date: Sun, 13 Oct 2024 18:13:30 +0200 Subject: [PATCH 2158/2194] Also use outermost const-anon for impl items in `non_local_defs` lint (cherry picked from commit b5e91a00c89a065f618693873ad7074a13ad6b90) --- compiler/rustc_lint/src/non_local_def.rs | 10 +++++++--- .../convoluted-locals-131474-with-mods.rs | 11 +++++++++++ .../lint/non-local-defs/convoluted-locals-131474.rs | 9 +++++++++ 3 files changed, 27 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_lint/src/non_local_def.rs b/compiler/rustc_lint/src/non_local_def.rs index 6fecddb331947..3c31b879bd6aa 100644 --- a/compiler/rustc_lint/src/non_local_def.rs +++ b/compiler/rustc_lint/src/non_local_def.rs @@ -301,9 +301,13 @@ fn did_has_local_parent( return false; }; - peel_parent_while(tcx, parent_did, |tcx, did| tcx.def_kind(did) == DefKind::Mod) - .map(|parent_did| parent_did == impl_parent || Some(parent_did) == outermost_impl_parent) - .unwrap_or(false) + peel_parent_while(tcx, parent_did, |tcx, did| { + tcx.def_kind(did) == DefKind::Mod + || (tcx.def_kind(did) == DefKind::Const + && tcx.opt_item_name(did) == Some(kw::Underscore)) + }) + .map(|parent_did| parent_did == impl_parent || Some(parent_did) == outermost_impl_parent) + .unwrap_or(false) } /// Given a `DefId` checks if it satisfies `f` if it does check with it's parent and continue diff --git a/tests/ui/lint/non-local-defs/convoluted-locals-131474-with-mods.rs b/tests/ui/lint/non-local-defs/convoluted-locals-131474-with-mods.rs index cef0f0205e809..72fd056d461ad 100644 --- a/tests/ui/lint/non-local-defs/convoluted-locals-131474-with-mods.rs +++ b/tests/ui/lint/non-local-defs/convoluted-locals-131474-with-mods.rs @@ -31,4 +31,15 @@ const _: () = { }; }; +// https://github.com/rust-lang/rust/issues/131643 +const _: () = { + const _: () = { + impl tmp::InnerTest {} + }; + + mod tmp { + pub(super) struct InnerTest; + } +}; + fn main() {} diff --git a/tests/ui/lint/non-local-defs/convoluted-locals-131474.rs b/tests/ui/lint/non-local-defs/convoluted-locals-131474.rs index 4881723f13bce..8e738544a718f 100644 --- a/tests/ui/lint/non-local-defs/convoluted-locals-131474.rs +++ b/tests/ui/lint/non-local-defs/convoluted-locals-131474.rs @@ -21,4 +21,13 @@ const _: () = { }; }; +// https://github.com/rust-lang/rust/issues/131643 +const _: () = { + const _: () = { + impl InnerTest {} + }; + + struct InnerTest; +}; + fn main() {} From 367458018689ded3bdd480f84512728e574d8a06 Mon Sep 17 00:00:00 2001 From: Weihang Lo Date: Tue, 29 Oct 2024 18:29:46 -0400 Subject: [PATCH 2159/2194] Update cargo --- src/tools/cargo | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/cargo b/src/tools/cargo index 15fbd2f607d4d..5ffbef3211a8c 160000 --- a/src/tools/cargo +++ b/src/tools/cargo @@ -1 +1 @@ -Subproject commit 15fbd2f607d4defc87053b8b76bf5038f2483cf4 +Subproject commit 5ffbef3211a8c378857905775a15c5b32a174d3b From e0816c87aacd579e1f2a14168e5843e7a7ec5fe5 Mon Sep 17 00:00:00 2001 From: Jan Sommer Date: Thu, 17 Oct 2024 11:03:45 +0200 Subject: [PATCH 2160/2194] Bump libc to 0.2.161 (cherry picked from commit a09c54d4d34627444d4d1416930c11ffeebd0d2e) --- library/Cargo.lock | 6 +++--- library/std/Cargo.toml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/library/Cargo.lock b/library/Cargo.lock index 59b76d8d4427d..268367cd9c144 100644 --- a/library/Cargo.lock +++ b/library/Cargo.lock @@ -1,6 +1,6 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -version = 3 +version = 4 [[package]] name = "addr2line" @@ -158,9 +158,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.159" +version = "0.2.161" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "561d97a539a36e26a9a5fad1ea11a3039a67714694aaa379433e580854bc3dc5" +checksum = "8e9489c2807c139ffd9c1794f4af0ebe86a828db53ecdc7fea2111d0fed085d1" dependencies = [ "rustc-std-workspace-core", ] diff --git a/library/std/Cargo.toml b/library/std/Cargo.toml index f2669326065d5..5f8dcde189bcf 100644 --- a/library/std/Cargo.toml +++ b/library/std/Cargo.toml @@ -39,7 +39,7 @@ miniz_oxide = { version = "0.7.0", optional = true, default-features = false } addr2line = { version = "0.22.0", optional = true, default-features = false } [target.'cfg(not(all(windows, target_env = "msvc")))'.dependencies] -libc = { version = "0.2.156", default-features = false, features = [ +libc = { version = "0.2.161", default-features = false, features = [ 'rustc-dep-of-std', ], public = true } From 1766bc36f57794846519425248821fec601fe75a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=AE=B8=E6=9D=B0=E5=8F=8B=20Jieyou=20Xu=20=28Joe=29?= <39484203+jieyouxu@users.noreply.github.com> Date: Fri, 18 Oct 2024 10:12:11 +0800 Subject: [PATCH 2161/2194] Avoid shadowing user provided types or type aliases in `thread_local!` By using qualified imports, i.e. `$crate::...::LocalKey`. (cherry picked from commit 7b2320c3df9e57e8920a8eeec94e907e3d3e6347) --- .../std/src/sys/thread_local/native/mod.rs | 31 +++++++++---------- library/std/src/sys/thread_local/os.rs | 17 ++++++---- library/std/tests/thread.rs | 23 ++++++++++++++ 3 files changed, 49 insertions(+), 22 deletions(-) diff --git a/library/std/src/sys/thread_local/native/mod.rs b/library/std/src/sys/thread_local/native/mod.rs index f498dee0899f9..a5dffe3c45883 100644 --- a/library/std/src/sys/thread_local/native/mod.rs +++ b/library/std/src/sys/thread_local/native/mod.rs @@ -49,20 +49,21 @@ pub use lazy::Storage as LazyStorage; #[unstable(feature = "thread_local_internals", issue = "none")] #[rustc_macro_transparency = "semitransparent"] pub macro thread_local_inner { - // used to generate the `LocalKey` value for const-initialized thread locals + // NOTE: we cannot import `LocalKey`, `LazyStorage` or `EagerStorage` with a `use` because that + // can shadow user provided type or type alias with a matching name. Please update the shadowing + // test in `tests/thread.rs` if these types are renamed. + + // Used to generate the `LocalKey` value for const-initialized thread locals. (@key $t:ty, const $init:expr) => {{ const __INIT: $t = $init; unsafe { - use $crate::mem::needs_drop; - use $crate::thread::LocalKey; - use $crate::thread::local_impl::EagerStorage; - - LocalKey::new(const { - if needs_drop::<$t>() { + $crate::thread::LocalKey::new(const { + if $crate::mem::needs_drop::<$t>() { |_| { #[thread_local] - static VAL: EagerStorage<$t> = EagerStorage::new(__INIT); + static VAL: $crate::thread::local_impl::EagerStorage<$t> + = $crate::thread::local_impl::EagerStorage::new(__INIT); VAL.get() } } else { @@ -84,21 +85,19 @@ pub macro thread_local_inner { } unsafe { - use $crate::mem::needs_drop; - use $crate::thread::LocalKey; - use $crate::thread::local_impl::LazyStorage; - - LocalKey::new(const { - if needs_drop::<$t>() { + $crate::thread::LocalKey::new(const { + if $crate::mem::needs_drop::<$t>() { |init| { #[thread_local] - static VAL: LazyStorage<$t, ()> = LazyStorage::new(); + static VAL: $crate::thread::local_impl::LazyStorage<$t, ()> + = $crate::thread::local_impl::LazyStorage::new(); VAL.get_or_init(init, __init) } } else { |init| { #[thread_local] - static VAL: LazyStorage<$t, !> = LazyStorage::new(); + static VAL: $crate::thread::local_impl::LazyStorage<$t, !> + = $crate::thread::local_impl::LazyStorage::new(); VAL.get_or_init(init, __init) } } diff --git a/library/std/src/sys/thread_local/os.rs b/library/std/src/sys/thread_local/os.rs index 26ce3322a16e3..f5a2aaa6c6a3f 100644 --- a/library/std/src/sys/thread_local/os.rs +++ b/library/std/src/sys/thread_local/os.rs @@ -15,19 +15,24 @@ pub macro thread_local_inner { $crate::thread::local_impl::thread_local_inner!(@key $t, { const INIT_EXPR: $t = $init; INIT_EXPR }) }, - // used to generate the `LocalKey` value for `thread_local!` + // NOTE: we cannot import `Storage` or `LocalKey` with a `use` because that can shadow user + // provided type or type alias with a matching name. Please update the shadowing test in + // `tests/thread.rs` if these types are renamed. + + // used to generate the `LocalKey` value for `thread_local!`. (@key $t:ty, $init:expr) => {{ #[inline] fn __init() -> $t { $init } + // NOTE: this cannot import `LocalKey` or `Storage` with a `use` because that can shadow + // user provided type or type alias with a matching name. Please update the shadowing test + // in `tests/thread.rs` if these types are renamed. unsafe { - use $crate::thread::LocalKey; - use $crate::thread::local_impl::Storage; - // Inlining does not work on windows-gnu due to linking errors around // dllimports. See https://github.com/rust-lang/rust/issues/109797. - LocalKey::new(#[cfg_attr(windows, inline(never))] |init| { - static VAL: Storage<$t> = Storage::new(); + $crate::thread::LocalKey::new(#[cfg_attr(windows, inline(never))] |init| { + static VAL: $crate::thread::local_impl::Storage<$t> + = $crate::thread::local_impl::Storage::new(); VAL.get(init, __init) }) } diff --git a/library/std/tests/thread.rs b/library/std/tests/thread.rs index 83574176186a4..1bb17d149fa10 100644 --- a/library/std/tests/thread.rs +++ b/library/std/tests/thread.rs @@ -38,6 +38,29 @@ fn thread_local_containing_const_statements() { assert_eq!(REFCELL.take(), 1); } +#[test] +fn thread_local_hygeiene() { + // Previously `thread_local_inner!` had use imports for `LocalKey`, `Storage`, `EagerStorage` + // and `LazyStorage`. The use imports will shadow a user-provided type or type alias if the + // user-provided type or type alias has the same name. Make sure that this does not happen. See + // . + // + // NOTE: if the internal implementation details change (i.e. get renamed), this test should be + // updated. + + #![allow(dead_code)] + type LocalKey = (); + type Storage = (); + type LazyStorage = (); + type EagerStorage = (); + thread_local! { + static A: LocalKey = const { () }; + static B: Storage = const { () }; + static C: LazyStorage = const { () }; + static D: EagerStorage = const { () }; + } +} + #[test] // Include an ignore list on purpose, so that new platforms don't miss it #[cfg_attr( From 90a1f5f7896f4ce0e21b40e52553dd5cc0fa6316 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=AE=B8=E6=9D=B0=E5=8F=8B=20Jieyou=20Xu=20=28Joe=29?= <39484203+jieyouxu@users.noreply.github.com> Date: Wed, 30 Oct 2024 20:17:42 +0800 Subject: [PATCH 2162/2194] Add a regression test for #132353 To catch at least one pattern that was miscompiled. The test is a minimization of the MCVE reported in . (cherry picked from commit 4d8bda335e23b7ff10ff0c645c825a90fc2646bb) --- ...lone-canonicalization-miscompile-132353.rs | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 tests/ui/mir/clone-canonicalization-miscompile-132353.rs diff --git a/tests/ui/mir/clone-canonicalization-miscompile-132353.rs b/tests/ui/mir/clone-canonicalization-miscompile-132353.rs new file mode 100644 index 0000000000000..ba740c10f9060 --- /dev/null +++ b/tests/ui/mir/clone-canonicalization-miscompile-132353.rs @@ -0,0 +1,25 @@ +//! The mir-opt added in unfortunately seems to lead +//! to a miscompile (reported in , minimization +//! reproduced in this test file). +//@ revisions: release debug +// Note: it's not strictly cargo's release profile, but any non-zero opt-level was sufficient to +// reproduce the miscompile. +//@[release] compile-flags: -C opt-level=1 +//@[debug] compile-flags: -C opt-level=0 +//@ run-pass + +fn pop_min(mut score2head: Vec>) -> Option { + loop { + if let Some(col) = score2head[0] { + score2head[0] = None; + return Some(col); + } + } +} + +fn main() { + let min = pop_min(vec![Some(1)]); + println!("min: {:?}", min); + // panic happened on 1.83.0 beta in release mode but not debug mode. + let _ = min.unwrap(); +} From b5bc13a36741c9a5199eada4baf331ff7bdfcc05 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=AE=B8=E6=9D=B0=E5=8F=8B=20Jieyou=20Xu=20=28Joe=29?= <39484203+jieyouxu@users.noreply.github.com> Date: Wed, 30 Oct 2024 21:11:37 +0800 Subject: [PATCH 2163/2194] Mark `simplify_aggregate_to_copy` mir-opt as unsound Co-authored-by: DianQK (cherry picked from commit 10b8ba4ecb19ac2eb7be97a1a1eb1ffae9fec534) --- compiler/rustc_mir_transform/src/gvn.rs | 4 ++- tests/codegen/clone_as_copy.rs | 2 ++ tests/codegen/try_question_mark_nop.rs | 14 +++------ tests/mir-opt/gvn_clone.rs | 2 ++ .../mir-opt/gvn_clone.{impl#0}-clone.GVN.diff | 6 ++-- tests/mir-opt/gvn_copy_aggregate.rs | 2 ++ tests/mir-opt/pre-codegen/clone_as_copy.rs | 2 ++ ..._clone.{impl#0}-clone.PreCodegen.after.mir | 6 +++- .../try_identity.old.PreCodegen.after.mir | 8 ++--- ..._to_slice.PreCodegen.after.panic-abort.mir | 30 +++++++++++-------- ...to_slice.PreCodegen.after.panic-unwind.mir | 30 +++++++++++-------- 11 files changed, 63 insertions(+), 43 deletions(-) diff --git a/compiler/rustc_mir_transform/src/gvn.rs b/compiler/rustc_mir_transform/src/gvn.rs index daf868559bcae..de53ebfcd0ee2 100644 --- a/compiler/rustc_mir_transform/src/gvn.rs +++ b/compiler/rustc_mir_transform/src/gvn.rs @@ -1079,7 +1079,9 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { } } - if let AggregateTy::Def(_, _) = ty + // unsound: https://github.com/rust-lang/rust/issues/132353 + if tcx.sess.opts.unstable_opts.unsound_mir_opts + && let AggregateTy::Def(_, _) = ty && let Some(value) = self.simplify_aggregate_to_copy(rvalue, location, &fields, variant_index) { diff --git a/tests/codegen/clone_as_copy.rs b/tests/codegen/clone_as_copy.rs index 36a59ae56b72b..6ba198297e226 100644 --- a/tests/codegen/clone_as_copy.rs +++ b/tests/codegen/clone_as_copy.rs @@ -1,4 +1,6 @@ //@ revisions: DEBUGINFO NODEBUGINFO +//@ compile-flags: -Zunsound-mir-opts +// FIXME: see //@ compile-flags: -O -Cno-prepopulate-passes //@ [DEBUGINFO] compile-flags: -Cdebuginfo=full diff --git a/tests/codegen/try_question_mark_nop.rs b/tests/codegen/try_question_mark_nop.rs index 65167f5c5af97..bbab0d9eb1dbf 100644 --- a/tests/codegen/try_question_mark_nop.rs +++ b/tests/codegen/try_question_mark_nop.rs @@ -1,10 +1,7 @@ //@ compile-flags: -O -Z merge-functions=disabled --edition=2021 //@ only-x86_64 // FIXME: Remove the `min-llvm-version`. -//@ revisions: NINETEEN TWENTY -//@[NINETEEN] min-llvm-version: 19 -//@[NINETEEN] ignore-llvm-version: 20-99 -//@[TWENTY] min-llvm-version: 20 +//@ min-llvm-version: 19 #![crate_type = "lib"] #![feature(try_blocks)] @@ -16,12 +13,9 @@ use std::ptr::NonNull; #[no_mangle] pub fn option_nop_match_32(x: Option) -> Option { // CHECK: start: - // NINETEEN-NEXT: [[TRUNC:%.*]] = trunc nuw i32 %0 to i1 - // NINETEEN-NEXT: [[FIRST:%.*]] = select i1 [[TRUNC]], i32 %0 - // NINETEEN-NEXT: insertvalue { i32, i32 } poison, i32 [[FIRST]], 0 - // TWENTY-NEXT: insertvalue { i32, i32 } poison, i32 %0, 0 - // CHECK-NEXT: insertvalue { i32, i32 } - // CHECK-NEXT: ret { i32, i32 } + // CHECK-NEXT: [[REG1:%.*]] = insertvalue { i32, i32 } poison, i32 %0, 0 + // CHECK-NEXT: [[REG2:%.*]] = insertvalue { i32, i32 } [[REG1]], i32 %1, 1 + // CHECK-NEXT: ret { i32, i32 } [[REG2]] match x { Some(x) => Some(x), None => None, diff --git a/tests/mir-opt/gvn_clone.rs b/tests/mir-opt/gvn_clone.rs index 08938c0e1b427..c16b665fbd39c 100644 --- a/tests/mir-opt/gvn_clone.rs +++ b/tests/mir-opt/gvn_clone.rs @@ -1,3 +1,5 @@ +//@ compile-flags: -Zunsound-mir-opts +// FIXME: see //@ test-mir-pass: GVN //@ compile-flags: -Zmir-enable-passes=+InstSimplify-before-inline diff --git a/tests/mir-opt/gvn_clone.{impl#0}-clone.GVN.diff b/tests/mir-opt/gvn_clone.{impl#0}-clone.GVN.diff index 57b0980a0bd17..8d5991872e180 100644 --- a/tests/mir-opt/gvn_clone.{impl#0}-clone.GVN.diff +++ b/tests/mir-opt/gvn_clone.{impl#0}-clone.GVN.diff @@ -1,7 +1,7 @@ -- // MIR for `::clone` before GVN -+ // MIR for `::clone` after GVN +- // MIR for `::clone` before GVN ++ // MIR for `::clone` after GVN - fn ::clone(_1: &AllCopy) -> AllCopy { + fn ::clone(_1: &AllCopy) -> AllCopy { debug self => _1; let mut _0: AllCopy; let mut _2: i32; diff --git a/tests/mir-opt/gvn_copy_aggregate.rs b/tests/mir-opt/gvn_copy_aggregate.rs index c9473025a15f2..7c181d1ad3784 100644 --- a/tests/mir-opt/gvn_copy_aggregate.rs +++ b/tests/mir-opt/gvn_copy_aggregate.rs @@ -1,3 +1,5 @@ +//@ compile-flags: -Zunsound-mir-opts +// FIXME: see //@ compile-flags: -Cdebuginfo=full // Check if we have transformed the nested clone to the copy in the complete pipeline. diff --git a/tests/mir-opt/pre-codegen/no_inlined_clone.{impl#0}-clone.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/no_inlined_clone.{impl#0}-clone.PreCodegen.after.mir index 9020cf1ef37f2..62a9cd9131f0b 100644 --- a/tests/mir-opt/pre-codegen/no_inlined_clone.{impl#0}-clone.PreCodegen.after.mir +++ b/tests/mir-opt/pre-codegen/no_inlined_clone.{impl#0}-clone.PreCodegen.after.mir @@ -3,9 +3,13 @@ fn ::clone(_1: &Foo) -> Foo { debug self => _1; let mut _0: Foo; + let mut _2: i32; bb0: { - _0 = copy (*_1); + StorageLive(_2); + _2 = copy ((*_1).0: i32); + _0 = Foo { a: move _2 }; + StorageDead(_2); return; } } diff --git a/tests/mir-opt/pre-codegen/try_identity.old.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/try_identity.old.PreCodegen.after.mir index 889e80d26e1cc..ac485f485b1cc 100644 --- a/tests/mir-opt/pre-codegen/try_identity.old.PreCodegen.after.mir +++ b/tests/mir-opt/pre-codegen/try_identity.old.PreCodegen.after.mir @@ -19,14 +19,14 @@ fn old(_1: Result) -> Result { } bb1: { - _3 = copy ((_1 as Ok).0: T); - _0 = copy _1; + _3 = move ((_1 as Ok).0: T); + _0 = Result::::Ok(copy _3); goto -> bb3; } bb2: { - _4 = copy ((_1 as Err).0: E); - _0 = copy _1; + _4 = move ((_1 as Err).0: E); + _0 = Result::::Err(copy _4); goto -> bb3; } diff --git a/tests/mir-opt/pre-codegen/vec_deref.vec_deref_to_slice.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/vec_deref.vec_deref_to_slice.PreCodegen.after.panic-abort.mir index 4d964b0afb78c..c3091bd439576 100644 --- a/tests/mir-opt/pre-codegen/vec_deref.vec_deref_to_slice.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/vec_deref.vec_deref_to_slice.PreCodegen.after.panic-abort.mir @@ -7,7 +7,7 @@ fn vec_deref_to_slice(_1: &Vec) -> &[u8] { debug self => _1; scope 2 (inlined Vec::::as_slice) { debug self => _1; - let mut _6: usize; + let mut _7: usize; scope 3 (inlined Vec::::as_ptr) { debug self => _1; let mut _2: &alloc::raw_vec::RawVec; @@ -16,6 +16,7 @@ fn vec_deref_to_slice(_1: &Vec) -> &[u8] { let mut _3: &alloc::raw_vec::RawVecInner; scope 5 (inlined alloc::raw_vec::RawVecInner::ptr::) { debug self => _3; + let mut _6: std::ptr::NonNull; scope 6 (inlined alloc::raw_vec::RawVecInner::non_null::) { debug self => _3; let mut _4: std::ptr::NonNull; @@ -31,20 +32,20 @@ fn vec_deref_to_slice(_1: &Vec) -> &[u8] { } } scope 10 (inlined Unique::::as_non_null_ptr) { - debug ((self: Unique).0: std::ptr::NonNull) => _4; + debug ((self: Unique).0: std::ptr::NonNull) => _6; debug ((self: Unique).1: std::marker::PhantomData) => const PhantomData::; } } scope 11 (inlined NonNull::::as_ptr) { - debug self => _4; + debug self => _6; } } } } scope 12 (inlined std::slice::from_raw_parts::<'_, u8>) { debug data => _5; - debug len => _6; - let _7: *const [u8]; + debug len => _7; + let _8: *const [u8]; scope 13 (inlined core::ub_checks::check_language_ub) { scope 14 (inlined core::ub_checks::check_language_ub::runtime) { } @@ -55,10 +56,10 @@ fn vec_deref_to_slice(_1: &Vec) -> &[u8] { } scope 17 (inlined slice_from_raw_parts::) { debug data => _5; - debug len => _6; + debug len => _7; scope 18 (inlined std::ptr::from_raw_parts::<[u8], u8>) { debug data_pointer => _5; - debug metadata => _6; + debug metadata => _7; } } } @@ -70,17 +71,22 @@ fn vec_deref_to_slice(_1: &Vec) -> &[u8] { _2 = &((*_1).0: alloc::raw_vec::RawVec); StorageLive(_3); _3 = &(((*_1).0: alloc::raw_vec::RawVec).0: alloc::raw_vec::RawVecInner); + StorageLive(_6); + StorageLive(_4); _4 = copy (((((*_1).0: alloc::raw_vec::RawVec).0: alloc::raw_vec::RawVecInner).0: std::ptr::Unique).0: std::ptr::NonNull); _5 = copy (_4.0: *const u8); + _6 = NonNull:: { pointer: copy _5 }; + StorageDead(_4); + StorageDead(_6); StorageDead(_3); StorageDead(_2); - StorageLive(_6); - _6 = copy ((*_1).1: usize); StorageLive(_7); - _7 = *const [u8] from (copy _5, copy _6); - _0 = &(*_7); + _7 = copy ((*_1).1: usize); + StorageLive(_8); + _8 = *const [u8] from (copy _5, copy _7); + _0 = &(*_8); + StorageDead(_8); StorageDead(_7); - StorageDead(_6); return; } } diff --git a/tests/mir-opt/pre-codegen/vec_deref.vec_deref_to_slice.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/vec_deref.vec_deref_to_slice.PreCodegen.after.panic-unwind.mir index 4d964b0afb78c..c3091bd439576 100644 --- a/tests/mir-opt/pre-codegen/vec_deref.vec_deref_to_slice.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/vec_deref.vec_deref_to_slice.PreCodegen.after.panic-unwind.mir @@ -7,7 +7,7 @@ fn vec_deref_to_slice(_1: &Vec) -> &[u8] { debug self => _1; scope 2 (inlined Vec::::as_slice) { debug self => _1; - let mut _6: usize; + let mut _7: usize; scope 3 (inlined Vec::::as_ptr) { debug self => _1; let mut _2: &alloc::raw_vec::RawVec; @@ -16,6 +16,7 @@ fn vec_deref_to_slice(_1: &Vec) -> &[u8] { let mut _3: &alloc::raw_vec::RawVecInner; scope 5 (inlined alloc::raw_vec::RawVecInner::ptr::) { debug self => _3; + let mut _6: std::ptr::NonNull; scope 6 (inlined alloc::raw_vec::RawVecInner::non_null::) { debug self => _3; let mut _4: std::ptr::NonNull; @@ -31,20 +32,20 @@ fn vec_deref_to_slice(_1: &Vec) -> &[u8] { } } scope 10 (inlined Unique::::as_non_null_ptr) { - debug ((self: Unique).0: std::ptr::NonNull) => _4; + debug ((self: Unique).0: std::ptr::NonNull) => _6; debug ((self: Unique).1: std::marker::PhantomData) => const PhantomData::; } } scope 11 (inlined NonNull::::as_ptr) { - debug self => _4; + debug self => _6; } } } } scope 12 (inlined std::slice::from_raw_parts::<'_, u8>) { debug data => _5; - debug len => _6; - let _7: *const [u8]; + debug len => _7; + let _8: *const [u8]; scope 13 (inlined core::ub_checks::check_language_ub) { scope 14 (inlined core::ub_checks::check_language_ub::runtime) { } @@ -55,10 +56,10 @@ fn vec_deref_to_slice(_1: &Vec) -> &[u8] { } scope 17 (inlined slice_from_raw_parts::) { debug data => _5; - debug len => _6; + debug len => _7; scope 18 (inlined std::ptr::from_raw_parts::<[u8], u8>) { debug data_pointer => _5; - debug metadata => _6; + debug metadata => _7; } } } @@ -70,17 +71,22 @@ fn vec_deref_to_slice(_1: &Vec) -> &[u8] { _2 = &((*_1).0: alloc::raw_vec::RawVec); StorageLive(_3); _3 = &(((*_1).0: alloc::raw_vec::RawVec).0: alloc::raw_vec::RawVecInner); + StorageLive(_6); + StorageLive(_4); _4 = copy (((((*_1).0: alloc::raw_vec::RawVec).0: alloc::raw_vec::RawVecInner).0: std::ptr::Unique).0: std::ptr::NonNull); _5 = copy (_4.0: *const u8); + _6 = NonNull:: { pointer: copy _5 }; + StorageDead(_4); + StorageDead(_6); StorageDead(_3); StorageDead(_2); - StorageLive(_6); - _6 = copy ((*_1).1: usize); StorageLive(_7); - _7 = *const [u8] from (copy _5, copy _6); - _0 = &(*_7); + _7 = copy ((*_1).1: usize); + StorageLive(_8); + _8 = *const [u8] from (copy _5, copy _7); + _0 = &(*_8); + StorageDead(_8); StorageDead(_7); - StorageDead(_6); return; } } From 0f95b22c12bf01116622ffff58573a3220bd5528 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=AE=B8=E6=9D=B0=E5=8F=8B=20Jieyou=20Xu=20=28Joe=29?= <39484203+jieyouxu@users.noreply.github.com> Date: Wed, 30 Oct 2024 23:02:18 +0800 Subject: [PATCH 2164/2194] Add a mir-opt GVN test for #128299 Co-authored-by: DianQK (cherry picked from commit cfb4c05d77df4a6bcc53924eddb3a35102b65da9) --- ..._aggregate_to_copy_miscompile.foo.GVN.diff | 72 +++++++++++++++++++ .../simplify_aggregate_to_copy_miscompile.rs | 32 +++++++++ 2 files changed, 104 insertions(+) create mode 100644 tests/mir-opt/simplify_aggregate_to_copy_miscompile.foo.GVN.diff create mode 100644 tests/mir-opt/simplify_aggregate_to_copy_miscompile.rs diff --git a/tests/mir-opt/simplify_aggregate_to_copy_miscompile.foo.GVN.diff b/tests/mir-opt/simplify_aggregate_to_copy_miscompile.foo.GVN.diff new file mode 100644 index 0000000000000..22d4277ee4515 --- /dev/null +++ b/tests/mir-opt/simplify_aggregate_to_copy_miscompile.foo.GVN.diff @@ -0,0 +1,72 @@ +- // MIR for `foo` before GVN ++ // MIR for `foo` after GVN + + fn foo(_1: &mut Option) -> Option { + debug v => _1; + let mut _0: std::option::Option; + let mut _2: &std::option::Option; + let mut _3: &std::option::Option; + let _4: &&mut std::option::Option; + let mut _5: isize; + let mut _7: !; + let mut _8: std::option::Option; + let mut _9: i32; + let mut _10: !; + let mut _11: &mut std::option::Option; + scope 1 { + debug col => _6; + let _6: i32; + } + + bb0: { +- StorageLive(_2); ++ nop; + StorageLive(_3); + StorageLive(_4); + _4 = &_1; +- _11 = deref_copy (*_4); +- _3 = &(*_11); ++ _11 = copy _1; ++ _3 = &(*_1); + _2 = get(move _3) -> [return: bb1, unwind unreachable]; + } + + bb1: { + StorageDead(_3); + _5 = discriminant((*_2)); + switchInt(move _5) -> [1: bb2, otherwise: bb3]; + } + + bb2: { +- StorageLive(_6); ++ nop; + _6 = copy (((*_2) as Some).0: i32); + StorageLive(_8); +- _8 = Option::::None; +- (*_1) = move _8; ++ _8 = const Option::::None; ++ (*_1) = const Option::::None; + StorageDead(_8); + StorageLive(_9); + _9 = copy _6; +- _0 = Option::::Some(move _9); ++ _0 = copy (*_2); + StorageDead(_9); +- StorageDead(_6); ++ nop; + StorageDead(_4); +- StorageDead(_2); ++ nop; + return; + } + + bb3: { + StorageLive(_10); + unreachable; + } ++ } ++ ++ ALLOC0 (size: 8, align: 4) { ++ 00 00 00 00 __ __ __ __ │ ....░░░░ + } + diff --git a/tests/mir-opt/simplify_aggregate_to_copy_miscompile.rs b/tests/mir-opt/simplify_aggregate_to_copy_miscompile.rs new file mode 100644 index 0000000000000..47721b768be79 --- /dev/null +++ b/tests/mir-opt/simplify_aggregate_to_copy_miscompile.rs @@ -0,0 +1,32 @@ +//! The `simplify_aggregate_to_copy` mir-opt introduced in +//! caused a miscompile because the initial +//! implementation +//! +//! > introduce[d] new dereferences without checking for aliasing +//! +//! This test demonstrates the behavior, and should be adjusted or removed when fixing and relanding +//! the mir-opt. +#![crate_type = "lib"] +// skip-filecheck +//@ compile-flags: -O -Zunsound-mir-opts +//@ test-mir-pass: GVN +#![allow(internal_features)] +#![feature(rustc_attrs, core_intrinsics)] + +// EMIT_MIR simplify_aggregate_to_copy_miscompile.foo.GVN.diff +#[no_mangle] +fn foo(v: &mut Option) -> Option { + if let &Some(col) = get(&v) { + *v = None; + return Some(col); + } else { + unsafe { std::intrinsics::unreachable() } + } +} + +#[no_mangle] +#[inline(never)] +#[rustc_nounwind] +fn get(v: &Option) -> &Option { + v +} From 12ed4c6655dfa8048e8a7d9b593ef59ef36c020c Mon Sep 17 00:00:00 2001 From: Lukas Markeffsky <@> Date: Sat, 2 Nov 2024 00:30:36 +0100 Subject: [PATCH 2165/2194] rustdoc: skip stability inheritance for some item kinds (cherry picked from commit 728315df79d19562b7be11011b54d20406abd1f4) --- src/librustdoc/passes/propagate_stability.rs | 74 +++++++++--- tests/rustdoc/stability.rs | 114 ++++++++++++++++--- 2 files changed, 157 insertions(+), 31 deletions(-) diff --git a/src/librustdoc/passes/propagate_stability.rs b/src/librustdoc/passes/propagate_stability.rs index f51e993bfa5d0..4867588604040 100644 --- a/src/librustdoc/passes/propagate_stability.rs +++ b/src/librustdoc/passes/propagate_stability.rs @@ -9,7 +9,7 @@ use rustc_attr::{Stability, StabilityLevel}; use rustc_hir::def_id::CRATE_DEF_ID; -use crate::clean::{Crate, Item, ItemId}; +use crate::clean::{Crate, Item, ItemId, ItemKind}; use crate::core::DocContext; use crate::fold::DocFolder; use crate::passes::Pass; @@ -38,22 +38,45 @@ impl<'a, 'tcx> DocFolder for StabilityPropagator<'a, 'tcx> { ItemId::DefId(def_id) => { let own_stability = self.cx.tcx.lookup_stability(def_id); - // If any of the item's parents was stabilized later or is still unstable, - // then use the parent's stability instead. - if let Some(own_stab) = own_stability - && let StabilityLevel::Stable { - since: own_since, - allowed_through_unstable_modules: false, - } = own_stab.level - && let Some(parent_stab) = parent_stability - && (parent_stab.is_unstable() - || parent_stab - .stable_since() - .is_some_and(|parent_since| parent_since > own_since)) - { - parent_stability - } else { - own_stability + let (ItemKind::StrippedItem(box kind) | kind) = &item.kind; + match kind { + ItemKind::ExternCrateItem { .. } + | ItemKind::ImportItem(..) + | ItemKind::StructItem(..) + | ItemKind::UnionItem(..) + | ItemKind::EnumItem(..) + | ItemKind::FunctionItem(..) + | ItemKind::ModuleItem(..) + | ItemKind::TypeAliasItem(..) + | ItemKind::StaticItem(..) + | ItemKind::TraitItem(..) + | ItemKind::TraitAliasItem(..) + | ItemKind::StructFieldItem(..) + | ItemKind::VariantItem(..) + | ItemKind::ForeignFunctionItem(..) + | ItemKind::ForeignStaticItem(..) + | ItemKind::ForeignTypeItem + | ItemKind::MacroItem(..) + | ItemKind::ProcMacroItem(..) + | ItemKind::ConstantItem(..) => { + // If any of the item's parents was stabilized later or is still unstable, + // then use the parent's stability instead. + merge_stability(own_stability, parent_stability) + } + + // Don't inherit the parent's stability for these items, because they + // are potentially accessible even if the parent is more unstable. + ItemKind::ImplItem(..) + | ItemKind::TyMethodItem(..) + | ItemKind::MethodItem(..) + | ItemKind::TyAssocConstItem(..) + | ItemKind::AssocConstItem(..) + | ItemKind::TyAssocTypeItem(..) + | ItemKind::AssocTypeItem(..) + | ItemKind::PrimitiveItem(..) + | ItemKind::KeywordItem => own_stability, + + ItemKind::StrippedItem(..) => unreachable!(), } } ItemId::Auto { .. } | ItemId::Blanket { .. } => { @@ -70,3 +93,20 @@ impl<'a, 'tcx> DocFolder for StabilityPropagator<'a, 'tcx> { Some(item) } } + +fn merge_stability( + own_stability: Option, + parent_stability: Option, +) -> Option { + if let Some(own_stab) = own_stability + && let StabilityLevel::Stable { since: own_since, allowed_through_unstable_modules: false } = + own_stab.level + && let Some(parent_stab) = parent_stability + && (parent_stab.is_unstable() + || parent_stab.stable_since().is_some_and(|parent_since| parent_since > own_since)) + { + parent_stability + } else { + own_stability + } +} diff --git a/tests/rustdoc/stability.rs b/tests/rustdoc/stability.rs index fc72154cad864..550eb0bc13776 100644 --- a/tests/rustdoc/stability.rs +++ b/tests/rustdoc/stability.rs @@ -1,6 +1,8 @@ #![feature(staged_api)] +#![feature(rustc_attrs)] +#![feature(rustdoc_internals)] -#![stable(feature = "rust1", since = "1.0.0")] +#![stable(feature = "core", since = "1.6.0")] //@ has stability/index.html //@ has - '//ul[@class="item-table"]/li[1]//a' AaStable @@ -26,7 +28,7 @@ pub struct ZzStable; #[unstable(feature = "unstable", issue = "none")] pub mod unstable { //@ !hasraw stability/unstable/struct.StableInUnstable.html \ - // '//span[@class="since"]' + // '//div[@class="main-heading"]//span[@class="since"]' //@ has - '//div[@class="stab unstable"]' 'experimental' #[stable(feature = "rust1", since = "1.0.0")] pub struct StableInUnstable; @@ -34,52 +36,136 @@ pub mod unstable { #[stable(feature = "rust1", since = "1.0.0")] pub mod stable_in_unstable { //@ !hasraw stability/unstable/stable_in_unstable/struct.Inner.html \ - // '//span[@class="since"]' + // '//div[@class="main-heading"]//span[@class="since"]' //@ has - '//div[@class="stab unstable"]' 'experimental' #[stable(feature = "rust1", since = "1.0.0")] pub struct Inner; } + + //@ has stability/struct.AaStable.html \ + // '//*[@id="method.foo"]//span[@class="since"]' '2.2.2' + impl super::AaStable { + #[stable(feature = "rust2", since = "2.2.2")] + pub fn foo() {} + } + + //@ has stability/unstable/struct.StableInUnstable.html \ + // '//*[@id="method.foo"]//span[@class="since"]' '1.0.0' + impl StableInUnstable { + #[stable(feature = "rust1", since = "1.0.0")] + pub fn foo() {} + } +} + +#[unstable(feature = "unstable", issue = "none")] +#[doc(hidden)] +pub mod unstable_stripped { + //@ has stability/struct.AaStable.html \ + // '//*[@id="method.foo"]//span[@class="since"]' '2.2.2' + impl super::AaStable { + #[stable(feature = "rust2", since = "2.2.2")] + pub fn foo() {} + } } #[stable(feature = "rust2", since = "2.2.2")] pub mod stable_later { //@ has stability/stable_later/struct.StableInLater.html \ - // '//span[@class="since"]' '2.2.2' + // '//div[@class="main-heading"]//span[@class="since"]' '2.2.2' #[stable(feature = "rust1", since = "1.0.0")] pub struct StableInLater; #[stable(feature = "rust1", since = "1.0.0")] pub mod stable_in_later { //@ has stability/stable_later/stable_in_later/struct.Inner.html \ - // '//span[@class="since"]' '2.2.2' + // '//div[@class="main-heading"]//span[@class="since"]' '2.2.2' #[stable(feature = "rust1", since = "1.0.0")] pub struct Inner; } } #[stable(feature = "rust1", since = "1.0.0")] -pub mod stable_earlier { - //@ has stability/stable_earlier/struct.StableInUnstable.html \ - // '//span[@class="since"]' '1.0.0' +#[rustc_allowed_through_unstable_modules] +pub mod stable_earlier1 { + //@ has stability/stable_earlier1/struct.StableInUnstable.html \ + // '//div[@class="main-heading"]//span[@class="since"]' '1.0.0' + //@ has - '//*[@id="method.foo"]//span[@class="since"]' '1.0.0' + #[doc(inline)] + #[stable(feature = "rust1", since = "1.0.0")] + pub use crate::unstable::StableInUnstable; + + //@ has stability/stable_earlier1/stable_in_unstable/struct.Inner.html \ + // '//div[@class="main-heading"]//span[@class="since"]' '1.0.0' + #[doc(inline)] + #[stable(feature = "rust1", since = "1.0.0")] + pub use crate::unstable::stable_in_unstable; + + //@ has stability/stable_earlier1/struct.StableInLater.html \ + // '//div[@class="main-heading"]//span[@class="since"]' '1.0.0' + #[doc(inline)] + #[stable(feature = "rust1", since = "1.0.0")] + pub use crate::stable_later::StableInLater; + + //@ has stability/stable_earlier1/stable_in_later/struct.Inner.html \ + // '//div[@class="main-heading"]//span[@class="since"]' '1.0.0' + #[doc(inline)] + #[stable(feature = "rust1", since = "1.0.0")] + pub use crate::stable_later::stable_in_later; +} + +/// These will inherit the crate stability. +#[stable(feature = "rust1", since = "1.0.0")] +pub mod stable_earlier2 { + //@ has stability/stable_earlier2/struct.StableInUnstable.html \ + // '//div[@class="main-heading"]//span[@class="since"]' '1.6.0' + //@ has - '//*[@id="method.foo"]//span[@class="since"]' '1.0.0' #[doc(inline)] #[stable(feature = "rust1", since = "1.0.0")] pub use crate::unstable::StableInUnstable; - //@ has stability/stable_earlier/stable_in_unstable/struct.Inner.html \ - // '//span[@class="since"]' '1.0.0' + //@ has stability/stable_earlier2/stable_in_unstable/struct.Inner.html \ + // '//div[@class="main-heading"]//span[@class="since"]' '1.6.0' #[doc(inline)] #[stable(feature = "rust1", since = "1.0.0")] pub use crate::unstable::stable_in_unstable; - //@ has stability/stable_earlier/struct.StableInLater.html \ - // '//span[@class="since"]' '1.0.0' + //@ has stability/stable_earlier2/struct.StableInLater.html \ + // '//div[@class="main-heading"]//span[@class="since"]' '1.6.0' #[doc(inline)] #[stable(feature = "rust1", since = "1.0.0")] pub use crate::stable_later::StableInLater; - //@ has stability/stable_earlier/stable_in_later/struct.Inner.html \ - // '//span[@class="since"]' '1.0.0' + //@ has stability/stable_earlier2/stable_in_later/struct.Inner.html \ + // '//div[@class="main-heading"]//span[@class="since"]' '1.6.0' #[doc(inline)] #[stable(feature = "rust1", since = "1.0.0")] pub use crate::stable_later::stable_in_later; } + +//@ !hasraw stability/trait.UnstableTraitWithStableMethod.html \ +// '//div[@class="main-heading"]//span[@class="since"]' +//@ has - '//*[@id="tymethod.foo"]//span[@class="since"]' '1.0.0' +//@ has - '//*[@id="method.bar"]//span[@class="since"]' '1.0.0' +#[unstable(feature = "unstable", issue = "none")] +pub trait UnstableTraitWithStableMethod { + #[stable(feature = "rust1", since = "1.0.0")] + fn foo(); + #[stable(feature = "rust1", since = "1.0.0")] + fn bar() {} +} + +//@ has stability/primitive.i32.html \ +// '//div[@class="main-heading"]//span[@class="since"]' '1.0.0' +#[rustc_doc_primitive = "i32"] +// +/// `i32` is always stable in 1.0, even if you look at it from core. +#[stable(feature = "rust1", since = "1.0.0")] +mod prim_i32 {} + +//@ has stability/keyword.if.html \ +// '//div[@class="main-heading"]//span[@class="since"]' '1.0.0' +#[doc(keyword = "if")] +// +/// We currently don't document stability for keywords, but let's test it anyway. +#[stable(feature = "rust1", since = "1.0.0")] +mod if_keyword {} From a160d9e36ad4703decc5e11d82da450918241119 Mon Sep 17 00:00:00 2001 From: Jeong YunWon Date: Thu, 24 Oct 2024 17:50:19 +0900 Subject: [PATCH 2166/2194] Avoid use imports in thread_local_inner! in statik Fixes #131863 for wasm targets All other macros were done in #131866, but this sub module is missed. (cherry picked from commit 5368b120a1742893460c515bb198342d6f0a3800) --- library/std/src/sys/thread_local/statik.rs | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/library/std/src/sys/thread_local/statik.rs b/library/std/src/sys/thread_local/statik.rs index ba94caa669027..4da01a84acf68 100644 --- a/library/std/src/sys/thread_local/statik.rs +++ b/library/std/src/sys/thread_local/statik.rs @@ -14,12 +14,11 @@ pub macro thread_local_inner { (@key $t:ty, const $init:expr) => {{ const __INIT: $t = $init; + // NOTE: Please update the shadowing test in `tests/thread.rs` if these types are renamed. unsafe { - use $crate::thread::LocalKey; - use $crate::thread::local_impl::EagerStorage; - - LocalKey::new(|_| { - static VAL: EagerStorage<$t> = EagerStorage { value: __INIT }; + $crate::thread::LocalKey::new(|_| { + static VAL: $crate::thread::local_impl::EagerStorage<$t> = + $crate::thread::local_impl::EagerStorage { value: __INIT }; &VAL.value }) } From c77b19bf309cc551f58a4bb40193836d08292a10 Mon Sep 17 00:00:00 2001 From: Urgau Date: Fri, 1 Nov 2024 12:44:55 +0100 Subject: [PATCH 2167/2194] Also treat `impl` definition parent as transparent regarding modules (cherry picked from commit 37db36594838d85f72e2282e73707071e80e31c0) --- compiler/rustc_lint/src/non_local_def.rs | 10 ++- .../convoluted-locals-132427.rs | 64 +++++++++++++++++++ 2 files changed, 72 insertions(+), 2 deletions(-) create mode 100644 tests/ui/lint/non-local-defs/convoluted-locals-132427.rs diff --git a/compiler/rustc_lint/src/non_local_def.rs b/compiler/rustc_lint/src/non_local_def.rs index 3c31b879bd6aa..3c33b2dd4789c 100644 --- a/compiler/rustc_lint/src/non_local_def.rs +++ b/compiler/rustc_lint/src/non_local_def.rs @@ -151,9 +151,15 @@ impl<'tcx> LateLintPass<'tcx> for NonLocalDefinitions { // }; // }; // ``` + // + // It isn't possible to mix a impl in a module with const-anon, but an item can + // be put inside a module and referenced by a impl so we also have to treat the + // item parent as transparent to module and for consistency we have to do the same + // for impl, otherwise the item-def and impl-def won't have the same parent. let outermost_impl_parent = peel_parent_while(cx.tcx, parent, |tcx, did| { - tcx.def_kind(did) == DefKind::Const - && tcx.opt_item_name(did) == Some(kw::Underscore) + tcx.def_kind(did) == DefKind::Mod + || (tcx.def_kind(did) == DefKind::Const + && tcx.opt_item_name(did) == Some(kw::Underscore)) }); // 2. We check if any of the paths reference a the `impl`-parent. diff --git a/tests/ui/lint/non-local-defs/convoluted-locals-132427.rs b/tests/ui/lint/non-local-defs/convoluted-locals-132427.rs new file mode 100644 index 0000000000000..5732e048ae38a --- /dev/null +++ b/tests/ui/lint/non-local-defs/convoluted-locals-132427.rs @@ -0,0 +1,64 @@ +// Regression tests for https://github.com/rust-lang/rust/issues/132427 + +//@ check-pass + +// original +mod auth { + const _: () = { + pub enum ArbitraryContext {} + + const _: () = { + impl ArbitraryContext {} + }; + }; +} + +mod z { + pub enum ArbitraryContext {} + + const _: () = { + const _: () = { + impl ArbitraryContext {} + }; + }; +} + +const _: () = { + mod auth { + const _: () = { + pub enum ArbitraryContext {} + + const _: () = { + impl ArbitraryContext {} + }; + }; + } +}; + +mod a { + mod b { + const _: () = { + pub enum ArbitraryContext {} + + const _: () = { + impl ArbitraryContext {} + }; + }; + } +} + +mod foo { + const _: () = { + mod auth { + const _: () = { + pub enum ArbitraryContext {} + + const _: () = { + impl ArbitraryContext {} + }; + }; + } + }; +} + +fn main() {} From 25ab47d5e6e4b90e90f402daaf2704d02d84a9e4 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 4 Nov 2024 15:41:32 +1100 Subject: [PATCH 2168/2194] Revert "Avoid nested replacement ranges" from #129346. It caused a test regression in the `cfg_eval.rs` crate. (The bugfix in #129346 was in a different commit; this commit was just a code simplification.) (cherry picked from commit 981dc02eaf876a25b95581411e841ba664dc9e97) --- .../rustc_parse/src/parser/attr_wrapper.rs | 28 ++++++++++++++----- 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/compiler/rustc_parse/src/parser/attr_wrapper.rs b/compiler/rustc_parse/src/parser/attr_wrapper.rs index 8bd615e6d7913..c85d0bd05cbd6 100644 --- a/compiler/rustc_parse/src/parser/attr_wrapper.rs +++ b/compiler/rustc_parse/src/parser/attr_wrapper.rs @@ -136,8 +136,9 @@ impl ToAttrTokenStream for LazyAttrTokenStreamImpl { node_replacements.array_windows() { assert!( - node_range.0.end <= next_node_range.0.start, - "Node ranges should be disjoint: ({:?}, {:?}) ({:?}, {:?})", + node_range.0.end <= next_node_range.0.start + || node_range.0.end >= next_node_range.0.end, + "Node ranges should be disjoint or nested: ({:?}, {:?}) ({:?}, {:?})", node_range, tokens, next_node_range, @@ -145,8 +146,20 @@ impl ToAttrTokenStream for LazyAttrTokenStreamImpl { ); } - // Process the replace ranges. - for (node_range, target) in node_replacements.into_iter() { + // Process the replace ranges, starting from the highest start + // position and working our way back. If have tokens like: + // + // `#[cfg(FALSE)] struct Foo { #[cfg(FALSE)] field: bool }` + // + // Then we will generate replace ranges for both + // the `#[cfg(FALSE)] field: bool` and the entire + // `#[cfg(FALSE)] struct Foo { #[cfg(FALSE)] field: bool }` + // + // By starting processing from the replace range with the greatest + // start position, we ensure that any (outer) replace range which + // encloses another (inner) replace range will fully overwrite the + // inner range's replacement. + for (node_range, target) in node_replacements.into_iter().rev() { assert!( !node_range.0.is_empty(), "Cannot replace an empty node range: {:?}", @@ -383,9 +396,10 @@ impl<'a> Parser<'a> { // from `ParserRange` form to `NodeRange` form. We will perform the actual // replacement only when we convert the `LazyAttrTokenStream` to an // `AttrTokenStream`. - self.capture_state - .parser_replacements - .drain(parser_replacements_start..parser_replacements_end) + self.capture_state.parser_replacements + [parser_replacements_start..parser_replacements_end] + .iter() + .cloned() .chain(inner_attr_parser_replacements) .map(|(parser_range, data)| { (NodeRange::new(parser_range, collect_pos.start_pos), data) From fa46a9e2b605de60b11a29f5951e650c3c0f5089 Mon Sep 17 00:00:00 2001 From: Kirill Bulatov Date: Mon, 11 Nov 2024 15:50:04 +0100 Subject: [PATCH 2169/2194] Use completion item indices instead of property matching when searching for the completion item to resolve --- .../rust-analyzer/src/handlers/request.rs | 18 +++++------- .../crates/rust-analyzer/src/lsp/ext.rs | 1 + .../crates/rust-analyzer/src/lsp/to_proto.rs | 29 +++++++++++++++---- 3 files changed, 33 insertions(+), 15 deletions(-) diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/request.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/request.rs index 9773d8dbce013..691ea6f567797 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/request.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/request.rs @@ -1068,7 +1068,7 @@ pub(crate) fn handle_completion_resolve( else { return Ok(original_completion); }; - let resolved_completions = to_proto::completion_items( + let mut resolved_completions = to_proto::completion_items( &snap.config, &forced_resolve_completions_config.fields_to_resolve, &line_index, @@ -1077,15 +1077,13 @@ pub(crate) fn handle_completion_resolve( resolve_data.trigger_character, resolved_completions, ); - let Some(mut resolved_completion) = resolved_completions.into_iter().find(|completion| { - completion.label == original_completion.label - && completion.kind == original_completion.kind - && completion.deprecated == original_completion.deprecated - && completion.preselect == original_completion.preselect - && completion.sort_text == original_completion.sort_text - }) else { - return Ok(original_completion); - }; + + let mut resolved_completion = + if resolved_completions.get(resolve_data.completion_item_index).is_some() { + resolved_completions.swap_remove(resolve_data.completion_item_index) + } else { + return Ok(original_completion); + }; if !resolve_data.imports.is_empty() { let additional_edits = snap diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/ext.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/ext.rs index 8039f0644eecf..6ddfe118d5e6e 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/ext.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/ext.rs @@ -826,6 +826,7 @@ pub struct CompletionResolveData { pub imports: Vec, pub version: Option, pub trigger_character: Option, + pub completion_item_index: usize, } #[derive(Debug, Serialize, Deserialize)] diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/to_proto.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/to_proto.rs index 375b7428c2dc7..cdc6fb17fd47f 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/to_proto.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/to_proto.rs @@ -391,18 +391,36 @@ fn completion_item( } else { Vec::new() }; - if something_to_resolve || !imports.is_empty() { - let data = lsp_ext::CompletionResolveData { + let (ref_resolve_data, resolve_data) = if something_to_resolve || !imports.is_empty() { + let mut item_index = acc.len(); + let ref_resolve_data = if ref_match.is_some() { + let ref_resolve_data = lsp_ext::CompletionResolveData { + position: tdpp.clone(), + imports: Vec::new(), + version, + trigger_character: completion_trigger_character, + completion_item_index: item_index, + }; + item_index += 1; + Some(to_value(ref_resolve_data).unwrap()) + } else { + None + }; + let resolve_data = lsp_ext::CompletionResolveData { position: tdpp.clone(), imports, version, trigger_character: completion_trigger_character, + completion_item_index: item_index, }; - lsp_item.data = Some(to_value(data).unwrap()); - } + (ref_resolve_data, Some(to_value(resolve_data).unwrap())) + } else { + (None, None) + }; if let Some((label, indel, relevance)) = ref_match { - let mut lsp_item_with_ref = lsp_types::CompletionItem { label, ..lsp_item.clone() }; + let mut lsp_item_with_ref = + lsp_types::CompletionItem { label, data: ref_resolve_data, ..lsp_item.clone() }; lsp_item_with_ref .additional_text_edits .get_or_insert_with(Default::default) @@ -411,6 +429,7 @@ fn completion_item( acc.push(lsp_item_with_ref); }; + lsp_item.data = resolve_data; acc.push(lsp_item); fn set_score( From f0db79f31ada049bf490c8f27be7443f45460f09 Mon Sep 17 00:00:00 2001 From: Kirill Bulatov Date: Mon, 11 Nov 2024 16:06:55 +0100 Subject: [PATCH 2170/2194] Update the file hash --- src/tools/rust-analyzer/docs/dev/lsp-extensions.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/rust-analyzer/docs/dev/lsp-extensions.md b/src/tools/rust-analyzer/docs/dev/lsp-extensions.md index 7764f7843a00b..b7c536e027964 100644 --- a/src/tools/rust-analyzer/docs/dev/lsp-extensions.md +++ b/src/tools/rust-analyzer/docs/dev/lsp-extensions.md @@ -1,5 +1,5 @@ $DIR/immediately-followed-by-lt.rs:11:4 + | +LL | w!('r#long'id); + | ^^^^^^^^ + | +help: if you meant to write a string literal, use double quotes + | +LL | w!("r#long"id); + | ~ ~ + +error: aborting due to 1 previous error + From 80f109a80a8c8aae389442895d896bbd32e68d6d Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 5 Nov 2024 02:02:56 +0000 Subject: [PATCH 2172/2194] Only disable cache if predicate has opaques within it (cherry picked from commit 49153739fd01d82ed999c763fd2771cb837d7dd2) --- .../src/traits/select/mod.rs | 66 +++++++++++++------ 1 file changed, 45 insertions(+), 21 deletions(-) diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index fba1d1025ca66..ea5b6ff19594f 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -12,26 +12,26 @@ use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet}; use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_errors::{Diag, EmissionGuarantee}; use rustc_hir as hir; -use rustc_hir::LangItem; use rustc_hir::def_id::DefId; -use rustc_infer::infer::BoundRegionConversionTime::{self, HigherRankedType}; -use rustc_infer::infer::DefineOpaqueTypes; +use rustc_hir::LangItem; use rustc_infer::infer::at::ToTrace; use rustc_infer::infer::relate::TypeRelation; +use rustc_infer::infer::BoundRegionConversionTime::{self, HigherRankedType}; +use rustc_infer::infer::DefineOpaqueTypes; use rustc_infer::traits::TraitObligation; use rustc_middle::bug; -use rustc_middle::dep_graph::{DepNodeIndex, dep_kinds}; +use rustc_middle::dep_graph::{dep_kinds, DepNodeIndex}; use rustc_middle::mir::interpret::ErrorHandled; pub use rustc_middle::traits::select::*; use rustc_middle::ty::abstract_const::NotConstEvaluatable; use rustc_middle::ty::error::TypeErrorToStringExt; -use rustc_middle::ty::print::{PrintTraitRefExt as _, with_no_trimmed_paths}; +use rustc_middle::ty::print::{with_no_trimmed_paths, PrintTraitRefExt as _}; use rustc_middle::ty::{ self, GenericArgsRef, PolyProjectionPredicate, Ty, TyCtxt, TypeFoldable, TypeVisitableExt, Upcast, }; -use rustc_span::Symbol; use rustc_span::symbol::sym; +use rustc_span::Symbol; use tracing::{debug, instrument, trace}; use self::EvaluationResult::*; @@ -40,9 +40,9 @@ use super::coherence::{self, Conflict}; use super::project::ProjectionTermObligation; use super::util::closure_trait_ref_and_return_type; use super::{ - ImplDerivedCause, Normalized, Obligation, ObligationCause, ObligationCauseCode, Overflow, - PolyTraitObligation, PredicateObligation, Selection, SelectionError, SelectionResult, - TraitQueryMode, const_evaluatable, project, util, wf, + const_evaluatable, project, util, wf, ImplDerivedCause, Normalized, Obligation, + ObligationCause, ObligationCauseCode, Overflow, PolyTraitObligation, PredicateObligation, + Selection, SelectionError, SelectionResult, TraitQueryMode, }; use crate::error_reporting::InferCtxtErrorExt; use crate::infer::{InferCtxt, InferOk, TypeFreshener}; @@ -1306,7 +1306,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } let tcx = self.tcx(); - if self.can_use_global_caches(param_env) { + if self.can_use_global_caches(param_env, trait_pred) { if let Some(res) = tcx.evaluation_cache.get(&(param_env, trait_pred), tcx) { return Some(res); } @@ -1335,7 +1335,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { return; } - if self.can_use_global_caches(param_env) && !trait_pred.has_infer() { + if self.can_use_global_caches(param_env, trait_pred) && !trait_pred.has_infer() { debug!(?trait_pred, ?result, "insert_evaluation_cache global"); // This may overwrite the cache with the same value // FIXME: Due to #50507 this overwrites the different values @@ -1479,7 +1479,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } /// Returns `true` if the global caches can be used. - fn can_use_global_caches(&self, param_env: ty::ParamEnv<'tcx>) -> bool { + fn can_use_global_caches( + &self, + param_env: ty::ParamEnv<'tcx>, + pred: ty::PolyTraitPredicate<'tcx>, + ) -> bool { // If there are any inference variables in the `ParamEnv`, then we // always use a cache local to this particular scope. Otherwise, we // switch to a global cache. @@ -1500,7 +1504,13 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // Avoid using the global cache when we're defining opaque types // as their hidden type may impact the result of candidate selection. - if !self.infcx.defining_opaque_types().is_empty() { + // + // HACK: This is still theoretically unsound. Goals can indirectly rely + // on opaques in the defining scope, and it's easier to do so with TAIT. + // However, if we disqualify *all* goals from being cached, perf suffers. + // This is likely fixed by better caching in general in the new solver. + // See: . + if !self.infcx.defining_opaque_types().is_empty() && pred.has_opaque_types() { return false; } @@ -1523,7 +1533,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let tcx = self.tcx(); let pred = cache_fresh_trait_pred.skip_binder(); - if self.can_use_global_caches(param_env) { + if self.can_use_global_caches(param_env, cache_fresh_trait_pred) { if let Some(res) = tcx.selection_cache.get(&(param_env, pred), tcx) { return Some(res); } @@ -1580,7 +1590,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { return; } - if self.can_use_global_caches(param_env) { + if self.can_use_global_caches(param_env, cache_fresh_trait_pred) { if let Err(Overflow(OverflowError::Canonical)) = candidate { // Don't cache overflow globally; we only produce this in certain modes. } else if !pred.has_infer() && !candidate.has_infer() { @@ -1787,7 +1797,11 @@ enum DropVictim { impl DropVictim { fn drop_if(should_drop: bool) -> DropVictim { - if should_drop { DropVictim::Yes } else { DropVictim::No } + if should_drop { + DropVictim::Yes + } else { + DropVictim::No + } } } @@ -1891,7 +1905,11 @@ impl<'tcx> SelectionContext<'_, 'tcx> { (ObjectCandidate(_) | ProjectionCandidate(_), ParamCandidate(victim_cand)) => { // Prefer these to a global where-clause bound // (see issue #50825). - if is_global(*victim_cand) { DropVictim::Yes } else { DropVictim::No } + if is_global(*victim_cand) { + DropVictim::Yes + } else { + DropVictim::No + } } ( ImplCandidate(_) @@ -2450,9 +2468,11 @@ impl<'tcx> SelectionContext<'_, 'tcx> { } else { // If this is an ill-formed auto/built-in trait, then synthesize // new error args for the missing generics. - let err_args = ty::GenericArgs::extend_with_error(tcx, trait_def_id, &[ - normalized_ty.into(), - ]); + let err_args = ty::GenericArgs::extend_with_error( + tcx, + trait_def_id, + &[normalized_ty.into()], + ); ty::TraitRef::new_from_args(tcx, trait_def_id, err_args) }; @@ -3154,7 +3174,11 @@ impl<'o, 'tcx> TraitObligationStackList<'o, 'tcx> { } fn depth(&self) -> usize { - if let Some(head) = self.head { head.depth } else { 0 } + if let Some(head) = self.head { + head.depth + } else { + 0 + } } } From 71ed4559585c66672ff0a28a524881d227380369 Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Thu, 14 Nov 2024 11:08:06 -0700 Subject: [PATCH 2173/2194] rustdoc-search: case-sensitive only when capitals are used This is the "smartcase" behavior, described by vim and dtolnay. (cherry picked from commit 32500aa8e0f23029c0fa69235d19f770106c016f) --- src/librustdoc/html/static/js/search.js | 11 +++++++---- tests/rustdoc-js-std/write.js | 24 ++++++++++++++++++++++++ tests/rustdoc-js/case.js | 17 +++++++++++++++++ tests/rustdoc-js/case.rs | 7 +++++++ 4 files changed, 55 insertions(+), 4 deletions(-) create mode 100644 tests/rustdoc-js-std/write.js create mode 100644 tests/rustdoc-js/case.js create mode 100644 tests/rustdoc-js/case.rs diff --git a/src/librustdoc/html/static/js/search.js b/src/librustdoc/html/static/js/search.js index eed64d024c046..526a32e194a8f 100644 --- a/src/librustdoc/html/static/js/search.js +++ b/src/librustdoc/html/static/js/search.js @@ -2098,6 +2098,7 @@ class DocSearch { const sortResults = async(results, isType, preferredCrate) => { const userQuery = parsedQuery.userQuery; const casedUserQuery = parsedQuery.original; + const isMixedCase = casedUserQuery !== userQuery; const result_list = []; for (const result of results.values()) { result.item = this.searchIndex[result.id]; @@ -2109,10 +2110,12 @@ class DocSearch { let a, b; // sort by exact case-sensitive match - a = (aaa.item.name !== casedUserQuery); - b = (bbb.item.name !== casedUserQuery); - if (a !== b) { - return a - b; + if (isMixedCase) { + a = (aaa.item.name !== casedUserQuery); + b = (bbb.item.name !== casedUserQuery); + if (a !== b) { + return a - b; + } } // sort by exact match with regard to the last word (mismatch goes later) diff --git a/tests/rustdoc-js-std/write.js b/tests/rustdoc-js-std/write.js new file mode 100644 index 0000000000000..4a9475102a544 --- /dev/null +++ b/tests/rustdoc-js-std/write.js @@ -0,0 +1,24 @@ +const EXPECTED = [ + { + 'query': 'write', + 'others': [ + { 'path': 'std::fmt', 'name': 'write' }, + { 'path': 'std::fs', 'name': 'write' }, + { 'path': 'std::ptr', 'name': 'write' }, + { 'path': 'std::fmt', 'name': 'Write' }, + { 'path': 'std::io', 'name': 'Write' }, + { 'path': 'std::hash::Hasher', 'name': 'write' }, + ], + }, + { + 'query': 'Write', + 'others': [ + { 'path': 'std::fmt', 'name': 'Write' }, + { 'path': 'std::io', 'name': 'Write' }, + { 'path': 'std::fmt', 'name': 'write' }, + { 'path': 'std::fs', 'name': 'write' }, + { 'path': 'std::ptr', 'name': 'write' }, + { 'path': 'std::hash::Hasher', 'name': 'write' }, + ], + }, +]; diff --git a/tests/rustdoc-js/case.js b/tests/rustdoc-js/case.js new file mode 100644 index 0000000000000..22b970eb1398e --- /dev/null +++ b/tests/rustdoc-js/case.js @@ -0,0 +1,17 @@ +const EXPECTED = [ + { + 'query': 'Foo', + 'others': [ + { 'path': 'case', 'name': 'Foo', 'desc': 'Docs for Foo' }, + { 'path': 'case', 'name': 'foo', 'desc': 'Docs for foo' }, + ], + }, + { + 'query': 'foo', + 'others': [ + // https://github.com/rust-lang/rust/issues/133017 + { 'path': 'case', 'name': 'Foo', 'desc': 'Docs for Foo' }, + { 'path': 'case', 'name': 'foo', 'desc': 'Docs for foo' }, + ], + }, +]; diff --git a/tests/rustdoc-js/case.rs b/tests/rustdoc-js/case.rs new file mode 100644 index 0000000000000..532edd55f1dc9 --- /dev/null +++ b/tests/rustdoc-js/case.rs @@ -0,0 +1,7 @@ +#![allow(nonstandard_style)] + +/// Docs for Foo +pub struct Foo; + +/// Docs for foo +pub struct foo; From 7757d3257191ab6b8fe90c1b3429de9729081025 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Fri, 11 Oct 2024 13:47:08 -0700 Subject: [PATCH 2174/2194] (ci) Update macOS to Xcode 15 (cherry picked from commit 94579ff9301fcee893cd0c4ad9284ab5ef51e6cd) --- src/ci/github-actions/jobs.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/ci/github-actions/jobs.yml b/src/ci/github-actions/jobs.yml index 8f49f623afaa4..876abb6d9152b 100644 --- a/src/ci/github-actions/jobs.yml +++ b/src/ci/github-actions/jobs.yml @@ -46,7 +46,7 @@ envs: RUSTC_RETRY_LINKER_ON_SEGFAULT: 1 MACOSX_DEPLOYMENT_TARGET: 10.12 MACOSX_STD_DEPLOYMENT_TARGET: 10.12 - SELECT_XCODE: /Applications/Xcode_14.3.1.app + SELECT_XCODE: /Applications/Xcode_15.2.app NO_LLVM_ASSERTIONS: 1 NO_DEBUG_ASSERTIONS: 1 NO_OVERFLOW_CHECKS: 1 @@ -282,7 +282,7 @@ auto: RUST_CONFIGURE_ARGS: --enable-full-tools --enable-sanitizers --enable-profiler --set rust.jemalloc --set rust.lto=thin --set rust.codegen-units=1 RUSTC_RETRY_LINKER_ON_SEGFAULT: 1 MACOSX_DEPLOYMENT_TARGET: 10.12 - SELECT_XCODE: /Applications/Xcode_14.3.1.app + SELECT_XCODE: /Applications/Xcode_15.2.app NO_LLVM_ASSERTIONS: 1 NO_DEBUG_ASSERTIONS: 1 NO_OVERFLOW_CHECKS: 1 @@ -298,7 +298,7 @@ auto: RUST_CONFIGURE_ARGS: --enable-sanitizers --enable-profiler --set rust.jemalloc --set target.aarch64-apple-ios-macabi.sanitizers=false --set target.x86_64-apple-ios-macabi.sanitizers=false RUSTC_RETRY_LINKER_ON_SEGFAULT: 1 MACOSX_DEPLOYMENT_TARGET: 10.12 - SELECT_XCODE: /Applications/Xcode_14.3.1.app + SELECT_XCODE: /Applications/Xcode_15.2.app NO_LLVM_ASSERTIONS: 1 NO_DEBUG_ASSERTIONS: 1 NO_OVERFLOW_CHECKS: 1 @@ -327,7 +327,7 @@ auto: --set llvm.ninja=false --set rust.lto=thin RUSTC_RETRY_LINKER_ON_SEGFAULT: 1 - SELECT_XCODE: /Applications/Xcode_14.3.1.app + SELECT_XCODE: /Applications/Xcode_15.4.app USE_XCODE_CLANG: 1 MACOSX_DEPLOYMENT_TARGET: 11.0 MACOSX_STD_DEPLOYMENT_TARGET: 11.0 @@ -347,7 +347,7 @@ auto: --enable-profiler --set rust.jemalloc RUSTC_RETRY_LINKER_ON_SEGFAULT: 1 - SELECT_XCODE: /Applications/Xcode_14.3.1.app + SELECT_XCODE: /Applications/Xcode_15.4.app USE_XCODE_CLANG: 1 MACOSX_DEPLOYMENT_TARGET: 11.0 MACOSX_STD_DEPLOYMENT_TARGET: 11.0 From 48c21ba81836684c4089bc2407c11a87b73fe4db Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Mon, 21 Oct 2024 11:40:12 -0700 Subject: [PATCH 2175/2194] Update debuginfo test for newer lldb For reasons I don't understand, lldb in Xcode 15 no longer prints objects as: (long) $0 = 19 instead, it is printing them as: (long) 19 (cherry picked from commit 16b91e887afcdbfe0db2232639f0c9d33b7e2246) --- tests/debuginfo/constant-ordering-prologue.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/debuginfo/constant-ordering-prologue.rs b/tests/debuginfo/constant-ordering-prologue.rs index f2d4fd37ce343..3136aff238a2d 100644 --- a/tests/debuginfo/constant-ordering-prologue.rs +++ b/tests/debuginfo/constant-ordering-prologue.rs @@ -20,11 +20,11 @@ // lldb-command:run // lldb-command:print a -// lldb-check: = 19 +// lldb-check: 19 // lldb-command:print b -// lldb-check: = 20 +// lldb-check: 20 // lldb-command:print c -// lldb-check: = 21.5 +// lldb-check: 21.5 fn binding(a: i64, b: u64, c: f64) { let x = 0; From 7b688e21d62609d59467b78b5b6f4a2dd40f3c80 Mon Sep 17 00:00:00 2001 From: bors Date: Tue, 15 Oct 2024 20:02:57 +0000 Subject: [PATCH 2176/2194] Auto merge of #13553 - SpriteOvO:manual_is_power_of_two-change-category, r=llogiq Change the category of `manual_is_power_of_two` to `pedantic` Fixes #13547. The value being checked might be a bit flag, suggesting `is_power_of_two` for it would make the code unreadable. changelog: [`manual_is_power_of_two`]: Change the category to `pedantic` --- src/tools/clippy/clippy_lints/src/manual_is_power_of_two.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/tools/clippy/clippy_lints/src/manual_is_power_of_two.rs b/src/tools/clippy/clippy_lints/src/manual_is_power_of_two.rs index da2a982ee170a..738201b8fe423 100644 --- a/src/tools/clippy/clippy_lints/src/manual_is_power_of_two.rs +++ b/src/tools/clippy/clippy_lints/src/manual_is_power_of_two.rs @@ -11,10 +11,12 @@ use rustc_session::declare_lint_pass; declare_clippy_lint! { /// ### What it does - /// Checks for expressions like `x.count_ones() == 1` or `x & (x - 1) == 0`, with x and unsigned integer, which are manual + /// Checks for expressions like `x.count_ones() == 1` or `x & (x - 1) == 0`, with x and unsigned integer, which may be manual /// reimplementations of `x.is_power_of_two()`. + /// /// ### Why is this bad? /// Manual reimplementations of `is_power_of_two` increase code complexity for little benefit. + /// /// ### Example /// ```no_run /// let a: u32 = 4; @@ -27,7 +29,7 @@ declare_clippy_lint! { /// ``` #[clippy::version = "1.82.0"] pub MANUAL_IS_POWER_OF_TWO, - complexity, + pedantic, "manually reimplementing `is_power_of_two`" } From 5f4dd1deeb5f23458fe58457f457cc2769e14951 Mon Sep 17 00:00:00 2001 From: bors Date: Sun, 27 Oct 2024 12:37:40 +0000 Subject: [PATCH 2177/2194] Auto merge of #13600 - samueltardieu:push-tzuvnutssmrs, r=xFrednet borrow_deref_ref: do not trigger on `&raw` references changelog: [`borrow_deref_ref`]: do not trigger on `&raw` references Fix #13584 --- src/tools/clippy/clippy_lints/src/borrow_deref_ref.rs | 4 ++-- src/tools/clippy/tests/ui/borrow_deref_ref.fixed | 6 ++++++ src/tools/clippy/tests/ui/borrow_deref_ref.rs | 6 ++++++ 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/src/tools/clippy/clippy_lints/src/borrow_deref_ref.rs b/src/tools/clippy/clippy_lints/src/borrow_deref_ref.rs index cba8224b84c9e..f2551a05b1a22 100644 --- a/src/tools/clippy/clippy_lints/src/borrow_deref_ref.rs +++ b/src/tools/clippy/clippy_lints/src/borrow_deref_ref.rs @@ -4,7 +4,7 @@ use clippy_utils::source::SpanRangeExt; use clippy_utils::ty::implements_trait; use clippy_utils::{get_parent_expr, is_from_proc_macro, is_lint_allowed}; use rustc_errors::Applicability; -use rustc_hir::{ExprKind, UnOp}; +use rustc_hir::{BorrowKind, ExprKind, UnOp}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::mir::Mutability; use rustc_middle::ty; @@ -49,7 +49,7 @@ declare_lint_pass!(BorrowDerefRef => [BORROW_DEREF_REF]); impl<'tcx> LateLintPass<'tcx> for BorrowDerefRef { fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &rustc_hir::Expr<'tcx>) { - if let ExprKind::AddrOf(_, Mutability::Not, addrof_target) = e.kind + if let ExprKind::AddrOf(BorrowKind::Ref, Mutability::Not, addrof_target) = e.kind && let ExprKind::Unary(UnOp::Deref, deref_target) = addrof_target.kind && !matches!(deref_target.kind, ExprKind::Unary(UnOp::Deref, ..)) && !e.span.from_expansion() diff --git a/src/tools/clippy/tests/ui/borrow_deref_ref.fixed b/src/tools/clippy/tests/ui/borrow_deref_ref.fixed index ea5e983de3bdb..22e984c46d248 100644 --- a/src/tools/clippy/tests/ui/borrow_deref_ref.fixed +++ b/src/tools/clippy/tests/ui/borrow_deref_ref.fixed @@ -71,3 +71,9 @@ mod false_negative { assert_ne!(addr_x, addr_y); } } + +fn issue_13584() { + let s = "Hello, world!\n"; + let p = &raw const *s; + let _ = p as *const i8; +} diff --git a/src/tools/clippy/tests/ui/borrow_deref_ref.rs b/src/tools/clippy/tests/ui/borrow_deref_ref.rs index 8c8905b150e62..61d89193f42f2 100644 --- a/src/tools/clippy/tests/ui/borrow_deref_ref.rs +++ b/src/tools/clippy/tests/ui/borrow_deref_ref.rs @@ -71,3 +71,9 @@ mod false_negative { assert_ne!(addr_x, addr_y); } } + +fn issue_13584() { + let s = "Hello, world!\n"; + let p = &raw const *s; + let _ = p as *const i8; +} From 3c7babbb128ba0855129b543be30795ac8320f1a Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 30 Oct 2024 14:45:17 +0000 Subject: [PATCH 2178/2194] Enforce that raw lifetime identifiers must be valid raw identifiers (cherry picked from commit 9785c7cf94f5e30742f886764f2d25b6a4da66e8) --- compiler/rustc_parse/messages.ftl | 2 ++ compiler/rustc_parse/src/errors.rs | 8 +++++ compiler/rustc_parse/src/lexer/mod.rs | 14 +++++--- .../ui/lifetimes/raw/raw-lt-invalid-raw-id.rs | 20 ++++++++++++ .../raw/raw-lt-invalid-raw-id.stderr | 32 +++++++++++++++++++ 5 files changed, 72 insertions(+), 4 deletions(-) create mode 100644 tests/ui/lifetimes/raw/raw-lt-invalid-raw-id.rs create mode 100644 tests/ui/lifetimes/raw/raw-lt-invalid-raw-id.stderr diff --git a/compiler/rustc_parse/messages.ftl b/compiler/rustc_parse/messages.ftl index 1af7fb9b86a7c..ef259703f0cf5 100644 --- a/compiler/rustc_parse/messages.ftl +++ b/compiler/rustc_parse/messages.ftl @@ -77,6 +77,8 @@ parse_box_syntax_removed_suggestion = use `Box::new()` instead parse_cannot_be_raw_ident = `{$ident}` cannot be a raw identifier +parse_cannot_be_raw_lifetime = `{$ident}` cannot be a raw lifetime + parse_catch_after_try = keyword `catch` cannot follow a `try` block .help = try using `match` on the result of the `try` block instead diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs index fdd500e90f807..7ec4ad6dc359f 100644 --- a/compiler/rustc_parse/src/errors.rs +++ b/compiler/rustc_parse/src/errors.rs @@ -2018,6 +2018,14 @@ pub(crate) struct CannotBeRawIdent { pub ident: Symbol, } +#[derive(Diagnostic)] +#[diag(parse_cannot_be_raw_lifetime)] +pub(crate) struct CannotBeRawLifetime { + #[primary_span] + pub span: Span, + pub ident: Symbol, +} + #[derive(Diagnostic)] #[diag(parse_keyword_lifetime)] pub(crate) struct KeywordLifetime { diff --git a/compiler/rustc_parse/src/lexer/mod.rs b/compiler/rustc_parse/src/lexer/mod.rs index d627ef3d2cbe3..226de65445c8a 100644 --- a/compiler/rustc_parse/src/lexer/mod.rs +++ b/compiler/rustc_parse/src/lexer/mod.rs @@ -294,15 +294,21 @@ impl<'psess, 'src> StringReader<'psess, 'src> { let prefix_span = self.mk_sp(start, ident_start); if prefix_span.at_least_rust_2021() { - let lifetime_name_without_tick = self.str_from(ident_start); + let span = self.mk_sp(start, self.pos); + + let lifetime_name_without_tick = Symbol::intern(&self.str_from(ident_start)); + if !lifetime_name_without_tick.can_be_raw() { + self.dcx().emit_err(errors::CannotBeRawLifetime { span, ident: lifetime_name_without_tick }); + } + // Put the `'` back onto the lifetime name. - let mut lifetime_name = String::with_capacity(lifetime_name_without_tick.len() + 1); + let mut lifetime_name = String::with_capacity(lifetime_name_without_tick.as_str().len() + 1); lifetime_name.push('\''); - lifetime_name += lifetime_name_without_tick; + lifetime_name += lifetime_name_without_tick.as_str(); let sym = Symbol::intern(&lifetime_name); // Make sure we mark this as a raw identifier. - self.psess.raw_identifier_spans.push(self.mk_sp(start, self.pos)); + self.psess.raw_identifier_spans.push(span); token::Lifetime(sym, IdentIsRaw::Yes) } else { diff --git a/tests/ui/lifetimes/raw/raw-lt-invalid-raw-id.rs b/tests/ui/lifetimes/raw/raw-lt-invalid-raw-id.rs new file mode 100644 index 0000000000000..882fad925f371 --- /dev/null +++ b/tests/ui/lifetimes/raw/raw-lt-invalid-raw-id.rs @@ -0,0 +1,20 @@ +//@ edition: 2021 + +// Reject raw lifetimes with identifier parts that wouldn't be valid raw identifiers. + +macro_rules! w { + ($tt:tt) => {}; +} + +w!('r#_); +//~^ ERROR `_` cannot be a raw lifetime +w!('r#self); +//~^ ERROR `self` cannot be a raw lifetime +w!('r#super); +//~^ ERROR `super` cannot be a raw lifetime +w!('r#Self); +//~^ ERROR `Self` cannot be a raw lifetime +w!('r#crate); +//~^ ERROR `crate` cannot be a raw lifetime + +fn main() {} diff --git a/tests/ui/lifetimes/raw/raw-lt-invalid-raw-id.stderr b/tests/ui/lifetimes/raw/raw-lt-invalid-raw-id.stderr new file mode 100644 index 0000000000000..4cbb89b7a558b --- /dev/null +++ b/tests/ui/lifetimes/raw/raw-lt-invalid-raw-id.stderr @@ -0,0 +1,32 @@ +error: `_` cannot be a raw lifetime + --> $DIR/raw-lt-invalid-raw-id.rs:9:4 + | +LL | w!('r#_); + | ^^^^ + +error: `self` cannot be a raw lifetime + --> $DIR/raw-lt-invalid-raw-id.rs:11:4 + | +LL | w!('r#self); + | ^^^^^^^ + +error: `super` cannot be a raw lifetime + --> $DIR/raw-lt-invalid-raw-id.rs:13:4 + | +LL | w!('r#super); + | ^^^^^^^^ + +error: `Self` cannot be a raw lifetime + --> $DIR/raw-lt-invalid-raw-id.rs:15:4 + | +LL | w!('r#Self); + | ^^^^^^^ + +error: `crate` cannot be a raw lifetime + --> $DIR/raw-lt-invalid-raw-id.rs:17:4 + | +LL | w!('r#crate); + | ^^^^^^^^ + +error: aborting due to 5 previous errors + From aa203c9fa0a8f3ef33fb29aa6b1d126043d92368 Mon Sep 17 00:00:00 2001 From: Jieyou Xu Date: Sun, 17 Nov 2024 00:33:40 +0800 Subject: [PATCH 2179/2194] Update cdb annotations for `numeric-types` with cdb `10.0.26100.2161` (cherry picked from commit 150327959386b1b71a59d57b29b4fda82f8eddbe) --- tests/debuginfo/numeric-types.rs | 61 +++++++++++++++++--------------- 1 file changed, 32 insertions(+), 29 deletions(-) diff --git a/tests/debuginfo/numeric-types.rs b/tests/debuginfo/numeric-types.rs index 9d232578979f9..ad0bca9bb7789 100644 --- a/tests/debuginfo/numeric-types.rs +++ b/tests/debuginfo/numeric-types.rs @@ -2,6 +2,11 @@ //@ ignore-windows-gnu: #128981 +// Note: u128 visualization was not supported in 10.0.22621.3233 but was fixed in 10.0.26100.2161. +// FIXME(jieyouxu): triple-check if this annotation works properly in CI, because it seems to +// ignore the test locally for me. +//@ min-cdb-version: 10.0.26100.2161 + // Tests the visualizations for `NonZero`, `Wrapping` and // `Atomic{Bool,I8,I16,I32,I64,Isize,U8,U16,U32,U64,Usize}` located in `libcore.natvis`. @@ -48,8 +53,8 @@ // cdb-check:nz_u64 : 0x64 [Type: core::num::nonzero::NonZero] // cdb-check: [] [Type: core::num::nonzero::NonZero] -// 128-bit integers don't seem to work in CDB // cdb-command: dx nz_u128 +// cdb-check:nz_u128 : 111 [Type: core::num::nonzero::NonZero] // cdb-check: [] [Type: core::num::nonzero::NonZero] // cdb-command: dx nz_usize @@ -58,101 +63,99 @@ // cdb-command: dx w_i8 // cdb-check:w_i8 : 10 [Type: core::num::wrapping::Wrapping] -// cdb-check: [] [Type: core::num::wrapping::Wrapping] +// cdb-check: [+0x000] __0 : 10 [Type: char] // cdb-command: dx w_i16 // cdb-check:w_i16 : 20 [Type: core::num::wrapping::Wrapping] -// cdb-check: [] [Type: core::num::wrapping::Wrapping] +// cdb-check: [+0x000] __0 : 20 [Type: short] // cdb-command: dx w_i32 // cdb-check:w_i32 : 30 [Type: core::num::wrapping::Wrapping] -// cdb-check: [] [Type: core::num::wrapping::Wrapping] +// cdb-check: [+0x000] __0 : 30 [Type: int] // cdb-command: dx w_i64 // cdb-check:w_i64 : 40 [Type: core::num::wrapping::Wrapping] -// cdb-check: [] [Type: core::num::wrapping::Wrapping] +// cdb-check: [+0x000] __0 : 40 [Type: __int64] -// 128-bit integers don't seem to work in CDB // cdb-command: dx w_i128 -// cdb-check:w_i128 [Type: core::num::wrapping::Wrapping] -// cdb-check: [] [Type: core::num::wrapping::Wrapping] +// cdb-check:w_i128 : 50 [Type: core::num::wrapping::Wrapping] +// cdb-check: [+0x000] __0 : 50 [Type: i128] // cdb-command: dx w_isize // cdb-check:w_isize : 60 [Type: core::num::wrapping::Wrapping] -// cdb-check: [] [Type: core::num::wrapping::Wrapping] +// cdb-check: [+0x000] __0 : 60 [Type: __int64] // cdb-command: dx w_u8 // cdb-check:w_u8 : 0x46 [Type: core::num::wrapping::Wrapping] -// cdb-check: [] [Type: core::num::wrapping::Wrapping] +// cdb-check: [+0x000] __0 : 0x46 [Type: unsigned char] // cdb-command: dx w_u16 // cdb-check:w_u16 : 0x50 [Type: core::num::wrapping::Wrapping] -// cdb-check: [] [Type: core::num::wrapping::Wrapping] +// cdb-check: [+0x000] __0 : 0x50 [Type: unsigned short] // cdb-command: dx w_u32 // cdb-check:w_u32 : 0x5a [Type: core::num::wrapping::Wrapping] -// cdb-check: [] [Type: core::num::wrapping::Wrapping] +// cdb-check: [+0x000] __0 : 0x5a [Type: unsigned int] // cdb-command: dx w_u64 // cdb-check:w_u64 : 0x64 [Type: core::num::wrapping::Wrapping] -// cdb-check: [] [Type: core::num::wrapping::Wrapping] +// cdb-check: [+0x000] __0 : 0x64 [Type: unsigned __int64] -// 128-bit integers don't seem to work in CDB // cdb-command: dx w_u128 -// cdb-check:w_u128 [Type: core::num::wrapping::Wrapping] -// cdb-check: [] [Type: core::num::wrapping::Wrapping] +// cdb-check:w_u128 : 110 [Type: core::num::wrapping::Wrapping] +// cdb-check: [+0x000] __0 : 110 [Type: u128] // cdb-command: dx w_usize // cdb-check:w_usize : 0x78 [Type: core::num::wrapping::Wrapping] -// cdb-check: [] [Type: core::num::wrapping::Wrapping] +// cdb-check: [+0x000] __0 : 0x78 [Type: unsigned __int64] // cdb-command: dx a_bool_t // cdb-check:a_bool_t : true [Type: core::sync::atomic::AtomicBool] -// cdb-check: [] [Type: core::sync::atomic::AtomicBool] +// cdb-check: [+0x000] v : 0x1 [Type: core::cell::UnsafeCell] // cdb-command: dx a_bool_f // cdb-check:a_bool_f : false [Type: core::sync::atomic::AtomicBool] -// cdb-check: [] [Type: core::sync::atomic::AtomicBool] +// cdb-check: [+0x000] v : 0x0 [Type: core::cell::UnsafeCell] // cdb-command: dx a_i8 // cdb-check:a_i8 : 2 [Type: core::sync::atomic::AtomicI8] -// cdb-check: [] [Type: core::sync::atomic::AtomicI8] +// cdb-check: [+0x000] v : 2 [Type: core::cell::UnsafeCell] // cdb-command: dx a_i16 // cdb-check:a_i16 : 4 [Type: core::sync::atomic::AtomicI16] -// cdb-check: [] [Type: core::sync::atomic::AtomicI16] +// cdb-check: [+0x000] v : 4 [Type: core::cell::UnsafeCell] // cdb-command: dx a_i32 // cdb-check:a_i32 : 8 [Type: core::sync::atomic::AtomicI32] -// cdb-check: [] [Type: core::sync::atomic::AtomicI32] +// cdb-check: [+0x000] v : 8 [Type: core::cell::UnsafeCell] // cdb-command: dx a_i64 // cdb-check:a_i64 : 16 [Type: core::sync::atomic::AtomicI64] -// cdb-check: [] [Type: core::sync::atomic::AtomicI64] +// cdb-check: [+0x000] v : 16 [Type: core::cell::UnsafeCell] // cdb-command: dx a_isize // cdb-check:a_isize : 32 [Type: core::sync::atomic::AtomicIsize] -// cdb-check: [] [Type: core::sync::atomic::AtomicIsize] +// cdb-check: [+0x000] v : 32 [Type: core::cell::UnsafeCell] // cdb-command: dx a_u8 // cdb-check:a_u8 : 0x40 [Type: core::sync::atomic::AtomicU8] -// cdb-check: [] [Type: core::sync::atomic::AtomicU8] +// cdb-check: [+0x000] v : 0x40 [Type: core::cell::UnsafeCell] // cdb-command: dx a_u16 // cdb-check:a_u16 : 0x80 [Type: core::sync::atomic::AtomicU16] -// cdb-check: [] [Type: core::sync::atomic::AtomicU16] +// cdb-check: [+0x000] v : 0x80 [Type: core::cell::UnsafeCell] // cdb-command: dx a_u32 // cdb-check:a_u32 : 0x100 [Type: core::sync::atomic::AtomicU32] -// cdb-check: [] [Type: core::sync::atomic::AtomicU32] +// cdb-check: [+0x000] v : 0x100 [Type: core::cell::UnsafeCell] // cdb-command: dx a_u64 // cdb-check:a_u64 : 0x200 [Type: core::sync::atomic::AtomicU64] -// cdb-check: [] [Type: core::sync::atomic::AtomicU64] +// cdb-check: [+0x000] v : 0x200 [Type: core::cell::UnsafeCell] // cdb-command: dx a_usize // cdb-check:a_usize : 0x400 [Type: core::sync::atomic::AtomicUsize] -// cdb-check: [] [Type: core::sync::atomic::AtomicUsize] +// cdb-check: [+0x000] v : 0x400 [Type: core::cell::UnsafeCell] // === GDB TESTS =================================================================================== From a3021df4987e8306e4eb5536e6f19df1134b7416 Mon Sep 17 00:00:00 2001 From: Jieyou Xu Date: Sun, 17 Nov 2024 00:42:30 +0800 Subject: [PATCH 2180/2194] Update cdb annotations for `range-types.rs` with cdb `10.0.26100.2161` (cherry picked from commit 94f3dcf6016203dff3c4033f3024e8a69dc2d757) --- tests/debuginfo/range-types.rs | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/tests/debuginfo/range-types.rs b/tests/debuginfo/range-types.rs index 8c18fd9addd48..068a55a576725 100644 --- a/tests/debuginfo/range-types.rs +++ b/tests/debuginfo/range-types.rs @@ -1,7 +1,10 @@ // Testing the display of range types in cdb. -// cdb-only -//@ min-cdb-version: 10.0.18317.1001 +//@ only-cdb + +// FIXME(jieyouxu): triple check in CI if the directive actually works +//@ min-cdb-version: 10.0.26100.2161 + //@ compile-flags:-g // === CDB TESTS ================================================================================== @@ -10,23 +13,26 @@ // cdb-command: dx r1,d // cdb-check:r1,d : (3..5) [Type: core::ops::range::Range] -// cdb-check: [] [Type: core::ops::range::Range] +// cdb-check: [+0x000] start : 3 [Type: int] +// cdb-check: [+0x004] end : 5 [Type: int] // cdb-command: dx r2,d // cdb-check:r2,d : (2..) [Type: core::ops::range::RangeFrom] -// cdb-check: [] [Type: core::ops::range::RangeFrom] +// cdb-check: [+0x000] start : 2 [Type: int] // cdb-command: dx r3,d // cdb-check:r3,d : (1..=4) [Type: core::ops::range::RangeInclusive] -// cdb-check: [] [Type: core::ops::range::RangeInclusive] +// cdb-check: [+0x000] start : 1 [Type: int] +// cdb-check: [+0x004] end : 4 [Type: int] +// cdb-check: [+0x008] exhausted : false [Type: bool] // cdb-command: dx r4,d // cdb-check:r4,d : (..10) [Type: core::ops::range::RangeTo] -// cdb-check: [] [Type: core::ops::range::RangeTo] +// cdb-check: [+0x000] end : 10 [Type: int] // cdb-command: dx r5,d // cdb-check:r5,d : (..=3) [Type: core::ops::range::RangeToInclusive] -// cdb-check: [] [Type: core::ops::range::RangeToInclusive] +// cdb-check: [+0x000] end : 3 [Type: int] // cdb-command: dx r6,d // cdb-check:r6,d [Type: core::ops::range::RangeFull] From 088f06a38337e03dabc8a99f7dfd5c7135e1ed6a Mon Sep 17 00:00:00 2001 From: Jieyou Xu Date: Sun, 17 Nov 2024 00:50:54 +0800 Subject: [PATCH 2181/2194] Update cdb annotations for `unit-type.rs` with cdb `10.0.26100.2161` (cherry picked from commit e70df0909a9f35b4138ac78ffc16fe5a9fb05d00) --- tests/debuginfo/unit-type.rs | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/tests/debuginfo/unit-type.rs b/tests/debuginfo/unit-type.rs index 42c0ff11f7113..0ffa2fe490a5e 100644 --- a/tests/debuginfo/unit-type.rs +++ b/tests/debuginfo/unit-type.rs @@ -1,5 +1,8 @@ //@ compile-flags:-g +// FIXME(jieyouxu): triple check if this works in CI +//@ min-cdb-version: 10.0.26100.2161 + // === GDB TESTS =================================================================================== // gdb-command: run @@ -26,18 +29,18 @@ // cdb-check: Breakpoint 0 hit // cdb-command: dx _ref -// cdb-check: _ref : 0x[...] : () [Type: tuple$<> *] +// cdb-check: _ref : 0x[...] [Type: tuple$<> *] // cdb-command: dx _ptr -// cdb-check: _ptr : 0x[...] : () [Type: tuple$<> *] +// cdb-check: _ptr : 0x[...] [Type: tuple$<> *] // cdb-command: dx _local -// cdb-check: _local : () [Type: tuple$<>] +// cdb-check: _local [Type: tuple$<>] // cdb-command: dx _field,d // cdb-check: _field,d [Type: unit_type::_TypeContainingUnitField] // cdb-check: [+0x[...]] _a : 123 [Type: unsigned int] -// cdb-check: [+0x[...]] _unit : () [Type: tuple$<>] +// cdb-check: [+0x[...]] _unit [Type: tuple$<>] // cdb-check: [+0x[...]] _b : 456 [Type: unsigned __int64] // Check that we can cast "void pointers" to their actual type in the debugger From 8435c75fa5e5172b6cd41ca50e3752680abe08df Mon Sep 17 00:00:00 2001 From: Jieyou Xu Date: Sun, 17 Nov 2024 04:16:59 +0800 Subject: [PATCH 2182/2194] Mark `numeric-types.rs` as 64-bit only for now This is to unblock the tree, a proper fix will need to be investigated. I think the debuginfo test suite supports revisions, however debugger directives do not respect such revisions, which is problematic. It's that 32-bit and 64-bit msvc of course have different integer widths for `isize` and `usize`, meaning their underlying integer is different and thus printed differently. (cherry picked from commit dccb6c0f279ebec551382bdb36db97622fca324b) --- tests/debuginfo/numeric-types.rs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/tests/debuginfo/numeric-types.rs b/tests/debuginfo/numeric-types.rs index ad0bca9bb7789..9a0fd01d7e236 100644 --- a/tests/debuginfo/numeric-types.rs +++ b/tests/debuginfo/numeric-types.rs @@ -3,8 +3,11 @@ //@ ignore-windows-gnu: #128981 // Note: u128 visualization was not supported in 10.0.22621.3233 but was fixed in 10.0.26100.2161. -// FIXME(jieyouxu): triple-check if this annotation works properly in CI, because it seems to -// ignore the test locally for me. + +// FIXME(#133107): this is temporarily marked as `only-64bit` because of course 32-bit msvc has +// a different integer width and thus underlying integer type display. Only marked as such to +// unblock the tree. +//@ only-64bit //@ min-cdb-version: 10.0.26100.2161 // Tests the visualizations for `NonZero`, `Wrapping` and From 3ccf055dccec14557ce0361dbd7ef648ae51ca9a Mon Sep 17 00:00:00 2001 From: Boxy Date: Mon, 25 Nov 2024 11:30:19 +0000 Subject: [PATCH 2183/2194] notes from master --- RELEASES.md | 407 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 407 insertions(+) diff --git a/RELEASES.md b/RELEASES.md index b49470c307569..d177e96f39813 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -1,3 +1,410 @@ +Version 1.83.0 (2024-11-28) +========================== + + + +Language +-------- +- [Stabilize `&mut`, `*mut`, `&Cell`, and `*const Cell` in const.](https://github.com/rust-lang/rust/pull/129195) +- [Allow creating references to statics in `const` initializers.](https://github.com/rust-lang/rust/pull/129759) +- [Implement raw lifetimes and labels (`'r#ident`).](https://github.com/rust-lang/rust/pull/126452) +- [Define behavior when atomic and non-atomic reads race.](https://github.com/rust-lang/rust/pull/128778) +- [Non-exhaustive structs may now be empty.](https://github.com/rust-lang/rust/pull/128934) +- [Disallow implicit coercions from places of type `!`](https://github.com/rust-lang/rust/pull/129392) +- [`const extern` functions can now be defined for other calling conventions.](https://github.com/rust-lang/rust/pull/129753) +- [Stabilize `expr_2021` macro fragment specifier in all editions.](https://github.com/rust-lang/rust/pull/129972) +- [The `non_local_definitions` lint now fires on less code and warns by default.](https://github.com/rust-lang/rust/pull/127117) + + + + +Compiler +-------- +- [Deprecate unsound `-Csoft-float` flag.](https://github.com/rust-lang/rust/pull/129897) +- Add many new tier 3 targets: + - [`aarch64_unknown_nto_qnx700`](https://github.com/rust-lang/rust/pull/127897) + - [`arm64e-apple-tvos`](https://github.com/rust-lang/rust/pull/130614) + - [`armv7-rtems-eabihf`](https://github.com/rust-lang/rust/pull/127021) + - [`loongarch64-unknown-linux-ohos`](https://github.com/rust-lang/rust/pull/130750) + - [`riscv32-wrs-vxworks` and `riscv64-wrs-vxworks`](https://github.com/rust-lang/rust/pull/130549) + - [`riscv32{e|em|emc}-unknown-none-elf`](https://github.com/rust-lang/rust/pull/130555) + - [`x86_64-unknown-hurd-gnu`](https://github.com/rust-lang/rust/pull/128345) + - [`x86_64-unknown-trusty`](https://github.com/rust-lang/rust/pull/130453) + +Refer to Rust's [platform support page][platform-support-doc] +for more information on Rust's tiered platform support. + + + + +Libraries +--------- +- [Implement `PartialEq` for `ExitCode`.](https://github.com/rust-lang/rust/pull/127633) +- [Document that `catch_unwind` can deal with foreign exceptions without UB, although the exact behavior is unspecified.](https://github.com/rust-lang/rust/pull/128321) +- [Implement `Default` for `HashMap`/`HashSet` iterators that don't already have it.](https://github.com/rust-lang/rust/pull/128711) +- [Bump Unicode to version 16.0.0.](https://github.com/rust-lang/rust/pull/130183) +- [Change documentation of `ptr::add`/`sub` to not claim equivalence with `offset`.](https://github.com/rust-lang/rust/pull/130229). + + + + +Stabilized APIs +--------------- + +- [`BufRead::skip_until`](https://doc.rust-lang.org/stable/std/io/trait.BufRead.html#method.skip_until) +- [`ControlFlow::break_value`](https://doc.rust-lang.org/stable/core/ops/enum.ControlFlow.html#method.break_value) +- [`ControlFlow::continue_value`](https://doc.rust-lang.org/stable/core/ops/enum.ControlFlow.html#method.continue_value) +- [`ControlFlow::map_break`](https://doc.rust-lang.org/stable/core/ops/enum.ControlFlow.html#method.map_break) +- [`ControlFlow::map_continue`](https://doc.rust-lang.org/stable/core/ops/enum.ControlFlow.html#method.map_continue) +- [`DebugList::finish_non_exhaustive`](https://doc.rust-lang.org/stable/core/fmt/struct.DebugList.html#method.finish_non_exhaustive) +- [`DebugMap::finish_non_exhaustive`](https://doc.rust-lang.org/stable/core/fmt/struct.DebugMap.html#method.finish_non_exhaustive) +- [`DebugSet::finish_non_exhaustive`](https://doc.rust-lang.org/stable/core/fmt/struct.DebugSet.html#method.finish_non_exhaustive) +- [`DebugTuple::finish_non_exhaustive`](https://doc.rust-lang.org/stable/core/fmt/struct.DebugTuple.html#method.finish_non_exhaustive) +- [`ErrorKind::ArgumentListTooLong`](https://doc.rust-lang.org/stable/std/io/enum.ErrorKind.html#variant.ArgumentListTooLong) +- [`ErrorKind::Deadlock`](https://doc.rust-lang.org/stable/std/io/enum.ErrorKind.html#variant.Deadlock) +- [`ErrorKind::DirectoryNotEmpty`](https://doc.rust-lang.org/stable/std/io/enum.ErrorKind.html#variant.DirectoryNotEmpty) +- [`ErrorKind::ExecutableFileBusy`](https://doc.rust-lang.org/stable/std/io/enum.ErrorKind.html#variant.ExecutableFileBusy) +- [`ErrorKind::FileTooLarge`](https://doc.rust-lang.org/stable/std/io/enum.ErrorKind.html#variant.FileTooLarge) +- [`ErrorKind::HostUnreachable`](https://doc.rust-lang.org/stable/std/io/enum.ErrorKind.html#variant.HostUnreachable) +- [`ErrorKind::IsADirectory`](https://doc.rust-lang.org/stable/std/io/enum.ErrorKind.html#variant.IsADirectory) +- [`ErrorKind::NetworkDown`](https://doc.rust-lang.org/stable/std/io/enum.ErrorKind.html#variant.NetworkDown) +- [`ErrorKind::NetworkUnreachable`](https://doc.rust-lang.org/stable/std/io/enum.ErrorKind.html#variant.NetworkUnreachable) +- [`ErrorKind::NotADirectory`](https://doc.rust-lang.org/stable/std/io/enum.ErrorKind.html#variant.NotADirectory) +- [`ErrorKind::NotSeekable`](https://doc.rust-lang.org/stable/std/io/enum.ErrorKind.html#variant.NotSeekable) +- [`ErrorKind::ReadOnlyFilesystem`](https://doc.rust-lang.org/stable/std/io/enum.ErrorKind.html#variant.ReadOnlyFilesystem) +- [`ErrorKind::ResourceBusy`](https://doc.rust-lang.org/stable/std/io/enum.ErrorKind.html#variant.ResourceBusy) +- [`ErrorKind::StaleNetworkFileHandle`](https://doc.rust-lang.org/stable/std/io/enum.ErrorKind.html#variant.StaleNetworkFileHandle) +- [`ErrorKind::StorageFull`](https://doc.rust-lang.org/stable/std/io/enum.ErrorKind.html#variant.StorageFull) +- [`ErrorKind::TooManyLinks`](https://doc.rust-lang.org/stable/std/io/enum.ErrorKind.html#variant.TooManyLinks) +- [`Option::get_or_insert_default`](https://doc.rust-lang.org/stable/core/option/enum.Option.html#method.get_or_insert_default) +- [`Waker::data`](https://doc.rust-lang.org/stable/core/task/struct.Waker.html#method.data) +- [`Waker::new`](https://doc.rust-lang.org/stable/core/task/struct.Waker.html#method.new) +- [`Waker::vtable`](https://doc.rust-lang.org/stable/core/task/struct.Waker.html#method.vtable) +- [`char::MIN`](https://doc.rust-lang.org/stable/core/primitive.char.html#associatedconstant.MIN) +- [`hash_map::Entry::insert_entry`](https://doc.rust-lang.org/stable/std/collections/hash_map/enum.Entry.html#method.insert_entry) +- [`hash_map::VacantEntry::insert_entry`](https://doc.rust-lang.org/stable/std/collections/hash_map/struct.VacantEntry.html#method.insert_entry) + +These APIs are now stable in const contexts: + +- [`Cell::into_inner`](https://doc.rust-lang.org/stable/core/cell/struct.Cell.html#method.into_inner) +- [`Duration::as_secs_f32`](https://doc.rust-lang.org/stable/core/time/struct.Duration.html#method.as_secs_f32) +- [`Duration::as_secs_f64`](https://doc.rust-lang.org/stable/core/time/struct.Duration.html#method.as_secs_f64) +- [`Duration::div_duration_f32`](https://doc.rust-lang.org/stable/core/time/struct.Duration.html#method.div_duration_f32) +- [`Duration::div_duration_f64`](https://doc.rust-lang.org/stable/core/time/struct.Duration.html#method.div_duration_f64) +- [`MaybeUninit::as_mut_ptr`](https://doc.rust-lang.org/stable/core/mem/union.MaybeUninit.html#method.as_mut_ptr) +- [`NonNull::as_mut`](https://doc.rust-lang.org/stable/core/ptr/struct.NonNull.html#method.as_mut) +- [`NonNull::copy_from`](https://doc.rust-lang.org/stable/core/ptr/struct.NonNull.html#method.copy_from) +- [`NonNull::copy_from_nonoverlapping`](https://doc.rust-lang.org/stable/core/ptr/struct.NonNull.html#method.copy_from_nonoverlapping) +- [`NonNull::copy_to`](https://doc.rust-lang.org/stable/core/ptr/struct.NonNull.html#method.copy_to) +- [`NonNull::copy_to_nonoverlapping`](https://doc.rust-lang.org/stable/core/ptr/struct.NonNull.html#method.copy_to_nonoverlapping) +- [`NonNull::slice_from_raw_parts`](https://doc.rust-lang.org/stable/core/ptr/struct.NonNull.html#method.slice_from_raw_parts) +- [`NonNull::write`](https://doc.rust-lang.org/stable/core/ptr/struct.NonNull.html#method.write) +- [`NonNull::write_bytes`](https://doc.rust-lang.org/stable/core/ptr/struct.NonNull.html#method.write_bytes) +- [`NonNull::write_unaligned`](https://doc.rust-lang.org/stable/core/ptr/struct.NonNull.html#method.write_unaligned) +- [`OnceCell::into_inner`](https://doc.rust-lang.org/stable/core/cell/struct.OnceCell.html#method.into_inner) +- [`Option::as_mut`](https://doc.rust-lang.org/stable/core/option/enum.Option.html#method.as_mut) +- [`Option::expect`](https://doc.rust-lang.org/stable/core/option/enum.Option.html#method.expect) +- [`Option::replace`](https://doc.rust-lang.org/stable/core/option/enum.Option.html#method.replace) +- [`Option::take`](https://doc.rust-lang.org/stable/core/option/enum.Option.html#method.take) +- [`Option::unwrap`](https://doc.rust-lang.org/stable/core/option/enum.Option.html#method.unwrap) +- [`Option::unwrap_unchecked`](https://doc.rust-lang.org/stable/core/option/enum.Option.html#method.unwrap_unchecked) +- [`Option::<&_>::copied`](https://doc.rust-lang.org/stable/core/option/enum.Option.html#method.copied) +- [`Option::<&mut _>::copied`](https://doc.rust-lang.org/stable/core/option/enum.Option.html#method.copied-1) +- [`Option::>::flatten`](https://doc.rust-lang.org/stable/core/option/enum.Option.html#method.flatten) +- [`Option::>::transpose`](https://doc.rust-lang.org/stable/core/option/enum.Option.html#method.transpose) +- [`RefCell::into_inner`](https://doc.rust-lang.org/stable/core/cell/struct.RefCell.html#method.into_inner) +- [`Result::as_mut`](https://doc.rust-lang.org/stable/core/result/enum.Result.html#method.as_mut) +- [`Result::<&_, _>::copied`](https://doc.rust-lang.org/stable/core/result/enum.Result.html#method.copied) +- [`Result::<&mut _, _>::copied`](https://doc.rust-lang.org/stable/core/result/enum.Result.html#method.copied-1) +- [`Result::, _>::transpose`](https://doc.rust-lang.org/stable/core/result/enum.Result.html#method.transpose) +- [`UnsafeCell::get_mut`](https://doc.rust-lang.org/stable/core/cell/struct.UnsafeCell.html#method.get_mut) +- [`UnsafeCell::into_inner`](https://doc.rust-lang.org/stable/core/cell/struct.UnsafeCell.html#method.into_inner) +- [`array::from_mut`](https://doc.rust-lang.org/stable/core/array/fn.from_mut.html) +- [`char::encode_utf8`](https://doc.rust-lang.org/stable/core/primitive.char.html#method.encode_utf8) +- [`{float}::classify`](https://doc.rust-lang.org/stable/core/primitive.f64.html#method.classify) +- [`{float}::is_finite`](https://doc.rust-lang.org/stable/core/primitive.f64.html#method.is_finite) +- [`{float}::is_infinite`](https://doc.rust-lang.org/stable/core/primitive.f64.html#method.is_infinite) +- [`{float}::is_nan`](https://doc.rust-lang.org/stable/core/primitive.f64.html#method.is_nan) +- [`{float}::is_normal`](https://doc.rust-lang.org/stable/core/primitive.f64.html#method.is_normal) +- [`{float}::is_sign_negative`](https://doc.rust-lang.org/stable/core/primitive.f64.html#method.is_sign_negative) +- [`{float}::is_sign_positive`](https://doc.rust-lang.org/stable/core/primitive.f64.html#method.is_sign_positive) +- [`{float}::is_subnormal`](https://doc.rust-lang.org/stable/core/primitive.f64.html#method.is_subnormal) +- [`{float}::from_bits`](https://doc.rust-lang.org/stable/core/primitive.f64.html#method.from_bits) +- [`{float}::from_be_bytes`](https://doc.rust-lang.org/stable/core/primitive.f64.html#method.from_be_bytes) +- [`{float}::from_le_bytes`](https://doc.rust-lang.org/stable/core/primitive.f64.html#method.from_le_bytes) +- [`{float}::from_ne_bytes`](https://doc.rust-lang.org/stable/core/primitive.f64.html#method.from_ne_bytes) +- [`{float}::to_bits`](https://doc.rust-lang.org/stable/core/primitive.f64.html#method.to_bits) +- [`{float}::to_be_bytes`](https://doc.rust-lang.org/stable/core/primitive.f64.html#method.to_be_bytes) +- [`{float}::to_le_bytes`](https://doc.rust-lang.org/stable/core/primitive.f64.html#method.to_le_bytes) +- [`{float}::to_ne_bytes`](https://doc.rust-lang.org/stable/core/primitive.f64.html#method.to_ne_bytes) +- [`mem::replace`](https://doc.rust-lang.org/stable/core/mem/fn.replace.html) +- [`ptr::replace`](https://doc.rust-lang.org/stable/core/ptr/fn.replace.html) +- [`ptr::slice_from_raw_parts_mut`](https://doc.rust-lang.org/stable/core/ptr/fn.slice_from_raw_parts_mut.html) +- [`ptr::write`](https://doc.rust-lang.org/stable/core/ptr/fn.write.html) +- [`ptr::write_unaligned`](https://doc.rust-lang.org/stable/core/ptr/fn.write_unaligned.html) +- [`<*const _>::copy_to`](https://doc.rust-lang.org/stable/core/primitive.pointer.html#method.copy_to) +- [`<*const _>::copy_to_nonoverlapping`](https://doc.rust-lang.org/stable/core/primitive.pointer.html#method.copy_to_nonoverlapping) +- [`<*mut _>::copy_from`](https://doc.rust-lang.org/stable/core/primitive.pointer.html#method.copy_from) +- [`<*mut _>::copy_from_nonoverlapping`](https://doc.rust-lang.org/stable/core/primitive.pointer.html#method.copy_from_nonoverlapping) +- [`<*mut _>::copy_to`](https://doc.rust-lang.org/stable/core/primitive.pointer.html#method.copy_to-1) +- [`<*mut _>::copy_to_nonoverlapping`](https://doc.rust-lang.org/stable/core/primitive.pointer.html#method.copy_to_nonoverlapping-1) +- [`<*mut _>::write`](https://doc.rust-lang.org/stable/core/primitive.pointer.html#method.write) +- [`<*mut _>::write_bytes`](https://doc.rust-lang.org/stable/core/primitive.pointer.html#method.write_bytes) +- [`<*mut _>::write_unaligned`](https://doc.rust-lang.org/stable/core/primitive.pointer.html#method.write_unaligned) +- [`slice::from_mut`](https://doc.rust-lang.org/stable/core/slice/fn.from_mut.html) +- [`slice::from_raw_parts_mut`](https://doc.rust-lang.org/stable/core/slice/fn.from_raw_parts_mut.html) +- [`<[_]>::first_mut`](https://doc.rust-lang.org/stable/core/primitive.slice.html#method.first_mut) +- [`<[_]>::last_mut`](https://doc.rust-lang.org/stable/core/primitive.slice.html#method.last_mut) +- [`<[_]>::first_chunk_mut`](https://doc.rust-lang.org/stable/core/primitive.slice.html#method.first_chunk_mut) +- [`<[_]>::last_chunk_mut`](https://doc.rust-lang.org/stable/core/primitive.slice.html#method.last_chunk_mut) +- [`<[_]>::split_at_mut`](https://doc.rust-lang.org/stable/core/primitive.slice.html#method.split_at_mut) +- [`<[_]>::split_at_mut_checked`](https://doc.rust-lang.org/stable/core/primitive.slice.html#method.split_at_mut_checked) +- [`<[_]>::split_at_mut_unchecked`](https://doc.rust-lang.org/stable/core/primitive.slice.html#method.split_at_mut_unchecked) +- [`<[_]>::split_first_mut`](https://doc.rust-lang.org/stable/core/primitive.slice.html#method.split_first_mut) +- [`<[_]>::split_last_mut`](https://doc.rust-lang.org/stable/core/primitive.slice.html#method.split_last_mut) +- [`<[_]>::split_first_chunk_mut`](https://doc.rust-lang.org/stable/core/primitive.slice.html#method.split_first_chunk_mut) +- [`<[_]>::split_last_chunk_mut`](https://doc.rust-lang.org/stable/core/primitive.slice.html#method.split_last_chunk_mut) +- [`str::as_bytes_mut`](https://doc.rust-lang.org/stable/core/primitive.str.html#method.as_bytes_mut) +- [`str::as_mut_ptr`](https://doc.rust-lang.org/stable/core/primitive.str.html#method.as_mut_ptr) +- [`str::from_utf8_unchecked_mut`](https://doc.rust-lang.org/stable/core/str/fn.from_utf8_unchecked_mut.html) + + + + +Cargo +----- +- [Introduced a new `CARGO_MANIFEST_PATH` environment variable, similar to `CARGO_MANIFEST_DIR` but pointing directly to the manifest file.](https://github.com/rust-lang/cargo/pull/14404/) +- [Added `package.autolib` to the manifest, allowing `[lib]` auto-discovery to be disabled.](https://github.com/rust-lang/cargo/pull/14591/) +- [Declare support level for each crate in Cargo's Charter / crate docs.](https://github.com/rust-lang/cargo/pull/14600/) +- [Declare new Intentional Artifacts as 'small' changes.](https://github.com/rust-lang/cargo/pull/14599/) + + + + +Rustdoc +------- + +- [The sidebar / hamburger menu table of contents now includes the `# headers` from the main item's doc comment](https://github.com/rust-lang/rust/pull/120736). This is similar to a third-party feature provided by the rustdoc-search-enhancements browser extension. + + + + +Compatibility Notes +------------------- +- [Warn against function pointers using unsupported ABI strings.](https://github.com/rust-lang/rust/pull/128784) +- [Check well-formedness of the source type's signature in fn pointer casts.](https://github.com/rust-lang/rust/pull/129021) This partly closes a soundness hole that comes when casting a function item to function pointer +- [Use equality instead of subtyping when resolving type dependent paths.](https://github.com/rust-lang/rust/pull/129073) +- Linking on macOS now correctly includes Rust's default deployment target. Due to a linker bug, you might have to pass `MACOSX_DEPLOYMENT_TARGET` or fix your `#[link]` attributes to point to the correct frameworks. See . +- [Rust will now correctly raise an error for `repr(Rust)` written on non-`struct`/`enum`/`union` items, since it previous did not have any effect.](https://github.com/rust-lang/rust/pull/129422) +- The future incompatibility lint `deprecated_cfg_attr_crate_type_name` [has been made into a hard error](https://github.com/rust-lang/rust/pull/129670). It was used to deny usage of `#![crate_type]` and `#![crate_name]` attributes in `#![cfg_attr]`, which required a hack in the compiler to be able to change the used crate type and crate name after cfg expansion. + Users can use `--crate-type` instead of `#![cfg_attr(..., crate_type = "...")]` and `--crate-name` instead of `#![cfg_attr(..., crate_name = "...")]` when running `rustc`/`cargo rustc` on the command line. + Use of those two attributes outside of `#![cfg_attr]` continue to be fully supported. +- Until now, paths into the sysroot were always prefixed with `/rustc/$hash` in diagnostics, codegen, backtrace, e.g. + ``` + thread 'main' panicked at 'hello world', map-panic.rs:2:50 + stack backtrace: + 0: std::panicking::begin_panic + at /rustc/a55dd71d5fb0ec5a6a3a9e8c27b2127ba491ce52/library/std/src/panicking.rs:616:12 + 1: map_panic::main::{{closure}} + at ./map-panic.rs:2:50 + 2: core::option::Option::map + at /rustc/a55dd71d5fb0ec5a6a3a9e8c27b2127ba491ce52/library/core/src/option.rs:929:29 + 3: map_panic::main + at ./map-panic.rs:2:30 + 4: core::ops::function::FnOnce::call_once + at /rustc/a55dd71d5fb0ec5a6a3a9e8c27b2127ba491ce52/library/core/src/ops/function.rs:248:5 + note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace. + ``` + [RFC 3127 said](https://rust-lang.github.io/rfcs/3127-trim-paths.html#changing-handling-of-sysroot-path-in-rustc) + > We want to change this behaviour such that, when `rust-src` source files can be discovered, the virtual path is discarded and therefore the local path will be embedded, unless there is a `--remap-path-prefix` that causes this local path to be remapped in the usual way. + + [#129687](https://github.com/rust-lang/rust/pull/129687) implements this behaviour, when `rust-src` is present at compile time, `rustc` replaces `/rustc/$hash` with a real path into the local `rust-src` component with best effort. + To sanitize this, users must explicitly supply `--remap-path-prefix==foo` or not have the `rust-src` component installed. + - The allow-by-default `missing_docs` lint used to disable itself when invoked through `rustc --test`/`cargo test`, resulting in `#[expect(missing_docs)]` emitting false positives due to the expectation being wrongly unfulfilled. This behavior [has now been removed](https://github.com/rust-lang/rust/pull/130025), which allows `#[expect(missing_docs)]` to be fulfilled in all scenarios, but will also report new `missing_docs` diagnostics for publicly reachable `#[cfg(test)]` items, [integration test](https://doc.rust-lang.org/cargo/reference/cargo-targets.html#integration-tests) crate-level documentation, and publicly reachable items in integration tests. +- [The `armv8r-none-eabihf` target now uses the Armv8-R required set of floating-point features.](https://github.com/rust-lang/rust/pull/130295) +- [Fix a soundness bug where rustc wouldn't detect unconstrained higher-ranked lifetimes in a `dyn Trait`'s associated types that occur due to supertraits.](https://github.com/rust-lang/rust/pull/130367) +- [Update the minimum external LLVM version to 18.](https://github.com/rust-lang/rust/pull/130487) +- [Remove `aarch64-fuchsia` and `x86_64-fuchsia` target aliases in favor of `aarch64-unknown-fuchsia` and `x86_64-unknown-fuchsia` respectively.](https://github.com/rust-lang/rust/pull/130657) +- [The ABI-level exception class of a Rust panic is now encoded with native-endian bytes, so it is legible in hex dumps.](https://github.com/rust-lang/rust/pull/130897) +- [Visual Studio 2013 is no longer supported for MSVC targets.](https://github.com/rust-lang/rust/pull/131070) +- [The sysroot no longer contains the `std` dynamic library in its top-level `lib/` dir.](https://github.com/rust-lang/rust/pull/131188) + +Version 1.82.0 (2024-10-17) +========================== + + + +Language +-------- +- [Don't make statement nonterminals match pattern nonterminals](https://github.com/rust-lang/rust/pull/120221/) +- [Patterns matching empty types can now be omitted in common cases](https://github.com/rust-lang/rust/pull/122792) +- [Enforce supertrait outlives obligations when using trait impls](https://github.com/rust-lang/rust/pull/124336) +- [`addr_of(_mut)!` macros and the newly stabilized `&raw (const|mut)` are now safe to use with all static items](https://github.com/rust-lang/rust/pull/125834) +- [size_of_val_raw: for length 0 this is safe to call](https://github.com/rust-lang/rust/pull/126152/) +- [Reorder trait bound modifiers *after* `for<...>` binder in trait bounds](https://github.com/rust-lang/rust/pull/127054/) +- [Stabilize opaque type precise capturing (RFC 3617)](https://github.com/rust-lang/rust/pull/127672) +- [Stabilize `&raw const` and `&raw mut` operators (RFC 2582)](https://github.com/rust-lang/rust/pull/127679) +- [Stabilize unsafe extern blocks (RFC 3484)](https://github.com/rust-lang/rust/pull/127921) +- [Stabilize nested field access in `offset_of!`](https://github.com/rust-lang/rust/pull/128284) +- [Do not require `T` to be live when dropping `[T; 0]`](https://github.com/rust-lang/rust/pull/128438) +- [Stabilize `const` operands in inline assembly](https://github.com/rust-lang/rust/pull/128570) +- [Stabilize floating-point arithmetic in `const fn`](https://github.com/rust-lang/rust/pull/128596) +- [Stabilize explicit opt-in to unsafe attributes](https://github.com/rust-lang/rust/pull/128771) +- [Document NaN bit patterns guarantees](https://github.com/rust-lang/rust/pull/129559) + + + + +Compiler +-------- +- [Promote riscv64gc-unknown-linux-musl to tier 2](https://github.com/rust-lang/rust/pull/122049) +- [Promote Mac Catalyst targets `aarch64-apple-ios-macabi` and `x86_64-apple-ios-macabi` to Tier 2, and ship them with rustup](https://github.com/rust-lang/rust/pull/126450) +- [Add tier 3 NuttX based targets for RISC-V and ARM](https://github.com/rust-lang/rust/pull/127755) +- [Add tier 3 powerpc-unknown-linux-muslspe target](https://github.com/rust-lang/rust/pull/127905) +- [Improved diagnostics to explain why a pattern is unreachable](https://github.com/rust-lang/rust/pull/128034) +- [The compiler now triggers the unreachable code warning properly for async functions that don't return/are `-> !`](https://github.com/rust-lang/rust/pull/128443) +- [Promote `aarch64-apple-darwin` to Tier 1](https://github.com/rust-lang/rust/pull/128592) +- [Add Trusty OS target `aarch64-unknown-trusty` and `armv7-unknown-trusty` as tier 3 targets](https://github.com/rust-lang/rust/pull/129490) +- [Promote `wasm32-wasip2` to Tier 2.](https://github.com/rust-lang/rust/pull/126967/) + + + + +Libraries +--------- +- [Generalize `{Rc,Arc}::make_mut()` to `Path`, `OsStr`, and `CStr`.](https://github.com/rust-lang/rust/pull/126877) + + + +Stabilized APIs +--------------- + +- [`std::thread::Builder::spawn_unchecked`](https://doc.rust-lang.org/stable/std/thread/struct.Builder.html#method.spawn_unchecked) +- [`std::str::CharIndices::offset`](https://doc.rust-lang.org/nightly/std/str/struct.CharIndices.html#method.offset) +- [`std::option::Option::is_none_or`](https://doc.rust-lang.org/nightly/std/option/enum.Option.html#method.is_none_or) +- [`[T]::is_sorted`](https://doc.rust-lang.org/nightly/std/primitive.slice.html#method.is_sorted) +- [`[T]::is_sorted_by`](https://doc.rust-lang.org/nightly/std/primitive.slice.html#method.is_sorted_by) +- [`[T]::is_sorted_by_key`](https://doc.rust-lang.org/nightly/std/primitive.slice.html#method.is_sorted_by_key) +- [`Iterator::is_sorted`](https://doc.rust-lang.org/nightly/std/iter/trait.Iterator.html#method.is_sorted) +- [`Iterator::is_sorted_by`](https://doc.rust-lang.org/nightly/std/iter/trait.Iterator.html#method.is_sorted_by) +- [`Iterator::is_sorted_by_key`](https://doc.rust-lang.org/nightly/std/iter/trait.Iterator.html#method.is_sorted_by_key) +- [`std::future::Ready::into_inner`](https://doc.rust-lang.org/nightly/std/future/struct.Ready.html#method.into_inner) +- [`std::iter::repeat_n`](https://doc.rust-lang.org/nightly/std/iter/fn.repeat_n.html) +- [`impl DoubleEndedIterator for Take>`](https://doc.rust-lang.org/nightly/std/iter/struct.Take.html#impl-DoubleEndedIterator-for-Take%3CRepeat%3CT%3E%3E) +- [`impl ExactSizeIterator for Take>`](https://doc.rust-lang.org/nightly/std/iter/struct.Take.html#impl-ExactSizeIterator-for-Take%3CRepeat%3CT%3E%3E) +- [`impl ExactSizeIterator for Take>`](https://doc.rust-lang.org/nightly/std/iter/struct.Take.html#impl-ExactSizeIterator-for-Take%3CRepeatWith%3CF%3E%3E) +- [`impl Default for std::collections::binary_heap::Iter`](https://doc.rust-lang.org/nightly/std/collections/binary_heap/struct.Iter.html#impl-Default-for-Iter%3C'_,+T%3E) +- [`impl Default for std::collections::btree_map::RangeMut`](https://doc.rust-lang.org/nightly/std/collections/btree_map/struct.RangeMut.html#impl-Default-for-RangeMut%3C'_,+K,+V%3E) +- [`impl Default for std::collections::btree_map::ValuesMut`](https://doc.rust-lang.org/nightly/std/collections/btree_map/struct.ValuesMut.html#impl-Default-for-ValuesMut%3C'_,+K,+V%3E) +- [`impl Default for std::collections::vec_deque::Iter`](https://doc.rust-lang.org/nightly/std/collections/vec_deque/struct.Iter.html#impl-Default-for-Iter%3C'_,+T%3E) +- [`impl Default for std::collections::vec_deque::IterMut`](https://doc.rust-lang.org/nightly/std/collections/vec_deque/struct.IterMut.html#impl-Default-for-IterMut%3C'_,+T%3E) +- [`Rc::new_uninit`](https://doc.rust-lang.org/nightly/std/rc/struct.Rc.html#method.new_uninit) +- [`Rc>::assume_init`](https://doc.rust-lang.org/nightly/std/rc/struct.Rc.html#method.assume_init) +- [`Rc<[T]>::new_uninit_slice`](https://doc.rust-lang.org/nightly/std/rc/struct.Rc.html#method.new_uninit_slice) +- [`Rc<[MaybeUninit]>::assume_init`](https://doc.rust-lang.org/nightly/std/rc/struct.Rc.html#method.assume_init-1) +- [`Arc::new_uninit`](https://doc.rust-lang.org/nightly/std/sync/struct.Arc.html#method.new_uninit) +- [`Arc>::assume_init`](https://doc.rust-lang.org/nightly/std/sync/struct.Arc.html#method.assume_init) +- [`Arc<[T]>::new_uninit_slice`](https://doc.rust-lang.org/nightly/std/sync/struct.Arc.html#method.new_uninit_slice) +- [`Arc<[MaybeUninit]>::assume_init`](https://doc.rust-lang.org/nightly/std/sync/struct.Arc.html#method.assume_init-1) +- [`Box::new_uninit`](https://doc.rust-lang.org/nightly/std/boxed/struct.Box.html#method.new_uninit) +- [`Box>::assume_init`](https://doc.rust-lang.org/nightly/std/boxed/struct.Box.html#method.assume_init) +- [`Box<[T]>::new_uninit_slice`](https://doc.rust-lang.org/nightly/std/boxed/struct.Box.html#method.new_uninit_slice) +- [`Box<[MaybeUninit]>::assume_init`](https://doc.rust-lang.org/nightly/std/boxed/struct.Box.html#method.assume_init-1) +- [`core::arch::x86_64::_bextri_u64`](https://doc.rust-lang.org/stable/core/arch/x86_64/fn._bextri_u64.html) +- [`core::arch::x86_64::_bextri_u32`](https://doc.rust-lang.org/stable/core/arch/x86_64/fn._bextri_u32.html) +- [`core::arch::x86::_mm_broadcastsi128_si256`](https://doc.rust-lang.org/stable/core/arch/x86/fn._mm_broadcastsi128_si256.html) +- [`core::arch::x86::_mm256_stream_load_si256`](https://doc.rust-lang.org/stable/core/arch/x86/fn._mm256_stream_load_si256.html) +- [`core::arch::x86::_tzcnt_u16`](https://doc.rust-lang.org/stable/core/arch/x86/fn._tzcnt_u16.html) +- [`core::arch::x86::_mm_extracti_si64`](https://doc.rust-lang.org/stable/core/arch/x86/fn._mm_extracti_si64.html) +- [`core::arch::x86::_mm_inserti_si64`](https://doc.rust-lang.org/stable/core/arch/x86/fn._mm_inserti_si64.html) +- [`core::arch::x86::_mm_storeu_si16`](https://doc.rust-lang.org/stable/core/arch/x86/fn._mm_storeu_si16.html) +- [`core::arch::x86::_mm_storeu_si32`](https://doc.rust-lang.org/stable/core/arch/x86/fn._mm_storeu_si32.html) +- [`core::arch::x86::_mm_storeu_si64`](https://doc.rust-lang.org/stable/core/arch/x86/fn._mm_storeu_si64.html) +- [`core::arch::x86::_mm_loadu_si16`](https://doc.rust-lang.org/stable/core/arch/x86/fn._mm_loadu_si16.html) +- [`core::arch::x86::_mm_loadu_si32`](https://doc.rust-lang.org/stable/core/arch/x86/fn._mm_loadu_si32.html) +- [`core::arch::wasm32::u8x16_relaxed_swizzle`](https://doc.rust-lang.org/nightly/core/arch/wasm32/fn.u8x16_relaxed_swizzle.html) +- [`core::arch::wasm32::i8x16_relaxed_swizzle`](https://doc.rust-lang.org/nightly/core/arch/wasm32/fn.i8x16_relaxed_swizzle.html) +- [`core::arch::wasm32::i32x4_relaxed_trunc_f32x4`](https://doc.rust-lang.org/nightly/core/arch/wasm32/fn.i32x4_relaxed_trunc_f32x4.html) +- [`core::arch::wasm32::u32x4_relaxed_trunc_f32x4`](https://doc.rust-lang.org/nightly/core/arch/wasm32/fn.u32x4_relaxed_trunc_f32x4.html) +- [`core::arch::wasm32::i32x4_relaxed_trunc_f64x2_zero`](https://doc.rust-lang.org/nightly/core/arch/wasm32/fn.i32x4_relaxed_trunc_f64x2_zero.html) +- [`core::arch::wasm32::u32x4_relaxed_trunc_f64x2_zero`](https://doc.rust-lang.org/nightly/core/arch/wasm32/fn.u32x4_relaxed_trunc_f64x2_zero.html) +- [`core::arch::wasm32::f32x4_relaxed_madd`](https://doc.rust-lang.org/nightly/core/arch/wasm32/fn.f32x4_relaxed_madd.html) +- [`core::arch::wasm32::f32x4_relaxed_nmadd`](https://doc.rust-lang.org/nightly/core/arch/wasm32/fn.f32x4_relaxed_nmadd.html) +- [`core::arch::wasm32::f64x2_relaxed_madd`](https://doc.rust-lang.org/nightly/core/arch/wasm32/fn.f64x2_relaxed_madd.html) +- [`core::arch::wasm32::f64x2_relaxed_nmadd`](https://doc.rust-lang.org/nightly/core/arch/wasm32/fn.f64x2_relaxed_nmadd.html) +- [`core::arch::wasm32::i8x16_relaxed_laneselect`](https://doc.rust-lang.org/nightly/core/arch/wasm32/fn.i8x16_relaxed_laneselect.html) +- [`core::arch::wasm32::u8x16_relaxed_laneselect`](https://doc.rust-lang.org/nightly/core/arch/wasm32/fn.u8x16_relaxed_laneselect.html) +- [`core::arch::wasm32::i16x8_relaxed_laneselect`](https://doc.rust-lang.org/nightly/core/arch/wasm32/fn.i16x8_relaxed_laneselect.html) +- [`core::arch::wasm32::u16x8_relaxed_laneselect`](https://doc.rust-lang.org/nightly/core/arch/wasm32/fn.u16x8_relaxed_laneselect.html) +- [`core::arch::wasm32::i32x4_relaxed_laneselect`](https://doc.rust-lang.org/nightly/core/arch/wasm32/fn.i32x4_relaxed_laneselect.html) +- [`core::arch::wasm32::u32x4_relaxed_laneselect`](https://doc.rust-lang.org/nightly/core/arch/wasm32/fn.u32x4_relaxed_laneselect.html) +- [`core::arch::wasm32::i64x2_relaxed_laneselect`](https://doc.rust-lang.org/nightly/core/arch/wasm32/fn.i64x2_relaxed_laneselect.html) +- [`core::arch::wasm32::u64x2_relaxed_laneselect`](https://doc.rust-lang.org/nightly/core/arch/wasm32/fn.u64x2_relaxed_laneselect.html) +- [`core::arch::wasm32::f32x4_relaxed_min`](https://doc.rust-lang.org/nightly/core/arch/wasm32/fn.f32x4_relaxed_min.html) +- [`core::arch::wasm32::f32x4_relaxed_max`](https://doc.rust-lang.org/nightly/core/arch/wasm32/fn.f32x4_relaxed_max.html) +- [`core::arch::wasm32::f64x2_relaxed_min`](https://doc.rust-lang.org/nightly/core/arch/wasm32/fn.f64x2_relaxed_min.html) +- [`core::arch::wasm32::f64x2_relaxed_max`](https://doc.rust-lang.org/nightly/core/arch/wasm32/fn.f64x2_relaxed_max.html) +- [`core::arch::wasm32::i16x8_relaxed_q15mulr`](https://doc.rust-lang.org/nightly/core/arch/wasm32/fn.i16x8_relaxed_q15mulr.html) +- [`core::arch::wasm32::u16x8_relaxed_q15mulr`](https://doc.rust-lang.org/nightly/core/arch/wasm32/fn.u16x8_relaxed_q15mulr.html) +- [`core::arch::wasm32::i16x8_relaxed_dot_i8x16_i7x16`](https://doc.rust-lang.org/nightly/core/arch/wasm32/fn.i16x8_relaxed_dot_i8x16_i7x16.html) +- [`core::arch::wasm32::u16x8_relaxed_dot_i8x16_i7x16`](https://doc.rust-lang.org/nightly/core/arch/wasm32/fn.u16x8_relaxed_dot_i8x16_i7x16.html) +- [`core::arch::wasm32::i32x4_relaxed_dot_i8x16_i7x16_add`](https://doc.rust-lang.org/nightly/core/arch/wasm32/fn.i32x4_relaxed_dot_i8x16_i7x16_add.html) +- [`core::arch::wasm32::u32x4_relaxed_dot_i8x16_i7x16_add`](https://doc.rust-lang.org/nightly/core/arch/wasm32/fn.u32x4_relaxed_dot_i8x16_i7x16_add.html) + +These APIs are now stable in const contexts: + +- [`std::task::Waker::from_raw`](https://doc.rust-lang.org/nightly/std/task/struct.Waker.html#method.from_raw) +- [`std::task::Context::from_waker`](https://doc.rust-lang.org/nightly/std/task/struct.Context.html#method.from_waker) +- [`std::task::Context::waker`](https://doc.rust-lang.org/nightly/std/task/struct.Context.html#method.waker) +- [`$integer::from_str_radix`](https://doc.rust-lang.org/nightly/std/primitive.u32.html#method.from_str_radix) +- [`std::num::ParseIntError::kind`](https://doc.rust-lang.org/nightly/std/num/struct.ParseIntError.html#method.kind) + + + +Cargo +----- +- [feat: Add `info` cargo subcommand](https://github.com/rust-lang/cargo/pull/14141/) + + + +Compatibility Notes +------------------- + - We now [disallow setting some built-in cfgs via the command-line](https://github.com/rust-lang/rust/pull/126158) with the newly added [`explicit_builtin_cfgs_in_flags`](https://doc.rust-lang.org/rustc/lints/listing/deny-by-default.html#explicit-builtin-cfgs-in-flags) lint in order to prevent incoherent state, eg. `windows` cfg active but target is Linux based. The appropriate [`rustc` flag](https://doc.rust-lang.org/rustc/command-line-arguments.html) should be used instead. +- The standard library has a new implementation of `binary_search` which is significantly improves performance ([#128254](https://github.com/rust-lang/rust/pull/128254)). However when a sorted slice has multiple values which compare equal, the new implementation may select a different value among the equal ones than the old implementation. +- [illumos/Solaris now sets `MSG_NOSIGNAL` when writing to sockets](https://github.com/rust-lang/rust/pull/128259). This avoids killing the process with SIGPIPE when writing to a closed socket, which matches the existing behavior on other UNIX targets. +- [Removes a problematic hack that always passed the --whole-archive linker flag for tests, which may cause linker errors for code accidentally relying on it.](https://github.com/rust-lang/rust/pull/128400) +- The WebAssembly target features `multivalue` and `reference-types` are now + both enabled by default. These two features both have subtle changes implied + for generated WebAssembly binaries. For the `multivalue` feature, WebAssembly + target support has changed when upgrading to LLVM 19. Support for generating + functions with multiple returns no longer works and + `-Ctarget-feature=+multivalue` has a different meaning than it did in LLVM 18 + and prior. There is no longer any supported means to generate a module that has + a function with multiple returns in WebAssembly from Rust source code. For the + `reference-types` feature the encoding of immediates in the `call_indirect`, a + commonly used instruction by the WebAssembly backend, has changed. Validators + and parsers which don't understand the `reference-types` proposal will no + longer accept modules produced by LLVM due to this change in encoding of + immediates. Additionally these features being enabled are encoded in the + `target_features` custom section and may affect downstream tooling such as + `wasm-opt` consuming the module. Generating a WebAssembly module that disables + default features requires `-Zbuild-std` support from Cargo and more information + can be found at + [rust-lang/rust#128511](https://github.com/rust-lang/rust/pull/128511). +- [Rust now raises unsafety errors for union patterns in parameter-position](https://github.com/rust-lang/rust/pull/130531) + + + + +Internal Changes +---------------- + +These changes do not affect any public interfaces of Rust, but they represent +significant improvements to the performance or internals of rustc and related +tools. + +- [Update to LLVM 19](https://github.com/rust-lang/rust/pull/127513) + Version 1.81.0 (2024-09-05) ========================== From c3eb2f2e7529cd0f24c823977388e5bc415dd966 Mon Sep 17 00:00:00 2001 From: Boxy Date: Mon, 25 Nov 2024 11:30:34 +0000 Subject: [PATCH 2184/2194] bump channel to stable --- src/ci/channel | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ci/channel b/src/ci/channel index 65b2df87f7df3..2bf5ad0447d33 100644 --- a/src/ci/channel +++ b/src/ci/channel @@ -1 +1 @@ -beta +stable From cefed0b13d12f1dfe7e1d716830111b4e9e49679 Mon Sep 17 00:00:00 2001 From: Pietro Albini Date: Mon, 25 Nov 2024 14:15:21 +0100 Subject: [PATCH 2185/2194] Revert "add new CI step: "setup upstream remote"" This reverts commit 4454fa998c9da1f1eee1602c8e8cd2732505c104. --- .github/workflows/ci.yml | 3 --- src/ci/scripts/setup-upstream-remote.sh | 24 ------------------------ src/ci/shared.sh | 12 ------------ 3 files changed, 39 deletions(-) delete mode 100755 src/ci/scripts/setup-upstream-remote.sh diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 003c1e5d7ebbe..b6dc27f123465 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -122,9 +122,6 @@ jobs: # which then uses log commands to actually set them. EXTRA_VARIABLES: ${{ toJson(matrix.env) }} - - name: setup upstream remote - run: src/ci/scripts/setup-upstream-remote.sh - - name: ensure the channel matches the target branch run: src/ci/scripts/verify-channel.sh diff --git a/src/ci/scripts/setup-upstream-remote.sh b/src/ci/scripts/setup-upstream-remote.sh deleted file mode 100755 index 52b4c98a89016..0000000000000 --- a/src/ci/scripts/setup-upstream-remote.sh +++ /dev/null @@ -1,24 +0,0 @@ -#!/bin/bash -# In CI environments, bootstrap is forced to use the remote upstream based -# on "git_repository" and "nightly_branch" values from src/stage0 file. -# This script configures the remote as it may not exist by default. - -set -euo pipefail -IFS=$'\n\t' - -ci_dir=$(cd $(dirname $0) && pwd)/.. -source "$ci_dir/shared.sh" - -git_repository=$(parse_stage0_file_by_key "git_repository") -nightly_branch=$(parse_stage0_file_by_key "nightly_branch") - -# Configure "rust-lang/rust" upstream remote only when it's not origin. -if [ -z "$(git config remote.origin.url | grep $git_repository)" ]; then - echo "Configuring https://github.com/$git_repository remote as upstream." - git remote add upstream "https://github.com/$git_repository" - REMOTE_NAME="upstream" -else - REMOTE_NAME="origin" -fi - -git fetch $REMOTE_NAME $nightly_branch diff --git a/src/ci/shared.sh b/src/ci/shared.sh index 1e6a008a5de81..2b0a10e4d08d9 100644 --- a/src/ci/shared.sh +++ b/src/ci/shared.sh @@ -136,15 +136,3 @@ function releaseChannel { echo $RUST_CI_OVERRIDE_RELEASE_CHANNEL fi } - -# Parse values from src/stage0 file by key -function parse_stage0_file_by_key { - local key="$1" - local file="$ci_dir/../stage0" - local value=$(awk -F= '{a[$1]=$2} END {print(a["'$key'"])}' $file) - if [ -z "$value" ]; then - echo "ERROR: Key '$key' not found in '$file'." - exit 1 - fi - echo "$value" -} From 6090960b9dcfc3caa3f87f1e94de9b78c25ba902 Mon Sep 17 00:00:00 2001 From: Pietro Albini Date: Mon, 25 Nov 2024 14:15:30 +0100 Subject: [PATCH 2186/2194] Revert "force "HEAD" for non-CI and `git_upstream_merge_base` for CI environment" This reverts commit 33ac202904e7820268b71b3280a7d2590378e3b9. --- src/tools/build_helper/src/git.rs | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) diff --git a/src/tools/build_helper/src/git.rs b/src/tools/build_helper/src/git.rs index 2aad5650fa898..1e28d552fe66c 100644 --- a/src/tools/build_helper/src/git.rs +++ b/src/tools/build_helper/src/git.rs @@ -1,8 +1,6 @@ use std::path::{Path, PathBuf}; use std::process::{Command, Stdio}; -use crate::ci::CiEnv; - pub struct GitConfig<'a> { pub git_repository: &'a str, pub nightly_branch: &'a str, @@ -116,8 +114,8 @@ fn git_upstream_merge_base( /// Searches for the nearest merge commit in the repository that also exists upstream. /// -/// It looks for the most recent commit made by the merge bot by matching the author's email -/// address with the merge bot's email. +/// If it fails to find the upstream remote, it then looks for the most recent commit made +/// by the merge bot by matching the author's email address with the merge bot's email. pub fn get_closest_merge_commit( git_dir: Option<&Path>, config: &GitConfig<'_>, @@ -129,15 +127,7 @@ pub fn get_closest_merge_commit( git.current_dir(git_dir); } - let merge_base = { - if CiEnv::is_ci() { - git_upstream_merge_base(config, git_dir).unwrap() - } else { - // For non-CI environments, ignore rust-lang/rust upstream as it usually gets - // outdated very quickly. - "HEAD".to_string() - } - }; + let merge_base = git_upstream_merge_base(config, git_dir).unwrap_or_else(|_| "HEAD".into()); git.args([ "rev-list", From 60c4250430b34b75ca2cfd43ccb04aa1d657dbde Mon Sep 17 00:00:00 2001 From: Kirill Bulatov Date: Mon, 25 Nov 2024 23:29:55 +0200 Subject: [PATCH 2187/2194] Revert "Update the file hash" This reverts commit f0db79f31ada049bf490c8f27be7443f45460f09. --- src/tools/rust-analyzer/docs/dev/lsp-extensions.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/rust-analyzer/docs/dev/lsp-extensions.md b/src/tools/rust-analyzer/docs/dev/lsp-extensions.md index b7c536e027964..7764f7843a00b 100644 --- a/src/tools/rust-analyzer/docs/dev/lsp-extensions.md +++ b/src/tools/rust-analyzer/docs/dev/lsp-extensions.md @@ -1,5 +1,5 @@